Skip to content

Commit

Permalink
sha1_name: tweak @{-N} lookup
Browse files Browse the repository at this point in the history
Have the lookup only look at "interesting" checkouts, meaning those
that tell you "Already on ..." don't count even though they also cause
a reflog entry.

Let interpret_nth_last_branch() return the number of characters
parsed, so that git-checkout can verify that the branch spec was
@{-N}, not @{-1}^2 or something like that.  (The latter will be added
later.)

Signed-off-by: Thomas Rast <trast@student.ethz.ch>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Thomas Rast authored and Junio C Hamano committed Jan 18, 2009
1 parent ae5a6c3 commit a884d0c
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 25 deletions.
4 changes: 3 additions & 1 deletion builtin-checkout.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,8 +361,10 @@ struct branch_info {
static void setup_branch_path(struct branch_info *branch)
{
struct strbuf buf = STRBUF_INIT;
int ret;

if (!interpret_nth_last_branch(branch->name, &buf)) {
if ((ret = interpret_nth_last_branch(branch->name, &buf))
&& ret == strlen(branch->name)) {
branch->name = xstrdup(buf.buf);
strbuf_splice(&buf, 0, 0, "refs/heads/", 11);
} else {
Expand Down
53 changes: 29 additions & 24 deletions sha1_name.c
Original file line number Diff line number Diff line change
Expand Up @@ -685,29 +685,28 @@ static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
const char *message, void *cb_data)
{
struct grab_nth_branch_switch_cbdata *cb = cb_data;
const char *match = NULL;

if (!prefixcmp(message, "checkout: moving to "))
match = message + strlen("checkout: moving to ");
else if (!prefixcmp(message, "checkout: moving from ")) {
const char *cp = message + strlen("checkout: moving from ");
if ((cp = strstr(cp, " to ")) != NULL) {
match = cp + 4;
}
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)
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) {
size_t len = strlen(match);
while (match[len-1] == '\n')
len--;
if (cb->nth-- <= 0) {
strbuf_reset(cb->buf);
strbuf_add(cb->buf, match, len);
return 1;
Expand All @@ -718,38 +717,44 @@ static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
/*
* This reads "@{-N}" syntax, finds the name of the Nth previous
* branch we were on, and places the name of the branch in the given
* buf and returns 0 if successful.
* buf and returns the number of characters parsed if successful.
*
* If the input is not of the accepted format, it returns a negative
* number to signal an error.
*
* If the input was ok but there are not N branch switches in the
* reflog, it returns 0.
*/
int interpret_nth_last_branch(const char *name, struct strbuf *buf)
{
int nth, i;
int nth;
struct grab_nth_branch_switch_cbdata cb;
const char *brace;
char *num_end;

if (name[0] != '@' || name[1] != '{' || name[2] != '-')
return -1;
for (i = 3, nth = 0; name[i] && name[i] != '}'; i++) {
char ch = name[i];
if ('0' <= ch && ch <= '9')
nth = nth * 10 + ch - '0';
else
return -1;
}
if (nth < 0 || 10 <= nth)
brace = strchr(name, '}');
if (!brace)
return -1;
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;
for_each_reflog_ent("HEAD", grab_nth_branch_switch, &cb);
return 0;

return brace-name+1;
}

/*
Expand Down

0 comments on commit a884d0c

Please sign in to comment.