-
Notifications
You must be signed in to change notification settings - Fork 142
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
Reduce deferred execution #326
Conversation
edcfa7e
to
def8a51
Compare
The failing CI test is due to #327 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sandr01d Great work, thanks for starting on this! I would propose implementing this change for all forgit functions within this single PR and move all bugfixing stuff to later PRs. What do you think?
Since there haven't been any objections so far, I'm moving this forward and started refactoring the other functions. If anyone wants to jump in feel free to do so and send a PR to this branch. |
A note regarding I'll keep collecting implementation details as comments here, so we can combine them in a commit message when we merge this. |
@sandr01d Thanks a lot for keeping this going! I'll probably have some time by the end of next week and am motivated to take over some functions as well. I will switch forgit to this branch for my daily work from now on in order to find regressions early while we're going. @cjappl @wfxr You maybe too? |
f37b74c
to
6d91c61
Compare
Notes to
|
I found a way to correctly use the |
c299aaa
to
fdd7966
Compare
So I came to the conclusion that we just have to disable the specific shellcheck for passing And I think I have finished |
Your code looks good to me. I gave it a quick test and everything works as expected so far. The ability to pass in files is very neat, great work! git log "${graph[@]}" --color=always --format="$log_format" ${FORGIT_LOG_GIT_OPTS:+$FORGIT_LOG_GIT_OPTS} "$@" ${_forgit_emojify:+$_forgit_emojify} But that is probably just hiding the issue and not doing anything better. Word splitting is intentional here so from my perspective disabling shellcheck as you do is fine. I think we should probably disable globbing and restore it after the line. |
@carlfriedrich I noticed you changed the default of |
Actually I did not change the default value, I just switched the logic of evaluation and transferred the default value to the new variable
Yes, that's definitley just a workaround and would clutter the code unnecessarily IMO. Disable globbing sounds reasonable. Maybe we could parse |
I did, but it was implicitly true by default before your change. Previously we only removed the
That does sound like a good approach to me. |
Oh I see! Sorry, that was a misunderstanding. Thanks for correcting it! |
920509e
to
8899354
Compare
@sandr01d I refactored most of |
Works for me |
Notes regarding d23ec19: I've exposed the new functions |
@sandr01d Thanks a lot for your effort on pushing this forward! I haven't had time for a detailed review, yet (might find time for it next week).
Yes, this is correct, forgit always runs in bash.
This will not run on MacOS's bash, unfortunately, because MacOS uses ancient bash version 3.2.57 (I think due to licensing issues). Is there a different way to implement this? |
Ah, I see thanks for the clarification. We could of course just set the IFS, parse all the arrays and unset it again like this: # set IFS
${IFS+"false"} && unset old_IFS || old_IFS="$IFS"
# parse all the arrays here
_forgit_log_git_opts=()
IFS=" " read -r -a _forgit_log_git_opts <<< "$FORGIT_LOG_GIT_OPTS"
_forgit_diff_git_opts=()
IFS=" " read -r -a _forgit_diff_git_opts <<< "$FORGIT_DIFF_GIT_OPTS"
# ...
# reset IFS
${old_IFS+"false"} && unset IFS || IFS="$old_IFS" But this is neither reusable nor pretty. I am not aware of a way to make this work in a function without a nameref, but I will do further research. I probably won't have time to work on it this week. In case you come up with something, let me know or feel free to push it to this branch. |
Forgit allows specifying git options in environment variables that are passed along to the individual git commands. We currently treat those as strings. This commit adds a _forgit_parse_array function and uses it to parse all such environment variables into arrays instead. This will allow us to get rid of deferred code, since we can pass the parsed arrays directly to the git commands and don't have to rely on eval.
Removes the deferred code that is used for creating the fzf preview functions and replaces it with _forgit_*_preview functions instead. These functions are exposed as forgit commands so they can be invoked from the fzf subshell. We split the exposed commands into public_commands and private_commands. The only difference between them is that public_commands are mentioned in the help text. This commit changes the flags variable in _forgit_blame from a string to an array. This is necessary to allow the flags to be passed to _forgit_blame_preview as individual arguments.
We often used deferred code to encapsulate git commands and make them reusable. This change removes deferred code for git commands and replaces it with functions instead. Some of the deferred code was used with xargs, which executes it on a subshell. To avoid having to expose the new git functions the same way we do with the preview functions, the usage of xargs in these cases is replaced with either a loop or a single command when possible.
We used to have a variable that was either undefined or contained a piece of deferred code that piped input through emojify when present on the system. To remove the deferred code here, this commit replaces the _forgit_emojify variable with a function that either pipes the input through emojify or through cat, depending on whether emojify is present.
We were using deferred code in git commands in some places without any reason. Each of these deferred code snippets was only executed a single time, so we can replace them with regular git commands. This commit changes how we handle the FORGIT_LOG_GRAPH_ENABLE environment variable. We previously used a variable that stored the --graph flag as a string and unset it, when FORGIT_LOG_GRAPH_ENABLE was set to anything other than true. We now create an empty array and add the --graph flag to it when FORGIT_LOG_GRAPH_ENABLE is unset or true. Doing it this way allows us to build a command line without having to use eval. The outcome is the same as before.
In _forgit_log and _forgit_enter it is possible to diff a single commit/file by pressing enter. We used to store the code that executes the diffs in variables and passed it to fzf as deferred code. This refactor reduces the amount of deferred code by using functions instead of variables.
_forgit_diff and _forgit_add allow editing the currently previewed file in the EDITOR. This used to be handled entirely using deferred code. This commit replaces the deferred code and binds the commands to functions instead.
Many commands allow copying the commit hash or stash name of the current selection to the clipboard. We previously used deferred code to do so. This commit replaces the deferred code and binds these commands to functions instead.
We used to store code that extracts the commit hash from a line in a variable. This commit replaces this variable with a function.
…l to _forgit_get_single_file_from_add_line
In some cases we need to pass multiple files to preview functions. These files are treated as a single string that is evaluated by fzf and passed on to our preview functions as individual arguments. This commit introduces a _forgit_quote_files function that ensures the resulting arguments are quoted properly.
5119c45
to
72cdf29
Compare
Alright, I've rebased on top of master now and we're ready to start testing. Let me know when whether you find any issues. In regards to merging, I would strongly recommend we merge this PR (without squashing it) once it's tested. This way, we can be absolutely certain that the final state resembles exactly what we've been testing and we avoid having to rebase and merge 11 PRs and any mistakes that might arise by doing so. |
Reporting back on mac, using fish shell. @sandr01d Adding files
Reset head
Git log
Diffing files
Git ignore
Checkout file
Checkout branch
Delete branch
Git clean
Git stash show/git stash push
cherry pick
Rebase
Fixup
Checkout commit
Revert commit
Blame
EDIT: THIS WORKS FINE! I had a configuration issue where I was using a non-standard FZF_DEFAULT_COMMAND
Original text below:
Checkout tag
Environment variables
|
Overall I give this a thumbs up on mac and fish on the basis of this "quick smoke test" this was all of the tests I could think to run, and everything seems generally solid. I will continue playing with it and using it as my daily driver. Let me know if you saw any test cases I missed or something I should spend time focusing on. Great work @sandr01d , for such an insane code review very few regressions as far as I can tell |
@cjappl First of all, thanks for the in depth testing!
I can reproduce this in this branch, but so can I in the master branch, so not a regression. Definitively a bug though, I agree that we should open a separate issue.
I think the easiest way to test this is to create a local repository, add a few files and create a few commits, then do a few changes, add them and use
This one I can not reproduce. I've checked our implementation on how we generate the file list for this command and it is by simply executing file=$(FZF_DEFAULT_OPTS="$opts" fzf --preview="$FORGIT blame_preview {} ${flags[*]}") What happens when you execute
I agree. Syntax highlighting would be super useful here.
Would be great if you could play around the environment variables we allow customizing the git commands with, such as |
Filed here #369 For the future, definitely does not have to be taken on until this big review lands
Good intuition. This was a config issue on my side. Fixing my config fixed the issue, this is not a regression or anything to worry about.
For the future, definitely does not have to be taken on until this big review lands
Will put some time on my calendar to do this tomorrow, same with git fixup. I have updated my big summary comment above with this info as well. |
@sandr01d You're probably right, that seems to be the safest way. I think GitHub should actually automatically close the 11 other PRs when we merge this, since they contain the same commits as in this branch. @cjappl Great test work, thanks a lot! I will do some testing during the next days as well. |
I have completed my testing and deem this good to ship on fish shell and macOS. My complete testing is in a previous comment. (including test cases I didn't do before. Let me know if there is anything else people can think to test that I have missed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚀 🎸 🔥
Since we did not find any new bugs I'm planning to merge this on Sunday when I don't hear any objections. |
@sandr01d Didn't have time for testing yet, but if you guys did not find anything then go for it! 🚀 |
Reintroduces the usage of eval for evaluating pagers. We removed all usage of eval with #326, which broke code defined by users in the $FORGIT_*_PAGER environment variables and git pagers. In this particular case, eval does exactly what we want, since we do want to execute code that is defined by the user outside of forgit.
Check list
Description
We've removed deferred code and replaced it with functions instead. This includes all usages of
eval
. There are four different types of functions we've added:_forgit_add_preview
) that are responsible for thefzf
preview_forgit_edit_add_file
) that are responsible for editing files with your$EDITOR
from within forgit functions_forgit_git_add
) that make simple git commands reusable_forgit_yank_sha
or_forgit_quote_files
) that were created either out of necessity or implement functions that were previously stored as deferred code in variables.We've exposed some of these functions as forgit commands. This includes all preview and edit functions and some of the utility functions, so they can be invoked from
fzf
's subshell. Additionaly some of the git functions were exposed to make it possible to use them withxargs
.In some places were we used deferred code before, we now make use of arrays to allow building commands while having control over globbing and word splitting. We do this for all the git opts environment variables, such as
FORGIT_ADD_GIT_OPTS
.In places were we could not avoid deferred execution (e.g. when having to pass arguments to preview functions as we do in
_forgit_log
) we ensured variables are quoted properly. Variables not quoted properly were one of the main source of bugs previously.Implementation Details
General
We now make use of the
-a
flag withread
which does exist in bash, but not in zsh. This is fine, since we always use bash for executing /bin/git-forgit since #241.gbl
It is now possible to pass more than one argument to
gbl
(e.g.gbl --color-by-age --color-lines
). This was a bug previously and the fix is a side effect of us now using an array for the flags instead of relying oneval
.grc
I've removed passing the files variable to the preview, as well as passing parameters to the git log command with
$*
. These were creating issues in the new implantation and they were actually always empty, because_forgit_revert
exits early when any arguments are passed. I copied them by mistake when I implemented_forgit_revert
, they did never actually serve any purpose.glo
,grb
&gfu
File arguments are now parsed using a different approach using
_forgit_quote_files
. The only difference in behavior to thesed
command we had previously is that the string that is printed out has each file name wrapped in single quotes, so they can be used safely without having to worry about globbing or word splitting. There is no need to quote this string when passing it to a preview function, because the individual file names inside it are already properly quoted. I changed the files variable names toquoted_files
to indicate this.Type of change
Test environment