In the command-line client, forbid
[svn.git] / subversion / svn / copy-cmd.c
blobcbb6310a031d350ac61388bddba9a292ca708902
1 /*
2 * copy-cmd.c -- Subversion copy command
4 * ====================================================================
5 * Copyright (c) 2000-2007 CollabNet. All rights reserved.
7 * This software is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at http://subversion.tigris.org/license-1.html.
10 * If newer versions of this license are posted there, you may use a
11 * newer version instead, at your option.
13 * This software consists of voluntary contributions made by many
14 * individuals. For exact contribution history, see the revision
15 * history and logs, available at http://subversion.tigris.org/.
16 * ====================================================================
19 /* ==================================================================== */
23 /*** Includes. ***/
25 #include "svn_client.h"
26 #include "svn_path.h"
27 #include "svn_error.h"
28 #include "cl.h"
30 #include "svn_private_config.h"
33 /*** Code. ***/
35 /* This implements the `svn_opt_subcommand_t' interface. */
36 svn_error_t *
37 svn_cl__copy(apr_getopt_t *os,
38 void *baton,
39 apr_pool_t *pool)
41 svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
42 svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
43 apr_array_header_t *targets, *sources;
44 const char *src_path, *dst_path;
45 svn_boolean_t srcs_are_urls, dst_is_url;
46 svn_commit_info_t *commit_info = NULL;
47 svn_error_t *err;
48 int i;
50 SVN_ERR(svn_opt_args_to_target_array2(&targets, os,
51 opt_state->targets, pool));
52 if (targets->nelts < 2)
53 return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);
55 /* Get the src list and associated peg revs */
56 sources = apr_array_make(pool, targets->nelts - 1,
57 sizeof(svn_client_copy_source_t *));
58 for (i = 0; i < (targets->nelts - 1); i++)
60 const char *target = APR_ARRAY_IDX(targets, i, const char *);
61 svn_client_copy_source_t *source = apr_palloc(pool, sizeof(*source));
62 const char *src;
63 svn_opt_revision_t *peg_revision = apr_palloc(pool,
64 sizeof(*peg_revision));
66 SVN_ERR(svn_opt_parse_path(peg_revision, &src, target, pool));
67 source->path = src;
68 source->revision = &(opt_state->start_revision);
69 source->peg_revision = peg_revision;
71 APR_ARRAY_PUSH(sources, svn_client_copy_source_t *) = source;
74 /* Figure out which type of trace editor to use.
75 If the src_paths are not homogeneous, setup_copy will return an error. */
76 src_path = APR_ARRAY_IDX(targets, 0, const char *);
77 srcs_are_urls = svn_path_is_url(src_path);
78 dst_path = APR_ARRAY_IDX(targets, targets->nelts - 1, const char *);
79 apr_array_pop(targets);
80 dst_is_url = svn_path_is_url(dst_path);
82 if ((! srcs_are_urls) && (! dst_is_url))
84 /* WC->WC */
85 if (! opt_state->quiet)
86 svn_cl__get_notifier(&ctx->notify_func2, &ctx->notify_baton2,
87 FALSE, FALSE, FALSE, pool);
89 else if ((! srcs_are_urls) && (dst_is_url))
91 /* WC->URL : Use notification. */
92 /* ### todo:
94 We'd like to use the notifier, but we MAY have a couple of
95 problems with that, the same problems that used to apply to
96 the old trace_editor:
98 1) We don't know where the commit editor for this case will
99 be anchored with respect to the repository, so we can't
100 use the DST_URL.
102 2) While we do know where the commit editor will be driven
103 from with respect to our working copy, we don't know what
104 basenames will be chosen for our committed things. So a
105 copy of dir1/foo.c to http://.../dir2/foo-copy-c would
106 display like: "Adding dir1/foo-copy.c", which could be a
107 bogus path.
110 else if ((srcs_are_urls) && (! dst_is_url))
112 /* URL->WC : Use checkout-style notification. */
113 if (! opt_state->quiet)
114 svn_cl__get_notifier(&ctx->notify_func2, &ctx->notify_baton2, TRUE,
115 FALSE, FALSE, pool);
117 /* else URL -> URL, meaning that no notification is needed. */
119 if (! dst_is_url)
121 ctx->log_msg_func3 = NULL;
122 if (opt_state->message || opt_state->filedata || opt_state->revprop_table)
123 return svn_error_create
124 (SVN_ERR_CL_UNNECESSARY_LOG_MESSAGE, NULL,
125 _("Local, non-commit operations do not take a log message "
126 "or revision properties"));
129 if (ctx->log_msg_func3)
130 SVN_ERR(svn_cl__make_log_msg_baton(&(ctx->log_msg_baton3), opt_state,
131 NULL, ctx->config, pool));
133 ctx->revprop_table = opt_state->revprop_table;
135 err = svn_client_copy4(&commit_info, sources, dst_path, TRUE,
136 opt_state->parents, ctx, pool);
138 if (ctx->log_msg_func3)
139 SVN_ERR(svn_cl__cleanup_log_msg(ctx->log_msg_baton3, err));
140 else if (err)
141 return err;
143 if (commit_info && ! opt_state->quiet)
144 SVN_ERR(svn_cl__print_commit_info(commit_info, pool));
146 return SVN_NO_ERROR;