dump.c

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

C
1,070
字号
                    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));  /* Run revision date properties through the time conversion to     canonicalize 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;  int version;  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);  if (! feedback_stream)    feedback_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));  /* If we're not using deltas, use the previous version, for     compatibility with svn 1.0.x. */  version = SVN_REPOS_DUMPFILE_FORMAT_VERSION;  if (!use_deltas)    version--;  /* Write out "general" metadata for the dumpfile.  In this case, a     magic header followed by a dumpfile format 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;      svn_pool_clear(subpool);      /* 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.  Otherwise, 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_replay2(to_root, "", SVN_INVALID_REVNUM, FALSE,                                    dump_editor, dump_edit_baton,                                    NULL, NULL, subpool));        }    loop_end:      SVN_ERR(svn_stream_printf(feedback_stream, pool,                                dumping                                ? _("* Dumped revision %ld.\n")                                : _("* Verified revision %ld.\n"),                                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 + =
减小字号Ctrl + -
显示快捷键?