Skip to content
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

Throw on non-zero exit code and on stderror output #9056

Merged
merged 2 commits into from
Jul 31, 2021

Conversation

mstv
Copy link
Member

@mstv mstv commented Apr 8, 2021

Fixes #6527
Fixes #8263
Fixes #8632
Closes #8906 as obsolete
Closes #8961 as obsolete

Proposed changes

  • Throw ExternalOperationException if a started process exits with a non-0 exit code or if the process printed output to StandardError
  • Suppress this exception for commands whose errors are handled

Screenshots

Before

After

Test methodology

  • manual
  • existing NUnit tests

Test environment(s)

  • Git Extensions 33.33.33
  • Build 3bed1c8
  • Git 2.27.0.windows.1 (recommended: 2.30.0 or later)
  • Microsoft Windows NT 10.0.19042.0
  • .NET Framework 4.8.4300.0
  • DPI 96dpi (no scaling)

✒️ I contribute this code under The Developer Certificate of Origin.

@ghost ghost assigned mstv Apr 8, 2021
@mstv mstv marked this pull request as draft April 8, 2021 00:33
@gerhardol
Copy link
Member

There are some more situations where errors are handled, where IsGitErrorMessage() parses the output.
Those should be changed though
(as well as ExitCode == 0 should be replaced with ExitedSuccessfull)

Some situations like "describe" and in RevParse() (that should have --quiet --verify and check status anyway) are handled in this PR.

diff --git a/GitCommands/Git/GitModule.cs b/GitCommands/Git/GitModule.cs
index 6aace..9124d 100644
--- a/GitCommands/Git/GitModule.cs
+++ b/GitCommands/Git/GitModule.cs
@@ -2507,14 +2507,12 @@ public IReadOnlyList<GitItemStatus> GetTreeFiles(ObjectId commitId, bool full)
             bool excludeAssumeUnchangedFiles = true, bool excludeSkipWorktreeFiles = true,
             UntrackedFilesMode untrackedFiles = UntrackedFilesMode.Default)
         {
-            var output = _gitExecutable.GetOutput(
-                GitCommandHelpers.GetAllChangedFilesCmd(excludeIgnoredFiles, untrackedFiles));
-
-            List<GitItemStatus> result = _getAllChangedFilesOutputParser.Parse(output).ToList();
-            if (IsGitErrorMessage(output))
+            var exec = _gitExecutable.Execute(GitCommandHelpers.GetAllChangedFilesCmd(excludeIgnoredFiles, untrackedFiles));
+            List<GitItemStatus> result = _getAllChangedFilesOutputParser.Parse(exec.StandardOutput).ToList();
+            if (!exec.ExitedSuccessfully)
             {
                 // No simple way to pass the error message, create fake file
-                result.Add(createErrorGitItemStatus(output));
+                result.Add(createErrorGitItemStatus(exec.StandardError));
             }
  
             if (!excludeAssumeUnchangedFiles || !excludeSkipWorktreeFiles)

Copy link
Member

@RussKie RussKie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 with few comments

GitCommands/Git/Executable.cs Outdated Show resolved Hide resolved
GitCommands/Git/Executable.cs Outdated Show resolved Hide resolved
GitUI/BranchTreePanel/RepoObjectsTree.cs Outdated Show resolved Hide resolved
Copy link
Member

@gerhardol gerhardol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+0
In general very much needed, good time to add this now.
Will use myself.
(only briely looked at the code now.)

Edit: Missing Working directory for exceptions
Also, the exception message do not have to be displayed in the log part, details is enough
(not checked if this PR really changed this)

I get an exception now when starting up, some dashboard repo does not exist I assume

"--pretty=format:\"%T\"",
"--max-count=1"
"--max-count=1",
$"-- {stashName}^3"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-- separates paths, stashNane is a ref
The order is correct now though

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The commit message contains the git error:

Fixup git arguments for GetStashDiffFiles

fatal: ambiguous argument 'stash@{0}^3': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions

sounds a bit confusing to me; but works well

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stashName is not a path, so it should not be separated with --

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without "--", git outputs the above fatal error with non-zero exit code.

!string.IsNullOrEmpty(secondRevision) &&
!string.IsNullOrEmpty(firstRevision) &&
!secondRevision.IsArtificial() &&
!firstRevision.IsArtificial()
? GitCommandCache
: null;

var patch = _gitExecutable.GetOutput(
bool nonZeroGitExitCode = firstId == ObjectId.WorkTreeId && secondId is not null && !isTracked;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should not be here but at the caller (may check arguments).
!isTracked cannot use git-diff (regardless of first/second commit).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

repro:

  • create a new file (untracked)
  • select Working directory, then Ctrl+click the checked out commit, which turns the added (exit code 0) into a removed file from this perspective (exit code 1)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The caller should not request this information, it is meaningless.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to have at least a comment explaining this. It is not obvious what this check is and why it is needed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should not be here but at the caller (may check arguments).
!isTracked cannot use git-diff (regardless of first/second commit).

The caller should not request this information, it is meaningless.

Explain it in other words, please.

It is not obvious what this check is and why it is needed.

Would you better understand it with nonZeroGitExitCodeExpected?
It is used once - in the next statement.

@mstv
Copy link
Member Author

mstv commented Apr 20, 2021

I get an exception now when starting up, some dashboard repo does not exist I assume

cannot reproduce

@mstv
Copy link
Member Author

mstv commented Apr 20, 2021

Missing Working directory for exceptions

How did you get this?
Usually the directory is there (renamed to just "Directory":

exception with wdir

@gerhardol
Copy link
Member

gerhardol commented Apr 20, 2021

Failure in repo without tags (similar to git-describe).
The problem during startup too.

Edit: fixed negated check

       public IReadOnlyList<IGitRef> GetRefs(GetRefsEnum getRef)
        {
            // We do not want to lock the repo for background operations.
            // The primary use of 'noLocks' is to run git-status the commit count as a background operation,
            // but to run the same in a foreground for FormCommit.
            //
            // Assume that all GetRefs() are done in the background, which may not be correct in the future.
            const bool noLocks = true;

            ArgumentString cmd = GitCommandHelpers.GetRefsCmd(getRef, noLocks, AppSettings.RefsSortBy, AppSettings.RefsSortOrder);
            ExecutionResult exec = _gitExecutable.Execute(cmd, throwOnErrorOutput: false);
            return exec.ExitedSuccessfully
                ? ParseRefs(exec.StandardOutput)
                : new List<IGitRef>();
        }

@gerhardol
Copy link
Member

gerhardol commented Apr 21, 2021

I have experienced a few more situations where Git exists with non-zero.
Pushed to a private branch, I believe you can pick them from there
(if you want a motivation let me know, I logged with stack trace while working today and have not investigated the details).

Edit: I also get warnings like git-diff --check is enabled, not recreated yet.

@mstv
Copy link
Member Author

mstv commented Apr 21, 2021

I have experienced a few more situations where Git exists with non-zero.
Pushed to a private branch, I believe you can pick them from there

Thank you. I have cherry-picked them to my work branch all. I will look at the details later.

@mstv
Copy link
Member Author

mstv commented Apr 22, 2021

(if you want a motivation let me know, I logged with stack trace while working today and have not investigated the details)

Yes, please, especially the exception text taken from StandardError. I find warnings or errors from these commands quite surprising.

@gerhardol
Copy link
Member

One more push with a fix for git-diff with core.safecrlf

@gerhardol
Copy link
Member

I still have an exception at startup. Just pushed a commit to be able to work.

The sidepanel is init without the working directory is set. That should be disallowed for basically all commands.
Have not found what causes this.

image

@mstv
Copy link
Member Author

mstv commented Apr 24, 2021

The sidepanel is init without the working directory is set. That should be disallowed for basically all commands.

Good catch! This might also be the cause why some of the ROT tests work unstable (and have been disabled).

@mstv
Copy link
Member Author

mstv commented Apr 29, 2021

(if you want a motivation let me know, I logged with stack trace while working today and have not investigated the details)

Yes, please, especially the exception text taken from StandardError. I find warnings or errors from these commands quite surprising.

I could not reproduce these exceptions. Could you provide details for the first four !fixup commits, please?

@gerhardol
Copy link
Member

gerhardol commented Apr 29, 2021

Added two commits where error is OK (this was the remaining fatal: reference I saw too)
Maybe all GetOutputLines() should be ignored

The commit messages has descriptions
(Some more time to explain the other four)

@gerhardol
Copy link
Member

42e27c7

Line patches exit with error and error text if patches cannot be applied
To use Execute() instead of GetOutput() the input array need to be made to a stream.

@gerhardol
Copy link
Member

git-mergetool can exit with error if user do not complete the merge
(pushed as well but my private branch is getting out of date)

diff --git a/GitCommands/Git/GitModule.cs b/GitCommands/Git/GitModule.cs
index e6ca8..6f2dd 100644
--- a/GitCommands/Git/GitModule.cs
+++ b/GitCommands/Git/GitModule.cs
@@ -880,7 +880,7 @@ public void RunMergeTool(string? fileName = "", string? customTool = null)
                 { !string.IsNullOrWhiteSpace(fileName), "--" },
                 fileName.ToPosixPath().QuoteNE()
             };
-            using var process = _gitExecutable.Start(args, createWindow: true);
+            using var process = _gitExecutable.Start(args, createWindow: true, throwOnErrorOutput: false);
             process.WaitForExit();
         }
 

Copy link
Member

@RussKie RussKie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@ghost
Copy link

ghost commented Jul 28, 2021

Hello @RussKie!

Because you've told me to reset the custom auto-merge settings, I'll use the configured settings for this repository when I'm merging this pull request.

@RussKie
Copy link
Member

RussKie commented Jul 28, 2021

I have few questions, disabling the auto-merge for now.

@RussKie RussKie added the 📭 needs: author feedback More info/confirmation awaited from OP; issues typically get closed after 30 days of inactivity label Jul 28, 2021
@ghost ghost removed the 📭 needs: author feedback More info/confirmation awaited from OP; issues typically get closed after 30 days of inactivity label Jul 30, 2021
@RussKie RussKie merged commit cea231d into gitextensions:master Jul 31, 2021
@ghost ghost added this to the 3.6 milestone Jul 31, 2021
@mstv mstv deleted the fix/6527_git_errors branch July 31, 2021 16:52
gerhardol added a commit to gerhardol/gitextensions that referenced this pull request Aug 12, 2021
gerhardol added a commit to gerhardol/gitextensions that referenced this pull request Aug 12, 2021
gerhardol added a commit to gerhardol/gitextensions that referenced this pull request Aug 12, 2021
mstv added a commit to mstv/gitextensions that referenced this pull request Aug 12, 2021
- Ignore StandardError output
- Use it only as exception text on non-zero exit code

makes gitextensions#9056 less intercepting, fixes gitextensions#9462
gerhardol pushed a commit to gerhardol/gitextensions that referenced this pull request Sep 8, 2021
- Ignore StandardError output
- Use it only as exception text on non-zero exit code

makes gitextensions#9056 less intercepting, fixes gitextensions#9462
gerhardol pushed a commit to gerhardol/gitextensions that referenced this pull request Sep 9, 2021
- Ignore StandardError output
- Use it only as exception text on non-zero exit code

makes gitextensions#9056 less intercepting, fixes gitextensions#9462

Except for the actual changes in Executable.cs, this is just renaming
the argument to match the changed functionality.
gerhardol pushed a commit to gerhardol/gitextensions that referenced this pull request Sep 9, 2021
- Ignore StandardError output
- Use it only as exception text on non-zero exit code

makes gitextensions#9056 less intercepting, fixes gitextensions#9462

Except for the actual changes in Executable.cs, this is just renaming
the argument to match the changed functionality.
gerhardol added a commit that referenced this pull request Sep 9, 2021
- Ignore StandardError output
- Use it only as exception text on non-zero exit code

makes #9056 less intercepting, fixes #9462

Except for the actual changes in Executable.cs, this is just renaming
the argument to match the changed functionality.

Co-authored-by: Michael Seibt <mstv@gmx.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants