]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/subversion/subversion/svn/commit-cmd.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.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 = svn_hash_gets(ctx->config, SVN_CONFIG_CATEGORY_CONFIG);
141   if (cfg)
142     SVN_ERR(svn_config_get_bool(cfg, &no_unlock,
143                                 SVN_CONFIG_SECTION_MISCELLANY,
144                                 SVN_CONFIG_OPTION_NO_UNLOCK, FALSE));
145
146   /* We're creating a new log message baton because we can use our base_dir
147      to store the temp file, instead of the current working directory.  The
148      client might not have write access to their working directory, but they
149      better have write access to the directory they're committing.  */
150   SVN_ERR(svn_cl__make_log_msg_baton(&(ctx->log_msg_baton3),
151                                      opt_state, base_dir,
152                                      ctx->config, pool));
153
154   /* Copies are done server-side, and cheaply, which means they're
155      effectively always done with infinite depth.  This is a potential
156      cause of confusion for users trying to commit copied subtrees in
157      part by restricting the commit's depth.  See issues #3699 and #3752. */
158   if (opt_state->depth < svn_depth_infinity)
159     {
160       cwnb.wrapped_func = ctx->notify_func2;
161       cwnb.wrapped_baton = ctx->notify_baton2;
162       cwnb.depth = opt_state->depth;
163       cwnb.warned = FALSE;
164       ctx->notify_func2 = copy_warning_notify_func;
165       ctx->notify_baton2 = &cwnb;
166     }
167
168   /* Commit. */
169   err = svn_client_commit6(targets,
170                            opt_state->depth,
171                            no_unlock,
172                            opt_state->keep_changelists,
173                            TRUE /* commit_as_operations */,
174                            opt_state->include_externals, /* file externals */
175                            opt_state->include_externals, /* dir externals */
176                            opt_state->changelists,
177                            opt_state->revprop_table,
178                            (opt_state->quiet
179                             ? NULL : svn_cl__print_commit_info),
180                            NULL,
181                            ctx,
182                            pool);
183   SVN_ERR(svn_cl__cleanup_log_msg(ctx->log_msg_baton3, err, pool));
184
185   return SVN_NO_ERROR;
186 }