#define APR_WANT_STRFUNC
#include <apr_want.h>
#include <apr_strings.h>
#include <apr_pools.h>
#include "client.h"
#include "svn_client.h"
#include "svn_error.h"
#include "svn_path.h"
#include "svn_private_config.h"
svn_error_t *
svn_client_log3(const apr_array_header_t *targets,
const svn_opt_revision_t *peg_revision,
const svn_opt_revision_t *start,
const svn_opt_revision_t *end,
int limit,
svn_boolean_t discover_changed_paths,
svn_boolean_t strict_node_history,
svn_log_message_receiver_t receiver,
void *receiver_baton,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
svn_ra_session_t *ra_session;
const char *url_or_path;
const char *ignored_url;
const char *base_name = NULL;
apr_array_header_t *condensed_targets;
svn_revnum_t ignored_revnum;
svn_opt_revision_t session_opt_rev;
if ((start->kind == svn_opt_revision_unspecified)
|| (end->kind == svn_opt_revision_unspecified))
{
return svn_error_create
(SVN_ERR_CLIENT_BAD_REVISION, NULL,
_("Missing required revision specification"));
}
url_or_path = APR_ARRAY_IDX(targets, 0, const char *);
if (svn_path_is_url(url_or_path))
{
if (peg_revision->kind == svn_opt_revision_base
|| peg_revision->kind == svn_opt_revision_committed
|| peg_revision->kind == svn_opt_revision_previous)
return svn_error_create
(SVN_ERR_CLIENT_BAD_REVISION, NULL,
_("Revision type requires a working copy path, not a URL"));
condensed_targets = apr_array_make(pool, 1, sizeof(const char *));
if (targets->nelts > 1)
{
int i;
for (i = 1; i < targets->nelts; i++)
(*((const char **)apr_array_push(condensed_targets))) =
APR_ARRAY_IDX(targets, i, const char *);
}
else
{
(*((const char **)apr_array_push(condensed_targets))) = "";
}
}
else
{
svn_wc_adm_access_t *adm_access;
apr_array_header_t *target_urls;
apr_array_header_t *real_targets;
int i;
target_urls = apr_array_make(pool, 1, sizeof(const char *));
real_targets = apr_array_make(pool, 1, sizeof(const char *));
for (i = 0; i < targets->nelts; i++)
{
const svn_wc_entry_t *entry;
const char *URL;
const char *target = APR_ARRAY_IDX(targets, i, const char *);
SVN_ERR(svn_wc_adm_probe_open3(&adm_access, NULL, target,
FALSE, 0, ctx->cancel_func,
ctx->cancel_baton, pool));
SVN_ERR(svn_wc_entry(&entry, target, adm_access, FALSE, pool));
if (! entry)
return svn_error_createf(SVN_ERR_UNVERSIONED_RESOURCE, NULL,
_("'%s' is not under version control"),
svn_path_local_style(target, pool));
if (! entry->url)
return svn_error_createf
(SVN_ERR_ENTRY_MISSING_URL, NULL,
_("Entry '%s' has no URL"),
svn_path_local_style(target, pool));
URL = apr_pstrdup(pool, entry->url);
SVN_ERR(svn_wc_adm_close(adm_access));
(*((const char **)apr_array_push(target_urls))) = URL;
(*((const char **)apr_array_push(real_targets))) = target;
}
if (target_urls->nelts == 0)
return SVN_NO_ERROR;
SVN_ERR(svn_path_condense_targets(&url_or_path, &condensed_targets,
target_urls, TRUE, pool));
if (condensed_targets->nelts == 0)
(*((const char **)apr_array_push(condensed_targets))) = "";
targets = real_targets;
}
if (start->kind == svn_opt_revision_number &&
end->kind == svn_opt_revision_number)
session_opt_rev = (start->value.number > end->value.number ?
*start : *end);
else if (start->kind == svn_opt_revision_date &&
end->kind == svn_opt_revision_date)
session_opt_rev = (start->value.date > end->value.date ? *start : *end);
else
session_opt_rev.kind = svn_opt_revision_unspecified;
{
const char *target;
if (peg_revision->kind == svn_opt_revision_base
|| peg_revision->kind == svn_opt_revision_committed
|| peg_revision->kind == svn_opt_revision_previous)
SVN_ERR(svn_path_condense_targets(&target, NULL, targets, TRUE, pool));
else
target = url_or_path;
SVN_ERR(svn_client__ra_session_from_path(&ra_session, &ignored_revnum,
&ignored_url, target,
peg_revision, &session_opt_rev,
ctx, pool));
}
{
svn_error_t *err = SVN_NO_ERROR;
svn_revnum_t start_revnum, end_revnum;
svn_boolean_t start_is_local = svn_client__revision_is_local(start);
svn_boolean_t end_is_local = svn_client__revision_is_local(end);
if (! start_is_local)
SVN_ERR(svn_client__get_revision_number
(&start_revnum, ra_session, start, base_name, pool));
if (! end_is_local)
SVN_ERR(svn_client__get_revision_number
(&end_revnum, ra_session, end, base_name, pool));
if (start_is_local || end_is_local)
{
int i;
for (i = 0; i < targets->nelts; i++)
{
const char *target = ((const char **)targets->elts)[i];
if (start_is_local)
SVN_ERR(svn_client__get_revision_number
(&start_revnum, ra_session, start, target, pool));
if (end_is_local)
SVN_ERR(svn_client__get_revision_number
(&end_revnum, ra_session, end, target, pool));
err = svn_ra_get_log(ra_session,
condensed_targets,
start_revnum,
end_revnum,
limit,
discover_changed_paths,
strict_node_history,
receiver,
receiver_baton,
pool);
if (err)
break;
}
}
else
{
err = svn_ra_get_log(ra_session,
condensed_targets,
start_revnum,
end_revnum,
limit,
discover_changed_paths,
strict_node_history,
receiver,
receiver_baton,
pool);
}
return err;
}
}
svn_error_t *
svn_client_log2(const apr_array_header_t *targets,
const svn_opt_revision_t *start,
const svn_opt_revision_t *end,
int limit,
svn_boolean_t discover_changed_paths,
svn_boolean_t strict_node_history,
svn_log_message_receiver_t receiver,
void *receiver_baton,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
svn_opt_revision_t peg_revision;
peg_revision.kind = svn_opt_revision_unspecified;
return svn_client_log3(targets, &peg_revision, start, end, limit,
discover_changed_paths, strict_node_history,
receiver, receiver_baton, ctx, pool);
}
svn_error_t *
svn_client_log(const apr_array_header_t *targets,
const svn_opt_revision_t *start,
const svn_opt_revision_t *end,
svn_boolean_t discover_changed_paths,
svn_boolean_t strict_node_history,
svn_log_message_receiver_t receiver,
void *receiver_baton,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
svn_error_t *err = SVN_NO_ERROR;
err = svn_client_log2(targets, start, end, 0, discover_changed_paths,
strict_node_history, receiver, receiver_baton, ctx,
pool);
if (err && (err->apr_err == SVN_ERR_FS_NO_SUCH_REVISION)
&& (start->kind == svn_opt_revision_head)
&& ((end->kind == svn_opt_revision_number)
&& (end->value.number == 1)))
{
svn_error_clear(err);
err = SVN_NO_ERROR;
SVN_ERR(receiver(receiver_baton,
NULL, 0, "", "", _("No commits in repository"),
pool));
}
return err;
}