[WIP PATCH 2/7] Add stripped dump editor

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Replace the default editor with a dump editor from libsvn_repos/dump.c
after stripping off filesystem dependencies. Currently, the dump
editor does nothing, but will dump some revision information to stdout
in future.

Signed-off-by: Ramkumar Ramachandra <artagnon@xxxxxxxxx>
---
 Makefile       |    2 +-
 dump_editor.c  |  365 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 dump_editor.h  |   10 ++
 svnclient_ra.c |   19 ++-
 4 files changed, 389 insertions(+), 7 deletions(-)
 create mode 100644 dump_editor.c
 create mode 100644 dump_editor.h

diff --git a/Makefile b/Makefile
index c3c695c..269c406 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
 svnclient_ra: *.c *.h
-	$(CC) -Wall -Werror -ggdb3 -O0 -o $@ svnclient_ra.c debug_editor.c -lsvn_client-1 -I. -I/usr/local/include/subversion-1 -I/usr/include/apr-1.0
+	$(CC) -Wall -ggdb3 -O0 -o $@ svnclient_ra.c debug_editor.c dump_editor.c -lsvn_client-1 -I. -I/usr/local/include/subversion-1 -I/usr/include/apr-1.0
 clean:
 	$(RM) svnclient_ra
diff --git a/dump_editor.c b/dump_editor.c
new file mode 100644
index 0000000..f5353b0
--- /dev/null
+++ b/dump_editor.c
@@ -0,0 +1,365 @@
+#include "svn_pools.h"
+#include "svn_error.h"
+#include "svn_iter.h"
+#include "svn_repos.h"
+#include "svn_string.h"
+#include "svn_dirent_uri.h"
+#include "svn_path.h"
+#include "svn_time.h"
+#include "svn_checksum.h"
+#include "svn_props.h"
+
+#define ARE_VALID_COPY_ARGS(p,r) ((p) && SVN_IS_VALID_REVNUM(r))
+/*----------------------------------------------------------------------*/
+/** An editor which dumps node-data in 'dumpfile format' to a file. **/
+
+/* Look, mom!  No file batons! */
+
+struct edit_baton
+{
+	/* The stream to dump to: stdout */
+	svn_stream_t *stream;
+	
+	svn_revnum_t current_rev;
+	
+	/* reusable buffer for writing file contents */
+	char buffer[SVN__STREAM_CHUNK_SIZE];
+	apr_size_t bufsize;
+};
+
+struct dir_baton
+{
+	struct edit_baton *edit_baton;
+	struct dir_baton *parent_dir_baton;
+
+	/* is this directory a new addition to this revision? */
+	svn_boolean_t added;
+
+	/* has this directory been written to the output stream? */
+	svn_boolean_t written_out;
+
+	/* the absolute path to this directory */
+	const char *path;
+
+	/* the comparison path and revision of this directory.  if both of
+	   these are valid, use them as a source against which to compare
+	   the directory instead of the default comparison source of PATH in
+	   the previous revision. */
+	const char *cmp_path;
+	svn_revnum_t cmp_rev;
+
+	/* hash of paths that need to be deleted, though some -might- be
+	   replaced.  maps const char * paths to this dir_baton.  (they're
+	   full paths, because that's what the editor driver gives us.  but
+	   really, they're all within this directory.) */
+	apr_hash_t *deleted_entries;
+
+	/* pool to be used for deleting the hash items */
+	apr_pool_t *pool;
+};
+
+
+/* Make a directory baton to represent the directory was path
+   (relative to EDIT_BATON's path) is PATH.
+
+   CMP_PATH/CMP_REV are the path/revision against which this directory
+   should be compared for changes.  If either is omitted (NULL for the
+   path, SVN_INVALID_REVNUM for the rev), just compare this directory
+   PATH against itself in the previous revision.
+
+   PARENT_DIR_BATON is the directory baton of this directory's parent,
+   or NULL if this is the top-level directory of the edit.  ADDED
+   indicated if this directory is newly added in this revision.
+   Perform all allocations in POOL.  */
+struct dir_baton *
+make_dir_baton(const char *path,
+               const char *cmp_path,
+               svn_revnum_t cmp_rev,
+               void *edit_baton,
+               void *parent_dir_baton,
+               svn_boolean_t added,
+               apr_pool_t *pool)
+{
+	struct edit_baton *eb = edit_baton;
+	struct dir_baton *pb = parent_dir_baton;
+	struct dir_baton *new_db = apr_pcalloc(pool, sizeof(*new_db));
+	const char *full_path;
+
+	/* A path relative to nothing?  I don't think so. */
+	SVN_ERR_ASSERT_NO_RETURN(!path || pb);
+
+	/* Construct the full path of this node. */
+	if (pb)
+		full_path = svn_path_join("/", path, pool);
+	else
+		full_path = apr_pstrdup(pool, "/");
+
+	/* Remove leading slashes from copyfrom paths. */
+	if (cmp_path)
+		cmp_path = ((*cmp_path == '/') ? cmp_path + 1 : cmp_path);
+
+	new_db->edit_baton = eb;
+	new_db->parent_dir_baton = pb;
+	new_db->path = full_path;
+	new_db->cmp_path = cmp_path ? apr_pstrdup(pool, cmp_path) : NULL;
+	new_db->cmp_rev = cmp_rev;
+	new_db->added = added;
+	new_db->written_out = FALSE;
+	new_db->deleted_entries = apr_hash_make(pool);
+	new_db->pool = pool;
+
+	return new_db;
+}
+
+
+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;
+}
+
+
+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;
+}
+
+
+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);
+
+	/* 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;
+}
+
+
+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_dirent_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;
+}
+
+
+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;
+}
+
+
+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);
+
+	/* 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, */
+	/*                   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;
+}
+
+
+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_dirent_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;
+}
+
+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;
+}
+
+svn_error_t *
+get_dump_editor(const svn_delta_editor_t **editor,
+                void **edit_baton,
+                svn_revnum_t to_rev,
+                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. */
+	svn_stream_for_stdout(&(eb->stream), pool);
+	eb->bufsize = sizeof(eb->buffer);
+	eb->current_rev = to_rev;
+
+
+	/* 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;
+}
diff --git a/dump_editor.h b/dump_editor.h
new file mode 100644
index 0000000..5e84223
--- /dev/null
+++ b/dump_editor.h
@@ -0,0 +1,10 @@
+#include "svn_pools.h"
+#include "svn_cmdline.h"
+#include "svn_client.h"
+#include "svn_ra.h"
+
+svn_error_t *
+get_dump_editor(const svn_delta_editor_t **editor,
+                void **edit_baton,
+                svn_revnum_t to_rev,
+                apr_pool_t *pool);
diff --git a/svnclient_ra.c b/svnclient_ra.c
index 2ed04af..24d99cb 100644
--- a/svnclient_ra.c
+++ b/svnclient_ra.c
@@ -4,6 +4,7 @@
 #include "svn_ra.h"
 
 #include "debug_editor.h"
+#include "dump_editor.h"
 
 static apr_pool_t *pool = NULL;
 static svn_client_ctx_t *ctx = NULL;
@@ -92,16 +93,22 @@ svn_error_t *open_connection(const char *url)
 
 svn_error_t *replay_range(svn_revnum_t start_revision, svn_revnum_t end_revision)
 {
+	svn_delta_editor_t *dump_editor, *debug_editor;
+	void *debug_baton, *dump_baton;
+	
 	svn_revnum_t latest_revision;
-	svn_delta_editor_t *editor, *debug_editor;
-	replay_baton_t *replay_baton = apr_palloc(pool, sizeof(replay_baton_t));
-	void *debug_baton;
 	SVN_ERR(svn_ra_get_latest_revnum(session, &latest_revision, pool));
 	printf("%ld\n", latest_revision);
-	editor = svn_delta_default_editor(pool);
+	
+	SVN_ERR(get_dump_editor((const svn_delta_editor_t **)&dump_editor,
+	                        &dump_baton, end_revision, pool));
+
 	SVN_ERR(svn_delta__get_debug_editor((const svn_delta_editor_t **)&debug_editor,
-	                                    &debug_baton, editor,
-	                                    NULL, pool));
+	                                    &debug_baton,
+	                                    (const svn_delta_editor_t *)dump_editor,
+	                                    dump_baton, pool));
+	
+	replay_baton_t *replay_baton = apr_palloc(pool, sizeof(replay_baton_t));
 	replay_baton->editor = debug_editor;
 	replay_baton->baton = debug_baton;
 	SVN_ERR(svn_ra_replay_range(session, start_revision, end_revision,
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]