3 * ====================================================================
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
20 * ====================================================================
23 * @file svn_diff_tree.h
24 * @brief Generic diff handler. Replacing the old svn_wc_diff_callbacks4_t
28 #ifndef SVN_DIFF_TREE_H
29 #define SVN_DIFF_TREE_H
31 #include "svn_types.h"
35 #endif /* __cplusplus */
38 * About the diff tree processor.
40 * Subversion uses two kinds of editors to describe changes. One to
41 * describe changes on how to *exactly* transform one tree to another tree,
42 * as efficiently as possible and one to describe the difference between trees
43 * in order to review the changes, or to allow applying them on a third tree
44 * which is similar to those other trees.
46 * The first case was originally handled by svn_delta_editor_t and might be
47 * replaced by svn_editor_t in a future version. This diff processor handles
48 * the other case and as such forms the layer below our diff and merge
51 * The major difference between this and the other editors is that this diff
52 * always provides access to the full text and/or properties in the left and
53 * right tree when applicable to allow processor implementers to decide how
54 * to interpret changes.
56 * Originally this diff processor was not formalized explicitly, but
57 * informally handled by the working copy diff callbacks. These callbacks just
58 * provided the information to drive a unified diff and a textual merge. To go
59 * one step further and allow full tree conflict detection we needed a better
60 * defined diff handling. Instead of adding yet a few more functions and
61 * arguments to the already overloaded diff callbacks the api was completely
62 * redesigned with a few points in mind.
64 * * It must be able to drive the old callbacks interface without users
65 * noticing the difference (100% compatible).
66 * (Implemented as svn_wc__wrap_diff_callbacks())
68 * * It should provide the information that was missing in the old interface,
69 * but required to close existing issues.
71 * E.g. - properties and children on deleted directories.
72 * - revision numbers and copyfrom information on directories.
74 * To cleanup the implementation and make it easier on diff processors to
75 * handle the results I also added the following constraints.
77 * * Diffs should be fully reversable: anything that is deleted should be
78 * available, just like something that is added.
79 * (Proven via svn_diff__tree_processor_reverse_create)
80 * ### Still in doubt if *_deleted() needs a copy_to argument, for the
83 * * Diff processors should have an easy way to communicate that they are
84 * not interrested in certain expensive to obtain results.
86 * * Directories should have clear open and close events to allow adding them
87 * before their children, but still allowing property changes to have
90 * * Files and directories should be handled as similar as possible as in
91 * many cases they are just nodes in a tree.
93 * * It should be easy to create diff wrappers to apply certain transforms.
95 * During the creation an additional requirement of knowing about 'some
96 * absent' nodes was added, to allow the merge to work on just this processor
99 * The api describes a clean open-close walk through a tree, depending on the
100 * driver multiple siblings can be described at the same time, but when a
101 * directory is closed all descendants are done.
103 * Note that it is possible for nodes to be described as a delete followed by
104 * an add at the same place within one parent. (Iff the diff is reversed you
105 * can see an add followed by a delete!)
106 * ### "An add followed by a delete" sounds wrong.
108 * The directory batons live between the open and close events of a directory
109 * and are thereby guaranteed to outlive the batons of their descendants.
112 /* Describes the source of a merge */
113 /* ### You mean a diff?
114 * ### How come many users don't set the 'repos_relpath' field? */
115 typedef struct svn_diff_source_t
117 /* Always available */
118 svn_revnum_t revision;
120 /* Depending on the driver available for copyfrom */
122 const char *repos_relpath;
126 * A callback vtable invoked by our diff-editors, as they receive diffs
127 * from the server. 'svn diff' and 'svn merge' implement their own versions
130 * All callbacks receive the processor and at least a parent baton. Forwarding
131 * the processor allows future extensions to call into the old functions without
132 * revving the entire API.
134 * Users must call svn_diff__tree_processor_create() to allow adding new
135 * callbacks later. (E.g. when we decide how to add move support) These
136 * extensions can then just call into other callbacks.
140 typedef struct svn_diff_tree_processor_t
142 /** The value passed to svn_diff__tree_processor_create() as BATON.
144 void *baton; /* To avoid an additional in some places
147 /* Called before a directory's children are processed.
149 * Set *SKIP_CHILDREN to TRUE, to skip calling callbacks for all
152 * Set *SKIP to TRUE to skip calling the added, deleted, changed
153 * or closed callback for this node only.
156 (*dir_opened)(void **new_dir_baton,
158 svn_boolean_t *skip_children,
160 const svn_diff_source_t *left_source,
161 const svn_diff_source_t *right_source,
162 const svn_diff_source_t *copyfrom_source,
163 void *parent_dir_baton,
164 const struct svn_diff_tree_processor_t *processor,
165 apr_pool_t *result_pool,
166 apr_pool_t *scratch_pool);
168 /* Called after a directory and all its children are added
171 (*dir_added)(const char *relpath,
172 const svn_diff_source_t *copyfrom_source,
173 const svn_diff_source_t *right_source,
174 /*const*/ apr_hash_t *copyfrom_props,
175 /*const*/ apr_hash_t *right_props,
177 const struct svn_diff_tree_processor_t *processor,
178 apr_pool_t *scratch_pool);
180 /* Called after all children of this node are reported as deleted.
182 * The default implementation calls dir_closed().
185 (*dir_deleted)(const char *relpath,
186 const svn_diff_source_t *left_source,
187 /*const*/ apr_hash_t *left_props,
189 const struct svn_diff_tree_processor_t *processor,
190 apr_pool_t *scratch_pool);
192 /* Called instead of dir_closed() if the properties on the directory
195 * The default implementation calls dir_closed().
198 (*dir_changed)(const char *relpath,
199 const svn_diff_source_t *left_source,
200 const svn_diff_source_t *right_source,
201 /*const*/ apr_hash_t *left_props,
202 /*const*/ apr_hash_t *right_props,
203 const apr_array_header_t *prop_changes,
205 const struct svn_diff_tree_processor_t *processor,
206 apr_pool_t *scratch_pool);
208 /* Called when a directory is closed without applying changes to
209 * the directory itself.
211 * When dir_changed or dir_deleted are handled by the default implementation
212 * they call dir_closed()
215 (*dir_closed)(const char *relpath,
216 const svn_diff_source_t *left_source,
217 const svn_diff_source_t *right_source,
219 const struct svn_diff_tree_processor_t *processor,
220 apr_pool_t *scratch_pool);
222 /* Called before file_added(), file_deleted(), file_changed() and
226 (*file_opened)(void **new_file_baton,
229 const svn_diff_source_t *left_source,
230 const svn_diff_source_t *right_source,
231 const svn_diff_source_t *copyfrom_source,
233 const struct svn_diff_tree_processor_t *processor,
234 apr_pool_t *result_pool,
235 apr_pool_t *scratch_pool);
237 /* Called after file_opened() for newly added and copied files */
239 (*file_added)(const char *relpath,
240 const svn_diff_source_t *copyfrom_source,
241 const svn_diff_source_t *right_source,
242 const char *copyfrom_file,
243 const char *right_file,
244 /*const*/ apr_hash_t *copyfrom_props,
245 /*const*/ apr_hash_t *right_props,
247 const struct svn_diff_tree_processor_t *processor,
248 apr_pool_t *scratch_pool);
250 /* Called after file_opened() for deleted or moved away files */
252 (*file_deleted)(const char *relpath,
253 const svn_diff_source_t *left_source,
254 const char *left_file,
255 /*const*/ apr_hash_t *left_props,
257 const struct svn_diff_tree_processor_t *processor,
258 apr_pool_t *scratch_pool);
260 /* Called after file_opened() for changed files */
262 (*file_changed)(const char *relpath,
263 const svn_diff_source_t *left_source,
264 const svn_diff_source_t *right_source,
265 const char *left_file,
266 const char *right_file,
267 /*const*/ apr_hash_t *left_props,
268 /*const*/ apr_hash_t *right_props,
269 svn_boolean_t file_modified,
270 const apr_array_header_t *prop_changes,
272 const struct svn_diff_tree_processor_t *processor,
273 apr_pool_t *scratch_pool);
275 /* Called after file_opened() for unmodified files */
277 (*file_closed)(const char *relpath,
278 const svn_diff_source_t *left_source,
279 const svn_diff_source_t *right_source,
281 const struct svn_diff_tree_processor_t *processor,
282 apr_pool_t *scratch_pool);
284 /* Called when encountering a marker for an absent file or directory */
286 (*node_absent)(const char *relpath,
288 const struct svn_diff_tree_processor_t *processor,
289 apr_pool_t *scratch_pool);
290 } svn_diff_tree_processor_t;
293 * Create a new svn_diff_tree_processor_t instance with all functions
294 * set to a callback doing nothing but copying the parent baton to
299 svn_diff_tree_processor_t *
300 svn_diff__tree_processor_create(void *baton,
301 apr_pool_t *result_pool);
304 * Create a new svn_diff_tree_processor_t instance with all functions setup
305 * to call into another svn_diff_tree_processor_t processor, but with all
306 * adds and deletes inverted.
309 */ /* Used by libsvn clients repository diff */
310 const svn_diff_tree_processor_t *
311 svn_diff__tree_processor_reverse_create(const svn_diff_tree_processor_t * processor,
312 const char *prefix_relpath,
313 apr_pool_t *result_pool);
316 * Create a new svn_diff_tree_processor_t instance with all functions setup
317 * to call into processor for all paths equal to and below prefix_relpath.
320 */ /* Used by libsvn clients repository diff */
321 const svn_diff_tree_processor_t *
322 svn_diff__tree_processor_filter_create(const svn_diff_tree_processor_t *processor,
323 const char *prefix_relpath,
324 apr_pool_t *result_pool);
327 * Create a new svn_diff_tree_processor_t instance with all function setup
328 * to call into processor with all adds with copyfrom information transformed
329 * to simple node changes.
332 */ /* Used by libsvn_wc diff editor */
333 const svn_diff_tree_processor_t *
334 svn_diff__tree_processor_copy_as_changed_create(
335 const svn_diff_tree_processor_t *processor,
336 apr_pool_t *result_pool);
340 * Create a new svn_diff_tree_processor_t instance with all functions setup
341 * to first call into processor1 and then processor2.
343 * This function is mostly a debug and migration helper.
346 */ /* Used by libsvn clients repository diff */
347 const svn_diff_tree_processor_t *
348 svn_diff__tree_processor_tee_create(const svn_diff_tree_processor_t *processor1,
349 const svn_diff_tree_processor_t *processor2,
350 apr_pool_t *result_pool);
354 svn_diff__source_create(svn_revnum_t revision,
355 apr_pool_t *result_pool);
359 #endif /* __cplusplus */
361 #endif /* SVN_DIFF_TREE_H */