2 * propset-cmd.c -- Set property values on files/dirs
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 /* ==================================================================== */
25 #include "svn_cmdline.h"
26 #include "svn_pools.h"
27 #include "svn_client.h"
28 #include "svn_string.h"
29 #include "svn_error.h"
31 #include "svn_subst.h"
33 #include "svn_props.h"
36 #include "svn_private_config.h"
41 /* This implements the `svn_opt_subcommand_t' interface. */
43 svn_cl__propset(apr_getopt_t
*os
,
47 svn_cl__opt_state_t
*opt_state
= ((svn_cl__cmd_baton_t
*) baton
)->opt_state
;
48 svn_client_ctx_t
*ctx
= ((svn_cl__cmd_baton_t
*) baton
)->ctx
;
49 const char *pname
, *pname_utf8
;
50 svn_string_t
*propval
= NULL
;
51 svn_boolean_t propval_came_from_cmdline
;
52 apr_array_header_t
*args
, *targets
;
55 /* PNAME and PROPVAL expected as first 2 arguments if filedata was
56 NULL, else PNAME alone will precede the targets. Get a UTF-8
57 version of the name, too. */
58 SVN_ERR(svn_opt_parse_num_args(&args
, os
,
59 opt_state
->filedata
? 1 : 2, pool
));
60 pname
= APR_ARRAY_IDX(args
, 0, const char *);
61 SVN_ERR(svn_utf_cstring_to_utf8(&pname_utf8
, pname
, pool
));
62 if (! svn_prop_name_is_valid(pname_utf8
))
63 return svn_error_createf(SVN_ERR_CLIENT_PROPERTY_NAME
, NULL
,
64 _("'%s' is not a valid Subversion property name"),
67 /* Get the PROPVAL from either an external file, or from the command
69 if (opt_state
->filedata
)
71 propval
= svn_string_create_from_buf(opt_state
->filedata
, pool
);
72 propval_came_from_cmdline
= FALSE
;
76 propval
= svn_string_create(APR_ARRAY_IDX(args
, 1, const char *), pool
);
77 propval_came_from_cmdline
= TRUE
;
80 /* We only want special Subversion property values to be in UTF-8
81 and LF line endings. All other propvals are taken literally. */
82 if (svn_prop_needs_translation(pname_utf8
))
83 SVN_ERR(svn_subst_translate_string(&propval
, propval
,
84 opt_state
->encoding
, pool
));
86 if (opt_state
->encoding
)
87 return svn_error_create
88 (SVN_ERR_UNSUPPORTED_FEATURE
, NULL
,
89 _("--encoding option applies only to textual"
90 " Subversion-controlled properties"));
92 /* Suck up all the remaining arguments into a targets array */
94 SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets
, os
,
98 /* Implicit "." is okay for revision properties; it just helps
99 us find the right repository. */
100 if (opt_state
->revprop
)
101 svn_opt_push_implicit_dot_target(targets
, pool
);
103 if (opt_state
->revprop
) /* operate on a revprop */
108 SVN_ERR(svn_cl__revprop_prepare(&opt_state
->start_revision
, targets
,
111 /* Let libsvn_client do the real work. */
112 SVN_ERR(svn_client_revprop_set(pname_utf8
, propval
,
113 URL
, &(opt_state
->start_revision
),
114 &rev
, opt_state
->force
, ctx
, pool
));
115 if (! opt_state
->quiet
)
119 (pool
, _("property '%s' set on repository revision %ld\n"),
123 else if (opt_state
->start_revision
.kind
!= svn_opt_revision_unspecified
)
125 return svn_error_createf
126 (SVN_ERR_CL_ARG_PARSING_ERROR
, NULL
,
127 _("Cannot specify revision for setting versioned property '%s'"),
130 else /* operate on a normal, versioned property (not a revprop) */
132 apr_pool_t
*subpool
= svn_pool_create(pool
);
134 if (opt_state
->depth
== svn_depth_unknown
)
135 opt_state
->depth
= svn_depth_empty
;
137 /* The customary implicit dot rule has been prone to user error
138 * here. People would do intuitive things like
140 * $ svn propset svn:executable script
142 * and then be surprised to get an error like:
144 * svn: Illegal target for the requested operation
145 * svn: Cannot set svn:executable on a directory ()
147 * So we don't do the implicit dot thing anymore. A * target
148 * must always be explicitly provided when setting a versioned
151 * http://subversion.tigris.org/issues/show_bug.cgi?id=924
156 if (targets
->nelts
== 0)
158 if (propval_came_from_cmdline
)
160 return svn_error_createf
161 (SVN_ERR_CL_INSUFFICIENT_ARGS
, NULL
,
162 _("Explicit target required ('%s' interpreted as prop value)"),
167 return svn_error_create
168 (SVN_ERR_CL_INSUFFICIENT_ARGS
, NULL
,
169 _("Explicit target argument required"));
173 for (i
= 0; i
< targets
->nelts
; i
++)
175 const char *target
= APR_ARRAY_IDX(targets
, i
, const char *);
176 svn_commit_info_t
*commit_info
;
177 svn_boolean_t success
;
179 svn_pool_clear(subpool
);
180 SVN_ERR(svn_cl__check_cancel(ctx
->cancel_baton
));
181 SVN_ERR(svn_cl__try(svn_client_propset3
182 (&commit_info
, pname_utf8
, propval
, target
,
183 opt_state
->depth
, opt_state
->force
,
184 SVN_INVALID_REVNUM
, opt_state
->changelists
,
186 &success
, opt_state
->quiet
,
187 SVN_ERR_UNVERSIONED_RESOURCE
,
188 SVN_ERR_ENTRY_NOT_FOUND
,
191 if (! opt_state
->quiet
)
192 svn_cl__check_boolean_prop_val(pname_utf8
, propval
->data
, subpool
);
194 if (success
&& (! opt_state
->quiet
))
198 (pool
, SVN_DEPTH_IS_RECURSIVE(opt_state
->depth
)
199 ? _("property '%s' set (recursively) on '%s'\n")
200 : _("property '%s' set on '%s'\n"),
201 pname
, svn_path_local_style(target
, pool
)));
204 svn_pool_destroy(subpool
);