2 * repos_diff_summarize.c -- The diff callbacks for summarizing
3 * the differences of two repository versions
5 * ====================================================================
6 * Licensed to the Apache Software Foundation (ASF) under one
7 * or more contributor license agreements. See the NOTICE file
8 * distributed with this work for additional information
9 * regarding copyright ownership. The ASF licenses this file
10 * to you under the Apache License, Version 2.0 (the
11 * "License"); you may not use this file except in compliance
12 * with the License. You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * Unless required by applicable law or agreed to in writing,
17 * software distributed under the License is distributed on an
18 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19 * KIND, either express or implied. See the License for the
20 * specific language governing permissions and limitations
22 * ====================================================================
26 #include "svn_dirent_uri.h"
28 #include "svn_props.h"
29 #include "svn_pools.h"
34 /* Diff callbacks baton. */
35 struct summarize_baton_t {
36 /* The target path of the diff, relative to the anchor; "" if target == anchor. */
39 /* The summarize callback passed down from the API */
40 svn_client_diff_summarize_func_t summarize_func;
42 /* Is the diff handling reversed? (add<->delete) */
43 svn_boolean_t reversed;
45 /* The summarize callback baton */
46 void *summarize_func_baton;
48 /* Which paths have a prop change. Key is a (const char *) path; the value
49 * is any non-null pointer to indicate that this path has a prop change. */
50 apr_hash_t *prop_changes;
54 /* Call B->summarize_func with B->summarize_func_baton, passing it a
55 * summary object composed from PATH (but made to be relative to the target
56 * of the diff), SUMMARIZE_KIND, PROP_CHANGED (or FALSE if the action is an
57 * add or delete) and NODE_KIND. */
59 send_summary(struct summarize_baton_t *b,
61 svn_client_diff_summarize_kind_t summarize_kind,
62 svn_boolean_t prop_changed,
63 svn_node_kind_t node_kind,
64 apr_pool_t *scratch_pool)
66 svn_client_diff_summarize_t *sum = apr_pcalloc(scratch_pool, sizeof(*sum));
68 SVN_ERR_ASSERT(summarize_kind != svn_client_diff_summarize_kind_normal
73 switch(summarize_kind)
75 case svn_client_diff_summarize_kind_added:
76 summarize_kind = svn_client_diff_summarize_kind_deleted;
78 case svn_client_diff_summarize_kind_deleted:
79 summarize_kind = svn_client_diff_summarize_kind_added;
86 /* PATH is relative to the anchor of the diff, but SUM->path needs to be
87 relative to the target of the diff. */
88 sum->path = svn_relpath_skip_ancestor(b->target, path);
89 sum->summarize_kind = summarize_kind;
90 if (summarize_kind == svn_client_diff_summarize_kind_modified
91 || summarize_kind == svn_client_diff_summarize_kind_normal)
92 sum->prop_changed = prop_changed;
93 sum->node_kind = node_kind;
95 SVN_ERR(b->summarize_func(sum, b->summarize_func_baton, scratch_pool));
99 /* Are there any changes to relevant (normal) props in PROPCHANGES? */
101 props_changed(const apr_array_header_t *propchanges,
102 apr_pool_t *scratch_pool)
104 apr_array_header_t *props;
106 svn_error_clear(svn_categorize_props(propchanges, NULL, NULL, &props,
108 return (props->nelts != 0);
113 cb_dir_deleted(svn_wc_notify_state_t *state,
114 svn_boolean_t *tree_conflicted,
117 apr_pool_t *scratch_pool)
119 struct summarize_baton_t *b = diff_baton;
121 SVN_ERR(send_summary(b, path, svn_client_diff_summarize_kind_deleted,
122 FALSE, svn_node_dir, scratch_pool));
128 cb_file_deleted(svn_wc_notify_state_t *state,
129 svn_boolean_t *tree_conflicted,
131 const char *tmpfile1,
132 const char *tmpfile2,
133 const char *mimetype1,
134 const char *mimetype2,
135 apr_hash_t *originalprops,
137 apr_pool_t *scratch_pool)
139 struct summarize_baton_t *b = diff_baton;
141 SVN_ERR(send_summary(b, path, svn_client_diff_summarize_kind_deleted,
142 FALSE, svn_node_file, scratch_pool));
148 cb_dir_added(svn_wc_notify_state_t *state,
149 svn_boolean_t *tree_conflicted,
151 svn_boolean_t *skip_children,
154 const char *copyfrom_path,
155 svn_revnum_t copyfrom_revision,
157 apr_pool_t *scratch_pool)
163 cb_dir_opened(svn_boolean_t *tree_conflicted,
165 svn_boolean_t *skip_children,
169 apr_pool_t *scratch_pool)
175 cb_dir_closed(svn_wc_notify_state_t *contentstate,
176 svn_wc_notify_state_t *propstate,
177 svn_boolean_t *tree_conflicted,
179 svn_boolean_t dir_was_added,
181 apr_pool_t *scratch_pool)
183 struct summarize_baton_t *b = diff_baton;
184 svn_boolean_t prop_change;
186 if (! svn_relpath_skip_ancestor(b->target, path))
189 prop_change = svn_hash_gets(b->prop_changes, path) != NULL;
190 if (dir_was_added || prop_change)
191 SVN_ERR(send_summary(b, path,
192 dir_was_added ? svn_client_diff_summarize_kind_added
193 : svn_client_diff_summarize_kind_normal,
194 prop_change, svn_node_dir, scratch_pool));
200 cb_file_added(svn_wc_notify_state_t *contentstate,
201 svn_wc_notify_state_t *propstate,
202 svn_boolean_t *tree_conflicted,
204 const char *tmpfile1,
205 const char *tmpfile2,
208 const char *mimetype1,
209 const char *mimetype2,
210 const char *copyfrom_path,
211 svn_revnum_t copyfrom_revision,
212 const apr_array_header_t *propchanges,
213 apr_hash_t *originalprops,
215 apr_pool_t *scratch_pool)
217 struct summarize_baton_t *b = diff_baton;
219 SVN_ERR(send_summary(b, path, svn_client_diff_summarize_kind_added,
220 props_changed(propchanges, scratch_pool),
221 svn_node_file, scratch_pool));
227 cb_file_opened(svn_boolean_t *tree_conflicted,
232 apr_pool_t *scratch_pool)
238 cb_file_changed(svn_wc_notify_state_t *contentstate,
239 svn_wc_notify_state_t *propstate,
240 svn_boolean_t *tree_conflicted,
242 const char *tmpfile1,
243 const char *tmpfile2,
246 const char *mimetype1,
247 const char *mimetype2,
248 const apr_array_header_t *propchanges,
249 apr_hash_t *originalprops,
251 apr_pool_t *scratch_pool)
253 struct summarize_baton_t *b = diff_baton;
254 svn_boolean_t text_change = (tmpfile2 != NULL);
255 svn_boolean_t prop_change = props_changed(propchanges, scratch_pool);
257 if (text_change || prop_change)
258 SVN_ERR(send_summary(b, path,
259 text_change ? svn_client_diff_summarize_kind_modified
260 : svn_client_diff_summarize_kind_normal,
261 prop_change, svn_node_file, scratch_pool));
267 cb_dir_props_changed(svn_wc_notify_state_t *propstate,
268 svn_boolean_t *tree_conflicted,
270 svn_boolean_t dir_was_added,
271 const apr_array_header_t *propchanges,
272 apr_hash_t *original_props,
274 apr_pool_t *scratch_pool)
276 struct summarize_baton_t *b = diff_baton;
278 if (props_changed(propchanges, scratch_pool))
279 svn_hash_sets(b->prop_changes, path, path);
285 svn_client__get_diff_summarize_callbacks(
286 svn_wc_diff_callbacks4_t **callbacks,
287 void **callback_baton,
289 svn_boolean_t reversed,
290 svn_client_diff_summarize_func_t summarize_func,
291 void *summarize_baton,
294 svn_wc_diff_callbacks4_t *cb = apr_palloc(pool, sizeof(*cb));
295 struct summarize_baton_t *b = apr_palloc(pool, sizeof(*b));
298 b->summarize_func = summarize_func;
299 b->summarize_func_baton = summarize_baton;
300 b->prop_changes = apr_hash_make(pool);
301 b->reversed = reversed;
303 cb->file_opened = cb_file_opened;
304 cb->file_changed = cb_file_changed;
305 cb->file_added = cb_file_added;
306 cb->file_deleted = cb_file_deleted;
307 cb->dir_deleted = cb_dir_deleted;
308 cb->dir_opened = cb_dir_opened;
309 cb->dir_added = cb_dir_added;
310 cb->dir_props_changed = cb_dir_props_changed;
311 cb->dir_closed = cb_dir_closed;