log.c revision 299742
1/*
2 * log.c :  Functions for logging Subversion operations
3 *
4 * ====================================================================
5 *    Licensed to the Apache Software Foundation (ASF) under one
6 *    or more contributor license agreements.  See the NOTICE file
7 *    distributed with this work for additional information
8 *    regarding copyright ownership.  The ASF licenses this file
9 *    to you under the Apache License, Version 2.0 (the
10 *    "License"); you may not use this file except in compliance
11 *    with the License.  You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 *    Unless required by applicable law or agreed to in writing,
16 *    software distributed under the License is distributed on an
17 *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18 *    KIND, either express or implied.  See the License for the
19 *    specific language governing permissions and limitations
20 *    under the License.
21 * ====================================================================
22 */
23
24
25
26
27#include <stdarg.h>
28
29#define APR_WANT_STRFUNC
30#include <apr_want.h>
31#include <apr_strings.h>
32
33#include "svn_types.h"
34#include "svn_error.h"
35#include "svn_mergeinfo.h"
36#include "svn_path.h"
37#include "svn_pools.h"
38#include "svn_string.h"
39#include "svn_hash.h"
40
41#include "private/svn_log.h"
42
43
44static const char *
45log_depth(svn_depth_t depth, apr_pool_t *pool)
46{
47  if (depth == svn_depth_unknown)
48    return "";
49  return apr_pstrcat(pool, " depth=", svn_depth_to_word(depth), SVN_VA_NULL);
50}
51
52static const char *
53log_include_merged_revisions(svn_boolean_t include_merged_revisions)
54{
55  if (include_merged_revisions)
56    return " include-merged-revisions";
57  return "";
58}
59
60
61const char *
62svn_log__reparent(const char *path, apr_pool_t *pool)
63{
64  return apr_psprintf(pool, "reparent %s", svn_path_uri_encode(path, pool));
65
66}
67
68const char *
69svn_log__change_rev_prop(svn_revnum_t rev, const char *name, apr_pool_t *pool)
70{
71  return apr_psprintf(pool, "change-rev-prop r%ld %s", rev,
72                      svn_path_uri_encode(name, pool));
73}
74
75const char *
76svn_log__rev_proplist(svn_revnum_t rev, apr_pool_t *pool)
77{
78  return apr_psprintf(pool, "rev-proplist r%ld", rev);
79}
80
81const char *
82svn_log__rev_prop(svn_revnum_t rev, const char *name, apr_pool_t *pool)
83{
84  return apr_psprintf(pool, "rev-prop r%ld %s", rev,
85                      svn_path_uri_encode(name, pool));
86}
87
88const char *
89svn_log__commit(svn_revnum_t rev, apr_pool_t *pool)
90{
91    return apr_psprintf(pool, "commit r%ld", rev);
92}
93
94const char *
95svn_log__get_file(const char *path, svn_revnum_t rev,
96                  svn_boolean_t want_contents, svn_boolean_t want_props,
97                  apr_pool_t *pool)
98{
99  return apr_psprintf(pool, "get-file %s r%ld%s%s",
100                      svn_path_uri_encode(path, pool), rev,
101                      want_contents ? " text" : "",
102                      want_props ? " props" : "");
103}
104
105const char *
106svn_log__get_dir(const char *path, svn_revnum_t rev,
107                 svn_boolean_t want_contents, svn_boolean_t want_props,
108                 apr_uint64_t dirent_fields,
109                 apr_pool_t *pool)
110{
111  return apr_psprintf(pool, "get-dir %s r%ld%s%s",
112                      svn_path_uri_encode(path, pool), rev,
113                      want_contents ? " text" : "",
114                      want_props ? " props" : "");
115}
116
117const char *
118svn_log__get_mergeinfo(const apr_array_header_t *paths,
119                       svn_mergeinfo_inheritance_t inherit,
120                       svn_boolean_t include_descendants,
121                       apr_pool_t *pool)
122{
123  int i;
124  apr_pool_t *iterpool = svn_pool_create(pool);
125  svn_stringbuf_t *space_separated_paths = svn_stringbuf_create_empty(pool);
126
127  for (i = 0; i < paths->nelts; i++)
128    {
129      const char *path = APR_ARRAY_IDX(paths, i, const char *);
130      svn_pool_clear(iterpool);
131      if (i != 0)
132        svn_stringbuf_appendcstr(space_separated_paths, " ");
133      svn_stringbuf_appendcstr(space_separated_paths,
134                               svn_path_uri_encode(path, iterpool));
135    }
136  svn_pool_destroy(iterpool);
137
138  return apr_psprintf(pool, "get-mergeinfo (%s) %s%s",
139                      space_separated_paths->data,
140                      svn_inheritance_to_word(inherit),
141                      include_descendants ? " include-descendants" : "");
142}
143
144const char *
145svn_log__checkout(const char *path, svn_revnum_t rev, svn_depth_t depth,
146                  apr_pool_t *pool)
147{
148  return apr_psprintf(pool, "checkout-or-export %s r%ld%s",
149                      svn_path_uri_encode(path, pool), rev,
150                      log_depth(depth, pool));
151}
152
153const char *
154svn_log__update(const char *path, svn_revnum_t rev, svn_depth_t depth,
155                svn_boolean_t send_copyfrom_args,
156                apr_pool_t *pool)
157{
158  return apr_psprintf(pool, "update %s r%ld%s%s",
159                      svn_path_uri_encode(path, pool), rev,
160                      log_depth(depth, pool),
161                      (send_copyfrom_args
162                       ? " send-copyfrom-args"
163                       : ""));
164}
165
166const char *
167svn_log__switch(const char *path, const char *dst_path, svn_revnum_t revnum,
168                svn_depth_t depth, apr_pool_t *pool)
169{
170  return apr_psprintf(pool, "switch %s %s@%ld%s",
171                      svn_path_uri_encode(path, pool),
172                      svn_path_uri_encode(dst_path, pool), revnum,
173                      log_depth(depth, pool));
174}
175
176const char *
177svn_log__status(const char *path, svn_revnum_t rev, svn_depth_t depth,
178                apr_pool_t *pool)
179{
180  return apr_psprintf(pool, "status %s r%ld%s",
181                      svn_path_uri_encode(path, pool), rev,
182                      log_depth(depth, pool));
183}
184
185const char *
186svn_log__diff(const char *path, svn_revnum_t from_revnum,
187              const char *dst_path, svn_revnum_t revnum,
188              svn_depth_t depth, svn_boolean_t ignore_ancestry,
189              apr_pool_t *pool)
190{
191  const char *log_ignore_ancestry = (ignore_ancestry
192                                     ? " ignore-ancestry"
193                                     : "");
194  if (strcmp(path, dst_path) == 0)
195    return apr_psprintf(pool, "diff %s r%ld:%ld%s%s",
196                        svn_path_uri_encode(path, pool), from_revnum, revnum,
197                        log_depth(depth, pool), log_ignore_ancestry);
198  return apr_psprintf(pool, "diff %s@%ld %s@%ld%s%s",
199                      svn_path_uri_encode(path, pool), from_revnum,
200                      svn_path_uri_encode(dst_path, pool), revnum,
201                      log_depth(depth, pool), log_ignore_ancestry);
202}
203
204const char *
205svn_log__log(const apr_array_header_t *paths,
206             svn_revnum_t start, svn_revnum_t end,
207             int limit, svn_boolean_t discover_changed_paths,
208             svn_boolean_t strict_node_history,
209             svn_boolean_t include_merged_revisions,
210             const apr_array_header_t *revprops, apr_pool_t *pool)
211{
212  int i;
213  apr_pool_t *iterpool = svn_pool_create(pool);
214  svn_stringbuf_t *space_separated_paths = svn_stringbuf_create_empty(pool);
215  svn_stringbuf_t *options = svn_stringbuf_create_empty(pool);
216
217  for (i = 0; i < paths->nelts; i++)
218    {
219      const char *path = APR_ARRAY_IDX(paths, i, const char *);
220      svn_pool_clear(iterpool);
221      if (i != 0)
222        svn_stringbuf_appendcstr(space_separated_paths, " ");
223      svn_stringbuf_appendcstr(space_separated_paths,
224                               svn_path_uri_encode(path, iterpool));
225    }
226
227  if (limit)
228    {
229      const char *tmp = apr_psprintf(pool, " limit=%d", limit);
230      svn_stringbuf_appendcstr(options, tmp);
231    }
232  if (discover_changed_paths)
233    svn_stringbuf_appendcstr(options, " discover-changed-paths");
234  if (strict_node_history)
235    svn_stringbuf_appendcstr(options, " strict");
236  if (include_merged_revisions)
237    svn_stringbuf_appendcstr(options,
238                        log_include_merged_revisions(include_merged_revisions));
239  if (revprops == NULL)
240    svn_stringbuf_appendcstr(options, " revprops=all");
241  else if (revprops->nelts > 0)
242    {
243      svn_stringbuf_appendcstr(options, " revprops=(");
244      for (i = 0; i < revprops->nelts; i++)
245        {
246          const char *name = APR_ARRAY_IDX(revprops, i, const char *);
247          svn_pool_clear(iterpool);
248          if (i != 0)
249            svn_stringbuf_appendcstr(options, " ");
250          svn_stringbuf_appendcstr(options, svn_path_uri_encode(name,
251                                                                iterpool));
252        }
253      svn_stringbuf_appendcstr(options, ")");
254    }
255  svn_pool_destroy(iterpool);
256  return apr_psprintf(pool, "log (%s) r%ld:%ld%s",
257                      space_separated_paths->data, start, end,
258                      options->data);
259}
260
261const char *
262svn_log__get_locations(const char *path, svn_revnum_t peg_revision,
263                       const apr_array_header_t *location_revisions,
264                       apr_pool_t *pool)
265{
266  const svn_revnum_t *revision_ptr, *revision_ptr_start, *revision_ptr_end;
267  apr_pool_t *iterpool = svn_pool_create(pool);
268  svn_stringbuf_t *space_separated_revnums = svn_stringbuf_create_empty(pool);
269
270  revision_ptr_start = (const svn_revnum_t *)location_revisions->elts;
271  revision_ptr = revision_ptr_start;
272  revision_ptr_end = revision_ptr + location_revisions->nelts;
273  while (revision_ptr < revision_ptr_end)
274    {
275      svn_pool_clear(iterpool);
276      if (revision_ptr != revision_ptr_start)
277        svn_stringbuf_appendcstr(space_separated_revnums, " ");
278      svn_stringbuf_appendcstr(space_separated_revnums,
279                               apr_psprintf(iterpool, "%ld", *revision_ptr));
280      ++revision_ptr;
281    }
282  svn_pool_destroy(iterpool);
283
284  return apr_psprintf(pool, "get-locations %s@%ld (%s)",
285                      svn_path_uri_encode(path, pool),
286                      peg_revision, space_separated_revnums->data);
287}
288
289const char *
290svn_log__get_location_segments(const char *path, svn_revnum_t peg_revision,
291                               svn_revnum_t start, svn_revnum_t end,
292                               apr_pool_t *pool)
293{
294  return apr_psprintf(pool, "get-location-segments %s@%ld r%ld:%ld",
295                      svn_path_uri_encode(path, pool),
296                      peg_revision, start, end);
297}
298
299const char *
300svn_log__get_file_revs(const char *path, svn_revnum_t start, svn_revnum_t end,
301                       svn_boolean_t include_merged_revisions,
302                       apr_pool_t *pool)
303{
304  return apr_psprintf(pool, "get-file-revs %s r%ld:%ld%s",
305                      svn_path_uri_encode(path, pool), start, end,
306                      log_include_merged_revisions(include_merged_revisions));
307}
308
309const char *
310svn_log__lock(apr_hash_t *targets,
311              svn_boolean_t steal, apr_pool_t *pool)
312{
313  apr_hash_index_t *hi;
314  apr_pool_t *iterpool = svn_pool_create(pool);
315  svn_stringbuf_t *space_separated_paths = svn_stringbuf_create_empty(pool);
316
317  for (hi = apr_hash_first(pool, targets); hi; hi = apr_hash_next(hi))
318    {
319      const char *path = apr_hash_this_key(hi);
320      svn_pool_clear(iterpool);
321      if (space_separated_paths->len)
322        svn_stringbuf_appendcstr(space_separated_paths, " ");
323      svn_stringbuf_appendcstr(space_separated_paths,
324                               svn_path_uri_encode(path, iterpool));
325    }
326  svn_pool_destroy(iterpool);
327
328  return apr_psprintf(pool, "lock (%s)%s", space_separated_paths->data,
329                      steal ? " steal" : "");
330}
331
332const char *
333svn_log__unlock(apr_hash_t *targets,
334                svn_boolean_t break_lock, apr_pool_t *pool)
335{
336  apr_hash_index_t *hi;
337  apr_pool_t *iterpool = svn_pool_create(pool);
338  svn_stringbuf_t *space_separated_paths = svn_stringbuf_create_empty(pool);
339
340  for (hi = apr_hash_first(pool, targets); hi; hi = apr_hash_next(hi))
341    {
342      const char *path = apr_hash_this_key(hi);
343      svn_pool_clear(iterpool);
344      if (space_separated_paths->len)
345        svn_stringbuf_appendcstr(space_separated_paths, " ");
346      svn_stringbuf_appendcstr(space_separated_paths,
347                               svn_path_uri_encode(path, iterpool));
348    }
349  svn_pool_destroy(iterpool);
350
351  return apr_psprintf(pool, "unlock (%s)%s", space_separated_paths->data,
352                      break_lock ? " break" : "");
353}
354
355const char *
356svn_log__lock_one_path(const char *path, svn_boolean_t steal,
357                       apr_pool_t *pool)
358{
359  apr_hash_t *paths = apr_hash_make(pool);
360  svn_hash_sets(paths, path, path);
361  return svn_log__lock(paths, steal, pool);
362}
363
364const char *
365svn_log__unlock_one_path(const char *path, svn_boolean_t break_lock,
366                         apr_pool_t *pool)
367{
368  apr_hash_t *paths = apr_hash_make(pool);
369  svn_hash_sets(paths, path, path);
370  return svn_log__unlock(paths, break_lock, pool);
371}
372
373const char *
374svn_log__replay(const char *path, svn_revnum_t rev, apr_pool_t *pool)
375{
376  const char *log_path;
377
378  if (path && path[0] != '\0')
379    log_path = svn_path_uri_encode(path, pool);
380  else
381    log_path = "/";
382  return apr_psprintf(pool, "replay %s r%ld", log_path, rev);
383}
384
385const char *
386svn_log__get_inherited_props(const char *path,
387                             svn_revnum_t rev,
388                             apr_pool_t *pool)
389{
390  const char *log_path;
391
392  if (path && path[0] != '\0')
393    log_path = svn_path_uri_encode(path, pool);
394  else
395    log_path = "/";
396  return apr_psprintf(pool, "get-inherited-props %s r%ld", log_path, rev);
397}
398