Reorganize the output to "svnserve --help".
[svn.git] / subversion / libsvn_diff / diff.c
blob75cfac6358a1e51a62f985d5bc8b536f948c158f
1 /*
2 * diff.c : routines for doing diffs
4 * ====================================================================
5 * Copyright (c) 2000-2004 CollabNet. All rights reserved.
7 * This software is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at http://subversion.tigris.org/license-1.html.
10 * If newer versions of this license are posted there, you may use a
11 * newer version instead, at your option.
13 * This software consists of voluntary contributions made by many
14 * individuals. For exact contribution history, see the revision
15 * history and logs, available at http://subversion.tigris.org/.
16 * ====================================================================
20 #include <apr.h>
21 #include <apr_pools.h>
22 #include <apr_general.h>
24 #include "svn_pools.h"
25 #include "svn_error.h"
26 #include "svn_diff.h"
27 #include "svn_types.h"
29 #include "diff.h"
32 svn_diff_t *
33 svn_diff__diff(svn_diff__lcs_t *lcs,
34 apr_off_t original_start, apr_off_t modified_start,
35 svn_boolean_t want_common,
36 apr_pool_t *pool)
38 svn_diff_t *diff;
39 svn_diff_t **diff_ref = &diff;
41 while (1)
43 if (original_start < lcs->position[0]->offset
44 || modified_start < lcs->position[1]->offset)
46 (*diff_ref) = apr_palloc(pool, sizeof(**diff_ref));
48 (*diff_ref)->type = svn_diff__type_diff_modified;
49 (*diff_ref)->original_start = original_start - 1;
50 (*diff_ref)->original_length =
51 lcs->position[0]->offset - original_start;
52 (*diff_ref)->modified_start = modified_start - 1;
53 (*diff_ref)->modified_length =
54 lcs->position[1]->offset - modified_start;
55 (*diff_ref)->latest_start = 0;
56 (*diff_ref)->latest_length = 0;
58 diff_ref = &(*diff_ref)->next;
61 /* Detect the EOF */
62 if (lcs->length == 0)
63 break;
65 original_start = lcs->position[0]->offset;
66 modified_start = lcs->position[1]->offset;
68 if (want_common)
70 (*diff_ref) = apr_palloc(pool, sizeof(**diff_ref));
72 (*diff_ref)->type = svn_diff__type_common;
73 (*diff_ref)->original_start = original_start - 1;
74 (*diff_ref)->original_length = lcs->length;
75 (*diff_ref)->modified_start = modified_start - 1;
76 (*diff_ref)->modified_length = lcs->length;
77 (*diff_ref)->latest_start = 0;
78 (*diff_ref)->latest_length = 0;
80 diff_ref = &(*diff_ref)->next;
83 original_start += lcs->length;
84 modified_start += lcs->length;
86 lcs = lcs->next;
89 *diff_ref = NULL;
91 return diff;
95 svn_error_t *
96 svn_diff_diff(svn_diff_t **diff,
97 void *diff_baton,
98 const svn_diff_fns_t *vtable,
99 apr_pool_t *pool)
101 svn_diff__tree_t *tree;
102 svn_diff__position_t *position_list[2];
103 svn_diff__lcs_t *lcs;
104 apr_pool_t *subpool;
105 apr_pool_t *treepool;
107 *diff = NULL;
109 subpool = svn_pool_create(pool);
110 treepool = svn_pool_create(pool);
112 svn_diff__tree_create(&tree, treepool);
114 /* Insert the data into the tree */
115 SVN_ERR(svn_diff__get_tokens(&position_list[0],
116 tree,
117 diff_baton, vtable,
118 svn_diff_datasource_original,
119 subpool));
121 SVN_ERR(svn_diff__get_tokens(&position_list[1],
122 tree,
123 diff_baton, vtable,
124 svn_diff_datasource_modified,
125 subpool));
127 /* The cool part is that we don't need the tokens anymore.
128 * Allow the app to clean them up if it wants to.
130 if (vtable->token_discard_all != NULL)
131 vtable->token_discard_all(diff_baton);
133 /* We don't need the nodes in the tree either anymore, nor the tree itself */
134 svn_pool_destroy(treepool);
136 /* Get the lcs */
137 lcs = svn_diff__lcs(position_list[0], position_list[1], subpool);
139 /* Produce the diff */
140 *diff = svn_diff__diff(lcs, 1, 1, TRUE, pool);
142 /* Get rid of all the data we don't have a use for anymore */
143 svn_pool_destroy(subpool);
145 return SVN_NO_ERROR;