@matheusbsbs / matheus-bagliano / commits / a884d0cb71
Fork 0

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 /*