1251881Speter/* 2251881Speter * commit-cmd.c -- Check changes into the repository. 3251881Speter * 4251881Speter * ==================================================================== 5251881Speter * Licensed to the Apache Software Foundation (ASF) under one 6251881Speter * or more contributor license agreements. See the NOTICE file 7251881Speter * distributed with this work for additional information 8251881Speter * regarding copyright ownership. The ASF licenses this file 9251881Speter * to you under the Apache License, Version 2.0 (the 10251881Speter * "License"); you may not use this file except in compliance 11251881Speter * with the License. You may obtain a copy of the License at 12251881Speter * 13251881Speter * http://www.apache.org/licenses/LICENSE-2.0 14251881Speter * 15251881Speter * Unless required by applicable law or agreed to in writing, 16251881Speter * software distributed under the License is distributed on an 17251881Speter * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18251881Speter * KIND, either express or implied. See the License for the 19251881Speter * specific language governing permissions and limitations 20251881Speter * under the License. 21251881Speter * ==================================================================== 22251881Speter */ 23251881Speter 24251881Speter/* ==================================================================== */ 25251881Speter 26251881Speter 27251881Speter 28251881Speter/*** Includes. ***/ 29251881Speter 30251881Speter#include <apr_general.h> 31251881Speter 32251881Speter#include "svn_hash.h" 33251881Speter#include "svn_error.h" 34251881Speter#include "svn_error_codes.h" 35251881Speter#include "svn_wc.h" 36251881Speter#include "svn_client.h" 37251881Speter#include "svn_path.h" 38251881Speter#include "svn_dirent_uri.h" 39251881Speter#include "svn_error.h" 40251881Speter#include "svn_config.h" 41251881Speter#include "cl.h" 42251881Speter 43251881Speter#include "svn_private_config.h" 44251881Speter 45251881Speter 46251881Speter 47251881Speter/* Wrapper notify_func2 function and baton for warning about 48251881Speter reduced-depth commits of copied directories. */ 49251881Speterstruct copy_warning_notify_baton 50251881Speter{ 51251881Speter svn_wc_notify_func2_t wrapped_func; 52251881Speter void *wrapped_baton; 53251881Speter svn_depth_t depth; 54251881Speter svn_boolean_t warned; 55251881Speter}; 56251881Speter 57251881Speterstatic void 58251881Spetercopy_warning_notify_func(void *baton, 59251881Speter const svn_wc_notify_t *notify, 60251881Speter apr_pool_t *pool) 61251881Speter{ 62251881Speter struct copy_warning_notify_baton *b = baton; 63251881Speter 64251881Speter /* Call the wrapped notification system (if any). */ 65251881Speter if (b->wrapped_func) 66251881Speter b->wrapped_func(b->wrapped_baton, notify, pool); 67251881Speter 68251881Speter /* If we're being notified about a copy of a directory when our 69251881Speter commit depth is less-than-infinite, and we've not already warned 70251881Speter about this situation, then warn about it (and remember that we 71251881Speter now have.) */ 72251881Speter if ((! b->warned) 73251881Speter && (b->depth < svn_depth_infinity) 74251881Speter && (notify->kind == svn_node_dir) 75251881Speter && ((notify->action == svn_wc_notify_commit_copied) || 76251881Speter (notify->action == svn_wc_notify_commit_copied_replaced))) 77251881Speter { 78251881Speter svn_error_t *err; 79251881Speter err = svn_cmdline_printf(pool, 80251881Speter _("svn: The depth of this commit is '%s', " 81251881Speter "but copies are always performed " 82251881Speter "recursively in the repository.\n"), 83251881Speter svn_depth_to_word(b->depth)); 84251881Speter /* ### FIXME: Try to return this error showhow? */ 85251881Speter svn_error_clear(err); 86251881Speter 87251881Speter /* We'll only warn once. */ 88251881Speter b->warned = TRUE; 89251881Speter } 90251881Speter} 91251881Speter 92251881Speter 93251881Speter 94251881Speter 95251881Speter/* This implements the `svn_opt_subcommand_t' interface. */ 96251881Spetersvn_error_t * 97251881Spetersvn_cl__commit(apr_getopt_t *os, 98251881Speter void *baton, 99251881Speter apr_pool_t *pool) 100251881Speter{ 101251881Speter svn_error_t *err; 102251881Speter svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state; 103251881Speter svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx; 104251881Speter apr_array_header_t *targets; 105251881Speter apr_array_header_t *condensed_targets; 106251881Speter const char *base_dir; 107251881Speter svn_config_t *cfg; 108251881Speter svn_boolean_t no_unlock = FALSE; 109251881Speter struct copy_warning_notify_baton cwnb; 110251881Speter 111251881Speter SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os, 112251881Speter opt_state->targets, 113251881Speter ctx, FALSE, pool)); 114251881Speter 115251881Speter SVN_ERR_W(svn_cl__check_targets_are_local_paths(targets), 116251881Speter _("Commit targets must be local paths")); 117251881Speter 118251881Speter /* Add "." if user passed 0 arguments. */ 119251881Speter svn_opt_push_implicit_dot_target(targets, pool); 120251881Speter 121251881Speter SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, pool)); 122251881Speter 123251881Speter /* Condense the targets (like commit does)... */ 124251881Speter SVN_ERR(svn_dirent_condense_targets(&base_dir, &condensed_targets, targets, 125251881Speter TRUE, pool, pool)); 126251881Speter 127251881Speter if ((! condensed_targets) || (! condensed_targets->nelts)) 128251881Speter { 129251881Speter const char *parent_dir, *base_name; 130251881Speter 131251881Speter SVN_ERR(svn_wc_get_actual_target2(&parent_dir, &base_name, ctx->wc_ctx, 132251881Speter base_dir, pool, pool)); 133251881Speter if (*base_name) 134251881Speter base_dir = apr_pstrdup(pool, parent_dir); 135251881Speter } 136251881Speter 137251881Speter if (opt_state->depth == svn_depth_unknown) 138251881Speter opt_state->depth = svn_depth_infinity; 139251881Speter 140299742Sdim cfg = ctx->config 141299742Sdim ? svn_hash_gets(ctx->config, SVN_CONFIG_CATEGORY_CONFIG) 142299742Sdim : NULL; 143251881Speter if (cfg) 144251881Speter SVN_ERR(svn_config_get_bool(cfg, &no_unlock, 145251881Speter SVN_CONFIG_SECTION_MISCELLANY, 146251881Speter SVN_CONFIG_OPTION_NO_UNLOCK, FALSE)); 147251881Speter 148251881Speter /* We're creating a new log message baton because we can use our base_dir 149251881Speter to store the temp file, instead of the current working directory. The 150251881Speter client might not have write access to their working directory, but they 151251881Speter better have write access to the directory they're committing. */ 152251881Speter SVN_ERR(svn_cl__make_log_msg_baton(&(ctx->log_msg_baton3), 153251881Speter opt_state, base_dir, 154251881Speter ctx->config, pool)); 155251881Speter 156251881Speter /* Copies are done server-side, and cheaply, which means they're 157251881Speter effectively always done with infinite depth. This is a potential 158251881Speter cause of confusion for users trying to commit copied subtrees in 159251881Speter part by restricting the commit's depth. See issues #3699 and #3752. */ 160251881Speter if (opt_state->depth < svn_depth_infinity) 161251881Speter { 162251881Speter cwnb.wrapped_func = ctx->notify_func2; 163251881Speter cwnb.wrapped_baton = ctx->notify_baton2; 164251881Speter cwnb.depth = opt_state->depth; 165251881Speter cwnb.warned = FALSE; 166251881Speter ctx->notify_func2 = copy_warning_notify_func; 167251881Speter ctx->notify_baton2 = &cwnb; 168251881Speter } 169251881Speter 170251881Speter /* Commit. */ 171251881Speter err = svn_client_commit6(targets, 172251881Speter opt_state->depth, 173251881Speter no_unlock, 174251881Speter opt_state->keep_changelists, 175251881Speter TRUE /* commit_as_operations */, 176251881Speter opt_state->include_externals, /* file externals */ 177251881Speter opt_state->include_externals, /* dir externals */ 178251881Speter opt_state->changelists, 179251881Speter opt_state->revprop_table, 180251881Speter (opt_state->quiet 181251881Speter ? NULL : svn_cl__print_commit_info), 182251881Speter NULL, 183251881Speter ctx, 184251881Speter pool); 185251881Speter SVN_ERR(svn_cl__cleanup_log_msg(ctx->log_msg_baton3, err, pool)); 186251881Speter 187251881Speter return SVN_NO_ERROR; 188251881Speter} 189