export.c

来自「subversion-1.4.3-1.tar.gz 配置svn的源码」· C语言 代码 · 共 958 行 · 第 1/3 页

C
958
字号
/* * export.c:  export a tree. * * ==================================================================== * 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 <apr_file_io.h>#include <apr_md5.h>#include "svn_types.h"#include "svn_wc.h"#include "svn_client.h"#include "svn_string.h"#include "svn_error.h"#include "svn_path.h"#include "svn_pools.h"#include "svn_subst.h"#include "svn_time.h"#include "svn_md5.h"#include "svn_props.h"#include "client.h"#include "svn_private_config.h"/*** Code. ***//* Add EXTERNALS_PROP_VAL for the export destination path PATH to   TRAVERSAL_INFO.  */static voidadd_externals(apr_hash_t *externals,              const char *path,              const svn_string_t *externals_prop_val){  apr_pool_t *pool = apr_hash_pool_get(externals);  if (! externals_prop_val)    return;  apr_hash_set(externals,                apr_pstrdup(pool, path),                APR_HASH_KEY_STRING,                apr_pstrmemdup(pool, externals_prop_val->data,                              externals_prop_val->len));}/* Helper function that gets the eol style and optionally overrides the   EOL marker for files marked as native with the EOL marker matching   the string specified in requested_value which is of the same format   as the svn:eol-style property values. */static svn_error_t *get_eol_style(svn_subst_eol_style_t *style,              const char **eol,              const char *value,              const char *requested_value){  svn_subst_eol_style_from_value(style, eol, value);  if (requested_value && *style == svn_subst_eol_style_native)    {      svn_subst_eol_style_t requested_style;      const char *requested_eol;            svn_subst_eol_style_from_value(&requested_style, &requested_eol,                                     requested_value);      if (requested_style == svn_subst_eol_style_fixed)        *eol = requested_eol;      else        return svn_error_createf(SVN_ERR_IO_UNKNOWN_EOL, NULL,                                 _("'%s' is not a valid EOL value"),                                 requested_value);    }  return SVN_NO_ERROR;}static svn_error_t *copy_one_versioned_file(const char *from,                        const char *to,                        svn_wc_adm_access_t *adm_access,                        svn_opt_revision_t *revision,                        const char *native_eol,                        apr_pool_t *pool){  const svn_wc_entry_t *entry;  apr_hash_t *kw = NULL;  svn_subst_eol_style_t style;  apr_hash_t *props;  const char *base;  svn_string_t *eol_style, *keywords, *executable, *externals, *special;  const char *eol = NULL;  svn_boolean_t local_mod = FALSE;  apr_time_t tm;            SVN_ERR(svn_wc_entry(&entry, from, adm_access, FALSE, pool));  /* Only export 'added' files when the revision is WORKING.     Otherwise, skip the 'added' files, since they didn't exist     in the BASE revision and don't have an associated text-base.     Don't export 'deleted' files and directories unless it's a     revision other than WORKING.  These files and directories     don't really exist in WORKING. */  if ((revision->kind != svn_opt_revision_working &&       entry->schedule == svn_wc_schedule_add) ||      (revision->kind == svn_opt_revision_working &&       entry->schedule == svn_wc_schedule_delete))    return SVN_NO_ERROR;  if (revision->kind != svn_opt_revision_working)    {      SVN_ERR(svn_wc_get_pristine_copy_path(from, &base,                                             pool));      SVN_ERR(svn_wc_get_prop_diffs(NULL, &props, from,                                     adm_access, pool));    }  else    {      svn_wc_status2_t *status;            base = from;      SVN_ERR(svn_wc_prop_list(&props, from,                                adm_access, pool));      SVN_ERR(svn_wc_status2(&status, from,                              adm_access, pool));      if (status->text_status != svn_wc_status_normal)        local_mod = TRUE;    }    eol_style = apr_hash_get(props, SVN_PROP_EOL_STYLE,                           APR_HASH_KEY_STRING);  keywords = apr_hash_get(props, SVN_PROP_KEYWORDS,                          APR_HASH_KEY_STRING);  executable = apr_hash_get(props, SVN_PROP_EXECUTABLE,                            APR_HASH_KEY_STRING);  externals = apr_hash_get(props, SVN_PROP_EXTERNALS,                           APR_HASH_KEY_STRING);  special = apr_hash_get(props, SVN_PROP_SPECIAL,                         APR_HASH_KEY_STRING);    if (eol_style)    SVN_ERR(get_eol_style(&style, &eol, eol_style->data, native_eol));    if (local_mod && (! special))    {      /* Use the modified time from the working copy of         the file */      SVN_ERR(svn_io_file_affected_time(&tm, from, pool));    }  else    {      tm = entry->cmt_date;    }  if (keywords)    {      const char *fmt;      const char *author;      if (local_mod)        {          /* For locally modified files, we'll append an 'M'             to the revision number, and set the author to             "(local)" since we can't always determine the             current user's username */          fmt = "%ldM";          author = _("(local)");        }      else        {          fmt = "%ld";          author = entry->cmt_author;        }            SVN_ERR(svn_subst_build_keywords2              (&kw, keywords->data,                apr_psprintf(pool, fmt, entry->cmt_rev),               entry->url, tm, author, pool));    }  SVN_ERR(svn_subst_copy_and_translate3(base, to, eol, FALSE,                                        kw, TRUE,                                        special ? TRUE : FALSE,                                        pool));  if (executable)    SVN_ERR(svn_io_set_file_executable(to, TRUE,                                        FALSE, pool));  if (! special)    SVN_ERR(svn_io_set_file_affected_time(tm, to, pool));  return SVN_NO_ERROR;}static svn_error_t *copy_versioned_files(const char *from,                     const char *to,                     svn_opt_revision_t *revision,                     svn_boolean_t force,                     svn_boolean_t recurse,                     const char *native_eol,                     svn_client_ctx_t *ctx,                     apr_pool_t *pool){  svn_wc_adm_access_t *adm_access;  const svn_wc_entry_t *entry;  svn_error_t *err;  apr_pool_t *iterpool;  apr_hash_t *entries;  apr_hash_index_t *hi;  apr_finfo_t finfo;  SVN_ERR(svn_wc_adm_probe_open3(&adm_access, NULL, from, FALSE,                                 0, ctx->cancel_func, ctx->cancel_baton,                                 pool));  SVN_ERR(svn_wc_entry(&entry, from, adm_access, FALSE, pool));  /* Bail if we're trying to export something that doesn't exist,     or isn't under version control. */  if (! entry)    {      SVN_ERR(svn_wc_adm_close(adm_access));      return svn_error_createf(SVN_ERR_UNVERSIONED_RESOURCE, NULL,                               _("'%s' is not under version control "                                 "or doesn't exist"),                               svn_path_local_style(from, pool));    }  /* Only export 'added' files when the revision is WORKING.     Otherwise, skip the 'added' files, since they didn't exist     in the BASE revision and don't have an associated text-base.     Don't export 'deleted' files and directories unless it's a     revision other than WORKING.  These files and directories     don't really exist in WORKING. */  if ((revision->kind != svn_opt_revision_working &&       entry->schedule == svn_wc_schedule_add) ||      (revision->kind == svn_opt_revision_working &&       entry->schedule == svn_wc_schedule_delete))    return SVN_NO_ERROR;  if (entry->kind == svn_node_dir)    {      /* Try to make the new directory.  If this fails because the         directory already exists, check our FORCE flag to see if we         care. */      SVN_ERR(svn_io_stat(&finfo, from, APR_FINFO_PROT, pool));      err = svn_io_dir_make(to, finfo.protection, pool);      if (err)        {          if (! APR_STATUS_IS_EEXIST(err->apr_err))            return err;          if (! force)            SVN_ERR_W(err, _("Destination directory exists, and will not be "                             "overwritten unless forced"));          else            svn_error_clear(err);        }      SVN_ERR(svn_wc_entries_read(&entries, adm_access, FALSE, pool));      iterpool = svn_pool_create(pool);      for (hi = apr_hash_first(pool, entries); hi; hi = apr_hash_next(hi))        {          const char *item;          const void *key;          void *val;                    svn_pool_clear(iterpool);          apr_hash_this(hi, &key, NULL, &val);                    item = key;          entry = val;                    if (ctx->cancel_func)            SVN_ERR(ctx->cancel_func(ctx->cancel_baton));                    /* ### We could also invoke ctx->notify_func somewhere in             ### here... Is it called for, though?  Not sure. */                     if (entry->kind == svn_node_dir)            {              if (strcmp(item, SVN_WC_ENTRY_THIS_DIR) == 0)                {                  ; /* skip this, it's the current directory that we're                       handling now. */                }              else                {                  if (recurse)                    {                      const char *new_from = svn_path_join(from, item,                                                            iterpool);                      const char *new_to = svn_path_join(to, item, iterpool);                                        SVN_ERR(copy_versioned_files(new_from, new_to,                                                    revision, force, recurse,                                                   native_eol, ctx,                                                   iterpool));                    }                }            }

⌨️ 快捷键说明

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