Skip to content

Improve performance of discarding many files#5407

Open
stefanhaller wants to merge 8 commits intomasterfrom
speed-up-discarding-files
Open

Improve performance of discarding many files#5407
stefanhaller wants to merge 8 commits intomasterfrom
speed-up-discarding-files

Conversation

@stefanhaller
Copy link
Collaborator

When selecting a directory containing many changed files, or when range-selecting many changed files, and then discarding them, this could be so slow that lazygit appeared to hang; especially since there was no UI feedback (e.g. a spinning status message).

This PR improves the performance greatly by batching the individual git calls into a single one if possible. It still doesn't add UI feedback though, hoping that the operation is now fast enough that it isn't needed.

While we're at it, we fix a bug that would cause "Discard unstaged changes" to discard more than just the visible files when filtering by path.

Fixes #4581.

This makes it mockable for tests, and is consistent with other uses in this
file.
Previously it would only check that *if* removeFile was called, the passed
argument was the expected one; but it didn't check whether it was called at all.
Improve this by recording the file names that are removed, and checking them at
the end of each scenario.

This is going to be even more important for the tests that we are about to add
in the next commit, because for those there can be several calls to removeFile
in a single scenario.
We have integration tests for this functionality, but those only test the
behavior, not the performance. In these unit tests you can see that we make
individual calls to git checkout and git reset for each file, which is very slow
when there are lots of files.
When discarding a directory, we only want to discard those files that are
visible in the current filter view. The tests show that this already works
correctly for discarding all changes, but it doesn't for discarding only
unstaged changes: in this case, untracked files are handled correctly, but
changes to tracked files are discarded without respecting the filter.
Useful when we need to call git with potentially tons of arguments that might
exceed the OS' command-line length limit.
Previously it would iterate over all changed files and call git checkout or git
reset for each one, which can take forever if there are hundreds or thousands of
files. Now it batches these into a single command if possible (taking care of
still passing the individual path names to the git call rather than just the
directory, which is necessary for making it work correctly when filtering --
this was actually broken for the "Discard unstaged changes" command, which is
fixed here).
This is probably the less severe case, but it could still be an issue for people
who have many modified top-level files they want to discard, and have
showRootItemInFileTree set to false; they could select all those files by
pressing 'v' and '>'.
@codacy-production
Copy link

Coverage summary from Codacy

See diff coverage on Codacy

Coverage variation Diff coverage
Report missing for ec7d6b41 93.30%
Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (ec7d6b4) Report Missing Report Missing Report Missing
Head commit (9f2a987) 60678 53134 87.57%

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#5407) 179 167 93.30%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

See your quality gate settings    Change summary preferences

Footnotes

  1. Codacy didn't receive coverage data for the commit, or there was an error processing the received data. Check your integration for errors and validate that your coverage setup is correct.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Discard changes can be very slow

1 participant