[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

[PATCH 08/13] Implement dump_node

From: Ramkumar Ramachandra <artagnon_at_gmail.com>
Date: Wed, 7 Jul 2010 02:14:48 +0200

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 <artagnon_at_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
Received on 2010-07-07 02:15:09 CEST

This is an archived mail posted to the Subversion Dev mailing list.