]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/subversion/subversion/svnbench/null-log-cmd.c
MFC r275385 (by bapt):
[FreeBSD/stable/10.git] / contrib / subversion / subversion / svnbench / null-log-cmd.c
1 /*
2  * log-cmd.c -- Display log messages
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 #define APR_WANT_STRFUNC
25 #define APR_WANT_STDIO
26 #include <apr_want.h>
27
28 #include "svn_cmdline.h"
29 #include "svn_compat.h"
30 #include "svn_path.h"
31 #include "svn_props.h"
32
33 #include "cl.h"
34
35 #include "svn_private_config.h"
36 #include "private/svn_string_private.h"
37
38 \f
39 /*** Code. ***/
40
41 /* Baton for log_entry_receiver() and log_entry_receiver_xml(). */
42 struct log_receiver_baton
43 {
44   /* Client context. */
45   svn_client_ctx_t *ctx;
46
47   /* Level of merge revision nesting */
48   apr_size_t merge_depth;
49
50   /* collect counters? */
51   svn_boolean_t quiet;
52
53   /* total revision counters */
54   apr_int64_t revisions;
55   apr_int64_t changes;
56   apr_int64_t message_lines;
57
58   /* part that came from merges */
59   apr_int64_t merges;
60   apr_int64_t merged_revs;
61   apr_int64_t merged_changes;
62   apr_int64_t merged_message_lines;
63 };
64
65
66 /* Implement `svn_log_entry_receiver_t', printing the logs in
67  * a human-readable and machine-parseable format.
68  *
69  * BATON is of type `struct log_receiver_baton'.
70  */
71 static svn_error_t *
72 log_entry_receiver(void *baton,
73                    svn_log_entry_t *log_entry,
74                    apr_pool_t *pool)
75 {
76   struct log_receiver_baton *lb = baton;
77   const char *author;
78   const char *date;
79   const char *message;
80
81   if (lb->ctx->cancel_func)
82     SVN_ERR(lb->ctx->cancel_func(lb->ctx->cancel_baton));
83
84   if (! SVN_IS_VALID_REVNUM(log_entry->revision))
85     {
86       lb->merge_depth--;
87       return SVN_NO_ERROR;
88     }
89
90   /* if we don't want counters, we are done */
91   if (lb->quiet)
92     return SVN_NO_ERROR;
93
94   /* extract the message and do all the other counting */
95   svn_compat_log_revprops_out(&author, &date, &message, log_entry->revprops);
96   if (log_entry->revision == 0 && message == NULL)
97     return SVN_NO_ERROR;
98
99   lb->revisions++;
100   if (lb->merge_depth)
101     lb->merged_revs++;
102
103   if (message != NULL)
104     {
105       int count = svn_cstring_count_newlines(message) + 1;
106       lb->message_lines += count;
107       if (lb->merge_depth)
108         lb->merged_message_lines += count;
109     }
110
111   if (log_entry->changed_paths2)
112     {
113       unsigned count = apr_hash_count(log_entry->changed_paths2);
114       lb->changes += count;
115       if (lb->merge_depth)
116         lb->merged_changes += count;
117     }
118
119   if (log_entry->has_children)
120     {
121       lb->merge_depth++;
122       lb->merges++;
123     }
124
125   return SVN_NO_ERROR;
126 }
127
128 /* This implements the `svn_opt_subcommand_t' interface. */
129 svn_error_t *
130 svn_cl__null_log(apr_getopt_t *os,
131                  void *baton,
132                  apr_pool_t *pool)
133 {
134   svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
135   svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
136   apr_array_header_t *targets;
137   struct log_receiver_baton lb = { 0 };
138   const char *target;
139   int i;
140   apr_array_header_t *revprops;
141   svn_opt_revision_t target_peg_revision;
142   const char *target_path_or_url;
143
144   SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
145                                                       opt_state->targets,
146                                                       ctx, FALSE, pool));
147
148   /* Add "." if user passed 0 arguments */
149   svn_opt_push_implicit_dot_target(targets, pool);
150
151   /* Determine if they really want a two-revision range. */
152   if (opt_state->used_change_arg)
153     {
154       if (opt_state->used_revision_arg && opt_state->revision_ranges->nelts > 1)
155         {
156           return svn_error_create
157             (SVN_ERR_CLIENT_BAD_REVISION, NULL,
158              _("-c and -r are mutually exclusive"));
159         }
160       for (i = 0; i < opt_state->revision_ranges->nelts; i++)
161         {
162           svn_opt_revision_range_t *range;
163           range = APR_ARRAY_IDX(opt_state->revision_ranges, i,
164                                 svn_opt_revision_range_t *);
165           if (range->start.value.number < range->end.value.number)
166             range->start.value.number++;
167           else
168             range->end.value.number++;
169         }
170     }
171
172   /* Parse the first target into path-or-url and peg revision. */
173   target = APR_ARRAY_IDX(targets, 0, const char *);
174   SVN_ERR(svn_opt_parse_path(&target_peg_revision, &target_path_or_url,
175                              target, pool));
176   if (target_peg_revision.kind == svn_opt_revision_unspecified)
177     target_peg_revision.kind = (svn_path_is_url(target)
178                                      ? svn_opt_revision_head
179                                      : svn_opt_revision_working);
180   APR_ARRAY_IDX(targets, 0, const char *) = target_path_or_url;
181
182   if (svn_path_is_url(target))
183     {
184       for (i = 1; i < targets->nelts; i++)
185         {
186           target = APR_ARRAY_IDX(targets, i, const char *);
187
188           if (svn_path_is_url(target) || target[0] == '/')
189             return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
190                                      _("Only relative paths can be specified"
191                                        " after a URL for 'svnbench log', "
192                                        "but '%s' is not a relative path"),
193                                      target);
194         }
195     }
196
197   lb.ctx = ctx;
198   lb.quiet = opt_state->quiet;
199
200   revprops = apr_array_make(pool, 3, sizeof(char *));
201   APR_ARRAY_PUSH(revprops, const char *) = SVN_PROP_REVISION_AUTHOR;
202   APR_ARRAY_PUSH(revprops, const char *) = SVN_PROP_REVISION_DATE;
203   if (!opt_state->quiet)
204     APR_ARRAY_PUSH(revprops, const char *) = SVN_PROP_REVISION_LOG;
205   SVN_ERR(svn_client_log5(targets,
206                           &target_peg_revision,
207                           opt_state->revision_ranges,
208                           opt_state->limit,
209                           opt_state->verbose,
210                           opt_state->stop_on_copy,
211                           opt_state->use_merge_history,
212                           revprops,
213                           log_entry_receiver,
214                           &lb,
215                           ctx,
216                           pool));
217
218   if (!opt_state->quiet)
219     {
220       if (opt_state->use_merge_history)
221         SVN_ERR(svn_cmdline_printf(pool,
222                       _("%15s revisions, %15s merged in %s merges\n"
223                         "%15s msg lines, %15s in merged revisions\n"
224                         "%15s changes,   %15s in merged revisions\n"),
225                       svn__ui64toa_sep(lb.revisions, ',', pool),
226                       svn__ui64toa_sep(lb.merged_revs, ',', pool),
227                       svn__ui64toa_sep(lb.merges, ',', pool),
228                       svn__ui64toa_sep(lb.message_lines, ',', pool),
229                       svn__ui64toa_sep(lb.merged_message_lines, ',', pool),
230                       svn__ui64toa_sep(lb.changes, ',', pool),
231                       svn__ui64toa_sep(lb.merged_changes, ',', pool)));
232       else
233         SVN_ERR(svn_cmdline_printf(pool,
234                       _("%15s revisions\n"
235                         "%15s msg lines\n"
236                         "%15s changes\n"),
237                       svn__ui64toa_sep(lb.revisions, ',', pool),
238                       svn__ui64toa_sep(lb.message_lines, ',', pool),
239                       svn__ui64toa_sep(lb.changes, ',', pool)));
240     }
241
242   return SVN_NO_ERROR;
243 }