1251881Speter/**
2251881Speter * @copyright
3251881Speter * ====================================================================
4251881Speter *    Licensed to the Apache Software Foundation (ASF) under one
5251881Speter *    or more contributor license agreements.  See the NOTICE file
6251881Speter *    distributed with this work for additional information
7251881Speter *    regarding copyright ownership.  The ASF licenses this file
8251881Speter *    to you under the Apache License, Version 2.0 (the
9251881Speter *    "License"); you may not use this file except in compliance
10251881Speter *    with the License.  You may obtain a copy of the License at
11251881Speter *
12251881Speter *      http://www.apache.org/licenses/LICENSE-2.0
13251881Speter *
14251881Speter *    Unless required by applicable law or agreed to in writing,
15251881Speter *    software distributed under the License is distributed on an
16251881Speter *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17251881Speter *    KIND, either express or implied.  See the License for the
18251881Speter *    specific language governing permissions and limitations
19251881Speter *    under the License.
20251881Speter * ====================================================================
21251881Speter * @endcopyright
22251881Speter *
23251881Speter * @file svn_wc.h
24251881Speter * @brief Generic diff handler. Replacing the old svn_wc_diff_callbacks4_t
25251881Speter * infrastructure
26251881Speter */
27251881Speter
28251881Speter#ifndef SVN_DIFF_PROCESSOR_H
29251881Speter#define SVN_DIFF_PROCESSOR_H
30251881Speter
31251881Speter#include "svn_types.h"
32251881Speter
33251881Speter#ifdef __cplusplus
34251881Speterextern "C" {
35251881Speter#endif /* __cplusplus */
36251881Speter
37251881Speter/*
38251881Speter *                   About the diff tree processor.
39251881Speter *
40251881Speter * Subversion uses two kinds of editors to describe changes. One to
41251881Speter * describe changes on how to *exactly* transform one tree to another tree,
42251881Speter * as efficiently as possible and one to describe the difference between trees
43251881Speter * in order to review the changes, or to allow applying them on a third tree
44251881Speter * which is similar to those other trees.
45251881Speter *
46251881Speter * The first case was originally handled by svn_delta_editor_t and might be
47251881Speter * replaced by svn_editor_t in a future version. This diff processor handles
48251881Speter * the other case and as such forms the layer below our diff and merge
49251881Speter * handling.
50251881Speter *
51251881Speter * The major difference between this and the other editors is that this diff
52251881Speter * always provides access to the full text and/or properties in the left and
53251881Speter * right tree when applicable to allow processor implementers to decide how
54251881Speter * to interpret changes.
55251881Speter *
56251881Speter * Originally this diff processor was not formalized explicitly, but
57251881Speter * informally handled by the working copy diff callbacks. These callbacks just
58251881Speter * provided the information to drive a unified diff and a textual merge. To go
59251881Speter * one step further and allow full tree conflict detection we needed a better
60251881Speter * defined diff handling. Instead of adding yet a few more functions and
61251881Speter * arguments to the already overloaded diff callbacks the api was completely
62251881Speter * redesigned with a few points in mind.
63251881Speter *
64251881Speter *   * It must be able to drive the old callbacks interface without users
65251881Speter *     noticing the difference (100% compatible).
66251881Speter *     (Implemented as svn_wc__wrap_diff_callbacks())
67251881Speter *
68251881Speter *   * It should provide the information that was missing in the old interface,
69251881Speter *     but required to close existing issues.
70251881Speter *
71251881Speter *     E.g. - properties and children on deleted directories.
72251881Speter *          - revision numbers and copyfrom information on directories.
73251881Speter *
74251881Speter * To cleanup the implementation and make it easier on diff processors to
75251881Speter * handle the results I also added the following constraints.
76251881Speter *
77251881Speter *   * Diffs should be fully reversable: anything that is deleted should be
78251881Speter *     available, just like something that is added.
79251881Speter *     (Proven via svn_diff__tree_processor_reverse_create)
80251881Speter *     ### Still in doubt if *_deleted() needs a copy_to argument, for the
81251881Speter *     ### 99% -> 100%.
82251881Speter *
83251881Speter *   * Diff processors should have an easy way to communicate that they are
84251881Speter *     not interrested in certain expensive to obtain results.
85251881Speter *
86251881Speter *   * Directories should have clear open and close events to allow adding them
87251881Speter *     before their children, but still allowing property changes to have
88251881Speter *     defined behavior.
89251881Speter *
90251881Speter *   * Files and directories should be handled as similar as possible as in
91251881Speter *     many cases they are just nodes in a tree.
92251881Speter *
93251881Speter *   * It should be easy to create diff wrappers to apply certain transforms.
94251881Speter *
95251881Speter * During the creation an additional requirement of knowing about 'some
96251881Speter * absent' nodes was added, to allow the merge to work on just this processor
97251881Speter * api.
98251881Speter *
99251881Speter * The api describes a clean open-close walk through a tree, depending on the
100251881Speter * driver multiple siblings can be described at the same time, but when a
101251881Speter * directory is closed all descendants are done.
102251881Speter *
103251881Speter * Note that it is possible for nodes to be described as a delete followed by
104251881Speter * an add at the same place within one parent. (Iff the diff is reversed you
105251881Speter * can see an add followed by a delete!)
106251881Speter *
107251881Speter * The directory batons live between the open and close events of a directory
108251881Speter * and are thereby guaranteed to outlive the batons of their descendants.
109251881Speter */
110251881Speter
111251881Speter/* Describes the source of a merge */
112251881Spetertypedef struct svn_diff_source_t
113251881Speter{
114251881Speter  /* Always available */
115251881Speter  svn_revnum_t revision;
116251881Speter
117251881Speter  /* Depending on the driver available for copyfrom */
118251881Speter  const char *repos_relpath;
119251881Speter} svn_diff_source_t;
120251881Speter
121251881Speter/**
122251881Speter * A callback vtable invoked by our diff-editors, as they receive diffs
123251881Speter * from the server. 'svn diff' and 'svn merge' implement their own versions
124251881Speter * of this vtable.
125251881Speter *
126251881Speter * All callbacks receive the processor and at least a parent baton. Forwarding
127251881Speter * the processor allows future extensions to call into the old functions without
128251881Speter * revving the entire API.
129251881Speter *
130251881Speter * Users must call svn_diff__tree_processor_create() to allow adding new
131251881Speter * callbacks later. (E.g. when we decide how to add move support) These
132251881Speter * extensions can then just call into other callbacks.
133251881Speter *
134251881Speter * @since New in 1.8.
135251881Speter */
136251881Spetertypedef struct svn_diff_tree_processor_t
137251881Speter{
138251881Speter  /** The value passed to svn_diff__tree_processor_create() as BATON.
139251881Speter   */
140251881Speter  void *baton; /* To avoid an additional in some places */
141251881Speter
142251881Speter  /* Called before a directories children are processed.
143251881Speter   *
144251881Speter   * Set *SKIP_CHILDREN to TRUE, to skip calling callbacks for all
145251881Speter   * children.
146251881Speter   *
147251881Speter   * Set *SKIP to TRUE to skip calling the added, deleted, changed
148251881Speter   * or closed callback for this node only.
149251881Speter   */
150251881Speter  svn_error_t *
151251881Speter  (*dir_opened)(void **new_dir_baton,
152251881Speter                svn_boolean_t *skip,
153251881Speter                svn_boolean_t *skip_children,
154251881Speter                const char *relpath,
155251881Speter                const svn_diff_source_t *left_source,
156251881Speter                const svn_diff_source_t *right_source,
157251881Speter                const svn_diff_source_t *copyfrom_source,
158251881Speter                void *parent_dir_baton,
159251881Speter                const struct svn_diff_tree_processor_t *processor,
160251881Speter                apr_pool_t *result_pool,
161251881Speter                apr_pool_t *scratch_pool);
162251881Speter
163251881Speter  /* Called after a directory and all its children are added
164251881Speter   */
165251881Speter  svn_error_t *
166251881Speter  (*dir_added)(const char *relpath,
167251881Speter               const svn_diff_source_t *copyfrom_source,
168251881Speter               const svn_diff_source_t *right_source,
169251881Speter               /*const*/ apr_hash_t *copyfrom_props,
170251881Speter               /*const*/ apr_hash_t *right_props,
171251881Speter               void *dir_baton,
172251881Speter               const struct svn_diff_tree_processor_t *processor,
173251881Speter               apr_pool_t *scratch_pool);
174251881Speter
175251881Speter  /* Called after all children of this node are reported as deleted.
176251881Speter   *
177251881Speter   * The default implementation calls dir_closed().
178251881Speter   */
179251881Speter  svn_error_t *
180251881Speter  (*dir_deleted)(const char *relpath,
181251881Speter                 const svn_diff_source_t *left_source,
182251881Speter                 /*const*/ apr_hash_t *left_props,
183251881Speter                 void *dir_baton,
184251881Speter                 const struct svn_diff_tree_processor_t *processor,
185251881Speter                 apr_pool_t *scratch_pool);
186251881Speter
187251881Speter  /* Called instead of dir_closed() if the properties on the directory
188251881Speter   *  were modified.
189251881Speter   *
190251881Speter   * The default implementation calls dir_closed().
191251881Speter   */
192251881Speter  svn_error_t *
193251881Speter  (*dir_changed)(const char *relpath,
194251881Speter                 const svn_diff_source_t *left_source,
195251881Speter                 const svn_diff_source_t *right_source,
196251881Speter                 /*const*/ apr_hash_t *left_props,
197251881Speter                 /*const*/ apr_hash_t *right_props,
198251881Speter                 const apr_array_header_t *prop_changes,
199251881Speter                 void *dir_baton,
200251881Speter                 const struct svn_diff_tree_processor_t *processor,
201251881Speter                 apr_pool_t *scratch_pool);
202251881Speter
203251881Speter  /* Called when a directory is closed without applying changes to
204251881Speter   * the directory itself.
205251881Speter   *
206251881Speter   * When dir_changed or dir_deleted are handled by the default implementation
207251881Speter   * they call dir_closed()
208251881Speter   */
209251881Speter  svn_error_t *
210251881Speter  (*dir_closed)(const char *relpath,
211251881Speter                const svn_diff_source_t *left_source,
212251881Speter                const svn_diff_source_t *right_source,
213251881Speter                void *dir_baton,
214251881Speter                const struct svn_diff_tree_processor_t *processor,
215251881Speter                apr_pool_t *scratch_pool);
216251881Speter
217251881Speter  /* Called before file_added(), file_deleted(), file_changed() and
218251881Speter     file_closed()
219251881Speter   */
220251881Speter  svn_error_t *
221251881Speter  (*file_opened)(void **new_file_baton,
222251881Speter                 svn_boolean_t *skip,
223251881Speter                 const char *relpath,
224251881Speter                 const svn_diff_source_t *left_source,
225251881Speter                 const svn_diff_source_t *right_source,
226251881Speter                 const svn_diff_source_t *copyfrom_source,
227251881Speter                 void *dir_baton,
228251881Speter                 const struct svn_diff_tree_processor_t *processor,
229251881Speter                 apr_pool_t *result_pool,
230251881Speter                 apr_pool_t *scratch_pool);
231251881Speter
232251881Speter  /* Called after file_opened() for newly added and copied files */
233251881Speter  svn_error_t *
234251881Speter  (*file_added)(const char *relpath,
235251881Speter                const svn_diff_source_t *copyfrom_source,
236251881Speter                const svn_diff_source_t *right_source,
237251881Speter                const char *copyfrom_file,
238251881Speter                const char *right_file,
239251881Speter                /*const*/ apr_hash_t *copyfrom_props,
240251881Speter                /*const*/ apr_hash_t *right_props,
241251881Speter                void *file_baton,
242251881Speter                const struct svn_diff_tree_processor_t *processor,
243251881Speter                apr_pool_t *scratch_pool);
244251881Speter
245251881Speter  /* Called after file_opened() for deleted or moved away files */
246251881Speter  svn_error_t *
247251881Speter  (*file_deleted)(const char *relpath,
248251881Speter                  const svn_diff_source_t *left_source,
249251881Speter                  const char *left_file,
250251881Speter                  /*const*/ apr_hash_t *left_props,
251251881Speter                  void *file_baton,
252251881Speter                  const struct svn_diff_tree_processor_t *processor,
253251881Speter                  apr_pool_t *scratch_pool);
254251881Speter
255251881Speter  /* Called after file_opened() for changed files */
256251881Speter  svn_error_t *
257251881Speter  (*file_changed)(const char *relpath,
258251881Speter                  const svn_diff_source_t *left_source,
259251881Speter                  const svn_diff_source_t *right_source,
260251881Speter                  const char *left_file,
261251881Speter                  const char *right_file,
262251881Speter                  /*const*/ apr_hash_t *left_props,
263251881Speter                  /*const*/ apr_hash_t *right_props,
264251881Speter                  svn_boolean_t file_modified,
265251881Speter                  const apr_array_header_t *prop_changes,
266251881Speter                  void *file_baton,
267251881Speter                  const struct svn_diff_tree_processor_t *processor,
268251881Speter                  apr_pool_t *scratch_pool);
269251881Speter
270251881Speter  /* Called after file_opened() for unmodified files */
271251881Speter  svn_error_t *
272251881Speter  (*file_closed)(const char *relpath,
273251881Speter                 const svn_diff_source_t *left_source,
274251881Speter                 const svn_diff_source_t *right_source,
275251881Speter                 void *file_baton,
276251881Speter                 const struct svn_diff_tree_processor_t *processor,
277251881Speter                 apr_pool_t *scratch_pool);
278251881Speter
279251881Speter  /* Called when encountering a marker for an absent file or directory */
280251881Speter  svn_error_t *
281251881Speter  (*node_absent)(const char *relpath,
282251881Speter                 void *dir_baton,
283251881Speter                 const struct svn_diff_tree_processor_t *processor,
284251881Speter                 apr_pool_t *scratch_pool);
285251881Speter} svn_diff_tree_processor_t;
286251881Speter
287251881Speter/**
288251881Speter * Create a new svn_diff_tree_processor_t instance with all functions
289251881Speter * set to a callback doing nothing but copying the parent baton to
290251881Speter * the new baton.
291251881Speter *
292251881Speter * @since New in 1.8.
293251881Speter */
294251881Spetersvn_diff_tree_processor_t *
295251881Spetersvn_diff__tree_processor_create(void *baton,
296251881Speter                                apr_pool_t *result_pool);
297251881Speter
298251881Speter/**
299251881Speter * Create a new svn_diff_tree_processor_t instance with all functions setup
300251881Speter * to call into another svn_diff_tree_processor_t processor, but with all
301251881Speter * adds and deletes inverted.
302251881Speter *
303251881Speter * @since New in 1.8.
304251881Speter */ /* Used by libsvn clients repository diff */
305251881Speterconst svn_diff_tree_processor_t *
306251881Spetersvn_diff__tree_processor_reverse_create(const svn_diff_tree_processor_t * processor,
307251881Speter                                        const char *prefix_relpath,
308251881Speter                                        apr_pool_t *result_pool);
309251881Speter
310251881Speter/**
311251881Speter * Create a new svn_diff_tree_processor_t instance with all functions setup
312251881Speter * to call into processor for all paths equal to and below prefix_relpath.
313251881Speter *
314251881Speter * @since New in 1.8.
315251881Speter */ /* Used by libsvn clients repository diff */
316251881Speterconst svn_diff_tree_processor_t *
317251881Spetersvn_diff__tree_processor_filter_create(const svn_diff_tree_processor_t *processor,
318251881Speter                                       const char *prefix_relpath,
319251881Speter                                       apr_pool_t *result_pool);
320251881Speter
321251881Speter/**
322251881Speter * Create a new svn_diff_tree_processor_t instace with all function setup
323251881Speter * to call into processor with all adds with copyfrom information transformed
324251881Speter * to simple node changes.
325251881Speter *
326251881Speter * @since New in 1.8.
327251881Speter */ /* Used by libsvn_wc diff editor */
328251881Speterconst svn_diff_tree_processor_t *
329251881Spetersvn_diff__tree_processor_copy_as_changed_create(
330251881Speter                                const svn_diff_tree_processor_t *processor,
331251881Speter                                apr_pool_t *result_pool);
332251881Speter
333251881Speter
334251881Speter/**
335251881Speter * Create a new svn_diff_tree_processor_t instance with all functions setup
336251881Speter * to first call into processor1 and then processor2.
337251881Speter *
338251881Speter * This function is mostly a debug and migration helper.
339251881Speter *
340251881Speter * @since New in 1.8.
341251881Speter */ /* Used by libsvn clients repository diff */
342251881Speterconst svn_diff_tree_processor_t *
343251881Spetersvn_diff__tree_processor_tee_create(const svn_diff_tree_processor_t *processor1,
344251881Speter                                    const svn_diff_tree_processor_t *processor2,
345251881Speter                                    apr_pool_t *result_pool);
346251881Speter
347251881Speter
348251881Spetersvn_diff_source_t *
349251881Spetersvn_diff__source_create(svn_revnum_t revision,
350251881Speter                        apr_pool_t *result_pool);
351251881Speter
352251881Speter#ifdef __cplusplus
353251881Speter}
354251881Speter#endif /* __cplusplus */
355251881Speter
356251881Speter#endif  /* SVN_DIFF_PROCESSOR_H */
357251881Speter
358