2 * update-cmd.c -- Bring work tree in sync with repository
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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
21 * ====================================================================
24 /* ==================================================================== */
30 #include "svn_pools.h"
31 #include "svn_client.h"
33 #include "svn_error_codes.h"
34 #include "svn_error.h"
37 #include "svn_private_config.h"
42 /* Print an update summary when there's more than one target to report
43 about. Each (const char *) path in TARGETS is an absolute or relative
44 dirent, and each (svn_revnum_t) entry in RESULT_REVS is the corresponding
45 updated revision, or SVN_INVALID_REVNUM if not a valid target. */
47 print_update_summary(apr_array_header_t *targets,
48 apr_array_header_t *result_revs,
49 apr_pool_t *scratch_pool)
52 const char *path_prefix;
54 svn_boolean_t printed_header = FALSE;
56 if (targets->nelts < 2)
59 SVN_ERR(svn_dirent_get_absolute(&path_prefix, "", scratch_pool));
61 iterpool = svn_pool_create(scratch_pool);
63 for (i = 0; i < targets->nelts; i++)
65 const char *path = APR_ARRAY_IDX(targets, i, const char *);
66 svn_revnum_t rev = SVN_INVALID_REVNUM;
68 svn_pool_clear(iterpool);
70 /* PATH shouldn't be a URL. */
71 SVN_ERR_ASSERT(! svn_path_is_url(path));
73 /* Grab the result revision from the corresponding slot in our
75 if (i < result_revs->nelts)
76 rev = APR_ARRAY_IDX(result_revs, i, svn_revnum_t);
78 /* No result rev? We must have skipped this path. At any rate,
79 nothing to report here. */
80 if (! SVN_IS_VALID_REVNUM(rev))
83 /* Convert to an absolute path if it's not already. */
84 if (! svn_dirent_is_absolute(path))
85 SVN_ERR(svn_dirent_get_absolute(&path, path, iterpool));
87 /* Print an update summary for this target, removing the current
88 working directory prefix from PATH (if PATH is at or under
89 $CWD), and converting the path to local style for display. */
92 SVN_ERR(svn_cmdline_printf(scratch_pool,
93 _("Summary of updates:\n")));
94 printed_header = TRUE;
97 SVN_ERR(svn_cmdline_printf(iterpool, _(" Updated '%s' to r%ld.\n"),
98 svn_cl__local_style_skip_ancestor(
99 path_prefix, path, iterpool),
103 svn_pool_destroy(iterpool);
107 /* This implements the `svn_opt_subcommand_t' interface. */
109 svn_cl__update(apr_getopt_t *os,
111 apr_pool_t *scratch_pool)
113 svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
114 svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
115 apr_array_header_t *targets;
117 svn_boolean_t depth_is_sticky;
118 struct svn_cl__check_externals_failed_notify_baton nwb;
119 apr_array_header_t *result_revs;
120 svn_error_t *err = SVN_NO_ERROR;
121 svn_error_t *externals_err = SVN_NO_ERROR;
123 SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
128 /* Add "." if user passed 0 arguments */
129 svn_opt_push_implicit_dot_target(targets, scratch_pool);
131 SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, scratch_pool));
133 SVN_ERR(svn_cl__check_targets_are_local_paths(targets));
135 /* If using changelists, convert targets into a set of paths that
136 match the specified changelist(s). */
137 if (opt_state->changelists)
139 svn_depth_t cl_depth = opt_state->depth;
140 if (cl_depth == svn_depth_unknown)
141 cl_depth = svn_depth_infinity;
142 SVN_ERR(svn_cl__changelist_paths(&targets,
143 opt_state->changelists, targets,
144 cl_depth, ctx, scratch_pool,
148 /* Deal with depthstuffs. */
149 if (opt_state->set_depth != svn_depth_unknown)
151 depth = opt_state->set_depth;
152 depth_is_sticky = TRUE;
156 depth = opt_state->depth;
157 depth_is_sticky = FALSE;
160 nwb.wrapped_func = ctx->notify_func2;
161 nwb.wrapped_baton = ctx->notify_baton2;
162 nwb.had_externals_error = FALSE;
163 ctx->notify_func2 = svn_cl__check_externals_failed_notify_wrapper;
164 ctx->notify_baton2 = &nwb;
166 SVN_ERR(svn_client_update4(&result_revs, targets,
167 &(opt_state->start_revision),
168 depth, depth_is_sticky,
169 opt_state->ignore_externals,
170 opt_state->force, TRUE /* adds_as_modification */,
174 if (nwb.had_externals_error)
175 externals_err = svn_error_create(SVN_ERR_CL_ERROR_PROCESSING_EXTERNALS,
177 _("Failure occurred processing one or "
178 "more externals definitions"));
180 if (! opt_state->quiet)
182 err = print_update_summary(targets, result_revs, scratch_pool);
184 return svn_error_compose_create(externals_err, err);
186 /* ### Layering problem: This call assumes that the baton we're
187 * passing is the one that was originally provided by
188 * svn_cl__get_notifier(), but that isn't promised. */
189 err = svn_cl__notifier_print_conflict_stats(nwb.wrapped_baton,
192 return svn_error_compose_create(externals_err, err);
195 return svn_error_compose_create(externals_err, err);