]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/subversion/subversion/svn/commit-cmd.c
MFC r275385 (by bapt):
[FreeBSD/stable/10.git] / contrib / subversion / subversion / svn / commit-cmd.c
1 /*
2  * commit-cmd.c -- Check changes into the repository.
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 \f
28 /*** Includes. ***/
29
30 #include <apr_general.h>
31
32 #include "svn_hash.h"
33 #include "svn_error.h"
34 #include "svn_error_codes.h"
35 #include "svn_wc.h"
36 #include "svn_client.h"
37 #include "svn_path.h"
38 #include "svn_dirent_uri.h"
39 #include "svn_error.h"
40 #include "svn_config.h"
41 #include "cl.h"
42
43 #include "svn_private_config.h"
44
45
46 \f
47 /* Wrapper notify_func2 function and baton for warning about
48    reduced-depth commits of copied directories.  */
49 struct copy_warning_notify_baton
50 {
51   svn_wc_notify_func2_t wrapped_func;
52   void *wrapped_baton;
53   svn_depth_t depth;
54   svn_boolean_t warned;
55 };
56
57 static void
58 copy_warning_notify_func(void *baton,
59                          const svn_wc_notify_t *notify,
60                          apr_pool_t *pool)
61 {
62   struct copy_warning_notify_baton *b = baton;
63
64   /* Call the wrapped notification system (if any). */
65   if (b->wrapped_func)
66     b->wrapped_func(b->wrapped_baton, notify, pool);
67
68   /* If we're being notified about a copy of a directory when our
69      commit depth is less-than-infinite, and we've not already warned
70      about this situation, then warn about it (and remember that we
71      now have.)  */
72   if ((! b->warned)
73       && (b->depth < svn_depth_infinity)
74       && (notify->kind == svn_node_dir)
75       && ((notify->action == svn_wc_notify_commit_copied) ||
76           (notify->action == svn_wc_notify_commit_copied_replaced)))
77     {
78       svn_error_t *err;
79       err = svn_cmdline_printf(pool,
80                                _("svn: The depth of this commit is '%s', "
81                                  "but copies are always performed "
82                                  "recursively in the repository.\n"),
83                                svn_depth_to_word(b->depth));
84       /* ### FIXME: Try to return this error showhow? */
85       svn_error_clear(err);
86
87       /* We'll only warn once. */
88       b->warned = TRUE;
89     }
90 }
91
92
93
94 \f
95 /* This implements the `svn_opt_subcommand_t' interface. */
96 svn_error_t *
97 svn_cl__commit(apr_getopt_t *os,
98                void *baton,
99                apr_pool_t *pool)
100 {
101   svn_error_t *err;
102   svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
103   svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
104   apr_array_header_t *targets;
105   apr_array_header_t *condensed_targets;
106   const char *base_dir;
107   svn_config_t *cfg;
108   svn_boolean_t no_unlock = FALSE;
109   struct copy_warning_notify_baton cwnb;
110
111   SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
112                                                       opt_state->targets,
113                                                       ctx, FALSE, pool));
114
115   SVN_ERR_W(svn_cl__check_targets_are_local_paths(targets),
116             _("Commit targets must be local paths"));
117
118   /* Add "." if user passed 0 arguments. */
119   svn_opt_push_implicit_dot_target(targets, pool);
120
121   SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, pool));
122
123   /* Condense the targets (like commit does)... */
124   SVN_ERR(svn_dirent_condense_targets(&base_dir, &condensed_targets, targets,
125                                       TRUE, pool, pool));
126
127   if ((! condensed_targets) || (! condensed_targets->nelts))
128     {
129       const char *parent_dir, *base_name;
130
131       SVN_ERR(svn_wc_get_actual_target2(&parent_dir, &base_name, ctx->wc_ctx,
132                                         base_dir, pool, pool));
133       if (*base_name)
134         base_dir = apr_pstrdup(pool, parent_dir);
135     }
136
137   if (opt_state->depth == svn_depth_unknown)
138     opt_state->depth = svn_depth_infinity;
139
140   cfg = ctx->config
141            ? svn_hash_gets(ctx->config, SVN_CONFIG_CATEGORY_CONFIG)
142            : NULL;
143   if (cfg)
144     SVN_ERR(svn_config_get_bool(cfg, &no_unlock,
145                                 SVN_CONFIG_SECTION_MISCELLANY,
146                                 SVN_CONFIG_OPTION_NO_UNLOCK, FALSE));
147
148   /* We're creating a new log message baton because we can use our base_dir
149      to store the temp file, instead of the current working directory.  The
150      client might not have write access to their working directory, but they
151      better have write access to the directory they're committing.  */
152   SVN_ERR(svn_cl__make_log_msg_baton(&(ctx->log_msg_baton3),
153                                      opt_state, base_dir,
154                                      ctx->config, pool));
155
156   /* Copies are done server-side, and cheaply, which means they're
157      effectively always done with infinite depth.  This is a potential
158      cause of confusion for users trying to commit copied subtrees in
159      part by restricting the commit's depth.  See issues #3699 and #3752. */
160   if (opt_state->depth < svn_depth_infinity)
161     {
162       cwnb.wrapped_func = ctx->notify_func2;
163       cwnb.wrapped_baton = ctx->notify_baton2;
164       cwnb.depth = opt_state->depth;
165       cwnb.warned = FALSE;
166       ctx->notify_func2 = copy_warning_notify_func;
167       ctx->notify_baton2 = &cwnb;
168     }
169
170   /* Commit. */
171   err = svn_client_commit6(targets,
172                            opt_state->depth,
173                            no_unlock,
174                            opt_state->keep_changelists,
175                            TRUE /* commit_as_operations */,
176                            opt_state->include_externals, /* file externals */
177                            opt_state->include_externals, /* dir externals */
178                            opt_state->changelists,
179                            opt_state->revprop_table,
180                            (opt_state->quiet
181                             ? NULL : svn_cl__print_commit_info),
182                            NULL,
183                            ctx,
184                            pool);
185   SVN_ERR(svn_cl__cleanup_log_msg(ctx->log_msg_baton3, err, pool));
186
187   return SVN_NO_ERROR;
188 }