From: Ramkumar Ramachandra <artagnon@gmail.com>
To: "Git Mailing List" <git@vger.kernel.org>
Cc: David Michael Barr <david.barr@cordelta.com>,
Jonathan Nieder <jrnieder@gmail.com>,
Sverre Rabbelier <srabbelier@gmail.com>,
Daniel Shahaf <daniel@shahaf.name>
Subject: [WIP PATCH 2/7] Add stripped dump editor
Date: Wed, 23 Jun 2010 18:22:15 +0200 [thread overview]
Message-ID: <1277310140-16891-3-git-send-email-artagnon@gmail.com> (raw)
In-Reply-To: <1277310140-16891-1-git-send-email-artagnon@gmail.com>
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@gmail.com>
---
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
next prev parent reply other threads:[~2010-06-23 16:21 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-06-23 16:22 [GSoC update] git-remote-svn: Week 8 Ramkumar Ramachandra
2010-06-23 16:22 ` [WIP PATCH 1/7] Add skeleton RA svnclient Ramkumar Ramachandra
2010-06-25 0:14 ` Jonathan Nieder
2010-06-25 9:07 ` Daniel Shahaf
2010-06-25 11:07 ` Ramkumar Ramachandra
2010-06-25 11:30 ` Daniel Shahaf
2010-06-25 15:30 ` OT: typesafe callbacks in C (Re: [WIP PATCH 1/7] Add skeleton RA svnclient) Jonathan Nieder
2010-06-25 14:45 ` [WIP PATCH 1/7] Add skeleton RA svnclient Jonathan Nieder
2010-06-25 13:34 ` Jonathan Nieder
2010-06-23 16:22 ` Ramkumar Ramachandra [this message]
2010-06-23 16:22 ` [WIP PATCH 3/7] Import dump_node to dump what changed and cleanup whitespace Ramkumar Ramachandra
2010-06-23 17:05 ` Ramkumar Ramachandra
2010-06-23 16:22 ` [WIP PATCH 4/7] Replace deprecated svn_path_join Ramkumar Ramachandra
2010-06-23 16:22 ` [WIP PATCH 5/7] Trigger dump_node in change_dir_prop Ramkumar Ramachandra
2010-06-23 16:22 ` [WIP PATCH 6/7] Add file_baton and trigger dump_node in change_file_prop Ramkumar Ramachandra
2010-06-23 16:22 ` [WIP PATCH 7/7] Dump the text delta Ramkumar Ramachandra
2010-06-23 17:18 ` [GSoC update] git-remote-svn: Week 8 Ramkumar Ramachandra
2010-06-25 0:42 ` Jonathan Nieder
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1277310140-16891-3-git-send-email-artagnon@gmail.com \
--to=artagnon@gmail.com \
--cc=daniel@shahaf.name \
--cc=david.barr@cordelta.com \
--cc=git@vger.kernel.org \
--cc=jrnieder@gmail.com \
--cc=srabbelier@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).