📄 dump.c
字号:
/* a simple delete+add, implied by a single 'replace' action. */ SVN_ERR(svn_stream_printf(eb->stream, pool, SVN_REPOS_DUMPFILE_NODE_ACTION ": replace\n")); /* 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.*/ 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) { 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) { 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) SVN_ERR(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)); 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. */ len = 2; return svn_stream_write(eb->stream, "\n\n", &len); /* ### needed? */ } /*** 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)); 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; 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 an 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)); 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; 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) 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 sum of the text and prop contents lengths. We write this only for the benefit of non-Subversion RFC-822 parsers. */ 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) { len = propstring->len; SVN_ERR(svn_stream_write(eb->stream, propstring->data, &len)); } /* Dump text content */ if (must_dump_text && (kind == svn_node_file)) { 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)); } 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; svn_pool_clear(subpool); /* 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_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. */ 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,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -