[PATCH v3 05/10] vcs-svn: move commit parameters logic to svndump.c
fast_export.c had logic to set up commit ref, author name, email, parent commit, import mark and git-svn-id: line based on both it's own state (current import batch history) and the arguments passed.
Do separate the layers: make fast_export focus on producing the fast-import stream, applying the deltas but not on svn-fe specific logic. svndump now is responsible for choosing commit parents, marks, ref name. Making it possible to generate incremental streams, produce stream for several branches at a time, customize progress lines generation and adding new logic becomes easier.
fast_export API changes:
- make fast_export_begin_commit to be more intuitive by using a set of
parameters closer to what gets written to fast-import.
- rename fast_export_end_commit to fast_export_progress as it does only
a progress line generation. fast_export_end_commit can be reintroduced
once the need will arise.
- git-svn-id line is now a caller concern. If it is needed, it should be
simply appended to the log message.
- author_name and author_email are now generated by the caller.
- ref name to be updated with the commit is now a parameter rather than
a fixed "refs/heads/master".
The caller now may have to setup temporary buffers for author identity, ref names, etc. This is a small additional per-commit cost to arrange and/or copy them. Though, it's only per-commit rather that per-path and might be worth the gain in readablity.
Signed-off-by: Dmitry Ivankov <divanorama@gmail.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
vcs-svn/fast_export.c | 47 +++++++++++++----------------------------------
vcs-svn/fast_export.h | 8 ++++----
vcs-svn/svndump.c | 44 +++++++++++++++++++++++++++++++++++++++-----
3 files changed, 56 insertions(+), 43 deletions(-)
Show changes to 3 files +56 −43
vcs-svn/fast_export.c, vcs-svn/fast_export.h, vcs-svn/svndump.c
diff --git a/vcs-svn/fast_export.c b/vcs-svn/fast_export.c
index 19d7c34..3dfccd2 100644
--- a/vcs-svn/fast_export.c
+++ b/vcs-svn/fast_export.c
@@ -13,9 +13,6 @@
#include "sliding_window.h"
#include "line_buffer.h"
-#define MAX_GITSVN_LINE_LEN 4096
-
-static uint32_t first_commit_done;
static struct line_buffer postimage = LINE_BUFFER_INIT;
static struct line_buffer report_buffer = LINE_BUFFER_INIT;
@@ -31,7 +28,6 @@ static int init_postimage(void)
void fast_export_init(int fd)
{
- first_commit_done = 0;
if (buffer_fdinit(&report_buffer, fd))
die_errno("cannot read from file descriptor %d", fd);
}
@@ -73,40 +69,23 @@ void fast_export_modify(const char *path, uint32_t mode, const char *dataref)
putchar('\n');
}
-static char gitsvnline[MAX_GITSVN_LINE_LEN];
-void fast_export_begin_commit(uint32_t revision, const char *author,
- const struct strbuf *log,
- const char *uuid, const char *url,
- unsigned long timestamp)
+void fast_export_begin_commit(const char *ref, uint32_t mark, const char *from,
+ const char *author_name, const char *author_email,
+ const struct strbuf *log, unsigned long timestamp)
{
- static const struct strbuf empty = STRBUF_INIT;
- if (!log)
- log = ∅
- if (*uuid && *url) {
- snprintf(gitsvnline, MAX_GITSVN_LINE_LEN,
- "\n\ngit-svn-id: %s@%"PRIu32" %s\n",
- url, revision, uuid);
- } else {
- *gitsvnline = '\0';
- }
- printf("commit refs/heads/master\n");
- printf("mark :%"PRIu32"\n", revision);
- printf("committer %s <%s@%s> %ld +0000\n",
- *author ? author : "nobody",
- *author ? author : "nobody",
- *uuid ? uuid : "local", timestamp);
- printf("data %"PRIuMAX"\n",
- (uintmax_t) (log->len + strlen(gitsvnline)));
+ printf("commit %s\n", ref);
+ if (mark)
+ printf("mark :%"PRIu32"\n", mark);
+ printf("committer %s <%s> %ld +0000\n",
+ author_name, author_email, timestamp);
+ printf("data %"PRIuMAX"\n", (uintmax_t) log->len);
fwrite(log->buf, log->len, 1, stdout);
- printf("%s\n", gitsvnline);
- if (!first_commit_done) {
- if (revision > 1)
- printf("from :%"PRIu32"\n", revision - 1);
- first_commit_done = 1;
- }
+ putchar('\n');
+ if (from && *from)
+ printf("from %s\n", from);
}
-void fast_export_end_commit(uint32_t revision)
+void fast_export_progress(uint32_t revision)
{
printf("progress Imported commit %"PRIu32".\n\n", revision);
}
diff --git a/vcs-svn/fast_export.h b/vcs-svn/fast_export.h
index 43d05b6..bf58880 100644
--- a/vcs-svn/fast_export.h
+++ b/vcs-svn/fast_export.h
@@ -10,10 +10,10 @@ void fast_export_reset(void);
void fast_export_delete(const char *path);
void fast_export_modify(const char *path, uint32_t mode, const char *dataref);
-void fast_export_begin_commit(uint32_t revision, const char *author,
- const struct strbuf *log, const char *uuid,
- const char *url, unsigned long timestamp);
-void fast_export_end_commit(uint32_t revision);
+void fast_export_begin_commit(const char *ref, uint32_t mark, const char *from,
+ const char *author_name, const char *author_email,
+ const struct strbuf *log, unsigned long timestamp);
+void fast_export_progress(uint32_t revision);
void fast_export_data(uint32_t mode, uint32_t len, struct line_buffer *input);
void fast_export_blob_delta(uint32_t mode,
uint32_t old_mode, const char *old_data,
diff --git a/vcs-svn/svndump.c b/vcs-svn/svndump.c
index 5cdf6b8..28d84c9 100644
--- a/vcs-svn/svndump.c
+++ b/vcs-svn/svndump.c
@@ -37,6 +37,8 @@
#define LENGTH_UNKNOWN (~0)
#define DATE_RFC2822_LEN 31
+#define MAX_GITSVN_LINE_LEN 4096
+
static struct line_buffer input = LINE_BUFFER_INIT;
static struct {
@@ -54,6 +56,7 @@ static struct {
static struct {
uint32_t version;
struct strbuf uuid, url;
+ int first_commit_done;
} dump_ctx;
static void reset_node_ctx(char *fname)
@@ -86,6 +89,7 @@ static void reset_dump_ctx(const char *url)
strbuf_addstr(&dump_ctx.url, url);
dump_ctx.version = 1;
strbuf_reset(&dump_ctx.uuid);
+ dump_ctx.first_commit_done = 0;
}
static void handle_property(const struct strbuf *key_buf,
@@ -299,19 +303,49 @@ static void handle_node(void)
node_ctx.textLength, &input);
}
+static void add_metadata_trailer(struct strbuf *buf)
+{
+ if (*dump_ctx.uuid.buf && *dump_ctx.url.buf)
+ strbuf_addf(buf, "\n\ngit-svn-id: %s@%"PRIu32" %s\n",
+ dump_ctx.url.buf, rev_ctx.revision, dump_ctx.uuid.buf);
+}
+
static void begin_revision(void)
{
+ static struct strbuf email;
+ const char *author;
+ uint32_t prev;
+ char buf[32];
+
if (!rev_ctx.revision) /* revision 0 gets no git commit. */
return;
- fast_export_begin_commit(rev_ctx.revision, rev_ctx.author.buf,
- &rev_ctx.log, dump_ctx.uuid.buf, dump_ctx.url.buf,
- rev_ctx.timestamp);
+ prev = dump_ctx.first_commit_done ? rev_ctx.revision - 1 : 0;
+ if (prev)
+ snprintf(buf, 32, ":%"PRIu32, prev);
+ else
+ *buf = 0;
+ author = *rev_ctx.author.buf ? rev_ctx.author.buf : "nobody";
+
+ strbuf_reset(&email);
+ strbuf_addstr(&email, author);
+ strbuf_addch(&email, '@');
+ if (*dump_ctx.uuid.buf)
+ strbuf_addstr(&email, dump_ctx.uuid.buf);
+ else
+ strbuf_addstr(&email, "local");
+
+ add_metadata_trailer(&rev_ctx.log);
+
+ fast_export_begin_commit("refs/heads/master", rev_ctx.revision, buf,
+ author, email.buf, &rev_ctx.log, rev_ctx.timestamp);
}
static void end_revision(void)
{
- if (rev_ctx.revision)
- fast_export_end_commit(rev_ctx.revision);
+ if (rev_ctx.revision) {
+ fast_export_progress(rev_ctx.revision);
+ dump_ctx.first_commit_done = 1;
+ }
}
void svndump_read(void)
--
1.7.3.4