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 140251881Speter cfg = svn_hash_gets(ctx->config, SVN_CONFIG_CATEGORY_CONFIG); 141251881Speter if (cfg) 142251881Speter SVN_ERR(svn_config_get_bool(cfg, &no_unlock, 143251881Speter SVN_CONFIG_SECTION_MISCELLANY, 144251881Speter SVN_CONFIG_OPTION_NO_UNLOCK, FALSE)); 145251881Speter 146251881Speter /* We're creating a new log message baton because we can use our base_dir 147251881Speter to store the temp file, instead of the current working directory. The 148251881Speter client might not have write access to their working directory, but they 149251881Speter better have write access to the directory they're committing. */ 150251881Speter SVN_ERR(svn_cl__make_log_msg_baton(&(ctx->log_msg_baton3), 151251881Speter opt_state, base_dir, 152251881Speter ctx->config, pool)); 153251881Speter 154251881Speter /* Copies are done server-side, and cheaply, which means they're 155251881Speter effectively always done with infinite depth. This is a potential 156251881Speter cause of confusion for users trying to commit copied subtrees in 157251881Speter part by restricting the commit's depth. See issues #3699 and #3752. */ 158251881Speter if (opt_state->depth < svn_depth_infinity) 159251881Speter { 160251881Speter cwnb.wrapped_func = ctx->notify_func2; 161251881Speter cwnb.wrapped_baton = ctx->notify_baton2; 162251881Speter cwnb.depth = opt_state->depth; 163251881Speter cwnb.warned = FALSE; 164251881Speter ctx->notify_func2 = copy_warning_notify_func; 165251881Speter ctx->notify_baton2 = &cwnb; 166251881Speter } 167251881Speter 168251881Speter /* Commit. */ 169251881Speter err = svn_client_commit6(targets, 170251881Speter opt_state->depth, 171251881Speter no_unlock, 172251881Speter opt_state->keep_changelists, 173251881Speter TRUE /* commit_as_operations */, 174251881Speter opt_state->include_externals, /* file externals */ 175251881Speter opt_state->include_externals, /* dir externals */ 176251881Speter opt_state->changelists, 177251881Speter opt_state->revprop_table, 178251881Speter (opt_state->quiet 179251881Speter ? NULL : svn_cl__print_commit_info), 180251881Speter NULL, 181251881Speter ctx, 182251881Speter pool); 183251881Speter SVN_ERR(svn_cl__cleanup_log_msg(ctx->log_msg_baton3, err, pool)); 184251881Speter 185251881Speter return SVN_NO_ERROR; 186251881Speter} 187