2 * diff_tree.c : default diff tree processor
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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
21 * ====================================================================
25 #include <apr_pools.h>
26 #include <apr_general.h>
30 #include "svn_dirent_uri.h"
31 #include "svn_error.h"
33 #include "svn_pools.h"
34 #include "svn_props.h"
35 #include "svn_types.h"
37 #include "private/svn_diff_tree.h"
38 #include "svn_private_config.h"
41 default_dir_opened(void **new_dir_baton,
43 svn_boolean_t *skip_children,
45 const svn_diff_source_t *left_source,
46 const svn_diff_source_t *right_source,
47 const svn_diff_source_t *copyfrom_source,
48 void *parent_dir_baton,
49 const svn_diff_tree_processor_t *processor,
50 apr_pool_t *result_pool,
51 apr_pool_t *scratch_pool)
53 *new_dir_baton = NULL;
58 default_dir_added(const char *relpath,
59 const svn_diff_source_t *copyfrom_source,
60 const svn_diff_source_t *right_source,
61 /*const*/ apr_hash_t *copyfrom_props,
62 /*const*/ apr_hash_t *right_props,
64 const svn_diff_tree_processor_t *processor,
65 apr_pool_t *scratch_pool)
67 SVN_ERR(processor->dir_closed(relpath, NULL, right_source,
75 default_dir_deleted(const char *relpath,
76 const svn_diff_source_t *left_source,
77 /*const*/ apr_hash_t *left_props,
79 const svn_diff_tree_processor_t *processor,
80 apr_pool_t *scratch_pool)
82 SVN_ERR(processor->dir_closed(relpath, left_source, NULL,
89 default_dir_changed(const char *relpath,
90 const svn_diff_source_t *left_source,
91 const svn_diff_source_t *right_source,
92 /*const*/ apr_hash_t *left_props,
93 /*const*/ apr_hash_t *right_props,
94 const apr_array_header_t *prop_changes,
96 const struct svn_diff_tree_processor_t *processor,
97 apr_pool_t *scratch_pool)
99 SVN_ERR(processor->dir_closed(relpath,
100 left_source, right_source,
102 processor, scratch_pool));
107 default_dir_closed(const char *relpath,
108 const svn_diff_source_t *left_source,
109 const svn_diff_source_t *right_source,
111 const svn_diff_tree_processor_t *processor,
112 apr_pool_t *scratch_pool)
118 default_file_opened(void **new_file_baton,
121 const svn_diff_source_t *left_source,
122 const svn_diff_source_t *right_source,
123 const svn_diff_source_t *copyfrom_source,
125 const svn_diff_tree_processor_t *processor,
126 apr_pool_t *result_pool,
127 apr_pool_t *scratch_pool)
129 *new_file_baton = dir_baton;
134 default_file_added(const char *relpath,
135 const svn_diff_source_t *copyfrom_source,
136 const svn_diff_source_t *right_source,
137 const char *copyfrom_file,
138 const char *right_file,
139 /*const*/ apr_hash_t *copyfrom_props,
140 /*const*/ apr_hash_t *right_props,
142 const svn_diff_tree_processor_t *processor,
143 apr_pool_t *scratch_pool)
145 SVN_ERR(processor->file_closed(relpath,
147 file_baton, processor, scratch_pool));
152 default_file_deleted(const char *relpath,
153 const svn_diff_source_t *left_source,
154 const char *left_file,
155 /*const*/ apr_hash_t *left_props,
157 const svn_diff_tree_processor_t *processor,
158 apr_pool_t *scratch_pool)
160 SVN_ERR(processor->file_closed(relpath,
162 file_baton, processor, scratch_pool));
167 default_file_changed(const char *relpath,
168 const svn_diff_source_t *left_source,
169 const svn_diff_source_t *right_source,
170 const char *left_file,
171 const char *right_file,
172 /*const*/ apr_hash_t *left_props,
173 /*const*/ apr_hash_t *right_props,
174 svn_boolean_t file_modified,
175 const apr_array_header_t *prop_changes,
177 const svn_diff_tree_processor_t *processor,
178 apr_pool_t *scratch_pool)
180 SVN_ERR(processor->file_closed(relpath,
181 left_source, right_source,
182 file_baton, processor, scratch_pool));
187 default_file_closed(const char *relpath,
188 const svn_diff_source_t *left_source,
189 const svn_diff_source_t *right_source,
191 const svn_diff_tree_processor_t *processor,
192 apr_pool_t *scratch_pool)
198 default_node_absent(const char *relpath,
200 const svn_diff_tree_processor_t *processor,
201 apr_pool_t *scratch_pool)
206 svn_diff_tree_processor_t *
207 svn_diff__tree_processor_create(void *baton,
208 apr_pool_t *result_pool)
210 svn_diff_tree_processor_t *tp = apr_pcalloc(result_pool, sizeof(*tp));
214 tp->dir_opened = default_dir_opened;
215 tp->dir_added = default_dir_added;
216 tp->dir_deleted = default_dir_deleted;
217 tp->dir_changed = default_dir_changed;
218 tp->dir_closed = default_dir_closed;
220 tp->file_opened = default_file_opened;
221 tp->file_added = default_file_added;
222 tp->file_deleted = default_file_deleted;
223 tp->file_changed = default_file_changed;
224 tp->file_closed = default_file_closed;
226 tp->node_absent = default_node_absent;
231 struct reverse_tree_baton_t
233 const svn_diff_tree_processor_t *processor;
237 reverse_dir_opened(void **new_dir_baton,
239 svn_boolean_t *skip_children,
241 const svn_diff_source_t *left_source,
242 const svn_diff_source_t *right_source,
243 const svn_diff_source_t *copyfrom_source,
244 void *parent_dir_baton,
245 const svn_diff_tree_processor_t *processor,
246 apr_pool_t *result_pool,
247 apr_pool_t *scratch_pool)
249 struct reverse_tree_baton_t *rb = processor->baton;
251 SVN_ERR(rb->processor->dir_opened(new_dir_baton, skip, skip_children,
253 right_source, left_source,
257 result_pool, scratch_pool));
262 reverse_dir_added(const char *relpath,
263 const svn_diff_source_t *copyfrom_source,
264 const svn_diff_source_t *right_source,
265 /*const*/ apr_hash_t *copyfrom_props,
266 /*const*/ apr_hash_t *right_props,
268 const svn_diff_tree_processor_t *processor,
269 apr_pool_t *scratch_pool)
271 struct reverse_tree_baton_t *rb = processor->baton;
273 SVN_ERR(rb->processor->dir_deleted(relpath,
284 reverse_dir_deleted(const char *relpath,
285 const svn_diff_source_t *left_source,
286 /*const*/ apr_hash_t *left_props,
288 const svn_diff_tree_processor_t *processor,
289 apr_pool_t *scratch_pool)
291 struct reverse_tree_baton_t *rb = processor->baton;
293 SVN_ERR(rb->processor->dir_added(relpath,
305 reverse_dir_changed(const char *relpath,
306 const svn_diff_source_t *left_source,
307 const svn_diff_source_t *right_source,
308 /*const*/ apr_hash_t *left_props,
309 /*const*/ apr_hash_t *right_props,
310 const apr_array_header_t *prop_changes,
312 const struct svn_diff_tree_processor_t *processor,
313 apr_pool_t *scratch_pool)
315 struct reverse_tree_baton_t *rb = processor->baton;
316 apr_array_header_t *reversed_prop_changes = NULL;
320 SVN_ERR_ASSERT(left_props != NULL && right_props != NULL);
321 SVN_ERR(svn_prop_diffs(&reversed_prop_changes, left_props, right_props,
325 SVN_ERR(rb->processor->dir_changed(relpath,
330 reversed_prop_changes,
338 reverse_dir_closed(const char *relpath,
339 const svn_diff_source_t *left_source,
340 const svn_diff_source_t *right_source,
342 const svn_diff_tree_processor_t *processor,
343 apr_pool_t *scratch_pool)
345 struct reverse_tree_baton_t *rb = processor->baton;
347 SVN_ERR(rb->processor->dir_closed(relpath,
357 reverse_file_opened(void **new_file_baton,
360 const svn_diff_source_t *left_source,
361 const svn_diff_source_t *right_source,
362 const svn_diff_source_t *copyfrom_source,
364 const svn_diff_tree_processor_t *processor,
365 apr_pool_t *result_pool,
366 apr_pool_t *scratch_pool)
368 struct reverse_tree_baton_t *rb = processor->baton;
370 SVN_ERR(rb->processor->file_opened(new_file_baton,
375 NULL /* copy_from */,
384 reverse_file_added(const char *relpath,
385 const svn_diff_source_t *copyfrom_source,
386 const svn_diff_source_t *right_source,
387 const char *copyfrom_file,
388 const char *right_file,
389 /*const*/ apr_hash_t *copyfrom_props,
390 /*const*/ apr_hash_t *right_props,
392 const svn_diff_tree_processor_t *processor,
393 apr_pool_t *scratch_pool)
395 struct reverse_tree_baton_t *rb = processor->baton;
397 SVN_ERR(rb->processor->file_deleted(relpath,
408 reverse_file_deleted(const char *relpath,
409 const svn_diff_source_t *left_source,
410 const char *left_file,
411 /*const*/ apr_hash_t *left_props,
413 const svn_diff_tree_processor_t *processor,
414 apr_pool_t *scratch_pool)
416 struct reverse_tree_baton_t *rb = processor->baton;
418 SVN_ERR(rb->processor->file_added(relpath,
419 NULL /* copyfrom src */,
421 NULL /* copyfrom file */,
423 NULL /* copyfrom props */,
432 reverse_file_changed(const char *relpath,
433 const svn_diff_source_t *left_source,
434 const svn_diff_source_t *right_source,
435 const char *left_file,
436 const char *right_file,
437 /*const*/ apr_hash_t *left_props,
438 /*const*/ apr_hash_t *right_props,
439 svn_boolean_t file_modified,
440 const apr_array_header_t *prop_changes,
442 const svn_diff_tree_processor_t *processor,
443 apr_pool_t *scratch_pool)
445 struct reverse_tree_baton_t *rb = processor->baton;
446 apr_array_header_t *reversed_prop_changes = NULL;
450 SVN_ERR_ASSERT(left_props != NULL && right_props != NULL);
451 SVN_ERR(svn_prop_diffs(&reversed_prop_changes, left_props, right_props,
455 SVN_ERR(rb->processor->file_changed(relpath,
463 reversed_prop_changes,
471 reverse_file_closed(const char *relpath,
472 const svn_diff_source_t *left_source,
473 const svn_diff_source_t *right_source,
475 const svn_diff_tree_processor_t *processor,
476 apr_pool_t *scratch_pool)
478 struct reverse_tree_baton_t *rb = processor->baton;
480 SVN_ERR(rb->processor->file_closed(relpath,
491 reverse_node_absent(const char *relpath,
493 const svn_diff_tree_processor_t *processor,
494 apr_pool_t *scratch_pool)
496 struct reverse_tree_baton_t *rb = processor->baton;
498 SVN_ERR(rb->processor->node_absent(relpath,
506 const svn_diff_tree_processor_t *
507 svn_diff__tree_processor_reverse_create(const svn_diff_tree_processor_t * processor,
508 apr_pool_t *result_pool)
510 struct reverse_tree_baton_t *rb;
511 svn_diff_tree_processor_t *reverse;
513 rb = apr_pcalloc(result_pool, sizeof(*rb));
514 rb->processor = processor;
516 reverse = svn_diff__tree_processor_create(rb, result_pool);
518 reverse->dir_opened = reverse_dir_opened;
519 reverse->dir_added = reverse_dir_added;
520 reverse->dir_deleted = reverse_dir_deleted;
521 reverse->dir_changed = reverse_dir_changed;
522 reverse->dir_closed = reverse_dir_closed;
524 reverse->file_opened = reverse_file_opened;
525 reverse->file_added = reverse_file_added;
526 reverse->file_deleted = reverse_file_deleted;
527 reverse->file_changed = reverse_file_changed;
528 reverse->file_closed = reverse_file_closed;
530 reverse->node_absent = reverse_node_absent;
535 struct filter_tree_baton_t
537 const svn_diff_tree_processor_t *processor;
538 const char *prefix_relpath;
542 filter_dir_opened(void **new_dir_baton,
544 svn_boolean_t *skip_children,
546 const svn_diff_source_t *left_source,
547 const svn_diff_source_t *right_source,
548 const svn_diff_source_t *copyfrom_source,
549 void *parent_dir_baton,
550 const svn_diff_tree_processor_t *processor,
551 apr_pool_t *result_pool,
552 apr_pool_t *scratch_pool)
554 struct filter_tree_baton_t *fb = processor->baton;
556 relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath);
560 /* Skip work for this, but NOT for DESCENDANTS */
565 SVN_ERR(fb->processor->dir_opened(new_dir_baton, skip, skip_children,
567 left_source, right_source,
571 result_pool, scratch_pool));
576 filter_dir_added(const char *relpath,
577 const svn_diff_source_t *copyfrom_source,
578 const svn_diff_source_t *right_source,
579 /*const*/ apr_hash_t *copyfrom_props,
580 /*const*/ apr_hash_t *right_props,
582 const svn_diff_tree_processor_t *processor,
583 apr_pool_t *scratch_pool)
585 struct filter_tree_baton_t *fb = processor->baton;
587 relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath);
588 assert(relpath != NULL); /* Driver error */
590 SVN_ERR(fb->processor->dir_added(relpath,
603 filter_dir_deleted(const char *relpath,
604 const svn_diff_source_t *left_source,
605 /*const*/ apr_hash_t *left_props,
607 const svn_diff_tree_processor_t *processor,
608 apr_pool_t *scratch_pool)
610 struct filter_tree_baton_t *fb = processor->baton;
612 relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath);
613 assert(relpath != NULL); /* Driver error */
615 SVN_ERR(fb->processor->dir_deleted(relpath,
626 filter_dir_changed(const char *relpath,
627 const svn_diff_source_t *left_source,
628 const svn_diff_source_t *right_source,
629 /*const*/ apr_hash_t *left_props,
630 /*const*/ apr_hash_t *right_props,
631 const apr_array_header_t *prop_changes,
633 const struct svn_diff_tree_processor_t *processor,
634 apr_pool_t *scratch_pool)
636 struct filter_tree_baton_t *fb = processor->baton;
638 relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath);
639 assert(relpath != NULL); /* Driver error */
641 SVN_ERR(fb->processor->dir_changed(relpath,
654 filter_dir_closed(const char *relpath,
655 const svn_diff_source_t *left_source,
656 const svn_diff_source_t *right_source,
658 const svn_diff_tree_processor_t *processor,
659 apr_pool_t *scratch_pool)
661 struct filter_tree_baton_t *fb = processor->baton;
663 relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath);
664 assert(relpath != NULL); /* Driver error */
666 SVN_ERR(fb->processor->dir_closed(relpath,
676 filter_file_opened(void **new_file_baton,
679 const svn_diff_source_t *left_source,
680 const svn_diff_source_t *right_source,
681 const svn_diff_source_t *copyfrom_source,
683 const svn_diff_tree_processor_t *processor,
684 apr_pool_t *result_pool,
685 apr_pool_t *scratch_pool)
687 struct filter_tree_baton_t *fb = processor->baton;
689 relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath);
697 SVN_ERR(fb->processor->file_opened(new_file_baton,
711 filter_file_added(const char *relpath,
712 const svn_diff_source_t *copyfrom_source,
713 const svn_diff_source_t *right_source,
714 const char *copyfrom_file,
715 const char *right_file,
716 /*const*/ apr_hash_t *copyfrom_props,
717 /*const*/ apr_hash_t *right_props,
719 const svn_diff_tree_processor_t *processor,
720 apr_pool_t *scratch_pool)
722 struct filter_tree_baton_t *fb = processor->baton;
724 relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath);
725 assert(relpath != NULL); /* Driver error */
727 SVN_ERR(fb->processor->file_added(relpath,
741 filter_file_deleted(const char *relpath,
742 const svn_diff_source_t *left_source,
743 const char *left_file,
744 /*const*/ apr_hash_t *left_props,
746 const svn_diff_tree_processor_t *processor,
747 apr_pool_t *scratch_pool)
749 struct filter_tree_baton_t *fb = processor->baton;
751 relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath);
752 assert(relpath != NULL); /* Driver error */
754 SVN_ERR(fb->processor->file_deleted(relpath,
766 filter_file_changed(const char *relpath,
767 const svn_diff_source_t *left_source,
768 const svn_diff_source_t *right_source,
769 const char *left_file,
770 const char *right_file,
771 /*const*/ apr_hash_t *left_props,
772 /*const*/ apr_hash_t *right_props,
773 svn_boolean_t file_modified,
774 const apr_array_header_t *prop_changes,
776 const svn_diff_tree_processor_t *processor,
777 apr_pool_t *scratch_pool)
779 struct filter_tree_baton_t *fb = processor->baton;
781 relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath);
782 assert(relpath != NULL); /* Driver error */
784 SVN_ERR(fb->processor->file_changed(relpath,
800 filter_file_closed(const char *relpath,
801 const svn_diff_source_t *left_source,
802 const svn_diff_source_t *right_source,
804 const svn_diff_tree_processor_t *processor,
805 apr_pool_t *scratch_pool)
807 struct filter_tree_baton_t *fb = processor->baton;
809 relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath);
810 assert(relpath != NULL); /* Driver error */
812 SVN_ERR(fb->processor->file_closed(relpath,
823 filter_node_absent(const char *relpath,
825 const svn_diff_tree_processor_t *processor,
826 apr_pool_t *scratch_pool)
828 struct filter_tree_baton_t *fb = processor->baton;
830 relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath);
831 assert(relpath != NULL); /* Driver error */
833 SVN_ERR(fb->processor->node_absent(relpath,
841 const svn_diff_tree_processor_t *
842 svn_diff__tree_processor_filter_create(const svn_diff_tree_processor_t * processor,
843 const char *prefix_relpath,
844 apr_pool_t *result_pool)
846 struct filter_tree_baton_t *fb;
847 svn_diff_tree_processor_t *filter;
849 fb = apr_pcalloc(result_pool, sizeof(*fb));
850 fb->processor = processor;
852 fb->prefix_relpath = apr_pstrdup(result_pool, prefix_relpath);
854 filter = svn_diff__tree_processor_create(fb, result_pool);
856 filter->dir_opened = filter_dir_opened;
857 filter->dir_added = filter_dir_added;
858 filter->dir_deleted = filter_dir_deleted;
859 filter->dir_changed = filter_dir_changed;
860 filter->dir_closed = filter_dir_closed;
862 filter->file_opened = filter_file_opened;
863 filter->file_added = filter_file_added;
864 filter->file_deleted = filter_file_deleted;
865 filter->file_changed = filter_file_changed;
866 filter->file_closed = filter_file_closed;
868 filter->node_absent = filter_node_absent;
873 struct copy_as_changed_baton_t
875 const svn_diff_tree_processor_t *processor;
879 copy_as_changed_dir_opened(void **new_dir_baton,
881 svn_boolean_t *skip_children,
883 const svn_diff_source_t *left_source,
884 const svn_diff_source_t *right_source,
885 const svn_diff_source_t *copyfrom_source,
886 void *parent_dir_baton,
887 const svn_diff_tree_processor_t *processor,
888 apr_pool_t *result_pool,
889 apr_pool_t *scratch_pool)
891 struct copy_as_changed_baton_t *cb = processor->baton;
893 if (!left_source && copyfrom_source)
895 assert(right_source != NULL);
897 left_source = copyfrom_source;
898 copyfrom_source = NULL;
901 SVN_ERR(cb->processor->dir_opened(new_dir_baton, skip, skip_children,
903 left_source, right_source,
907 result_pool, scratch_pool));
912 copy_as_changed_dir_added(const char *relpath,
913 const svn_diff_source_t *copyfrom_source,
914 const svn_diff_source_t *right_source,
915 /*const*/ apr_hash_t *copyfrom_props,
916 /*const*/ apr_hash_t *right_props,
918 const svn_diff_tree_processor_t *processor,
919 apr_pool_t *scratch_pool)
921 struct copy_as_changed_baton_t *cb = processor->baton;
925 apr_array_header_t *propchanges;
926 SVN_ERR(svn_prop_diffs(&propchanges, right_props, copyfrom_props,
928 SVN_ERR(cb->processor->dir_changed(relpath,
940 SVN_ERR(cb->processor->dir_added(relpath,
954 copy_as_changed_dir_deleted(const char *relpath,
955 const svn_diff_source_t *left_source,
956 /*const*/ apr_hash_t *left_props,
958 const svn_diff_tree_processor_t *processor,
959 apr_pool_t *scratch_pool)
961 struct copy_as_changed_baton_t *cb = processor->baton;
963 SVN_ERR(cb->processor->dir_deleted(relpath,
974 copy_as_changed_dir_changed(const char *relpath,
975 const svn_diff_source_t *left_source,
976 const svn_diff_source_t *right_source,
977 /*const*/ apr_hash_t *left_props,
978 /*const*/ apr_hash_t *right_props,
979 const apr_array_header_t *prop_changes,
981 const struct svn_diff_tree_processor_t *processor,
982 apr_pool_t *scratch_pool)
984 struct copy_as_changed_baton_t *cb = processor->baton;
986 SVN_ERR(cb->processor->dir_changed(relpath,
999 copy_as_changed_dir_closed(const char *relpath,
1000 const svn_diff_source_t *left_source,
1001 const svn_diff_source_t *right_source,
1003 const svn_diff_tree_processor_t *processor,
1004 apr_pool_t *scratch_pool)
1006 struct copy_as_changed_baton_t *cb = processor->baton;
1008 SVN_ERR(cb->processor->dir_closed(relpath,
1014 return SVN_NO_ERROR;
1017 static svn_error_t *
1018 copy_as_changed_file_opened(void **new_file_baton,
1019 svn_boolean_t *skip,
1020 const char *relpath,
1021 const svn_diff_source_t *left_source,
1022 const svn_diff_source_t *right_source,
1023 const svn_diff_source_t *copyfrom_source,
1025 const svn_diff_tree_processor_t *processor,
1026 apr_pool_t *result_pool,
1027 apr_pool_t *scratch_pool)
1029 struct copy_as_changed_baton_t *cb = processor->baton;
1031 if (!left_source && copyfrom_source)
1033 assert(right_source != NULL);
1035 left_source = copyfrom_source;
1036 copyfrom_source = NULL;
1039 SVN_ERR(cb->processor->file_opened(new_file_baton,
1049 return SVN_NO_ERROR;
1052 static svn_error_t *
1053 copy_as_changed_file_added(const char *relpath,
1054 const svn_diff_source_t *copyfrom_source,
1055 const svn_diff_source_t *right_source,
1056 const char *copyfrom_file,
1057 const char *right_file,
1058 /*const*/ apr_hash_t *copyfrom_props,
1059 /*const*/ apr_hash_t *right_props,
1061 const svn_diff_tree_processor_t *processor,
1062 apr_pool_t *scratch_pool)
1064 struct copy_as_changed_baton_t *cb = processor->baton;
1066 if (copyfrom_source)
1068 apr_array_header_t *propchanges;
1070 SVN_ERR(svn_prop_diffs(&propchanges, right_props, copyfrom_props,
1073 /* "" is sometimes a marker for just modified (E.g. no-textdeltas),
1074 and it is certainly not a file */
1075 if (*copyfrom_file && *right_file)
1077 SVN_ERR(svn_io_files_contents_same_p(&same, copyfrom_file,
1078 right_file, scratch_pool));
1083 SVN_ERR(cb->processor->file_changed(relpath,
1098 SVN_ERR(cb->processor->file_added(relpath,
1109 return SVN_NO_ERROR;
1112 static svn_error_t *
1113 copy_as_changed_file_deleted(const char *relpath,
1114 const svn_diff_source_t *left_source,
1115 const char *left_file,
1116 /*const*/ apr_hash_t *left_props,
1118 const svn_diff_tree_processor_t *processor,
1119 apr_pool_t *scratch_pool)
1121 struct copy_as_changed_baton_t *cb = processor->baton;
1123 SVN_ERR(cb->processor->file_deleted(relpath,
1131 return SVN_NO_ERROR;
1134 static svn_error_t *
1135 copy_as_changed_file_changed(const char *relpath,
1136 const svn_diff_source_t *left_source,
1137 const svn_diff_source_t *right_source,
1138 const char *left_file,
1139 const char *right_file,
1140 /*const*/ apr_hash_t *left_props,
1141 /*const*/ apr_hash_t *right_props,
1142 svn_boolean_t file_modified,
1143 const apr_array_header_t *prop_changes,
1145 const svn_diff_tree_processor_t *processor,
1146 apr_pool_t *scratch_pool)
1148 struct copy_as_changed_baton_t *cb = processor->baton;
1150 SVN_ERR(cb->processor->file_changed(relpath,
1162 return SVN_NO_ERROR;
1165 static svn_error_t *
1166 copy_as_changed_file_closed(const char *relpath,
1167 const svn_diff_source_t *left_source,
1168 const svn_diff_source_t *right_source,
1170 const svn_diff_tree_processor_t *processor,
1171 apr_pool_t *scratch_pool)
1173 struct copy_as_changed_baton_t *cb = processor->baton;
1175 SVN_ERR(cb->processor->file_closed(relpath,
1182 return SVN_NO_ERROR;
1185 static svn_error_t *
1186 copy_as_changed_node_absent(const char *relpath,
1188 const svn_diff_tree_processor_t *processor,
1189 apr_pool_t *scratch_pool)
1191 struct copy_as_changed_baton_t *cb = processor->baton;
1193 SVN_ERR(cb->processor->node_absent(relpath,
1197 return SVN_NO_ERROR;
1201 const svn_diff_tree_processor_t *
1202 svn_diff__tree_processor_copy_as_changed_create(
1203 const svn_diff_tree_processor_t * processor,
1204 apr_pool_t *result_pool)
1206 struct copy_as_changed_baton_t *cb;
1207 svn_diff_tree_processor_t *filter;
1209 cb = apr_pcalloc(result_pool, sizeof(*cb));
1210 cb->processor = processor;
1212 filter = svn_diff__tree_processor_create(cb, result_pool);
1213 filter->dir_opened = copy_as_changed_dir_opened;
1214 filter->dir_added = copy_as_changed_dir_added;
1215 filter->dir_deleted = copy_as_changed_dir_deleted;
1216 filter->dir_changed = copy_as_changed_dir_changed;
1217 filter->dir_closed = copy_as_changed_dir_closed;
1219 filter->file_opened = copy_as_changed_file_opened;
1220 filter->file_added = copy_as_changed_file_added;
1221 filter->file_deleted = copy_as_changed_file_deleted;
1222 filter->file_changed = copy_as_changed_file_changed;
1223 filter->file_closed = copy_as_changed_file_closed;
1225 filter->node_absent = copy_as_changed_node_absent;
1231 /* Processor baton for the tee tree processor */
1234 const svn_diff_tree_processor_t *p1;
1235 const svn_diff_tree_processor_t *p2;
1238 /* Wrapper baton for file and directory batons in the tee processor */
1239 struct tee_node_baton_t
1245 static svn_error_t *
1246 tee_dir_opened(void **new_dir_baton,
1247 svn_boolean_t *skip,
1248 svn_boolean_t *skip_children,
1249 const char *relpath,
1250 const svn_diff_source_t *left_source,
1251 const svn_diff_source_t *right_source,
1252 const svn_diff_source_t *copyfrom_source,
1253 void *parent_dir_baton,
1254 const svn_diff_tree_processor_t *processor,
1255 apr_pool_t *result_pool,
1256 apr_pool_t *scratch_pool)
1258 struct tee_baton_t *tb = processor->baton;
1259 struct tee_node_baton_t *pb = parent_dir_baton;
1260 struct tee_node_baton_t *nb = apr_pcalloc(result_pool, sizeof(*nb));
1262 SVN_ERR(tb->p1->dir_opened(&(nb->baton1),
1269 pb ? pb->baton1 : NULL,
1274 SVN_ERR(tb->p2->dir_opened(&(nb->baton2),
1281 pb ? pb->baton2 : NULL,
1286 *new_dir_baton = nb;
1288 return SVN_NO_ERROR;
1291 static svn_error_t *
1292 tee_dir_added(const char *relpath,
1293 const svn_diff_source_t *copyfrom_source,
1294 const svn_diff_source_t *right_source,
1295 /*const*/ apr_hash_t *copyfrom_props,
1296 /*const*/ apr_hash_t *right_props,
1298 const svn_diff_tree_processor_t *processor,
1299 apr_pool_t *scratch_pool)
1301 struct tee_baton_t *tb = processor->baton;
1302 struct tee_node_baton_t *db = dir_baton;
1304 SVN_ERR(tb->p1->dir_added(relpath,
1313 SVN_ERR(tb->p2->dir_added(relpath,
1322 return SVN_NO_ERROR;
1325 static svn_error_t *
1326 tee_dir_deleted(const char *relpath,
1327 const svn_diff_source_t *left_source,
1328 /*const*/ apr_hash_t *left_props,
1330 const svn_diff_tree_processor_t *processor,
1331 apr_pool_t *scratch_pool)
1333 struct tee_baton_t *tb = processor->baton;
1334 struct tee_node_baton_t *db = dir_baton;
1336 SVN_ERR(tb->p1->dir_deleted(relpath,
1343 SVN_ERR(tb->p2->dir_deleted(relpath,
1350 return SVN_NO_ERROR;
1353 static svn_error_t *
1354 tee_dir_changed(const char *relpath,
1355 const svn_diff_source_t *left_source,
1356 const svn_diff_source_t *right_source,
1357 /*const*/ apr_hash_t *left_props,
1358 /*const*/ apr_hash_t *right_props,
1359 const apr_array_header_t *prop_changes,
1361 const struct svn_diff_tree_processor_t *processor,
1362 apr_pool_t *scratch_pool)
1364 struct tee_baton_t *tb = processor->baton;
1365 struct tee_node_baton_t *db = dir_baton;
1367 SVN_ERR(tb->p1->dir_changed(relpath,
1377 SVN_ERR(tb->p2->dir_changed(relpath,
1386 return SVN_NO_ERROR;
1389 static svn_error_t *
1390 tee_dir_closed(const char *relpath,
1391 const svn_diff_source_t *left_source,
1392 const svn_diff_source_t *right_source,
1394 const svn_diff_tree_processor_t *processor,
1395 apr_pool_t *scratch_pool)
1397 struct tee_baton_t *tb = processor->baton;
1398 struct tee_node_baton_t *db = dir_baton;
1400 SVN_ERR(tb->p1->dir_closed(relpath,
1407 SVN_ERR(tb->p2->dir_closed(relpath,
1413 return SVN_NO_ERROR;
1416 static svn_error_t *
1417 tee_file_opened(void **new_file_baton,
1418 svn_boolean_t *skip,
1419 const char *relpath,
1420 const svn_diff_source_t *left_source,
1421 const svn_diff_source_t *right_source,
1422 const svn_diff_source_t *copyfrom_source,
1424 const svn_diff_tree_processor_t *processor,
1425 apr_pool_t *result_pool,
1426 apr_pool_t *scratch_pool)
1428 struct tee_baton_t *tb = processor->baton;
1429 struct tee_node_baton_t *pb = dir_baton;
1430 struct tee_node_baton_t *nb = apr_pcalloc(result_pool, sizeof(*nb));
1432 SVN_ERR(tb->p1->file_opened(&(nb->baton1),
1438 pb ? pb->baton1 : NULL,
1443 SVN_ERR(tb->p2->file_opened(&(nb->baton2),
1449 pb ? pb->baton2 : NULL,
1454 *new_file_baton = nb;
1456 return SVN_NO_ERROR;
1459 static svn_error_t *
1460 tee_file_added(const char *relpath,
1461 const svn_diff_source_t *copyfrom_source,
1462 const svn_diff_source_t *right_source,
1463 const char *copyfrom_file,
1464 const char *right_file,
1465 /*const*/ apr_hash_t *copyfrom_props,
1466 /*const*/ apr_hash_t *right_props,
1468 const svn_diff_tree_processor_t *processor,
1469 apr_pool_t *scratch_pool)
1471 struct tee_baton_t *tb = processor->baton;
1472 struct tee_node_baton_t *fb = file_baton;
1474 SVN_ERR(tb->p1->file_added(relpath,
1485 SVN_ERR(tb->p2->file_added(relpath,
1495 return SVN_NO_ERROR;
1498 static svn_error_t *
1499 tee_file_deleted(const char *relpath,
1500 const svn_diff_source_t *left_source,
1501 const char *left_file,
1502 /*const*/ apr_hash_t *left_props,
1504 const svn_diff_tree_processor_t *processor,
1505 apr_pool_t *scratch_pool)
1507 struct tee_baton_t *tb = processor->baton;
1508 struct tee_node_baton_t *fb = file_baton;
1510 SVN_ERR(tb->p1->file_deleted(relpath,
1518 SVN_ERR(tb->p2->file_deleted(relpath,
1525 return SVN_NO_ERROR;
1528 static svn_error_t *
1529 tee_file_changed(const char *relpath,
1530 const svn_diff_source_t *left_source,
1531 const svn_diff_source_t *right_source,
1532 const char *left_file,
1533 const char *right_file,
1534 /*const*/ apr_hash_t *left_props,
1535 /*const*/ apr_hash_t *right_props,
1536 svn_boolean_t file_modified,
1537 const apr_array_header_t *prop_changes,
1539 const svn_diff_tree_processor_t *processor,
1540 apr_pool_t *scratch_pool)
1542 struct tee_baton_t *tb = processor->baton;
1543 struct tee_node_baton_t *fb = file_baton;
1545 SVN_ERR(tb->p1->file_changed(relpath,
1558 SVN_ERR(tb->p2->file_changed(relpath,
1570 return SVN_NO_ERROR;
1573 static svn_error_t *
1574 tee_file_closed(const char *relpath,
1575 const svn_diff_source_t *left_source,
1576 const svn_diff_source_t *right_source,
1578 const svn_diff_tree_processor_t *processor,
1579 apr_pool_t *scratch_pool)
1581 struct tee_baton_t *tb = processor->baton;
1582 struct tee_node_baton_t *fb = file_baton;
1584 SVN_ERR(tb->p1->file_closed(relpath,
1591 SVN_ERR(tb->p2->file_closed(relpath,
1598 return SVN_NO_ERROR;
1601 static svn_error_t *
1602 tee_node_absent(const char *relpath,
1604 const svn_diff_tree_processor_t *processor,
1605 apr_pool_t *scratch_pool)
1607 struct tee_baton_t *tb = processor->baton;
1608 struct tee_node_baton_t *db = dir_baton;
1610 SVN_ERR(tb->p1->node_absent(relpath,
1611 db ? db->baton1 : NULL,
1615 SVN_ERR(tb->p2->node_absent(relpath,
1616 db ? db->baton2 : NULL,
1620 return SVN_NO_ERROR;
1623 const svn_diff_tree_processor_t *
1624 svn_diff__tree_processor_tee_create(const svn_diff_tree_processor_t *processor1,
1625 const svn_diff_tree_processor_t *processor2,
1626 apr_pool_t *result_pool)
1628 struct tee_baton_t *tb = apr_pcalloc(result_pool, sizeof(*tb));
1629 svn_diff_tree_processor_t *tee;
1630 tb->p1 = processor1;
1631 tb->p2 = processor2;
1633 tee = svn_diff__tree_processor_create(tb, result_pool);
1635 tee->dir_opened = tee_dir_opened;
1636 tee->dir_added = tee_dir_added;
1637 tee->dir_deleted = tee_dir_deleted;
1638 tee->dir_changed = tee_dir_changed;
1639 tee->dir_closed = tee_dir_closed;
1640 tee->file_opened = tee_file_opened;
1641 tee->file_added = tee_file_added;
1642 tee->file_deleted = tee_file_deleted;
1643 tee->file_changed = tee_file_changed;
1644 tee->file_closed = tee_file_closed;
1645 tee->node_absent = tee_node_absent;
1651 svn_diff__source_create(svn_revnum_t revision,
1652 apr_pool_t *result_pool)
1654 svn_diff_source_t *src = apr_pcalloc(result_pool, sizeof(*src));
1656 src->revision = revision;