* Re: [RFC PATCH 0/5] Localise error headers
From: Duy Nguyen @ 2017-01-07 9:34 UTC (permalink / raw)
To: Stefan Beller; +Cc: Michael J Gruber, git@vger.kernel.org
In-Reply-To: <CACsJy8B0UT4_CF=qu081ep6nzdBXxnnNbma-wCYeajAuXaKg5w@mail.gmail.com>
On Wed, Jan 4, 2017 at 8:25 PM, Duy Nguyen <pclouds@gmail.com> wrote:
> On Wed, Jan 4, 2017 at 2:45 AM, Stefan Beller <sbeller@google.com> wrote:
>>> In this implementation, the gettext call for the header and the body are done
>>> in different places (error function vs. caller) but this call pattern seems to
>>> be the easiest variant for the caller, because the message body has to be marked
>>> for localisation in any case, and N_() requires more letters than _(), an extra
>>> argument to die() etc. even more than the extra "_" in the function name.
>>
>> I see. We have to markup the strings to be translatable such that the .po files
>> are complete. It would be really handy if there was a way to say "anything that
>> is fed to this function (die_) needs to be marked for translation.
>>
>> Looking through
>> https://www.gnu.org/software/gettext/manual/html_node/xgettext-Invocation.html
>> such a thing doesn't seem to exist.
>
> I think --keyword is exactly for that purpose: marking more text for
> translations besides standard markers like _() or N_(). Yes we need to
> call gettext() explicitly in die_() later on. We already do that for
> parse-options. We just need to N_() the strings, without actually
> spelling it out.
>
>>
>> So in that case die_(_(...)) seems to be the easiest way forward.
>
> I still prefer changing the die_routine though since die() in many
> cases could be used in both plumbing and porcelain contexts. And we
> have tried to keep plumbing output (and behavior) as stable as
> possible. The approach has some similarity to unpack_trees() which
> shares the same porcelain/plumbing problem.
On the other hand, making die(), not die_(), translatable means the
translators will have to translate them _all_ even if only some will
end up being displayed. That's 2000+ strings according to git-grep.
And some of them, like die("BUG:..") should definitely not be
translated. So +1 to die_(), unless we decide all strings are safe to
translate.
--
Duy
^ permalink raw reply
* Re: [PATCH v5 00/16] pathspec cleanup
From: Duy Nguyen @ 2017-01-07 9:29 UTC (permalink / raw)
To: Brandon Williams; +Cc: Git Mailing List, Stefan Beller, Junio C Hamano
In-Reply-To: <20170104180411.150000-1-bmwill@google.com>
On Thu, Jan 5, 2017 at 1:03 AM, Brandon Williams <bmwill@google.com> wrote:
> Changes in v5:
> * Move GUARD_PATHSPEC to prevent checking if pathspec is null twice.
> * Mark a string containing 'mnemonic' for translation.
Argh.. I've run out of things to complain about! Ack!
--
Duy
^ permalink raw reply
* Re: [PATCH 3/3] execv_dashed_external: wait for child on signal death
From: Duy Nguyen @ 2017-01-07 9:07 UTC (permalink / raw)
To: Jeff King; +Cc: Johannes Sixt, Trygve Aaberge, Git Mailing List
In-Reply-To: <20170107012223.c27toqr6ck44kfpj@sigill.intra.peff.net>
On Sat, Jan 7, 2017 at 8:22 AM, Jeff King <peff@peff.net> wrote:
> When you hit ^C to interrupt a git command going to a pager,
> this usually leaves the pager running. But when a dashed
> external is in use, the pager ends up in a funny state and
> quits (but only after eating one more character from the
> terminal!). This fixes it.
>
> Explaining the reason will require a little background.
>
> ...
I see I have exposed a bug and I'm glad you are around to fix it. Even
reading your explanation is scary enough, let alone finding it.
Thanks!
--
Duy
^ permalink raw reply
* [BUG] push sometimes omits status table when remote dies
From: Jeff King @ 2017-01-07 8:48 UTC (permalink / raw)
To: git
If I run t5504 under heavy load, it sometimes fails tests 8 and 9, which
make a broken push to the remote. The failure looks like this:
expecting success:
rm -rf dst &&
git init dst &&
(
cd dst &&
git config transfer.fsckobjects true
) &&
test_must_fail git push --porcelain dst master:refs/heads/test >act &&
test_cmp exp act
Initialized empty Git repository in /var/ram/git-stress/root-13/trash directory.t5504-fetch-receive-strict/dst/.git/
remote: fatal: object of unexpected type
error: failed to push some refs to 'dst'
--- exp 2017-01-07 08:44:24.465771756 +0000
+++ act 2017-01-07 08:44:24.493771755 +0000
@@ -1,2 +0,0 @@
-To dst
-! refs/heads/master:refs/heads/test [remote rejected] (unpacker error)
not ok 9 - push with transfer.fsckobjects
So it looks like we correctly fail the push, but the expected porcelain
output is missing. I'm _guessing_ what happens is that the local
git-push sees SIGPIPE writing to the remote side, and dies before it
gets a chance to write the message.
I'm not sure if this is something we should be fixing, or if the test is
simply a bit flaky (and we should work around it).
-Peff
^ permalink raw reply
* [PATCH] rebase--interactive: count squash commits above 10 correctly
From: Jeff King @ 2017-01-07 8:23 UTC (permalink / raw)
To: Brandon Tolsch; +Cc: Johannes Schindelin, Vasco Almeida, git
In-Reply-To: <CAMWRQeRaQQQcJ-R8eHc7f0KqZF2eEkYJOyTb9n7ds78pTqV-AA@mail.gmail.com>
On Fri, Jan 06, 2017 at 01:04:05AM -0800, Brandon Tolsch wrote:
> git --version: 2.11.0
>
> When using git rebase -i to squash a series of commits that includes
> more than 10 commits, the generated commit message you are given to
> edit counts the old messages incorrectly. It will say the total
> number of commits is (actual % 10) (if they were 0-based) and it will
> also count the commits as (actual % 10).
Looks like a regression in v2.10. Here's the fix.
-- >8 --
Subject: rebase--interactive: count squash commits above 10 correctly
We generate the squash commit message incrementally running
a sed script once for each commit. It parses "This is
a combination of <N> commits" from the first line of the
existing message, adds one to <N>, and uses the result as
the number of our current message.
Since f2d17068fd (i18n: rebase-interactive: mark comments of
squash for translation, 2016-06-17), the first line may be
localized, and sed uses a pretty liberal regex, looking for:
/^#.*([0-9][0-9]*)/
The "[0-9][0-9]*" tries to match double digits, but it
doesn't quite work. The first ".*" is greedy, so if you
have:
This is a combination of 10 commits.
it will eat up "This is a combination of 1", leaving "0" to
match the first "[0-9]" digit, and then skipping the
optional match of "[0-9]*".
As a result, the count resets every 10 commits, and a
15-commit squash would end up as:
# This is a combination of 5 commits.
# This is the 1st commit message:
...
# This is the commit message #2:
... and so on ..
# This is the commit message #10:
...
# This is the commit message #1:
...
# This is the commit message #2:
... etc, up to 5 ...
We can fix this by making the ".*" less greedy. Instead of
depending on ".*?" working portably, we can just limit the
match to non-digit characters, which accomplishes the same
thing.
Reported-by: Brandon Tolsch <btolsch@gmail.com>
Signed-off-by: Jeff King <peff@peff.net>
---
I didn't include a test here, mostly because this bug is so weirdly
specific that it seems unlikely to happen again. Especially in light of
this code going away in favor of the C rebase helper, which Dscho
already confirmed is not buggy (and I did not look at the code, but it
cannot possibly do anything as gross as these repeated sed invocations).
It also is a little tricky to automatically extract the comments (you
have to override GIT_EDITOR, but we also invoke GIT_EDITOR for the insn
sheet).
I was able to replicate and confirm the fix manually with:
git commit -q --allow-empty -m base
git commit -q --allow-empty -m squash
git tag base
for i in $(seq 15); do
echo $i >$i
git add $i
git commit -qm "squash! squash"
done
git rebase --autosquash -i base
I'd also suggest that "the commit message #4" is grammatically
questionable. Probably "This is commit message #4" would be fine.
git-rebase--interactive.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index b0a6f2b7ba..4734094a3f 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -425,7 +425,7 @@ update_squash_messages () {
if test -f "$squash_msg"; then
mv "$squash_msg" "$squash_msg".bak || exit
count=$(($(sed -n \
- -e "1s/^$comment_char.*\([0-9][0-9]*\).*/\1/p" \
+ -e "1s/^$comment_char[^0-9]*\([0-9][0-9]*\).*/\1/p" \
-e "q" < "$squash_msg".bak)+1))
{
printf '%s\n' "$comment_char $(eval_ngettext \
--
2.11.0.527.gfef230ca76
^ permalink raw reply related
* Re: [PATCH 3/3] execv_dashed_external: wait for child on signal death
From: Jeff King @ 2017-01-07 7:34 UTC (permalink / raw)
To: Johannes Sixt; +Cc: Trygve Aaberge, Nguyễn Thái Ngọc Duy, git
In-Reply-To: <650a25f6-5f22-8efb-3048-6afadbaa7092@kdbg.org>
On Sat, Jan 07, 2017 at 08:28:22AM +0100, Johannes Sixt wrote:
> > But when you have a dashed external (or an alias pointing to
> > a builtin, which will re-exec git for the builtin), there's
> > an extra process in the mix. For instance, running:
> >
> > git -c alias.l=log log
>
> This should be
>
> git -c alias.l=log l
Yeah, it should be.
> For the complete series:
>
> Acked-by: Johannes Sixt <j6t@kdbg.org>
Thanks.
> What should we add to Documentation/technical/api-run-command.txt about the
> new flag? "Do not use?" "Understand the commit message of <this commit>
> before setting the flag to true?"
I think it can be explained pretty easily as "after killing all children
marked for clean_on_exit, do a blocking waitpid() on any child that is
also marked wait_after_clean". But I notice we do not actually document
clean_on_exit, either, nor most of the options in "struct
child_process".
IMHO it would be an improvement to merge the contents of the
technical/api-run-command.txt documentation into the header file, and
document each option with a comment above its definition. That makes it
a lot easier to have the will to document any newly-added options,
because if you don't they look bad next to the others. :)
Mechanics aside, I am not sure if we need a "do not use" or "here are
the caveats". I think if we explain what it does, we can rely on list
discussion and review to catch any obviously-stupid uses (both of it and
of clean_on_exit).
-Peff
^ permalink raw reply
* Re: [PATCH 3/3] execv_dashed_external: wait for child on signal death
From: Johannes Sixt @ 2017-01-07 7:28 UTC (permalink / raw)
To: Jeff King; +Cc: Trygve Aaberge, Nguyễn Thái Ngọc Duy, git
In-Reply-To: <20170107012223.c27toqr6ck44kfpj@sigill.intra.peff.net>
Am 07.01.2017 um 02:22 schrieb Jeff King:
> When you hit ^C to interrupt a git command going to a pager,
> this usually leaves the pager running. But when a dashed
> external is in use, the pager ends up in a funny state and
> quits (but only after eating one more character from the
> terminal!). This fixes it.
>
> Explaining the reason will require a little background.
>
> When git runs a pager, it's important for the git process to
> hang around and wait for the pager to finish, even though it
> has no more data to feed it. This is because git spawns the
> pager as a child, and thus the git process is the session
> leader on the terminal. After it dies, the pager will finish
> its current read from the terminal (eating the one
> character), and then get EIO trying to read again.
>
> When you hit ^C, that sends SIGINT to git and to the pager,
> and it's a similar situation. The pager ignores it, but the
> git process needs to hang around until the pager is done. We
> addressed that long ago in a3da882120 (pager: do
> wait_for_pager on signal death, 2009-01-22).
>
> But when you have a dashed external (or an alias pointing to
> a builtin, which will re-exec git for the builtin), there's
> an extra process in the mix. For instance, running:
>
> git -c alias.l=log log
This should be
git -c alias.l=log l
>
> will end up with a process tree like:
>
> git (parent)
> \
> git-log (child)
> \
> less (pager)
>
> If you hit ^C, SIGINT goes to all of them. The pager ignores
> it, and the child git process will end up in wait_for_pager().
> But the parent git process will die, and the usual EIO
> trouble happens.
>
> So we really want the parent git process to wait_for_pager(),
> but of course it doesn't know anything about the pager at
> all, since it was started by the child. However, we can
> have it wait on the git-log child, which in turn is waiting
> on the pager. And that's what this patch does.
>
> There are a few design decisions here worth explaining:
>
> 1. The new feature is attached to run-command's
> clean_on_exit feature. Partly this is convenience,
> since that feature already has a signal handler that
> deals with child cleanup.
>
> But it's also a meaningful connection. The main reason
> that dashed externals use clean_on_exit is to bind the
> two processes together. If somebody kills the parent
> with a signal, we propagate that to the child (in this
> instance with SIGINT, we do propagate but it doesn't
> matter because the original signal went to the whole
> process group). Likewise, we do not want the parent
> to go away until the child has done so.
>
> In a traditional Unix world, we'd probably accomplish
> this binding by just having the parent execve() the
> child directly. But since that doesn't work on Windows,
> everything goes through run_command's more spawn-like
> interface.
>
> 2. We do _not_ automatically waitpid() on any
> clean_on_exit children. For dashed externals this makes
> sense; we know that the parent is doing nothing but
> waiting for the child to exit anyway. But with other
> children, it's possible that the child, after getting
> the signal, could be waiting on the parent to do
> something (like closing a descriptor). If we were to
> wait on such a child, we'd end up in a deadlock. So
> this errs on the side of caution, and lets callers
> enable the feature explicitly.
>
> 3. When we send children the cleanup signal, we send all
> the signals first, before waiting on any children. This
> is to avoid the case where one child might be waiting
> on another one to exit, causing a deadlock. We inform
> all of them that it's time to die before reaping any.
>
> In practice, there is only ever one dashed external run
> from a given process, so this doesn't matter much now.
> But it future-proofs us if other callers start using
> the wait_after_clean mechanism.
>
> There's no automated test here, because it would end up racy
> and unportable. But it's easy to reproduce the situation by
> running the log command given above and hitting ^C.
>
> Signed-off-by: Jeff King <peff@peff.net>
> ---
> git.c | 1 +
> run-command.c | 19 +++++++++++++++++++
> run-command.h | 1 +
> 3 files changed, 21 insertions(+)
>
> diff --git a/git.c b/git.c
> index bc2f2a7ec9..c8fe6637df 100644
> --- a/git.c
> +++ b/git.c
> @@ -588,6 +588,7 @@ static void execv_dashed_external(const char **argv)
> argv_array_pushf(&cmd.args, "git-%s", argv[0]);
> argv_array_pushv(&cmd.args, argv + 1);
> cmd.clean_on_exit = 1;
> + cmd.wait_after_clean = 1;
> cmd.silent_exec_failure = 1;
>
> trace_argv_printf(cmd.args.argv, "trace: exec:");
> diff --git a/run-command.c b/run-command.c
> index ca905a9e80..73bfba7ef9 100644
> --- a/run-command.c
> +++ b/run-command.c
> @@ -29,6 +29,8 @@ static int installed_child_cleanup_handler;
>
> static void cleanup_children(int sig, int in_signal)
> {
> + struct child_to_clean *children_to_wait_for = NULL;
> +
> while (children_to_clean) {
> struct child_to_clean *p = children_to_clean;
> children_to_clean = p->next;
> @@ -45,6 +47,23 @@ static void cleanup_children(int sig, int in_signal)
> }
>
> kill(p->pid, sig);
> +
> + if (p->process->wait_after_clean) {
> + p->next = children_to_wait_for;
> + children_to_wait_for = p;
> + } else {
> + if (!in_signal)
> + free(p);
> + }
> + }
> +
> + while (children_to_wait_for) {
> + struct child_to_clean *p = children_to_wait_for;
> + children_to_wait_for = p->next;
> +
> + while (waitpid(p->pid, NULL, 0) < 0 && errno == EINTR)
> + ; /* spin waiting for process exit or error */
> +
> if (!in_signal)
> free(p);
> }
> diff --git a/run-command.h b/run-command.h
> index dd1c78c28d..4fa8f65adb 100644
> --- a/run-command.h
> +++ b/run-command.h
> @@ -43,6 +43,7 @@ struct child_process {
> unsigned stdout_to_stderr:1;
> unsigned use_shell:1;
> unsigned clean_on_exit:1;
> + unsigned wait_after_clean:1;
> void (*clean_on_exit_handler)(struct child_process *process);
> void *clean_on_exit_handler_cbdata;
> };
>
Very nice write-up and an "obviously correct patch" (FLW).
For the complete series:
Acked-by: Johannes Sixt <j6t@kdbg.org>
What should we add to Documentation/technical/api-run-command.txt about
the new flag? "Do not use?" "Understand the commit message of <this
commit> before setting the flag to true?"
-- Hannes
^ permalink raw reply
* Re: [ANNOUNCE] git-test: run automated tests against a range of Git commits
From: Jeff King @ 2017-01-07 7:18 UTC (permalink / raw)
To: Michael Haggerty; +Cc: git discussion list
In-Reply-To: <1341c01a-aca7-699c-c53a-28d048614bfe@alum.mit.edu>
On Fri, Jan 06, 2017 at 04:52:16PM +0100, Michael Haggerty wrote:
> I just released `git test`, a script for running automated
> tests across a range of Git commits and keeping track of the results in
> git notes:
>
> https://github.com/mhagger/git-test
>
> This is a script that I've been using in one form or another for years
> and I find it really handy [1].
Neat. I usually "git rebase -x 'make -j8 test' @{u}" after finishing a
topic to make sure the intermediate steps are good. But it would be neat
to have this running continuously in the background to alert me to
problems sooner (and the key thing there is that it remembers
already-run tests, so it should be safe to basically for new commits
every 10 seconds or so).
I did hit a few interesting cases trying out "git test". So here's a
narrative, and you can pick out where there may be room for improvement
in the tool, and where I'm just being dumb. :)
I tried it out first on a topic I finished earlier today, which has 3
commits. So I did:
$ git test add 'make -j8 test'
$ git test range @{u}..HEAD
It barfed on the first commit, because the script expects "git co" to
work, but I don't have that alias. No big deal (and I already submitted
a PR to fix it).
So then I reinvoked it like:
$ git test range @{u}..HEAD
and it actually ran some tests. Yay.
And then of course I wanted to prove to myself how cool the notes
feature is, so I ran it again. It didn't run any tests this time. Yay
again. But there were a few surprises:
$ git test range @{u}..HEAD
setup_test default
Using test default; command: make -j8 test
Old status: bad
Tree 9fcdbd5c78^{tree} is already known to be bad!
Old status: good
Tree c22f4f6624^{tree} is already known to be good.
Old status: good
Tree 19e2e62e5e^{tree} is already known to be good.
Already on 'jk/wait-for-child-cleanup'
Your branch is ahead of 'origin/master' by 3 commits.
ALL TESTS SUCCESSFUL
My initial run with "git co" had left the first commit marked as "bad".
That's not _too_ surprising, since it did indeed fail. I think it's
probably a bug to record a failure note, though, if checking out fails.
It's not necessarily an immutable property of the tree. In my case, it
was obviously dependent on a change in the git-test code, but that's
hopefully a fairly uncommon occurrence. But there are other reasons for
git-checkout to complain. For instance, imagine topic "foo" creates file
"foo.c". If I do:
$ echo content >foo.c
$ git test foo@{u}..foo
then checkout will complain about overwriting the untracked "foo.c".
It's reasonable to abort the operation there, but probably not to write
a permanent failure note. The problem wasn't in "foo", but in my local
tree.
The second thing that surprised me was "ALL TESTS SUCCESSFUL", when
clearly one of them was known-bad. :)
So at this point I knew I needed to re-run the test. Looks like there's
a "--force" option. Let's try it. There's no need to re-run the other
two, so let's just give it one commit:
$ git test range -f HEAD~2
...
Object 95649d6cf9ec68f05d1dc57ec1b989b8d263a7ae^{tree} has no note
Object e1970ce43abfbf625bce68516857e910748e5965^{tree} has no note
Object 368f99d57e8ed17243f2e164431449d48bfca2fb^{tree} has no note
Object ceede59ea90cebad52ba9c8263fef3fb6ef17593^{tree} has no note
Object dfe070511c652f2b8e1bf6540f238c9ca9ba41d3^{tree} has no note
Object 902d960b382a0cd424618ff4e1316da40e4be2f6^{tree} has no note
...
This started spewing out many lines like the one above, until I hit ^C.
Yikes!
Thinking something was wrong with the "-f" option, I tried it without:
$ git test range -f HEAD~2
...
commit e83c5163316f89bfbde7d9ab23ca2e25604af290 (origin/initial)
Author: Linus Torvalds <torvalds@ppc970.osdl.org>
Date: Thu Apr 7 15:13:13 2005 -0700
Initial revision of "git", the information manager from hell
Oops. Now I see the problem. I was expecting the arguments to be
rebase-like. But they're really rev-list like. So in both cases it
wanted to test all the way up from the root commits to HEAD~2. The "-f"
version never got to testing a commit because it was so busy trying to
delete the old notes.
I see the symmetry and simplicity in allowing the user to specify a full
range. But it also seems like it's easy to make a mistake that's going
to want to test a lot of commits. I wonder if it should complain when
there's no lower bound to the commit range. Or alternatively, if there's
a single positive reference, treat it as a lower bound, with HEAD as the
upper bound (which is vaguely rebase-like).
A few other observations about the note deletion:
- The "has no note" message should perhaps be suppressed. We're just
trying to overwrite the value if there is one (alternatively,
instead of removing it, just overwrite it, so the old note stays
until we get a result one way or the other).
- It was sufficiently slow that it looks like we invoke "git notes
remove" once per commit. It would be a lot more efficient to batch
them (not just in terms of process startup, but because you're going
to write a _ton_ of intermediate notes trees).
Of course none of that matters if you don't do something stupid like
trying to "git test" 45,000 commits. :)
So OK. Now I know what's going on. And I can get what I want with:
$ git test range -f HEAD~3..HEAD~2
which works, and now all of my tests are correctly marked. Of course
that's a lot to type. It would be easier as:
$ git test range -f -1 HEAD~2
usage: git-test [-h] {add,range,help} ...
git-test: error: unrecognized arguments: HEAD~2
but the tool doesn't seem to like passing through the rev-list argument.
It would be even easier if I could just repeat my range and only re-test
the "bad" commits. It was then that I decided to actually read the rest
of "git test help range" and see that you already wrote such an option,
cleverly hidden under the name "--retest".
And one final nit. I notice there is also a "--keep-going" option. Which
made me surprised that we bothered to test HEAD~1 and HEAD, when we knew
that HEAD~2 was bogus. I suspect this is related to the "ALL TESTS
SUCCESSFUL" issue. Presumably cached test results are not treated as
"bad" in general, which seems funny to me.
So those were all little cosmetic things. The other big thing I wanted
to see was what it's like to fix a bug deep in a topic. So I used "git
rebase -i" to inset a compile error into the first commit of my 3-patch
series. And then I tested it:
$ git test add -t compile 'make -j8'
$ git test range -t compile HEAD~3..
As predicted, it stopped at the first commit and told me it was buggy.
But I'm dumped onto a detached HEAD, and I'm on my own to actually get
the working tree to a state where I can test and fix on my actual
branch.
That's a nice outcome of the "git rebase -x make" approach. When you hit
a bug, you can fix it, "git commit --amend", and "git rebase
--continue". The downside is that it takes ownership of the branch while
you're doing it. So the whole concept of "run this in the background
with a separate worktree" breaks down completely.
I think it should be possible to script the next steps, though.
Something like like "git test fix foo", which would:
- expand the range of foo@{u}..foo to get the list of commits
- see which ones were marked as broken
- kick off an interactive rebase, but override GIT_EDITOR to mark any
broken ones as "edit" instead of "pick"
That lets you separate the act of testing from the act of fixing. You
can let the tester run continuously in the background, and only stop to
fix when you're at an appropriate point in your work.
Anyway. Seems like a neat tool. I may play around with it and see if I
can fit it into my workflow.
-Peff
^ permalink raw reply
* Re: [PATCH v2 4/4] mergetool: fix running in subdir when rerere enabled
From: Richard Hansen @ 2017-01-07 2:16 UTC (permalink / raw)
To: Johannes Sixt; +Cc: git, davvid, sbeller, simon
In-Reply-To: <199807ae-844c-57cd-28cf-2c10b3aee7a9@kdbg.org>
[-- Attachment #1: Type: text/plain, Size: 2562 bytes --]
On 2017-01-06 04:42, Johannes Sixt wrote:
> Am 06.01.2017 um 02:09 schrieb Richard Hansen:
>> If rerere is enabled and no pathnames are given, run cd_to_toplevel
>> before running 'git diff --name-only' so that 'git diff --name-only'
>> sees the pathnames emitted by 'git rerere remaining'.
>>
>> Also run cd_to_toplevel before running 'git rerere remaining' in case
>> 'git rerere remaining' is ever changed to print pathnames relative to
>> the current directory rather than to $GIT_WORK_TREE.
>>
>> This fixes a regression introduced in
>> 57937f70a09c12ef484c290865dac4066d207c9c (v2.11.0).
>>
>> Signed-off-by: Richard Hansen <hansenr@google.com>
>> ---
>> git-mergetool.sh | 1 +
>> t/t7610-mergetool.sh | 2 +-
>> 2 files changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/git-mergetool.sh b/git-mergetool.sh
>> index e52b4e4f2..67ea0d6db 100755
>> --- a/git-mergetool.sh
>> +++ b/git-mergetool.sh
>> @@ -456,6 +456,7 @@ main () {
>>
>> if test $# -eq 0 && test -e "$GIT_DIR/MERGE_RR"
>> then
>> + cd_to_toplevel
>> set -- $(git rerere remaining)
>> if test $# -eq 0
>> then
>
> This cannot be a complete solution. Why do we have another
> cd_to_toplevel later, after `git diff --name-only -- "$@"`?
The arguments passed to 'git diff' (including the -O argument) are all
interpreted as relative to the current working directory, yet 'git diff
--name-only' outputs pathnames that are relative to the top-level
directory. Thus:
* cd_to_toplevel MUST NOT be run before that 'git diff' command
unless all pathnames relative to $PWD are converted to absolute (or
relative to the top-level directory), and
* cd_to_toplevel MUST be run after 'git diff' so that $files is
interpreted correctly.
And now I realize that my change breaks -O<foo> if <foo> is relative to
$PWD. Grr. Too bad we don't have tests for running mergetool
-O<relative-path> from a subdirectory.
>
> Maybe it is necessary to revert back to the flow control that we had
> before 57937f70a09c ("mergetool: honor diff.orderFile", 2016-10-07)? It
> did not have `test $# -eq 0` and `test -e "$GIT_DIR/MERGE_RR"` in a
> single condition.
Reverting to the previous control flow won't work unless the -O pathname
is converted to absolute (or relative to the top-level directory). But
I'll have to do that anyway. Blech.
Do we already have a helper shell function somewhere that converts a
pathname to absolute? Thanks to symlinks it's trickier than one might
expect.
Thanks,
Richard
>
> -- Hannes
[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4845 bytes --]
^ permalink raw reply
* Re: [PATCH v2 2/4] t7610: make tests more independent and debuggable
From: Richard Hansen @ 2017-01-07 1:53 UTC (permalink / raw)
To: Stefan Beller
Cc: git@vger.kernel.org, David Aguilar, Johannes Sixt, Simon Ruderich
In-Reply-To: <CAGZ79kbRee+3MbAHCSFB0QqGMMF5bcZMiEHV-coRh87vFfq0Ag@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 3039 bytes --]
On 2017-01-05 20:31, Stefan Beller wrote:
> On Thu, Jan 5, 2017 at 5:09 PM, Richard Hansen <hansenr@google.com> wrote:
>> Reduce how much a test can interfere other tests:
>
> A bullet point list as an unordered list often indicates that you're
> doing multiple
> things at once, possibly unrelated, so they could go into different patches. ;)
OK, I'll split it up.
>
> While telling you to make even more commits: you may also want to make
> a patch with an entry to the .mailmap file (assuming you're the same
> Richard Hansen that contributed from rhansen@bbn.com);
> Welcome to Google!
Good idea, thanks!
>
>>
>> * Move setup code that multiple tests depend on to the 'setup' test
>> case.
>> * Run 'git reset --hard' after every test (pass or fail) to clean up
>> in case the test fails and leaves the repository in a strange
>> state.
>> * If the repository must be in a particular state (beyond what is
>> already done by the 'setup' test case) before the test can run,
>> make the necessary repository changes in the test script even if
>> it means duplicating some lines of code from the previous test
>> case.
>> * Never assume that a particular commit is checked out.
>> * Always work on a test-specific branch when the test might create a
>> commit. This is not always necessary for correctness, but it
>> improves debuggability by ensuring a commit created by test #N
>> shows up on the testN branch, not the branch for test #N-1.
>
>
>
>
>> @@ -112,6 +146,7 @@ test_expect_success 'custom mergetool' '
>> '
>>
>> test_expect_success 'mergetool crlf' '
>> + test_when_finished "git reset --hard" &&
>> test_config core.autocrlf true &&
>> git checkout -b test$test_count branch1 &&
>> test_must_fail git merge master >/dev/null 2>&1 &&
>> @@ -129,11 +164,11 @@ test_expect_success 'mergetool crlf' '
>> git submodule update -N &&
>> test "$(cat submod/bar)" = "master submodule" &&
>> git commit -m "branch1 resolved with mergetool - autocrlf" &&
>
>> - test_config core.autocrlf false &&
>> - git reset --hard
>> + test_config core.autocrlf false
>> '
>
> This is the nit that led me to writing this email in the first place:
> test_config is a function that sets a configuration for a single test only,
> so it makes no sense as the last statement of a test. (In its implementation
> it un-configures with test_when_finished)
>
> So I think we do not want to add it back, but rather remove this
> test_config statement.
OK, will do.
>
> But to do this we need to actually be careful with the order of the newly
> added test_when_finished "git reset --hard" and test_config core.autocrlf true,
> which uses test_when_finished internally.
Ah, yes. Tricky. I'll add a comment.
>
> The order seems correct to me, as the reset would be executed after the
> "test_config core.autocrlf true" is un-configured.
Agreed; test_when_finished is LIFO (though the order is not documented).
-Richard
[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4845 bytes --]
^ permalink raw reply
* Re: [PATCH 4/5] unpack-trees: factor file removal out of check_updates
From: Jeff King @ 2017-01-07 1:36 UTC (permalink / raw)
To: Stefan Beller; +Cc: gitster, l.s.r, git
In-Reply-To: <20170106210330.31761-5-sbeller@google.com>
On Fri, Jan 06, 2017 at 01:03:29PM -0800, Stefan Beller wrote:
> +static int remove_workingtree_files(struct unpack_trees_options *o,
> + struct progress *progress)
> +{
> + int i;
> + unsigned cnt = 0;
> + struct index_state *index = &o->result;
> +
> + for (i = 0; i < index->cache_nr; i++) {
> + const struct cache_entry *ce = index->cache[i];
> +
> + if (ce->ce_flags & CE_WT_REMOVE) {
> + display_progress(progress, ++cnt);
> + if (o->update && !o->dry_run)
> + unlink_entry(ce);
> + }
> + }
> +
> + return cnt;
> +}
"cnt" is unsigned here, as it is in the caller. Should the return value
match?
-Peff
^ permalink raw reply
* Re: [PATCH] branch_get_push: do not segfault when HEAD is detached
From: Jeff King @ 2017-01-07 1:31 UTC (permalink / raw)
To: Kyle Meyer; +Cc: Johannes Schindelin, git
In-Reply-To: <87bmvjll8m.fsf@kyleam.com>
On Fri, Jan 06, 2017 at 08:19:53PM -0500, Kyle Meyer wrote:
> > The other option is just "git checkout --detach", which is also used in
> > the test suite. I tend to prefer it because it's a little more obvious
> > to a reader.
>
> True, that does seem clearer. Seems I should've waited a bit before
> sending out v2.
I think it's OK either way. Junio can also mark it up while applying,
too, if he has a preference.
-Peff
^ permalink raw reply
* [PATCH 3/3] execv_dashed_external: wait for child on signal death
From: Jeff King @ 2017-01-07 1:22 UTC (permalink / raw)
To: Johannes Sixt; +Cc: Trygve Aaberge, Nguyễn Thái Ngọc Duy, git
In-Reply-To: <20170107011445.3e4fv6vdtimrwhgv@sigill.intra.peff.net>
When you hit ^C to interrupt a git command going to a pager,
this usually leaves the pager running. But when a dashed
external is in use, the pager ends up in a funny state and
quits (but only after eating one more character from the
terminal!). This fixes it.
Explaining the reason will require a little background.
When git runs a pager, it's important for the git process to
hang around and wait for the pager to finish, even though it
has no more data to feed it. This is because git spawns the
pager as a child, and thus the git process is the session
leader on the terminal. After it dies, the pager will finish
its current read from the terminal (eating the one
character), and then get EIO trying to read again.
When you hit ^C, that sends SIGINT to git and to the pager,
and it's a similar situation. The pager ignores it, but the
git process needs to hang around until the pager is done. We
addressed that long ago in a3da882120 (pager: do
wait_for_pager on signal death, 2009-01-22).
But when you have a dashed external (or an alias pointing to
a builtin, which will re-exec git for the builtin), there's
an extra process in the mix. For instance, running:
git -c alias.l=log log
will end up with a process tree like:
git (parent)
\
git-log (child)
\
less (pager)
If you hit ^C, SIGINT goes to all of them. The pager ignores
it, and the child git process will end up in wait_for_pager().
But the parent git process will die, and the usual EIO
trouble happens.
So we really want the parent git process to wait_for_pager(),
but of course it doesn't know anything about the pager at
all, since it was started by the child. However, we can
have it wait on the git-log child, which in turn is waiting
on the pager. And that's what this patch does.
There are a few design decisions here worth explaining:
1. The new feature is attached to run-command's
clean_on_exit feature. Partly this is convenience,
since that feature already has a signal handler that
deals with child cleanup.
But it's also a meaningful connection. The main reason
that dashed externals use clean_on_exit is to bind the
two processes together. If somebody kills the parent
with a signal, we propagate that to the child (in this
instance with SIGINT, we do propagate but it doesn't
matter because the original signal went to the whole
process group). Likewise, we do not want the parent
to go away until the child has done so.
In a traditional Unix world, we'd probably accomplish
this binding by just having the parent execve() the
child directly. But since that doesn't work on Windows,
everything goes through run_command's more spawn-like
interface.
2. We do _not_ automatically waitpid() on any
clean_on_exit children. For dashed externals this makes
sense; we know that the parent is doing nothing but
waiting for the child to exit anyway. But with other
children, it's possible that the child, after getting
the signal, could be waiting on the parent to do
something (like closing a descriptor). If we were to
wait on such a child, we'd end up in a deadlock. So
this errs on the side of caution, and lets callers
enable the feature explicitly.
3. When we send children the cleanup signal, we send all
the signals first, before waiting on any children. This
is to avoid the case where one child might be waiting
on another one to exit, causing a deadlock. We inform
all of them that it's time to die before reaping any.
In practice, there is only ever one dashed external run
from a given process, so this doesn't matter much now.
But it future-proofs us if other callers start using
the wait_after_clean mechanism.
There's no automated test here, because it would end up racy
and unportable. But it's easy to reproduce the situation by
running the log command given above and hitting ^C.
Signed-off-by: Jeff King <peff@peff.net>
---
git.c | 1 +
run-command.c | 19 +++++++++++++++++++
run-command.h | 1 +
3 files changed, 21 insertions(+)
diff --git a/git.c b/git.c
index bc2f2a7ec9..c8fe6637df 100644
--- a/git.c
+++ b/git.c
@@ -588,6 +588,7 @@ static void execv_dashed_external(const char **argv)
argv_array_pushf(&cmd.args, "git-%s", argv[0]);
argv_array_pushv(&cmd.args, argv + 1);
cmd.clean_on_exit = 1;
+ cmd.wait_after_clean = 1;
cmd.silent_exec_failure = 1;
trace_argv_printf(cmd.args.argv, "trace: exec:");
diff --git a/run-command.c b/run-command.c
index ca905a9e80..73bfba7ef9 100644
--- a/run-command.c
+++ b/run-command.c
@@ -29,6 +29,8 @@ static int installed_child_cleanup_handler;
static void cleanup_children(int sig, int in_signal)
{
+ struct child_to_clean *children_to_wait_for = NULL;
+
while (children_to_clean) {
struct child_to_clean *p = children_to_clean;
children_to_clean = p->next;
@@ -45,6 +47,23 @@ static void cleanup_children(int sig, int in_signal)
}
kill(p->pid, sig);
+
+ if (p->process->wait_after_clean) {
+ p->next = children_to_wait_for;
+ children_to_wait_for = p;
+ } else {
+ if (!in_signal)
+ free(p);
+ }
+ }
+
+ while (children_to_wait_for) {
+ struct child_to_clean *p = children_to_wait_for;
+ children_to_wait_for = p->next;
+
+ while (waitpid(p->pid, NULL, 0) < 0 && errno == EINTR)
+ ; /* spin waiting for process exit or error */
+
if (!in_signal)
free(p);
}
diff --git a/run-command.h b/run-command.h
index dd1c78c28d..4fa8f65adb 100644
--- a/run-command.h
+++ b/run-command.h
@@ -43,6 +43,7 @@ struct child_process {
unsigned stdout_to_stderr:1;
unsigned use_shell:1;
unsigned clean_on_exit:1;
+ unsigned wait_after_clean:1;
void (*clean_on_exit_handler)(struct child_process *process);
void *clean_on_exit_handler_cbdata;
};
--
2.11.0.527.gfef230ca76
^ permalink raw reply related
* Re: [PATCH] branch_get_push: do not segfault when HEAD is detached
From: Kyle Meyer @ 2017-01-07 1:19 UTC (permalink / raw)
To: Jeff King; +Cc: Johannes Schindelin, git
In-Reply-To: <20170107011138.uuy6ob234kyy3y4e@sigill.intra.peff.net>
Jeff King <peff@peff.net> writes:
> On Fri, Jan 06, 2017 at 08:09:32PM -0500, Kyle Meyer wrote:
>
>> > $ git grep -c HEAD^{} junio/pu -- t/
>> > junio/pu:t/t3200-branch.sh:3
>> >
>> > Maybe use HEAD^0 just for consistency?
>>
>> Yes, thanks for pointing that out.
>
> The other option is just "git checkout --detach", which is also used in
> the test suite. I tend to prefer it because it's a little more obvious
> to a reader.
True, that does seem clearer. Seems I should've waited a bit before
sending out v2.
--
Kyle
^ permalink raw reply
* [PATCH 2/3] execv_dashed_external: stop exiting with negative code
From: Jeff King @ 2017-01-07 1:17 UTC (permalink / raw)
To: Johannes Sixt; +Cc: Trygve Aaberge, Nguyễn Thái Ngọc Duy, git
In-Reply-To: <20170107011445.3e4fv6vdtimrwhgv@sigill.intra.peff.net>
When we try to exec a git sub-command, we pass along the
status code from run_command(). But that may return -1 if we
ran into an error with pipe() or execve(). This tends to
work (and end up as 255 due to twos-complement wraparound
and truncation), but in general it's probably a good idea to
avoid negative exit codes for portability.
We can easily translate to the normal generic "128" code we
get when syscalls cause us to die.
Signed-off-by: Jeff King <peff@peff.net>
---
I know that negative exit codes were a problem once upon a time on
Windows, but I think that is fine since 47e3de0e79 (MinGW: truncate
exit()'s argument to lowest 8 bits, 2009-07-05). Still, I think it's a
weird portability thing that we are better off avoiding (and certainly I
wouldn't be surprised if some callers assume everything >128 is a
signal).
git.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/git.c b/git.c
index d0e04d5c97..bc2f2a7ec9 100644
--- a/git.c
+++ b/git.c
@@ -593,12 +593,16 @@ static void execv_dashed_external(const char **argv)
trace_argv_printf(cmd.args.argv, "trace: exec:");
/*
- * if we fail because the command is not found, it is
- * OK to return. Otherwise, we just pass along the status code.
+ * If we fail because the command is not found, it is
+ * OK to return. Otherwise, we just pass along the status code,
+ * or our usual generic code if we were not even able to exec
+ * the program.
*/
status = run_command(&cmd);
- if (status >= 0 || errno != ENOENT)
+ if (status >= 0)
exit(status);
+ else if (errno != ENOENT)
+ exit(128);
}
static int run_argv(int *argcp, const char ***argv)
--
2.11.0.527.gfef230ca76
^ permalink raw reply related
* [PATCH 1/3] execv_dashed_external: use child_process struct
From: Jeff King @ 2017-01-07 1:16 UTC (permalink / raw)
To: Johannes Sixt; +Cc: Trygve Aaberge, Nguyễn Thái Ngọc Duy, git
In-Reply-To: <20170107011445.3e4fv6vdtimrwhgv@sigill.intra.peff.net>
When we run a dashed external, we use the one-liner
run_command_v_opt() to do so. Let's switch to using a
child_process struct, which has two advantages:
1. We can drop all of the allocation and cleanup code for
building our custom argv array, and just rely on the
builtin argv_array (at the minor cost of doing a few
extra mallocs).
2. We have access to the complete range of child_process
options, not just the ones that the "_opt()" form can
forward.
Signed-off-by: Jeff King <peff@peff.net>
---
It's possible people may disagree with reason (2), and we should add a
new RUN_WAIT_AFTER_CLEAN flag in the final patch. IMHO the whole
run_command_v_opt() thing is a good sign that you should be switching to
a child_process struct. :)
git.c | 25 +++++++------------------
1 file changed, 7 insertions(+), 18 deletions(-)
diff --git a/git.c b/git.c
index dce529fcbf..d0e04d5c97 100644
--- a/git.c
+++ b/git.c
@@ -575,8 +575,7 @@ static void handle_builtin(int argc, const char **argv)
static void execv_dashed_external(const char **argv)
{
- struct strbuf cmd = STRBUF_INIT;
- const char *tmp;
+ struct child_process cmd = CHILD_PROCESS_INIT;
int status;
if (get_super_prefix())
@@ -586,30 +585,20 @@ static void execv_dashed_external(const char **argv)
use_pager = check_pager_config(argv[0]);
commit_pager_choice();
- strbuf_addf(&cmd, "git-%s", argv[0]);
+ argv_array_pushf(&cmd.args, "git-%s", argv[0]);
+ argv_array_pushv(&cmd.args, argv + 1);
+ cmd.clean_on_exit = 1;
+ cmd.silent_exec_failure = 1;
- /*
- * argv[0] must be the git command, but the argv array
- * belongs to the caller, and may be reused in
- * subsequent loop iterations. Save argv[0] and
- * restore it on error.
- */
- tmp = argv[0];
- argv[0] = cmd.buf;
-
- trace_argv_printf(argv, "trace: exec:");
+ trace_argv_printf(cmd.args.argv, "trace: exec:");
/*
* if we fail because the command is not found, it is
* OK to return. Otherwise, we just pass along the status code.
*/
- status = run_command_v_opt(argv, RUN_SILENT_EXEC_FAILURE | RUN_CLEAN_ON_EXIT);
+ status = run_command(&cmd);
if (status >= 0 || errno != ENOENT)
exit(status);
-
- argv[0] = tmp;
-
- strbuf_release(&cmd);
}
static int run_argv(int *argcp, const char ***argv)
--
2.11.0.527.gfef230ca76
^ permalink raw reply related
* [PATCH 0/3] fix ^C killing pager when running alias
From: Jeff King @ 2017-01-07 1:14 UTC (permalink / raw)
To: Johannes Sixt; +Cc: Trygve Aaberge, Nguyễn Thái Ngọc Duy, git
In-Reply-To: <20170106232042.ptn6grtll5wpxhc4@sigill.intra.peff.net>
On Fri, Jan 06, 2017 at 06:20:42PM -0500, Jeff King wrote:
> > In general, I think it is wrong to wait for child processes when a signal
> > was received. After all, it is the purpose of a (deadly) signal to have the
> > process go away. There may be programs that know it better, like less, but
> > git should not attempt to know better in general.
> >
> > We do apply some special behavior for certain cases like we do for the
> > pager. And now the case with aliases is another special situation. The
> > parent git process only delegates to the child, and as such it is reasonable
> > that it binds its life time to the first child, which executes the expanded
> > alias.
>
> Yeah, I think I agree. That binding is something you want in many cases,
> but not necessarily all. The original purpose of clean_on_exit was to
> create a binding like that, but of course it can be (and with the
> smudge-filter stuff, arguably has been) used for other cases, too.
>
> I'll work up a patch that makes it a separate option, which should be
> pretty easy.
Yeah, this did turn out to be really easy. I spent most of the time
trying to explain the issue in the commit message in a sane way.
Hopefully it didn't end up _too_ long. :)
The interesting bit is in the third one. The first is a necessary
preparatory step, and the second is a cleanup I noticed in the
neighborhood.
[1/3]: execv_dashed_external: use child_process struct
[2/3]: execv_dashed_external: stop exiting with negative code
[3/3]: execv_dashed_external: wait for child on signal death
git.c | 36 +++++++++++++++---------------------
run-command.c | 19 +++++++++++++++++++
run-command.h | 1 +
3 files changed, 35 insertions(+), 21 deletions(-)
-Peff
^ permalink raw reply
* [PATCH v2] branch_get_push: do not segfault when HEAD is detached
From: Kyle Meyer @ 2017-01-07 1:12 UTC (permalink / raw)
To: git; +Cc: Jeff King, Johannes Schindelin, Kyle Meyer
In-Reply-To: <20170106045623.21118-1-kyle@kyleam.com>
Move the detached HEAD check from branch_get_push_1() to
branch_get_push() to avoid setting branch->push_tracking_ref when
branch is NULL.
Signed-off-by: Kyle Meyer <kyle@kyleam.com>
---
remote.c | 6 +++---
t/t1514-rev-parse-push.sh | 6 ++++++
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/remote.c b/remote.c
index ad6c5424e..d5eaec737 100644
--- a/remote.c
+++ b/remote.c
@@ -1716,9 +1716,6 @@ static const char *branch_get_push_1(struct branch *branch, struct strbuf *err)
{
struct remote *remote;
- if (!branch)
- return error_buf(err, _("HEAD does not point to a branch"));
-
remote = remote_get(pushremote_for_branch(branch, NULL));
if (!remote)
return error_buf(err,
@@ -1778,6 +1775,9 @@ static const char *branch_get_push_1(struct branch *branch, struct strbuf *err)
const char *branch_get_push(struct branch *branch, struct strbuf *err)
{
+ if (!branch)
+ return error_buf(err, _("HEAD does not point to a branch"));
+
if (!branch->push_tracking_ref)
branch->push_tracking_ref = branch_get_push_1(branch, err);
return branch->push_tracking_ref;
diff --git a/t/t1514-rev-parse-push.sh b/t/t1514-rev-parse-push.sh
index 7214f5b33..623a32aa6 100755
--- a/t/t1514-rev-parse-push.sh
+++ b/t/t1514-rev-parse-push.sh
@@ -60,4 +60,10 @@ test_expect_success '@{push} with push refspecs' '
resolve topic@{push} refs/remotes/origin/magic/topic
'
+test_expect_success 'resolving @{push} fails with a detached HEAD' '
+ git checkout HEAD^0 &&
+ test_when_finished "git checkout -" &&
+ test_must_fail git rev-parse @{push}
+'
+
test_done
--
2.11.0
^ permalink raw reply related
* Re: [PATCH] branch_get_push: do not segfault when HEAD is detached
From: Jeff King @ 2017-01-07 1:11 UTC (permalink / raw)
To: Kyle Meyer; +Cc: Johannes Schindelin, git
In-Reply-To: <87inprllpv.fsf@kyleam.com>
On Fri, Jan 06, 2017 at 08:09:32PM -0500, Kyle Meyer wrote:
> > $ git grep -c HEAD^{} junio/pu -- t/
> > junio/pu:t/t3200-branch.sh:3
> >
> > Maybe use HEAD^0 just for consistency?
>
> Yes, thanks for pointing that out.
The other option is just "git checkout --detach", which is also used in
the test suite. I tend to prefer it because it's a little more obvious
to a reader.
-Peff
^ permalink raw reply
* Re: [PATCH] branch_get_push: do not segfault when HEAD is detached
From: Kyle Meyer @ 2017-01-07 1:09 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git, Jeff King
In-Reply-To: <alpine.DEB.2.20.1701061438300.3469@virtualbox>
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
[...]
>> +test_expect_success 'resolving @{push} fails with a detached HEAD' '
>> + git checkout HEAD^{} &&
>
> I seem to recall that we prefer HEAD^0 over HEAD^{} and the existing
> scripts seem to agree with me:
>
> $ git grep -c HEAD^0 junio/pu -- t/
> junio/pu:t/t1450-fsck.sh:1
> junio/pu:t/t1507-rev-parse-upstream.sh:2
> junio/pu:t/t2020-checkout-detach.sh:5
> junio/pu:t/t3200-branch.sh:1
> junio/pu:t/t3203-branch-output.sh:3
> junio/pu:t/t3400-rebase.sh:1
> junio/pu:t/t3404-rebase-interactive.sh:1
> junio/pu:t/t5407-post-rewrite-hook.sh:2
> junio/pu:t/t5505-remote.sh:1
> junio/pu:t/t5510-fetch.sh:1
> junio/pu:t/t5533-push-cas.sh:3
> junio/pu:t/t6035-merge-dir-to-symlink.sh:3
> junio/pu:t/t7201-co.sh:2
> junio/pu:t/t7402-submodule-rebase.sh:1
> junio/pu:t/t9105-git-svn-commit-diff.sh:1
> junio/pu:t/t9107-git-svn-migrate.sh:1
>
> $ git grep -c HEAD^{} junio/pu -- t/
> junio/pu:t/t3200-branch.sh:3
>
> Maybe use HEAD^0 just for consistency?
Yes, thanks for pointing that out.
--
Kyle
^ permalink raw reply
* Re: [PATCH] submodule update --init: displays correct path from submodule
From: Stefan Beller @ 2017-01-07 1:01 UTC (permalink / raw)
To: David Turner; +Cc: Junio C Hamano, git@vger.kernel.org
In-Reply-To: <1483750501.31165.9.camel@frank>
On Fri, Jan 6, 2017 at 4:55 PM, David Turner <novalis@novalis.org> wrote:
> (for the test)
> Signed-off-by: David Turner <dturner@twosigma.com>
>
> TIL: super-prefix!
yeah that was introduced recently for prefixes from "outside the repository"
e.g. a superproject, its first user is grep --recurse-submodules.
Also I realize I have set diff.context to 15 as I was experimenting
with it earlier,
and forgot to turn it off. So a lot of context in the diff for the patch.
Thanks for the bug report,
Stefan
^ permalink raw reply
* Re: [PATCH] submodule update --init: displays correct path from submodule
From: David Turner @ 2017-01-07 0:55 UTC (permalink / raw)
To: Stefan Beller; +Cc: gitster, git
In-Reply-To: <20170107001953.3196-1-sbeller@google.com>
(for the test)
Signed-off-by: David Turner <dturner@twosigma.com>
TIL: super-prefix!
On Fri, 2017-01-06 at 16:19 -0800, Stefan Beller wrote:
> In the submodule helper we did not correctly handled the display path
> for initializing submodules when both the submodule is inside a
> subdirectory as well as the command being invoked from a subdirectory
> (as viewed from the superproject).
>
> This was broken in 3604242f080, which was written at a time where
> there was no super-prefix available, so we abused the --prefix option
> for the same purpose and could get only one case right (the call from
> within a subdirectory, not the submodule being in a subdirectory).
>
> Test-provided-by: David Turner <novalis@novalis.org>
> Signed-off-by: Stefan Beller <sbeller@google.com>
> ---
>
> applies on sb/submodule-embed-gitdir as that contains 89c862655
> (submodule helper: support super prefix)
>
> builtin/submodule--helper.c | 13 +++++++------
> git-submodule.sh | 2 +-
> t/t7406-submodule-update.sh | 17 +++++++++++++++++
> 3 files changed, 25 insertions(+), 7 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index 242d9911a6..7b3f9fc293 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -305,32 +305,36 @@ static int module_list(int argc, const char **argv, const char *prefix)
>
> utf8_fprintf(stdout, "%s\n", ce->name);
> }
> return 0;
> }
>
> static void init_submodule(const char *path, const char *prefix, int quiet)
> {
> const struct submodule *sub;
> struct strbuf sb = STRBUF_INIT;
> char *upd = NULL, *url = NULL, *displaypath;
>
> /* Only loads from .gitmodules, no overlay with .git/config */
> gitmodules_config();
>
> - if (prefix) {
> - strbuf_addf(&sb, "%s%s", prefix, path);
> + if (prefix && get_super_prefix())
> + die("BUG: cannot have prefix and superprefix");
> + else if (prefix)
> + displaypath = xstrdup(relative_path(path, prefix, &sb));
> + else if (get_super_prefix()) {
> + strbuf_addf(&sb, "%s%s", get_super_prefix(), path);
> displaypath = strbuf_detach(&sb, NULL);
> } else
> displaypath = xstrdup(path);
>
> sub = submodule_from_path(null_sha1, path);
>
> if (!sub)
> die(_("No url found for submodule path '%s' in .gitmodules"),
> displaypath);
>
> /*
> * Copy url setting when it is not set yet.
> * To look up the url in .git/config, we must not fall back to
> * .gitmodules, so look it up directly.
> */
> @@ -391,33 +395,30 @@ static void init_submodule(const char *path, const char *prefix, int quiet)
> }
> strbuf_release(&sb);
> free(displaypath);
> free(url);
> free(upd);
> }
>
> static int module_init(int argc, const char **argv, const char *prefix)
> {
> struct pathspec pathspec;
> struct module_list list = MODULE_LIST_INIT;
> int quiet = 0;
> int i;
>
> struct option module_init_options[] = {
> - OPT_STRING(0, "prefix", &prefix,
> - N_("path"),
> - N_("alternative anchor for relative paths")),
> OPT__QUIET(&quiet, N_("Suppress output for initializing a submodule")),
> OPT_END()
> };
>
> const char *const git_submodule_helper_usage[] = {
> N_("git submodule--helper init [<path>]"),
> NULL
> };
>
> argc = parse_options(argc, argv, prefix, module_init_options,
> git_submodule_helper_usage, 0);
>
> if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
> return 1;
>
> @@ -1117,31 +1118,31 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
>
> struct cmd_struct {
> const char *cmd;
> int (*fn)(int, const char **, const char *);
> unsigned option;
> };
>
> static struct cmd_struct commands[] = {
> {"list", module_list, 0},
> {"name", module_name, 0},
> {"clone", module_clone, 0},
> {"update-clone", update_clone, 0},
> {"relative-path", resolve_relative_path, 0},
> {"resolve-relative-url", resolve_relative_url, 0},
> {"resolve-relative-url-test", resolve_relative_url_test, 0},
> - {"init", module_init, 0},
> + {"init", module_init, SUPPORT_SUPER_PREFIX},
> {"remote-branch", resolve_remote_submodule_branch, 0},
> {"absorb-git-dirs", absorb_git_dirs, SUPPORT_SUPER_PREFIX},
> };
>
> int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
> {
> int i;
> if (argc < 2)
> die(_("submodule--helper subcommand must be "
> "called with a subcommand"));
>
> for (i = 0; i < ARRAY_SIZE(commands); i++) {
> if (!strcmp(argv[1], commands[i].cmd)) {
> if (get_super_prefix() &&
> !(commands[i].option & SUPPORT_SUPER_PREFIX))
> diff --git a/git-submodule.sh b/git-submodule.sh
> index 9285b5c43d..4e47ff8ad8 100755
> --- a/git-submodule.sh
> +++ b/git-submodule.sh
> @@ -362,31 +362,31 @@ cmd_init()
> ;;
> --)
> shift
> break
> ;;
> -*)
> usage
> ;;
> *)
> break
> ;;
> esac
> shift
> done
>
> - git ${wt_prefix:+-C "$wt_prefix"} submodule--helper init ${GIT_QUIET:+--quiet} ${prefix:+--prefix "$prefix"} "$@"
> + git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper init ${GIT_QUIET:+--quiet} "$@"
> }
>
> #
> # Unregister submodules from .git/config and remove their work tree
> #
> cmd_deinit()
> {
> # parse $args after "submodule ... deinit".
> deinit_all=
> while test $# -ne 0
> do
> case "$1" in
> -f|--force)
> force=$1
> ;;
> diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
> index 64f322c4cc..725bbed1f8 100755
> --- a/t/t7406-submodule-update.sh
> +++ b/t/t7406-submodule-update.sh
> @@ -128,30 +128,47 @@ done.
> Cloning into '$pwd/recursivesuper/super/submodule'...
> done.
> EOF
>
> test_expect_success 'submodule update --init --recursive from subdirectory' '
> git -C recursivesuper/super reset --hard HEAD^ &&
> (cd recursivesuper &&
> mkdir tmp &&
> cd tmp &&
> git submodule update --init --recursive ../super >../../actual 2>../../actual2
> ) &&
> test_i18ncmp expect actual &&
> test_i18ncmp expect2 actual2
> '
>
> +cat <<EOF >expect2
> +Submodule 'foo/sub' ($pwd/withsubs/../rebasing) registered for path 'sub'
> +EOF
> +
> +test_expect_success 'submodule update --init from and of subdirectory' '
> + git init withsubs &&
> + (cd withsubs &&
> + mkdir foo &&
> + git submodule add "$(pwd)/../rebasing" foo/sub &&
> + (cd foo &&
> + git submodule deinit -f sub &&
> + git submodule update --init sub 2>../../actual2
> + )
> + ) &&
> + test_i18ncmp expect2 actual2
> +'
> +
> apos="'";
> test_expect_success 'submodule update does not fetch already present commits' '
> (cd submodule &&
> echo line3 >> file &&
> git add file &&
> test_tick &&
> git commit -m "upstream line3"
> ) &&
> (cd super/submodule &&
> head=$(git rev-parse --verify HEAD) &&
> echo "Submodule path ${apos}submodule$apos: checked out $apos$head$apos" > ../../expected &&
> git reset --hard HEAD~1
> ) &&
> (cd super &&
> git submodule update > ../actual 2> ../actual.err
^ permalink raw reply
* [PATCH] submodule update --init: displays correct path from submodule
From: Stefan Beller @ 2017-01-07 0:19 UTC (permalink / raw)
To: gitster; +Cc: novalis, git, Stefan Beller
In the submodule helper we did not correctly handled the display path
for initializing submodules when both the submodule is inside a
subdirectory as well as the command being invoked from a subdirectory
(as viewed from the superproject).
This was broken in 3604242f080, which was written at a time where
there was no super-prefix available, so we abused the --prefix option
for the same purpose and could get only one case right (the call from
within a subdirectory, not the submodule being in a subdirectory).
Test-provided-by: David Turner <novalis@novalis.org>
Signed-off-by: Stefan Beller <sbeller@google.com>
---
applies on sb/submodule-embed-gitdir as that contains 89c862655
(submodule helper: support super prefix)
builtin/submodule--helper.c | 13 +++++++------
git-submodule.sh | 2 +-
t/t7406-submodule-update.sh | 17 +++++++++++++++++
3 files changed, 25 insertions(+), 7 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 242d9911a6..7b3f9fc293 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -305,32 +305,36 @@ static int module_list(int argc, const char **argv, const char *prefix)
utf8_fprintf(stdout, "%s\n", ce->name);
}
return 0;
}
static void init_submodule(const char *path, const char *prefix, int quiet)
{
const struct submodule *sub;
struct strbuf sb = STRBUF_INIT;
char *upd = NULL, *url = NULL, *displaypath;
/* Only loads from .gitmodules, no overlay with .git/config */
gitmodules_config();
- if (prefix) {
- strbuf_addf(&sb, "%s%s", prefix, path);
+ if (prefix && get_super_prefix())
+ die("BUG: cannot have prefix and superprefix");
+ else if (prefix)
+ displaypath = xstrdup(relative_path(path, prefix, &sb));
+ else if (get_super_prefix()) {
+ strbuf_addf(&sb, "%s%s", get_super_prefix(), path);
displaypath = strbuf_detach(&sb, NULL);
} else
displaypath = xstrdup(path);
sub = submodule_from_path(null_sha1, path);
if (!sub)
die(_("No url found for submodule path '%s' in .gitmodules"),
displaypath);
/*
* Copy url setting when it is not set yet.
* To look up the url in .git/config, we must not fall back to
* .gitmodules, so look it up directly.
*/
@@ -391,33 +395,30 @@ static void init_submodule(const char *path, const char *prefix, int quiet)
}
strbuf_release(&sb);
free(displaypath);
free(url);
free(upd);
}
static int module_init(int argc, const char **argv, const char *prefix)
{
struct pathspec pathspec;
struct module_list list = MODULE_LIST_INIT;
int quiet = 0;
int i;
struct option module_init_options[] = {
- OPT_STRING(0, "prefix", &prefix,
- N_("path"),
- N_("alternative anchor for relative paths")),
OPT__QUIET(&quiet, N_("Suppress output for initializing a submodule")),
OPT_END()
};
const char *const git_submodule_helper_usage[] = {
N_("git submodule--helper init [<path>]"),
NULL
};
argc = parse_options(argc, argv, prefix, module_init_options,
git_submodule_helper_usage, 0);
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
return 1;
@@ -1117,31 +1118,31 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
struct cmd_struct {
const char *cmd;
int (*fn)(int, const char **, const char *);
unsigned option;
};
static struct cmd_struct commands[] = {
{"list", module_list, 0},
{"name", module_name, 0},
{"clone", module_clone, 0},
{"update-clone", update_clone, 0},
{"relative-path", resolve_relative_path, 0},
{"resolve-relative-url", resolve_relative_url, 0},
{"resolve-relative-url-test", resolve_relative_url_test, 0},
- {"init", module_init, 0},
+ {"init", module_init, SUPPORT_SUPER_PREFIX},
{"remote-branch", resolve_remote_submodule_branch, 0},
{"absorb-git-dirs", absorb_git_dirs, SUPPORT_SUPER_PREFIX},
};
int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
{
int i;
if (argc < 2)
die(_("submodule--helper subcommand must be "
"called with a subcommand"));
for (i = 0; i < ARRAY_SIZE(commands); i++) {
if (!strcmp(argv[1], commands[i].cmd)) {
if (get_super_prefix() &&
!(commands[i].option & SUPPORT_SUPER_PREFIX))
diff --git a/git-submodule.sh b/git-submodule.sh
index 9285b5c43d..4e47ff8ad8 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -362,31 +362,31 @@ cmd_init()
;;
--)
shift
break
;;
-*)
usage
;;
*)
break
;;
esac
shift
done
- git ${wt_prefix:+-C "$wt_prefix"} submodule--helper init ${GIT_QUIET:+--quiet} ${prefix:+--prefix "$prefix"} "$@"
+ git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper init ${GIT_QUIET:+--quiet} "$@"
}
#
# Unregister submodules from .git/config and remove their work tree
#
cmd_deinit()
{
# parse $args after "submodule ... deinit".
deinit_all=
while test $# -ne 0
do
case "$1" in
-f|--force)
force=$1
;;
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index 64f322c4cc..725bbed1f8 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -128,30 +128,47 @@ done.
Cloning into '$pwd/recursivesuper/super/submodule'...
done.
EOF
test_expect_success 'submodule update --init --recursive from subdirectory' '
git -C recursivesuper/super reset --hard HEAD^ &&
(cd recursivesuper &&
mkdir tmp &&
cd tmp &&
git submodule update --init --recursive ../super >../../actual 2>../../actual2
) &&
test_i18ncmp expect actual &&
test_i18ncmp expect2 actual2
'
+cat <<EOF >expect2
+Submodule 'foo/sub' ($pwd/withsubs/../rebasing) registered for path 'sub'
+EOF
+
+test_expect_success 'submodule update --init from and of subdirectory' '
+ git init withsubs &&
+ (cd withsubs &&
+ mkdir foo &&
+ git submodule add "$(pwd)/../rebasing" foo/sub &&
+ (cd foo &&
+ git submodule deinit -f sub &&
+ git submodule update --init sub 2>../../actual2
+ )
+ ) &&
+ test_i18ncmp expect2 actual2
+'
+
apos="'";
test_expect_success 'submodule update does not fetch already present commits' '
(cd submodule &&
echo line3 >> file &&
git add file &&
test_tick &&
git commit -m "upstream line3"
) &&
(cd super/submodule &&
head=$(git rev-parse --verify HEAD) &&
echo "Submodule path ${apos}submodule$apos: checked out $apos$head$apos" > ../../expected &&
git reset --hard HEAD~1
) &&
(cd super &&
git submodule update > ../actual 2> ../actual.err
--
2.11.0.rc2.30.g7c4be45.dirty
^ permalink raw reply related
* Re: Regression: Ctrl-c from the pager in an alias exits it
From: Jeff King @ 2017-01-06 23:20 UTC (permalink / raw)
To: Johannes Sixt; +Cc: Trygve Aaberge, Nguyễn Thái Ngọc Duy, git
In-Reply-To: <2ed6f78b-7704-c724-c99b-e310c383c4e8@kdbg.org>
On Fri, Jan 06, 2017 at 11:42:25PM +0100, Johannes Sixt wrote:
> > So I dunno. Maybe this waiting should be restricted only to certain
> > cases like executing git sub-commands.
>
> If given it some thought.
>
> In general, I think it is wrong to wait for child processes when a signal
> was received. After all, it is the purpose of a (deadly) signal to have the
> process go away. There may be programs that know it better, like less, but
> git should not attempt to know better in general.
>
> We do apply some special behavior for certain cases like we do for the
> pager. And now the case with aliases is another special situation. The
> parent git process only delegates to the child, and as such it is reasonable
> that it binds its life time to the first child, which executes the expanded
> alias.
Yeah, I think I agree. That binding is something you want in many cases,
but not necessarily all. The original purpose of clean_on_exit was to
create a binding like that, but of course it can be (and with the
smudge-filter stuff, arguably has been) used for other cases, too.
I'll work up a patch that makes it a separate option, which should be
pretty easy.
-Peff
^ permalink raw reply
* Git filesystem case-insensitive to case-sensitive system broken
From: Steven Robertson @ 2017-01-06 21:56 UTC (permalink / raw)
To: git
Hello,
I was doing development on a linux box on AWS, when we found a code
bug that had me switching to running the code on a Mac instead. We
discovered that we had accidentally named two files the same when
looked at case-insensitively, which made git commands afterwards
display the wrong thing. It looked like this (ignoring some things
that aren't relevant):
$ git status
modified: tests/test_system/show_19_L.txt
no changes added to commit (use "git add" and/or "git commit -a")
$ git checkout tests/test_system/show_19_L.txt
$ git status
modified: tests/test_system/show_19_l.txt
no changes added to commit (use "git add" and/or "git commit -a")
$ git checkout tests/test_system/show_19_l.txt
$ git status
modified: tests/test_system/show_19_L.txt
no changes added to commit (use "git add" and/or "git commit -a")
$ diff tests/test_system/show_19_L.txt tests/test_system/show_19_l.txt
$
Those two files are different in our repo, and as such git thinks that
we modified one of them when we try and pull it down from github
again.
Thanks for looking at this!
-- Steven
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox