1 /*
2  * cancel.c:  Routines to support cancellation of running subversion functions.
3  *
4  * ====================================================================
5  *    Licensed to the Apache Software Foundation (ASF) under one
6  *    or more contributor license agreements.  See the NOTICE file
7  *    distributed with this work for additional information
8  *    regarding copyright ownership.  The ASF licenses this file
9  *    to you under the Apache License, Version 2.0 (the
10  *    "License"); you may not use this file except in compliance
11  *    with the License.  You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  *    Unless required by applicable law or agreed to in writing,
16  *    software distributed under the License is distributed on an
17  *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18  *    KIND, either express or implied.  See the License for the
19  *    specific language governing permissions and limitations
20  *    under the License.
21  * ====================================================================
22  */
23 
24 #include "svn_delta.h"
25 
26 struct edit_baton
27 {
28   const svn_delta_editor_t *wrapped_editor;
29   void *wrapped_edit_baton;
30 
31   svn_cancel_func_t cancel_func;
32   void *cancel_baton;
33 };
34 
35 struct dir_baton
36 {
37   void *edit_baton;
38   void *wrapped_dir_baton;
39 };
40 
41 struct file_baton
42 {
43   void *edit_baton;
44   void *wrapped_file_baton;
45 };
46 
47 static svn_error_t *
set_target_revision(void * edit_baton,svn_revnum_t target_revision,apr_pool_t * pool)48 set_target_revision(void *edit_baton,
49                     svn_revnum_t target_revision,
50                     apr_pool_t *pool)
51 {
52   struct edit_baton *eb = edit_baton;
53 
54   SVN_ERR(eb->cancel_func(eb->cancel_baton));
55 
56   return eb->wrapped_editor->set_target_revision(eb->wrapped_edit_baton,
57                                                  target_revision,
58                                                  pool);
59 }
60 
61 static svn_error_t *
open_root(void * edit_baton,svn_revnum_t base_revision,apr_pool_t * pool,void ** root_baton)62 open_root(void *edit_baton,
63           svn_revnum_t base_revision,
64           apr_pool_t *pool,
65           void **root_baton)
66 {
67   struct edit_baton *eb = edit_baton;
68   struct dir_baton *dir_baton = apr_palloc(pool, sizeof(*dir_baton));
69 
70   SVN_ERR(eb->cancel_func(eb->cancel_baton));
71 
72   SVN_ERR(eb->wrapped_editor->open_root(eb->wrapped_edit_baton,
73                                         base_revision,
74                                         pool,
75                                         &dir_baton->wrapped_dir_baton));
76 
77   dir_baton->edit_baton = edit_baton;
78 
79   *root_baton = dir_baton;
80 
81   return SVN_NO_ERROR;
82 }
83 
84 static svn_error_t *
delete_entry(const char * path,svn_revnum_t base_revision,void * parent_baton,apr_pool_t * pool)85 delete_entry(const char *path,
86              svn_revnum_t base_revision,
87              void *parent_baton,
88              apr_pool_t *pool)
89 {
90   struct dir_baton *pb = parent_baton;
91   struct edit_baton *eb = pb->edit_baton;
92 
93   SVN_ERR(eb->cancel_func(eb->cancel_baton));
94 
95   return eb->wrapped_editor->delete_entry(path,
96                                           base_revision,
97                                           pb->wrapped_dir_baton,
98                                           pool);
99 }
100 
101 static svn_error_t *
add_directory(const char * path,void * parent_baton,const char * copyfrom_path,svn_revnum_t copyfrom_revision,apr_pool_t * pool,void ** child_baton)102 add_directory(const char *path,
103               void *parent_baton,
104               const char *copyfrom_path,
105               svn_revnum_t copyfrom_revision,
106               apr_pool_t *pool,
107               void **child_baton)
108 {
109   struct dir_baton *pb = parent_baton;
110   struct edit_baton *eb = pb->edit_baton;
111   struct dir_baton *b = apr_palloc(pool, sizeof(*b));
112 
113   SVN_ERR(eb->cancel_func(eb->cancel_baton));
114 
115   SVN_ERR(eb->wrapped_editor->add_directory(path,
116                                             pb->wrapped_dir_baton,
117                                             copyfrom_path,
118                                             copyfrom_revision,
119                                             pool,
120                                             &b->wrapped_dir_baton));
121 
122   b->edit_baton = eb;
123   *child_baton = b;
124 
125   return SVN_NO_ERROR;
126 }
127 
128 static svn_error_t *
open_directory(const char * path,void * parent_baton,svn_revnum_t base_revision,apr_pool_t * pool,void ** child_baton)129 open_directory(const char *path,
130                void *parent_baton,
131                svn_revnum_t base_revision,
132                apr_pool_t *pool,
133                void **child_baton)
134 {
135   struct dir_baton *pb = parent_baton;
136   struct edit_baton *eb = pb->edit_baton;
137   struct dir_baton *db = apr_palloc(pool, sizeof(*db));
138 
139   SVN_ERR(eb->cancel_func(eb->cancel_baton));
140 
141   SVN_ERR(eb->wrapped_editor->open_directory(path,
142                                              pb->wrapped_dir_baton,
143                                              base_revision,
144                                              pool,
145                                              &db->wrapped_dir_baton));
146 
147   db->edit_baton = eb;
148   *child_baton = db;
149 
150   return SVN_NO_ERROR;
151 }
152 
153 static svn_error_t *
add_file(const char * path,void * parent_baton,const char * copyfrom_path,svn_revnum_t copyfrom_revision,apr_pool_t * pool,void ** file_baton)154 add_file(const char *path,
155          void *parent_baton,
156          const char *copyfrom_path,
157          svn_revnum_t copyfrom_revision,
158          apr_pool_t *pool,
159          void **file_baton)
160 {
161   struct dir_baton *pb = parent_baton;
162   struct edit_baton *eb = pb->edit_baton;
163   struct file_baton *fb = apr_palloc(pool, sizeof(*fb));
164 
165   SVN_ERR(eb->cancel_func(eb->cancel_baton));
166 
167   SVN_ERR(eb->wrapped_editor->add_file(path,
168                                        pb->wrapped_dir_baton,
169                                        copyfrom_path,
170                                        copyfrom_revision,
171                                        pool,
172                                        &fb->wrapped_file_baton));
173 
174   fb->edit_baton = eb;
175   *file_baton = fb;
176 
177   return SVN_NO_ERROR;
178 }
179 
180 static svn_error_t *
open_file(const char * path,void * parent_baton,svn_revnum_t base_revision,apr_pool_t * pool,void ** file_baton)181 open_file(const char *path,
182           void *parent_baton,
183           svn_revnum_t base_revision,
184           apr_pool_t *pool,
185           void **file_baton)
186 {
187   struct dir_baton *pb = parent_baton;
188   struct edit_baton *eb = pb->edit_baton;
189   struct file_baton *fb = apr_palloc(pool, sizeof(*fb));
190 
191   SVN_ERR(eb->cancel_func(eb->cancel_baton));
192 
193   SVN_ERR(eb->wrapped_editor->open_file(path,
194                                         pb->wrapped_dir_baton,
195                                         base_revision,
196                                         pool,
197                                         &fb->wrapped_file_baton));
198 
199   fb->edit_baton = eb;
200   *file_baton = fb;
201 
202   return SVN_NO_ERROR;
203 }
204 
205 static svn_error_t *
apply_textdelta(void * file_baton,const char * base_checksum,apr_pool_t * pool,svn_txdelta_window_handler_t * handler,void ** handler_baton)206 apply_textdelta(void *file_baton,
207                 const char *base_checksum,
208                 apr_pool_t *pool,
209                 svn_txdelta_window_handler_t *handler,
210                 void **handler_baton)
211 {
212   struct file_baton *fb = file_baton;
213   struct edit_baton *eb = fb->edit_baton;
214 
215   SVN_ERR(eb->cancel_func(eb->cancel_baton));
216 
217   return eb->wrapped_editor->apply_textdelta(fb->wrapped_file_baton,
218                                              base_checksum,
219                                              pool,
220                                              handler,
221                                              handler_baton);
222 }
223 
224 static svn_error_t *
apply_textdelta_stream(const svn_delta_editor_t * editor,void * file_baton,const char * base_checksum,svn_txdelta_stream_open_func_t open_func,void * open_baton,apr_pool_t * scratch_pool)225 apply_textdelta_stream(const svn_delta_editor_t *editor,
226                        void *file_baton,
227                        const char *base_checksum,
228                        svn_txdelta_stream_open_func_t open_func,
229                        void *open_baton,
230                        apr_pool_t *scratch_pool)
231 {
232   struct file_baton *fb = file_baton;
233   struct edit_baton *eb = fb->edit_baton;
234 
235   SVN_ERR(eb->cancel_func(eb->cancel_baton));
236 
237   return eb->wrapped_editor->apply_textdelta_stream(eb->wrapped_editor,
238                                                     fb->wrapped_file_baton,
239                                                     base_checksum,
240                                                     open_func, open_baton,
241                                                     scratch_pool);
242 }
243 
244 static svn_error_t *
close_file(void * file_baton,const char * text_checksum,apr_pool_t * pool)245 close_file(void *file_baton,
246            const char *text_checksum,
247            apr_pool_t *pool)
248 {
249   struct file_baton *fb = file_baton;
250   struct edit_baton *eb = fb->edit_baton;
251 
252   SVN_ERR(eb->cancel_func(eb->cancel_baton));
253 
254   return eb->wrapped_editor->close_file(fb->wrapped_file_baton,
255                                         text_checksum, pool);
256 }
257 
258 static svn_error_t *
absent_file(const char * path,void * file_baton,apr_pool_t * pool)259 absent_file(const char *path,
260             void *file_baton,
261             apr_pool_t *pool)
262 {
263   struct file_baton *fb = file_baton;
264   struct edit_baton *eb = fb->edit_baton;
265 
266   SVN_ERR(eb->cancel_func(eb->cancel_baton));
267 
268   return eb->wrapped_editor->absent_file(path, fb->wrapped_file_baton,
269                                          pool);
270 }
271 
272 static svn_error_t *
close_directory(void * dir_baton,apr_pool_t * pool)273 close_directory(void *dir_baton,
274                 apr_pool_t *pool)
275 {
276   struct dir_baton *db = dir_baton;
277   struct edit_baton *eb = db->edit_baton;
278 
279   SVN_ERR(eb->cancel_func(eb->cancel_baton));
280 
281   return eb->wrapped_editor->close_directory(db->wrapped_dir_baton, pool);
282 }
283 
284 static svn_error_t *
absent_directory(const char * path,void * dir_baton,apr_pool_t * pool)285 absent_directory(const char *path,
286                  void *dir_baton,
287                  apr_pool_t *pool)
288 {
289   struct dir_baton *db = dir_baton;
290   struct edit_baton *eb = db->edit_baton;
291 
292   SVN_ERR(eb->cancel_func(eb->cancel_baton));
293 
294   return eb->wrapped_editor->absent_directory(path, db->wrapped_dir_baton,
295                                               pool);
296 }
297 
298 static svn_error_t *
change_file_prop(void * file_baton,const char * name,const svn_string_t * value,apr_pool_t * pool)299 change_file_prop(void *file_baton,
300                  const char *name,
301                  const svn_string_t *value,
302                  apr_pool_t *pool)
303 {
304   struct file_baton *fb = file_baton;
305   struct edit_baton *eb = fb->edit_baton;
306 
307   SVN_ERR(eb->cancel_func(eb->cancel_baton));
308 
309   return eb->wrapped_editor->change_file_prop(fb->wrapped_file_baton,
310                                               name, value, pool);
311 }
312 
313 static svn_error_t *
change_dir_prop(void * dir_baton,const char * name,const svn_string_t * value,apr_pool_t * pool)314 change_dir_prop(void *dir_baton,
315                 const char *name,
316                 const svn_string_t *value,
317                 apr_pool_t *pool)
318 {
319   struct dir_baton *db = dir_baton;
320   struct edit_baton *eb = db->edit_baton;
321 
322   SVN_ERR(eb->cancel_func(eb->cancel_baton));
323 
324   return eb->wrapped_editor->change_dir_prop(db->wrapped_dir_baton,
325                                              name,
326                                              value,
327                                              pool);
328 }
329 
330 static svn_error_t *
close_edit(void * edit_baton,apr_pool_t * pool)331 close_edit(void *edit_baton,
332            apr_pool_t *pool)
333 {
334   struct edit_baton *eb = edit_baton;
335 
336   SVN_ERR(eb->cancel_func(eb->cancel_baton));
337 
338   return eb->wrapped_editor->close_edit(eb->wrapped_edit_baton, pool);
339 }
340 
341 static svn_error_t *
abort_edit(void * edit_baton,apr_pool_t * pool)342 abort_edit(void *edit_baton,
343            apr_pool_t *pool)
344 {
345   struct edit_baton *eb = edit_baton;
346 
347   SVN_ERR(eb->cancel_func(eb->cancel_baton));
348 
349   return eb->wrapped_editor->abort_edit(eb->wrapped_edit_baton, pool);
350 }
351 
352 svn_error_t *
svn_delta_get_cancellation_editor(svn_cancel_func_t cancel_func,void * cancel_baton,const svn_delta_editor_t * wrapped_editor,void * wrapped_edit_baton,const svn_delta_editor_t ** editor,void ** edit_baton,apr_pool_t * pool)353 svn_delta_get_cancellation_editor(svn_cancel_func_t cancel_func,
354                                   void *cancel_baton,
355                                   const svn_delta_editor_t *wrapped_editor,
356                                   void *wrapped_edit_baton,
357                                   const svn_delta_editor_t **editor,
358                                   void **edit_baton,
359                                   apr_pool_t *pool)
360 {
361   if (cancel_func)
362     {
363       svn_delta_editor_t *tree_editor = svn_delta_default_editor(pool);
364       struct edit_baton *eb = apr_palloc(pool, sizeof(*eb));
365 
366       tree_editor->set_target_revision = set_target_revision;
367       tree_editor->open_root = open_root;
368       tree_editor->delete_entry = delete_entry;
369       tree_editor->add_directory = add_directory;
370       tree_editor->open_directory = open_directory;
371       tree_editor->change_dir_prop = change_dir_prop;
372       tree_editor->close_directory = close_directory;
373       tree_editor->absent_directory = absent_directory;
374       tree_editor->add_file = add_file;
375       tree_editor->open_file = open_file;
376       tree_editor->apply_textdelta = apply_textdelta;
377       tree_editor->apply_textdelta_stream = apply_textdelta_stream;
378       tree_editor->change_file_prop = change_file_prop;
379       tree_editor->close_file = close_file;
380       tree_editor->absent_file = absent_file;
381       tree_editor->close_edit = close_edit;
382       tree_editor->abort_edit = abort_edit;
383 
384       eb->wrapped_editor = wrapped_editor;
385       eb->wrapped_edit_baton = wrapped_edit_baton;
386       eb->cancel_func = cancel_func;
387       eb->cancel_baton = cancel_baton;
388 
389       *editor = tree_editor;
390       *edit_baton = eb;
391     }
392   else
393     {
394       *editor = wrapped_editor;
395       *edit_baton = wrapped_edit_baton;
396     }
397 
398   return SVN_NO_ERROR;
399 }
400