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

📄 dump.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 3 页
字号:
  SVN_ERR (dump_node (eb, path, 
                      svn_node_file,
                      val ? svn_node_action_replace : svn_node_action_add,
                      is_copy,
                      is_copy ? copyfrom_path : NULL, 
                      is_copy ? copyfrom_rev : SVN_INVALID_REVNUM, 
                      pool));

  if (val)
    /* delete the path, it's now been dumped. */
    apr_hash_set (pb->deleted_entries, path, APR_HASH_KEY_STRING, NULL);

  *file_baton = NULL;  /* muhahahaha */
  return SVN_NO_ERROR;
}


static svn_error_t *
open_file (const char *path,
           void *parent_baton,
           svn_revnum_t ancestor_revision,
           apr_pool_t *pool,
           void **file_baton)
{
  struct dir_baton *pb = parent_baton;
  struct edit_baton *eb = pb->edit_baton;
  const char *cmp_path = NULL;
  svn_revnum_t cmp_rev = SVN_INVALID_REVNUM;
  
  /* If the parent directory has explicit comparison path and rev,
     record the same for this one. */
  if (pb && ARE_VALID_COPY_ARGS (pb->cmp_path, pb->cmp_rev))
    {
      cmp_path = svn_path_join (pb->cmp_path, 
                                svn_path_basename (path, pool), pool);
      cmp_rev = pb->cmp_rev;
    }

  SVN_ERR (dump_node (eb, path, 
                      svn_node_file, svn_node_action_change, 
                      FALSE, cmp_path, cmp_rev, pool));

  *file_baton = NULL;  /* muhahahaha again */
  return SVN_NO_ERROR;
}


static svn_error_t *
change_dir_prop (void *parent_baton,
                 const char *name,
                 const svn_string_t *value,
                 apr_pool_t *pool)
{
  struct dir_baton *db = parent_baton;
  struct edit_baton *eb = db->edit_baton;

  /* This function is what distinguishes between a directory that is
     opened to merely get somewhere, vs. one that is opened because it
     *actually* changed by itself.  */
  if (! db->written_out)
    {
      SVN_ERR (dump_node (eb, db->path, 
                          svn_node_dir, svn_node_action_change, 
                          FALSE, db->cmp_path, db->cmp_rev, pool));
      db->written_out = TRUE;
    }
  return SVN_NO_ERROR;
}



static svn_error_t *
get_dump_editor (const svn_delta_editor_t **editor,
                 void **edit_baton,
                 svn_fs_t *fs,
                 svn_revnum_t to_rev,
                 const char *root_path,
                 svn_stream_t *stream,
                 svn_stream_t *feedback_stream,
                 svn_revnum_t oldest_dumped_rev,
                 svn_boolean_t use_deltas,
                 apr_pool_t *pool)
{
  /* Allocate an edit baton to be stored in every directory baton.
     Set it up for the directory baton we create here, which is the
     root baton. */
  struct edit_baton *eb = apr_pcalloc (pool, sizeof (*eb));
  svn_delta_editor_t *dump_editor = svn_delta_default_editor (pool);

  /* Set up the edit baton. */
  eb->stream = stream;
  eb->feedback_stream = feedback_stream;
  eb->oldest_dumped_rev = oldest_dumped_rev;
  eb->bufsize = sizeof(eb->buffer);
  eb->path = apr_pstrdup (pool, root_path);
  SVN_ERR (svn_fs_revision_root (&(eb->fs_root), fs, to_rev, pool));
  eb->current_rev = to_rev;
  eb->use_deltas = use_deltas;

  /* Set up the editor. */
  dump_editor->open_root = open_root;
  dump_editor->delete_entry = delete_entry;
  dump_editor->add_directory = add_directory;
  dump_editor->open_directory = open_directory;
  dump_editor->close_directory = close_directory;
  dump_editor->change_dir_prop = change_dir_prop;
  dump_editor->add_file = add_file;
  dump_editor->open_file = open_file;

  *edit_baton = eb;
  *editor = dump_editor;
  
  return SVN_NO_ERROR;
}

/*----------------------------------------------------------------------*/

/** The main dumping routine, svn_repos_dump_fs. **/


/* Helper for svn_repos_dump_fs.

   Write a revision record of REV in FS to writable STREAM, using POOL.
 */
static svn_error_t *
write_revision_record (svn_stream_t *stream,
                       svn_fs_t *fs,
                       svn_revnum_t rev,
                       apr_pool_t *pool)
{
  apr_size_t len;
  apr_hash_t *props;
  svn_stringbuf_t *encoded_prophash;
  apr_time_t timetemp;
  svn_string_t *datevalue;

  /* Read the revision props even if we're aren't going to dump
     them for verification purposes */
  SVN_ERR (svn_fs_revision_proplist (&props, fs, rev, pool));

  /* If we have no stream, and we aren't validating anything, we might
     as well just go home now. */
  if (! stream)
    return SVN_NO_ERROR;

  /* Run revision date properties through the time conversion to
     canonize them. */
  /* ### Remove this when it is no longer needed for sure. */
  datevalue = apr_hash_get (props, SVN_PROP_REVISION_DATE,
                            APR_HASH_KEY_STRING);
  if (datevalue)
    {
      SVN_ERR (svn_time_from_cstring (&timetemp, datevalue->data, pool));
      datevalue = svn_string_create (svn_time_to_cstring (timetemp, pool),
                                     pool);
      apr_hash_set (props, SVN_PROP_REVISION_DATE, APR_HASH_KEY_STRING,
                    datevalue);
    }

  write_hash_to_stringbuf (props, NULL, &encoded_prophash, pool);

  /* ### someday write a revision-content-checksum */

  SVN_ERR (svn_stream_printf (stream, pool,
                              SVN_REPOS_DUMPFILE_REVISION_NUMBER 
                              ": %ld\n", rev));
  SVN_ERR (svn_stream_printf (stream, pool,
                              SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH
                              ": %" APR_SIZE_T_FMT "\n",
                              encoded_prophash->len));
  
  /* Write out a regular Content-length header for the benefit of
     non-Subversion RFC-822 parsers. */
  SVN_ERR (svn_stream_printf (stream, pool,
                              SVN_REPOS_DUMPFILE_CONTENT_LENGTH
                              ": %" APR_SIZE_T_FMT "\n\n",
                              encoded_prophash->len));
  
  len = encoded_prophash->len;
  SVN_ERR (svn_stream_write (stream, encoded_prophash->data, &len));
  
  len = 1;
  SVN_ERR (svn_stream_write (stream, "\n", &len));
  
  return SVN_NO_ERROR;
}



/* The main dumper. */
svn_error_t *
svn_repos_dump_fs2 (svn_repos_t *repos,
                    svn_stream_t *stream,
                    svn_stream_t *feedback_stream,
                    svn_revnum_t start_rev,
                    svn_revnum_t end_rev,
                    svn_boolean_t incremental,
                    svn_boolean_t use_deltas,
                    svn_cancel_func_t cancel_func,
                    void *cancel_baton,
                    apr_pool_t *pool)
{
  const svn_delta_editor_t *dump_editor;
  void *dump_edit_baton;
  svn_revnum_t i;  
  svn_fs_t *fs = svn_repos_fs (repos);
  apr_pool_t *subpool = svn_pool_create (pool);
  svn_revnum_t youngest;
  const char *uuid;
  svn_boolean_t dumping = (stream != NULL);

  /* Determine the current youngest revision of the filesystem. */
  SVN_ERR (svn_fs_youngest_rev (&youngest, fs, pool));

  /* Use default vals if necessary. */
  if (! SVN_IS_VALID_REVNUM(start_rev))
    start_rev = 0;
  if (! SVN_IS_VALID_REVNUM(end_rev))
    end_rev = youngest;
  if (! stream)
    stream = svn_stream_empty (pool);

  /* Validate the revisions. */
  if (start_rev > end_rev)
    return svn_error_createf (SVN_ERR_REPOS_BAD_ARGS, NULL,
                              _("Start revision %ld"
                                " is greater than end revision %ld"),
                              start_rev, end_rev);
  if (end_rev > youngest)
    return svn_error_createf (SVN_ERR_REPOS_BAD_ARGS, NULL,
                              _("End revision %ld is invalid "
                                "(youngest revision is %ld)"),
                              end_rev, youngest);
  if ((start_rev == 0) && incremental)
    incremental = FALSE; /* revision 0 looks the same regardless of
                            whether or not this is an incremental
                            dump, so just simplify things. */

  /* Write out the UUID. */
  SVN_ERR (svn_fs_get_uuid(fs, &uuid, pool));

  /* Write out "general" metadata for the dumpfile.  In this case, a
     magic header followed by a dumpfile format version. */
  if (stream)
    {
      int version = SVN_REPOS_DUMPFILE_FORMAT_VERSION;

      /* If we're not using deltas, use the previous version, for
         compatibility with svn 1.0.x. */
      if (!use_deltas)
        version--;
      SVN_ERR (svn_stream_printf (stream, pool, 
                                  SVN_REPOS_DUMPFILE_MAGIC_HEADER ": %d\n\n", 
                                  version));
      SVN_ERR (svn_stream_printf (stream, pool, SVN_REPOS_DUMPFILE_UUID
                                  ": %s\n\n", uuid));
    }

  /* Main loop:  we're going to dump revision i.  */
  for (i = start_rev; i <= end_rev; i++)
    {
      svn_revnum_t from_rev, to_rev;
      svn_fs_root_t *to_root;
      svn_boolean_t use_deltas_for_rev;

      /* Check for cancellation. */
      if (cancel_func)
        SVN_ERR (cancel_func (cancel_baton));

      /* Special-case the initial revision dump: it needs to contain
         *all* nodes, because it's the foundation of all future
         revisions in the dumpfile. */
      if ((i == start_rev) && (! incremental))
        {
          /* Special-special-case a dump of revision 0. */
          if (i == 0)
            {
              /* Just write out the one revision 0 record and move on.
                 The parser might want to use its properties. */
              SVN_ERR (write_revision_record (stream, fs, 0, subpool));
              to_rev = 0;
              goto loop_end;
            }

          /* Compare START_REV to revision 0, so that everything
             appears to be added.  */
          from_rev = 0;
          to_rev = i;
        }
      else
        {
          /* In the normal case, we want to compare consecutive revs. */
          from_rev = i - 1;
          to_rev = i;
        }

      /* Write the revision record. */
      SVN_ERR (write_revision_record (stream, fs, to_rev, subpool));

      /* Fetch the editor which dumps nodes to a file.  Regardless of
         what we've been told, don't use deltas for the first rev of a
         non-incremental dump. */
      use_deltas_for_rev = use_deltas && (incremental || i != start_rev);
      SVN_ERR (get_dump_editor (&dump_editor, &dump_edit_baton, fs, to_rev,
                                "/", stream, feedback_stream, start_rev,
                                use_deltas_for_rev, subpool));

      /* Drive the editor in one way or another. */
      SVN_ERR (svn_fs_revision_root (&to_root, fs, to_rev, subpool));

      /* If this is the first revision of a non-incremental dump,
         we're in for a full tree dump.  Othersise, we want to simply
         replay the revision.  */
      if ((i == start_rev) && (! incremental))
        {
          svn_fs_root_t *from_root;
          SVN_ERR (svn_fs_revision_root (&from_root, fs, from_rev, subpool));
          SVN_ERR (svn_repos_dir_delta (from_root, "/", "",
                                        to_root, "/",
                                        dump_editor, dump_edit_baton,
                                        NULL,
                                        NULL,
                                        FALSE, /* don't send text-deltas */
                                        TRUE, /* recurse */
                                        FALSE, /* don't send entry props */
                                        FALSE, /* don't ignore ancestry */
                                        subpool));
        }
      else
        {
          SVN_ERR (svn_repos_replay (to_root, dump_editor, 
                                     dump_edit_baton, subpool));
        }

    loop_end:
      /* Reuse all memory consumed by the dump of this one revision. */
      svn_pool_clear (subpool);
      if (feedback_stream)
        SVN_ERR (svn_stream_printf (feedback_stream, pool,
                                    _("* %s revision %ld.\n"),
                                    dumping ? "Dumped" : "Verified",
                                    to_rev));
    }

  svn_pool_destroy (subpool);

  return SVN_NO_ERROR;
}

svn_error_t *
svn_repos_dump_fs (svn_repos_t *repos,
                   svn_stream_t *stream,
                   svn_stream_t *feedback_stream,
                   svn_revnum_t start_rev,
                   svn_revnum_t end_rev,
                   svn_boolean_t incremental,
                   svn_cancel_func_t cancel_func,
                   void *cancel_baton,
                   apr_pool_t *pool)
{
  return svn_repos_dump_fs2 (repos, stream, feedback_stream, start_rev,
                             end_rev, incremental, FALSE, cancel_func,
                             cancel_baton, pool);
}

⌨️ 快捷键说明

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