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 + -
显示快捷键?