12
static int dump_from_file;
13
static const char *private_ref;
14
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; };
17
18
static int cmd_capabilities(const char *line);
19
static int cmd_import(const char *line);
49
fflush(stdout);
50
}
51
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
+
99
static int cmd_import(const char *line)
100
{
101
int code;
102
int dumpin_fd;
55
- unsigned int startrev = 0;
103
+ char *note_msg;
104
+ unsigned char head_sha1[20];
105
+ unsigned int startrev;
106
struct argv_array svndump_argv = ARGV_ARRAY_INIT;
107
struct child_process svndump_proc;
108
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, ¬e))
119
+ die("Revision number couldn't be parsed from note.");
120
+ startrev = note.rev_nr + 1;
121
+ free(note_msg);
122
+ }
123
+ }
124
+
125
if (dump_from_file) {
126
dumpin_fd = open(url, O_RDONLY);
127
if(dumpin_fd < 0)
145
"feature export-marks=%s\n", marksfilename, marksfilename);
146
147
svndump_init_fd(dumpin_fd, STDIN_FILENO);
82
- svndump_read(url, private_ref);
148
+ svndump_read(url, private_ref, notes_ref);
149
svndump_deinit();
150
svndump_reset();
151
216
int main(int argc, const char **argv)
217
{
218
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;
221
static struct remote *remote;
222
const char *url_in;
223
243
strbuf_addf(&private_ref_sb, "refs/svn/%s/master", remote->name);
244
private_ref = private_ref_sb.buf;
245
246
+ strbuf_addf(¬es_ref_sb, "refs/notes/%s/revs", remote->name);
247
+ notes_ref = notes_ref_sb.buf;
248
+
249
strbuf_addf(&marksfilename_sb, "%s/info/fast-import/remote-svn/%s.marks",
250
get_git_dir(), remote->name);
251
marksfilename = marksfilename_sb.buf;
265
strbuf_release(&buf);
266
strbuf_release(&url_sb);
267
strbuf_release(&private_ref_sb);
268
+ strbuf_release(¬es_ref_sb);
269
strbuf_release(&marksfilename_sb);
270
return 0;
271
}