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

📄 adm_crawler.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * adm_crawler.c:  report local WC mods to an Editor.
 *
 * ====================================================================
 * 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/.
 * ====================================================================
 */

/* ==================================================================== */


#include <string.h>

#include <apr_pools.h>
#include <apr_file_io.h>
#include <apr_hash.h>
#include <apr_md5.h>

#include <assert.h>

#include "svn_types.h"
#include "svn_pools.h"
#include "svn_wc.h"
#include "svn_io.h"
#include "svn_md5.h"
#include "svn_base64.h"
#include "svn_sorts.h"
#include "svn_delta.h"
#include "svn_path.h"

#include "wc.h"
#include "adm_files.h"
#include "props.h"
#include "translate.h"
#include "entries.h"

#include "svn_private_config.h"


/* Helper for report_revisions().
   
   Perform an atomic restoration of the file FILE_PATH; that is, copy
   the file's text-base to the administrative tmp area, and then move
   that file to FILE_PATH with possible translations/expansions.  If
   USE_COMMIT_TIMES is set, then set working file's timestamp to
   last-commit-time.  Either way, set entry-timestamp to match that of
   the working file when all is finished. */
static svn_error_t *
restore_file (const char *file_path,
              svn_wc_adm_access_t *adm_access,
              svn_boolean_t use_commit_times,
              apr_pool_t *pool)
{
  const char *text_base_path, *tmp_text_base_path;
  svn_subst_keywords_t *keywords;
  const char *eol;
  const svn_wc_entry_t *entry;
  svn_wc_entry_t newentry;
  apr_time_t tstamp;
  const char *bname;
  apr_uint32_t modify_flags = 0;
  svn_boolean_t special;

  text_base_path = svn_wc__text_base_path (file_path, FALSE, pool);
  tmp_text_base_path = svn_wc__text_base_path (file_path, TRUE, pool);
  bname = svn_path_basename (file_path, pool);

  SVN_ERR (svn_io_copy_file (text_base_path, tmp_text_base_path,
                             FALSE, pool));

  SVN_ERR (svn_wc__get_eol_style (NULL, &eol, file_path, adm_access, pool));
  SVN_ERR (svn_wc__get_keywords (&keywords,
                                 file_path, adm_access, NULL, pool));
  SVN_ERR (svn_wc__get_special (&special, file_path, adm_access, pool));
                                
  
  /* When copying the tmp-text-base out to the working copy, make
     sure to do any eol translations or keyword substitutions,
     as dictated by the property values.  If these properties
     are turned off, then this is just a normal copy. */
  SVN_ERR (svn_subst_copy_and_translate2 (tmp_text_base_path,
                                          file_path,
                                          eol, FALSE, /* don't repair */
                                          keywords,
                                          TRUE, /* expand keywords */
                                          special,
                                          pool));
  
  SVN_ERR (svn_io_remove_file (tmp_text_base_path, pool));

  /* If necessary, tweak the new working file's executable bit. */
  SVN_ERR (svn_wc__maybe_set_executable (NULL, file_path, adm_access, pool));

  /* Remove any text conflict */
  SVN_ERR (svn_wc_resolved_conflict (file_path, adm_access, TRUE, FALSE, FALSE,
                                     NULL, NULL, pool));

  SVN_ERR (svn_wc_entry (&entry, file_path, adm_access, FALSE, pool));
  assert(entry != NULL);

  /* Possibly set timestamp to last-commit-time. */
  if (use_commit_times && (! special))
    {
      SVN_ERR (svn_io_set_file_affected_time (entry->cmt_date,
                                              file_path, pool));
      tstamp = entry->cmt_date;
    }
  else
    {
      SVN_ERR (svn_io_file_affected_time (&tstamp, file_path, pool));
    }
  
  /* Modify our entry's text-timestamp to match the working file. */
  modify_flags |= SVN_WC__ENTRY_MODIFY_TEXT_TIME;
  newentry.text_time = tstamp;
  SVN_ERR (svn_wc__entry_modify (adm_access, bname,
                                 &newentry, modify_flags,
                                 TRUE /* do_sync now */, pool));

  return SVN_NO_ERROR;
}


/* The recursive crawler that describes a mixed-revision working
   copy to an RA layer.  Used to initiate updates.

   This is a depth-first recursive walk of DIR_PATH under ADM_ACCESS.
   Look at each entry and check if its revision is different than
   DIR_REV.  If so, report this fact to REPORTER.  If an entry is
   missing from disk, report its absence to REPORTER.  If an entry has
   a different URL than expected, report that to REPORTER.  Finally,
   if REPORT_EVERYTHING is set, then report all children unconditionally.

   If TRAVERSAL_INFO is non-null, record this directory's
   value of svn:externals in both TRAVERSAL_INFO->externals_old and
   TRAVERSAL_INFO->externals_new, using wc_path + dir_path as the key,
   and the raw (unparsed) value of the property as the value.  NOTE:
   We set the value in both places, because its absence in just one or
   the other place signals that the property was added or deleted;
   thus, storing it in both places signals that it is present and, by
   default, unchanged.

   If RESTORE_FILES is set, then unexpectedly missing working files
   will be restored from text-base and NOTIFY_FUNC/NOTIFY_BATON
   will be called to report the restoration.  USE_COMMIT_TIMES is
   passed to restore_file() helper. */
static svn_error_t *
report_revisions (svn_wc_adm_access_t *adm_access,
                  const char *dir_path,
                  svn_revnum_t dir_rev,
                  const svn_ra_reporter_t *reporter,
                  void *report_baton,
                  svn_wc_notify_func_t notify_func,
                  void *notify_baton,
                  svn_boolean_t restore_files,
                  svn_boolean_t recurse,
                  svn_boolean_t report_everything,
                  svn_boolean_t use_commit_times,
                  svn_wc_traversal_info_t *traversal_info,
                  apr_pool_t *pool)
{
  apr_hash_t *entries, *dirents;
  apr_hash_index_t *hi;
  apr_pool_t *subpool = svn_pool_create (pool), *iterpool;
  const svn_wc_entry_t *dot_entry;
  const char *this_url, *this_path, *full_path, *this_full_path;
  svn_wc_adm_access_t *dir_access;

  /* Get both the SVN Entries and the actual on-disk entries.   Also
     notice that we're picking up hidden entries too. */
  full_path = svn_path_join (svn_wc_adm_access_path (adm_access), 
                             dir_path, subpool);
  SVN_ERR (svn_wc_adm_retrieve (&dir_access, adm_access, full_path, subpool));
  SVN_ERR (svn_wc_entries_read (&entries, dir_access, TRUE, subpool));
  SVN_ERR (svn_io_get_dirents (&dirents, full_path, subpool));
  
  /*** Do the real reporting and recursing. ***/
  
  /* First, look at "this dir" to see what its URL is. */
  dot_entry = apr_hash_get (entries, SVN_WC_ENTRY_THIS_DIR, 
                            APR_HASH_KEY_STRING);

  /* If "this dir" has "svn:externals" property set on it, store its name
     in traversal_info. */
  if (traversal_info)
    {
      const svn_string_t *val;
      SVN_ERR (svn_wc_prop_get (&val, SVN_PROP_EXTERNALS, full_path, adm_access,
                                subpool));
      if (val)
        {
          apr_pool_t *dup_pool = traversal_info->pool;
          const char *dup_path = apr_pstrdup (dup_pool, full_path);
          const char *dup_val = apr_pstrmemdup (dup_pool, val->data, val->len);
          apr_hash_set (traversal_info->externals_old,
                        dup_path, APR_HASH_KEY_STRING, dup_val);
          apr_hash_set (traversal_info->externals_new,
                        dup_path, APR_HASH_KEY_STRING, dup_val);
        }
    }

  /* Looping over current directory's SVN entries: */
  iterpool = svn_pool_create (subpool);

  for (hi = apr_hash_first (subpool, entries); hi; hi = apr_hash_next (hi))
    {
      const void *key;
      apr_ssize_t klen;
      void *val;
      const svn_wc_entry_t *current_entry; 
      svn_node_kind_t *dirent_kind;
      svn_boolean_t missing = FALSE;

      /* Clear the iteration subpool here because the loop has a bunch
         of 'continue' jump statements. */
      svn_pool_clear (iterpool);

      /* Get the next entry */
      apr_hash_this (hi, &key, &klen, &val);
      current_entry = val;

      /* Compute the name of the entry.  Skip THIS_DIR altogether. */
      if (! strcmp (key, SVN_WC_ENTRY_THIS_DIR))
        continue;

      /* Compute the paths and URLs we need. */
      this_url = svn_path_join (dot_entry->url, 
                                svn_path_uri_encode (key, iterpool), iterpool);
      this_path = svn_path_join (dir_path, key, iterpool);
      this_full_path = svn_path_join (full_path, key, iterpool);

      /*** The Big Tests: ***/

      /* If the entry is 'deleted' or 'absent', make sure the server
         knows it's gone... unless we're reporting everything, in
         which case it's already missing on the server.  */
      if ((current_entry->deleted || current_entry->absent)
          && (! report_everything))
        {
          SVN_ERR (reporter->delete_path (report_baton, this_path, iterpool));
          continue;
        }
      
      /* Is the entry on disk?  Set a flag if not. */
      dirent_kind = (svn_node_kind_t *) apr_hash_get (dirents, key, klen);
      if (! dirent_kind)
        {
          /* It is possible on a case insensitive system that the
             entry is not really missing, so we call our trusty but
             expensive friend svn_io_check_path to be sure. */
          dirent_kind = apr_palloc (iterpool, sizeof(*dirent_kind)); 
          SVN_ERR (svn_io_check_path (this_full_path, dirent_kind,
                                      iterpool));
          if (*dirent_kind == svn_node_none)
            {
              dirent_kind = NULL;
              missing = TRUE;
            }
        }
      
      /* From here on out, ignore any entry scheduled for addition */
      if (current_entry->schedule == svn_wc_schedule_add)
        continue;
      
      /*** Files ***/
      if (current_entry->kind == svn_node_file) 
        {
          /* If the dirent changed kind, report it as missing and

⌨️ 快捷键说明

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