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

📄 delta.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 3 页
字号:
      else
        SVN_ERR (svn_fs_contents_changed (&changed, 
                                          c->target_root, target_path,
                                          c->source_root, source_path,
                                          subpool));
    }
  else
    {
      /* If there isn't a source path, this is an add, which
         necessarily has textual mods. */
    }

  /* If there is a change, and the context indicates that we should
     care about it, then hand it off to a delta stream.  */
  if (changed)
    {
      svn_txdelta_stream_t *delta_stream = NULL;
      unsigned char source_digest[APR_MD5_DIGESTSIZE];
      const char *source_hex_digest = NULL;

      if (c->text_deltas)
        {
          /* Get a delta stream turning an empty file into one having
             TARGET_PATH's contents.  */
          SVN_ERR (svn_fs_get_file_delta_stream 
                   (&delta_stream, 
                    source_path ? c->source_root : NULL,
                    source_path ? source_path : NULL,
                    c->target_root, target_path, subpool));
        }

      if (source_path)
        {
          SVN_ERR (svn_fs_file_md5_checksum
                   (source_digest, c->source_root, source_path, subpool));

          source_hex_digest = svn_md5_digest_to_cstring (source_digest,
                                                         subpool);
        }

      SVN_ERR (send_text_delta (c, file_baton, source_hex_digest,
                                delta_stream, subpool));
    }

  /* Cleanup. */
  svn_pool_destroy (subpool);

  return SVN_NO_ERROR;
}




/* Generic directory deltafication routines.  */


/* Emit a delta to delete the entry named TARGET_ENTRY from DIR_BATON.  */
static svn_error_t *
delete (struct context *c, 
        void *dir_baton, 
        const char *edit_path,
        apr_pool_t *pool)
{
  return c->editor->delete_entry (edit_path, SVN_INVALID_REVNUM, 
                                  dir_baton, pool);
}


/* If authorized, emit a delta to create the entry named TARGET_ENTRY
   at the location EDIT_PATH.  If not authorized, indicate that
   EDIT_PATH is absent.  Pass DIR_BATON through to editor functions
   that require it. */
static svn_error_t *
add_file_or_dir (struct context *c, void *dir_baton,
                 const char *target_path,
                 const char *edit_path,
                 svn_node_kind_t tgt_kind,
                 apr_pool_t *pool)
{
  struct context *context = c;
  svn_boolean_t allowed;

  /* Sanity-check our input. */
  assert (target_path && edit_path);

  if (c->authz_read_func)
    {
      SVN_ERR (c->authz_read_func (&allowed, c->target_root, target_path,
                                   c->authz_read_baton, pool));
      if (!allowed)
        return absent_file_or_dir (c, dir_baton, edit_path, tgt_kind, pool);
    }

  if (tgt_kind == svn_node_dir)
    {
      void *subdir_baton;

      SVN_ERR (context->editor->add_directory (edit_path, dir_baton, NULL, 
                                               SVN_INVALID_REVNUM, pool, 
                                               &subdir_baton));
      SVN_ERR (delta_dirs (context, subdir_baton, 
                           NULL, target_path, edit_path, pool));
      SVN_ERR (context->editor->close_directory (subdir_baton, pool));
    }
  else
    {
      void *file_baton;
      unsigned char digest[APR_MD5_DIGESTSIZE];

      SVN_ERR (context->editor->add_file (edit_path, dir_baton,
                                          NULL, SVN_INVALID_REVNUM, pool, 
                                          &file_baton));
      SVN_ERR (delta_files (context, file_baton, NULL, target_path, pool));
      SVN_ERR (svn_fs_file_md5_checksum (digest, context->target_root,
                                         target_path, pool));
      SVN_ERR (context->editor->close_file
               (file_baton, svn_md5_digest_to_cstring (digest, pool), pool));
    }

  return SVN_NO_ERROR;
}


/* If authorized, emit a delta to modify EDIT_PATH with the changes
   from SOURCE_PATH to TARGET_PATH.  If not authorized, indicate that
   EDIT_PATH is absent.  Pass DIR_BATON through to editor functions
   that require it. */
static svn_error_t *
replace_file_or_dir (struct context *c, 
                     void *dir_baton,
                     const char *source_path,
                     const char *target_path,
                     const char *edit_path,
                     svn_node_kind_t tgt_kind,
                     apr_pool_t *pool)
{
  svn_revnum_t base_revision = SVN_INVALID_REVNUM;
  svn_boolean_t allowed;

  /* Sanity-check our input. */
  assert (target_path && source_path && edit_path);

  if (c->authz_read_func)
    {
      SVN_ERR (c->authz_read_func (&allowed, c->target_root, target_path,
                                   c->authz_read_baton, pool));
      if (!allowed)
        return absent_file_or_dir (c, dir_baton, edit_path, tgt_kind, pool);
    }

  /* Get the base revision for the entry from the hash. */
  base_revision = get_path_revision (c->source_root, source_path, pool);

  if (tgt_kind == svn_node_dir)
    {
      void *subdir_baton;

      SVN_ERR (c->editor->open_directory (edit_path, dir_baton, 
                                          base_revision, pool, 
                                          &subdir_baton));
      SVN_ERR (delta_dirs (c, subdir_baton, source_path, target_path, 
                           edit_path, pool));
      SVN_ERR (c->editor->close_directory (subdir_baton, pool));
    }
  else
    {
      void *file_baton;
      unsigned char digest[APR_MD5_DIGESTSIZE];

      SVN_ERR (c->editor->open_file (edit_path, dir_baton, base_revision, 
                                     pool, &file_baton));
      SVN_ERR (delta_files (c, file_baton, source_path, target_path, pool));
      SVN_ERR (svn_fs_file_md5_checksum (digest, c->target_root,
                                         target_path, pool));
      SVN_ERR (c->editor->close_file 
               (file_baton, svn_md5_digest_to_cstring (digest, pool), pool));
    }

  return SVN_NO_ERROR;
}


/* In directory DIR_BATON, indicate that EDIT_PATH  (relative to the
   edit root) is absent by invoking C->editor->absent_directory or
   C->editor->absent_file (depending on TGT_KIND). */
static svn_error_t *
absent_file_or_dir (struct context *c,
                    void *dir_baton,
                    const char *edit_path,
                    svn_node_kind_t tgt_kind,
                    apr_pool_t *pool)
{
  assert (edit_path);

  if (tgt_kind == svn_node_dir)
    SVN_ERR (c->editor->absent_directory (edit_path, dir_baton, pool));
  else
    SVN_ERR (c->editor->absent_file (edit_path, dir_baton, pool));

  return SVN_NO_ERROR;
}


/* Emit deltas to turn SOURCE_PATH into TARGET_PATH.  Assume that
   DIR_BATON represents the directory we're constructing to the editor
   in the context C.  */
static svn_error_t *
delta_dirs (struct context *c, 
            void *dir_baton,
            const char *source_path, 
            const char *target_path,
            const char *edit_path,
            apr_pool_t *pool)
{
  apr_hash_t *s_entries = 0, *t_entries = 0;
  apr_hash_index_t *hi;
  apr_pool_t *subpool;

  assert (target_path);

  /* Compare the property lists.  */
  SVN_ERR (delta_proplists (c, source_path, target_path,
                            change_dir_prop, dir_baton, pool));

  /* Get the list of entries in each of source and target.  */
  SVN_ERR (svn_fs_dir_entries (&t_entries, c->target_root,
                               target_path, pool));
  if (source_path)
    SVN_ERR (svn_fs_dir_entries (&s_entries, c->source_root,
                                 source_path, pool));

  /* Make a subpool for local allocations. */
  subpool = svn_pool_create (pool);

  /* Loop over the hash of entries in the target, searching for its
     partner in the source.  If we find the matching partner entry,
     use editor calls to replace the one in target with a new version
     if necessary, then remove that entry from the source entries
     hash.  If we can't find a related node in the source, we use
     editor calls to add the entry as a new item in the target.
     Having handled all the entries that exist in target, any entries
     still remaining the source entries hash represent entries that no
     longer exist in target.  Use editor calls to delete those entries
     from the target tree. */
  for (hi = apr_hash_first (pool, t_entries); hi; hi = apr_hash_next (hi))
    {
      const svn_fs_dirent_t *s_entry, *t_entry;
      const void *key;
      void *val;
      apr_ssize_t klen;
      const char *t_fullpath;
      const char *e_fullpath;
      const char *s_fullpath;
      svn_node_kind_t tgt_kind;

      /* KEY is the entry name in target, VAL the dirent */
      apr_hash_this (hi, &key, &klen, &val);
      t_entry = val;
      tgt_kind = t_entry->kind;
      t_fullpath = svn_path_join (target_path, t_entry->name, subpool);
      e_fullpath = svn_path_join (edit_path, t_entry->name, subpool);

      /* Can we find something with the same name in the source
         entries hash? */
      if (s_entries && ((s_entry = apr_hash_get (s_entries, key, klen)) != 0))
        {
          int distance;
          svn_node_kind_t src_kind;

          s_fullpath = svn_path_join (source_path, t_entry->name, subpool);
          src_kind = s_entry->kind;

          if (c->recurse || (src_kind != svn_node_dir))
            {
              /* Use svn_fs_compare_ids() to compare our current
                 source and target ids.

                    0: means they are the same id, and this is a noop.
                   -1: means they are unrelated, so we have to delete the
                       old one and add the new one.
                    1: means the nodes are related through ancestry, so go
                       ahead and do the replace directly.  */
              distance = svn_fs_compare_ids (s_entry->id, t_entry->id);
              if (distance == 0)
                {
                  /* no-op */
                }
              else if ((src_kind != tgt_kind)
                       || ((distance == -1) && (! c->ignore_ancestry)))
                {
                  SVN_ERR (delete (c, dir_baton, e_fullpath, subpool));
                  SVN_ERR (add_file_or_dir (c, dir_baton, t_fullpath,
                                            e_fullpath, tgt_kind, subpool));
                }
              else
                {
                  SVN_ERR (replace_file_or_dir (c, dir_baton, s_fullpath,
                                                t_fullpath, e_fullpath, 
                                                tgt_kind, subpool));
                }
            }

          /*  Remove the entry from the source_hash. */
          apr_hash_set (s_entries, key, APR_HASH_KEY_STRING, NULL);
        }            
      else
        {
          if (c->recurse || (tgt_kind != svn_node_dir))
            {
              SVN_ERR (add_file_or_dir (c, dir_baton, t_fullpath,
                                        e_fullpath, tgt_kind, subpool));
            }
        }

      /* Clear out our subpool for the next iteration... */
      svn_pool_clear (subpool);
    }

  /* All that is left in the source entries hash are things that need
     to be deleted.  Delete them.  */
  if (s_entries)
    {
      for (hi = apr_hash_first (pool, s_entries); hi; hi = apr_hash_next (hi))
        {
          const svn_fs_dirent_t *s_entry;
          const void *key;
          void *val;
          apr_ssize_t klen;
          const char *e_fullpath;
          svn_node_kind_t src_kind;
          
          /* KEY is the entry name in source, VAL the dirent */
          apr_hash_this (hi, &key, &klen, &val);
          s_entry = val;
          src_kind = s_entry->kind;
          e_fullpath = svn_path_join (edit_path, s_entry->name, subpool);

          /* Do we actually want to delete the dir if we're non-recursive? */
          if (c->recurse || (src_kind != svn_node_dir))
            SVN_ERR (delete (c, dir_baton, e_fullpath, subpool));

          /* Clear out our subpool for the next iteration... */
          svn_pool_clear (subpool);
        }
    }

  /* Destroy local allocation subpool. */
  svn_pool_destroy (subpool);

  return SVN_NO_ERROR;
}

⌨️ 快捷键说明

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