-
Notifications
You must be signed in to change notification settings - Fork 411
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
delta incorrectly thinks that the input files are the same within git a hook🐛 #989
Comments
Further investigation reveals that the exit code from delta is wrong in this scenario. Both I changed my diff -u "${dst}" "${tmp}" | delta --side-by-side --paging never --width "$(tput cols)" and then check for See discussion on #626. #!/bin/bash
set -e
write-file() {
local -r dst="$1"; shift || return
local -r src="$1"; shift || return
if [[ -f "${dst}" ]]; then
local -r tmp="$(mktemp)" && trap "rm -f '${tmp}'" RETURN || return
cp "${src}" "${tmp}"
diff -u "${dst}" "${tmp}" && echo SAME || echo DIFFERENT
git diff --no-index "${dst}" "${tmp}" && echo SAME || echo DIFFERENT
diff -u "${dst}" "${tmp}" | delta --side-by-side --paging never --width "$(tput cols)"
if [ ${PIPESTATUS[0]} -eq 0 ]; then
echo -e "\e[36m=\e[0m Already up to date: \e[36m${dst}\e[0m"
else
echo -e "\n\e[33m≠\e[0m File contents changed: \e[33m${dst}\e[0m\n"
cp $([[ $- == *i* ]] && echo -i ]]) "${tmp}" "${dst}"
fi
else
cp "${src}" "${dst}" && echo -e "\e[94m✓\e[0m Successfully wrote: \e[94m${dst}\e[0m"
fi
}
write-file foo <( sed 's/bar/baz/' foo ) |
Hi @salmankhilji, can we summarize what you're proposing as follows?
|
I'm afraid not. I suppose mentioning issue #626 was a mistake as that had to do with delta not working correctly with fds. In summary if In the repro steps filed above, we write the word
we expect to see side-by-side output similar to the one shown within the screenshot towards the end. That is because we clean up the repo and the However, if you look closely, I manually ran the Git hook by hand at the very end within the screenshot. The second to the last execution was from within the Git hook itself and incorrectly produced the output |
Hi @salmankhilji -- I know that you have gone to a lot of trouble explaining the situation with git hooks above, but I feel that it must be possible to simplify this! After all, delta is a command line executable whose inputs are (off the top of my head):
Can you provide a minimal self-contained example of a delta command that produces incorrect output or an incorrect exit code? I think that it should be possible to do this without needing to consider delta in the context of a git hook, right? Just a one line command supplying arguments and/or stdin and/or env vars.
The point of my example wasn't anything related to file descriptors or process substitution -- I just used
What I'm trying to do here is distill what you wrote above down to its essence:
diff -u "${dst}" "${tmp}" | delta --side-by-side --paging never --width "$(tput cols)"
|
Take 2: this is as simple as I can make it.
The expected output in Step 4 should be exactly the same as Step 3. The script also sets up the #!/bin/bash
if delta bar bar >/dev/null; then
echo SAME
else
echo DIFFERENT
fi
if delta bar baz >/dev/null; then
echo SAME
else
echo DIFFERENT
fi When Git runs the script, the environment is different. I manually recreated the exact same environment, and, disappointingly, the results are still the same:
(This is essentially Step 3 above with the environment that Git runs the hooks within.) |
Thanks, I can reproduce that. Nice mystery! It can't be too complicated what's going wrong there but not immediately obvious to me. I'll look into it if you don't get to it first (e.g. simply by putting print statement in the Rust code). |
This occurs because delta only operates in diff mode ( Line 134 in 1403fe2
Thus a minimal reproduction is
I haven't thought through yet whether this should be changed. |
#995 changes things so that delta runs in "diff mode" iff it receives two positional arguments (previously it only tried diff mode when its input was a tty). Can anyone think of any way this will go wrong / why I was doing it the previous way? The new way feels more correct: if there are two positional arguments then the author must have intended diff mode. When using delta as a git pager, or a viewer for input on stdin, I can't think of a situation where the user would supply two positional arguments -- anyone else? We need to be slightly careful since it works today, so the change would break behavior for anyone who's using it today for some reason. |
Thanks for the fix! For my educational purposes, I'm curious as how the fix, which is based on the number of arguments passed, would compare with checking for certain |
I'd say: We don't want |
In other words, delta should be a normal Unix executable whose behaviour is predictable given its arguments and standard input. Its behavior shouldn't depend on whether it has been invoked by git, or is involved a git hook. (delta does violate that a bit! But hopefully justifiably.) |
@dandavison this timely fix unbeknownst to me saved a proof of concept I implemented yesterday. Details: https://www.reddit.com/r/neovim/comments/tfcmyh/function_for_creating_local_diffs_in_a_scratch Thanks! |
Excellent, glad to hear that! The special behavior based on tty detection wasn't the right thing to be doing here; I'm not sure why I was doing it :/ |
Within a git hook, pass two different files to
delta
. The exit code incorrectly indicates that the files are the same. If the same hook script is run manually, then it works correctly.Steps to Reproduce
write-file
routine takes two arguments. The first argument is the name of the destination file that we want to write. The second argument is a source file that we want to write to the destination. The routine usesdelta
to compare the contents of the files. If the destination file already exists and the contents of the file are different, then we ask for confirmation to overwrite an existing file. (Of course, the spew fromdelta
is helpful in deciding if we want to overwrite the existing file.)mkdir my_repo
cd $_
echo bar >foo
git init
git add .
git commit -m "initial commit"
cp ../delta-bug.bash .git/hooks/post-checkout
cat foo
git checkout -f
In Step 2, we wrote
bar
to the file namedfoo
and committed the file in Step 8.In Step 9, we then set up a
post-checkout
hook so our hook would get called after every checkout.In Step 11, we expect delta to show that we are overwriting the contents
bar
withbaz
(Notice that oursed
command in the script replacesbar
withbaz
. However, we observe thatdelta
incorrectly thinks that the files are the same because of the following in the transcript below:We then manually run the Git hook. We observe that manually running the Git hook works as expected.
Screenshot
Version
$ delta --version
delta 0.12.0
The text was updated successfully, but these errors were encountered: