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

📄 update_editor.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 5 页
字号:
  fb = make_file_baton (pb, path, adding, pool);

  /* It is interesting to note: everything below is just validation. We
     aren't actually doing any "work" or fetching any persistent data. */

  SVN_ERR (svn_io_check_path (fb->path, &kind, subpool));
  SVN_ERR (svn_wc_adm_retrieve (&adm_access, eb->adm_access, 
                                pb->path, subpool));
  SVN_ERR (svn_wc_entry (&entry, fb->path, adm_access, FALSE, subpool));
  
  /* Sanity checks. */

  /* If adding, there should be nothing with this name. */
  if (adding && (kind != svn_node_none))
    return svn_error_createf
      (SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
       _("Failed to add file '%s': object of the same name already exists"),
       fb->path);

  /* sussman sez: If we're trying to add a file that's already in
     `entries' (but not on disk), that's okay.  It's probably because
     the user deleted the working version and ran 'svn up' as a means
     of getting the file back.  

     It certainly doesn't hurt to re-add the file.  We can't possibly
     get the entry showing up twice in `entries', since it's a hash;
     and we know that we won't lose any local mods.  Let the existing
     entry be overwritten.

     sussman follows up to himself, many months later: the above
     scenario is fine, as long as the pre-existing entry isn't
     scheduled for addition.  that's a genuine tree-conflict,
     regardless of whether the working file still exists.  */

  if (adding && entry && entry->schedule == svn_wc_schedule_add)
    return svn_error_createf
      (SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
       _("Failed to add file '%s': object of the same name is already "
         "scheduled for addition"), fb->path);
    

  /* If replacing, make sure the .svn entry already exists. */
  if ((! adding) && (! entry))
    return svn_error_createf (SVN_ERR_UNVERSIONED_RESOURCE, NULL,
                              _("File '%s' in directory '%s' "
                                "is not a versioned resource"),
                              fb->name, pb->path);
  
  /* ### todo:  right now the incoming copyfrom* args are being
     completely ignored!  Someday the editor-driver may expect us to
     support this optimization;  when that happens, this func needs to
     -copy- the specified existing wc file to this location.  From
     there, the driver can apply_textdelta on it, etc. */

  svn_pool_destroy (subpool);

  *file_baton = fb;
  return SVN_NO_ERROR;
}


static svn_error_t *
add_file (const char *name,
          void *parent_baton,
          const char *copyfrom_path,
          svn_revnum_t copyfrom_revision,
          apr_pool_t *pool,
          void **file_baton)
{
  return add_or_open_file (name, parent_baton, copyfrom_path, 
                           copyfrom_revision, file_baton, TRUE, pool);
}


static svn_error_t *
open_file (const char *name,
           void *parent_baton,
           svn_revnum_t base_revision,
           apr_pool_t *pool,
           void **file_baton)
{
  return add_or_open_file (name, parent_baton, NULL, base_revision, 
                           file_baton, FALSE, pool);
}


static svn_error_t *
apply_textdelta (void *file_baton, 
                 const char *base_checksum,
                 apr_pool_t *pool,
                 svn_txdelta_window_handler_t *handler,
                 void **handler_baton)
{
  struct file_baton *fb = file_baton;
  struct edit_baton *eb = fb->edit_baton;
  apr_pool_t *handler_pool = svn_pool_create (fb->pool);
  struct handler_baton *hb = apr_palloc (handler_pool, sizeof (*hb));
  svn_error_t *err;
  svn_wc_adm_access_t *adm_access;
  const svn_wc_entry_t *ent;

  /* Open the text base for reading, unless this is a checkout. */
  hb->source = NULL;

  /* 
     kff todo: what we really need to do here is:
       
     1. See if there's a file or dir by this name already here.
     2. See if it's under revision control.
     3. If both are true, open text-base.
     4. If only 1 is true, bail, because we can't go destroying user's
        files (or as an alternative to bailing, move it to some tmp
        name and somehow tell the user, but communicating with the
        user without erroring is a whole callback system we haven't
        finished inventing yet.)
  */

  /* Before applying incoming svndiff data to text base, make sure
     text base hasn't been corrupted, and that its checksum
     matches the expected base checksum. */
  SVN_ERR (svn_wc_adm_retrieve (&adm_access, eb->adm_access,
                                svn_path_dirname (fb->path, pool), pool));
  SVN_ERR (svn_wc_entry (&ent, fb->path, adm_access, FALSE, pool));
      
  /* Only compare checksums this file has an entry, and the entry has
     a checksum.  If there's no entry, it just means the file is
     created in this update, so there won't be any previously recorded
     checksum to compare against.  If no checksum, well, for backwards
     compatibility we assume that no checksum always matches. */
  if (ent && ent->checksum)
    {
      unsigned char digest[APR_MD5_DIGESTSIZE];
      const char *hex_digest;
      const char *tb;
      
      tb = svn_wc__text_base_path (fb->path, FALSE, pool);
      SVN_ERR (svn_io_file_checksum (digest, tb, pool));
      hex_digest = svn_md5_digest_to_cstring (digest, pool);
      
      /* Compare the base_checksum here, rather than in the window
         handler, because there's no guarantee that the handler will
         see every byte of the base file. */
      if (base_checksum)
        {
          if (strcmp (hex_digest, base_checksum) != 0)
            return svn_error_createf
              (SVN_ERR_WC_CORRUPT_TEXT_BASE, NULL,
               _("Checksum mismatch for '%s'; expected: '%s', actual: '%s'"),
               tb, base_checksum, hex_digest);
        }
      
      if (strcmp (hex_digest, ent->checksum) != 0)
        {
          /* Compatibility hack: working copies created before 13 Jan
             2003 may have entry checksums stored in base64.  See
             svn_io_file_checksum_base64()'s doc string for
             details. */ 
          const char *base64_digest 
            = (svn_base64_from_md5 (digest, pool))->data;
              
          if (strcmp (base64_digest, ent->checksum) != 0)
            {
              return svn_error_createf
                (SVN_ERR_WC_CORRUPT_TEXT_BASE, NULL,
                 _("Checksum mismatch for '%s'; recorded: '%s', actual: '%s'"),
                 tb, ent->checksum, hex_digest);
            }
        }
    }
  
  err = svn_wc__open_text_base (&hb->source, fb->path, APR_READ,
                                handler_pool);
  if (err && !APR_STATUS_IS_ENOENT(err->apr_err))
    {
      if (hb->source)
        {
          svn_error_t *err2 = svn_wc__close_text_base (hb->source,
                                                       fb->path,
                                                       0, handler_pool);
          if (err2)
            svn_error_clear (err2);
        }
      svn_pool_destroy (handler_pool);
      return err;
    }
  else if (err)
    {
      svn_error_clear (err);
      hb->source = NULL;  /* make sure */
    }
  
  /* Open the text base for writing (this will get us a temporary file).  */
  hb->dest = NULL;
  err = svn_wc__open_text_base (&hb->dest, fb->path,
                                (APR_WRITE | APR_TRUNCATE | APR_CREATE),
                                handler_pool);
  if (err)
    {
      if (hb->dest)
        svn_error_clear (svn_wc__close_text_base (hb->dest, fb->path, 0,
                                                  handler_pool));
      svn_pool_destroy (handler_pool);
      return err;
    }
  
  /* Prepare to apply the delta.  */
  {
    const char *tmp_path;

    apr_file_name_get (&tmp_path, hb->dest);
    svn_txdelta_apply (svn_stream_from_aprfile (hb->source, handler_pool),
                       svn_stream_from_aprfile (hb->dest, handler_pool),
                       fb->digest, tmp_path, handler_pool,
                       &hb->apply_handler, &hb->apply_baton);
  }
  
  hb->pool = handler_pool;
  hb->fb = fb;
  
  /* We're all set.  */
  *handler_baton = hb;
  *handler = window_handler;

  return SVN_NO_ERROR;
}




static svn_error_t *
change_file_prop (void *file_baton,
                  const char *name,
                  const svn_string_t *value,
                  apr_pool_t *pool)
{
  struct file_baton *fb = file_baton;
  struct edit_baton *eb = fb->edit_baton;
  svn_prop_t *propchange;

  /* Push a new propchange to the file baton's array of propchanges */
  propchange = apr_array_push (fb->propchanges);
  propchange->name = apr_pstrdup (fb->pool, name);
  propchange->value = value ? svn_string_dup (value, fb->pool) : NULL;

  /* Let close_file() know that propchanges are waiting to be
     applied. */
  fb->prop_changed = 1;

  /* Special case: if the file is added during a checkout, cache the
     last-changed-date propval for future use. */
  if (eb->use_commit_times
      && (strcmp (name, SVN_PROP_ENTRY_COMMITTED_DATE) == 0))
    fb->last_changed_date = apr_pstrdup (fb->pool, value->data);

  return SVN_NO_ERROR;
}



/* This is the small planet.  It has the complex responsibility of
 * "integrating" a new revision of a file into a working copy. 
 *
 * Given a @a file_path either already under version control, or
 * prepared (see below) to join revision control, fully install a @a
 * new_revision of the file; @a new_revision must be 0 if copyfrom
 * args are passed, see below for details.  @a adm_access is an access
 * baton with a write lock for the directory containing @a file_path.
 *
 * If @a file_path is not already under version control (i.e., does
 * not have an entry), then the raw data (for example the new text
 * base and new props) required to put it under version control must
 * be provided by the caller.  See below for details.
 *
 * By "install", we mean: create a new text-base and prop-base, merge
 * any textual and property changes into the working file, and finally
 * update all metadata so that the working copy believes it has a new
 * working revision of the file.  All of this work includes being
 * sensitive to eol translation, keyword substitution, and performing
 * all actions using a journaled logfile.
 *
 * The caller provides a @a new_text_path which points to a temporary
 * file containing the 'new' base text of the file at revision @a
 * new_revision.  This function automatically removes @a new_text_path
 * upon successful completion.  If there is no new text, then caller
 * must set @a new_text_path to @c NULL.
 *
 * The caller also provides the new properties for the file in the
 * @a props array; if there are no new props, then caller must pass 
 * @c NULL instead.  This argument is an array of @c svn_prop_t structures, 
 * and can be interpreted in one of two ways:
 *
 *    - if @a is_full_proplist is true, then the array represents the
 *      complete list of all properties for the file.  It is the new
 *      'pristine' proplist.
 *
 *    - if @a is_full_proplist is false, then the array represents a set of
 *      *differences* against the file's existing pristine proplist.
 *      (A deletion is represented by setting an @c svn_prop_t's 'value'
 *      field to @c NULL.)  
 *
 * Note that the @a props array is expected to contain all categories of
 * props, not just 'regular' ones that the user sees.  (See <tt>enum
 * svn_prop_kind</tt>).
 *
 * If @a content_state is non-null, set @a *content_state to the state of
 * the file contents after the installation; if return error, the
 * value of @a *content_state is undefined.
 *
 * If @a prop_state is non-null, set @a *prop_state to the state of the
 * properties after the installation; if return error, the value of
 * @a *prop_state is undefined.
 *
 * If @a new_url is non-null, then this URL will be attached to the file
 * in the 'entries' file.  Otherwise, the file will simply "inherit"
 * its URL from the parent dir.
 *
 * If @a is_add is true, schedule the new file for addition; and if
 * @a copyfrom_url is non-null, then store it and @a copyfrom_rev as
 * copyfrom history for the added file.  An assertion error may occur
 * if copyfrom args while @a is_add is false.  An assertion error may
 * occur if @a copyfrom_url is non-null but @a copyfrom_rev is not a
 * valid revision number.  An assertion error may occur if @a is_add
 * is true but @a new_revision is not 0.
 *
 * If @a diff3_cmd is non-null, then use it as the diff3 command for
 * any merging; otherwise, use the built-in merge code.
 *
 * If @a timestamp_string is non-null, then use it to set the
 * timestamp on the final working file.  The string should be
 * formatted for use by svn_time_from_cstring().
 *
 * @a pool is used for all bookkeeping work during the installation.
 */
static svn_error_t *
install_file (svn_wc_notify_state_t *content_state,
              svn_wc_notify_state_t *prop_state,
              svn_wc_adm_access_t *adm_access,
              int *log_number,
              const char *file_path,
              svn_revnum_t new_revision,
              const char *new_text_path,
              const apr_array_header_t *props,
              svn_boolean_t is_full_proplist,
              const char *new_URL,
              svn_boolean_t is_add,
              const char *copyfrom_url,
              svn_revnum_t copyfrom_rev,
              const char *diff3_cmd,
              const char *timestamp_string,
              apr_pool_t *pool)
{
  apr_file_t *log_fp = NULL;
  char *revision_str = NULL;
  const char *parent_dir, *base_name;
  svn_stringbuf_t *log_accum;
  svn_boolean_t is_locally_modified;
  svn_boolean_t mag

⌨️ 快捷键说明

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