1/* 2 * propset-cmd.c -- Set property values on files/dirs 3 * 4 * ==================================================================== 5 * Licensed to the Apache Software Foundation (ASF) under one 6 * or more contributor license agreements. See the NOTICE file 7 * distributed with this work for additional information 8 * regarding copyright ownership. The ASF licenses this file 9 * to you under the Apache License, Version 2.0 (the 10 * "License"); you may not use this file except in compliance 11 * with the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, 16 * software distributed under the License is distributed on an 17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18 * KIND, either express or implied. See the License for the 19 * specific language governing permissions and limitations 20 * under the License. 21 * ==================================================================== 22 */ 23 24/* ==================================================================== */ 25 26 27 28/*** Includes. ***/ 29 30#include "svn_cmdline.h" 31#include "svn_pools.h" 32#include "svn_client.h" 33#include "svn_string.h" 34#include "svn_error.h" 35#include "svn_utf.h" 36#include "svn_subst.h" 37#include "svn_path.h" 38#include "svn_props.h" 39#include "cl.h" 40 41#include "svn_private_config.h" 42 43 44/*** Code. ***/ 45 46/* This implements the `svn_opt_subcommand_t' interface. */ 47svn_error_t * 48svn_cl__propset(apr_getopt_t *os, 49 void *baton, 50 apr_pool_t *scratch_pool) 51{ 52 svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state; 53 svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx; 54 const char *pname, *pname_utf8; 55 svn_string_t *propval = NULL; 56 svn_boolean_t propval_came_from_cmdline; 57 apr_array_header_t *args, *targets; 58 59 /* PNAME and PROPVAL expected as first 2 arguments if filedata was 60 NULL, else PNAME alone will precede the targets. Get a UTF-8 61 version of the name, too. */ 62 SVN_ERR(svn_opt_parse_num_args(&args, os, 63 opt_state->filedata ? 1 : 2, scratch_pool)); 64 pname = APR_ARRAY_IDX(args, 0, const char *); 65 SVN_ERR(svn_utf_cstring_to_utf8(&pname_utf8, pname, scratch_pool)); 66 if (! svn_prop_name_is_valid(pname_utf8)) 67 return svn_error_createf(SVN_ERR_CLIENT_PROPERTY_NAME, NULL, 68 _("'%s' is not a valid Subversion property name"), 69 pname_utf8); 70 if (!opt_state->force) 71 SVN_ERR(svn_cl__check_svn_prop_name(pname_utf8, opt_state->revprop, 72 svn_cl__prop_use_set, scratch_pool)); 73 74 /* Get the PROPVAL from either an external file, or from the command 75 line. */ 76 if (opt_state->filedata) 77 { 78 propval = svn_string_create_from_buf(opt_state->filedata, scratch_pool); 79 propval_came_from_cmdline = FALSE; 80 } 81 else 82 { 83 propval = svn_string_create(APR_ARRAY_IDX(args, 1, const char *), 84 scratch_pool); 85 propval_came_from_cmdline = TRUE; 86 } 87 88 /* We only want special Subversion property values to be in UTF-8 89 and LF line endings. All other propvals are taken literally. */ 90 if (svn_prop_needs_translation(pname_utf8)) 91 SVN_ERR(svn_subst_translate_string2(&propval, NULL, NULL, propval, 92 opt_state->encoding, FALSE, 93 scratch_pool, scratch_pool)); 94 else if (opt_state->encoding) 95 return svn_error_create 96 (SVN_ERR_UNSUPPORTED_FEATURE, NULL, 97 _("--encoding option applies only to textual" 98 " Subversion-controlled properties")); 99 100 /* Suck up all the remaining arguments into a targets array */ 101 102 SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os, 103 opt_state->targets, 104 ctx, FALSE, 105 scratch_pool)); 106 107 /* Implicit "." is okay for revision properties; it just helps 108 us find the right repository. */ 109 if (opt_state->revprop) 110 svn_opt_push_implicit_dot_target(targets, scratch_pool); 111 112 SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, scratch_pool)); 113 114 if (opt_state->revprop) /* operate on a revprop */ 115 { 116 svn_revnum_t rev; 117 const char *URL; 118 119 SVN_ERR(svn_cl__revprop_prepare(&opt_state->start_revision, targets, 120 &URL, ctx, scratch_pool)); 121 122 /* Let libsvn_client do the real work. */ 123 SVN_ERR(svn_client_revprop_set2(pname_utf8, propval, NULL, 124 URL, &(opt_state->start_revision), 125 &rev, opt_state->force, ctx, 126 scratch_pool)); 127 } 128 else if (opt_state->start_revision.kind != svn_opt_revision_unspecified) 129 { 130 return svn_error_createf 131 (SVN_ERR_CL_ARG_PARSING_ERROR, NULL, 132 _("Cannot specify revision for setting versioned property '%s'"), 133 pname); 134 } 135 else /* operate on a normal, versioned property (not a revprop) */ 136 { 137 if (opt_state->depth == svn_depth_unknown) 138 opt_state->depth = svn_depth_empty; 139 140 /* The customary implicit dot rule has been prone to user error 141 * here. People would do intuitive things like 142 * 143 * $ svn propset svn:executable script 144 * 145 * and then be surprised to get an error like: 146 * 147 * svn: Illegal target for the requested operation 148 * svn: Cannot set svn:executable on a directory () 149 * 150 * So we don't do the implicit dot thing anymore. A * target 151 * must always be explicitly provided when setting a versioned 152 * property. See 153 * 154 * http://subversion.tigris.org/issues/show_bug.cgi?id=924 155 * 156 * for more details. 157 */ 158 159 if (targets->nelts == 0) 160 { 161 if (propval_came_from_cmdline) 162 { 163 return svn_error_createf 164 (SVN_ERR_CL_INSUFFICIENT_ARGS, NULL, 165 _("Explicit target required ('%s' interpreted as prop value)"), 166 propval->data); 167 } 168 else 169 { 170 return svn_error_create 171 (SVN_ERR_CL_INSUFFICIENT_ARGS, NULL, 172 _("Explicit target argument required")); 173 } 174 } 175 176 SVN_ERR(svn_cl__propset_print_binary_mime_type_warning(targets, 177 pname_utf8, 178 propval, 179 scratch_pool)); 180 181 SVN_ERR(svn_client_propset_local(pname_utf8, propval, targets, 182 opt_state->depth, opt_state->force, 183 opt_state->changelists, ctx, 184 scratch_pool)); 185 186 if (! opt_state->quiet) 187 svn_cl__check_boolean_prop_val(pname_utf8, propval->data, scratch_pool); 188 } 189 190 return SVN_NO_ERROR; 191} 192