1 | /* |
---|
2 | * debug_editor.c : An editor that writes the operations it does to stderr. |
---|
3 | * |
---|
4 | * ==================================================================== |
---|
5 | * Copyright (c) 2000-2004 CollabNet. All rights reserved. |
---|
6 | * |
---|
7 | * This software is licensed as described in the file COPYING, which |
---|
8 | * you should have received as part of this distribution. The terms |
---|
9 | * are also available at http://subversion.tigris.org/license-1.html. |
---|
10 | * If newer versions of this license are posted there, you may use a |
---|
11 | * newer version instead, at your option. |
---|
12 | * |
---|
13 | * This software consists of voluntary contributions made by many |
---|
14 | * individuals. For exact contribution history, see the revision |
---|
15 | * history and logs, available at http://subversion.tigris.org/. |
---|
16 | * ==================================================================== |
---|
17 | */ |
---|
18 | |
---|
19 | #include "debug_editor.h" |
---|
20 | |
---|
21 | struct edit_baton |
---|
22 | { |
---|
23 | const svn_delta_editor_t *wrapped_editor; |
---|
24 | void *wrapped_edit_baton; |
---|
25 | |
---|
26 | int indent_level; |
---|
27 | |
---|
28 | svn_stream_t *out; |
---|
29 | }; |
---|
30 | |
---|
31 | struct dir_baton |
---|
32 | { |
---|
33 | void *edit_baton; |
---|
34 | void *wrapped_dir_baton; |
---|
35 | }; |
---|
36 | |
---|
37 | struct file_baton |
---|
38 | { |
---|
39 | void *edit_baton; |
---|
40 | void *wrapped_file_baton; |
---|
41 | }; |
---|
42 | |
---|
43 | static svn_error_t * |
---|
44 | write_indent(struct edit_baton *eb, apr_pool_t *pool) |
---|
45 | { |
---|
46 | int i; |
---|
47 | |
---|
48 | for (i = 0; i < eb->indent_level; ++i) |
---|
49 | SVN_ERR(svn_stream_printf(eb->out, pool, " ")); |
---|
50 | |
---|
51 | return SVN_NO_ERROR; |
---|
52 | } |
---|
53 | |
---|
54 | static svn_error_t * |
---|
55 | set_target_revision(void *edit_baton, |
---|
56 | svn_revnum_t target_revision, |
---|
57 | apr_pool_t *pool) |
---|
58 | { |
---|
59 | struct edit_baton *eb = edit_baton; |
---|
60 | |
---|
61 | SVN_ERR(write_indent(eb, pool)); |
---|
62 | SVN_ERR(svn_stream_printf(eb->out, pool, "set_target_revision : %ld\n", |
---|
63 | target_revision)); |
---|
64 | |
---|
65 | return eb->wrapped_editor->set_target_revision(eb->wrapped_edit_baton, |
---|
66 | target_revision, |
---|
67 | pool); |
---|
68 | } |
---|
69 | |
---|
70 | static svn_error_t * |
---|
71 | open_root(void *edit_baton, |
---|
72 | svn_revnum_t base_revision, |
---|
73 | apr_pool_t *pool, |
---|
74 | void **root_baton) |
---|
75 | { |
---|
76 | struct edit_baton *eb = edit_baton; |
---|
77 | struct dir_baton *dir_baton = apr_palloc(pool, sizeof(*dir_baton)); |
---|
78 | |
---|
79 | SVN_ERR(write_indent(eb, pool)); |
---|
80 | SVN_ERR(svn_stream_printf(eb->out, pool, "open_root : %ld\n", |
---|
81 | base_revision)); |
---|
82 | eb->indent_level++; |
---|
83 | |
---|
84 | SVN_ERR(eb->wrapped_editor->open_root(eb->wrapped_edit_baton, |
---|
85 | base_revision, |
---|
86 | pool, |
---|
87 | &dir_baton->wrapped_dir_baton)); |
---|
88 | |
---|
89 | dir_baton->edit_baton = edit_baton; |
---|
90 | |
---|
91 | *root_baton = dir_baton; |
---|
92 | |
---|
93 | return SVN_NO_ERROR; |
---|
94 | } |
---|
95 | |
---|
96 | static svn_error_t * |
---|
97 | delete_entry(const char *path, |
---|
98 | svn_revnum_t base_revision, |
---|
99 | void *parent_baton, |
---|
100 | apr_pool_t *pool) |
---|
101 | { |
---|
102 | struct dir_baton *pb = parent_baton; |
---|
103 | struct edit_baton *eb = pb->edit_baton; |
---|
104 | |
---|
105 | SVN_ERR(write_indent(eb, pool)); |
---|
106 | SVN_ERR(svn_stream_printf(eb->out, pool, "delete_entry : %s:%ld\n", |
---|
107 | path, base_revision)); |
---|
108 | |
---|
109 | return eb->wrapped_editor->delete_entry(path, |
---|
110 | base_revision, |
---|
111 | pb->wrapped_dir_baton, |
---|
112 | pool); |
---|
113 | } |
---|
114 | |
---|
115 | static svn_error_t * |
---|
116 | add_directory(const char *path, |
---|
117 | void *parent_baton, |
---|
118 | const char *copyfrom_path, |
---|
119 | svn_revnum_t copyfrom_revision, |
---|
120 | apr_pool_t *pool, |
---|
121 | void **child_baton) |
---|
122 | { |
---|
123 | struct dir_baton *pb = parent_baton; |
---|
124 | struct edit_baton *eb = pb->edit_baton; |
---|
125 | struct dir_baton *b = apr_palloc(pool, sizeof(*b)); |
---|
126 | |
---|
127 | SVN_ERR(write_indent(eb, pool)); |
---|
128 | SVN_ERR(svn_stream_printf(eb->out, pool, |
---|
129 | "add_directory : '%s' [from '%s':%ld]\n", |
---|
130 | path, copyfrom_path, copyfrom_revision)); |
---|
131 | eb->indent_level++; |
---|
132 | |
---|
133 | SVN_ERR(eb->wrapped_editor->add_directory(path, |
---|
134 | pb->wrapped_dir_baton, |
---|
135 | copyfrom_path, |
---|
136 | copyfrom_revision, |
---|
137 | pool, |
---|
138 | &b->wrapped_dir_baton)); |
---|
139 | |
---|
140 | b->edit_baton = eb; |
---|
141 | *child_baton = b; |
---|
142 | |
---|
143 | return SVN_NO_ERROR; |
---|
144 | } |
---|
145 | |
---|
146 | static svn_error_t * |
---|
147 | open_directory(const char *path, |
---|
148 | void *parent_baton, |
---|
149 | svn_revnum_t base_revision, |
---|
150 | apr_pool_t *pool, |
---|
151 | void **child_baton) |
---|
152 | { |
---|
153 | struct dir_baton *pb = parent_baton; |
---|
154 | struct edit_baton *eb = pb->edit_baton; |
---|
155 | struct dir_baton *db = apr_palloc(pool, sizeof(*db)); |
---|
156 | |
---|
157 | SVN_ERR(write_indent(eb, pool)); |
---|
158 | SVN_ERR(svn_stream_printf(eb->out, pool, "open_directory : '%s':%ld\n", |
---|
159 | path, base_revision)); |
---|
160 | eb->indent_level++; |
---|
161 | |
---|
162 | SVN_ERR(eb->wrapped_editor->open_directory(path, |
---|
163 | pb->wrapped_dir_baton, |
---|
164 | base_revision, |
---|
165 | pool, |
---|
166 | &db->wrapped_dir_baton)); |
---|
167 | |
---|
168 | db->edit_baton = eb; |
---|
169 | *child_baton = db; |
---|
170 | |
---|
171 | return SVN_NO_ERROR; |
---|
172 | } |
---|
173 | |
---|
174 | static svn_error_t * |
---|
175 | add_file(const char *path, |
---|
176 | void *parent_baton, |
---|
177 | const char *copyfrom_path, |
---|
178 | svn_revnum_t copyfrom_revision, |
---|
179 | apr_pool_t *pool, |
---|
180 | void **file_baton) |
---|
181 | { |
---|
182 | struct dir_baton *pb = parent_baton; |
---|
183 | struct edit_baton *eb = pb->edit_baton; |
---|
184 | struct file_baton *fb = apr_palloc(pool, sizeof(*fb)); |
---|
185 | |
---|
186 | SVN_ERR(write_indent(eb, pool)); |
---|
187 | SVN_ERR(svn_stream_printf(eb->out, pool, |
---|
188 | "add_file : '%s' [from '%s':%ld]\n", |
---|
189 | path, copyfrom_path, copyfrom_revision)); |
---|
190 | |
---|
191 | eb->indent_level++; |
---|
192 | |
---|
193 | SVN_ERR(eb->wrapped_editor->add_file(path, |
---|
194 | pb->wrapped_dir_baton, |
---|
195 | copyfrom_path, |
---|
196 | copyfrom_revision, |
---|
197 | pool, |
---|
198 | &fb->wrapped_file_baton)); |
---|
199 | |
---|
200 | fb->edit_baton = eb; |
---|
201 | *file_baton = fb; |
---|
202 | |
---|
203 | return SVN_NO_ERROR; |
---|
204 | } |
---|
205 | |
---|
206 | static svn_error_t * |
---|
207 | open_file(const char *path, |
---|
208 | void *parent_baton, |
---|
209 | svn_revnum_t base_revision, |
---|
210 | apr_pool_t *pool, |
---|
211 | void **file_baton) |
---|
212 | { |
---|
213 | struct dir_baton *pb = parent_baton; |
---|
214 | struct edit_baton *eb = pb->edit_baton; |
---|
215 | struct file_baton *fb = apr_palloc(pool, sizeof(*fb)); |
---|
216 | |
---|
217 | SVN_ERR(write_indent(eb, pool)); |
---|
218 | SVN_ERR(svn_stream_printf(eb->out, pool, "open_file : '%s':%ld\n", |
---|
219 | path, base_revision)); |
---|
220 | |
---|
221 | eb->indent_level++; |
---|
222 | |
---|
223 | SVN_ERR(eb->wrapped_editor->open_file(path, |
---|
224 | pb->wrapped_dir_baton, |
---|
225 | base_revision, |
---|
226 | pool, |
---|
227 | &fb->wrapped_file_baton)); |
---|
228 | |
---|
229 | fb->edit_baton = eb; |
---|
230 | *file_baton = fb; |
---|
231 | |
---|
232 | return SVN_NO_ERROR; |
---|
233 | } |
---|
234 | |
---|
235 | static svn_error_t * |
---|
236 | apply_textdelta(void *file_baton, |
---|
237 | const char *base_checksum, |
---|
238 | apr_pool_t *pool, |
---|
239 | svn_txdelta_window_handler_t *handler, |
---|
240 | void **handler_baton) |
---|
241 | { |
---|
242 | struct file_baton *fb = file_baton; |
---|
243 | struct edit_baton *eb = fb->edit_baton; |
---|
244 | |
---|
245 | SVN_ERR(write_indent(eb, pool)); |
---|
246 | SVN_ERR(svn_stream_printf(eb->out, pool, "apply_textdelta : %s\n", |
---|
247 | base_checksum)); |
---|
248 | |
---|
249 | SVN_ERR(eb->wrapped_editor->apply_textdelta(fb->wrapped_file_baton, |
---|
250 | base_checksum, |
---|
251 | pool, |
---|
252 | handler, |
---|
253 | handler_baton)); |
---|
254 | |
---|
255 | return SVN_NO_ERROR; |
---|
256 | } |
---|
257 | |
---|
258 | static svn_error_t * |
---|
259 | close_file(void *file_baton, |
---|
260 | const char *text_checksum, |
---|
261 | apr_pool_t *pool) |
---|
262 | { |
---|
263 | struct file_baton *fb = file_baton; |
---|
264 | struct edit_baton *eb = fb->edit_baton; |
---|
265 | |
---|
266 | eb->indent_level--; |
---|
267 | |
---|
268 | SVN_ERR(write_indent(eb, pool)); |
---|
269 | SVN_ERR(svn_stream_printf(eb->out, pool, "close_file : %s\n", |
---|
270 | text_checksum)); |
---|
271 | |
---|
272 | SVN_ERR(eb->wrapped_editor->close_file(fb->wrapped_file_baton, |
---|
273 | text_checksum, pool)); |
---|
274 | |
---|
275 | return SVN_NO_ERROR; |
---|
276 | } |
---|
277 | |
---|
278 | static svn_error_t * |
---|
279 | absent_file(const char *path, |
---|
280 | void *file_baton, |
---|
281 | apr_pool_t *pool) |
---|
282 | { |
---|
283 | struct file_baton *fb = file_baton; |
---|
284 | struct edit_baton *eb = fb->edit_baton; |
---|
285 | |
---|
286 | SVN_ERR(write_indent(eb, pool)); |
---|
287 | SVN_ERR(svn_stream_printf(eb->out, pool, "absent_file : %s\n", path)); |
---|
288 | |
---|
289 | SVN_ERR(eb->wrapped_editor->absent_file(path, fb->wrapped_file_baton, |
---|
290 | pool)); |
---|
291 | |
---|
292 | return SVN_NO_ERROR; |
---|
293 | } |
---|
294 | |
---|
295 | static svn_error_t * |
---|
296 | close_directory(void *dir_baton, |
---|
297 | apr_pool_t *pool) |
---|
298 | { |
---|
299 | struct dir_baton *db = dir_baton; |
---|
300 | struct edit_baton *eb = db->edit_baton; |
---|
301 | |
---|
302 | eb->indent_level--; |
---|
303 | SVN_ERR(write_indent(eb, pool)); |
---|
304 | SVN_ERR(svn_stream_printf(eb->out, pool, "close_directory\n")); |
---|
305 | |
---|
306 | SVN_ERR(eb->wrapped_editor->close_directory(db->wrapped_dir_baton, |
---|
307 | pool)); |
---|
308 | |
---|
309 | return SVN_NO_ERROR; |
---|
310 | } |
---|
311 | |
---|
312 | static svn_error_t * |
---|
313 | absent_directory(const char *path, |
---|
314 | void *dir_baton, |
---|
315 | apr_pool_t *pool) |
---|
316 | { |
---|
317 | struct dir_baton *db = dir_baton; |
---|
318 | struct edit_baton *eb = db->edit_baton; |
---|
319 | |
---|
320 | SVN_ERR(write_indent(eb, pool)); |
---|
321 | SVN_ERR(svn_stream_printf(eb->out, pool, "absent_directory : %s\n", |
---|
322 | path)); |
---|
323 | |
---|
324 | SVN_ERR(eb->wrapped_editor->absent_directory(path, db->wrapped_dir_baton, |
---|
325 | pool)); |
---|
326 | |
---|
327 | return SVN_NO_ERROR; |
---|
328 | } |
---|
329 | |
---|
330 | static svn_error_t * |
---|
331 | change_file_prop(void *file_baton, |
---|
332 | const char *name, |
---|
333 | const svn_string_t *value, |
---|
334 | apr_pool_t *pool) |
---|
335 | { |
---|
336 | struct file_baton *fb = file_baton; |
---|
337 | struct edit_baton *eb = fb->edit_baton; |
---|
338 | |
---|
339 | SVN_ERR(write_indent(eb, pool)); |
---|
340 | SVN_ERR(svn_stream_printf(eb->out, pool, "change_file_prop : %s\n", |
---|
341 | name)); |
---|
342 | |
---|
343 | SVN_ERR(eb->wrapped_editor->change_file_prop(fb->wrapped_file_baton, |
---|
344 | name, |
---|
345 | value, |
---|
346 | pool)); |
---|
347 | |
---|
348 | return SVN_NO_ERROR; |
---|
349 | } |
---|
350 | |
---|
351 | static svn_error_t * |
---|
352 | change_dir_prop(void *dir_baton, |
---|
353 | const char *name, |
---|
354 | const svn_string_t *value, |
---|
355 | apr_pool_t *pool) |
---|
356 | { |
---|
357 | struct dir_baton *db = dir_baton; |
---|
358 | struct edit_baton *eb = db->edit_baton; |
---|
359 | |
---|
360 | SVN_ERR(write_indent(eb, pool)); |
---|
361 | SVN_ERR(svn_stream_printf(eb->out, pool, "change_dir_prop : %s\n", name)); |
---|
362 | |
---|
363 | SVN_ERR(eb->wrapped_editor->change_dir_prop(db->wrapped_dir_baton, |
---|
364 | name, |
---|
365 | value, |
---|
366 | pool)); |
---|
367 | |
---|
368 | return SVN_NO_ERROR; |
---|
369 | } |
---|
370 | |
---|
371 | static svn_error_t * |
---|
372 | close_edit(void *edit_baton, |
---|
373 | apr_pool_t *pool) |
---|
374 | { |
---|
375 | struct edit_baton *eb = edit_baton; |
---|
376 | |
---|
377 | SVN_ERR(write_indent(eb, pool)); |
---|
378 | SVN_ERR(svn_stream_printf(eb->out, pool, "close_edit\n")); |
---|
379 | |
---|
380 | SVN_ERR(eb->wrapped_editor->close_edit(eb->wrapped_edit_baton, pool)); |
---|
381 | |
---|
382 | return SVN_NO_ERROR; |
---|
383 | } |
---|
384 | |
---|
385 | svn_error_t * |
---|
386 | svn_delta__get_debug_editor(const svn_delta_editor_t **editor, |
---|
387 | void **edit_baton, |
---|
388 | const svn_delta_editor_t *wrapped_editor, |
---|
389 | void *wrapped_edit_baton, |
---|
390 | apr_pool_t *pool) |
---|
391 | { |
---|
392 | svn_delta_editor_t *tree_editor = svn_delta_default_editor(pool); |
---|
393 | struct edit_baton *eb = apr_palloc(pool, sizeof(*eb)); |
---|
394 | apr_file_t *errfp; |
---|
395 | svn_stream_t *out; |
---|
396 | |
---|
397 | apr_status_t apr_err = apr_file_open_stderr(&errfp, pool); |
---|
398 | if (apr_err) |
---|
399 | return svn_error_wrap_apr(apr_err, "Problem opening stderr"); |
---|
400 | |
---|
401 | out = svn_stream_from_aprfile2(errfp, TRUE, pool); |
---|
402 | |
---|
403 | tree_editor->set_target_revision = set_target_revision; |
---|
404 | tree_editor->open_root = open_root; |
---|
405 | tree_editor->delete_entry = delete_entry; |
---|
406 | tree_editor->add_directory = add_directory; |
---|
407 | tree_editor->open_directory = open_directory; |
---|
408 | tree_editor->change_dir_prop = change_dir_prop; |
---|
409 | tree_editor->close_directory = close_directory; |
---|
410 | tree_editor->absent_directory = absent_directory; |
---|
411 | tree_editor->add_file = add_file; |
---|
412 | tree_editor->open_file = open_file; |
---|
413 | tree_editor->apply_textdelta = apply_textdelta; |
---|
414 | tree_editor->change_file_prop = change_file_prop; |
---|
415 | tree_editor->close_file = close_file; |
---|
416 | tree_editor->absent_file = absent_file; |
---|
417 | tree_editor->close_edit = close_edit; |
---|
418 | |
---|
419 | eb->wrapped_editor = wrapped_editor; |
---|
420 | eb->wrapped_edit_baton = wrapped_edit_baton; |
---|
421 | eb->out = out; |
---|
422 | eb->indent_level = 0; |
---|
423 | |
---|
424 | *editor = tree_editor; |
---|
425 | *edit_baton = eb; |
---|
426 | |
---|
427 | return SVN_NO_ERROR; |
---|
428 | } |
---|