2 * checkout.c: wrappers around wc checkout functionality
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"
32 #include "svn_client.h"
34 #include "svn_types.h"
35 #include "svn_error.h"
36 #include "svn_dirent_uri.h"
43 #include "private/svn_wc_private.h"
45 #include "svn_private_config.h"
48 /*** Public Interfaces. ***/
51 initialize_area(const char *local_abspath,
52 const svn_client__pathrev_t *pathrev,
54 svn_client_ctx_t *ctx,
57 if (depth == svn_depth_unknown)
58 depth = svn_depth_infinity;
60 /* Make the unversioned directory into a versioned one. */
61 SVN_ERR(svn_wc_ensure_adm4(ctx->wc_ctx, local_abspath, pathrev->url,
62 pathrev->repos_root_url, pathrev->repos_uuid,
63 pathrev->rev, depth, pool));
69 svn_client__checkout_internal(svn_revnum_t *result_rev,
71 const char *local_abspath,
72 const svn_opt_revision_t *peg_revision,
73 const svn_opt_revision_t *revision,
75 svn_boolean_t ignore_externals,
76 svn_boolean_t allow_unver_obstructions,
77 svn_boolean_t *timestamp_sleep,
78 svn_client_ctx_t *ctx,
82 apr_pool_t *session_pool = svn_pool_create(pool);
83 svn_ra_session_t *ra_session;
84 svn_client__pathrev_t *pathrev;
86 /* Sanity check. Without these, the checkout is meaningless. */
87 SVN_ERR_ASSERT(local_abspath != NULL);
88 SVN_ERR_ASSERT(svn_uri_is_canonical(url, pool));
89 SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
91 /* Fulfill the docstring promise of svn_client_checkout: */
92 if ((revision->kind != svn_opt_revision_number)
93 && (revision->kind != svn_opt_revision_date)
94 && (revision->kind != svn_opt_revision_head))
95 return svn_error_create(SVN_ERR_CLIENT_BAD_REVISION, NULL, NULL);
97 /* Get the RA connection. */
98 SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &pathrev,
99 url, NULL, peg_revision, revision,
102 pathrev = svn_client__pathrev_dup(pathrev, pool);
103 SVN_ERR(svn_ra_check_path(ra_session, "", pathrev->rev, &kind, pool));
105 svn_pool_destroy(session_pool);
107 if (kind == svn_node_none)
108 return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
109 _("URL '%s' doesn't exist"), pathrev->url);
110 else if (kind == svn_node_file)
111 return svn_error_createf
112 (SVN_ERR_UNSUPPORTED_FEATURE , NULL,
113 _("URL '%s' refers to a file, not a directory"), pathrev->url);
115 SVN_ERR(svn_io_check_path(local_abspath, &kind, pool));
117 if (kind == svn_node_none)
119 /* Bootstrap: create an incomplete working-copy root dir. Its
120 entries file should only have an entry for THIS_DIR with a
121 URL, revnum, and an 'incomplete' flag. */
122 SVN_ERR(svn_io_make_dir_recursively(local_abspath, pool));
123 SVN_ERR(initialize_area(local_abspath, pathrev, depth, ctx, pool));
125 else if (kind == svn_node_dir)
128 const char *entry_url;
130 SVN_ERR(svn_wc_check_wc2(&wc_format, ctx->wc_ctx, local_abspath, pool));
133 SVN_ERR(initialize_area(local_abspath, pathrev, depth, ctx, pool));
137 /* Get PATH's URL. */
138 SVN_ERR(svn_wc__node_get_url(&entry_url, ctx->wc_ctx, local_abspath,
141 /* If PATH's existing URL matches the incoming one, then
142 just update. This allows 'svn co' to restart an
143 interrupted checkout. Otherwise bail out. */
144 if (strcmp(entry_url, pathrev->url) != 0)
145 return svn_error_createf(
146 SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
147 _("'%s' is already a working copy for a"
149 svn_dirent_local_style(local_abspath, pool));
154 return svn_error_createf(SVN_ERR_WC_NODE_KIND_CHANGE, NULL,
155 _("'%s' already exists and is not a directory"),
156 svn_dirent_local_style(local_abspath, pool));
159 /* Have update fix the incompleteness. */
160 SVN_ERR(svn_client__update_internal(result_rev, local_abspath,
161 revision, depth, TRUE,
163 allow_unver_obstructions,
164 TRUE /* adds_as_modification */,
166 timestamp_sleep, ctx, pool));
172 svn_client_checkout3(svn_revnum_t *result_rev,
175 const svn_opt_revision_t *peg_revision,
176 const svn_opt_revision_t *revision,
178 svn_boolean_t ignore_externals,
179 svn_boolean_t allow_unver_obstructions,
180 svn_client_ctx_t *ctx,
183 const char *local_abspath;
185 svn_boolean_t sleep_here = FALSE;
187 SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
189 err = svn_client__checkout_internal(result_rev, URL, local_abspath,
190 peg_revision, revision, depth,
192 allow_unver_obstructions, &sleep_here,
195 svn_io_sleep_for_timestamps(local_abspath, pool);
197 return svn_error_trace(err);