1/** 2 * @copyright 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 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 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 19 * under the License. 20 * ==================================================================== 21 * @endcopyright 22 * 23 * @file svn_wc.h 24 * @brief Generic diff handler. Replacing the old svn_wc_diff_callbacks4_t 25 * infrastructure 26 */ 27 28#ifndef SVN_DIFF_PROCESSOR_H 29#define SVN_DIFF_PROCESSOR_H 30 31#include "svn_types.h" 32 33#ifdef __cplusplus 34extern "C" { 35#endif /* __cplusplus */ 36 37/* 38 * About the diff tree processor. 39 * 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. 45 * 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 49 * handling. 50 * 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. 55 * 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. 63 * 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()) 67 * 68 * * It should provide the information that was missing in the old interface, 69 * but required to close existing issues. 70 * 71 * E.g. - properties and children on deleted directories. 72 * - revision numbers and copyfrom information on directories. 73 * 74 * To cleanup the implementation and make it easier on diff processors to 75 * handle the results I also added the following constraints. 76 * 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 81 * ### 99% -> 100%. 82 * 83 * * Diff processors should have an easy way to communicate that they are 84 * not interrested in certain expensive to obtain results. 85 * 86 * * Directories should have clear open and close events to allow adding them 87 * before their children, but still allowing property changes to have 88 * defined behavior. 89 * 90 * * Files and directories should be handled as similar as possible as in 91 * many cases they are just nodes in a tree. 92 * 93 * * It should be easy to create diff wrappers to apply certain transforms. 94 * 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 97 * api. 98 * 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. 102 * 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 * 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. 109 */ 110 111/* Describes the source of a merge */ 112typedef struct svn_diff_source_t 113{ 114 /* Always available */ 115 svn_revnum_t revision; 116 117 /* Depending on the driver available for copyfrom */ 118 const char *repos_relpath; 119} svn_diff_source_t; 120 121/** 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 124 * of this vtable. 125 * 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. 129 * 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. 133 * 134 * @since New in 1.8. 135 */ 136typedef struct svn_diff_tree_processor_t 137{ 138 /** The value passed to svn_diff__tree_processor_create() as BATON. 139 */ 140 void *baton; /* To avoid an additional in some places */ 141 142 /* Called before a directories children are processed. 143 * 144 * Set *SKIP_CHILDREN to TRUE, to skip calling callbacks for all 145 * children. 146 * 147 * Set *SKIP to TRUE to skip calling the added, deleted, changed 148 * or closed callback for this node only. 149 */ 150 svn_error_t * 151 (*dir_opened)(void **new_dir_baton, 152 svn_boolean_t *skip, 153 svn_boolean_t *skip_children, 154 const char *relpath, 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); 162 163 /* Called after a directory and all its children are added 164 */ 165 svn_error_t * 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, 171 void *dir_baton, 172 const struct svn_diff_tree_processor_t *processor, 173 apr_pool_t *scratch_pool); 174 175 /* Called after all children of this node are reported as deleted. 176 * 177 * The default implementation calls dir_closed(). 178 */ 179 svn_error_t * 180 (*dir_deleted)(const char *relpath, 181 const svn_diff_source_t *left_source, 182 /*const*/ apr_hash_t *left_props, 183 void *dir_baton, 184 const struct svn_diff_tree_processor_t *processor, 185 apr_pool_t *scratch_pool); 186 187 /* Called instead of dir_closed() if the properties on the directory 188 * were modified. 189 * 190 * The default implementation calls dir_closed(). 191 */ 192 svn_error_t * 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, 199 void *dir_baton, 200 const struct svn_diff_tree_processor_t *processor, 201 apr_pool_t *scratch_pool); 202 203 /* Called when a directory is closed without applying changes to 204 * the directory itself. 205 * 206 * When dir_changed or dir_deleted are handled by the default implementation 207 * they call dir_closed() 208 */ 209 svn_error_t * 210 (*dir_closed)(const char *relpath, 211 const svn_diff_source_t *left_source, 212 const svn_diff_source_t *right_source, 213 void *dir_baton, 214 const struct svn_diff_tree_processor_t *processor, 215 apr_pool_t *scratch_pool); 216 217 /* Called before file_added(), file_deleted(), file_changed() and 218 file_closed() 219 */ 220 svn_error_t * 221 (*file_opened)(void **new_file_baton, 222 svn_boolean_t *skip, 223 const char *relpath, 224 const svn_diff_source_t *left_source, 225 const svn_diff_source_t *right_source, 226 const svn_diff_source_t *copyfrom_source, 227 void *dir_baton, 228 const struct svn_diff_tree_processor_t *processor, 229 apr_pool_t *result_pool, 230 apr_pool_t *scratch_pool); 231 232 /* Called after file_opened() for newly added and copied files */ 233 svn_error_t * 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, 241 void *file_baton, 242 const struct svn_diff_tree_processor_t *processor, 243 apr_pool_t *scratch_pool); 244 245 /* Called after file_opened() for deleted or moved away files */ 246 svn_error_t * 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, 251 void *file_baton, 252 const struct svn_diff_tree_processor_t *processor, 253 apr_pool_t *scratch_pool); 254 255 /* Called after file_opened() for changed files */ 256 svn_error_t * 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, 266 void *file_baton, 267 const struct svn_diff_tree_processor_t *processor, 268 apr_pool_t *scratch_pool); 269 270 /* Called after file_opened() for unmodified files */ 271 svn_error_t * 272 (*file_closed)(const char *relpath, 273 const svn_diff_source_t *left_source, 274 const svn_diff_source_t *right_source, 275 void *file_baton, 276 const struct svn_diff_tree_processor_t *processor, 277 apr_pool_t *scratch_pool); 278 279 /* Called when encountering a marker for an absent file or directory */ 280 svn_error_t * 281 (*node_absent)(const char *relpath, 282 void *dir_baton, 283 const struct svn_diff_tree_processor_t *processor, 284 apr_pool_t *scratch_pool); 285} svn_diff_tree_processor_t; 286 287/** 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 290 * the new baton. 291 * 292 * @since New in 1.8. 293 */ 294svn_diff_tree_processor_t * 295svn_diff__tree_processor_create(void *baton, 296 apr_pool_t *result_pool); 297 298/** 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. 302 * 303 * @since New in 1.8. 304 */ /* Used by libsvn clients repository diff */ 305const svn_diff_tree_processor_t * 306svn_diff__tree_processor_reverse_create(const svn_diff_tree_processor_t * processor, 307 const char *prefix_relpath, 308 apr_pool_t *result_pool); 309 310/** 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. 313 * 314 * @since New in 1.8. 315 */ /* Used by libsvn clients repository diff */ 316const svn_diff_tree_processor_t * 317svn_diff__tree_processor_filter_create(const svn_diff_tree_processor_t *processor, 318 const char *prefix_relpath, 319 apr_pool_t *result_pool); 320 321/** 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. 325 * 326 * @since New in 1.8. 327 */ /* Used by libsvn_wc diff editor */ 328const svn_diff_tree_processor_t * 329svn_diff__tree_processor_copy_as_changed_create( 330 const svn_diff_tree_processor_t *processor, 331 apr_pool_t *result_pool); 332 333 334/** 335 * Create a new svn_diff_tree_processor_t instance with all functions setup 336 * to first call into processor1 and then processor2. 337 * 338 * This function is mostly a debug and migration helper. 339 * 340 * @since New in 1.8. 341 */ /* Used by libsvn clients repository diff */ 342const svn_diff_tree_processor_t * 343svn_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); 346 347 348svn_diff_source_t * 349svn_diff__source_create(svn_revnum_t revision, 350 apr_pool_t *result_pool); 351 352#ifdef __cplusplus 353} 354#endif /* __cplusplus */ 355 356#endif /* SVN_DIFF_PROCESSOR_H */ 357 358