fix: report a missing git instead of an unhandled FileNotFoundError - #620
Open
Eljees wants to merge 2 commits into
Open
fix: report a missing git instead of an unhandled FileNotFoundError#620Eljees wants to merge 2 commits into
Eljees wants to merge 2 commits into
Conversation
…achmann1234#303) subprocess.Popen sits outside the try in command_runner.execute, so when the executable itself is missing the FileNotFoundError escapes raw. Both entry points call GitPathTool.set_cwd before their own error handling begins -- diff_quality_tool.main already has `except OSError -> LOGGER.error -> return 1` further down, it simply never gets the chance to run -- so `diff-cover` and `diff-quality` print a traceback when git is not installed. Add ExecutableNotFoundError as a subclass of CommandError, so anything that already catches CommandError keeps working, and raise it from execute() only for the FileNotFoundError that Popen throws. A command that runs and then fails is untouched: tests/test_integration.py requires CommandError to escape main() in that case, and it still does. Both main() functions now wrap set_cwd and report the message through LOGGER.error, returning 1. This is the same class of fix as Bachmann1234#380 for Bachmann1234#378, which covered the "the linter is not installed" path through run_command_for_code; the "git is not installed" path through execute was left as it was.
CodeQL flagged `assert "https://git-scm.com/" in message` as py/incomplete-url-substring-sanitization. The rule is about URL checks done with substring containment, and a test assertion is written the same way as the pattern it warns about. Import GIT_INSTALL_URL and assert on the whole trailing sentence instead, which is a stricter assertion anyway, and use the constant for the negative case as well.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #303.
Problem
With git not installed (or not on
PATH), both entry points end in a traceback:Two things are going on:
command_runner.executeputssubprocess.Popen(...)outside thetry. Thetryonly coversprocess.communicate(), so theFileNotFoundErrorthatPopenraises when the executable does not exist escapes untouched.
Both
main()functions callGitPathTool.set_cwd(directory)before their ownerror handling starts.
diff_quality_tool.mainalready hasand
FileNotFoundErroris anOSError— the handler for this case is alreadywritten, the failure just happens a few lines above the block that would catch it.
diff_cover_tool.mainhas no handling at that point at all.Precedent
This is the same class of defect as #378 ("Running diff-quality with a tool which is
not installed gives FileNotFoundError rather than helpful message"), fixed by #380.
That fix landed in
run_command_for_codeand covers "the linter is not installed";the "git is not installed" path goes through
executeand was left as it was.Fix
ExecutableNotFoundError(CommandError)— a subclass, sogit_diff.py'sexcept CommandErrorand every other existing handler keep working unchanged.execute()raises it for theFileNotFoundErrorfromPopenonly, with the messageImprove error reporting when "git" is not found #303 asked for. The git-scm.com link is added only when the missing binary is
git.main()functions wrapset_cwdand report throughLOGGER.error, returning 1.The narrow catch is deliberate
My first version caught
CommandErrorwholesale inmain(), and two of your existingtests rejected it —
tests/test_integration.py::TestDiffCoverIntegration::test_git_diff_errorand::TestDiffQualityIntegration::test_git_diff_error_diff_quality. Both set up a git thatruns and exits 1, and both require
CommandErrorto propagate out ofmain(). That isthe project saying "the command ran and failed" and "there is no command to run" are
different things, which is where the separate subclass came from. Both tests pass here.
Tests
tests/test_command_runner_missing_executable.py, six cases:execute(), a non-gitbinary getting no git link, the subclass relationship, both
main()functions, andwhich is green on both sides — that is what shows the error semantics did not move.
Verification
main(e34eec3, release 10.5.0), whole suiteFileNotFoundErrorescapedexecute()and bothmain()sCommandError— silent, as it must bemainblack,isort,doc8)ruffandpylintarecontinue-on-error: trueinverify.yaml, so I checked theblocking three;
diff-qualityon this diff reports 100% for pyflakes.