From: Junio C Hamano <gitster@pobox.com>
To: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Cc: Thomas Rast <trast@student.ethz.ch>,
git@vger.kernel.org, Johannes Sixt <johannes.sixt@telecom.at>,
Johan Herland <johan@herland.net>
Subject: Re: [PATCH] interpret_nth_last_branch(): avoid traversing the reflogs twice
Date: Mon, 19 Jan 2009 00:08:09 -0800 [thread overview]
Message-ID: <7vprijra52.fsf@gitster.siamese.dyndns.org> (raw)
In-Reply-To: <alpine.DEB.1.00.0901182152010.3586@pacific.mpi-cbg.de> (Johannes Schindelin's message of "Sun, 18 Jan 2009 21:59:40 +0100 (CET)")
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> On Sat, 17 Jan 2009, Junio C Hamano wrote:
> ...
>> My HEAD reflog is 7MB long with 39000 entries, and among them, 13100
>> entries have "checkout: moving ".
>>
>> I know I will never want to switch back to the 10000th from the last
>> branch. I am quite sure that I would forget which branch I was on after
>> switching branches three or four times (hence my original hardcoded
>> limitation of 10 which "should be plenty"). When I know I only have to
>> keep track of 10 entries, having to keep track of 13100 entries, even if
>> it is 36kB (it would actually be 260kB in my case) feels there is
>> something wrong in the design.
>
> Hrm. So let's leave it as a two-pass thing?
Well, I would rather be in favor of something like this.
-- >8 --
Subject: 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 the latest 16 (which is an arbitrary limitation that should be
plenty) such entry, to switch back to the branch we were recently on.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
sha1_name.c | 48 +++++++++++++++++++++------------------------
t/t2012-checkout-last.sh | 44 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 66 insertions(+), 26 deletions(-)
diff --git a/sha1_name.c b/sha1_name.c
index 9e1538e..d6622f2 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -684,10 +684,11 @@ static int get_sha1_oneline(const char *prefix, unsigned char *sha1)
return retval;
}
+#define MAX_PREVIOUS_BRANCH 16
+
struct grab_nth_branch_switch_cbdata {
- int counting;
- int nth;
- struct strbuf *buf;
+ long cnt;
+ struct strbuf buf[MAX_PREVIOUS_BRANCH];
};
static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
@@ -697,6 +698,7 @@ static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
struct grab_nth_branch_switch_cbdata *cb = cb_data;
const char *match = NULL, *target = NULL;
size_t len;
+ int nth;
if (!prefixcmp(message, "checkout: moving from ")) {
match = message + strlen("checkout: moving from ");
@@ -711,16 +713,9 @@ static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
if (target[len] == '\n' && !strncmp(match, target, len))
return 0;
- if (cb->counting) {
- cb->nth++;
- return 0;
- }
-
- if (cb->nth-- <= 0) {
- strbuf_reset(cb->buf);
- strbuf_add(cb->buf, match, len);
- return 1;
- }
+ nth = cb->cnt++ % MAX_PREVIOUS_BRANCH;
+ strbuf_reset(&cb->buf[nth]);
+ strbuf_add(&cb->buf[nth], match, len);
return 0;
}
@@ -737,7 +732,8 @@ static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
*/
int interpret_nth_last_branch(const char *name, struct strbuf *buf)
{
- int nth;
+ long nth;
+ int i;
struct grab_nth_branch_switch_cbdata cb;
const char *brace;
char *num_end;
@@ -750,19 +746,19 @@ int interpret_nth_last_branch(const char *name, struct strbuf *buf)
nth = strtol(name+3, &num_end, 10);
if (num_end != brace)
return -1;
-
- cb.counting = 1;
- cb.nth = 0;
- cb.buf = buf;
- for_each_reflog_ent("HEAD", grab_nth_branch_switch, &cb);
-
- if (cb.nth < nth)
- return 0;
-
- cb.counting = 0;
- cb.nth -= nth;
- cb.buf = buf;
+ if (nth <= 0 || MAX_PREVIOUS_BRANCH < nth)
+ return -1;
+ for (i = 0; i < MAX_PREVIOUS_BRANCH; i++)
+ strbuf_init(&cb.buf[i], 20);
+ cb.cnt = 0;
for_each_reflog_ent("HEAD", grab_nth_branch_switch, &cb);
+ if (cb.cnt < nth)
+ return -1;
+ i = (cb.cnt + MAX_PREVIOUS_BRANCH - nth) % MAX_PREVIOUS_BRANCH;
+ strbuf_reset(buf);
+ strbuf_add(buf, cb.buf[i].buf, cb.buf[i].len);
+ for (i = 0; i < MAX_PREVIOUS_BRANCH; i++)
+ strbuf_release(&cb.buf[i]);
return brace-name+1;
}
diff --git a/t/t2012-checkout-last.sh b/t/t2012-checkout-last.sh
index 320f6eb..87b30a2 100755
--- a/t/t2012-checkout-last.sh
+++ b/t/t2012-checkout-last.sh
@@ -47,4 +47,48 @@ test_expect_success '"checkout -" detaches again' '
test_must_fail git symbolic-ref HEAD
'
+test_expect_success 'more switches' '
+ for i in 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
+ do
+ git checkout -b branch$i
+ done
+'
+
+more_switches () {
+ for i in 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
+ do
+ git checkout branch$i
+ done
+}
+
+test_expect_success 'switch to the last' '
+ more_switches &&
+ git checkout @{-1} &&
+ test "z$(git symbolic-ref HEAD)" = "zrefs/heads/branch2"
+'
+
+test_expect_success 'switch to second from the last' '
+ more_switches &&
+ git checkout @{-2} &&
+ test "z$(git symbolic-ref HEAD)" = "zrefs/heads/branch3"
+'
+
+test_expect_success 'switch to third from the last' '
+ more_switches &&
+ git checkout @{-3} &&
+ test "z$(git symbolic-ref HEAD)" = "zrefs/heads/branch4"
+'
+
+test_expect_success 'switch to fourth from the last' '
+ more_switches &&
+ git checkout @{-4} &&
+ test "z$(git symbolic-ref HEAD)" = "zrefs/heads/branch5"
+'
+
+test_expect_success 'switch to twelfth from the last' '
+ more_switches &&
+ git checkout @{-12} &&
+ test "z$(git symbolic-ref HEAD)" = "zrefs/heads/branch13"
+'
+
test_done
--
1.6.1.245.gdd9f9
next prev parent reply other threads:[~2009-01-19 8:09 UTC|newest]
Thread overview: 102+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-01-15 0:06 [PATCH] checkout: implement "-" shortcut name for last branch Thomas Rast
2009-01-15 0:12 ` [PATCH v2] " Thomas Rast
2009-01-15 7:27 ` Johannes Sixt
2009-01-15 13:15 ` Johannes Schindelin
2009-01-15 13:59 ` Thomas Rast
2009-01-15 14:09 ` Johannes Schindelin
2009-01-15 14:17 ` Johannes Schindelin
2009-01-15 20:12 ` Junio C Hamano
2009-01-15 20:35 ` Johannes Schindelin
2009-01-16 12:52 ` [PATCH] revision walker: include a detached HEAD in --all Johannes Schindelin
2009-01-16 13:12 ` Santi Béjar
2009-01-16 13:17 ` Johannes Schindelin
2009-01-16 13:22 ` David Kastrup
2009-01-16 13:46 ` Santi Béjar
2009-01-16 13:50 ` Santi Béjar
2009-01-18 6:01 ` Junio C Hamano
2009-01-18 6:36 ` Junio C Hamano
2009-01-18 14:06 ` Johannes Schindelin
2009-01-18 13:42 ` Johannes Schindelin
2009-01-15 16:32 ` [PATCH v2] checkout: implement "-" shortcut name for last branch Johan Herland
2009-01-15 16:50 ` Johannes Schindelin
2009-01-15 20:11 ` Junio C Hamano
2009-01-15 20:50 ` Junio C Hamano
2009-01-17 3:30 ` [PATCH/RFC v3 0/6] N-th last checked out branch Thomas Rast
2009-01-17 5:52 ` Johannes Schindelin
2009-01-17 13:38 ` Thomas Rast
2009-01-17 13:40 ` [PATCH/RFC v3bis 1/2] sha1_name: implement @{-N} syntax for N-th last checked out Thomas Rast
2009-01-17 13:40 ` [PATCH/RFC v3bis 2/2] checkout: implement '@{-N}' and '-' special abbreviations Thomas Rast
2009-01-17 15:04 ` [PATCH] interpret_nth_last_branch(): avoid traversing the reflogs twice Johannes Schindelin
2009-01-17 16:09 ` [PATCH/RFC v4 0/5] N-th last checked out branch Thomas Rast
2009-01-17 16:09 ` [PATCH/RFC v4 1/5] checkout: implement "@{-N}" shortcut name for N-th last branch Thomas Rast
2009-01-17 16:09 ` [PATCH/RFC v4 2/5] sha1_name: tweak @{-N} lookup Thomas Rast
2009-01-17 16:09 ` [PATCH/RFC v4 3/5] sha1_name: support @{-N} syntax in get_sha1() Thomas Rast
2009-01-17 16:09 ` [PATCH/RFC v4 4/5] checkout: implement "-" abbreviation, add docs and tests Thomas Rast
2009-01-17 16:09 ` [PATCH/RFC v4 5/5] interpret_nth_last_branch(): avoid traversing the reflogs twice Thomas Rast
2009-01-17 18:08 ` [PATCH 6/5] Fix parsing of @{-1}@{1} Johannes Schindelin
2009-01-17 20:02 ` Junio C Hamano
2009-01-17 21:22 ` Johannes Schindelin
2009-01-17 19:57 ` [PATCH/RFC v4 4/5] checkout: implement "-" abbreviation, add docs and tests Junio C Hamano
2009-01-17 17:55 ` [PATCH/RFC v4 3/5] sha1_name: support @{-N} syntax in get_sha1() Johannes Schindelin
2009-01-17 19:37 ` Junio C Hamano
2009-01-18 0:54 ` [PATCH/RFC v4 2/5] sha1_name: tweak @{-N} lookup Junio C Hamano
2009-01-17 16:49 ` [PATCH/RFC v4 0/5] N-th last checked out branch Johannes Schindelin
2009-01-17 19:13 ` [PATCH] interpret_nth_last_branch(): avoid traversing the reflogs twice Junio C Hamano
2009-01-17 19:29 ` Johannes Schindelin
2009-01-18 0:43 ` Junio C Hamano
2009-01-18 1:12 ` Johannes Schindelin
2009-01-18 7:25 ` Junio C Hamano
2009-01-18 20:59 ` Johannes Schindelin
2009-01-19 8:08 ` Junio C Hamano [this message]
2009-01-19 8:19 ` Junio C Hamano
2009-01-19 12:33 ` Johannes Schindelin
2009-01-20 0:11 ` Thomas Rast
2009-01-20 0:23 ` Johannes Schindelin
2009-01-20 0:41 ` Thomas Rast
2009-01-20 6:21 ` [PATCH] interpret_nth_last_branch(): plug small memleak Junio C Hamano
2009-01-20 10:15 ` Johannes Schindelin
2009-01-20 6:22 ` [PATCH] Introduce for_each_recent_reflog_ent() Junio C Hamano
2009-01-20 10:15 ` Johannes Schindelin
2009-01-20 8:35 ` [PATCH] interpret_nth_last_branch(): avoid traversing the reflogs twice Junio C Hamano
2009-01-21 0:16 ` [VALGRIND PATCH for nth_last patch series] Fix invalid memory access Johannes Schindelin
2009-01-21 8:45 ` Junio C Hamano
2009-01-21 9:18 ` Thomas Rast
2009-01-21 10:13 ` Junio C Hamano
2009-01-21 12:06 ` Johannes Schindelin
2009-01-24 22:21 ` Thomas Rast
2009-01-24 22:23 ` [PATCH next] t1505: remove debugging cruft Thomas Rast
2009-01-25 20:35 ` Junio C Hamano
2009-01-21 11:56 ` [VALGRIND PATCH for nth_last patch series] Fix invalid memory access Johannes Schindelin
2009-01-19 12:41 ` [PATCH] @{-<n>}: avoid crash with corrupt reflog Johannes Schindelin
2009-01-19 14:57 ` Johannes Schindelin
2009-01-17 3:30 ` [PATCH/RFC v3 1/6] reflog: refactor parsing and checking Thomas Rast
2009-01-17 5:35 ` Johannes Schindelin
2009-01-17 3:30 ` [PATCH/RFC v3 2/6] reflog: refactor log open+mmap Thomas Rast
2009-01-17 5:40 ` Johannes Schindelin
2009-01-17 3:30 ` [PATCH/RFC v3 3/6] reflog: make for_each_reflog_ent use mmap Thomas Rast
2009-01-17 3:30 ` [PATCH/RFC v3 4/6] reflog: add backwards iterator Thomas Rast
2009-01-17 3:30 ` [PATCH/RFC v3 5/6] sha1_name: implement @{-N} syntax for N-th last checked out Thomas Rast
2009-01-17 3:30 ` [PATCH/RFC v3 6/6] checkout: implement '@{-N}' and '-' special abbreviations Thomas Rast
2009-01-16 12:31 ` [PATCH v2] checkout: implement "-" shortcut name for last branch Johannes Schindelin
2009-01-15 0:45 ` [PATCH] " Johannes Schindelin
2009-01-15 14:01 ` Thomas Rast
2009-01-15 14:14 ` Johannes Schindelin
2009-01-15 17:05 ` Thomas Rast
2009-01-15 18:34 ` Johannes Schindelin
2009-01-16 9:08 ` Thomas Rast
2009-01-16 11:18 ` Johannes Schindelin
2009-01-18 1:38 ` [TOY PATCH] git-resurrect: find traces of a branch name and resurrect it Thomas Rast
2009-01-18 16:19 ` Johannes Schindelin
2009-01-20 9:01 ` Thomas Rast
2009-01-20 16:57 ` Boyd Stephen Smith Jr.
2009-01-20 20:50 ` Boyd Stephen Smith Jr.
2009-01-23 20:03 ` [PATCH] contrib " Thomas Rast
2009-01-23 21:00 ` Boyd Stephen Smith Jr.
2009-01-26 11:54 ` Thomas Rast
2009-01-26 12:40 ` [PATCH v2] " Thomas Rast
2009-01-27 6:31 ` Junio C Hamano
2009-01-30 22:52 ` Thomas Rast
2009-02-01 21:34 ` [PATCH v3] " Thomas Rast
2009-02-02 2:31 ` Junio C Hamano
2009-02-04 10:04 ` [PATCH v4] " Thomas Rast
2009-02-05 8:38 ` Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=7vprijra52.fsf@gitster.siamese.dyndns.org \
--to=gitster@pobox.com \
--cc=Johannes.Schindelin@gmx.de \
--cc=git@vger.kernel.org \
--cc=johan@herland.net \
--cc=johannes.sixt@telecom.at \
--cc=trast@student.ethz.ch \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).