You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@subversion.apache.org by Ramkumar Ramachandra <ar...@gmail.com> on 2010/07/07 00:14:48 UTC
[PATCH 08/13] Implement dump_node
Add a new dump_node function to dump node headers Node-path,
Node-kind, Node-action and set the right variables to trigger dumping
properties. Copies are also handled appropriately using eb->is_copy,
copyfrom_path, copyfrom_rev informatino from the caller. Also add a
related dump_props helper function that uses write_hash_to_stringbuf
to dump properties.
Signed-off-by: Ramkumar Ramachandra <ar...@gmail.com>
---
dump_editor.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
dumpr_util.c | 48 +++++++++++++++++++++
dumpr_util.h | 5 ++
3 files changed, 185 insertions(+), 0 deletions(-)
diff --git a/dump_editor.c b/dump_editor.c
index 6e9b0f5..0f7d231 100644
--- a/dump_editor.c
+++ b/dump_editor.c
@@ -15,6 +15,10 @@
#include "dumpr_util.h"
+#define ARE_VALID_COPY_ARGS(p,r) ((p) && SVN_IS_VALID_REVNUM(r))
+
+svn_boolean_t must_dump_props = FALSE, must_dump_text = FALSE,
+ dump_props_pending = FALSE;
/* Make a directory baton to represent the directory was path
(relative to EDIT_BATON's path) is PATH.
@@ -70,6 +74,134 @@ struct dir_baton *make_dir_baton(const char *path,
return new_db;
}
+/*
+ * Write out a node record for PATH of type KIND under EB->FS_ROOT.
+ * ACTION describes what is happening to the node (see enum svn_node_action).
+ * Write record to writable EB->STREAM, using EB->BUFFER to write in chunks.
+ *
+ * If the node was itself copied, IS_COPY is TRUE and the
+ * path/revision of the copy source are in CMP_PATH/CMP_REV. If
+ * IS_COPY is FALSE, yet CMP_PATH/CMP_REV are valid, this node is part
+ * of a copied subtree.
+ */
+svn_error_t *dump_node(struct edit_baton *eb,
+ const char *path, /* an absolute path. */
+ svn_node_kind_t kind,
+ enum svn_node_action action,
+ const char *cmp_path,
+ svn_revnum_t cmp_rev,
+ apr_pool_t *pool)
+{
+ /* Some pending properties to dump? */
+ SVN_ERR(dump_props(eb, &dump_props_pending, TRUE, pool));
+
+ /* Write out metadata headers for this file node. */
+ SVN_ERR(svn_stream_printf(eb->stream, pool,
+ SVN_REPOS_DUMPFILE_NODE_PATH ": %s\n",
+ (*path == '/') ? path + 1 : path));
+
+ if (kind == svn_node_file)
+ SVN_ERR(svn_stream_printf(eb->stream, pool,
+ SVN_REPOS_DUMPFILE_NODE_KIND ": file\n"));
+ else if (kind == svn_node_dir)
+ SVN_ERR(svn_stream_printf(eb->stream, pool,
+ SVN_REPOS_DUMPFILE_NODE_KIND ": dir\n"));
+
+ /* Remove leading slashes from copyfrom paths. */
+ if (cmp_path)
+ cmp_path = ((*cmp_path == '/') ? cmp_path + 1 : cmp_path);
+
+ switch (action) {
+ /* Appropriately handle the four svn_node_action actions */
+
+ case svn_node_action_change:
+ SVN_ERR(svn_stream_printf(eb->stream, pool,
+ SVN_REPOS_DUMPFILE_NODE_ACTION
+ ": change\n"));
+ break;
+
+ case svn_node_action_replace:
+ if (!eb->is_copy) {
+ /* 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. */
+ must_dump_props = TRUE;
+ break;
+ }
+ /* More complex case: eb->is_copy is true, and
+ cmp_path/ cmp_rev are present: delete the original,
+ and then re-add it */
+
+ /* 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,
+ cmp_path, cmp_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_props = FALSE;
+ eb->is_copy = FALSE;
+ break;
+
+ case 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. */
+ SVN_ERR(svn_stream_printf(eb->stream, pool, "\n\n"));
+ must_dump_props = FALSE;
+ break;
+
+ case svn_node_action_add:
+ SVN_ERR(svn_stream_printf(eb->stream, pool,
+ SVN_REPOS_DUMPFILE_NODE_ACTION ": add\n"));
+
+ if (!eb->is_copy) {
+ /* If it's a file or directory not copied from
+ somewhere, wait for change_file_prop or
+ change_directory_prop */
+ dump_props_pending = TRUE;
+ break;
+ }
+
+ 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));
+
+ /* Dump the text only if apply_textdelta sets
+ must_dump_text */
+
+ /* UGLY hack: If a directory was copied from a
+ previous revision, nothing else can be done, and
+ close_file won't be called to write two blank
+ lines; write them here */
+ if (kind == svn_node_dir)
+ SVN_ERR(svn_stream_printf(eb->stream, pool, "\n\n"));
+
+ eb->is_copy = FALSE;
+
+ break;
+ }
+
+ /* Dump property headers */
+ SVN_ERR(dump_props(eb, &must_dump_props, FALSE, pool));
+
+ return SVN_NO_ERROR;
+}
+
svn_error_t *open_root(void *edit_baton,
svn_revnum_t base_revision,
apr_pool_t *pool,
diff --git a/dumpr_util.c b/dumpr_util.c
index 41940d4..a3328b6 100644
--- a/dumpr_util.c
+++ b/dumpr_util.c
@@ -62,3 +62,51 @@ void write_hash_to_stringbuf(apr_hash_t *properties,
}
}
}
+
+svn_error_t *dump_props(struct edit_baton *eb,
+ svn_boolean_t *trigger_var,
+ svn_boolean_t dump_data_too,
+ apr_pool_t *pool)
+{
+ if (trigger_var && !*trigger_var)
+ return SVN_NO_ERROR;
+
+ /* Build a propstring to print */
+ svn_stringbuf_setempty(eb->propstring);
+ write_hash_to_stringbuf(eb->properties,
+ FALSE,
+ &(eb->propstring), eb->pool);
+ write_hash_to_stringbuf(eb->del_properties,
+ TRUE,
+ &(eb->propstring), eb->pool);
+ svn_stringbuf_appendbytes(eb->propstring, "PROPS-END\n", 10);
+
+ /* prop-delta header */
+ SVN_ERR(svn_stream_printf(eb->stream, pool,
+ SVN_REPOS_DUMPFILE_PROP_DELTA
+ ": true\n"));
+
+ /* prop-content-length header */
+ SVN_ERR(svn_stream_printf(eb->stream, pool,
+ SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH
+ ": %" APR_SIZE_T_FMT "\n", eb->propstring->len));
+
+ if (dump_data_too) {
+ /* content-length header */
+ SVN_ERR(svn_stream_printf(eb->stream, pool,
+ SVN_REPOS_DUMPFILE_CONTENT_LENGTH
+ ": %" APR_SIZE_T_FMT "\n\n",
+ eb->propstring->len));
+
+ /* the properties themselves */
+ SVN_ERR(svn_stream_write(eb->stream, eb->propstring->data,
+ &(eb->propstring->len)));
+
+ /* Cleanup so that data is never dumped twice */
+ apr_hash_clear(eb->properties);
+ apr_hash_clear(eb->del_properties);
+ if (trigger_var)
+ *trigger_var = FALSE;
+ }
+ return SVN_NO_ERROR;
+}
diff --git a/dumpr_util.h b/dumpr_util.h
index 96670ff..79de1ab 100644
--- a/dumpr_util.h
+++ b/dumpr_util.h
@@ -66,4 +66,9 @@ void write_hash_to_stringbuf(apr_hash_t *properties,
svn_stringbuf_t **strbuf,
apr_pool_t *pool);
+svn_error_t *dump_props(struct edit_baton *eb,
+ svn_boolean_t *trigger_var,
+ svn_boolean_t dump_data_too,
+ apr_pool_t *pool);
+
#endif
--
1.7.1