Instead of traversing them twice, we just build a list of branch switches,
pick the one we're interested in, and free the list again.
Signed-off-by: Johannes Schindelin <redacted>
---
On Sat, 17 Jan 2009, Thomas Rast wrote:
> Johannes Schindelin wrote:
>
> > I really have to ask: why did you not work on top of Junio's
> > patch, just adding docs, tests, and checkout -? And then -- maybe --
> > the string_list...
Of course, I meant the patch as-is, with Junio as author. But
hey, if he does not care...
> > Although I have to admit that I am not _that_ convinced the
> > string_list is worth it: reflogs are not evaluated all the time, so
> > it is definitely not performance critical.
>
> I take it you have some idea where and how string_list fits into
> this topic?
Indeed.
This patch was generated using --collapse-non-alnums for readability.
Did not really help much.
sha1_name.c | 72 ++++++++++++++++++++++++----------------------------------
1 files changed, 30 insertions(+), 42 deletions(-)
diff --git a/sha1_name.c b/sha1_name.c
index 2bbc5f1..306d04b 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -6,6 +6,7 @@
#include "tree-walk.h"
#include "refs.h"
#include "cache-tree.h"
+#include "string-list.h"
static int find_short_object_filename(int len, const char *name, unsigned char *sha1)
{@@ -691,43 +692,31 @@ static int get_sha1_oneline(const char *prefix, unsigned char *sha1)
return retval;
}
-struct grab_nth_branch_switch_cbdata {
- int counting;
- int nth;
- struct strbuf *buf;
-};
-
-static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
+static int add_one_branch_switch(unsigned char *osha1, unsigned char *nsha1,
const char *email, unsigned long timestamp, int tz,
const char *message, void *cb_data)
{
- struct grab_nth_branch_switch_cbdata *cb = cb_data;
+ struct string_list *list = cb_data;
const char *match = NULL, *target = NULL;
size_t len;
-
- if (!prefixcmp(message, "checkout: moving from ")) {
- match = message + strlen("checkout: moving from ");
- if ((target = strstr(match, " to ")) != NULL)
- target += 4;
- }
-
- if (!match)
+
+ if (prefixcmp(message, "checkout: moving from "))
return 0;
- len = target - match - 4;
- 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;
- }
+ match = message + strlen("checkout: moving from ");
+
+ /* Is it "moving" from a branch to itself? Then ignore it. */
+ if ((target = strstr(match, " to ")) != NULL) {
+ target += 4;
+ len = target - match - 4;
+ if (target[len] == '\n' && !strncmp(match, target, len))
+ return 0;
+ }
+ else
+ len = strchrnul(match, ' ') - match;
+
+ string_list_append(xstrndup(match, len), list);
+
return 0;
}
@@ -745,7 +734,7 @@ 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;
- struct grab_nth_branch_switch_cbdata cb;
+ struct string_list branch_list = { NULL, 0, 0, 0 };
const char *brace;
char *num_end;
@@ -758,18 +747,17 @@ int interpret_nth_last_branch(const char *name, struct strbuf *buf)
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)
+ for_each_reflog_ent("HEAD", add_one_branch_switch, &branch_list);
+
+ if (branch_list.nr < nth)
return 0;
-
- cb.counting = 0;
- cb.nth -= nth;
- cb.buf = buf;
- for_each_reflog_ent("HEAD", grab_nth_branch_switch, &cb);
+
+ strbuf_reset(buf);
+ strbuf_addstr(buf, branch_list.items[branch_list.nr - nth].string);
+
+ /* force free()ing the items */
+ branch_list.strdup_strings = 1;
+ string_list_clear(&branch_list, 0);
return brace-name+1;
}--
1.6.1.325.g062d4