Message ID | 20181018100023.7327-3-phillip.wood@talktalk.net (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | am/rebase: share read_author_script() | expand |
Phillip Wood <phillip.wood@talktalk.net> writes: > From: Phillip Wood <phillip.wood@dunelm.org.uk> > > If there are errors in a user edited author-script there was no > indication of what was wrong. This commit adds some specific error messages > depending on the problem. It also relaxes the requirement that the > variables appear in a specific order in the file to match the behavior > of 'rebase --interactive'. That relaxing is sensible; there is no reason to insist that the file we are reading was written by exactly the same writer as we have. > diff --git a/builtin/am.c b/builtin/am.c > index b68578bc3f..d42b725273 100644 > --- a/builtin/am.c > +++ b/builtin/am.c > @@ -270,8 +270,11 @@ static int parse_key_value_squoted(char *buf, struct string_list *list) > struct string_list_item *item; > char *np; > char *cp = strchr(buf, '='); > - if (!cp) > - return -1; > + if (!cp) { > + np = strchrnul(buf, '\n'); > + return error(_("unable to parse '%.*s'"), > + (int) (np - buf), buf); > + } We are unable to parse because it is not of KEY='VALUE' form. Is that something worth reporting, e.g. "no key present in '%.*s'"? > @@ -280,7 +283,8 @@ static int parse_key_value_squoted(char *buf, struct string_list *list) > *np = '\0'; > cp = sq_dequote(cp); > if (!cp) > - return -1; > + return error(_("unable to dequote value of '%s'"), > + item->string); At this point, item->string is what we earlier found on the left hand side of the '=', i.e. the key. The message makes sense. > @@ -308,6 +312,7 @@ static int read_author_script(struct am_state *state) > struct strbuf buf = STRBUF_INIT; > struct string_list kv = STRING_LIST_INIT_DUP; > int retval = -1; /* assume failure */ > + int i, name_i = -2, email_i = -2, date_i = -2, err = 0; That -2 is somewhat cute. If we find a dup, then it will become -1 so later check for missing field would not trigger. > @@ -326,14 +331,38 @@ static int read_author_script(struct am_state *state) > if (parse_key_value_squoted(buf.buf, &kv)) > goto finish; > > - if (kv.nr != 3 || > - strcmp(kv.items[0].string, "GIT_AUTHOR_NAME") || > - strcmp(kv.items[1].string, "GIT_AUTHOR_EMAIL") || > - strcmp(kv.items[2].string, "GIT_AUTHOR_DATE")) > + for (i = 0; i < kv.nr; i++) { > + if (!strcmp(kv.items[i].string, "GIT_AUTHOR_NAME")) { > + if (name_i >= 0) > + name_i = error(_("'GIT_AUTHOR_NAME' already given")); > + else > + name_i = i; However, if you have three instances of GIT_AUTHOR_NAME, then - the first one makes name_i point at it - the second one triggers an error and name_i becomes -1 - the third one makes name_i point at it again And name_i is not -2 so we won't give "missing" error, which is OK, but we end up having a usable name even though we said we detected duplicate! You can probably compare name_i with -2 when detecting the dup to fix it, i.e. if (name_i != -2) name_i = error("found dup"); else name_i = i; > + } else if (!strcmp(kv.items[i].string, "GIT_AUTHOR_EMAIL")) { > + if (email_i >= 0) > + email_i = error(_("'GIT_AUTHOR_EMAIL' already given")); > + else > + email_i = i; > + } else if (!strcmp(kv.items[i].string, "GIT_AUTHOR_DATE")) { > + if (date_i >= 0) > + date_i = error(_("'GIT_AUTHOR_DATE' already given")); > + else > + date_i = i; > + } else { > + err = error(_("unknown variable '%s'"), > + kv.items[i].string); > + } > + } > + if (name_i == -2) > + error(_("missing 'GIT_AUTHOR_NAME'")); > + if (email_i == -2) > + error(_("missing 'GIT_AUTHOR_EMAIL'")); > + if (date_i == -2) > + error(_("missing 'GIT_AUTHOR_DATE'")); > + if (date_i < 0 || email_i < 0 || date_i < 0 || err) > goto finish; > - state->author_name = kv.items[0].util; > - state->author_email = kv.items[1].util; > - state->author_date = kv.items[2].util; > + state->author_name = kv.items[name_i].util; > + state->author_email = kv.items[email_i].util; > + state->author_date = kv.items[date_i].util; > retval = 0; > finish: > string_list_clear(&kv, !!retval);
diff --git a/builtin/am.c b/builtin/am.c index b68578bc3f..d42b725273 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -270,8 +270,11 @@ static int parse_key_value_squoted(char *buf, struct string_list *list) struct string_list_item *item; char *np; char *cp = strchr(buf, '='); - if (!cp) - return -1; + if (!cp) { + np = strchrnul(buf, '\n'); + return error(_("unable to parse '%.*s'"), + (int) (np - buf), buf); + } np = strchrnul(cp, '\n'); *cp++ = '\0'; item = string_list_append(list, buf); @@ -280,7 +283,8 @@ static int parse_key_value_squoted(char *buf, struct string_list *list) *np = '\0'; cp = sq_dequote(cp); if (!cp) - return -1; + return error(_("unable to dequote value of '%s'"), + item->string); item->util = xstrdup(cp); } return 0; @@ -308,6 +312,7 @@ static int read_author_script(struct am_state *state) struct strbuf buf = STRBUF_INIT; struct string_list kv = STRING_LIST_INIT_DUP; int retval = -1; /* assume failure */ + int i, name_i = -2, email_i = -2, date_i = -2, err = 0; int fd; assert(!state->author_name); @@ -326,14 +331,38 @@ static int read_author_script(struct am_state *state) if (parse_key_value_squoted(buf.buf, &kv)) goto finish; - if (kv.nr != 3 || - strcmp(kv.items[0].string, "GIT_AUTHOR_NAME") || - strcmp(kv.items[1].string, "GIT_AUTHOR_EMAIL") || - strcmp(kv.items[2].string, "GIT_AUTHOR_DATE")) + for (i = 0; i < kv.nr; i++) { + if (!strcmp(kv.items[i].string, "GIT_AUTHOR_NAME")) { + if (name_i >= 0) + name_i = error(_("'GIT_AUTHOR_NAME' already given")); + else + name_i = i; + } else if (!strcmp(kv.items[i].string, "GIT_AUTHOR_EMAIL")) { + if (email_i >= 0) + email_i = error(_("'GIT_AUTHOR_EMAIL' already given")); + else + email_i = i; + } else if (!strcmp(kv.items[i].string, "GIT_AUTHOR_DATE")) { + if (date_i >= 0) + date_i = error(_("'GIT_AUTHOR_DATE' already given")); + else + date_i = i; + } else { + err = error(_("unknown variable '%s'"), + kv.items[i].string); + } + } + if (name_i == -2) + error(_("missing 'GIT_AUTHOR_NAME'")); + if (email_i == -2) + error(_("missing 'GIT_AUTHOR_EMAIL'")); + if (date_i == -2) + error(_("missing 'GIT_AUTHOR_DATE'")); + if (date_i < 0 || email_i < 0 || date_i < 0 || err) goto finish; - state->author_name = kv.items[0].util; - state->author_email = kv.items[1].util; - state->author_date = kv.items[2].util; + state->author_name = kv.items[name_i].util; + state->author_email = kv.items[email_i].util; + state->author_date = kv.items[date_i].util; retval = 0; finish: string_list_clear(&kv, !!retval);