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 * ====================================================================
24 * @brief Generic diff handler. Replacing the old svn_wc_diff_callbacks4_t
28 #ifndef SVN_DIFF_PROCESSOR_H
29 #define SVN_DIFF_PROCESSOR_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!)
107 * The directory batons live between the open and close events of a directory
108 * and are thereby guaranteed to outlive the batons of their descendants.
111 /* Describes the source of a merge */
112 typedef struct svn_diff_source_t
114 /* Always available */
115 svn_revnum_t revision;
117 /* Depending on the driver available for copyfrom */
118 const char *repos_relpath;
122 * A callback vtable invoked by our diff-editors, as they receive diffs
123 * from the server. 'svn diff' and 'svn merge' implement their own versions
126 * All callbacks receive the processor and at least a parent baton. Forwarding
127 * the processor allows future extensions to call into the old functions without
128 * revving the entire API.
130 * Users must call svn_diff__tree_processor_create() to allow adding new
131 * callbacks later. (E.g. when we decide how to add move support) These
132 * extensions can then just call into other callbacks.
136 typedef struct svn_diff_tree_processor_t
138 /** The value passed to svn_diff__tree_processor_create() as BATON.
140 void *baton; /* To avoid an additional in some places */
142 /* Called before a directories children are processed.
144 * Set *SKIP_CHILDREN to TRUE, to skip calling callbacks for all
147 * Set *SKIP to TRUE to skip calling the added, deleted, changed
148 * or closed callback for this node only.
151 (*dir_opened)(void **new_dir_baton,
153 svn_boolean_t *skip_children,
155 const svn_diff_source_t *left_source,
156 const svn_diff_source_t *right_source,
157 const svn_diff_source_t *copyfrom_source,
158 void *parent_dir_baton,
159 const struct svn_diff_tree_processor_t *processor,
160 apr_pool_t *result_pool,
161 apr_pool_t *scratch_pool);
163 /* Called after a directory and all its children are added
166 (*dir_added)(const char *relpath,
167 const svn_diff_source_t *copyfrom_source,
168 const svn_diff_source_t *right_source,
169 /*const*/ apr_hash_t *copyfrom_props,
170 /*const*/ apr_hash_t *right_props,
172 const struct svn_diff_tree_processor_t *processor,
173 apr_pool_t *scratch_pool);
175 /* Called after all children of this node are reported as deleted.
177 * The default implementation calls dir_closed().
180 (*dir_deleted)(const char *relpath,
181 const svn_diff_source_t *left_source,
182 /*const*/ apr_hash_t *left_props,
184 const struct svn_diff_tree_processor_t *processor,
185 apr_pool_t *scratch_pool);
187 /* Called instead of dir_closed() if the properties on the directory
190 * The default implementation calls dir_closed().
193 (*dir_changed)(const char *relpath,
194 const svn_diff_source_t *left_source,
195 const svn_diff_source_t *right_source,
196 /*const*/ apr_hash_t *left_props,
197 /*const*/ apr_hash_t *right_props,
198 const apr_array_header_t *prop_changes,
200 const struct svn_diff_tree_processor_t *processor,
201 apr_pool_t *scratch_pool);
203 /* Called when a directory is closed without applying changes to
204 * the directory itself.
206 * When dir_changed or dir_deleted are handled by the default implementation
207 * they call dir_closed()
210 (*dir_closed)(const char *relpath,
211 const svn_diff_source_t *left_source,
212 const svn_diff_source_t *right_source,
214 const struct svn_diff_tree_processor_t *processor,
215 apr_pool_t *scratch_pool);
217 /* Called before file_added(), file_deleted(), file_changed() and
221 (*file_opened)(void **new_file_baton,
224 const svn_diff_source_t *left_source,
225 const svn_diff_source_t *right_source,
226 const svn_diff_source_t *copyfrom_source,
228 const struct svn_diff_tree_processor_t *processor,
229 apr_pool_t *result_pool,
230 apr_pool_t *scratch_pool);
232 /* Called after file_opened() for newly added and copied files */
234 (*file_added)(const char *relpath,
235 const svn_diff_source_t *copyfrom_source,
236 const svn_diff_source_t *right_source,
237 const char *copyfrom_file,
238 const char *right_file,
239 /*const*/ apr_hash_t *copyfrom_props,
240 /*const*/ apr_hash_t *right_props,
242 const struct svn_diff_tree_processor_t *processor,
243 apr_pool_t *scratch_pool);
245 /* Called after file_opened() for deleted or moved away files */
247 (*file_deleted)(const char *relpath,
248 const svn_diff_source_t *left_source,
249 const char *left_file,
250 /*const*/ apr_hash_t *left_props,
252 const struct svn_diff_tree_processor_t *processor,
253 apr_pool_t *scratch_pool);
255 /* Called after file_opened() for changed files */
257 (*file_changed)(const char *relpath,
258 const svn_diff_source_t *left_source,
259 const svn_diff_source_t *right_source,
260 const char *left_file,
261 const char *right_file,
262 /*const*/ apr_hash_t *left_props,
263 /*const*/ apr_hash_t *right_props,
264 svn_boolean_t file_modified,
265 const apr_array_header_t *prop_changes,
267 const struct svn_diff_tree_processor_t *processor,
268 apr_pool_t *scratch_pool);
270 /* Called after file_opened() for unmodified files */
272 (*file_closed)(const char *relpath,
273 const svn_diff_source_t *left_source,
274 const svn_diff_source_t *right_source,
276 const struct svn_diff_tree_processor_t *processor,
277 apr_pool_t *scratch_pool);
279 /* Called when encountering a marker for an absent file or directory */
281 (*node_absent)(const char *relpath,
283 const struct svn_diff_tree_processor_t *processor,
284 apr_pool_t *scratch_pool);
285 } svn_diff_tree_processor_t;
288 * Create a new svn_diff_tree_processor_t instance with all functions
289 * set to a callback doing nothing but copying the parent baton to
294 svn_diff_tree_processor_t *
295 svn_diff__tree_processor_create(void *baton,
296 apr_pool_t *result_pool);
299 * Create a new svn_diff_tree_processor_t instance with all functions setup
300 * to call into another svn_diff_tree_processor_t processor, but with all
301 * adds and deletes inverted.
304 */ /* Used by libsvn clients repository diff */
305 const svn_diff_tree_processor_t *
306 svn_diff__tree_processor_reverse_create(const svn_diff_tree_processor_t * processor,
307 const char *prefix_relpath,
308 apr_pool_t *result_pool);
311 * Create a new svn_diff_tree_processor_t instance with all functions setup
312 * to call into processor for all paths equal to and below prefix_relpath.
315 */ /* Used by libsvn clients repository diff */
316 const svn_diff_tree_processor_t *
317 svn_diff__tree_processor_filter_create(const svn_diff_tree_processor_t *processor,
318 const char *prefix_relpath,
319 apr_pool_t *result_pool);
322 * Create a new svn_diff_tree_processor_t instace with all function setup
323 * to call into processor with all adds with copyfrom information transformed
324 * to simple node changes.
327 */ /* Used by libsvn_wc diff editor */
328 const svn_diff_tree_processor_t *
329 svn_diff__tree_processor_copy_as_changed_create(
330 const svn_diff_tree_processor_t *processor,
331 apr_pool_t *result_pool);
335 * Create a new svn_diff_tree_processor_t instance with all functions setup
336 * to first call into processor1 and then processor2.
338 * This function is mostly a debug and migration helper.
341 */ /* Used by libsvn clients repository diff */
342 const svn_diff_tree_processor_t *
343 svn_diff__tree_processor_tee_create(const svn_diff_tree_processor_t *processor1,
344 const svn_diff_tree_processor_t *processor2,
345 apr_pool_t *result_pool);
349 svn_diff__source_create(svn_revnum_t revision,
350 apr_pool_t *result_pool);
354 #endif /* __cplusplus */
356 #endif /* SVN_DIFF_PROCESSOR_H */