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