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

checkout: implement "@{-N}" shortcut name for N-th last branch

Implement a shortcut @{-N} for the N-th last branch checked out, that works by parsing the reflog for the message added by previous git-checkout invocations. We expand the @{-N} to the branch name, so that you end up on an attached HEAD on that branch. Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Jan 17, 2009 at 17:09 UTC ae5a6c3684c378bc32c1f6ecc0e6dc45300c14c1
3 files changed +87 -2
builtin-checkout.c
+8 -2
@@ -361,8 +361,14 @@ struct branch_info {
361 static void setup_branch_path(struct branch_info *branch)
362 {
363 struct strbuf buf = STRBUF_INIT;
364 - strbuf_addstr(&buf, "refs/heads/");
365 - strbuf_addstr(&buf, branch->name);
364 +
365 + if (!interpret_nth_last_branch(branch->name, &buf)) {
366 + branch->name = xstrdup(buf.buf);
367 + strbuf_splice(&buf, 0, 0, "refs/heads/", 11);
368 + } else {
369 + strbuf_addstr(&buf, "refs/heads/");
370 + strbuf_addstr(&buf, branch->name);
371 + }
372 branch->path = strbuf_detach(&buf, NULL);
373 }
374
cache.h
+1
@@ -663,6 +663,7 @@ extern int read_ref(const char *filename, unsigned char *sha1);
663 extern const char *resolve_ref(const char *path, unsigned char *sha1, int, int *);
664 extern int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref);
665 extern int dwim_log(const char *str, int len, unsigned char *sha1, char **ref);
666 +extern int interpret_nth_last_branch(const char *str, struct strbuf *);
667
668 extern int refname_match(const char *abbrev_name, const char *full_name, const char **rules);
669 extern const char *ref_rev_parse_rules[];
sha1_name.c
+78
@@ -674,6 +674,84 @@ static int get_sha1_oneline(const char *prefix, unsigned char *sha1)
674 return retval;
675 }
676
677 +struct grab_nth_branch_switch_cbdata {
678 + int counting;
679 + int nth;
680 + struct strbuf *buf;
681 +};
682 +
683 +static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
684 + const char *email, unsigned long timestamp, int tz,
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 + }
697 + }
698 +
699 + if (!match)
700 + return 0;
701 +
702 + if (cb->counting) {
703 + cb->nth++;
704 + return 0;
705 + }
706 +
707 + if (--cb->nth <= 0) {
708 + size_t len = strlen(match);
709 + while (match[len-1] == '\n')
710 + len--;
711 + strbuf_reset(cb->buf);
712 + strbuf_add(cb->buf, match, len);
713 + return 1;
714 + }
715 + return 0;
716 +}
717 +
718 +/*
719 + * This reads "@{-N}" syntax, finds the name of the Nth previous
720 + * branch we were on, and places the name of the branch in the given
721 + * buf and returns 0 if successful.
722 + *
723 + * If the input is not of the accepted format, it returns a negative
724 + * number to signal an error.
725 + */
726 +int interpret_nth_last_branch(const char *name, struct strbuf *buf)
727 +{
728 + int nth, i;
729 + struct grab_nth_branch_switch_cbdata cb;
730 +
731 + if (name[0] != '@' || name[1] != '{' || name[2] != '-')
732 + 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)
741 + return -1;
742 +
743 + cb.counting = 1;
744 + cb.nth = 0;
745 + cb.buf = buf;
746 + for_each_reflog_ent("HEAD", grab_nth_branch_switch, &cb);
747 +
748 + cb.counting = 0;
749 + cb.nth -= nth;
750 + cb.buf = buf;
751 + for_each_reflog_ent("HEAD", grab_nth_branch_switch, &cb);
752 + return 0;
753 +}
754 +
755 /*
756 * This is like "get_sha1_basic()", except it allows "sha1 expressions",
757 * notably "xyz^" for "parent of xyz"