* [PATCH v5 0/2] Add @ shortcut, again @ 2013-09-02 6:34 Felipe Contreras 2013-09-02 6:34 ` [PATCH v5 1/2] sha1-name: pass len argument to interpret_branch_name() Felipe Contreras 2013-09-02 6:34 ` [PATCH v5 2/2] Add new @ shortcut for HEAD Felipe Contreras 0 siblings, 2 replies; 8+ messages in thread From: Felipe Contreras @ 2013-09-02 6:34 UTC (permalink / raw) To: git; +Cc: Stefano Lattarini, Felipe Contreras Felipe Contreras (2): sha1-name: pass len argument to interpret_branch_name() Add new @ shortcut for HEAD Documentation/git-check-ref-format.txt | 2 ++ Documentation/revisions.txt | 3 +++ cache.h | 2 +- refs.c | 6 +++++- revision.c | 2 +- sha1_name.c | 36 ++++++++++++++++++++++++++++++---- t/t1508-at-combinations.sh | 4 ++++ 7 files changed, 48 insertions(+), 7 deletions(-) -- 1.8.4-338-gefd7fa6 ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v5 1/2] sha1-name: pass len argument to interpret_branch_name() 2013-09-02 6:34 [PATCH v5 0/2] Add @ shortcut, again Felipe Contreras @ 2013-09-02 6:34 ` Felipe Contreras 2013-09-03 18:40 ` Junio C Hamano 2013-09-02 6:34 ` [PATCH v5 2/2] Add new @ shortcut for HEAD Felipe Contreras 1 sibling, 1 reply; 8+ messages in thread From: Felipe Contreras @ 2013-09-02 6:34 UTC (permalink / raw) To: git; +Cc: Stefano Lattarini, Felipe Contreras This is useful to make sure we don't step outside the boundaries of what we are interpreting at the moment. For example while interpreting foobar@{u}~1, the job of interpret_branch_name() ends right before ~1, but there's no way to figure that out inside the function, unless the len argument is passed. So let's do that. Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com> --- cache.h | 2 +- refs.c | 2 +- revision.c | 2 +- sha1_name.c | 10 ++++++---- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/cache.h b/cache.h index 85b544f..9fbc5fa 100644 --- a/cache.h +++ b/cache.h @@ -893,7 +893,7 @@ extern char *resolve_refdup(const char *ref, unsigned char *sha1, int reading, i extern int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref); extern int dwim_log(const char *str, int len, unsigned char *sha1, char **ref); -extern int interpret_branch_name(const char *str, struct strbuf *); +extern int interpret_branch_name(const char *str, int len, struct strbuf *); extern int get_sha1_mb(const char *str, unsigned char *sha1); extern int refname_match(const char *abbrev_name, const char *full_name, const char **rules); diff --git a/refs.c b/refs.c index 7922261..8fd5faf 100644 --- a/refs.c +++ b/refs.c @@ -1951,7 +1951,7 @@ static int remove_empty_directories(const char *file) static char *substitute_branch_name(const char **string, int *len) { struct strbuf buf = STRBUF_INIT; - int ret = interpret_branch_name(*string, &buf); + int ret = interpret_branch_name(*string, *len, &buf); if (ret == *len) { size_t size; diff --git a/revision.c b/revision.c index 84ccc05..3ef1384 100644 --- a/revision.c +++ b/revision.c @@ -200,7 +200,7 @@ static void add_pending_object_with_mode(struct rev_info *revs, revs->no_walk = 0; if (revs->reflog_info && obj->type == OBJ_COMMIT) { struct strbuf buf = STRBUF_INIT; - int len = interpret_branch_name(name, &buf); + int len = interpret_branch_name(name, 0, &buf); int st; if (0 < len && name[len] && buf.len) diff --git a/sha1_name.c b/sha1_name.c index 65ad066..93197b9 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -1012,7 +1012,7 @@ static int reinterpret(const char *name, int namelen, int len, struct strbuf *bu int ret; strbuf_add(buf, name + len, namelen - len); - ret = interpret_branch_name(buf->buf, &tmp); + ret = interpret_branch_name(buf->buf, buf->len, &tmp); /* that data was not interpreted, remove our cruft */ if (ret < 0) { strbuf_setlen(buf, used); @@ -1046,14 +1046,16 @@ static int reinterpret(const char *name, int namelen, int len, struct strbuf *bu * If the input was ok but there are not N branch switches in the * reflog, it returns 0. */ -int interpret_branch_name(const char *name, struct strbuf *buf) +int interpret_branch_name(const char *name, int namelen, struct strbuf *buf) { char *cp; struct branch *upstream; - int namelen = strlen(name); int len = interpret_nth_prior_checkout(name, buf); int tmp_len; + if (!namelen) + namelen = strlen(name); + if (!len) { return len; /* syntax Ok, not enough switches */ } else if (len > 0) { @@ -1100,7 +1102,7 @@ int interpret_branch_name(const char *name, struct strbuf *buf) int strbuf_branchname(struct strbuf *sb, const char *name) { int len = strlen(name); - int used = interpret_branch_name(name, sb); + int used = interpret_branch_name(name, len, sb); if (used == len) return 0; -- 1.8.4-338-gefd7fa6 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v5 1/2] sha1-name: pass len argument to interpret_branch_name() 2013-09-02 6:34 ` [PATCH v5 1/2] sha1-name: pass len argument to interpret_branch_name() Felipe Contreras @ 2013-09-03 18:40 ` Junio C Hamano 0 siblings, 0 replies; 8+ messages in thread From: Junio C Hamano @ 2013-09-03 18:40 UTC (permalink / raw) To: Felipe Contreras; +Cc: git, Stefano Lattarini Felipe Contreras <felipe.contreras@gmail.com> writes: > This is useful to make sure we don't step outside the boundaries of what > we are interpreting at the moment. For example while interpreting > foobar@{u}~1, the job of interpret_branch_name() ends right before ~1, > but there's no way to figure that out inside the function, unless the > len argument is passed. > > So let's do that. > > Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com> Makes sense to me. Thanks. > --- > cache.h | 2 +- > refs.c | 2 +- > revision.c | 2 +- > sha1_name.c | 10 ++++++---- > 4 files changed, 9 insertions(+), 7 deletions(-) > > diff --git a/cache.h b/cache.h > index 85b544f..9fbc5fa 100644 > --- a/cache.h > +++ b/cache.h > @@ -893,7 +893,7 @@ extern char *resolve_refdup(const char *ref, unsigned char *sha1, int reading, i > > extern int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref); > extern int dwim_log(const char *str, int len, unsigned char *sha1, char **ref); > -extern int interpret_branch_name(const char *str, struct strbuf *); > +extern int interpret_branch_name(const char *str, int len, struct strbuf *); > extern int get_sha1_mb(const char *str, unsigned char *sha1); > > extern int refname_match(const char *abbrev_name, const char *full_name, const char **rules); > diff --git a/refs.c b/refs.c > index 7922261..8fd5faf 100644 > --- a/refs.c > +++ b/refs.c > @@ -1951,7 +1951,7 @@ static int remove_empty_directories(const char *file) > static char *substitute_branch_name(const char **string, int *len) > { > struct strbuf buf = STRBUF_INIT; > - int ret = interpret_branch_name(*string, &buf); > + int ret = interpret_branch_name(*string, *len, &buf); > > if (ret == *len) { > size_t size; > diff --git a/revision.c b/revision.c > index 84ccc05..3ef1384 100644 > --- a/revision.c > +++ b/revision.c > @@ -200,7 +200,7 @@ static void add_pending_object_with_mode(struct rev_info *revs, > revs->no_walk = 0; > if (revs->reflog_info && obj->type == OBJ_COMMIT) { > struct strbuf buf = STRBUF_INIT; > - int len = interpret_branch_name(name, &buf); > + int len = interpret_branch_name(name, 0, &buf); > int st; > > if (0 < len && name[len] && buf.len) > diff --git a/sha1_name.c b/sha1_name.c > index 65ad066..93197b9 100644 > --- a/sha1_name.c > +++ b/sha1_name.c > @@ -1012,7 +1012,7 @@ static int reinterpret(const char *name, int namelen, int len, struct strbuf *bu > int ret; > > strbuf_add(buf, name + len, namelen - len); > - ret = interpret_branch_name(buf->buf, &tmp); > + ret = interpret_branch_name(buf->buf, buf->len, &tmp); > /* that data was not interpreted, remove our cruft */ > if (ret < 0) { > strbuf_setlen(buf, used); > @@ -1046,14 +1046,16 @@ static int reinterpret(const char *name, int namelen, int len, struct strbuf *bu > * If the input was ok but there are not N branch switches in the > * reflog, it returns 0. > */ > -int interpret_branch_name(const char *name, struct strbuf *buf) > +int interpret_branch_name(const char *name, int namelen, struct strbuf *buf) > { > char *cp; > struct branch *upstream; > - int namelen = strlen(name); > int len = interpret_nth_prior_checkout(name, buf); > int tmp_len; > > + if (!namelen) > + namelen = strlen(name); > + > if (!len) { > return len; /* syntax Ok, not enough switches */ > } else if (len > 0) { > @@ -1100,7 +1102,7 @@ int interpret_branch_name(const char *name, struct strbuf *buf) > int strbuf_branchname(struct strbuf *sb, const char *name) > { > int len = strlen(name); > - int used = interpret_branch_name(name, sb); > + int used = interpret_branch_name(name, len, sb); > > if (used == len) > return 0; ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v5 2/2] Add new @ shortcut for HEAD 2013-09-02 6:34 [PATCH v5 0/2] Add @ shortcut, again Felipe Contreras 2013-09-02 6:34 ` [PATCH v5 1/2] sha1-name: pass len argument to interpret_branch_name() Felipe Contreras @ 2013-09-02 6:34 ` Felipe Contreras 2013-09-03 18:50 ` Junio C Hamano 1 sibling, 1 reply; 8+ messages in thread From: Felipe Contreras @ 2013-09-02 6:34 UTC (permalink / raw) To: git; +Cc: Stefano Lattarini, Felipe Contreras, Junio C Hamano Typing 'HEAD' is tedious, especially when we can use '@' instead. The reason for choosing '@' is that it follows naturally from the ref@op syntax (e.g. HEAD@{u}), except we have no ref, and no operation, and when we don't have those, it makes sens to assume 'HEAD'. So now we can use 'git show @~1', and all that goody goodness. Until now '@' was a valid name, but it conflicts with this idea, so let's make it invalid. Probably very few people, if any, used this name. Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> --- Documentation/git-check-ref-format.txt | 2 ++ Documentation/revisions.txt | 3 +++ refs.c | 4 ++++ sha1_name.c | 26 ++++++++++++++++++++++++++ t/t1508-at-combinations.sh | 4 ++++ 5 files changed, 39 insertions(+) diff --git a/Documentation/git-check-ref-format.txt b/Documentation/git-check-ref-format.txt index a49be1b..fc02959 100644 --- a/Documentation/git-check-ref-format.txt +++ b/Documentation/git-check-ref-format.txt @@ -54,6 +54,8 @@ Git imposes the following rules on how references are named: . They cannot contain a sequence `@{`. +. They cannot be the single character `@`. + . They cannot contain a `\`. These rules make it easy for shell script based tools to parse diff --git a/Documentation/revisions.txt b/Documentation/revisions.txt index d477b3f..09896a3 100644 --- a/Documentation/revisions.txt +++ b/Documentation/revisions.txt @@ -58,6 +58,9 @@ the '$GIT_DIR/refs' directory or from the '$GIT_DIR/packed-refs' file. While the ref name encoding is unspecified, UTF-8 is preferred as some output processing may assume ref names in UTF-8. +'@':: + '@' alone is a shortcut for 'HEAD'. + '<refname>@\{<date>\}', e.g. 'master@\{yesterday\}', 'HEAD@\{5 minutes ago\}':: A ref followed by the suffix '@' with a date specification enclosed in a brace diff --git a/refs.c b/refs.c index 8fd5faf..bfe10e2 100644 --- a/refs.c +++ b/refs.c @@ -72,6 +72,10 @@ int check_refname_format(const char *refname, int flags) { int component_len, component_count = 0; + if (!strcmp(refname, "@")) + /* Refname is a single character '@'. */ + return -1; + while (1) { /* We are at the start of a path component. */ component_len = check_refname_component(refname, flags); diff --git a/sha1_name.c b/sha1_name.c index 93197b9..b8ece6e 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -1004,6 +1004,26 @@ int get_sha1_mb(const char *name, unsigned char *sha1) return st; } +/* parse @something syntax, when 'something' is not {.*} */ +static int interpret_empty_at(const char *name, int namelen, int len, struct strbuf *buf) +{ + const char *next; + + if (len || name[1] == '{') + return -1; + + /* make sure it's a single @, or @@{.*}, not @foo */ + next = strchr(name + len + 1, '@'); + if (!next) + next = name + namelen; + if (next != 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 */ @@ -1068,9 +1088,15 @@ int interpret_branch_name(const char *name, int namelen, struct strbuf *buf) cp = strchr(name, '@'); if (!cp) 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)); if (!tmp_len) return -1; + len = cp + tmp_len - name; cp = xstrndup(name, cp - name); upstream = branch_get(*cp ? cp : NULL); diff --git a/t/t1508-at-combinations.sh b/t/t1508-at-combinations.sh index e5aea3b..3a52375 100755 --- a/t/t1508-at-combinations.sh +++ b/t/t1508-at-combinations.sh @@ -32,6 +32,7 @@ test_expect_success 'setup' ' git checkout -b upstream-branch && test_commit upstream-one && test_commit upstream-two && + git checkout -b @at-test && git checkout -b old-branch && test_commit old-one && test_commit old-two && @@ -55,6 +56,9 @@ check "HEAD@{u}" ref refs/heads/upstream-branch check "@{u}@{1}" commit upstream-one check "@{-1}@{u}" ref refs/heads/master check "@{-1}@{u}@{1}" commit master-one +check "@" commit new-two +check "@@{u}" ref refs/heads/upstream-branch +check "@at-test" ref refs/heads/@at-test nonsense "@{u}@{-1}" nonsense "@{0}@{0}" nonsense "@{1}@{u}" -- 1.8.4-338-gefd7fa6 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v5 2/2] Add new @ shortcut for HEAD 2013-09-02 6:34 ` [PATCH v5 2/2] Add new @ shortcut for HEAD Felipe Contreras @ 2013-09-03 18:50 ` Junio C Hamano 2013-09-09 2:09 ` Felipe Contreras 0 siblings, 1 reply; 8+ messages in thread From: Junio C Hamano @ 2013-09-03 18:50 UTC (permalink / raw) To: Felipe Contreras; +Cc: git, Stefano Lattarini Felipe Contreras <felipe.contreras@gmail.com> writes: > diff --git a/sha1_name.c b/sha1_name.c > index 93197b9..b8ece6e 100644 > --- a/sha1_name.c > +++ b/sha1_name.c > @@ -1004,6 +1004,26 @@ int get_sha1_mb(const char *name, unsigned char *sha1) > return st; > } > > +/* parse @something syntax, when 'something' is not {.*} */ > +static int interpret_empty_at(const char *name, int namelen, int len, struct strbuf *buf) > +{ > + const char *next; > + > + if (len || name[1] == '{') > + return -1; > + > + /* make sure it's a single @, or @@{.*}, not @foo */ > + next = strchr(name + len + 1, '@'); > + if (!next) > + next = name + namelen; > + if (next != name + 1) > + return -1; > + > + strbuf_reset(buf); > + strbuf_add(buf, "HEAD", 4); > + return 1; > +} Hmph, is the above sufficient? I added a case that mimics Stefano's original regression report (which is handled) and another that uses doubled "@" for the same purpose of introducing a "funny" hierarchy, and it appears that "checkout -b" chokes on it. t/t1508-at-combinations.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/t/t1508-at-combinations.sh b/t/t1508-at-combinations.sh index 3a52375..ceb8449 100755 --- a/t/t1508-at-combinations.sh +++ b/t/t1508-at-combinations.sh @@ -32,6 +32,8 @@ test_expect_success 'setup' ' git checkout -b upstream-branch && test_commit upstream-one && test_commit upstream-two && + git checkout -b @/at-test && + git checkout -b @@/at-test && git checkout -b @at-test && git checkout -b old-branch && test_commit old-one && @@ -58,6 +60,8 @@ check "@{-1}@{u}" ref refs/heads/master check "@{-1}@{u}@{1}" commit master-one check "@" commit new-two check "@@{u}" ref refs/heads/upstream-branch +check "@@/at-test" ref refs/heads/@@/at-test +check "@/at-test" ref refs/heads/@/at-test check "@at-test" ref refs/heads/@at-test nonsense "@{u}@{-1}" nonsense "@{0}@{0}" ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v5 2/2] Add new @ shortcut for HEAD 2013-09-03 18:50 ` Junio C Hamano @ 2013-09-09 2:09 ` Felipe Contreras 2013-09-09 22:54 ` Junio C Hamano 0 siblings, 1 reply; 8+ messages in thread From: Felipe Contreras @ 2013-09-09 2:09 UTC (permalink / raw) To: Junio C Hamano; +Cc: git, Stefano Lattarini On Tue, Sep 3, 2013 at 1:50 PM, Junio C Hamano <gitster@pobox.com> wrote: > Felipe Contreras <felipe.contreras@gmail.com> writes: > >> diff --git a/sha1_name.c b/sha1_name.c >> index 93197b9..b8ece6e 100644 >> --- a/sha1_name.c >> +++ b/sha1_name.c >> @@ -1004,6 +1004,26 @@ int get_sha1_mb(const char *name, unsigned char *sha1) >> return st; >> } >> >> +/* parse @something syntax, when 'something' is not {.*} */ >> +static int interpret_empty_at(const char *name, int namelen, int len, struct strbuf *buf) >> +{ >> + const char *next; >> + >> + if (len || name[1] == '{') >> + return -1; >> + >> + /* make sure it's a single @, or @@{.*}, not @foo */ >> + next = strchr(name + len + 1, '@'); >> + if (!next) >> + next = name + namelen; >> + if (next != name + 1) >> + return -1; >> + >> + strbuf_reset(buf); >> + strbuf_add(buf, "HEAD", 4); >> + return 1; >> +} > > Hmph, is the above sufficient? I added a case that mimics Stefano's > original regression report (which is handled) and another that uses > doubled "@" for the same purpose of introducing a "funny" hierarchy, > and it appears that "checkout -b" chokes on it. This fixes it: --- a/sha1_name.c +++ b/sha1_name.c @@ -1014,6 +1014,8 @@ static int interpret_empty_at(const char *name, int namelen, int len, struct str /* make sure it's a single @, or @@{.*}, not @foo */ next = strchr(name + len + 1, '@'); + if (next && next[1] != '{') + return -1; if (!next) next = name + namelen; if (next != name + 1) -- Felipe Contreras ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v5 2/2] Add new @ shortcut for HEAD 2013-09-09 2:09 ` Felipe Contreras @ 2013-09-09 22:54 ` Junio C Hamano 2013-09-10 22:08 ` Junio C Hamano 0 siblings, 1 reply; 8+ messages in thread From: Junio C Hamano @ 2013-09-09 22:54 UTC (permalink / raw) To: Felipe Contreras; +Cc: git, Stefano Lattarini Felipe Contreras <felipe.contreras@gmail.com> writes: >> Hmph, is the above sufficient? I added a case that mimics Stefano's >> original regression report (which is handled) and another that uses >> doubled "@" for the same purpose of introducing a "funny" hierarchy, >> and it appears that "checkout -b" chokes on it. > > This fixes it: > > --- a/sha1_name.c > +++ b/sha1_name.c > @@ -1014,6 +1014,8 @@ static int interpret_empty_at(const char *name, > int namelen, int len, struct str > > /* make sure it's a single @, or @@{.*}, not @foo */ > next = strchr(name + len + 1, '@'); > + if (next && next[1] != '{') > + return -1; > if (!next) > next = name + namelen; > if (next != name + 1) I think this should be sufficient for all cases, as the sequence "@{" cannot be a part of valid reference names. Thanks. I see v6 was posted yesterday after this message, but it does not seem to have this fix, nor the additional test case I gave you in the message upthread. Sent a wrong version of patch by mistake? ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v5 2/2] Add new @ shortcut for HEAD 2013-09-09 22:54 ` Junio C Hamano @ 2013-09-10 22:08 ` Junio C Hamano 0 siblings, 0 replies; 8+ messages in thread From: Junio C Hamano @ 2013-09-10 22:08 UTC (permalink / raw) To: Felipe Contreras; +Cc: git, Stefano Lattarini Junio C Hamano <gitster@pobox.com> writes: > Felipe Contreras <felipe.contreras@gmail.com> writes: > >>> Hmph, is the above sufficient? I added a case that mimics Stefano's >>> original regression report (which is handled) and another that uses >>> doubled "@" for the same purpose of introducing a "funny" hierarchy, >>> and it appears that "checkout -b" chokes on it. >> >> This fixes it: >> >> --- a/sha1_name.c >> +++ b/sha1_name.c >> @@ -1014,6 +1014,8 @@ static int interpret_empty_at(const char *name, >> int namelen, int len, struct str >> >> /* make sure it's a single @, or @@{.*}, not @foo */ >> next = strchr(name + len + 1, '@'); >> + if (next && next[1] != '{') >> + return -1; >> if (!next) >> next = name + namelen; >> if (next != name + 1) > > I think this should be sufficient for all cases, as the sequence > "@{" cannot be a part of valid reference names. > > Thanks. > > I see v6 was posted yesterday after this message, but it does not > seem to have this fix, nor the additional test case I gave you in > the message upthread. Sent a wrong version of patch by mistake? Ping? I could squash the fixup at the tip of on fc/at-head in if you want me to, but v6 seems to be a mistake to me. ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2013-09-10 22:08 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2013-09-02 6:34 [PATCH v5 0/2] Add @ shortcut, again Felipe Contreras 2013-09-02 6:34 ` [PATCH v5 1/2] sha1-name: pass len argument to interpret_branch_name() Felipe Contreras 2013-09-03 18:40 ` Junio C Hamano 2013-09-02 6:34 ` [PATCH v5 2/2] Add new @ shortcut for HEAD Felipe Contreras 2013-09-03 18:50 ` Junio C Hamano 2013-09-09 2:09 ` Felipe Contreras 2013-09-09 22:54 ` Junio C Hamano 2013-09-10 22:08 ` Junio C Hamano
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).