* default behaviour for `gitmerge` (no arguments) @ 2010-01-11 18:49 Gareth Adams 2010-01-11 19:43 ` Junio C Hamano 0 siblings, 1 reply; 30+ messages in thread From: Gareth Adams @ 2010-01-11 18:49 UTC (permalink / raw) To: git Hi there, long time user; first time caller here. I wanted to suggest an improvement to git-merge which will either save some typing or save some network resources. It won't save huge amounts of either but every little helps! Currently, some of my colleagues frequently end up typing: git pull; ...; git checkout otherbranch; git pull Now, we have quite a low commit rate, it's unlikely (albeit vaguely possible) that two people are working on the branch at the same time. This means the second pull is doing a fetch which it effectively pointless. Now of course this is a tiny amount of wastage, and while I could argue that it would be an issue under poor network conditions that's not my point. As a coder I'd want to get rid of the redundant fetch if I know it's redundant. Unfortunately my other option is: git pull; ...; git checkout otherbranch; git merge myremote/otherbranch which is annoying extra typing. Even with tab completion, it's redundant extra typing because in these cases I'm trying to merge with the branch being tracked. My suggestion is that `git merge` defaults to the same merge that a `git pull` would perform, and there are 2 extra factors that make me think it's a workable idea: 1) At the moment, `git merge` does nothing. Except mock me for not giving it a command in a format it recognises. This change wouldn't have any effect that would cause anyone a problem 2) When I checkout a branch which has unmerged changes in the tracking branch, git *tells me* what branch I will be taking action with "Your branch is behind the tracked remote branch '...' by 4 commits, and can be fast-forwarded" - but then makes me type it out explicitly anyway! I appreciate that there are many workflows where there is an advantage in performing a second pull in case there are additional changes since the first pull, but I still think there is a string case for git merge having a more sensible default, as git pull does. What do you think? Thanks, Gareth ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: default behaviour for `gitmerge` (no arguments) 2010-01-11 18:49 default behaviour for `gitmerge` (no arguments) Gareth Adams @ 2010-01-11 19:43 ` Junio C Hamano 2010-01-12 16:23 ` Jeff King 0 siblings, 1 reply; 30+ messages in thread From: Junio C Hamano @ 2010-01-11 19:43 UTC (permalink / raw) To: Gareth Adams; +Cc: git Gareth Adams <gareth.adams@gmail.com> writes: > Unfortunately my other option is: > > git pull; ...; git checkout otherbranch; git merge myremote/otherbranch > > which is annoying extra typing. Replace 'pull' with 'fetch' and a bit more regular pattern would emerge. The code indeed knows (as you can see "git pull" can figure it out) what other ref the current branch is configured to merge with by default. There is even a plumbing to do this for script writers. $ git for-each-ref --format='%(upstream)' $(git symbolic-ref HEAD) We can teach this short-hand to "git merge", perhaps: $ git merge --default But "no argument" cannot be the short-hand, because... > 1) At the moment, `git merge` does nothing. Except mock me for not giving it a > command in a format it recognises. This change wouldn't have any effect that > would cause anyone a problem ... except for people who uses a script that does commits= while some condition do commit=$(find some other commit that should be merged) commits="$commits$commit " done git merge $commits and expect the last step will fail without doing any damage when the loop finds no new developments. "no argument means --default" will break their scripts. ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: default behaviour for `gitmerge` (no arguments) 2010-01-11 19:43 ` Junio C Hamano @ 2010-01-12 16:23 ` Jeff King 2010-01-12 18:11 ` Junio C Hamano 0 siblings, 1 reply; 30+ messages in thread From: Jeff King @ 2010-01-12 16:23 UTC (permalink / raw) To: Junio C Hamano; +Cc: Gareth Adams, git On Mon, Jan 11, 2010 at 11:43:40AM -0800, Junio C Hamano wrote: > The code indeed knows (as you can see "git pull" can figure it out) what > other ref the current branch is configured to merge with by default. > There is even a plumbing to do this for script writers. > > $ git for-each-ref --format='%(upstream)' $(git symbolic-ref HEAD) > > We can teach this short-hand to "git merge", perhaps: > > $ git merge --default > > But "no argument" cannot be the short-hand, because... Hmm. If we had the oft-discussed-but-never-agreed-upon shorthand for "the upstream of" then we wouldn't need a special merge option. You could just do: git merge %HEAD ;# (or git merge %, IIRC the proposal correctly) -Peff ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: default behaviour for `gitmerge` (no arguments) 2010-01-12 16:23 ` Jeff King @ 2010-01-12 18:11 ` Junio C Hamano 2010-01-12 18:25 ` Jeff King 0 siblings, 1 reply; 30+ messages in thread From: Junio C Hamano @ 2010-01-12 18:11 UTC (permalink / raw) To: Jeff King; +Cc: Gareth Adams, git Jeff King <peff@peff.net> writes: > Hmm. If we had the oft-discussed-but-never-agreed-upon shorthand for > "the upstream of" then we wouldn't need a special merge option. You > could just do: > > git merge %HEAD ;# (or git merge %, IIRC the proposal correctly) I don't think "whatever _HEAD_ tracks" makes sense at the semantic level (i.e. you don't do "branch.HEAD.merge") but a syntax for "whatever the named _branch_ tracks" with "if a branch is not named, the current branch is implied" (i.e. the one in parentheses) would. It is an entirely different matter what the special syntax to trigger that "upstream-ness" should be. I vaguely recall @{upstream} or @{u} were the concensus? ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: default behaviour for `gitmerge` (no arguments) 2010-01-12 18:11 ` Junio C Hamano @ 2010-01-12 18:25 ` Jeff King 2010-01-13 6:57 ` Junio C Hamano 0 siblings, 1 reply; 30+ messages in thread From: Jeff King @ 2010-01-12 18:25 UTC (permalink / raw) To: Junio C Hamano; +Cc: Johannes Schindelin, Gareth Adams, git On Tue, Jan 12, 2010 at 10:11:26AM -0800, Junio C Hamano wrote: > Jeff King <peff@peff.net> writes: > > > Hmm. If we had the oft-discussed-but-never-agreed-upon shorthand for > > "the upstream of" then we wouldn't need a special merge option. You > > could just do: > > > > git merge %HEAD ;# (or git merge %, IIRC the proposal correctly) > > I don't think "whatever _HEAD_ tracks" makes sense at the semantic level > (i.e. you don't do "branch.HEAD.merge") but a syntax for "whatever the > named _branch_ tracks" with "if a branch is not named, the current branch > is implied" (i.e. the one in parentheses) would. The patch that Dscho provided would actually convert HEAD@{upstream} into the upstream of whatever HEAD pointed at. Which I think makes sense. We don't do it for reflogs, but that is because it is useful to distinguish between the reflog for a symref and the thing it points to. But since one would presumably not make such a configuration for a symref, that distinction is not useful. > It is an entirely different matter what the special syntax to trigger that > "upstream-ness" should be. I vaguely recall @{upstream} or @{u} were the > concensus? Ah, right. I remembered hating "%" even as I typed it, but I had forgotten about the followup discussion. Looking at it again, I note: 1. The last posted patch still has a misplaced free() (patch below), but I think otherwise is not buggy. 2. We don't complain on "git show @{usptream}" and we probably should. I remember there being some complications because the contents of @{} were passed to approxidate, but I think we can get around that by letting approxidate complain if _nothing_ in the date was useful. So "git show @{2.weeks.and.7.hot.dogs.ago}" would still work, but "git show @{totally.bogus.input}" would complain. 3. I have actually been running with Dscho's patch for the last couple of months, and I don't remember using it once. So perhaps it is not as useful as I might have thought. :) Anyway, fixup patch is below. I don't expect you to pick up the topic or anything, but since I went to the trouble to find the bug once upon a time, I thought I would post the fix for anybody who does want to pick it up. diff --git a/sha1_name.c b/sha1_name.c index b73b93e..da90ebe 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -275,9 +275,9 @@ static char *substitute_branch_name(const char **string, int *len) char *ref = xstrndup(*string, *len - ret); struct branch *tracking = branch_get(*ref ? ref : NULL); - free(ref); if (!tracking) die ("No tracking branch found for '%s'", ref); + free(ref); if (tracking->merge && tracking->merge[0]->dst) { *string = xstrdup(tracking->merge[0]->dst); *len = strlen(*string); ^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: default behaviour for `gitmerge` (no arguments) 2010-01-12 18:25 ` Jeff King @ 2010-01-13 6:57 ` Junio C Hamano 2010-01-13 9:26 ` Johannes Schindelin 2010-01-20 9:38 ` [PATCH 0/2] @{u} updates Junio C Hamano 0 siblings, 2 replies; 30+ messages in thread From: Junio C Hamano @ 2010-01-13 6:57 UTC (permalink / raw) To: Jeff King; +Cc: Johannes Schindelin, Gareth Adams, git Jeff King <peff@peff.net> writes: > Ah, right. I remembered hating "%" even as I typed it, but I had > forgotten about the followup discussion. Looking at it again, I note: > > 1. The last posted patch still has a misplaced free() (patch below), > but I think otherwise is not buggy. > > 2. We don't complain on "git show @{usptream}" and we probably should. > I remember there being some complications because the contents of > @{} were passed to approxidate, but I think we can get around that > by letting approxidate complain if _nothing_ in the date was > useful. So "git show @{2.weeks.and.7.hot.dogs.ago}" would still > work, but "git show @{totally.bogus.input}" would complain. > > 3. I have actually been running with Dscho's patch for the last couple > of months, and I don't remember using it once. So perhaps it is not > as useful as I might have thought. :) I presume we are discussing this patch? http://article.gmane.org/gmane.comp.version-control.git/128121 I'll squash the free() fix; thanks. I wondered why it doesn't hook into interpret_branch_name(), and instead adds itself to the static substitute_branch_name(); it forbids the use of the syntax from by callers of strbuf_branchname(). I agree with your point #2 above. Regarding your point #3, I don't think the notation should be that useful if your workflow is sane. The original use case that triggered the resurrection of the patch went like this: git fetch && for local in my set of local branches do git checkout $local && git merge $local@{upstream} || { echo failed to merge on $local break } done and the new notation might look useful in the scenario. But the thing is, constantly merging with the other side, even if you haven't added anything of value since you merged from there last time, is a bad practice to begin with. I added one use case that is sane _and_ will be helped by the new notation to the rewritten version of Dscho's patch (below). Just to refresh our memory from the old thread and make sure we are discussing the same patch, here is what I am planning to queue. The log message and documentation are somewhat updated to avoid the word "track" because it seems that everybody gets confused and starts talking different things whenever that word is used. For the same reason, the test script was renamed. In this set-up, for example: [remote "filfre"] url = ... fetch = +refs/heads/nitfol:refs/heads/rezrov [branch "frotz"] remote = filfre merge = refs/heads/nitfol some people say rezrov tracks nitfol from filfre but Dscho's patch says frotz tracks nitfol from filfre. They _may_ both track, but they "track" the other in a quite differently way, so the word has become meaningless. I've been trying to be careful and used different words to disambiguate whenever I had to talk about these concepts: - The purpose of rezrov is to keep a tab on the progress of the nitfol branch at the remote end. We say rezrov is a remote tracking branch for nitfol from filfre. - On the other hand, we have branch frotz that forked from nitfol that came from filfre. It builds on top of that history by occasionally merging with it at key points in the history. So we say frotz builds on top of nitfol from filfre. We also say nitfol at filfre is the upstream of frotz. -- >8 -- Date: Thu, 10 Sep 2009 17:25:57 +0200 Subject: [PATCH] Introduce <branch>@{upstream} notation A new notation '<branch>@{upstream}' refers to the branch <branch> is set to build on top of. Missing <branch> (i.e. '@{upstream}') defaults to the current branch. This allows you to run, for example, for l in list of local branches do git log --oneline --left-right $l...$l@{upstream} done to inspect each of the local branches you are interested in for the divergence from its upstream. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com> --- Documentation/git-rev-parse.txt | 4 ++ sha1_name.c | 39 ++++++++++++++++++++-- t/t1506-rev-parse-upstream.sh | 69 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+), 3 deletions(-) create mode 100755 t/t1506-rev-parse-upstream.sh diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt index 82045a2..923b56a 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 '@{upstream}' to a ref (short form 'ref@{u}') refers to + the branch the ref is set to build on top of. Missing ref defaults + to 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..fb4e214 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[] = { "@{upstream}", "@{u}" }; + 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>@{upstream}. */ static char *substitute_branch_name(const char **string, int *len) { @@ -254,6 +270,21 @@ 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); + + if (!tracking) + die ("No tracking branch found for '%s'", ref); + 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 +371,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-upstream.sh b/t/t1506-rev-parse-upstream.sh new file mode 100755 index 0000000..5abdc13 --- /dev/null +++ b/t/t1506-rev-parse-upstream.sh @@ -0,0 +1,69 @@ +#!/bin/sh + +test_description='test <branch>@{upstream} 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 '@{upstream} resolves to correct full name' ' + test refs/remotes/origin/master = "$(full_name @{upstream})" +' + +test_expect_success '@{u} resolves to correct full name' ' + test refs/remotes/origin/master = "$(full_name @{u})" +' + +test_expect_success 'my-side@{upstream} resolves to correct full name' ' + test refs/remotes/origin/side = "$(full_name my-side@{u})" +' + +test_expect_success 'my-side@{u} 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@{u})" +' + +test_expect_success 'not-tracking@{u} fails' ' + test_must_fail full_name non-tracking@{u} && + (cd clone && git checkout --no-track -b non-tracking) && + test_must_fail full_name non-tracking@{u} +' + +test_expect_success '<branch>@{u}@{1} resolves correctly' ' + test_commit 6 && + (cd clone && git fetch) && + test 5 = $(commit_subject my-side@{u}@{1}) +' + +test_expect_success '@{u} without specifying branch fails on a detached HEAD' ' + git checkout HEAD^0 && + test_must_fail git rev-parse @{u} +' + +test_done -- 1.6.6.280.ge295b7.dirty ^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: default behaviour for `gitmerge` (no arguments) 2010-01-13 6:57 ` Junio C Hamano @ 2010-01-13 9:26 ` Johannes Schindelin 2010-01-13 9:47 ` Junio C Hamano 2010-01-20 9:38 ` [PATCH 0/2] @{u} updates Junio C Hamano 1 sibling, 1 reply; 30+ messages in thread From: Johannes Schindelin @ 2010-01-13 9:26 UTC (permalink / raw) To: Junio C Hamano; +Cc: Jeff King, Gareth Adams, git Hi, On Tue, 12 Jan 2010, Junio C Hamano wrote: > I wondered why it doesn't hook into interpret_branch_name(), and instead > adds itself to the static substitute_branch_name(); it forbids the use > of the syntax from by callers of strbuf_branchname(). I _think_ it was to allow something like git log -g @{u} but frankly, this is so long ago, I do not remember, I reconstructed this reasoning as being the most likely. Ciao, Dscho ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: default behaviour for `gitmerge` (no arguments) 2010-01-13 9:26 ` Johannes Schindelin @ 2010-01-13 9:47 ` Junio C Hamano 2010-01-13 11:04 ` Johannes Schindelin 0 siblings, 1 reply; 30+ messages in thread From: Junio C Hamano @ 2010-01-13 9:47 UTC (permalink / raw) To: Johannes Schindelin; +Cc: Jeff King, Gareth Adams, git Johannes Schindelin <Johannes.Schindelin@gmx.de> writes: >> I wondered why it doesn't hook into interpret_branch_name(), and instead >> adds itself to the static substitute_branch_name(); it forbids the use >> of the syntax from by callers of strbuf_branchname(). > > I _think_ it was to allow something like > > git log -g @{u} > > but frankly, this is so long ago, I do not remember, I reconstructed this > reasoning as being the most likely. That is not the question I was asking. If you compare substitute_branch_name() and interpret_branch_name() before your patch, you will notice that they are _meant_ to do the same thing, with different external API, only because many callers in sha1_name.c do not use strbuf to hold their names. The primary API is the latter (which is extern), and the former (which is static) is merely a helping wrapper that is internal to sha1_name.c But with your patch, they suddenly have different semantics, and the function that implements the primary API doesn't know anything about this new @{upstream} syntax. This discrepancy will affect callers of strbuf_branchname(), e.g. merge_name() in builtin-merge.c that prepares the "Merge branch nitfol of remote frotz" message, or delete_branches() in builtin-branch.c. Note that I am not saying "branch -d @{upstream}" should or should not work (at least not yet---I haven't thought the issues through). But I wanted to know if this subtle change in the semantics was a deliberate choice, and if so wanted to see the reason behind it described clearly. ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: default behaviour for `gitmerge` (no arguments) 2010-01-13 9:47 ` Junio C Hamano @ 2010-01-13 11:04 ` Johannes Schindelin 2010-01-13 19:48 ` Junio C Hamano 0 siblings, 1 reply; 30+ messages in thread From: Johannes Schindelin @ 2010-01-13 11:04 UTC (permalink / raw) To: Junio C Hamano; +Cc: Jeff King, Gareth Adams, git Hi, On Wed, 13 Jan 2010, Junio C Hamano wrote: > Johannes Schindelin <Johannes.Schindelin@gmx.de> writes: > > >> I wondered why it doesn't hook into interpret_branch_name(), and > >> instead adds itself to the static substitute_branch_name(); it > >> forbids the use of the syntax from by callers of strbuf_branchname(). > > > > I _think_ it was to allow something like > > > > git log -g @{u} > > > > but frankly, this is so long ago, I do not remember, I reconstructed this > > reasoning as being the most likely. > > That is not the question I was asking. > > If you compare substitute_branch_name() and interpret_branch_name() before > your patch, you will notice that they are _meant_ to do the same thing, > with different external API, only because many callers in sha1_name.c do > not use strbuf to hold their names. The primary API is the latter (which > is extern), and the former (which is static) is merely a helping wrapper > that is internal to sha1_name.c So you meant to say that substitute_branch_name() calls interpret_branch_name(), so the change should be in the latter. (This is supposed to be the summary of your 4 paragraphs.) I have no problems with that, except that I do not have the time to do it myself. Ciao, Dscho ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: default behaviour for `gitmerge` (no arguments) 2010-01-13 11:04 ` Johannes Schindelin @ 2010-01-13 19:48 ` Junio C Hamano 2010-01-13 22:49 ` Johannes Schindelin 0 siblings, 1 reply; 30+ messages in thread From: Junio C Hamano @ 2010-01-13 19:48 UTC (permalink / raw) To: Johannes Schindelin; +Cc: Jeff King, Gareth Adams, git Johannes Schindelin <Johannes.Schindelin@gmx.de> writes: > So you meant to say that substitute_branch_name() calls > interpret_branch_name(), so the change should be in the latter. (This is > supposed to be the summary of your 4 paragraphs.) Not quite. What I was asking was: *PROVIDED* *IF* you wanted to keep the same semantics between them, then you would have patched i-b-n, but you didn't. Was there a reason callers of s-b-n should know about @{u} but callers of i-b-n shouldn't? Expected answer was either: (a) Codepath X that uses i-b-n shouldn't interpret @{upstream} as a symbolic name given by the user, but it should treat it as a mere SHA-1 expression instead for *this and that* reason. Otherwise we will see *this* breakage when the user does *that*. That is why i-b-n doesn't know about the new syntax; or (b) It was a thinko; all codepaths that use i-b-n should know the new syntax as they _are_ interested in learning the symbolic name when the user gives @{upstream}. ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: default behaviour for `gitmerge` (no arguments) 2010-01-13 19:48 ` Junio C Hamano @ 2010-01-13 22:49 ` Johannes Schindelin 2010-01-13 23:13 ` Junio C Hamano 0 siblings, 1 reply; 30+ messages in thread From: Johannes Schindelin @ 2010-01-13 22:49 UTC (permalink / raw) To: Junio C Hamano; +Cc: Jeff King, Gareth Adams, git Hi, On Wed, 13 Jan 2010, Junio C Hamano wrote: > Johannes Schindelin <Johannes.Schindelin@gmx.de> writes: > > What I was asking was: > > *PROVIDED* *IF* you wanted to keep the same semantics between > them, then you would have patched i-b-n, but you didn't. Was there > a reason callers of s-b-n should know about @{u} but callers of i-b-n > shouldn't? > > Expected answer was either: > > (a) Codepath X that uses i-b-n shouldn't interpret @{upstream} as > a symbolic name given by the user, but it should treat it as a > mere SHA-1 expression instead for *this and that* reason. > Otherwise we will see *this* breakage when the user does > *that*. That is why i-b-n doesn't know about the new syntax; > or > > (b) It was a thinko; all codepaths that use i-b-n should know the > new syntax as they _are_ interested in learning the symbolic > name when the user gives @{upstream}. And I gave answer (c): I do not remember. Ciao, Dscho ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: default behaviour for `gitmerge` (no arguments) 2010-01-13 22:49 ` Johannes Schindelin @ 2010-01-13 23:13 ` Junio C Hamano 0 siblings, 0 replies; 30+ messages in thread From: Junio C Hamano @ 2010-01-13 23:13 UTC (permalink / raw) To: Johannes Schindelin; +Cc: Jeff King, Gareth Adams, git Johannes Schindelin <Johannes.Schindelin@gmx.de> writes: >> What I was asking was: >> >> *PROVIDED* *IF* you wanted to keep the same semantics between >> them, then you would have patched i-b-n, but you didn't. Was there >> a reason callers of s-b-n should know about @{u} but callers of i-b-n >> shouldn't? >> >> Expected answer was either: >> >> (a) Codepath X that uses i-b-n shouldn't interpret @{upstream} as >> a symbolic name given by the user, but it should treat it as a >> mere SHA-1 expression instead for *this and that* reason. >> Otherwise we will see *this* breakage when the user does >> *that*. That is why i-b-n doesn't know about the new syntax; >> or >> >> (b) It was a thinko; all codepaths that use i-b-n should know the >> new syntax as they _are_ interested in learning the symbolic >> name when the user gives @{upstream}. > > And I gave answer (c): I do not remember. That's fine. As long as we know it is (c) (your earlier response sounded as if you were saying (b)), we know that there might be issues we need to find and carefully look at before using this topic. ^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 0/2] @{u} updates 2010-01-13 6:57 ` Junio C Hamano 2010-01-13 9:26 ` Johannes Schindelin @ 2010-01-20 9:38 ` Junio C Hamano 2010-01-20 9:38 ` [PATCH 1/2] t1506: more test for @{upstream} syntax Junio C Hamano ` (2 more replies) 1 sibling, 3 replies; 30+ messages in thread From: Junio C Hamano @ 2010-01-20 9:38 UTC (permalink / raw) To: git; +Cc: Jeff King, Johannes Schindelin Earlier I wondered if the approach Dscho's patch takes to teach the new @{upstream} syntax to substitute_branch_name() (hence dwim_ref()) without teaching it to interpret_branch_name() (hence strbuf_branchname()) was a bad idea. I thought about this a bit more; there are some downsides for not doing so. The first patch adds a handful of tests that show why strbuf_branchname() callers may also want to learn about the new syntax. The second patch moves the logic to interpret_branch_name() to make them happier. The name of the key function was changed from tracked_suffix() to upstream_mark(), not only because the syntax talks about @{upstream}, but because the parsing needs to recognize the @{u}/@{upstream} mark at the beginning of the given string (that is a suffix to some other string), and strip it (the earlier code wanted @{u} to be at the very end but the callers need to have it at the beginning). Junio C Hamano (2): t1506: more test for @{upstream} syntax Teach @{upstream} syntax to strbuf_branchanme() sha1_name.c | 116 ++++++++++++++++++++++++++--------------- t/t1506-rev-parse-upstream.sh | 41 ++++++++++++++ 2 files changed, 115 insertions(+), 42 deletions(-) ^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 1/2] t1506: more test for @{upstream} syntax 2010-01-20 9:38 ` [PATCH 0/2] @{u} updates Junio C Hamano @ 2010-01-20 9:38 ` Junio C Hamano 2010-01-26 13:07 ` Jeff King 2010-01-20 9:38 ` [PATCH 2/2] Teach @{upstream} syntax to strbuf_branchanme() Junio C Hamano 2010-01-20 13:08 ` [PATCH 0/2] @{u} updates Johannes Schindelin 2 siblings, 1 reply; 30+ messages in thread From: Junio C Hamano @ 2010-01-20 9:38 UTC (permalink / raw) To: git; +Cc: Jeff King, Johannes Schindelin This adds a few more tests that exercises @{upstream} syntax by commands that operate differently when they are given branch name as opposed to a refname (i.e. where "master" and "refs/heads/master" makes a difference). Signed-off-by: Junio C Hamano <gitster@pobox.com> --- t/t1506-rev-parse-upstream.sh | 41 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 41 insertions(+), 0 deletions(-) diff --git a/t/t1506-rev-parse-upstream.sh b/t/t1506-rev-parse-upstream.sh index 5abdc13..a2c7f92 100755 --- a/t/t1506-rev-parse-upstream.sh +++ b/t/t1506-rev-parse-upstream.sh @@ -66,4 +66,45 @@ test_expect_success '@{u} without specifying branch fails on a detached HEAD' ' test_must_fail git rev-parse @{u} ' +test_expect_success 'checkout -b new my-side@{u} forks from the same' ' +( + cd clone && + git checkout -b new my-side@{u} && + git rev-parse --symbolic-full-name my-side@{u} >expect && + git rev-parse --symbolic-full-name new@{u} >actual && + test_cmp expect actual +) +' + +test_expect_failure 'merge my-side@{u} records the correct name' ' +( + sq="'\''" && + cd clone || exit + git checkout master || exit + git branch -D new ;# can fail but is ok + git branch -t new my-side@{u} && + git merge -s ours new@{u} && + git show -s --pretty=format:%s >actual && + echo "Merge remote branch ${sq}origin/side${sq}" >expect && + test_cmp expect actual +) +' + +test_expect_failure 'branch -d other@{u}' ' + git checkout -t -b other master && + git branch -d @{u} && + git for-each-ref refs/heads/master >actual && + >expect && + test_cmp expect actual +' + +test_expect_failure 'checkout other@{u}' ' + git branch -f master HEAD && + git checkout -t -b another master && + git checkout @{u} && + git symbolic-ref HEAD >actual && + echo refs/heads/master >expect && + test_cmp expect actual +' + test_done -- 1.6.6.513.g63f4c ^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH 1/2] t1506: more test for @{upstream} syntax 2010-01-20 9:38 ` [PATCH 1/2] t1506: more test for @{upstream} syntax Junio C Hamano @ 2010-01-26 13:07 ` Jeff King 2010-01-26 19:58 ` Junio C Hamano 2010-01-26 21:32 ` Junio C Hamano 0 siblings, 2 replies; 30+ messages in thread From: Jeff King @ 2010-01-26 13:07 UTC (permalink / raw) To: Junio C Hamano; +Cc: git, Johannes Schindelin On Wed, Jan 20, 2010 at 01:38:41AM -0800, Junio C Hamano wrote: > This adds a few more tests that exercises @{upstream} syntax by commands > that operate differently when they are given branch name as opposed to a > refname (i.e. where "master" and "refs/heads/master" makes a difference). Overall this looks good, but there are a few minor defects. I haven't had a chance to fix them yet, but here are tests showing them. I hope to get to them pre-1.7.0, but please feel free to take a crack at them if you want. The first one is that @{usptream} silently becomes @{0}. I think we need to double-check whether approxidate found absolutely nothing, and complain if that is the case. diff --git a/t/t0101-at-syntax.sh b/t/t0101-at-syntax.sh new file mode 100755 index 0000000..da43386 --- /dev/null +++ b/t/t0101-at-syntax.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +test_description='various @{whatever} syntax tests' +. ./test-lib.sh + +test_expect_success 'setup' ' + test_commit one && + test_commit two +' + +check_at() { + echo "$2" >expect && + git log -1 --format=%s "$1" >actual && + test_cmp expect actual +} + +test_expect_success '@{0} shows current' ' + check_at @{0} two +' + +test_expect_success '@{1} shows old' ' + check_at @{1} one +' + +test_expect_success '@{now} shows current' ' + check_at @{now} two +' + +test_expect_success '@{30.years.ago} shows old' ' + check_at @{30.years.ago} one +' + +test_expect_success 'silly approxidates work' ' + check_at @{3.hot.dogs.and.30.years.ago} one +' + +test_expect_failure 'complain about total nonsense' ' + test_must_fail git log -1 --format=%s @{utter.bogosity} +' + +test_done The second one is that "log -g branch@{u}" shows the correct commits (from the upstream of "branch"), but displays the incorrect reflog information (it shows information for "branch", not for its upstream). diff --git a/t/t1507-rev-parse-upstream.sh b/t/t1507-rev-parse-upstream.sh index 95c9b09..cbe1b25 100755 --- a/t/t1507-rev-parse-upstream.sh +++ b/t/t1507-rev-parse-upstream.sh @@ -107,4 +107,18 @@ test_expect_success 'checkout other@{u}' ' test_cmp expect actual ' +cat >expect <<EOF +commit 8f489d01d0cc65c3b0f09504ec50b5ed02a70bd5 +Reflog: refs/heads/master@{0} (C O Mitter <committer@example.com>) +Reflog message: branch: Created from HEAD +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:15:13 2005 -0700 + + 3 +EOF +test_expect_failure 'log -g other@{u}' ' + git log -1 -g other@{u} >actual && + test_cmp expect actual +' + test_done ^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH 1/2] t1506: more test for @{upstream} syntax 2010-01-26 13:07 ` Jeff King @ 2010-01-26 19:58 ` Junio C Hamano 2010-01-27 10:24 ` Jeff King 2010-01-26 21:32 ` Junio C Hamano 1 sibling, 1 reply; 30+ messages in thread From: Junio C Hamano @ 2010-01-26 19:58 UTC (permalink / raw) To: Jeff King; +Cc: git, Johannes Schindelin Jeff King <peff@peff.net> writes: > The first one is that @{usptream} silently becomes @{0}. I think > we need to double-check whether approxidate found absolutely nothing, > and complain if that is the case. This is not a new problem introduced by Dscho's @{u} series; it was there even before 861f00e (fix reflog approxidate parsing bug, 2008-04-30). Nevertheless, it would be nice to fix it. -- >8 -- Subject: approxidate_careful() reports errorneous date string For a long time, the time based reflog syntax (e.g. master@{yesterday}) didn't complain when the "human readable" timestamp was misspelled, as the underlying mechanism tried to be as lenient as possible. The funny thing was that parsing of "@{now}" even relied on the fact that anything not recognized by the machinery returned the current timestamp. Introduce approxidate_careful() that takes an optional pointer to an integer, that gets assigned 1 when the input does not make sense as a timestamp. As I am too lazy to fix all the callers that use approxidate(), most of the callers do not take advantage of the error checking, but convert the code to parse reflog to use it as a demonstration. Tests are mostly from Jeff King. Signed-off-by: Junio C Hamano <gitster@pobox.com> --- cache.h | 3 ++- date.c | 43 +++++++++++++++++++++++++++++++++++-------- sha1_name.c | 5 ++++- t/t0101-at-syntax.sh | 45 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 10 deletions(-) diff --git a/cache.h b/cache.h index b3370eb..f0fea2d 100644 --- a/cache.h +++ b/cache.h @@ -762,7 +762,8 @@ const char *show_date_relative(unsigned long time, int tz, size_t timebuf_size); int parse_date(const char *date, char *buf, int bufsize); void datestamp(char *buf, int bufsize); -unsigned long approxidate(const char *); +#define approxidate(s) approxidate_careful(s, NULL) +unsigned long approxidate_careful(const char *, int *); unsigned long approxidate_relative(const char *date, const struct timeval *now); enum date_mode parse_date_format(const char *format); diff --git a/date.c b/date.c index 45f3684..002aa3c 100644 --- a/date.c +++ b/date.c @@ -696,6 +696,11 @@ static unsigned long update_tm(struct tm *tm, struct tm *now, unsigned long sec) return n; } +static void date_now(struct tm *tm, struct tm *now, int *num) +{ + update_tm(tm, now, 0); +} + static void date_yesterday(struct tm *tm, struct tm *now, int *num) { update_tm(tm, now, 24*60*60); @@ -770,6 +775,7 @@ static const struct special { { "PM", date_pm }, { "AM", date_am }, { "never", date_never }, + { "now", date_now }, { NULL } }; @@ -790,7 +796,7 @@ static const struct typelen { { NULL } }; -static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm *now, int *num) +static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm *now, int *num, int *touched) { const struct typelen *tl; const struct special *s; @@ -804,6 +810,7 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm int match = match_string(date, month_names[i]); if (match >= 3) { tm->tm_mon = i; + *touched = 1; return end; } } @@ -812,6 +819,7 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm int len = strlen(s->name); if (match_string(date, s->name) == len) { s->fn(tm, now, num); + *touched = 1; return end; } } @@ -821,11 +829,14 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm int len = strlen(number_name[i]); if (match_string(date, number_name[i]) == len) { *num = i; + *touched = 1; return end; } } - if (match_string(date, "last") == 4) + if (match_string(date, "last") == 4) { *num = 1; + *touched = 1; + } return end; } @@ -835,6 +846,7 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm if (match_string(date, tl->type) >= len-1) { update_tm(tm, now, tl->length * *num); *num = 0; + *touched = 1; return end; } tl++; @@ -852,6 +864,7 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm diff += 7*n; update_tm(tm, now, diff * 24 * 60 * 60); + *touched = 1; return end; } } @@ -866,6 +879,7 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm tm->tm_year--; } tm->tm_mon = n; + *touched = 1; return end; } @@ -873,6 +887,7 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm update_tm(tm, now, 0); /* fill in date fields if needed */ tm->tm_year -= *num; *num = 0; + *touched = 1; return end; } @@ -929,9 +944,12 @@ static void pending_number(struct tm *tm, int *num) } } -static unsigned long approxidate_str(const char *date, const struct timeval *tv) +static unsigned long approxidate_str(const char *date, + const struct timeval *tv, + int *error_ret) { int number = 0; + int touched = 0; struct tm tm, now; time_t time_sec; @@ -951,33 +969,42 @@ static unsigned long approxidate_str(const char *date, const struct timeval *tv) if (isdigit(c)) { pending_number(&tm, &number); date = approxidate_digit(date-1, &tm, &number); + touched = 1; continue; } if (isalpha(c)) - date = approxidate_alpha(date-1, &tm, &now, &number); + date = approxidate_alpha(date-1, &tm, &now, &number, &touched); } pending_number(&tm, &number); + if (!touched) + *error_ret = 1; return update_tm(&tm, &now, 0); } unsigned long approxidate_relative(const char *date, const struct timeval *tv) { char buffer[50]; + int errors = 0; if (parse_date(date, buffer, sizeof(buffer)) > 0) return strtoul(buffer, NULL, 0); - return approxidate_str(date, tv); + return approxidate_str(date, tv, &errors); } -unsigned long approxidate(const char *date) +unsigned long approxidate_careful(const char *date, int *error_ret) { struct timeval tv; char buffer[50]; + int dummy = 0; + if (!error_ret) + error_ret = &dummy; - if (parse_date(date, buffer, sizeof(buffer)) > 0) + if (parse_date(date, buffer, sizeof(buffer)) > 0) { + *error_ret = 0; return strtoul(buffer, NULL, 0); + } gettimeofday(&tv, NULL); - return approxidate_str(date, &tv); + return approxidate_str(date, &tv, error_ret); } diff --git a/sha1_name.c b/sha1_name.c index 9215ad1..ed4c028 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -413,8 +413,11 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1) } else if (0 <= nth) at_time = 0; else { + int errors = 0; char *tmp = xstrndup(str + at + 2, reflog_len); - at_time = approxidate(tmp); + at_time = approxidate_careful(tmp, &errors); + if (errors) + die("Bogus timestamp '%s'", tmp); free(tmp); } if (read_ref_at(real_ref, at_time, nth, sha1, NULL, diff --git a/t/t0101-at-syntax.sh b/t/t0101-at-syntax.sh new file mode 100755 index 0000000..ccabc37 --- /dev/null +++ b/t/t0101-at-syntax.sh @@ -0,0 +1,45 @@ +#!/bin/sh + +test_description='various @{whatever} syntax tests' +. ./test-lib.sh + +test_expect_success 'setup' ' + test_commit one && + test_commit two +' + +check_at() { + echo "$2" >expect && + git log -1 --format=%s "$1" >actual && + test_cmp expect actual +} + +test_expect_success '@{0} shows current' ' + check_at @{0} two +' + +test_expect_success '@{1} shows old' ' + check_at @{1} one +' + +test_expect_success '@{now} shows current' ' + check_at @{now} two +' + +test_expect_success '@{30.years.ago} shows old' ' + check_at @{30.years.ago} one +' + +test_expect_success 'silly approxidates work' ' + check_at @{3.hot.dogs.and.30.years.ago} one +' + +test_expect_success 'notice misspelled upstream' ' + test_must_fail git log -1 --format=%s @{usptream} +' + +test_expect_success 'complain about total nonsense' ' + test_must_fail git log -1 --format=%s @{utter.bogosity} +' + +test_done ^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH 1/2] t1506: more test for @{upstream} syntax 2010-01-26 19:58 ` Junio C Hamano @ 2010-01-27 10:24 ` Jeff King 2010-01-27 18:50 ` Junio C Hamano 0 siblings, 1 reply; 30+ messages in thread From: Jeff King @ 2010-01-27 10:24 UTC (permalink / raw) To: Junio C Hamano; +Cc: git, Johannes Schindelin On Tue, Jan 26, 2010 at 11:58:00AM -0800, Junio C Hamano wrote: > > The first one is that @{usptream} silently becomes @{0}. I think > > we need to double-check whether approxidate found absolutely nothing, > > and complain if that is the case. > > This is not a new problem introduced by Dscho's @{u} series; it was there > even before 861f00e (fix reflog approxidate parsing bug, 2008-04-30). True, though now that there is something besides an approxidate to misspell, it is slightly worse. :) > Introduce approxidate_careful() that takes an optional pointer to an > integer, that gets assigned 1 when the input does not make sense as a > timestamp. A minor nit, but wouldn't: int approxidate_careful(const char *str, unsigned long *out); returning an error code be the more usual pattern for a function with error-plus-output (your approxidate wrapper would have to be a function then, not a macro)? > As I am too lazy to fix all the callers that use approxidate(), most of > the callers do not take advantage of the error checking, but convert the > code to parse reflog to use it as a demonstration. I think that is fine, and was the approach I was also going to take. Approxidate was meant to be "try to make sense of anything". It is mainly a problem here because we are combining it with other input, and it is hard to tell a misspelling of that other input from a nonsensical approxidate. Now that the _careful infrastructure is there, we can fix other callsites if people care. > @@ -413,8 +413,11 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1) > } else if (0 <= nth) > at_time = 0; > else { > + int errors = 0; > char *tmp = xstrndup(str + at + 2, reflog_len); > - at_time = approxidate(tmp); > + at_time = approxidate_careful(tmp, &errors); > + if (errors) > + die("Bogus timestamp '%s'", tmp); > free(tmp); I was just going to "return -1" here, which yields: $ git show @{bogosity} fatal: ambiguous argument '@{bogosity}': unknown revision or path not in the working tree. Use '--' to separate paths from revisions instead of $ git show @{bogosity} fatal: Bogus timestamp 'bogosity' I can't imagine anybody being upset that they had a path '@{usptream}' in their repository which was prematurely interpreted as a bogus ref (especially since it is _always_ a ref in the current behavior), but it just seemed more consistent with the rest of get_sha1_basic, which generally does not die. On the other hand, I think the error message the user sees in your case is probably more helpful. > +test_expect_success '@{30.years.ago} shows old' ' > + check_at @{30.years.ago} one Side note: I chose this because we needed to go back from the current time beyond where test_tick would place the commit. Which means this test has a 2035 bug. :) I had originally had 100.years.ago, but we seem to have some data-type issues with our date handling. We represent seconds-since-epoch as unsigned long, which means: - even though approxidate handles it internally, we can't represent dates earlier than the epoch. If you simply store approxidate's output as a signed time_t, as test-date does, it does work back to 1901. But the reflog code treats it as unsigned, so 100.years.ago, though representable, is considered to be far in the future. - on many platforms ulong is 32 bits, meaning we have 2038 problems (though because it's unsigned, I am not sure if we actually have 2106 problems; I suspect it may be a mix because of the way different parts of the system use time_t versus ulong). Presumably time_t will move to 64 bits in the next decade or two, and hopefully ulong along with it. Now obviously neither is a pressing issue. Probably nobody is importing any pre-epoch commits, and we have a few decades to worry about future issues. But I did legitimately see the bug when trying to guess a "long time ago" value. It might be nice to use a signed time_t, and to deal with the overflow (even if it is just to barf and say "bad time" instead of silently producing wrong, future results). -Peff ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/2] t1506: more test for @{upstream} syntax 2010-01-27 10:24 ` Jeff King @ 2010-01-27 18:50 ` Junio C Hamano 2010-01-28 8:52 ` Jeff King 0 siblings, 1 reply; 30+ messages in thread From: Junio C Hamano @ 2010-01-27 18:50 UTC (permalink / raw) To: Jeff King; +Cc: git, Johannes Schindelin Jeff King <peff@peff.net> writes: > A minor nit, but wouldn't: > > int approxidate_careful(const char *str, unsigned long *out); > > returning an error code be the more usual pattern for a function with > error-plus-output (your approxidate wrapper would have to be a function then, > not a macro)? I don't have strong preference either way; the one in the patch was modelled after setup_git_directory_gently(&nongit_ok), and slightly easier to work with for existing callers that don't care enough. >> @@ -413,8 +413,11 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1) >> } else if (0 <= nth) >> at_time = 0; >> else { >> + int errors = 0; >> char *tmp = xstrndup(str + at + 2, reflog_len); >> - at_time = approxidate(tmp); >> + at_time = approxidate_careful(tmp, &errors); >> + if (errors) >> + die("Bogus timestamp '%s'", tmp); >> free(tmp); > > I was just going to "return -1" here, which yields: > > $ git show @{bogosity} > fatal: ambiguous argument '@{bogosity}': unknown revision or path not in the working tree. > Use '--' to separate paths from revisions > > instead of > > $ git show @{bogosity} > fatal: Bogus timestamp 'bogosity' Good point. Let's change it to silently return -1 and let the caller take care of it. Perhaps there are some callers that say "does this name an object? If not, let's try pathname". >> +test_expect_success '@{30.years.ago} shows old' ' >> + check_at @{30.years.ago} one > > Side note: I chose this because we needed to go back from the current > time beyond where test_tick would place the commit. Which means this > test has a 2035 bug. :) Can't we use an absolute date, given that test_tick gives fixed timestamp sequence to pretend as if we were still in 2005 when we are running these tests? sha1_name.c | 4 ++-- t/t0101-at-syntax.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sha1_name.c b/sha1_name.c index f4a74fe..04fb3b8 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -398,9 +398,9 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1) int errors = 0; char *tmp = xstrndup(str + at + 2, reflog_len); at_time = approxidate_careful(tmp, &errors); - if (errors) - die("Bogus timestamp '%s'", tmp); free(tmp); + if (errors) + return -1; } if (read_ref_at(real_ref, at_time, nth, sha1, NULL, &co_time, &co_tz, &co_cnt)) { diff --git a/t/t0101-at-syntax.sh b/t/t0101-at-syntax.sh index ccabc37..5e298c5 100755 --- a/t/t0101-at-syntax.sh +++ b/t/t0101-at-syntax.sh @@ -26,8 +26,8 @@ test_expect_success '@{now} shows current' ' check_at @{now} two ' -test_expect_success '@{30.years.ago} shows old' ' - check_at @{30.years.ago} one +test_expect_success '@{2001-09-17} (before the first commit) shows old' ' + check_at @{2001-09-17} one ' test_expect_success 'silly approxidates work' ' ^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH 1/2] t1506: more test for @{upstream} syntax 2010-01-27 18:50 ` Junio C Hamano @ 2010-01-28 8:52 ` Jeff King 0 siblings, 0 replies; 30+ messages in thread From: Jeff King @ 2010-01-28 8:52 UTC (permalink / raw) To: Junio C Hamano; +Cc: git, Johannes Schindelin On Wed, Jan 27, 2010 at 10:50:07AM -0800, Junio C Hamano wrote: > > A minor nit, but wouldn't: > > > > int approxidate_careful(const char *str, unsigned long *out); > > > > returning an error code be the more usual pattern for a function with > > error-plus-output (your approxidate wrapper would have to be a function then, > > not a macro)? > > I don't have strong preference either way; the one in the patch was > modelled after setup_git_directory_gently(&nongit_ok), and slightly easier > to work with for existing callers that don't care enough. Looks like you have already pushed out the original patch, so let's not worry about it. > >> +test_expect_success '@{30.years.ago} shows old' ' > >> + check_at @{30.years.ago} one > > > > Side note: I chose this because we needed to go back from the current > > time beyond where test_tick would place the commit. Which means this > > test has a 2035 bug. :) > > Can't we use an absolute date, given that test_tick gives fixed timestamp > sequence to pretend as if we were still in 2005 when we are running these > tests? > [...] > --- a/t/t0101-at-syntax.sh > +++ b/t/t0101-at-syntax.sh > @@ -26,8 +26,8 @@ test_expect_success '@{now} shows current' ' > check_at @{now} two > ' > > -test_expect_success '@{30.years.ago} shows old' ' > - check_at @{30.years.ago} one > +test_expect_success '@{2001-09-17} (before the first commit) shows old' ' > + check_at @{2001-09-17} one > ' > > test_expect_success 'silly approxidates work' ' Yes, I don't know why I was so concerned with using a relative approxidate when an absolute one would suffice. However, we should make a matching change in the silly approxidate entry, too. Like this: -- >8 -- Subject: [PATCH] t0101: use absolute date The original version used relative approxidates, which don't reproduce as reliably as absolute ones. Commit 6c647a fixed this for one case, but missed the "silly" case. Signed-off-by: Jeff King <peff@peff.net> --- t/t0101-at-syntax.sh | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/t/t0101-at-syntax.sh b/t/t0101-at-syntax.sh index 5e298c5..a1998b5 100755 --- a/t/t0101-at-syntax.sh +++ b/t/t0101-at-syntax.sh @@ -31,7 +31,7 @@ test_expect_success '@{2001-09-17} (before the first commit) shows old' ' ' test_expect_success 'silly approxidates work' ' - check_at @{3.hot.dogs.and.30.years.ago} one + check_at @{3.hot.dogs.on.2001-09-17} one ' test_expect_success 'notice misspelled upstream' ' ^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH 1/2] t1506: more test for @{upstream} syntax 2010-01-26 13:07 ` Jeff King 2010-01-26 19:58 ` Junio C Hamano @ 2010-01-26 21:32 ` Junio C Hamano 2010-01-27 11:40 ` Jeff King 1 sibling, 1 reply; 30+ messages in thread From: Junio C Hamano @ 2010-01-26 21:32 UTC (permalink / raw) To: Jeff King; +Cc: git, Johannes Schindelin Jeff King <peff@peff.net> writes: > The second one is that "log -g branch@{u}" shows the correct commits > (from the upstream of "branch"), but displays the incorrect reflog > information (it shows information for "branch", not for its upstream). That "walk-reflog" code is tricky. How about this? I don't know if it deals with things like "@{-1}@{u}@{now}"; the users should have every right to expect it to, but I didn't consciously try to make that work with this patch. revision.c | 18 ++++++++++++++---- t/t1507-rev-parse-upstream.sh | 29 +++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/revision.c b/revision.c index f54d43f..75071af 100644 --- a/revision.c +++ b/revision.c @@ -134,10 +134,20 @@ static void add_pending_object_with_mode(struct rev_info *revs, struct object *o { if (revs->no_walk && (obj->flags & UNINTERESTING)) revs->no_walk = 0; - if (revs->reflog_info && obj->type == OBJ_COMMIT && - add_reflog_for_walk(revs->reflog_info, - (struct commit *)obj, name)) - return; + if (revs->reflog_info && obj->type == OBJ_COMMIT) { + struct strbuf buf = STRBUF_INIT; + int len = interpret_branch_name(name, &buf); + int st; + + if (len && name[len]) + strbuf_addstr(&buf, name + len); + st = add_reflog_for_walk(revs->reflog_info, + (struct commit *)obj, + buf.buf[0] ? buf.buf: name); + strbuf_release(&buf); + if (st) + return; + } add_object_array_with_mode(obj, name, &revs->pending, mode); } diff --git a/t/t1507-rev-parse-upstream.sh b/t/t1507-rev-parse-upstream.sh index 95c9b09..8c8dfda 100755 --- a/t/t1507-rev-parse-upstream.sh +++ b/t/t1507-rev-parse-upstream.sh @@ -107,4 +107,33 @@ test_expect_success 'checkout other@{u}' ' test_cmp expect actual ' +cat >expect <<EOF +commit 8f489d01d0cc65c3b0f09504ec50b5ed02a70bd5 +Reflog: master@{0} (C O Mitter <committer@example.com>) +Reflog message: branch: Created from HEAD +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:15:13 2005 -0700 + + 3 +EOF +test_expect_success 'log -g other@{u}' ' + git log -1 -g other@{u} >actual && + test_cmp expect actual +' + +cat >expect <<EOF +commit 8f489d01d0cc65c3b0f09504ec50b5ed02a70bd5 +Reflog: master@{Thu Apr 7 15:17:13 2005 -0700} (C O Mitter <committer@example.com>) +Reflog message: branch: Created from HEAD +Author: A U Thor <author@example.com> +Date: Thu Apr 7 15:15:13 2005 -0700 + + 3 +EOF + +test_expect_success 'log -g other@{u}@{now}' ' + git log -1 -g other@{u}@{now} >actual && + test_cmp expect actual +' + test_done ^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH 1/2] t1506: more test for @{upstream} syntax 2010-01-26 21:32 ` Junio C Hamano @ 2010-01-27 11:40 ` Jeff King 2010-01-27 19:10 ` Junio C Hamano 0 siblings, 1 reply; 30+ messages in thread From: Jeff King @ 2010-01-27 11:40 UTC (permalink / raw) To: Junio C Hamano; +Cc: git, Johannes Schindelin On Tue, Jan 26, 2010 at 01:32:07PM -0800, Junio C Hamano wrote: > I don't know if it deals with things like "@{-1}@{u}@{now}"; the users > should have every right to expect it to, but I didn't consciously try to > make that work with this patch. Nice. This also fixes "git log -g @{-1}". Static uses like "git show @{u}@{1.week.ago}" and "git show @{-1}@{1.week.ago}" were already fine, so I think the bug was really confined to the reflog walker (and your fix is therefore correct). Using "git show @{-1}@{u}" is still broken, though. I tried tracing the parsing through get_sha1_basic and interpret_branch_name, but it's pretty confusing. Especially as we seem to deal with @{upstream}, @{now}, and @{-1} at different places. I think the patch below does what we want, but the whole thing feels overly complicated to me, especially with the split of parsing @{...} between get_sha1_basic and interpret_branch_name. I guess we have spots that don't take reflogs but do take branch names, but I think the code would be much simpler if the syntax were parsed in one place, and then we threw out or complained about bogus semantics (like "checkout @{now}"). --- diff --git a/sha1_name.c b/sha1_name.c index ed4c028..ef8f3fa 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -881,8 +881,28 @@ int interpret_branch_name(const char *name, struct strbuf *buf) if (!len) return len; /* syntax Ok, not enough switches */ - if (0 < len) - return len; /* consumed from the front */ + if (0 < len && len == namelen) + return len; /* consumed all */ + else if (0 < len) { + /* 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; + } + cp = strchr(name, '@'); if (!cp) return -1; ^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH 1/2] t1506: more test for @{upstream} syntax 2010-01-27 11:40 ` Jeff King @ 2010-01-27 19:10 ` Junio C Hamano 2010-01-28 9:44 ` Jeff King 0 siblings, 1 reply; 30+ messages in thread From: Junio C Hamano @ 2010-01-27 19:10 UTC (permalink / raw) To: Jeff King; +Cc: git, Johannes Schindelin Jeff King <peff@peff.net> writes: > Using "git show @{-1}@{u}" is still broken, though. > > I tried tracing the parsing through get_sha1_basic and > interpret_branch_name, but it's pretty confusing. Especially as we seem > to deal with @{upstream}, @{now}, and @{-1} at different places. > > I think the patch below does what we want, but the whole thing feels > overly complicated to me, especially with the split of parsing @{...} > between get_sha1_basic and interpret_branch_name. I guess we have spots > that don't take reflogs but do take branch names, but I think the code > would be much simpler if the syntax were parsed in one place, and then > we threw out or complained about bogus semantics (like "checkout > @{now}"). I wanted to do something like what your patch does by iterating over the input inside get_sha1_basic() while we still see @{...}, parsing pieces from the beginning, not from the end like the original "do we have the reflog indicator at the end? If so strip it and deal with what we have at the front". Your patch to i-b-n does that by recursing inside, which is a nice solution. Care to roll a patch with additional tests, to build on top of 105e473 (Fix log -g this@{upstream}, 2010-01-26)? ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/2] t1506: more test for @{upstream} syntax 2010-01-27 19:10 ` Junio C Hamano @ 2010-01-28 9:44 ` Jeff King 2010-01-28 9:50 ` [PATCH 1/3] test combinations of @{} syntax Jeff King ` (2 more replies) 0 siblings, 3 replies; 30+ messages in thread From: Jeff King @ 2010-01-28 9:44 UTC (permalink / raw) To: Junio C Hamano; +Cc: git, Johannes Schindelin On Wed, Jan 27, 2010 at 11:10:21AM -0800, Junio C Hamano wrote: > I wanted to do something like what your patch does by iterating over the > input inside get_sha1_basic() while we still see @{...}, parsing pieces > from the beginning, not from the end like the original "do we have the > reflog indicator at the end? If so strip it and deal with what we have at > the front". Your patch to i-b-n does that by recursing inside, which is a > nice solution. Yeah, I wanted to do that too, but it just ended up very messy. I suppose the i-b-n solution is reasonably elegant, and it should correctly handle non-get-sha1 instances like: git checkout @{-1}@{u} > Care to roll a patch with additional tests, to build on top of 105e473 > (Fix log -g this@{upstream}, 2010-01-26)? Yep, series to follow: [1/3]: test combinations of @{} syntax [2/3]: fix parsing of @{-1}@{u} combination [3/3]: reject @{-1} not at beginning of object name -Peff ^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 1/3] test combinations of @{} syntax 2010-01-28 9:44 ` Jeff King @ 2010-01-28 9:50 ` Jeff King 2010-01-28 9:52 ` [PATCH 2/3] fix parsing of @{-1}@{u} combination Jeff King 2010-01-28 9:56 ` [PATCH 3/3] reject @{-1} not at beginning of object name Jeff King 2 siblings, 0 replies; 30+ messages in thread From: Jeff King @ 2010-01-28 9:50 UTC (permalink / raw) To: Junio C Hamano; +Cc: git, Johannes Schindelin Now that we have several different types of @{} syntax, it is a good idea to test them together, which reveals some failures. Signed-off-by: Jeff King <peff@peff.net> --- While this is conceptually similar to the tests in t0101, it feels better to me to test features in combination only after they have been tested by themselves. Thus a new script > 1507. t/t1508-at-combinations.sh | 51 ++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 51 insertions(+), 0 deletions(-) create mode 100755 t/t1508-at-combinations.sh diff --git a/t/t1508-at-combinations.sh b/t/t1508-at-combinations.sh new file mode 100755 index 0000000..59f0463 --- /dev/null +++ b/t/t1508-at-combinations.sh @@ -0,0 +1,51 @@ +#!/bin/sh + +test_description='test various @{X} syntax combinations together' +. ./test-lib.sh + +check() { +test_expect_${3:-success} "$1 = $2" " + echo '$2' >expect && + git log -1 --format=%s '$1' >actual && + test_cmp expect actual +" +} +nonsense() { +test_expect_${2:-success} "$1 is nonsensical" " + test_must_fail git log -1 '$1' +" +} +fail() { + "$@" failure +} + +test_expect_success 'setup' ' + test_commit master-one && + test_commit master-two && + git checkout -b upstream-branch && + test_commit upstream-one && + test_commit upstream-two && + git checkout -b old-branch && + test_commit old-one && + test_commit old-two && + git checkout -b new-branch && + test_commit new-one && + test_commit new-two && + git config branch.old-branch.remote . && + git config branch.old-branch.merge refs/heads/master && + git config branch.new-branch.remote . && + git config branch.new-branch.merge refs/heads/upstream-branch +' + +check HEAD new-two +check "@{1}" new-one +check "@{-1}" old-two +check "@{-1}@{1}" old-one +check "@{u}" upstream-two +check "@{u}@{1}" upstream-one +fail check "@{-1}@{u}" master-two +fail check "@{-1}@{u}@{1}" master-one +fail nonsense "@{u}@{-1}" +nonsense "@{1}@{u}" + +test_done -- 1.7.0.rc0.41.g538720 ^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 2/3] fix parsing of @{-1}@{u} combination 2010-01-28 9:44 ` Jeff King 2010-01-28 9:50 ` [PATCH 1/3] test combinations of @{} syntax Jeff King @ 2010-01-28 9:52 ` Jeff King 2010-01-28 9:56 ` [PATCH 3/3] reject @{-1} not at beginning of object name Jeff King 2 siblings, 0 replies; 30+ messages in thread From: Jeff King @ 2010-01-28 9:52 UTC (permalink / raw) To: Junio C Hamano; +Cc: git, Johannes Schindelin Previously interpret_branch_name would see @{-1} and stop parsing, leaving the @{u} as cruft that provoked an error. Instead, we should recurse if there is more to parse. Signed-off-by: Jeff King <peff@peff.net> --- A straight repost of the previous "how about this" patch, but marking successful tests. sha1_name.c | 24 ++++++++++++++++++++++-- t/t1508-at-combinations.sh | 4 ++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/sha1_name.c b/sha1_name.c index c7f1510..00fc415 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -881,8 +881,28 @@ int interpret_branch_name(const char *name, struct strbuf *buf) if (!len) return len; /* syntax Ok, not enough switches */ - if (0 < len) - return len; /* consumed from the front */ + if (0 < len && len == namelen) + return len; /* consumed all */ + else if (0 < len) { + /* 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; + } + cp = strchr(name, '@'); if (!cp) return -1; diff --git a/t/t1508-at-combinations.sh b/t/t1508-at-combinations.sh index 59f0463..2a46af2 100755 --- a/t/t1508-at-combinations.sh +++ b/t/t1508-at-combinations.sh @@ -43,8 +43,8 @@ check "@{-1}" old-two check "@{-1}@{1}" old-one check "@{u}" upstream-two check "@{u}@{1}" upstream-one -fail check "@{-1}@{u}" master-two -fail check "@{-1}@{u}@{1}" master-one +check "@{-1}@{u}" master-two +check "@{-1}@{u}@{1}" master-one fail nonsense "@{u}@{-1}" nonsense "@{1}@{u}" -- 1.7.0.rc0.41.g538720 ^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 3/3] reject @{-1} not at beginning of object name 2010-01-28 9:44 ` Jeff King 2010-01-28 9:50 ` [PATCH 1/3] test combinations of @{} syntax Jeff King 2010-01-28 9:52 ` [PATCH 2/3] fix parsing of @{-1}@{u} combination Jeff King @ 2010-01-28 9:56 ` Jeff King 2010-01-28 20:02 ` Junio C Hamano 2 siblings, 1 reply; 30+ messages in thread From: Jeff King @ 2010-01-28 9:56 UTC (permalink / raw) To: Junio C Hamano; +Cc: Shawn O. Pearce, git, Johannes Schindelin Something like foo@{-1} is nonsensical, as the @{-N} syntax is reserved for "the Nth last branch", and is not an actual reflog selector. We should not feed such nonsense to approxidate at all. Signed-off-by: Jeff King <peff@peff.net> --- We didn't discuss this one, but I came across it while trying to be complete in testing the combinations. Right now "foo@{-1}" is interpreted as a reflog entry at approxidate "-1". Approxidate doesn't signal an error because it thinks it has found something useful. But AFAIK we have declared all @{-...} to be Nth last branch, so it is simply a semantic error. Let me know if that is not the case (that is, if it was intentional to leave foo@{-1} as the reflog at date "-1" because it has some meaning that I am missing) and we can drop this patch. sha1_name.c | 4 ++++ t/t1508-at-combinations.sh | 2 +- 2 files changed, 5 insertions(+), 1 deletions(-) diff --git a/sha1_name.c b/sha1_name.c index 00fc415..7729925 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -399,6 +399,10 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1) unsigned long co_time; 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? */ for (i = nth = 0; 0 <= nth && i < reflog_len; i++) { char ch = str[at+2+i]; diff --git a/t/t1508-at-combinations.sh b/t/t1508-at-combinations.sh index 2a46af2..d5d6244 100755 --- a/t/t1508-at-combinations.sh +++ b/t/t1508-at-combinations.sh @@ -45,7 +45,7 @@ check "@{u}" upstream-two check "@{u}@{1}" upstream-one check "@{-1}@{u}" master-two check "@{-1}@{u}@{1}" master-one -fail nonsense "@{u}@{-1}" +nonsense "@{u}@{-1}" nonsense "@{1}@{u}" test_done -- 1.7.0.rc0.41.g538720 ^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH 3/3] reject @{-1} not at beginning of object name 2010-01-28 9:56 ` [PATCH 3/3] reject @{-1} not at beginning of object name Jeff King @ 2010-01-28 20:02 ` Junio C Hamano 2010-01-29 11:22 ` Jeff King 0 siblings, 1 reply; 30+ messages in thread From: Junio C Hamano @ 2010-01-28 20:02 UTC (permalink / raw) To: Jeff King; +Cc: Shawn O. Pearce, git, Johannes Schindelin Jeff King <peff@peff.net> writes: > Something like foo@{-1} is nonsensical, as the @{-N} syntax > is reserved for "the Nth last branch", and is not an actual > reflog selector. We should not feed such nonsense to > approxidate at all. > > Signed-off-by: Jeff King <peff@peff.net> > --- > We didn't discuss this one, but I came across it while trying to be > complete in testing the combinations. Right now "foo@{-1}" is > interpreted as a reflog entry at approxidate "-1". Approxidate doesn't > signal an error because it thinks it has found something useful. But > AFAIK we have declared all @{-...} to be Nth last branch, so it is > simply a semantic error. > > Let me know if that is not the case (that is, if it was intentional to > leave foo@{-1} as the reflog at date "-1" because it has some meaning > that I am missing) and we can drop this patch. I think the patch is fine as is. We might want to use @{-some string that has non digit} for other purposes and it may be a safer change to tweak the "do we only have digits" check in the post-context to detect and reject only @{-<all digits>}. But what I am puzzled by the code structure of get_sha1_basic(), which looks like this: get_sha1_basic() { - do we have @{...} at end? If so, and if it is not a magic like @{u}, set "len" (points at the end of stuff that should name a ref) and "reflog_len" (the length of the reflog time/num specifier that is applied to that ref). - did we find @{...} in the above check, and is it at the beginning? Then it is not a reflog syntax, but is a N-th branch switch. Substitute that @{...} with the real refname and retry. If it is not @{-N}, then that @{...} reflog derefence should apply to the current branch, so set it to real_ref and go to "reflog" part. - if we have @{...} at the end, get the canonical name of the ref the reflog notation is applied to. - otherwise, get the canonical name of the ref; in this case, there is no @{...} at the end, si this is what is eventually returned. - "reflog" part: by now, real_ref holds the ref @{...} is being applied to. Read from its reflog. } And the place that parses @{-1} and @{u} are different, even though both dwim_log() called by the third one and dwim_ref() called by the fourth one call substitute_branch_name() and they are perfectly capable of resolving @{-1} and @{u} (and even nested stuff like @{-1}@{u}@{u} with your patch). But somehow we kept the special case code to parse @{-1} in the second one. Side note. I am wondering if dwim_log()'s current implementation is even correct in the first place. When you have two "ambiguous" refs, it appears to me that you will get a warning from dwim_ref(), but if only one of them has a reflog associated with it, dwim_log() won't complain. Why isn't the function be (1) dwim_ref() to find the ref from abbreviated refname given in str; and then (2) check if the log exists for that ref? It might be cleaner if the logic went like this instead: - find the last @{...} in the string that is not what i-b-n should resolve (i.e. @{-1} and @{u}); that is @{time/num} reflog reference. You can have at most one reflog reference and it always has to come at the end. - feed the remainder to (an updated) i-b-n that knows how to grok: - @{-N} is nth-priour checkout; it has to come at the beginning and you can have at most one. If you find it, substitute it with the real branch name and continue. (e.g. @{-1}@{u} becomes master@{u}) - does it begin with @{...}? If not, the part before @{...} is the name of the ref (e.g. "next" in "next@{u}@{u}") the later magic sequence (e.g. "@{u}@{u}") is applied to; otherwise apply the magic to what HEAD points at (e.g. "@{u}" applies @{u} to the current branch). Remember that ref and strip it away from the input. - while we see sequence of @{...}, apply the magic to the ref repeatedly (e.g. "next@{u}@{u}" has remembered "refs/heads/next" in the previous step, and @{u} is applied to produce "master" if next follows master, and then applying @{u} to that result will tell us that it follows "refs/remotes/origin/master"). - now we have what ref the caller was talking about with the beginning part of the input (i.e. without "@{time/num}" at the end). If we had @{time/num} in the original input, open the reflog and find an appropriate entry in it. Otherwise what we received from (the updated) i-b-n is what we found. Find out what object the ref points at. But that is a kind of code churn that may not be worth doing. I dunno. ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 3/3] reject @{-1} not at beginning of object name 2010-01-28 20:02 ` Junio C Hamano @ 2010-01-29 11:22 ` Jeff King 0 siblings, 0 replies; 30+ messages in thread From: Jeff King @ 2010-01-29 11:22 UTC (permalink / raw) To: Junio C Hamano; +Cc: Shawn O. Pearce, git, Johannes Schindelin On Thu, Jan 28, 2010 at 12:02:53PM -0800, Junio C Hamano wrote: > We might want to use @{-some string that has non digit} for other purposes > and it may be a safer change to tweak the "do we only have digits" check > in the post-context to detect and reject only @{-<all digits>}. I considered that, but I didn't think it was really worth it. If we later want to make @{-foobar} meaningful, we can loosen the safety check then. > But what I am puzzled by the code structure of get_sha1_basic(), which > looks like this: You are not the only one who is puzzled. :) But yes, your analysis of what is there now looks right to me. > And the place that parses @{-1} and @{u} are different, even though both > dwim_log() called by the third one and dwim_ref() called by the fourth one > call substitute_branch_name() and they are perfectly capable of resolving > @{-1} and @{u} (and even nested stuff like @{-1}@{u}@{u} with your patch). Ooh, gross. I didn't try @{u}@{u} in my tests, but it should work. > Side note. I am wondering if dwim_log()'s current implementation is > even correct in the first place. When you have two "ambiguous" refs, > it appears to me that you will get a warning from dwim_ref(), but if > only one of them has a reflog associated with it, dwim_log() won't > complain. Why isn't the function be (1) dwim_ref() to find the ref > from abbreviated refname given in str; and then (2) check if the log > exists for that ref? I guess the original rationale was that you might have reflog'd one, so by asking for "foo@{yesterday}" you are disambiguating as "the one with a reflog". But that seems kind of useless to me since: 1. It is somewhat error-prone, as it assumes that from the user's perspective, the fact that one ref has a log and the other does not is somehow a meaningful disambiguation. Which implies that users carefully figure out which refs have reflogs and which do not, and I don't think that is true. 2. For quite a while, we have had logallrefupdates on by default (and I don't remember the exact semantics before that, but wasn't it enough to simply create a "logs" directory, which meant that you either logged everything or nothing?). So I don't even know how you would get into a situation where one ref has a log and the other does not. In other words, I totally agree with your statement, and we could probably just drop the dwim_log code. > It might be cleaner if the logic went like this instead: Your logic makes sense to me. I think we could also simply do a left-to-right parse, eating refs, @{-N}, and @{u} as we go and converting them into a "real ref". If we get to something else, we stop. If we have a @{} left, it's a reflog. Otherwise, it's bogus (I think ^ suffixes and such have already been stripped off at this point). Interpret_branch_name already does most of the "eating..." part above (and it needs to remain separate from get_sha1_basic, as things like "checkout" need to use it directly). But I didn't really look too hard at it, as: > But that is a kind of code churn that may not be worth doing. I dunno. Yeah, the code was sufficiently nasty and sufficiently core that I didn't really want to risk breaking it for the sake of cleanup (especially not during the -rc cycle). -Peff ^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 2/2] Teach @{upstream} syntax to strbuf_branchanme() 2010-01-20 9:38 ` [PATCH 0/2] @{u} updates Junio C Hamano 2010-01-20 9:38 ` [PATCH 1/2] t1506: more test for @{upstream} syntax Junio C Hamano @ 2010-01-20 9:38 ` Junio C Hamano 2010-01-20 13:08 ` [PATCH 0/2] @{u} updates Johannes Schindelin 2 siblings, 0 replies; 30+ messages in thread From: Junio C Hamano @ 2010-01-20 9:38 UTC (permalink / raw) To: git; +Cc: Jeff King, Johannes Schindelin This teaches @{upstream} syntax to interpret_branch_name(), instead of dwim_ref() machinery. There are places in git UI that behaves differently when you give a local branch name and when you give an extended SHA-1 expression that evaluates to the commit object name at the tip of the branch. The intent is that the special syntax such as @{-1} can stand in as if the user spelled the name of the branch in such places. The name of the branch "frotz" to switch to ("git checkout frotz"), and the name of the branch "nitfol" to fork a new branch "frotz" from ("git checkout -b frotz nitfol"), are examples of such places. These places take only the name of the branch (e.g. "frotz"), and they are supposed to act differently to an equivalent refname (e.g. "refs/heads/frotz"), so hooking the @{upstream} and @{-N} syntax to dwim_ref() is insufficient when we want to deal with cases a local branch is forked from another local branch and use "forked@{upstream}" to name the forkee branch. The "upstream" syntax "forked@{u}" is to specify the ref that "forked" is configured to merge with, and most often the forkee is a remote tracking branch, not a local branch. We cannot simply return a local branch name, but that does not necessarily mean we have to returns the full refname (e.g. refs/remotes/origin/frotz, when returning origin/frotz is enough). This update calls shorten_unambiguous_ref() to do so. Signed-off-by: Junio C Hamano <gitster@pobox.com> --- sha1_name.c | 116 ++++++++++++++++++++++++++--------------- t/t1506-rev-parse-upstream.sh | 6 +- 2 files changed, 77 insertions(+), 45 deletions(-) diff --git a/sha1_name.c b/sha1_name.c index fb4e214..2376c6d 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -239,24 +239,10 @@ static int ambiguous_path(const char *path, int len) return slash; } -static inline int tracked_suffix(const char *string, int len) -{ - const char *suffix[] = { "@{upstream}", "@{u}" }; - 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>} or - * of the form <branch>@{upstream}. + * later free()ing) if the string passed in is a magic short-hand form + * to name a branch. */ static char *substitute_branch_name(const char **string, int *len) { @@ -270,21 +256,6 @@ 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); - - if (!tracking) - die ("No tracking branch found for '%s'", ref); - free(ref); - if (tracking->merge && tracking->merge[0]->dst) { - *string = xstrdup(tracking->merge[0]->dst); - *len = strlen(*string); - return (char *)*string; - } - } - return NULL; } @@ -354,6 +325,20 @@ int dwim_log(const char *str, int len, unsigned char *sha1, char **log) return logs_found; } +static inline int upstream_mark(const char *string, int len) +{ + const char *suffix[] = { "@{upstream}", "@{u}" }; + int i; + + for (i = 0; i < ARRAY_SIZE(suffix); i++) { + int suffix_len = strlen(suffix[i]); + if (suffix_len <= len + && !memcmp(string, suffix[i], suffix_len)) + return suffix_len; + } + return 0; +} + static int get_sha1_1(const char *name, int len, unsigned char *sha1); static int get_sha1_basic(const char *str, int len, unsigned char *sha1) @@ -371,7 +356,7 @@ 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] == '{') { - if (!tracked_suffix(str + at, len - at)) { + if (!upstream_mark(str + at, len - at)) { reflog_len = (len-1) - (at+2); len = at; } @@ -773,17 +758,10 @@ 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 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. + * Parse @{-N} syntax, return the number of characters parsed + * if successful; otherwise signal an error with negative value. */ -int interpret_branch_name(const char *name, struct strbuf *buf) +static int interpret_nth_prior_checkout(const char *name, struct strbuf *buf) { long nth; int i, retval; @@ -828,6 +806,60 @@ release_return: } /* + * 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 + * of the branch from the command line. + * + * - "@{-N}" finds the name of the Nth previous branch we were on, and + * places the name of the branch in the given buf and returns the + * number of characters parsed if successful. + * + * - "<branch>@{upstream}" finds the name of the other ref that + * <branch> is configured to merge with (missing <branch> defaults + * to the current branch), and places the name of the branch in the + * given 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_branch_name(const char *name, struct strbuf *buf) +{ + char *cp; + struct branch *upstream; + int namelen = strlen(name); + int len = interpret_nth_prior_checkout(name, buf); + int tmp_len; + + if (!len) + return len; /* syntax Ok, not enough switches */ + if (0 < len) + return len; /* consumed from the front */ + cp = strchr(name, '@'); + if (!cp) + return -1; + 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); + if (!upstream + || !upstream->merge + || !upstream->merge[0]->dst) + return error("No upstream branch found for '%s'", cp); + free(cp); + cp = shorten_unambiguous_ref(upstream->merge[0]->dst, 0); + strbuf_reset(buf); + strbuf_addstr(buf, cp); + free(cp); + return len; +} + +/* * This is like "get_sha1_basic()", except it allows "sha1 expressions", * notably "xyz^" for "parent of xyz" */ diff --git a/t/t1506-rev-parse-upstream.sh b/t/t1506-rev-parse-upstream.sh index a2c7f92..95c9b09 100755 --- a/t/t1506-rev-parse-upstream.sh +++ b/t/t1506-rev-parse-upstream.sh @@ -76,7 +76,7 @@ test_expect_success 'checkout -b new my-side@{u} forks from the same' ' ) ' -test_expect_failure 'merge my-side@{u} records the correct name' ' +test_expect_success 'merge my-side@{u} records the correct name' ' ( sq="'\''" && cd clone || exit @@ -90,7 +90,7 @@ test_expect_failure 'merge my-side@{u} records the correct name' ' ) ' -test_expect_failure 'branch -d other@{u}' ' +test_expect_success 'branch -d other@{u}' ' git checkout -t -b other master && git branch -d @{u} && git for-each-ref refs/heads/master >actual && @@ -98,7 +98,7 @@ test_expect_failure 'branch -d other@{u}' ' test_cmp expect actual ' -test_expect_failure 'checkout other@{u}' ' +test_expect_success 'checkout other@{u}' ' git branch -f master HEAD && git checkout -t -b another master && git checkout @{u} && -- 1.6.6.513.g63f4c ^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH 0/2] @{u} updates 2010-01-20 9:38 ` [PATCH 0/2] @{u} updates Junio C Hamano 2010-01-20 9:38 ` [PATCH 1/2] t1506: more test for @{upstream} syntax Junio C Hamano 2010-01-20 9:38 ` [PATCH 2/2] Teach @{upstream} syntax to strbuf_branchanme() Junio C Hamano @ 2010-01-20 13:08 ` Johannes Schindelin 2 siblings, 0 replies; 30+ messages in thread From: Johannes Schindelin @ 2010-01-20 13:08 UTC (permalink / raw) To: Junio C Hamano; +Cc: git, Jeff King Hi, On Wed, 20 Jan 2010, Junio C Hamano wrote: > Earlier I wondered if the approach Dscho's patch takes to teach the new > @{upstream} syntax to substitute_branch_name() (hence dwim_ref()) without > teaching it to interpret_branch_name() (hence strbuf_branchname()) was a > bad idea. I thought about this a bit more; there are some downsides for > not doing so. > > The first patch adds a handful of tests that show why strbuf_branchname() > callers may also want to learn about the new syntax. The second patch > moves the logic to interpret_branch_name() to make them happier. Looks good to me. Ciao, Dscho ^ permalink raw reply [flat|nested] 30+ messages in thread
end of thread, other threads:[~2010-01-29 11:22 UTC | newest] Thread overview: 30+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2010-01-11 18:49 default behaviour for `gitmerge` (no arguments) Gareth Adams 2010-01-11 19:43 ` Junio C Hamano 2010-01-12 16:23 ` Jeff King 2010-01-12 18:11 ` Junio C Hamano 2010-01-12 18:25 ` Jeff King 2010-01-13 6:57 ` Junio C Hamano 2010-01-13 9:26 ` Johannes Schindelin 2010-01-13 9:47 ` Junio C Hamano 2010-01-13 11:04 ` Johannes Schindelin 2010-01-13 19:48 ` Junio C Hamano 2010-01-13 22:49 ` Johannes Schindelin 2010-01-13 23:13 ` Junio C Hamano 2010-01-20 9:38 ` [PATCH 0/2] @{u} updates Junio C Hamano 2010-01-20 9:38 ` [PATCH 1/2] t1506: more test for @{upstream} syntax Junio C Hamano 2010-01-26 13:07 ` Jeff King 2010-01-26 19:58 ` Junio C Hamano 2010-01-27 10:24 ` Jeff King 2010-01-27 18:50 ` Junio C Hamano 2010-01-28 8:52 ` Jeff King 2010-01-26 21:32 ` Junio C Hamano 2010-01-27 11:40 ` Jeff King 2010-01-27 19:10 ` Junio C Hamano 2010-01-28 9:44 ` Jeff King 2010-01-28 9:50 ` [PATCH 1/3] test combinations of @{} syntax Jeff King 2010-01-28 9:52 ` [PATCH 2/3] fix parsing of @{-1}@{u} combination Jeff King 2010-01-28 9:56 ` [PATCH 3/3] reject @{-1} not at beginning of object name Jeff King 2010-01-28 20:02 ` Junio C Hamano 2010-01-29 11:22 ` Jeff King 2010-01-20 9:38 ` [PATCH 2/2] Teach @{upstream} syntax to strbuf_branchanme() Junio C Hamano 2010-01-20 13:08 ` [PATCH 0/2] @{u} updates Johannes Schindelin
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).