|
|
@ -431,6 +431,7 @@ static inline int upstream_mark(const char *string, int len) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int get_sha1_1(const char *name, int len, unsigned char *sha1, unsigned lookup_flags); |
|
|
|
static int get_sha1_1(const char *name, int len, unsigned char *sha1, unsigned lookup_flags); |
|
|
|
|
|
|
|
static int interpret_nth_prior_checkout(const char *name, struct strbuf *buf); |
|
|
|
|
|
|
|
|
|
|
|
static int get_sha1_basic(const char *str, int len, unsigned char *sha1) |
|
|
|
static int get_sha1_basic(const char *str, int len, unsigned char *sha1) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -448,7 +449,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1) |
|
|
|
unsigned char tmp_sha1[20]; |
|
|
|
unsigned char tmp_sha1[20]; |
|
|
|
char *real_ref = NULL; |
|
|
|
char *real_ref = NULL; |
|
|
|
int refs_found = 0; |
|
|
|
int refs_found = 0; |
|
|
|
int at, reflog_len; |
|
|
|
int at, reflog_len, nth_prior = 0; |
|
|
|
|
|
|
|
|
|
|
|
if (len == 40 && !get_sha1_hex(str, sha1)) { |
|
|
|
if (len == 40 && !get_sha1_hex(str, sha1)) { |
|
|
|
refs_found = dwim_ref(str, len, tmp_sha1, &real_ref); |
|
|
|
refs_found = dwim_ref(str, len, tmp_sha1, &real_ref); |
|
|
@ -464,8 +465,15 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1) |
|
|
|
/* basic@{time or number or -number} format to query ref-log */ |
|
|
|
/* basic@{time or number or -number} format to query ref-log */ |
|
|
|
reflog_len = at = 0; |
|
|
|
reflog_len = at = 0; |
|
|
|
if (len && str[len-1] == '}') { |
|
|
|
if (len && str[len-1] == '}') { |
|
|
|
for (at = len-2; at >= 0; at--) { |
|
|
|
for (at = len-4; at >= 0; at--) { |
|
|
|
if (str[at] == '@' && str[at+1] == '{') { |
|
|
|
if (str[at] == '@' && str[at+1] == '{') { |
|
|
|
|
|
|
|
if (str[at+2] == '-') { |
|
|
|
|
|
|
|
if (at != 0) |
|
|
|
|
|
|
|
/* @{-N} not at start */ |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
nth_prior = 1; |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
if (!upstream_mark(str + at, len - at)) { |
|
|
|
if (!upstream_mark(str + at, len - at)) { |
|
|
|
reflog_len = (len-1) - (at+2); |
|
|
|
reflog_len = (len-1) - (at+2); |
|
|
|
len = at; |
|
|
|
len = at; |
|
|
@ -479,20 +487,22 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1) |
|
|
|
if (len && ambiguous_path(str, len)) |
|
|
|
if (len && ambiguous_path(str, len)) |
|
|
|
return -1; |
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
|
|
if (!len && reflog_len) { |
|
|
|
if (nth_prior) { |
|
|
|
struct strbuf buf = STRBUF_INIT; |
|
|
|
struct strbuf buf = STRBUF_INIT; |
|
|
|
int ret; |
|
|
|
int detached; |
|
|
|
/* try the @{-N} syntax for n-th checkout */ |
|
|
|
|
|
|
|
ret = interpret_branch_name(str+at, &buf); |
|
|
|
if (interpret_nth_prior_checkout(str, &buf) > 0) { |
|
|
|
if (ret > 0) { |
|
|
|
detached = (buf.len == 40 && !get_sha1_hex(buf.buf, sha1)); |
|
|
|
/* substitute this branch name and restart */ |
|
|
|
strbuf_release(&buf); |
|
|
|
return get_sha1_1(buf.buf, buf.len, sha1, 0); |
|
|
|
if (detached) |
|
|
|
} else if (ret == 0) { |
|
|
|
return 0; |
|
|
|
return -1; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!len && reflog_len) |
|
|
|
/* allow "@{...}" to mean the current branch reflog */ |
|
|
|
/* allow "@{...}" to mean the current branch reflog */ |
|
|
|
refs_found = dwim_ref("HEAD", 4, sha1, &real_ref); |
|
|
|
refs_found = dwim_ref("HEAD", 4, sha1, &real_ref); |
|
|
|
} else if (reflog_len) |
|
|
|
else if (reflog_len) |
|
|
|
refs_found = dwim_log(str, len, sha1, &real_ref); |
|
|
|
refs_found = dwim_log(str, len, sha1, &real_ref); |
|
|
|
else |
|
|
|
else |
|
|
|
refs_found = dwim_ref(str, len, sha1, &real_ref); |
|
|
|
refs_found = dwim_ref(str, len, sha1, &real_ref); |
|
|
@ -511,10 +521,6 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1) |
|
|
|
unsigned long co_time; |
|
|
|
unsigned long co_time; |
|
|
|
int co_tz, co_cnt; |
|
|
|
int co_tz, co_cnt; |
|
|
|
|
|
|
|
|
|
|
|
/* a @{-N} placed anywhere except the start is an error */ |
|
|
|
|
|
|
|
if (str[at+2] == '-') |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Is it asking for N-th entry, or approxidate? */ |
|
|
|
/* Is it asking for N-th entry, or approxidate? */ |
|
|
|
for (i = nth = 0; 0 <= nth && i < reflog_len; i++) { |
|
|
|
for (i = nth = 0; 0 <= nth && i < reflog_len; i++) { |
|
|
|
char ch = str[at+2+i]; |
|
|
|
char ch = str[at+2+i]; |
|
|
@ -996,6 +1002,38 @@ int get_sha1_mb(const char *name, unsigned char *sha1) |
|
|
|
return st; |
|
|
|
return st; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* parse @something syntax, when 'something' is not {.*} */ |
|
|
|
|
|
|
|
static int interpret_empty_at(const char *name, int namelen, int len, struct strbuf *buf) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (len || name[1] == '{') |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
strbuf_reset(buf); |
|
|
|
|
|
|
|
strbuf_add(buf, "HEAD", 4); |
|
|
|
|
|
|
|
return 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int reinterpret(const char *name, int namelen, int len, struct strbuf *buf) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
/* we have extra data, which might need further processing */ |
|
|
|
|
|
|
|
struct strbuf tmp = STRBUF_INIT; |
|
|
|
|
|
|
|
int used = buf->len; |
|
|
|
|
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
strbuf_add(buf, name + len, namelen - len); |
|
|
|
|
|
|
|
ret = interpret_branch_name(buf->buf, &tmp); |
|
|
|
|
|
|
|
/* that data was not interpreted, remove our cruft */ |
|
|
|
|
|
|
|
if (ret < 0) { |
|
|
|
|
|
|
|
strbuf_setlen(buf, used); |
|
|
|
|
|
|
|
return len; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
strbuf_reset(buf); |
|
|
|
|
|
|
|
strbuf_addbuf(buf, &tmp); |
|
|
|
|
|
|
|
strbuf_release(&tmp); |
|
|
|
|
|
|
|
/* tweak for size of {-N} versus expanded ref name */ |
|
|
|
|
|
|
|
return ret - used + len; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
/* |
|
|
|
* This reads short-hand syntax that not only evaluates to a commit |
|
|
|
* This reads short-hand syntax that not only evaluates to a commit |
|
|
|
* object name, but also can act as if the end user spelled the name |
|
|
|
* object name, but also can act as if the end user spelled the name |
|
|
@ -1025,36 +1063,27 @@ int interpret_branch_name(const char *name, struct strbuf *buf) |
|
|
|
int len = interpret_nth_prior_checkout(name, buf); |
|
|
|
int len = interpret_nth_prior_checkout(name, buf); |
|
|
|
int tmp_len; |
|
|
|
int tmp_len; |
|
|
|
|
|
|
|
|
|
|
|
if (!len) |
|
|
|
if (!len) { |
|
|
|
return len; /* syntax Ok, not enough switches */ |
|
|
|
return len; /* syntax Ok, not enough switches */ |
|
|
|
if (0 < len && len == namelen) |
|
|
|
} else if (len > 0) { |
|
|
|
|
|
|
|
if (len == namelen) |
|
|
|
return len; /* consumed all */ |
|
|
|
return len; /* consumed all */ |
|
|
|
else if (0 < len) { |
|
|
|
else |
|
|
|
/* we have extra data, which might need further processing */ |
|
|
|
return reinterpret(name, namelen, len, buf); |
|
|
|
struct strbuf tmp = STRBUF_INIT; |
|
|
|
|
|
|
|
int used = buf->len; |
|
|
|
|
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
strbuf_add(buf, name + len, namelen - len); |
|
|
|
|
|
|
|
ret = interpret_branch_name(buf->buf, &tmp); |
|
|
|
|
|
|
|
/* that data was not interpreted, remove our cruft */ |
|
|
|
|
|
|
|
if (ret < 0) { |
|
|
|
|
|
|
|
strbuf_setlen(buf, used); |
|
|
|
|
|
|
|
return len; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
strbuf_reset(buf); |
|
|
|
|
|
|
|
strbuf_addbuf(buf, &tmp); |
|
|
|
|
|
|
|
strbuf_release(&tmp); |
|
|
|
|
|
|
|
/* tweak for size of {-N} versus expanded ref name */ |
|
|
|
|
|
|
|
return ret - used + len; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
cp = strchr(name, '@'); |
|
|
|
cp = strchr(name, '@'); |
|
|
|
if (!cp) |
|
|
|
if (!cp) |
|
|
|
return -1; |
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
len = interpret_empty_at(name, namelen, cp - name, buf); |
|
|
|
|
|
|
|
if (len > 0) |
|
|
|
|
|
|
|
return reinterpret(name, namelen, len, buf); |
|
|
|
|
|
|
|
|
|
|
|
tmp_len = upstream_mark(cp, namelen - (cp - name)); |
|
|
|
tmp_len = upstream_mark(cp, namelen - (cp - name)); |
|
|
|
if (!tmp_len) |
|
|
|
if (!tmp_len) |
|
|
|
return -1; |
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
|
|
len = cp + tmp_len - name; |
|
|
|
len = cp + tmp_len - name; |
|
|
|
cp = xstrndup(name, cp - name); |
|
|
|
cp = xstrndup(name, cp - name); |
|
|
|
upstream = branch_get(*cp ? cp : NULL); |
|
|
|
upstream = branch_get(*cp ? cp : NULL); |
|
|
|