⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 copy.c

📁 subversion-1.4.3-1.tar.gz 配置svn的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * copy.c:  wc 'copy' functionality. * * ==================================================================== * Copyright (c) 2000-2006 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 <string.h>#include "svn_wc.h"#include "svn_pools.h"#include "svn_error.h"#include "svn_path.h"#include "wc.h"#include "adm_files.h"#include "entries.h"#include "props.h"#include "translate.h"#include "svn_private_config.h"/*** Code. ***//* This function effectively creates and schedules a file for   addition, but does extra administrative things to allow it to   function as a 'copy'.   ASSUMPTIONS:     - src_path points to a file under version control     - dst_parent points to a dir under version control, in the same                  working copy.     - dst_basename will be the 'new' name of the copied file in dst_parent */static svn_error_t *copy_file_administratively(const char *src_path,                            svn_wc_adm_access_t *src_access,                           svn_wc_adm_access_t *dst_parent,                           const char *dst_basename,                           svn_wc_notify_func2_t notify_copied,                           void *notify_baton,                           apr_pool_t *pool){  svn_node_kind_t dst_kind;  const svn_wc_entry_t *src_entry, *dst_entry;  /* The 'dst_path' is simply dst_parent/dst_basename */  const char *dst_path    = svn_path_join(svn_wc_adm_access_path(dst_parent), dst_basename, pool);  /* Discover the paths to the two text-base files */  const char *src_txtb = svn_wc__text_base_path(src_path, FALSE, pool);  const char *tmp_txtb = svn_wc__text_base_path(dst_path, TRUE, pool);  /* Sanity check:  if dst file exists already, don't allow overwrite. */  SVN_ERR(svn_io_check_path(dst_path, &dst_kind, pool));  if (dst_kind != svn_node_none)    return svn_error_createf(SVN_ERR_ENTRY_EXISTS, NULL,                             _("'%s' already exists and is in the way"),                             svn_path_local_style(dst_path, pool));  /* Even if DST_PATH doesn't exist it may still be a versioned file; it     may be scheduled for deletion, or the user may simply have removed the     working copy.  Since we are going to write to DST_PATH text-base and     prop-base we need to detect such cases and abort. */  SVN_ERR(svn_wc_entry(&dst_entry, dst_path, dst_parent, FALSE, pool));  if (dst_entry && dst_entry->kind == svn_node_file)    {      if (dst_entry->schedule != svn_wc_schedule_delete)        return svn_error_createf(SVN_ERR_ENTRY_EXISTS, NULL,                                 _("There is already a versioned item '%s'"),                                 svn_path_local_style(dst_path, pool));    }  /* Sanity check:  you cannot make a copy of something that's not     in the repository.  See comment at the bottom of this file for an     explanation. */  SVN_ERR(svn_wc_entry(&src_entry, src_path, src_access, FALSE, pool));  if (! src_entry)    return svn_error_createf       (SVN_ERR_UNVERSIONED_RESOURCE, NULL,       _("Cannot copy or move '%s': it's not under version control"),       svn_path_local_style(src_path, pool));  if ((src_entry->schedule == svn_wc_schedule_add)      || (! src_entry->url)      || (src_entry->copied))    return svn_error_createf       (SVN_ERR_UNSUPPORTED_FEATURE, NULL,       _("Cannot copy or move '%s': it's not in the repository yet; "         "try committing first"),       svn_path_local_style(src_path, pool));  /* Schedule the new file for addition in its parent, WITH HISTORY. */  {    char *copyfrom_url;    const char *tmp_wc_text;    svn_revnum_t copyfrom_rev;    apr_hash_t *props, *base_props;    SVN_ERR(svn_wc_get_ancestry(&copyfrom_url, &copyfrom_rev,                                src_path, src_access, pool));    /* Load source base and working props. */    SVN_ERR(svn_wc__load_props(&base_props, &props, src_access,                               src_entry->name, pool));    /* Copy pristine text-base to temporary location. */    SVN_ERR(svn_io_copy_file(src_txtb, tmp_txtb, TRUE, pool));    /* Copy working copy file to temporary location */    {      svn_boolean_t special;      SVN_ERR(svn_wc_create_tmp_file2(NULL, &tmp_wc_text,                                      svn_wc_adm_access_path(dst_parent),                                      svn_io_file_del_none, pool));      SVN_ERR(svn_wc__get_special(&special, src_path, src_access, pool));      if (special)        {          SVN_ERR(svn_subst_copy_and_translate3(src_path, tmp_wc_text,                                                NULL, FALSE, NULL,                                                FALSE, special, pool));        }      else        SVN_ERR(svn_io_copy_file(src_path, tmp_wc_text, TRUE, pool));    }    SVN_ERR(svn_wc_add_repos_file2(dst_path, dst_parent,                                   tmp_txtb, tmp_wc_text,                                   base_props, props,                                   copyfrom_url, copyfrom_rev, pool));  }  /* Report the addition to the caller. */  if (notify_copied != NULL)    {      svn_wc_notify_t *notify = svn_wc_create_notify(dst_path,                                                     svn_wc_notify_add,                                                     pool);      notify->kind = svn_node_file;      (*notify_copied)(notify_baton, notify, pool);    }  return SVN_NO_ERROR;}/* Recursively crawl over a directory PATH and do a number of things:     - Remove lock tokens     - Remove WC props     - Convert deleted items to schedule-delete items     - Set .svn directories to be hidden*/static svn_error_t *post_copy_cleanup(svn_wc_adm_access_t *adm_access,                  apr_pool_t *pool){  apr_pool_t *subpool = svn_pool_create(pool);  apr_hash_t *entries;  apr_hash_index_t *hi;  svn_wc_entry_t *entry;  const char *path = svn_wc_adm_access_path(adm_access);    /* Remove wcprops. */  SVN_ERR(svn_wc__remove_wcprops(adm_access, NULL, FALSE, pool));  /* Read this directory's entries file. */  SVN_ERR(svn_wc_entries_read(&entries, adm_access, FALSE, pool));  /* Because svn_io_copy_dir_recursively() doesn't copy directory     permissions, we'll patch up our tree's .svn subdirs to be     hidden. */#ifdef APR_FILE_ATTR_HIDDEN  {    const char *adm_dir = svn_wc__adm_path(path, FALSE, pool, NULL);    const char *path_apr;    apr_status_t status;    SVN_ERR(svn_path_cstring_from_utf8(&path_apr, adm_dir, pool));    status = apr_file_attrs_set(path_apr,                                APR_FILE_ATTR_HIDDEN,                                APR_FILE_ATTR_HIDDEN,                                pool);    if (status)      return svn_error_wrap_apr(status, _("Can't hide directory '%s'"),                                svn_path_local_style(adm_dir, pool));  }#endif  /* Loop over all children, removing lock tokens and recursing into     directories. */  SVN_ERR(svn_wc_entries_read(&entries, adm_access, TRUE, pool));  for (hi = apr_hash_first(pool, entries); hi; hi = apr_hash_next(hi))    {      const void *key;      void *val;      svn_node_kind_t kind;      svn_boolean_t deleted = FALSE;      apr_uint32_t flags = SVN_WC__ENTRY_MODIFY_FORCE;      svn_pool_clear(subpool);      apr_hash_this(hi, &key, NULL, &val);      entry = val;      kind = entry->kind;      deleted = entry->deleted;      /* Convert deleted="true" into schedule="delete" for all         children (and grandchildren, if RECURSE is set) of the path         represented by ADM_ACCESS.  The result of this is that when         the copy is committed the items in question get deleted and         the result is a directory in the repository that matches the         original source directory for copy.  If this were not done         the deleted="true" items would simply vanish from the entries         file as the copy is added to the working copy.  The new         schedule="delete" files do not have a text-base and so their         scheduled deletion cannot be reverted.  For directories a         placeholder with an svn_node_kind_t of svn_node_file and         schedule="delete" is used to avoid the problems associated         with creating a directory.  See Issue #2101 for details. */      if (entry->deleted)        {          entry->schedule = svn_wc_schedule_delete;          flags |= SVN_WC__ENTRY_MODIFY_SCHEDULE;                    entry->deleted = FALSE;          flags |= SVN_WC__ENTRY_MODIFY_DELETED;          if (entry->kind == svn_node_dir)            {              /* ### WARNING: Very dodgy stuff here! ###              Directories are a problem since a schedule delete directory              needs an admin directory to be present.  It's possible to              create a dummy admin directory and that sort of works, it's              good enough if the user commits the copy.  Where it falls              down is if the user *reverts* the dummy directory since the              now schedule normal, copied, directory doesn't have the              correct contents.              The dodgy solution is to cheat and use a schedule delete file              as a placeholder!  This is sufficient to provide a delete

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -