sha1_name: tweak @{-N} lookup
Have the lookup only look at "interesting" checkouts, meaning those that tell you "Already on ..." don't count even though they also cause a reflog entry. Let interpret_nth_last_branch() return the number of characters parsed, so that git-checkout can verify that the branch spec was @{-N}, not @{-1}^2 or something like that. (The latter will be added later.) Signed-off-by: Thomas Rast <trast@student.ethz.ch> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Thomas Rast committed
Jan 17, 2009 at 17:09 UTC
a884d0cb71463c28d0329c593dce1ef9758f6177
2 files changed
+32
-25
builtin-checkout.c
+3
-1
@@ -361,8 +361,10 @@ struct branch_info {
361
static void setup_branch_path(struct branch_info *branch)
362
{
363
struct strbuf buf = STRBUF_INIT;
364
+ int ret;
365
365
- if (!interpret_nth_last_branch(branch->name, &buf)) {
366
+ if ((ret = interpret_nth_last_branch(branch->name, &buf))
367
+ && ret == strlen(branch->name)) {
368
branch->name = xstrdup(buf.buf);
369
strbuf_splice(&buf, 0, 0, "refs/heads/", 11);
370
} else {
sha1_name.c
+29
-24
@@ -685,29 +685,28 @@ static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
685
const char *message, void *cb_data)
686
{
687
struct grab_nth_branch_switch_cbdata *cb = cb_data;
688
- const char *match = NULL;
689
-
690
- if (!prefixcmp(message, "checkout: moving to "))
691
- match = message + strlen("checkout: moving to ");
692
- else if (!prefixcmp(message, "checkout: moving from ")) {
693
- const char *cp = message + strlen("checkout: moving from ");
694
- if ((cp = strstr(cp, " to ")) != NULL) {
695
- match = cp + 4;
696
- }
688
+ const char *match = NULL, *target = NULL;
689
+ size_t len;
690
+
691
+ if (!prefixcmp(message, "checkout: moving from ")) {
692
+ match = message + strlen("checkout: moving from ");
693
+ if ((target = strstr(match, " to ")) != NULL)
694
+ target += 4;
695
}
696
697
if (!match)
698
return 0;
699
700
+ len = target - match - 4;
701
+ if (target[len] == '\n' && !strncmp(match, target, len))
702
+ return 0;
703
+
704
if (cb->counting) {
705
cb->nth++;
706
return 0;
707
}
708
707
- if (--cb->nth <= 0) {
708
- size_t len = strlen(match);
709
- while (match[len-1] == '\n')
710
- len--;
709
+ if (cb->nth-- <= 0) {
710
strbuf_reset(cb->buf);
711
strbuf_add(cb->buf, match, len);
712
return 1;
@@ -718,26 +717,28 @@ static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
717
/*
718
* This reads "@{-N}" syntax, finds the name of the Nth previous
719
* branch we were on, and places the name of the branch in the given
721
- * buf and returns 0 if successful.
720
+ * buf and returns the number of characters parsed if successful.
721
*
722
* If the input is not of the accepted format, it returns a negative
723
* number to signal an error.
724
+ *
725
+ * If the input was ok but there are not N branch switches in the
726
+ * reflog, it returns 0.
727
*/
728
int interpret_nth_last_branch(const char *name, struct strbuf *buf)
729
{
728
- int nth, i;
730
+ int nth;
731
struct grab_nth_branch_switch_cbdata cb;
732
+ const char *brace;
733
+ char *num_end;
734
735
if (name[0] != '@' || name[1] != '{' || name[2] != '-')
736
return -1;
733
- for (i = 3, nth = 0; name[i] && name[i] != '}'; i++) {
734
- char ch = name[i];
735
- if ('0' <= ch && ch <= '9')
736
- nth = nth * 10 + ch - '0';
737
- else
738
- return -1;
739
- }
740
- if (nth < 0 || 10 <= nth)
737
+ brace = strchr(name, '}');
738
+ if (!brace)
739
+ return -1;
740
+ nth = strtol(name+3, &num_end, 10);
741
+ if (num_end != brace)
742
return -1;
743
744
cb.counting = 1;
@@ -745,11 +746,15 @@ int interpret_nth_last_branch(const char *name, struct strbuf *buf)
746
cb.buf = buf;
747
for_each_reflog_ent("HEAD", grab_nth_branch_switch, &cb);
748
749
+ if (cb.nth < nth)
750
+ return 0;
751
+
752
cb.counting = 0;
753
cb.nth -= nth;
754
cb.buf = buf;
755
for_each_reflog_ent("HEAD", grab_nth_branch_switch, &cb);
752
- return 0;
756
+
757
+ return brace-name+1;
758
}
759
760
/*