#define APR_WANT_STRFUNC
#define APR_WANT_STDIO
#include <apr_want.h>
#include "svn_cmdline.h"
#include "svn_compat.h"
#include "svn_path.h"
#include "svn_props.h"
#include "cl.h"
#include "svn_private_config.h"
#include "private/svn_string_private.h"
struct log_receiver_baton
{
svn_client_ctx_t *ctx;
apr_size_t merge_depth;
svn_boolean_t quiet;
apr_int64_t revisions;
apr_int64_t changes;
apr_int64_t message_lines;
apr_int64_t merges;
apr_int64_t merged_revs;
apr_int64_t merged_changes;
apr_int64_t merged_message_lines;
};
static svn_error_t *
log_entry_receiver(void *baton,
svn_log_entry_t *log_entry,
apr_pool_t *pool)
{
struct log_receiver_baton *lb = baton;
const char *author;
const char *date;
const char *message;
if (lb->ctx->cancel_func)
SVN_ERR(lb->ctx->cancel_func(lb->ctx->cancel_baton));
if (! SVN_IS_VALID_REVNUM(log_entry->revision))
{
lb->merge_depth--;
return SVN_NO_ERROR;
}
if (lb->quiet)
return SVN_NO_ERROR;
svn_compat_log_revprops_out(&author, &date, &message, log_entry->revprops);
if (log_entry->revision == 0 && message == NULL)
return SVN_NO_ERROR;
lb->revisions++;
if (lb->merge_depth)
lb->merged_revs++;
if (message != NULL)
{
int count = svn_cstring_count_newlines(message) + 1;
lb->message_lines += count;
if (lb->merge_depth)
lb->merged_message_lines += count;
}
if (log_entry->changed_paths2)
{
unsigned count = apr_hash_count(log_entry->changed_paths2);
lb->changes += count;
if (lb->merge_depth)
lb->merged_changes += count;
}
if (log_entry->has_children)
{
lb->merge_depth++;
lb->merges++;
}
return SVN_NO_ERROR;
}
svn_error_t *
svn_cl__null_log(apr_getopt_t *os,
void *baton,
apr_pool_t *pool)
{
svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
apr_array_header_t *targets;
struct log_receiver_baton lb = { 0 };
const char *target;
int i;
apr_array_header_t *revprops;
svn_opt_revision_t target_peg_revision;
const char *target_path_or_url;
SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
opt_state->targets,
ctx, FALSE, pool));
svn_opt_push_implicit_dot_target(targets, pool);
if (opt_state->used_change_arg)
{
if (opt_state->used_revision_arg && opt_state->revision_ranges->nelts > 1)
{
return svn_error_create
(SVN_ERR_CLIENT_BAD_REVISION, NULL,
_("-c and -r are mutually exclusive"));
}
for (i = 0; i < opt_state->revision_ranges->nelts; i++)
{
svn_opt_revision_range_t *range;
range = APR_ARRAY_IDX(opt_state->revision_ranges, i,
svn_opt_revision_range_t *);
if (range->start.value.number < range->end.value.number)
range->start.value.number++;
else
range->end.value.number++;
}
}
target = APR_ARRAY_IDX(targets, 0, const char *);
SVN_ERR(svn_opt_parse_path(&target_peg_revision, &target_path_or_url,
target, pool));
if (target_peg_revision.kind == svn_opt_revision_unspecified)
target_peg_revision.kind = (svn_path_is_url(target)
? svn_opt_revision_head
: svn_opt_revision_working);
APR_ARRAY_IDX(targets, 0, const char *) = target_path_or_url;
if (svn_path_is_url(target))
{
for (i = 1; i < targets->nelts; i++)
{
target = APR_ARRAY_IDX(targets, i, const char *);
if (svn_path_is_url(target) || target[0] == '/')
return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
_("Only relative paths can be specified"
" after a URL for 'svnbench log', "
"but '%s' is not a relative path"),
target);
}
}
lb.ctx = ctx;
lb.quiet = opt_state->quiet;
revprops = apr_array_make(pool, 3, sizeof(char *));
APR_ARRAY_PUSH(revprops, const char *) = SVN_PROP_REVISION_AUTHOR;
APR_ARRAY_PUSH(revprops, const char *) = SVN_PROP_REVISION_DATE;
if (!opt_state->quiet)
APR_ARRAY_PUSH(revprops, const char *) = SVN_PROP_REVISION_LOG;
SVN_ERR(svn_client_log5(targets,
&target_peg_revision,
opt_state->revision_ranges,
opt_state->limit,
opt_state->verbose,
opt_state->stop_on_copy,
opt_state->use_merge_history,
revprops,
log_entry_receiver,
&lb,
ctx,
pool));
if (!opt_state->quiet)
{
if (opt_state->use_merge_history)
SVN_ERR(svn_cmdline_printf(pool,
_("%15s revisions, %15s merged in %s merges\n"
"%15s msg lines, %15s in merged revisions\n"
"%15s changes, %15s in merged revisions\n"),
svn__ui64toa_sep(lb.revisions, ',', pool),
svn__ui64toa_sep(lb.merged_revs, ',', pool),
svn__ui64toa_sep(lb.merges, ',', pool),
svn__ui64toa_sep(lb.message_lines, ',', pool),
svn__ui64toa_sep(lb.merged_message_lines, ',', pool),
svn__ui64toa_sep(lb.changes, ',', pool),
svn__ui64toa_sep(lb.merged_changes, ',', pool)));
else
SVN_ERR(svn_cmdline_printf(pool,
_("%15s revisions\n"
"%15s msg lines\n"
"%15s changes\n"),
svn__ui64toa_sep(lb.revisions, ',', pool),
svn__ui64toa_sep(lb.message_lines, ',', pool),
svn__ui64toa_sep(lb.changes, ',', pool)));
}
return SVN_NO_ERROR;
}