svn_diff_tree.h revision 299742
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_diff_tree.h 24 * @brief Generic diff handler. Replacing the old svn_wc_diff_callbacks4_t 25 * infrastructure 26 */ 27 28#ifndef SVN_DIFF_TREE_H 29#define SVN_DIFF_TREE_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 * ### "An add followed by a delete" sounds wrong. 107 * 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. 110 */ 111 112/* Describes the source of a merge */ 113/* ### You mean a diff? 114 * ### How come many users don't set the 'repos_relpath' field? */ 115typedef struct svn_diff_source_t 116{ 117 /* Always available */ 118 svn_revnum_t revision; 119 120 /* Depending on the driver available for copyfrom */ 121 /* ### What? */ 122 const char *repos_relpath; 123} svn_diff_source_t; 124 125/** 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 128 * of this vtable. 129 * 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. 133 * 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. 137 * 138 * @since New in 1.8. 139 */ 140typedef struct svn_diff_tree_processor_t 141{ 142 /** The value passed to svn_diff__tree_processor_create() as BATON. 143 */ 144 void *baton; /* To avoid an additional in some places 145 * ### What? */ 146 147 /* Called before a directory's children are processed. 148 * 149 * Set *SKIP_CHILDREN to TRUE, to skip calling callbacks for all 150 * children. 151 * 152 * Set *SKIP to TRUE to skip calling the added, deleted, changed 153 * or closed callback for this node only. 154 */ 155 svn_error_t * 156 (*dir_opened)(void **new_dir_baton, 157 svn_boolean_t *skip, 158 svn_boolean_t *skip_children, 159 const char *relpath, 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); 167 168 /* Called after a directory and all its children are added 169 */ 170 svn_error_t * 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, 176 void *dir_baton, 177 const struct svn_diff_tree_processor_t *processor, 178 apr_pool_t *scratch_pool); 179 180 /* Called after all children of this node are reported as deleted. 181 * 182 * The default implementation calls dir_closed(). 183 */ 184 svn_error_t * 185 (*dir_deleted)(const char *relpath, 186 const svn_diff_source_t *left_source, 187 /*const*/ apr_hash_t *left_props, 188 void *dir_baton, 189 const struct svn_diff_tree_processor_t *processor, 190 apr_pool_t *scratch_pool); 191 192 /* Called instead of dir_closed() if the properties on the directory 193 * were modified. 194 * 195 * The default implementation calls dir_closed(). 196 */ 197 svn_error_t * 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, 204 void *dir_baton, 205 const struct svn_diff_tree_processor_t *processor, 206 apr_pool_t *scratch_pool); 207 208 /* Called when a directory is closed without applying changes to 209 * the directory itself. 210 * 211 * When dir_changed or dir_deleted are handled by the default implementation 212 * they call dir_closed() 213 */ 214 svn_error_t * 215 (*dir_closed)(const char *relpath, 216 const svn_diff_source_t *left_source, 217 const svn_diff_source_t *right_source, 218 void *dir_baton, 219 const struct svn_diff_tree_processor_t *processor, 220 apr_pool_t *scratch_pool); 221 222 /* Called before file_added(), file_deleted(), file_changed() and 223 file_closed() 224 */ 225 svn_error_t * 226 (*file_opened)(void **new_file_baton, 227 svn_boolean_t *skip, 228 const char *relpath, 229 const svn_diff_source_t *left_source, 230 const svn_diff_source_t *right_source, 231 const svn_diff_source_t *copyfrom_source, 232 void *dir_baton, 233 const struct svn_diff_tree_processor_t *processor, 234 apr_pool_t *result_pool, 235 apr_pool_t *scratch_pool); 236 237 /* Called after file_opened() for newly added and copied files */ 238 svn_error_t * 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, 246 void *file_baton, 247 const struct svn_diff_tree_processor_t *processor, 248 apr_pool_t *scratch_pool); 249 250 /* Called after file_opened() for deleted or moved away files */ 251 svn_error_t * 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, 256 void *file_baton, 257 const struct svn_diff_tree_processor_t *processor, 258 apr_pool_t *scratch_pool); 259 260 /* Called after file_opened() for changed files */ 261 svn_error_t * 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, 271 void *file_baton, 272 const struct svn_diff_tree_processor_t *processor, 273 apr_pool_t *scratch_pool); 274 275 /* Called after file_opened() for unmodified files */ 276 svn_error_t * 277 (*file_closed)(const char *relpath, 278 const svn_diff_source_t *left_source, 279 const svn_diff_source_t *right_source, 280 void *file_baton, 281 const struct svn_diff_tree_processor_t *processor, 282 apr_pool_t *scratch_pool); 283 284 /* Called when encountering a marker for an absent file or directory */ 285 svn_error_t * 286 (*node_absent)(const char *relpath, 287 void *dir_baton, 288 const struct svn_diff_tree_processor_t *processor, 289 apr_pool_t *scratch_pool); 290} svn_diff_tree_processor_t; 291 292/** 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 295 * the new baton. 296 * 297 * @since New in 1.8. 298 */ 299svn_diff_tree_processor_t * 300svn_diff__tree_processor_create(void *baton, 301 apr_pool_t *result_pool); 302 303/** 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. 307 * 308 * @since New in 1.8. 309 */ /* Used by libsvn clients repository diff */ 310const svn_diff_tree_processor_t * 311svn_diff__tree_processor_reverse_create(const svn_diff_tree_processor_t * processor, 312 const char *prefix_relpath, 313 apr_pool_t *result_pool); 314 315/** 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. 318 * 319 * @since New in 1.8. 320 */ /* Used by libsvn clients repository diff */ 321const svn_diff_tree_processor_t * 322svn_diff__tree_processor_filter_create(const svn_diff_tree_processor_t *processor, 323 const char *prefix_relpath, 324 apr_pool_t *result_pool); 325 326/** 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. 330 * 331 * @since New in 1.8. 332 */ /* Used by libsvn_wc diff editor */ 333const svn_diff_tree_processor_t * 334svn_diff__tree_processor_copy_as_changed_create( 335 const svn_diff_tree_processor_t *processor, 336 apr_pool_t *result_pool); 337 338 339/** 340 * Create a new svn_diff_tree_processor_t instance with all functions setup 341 * to first call into processor1 and then processor2. 342 * 343 * This function is mostly a debug and migration helper. 344 * 345 * @since New in 1.8. 346 */ /* Used by libsvn clients repository diff */ 347const svn_diff_tree_processor_t * 348svn_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); 351 352 353svn_diff_source_t * 354svn_diff__source_create(svn_revnum_t revision, 355 apr_pool_t *result_pool); 356 357#ifdef __cplusplus 358} 359#endif /* __cplusplus */ 360 361#endif /* SVN_DIFF_TREE_H */ 362 363