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

interpret_nth_last_branch(): avoid traversing the reflog twice

You can have quite a many reflog entries, but you typically won't recall which branch you were on after switching branches for more than several times. Instead of reading the reflog twice, this reads the branch switching event and keeps as many entries as the user asked from the latest such entries, which is the minimum required to be able to switch back to the branch we were recently on. [jc: improvements from Dscho squashed in] Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Jan 19, 2009 at 00:04 UTC c2883e62f5b9980e5402431f2261c961354d0f15
2 files changed +65 -24
sha1_name.c
+21 -24
@@ -685,8 +685,7 @@ static int get_sha1_oneline(const char *prefix, unsigned char *sha1)
685 }
686
687 struct grab_nth_branch_switch_cbdata {
688 - int counting;
689 - int nth;
688 + long cnt, alloc;
689 struct strbuf *buf;
690 };
691
@@ -697,6 +696,7 @@ static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
696 struct grab_nth_branch_switch_cbdata *cb = cb_data;
697 const char *match = NULL, *target = NULL;
698 size_t len;
699 + int nth;
700
701 if (!prefixcmp(message, "checkout: moving from ")) {
702 match = message + strlen("checkout: moving from ");
@@ -711,16 +711,9 @@ static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
711 if (target[len] == '\n' && !strncmp(match, target, len))
712 return 0;
713
714 - if (cb->counting) {
715 - cb->nth++;
716 - return 0;
717 - }
718 -
719 - if (cb->nth-- <= 0) {
720 - strbuf_reset(cb->buf);
721 - strbuf_add(cb->buf, match, len);
722 - return 1;
723 - }
714 + nth = cb->cnt++ % cb->alloc;
715 + strbuf_reset(&cb->buf[nth]);
716 + strbuf_add(&cb->buf[nth], match, len);
717 return 0;
718 }
719
@@ -737,7 +730,8 @@ static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
730 */
731 int interpret_nth_last_branch(const char *name, struct strbuf *buf)
732 {
740 - int nth;
733 + long nth;
734 + int i;
735 struct grab_nth_branch_switch_cbdata cb;
736 const char *brace;
737 char *num_end;
@@ -750,19 +744,22 @@ int interpret_nth_last_branch(const char *name, struct strbuf *buf)
744 nth = strtol(name+3, &num_end, 10);
745 if (num_end != brace)
746 return -1;
753 -
754 - cb.counting = 1;
755 - cb.nth = 0;
756 - cb.buf = buf;
747 + if (nth <= 0)
748 + return -1;
749 + cb.alloc = nth;
750 + cb.buf = xmalloc(nth * sizeof(struct strbuf));
751 + for (i = 0; i < nth; i++)
752 + strbuf_init(&cb.buf[i], 20);
753 + cb.cnt = 0;
754 for_each_reflog_ent("HEAD", grab_nth_branch_switch, &cb);
758 -
759 - if (cb.nth < nth)
755 + if (cb.cnt < nth)
756 return 0;
761 -
762 - cb.counting = 0;
763 - cb.nth -= nth;
764 - cb.buf = buf;
765 - for_each_reflog_ent("HEAD", grab_nth_branch_switch, &cb);
757 + i = cb.cnt % nth;
758 + strbuf_reset(buf);
759 + strbuf_add(buf, cb.buf[i].buf, cb.buf[i].len);
760 + for (i = 0; i < nth; i++)
761 + strbuf_release(&cb.buf[i]);
762 + free(cb.buf);
763
764 return brace-name+1;
765 }
t/t2012-checkout-last.sh
+44
@@ -47,4 +47,48 @@ test_expect_success '"checkout -" detaches again' '
47 test_must_fail git symbolic-ref HEAD
48 '
49
50 +test_expect_success 'more switches' '
51 + for i in 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
52 + do
53 + git checkout -b branch$i
54 + done
55 +'
56 +
57 +more_switches () {
58 + for i in 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
59 + do
60 + git checkout branch$i
61 + done
62 +}
63 +
64 +test_expect_success 'switch to the last' '
65 + more_switches &&
66 + git checkout @{-1} &&
67 + test "z$(git symbolic-ref HEAD)" = "zrefs/heads/branch2"
68 +'
69 +
70 +test_expect_success 'switch to second from the last' '
71 + more_switches &&
72 + git checkout @{-2} &&
73 + test "z$(git symbolic-ref HEAD)" = "zrefs/heads/branch3"
74 +'
75 +
76 +test_expect_success 'switch to third from the last' '
77 + more_switches &&
78 + git checkout @{-3} &&
79 + test "z$(git symbolic-ref HEAD)" = "zrefs/heads/branch4"
80 +'
81 +
82 +test_expect_success 'switch to fourth from the last' '
83 + more_switches &&
84 + git checkout @{-4} &&
85 + test "z$(git symbolic-ref HEAD)" = "zrefs/heads/branch5"
86 +'
87 +
88 +test_expect_success 'switch to twelfth from the last' '
89 + more_switches &&
90 + git checkout @{-12} &&
91 + test "z$(git symbolic-ref HEAD)" = "zrefs/heads/branch13"
92 +'
93 +
94 test_done