#include "svn_client.h"
#include "svn_path.h"
#include "svn_error.h"
#include "svn_types.h"
#include "cl.h"
#include "svn_private_config.h"
svn_error_t *
svn_cl__merge(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;
const char *sourcepath1, *sourcepath2, *targetpath;
svn_boolean_t using_alternate_syntax = FALSE;
svn_error_t *err;
svn_opt_revision_t peg_revision;
apr_array_header_t *options;
if (opt_state->start_revision.kind != svn_opt_revision_unspecified)
{
if (opt_state->end_revision.kind == svn_opt_revision_unspecified)
return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0,
_("Second revision required"));
using_alternate_syntax = TRUE;
}
SVN_ERR(svn_opt_args_to_target_array2(&targets, os,
opt_state->targets, pool));
if (using_alternate_syntax)
{
if (targets->nelts < 1)
return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, NULL, NULL);
if (targets->nelts > 2)
return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
_("Too many arguments given"));
SVN_ERR(svn_opt_parse_path(&peg_revision, &sourcepath1,
((const char **)(targets->elts))[0], pool));
sourcepath2 = sourcepath1;
if (peg_revision.kind == svn_opt_revision_unspecified)
peg_revision.kind = svn_path_is_url(sourcepath1)
? svn_opt_revision_head : svn_opt_revision_working;
if (targets->nelts == 2)
targetpath = ((const char **) (targets->elts))[1];
else
targetpath = "";
}
else
{
if (targets->nelts < 2)
return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, NULL, NULL);
if (targets->nelts > 3)
return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
_("Too many arguments given"));
SVN_ERR(svn_opt_parse_path(&opt_state->start_revision, &sourcepath1,
((const char **) (targets->elts))[0],
pool));
SVN_ERR(svn_opt_parse_path(&opt_state->end_revision, &sourcepath2,
((const char **) (targets->elts))[1],
pool));
if ((opt_state->start_revision.kind == svn_opt_revision_unspecified
&& ! svn_path_is_url(sourcepath1))
||
(opt_state->end_revision.kind == svn_opt_revision_unspecified
&& ! svn_path_is_url(sourcepath2)))
return svn_error_create
(SVN_ERR_CLIENT_BAD_REVISION, 0,
_("A working copy merge source needs an explicit revision"));
if (targets->nelts == 3)
targetpath = ((const char **) (targets->elts))[2];
else
targetpath = "";
}
if (! strcmp(targetpath, ""))
{
char *sp1_basename, *sp2_basename;
sp1_basename = svn_path_basename(sourcepath1, pool);
sp2_basename = svn_path_basename(sourcepath2, pool);
if (! strcmp(sp1_basename, sp2_basename))
{
svn_node_kind_t kind;
const char *decoded_path = svn_path_uri_decode(sp1_basename, pool);
SVN_ERR(svn_io_check_path(decoded_path, &kind, pool));
if (kind == svn_node_file)
{
targetpath = decoded_path;
}
}
}
if (opt_state->start_revision.kind == svn_opt_revision_unspecified)
opt_state->start_revision.kind = svn_opt_revision_head;
if (opt_state->end_revision.kind == svn_opt_revision_unspecified)
opt_state->end_revision.kind = svn_opt_revision_head;
if (! opt_state->quiet)
svn_cl__get_notifier(&ctx->notify_func2, &ctx->notify_baton2, FALSE,
FALSE, FALSE, pool);
if (opt_state->extensions)
options = svn_cstring_split(opt_state->extensions, " \t\n\r", TRUE, pool);
else
options = NULL;
if (using_alternate_syntax)
{
err = svn_client_merge_peg2(sourcepath1,
&(opt_state->start_revision),
&(opt_state->end_revision),
&peg_revision,
targetpath,
opt_state->nonrecursive ? FALSE : TRUE,
opt_state->ignore_ancestry,
opt_state->force,
opt_state->dry_run,
options,
ctx,
pool);
}
else
{
err = svn_client_merge2(sourcepath1,
&(opt_state->start_revision),
sourcepath2,
&(opt_state->end_revision),
targetpath,
opt_state->nonrecursive ? FALSE : TRUE,
opt_state->ignore_ancestry,
opt_state->force,
opt_state->dry_run,
options,
ctx,
pool);
}
if (err)
return svn_cl__may_need_force(err);
return SVN_NO_ERROR;
}