📄 dump.c
字号:
/* definitely need to dump all content for a replace. */
if (kind == svn_node_file)
must_dump_text = TRUE;
must_dump_props = TRUE;
}
else
{
/* more complex: delete original, then add-with-history. */
/* the path & kind headers have already been printed; just
add a delete action, and end the current record.*/
if (eb->stream)
SVN_ERR (svn_stream_printf (eb->stream, pool,
SVN_REPOS_DUMPFILE_NODE_ACTION
": delete\n\n"));
/* recurse: print an additional add-with-history record. */
SVN_ERR (dump_node (eb, path, kind, svn_node_action_add,
is_copy, compare_path, compare_rev, pool));
/* we can leave this routine quietly now, don't need to dump
any content; that was already done in the second record. */
must_dump_text = FALSE;
must_dump_props = FALSE;
}
}
else if (action == svn_node_action_delete)
{
if (eb->stream)
SVN_ERR (svn_stream_printf (eb->stream, pool,
SVN_REPOS_DUMPFILE_NODE_ACTION
": delete\n"));
/* we can leave this routine quietly now, don't need to dump
any content. */
must_dump_text = FALSE;
must_dump_props = FALSE;
}
else if (action == svn_node_action_add)
{
if (eb->stream)
SVN_ERR (svn_stream_printf (eb->stream, pool,
SVN_REPOS_DUMPFILE_NODE_ACTION ": add\n"));
if (! is_copy)
{
/* Dump all contents for a simple 'add'. */
if (kind == svn_node_file)
must_dump_text = TRUE;
must_dump_props = TRUE;
}
else
{
if ((cmp_rev < eb->oldest_dumped_rev)
&& eb->feedback_stream)
svn_stream_printf
(eb->feedback_stream, pool,
_("WARNING: Referencing data in revision %ld"
", which is older than the oldest\nWARNING: dumped revision "
"(%ld). Loading this dump into an empty "
"repository\nWARNING: will fail.\n"),
cmp_rev, eb->oldest_dumped_rev);
if (eb->stream)
SVN_ERR (svn_stream_printf (eb->stream, pool,
SVN_REPOS_DUMPFILE_NODE_COPYFROM_REV
": %ld\n"
SVN_REPOS_DUMPFILE_NODE_COPYFROM_PATH
": %s\n",
cmp_rev, cmp_path));
SVN_ERR (svn_fs_revision_root (&compare_root,
svn_fs_root_fs (eb->fs_root),
compare_rev, pool));
/* Need to decide if the copied node had any extra textual or
property mods as well. */
SVN_ERR (svn_fs_props_changed (&must_dump_props,
compare_root, compare_path,
eb->fs_root, path, pool));
if (kind == svn_node_file)
SVN_ERR (svn_fs_contents_changed (&must_dump_text,
compare_root, compare_path,
eb->fs_root, path, pool));
/* ### someday write a node-copyfrom-source-checksum. */
}
}
if ((! must_dump_text) && (! must_dump_props))
{
/* If we're not supposed to dump text or props, so be it, we can
just go home. However, if either one needs to be dumped,
then our dumpstream format demands that at a *minimum*, we
see a lone "PROPS-END" as a divider between text and props
content within the content-block. */
if (eb->stream)
{
len = 2;
return svn_stream_write (eb->stream, "\n\n", &len); /* ### needed? */
}
return SVN_NO_ERROR;
}
/*** Start prepping content to dump... ***/
/* If we are supposed to dump properties, write out a property
length header and generate a stringbuf that contains those
property values here. */
if (must_dump_props)
{
apr_hash_t *prophash, *oldhash = NULL;
apr_size_t proplen;
SVN_ERR (svn_fs_node_proplist (&prophash, eb->fs_root, path, pool));
if (eb->use_deltas && compare_root)
{
/* Fetch the old property hash to diff against and output a header
saying that our property contents are a delta. */
SVN_ERR (svn_fs_node_proplist (&oldhash, compare_root, compare_path,
pool));
if (eb->stream)
SVN_ERR (svn_stream_printf (eb->stream, pool,
SVN_REPOS_DUMPFILE_PROP_DELTA
": true\n"));
}
write_hash_to_stringbuf (prophash, oldhash, &propstring, pool);
proplen = propstring->len;
content_length += proplen;
if (eb->stream)
SVN_ERR (svn_stream_printf (eb->stream, pool,
SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH
": %" APR_SIZE_T_FMT "\n", proplen));
}
/* If we are supposed to dump text, write out a text length header
here, and a md5 checksum (if available.) */
if (must_dump_text && (kind == svn_node_file))
{
unsigned char md5_digest[APR_MD5_DIGESTSIZE];
const char *hex_digest;
svn_filesize_t textlen;
if (eb->use_deltas)
{
/* Compute the text delta now and write it into a temporary
file, so that we can find its length. Output a header
saying our text contents are a delta. */
SVN_ERR (store_delta (&delta_file, &textlen, compare_root,
compare_path, eb->fs_root, path, pool));
if (eb->stream)
SVN_ERR (svn_stream_printf (eb->stream, pool,
SVN_REPOS_DUMPFILE_TEXT_DELTA
": true\n"));
}
else
{
/* Just fetch the length of the file. */
SVN_ERR (svn_fs_file_length (&textlen, eb->fs_root, path, pool));
}
content_length += textlen;
if (eb->stream)
SVN_ERR (svn_stream_printf (eb->stream, pool,
SVN_REPOS_DUMPFILE_TEXT_CONTENT_LENGTH
": %" SVN_FILESIZE_T_FMT "\n", textlen));
SVN_ERR (svn_fs_file_md5_checksum (md5_digest, eb->fs_root, path, pool));
hex_digest = svn_md5_digest_to_cstring (md5_digest, pool);
if (hex_digest && eb->stream)
SVN_ERR (svn_stream_printf (eb->stream, pool,
SVN_REPOS_DUMPFILE_TEXT_CONTENT_CHECKSUM
": %s\n", hex_digest));
}
/* 'Content-length:' is the last header before we dump the content,
and is the summation of the text and prop contents lengths. We
write this only for the benefit of non-Subversion RFC-822
parsers. */
if (eb->stream)
SVN_ERR (svn_stream_printf (eb->stream, pool,
SVN_REPOS_DUMPFILE_CONTENT_LENGTH
": %" SVN_FILESIZE_T_FMT "\n\n",
content_length));
/* Dump property content if we're supposed to do so. */
if (must_dump_props && eb->stream)
{
len = propstring->len;
SVN_ERR (svn_stream_write (eb->stream, propstring->data, &len));
}
/* Dump text content */
if (must_dump_text && (kind == svn_node_file) && eb->stream)
{
svn_stream_t *contents;
if (delta_file)
contents = svn_stream_from_aprfile (delta_file, pool);
else
SVN_ERR (svn_fs_file_contents (&contents, eb->fs_root, path, pool));
SVN_ERR (svn_stream_copy (contents, eb->stream, pool));
}
if (eb->stream)
{
len = 2;
SVN_ERR (svn_stream_write (eb->stream, "\n\n", &len)); /* ### needed? */
}
return SVN_NO_ERROR;
}
static svn_error_t *
open_root (void *edit_baton,
svn_revnum_t base_revision,
apr_pool_t *pool,
void **root_baton)
{
*root_baton = make_dir_baton (NULL, NULL, SVN_INVALID_REVNUM,
edit_baton, NULL, FALSE, pool);
return SVN_NO_ERROR;
}
static svn_error_t *
delete_entry (const char *path,
svn_revnum_t revision,
void *parent_baton,
apr_pool_t *pool)
{
struct dir_baton *pb = parent_baton;
const char *mypath = apr_pstrdup (pb->pool, path);
/* remember this path needs to be deleted. */
apr_hash_set (pb->deleted_entries, mypath, APR_HASH_KEY_STRING, pb);
return SVN_NO_ERROR;
}
static svn_error_t *
add_directory (const char *path,
void *parent_baton,
const char *copyfrom_path,
svn_revnum_t copyfrom_rev,
apr_pool_t *pool,
void **child_baton)
{
struct dir_baton *pb = parent_baton;
struct edit_baton *eb = pb->edit_baton;
void *val;
svn_boolean_t is_copy = FALSE;
struct dir_baton *new_db
= make_dir_baton (path, copyfrom_path, copyfrom_rev, eb, pb, TRUE, pool);
/* This might be a replacement -- is the path already deleted? */
val = apr_hash_get (pb->deleted_entries, path, APR_HASH_KEY_STRING);
/* Detect an add-with-history. */
is_copy = ARE_VALID_COPY_ARGS (copyfrom_path, copyfrom_rev) ? TRUE : FALSE;
/* Dump the node. */
SVN_ERR (dump_node (eb, path,
svn_node_dir,
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);
new_db->written_out = TRUE;
*child_baton = new_db;
return SVN_NO_ERROR;
}
static svn_error_t *
open_directory (const char *path,
void *parent_baton,
svn_revnum_t base_revision,
apr_pool_t *pool,
void **child_baton)
{
struct dir_baton *pb = parent_baton;
struct edit_baton *eb = pb->edit_baton;
struct dir_baton *new_db;
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;
}
new_db = make_dir_baton (path, cmp_path, cmp_rev, eb, pb, FALSE, pool);
*child_baton = new_db;
return SVN_NO_ERROR;
}
static svn_error_t *
close_directory (void *dir_baton,
apr_pool_t *pool)
{
struct dir_baton *db = dir_baton;
struct edit_baton *eb = db->edit_baton;
apr_hash_index_t *hi;
apr_pool_t *subpool = svn_pool_create (pool);
for (hi = apr_hash_first (pool, db->deleted_entries);
hi;
hi = apr_hash_next (hi))
{
const void *key;
const char *path;
apr_hash_this (hi, &key, NULL, NULL);
path = key;
/* By sending 'svn_node_unknown', the Node-kind: header simply won't
be written out. No big deal at all, really. The loader
shouldn't care. */
SVN_ERR (dump_node (eb, path,
svn_node_unknown, svn_node_action_delete,
FALSE, NULL, SVN_INVALID_REVNUM, subpool));
svn_pool_clear (subpool);
}
svn_pool_destroy (subpool);
return SVN_NO_ERROR;
}
static svn_error_t *
add_file (const char *path,
void *parent_baton,
const char *copyfrom_path,
svn_revnum_t copyfrom_rev,
apr_pool_t *pool,
void **file_baton)
{
struct dir_baton *pb = parent_baton;
struct edit_baton *eb = pb->edit_baton;
void *val;
svn_boolean_t is_copy = FALSE;
/* This might be a replacement -- is the path already deleted? */
val = apr_hash_get (pb->deleted_entries, path, APR_HASH_KEY_STRING);
/* Detect add-with-history. */
is_copy = ARE_VALID_COPY_ARGS (copyfrom_path, copyfrom_rev) ? TRUE : FALSE;
/* Dump the node. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -