]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/subversion/subversion/libsvn_client/diff_summarize.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / subversion / subversion / libsvn_client / diff_summarize.c
1 /*
2  * repos_diff_summarize.c -- The diff callbacks for summarizing
3  * the differences of two repository versions
4  *
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
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
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
21  *    under the License.
22  * ====================================================================
23  */
24
25
26 #include "svn_dirent_uri.h"
27 #include "svn_hash.h"
28 #include "svn_props.h"
29 #include "svn_pools.h"
30
31 #include "client.h"
32
33
34 /* Diff callbacks baton.  */
35 struct summarize_baton_t {
36   /* The target path of the diff, relative to the anchor; "" if target == anchor. */
37   const char *target;
38
39   /* The summarize callback passed down from the API */
40   svn_client_diff_summarize_func_t summarize_func;
41
42   /* Is the diff handling reversed? (add<->delete) */
43   svn_boolean_t reversed;
44
45   /* The summarize callback baton */
46   void *summarize_func_baton;
47
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;
51 };
52
53
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. */
58 static svn_error_t *
59 send_summary(struct summarize_baton_t *b,
60              const char *path,
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)
65 {
66   svn_client_diff_summarize_t *sum = apr_pcalloc(scratch_pool, sizeof(*sum));
67
68   SVN_ERR_ASSERT(summarize_kind != svn_client_diff_summarize_kind_normal
69                  || prop_changed);
70
71   if (b->reversed)
72     {
73       switch(summarize_kind)
74         {
75           case svn_client_diff_summarize_kind_added:
76             summarize_kind = svn_client_diff_summarize_kind_deleted;
77             break;
78           case svn_client_diff_summarize_kind_deleted:
79             summarize_kind = svn_client_diff_summarize_kind_added;
80             break;
81           default:
82             break;
83         }
84     }
85
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;
94
95   SVN_ERR(b->summarize_func(sum, b->summarize_func_baton, scratch_pool));
96   return SVN_NO_ERROR;
97 }
98
99 /* Are there any changes to relevant (normal) props in PROPCHANGES? */
100 static svn_boolean_t
101 props_changed(const apr_array_header_t *propchanges,
102               apr_pool_t *scratch_pool)
103 {
104   apr_array_header_t *props;
105
106   svn_error_clear(svn_categorize_props(propchanges, NULL, NULL, &props,
107                                        scratch_pool));
108   return (props->nelts != 0);
109 }
110
111
112 static svn_error_t *
113 cb_dir_deleted(svn_wc_notify_state_t *state,
114                svn_boolean_t *tree_conflicted,
115                const char *path,
116                void *diff_baton,
117                apr_pool_t *scratch_pool)
118 {
119   struct summarize_baton_t *b = diff_baton;
120
121   SVN_ERR(send_summary(b, path, svn_client_diff_summarize_kind_deleted,
122                        FALSE, svn_node_dir, scratch_pool));
123
124   return SVN_NO_ERROR;
125 }
126
127 static svn_error_t *
128 cb_file_deleted(svn_wc_notify_state_t *state,
129                 svn_boolean_t *tree_conflicted,
130                 const char *path,
131                 const char *tmpfile1,
132                 const char *tmpfile2,
133                 const char *mimetype1,
134                 const char *mimetype2,
135                 apr_hash_t *originalprops,
136                 void *diff_baton,
137                 apr_pool_t *scratch_pool)
138 {
139   struct summarize_baton_t *b = diff_baton;
140
141   SVN_ERR(send_summary(b, path, svn_client_diff_summarize_kind_deleted,
142                        FALSE, svn_node_file, scratch_pool));
143
144   return SVN_NO_ERROR;
145 }
146
147 static svn_error_t *
148 cb_dir_added(svn_wc_notify_state_t *state,
149              svn_boolean_t *tree_conflicted,
150              svn_boolean_t *skip,
151              svn_boolean_t *skip_children,
152              const char *path,
153              svn_revnum_t rev,
154              const char *copyfrom_path,
155              svn_revnum_t copyfrom_revision,
156              void *diff_baton,
157              apr_pool_t *scratch_pool)
158 {
159   return SVN_NO_ERROR;
160 }
161
162 static svn_error_t *
163 cb_dir_opened(svn_boolean_t *tree_conflicted,
164               svn_boolean_t *skip,
165               svn_boolean_t *skip_children,
166               const char *path,
167               svn_revnum_t rev,
168               void *diff_baton,
169               apr_pool_t *scratch_pool)
170 {
171   return SVN_NO_ERROR;
172 }
173
174 static svn_error_t *
175 cb_dir_closed(svn_wc_notify_state_t *contentstate,
176               svn_wc_notify_state_t *propstate,
177               svn_boolean_t *tree_conflicted,
178               const char *path,
179               svn_boolean_t dir_was_added,
180               void *diff_baton,
181               apr_pool_t *scratch_pool)
182 {
183   struct summarize_baton_t *b = diff_baton;
184   svn_boolean_t prop_change;
185
186   if (! svn_relpath_skip_ancestor(b->target, path))
187     return SVN_NO_ERROR;
188
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));
195
196   return SVN_NO_ERROR;
197 }
198
199 static svn_error_t *
200 cb_file_added(svn_wc_notify_state_t *contentstate,
201               svn_wc_notify_state_t *propstate,
202               svn_boolean_t *tree_conflicted,
203               const char *path,
204               const char *tmpfile1,
205               const char *tmpfile2,
206               svn_revnum_t rev1,
207               svn_revnum_t rev2,
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,
214               void *diff_baton,
215               apr_pool_t *scratch_pool)
216 {
217   struct summarize_baton_t *b = diff_baton;
218
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));
222
223   return SVN_NO_ERROR;
224 }
225
226 static svn_error_t *
227 cb_file_opened(svn_boolean_t *tree_conflicted,
228                svn_boolean_t *skip,
229                const char *path,
230                svn_revnum_t rev,
231                void *diff_baton,
232                apr_pool_t *scratch_pool)
233 {
234   return SVN_NO_ERROR;
235 }
236
237 static svn_error_t *
238 cb_file_changed(svn_wc_notify_state_t *contentstate,
239                 svn_wc_notify_state_t *propstate,
240                 svn_boolean_t *tree_conflicted,
241                 const char *path,
242                 const char *tmpfile1,
243                 const char *tmpfile2,
244                 svn_revnum_t rev1,
245                 svn_revnum_t rev2,
246                 const char *mimetype1,
247                 const char *mimetype2,
248                 const apr_array_header_t *propchanges,
249                 apr_hash_t *originalprops,
250                 void *diff_baton,
251                 apr_pool_t *scratch_pool)
252 {
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);
256
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));
262
263   return SVN_NO_ERROR;
264 }
265
266 static svn_error_t *
267 cb_dir_props_changed(svn_wc_notify_state_t *propstate,
268                      svn_boolean_t *tree_conflicted,
269                      const char *path,
270                      svn_boolean_t dir_was_added,
271                      const apr_array_header_t *propchanges,
272                      apr_hash_t *original_props,
273                      void *diff_baton,
274                      apr_pool_t *scratch_pool)
275 {
276   struct summarize_baton_t *b = diff_baton;
277
278   if (props_changed(propchanges, scratch_pool))
279     svn_hash_sets(b->prop_changes, path, path);
280
281   return SVN_NO_ERROR;
282 }
283
284 svn_error_t *
285 svn_client__get_diff_summarize_callbacks(
286                         svn_wc_diff_callbacks4_t **callbacks,
287                         void **callback_baton,
288                         const char *target,
289                         svn_boolean_t reversed,
290                         svn_client_diff_summarize_func_t summarize_func,
291                         void *summarize_baton,
292                         apr_pool_t *pool)
293 {
294   svn_wc_diff_callbacks4_t *cb = apr_palloc(pool, sizeof(*cb));
295   struct summarize_baton_t *b = apr_palloc(pool, sizeof(*b));
296
297   b->target = target;
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;
302
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;
312
313   *callbacks = cb;
314   *callback_baton = b;
315
316   return SVN_NO_ERROR;
317 }