* subversion/mod_dav_svn/reports/replay.c
[svn.git] / subversion / libsvn_client / repos_diff_summarize.c
blob01d347f8104fba3d4f8a47ac0e60c9368be8eb17
1 /*
2 * repos_diff_summarize.c -- The diff summarize editor for summarizing
3 * the differences of two repository versions
5 * ====================================================================
6 * Copyright (c) 2005-2006 CollabNet. All rights reserved.
8 * This software is licensed as described in the file COPYING, which
9 * you should have received as part of this distribution. The terms
10 * are also available at http://subversion.tigris.org/license-1.html.
11 * If newer versions of this license are posted there, you may use a
12 * newer version instead, at your option.
14 * This software consists of voluntary contributions made by many
15 * individuals. For exact contribution history, see the revision
16 * history and logs, available at http://subversion.tigris.org/.
17 * ====================================================================
21 #include "svn_props.h"
22 #include "svn_pools.h"
24 #include "client.h"
27 /* Overall crawler editor baton. */
28 struct edit_baton {
29 /* The target of the diff, relative to the root of the edit */
30 const char *target;
32 /* The summarize callback passed down from the API */
33 svn_client_diff_summarize_func_t summarize_func;
35 /* The summarize callback baton */
36 void *summarize_func_baton;
38 /* An RA session used to check the kind of deleted paths */
39 svn_ra_session_t *ra_session;
41 /* The start revision for the comparison */
42 svn_revnum_t revision;
46 /* Item baton. */
47 struct item_baton {
48 /* The overall crawler editor baton */
49 struct edit_baton *edit_baton;
51 /* The summarize filled by the editor calls, NULL if this item hasn't
52 been modified (yet) */
53 svn_client_diff_summarize_t *summarize;
55 /* The path of the file or directory within the repository */
56 const char *path;
58 /* The kind of this item */
59 svn_node_kind_t node_kind;
61 /* The file/directory pool */
62 apr_pool_t *item_pool;
66 /* Create an item baton, with the fields initialized to EDIT_BATON, PATH,
67 * NODE_KIND and POOL, respectively. Allocate the returned structure in POOL.
69 static struct item_baton *
70 create_item_baton(struct edit_baton *edit_baton,
71 const char *path,
72 svn_node_kind_t node_kind,
73 apr_pool_t *pool)
75 struct item_baton *b = apr_pcalloc(pool, sizeof(*b));
77 b->edit_baton = edit_baton;
78 /* Issue #2765: b->path is supposed to be relative to the target.
79 If the target is a file, just use an empty path. This way the
80 receiver can just concatenate this path to the original path
81 without doing any extra checks. */
82 if (node_kind == svn_node_file && strcmp(path, edit_baton->target) == 0)
83 b->path = "";
84 else
85 b->path = apr_pstrdup(pool, path);
86 b->node_kind = node_kind;
87 b->item_pool = pool;
89 return b;
92 /* Make sure that this item baton contains a summarize struct.
93 * If it doesn't before this call, allocate a new struct in the item's pool,
94 * initializing the diff kind to normal.
95 * All other fields are also initialized from IB to to NULL/invalid values. */
96 static void
97 ensure_summarize(struct item_baton *ib)
99 svn_client_diff_summarize_t *sum;
100 if (ib->summarize)
101 return;
103 sum = apr_pcalloc(ib->item_pool, sizeof(*sum));
105 sum->node_kind = ib->node_kind;
106 sum->summarize_kind = svn_client_diff_summarize_kind_normal;
107 sum->path = ib->path;
109 ib->summarize = sum;
113 /* An editor function. The root of the comparison hierarchy */
114 static svn_error_t *
115 open_root(void *edit_baton,
116 svn_revnum_t base_revision,
117 apr_pool_t *pool,
118 void **root_baton)
120 struct item_baton *ib = create_item_baton(edit_baton, "",
121 svn_node_dir, pool);
123 *root_baton = ib;
124 return SVN_NO_ERROR;
127 /* An editor function. */
128 static svn_error_t *
129 delete_entry(const char *path,
130 svn_revnum_t base_revision,
131 void *parent_baton,
132 apr_pool_t *pool)
134 struct item_baton *ib = parent_baton;
135 struct edit_baton *eb = ib->edit_baton;
136 svn_client_diff_summarize_t *sum;
137 svn_node_kind_t kind;
139 /* We need to know if this is a directory or a file */
140 SVN_ERR(svn_ra_check_path(eb->ra_session,
141 path,
142 eb->revision,
143 &kind,
144 pool));
146 sum = apr_pcalloc(pool, sizeof(*sum));
147 sum->summarize_kind = svn_client_diff_summarize_kind_deleted;
148 sum->path = path;
149 sum->node_kind = kind;
151 SVN_ERR(eb->summarize_func(sum, eb->summarize_func_baton, pool));
153 return SVN_NO_ERROR;
156 /* An editor function. */
157 static svn_error_t *
158 add_directory(const char *path,
159 void *parent_baton,
160 const char *copyfrom_path,
161 svn_revnum_t copyfrom_rev,
162 apr_pool_t *pool,
163 void **child_baton)
165 struct item_baton *pb = parent_baton;
166 struct item_baton *cb;
168 cb = create_item_baton(pb->edit_baton, path, svn_node_dir, pool);
169 ensure_summarize(cb);
170 cb->summarize->summarize_kind = svn_client_diff_summarize_kind_added;
172 *child_baton = cb;
173 return SVN_NO_ERROR;
176 /* An editor function. */
177 static svn_error_t *
178 open_directory(const char *path,
179 void *parent_baton,
180 svn_revnum_t base_revision,
181 apr_pool_t *pool,
182 void **child_baton)
184 struct item_baton *pb = parent_baton;
185 struct item_baton *cb;
187 cb = create_item_baton(pb->edit_baton, path, svn_node_dir, pool);
189 *child_baton = cb;
190 return SVN_NO_ERROR;
194 /* An editor function. */
195 static svn_error_t *
196 close_directory(void *dir_baton,
197 apr_pool_t *pool)
199 struct item_baton *ib = dir_baton;
200 struct edit_baton *eb = ib->edit_baton;
202 if (ib->summarize)
203 SVN_ERR(eb->summarize_func(ib->summarize, eb->summarize_func_baton,
204 pool));
206 return SVN_NO_ERROR;
210 /* An editor function. */
211 static svn_error_t *
212 add_file(const char *path,
213 void *parent_baton,
214 const char *copyfrom_path,
215 svn_revnum_t copyfrom_rev,
216 apr_pool_t *pool,
217 void **file_baton)
219 struct item_baton *pb = parent_baton;
220 struct item_baton *cb;
222 cb = create_item_baton(pb->edit_baton, path, svn_node_file, pool);
223 ensure_summarize(cb);
224 cb->summarize->summarize_kind = svn_client_diff_summarize_kind_added;
226 *file_baton = cb;
227 return SVN_NO_ERROR;
230 /* An editor function. */
231 static svn_error_t *
232 open_file(const char *path,
233 void *parent_baton,
234 svn_revnum_t base_revision,
235 apr_pool_t *pool,
236 void **file_baton)
238 struct item_baton *pb = parent_baton;
239 struct item_baton *cb;
241 cb = create_item_baton(pb->edit_baton, path, svn_node_file, pool);
243 *file_baton = cb;
244 return SVN_NO_ERROR;
247 /* An editor function. */
248 static svn_error_t *
249 apply_textdelta(void *file_baton,
250 const char *base_checksum,
251 apr_pool_t *pool,
252 svn_txdelta_window_handler_t *handler,
253 void **handler_baton)
255 struct item_baton *ib = file_baton;
257 ensure_summarize(ib);
258 if (ib->summarize->summarize_kind == svn_client_diff_summarize_kind_normal)
259 ib->summarize->summarize_kind = svn_client_diff_summarize_kind_modified;
261 *handler = svn_delta_noop_window_handler;
262 *handler_baton = NULL;
264 return SVN_NO_ERROR;
268 /* An editor function. */
269 static svn_error_t *
270 close_file(void *file_baton,
271 const char *text_checksum,
272 apr_pool_t *pool)
274 struct item_baton *fb = file_baton;
275 struct edit_baton *eb = fb->edit_baton;
277 if (fb->summarize)
278 SVN_ERR(eb->summarize_func(fb->summarize, eb->summarize_func_baton,
279 pool));
281 return SVN_NO_ERROR;
285 /* An editor function, implementing both change_file_prop and
286 * change_dir_prop. */
287 static svn_error_t *
288 change_prop(void *entry_baton,
289 const char *name,
290 const svn_string_t *value,
291 apr_pool_t *pool)
293 struct item_baton *ib = entry_baton;
295 if (svn_property_kind(NULL, name) == svn_prop_regular_kind)
297 ensure_summarize(ib);
298 ib->summarize->prop_changed = TRUE;
301 return SVN_NO_ERROR;
304 /* Create a repository diff summarize editor and baton. */
305 svn_error_t *
306 svn_client__get_diff_summarize_editor(const char *target,
307 svn_client_diff_summarize_func_t
308 summarize_func,
309 void *item_baton,
310 svn_ra_session_t *ra_session,
311 svn_revnum_t revision,
312 svn_cancel_func_t cancel_func,
313 void *cancel_baton,
314 const svn_delta_editor_t **editor,
315 void **edit_baton,
316 apr_pool_t *pool)
318 svn_delta_editor_t *tree_editor = svn_delta_default_editor(pool);
319 struct edit_baton *eb = apr_palloc(pool, sizeof(*eb));
321 eb->target = target;
322 eb->summarize_func = summarize_func;
323 eb->summarize_func_baton = item_baton;
324 eb->ra_session = ra_session;
325 eb->revision = revision;
327 tree_editor->open_root = open_root;
328 tree_editor->delete_entry = delete_entry;
329 tree_editor->add_directory = add_directory;
330 tree_editor->open_directory = open_directory;
331 tree_editor->change_dir_prop = change_prop;
332 tree_editor->close_directory = close_directory;
334 tree_editor->add_file = add_file;
335 tree_editor->open_file = open_file;
336 tree_editor->apply_textdelta = apply_textdelta;
337 tree_editor->change_file_prop = change_prop;
338 tree_editor->close_file = close_file;
340 SVN_ERR(svn_delta_get_cancellation_editor
341 (cancel_func, cancel_baton, tree_editor, eb, editor, edit_baton,
342 pool));
344 return SVN_NO_ERROR;