Johannes Schindelin venit, vidit, dixit 10.09.2009 11:36: > > Often, it is quite interesting to inspect the branch tracked by a given > branch. This patch introduces a nice notation to get at the tracked > branch: '<branch>@{tracked}' can be used to access that tracked branch. > > A special shortcut '@{tracked}' refers to the branch tracked by the > current branch. Sorry, I didn't know the name of the long form was up for discussion. But it should certainly coincide with the key which for-each-ref uses, shouldn't it? I don't care whether tracked or upstream, but for-each-ref's "upstream" has set the precedent. > > Suggested by Pasky. > > The syntax was suggested by Junio. > > Signed-off-by: Johannes Schindelin <johannes.schindelin@xxxxxx> > --- > > I decided that I like @{tracked} better than @{upstream} (which > reads to me more like the upstream _repository_), but hey, I made > the code flexible enough to change that at a whim. > > Documentation/git-rev-parse.txt | 4 ++ > sha1_name.c | 37 ++++++++++++++++++++-- > t/t1506-rev-parse-tracked.sh | 64 +++++++++++++++++++++++++++++++++++++++ > 3 files changed, 102 insertions(+), 3 deletions(-) > create mode 100755 t/t1506-rev-parse-tracked.sh > > diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt > index 82045a2..09a2145 100644 > --- a/Documentation/git-rev-parse.txt > +++ b/Documentation/git-rev-parse.txt > @@ -231,6 +231,10 @@ when you run 'git-merge'. > * The special construct '@\{-<n>\}' means the <n>th branch checked out > before the current one. > > +* The suffix '@{tracked}' to a ref (short form 'blabla@{t}') refers to > + the branch tracked by that ref. If no ref was specified, it means the > + branch tracked by the current branch. > + > * A suffix '{caret}' to a revision parameter means the first parent of > that commit object. '{caret}<n>' means the <n>th parent (i.e. > 'rev{caret}' > diff --git a/sha1_name.c b/sha1_name.c > index 44bb62d..a886846 100644 > --- a/sha1_name.c > +++ b/sha1_name.c > @@ -5,6 +5,7 @@ > #include "blob.h" > #include "tree-walk.h" > #include "refs.h" > +#include "remote.h" > > static int find_short_object_filename(int len, const char *name, unsigned char *sha1) > { > @@ -238,9 +239,24 @@ static int ambiguous_path(const char *path, int len) > return slash; > } > > +static inline int tracked_suffix(const char *string, int len) > +{ > + const char *suffix[] = { "@{tracked}", "@{t}" }; > + int i; > + > + for (i = 0; i < ARRAY_SIZE(suffix); i++) { > + int suffix_len = strlen(suffix[i]); > + if (len >= suffix_len && !memcmp(string + len - suffix_len, > + suffix[i], suffix_len)) > + return suffix_len; > + } > + return 0; > +} > + > /* > * *string and *len will only be substituted, and *string returned (for > - * later free()ing) if the string passed in is of the form @{-<n>}. > + * later free()ing) if the string passed in is of the form @{-<n>} or > + * of the form <branch>@{tracked}. > */ > static char *substitute_branch_name(const char **string, int *len) > { > @@ -254,6 +270,19 @@ static char *substitute_branch_name(const char **string, int *len) > return (char *)*string; > } > > + ret = tracked_suffix(*string, *len); > + if (ret) { > + char *ref = xstrndup(*string, *len - ret); > + struct branch *tracking = branch_get(*ref ? ref : NULL); > + > + free(ref); > + if (tracking->merge && tracking->merge[0]->dst) { > + *string = xstrdup(tracking->merge[0]->dst); > + *len = strlen(*string); > + return (char *)*string; > + } > + } > + > return NULL; > } > > @@ -340,8 +369,10 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1) > if (len && str[len-1] == '}') { > for (at = len-2; at >= 0; at--) { > if (str[at] == '@' && str[at+1] == '{') { > - reflog_len = (len-1) - (at+2); > - len = at; > + if (!tracked_suffix(str + at, len - at)) { > + reflog_len = (len-1) - (at+2); > + len = at; > + } > break; > } > } > diff --git a/t/t1506-rev-parse-tracked.sh b/t/t1506-rev-parse-tracked.sh > new file mode 100755 > index 0000000..89193e1 > --- /dev/null > +++ b/t/t1506-rev-parse-tracked.sh > @@ -0,0 +1,64 @@ > +#!/bin/sh > + > +test_description='test <branch>@{tracked} syntax' > + > +. ./test-lib.sh > + > + > +test_expect_success 'setup' ' > + > + test_commit 1 && > + git checkout -b side && > + test_commit 2 && > + git checkout master && > + git clone . clone && > + test_commit 3 && > + (cd clone && > + test_commit 4 && > + git branch --track my-side origin/side) > + > +' > + > +full_name () { > + (cd clone && > + git rev-parse --symbolic-full-name "$@") > +} > + > +commit_subject () { > + (cd clone && > + git show -s --pretty=format:%s "$@") > +} > + > +test_expect_success '@{tracked} resolves to correct full name' ' > + test refs/remotes/origin/master = "$(full_name @{tracked})" > +' > + > +test_expect_success '@{t} resolves to correct full name' ' > + test refs/remotes/origin/master = "$(full_name @{t})" > +' > + > +test_expect_success 'my-side@{tracked} resolves to correct full name' ' > + test refs/remotes/origin/side = "$(full_name my-side@{t})" > +' > + > +test_expect_success 'my-side@{t} resolves to correct commit' ' > + git checkout side && > + test_commit 5 && > + (cd clone && git fetch) && > + test 2 = "$(commit_subject my-side)" && > + test 5 = "$(commit_subject my-side@{t})" > +' > + > +test_expect_success 'not-tracking@{t} fails' ' > + test_must_fail full_name non-tracking@{t} && > + (cd clone && git checkout --no-track -b non-tracking) && > + test_must_fail full_name non-tracking@{t} > +' > + > +test_expect_success '<branch>@{t}@{1} resolves correctly' ' > + test_commit 6 && > + (cd clone && git fetch) && > + test 5 = $(commit_subject my-side@{t}@{1}) > +' > + > +test_done -- 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