/* This implements the `svn_opt_subcommand_t' interface. */ svn_error_t * svn_cl__lock(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 *comment; SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os, opt_state->targets, pool)); /* We only support locking files, so '.' is not valid. */ if (! targets->nelts) return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL); /* Get comment. */ SVN_ERR(get_comment(&comment, ctx, opt_state, pool)); svn_cl__get_notifier(&ctx->notify_func2, &ctx->notify_baton2, FALSE, FALSE, FALSE, pool); SVN_ERR(svn_client_lock(targets, comment, opt_state->force, ctx, pool)); return SVN_NO_ERROR; }
/* This implements the `svn_opt_subcommand_t' interface. */ svn_error_t * svn_cl__add(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; int i; apr_pool_t *subpool; SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os, opt_state->targets, pool)); if (! targets->nelts) return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL); if (! opt_state->quiet) svn_cl__get_notifier(&ctx->notify_func2, &ctx->notify_baton2, FALSE, FALSE, FALSE, pool); if (opt_state->depth == svn_depth_unknown) opt_state->depth = svn_depth_infinity; subpool = svn_pool_create(pool); for (i = 0; i < targets->nelts; i++) { const char *target = APR_ARRAY_IDX(targets, i, const char *); svn_pool_clear(subpool); SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton)); SVN_ERR(svn_cl__try (svn_client_add4(target, opt_state->depth, opt_state->force, opt_state->no_ignore, opt_state->parents, ctx, subpool), NULL, opt_state->quiet, SVN_ERR_ENTRY_EXISTS, SVN_ERR_WC_PATH_NOT_FOUND, SVN_NO_ERROR)); } svn_pool_destroy(subpool); return SVN_NO_ERROR; }
/* This implements the `svn_opt_subcommand_t' interface. */ svn_error_t * svn_cl__status(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; apr_pool_t *subpool; apr_hash_t *master_cl_hash = apr_hash_make(pool); int i; svn_opt_revision_t rev; struct status_baton sb; SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os, opt_state->targets, ctx, pool)); /* Add "." if user passed 0 arguments */ svn_opt_push_implicit_dot_target(targets, pool); /* We want our -u statuses to be against HEAD. */ rev.kind = svn_opt_revision_head; /* The notification callback, leave the notifier as NULL in XML mode */ if (! opt_state->xml) svn_cl__get_notifier(&ctx->notify_func2, &ctx->notify_baton2, FALSE, FALSE, FALSE, pool); subpool = svn_pool_create(pool); sb.had_print_error = FALSE; if (opt_state->xml) { /* If output is not incremental, output the XML header and wrap everything in a top-level element. This makes the output in its entirety a well-formed XML document. */ if (! opt_state->incremental) SVN_ERR(svn_cl__xml_print_header("status", pool)); } else { if (opt_state->incremental) return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, _("'incremental' option only valid in XML " "mode")); } sb.detailed = (opt_state->verbose || opt_state->update); sb.show_last_committed = opt_state->verbose; sb.skip_unrecognized = opt_state->quiet; sb.repos_locks = opt_state->update; sb.xml_mode = opt_state->xml; sb.cached_changelists = master_cl_hash; sb.cl_pool = pool; SVN_ERR(svn_opt__eat_peg_revisions(&targets, targets, pool)); for (i = 0; i < targets->nelts; i++) { const char *target = APR_ARRAY_IDX(targets, i, const char *); svn_revnum_t repos_rev = SVN_INVALID_REVNUM; svn_pool_clear(subpool); SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton)); if (opt_state->xml) SVN_ERR(print_start_target_xml(svn_path_local_style(target, subpool), subpool)); /* Retrieve a hash of status structures with the information requested by the user. */ SVN_ERR(svn_cl__try(svn_client_status4(&repos_rev, target, &rev, print_status, &sb, opt_state->depth, opt_state->verbose, opt_state->update, opt_state->no_ignore, opt_state->ignore_externals, opt_state->changelists, ctx, subpool), NULL, opt_state->quiet, /* not versioned: */ SVN_ERR_WC_NOT_DIRECTORY, SVN_NO_ERROR)); if (opt_state->xml) SVN_ERR(print_finish_target_xml(repos_rev, subpool)); } /* If any paths were cached because they were associatied with changelists, we can now display them as grouped changelists. */ if (apr_hash_count(master_cl_hash) > 0) { apr_hash_index_t *hi; svn_stringbuf_t *buf; if (opt_state->xml) buf = svn_stringbuf_create("", pool); for (hi = apr_hash_first(pool, master_cl_hash); hi; hi = apr_hash_next(hi)) { const char *changelist_name; apr_array_header_t *path_array; const void *key; void *val; int j; apr_hash_this(hi, &key, NULL, &val); changelist_name = key; path_array = val; /* ### TODO: For non-XML output, we shouldn't print the ### leading \n on the first changelist if there were no ### non-changelist entries. */ if (opt_state->xml) { svn_stringbuf_set(buf, ""); svn_xml_make_open_tag(&buf, pool, svn_xml_normal, "changelist", "name", changelist_name, NULL); SVN_ERR(svn_cl__error_checked_fputs(buf->data, stdout)); } else SVN_ERR(svn_cmdline_printf(pool, _("\n--- Changelist '%s':\n"), changelist_name)); for (j = 0; j < path_array->nelts; j++) { struct status_cache *scache = APR_ARRAY_IDX(path_array, j, struct status_cache *); SVN_ERR(print_status_normal_or_xml(&sb, scache->path, scache->status, pool)); } if (opt_state->xml) { svn_stringbuf_set(buf, ""); svn_xml_make_close_tag(&buf, pool, "changelist"); SVN_ERR(svn_cl__error_checked_fputs(buf->data, stdout)); } } }
/* This implements the `svn_opt_subcommand_t' interface. */ svn_error_t * svn_cl__move(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 *dst_path; svn_commit_info_t *commit_info = NULL; svn_error_t *err; SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os, opt_state->targets, ctx, pool)); if (targets->nelts < 2) return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL); if (opt_state->start_revision.kind != svn_opt_revision_unspecified && opt_state->start_revision.kind != svn_opt_revision_head) { return svn_error_create (SVN_ERR_UNSUPPORTED_FEATURE, NULL, _("Cannot specify revisions (except HEAD) with move operations")); } if (! opt_state->quiet) svn_cl__get_notifier(&ctx->notify_func2, &ctx->notify_baton2, FALSE, FALSE, FALSE, pool); dst_path = APR_ARRAY_IDX(targets, targets->nelts - 1, const char *); apr_array_pop(targets); if (! svn_path_is_url(dst_path)) { ctx->log_msg_func3 = NULL; if (opt_state->message || opt_state->filedata || opt_state->revprop_table) return svn_error_create (SVN_ERR_CL_UNNECESSARY_LOG_MESSAGE, NULL, _("Local, non-commit operations do not take a log message " "or revision properties")); } if (ctx->log_msg_func3) SVN_ERR(svn_cl__make_log_msg_baton(&(ctx->log_msg_baton3), opt_state, NULL, ctx->config, pool)); SVN_ERR(svn_opt__eat_peg_revisions(&targets, targets, pool)); err = svn_client_move5(&commit_info, targets, dst_path, opt_state->force, TRUE, opt_state->parents, opt_state->revprop_table, ctx, pool); if (err) err = svn_cl__may_need_force(err); if (ctx->log_msg_func3) SVN_ERR(svn_cl__cleanup_log_msg(ctx->log_msg_baton3, err, pool)); else if (err) return err; if (commit_info && ! opt_state->quiet) SVN_ERR(svn_cl__print_commit_info(commit_info, pool)); return SVN_NO_ERROR; }
/* This implements the `svn_opt_subcommand_t' interface. */ svn_error_t * svn_cl__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; const char *target; int i; svn_opt_revision_t peg_revision; const char *true_path; apr_array_header_t *revprops; if (!opt_state->xml) { if (opt_state->all_revprops) return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, _("'with-all-revprops' option only valid in" " XML mode")); if (opt_state->revprop_table != NULL) return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, _("'with-revprop' option only valid in" " XML mode")); } SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os, opt_state->targets, pool)); /* Add "." if user passed 0 arguments */ svn_opt_push_implicit_dot_target(targets, pool); target = APR_ARRAY_IDX(targets, 0, const char *); /* Determine if they really want a two-revision range. */ if (opt_state->used_change_arg) { if (opt_state->start_revision.value.number < opt_state->end_revision.value.number) opt_state->start_revision = opt_state->end_revision; else opt_state->end_revision = opt_state->start_revision; } /* Strip peg revision if targets contains an URI. */ SVN_ERR(svn_opt_parse_path(&peg_revision, &true_path, target, pool)); APR_ARRAY_IDX(targets, 0, const char *) = true_path; if ((opt_state->start_revision.kind != svn_opt_revision_unspecified) && (opt_state->end_revision.kind == svn_opt_revision_unspecified)) { /* If the user specified exactly one revision, then start rev is set but end is not. We show the log message for just that revision by making end equal to start. Note that if the user requested a single dated revision, then this will cause the same date to be resolved twice. The extra code complexity to get around this slight inefficiency doesn't seem worth it, however. */ opt_state->end_revision = opt_state->start_revision; } else if (opt_state->start_revision.kind == svn_opt_revision_unspecified) { /* Default to any specified peg revision. Otherwise, if the first target is an URL, then we default to HEAD:0. Lastly, the default is BASE:0 since WC@HEAD may not exist. */ if (peg_revision.kind == svn_opt_revision_unspecified) { if (svn_path_is_url(target)) opt_state->start_revision.kind = svn_opt_revision_head; else opt_state->start_revision.kind = svn_opt_revision_base; } else opt_state->start_revision = peg_revision; if (opt_state->end_revision.kind == svn_opt_revision_unspecified) { opt_state->end_revision.kind = svn_opt_revision_number; opt_state->end_revision.value.number = 0; } } 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)) return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, _("Only relative paths can be specified " "after a URL")); } } lb.cancel_func = ctx->cancel_func; lb.cancel_baton = ctx->cancel_baton; lb.omit_log_message = opt_state->quiet; lb.merge_stack = apr_array_make(pool, 0, sizeof(svn_revnum_t)); lb.pool = pool; if (! opt_state->quiet) svn_cl__get_notifier(&ctx->notify_func2, &ctx->notify_baton2, FALSE, FALSE, FALSE, pool); if (opt_state->xml) { /* If output is not incremental, output the XML header and wrap everything in a top-level element. This makes the output in its entirety a well-formed XML document. */ if (! opt_state->incremental) SVN_ERR(svn_cl__xml_print_header("log", pool)); if (opt_state->all_revprops) revprops = NULL; else if (opt_state->revprop_table != NULL) { apr_hash_index_t *hi; revprops = apr_array_make(pool, apr_hash_count(opt_state->revprop_table), sizeof(char *)); for (hi = apr_hash_first(pool, opt_state->revprop_table); hi != NULL; hi = apr_hash_next(hi)) { char *property; svn_string_t *value; apr_hash_this(hi, (void *)&property, NULL, (void *)&value); if (value && value->data[0] != '\0') return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, _("cannot assign with 'with-revprop'" " option (drop the '=')")); APR_ARRAY_PUSH(revprops, char *) = property; } } else { 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_log4(targets, &peg_revision, &(opt_state->start_revision), &(opt_state->end_revision), opt_state->limit, opt_state->verbose, opt_state->stop_on_copy, opt_state->use_merge_history, revprops, log_entry_receiver_xml, &lb, ctx, pool)); if (! opt_state->incremental) SVN_ERR(svn_cl__xml_print_footer("log", pool)); } else /* default output format */ { 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_log4(targets, &peg_revision, &(opt_state->start_revision), &(opt_state->end_revision), 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->incremental) SVN_ERR(svn_cmdline_printf(pool, SEP_STRING)); } return SVN_NO_ERROR; }
/* This implements the `svn_opt_subcommand_t' interface. */ svn_error_t * svn_cl__copy(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, *sources; const char *src_path, *dst_path; svn_boolean_t srcs_are_urls, dst_is_url; svn_commit_info_t *commit_info = NULL; svn_error_t *err; int i; SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os, opt_state->targets, ctx, pool)); if (targets->nelts < 2) return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL); /* Get the src list and associated peg revs */ sources = apr_array_make(pool, targets->nelts - 1, sizeof(svn_client_copy_source_t *)); for (i = 0; i < (targets->nelts - 1); i++) { const char *target = APR_ARRAY_IDX(targets, i, const char *); svn_client_copy_source_t *source = apr_palloc(pool, sizeof(*source)); const char *src; svn_opt_revision_t *peg_revision = apr_palloc(pool, sizeof(*peg_revision)); SVN_ERR(svn_opt_parse_path(peg_revision, &src, target, pool)); source->path = src; source->revision = &(opt_state->start_revision); source->peg_revision = peg_revision; APR_ARRAY_PUSH(sources, svn_client_copy_source_t *) = source; } SVN_ERR(svn_opt__eat_peg_revisions(&targets, targets, pool)); /* Figure out which type of trace editor to use. If the src_paths are not homogeneous, setup_copy will return an error. */ src_path = APR_ARRAY_IDX(targets, 0, const char *); srcs_are_urls = svn_path_is_url(src_path); dst_path = APR_ARRAY_IDX(targets, targets->nelts - 1, const char *); apr_array_pop(targets); dst_is_url = svn_path_is_url(dst_path); if ((! srcs_are_urls) && (! dst_is_url)) { /* WC->WC */ if (! opt_state->quiet) svn_cl__get_notifier(&ctx->notify_func2, &ctx->notify_baton2, FALSE, FALSE, FALSE, pool); } else if ((! srcs_are_urls) && (dst_is_url)) { /* WC->URL : Use notification. */ /* ### todo: We'd like to use the notifier, but we MAY have a couple of problems with that, the same problems that used to apply to the old trace_editor: 1) We don't know where the commit editor for this case will be anchored with respect to the repository, so we can't use the DST_URL. 2) While we do know where the commit editor will be driven from with respect to our working copy, we don't know what basenames will be chosen for our committed things. So a copy of dir1/foo.c to http://.../dir2/foo-copy-c would display like: "Adding dir1/foo-copy.c", which could be a bogus path. */ } else if ((srcs_are_urls) && (! dst_is_url)) { /* URL->WC : Use checkout-style notification. */ if (! opt_state->quiet) svn_cl__get_notifier(&ctx->notify_func2, &ctx->notify_baton2, TRUE, FALSE, FALSE, pool); } /* else URL -> URL, meaning that no notification is needed. */ if (! dst_is_url) { ctx->log_msg_func3 = NULL; if (opt_state->message || opt_state->filedata || opt_state->revprop_table) return svn_error_create (SVN_ERR_CL_UNNECESSARY_LOG_MESSAGE, NULL, _("Local, non-commit operations do not take a log message " "or revision properties")); } if (ctx->log_msg_func3) SVN_ERR(svn_cl__make_log_msg_baton(&(ctx->log_msg_baton3), opt_state, NULL, ctx->config, pool)); err = svn_client_copy5(&commit_info, sources, dst_path, TRUE, opt_state->parents, opt_state->ignore_externals, opt_state->revprop_table, ctx, pool); if (ctx->log_msg_func3) SVN_ERR(svn_cl__cleanup_log_msg(ctx->log_msg_baton3, err, pool)); else if (err) return err; if (commit_info && ! opt_state->quiet) SVN_ERR(svn_cl__print_commit_info(commit_info, pool)); return SVN_NO_ERROR; }
/* This implements the `svn_opt_subcommand_t' interface. */ svn_error_t * svn_cl__propset(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; const char *pname, *pname_utf8; svn_string_t *propval = NULL; svn_boolean_t propval_came_from_cmdline; apr_array_header_t *args, *targets; int i; /* PNAME and PROPVAL expected as first 2 arguments if filedata was NULL, else PNAME alone will precede the targets. Get a UTF-8 version of the name, too. */ SVN_ERR(svn_opt_parse_num_args(&args, os, opt_state->filedata ? 1 : 2, pool)); pname = APR_ARRAY_IDX(args, 0, const char *); SVN_ERR(svn_utf_cstring_to_utf8(&pname_utf8, pname, pool)); if (! svn_prop_name_is_valid(pname_utf8)) return svn_error_createf(SVN_ERR_CLIENT_PROPERTY_NAME, NULL, _("'%s' is not a valid Subversion property name"), pname_utf8); /* Get the PROPVAL from either an external file, or from the command line. */ if (opt_state->filedata) { propval = svn_string_create_from_buf(opt_state->filedata, pool); propval_came_from_cmdline = FALSE; } else { propval = svn_string_create(APR_ARRAY_IDX(args, 1, const char *), pool); propval_came_from_cmdline = TRUE; } /* We only want special Subversion property values to be in UTF-8 and LF line endings. All other propvals are taken literally. */ if (svn_prop_needs_translation(pname_utf8)) SVN_ERR(svn_subst_translate_string(&propval, propval, opt_state->encoding, pool)); else if (opt_state->encoding) return svn_error_create (SVN_ERR_UNSUPPORTED_FEATURE, NULL, _("--encoding option applies only to textual" " Subversion-controlled properties")); /* Suck up all the remaining arguments into a targets array */ SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os, opt_state->targets, ctx, pool)); if (! opt_state->quiet) svn_cl__get_notifier(&ctx->notify_func2, &ctx->notify_baton2, FALSE, FALSE, FALSE, pool); /* Implicit "." is okay for revision properties; it just helps us find the right repository. */ if (opt_state->revprop) svn_opt_push_implicit_dot_target(targets, pool); SVN_ERR(svn_opt__eat_peg_revisions(&targets, targets, pool)); if (opt_state->revprop) /* operate on a revprop */ { svn_revnum_t rev; const char *URL; SVN_ERR(svn_cl__revprop_prepare(&opt_state->start_revision, targets, &URL, pool)); /* Let libsvn_client do the real work. */ SVN_ERR(svn_client_revprop_set2(pname_utf8, propval, NULL, URL, &(opt_state->start_revision), &rev, opt_state->force, ctx, pool)); } else if (opt_state->start_revision.kind != svn_opt_revision_unspecified) { return svn_error_createf (SVN_ERR_CL_ARG_PARSING_ERROR, NULL, _("Cannot specify revision for setting versioned property '%s'"), pname); } else /* operate on a normal, versioned property (not a revprop) */ { apr_pool_t *subpool = svn_pool_create(pool); if (opt_state->depth == svn_depth_unknown) opt_state->depth = svn_depth_empty; /* The customary implicit dot rule has been prone to user error * here. People would do intuitive things like * * $ svn propset svn:executable script * * and then be surprised to get an error like: * * svn: Illegal target for the requested operation * svn: Cannot set svn:executable on a directory () * * So we don't do the implicit dot thing anymore. A * target * must always be explicitly provided when setting a versioned * property. See * * http://subversion.tigris.org/issues/show_bug.cgi?id=924 * * for more details. */ if (targets->nelts == 0) { if (propval_came_from_cmdline) { return svn_error_createf (SVN_ERR_CL_INSUFFICIENT_ARGS, NULL, _("Explicit target required ('%s' interpreted as prop value)"), propval->data); } else { return svn_error_create (SVN_ERR_CL_INSUFFICIENT_ARGS, NULL, _("Explicit target argument required")); } } for (i = 0; i < targets->nelts; i++) { const char *target = APR_ARRAY_IDX(targets, i, const char *); svn_commit_info_t *commit_info; svn_pool_clear(subpool); SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton)); SVN_ERR(svn_cl__try(svn_client_propset3 (&commit_info, pname_utf8, propval, target, opt_state->depth, opt_state->force, SVN_INVALID_REVNUM, opt_state->changelists, NULL, ctx, subpool), NULL, opt_state->quiet, SVN_ERR_UNVERSIONED_RESOURCE, SVN_ERR_ENTRY_NOT_FOUND, SVN_NO_ERROR)); if (! opt_state->quiet) svn_cl__check_boolean_prop_val(pname_utf8, propval->data, subpool); } svn_pool_destroy(subpool); } return SVN_NO_ERROR; }
/* This implements the `svn_opt_subcommand_t' interface. */ svn_error_t * svn_cl__export(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; const char *from, *to; apr_array_header_t *targets; svn_error_t *err; svn_opt_revision_t peg_revision; const char *truefrom; SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os, opt_state->targets, ctx, pool)); /* We want exactly 1 or 2 targets for this subcommand. */ if (targets->nelts < 1) return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL); if (targets->nelts > 2) return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, 0, NULL); /* The first target is the `from' path. */ from = APR_ARRAY_IDX(targets, 0, const char *); /* Get the peg revision if present. */ SVN_ERR(svn_opt_parse_path(&peg_revision, &truefrom, from, pool)); /* If only one target was given, split off the basename to use as the `to' path. Else, a `to' path was supplied. */ if (targets->nelts == 1) to = svn_path_uri_decode(svn_path_basename(truefrom, pool), pool); else to = APR_ARRAY_IDX(targets, 1, const char *); SVN_ERR(svn_opt__split_arg_at_peg_revision(&to, NULL, to, pool)); if (! opt_state->quiet) svn_cl__get_notifier(&ctx->notify_func2, &ctx->notify_baton2, FALSE, TRUE, FALSE, pool); if (opt_state->depth == svn_depth_unknown) opt_state->depth = svn_depth_infinity; /* Decode the partially encoded URL and escape all URL unsafe characters. */ if (svn_path_is_url(truefrom)) truefrom = svn_path_uri_encode(svn_path_uri_decode(truefrom, pool), pool); /* Do the export. */ err = svn_client_export4(NULL, truefrom, to, &peg_revision, &(opt_state->start_revision), opt_state->force, opt_state->ignore_externals, opt_state->depth, opt_state->native_eol, ctx, pool); if (err && err->apr_err == SVN_ERR_WC_OBSTRUCTED_UPDATE && !opt_state->force) SVN_ERR_W(err, _("Destination directory exists; please remove " "the directory or use --force to overwrite")); return err; }