📄 checkout.c
字号:
/*
* checkout.c: wrappers around wc checkout functionality
*
* ====================================================================
* Copyright (c) 2000-2004 CollabNet. All rights reserved.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://subversion.tigris.org/license-1.html.
* If newer versions of this license are posted there, you may use a
* newer version instead, at your option.
*
* This software consists of voluntary contributions made by many
* individuals. For exact contribution history, see the revision
* history and logs, available at http://subversion.tigris.org/.
* ====================================================================
*/
/* ==================================================================== */
/*** Includes. ***/
#include <assert.h>
#include "svn_wc.h"
#include "svn_pools.h"
#include "svn_delta.h"
#include "svn_client.h"
#include "svn_ra.h"
#include "svn_string.h"
#include "svn_types.h"
#include "svn_error.h"
#include "svn_path.h"
#include "svn_io.h"
#include "svn_opt.h"
#include "svn_time.h"
#include "client.h"
#include "svn_private_config.h"
/*** Public Interfaces. ***/
svn_error_t *
svn_client__checkout_internal (svn_revnum_t *result_rev,
const char *URL,
const char *path,
const svn_opt_revision_t *revision,
svn_boolean_t recurse,
svn_boolean_t *timestamp_sleep,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
svn_wc_traversal_info_t *traversal_info = svn_wc_init_traversal_info (pool);
svn_error_t *err = NULL;
svn_revnum_t revnum;
svn_boolean_t sleep_here = FALSE;
svn_boolean_t *use_sleep = timestamp_sleep ? timestamp_sleep : &sleep_here;
/* Sanity check. Without these, the checkout is meaningless. */
assert (path != NULL);
assert (URL != NULL);
/* 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);
/* Canonicalize the URL. */
URL = svn_path_canonicalize (URL, pool);
{
void *ra_baton, *session;
svn_ra_plugin_t *ra_lib;
svn_node_kind_t kind;
const char *uuid;
/* Get the RA vtable that matches URL. */
SVN_ERR (svn_ra_init_ra_libs (&ra_baton, pool));
SVN_ERR (svn_ra_get_ra_library (&ra_lib, ra_baton, URL, pool));
/* Open an RA session to URL. Note that we do not have an admin area
for storing temp files. */
SVN_ERR (svn_client__open_ra_session (&session, ra_lib, URL, NULL,
NULL, NULL, FALSE, TRUE,
ctx, pool));
SVN_ERR (svn_client__get_revision_number
(&revnum, ra_lib, session, revision, path, pool));
SVN_ERR (ra_lib->check_path (session, "", revnum, &kind, pool));
if (kind == svn_node_none)
return svn_error_createf (SVN_ERR_RA_ILLEGAL_URL, NULL,
_("URL '%s' doesn't exist"), 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"), URL);
/* Get the repos UUID. */
SVN_ERR (ra_lib->get_uuid (session, &uuid, pool));
SVN_ERR (svn_io_check_path (path, &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 (path, pool));
SVN_ERR (svn_wc_ensure_adm (path, uuid, URL, revnum, pool));
/* Have update fix the incompleteness. */
err = svn_client__update_internal (result_rev, path, revision,
recurse, use_sleep, ctx, pool);
}
else if (kind == svn_node_dir)
{
int wc_format;
const svn_wc_entry_t *entry;
svn_wc_adm_access_t *adm_access;
SVN_ERR (svn_wc_check_wc (path, &wc_format, pool));
if (! wc_format)
{
/* Make the unversioned directory into a versioned one. */
SVN_ERR (svn_wc_ensure_adm (path, uuid, URL, revnum, pool));
err = svn_client__update_internal (result_rev, path, revision,
recurse, use_sleep, ctx, pool);
goto done;
}
/* Get PATH's entry. */
SVN_ERR (svn_wc_adm_open2 (&adm_access, NULL, path,
FALSE, 0, pool));
SVN_ERR (svn_wc_entry (&entry, path, adm_access, FALSE, pool));
SVN_ERR (svn_wc_adm_close (adm_access));
/* If PATH's existing URL matches the incoming one, then
just update. This allows 'svn co' to restart an
interrupted checkout. */
if (entry->url && (strcmp (entry->url, URL) == 0))
{
err = svn_client__update_internal (result_rev, path, revision,
recurse, use_sleep, ctx, pool);
}
else
{
const char *errmsg;
errmsg = apr_psprintf
(pool,
_("'%s' is already a working copy for a different URL"), path);
if (entry->incomplete)
errmsg = apr_pstrcat
(pool, errmsg, _("; run 'svn update' to complete it."), NULL);
return svn_error_create (SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
errmsg);
}
}
else
{
return svn_error_createf (SVN_ERR_WC_NODE_KIND_CHANGE, NULL,
_("'%s' is already a file/something else"),
path);
}
done:
if (err)
{
/* Don't rely on the error handling to handle the sleep later, do
it now */
svn_sleep_for_timestamps ();
return err;
}
*use_sleep = TRUE;
}
/* We handle externals after the initial checkout is complete, so
that fetching external items (and any errors therefrom) doesn't
delay the primary checkout.
### Should we really do externals if recurse is false?
*/
SVN_ERR (svn_client__handle_externals (traversal_info, FALSE, use_sleep,
ctx, pool));
if (sleep_here)
svn_sleep_for_timestamps ();
return SVN_NO_ERROR;
}
svn_error_t *
svn_client_checkout (svn_revnum_t *result_rev,
const char *URL,
const char *path,
const svn_opt_revision_t *revision,
svn_boolean_t recurse,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
return svn_client__checkout_internal (result_rev, URL, path,
revision, recurse, NULL, ctx, pool);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -