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 <johannes.schindelin@xxxxxx> --- 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 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html