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
40#include "private/svn_log.h"
41
42
43static const char *
44log_depth(svn_depth_t depth, apr_pool_t *pool)
45{
46  if (depth == svn_depth_unknown)
47    return "";
48  return apr_pstrcat(pool, " depth=", svn_depth_to_word(depth), (char *)NULL);
49}
50
51static const char *
52log_include_merged_revisions(svn_boolean_t include_merged_revisions)
53{
54  if (include_merged_revisions)
55    return " include-merged-revisions";
56  return "";
57}
58
59
60const char *
61svn_log__reparent(const char *path, apr_pool_t *pool)
62{
63  return apr_psprintf(pool, "reparent %s", svn_path_uri_encode(path, pool));
64
65}
66
67const char *
68svn_log__change_rev_prop(svn_revnum_t rev, const char *name, apr_pool_t *pool)
69{
70  return apr_psprintf(pool, "change-rev-prop r%ld %s", rev,
71                      svn_path_uri_encode(name, pool));
72}
73
74const char *
75svn_log__rev_proplist(svn_revnum_t rev, apr_pool_t *pool)
76{
77  return apr_psprintf(pool, "rev-proplist r%ld", rev);
78}
79
80const char *
81svn_log__rev_prop(svn_revnum_t rev, const char *name, apr_pool_t *pool)
82{
83  return apr_psprintf(pool, "rev-prop r%ld %s", rev,
84                      svn_path_uri_encode(name, pool));
85}
86
87const char *
88svn_log__commit(svn_revnum_t rev, apr_pool_t *pool)
89{
90    return apr_psprintf(pool, "commit r%ld", rev);
91}
92
93const char *
94svn_log__get_file(const char *path, svn_revnum_t rev,
95                  svn_boolean_t want_contents, svn_boolean_t want_props,
96                  apr_pool_t *pool)
97{
98  return apr_psprintf(pool, "get-file %s r%ld%s%s",
99                      svn_path_uri_encode(path, pool), rev,
100                      want_contents ? " text" : "",
101                      want_props ? " props" : "");
102}
103
104const char *
105svn_log__get_dir(const char *path, svn_revnum_t rev,
106                 svn_boolean_t want_contents, svn_boolean_t want_props,
107                 apr_uint64_t dirent_fields,
108                 apr_pool_t *pool)
109{
110  return apr_psprintf(pool, "get-dir %s r%ld%s%s",
111                      svn_path_uri_encode(path, pool), rev,
112                      want_contents ? " text" : "",
113                      want_props ? " props" : "");
114}
115
116const char *
117svn_log__get_mergeinfo(const apr_array_header_t *paths,
118                       svn_mergeinfo_inheritance_t inherit,
119                       svn_boolean_t include_descendants,
120                       apr_pool_t *pool)
121{
122  int i;
123  apr_pool_t *iterpool = svn_pool_create(pool);
124  svn_stringbuf_t *space_separated_paths = svn_stringbuf_create_empty(pool);
125
126  for (i = 0; i < paths->nelts; i++)
127    {
128      const char *path = APR_ARRAY_IDX(paths, i, const char *);
129      svn_pool_clear(iterpool);
130      if (i != 0)
131        svn_stringbuf_appendcstr(space_separated_paths, " ");
132      svn_stringbuf_appendcstr(space_separated_paths,
133                               svn_path_uri_encode(path, iterpool));
134    }
135  svn_pool_destroy(iterpool);
136
137  return apr_psprintf(pool, "get-mergeinfo (%s) %s%s",
138                      space_separated_paths->data,
139                      svn_inheritance_to_word(inherit),
140                      include_descendants ? " include-descendants" : "");
141}
142
143const char *
144svn_log__checkout(const char *path, svn_revnum_t rev, svn_depth_t depth,
145                  apr_pool_t *pool)
146{
147  return apr_psprintf(pool, "checkout-or-export %s r%ld%s",
148                      svn_path_uri_encode(path, pool), rev,
149                      log_depth(depth, pool));
150}
151
152const char *
153svn_log__update(const char *path, svn_revnum_t rev, svn_depth_t depth,
154                svn_boolean_t send_copyfrom_args,
155                apr_pool_t *pool)
156{
157  return apr_psprintf(pool, "update %s r%ld%s%s",
158                      svn_path_uri_encode(path, pool), rev,
159                      log_depth(depth, pool),
160                      (send_copyfrom_args
161                       ? " send-copyfrom-args"
162                       : ""));
163}
164
165const char *
166svn_log__switch(const char *path, const char *dst_path, svn_revnum_t revnum,
167                svn_depth_t depth, apr_pool_t *pool)
168{
169  return apr_psprintf(pool, "switch %s %s@%ld%s",
170                      svn_path_uri_encode(path, pool),
171                      svn_path_uri_encode(dst_path, pool), revnum,
172                      log_depth(depth, pool));
173}
174
175const char *
176svn_log__status(const char *path, svn_revnum_t rev, svn_depth_t depth,
177                apr_pool_t *pool)
178{
179  return apr_psprintf(pool, "status %s r%ld%s",
180                      svn_path_uri_encode(path, pool), rev,
181                      log_depth(depth, pool));
182}
183
184const char *
185svn_log__diff(const char *path, svn_revnum_t from_revnum,
186              const char *dst_path, svn_revnum_t revnum,
187              svn_depth_t depth, svn_boolean_t ignore_ancestry,
188              apr_pool_t *pool)
189{
190  const char *log_ignore_ancestry = (ignore_ancestry
191                                     ? " ignore-ancestry"
192                                     : "");
193  if (strcmp(path, dst_path) == 0)
194    return apr_psprintf(pool, "diff %s r%ld:%ld%s%s",
195                        svn_path_uri_encode(path, pool), from_revnum, revnum,
196                        log_depth(depth, pool), log_ignore_ancestry);
197  return apr_psprintf(pool, "diff %s@%ld %s@%ld%s%s",
198                      svn_path_uri_encode(path, pool), from_revnum,
199                      svn_path_uri_encode(dst_path, pool), revnum,
200                      log_depth(depth, pool), log_ignore_ancestry);
201}
202
203const char *
204svn_log__log(const apr_array_header_t *paths,
205             svn_revnum_t start, svn_revnum_t end,
206             int limit, svn_boolean_t discover_changed_paths,
207             svn_boolean_t strict_node_history,
208             svn_boolean_t include_merged_revisions,
209             const apr_array_header_t *revprops, apr_pool_t *pool)
210{
211  int i;
212  apr_pool_t *iterpool = svn_pool_create(pool);
213  svn_stringbuf_t *space_separated_paths = svn_stringbuf_create_empty(pool);
214  svn_stringbuf_t *options = svn_stringbuf_create_empty(pool);
215
216  for (i = 0; i < paths->nelts; i++)
217    {
218      const char *path = APR_ARRAY_IDX(paths, i, const char *);
219      svn_pool_clear(iterpool);
220      if (i != 0)
221        svn_stringbuf_appendcstr(space_separated_paths, " ");
222      svn_stringbuf_appendcstr(space_separated_paths,
223                               svn_path_uri_encode(path, iterpool));
224    }
225
226  if (limit)
227    {
228      const char *tmp = apr_psprintf(pool, " limit=%d", limit);
229      svn_stringbuf_appendcstr(options, tmp);
230    }
231  if (discover_changed_paths)
232    svn_stringbuf_appendcstr(options, " discover-changed-paths");
233  if (strict_node_history)
234    svn_stringbuf_appendcstr(options, " strict");
235  if (include_merged_revisions)
236    svn_stringbuf_appendcstr(options,
237                        log_include_merged_revisions(include_merged_revisions));
238  if (revprops == NULL)
239    svn_stringbuf_appendcstr(options, " revprops=all");
240  else if (revprops->nelts > 0)
241    {
242      svn_stringbuf_appendcstr(options, " revprops=(");
243      for (i = 0; i < revprops->nelts; i++)
244        {
245          const char *name = APR_ARRAY_IDX(revprops, i, const char *);
246          svn_pool_clear(iterpool);
247          if (i != 0)
248            svn_stringbuf_appendcstr(options, " ");
249          svn_stringbuf_appendcstr(options, svn_path_uri_encode(name,
250                                                                iterpool));
251        }
252      svn_stringbuf_appendcstr(options, ")");
253    }
254  svn_pool_destroy(iterpool);
255  return apr_psprintf(pool, "log (%s) r%ld:%ld%s",
256                      space_separated_paths->data, start, end,
257                      options->data);
258}
259
260const char *
261svn_log__get_locations(const char *path, svn_revnum_t peg_revision,
262                       const apr_array_header_t *location_revisions,
263                       apr_pool_t *pool)
264{
265  const svn_revnum_t *revision_ptr, *revision_ptr_start, *revision_ptr_end;
266  apr_pool_t *iterpool = svn_pool_create(pool);
267  svn_stringbuf_t *space_separated_revnums = svn_stringbuf_create_empty(pool);
268
269  revision_ptr_start = (const svn_revnum_t *)location_revisions->elts;
270  revision_ptr = revision_ptr_start;
271  revision_ptr_end = revision_ptr + location_revisions->nelts;
272  while (revision_ptr < revision_ptr_end)
273    {
274      svn_pool_clear(iterpool);
275      if (revision_ptr != revision_ptr_start)
276        svn_stringbuf_appendcstr(space_separated_revnums, " ");
277      svn_stringbuf_appendcstr(space_separated_revnums,
278                               apr_psprintf(iterpool, "%ld", *revision_ptr));
279      ++revision_ptr;
280    }
281  svn_pool_destroy(iterpool);
282
283  return apr_psprintf(pool, "get-locations %s@%ld (%s)",
284                      svn_path_uri_encode(path, pool),
285                      peg_revision, space_separated_revnums->data);
286}
287
288const char *
289svn_log__get_location_segments(const char *path, svn_revnum_t peg_revision,
290                               svn_revnum_t start, svn_revnum_t end,
291                               apr_pool_t *pool)
292{
293  return apr_psprintf(pool, "get-location-segments %s@%ld r%ld:%ld",
294                      svn_path_uri_encode(path, pool),
295                      peg_revision, start, end);
296}
297
298const char *
299svn_log__get_file_revs(const char *path, svn_revnum_t start, svn_revnum_t end,
300                       svn_boolean_t include_merged_revisions,
301                       apr_pool_t *pool)
302{
303  return apr_psprintf(pool, "get-file-revs %s r%ld:%ld%s",
304                      svn_path_uri_encode(path, pool), start, end,
305                      log_include_merged_revisions(include_merged_revisions));
306}
307
308const char *
309svn_log__lock(const apr_array_header_t *paths,
310              svn_boolean_t steal, apr_pool_t *pool)
311{
312  int i;
313  apr_pool_t *iterpool = svn_pool_create(pool);
314  svn_stringbuf_t *space_separated_paths = svn_stringbuf_create_empty(pool);
315
316  for (i = 0; i < paths->nelts; i++)
317    {
318      const char *path = APR_ARRAY_IDX(paths, i, const char *);
319      svn_pool_clear(iterpool);
320      if (i != 0)
321        svn_stringbuf_appendcstr(space_separated_paths, " ");
322      svn_stringbuf_appendcstr(space_separated_paths,
323                               svn_path_uri_encode(path, iterpool));
324    }
325  svn_pool_destroy(iterpool);
326
327  return apr_psprintf(pool, "lock (%s)%s", space_separated_paths->data,
328                      steal ? " steal" : "");
329}
330
331const char *
332svn_log__unlock(const apr_array_header_t *paths,
333                svn_boolean_t break_lock, apr_pool_t *pool)
334{
335  int i;
336  apr_pool_t *iterpool = svn_pool_create(pool);
337  svn_stringbuf_t *space_separated_paths = svn_stringbuf_create_empty(pool);
338
339  for (i = 0; i < paths->nelts; i++)
340    {
341      const char *path = APR_ARRAY_IDX(paths, i, const char *);
342      svn_pool_clear(iterpool);
343      if (i != 0)
344        svn_stringbuf_appendcstr(space_separated_paths, " ");
345      svn_stringbuf_appendcstr(space_separated_paths,
346                               svn_path_uri_encode(path, iterpool));
347    }
348  svn_pool_destroy(iterpool);
349
350  return apr_psprintf(pool, "unlock (%s)%s", space_separated_paths->data,
351                      break_lock ? " break" : "");
352}
353
354const char *
355svn_log__lock_one_path(const char *path, svn_boolean_t steal,
356                       apr_pool_t *pool)
357{
358    apr_array_header_t *paths = apr_array_make(pool, 1, sizeof(path));
359    APR_ARRAY_PUSH(paths, const char *) = path;
360    return svn_log__lock(paths, steal, pool);
361}
362
363const char *
364svn_log__unlock_one_path(const char *path, svn_boolean_t break_lock,
365                         apr_pool_t *pool)
366{
367    apr_array_header_t *paths = apr_array_make(pool, 1, sizeof(path));
368    APR_ARRAY_PUSH(paths, const char *) = path;
369    return svn_log__unlock(paths, break_lock, pool);
370}
371
372const char *
373svn_log__replay(const char *path, svn_revnum_t rev, apr_pool_t *pool)
374{
375  const char *log_path;
376
377  if (path && path[0] != '\0')
378    log_path = svn_path_uri_encode(path, pool);
379  else
380    log_path = "/";
381  return apr_psprintf(pool, "replay %s r%ld", log_path, rev);
382}
383
384const char *
385svn_log__get_inherited_props(const char *path,
386                             svn_revnum_t rev,
387                             apr_pool_t *pool)
388{
389  const char *log_path;
390
391  if (path && path[0] != '\0')
392    log_path = svn_path_uri_encode(path, pool);
393  else
394    log_path = "/";
395  return apr_psprintf(pool, "get-inherited-props %s r%ld", log_path, rev);
396}
397