Skip to content

Commit 8e43a1d

Browse files
flyingflogitster
authored andcommitted
remote-svn: add incremental import
Search for a note attached to the ref to update and read it's 'Revision-number:'-line. Start import from the next svn revision. If there is no next revision in the svn repo, svnrdump terminates with a message on stderr an non-zero return value. This looks a little weird, but there is no other way to know whether there is a new revision in the svn repo. On the start of an incremental import, the parent of the first commit in the fast-import stream is set to the branch name to update. All following commits specify their parent by a mark number. Previous mark files are currently not reused. Signed-off-by: Florian Achleitner <[email protected]> Acked-by: David Michael Barr <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 8d7cd8e commit 8e43a1d

File tree

7 files changed

+95
-17
lines changed

7 files changed

+95
-17
lines changed

contrib/svn-fe/svn-fe.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ int main(int argc, char **argv)
1010
{
1111
if (svndump_init(NULL))
1212
return 1;
13-
svndump_read((argc > 1) ? argv[1] : NULL, "refs/heads/master");
13+
svndump_read((argc > 1) ? argv[1] : NULL, "refs/heads/master",
14+
"refs/notes/svn/revs");
1415
svndump_deinit();
1516
svndump_reset();
1617
return 0;

remote-testsvn.c

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ static const char *url;
1212
static int dump_from_file;
1313
static const char *private_ref;
1414
static const char *remote_ref = "refs/heads/master";
15-
static const char *marksfilename;
15+
static const char *marksfilename, *notes_ref;
16+
struct rev_note { unsigned int rev_nr; };
1617

1718
static int cmd_capabilities(const char *line);
1819
static int cmd_import(const char *line);
@@ -48,14 +49,79 @@ static void terminate_batch(void)
4849
fflush(stdout);
4950
}
5051

52+
/* NOTE: 'ref' refers to a git reference, while 'rev' refers to a svn revision. */
53+
static char *read_ref_note(const unsigned char sha1[20])
54+
{
55+
const unsigned char *note_sha1;
56+
char *msg = NULL;
57+
unsigned long msglen;
58+
enum object_type type;
59+
60+
init_notes(NULL, notes_ref, NULL, 0);
61+
if (!(note_sha1 = get_note(NULL, sha1)))
62+
return NULL; /* note tree not found */
63+
if (!(msg = read_sha1_file(note_sha1, &type, &msglen)))
64+
error("Empty notes tree. %s", notes_ref);
65+
else if (!msglen || type != OBJ_BLOB) {
66+
error("Note contains unusable content. "
67+
"Is something else using this notes tree? %s", notes_ref);
68+
free(msg);
69+
msg = NULL;
70+
}
71+
free_notes(NULL);
72+
return msg;
73+
}
74+
75+
static int parse_rev_note(const char *msg, struct rev_note *res)
76+
{
77+
const char *key, *value, *end;
78+
size_t len;
79+
80+
while (*msg) {
81+
end = strchr(msg, '\n');
82+
len = end ? end - msg : strlen(msg);
83+
84+
key = "Revision-number: ";
85+
if (!prefixcmp(msg, key)) {
86+
long i;
87+
char *end;
88+
value = msg + strlen(key);
89+
i = strtol(value, &end, 0);
90+
if (end == value || i < 0 || i > UINT32_MAX)
91+
return -1;
92+
res->rev_nr = i;
93+
}
94+
msg += len + 1;
95+
}
96+
return 0;
97+
}
98+
5199
static int cmd_import(const char *line)
52100
{
53101
int code;
54102
int dumpin_fd;
55-
unsigned int startrev = 0;
103+
char *note_msg;
104+
unsigned char head_sha1[20];
105+
unsigned int startrev;
56106
struct argv_array svndump_argv = ARGV_ARRAY_INIT;
57107
struct child_process svndump_proc;
58108

109+
if (read_ref(private_ref, head_sha1))
110+
startrev = 0;
111+
else {
112+
note_msg = read_ref_note(head_sha1);
113+
if(note_msg == NULL) {
114+
warning("No note found for %s.", private_ref);
115+
startrev = 0;
116+
} else {
117+
struct rev_note note = { 0 };
118+
if (parse_rev_note(note_msg, &note))
119+
die("Revision number couldn't be parsed from note.");
120+
startrev = note.rev_nr + 1;
121+
free(note_msg);
122+
}
123+
}
124+
59125
if (dump_from_file) {
60126
dumpin_fd = open(url, O_RDONLY);
61127
if(dumpin_fd < 0)
@@ -79,7 +145,7 @@ static int cmd_import(const char *line)
79145
"feature export-marks=%s\n", marksfilename, marksfilename);
80146

81147
svndump_init_fd(dumpin_fd, STDIN_FILENO);
82-
svndump_read(url, private_ref);
148+
svndump_read(url, private_ref, notes_ref);
83149
svndump_deinit();
84150
svndump_reset();
85151

@@ -150,7 +216,8 @@ static int do_command(struct strbuf *line)
150216
int main(int argc, const char **argv)
151217
{
152218
struct strbuf buf = STRBUF_INIT, url_sb = STRBUF_INIT,
153-
private_ref_sb = STRBUF_INIT, marksfilename_sb = STRBUF_INIT;
219+
private_ref_sb = STRBUF_INIT, marksfilename_sb = STRBUF_INIT,
220+
notes_ref_sb = STRBUF_INIT;
154221
static struct remote *remote;
155222
const char *url_in;
156223

@@ -176,6 +243,9 @@ int main(int argc, const char **argv)
176243
strbuf_addf(&private_ref_sb, "refs/svn/%s/master", remote->name);
177244
private_ref = private_ref_sb.buf;
178245

246+
strbuf_addf(&notes_ref_sb, "refs/notes/%s/revs", remote->name);
247+
notes_ref = notes_ref_sb.buf;
248+
179249
strbuf_addf(&marksfilename_sb, "%s/info/fast-import/remote-svn/%s.marks",
180250
get_git_dir(), remote->name);
181251
marksfilename = marksfilename_sb.buf;
@@ -195,6 +265,7 @@ int main(int argc, const char **argv)
195265
strbuf_release(&buf);
196266
strbuf_release(&url_sb);
197267
strbuf_release(&private_ref_sb);
268+
strbuf_release(&notes_ref_sb);
198269
strbuf_release(&marksfilename_sb);
199270
return 0;
200271
}

test-svn-fe.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ int main(int argc, char *argv[])
4040
if (argc == 2) {
4141
if (svndump_init(argv[1]))
4242
return 1;
43-
svndump_read(NULL, "refs/heads/master");
43+
svndump_read(NULL, "refs/heads/master", "refs/notes/svn/revs");
4444
svndump_deinit();
4545
svndump_reset();
4646
return 0;

vcs-svn/fast_export.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,19 @@ void fast_export_modify(const char *path, uint32_t mode, const char *dataref)
6868
}
6969

7070
void fast_export_begin_note(uint32_t revision, const char *author,
71-
const char *log, unsigned long timestamp)
71+
const char *log, unsigned long timestamp, const char *note_ref)
7272
{
73+
static int firstnote = 1;
7374
size_t loglen = strlen(log);
74-
printf("commit refs/notes/svn/revs\n");
75+
printf("commit %s\n", note_ref);
7576
printf("committer %s <%s@%s> %ld +0000\n", author, author, "local", timestamp);
7677
printf("data %"PRIuMAX"\n", (uintmax_t)loglen);
7778
fwrite(log, loglen, 1, stdout);
79+
if (firstnote) {
80+
if (revision > 1)
81+
printf("from %s^0", note_ref);
82+
firstnote = 0;
83+
}
7884
fputc('\n', stdout);
7985
}
8086

vcs-svn/fast_export.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ void fast_export_delete(const char *path);
1111
void fast_export_modify(const char *path, uint32_t mode, const char *dataref);
1212
void fast_export_note(const char *committish, const char *dataref);
1313
void fast_export_begin_note(uint32_t revision, const char *author,
14-
const char *log, unsigned long timestamp);
14+
const char *log, unsigned long timestamp, const char *note_ref);
1515
void fast_export_begin_commit(uint32_t revision, const char *author,
16-
const struct strbuf *log, const char *uuid,
17-
const char *url, unsigned long timestamp, const char *local_ref);
16+
const struct strbuf *log, const char *uuid,const char *url,
17+
unsigned long timestamp, const char *local_ref);
1818
void fast_export_end_commit(uint32_t revision);
1919
void fast_export_data(uint32_t mode, off_t len, struct line_buffer *input);
2020
void fast_export_buf_to_data(const struct strbuf *data);

vcs-svn/svndump.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -309,20 +309,20 @@ static void begin_revision(const char *remote_ref)
309309
rev_ctx.timestamp, remote_ref);
310310
}
311311

312-
static void end_revision(void)
312+
static void end_revision(const char *note_ref)
313313
{
314314
struct strbuf mark = STRBUF_INIT;
315315
if (rev_ctx.revision) {
316316
fast_export_end_commit(rev_ctx.revision);
317317
fast_export_begin_note(rev_ctx.revision, "remote-svn",
318-
"Note created by remote-svn.", rev_ctx.timestamp);
318+
"Note created by remote-svn.", rev_ctx.timestamp, note_ref);
319319
strbuf_addf(&mark, ":%"PRIu32, rev_ctx.revision);
320320
fast_export_note(mark.buf, "inline");
321321
fast_export_buf_to_data(&rev_ctx.note);
322322
}
323323
}
324324

325-
void svndump_read(const char *url, const char *local_ref)
325+
void svndump_read(const char *url, const char *local_ref, const char *notes_ref)
326326
{
327327
char *val;
328328
char *t;
@@ -363,7 +363,7 @@ void svndump_read(const char *url, const char *local_ref)
363363
if (active_ctx == REV_CTX)
364364
begin_revision(local_ref);
365365
if (active_ctx != DUMP_CTX)
366-
end_revision();
366+
end_revision(notes_ref);
367367
active_ctx = REV_CTX;
368368
reset_rev_ctx(atoi(val));
369369
strbuf_addf(&rev_ctx.note, "%s\n", t);
@@ -479,7 +479,7 @@ void svndump_read(const char *url, const char *local_ref)
479479
if (active_ctx == REV_CTX)
480480
begin_revision(local_ref);
481481
if (active_ctx != DUMP_CTX)
482-
end_revision();
482+
end_revision(notes_ref);
483483
}
484484

485485
static void init(int report_fd)

vcs-svn/svndump.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
int svndump_init(const char *filename);
55
int svndump_init_fd(int in_fd, int back_fd);
6-
void svndump_read(const char *url, const char *local_ref);
6+
void svndump_read(const char *url, const char *local_ref, const char *notes_ref);
77
void svndump_deinit(void);
88
void svndump_reset(void);
99

0 commit comments

Comments
 (0)