]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/subversion/subversion/libsvn_client/diff_summarize.c
MFC r275385 (by bapt):
[FreeBSD/stable/10.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_path.h"
29 #include "svn_props.h"
30 #include "svn_pools.h"
31
32 #include "private/svn_wc_private.h"
33
34 #include "client.h"
35
36
37 /* Diff callbacks baton.  */
38 struct summarize_baton_t {
39   apr_pool_t *baton_pool; /* For allocating skip_path */
40
41   /* The target path of the diff, relative to the anchor; "" if target == anchor. */
42   const char *skip_relpath;
43
44   /* The summarize callback passed down from the API */
45   svn_client_diff_summarize_func_t summarize_func;
46
47   /* The summarize callback baton */
48   void *summarize_func_baton;
49 };
50
51 /* Call B->summarize_func with B->summarize_func_baton, passing it a
52  * summary object composed from PATH (but made to be relative to the target
53  * of the diff), SUMMARIZE_KIND, PROP_CHANGED (or FALSE if the action is an
54  * add or delete) and NODE_KIND. */
55 static svn_error_t *
56 send_summary(struct summarize_baton_t *b,
57              const char *path,
58              svn_client_diff_summarize_kind_t summarize_kind,
59              svn_boolean_t prop_changed,
60              svn_node_kind_t node_kind,
61              apr_pool_t *scratch_pool)
62 {
63   svn_client_diff_summarize_t *sum = apr_pcalloc(scratch_pool, sizeof(*sum));
64
65   SVN_ERR_ASSERT(summarize_kind != svn_client_diff_summarize_kind_normal
66                  || prop_changed);
67
68   /* PATH is relative to the anchor of the diff, but SUM->path needs to be
69      relative to the target of the diff. */
70   sum->path = svn_relpath_skip_ancestor(b->skip_relpath, path);
71   sum->summarize_kind = summarize_kind;
72   if (summarize_kind == svn_client_diff_summarize_kind_modified
73       || summarize_kind == svn_client_diff_summarize_kind_normal)
74     sum->prop_changed = prop_changed;
75   sum->node_kind = node_kind;
76
77   SVN_ERR(b->summarize_func(sum, b->summarize_func_baton, scratch_pool));
78   return SVN_NO_ERROR;
79 }
80
81 /* Are there any changes to relevant (normal) props in PROPS? */
82 static svn_boolean_t
83 props_changed_hash(apr_hash_t *props,
84                    apr_pool_t *scratch_pool)
85 {
86   apr_hash_index_t *hi;
87
88   if (!props)
89     return FALSE;
90
91   for (hi = apr_hash_first(scratch_pool, props); hi; hi = apr_hash_next(hi))
92     {
93       const char *name = apr_hash_this_key(hi);
94
95       if (svn_property_kind2(name) == svn_prop_regular_kind)
96         {
97           return TRUE;
98         }
99     }
100
101   return FALSE;
102 }
103
104 /* Are there any changes to relevant (normal) props in PROPCHANGES? */
105 static svn_boolean_t
106 props_changed(const apr_array_header_t *propchanges,
107               apr_pool_t *scratch_pool)
108 {
109   apr_array_header_t *props;
110
111   svn_error_clear(svn_categorize_props(propchanges, NULL, NULL, &props,
112                                        scratch_pool));
113   return (props->nelts != 0);
114 }
115
116 /* svn_diff_tree_processor_t callback */
117 static svn_error_t *
118 diff_dir_opened(void **new_dir_baton,
119                 svn_boolean_t *skip,
120                 svn_boolean_t *skip_children,
121                 const char *relpath,
122                 const svn_diff_source_t *left_source,
123                 const svn_diff_source_t *right_source,
124                 const svn_diff_source_t *copyfrom_source,
125                 void *parent_dir_baton,
126                 const struct svn_diff_tree_processor_t *processor,
127                 apr_pool_t *result_pool,
128                 apr_pool_t *scratch_pool)
129 {
130   /* struct summarize_baton_t *b = processor->baton; */
131
132   /* ### Send here instead of from dir_added() ? */
133   /*if (!left_source)
134     {
135       SVN_ERR(send_summary(b, relpath, svn_client_diff_summarize_kind_added,
136                            FALSE, svn_node_dir, scratch_pool));
137     }*/
138
139   return SVN_NO_ERROR;
140 }
141
142 /* svn_diff_tree_processor_t callback */
143 static svn_error_t *
144 diff_dir_changed(const char *relpath,
145                  const svn_diff_source_t *left_source,
146                  const svn_diff_source_t *right_source,
147                  /*const*/ apr_hash_t *left_props,
148                  /*const*/ apr_hash_t *right_props,
149                  const apr_array_header_t *prop_changes,
150                  void *dir_baton,
151                  const struct svn_diff_tree_processor_t *processor,
152                  apr_pool_t *scratch_pool)
153 {
154   struct summarize_baton_t *b = processor->baton;
155
156   SVN_ERR(send_summary(b, relpath, svn_client_diff_summarize_kind_normal,
157                        TRUE, svn_node_dir, scratch_pool));
158
159   return SVN_NO_ERROR;
160 }
161
162 /* svn_diff_tree_processor_t callback */
163 static svn_error_t *
164 diff_dir_added(const char *relpath,
165                const svn_diff_source_t *copyfrom_source,
166                const svn_diff_source_t *right_source,
167                /*const*/ apr_hash_t *copyfrom_props,
168                /*const*/ apr_hash_t *right_props,
169                void *dir_baton,
170                const struct svn_diff_tree_processor_t *processor,
171                apr_pool_t *scratch_pool)
172 {
173   struct summarize_baton_t *b = processor->baton;
174
175   /* ### Send from dir_opened without prop info? */
176   SVN_ERR(send_summary(b, relpath, svn_client_diff_summarize_kind_added,
177                        props_changed_hash(right_props, scratch_pool),
178                        svn_node_dir, scratch_pool));
179
180   return SVN_NO_ERROR;
181 }
182
183 /* svn_diff_tree_processor_t callback */
184 static svn_error_t *
185 diff_dir_deleted(const char *relpath,
186                  const svn_diff_source_t *left_source,
187                  /*const*/ apr_hash_t *left_props,
188                  void *dir_baton,
189                  const struct svn_diff_tree_processor_t *processor,
190                  apr_pool_t *scratch_pool)
191 {
192   struct summarize_baton_t *b = processor->baton;
193
194   SVN_ERR(send_summary(b, relpath, svn_client_diff_summarize_kind_deleted,
195                        FALSE, svn_node_dir, scratch_pool));
196
197   return SVN_NO_ERROR;
198 }
199
200 /* svn_diff_tree_processor_t callback */
201 static svn_error_t *
202 diff_file_added(const char *relpath,
203                 const svn_diff_source_t *copyfrom_source,
204                 const svn_diff_source_t *right_source,
205                 const char *copyfrom_file,
206                 const char *right_file,
207                 /*const*/ apr_hash_t *copyfrom_props,
208                 /*const*/ apr_hash_t *right_props,
209                 void *file_baton,
210                 const struct svn_diff_tree_processor_t *processor,
211                 apr_pool_t *scratch_pool)
212 {
213   struct summarize_baton_t *b = processor->baton;
214
215   SVN_ERR(send_summary(b, relpath, svn_client_diff_summarize_kind_added,
216                        props_changed_hash(right_props, scratch_pool),
217                        svn_node_file, scratch_pool));
218
219   return SVN_NO_ERROR;
220 }
221
222 /* svn_diff_tree_processor_t callback */
223 static svn_error_t *
224 diff_file_changed(const char *relpath,
225                   const svn_diff_source_t *left_source,
226                   const svn_diff_source_t *right_source,
227                   const char *left_file,
228                   const char *right_file,
229                   /*const*/ apr_hash_t *left_props,
230                   /*const*/ apr_hash_t *right_props,
231                   svn_boolean_t file_modified,
232                   const apr_array_header_t *prop_changes,
233                   void *file_baton,
234                   const struct svn_diff_tree_processor_t *processor,
235                   apr_pool_t *scratch_pool)
236 {
237   struct summarize_baton_t *b = processor->baton;
238
239   SVN_ERR(send_summary(b, relpath,
240                        file_modified ? svn_client_diff_summarize_kind_modified
241                                      : svn_client_diff_summarize_kind_normal,
242                        props_changed(prop_changes, scratch_pool),
243                        svn_node_file, scratch_pool));
244
245   return SVN_NO_ERROR;
246 }
247
248 /* svn_diff_tree_processor_t callback */
249 static svn_error_t *
250 diff_file_deleted(const char *relpath,
251                   const svn_diff_source_t *left_source,
252                   const char *left_file,
253                   /*const*/ apr_hash_t *left_props,
254                   void *file_baton,
255                   const struct svn_diff_tree_processor_t *processor,
256                   apr_pool_t *scratch_pool)
257 {
258   struct summarize_baton_t *b = processor->baton;
259
260   SVN_ERR(send_summary(b, relpath, svn_client_diff_summarize_kind_deleted,
261                        FALSE, svn_node_file, scratch_pool));
262
263   return SVN_NO_ERROR;
264 }
265
266 svn_error_t *
267 svn_client__get_diff_summarize_callbacks(
268                         const svn_diff_tree_processor_t **diff_processor,
269                         const char ***p_root_relpath,
270                         svn_client_diff_summarize_func_t summarize_func,
271                         void *summarize_baton,
272                         const char *original_target,
273                         apr_pool_t *result_pool,
274                         apr_pool_t *scratch_pool)
275 {
276   svn_diff_tree_processor_t *dp;
277   struct summarize_baton_t *b = apr_pcalloc(result_pool, sizeof(*b));
278
279   b->baton_pool = result_pool;
280   b->summarize_func = summarize_func;
281   b->summarize_func_baton = summarize_baton;
282
283   dp = svn_diff__tree_processor_create(b, result_pool);
284
285   /*dp->file_opened = diff_file_opened;*/
286   dp->file_added = diff_file_added;
287   dp->file_deleted = diff_file_deleted;
288   dp->file_changed = diff_file_changed;
289
290   dp->dir_opened = diff_dir_opened;
291   dp->dir_changed = diff_dir_changed;
292   dp->dir_deleted = diff_dir_deleted;
293   dp->dir_added = diff_dir_added;
294
295   *diff_processor = dp;
296   *p_root_relpath = &b->skip_relpath;
297
298   return SVN_NO_ERROR;
299 }
300
301 svn_client_diff_summarize_t *
302 svn_client_diff_summarize_dup(const svn_client_diff_summarize_t *diff,
303                               apr_pool_t *pool)
304 {
305   svn_client_diff_summarize_t *dup_diff = apr_palloc(pool, sizeof(*dup_diff));
306
307   *dup_diff = *diff;
308
309   if (diff->path)
310     dup_diff->path = apr_pstrdup(pool, diff->path);
311
312   return dup_diff;
313 }