mark parsing in fast-import
Hallo Shawn,
Shawn O. Pearce schrieb am Mon 14. Apr, 19:29 (-0400):
Show 14 quoted lines
> Jrg Sommer <joerg@alea.gnuu.de> wrote:
> > The format of the marks is as close as possible to the format of the
> > marks used by fast-export and fast-import,
>
> Yay.
>
> > i.e. :001 == :1 and
> > “:12a” == :12. It differs from the format of fast-import in that point
> > that it requires a digit after the colon, i.e. “:abc” != :0 and “:-12”
> > and “:+12” aren't allowed.
>
> Uh, that's a bug in fast-import. ":4abc" is _not_ a mark if you
> read the language specification. Only ":4" is a mark. So we are
> accepting crap and reading it in odd ways. Not good.
diff --git a/fast-import.c b/fast-import.c
index 73e5439..f60e4ab 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -1690,10 +1690,31 @@ static void skip_optional_lf(void)
ungetc(term_char, stdin);
}
+static inline int parse_mark(const const char *str, uintmax_t* mark,
+ char **after_mark)
+{
+ if (!str || str[0] != ':' || !isdigit(str[1]))
+ return 1;
+
+ char *am;
+ const uintmax_t m = strtoumax(&str[1], &am, 10);
+ if (errno == 0) {
+ *mark = m;
+ *after_mark = am;
+ return 0;
+ }
+ return 1;
+}
+
static void cmd_mark(void)
{
- if (!prefixcmp(command_buf.buf, "mark :")) {
- next_mark = strtoumax(command_buf.buf + 6, NULL, 10);
+ uintmax_t mark = 0;
+ char *after_mark = NULL;
+
+ if (!prefixcmp(command_buf.buf, "mark ") &&
+ parse_mark(&command_buf.buf[5], &mark, &after_mark) &&
+ *after_mark == '\0') {
+ next_mark = mark;
read_next_command();
}
else
@@ -1878,7 +1899,10 @@ static void file_change_m(struct branch *b)
if (*p == ':') {
char *x;
- oe = find_mark(strtoumax(p + 1, &x, 10));
+ uintmax_t m;
+ if (parse_mark(p, &m, &x))
+ die("Invalid mark: %s", p);
+ oe = find_mark(m);
hashcpy(sha1, oe->sha1);
p = x;
} else if (!prefixcmp(p, "inline")) {
@@ -2045,7 +2069,11 @@ static int cmd_from(struct branch *b)
hashcpy(b->branch_tree.versions[0].sha1, t);
hashcpy(b->branch_tree.versions[1].sha1, t);
} else if (*from == ':') {
- uintmax_t idnum = strtoumax(from + 1, NULL, 10);
+ char *after_mark;
+ uintmax_t idnum;
+ if (parse_mark(from, &idnum, &after_mark) ||
+ *after_mark != '\0')
+ die("Not a valid mark: %s", from);
struct object_entry *oe = find_mark(idnum);
if (oe->type != OBJ_COMMIT)
die("Mark :%" PRIuMAX " not a commit", idnum);
@@ -2080,7 +2108,11 @@ static struct hash_list *cmd_merge(unsigned int *count)
if (s)
hashcpy(n->sha1, s->sha1);
else if (*from == ':') {
- uintmax_t idnum = strtoumax(from + 1, NULL, 10);
+ char *after_mark;
+ uintmax_t idnum;
+ if (parse_mark(from, &idnum, &after_mark) ||
+ *after_mark != '\0')
+ die("Not a valid mark: %s", from);
struct object_entry *oe = find_mark(idnum);
if (oe->type != OBJ_COMMIT)
die("Mark :%" PRIuMAX " not a commit", idnum);
@@ -2228,7 +2260,10 @@ static void cmd_new_tag(void)
hashcpy(sha1, s->sha1);
} else if (*from == ':') {
struct object_entry *oe;
- from_mark = strtoumax(from + 1, NULL, 10);
+ char *after_mark;
+ if (parse_mark(from, &from_mark, &after_mark) ||
+ *after_mark != '\0')
+ die("Not a valid mark: %s", from);
oe = find_mark(from_mark);
if (oe->type != OBJ_COMMIT)
die("Mark :%" PRIuMAX " not a commit", from_mark);
@@ -2333,9 +2368,8 @@ static void import_marks(const char *input_file)
if (line[0] != ':' || !end)
die("corrupt mark line: %s", line);
*end = 0;
- mark = strtoumax(line + 1, &end, 10);
- if (!mark || end == line + 1
- || *end != ' ' || get_sha1(end + 1, sha1))
+ if (parse_mark(line, &mark, &end) || !mark ||
+ *end != ' ' || get_sha1(end + 1, sha1))
die("corrupt mark line: %s", line);
e = find_object(sha1);
if (!e) {
Bye, Jörg.
--
Wer eher stirbt ist länger tot.
(Un B. Kant)