aboutsummaryrefslogtreecommitdiff
path: root/subversion/libsvn_client/checkout.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_client/checkout.c')
-rw-r--r--subversion/libsvn_client/checkout.c198
1 files changed, 198 insertions, 0 deletions
diff --git a/subversion/libsvn_client/checkout.c b/subversion/libsvn_client/checkout.c
new file mode 100644
index 000000000000..41be776f16e2
--- /dev/null
+++ b/subversion/libsvn_client/checkout.c
@@ -0,0 +1,198 @@
+/*
+ * checkout.c: wrappers around wc checkout functionality
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ */
+
+/* ==================================================================== */
+
+
+
+/*** Includes. ***/
+
+#include "svn_pools.h"
+#include "svn_wc.h"
+#include "svn_client.h"
+#include "svn_ra.h"
+#include "svn_types.h"
+#include "svn_error.h"
+#include "svn_dirent_uri.h"
+#include "svn_path.h"
+#include "svn_io.h"
+#include "svn_opt.h"
+#include "svn_time.h"
+#include "client.h"
+
+#include "private/svn_wc_private.h"
+
+#include "svn_private_config.h"
+
+
+/*** Public Interfaces. ***/
+
+static svn_error_t *
+initialize_area(const char *local_abspath,
+ const svn_client__pathrev_t *pathrev,
+ svn_depth_t depth,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
+{
+ if (depth == svn_depth_unknown)
+ depth = svn_depth_infinity;
+
+ /* Make the unversioned directory into a versioned one. */
+ SVN_ERR(svn_wc_ensure_adm4(ctx->wc_ctx, local_abspath, pathrev->url,
+ pathrev->repos_root_url, pathrev->repos_uuid,
+ pathrev->rev, depth, pool));
+ return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_client__checkout_internal(svn_revnum_t *result_rev,
+ const char *url,
+ const char *local_abspath,
+ const svn_opt_revision_t *peg_revision,
+ const svn_opt_revision_t *revision,
+ svn_depth_t depth,
+ svn_boolean_t ignore_externals,
+ svn_boolean_t allow_unver_obstructions,
+ svn_boolean_t *timestamp_sleep,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
+{
+ svn_node_kind_t kind;
+ apr_pool_t *session_pool = svn_pool_create(pool);
+ svn_ra_session_t *ra_session;
+ svn_client__pathrev_t *pathrev;
+
+ /* Sanity check. Without these, the checkout is meaningless. */
+ SVN_ERR_ASSERT(local_abspath != NULL);
+ SVN_ERR_ASSERT(svn_uri_is_canonical(url, pool));
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+
+ /* Fulfill the docstring promise of svn_client_checkout: */
+ if ((revision->kind != svn_opt_revision_number)
+ && (revision->kind != svn_opt_revision_date)
+ && (revision->kind != svn_opt_revision_head))
+ return svn_error_create(SVN_ERR_CLIENT_BAD_REVISION, NULL, NULL);
+
+ /* Get the RA connection. */
+ SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &pathrev,
+ url, NULL, peg_revision, revision,
+ ctx, session_pool));
+
+ pathrev = svn_client__pathrev_dup(pathrev, pool);
+ SVN_ERR(svn_ra_check_path(ra_session, "", pathrev->rev, &kind, pool));
+
+ svn_pool_destroy(session_pool);
+
+ if (kind == svn_node_none)
+ return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
+ _("URL '%s' doesn't exist"), pathrev->url);
+ else if (kind == svn_node_file)
+ return svn_error_createf
+ (SVN_ERR_UNSUPPORTED_FEATURE , NULL,
+ _("URL '%s' refers to a file, not a directory"), pathrev->url);
+
+ SVN_ERR(svn_io_check_path(local_abspath, &kind, pool));
+
+ if (kind == svn_node_none)
+ {
+ /* Bootstrap: create an incomplete working-copy root dir. Its
+ entries file should only have an entry for THIS_DIR with a
+ URL, revnum, and an 'incomplete' flag. */
+ SVN_ERR(svn_io_make_dir_recursively(local_abspath, pool));
+ SVN_ERR(initialize_area(local_abspath, pathrev, depth, ctx, pool));
+ }
+ else if (kind == svn_node_dir)
+ {
+ int wc_format;
+ const char *entry_url;
+
+ SVN_ERR(svn_wc_check_wc2(&wc_format, ctx->wc_ctx, local_abspath, pool));
+ if (! wc_format)
+ {
+ SVN_ERR(initialize_area(local_abspath, pathrev, depth, ctx, pool));
+ }
+ else
+ {
+ /* Get PATH's URL. */
+ SVN_ERR(svn_wc__node_get_url(&entry_url, ctx->wc_ctx, local_abspath,
+ pool, pool));
+
+ /* If PATH's existing URL matches the incoming one, then
+ just update. This allows 'svn co' to restart an
+ interrupted checkout. Otherwise bail out. */
+ if (strcmp(entry_url, pathrev->url) != 0)
+ return svn_error_createf(
+ SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
+ _("'%s' is already a working copy for a"
+ " different URL"),
+ svn_dirent_local_style(local_abspath, pool));
+ }
+ }
+ else
+ {
+ return svn_error_createf(SVN_ERR_WC_NODE_KIND_CHANGE, NULL,
+ _("'%s' already exists and is not a directory"),
+ svn_dirent_local_style(local_abspath, pool));
+ }
+
+ /* Have update fix the incompleteness. */
+ SVN_ERR(svn_client__update_internal(result_rev, local_abspath,
+ revision, depth, TRUE,
+ ignore_externals,
+ allow_unver_obstructions,
+ TRUE /* adds_as_modification */,
+ FALSE, FALSE,
+ timestamp_sleep, ctx, pool));
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_checkout3(svn_revnum_t *result_rev,
+ const char *URL,
+ const char *path,
+ const svn_opt_revision_t *peg_revision,
+ const svn_opt_revision_t *revision,
+ svn_depth_t depth,
+ svn_boolean_t ignore_externals,
+ svn_boolean_t allow_unver_obstructions,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
+{
+ const char *local_abspath;
+ svn_error_t *err;
+ svn_boolean_t sleep_here = FALSE;
+
+ SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
+
+ err = svn_client__checkout_internal(result_rev, URL, local_abspath,
+ peg_revision, revision, depth,
+ ignore_externals,
+ allow_unver_obstructions, &sleep_here,
+ ctx, pool);
+ if (sleep_here)
+ svn_io_sleep_for_timestamps(local_abspath, pool);
+
+ return svn_error_trace(err);
+}