00001 /** 00002 * @copyright 00003 * ==================================================================== 00004 * Copyright (c) 2000-2007 CollabNet. All rights reserved. 00005 * 00006 * This software is licensed as described in the file COPYING, which 00007 * you should have received as part of this distribution. The terms 00008 * are also available at http://subversion.tigris.org/license-1.html. 00009 * If newer versions of this license are posted there, you may use a 00010 * newer version instead, at your option. 00011 * 00012 * This software consists of voluntary contributions made by many 00013 * individuals. For exact contribution history, see the revision 00014 * history and logs, available at http://subversion.tigris.org/. 00015 * ==================================================================== 00016 * @endcopyright 00017 * 00018 * @file svn_diff.h 00019 * @brief Contextual diffing. 00020 * 00021 * This is an internalized library for performing contextual diffs 00022 * between sources of data. 00023 * 00024 * @note This is different than Subversion's binary-diffing engine. 00025 * That API lives in @c svn_delta.h -- see the "text deltas" section. A 00026 * "text delta" is way of representing precise binary diffs between 00027 * strings of data. The Subversion client and server send text deltas 00028 * to one another during updates and commits. 00029 * 00030 * This API, however, is (or will be) used for performing *contextual* 00031 * merges between files in the working copy. During an update or 00032 * merge, 3-way file merging is needed. And 'svn diff' needs to show 00033 * the differences between 2 files. 00034 * 00035 * The nice thing about this API is that it's very general. It 00036 * operates on any source of data (a "datasource") and calculates 00037 * contextual differences on "tokens" within the data. In our 00038 * particular usage, the datasources are files and the tokens are 00039 * lines. But the possibilities are endless. 00040 */ 00041 00042 00043 #ifndef SVN_DIFF_H 00044 #define SVN_DIFF_H 00045 00046 #include <apr.h> 00047 #include <apr_pools.h> 00048 #include <apr_file_io.h> 00049 00050 #include "svn_types.h" 00051 #include "svn_error.h" 00052 #include "svn_io.h" 00053 #include "svn_version.h" 00054 00055 #ifdef __cplusplus 00056 extern "C" { 00057 #endif /* __cplusplus */ 00058 00059 00060 00061 /** 00062 * Get libsvn_diff version information. 00063 * 00064 * @since New in 1.1. 00065 */ 00066 const svn_version_t *svn_diff_version(void); 00067 00068 00069 /* Diffs. */ 00070 00071 /** An opaque type that represents a difference between either two or 00072 * three datasources. This object is returned by svn_diff_diff(), 00073 * svn_diff_diff3() and svn_diff_diff4(), and consumed by a number of 00074 * other routines. 00075 */ 00076 typedef struct svn_diff_t svn_diff_t; 00077 00078 /** 00079 * There are four types of datasources. In GNU diff3 terminology, 00080 * the first three types correspond to the phrases "older", "mine", 00081 * and "yours". 00082 */ 00083 typedef enum svn_diff_datasource_e 00084 { 00085 /** The oldest form of the data. */ 00086 svn_diff_datasource_original, 00087 00088 /** The same data, but potentially changed by the user. */ 00089 svn_diff_datasource_modified, 00090 00091 /** The latest version of the data, possibly different than the 00092 * user's modified version. 00093 */ 00094 svn_diff_datasource_latest, 00095 00096 /** The common ancestor of original and modified. */ 00097 svn_diff_datasource_ancestor 00098 00099 } svn_diff_datasource_e; 00100 00101 00102 /** A vtable for reading data from the three datasources. */ 00103 typedef struct svn_diff_fns_t 00104 { 00105 /** Open the datasource of type @a datasource. */ 00106 svn_error_t *(*datasource_open)(void *diff_baton, 00107 svn_diff_datasource_e datasource); 00108 00109 /** Close the datasource of type @a datasource. */ 00110 svn_error_t *(*datasource_close)(void *diff_baton, 00111 svn_diff_datasource_e datasource); 00112 00113 /** Get the next "token" from the datasource of type @a datasource. 00114 * Return a "token" in @a *token. Return a hash of "token" in @a *hash. 00115 * Leave @a token and @a hash untouched when the datasource is exhausted. 00116 */ 00117 svn_error_t *(*datasource_get_next_token)(apr_uint32_t *hash, void **token, 00118 void *diff_baton, 00119 svn_diff_datasource_e datasource); 00120 00121 /** A function for ordering the tokens, resembling 'strcmp' in functionality. 00122 * @a compare should contain the return value of the comparison: 00123 * If @a ltoken and @a rtoken are "equal", return 0. If @a ltoken is 00124 * "less than" @a rtoken, return a number < 0. If @a ltoken is 00125 * "greater than" @a rtoken, return a number > 0. 00126 */ 00127 svn_error_t *(*token_compare)(void *diff_baton, 00128 void *ltoken, 00129 void *rtoken, 00130 int *compare); 00131 00132 /** Free @a token from memory, the diff algorithm is done with it. */ 00133 void (*token_discard)(void *diff_baton, 00134 void *token); 00135 00136 /** Free *all* tokens from memory, they're no longer needed. */ 00137 void (*token_discard_all)(void *diff_baton); 00138 } svn_diff_fns_t; 00139 00140 00141 /* The Main Events */ 00142 00143 /** Given a vtable of @a diff_fns/@a diff_baton for reading datasources, 00144 * return a diff object in @a *diff that represents a difference between 00145 * an "original" and "modified" datasource. Do all allocation in @a pool. 00146 */ 00147 svn_error_t *svn_diff_diff(svn_diff_t **diff, 00148 void *diff_baton, 00149 const svn_diff_fns_t *diff_fns, 00150 apr_pool_t *pool); 00151 00152 /** Given a vtable of @a diff_fns/@a diff_baton for reading datasources, 00153 * return a diff object in @a *diff that represents a difference between 00154 * three datasources: "original", "modified", and "latest". Do all 00155 * allocation in @a pool. 00156 */ 00157 svn_error_t *svn_diff_diff3(svn_diff_t **diff, 00158 void *diff_baton, 00159 const svn_diff_fns_t *diff_fns, 00160 apr_pool_t *pool); 00161 00162 /** Given a vtable of @a diff_fns/@a diff_baton for reading datasources, 00163 * return a diff object in @a *diff that represents a difference between 00164 * two datasources: "original" and "latest", adjusted to become a full 00165 * difference between "original", "modified" and "latest" using "ancestor". 00166 * Do all allocation in @a pool. 00167 */ 00168 svn_error_t *svn_diff_diff4(svn_diff_t **diff, 00169 void *diff_baton, 00170 const svn_diff_fns_t *diff_fns, 00171 apr_pool_t *pool); 00172 00173 00174 /* Utility functions */ 00175 00176 /** Determine if a diff object contains conflicts. If it does, return 00177 * @c TRUE, else return @c FALSE. 00178 */ 00179 svn_boolean_t 00180 svn_diff_contains_conflicts(svn_diff_t *diff); 00181 00182 00183 /** Determine if a diff object contains actual differences between the 00184 * datasources. If so, return @c TRUE, else return @c FALSE. 00185 */ 00186 svn_boolean_t 00187 svn_diff_contains_diffs(svn_diff_t *diff); 00188 00189 00190 00191 00192 /* Displaying Diffs */ 00193 00194 /** A vtable for displaying (or consuming) differences between datasources. 00195 * 00196 * Differences, similarities, and conflicts are described by lining up 00197 * "ranges" of data. 00198 * 00199 * @note These callbacks describe data ranges in units of "tokens". 00200 * A "token" is whatever you've defined it to be in your datasource 00201 * @c svn_diff_fns_t vtable. 00202 */ 00203 typedef struct svn_diff_output_fns_t 00204 { 00205 /* Two-way and three-way diffs both call the first two output functions: */ 00206 00207 /** 00208 * If doing a two-way diff, then an *identical* data range was found 00209 * between the "original" and "modified" datasources. Specifically, 00210 * the match starts at @a original_start and goes for @a original_length 00211 * tokens in the original data, and at @a modified_start for 00212 * @a modified_length tokens in the modified data. 00213 * 00214 * If doing a three-way diff, then all three datasources have 00215 * matching data ranges. The range @a latest_start, @a latest_length in 00216 * the "latest" datasource is identical to the range @a original_start, 00217 * @a original_length in the original data, and is also identical to 00218 * the range @a modified_start, @a modified_length in the modified data. 00219 */ 00220 svn_error_t *(*output_common)(void *output_baton, 00221 apr_off_t original_start, 00222 apr_off_t original_length, 00223 apr_off_t modified_start, 00224 apr_off_t modified_length, 00225 apr_off_t latest_start, 00226 apr_off_t latest_length); 00227 00228 /** 00229 * If doing a two-way diff, then an *conflicting* data range was found 00230 * between the "original" and "modified" datasources. Specifically, 00231 * the conflict starts at @a original_start and goes for @a original_length 00232 * tokens in the original data, and at @a modified_start for 00233 * @a modified_length tokens in the modified data. 00234 * 00235 * If doing a three-way diff, then an identical data range was discovered 00236 * between the "original" and "latest" datasources, but this conflicts with 00237 * a range in the "modified" datasource. 00238 */ 00239 svn_error_t *(*output_diff_modified)(void *output_baton, 00240 apr_off_t original_start, 00241 apr_off_t original_length, 00242 apr_off_t modified_start, 00243 apr_off_t modified_length, 00244 apr_off_t latest_start, 00245 apr_off_t latest_length); 00246 00247 /* ------ The following callbacks are used by three-way diffs only --- */ 00248 00249 /** An identical data range was discovered between the "original" and 00250 * "modified" datasources, but this conflicts with a range in the 00251 * "latest" datasource. 00252 */ 00253 svn_error_t *(*output_diff_latest)(void *output_baton, 00254 apr_off_t original_start, 00255 apr_off_t original_length, 00256 apr_off_t modified_start, 00257 apr_off_t modified_length, 00258 apr_off_t latest_start, 00259 apr_off_t latest_length); 00260 00261 /** An identical data range was discovered between the "modified" and 00262 * "latest" datasources, but this conflicts with a range in the 00263 * "original" datasource. 00264 */ 00265 svn_error_t *(*output_diff_common)(void *output_baton, 00266 apr_off_t original_start, 00267 apr_off_t original_length, 00268 apr_off_t modified_start, 00269 apr_off_t modified_length, 00270 apr_off_t latest_start, 00271 apr_off_t latest_length); 00272 00273 /** All three datasources have conflicting data ranges. The range 00274 * @a latest_start, @a latest_length in the "latest" datasource conflicts 00275 * with the range @a original_start, @a original_length in the "original" 00276 * datasource, and also conflicts with the range @a modified_start, 00277 * @a modified_length in the "modified" datasource. 00278 * If there are common ranges in the "modified" and "latest" datasources 00279 * in this conflicting range, @a resolved_diff will contain a diff 00280 * which can be used to retrieve the common and conflicting ranges. 00281 */ 00282 svn_error_t *(*output_conflict)(void *output_baton, 00283 apr_off_t original_start, 00284 apr_off_t original_length, 00285 apr_off_t modified_start, 00286 apr_off_t modified_length, 00287 apr_off_t latest_start, 00288 apr_off_t latest_length, 00289 svn_diff_t *resolved_diff); 00290 } svn_diff_output_fns_t; 00291 00292 00293 /** Given a vtable of @a output_fns/@a output_baton for consuming 00294 * differences, output the differences in @a diff. 00295 */ 00296 svn_error_t * 00297 svn_diff_output(svn_diff_t *diff, 00298 void *output_baton, 00299 const svn_diff_output_fns_t *output_fns); 00300 00301 00302 00303 /* Diffs on files */ 00304 00305 /** To what extent whitespace should be ignored when comparing lines. 00306 * 00307 * @since New in 1.4. 00308 */ 00309 typedef enum svn_diff_file_ignore_space_t 00310 { 00311 /** Ignore no whitespace. */ 00312 svn_diff_file_ignore_space_none, 00313 00314 /** Ignore changes in sequences of whitespace characters, treating each 00315 * sequence of whitespace characters as a single space. */ 00316 svn_diff_file_ignore_space_change, 00317 00318 /** Ignore all whitespace characters. */ 00319 svn_diff_file_ignore_space_all 00320 } svn_diff_file_ignore_space_t; 00321 00322 /** Options to control the behaviour of the file diff routines. 00323 * 00324 * @since New in 1.4. 00325 * 00326 * @note This structure may be extended in the future, so to preserve binary 00327 * compatibility, users must not allocate structs of this type themselves. 00328 * @see svn_diff_file_options_create(). 00329 * 00330 * @note Although its name suggests otherwise, this structure is used to 00331 * pass options to file as well as in-memory diff functions. 00332 */ 00333 typedef struct svn_diff_file_options_t 00334 { 00335 /** To what extent whitespace should be ignored when comparing lines. 00336 * The default is @c svn_diff_file_ignore_space_none. */ 00337 svn_diff_file_ignore_space_t ignore_space; 00338 /** Whether to treat all end-of-line markers the same when comparing lines. 00339 * The default is @c FALSE. */ 00340 svn_boolean_t ignore_eol_style; 00341 /** Whether the '@@' lines of the unified diff output should include a prefix 00342 * of the nearest preceding line that starts with a character that might be 00343 * the initial character of a C language identifier. The default is 00344 * @c FALSE. 00345 */ 00346 svn_boolean_t show_c_function; 00347 } svn_diff_file_options_t; 00348 00349 /** Allocate a @c svn_diff_file_options_t structure in @a pool, initializing 00350 * it with default values. 00351 * 00352 * @since New in 1.4. 00353 */ 00354 svn_diff_file_options_t * 00355 svn_diff_file_options_create(apr_pool_t *pool); 00356 00357 /** 00358 * Parse @a args, an array of <tt>const char *</tt> command line switches 00359 * and adjust @a options accordingly. @a options is assumed to be initialized 00360 * with default values. @a pool is used for temporary allocation. 00361 * 00362 * @since New in 1.4. 00363 * 00364 * The following options are supported: 00365 * - --ignore-space-change, -b 00366 * - --ignore-all-space, -w 00367 * - --ignore-eol-style 00368 * - --unified, -u (for compatibility, does nothing). 00369 */ 00370 svn_error_t * 00371 svn_diff_file_options_parse(svn_diff_file_options_t *options, 00372 const apr_array_header_t *args, 00373 apr_pool_t *pool); 00374 00375 00376 /** A convenience function to produce a diff between two files. 00377 * 00378 * @since New in 1.4. 00379 * 00380 * Return a diff object in @a *diff (allocated from @a pool) that represents 00381 * the difference between an @a original file and @a modified file. 00382 * (The file arguments must be full paths to the files.) 00383 * 00384 * Compare lines according to the relevant fields of @a options. 00385 */ 00386 svn_error_t * 00387 svn_diff_file_diff_2(svn_diff_t **diff, 00388 const char *original, 00389 const char *modified, 00390 const svn_diff_file_options_t *options, 00391 apr_pool_t *pool); 00392 00393 /** Similar to svn_file_diff_2(), but with @a options set to a struct with 00394 * default options. 00395 * 00396 * @deprecated Provided for backwards compatibility with the 1.3 API. 00397 */ 00398 svn_error_t * 00399 svn_diff_file_diff(svn_diff_t **diff, 00400 const char *original, 00401 const char *modified, 00402 apr_pool_t *pool); 00403 00404 /** A convenience function to produce a diff between three files. 00405 * 00406 * @since New in 1.4. 00407 * 00408 * Return a diff object in @a *diff (allocated from @a pool) that represents 00409 * the difference between an @a original file, @a modified file, and @a latest 00410 * file. 00411 * 00412 * Compare lines according to the relevant fields of @a options. 00413 */ 00414 svn_error_t * 00415 svn_diff_file_diff3_2(svn_diff_t **diff, 00416 const char *original, 00417 const char *modified, 00418 const char *latest, 00419 const svn_diff_file_options_t *options, 00420 apr_pool_t *pool); 00421 00422 /** Similar to svn_diff_file_diff3_2(), but with @a options set to a struct 00423 * with default options. 00424 * 00425 * @deprecated Provided for backwards compatibility with the 1.3 API. 00426 */ 00427 svn_error_t * 00428 svn_diff_file_diff3(svn_diff_t **diff, 00429 const char *original, 00430 const char *modified, 00431 const char *latest, 00432 apr_pool_t *pool); 00433 00434 /** A convenience function to produce a diff between four files. 00435 * 00436 * @since New in 1.4. 00437 * 00438 * Return a diff object in @a *diff (allocated from @a pool) that represents 00439 * the difference between an @a original file, @a modified file, @a latest 00440 * and @a ancestor file. (The file arguments must be full paths to the files.) 00441 * 00442 * Compare lines according to the relevant fields of @a options. 00443 */ 00444 svn_error_t * 00445 svn_diff_file_diff4_2(svn_diff_t **diff, 00446 const char *original, 00447 const char *modified, 00448 const char *latest, 00449 const char *ancestor, 00450 const svn_diff_file_options_t *options, 00451 apr_pool_t *pool); 00452 00453 /** Simliar to svn_file_diff4_2(), but with @a options set to a struct with 00454 * default options. 00455 * 00456 * @deprecated Provided for backwards compatibility with the 1.3 API. 00457 */ 00458 svn_error_t * 00459 svn_diff_file_diff4(svn_diff_t **diff, 00460 const char *original, 00461 const char *modified, 00462 const char *latest, 00463 const char *ancestor, 00464 apr_pool_t *pool); 00465 00466 /** A convenience function to produce unified diff output from the 00467 * diff generated by svn_diff_file_diff(). 00468 * 00469 * @since New in 1.5. 00470 * 00471 * Output a @a diff between @a original_path and @a modified_path in unified 00472 * context diff format to @a output_stream. Optionally supply 00473 * @a original_header and/or @a modified_header to be displayed in the header 00474 * of the output. If @a original_header or @a modified_header is @c NULL, a 00475 * default header will be displayed, consisting of path and last modified time. 00476 * Output all headers and markers in @a header_encoding. If @a relative_to_dir 00477 * is not @c NULL, the @a original_path and @a modified_path will have the 00478 * @a relative_to_dir stripped from the front of the respective paths. If 00479 * @a relative_to_dir is @c NULL, paths will be not be modified. If 00480 * @a relative_to_dir is not @c NULL but @a relative_to_dir is not a parent 00481 * path of the target, an error is returned. Finally, if @a relative_to_dir 00482 * is a URL, an error will be returned. 00483 */ 00484 svn_error_t * 00485 svn_diff_file_output_unified3(svn_stream_t *output_stream, 00486 svn_diff_t *diff, 00487 const char *original_path, 00488 const char *modified_path, 00489 const char *original_header, 00490 const char *modified_header, 00491 const char *header_encoding, 00492 const char *relative_to_dir, 00493 svn_boolean_t show_c_function, 00494 apr_pool_t *pool); 00495 00496 /** Similar to svn_diff_file_output_unified3(), but with @a relative_to_dir 00497 * set to NULL and @a show_c_function to false. 00498 * 00499 * @deprecated Provided for backwards compatibility with the 1.3 API. 00500 */ 00501 svn_error_t * 00502 svn_diff_file_output_unified2(svn_stream_t *output_stream, 00503 svn_diff_t *diff, 00504 const char *original_path, 00505 const char *modified_path, 00506 const char *original_header, 00507 const char *modified_header, 00508 const char *header_encoding, 00509 apr_pool_t *pool); 00510 00511 /** Similar to svn_diff_file_output_unified2(), but with @a header_encoding 00512 * set to @c APR_LOCALE_CHARSET. 00513 * 00514 * @deprecated Provided for backward compatibility with the 1.2 API. 00515 */ 00516 svn_error_t * 00517 svn_diff_file_output_unified(svn_stream_t *output_stream, 00518 svn_diff_t *diff, 00519 const char *original_path, 00520 const char *modified_path, 00521 const char *original_header, 00522 const char *modified_header, 00523 apr_pool_t *pool); 00524 00525 00526 /** A convenience function to produce diff3 output from the 00527 * diff generated by svn_diff_file_diff3(). 00528 * 00529 * Output a @a diff between @a original_path, @a modified_path and 00530 * @a latest_path in merged format to @a output_stream. Optionally supply 00531 * @a conflict_modified, @a conflict_original, @a conflict_separator and/or 00532 * @a conflict_latest to be displayed as conflict markers in the output. 00533 * If @a conflict_original, @a conflict_modified, @a conflict_latest and/or 00534 * @a conflict_separator is @c NULL, a default marker will be displayed. 00535 * Set @a display_original_in_conflict and @a display_resolved_conflicts 00536 * as desired. Note that these options are mutually exclusive. 00537 */ 00538 svn_error_t * 00539 svn_diff_file_output_merge(svn_stream_t *output_stream, 00540 svn_diff_t *diff, 00541 const char *original_path, 00542 const char *modified_path, 00543 const char *latest_path, 00544 const char *conflict_original, 00545 const char *conflict_modified, 00546 const char *conflict_latest, 00547 const char *conflict_separator, 00548 svn_boolean_t display_original_in_conflict, 00549 svn_boolean_t display_resolved_conflicts, 00550 apr_pool_t *pool); 00551 00552 00553 00554 /* Diffs on in-memory structures */ 00555 00556 /** Generate @a diff output from the @a original and @a modified 00557 * in-memory strings. @a diff will be allocated from @a pool. 00558 * 00559 * @since New in 1.5. 00560 */ 00561 svn_error_t * 00562 svn_diff_mem_string_diff(svn_diff_t **diff, 00563 const svn_string_t *original, 00564 const svn_string_t *modified, 00565 const svn_diff_file_options_t *options, 00566 apr_pool_t *pool); 00567 00568 00569 /** Generate @a diff output from the @a orginal, @a modified and @a latest 00570 * in-memory strings. @a diff will be allocated in @a pool. 00571 * 00572 * @since New in 1.5. 00573 */ 00574 svn_error_t * 00575 svn_diff_mem_string_diff3(svn_diff_t **diff, 00576 const svn_string_t *original, 00577 const svn_string_t *modified, 00578 const svn_string_t *latest, 00579 const svn_diff_file_options_t *options, 00580 apr_pool_t *pool); 00581 00582 00583 /** Generate @a diff output from the @a original, @a modified and @a latest 00584 * in-memory strings, using @a ancestor. @a diff will be allocated in @a pool. 00585 * 00586 * @since New in 1.5. 00587 */ 00588 svn_error_t * 00589 svn_diff_mem_string_diff4(svn_diff_t **diff, 00590 const svn_string_t *original, 00591 const svn_string_t *modified, 00592 const svn_string_t *latest, 00593 const svn_string_t *ancestor, 00594 const svn_diff_file_options_t *options, 00595 apr_pool_t *pool); 00596 00597 00598 /** Outputs the @a diff object generated by svn_diff_mem_string_diff() 00599 * in unified diff format on @a output_stream, using @a original 00600 * and @a modified for the text in the output. 00601 * Outputs the header and markers in @a header_encoding. 00602 * 00603 * @a original_header and @a modified header are 00604 * used to fill the field after the "---" and "+++" header markers. 00605 * 00606 * @since New in 1.5. 00607 */ 00608 svn_error_t * 00609 svn_diff_mem_string_output_unified(svn_stream_t *output_stream, 00610 svn_diff_t *diff, 00611 const char *original_header, 00612 const char *modified_header, 00613 const char *header_encoding, 00614 const svn_string_t *original, 00615 const svn_string_t *modified, 00616 apr_pool_t *pool); 00617 00618 /** Output the @a diff generated by svn_diff_mem_string_diff3() in diff3 00619 * format on @a output_stream, using @a original, @a modified and @a latest 00620 * for content changes. 00621 * 00622 * Use the conflict markers @a conflict_original, @a conflict_modified, 00623 * @a conflict_latest and @a conflict_separator or the default one for 00624 * each of these if @c NULL is passed. 00625 * 00626 * Insert the original in the output if @a display_original_in_conflict 00627 * is @c TRUE. 00628 * 00629 * @note @a display_original_in_conflict and @a display_resolved_conflicts 00630 * are mutually exclusive. 00631 */ 00632 svn_error_t * 00633 svn_diff_mem_string_output_merge(svn_stream_t *output_stream, 00634 svn_diff_t *diff, 00635 const svn_string_t *original, 00636 const svn_string_t *modified, 00637 const svn_string_t *latest, 00638 const char *conflict_original, 00639 const char *conflict_modified, 00640 const char *conflict_latest, 00641 const char *conflict_separator, 00642 svn_boolean_t display_original_in_conflict, 00643 svn_boolean_t display_resolved_conflicts, 00644 apr_pool_t *pool); 00645 00646 00647 #ifdef __cplusplus 00648 } 00649 #endif /* __cplusplus */ 00650 00651 #endif /* SVN_DIFF_H */