propset-cmd.c revision 362181
14Srgrimes/*
24Srgrimes * propset-cmd.c -- Set property values on files/dirs
34Srgrimes *
44Srgrimes * ====================================================================
54Srgrimes *    Licensed to the Apache Software Foundation (ASF) under one
64Srgrimes *    or more contributor license agreements.  See the NOTICE file
74Srgrimes *    distributed with this work for additional information
84Srgrimes *    regarding copyright ownership.  The ASF licenses this file
94Srgrimes *    to you under the Apache License, Version 2.0 (the
104Srgrimes *    "License"); you may not use this file except in compliance
114Srgrimes *    with the License.  You may obtain a copy of the License at
124Srgrimes *
134Srgrimes *      http://www.apache.org/licenses/LICENSE-2.0
144Srgrimes *
154Srgrimes *    Unless required by applicable law or agreed to in writing,
164Srgrimes *    software distributed under the License is distributed on an
174Srgrimes *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
184Srgrimes *    KIND, either express or implied.  See the License for the
194Srgrimes *    specific language governing permissions and limitations
204Srgrimes *    under the License.
214Srgrimes * ====================================================================
224Srgrimes */
234Srgrimes
244Srgrimes/* ==================================================================== */
254Srgrimes
264Srgrimes
274Srgrimes
284Srgrimes/*** Includes. ***/
294Srgrimes
304Srgrimes#include "svn_cmdline.h"
314Srgrimes#include "svn_pools.h"
324Srgrimes#include "svn_client.h"
334Srgrimes#include "svn_string.h"
344Srgrimes#include "svn_error.h"
354Srgrimes#include "svn_utf.h"
36620Srgrimes#include "svn_subst.h"
3750477Speter#include "svn_path.h"
384Srgrimes#include "svn_props.h"
394Srgrimes#include "cl.h"
404Srgrimes
414Srgrimes#include "svn_private_config.h"
424Srgrimes
438876Srgrimes
444Srgrimes/*** Code. ***/
454Srgrimes
464Srgrimes/* This implements the `svn_opt_subcommand_t' interface. */
474Srgrimessvn_error_t *
4832358Seivindsvn_cl__propset(apr_getopt_t *os,
4932726Seivind                void *baton,
5025460Sjoerg                apr_pool_t *scratch_pool)
5171785Speter{
5253888Sdillon  svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
5337272Sjmg  svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
5445720Speter  const char *pname;
5546806Sphk  svn_string_t *propval = NULL;
5625164Speter  svn_boolean_t propval_came_from_cmdline;
572056Swollman  apr_array_header_t *args, *targets;
582056Swollman
5945720Speter  /* PNAME and PROPVAL expected as first 2 arguments if filedata was
602056Swollman     NULL, else PNAME alone will precede the targets.  Get a UTF-8
6131328Speter     version of the name, too. */
6236809Sbde  SVN_ERR(svn_opt_parse_num_args(&args, os,
6367365Sjhb                                 opt_state->filedata ? 1 : 2, scratch_pool));
642056Swollman  pname = APR_ARRAY_IDX(args, 0, const char *);
652056Swollman  SVN_ERR(svn_utf_cstring_to_utf8(&pname, pname, scratch_pool));
6636809Sbde  if (! svn_prop_name_is_valid(pname))
6712604Sbde    return svn_error_createf(SVN_ERR_CLIENT_PROPERTY_NAME, NULL,
6849558Sphk                             _("'%s' is not a valid Subversion property name"),
694Srgrimes                             pname);
7020641Sbde  if (!opt_state->force)
717090Sbde    SVN_ERR(svn_cl__check_svn_prop_name(pname, opt_state->revprop,
7227288Sfsmp                                        svn_cl__prop_use_set, scratch_pool));
7325164Speter
7450197Speter  /* Get the PROPVAL from either an external file, or from the command
7550197Speter     line. */
7625164Speter  if (opt_state->filedata)
7727288Sfsmp    {
7871785Speter      propval = svn_string_create_from_buf(opt_state->filedata, scratch_pool);
7950769Sdfr      propval_came_from_cmdline = FALSE;
8055117Sbde    }
8146915Speter  else
8255117Sbde    {
8346915Speter      propval = svn_string_create(APR_ARRAY_IDX(args, 1, const char *),
8442817Speter                                  scratch_pool);
8512604Sbde      propval_came_from_cmdline = TRUE;
8642817Speter    }
8712604Sbde
8865500Smsmith  /* We only want special Subversion property values to be in UTF-8
8965500Smsmith     and LF line endings.  All other propvals are taken literally. */
9065500Smsmith  if (svn_prop_needs_translation(pname))
9165500Smsmith    SVN_ERR(svn_subst_translate_string2(&propval, NULL, NULL, propval,
9242817Speter                                        opt_state->encoding, FALSE,
9342817Speter                                        scratch_pool, scratch_pool));
9442817Speter  else if (opt_state->encoding)
9542817Speter    return svn_error_create
9642817Speter      (SVN_ERR_UNSUPPORTED_FEATURE, NULL,
9742817Speter       _("--encoding option applies only to textual"
9846806Sphk         " Subversion-controlled properties"));
9946806Sphk
10042817Speter  /* Suck up all the remaining arguments into a targets array */
10145720Speter
10245720Speter  SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
1034Srgrimes                                                      opt_state->targets,
1044Srgrimes                                                      ctx, FALSE,
1054Srgrimes                                                      scratch_pool));
10610665Sbde
10742817Speter  /* Implicit "." is okay for revision properties; it just helps
10842817Speter     us find the right repository. */
10942817Speter  if (opt_state->revprop)
11042817Speter    svn_opt_push_implicit_dot_target(targets, scratch_pool);
11142817Speter
11242817Speter  SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, scratch_pool));
11310665Sbde
11410653Sdg  if (opt_state->revprop)  /* operate on a revprop */
1154Srgrimes    {
1164Srgrimes      svn_revnum_t rev;
11729675Sgibbs      const char *URL;
11850184Speter
11950184Speter      SVN_ERR(svn_cl__revprop_prepare(&opt_state->start_revision, targets,
12050184Speter                                      &URL, ctx, scratch_pool));
12150184Speter
12250184Speter      /* Let libsvn_client do the real work. */
12350184Speter      SVN_ERR(svn_client_revprop_set2(pname, propval, NULL,
12450184Speter                                      URL, &(opt_state->start_revision),
12550184Speter                                      &rev, opt_state->force, ctx,
12650184Speter                                      scratch_pool));
12750184Speter    }
12850184Speter  else if (opt_state->start_revision.kind != svn_opt_revision_unspecified)
12950184Speter    {
13050184Speter      return svn_error_createf
13150184Speter        (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
13229675Sgibbs         _("Cannot specify revision for setting versioned property '%s'"),
13327288Sfsmp         pname);
13427288Sfsmp    }
13525172Speter  else  /* operate on a normal, versioned property (not a revprop) */
13627288Sfsmp    {
13727288Sfsmp      if (opt_state->depth == svn_depth_unknown)
13825172Speter        opt_state->depth = svn_depth_empty;
13927288Sfsmp
14012791Sgibbs      /* The customary implicit dot rule has been prone to user error
14145720Speter       * here.  People would do intuitive things like
14254073Smdodd       *
14312791Sgibbs       *    $ svn propset svn:executable script
14438779Snsouch       *
14538779Snsouch       * and then be surprised to get an error like:
14638779Snsouch       *
14771785Speter       *    svn: Illegal target for the requested operation
14850184Speter       *    svn: Cannot set svn:executable on a directory ()
14950184Speter       *
15050184Speter       * So we don't do the implicit dot thing anymore.  A * target
15150184Speter       * must always be explicitly provided when setting a versioned
15245720Speter       * property.  See
15350769Sdfr       *
15450769Sdfr       *    https://issues.apache.org/jira/browse/SVN-924
15545720Speter       *
15631336Sbde       * for more details.
15731336Sbde       */
15831336Sbde
15931336Sbde      if (targets->nelts == 0)
16031336Sbde        {
16142817Speter          if (propval_came_from_cmdline)
16231337Sbde            {
16342817Speter              return svn_error_createf
16442817Speter                (SVN_ERR_CL_INSUFFICIENT_ARGS, NULL,
16542817Speter                 _("Explicit target required ('%s' interpreted as prop value)"),
16642817Speter                 propval->data);
16742817Speter            }
16822564Sbde          else
16910665Sbde            {
17010665Sbde              return svn_error_create
17120641Sbde                (SVN_ERR_CL_INSUFFICIENT_ARGS, NULL,
17227561Sfsmp                 _("Explicit target argument required"));
17327561Sfsmp            }
17427615Sfsmp        }
17527561Sfsmp
17627561Sfsmp      SVN_ERR(svn_cl__propset_print_binary_mime_type_warning(targets,
17720641Sbde                                                             pname,
17820641Sbde                                                             propval,
17920641Sbde                                                             scratch_pool));
18020641Sbde
18120641Sbde      SVN_ERR(svn_client_propset_local(pname, propval, targets,
18220641Sbde                                       opt_state->depth, opt_state->force,
18320641Sbde                                       opt_state->changelists, ctx,
18420641Sbde                                       scratch_pool));
18520641Sbde
18620641Sbde      if (! opt_state->quiet)
18720641Sbde        svn_cl__check_boolean_prop_val(pname, propval->data, scratch_pool);
18820641Sbde    }
18920641Sbde
19020641Sbde  return SVN_NO_ERROR;
19120641Sbde}
19220641Sbde