1251881Speter/*
2251881Speter * log.c :  Functions for logging Subversion operations
3251881Speter *
4251881Speter * ====================================================================
5251881Speter *    Licensed to the Apache Software Foundation (ASF) under one
6251881Speter *    or more contributor license agreements.  See the NOTICE file
7251881Speter *    distributed with this work for additional information
8251881Speter *    regarding copyright ownership.  The ASF licenses this file
9251881Speter *    to you under the Apache License, Version 2.0 (the
10251881Speter *    "License"); you may not use this file except in compliance
11251881Speter *    with the License.  You may obtain a copy of the License at
12251881Speter *
13251881Speter *      http://www.apache.org/licenses/LICENSE-2.0
14251881Speter *
15251881Speter *    Unless required by applicable law or agreed to in writing,
16251881Speter *    software distributed under the License is distributed on an
17251881Speter *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18251881Speter *    KIND, either express or implied.  See the License for the
19251881Speter *    specific language governing permissions and limitations
20251881Speter *    under the License.
21251881Speter * ====================================================================
22251881Speter */
23251881Speter
24251881Speter
25251881Speter
26251881Speter
27251881Speter#include <stdarg.h>
28251881Speter
29251881Speter#define APR_WANT_STRFUNC
30251881Speter#include <apr_want.h>
31251881Speter#include <apr_strings.h>
32251881Speter
33251881Speter#include "svn_types.h"
34251881Speter#include "svn_error.h"
35251881Speter#include "svn_mergeinfo.h"
36251881Speter#include "svn_path.h"
37251881Speter#include "svn_pools.h"
38251881Speter#include "svn_string.h"
39251881Speter
40251881Speter#include "private/svn_log.h"
41251881Speter
42251881Speter
43251881Speterstatic const char *
44251881Speterlog_depth(svn_depth_t depth, apr_pool_t *pool)
45251881Speter{
46251881Speter  if (depth == svn_depth_unknown)
47251881Speter    return "";
48251881Speter  return apr_pstrcat(pool, " depth=", svn_depth_to_word(depth), (char *)NULL);
49251881Speter}
50251881Speter
51251881Speterstatic const char *
52251881Speterlog_include_merged_revisions(svn_boolean_t include_merged_revisions)
53251881Speter{
54251881Speter  if (include_merged_revisions)
55251881Speter    return " include-merged-revisions";
56251881Speter  return "";
57251881Speter}
58251881Speter
59251881Speter
60251881Speterconst char *
61251881Spetersvn_log__reparent(const char *path, apr_pool_t *pool)
62251881Speter{
63251881Speter  return apr_psprintf(pool, "reparent %s", svn_path_uri_encode(path, pool));
64251881Speter
65251881Speter}
66251881Speter
67251881Speterconst char *
68251881Spetersvn_log__change_rev_prop(svn_revnum_t rev, const char *name, apr_pool_t *pool)
69251881Speter{
70251881Speter  return apr_psprintf(pool, "change-rev-prop r%ld %s", rev,
71251881Speter                      svn_path_uri_encode(name, pool));
72251881Speter}
73251881Speter
74251881Speterconst char *
75251881Spetersvn_log__rev_proplist(svn_revnum_t rev, apr_pool_t *pool)
76251881Speter{
77251881Speter  return apr_psprintf(pool, "rev-proplist r%ld", rev);
78251881Speter}
79251881Speter
80251881Speterconst char *
81251881Spetersvn_log__rev_prop(svn_revnum_t rev, const char *name, apr_pool_t *pool)
82251881Speter{
83251881Speter  return apr_psprintf(pool, "rev-prop r%ld %s", rev,
84251881Speter                      svn_path_uri_encode(name, pool));
85251881Speter}
86251881Speter
87251881Speterconst char *
88251881Spetersvn_log__commit(svn_revnum_t rev, apr_pool_t *pool)
89251881Speter{
90251881Speter    return apr_psprintf(pool, "commit r%ld", rev);
91251881Speter}
92251881Speter
93251881Speterconst char *
94251881Spetersvn_log__get_file(const char *path, svn_revnum_t rev,
95251881Speter                  svn_boolean_t want_contents, svn_boolean_t want_props,
96251881Speter                  apr_pool_t *pool)
97251881Speter{
98251881Speter  return apr_psprintf(pool, "get-file %s r%ld%s%s",
99251881Speter                      svn_path_uri_encode(path, pool), rev,
100251881Speter                      want_contents ? " text" : "",
101251881Speter                      want_props ? " props" : "");
102251881Speter}
103251881Speter
104251881Speterconst char *
105251881Spetersvn_log__get_dir(const char *path, svn_revnum_t rev,
106251881Speter                 svn_boolean_t want_contents, svn_boolean_t want_props,
107251881Speter                 apr_uint64_t dirent_fields,
108251881Speter                 apr_pool_t *pool)
109251881Speter{
110251881Speter  return apr_psprintf(pool, "get-dir %s r%ld%s%s",
111251881Speter                      svn_path_uri_encode(path, pool), rev,
112251881Speter                      want_contents ? " text" : "",
113251881Speter                      want_props ? " props" : "");
114251881Speter}
115251881Speter
116251881Speterconst char *
117251881Spetersvn_log__get_mergeinfo(const apr_array_header_t *paths,
118251881Speter                       svn_mergeinfo_inheritance_t inherit,
119251881Speter                       svn_boolean_t include_descendants,
120251881Speter                       apr_pool_t *pool)
121251881Speter{
122251881Speter  int i;
123251881Speter  apr_pool_t *iterpool = svn_pool_create(pool);
124251881Speter  svn_stringbuf_t *space_separated_paths = svn_stringbuf_create_empty(pool);
125251881Speter
126251881Speter  for (i = 0; i < paths->nelts; i++)
127251881Speter    {
128251881Speter      const char *path = APR_ARRAY_IDX(paths, i, const char *);
129251881Speter      svn_pool_clear(iterpool);
130251881Speter      if (i != 0)
131251881Speter        svn_stringbuf_appendcstr(space_separated_paths, " ");
132251881Speter      svn_stringbuf_appendcstr(space_separated_paths,
133251881Speter                               svn_path_uri_encode(path, iterpool));
134251881Speter    }
135251881Speter  svn_pool_destroy(iterpool);
136251881Speter
137251881Speter  return apr_psprintf(pool, "get-mergeinfo (%s) %s%s",
138251881Speter                      space_separated_paths->data,
139251881Speter                      svn_inheritance_to_word(inherit),
140251881Speter                      include_descendants ? " include-descendants" : "");
141251881Speter}
142251881Speter
143251881Speterconst char *
144251881Spetersvn_log__checkout(const char *path, svn_revnum_t rev, svn_depth_t depth,
145251881Speter                  apr_pool_t *pool)
146251881Speter{
147251881Speter  return apr_psprintf(pool, "checkout-or-export %s r%ld%s",
148251881Speter                      svn_path_uri_encode(path, pool), rev,
149251881Speter                      log_depth(depth, pool));
150251881Speter}
151251881Speter
152251881Speterconst char *
153251881Spetersvn_log__update(const char *path, svn_revnum_t rev, svn_depth_t depth,
154251881Speter                svn_boolean_t send_copyfrom_args,
155251881Speter                apr_pool_t *pool)
156251881Speter{
157251881Speter  return apr_psprintf(pool, "update %s r%ld%s%s",
158251881Speter                      svn_path_uri_encode(path, pool), rev,
159251881Speter                      log_depth(depth, pool),
160251881Speter                      (send_copyfrom_args
161251881Speter                       ? " send-copyfrom-args"
162251881Speter                       : ""));
163251881Speter}
164251881Speter
165251881Speterconst char *
166251881Spetersvn_log__switch(const char *path, const char *dst_path, svn_revnum_t revnum,
167251881Speter                svn_depth_t depth, apr_pool_t *pool)
168251881Speter{
169251881Speter  return apr_psprintf(pool, "switch %s %s@%ld%s",
170251881Speter                      svn_path_uri_encode(path, pool),
171251881Speter                      svn_path_uri_encode(dst_path, pool), revnum,
172251881Speter                      log_depth(depth, pool));
173251881Speter}
174251881Speter
175251881Speterconst char *
176251881Spetersvn_log__status(const char *path, svn_revnum_t rev, svn_depth_t depth,
177251881Speter                apr_pool_t *pool)
178251881Speter{
179251881Speter  return apr_psprintf(pool, "status %s r%ld%s",
180251881Speter                      svn_path_uri_encode(path, pool), rev,
181251881Speter                      log_depth(depth, pool));
182251881Speter}
183251881Speter
184251881Speterconst char *
185251881Spetersvn_log__diff(const char *path, svn_revnum_t from_revnum,
186251881Speter              const char *dst_path, svn_revnum_t revnum,
187251881Speter              svn_depth_t depth, svn_boolean_t ignore_ancestry,
188251881Speter              apr_pool_t *pool)
189251881Speter{
190251881Speter  const char *log_ignore_ancestry = (ignore_ancestry
191251881Speter                                     ? " ignore-ancestry"
192251881Speter                                     : "");
193251881Speter  if (strcmp(path, dst_path) == 0)
194251881Speter    return apr_psprintf(pool, "diff %s r%ld:%ld%s%s",
195251881Speter                        svn_path_uri_encode(path, pool), from_revnum, revnum,
196251881Speter                        log_depth(depth, pool), log_ignore_ancestry);
197251881Speter  return apr_psprintf(pool, "diff %s@%ld %s@%ld%s%s",
198251881Speter                      svn_path_uri_encode(path, pool), from_revnum,
199251881Speter                      svn_path_uri_encode(dst_path, pool), revnum,
200251881Speter                      log_depth(depth, pool), log_ignore_ancestry);
201251881Speter}
202251881Speter
203251881Speterconst char *
204251881Spetersvn_log__log(const apr_array_header_t *paths,
205251881Speter             svn_revnum_t start, svn_revnum_t end,
206251881Speter             int limit, svn_boolean_t discover_changed_paths,
207251881Speter             svn_boolean_t strict_node_history,
208251881Speter             svn_boolean_t include_merged_revisions,
209251881Speter             const apr_array_header_t *revprops, apr_pool_t *pool)
210251881Speter{
211251881Speter  int i;
212251881Speter  apr_pool_t *iterpool = svn_pool_create(pool);
213251881Speter  svn_stringbuf_t *space_separated_paths = svn_stringbuf_create_empty(pool);
214251881Speter  svn_stringbuf_t *options = svn_stringbuf_create_empty(pool);
215251881Speter
216251881Speter  for (i = 0; i < paths->nelts; i++)
217251881Speter    {
218251881Speter      const char *path = APR_ARRAY_IDX(paths, i, const char *);
219251881Speter      svn_pool_clear(iterpool);
220251881Speter      if (i != 0)
221251881Speter        svn_stringbuf_appendcstr(space_separated_paths, " ");
222251881Speter      svn_stringbuf_appendcstr(space_separated_paths,
223251881Speter                               svn_path_uri_encode(path, iterpool));
224251881Speter    }
225251881Speter
226251881Speter  if (limit)
227251881Speter    {
228251881Speter      const char *tmp = apr_psprintf(pool, " limit=%d", limit);
229251881Speter      svn_stringbuf_appendcstr(options, tmp);
230251881Speter    }
231251881Speter  if (discover_changed_paths)
232251881Speter    svn_stringbuf_appendcstr(options, " discover-changed-paths");
233251881Speter  if (strict_node_history)
234251881Speter    svn_stringbuf_appendcstr(options, " strict");
235251881Speter  if (include_merged_revisions)
236251881Speter    svn_stringbuf_appendcstr(options,
237251881Speter                        log_include_merged_revisions(include_merged_revisions));
238251881Speter  if (revprops == NULL)
239251881Speter    svn_stringbuf_appendcstr(options, " revprops=all");
240251881Speter  else if (revprops->nelts > 0)
241251881Speter    {
242251881Speter      svn_stringbuf_appendcstr(options, " revprops=(");
243251881Speter      for (i = 0; i < revprops->nelts; i++)
244251881Speter        {
245251881Speter          const char *name = APR_ARRAY_IDX(revprops, i, const char *);
246251881Speter          svn_pool_clear(iterpool);
247251881Speter          if (i != 0)
248251881Speter            svn_stringbuf_appendcstr(options, " ");
249251881Speter          svn_stringbuf_appendcstr(options, svn_path_uri_encode(name,
250251881Speter                                                                iterpool));
251251881Speter        }
252251881Speter      svn_stringbuf_appendcstr(options, ")");
253251881Speter    }
254251881Speter  svn_pool_destroy(iterpool);
255251881Speter  return apr_psprintf(pool, "log (%s) r%ld:%ld%s",
256251881Speter                      space_separated_paths->data, start, end,
257251881Speter                      options->data);
258251881Speter}
259251881Speter
260251881Speterconst char *
261251881Spetersvn_log__get_locations(const char *path, svn_revnum_t peg_revision,
262251881Speter                       const apr_array_header_t *location_revisions,
263251881Speter                       apr_pool_t *pool)
264251881Speter{
265251881Speter  const svn_revnum_t *revision_ptr, *revision_ptr_start, *revision_ptr_end;
266251881Speter  apr_pool_t *iterpool = svn_pool_create(pool);
267251881Speter  svn_stringbuf_t *space_separated_revnums = svn_stringbuf_create_empty(pool);
268251881Speter
269251881Speter  revision_ptr_start = (const svn_revnum_t *)location_revisions->elts;
270251881Speter  revision_ptr = revision_ptr_start;
271251881Speter  revision_ptr_end = revision_ptr + location_revisions->nelts;
272251881Speter  while (revision_ptr < revision_ptr_end)
273251881Speter    {
274251881Speter      svn_pool_clear(iterpool);
275251881Speter      if (revision_ptr != revision_ptr_start)
276251881Speter        svn_stringbuf_appendcstr(space_separated_revnums, " ");
277251881Speter      svn_stringbuf_appendcstr(space_separated_revnums,
278251881Speter                               apr_psprintf(iterpool, "%ld", *revision_ptr));
279251881Speter      ++revision_ptr;
280251881Speter    }
281251881Speter  svn_pool_destroy(iterpool);
282251881Speter
283251881Speter  return apr_psprintf(pool, "get-locations %s@%ld (%s)",
284251881Speter                      svn_path_uri_encode(path, pool),
285251881Speter                      peg_revision, space_separated_revnums->data);
286251881Speter}
287251881Speter
288251881Speterconst char *
289251881Spetersvn_log__get_location_segments(const char *path, svn_revnum_t peg_revision,
290251881Speter                               svn_revnum_t start, svn_revnum_t end,
291251881Speter                               apr_pool_t *pool)
292251881Speter{
293251881Speter  return apr_psprintf(pool, "get-location-segments %s@%ld r%ld:%ld",
294251881Speter                      svn_path_uri_encode(path, pool),
295251881Speter                      peg_revision, start, end);
296251881Speter}
297251881Speter
298251881Speterconst char *
299251881Spetersvn_log__get_file_revs(const char *path, svn_revnum_t start, svn_revnum_t end,
300251881Speter                       svn_boolean_t include_merged_revisions,
301251881Speter                       apr_pool_t *pool)
302251881Speter{
303251881Speter  return apr_psprintf(pool, "get-file-revs %s r%ld:%ld%s",
304251881Speter                      svn_path_uri_encode(path, pool), start, end,
305251881Speter                      log_include_merged_revisions(include_merged_revisions));
306251881Speter}
307251881Speter
308251881Speterconst char *
309251881Spetersvn_log__lock(const apr_array_header_t *paths,
310251881Speter              svn_boolean_t steal, apr_pool_t *pool)
311251881Speter{
312251881Speter  int i;
313251881Speter  apr_pool_t *iterpool = svn_pool_create(pool);
314251881Speter  svn_stringbuf_t *space_separated_paths = svn_stringbuf_create_empty(pool);
315251881Speter
316251881Speter  for (i = 0; i < paths->nelts; i++)
317251881Speter    {
318251881Speter      const char *path = APR_ARRAY_IDX(paths, i, const char *);
319251881Speter      svn_pool_clear(iterpool);
320251881Speter      if (i != 0)
321251881Speter        svn_stringbuf_appendcstr(space_separated_paths, " ");
322251881Speter      svn_stringbuf_appendcstr(space_separated_paths,
323251881Speter                               svn_path_uri_encode(path, iterpool));
324251881Speter    }
325251881Speter  svn_pool_destroy(iterpool);
326251881Speter
327251881Speter  return apr_psprintf(pool, "lock (%s)%s", space_separated_paths->data,
328251881Speter                      steal ? " steal" : "");
329251881Speter}
330251881Speter
331251881Speterconst char *
332251881Spetersvn_log__unlock(const apr_array_header_t *paths,
333251881Speter                svn_boolean_t break_lock, apr_pool_t *pool)
334251881Speter{
335251881Speter  int i;
336251881Speter  apr_pool_t *iterpool = svn_pool_create(pool);
337251881Speter  svn_stringbuf_t *space_separated_paths = svn_stringbuf_create_empty(pool);
338251881Speter
339251881Speter  for (i = 0; i < paths->nelts; i++)
340251881Speter    {
341251881Speter      const char *path = APR_ARRAY_IDX(paths, i, const char *);
342251881Speter      svn_pool_clear(iterpool);
343251881Speter      if (i != 0)
344251881Speter        svn_stringbuf_appendcstr(space_separated_paths, " ");
345251881Speter      svn_stringbuf_appendcstr(space_separated_paths,
346251881Speter                               svn_path_uri_encode(path, iterpool));
347251881Speter    }
348251881Speter  svn_pool_destroy(iterpool);
349251881Speter
350251881Speter  return apr_psprintf(pool, "unlock (%s)%s", space_separated_paths->data,
351251881Speter                      break_lock ? " break" : "");
352251881Speter}
353251881Speter
354251881Speterconst char *
355251881Spetersvn_log__lock_one_path(const char *path, svn_boolean_t steal,
356251881Speter                       apr_pool_t *pool)
357251881Speter{
358251881Speter    apr_array_header_t *paths = apr_array_make(pool, 1, sizeof(path));
359251881Speter    APR_ARRAY_PUSH(paths, const char *) = path;
360251881Speter    return svn_log__lock(paths, steal, pool);
361251881Speter}
362251881Speter
363251881Speterconst char *
364251881Spetersvn_log__unlock_one_path(const char *path, svn_boolean_t break_lock,
365251881Speter                         apr_pool_t *pool)
366251881Speter{
367251881Speter    apr_array_header_t *paths = apr_array_make(pool, 1, sizeof(path));
368251881Speter    APR_ARRAY_PUSH(paths, const char *) = path;
369251881Speter    return svn_log__unlock(paths, break_lock, pool);
370251881Speter}
371251881Speter
372251881Speterconst char *
373251881Spetersvn_log__replay(const char *path, svn_revnum_t rev, apr_pool_t *pool)
374251881Speter{
375251881Speter  const char *log_path;
376251881Speter
377251881Speter  if (path && path[0] != '\0')
378251881Speter    log_path = svn_path_uri_encode(path, pool);
379251881Speter  else
380251881Speter    log_path = "/";
381251881Speter  return apr_psprintf(pool, "replay %s r%ld", log_path, rev);
382251881Speter}
383251881Speter
384251881Speterconst char *
385251881Spetersvn_log__get_inherited_props(const char *path,
386251881Speter                             svn_revnum_t rev,
387251881Speter                             apr_pool_t *pool)
388251881Speter{
389251881Speter  const char *log_path;
390251881Speter
391251881Speter  if (path && path[0] != '\0')
392251881Speter    log_path = svn_path_uri_encode(path, pool);
393251881Speter  else
394251881Speter    log_path = "/";
395251881Speter  return apr_psprintf(pool, "get-inherited-props %s r%ld", log_path, rev);
396251881Speter}
397