Skip to content

Commit 23d4c9c

Browse files
authored
Merge pull request #1985 from tyrielv/tyrielv/auth-exit-code
Add unique exit code for mount authentication failures
2 parents c585068 + 43681f7 commit 23d4c9c

8 files changed

Lines changed: 59 additions & 11 deletions

File tree

GVFS/GVFS.Common/GVFSPlatform.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System;
55
using System.Collections.Generic;
66
using System.ComponentModel;
7+
using System.Diagnostics;
78
using System.IO;
89
using System.IO.Pipes;
910

@@ -51,7 +52,7 @@ public static void Register(GVFSPlatform platform)
5152
/// This method should only be called by processes whose code we own as the background process must
5253
/// do some extra work after it starts.
5354
/// </remarks>
54-
public abstract void StartBackgroundVFS4GProcess(ITracer tracer, string programName, string[] args);
55+
public abstract Process StartBackgroundVFS4GProcess(ITracer tracer, string programName, string[] args);
5556

5657
/// <summary>
5758
/// Adjusts the current process for running in the background.

GVFS/GVFS.Common/Git/GitAuthentication.cs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,8 @@ public bool TryInitialize(ITracer tracer, Enlistment enlistment, out string erro
200200
enlistment,
201201
new RetryConfig(),
202202
out _,
203-
out errorMessage);
203+
out errorMessage,
204+
out _);
204205
}
205206

206207
/// <summary>
@@ -217,7 +218,8 @@ public bool TryInitializeAndQueryGVFSConfig(
217218
Enlistment enlistment,
218219
RetryConfig retryConfig,
219220
out ServerGVFSConfig serverGVFSConfig,
220-
out string errorMessage)
221+
out string errorMessage,
222+
out bool isAuthFailure)
221223
{
222224
if (this.isInitialized)
223225
{
@@ -226,6 +228,7 @@ public bool TryInitializeAndQueryGVFSConfig(
226228

227229
serverGVFSConfig = null;
228230
errorMessage = null;
231+
isAuthFailure = false;
229232

230233
using (ConfigHttpRequestor configRequestor = new ConfigHttpRequestor(tracer, enlistment, retryConfig))
231234
{
@@ -253,19 +256,26 @@ public bool TryInitializeAndQueryGVFSConfig(
253256

254257
if (!this.TryCallGitCredential(tracer, out errorMessage))
255258
{
259+
isAuthFailure = true;
256260
tracer.RelatedWarning("{0}: Credential fetch failed: {1}", nameof(this.TryInitializeAndQueryGVFSConfig), errorMessage);
257261
return false;
258262
}
259263

260264
this.isInitialized = true;
261265

262266
// Retry with credentials using the same ConfigHttpRequestor (reuses HttpClient/connection)
263-
if (configRequestor.TryQueryGVFSConfig(true, out serverGVFSConfig, out _, out errorMessage))
267+
HttpStatusCode? retryHttpStatus;
268+
if (configRequestor.TryQueryGVFSConfig(true, out serverGVFSConfig, out retryHttpStatus, out errorMessage))
264269
{
265270
tracer.RelatedInfo("{0}: Config obtained with credentials", nameof(this.TryInitializeAndQueryGVFSConfig));
266271
return true;
267272
}
268273

274+
if (retryHttpStatus == HttpStatusCode.Unauthorized || retryHttpStatus == HttpStatusCode.Forbidden)
275+
{
276+
isAuthFailure = true;
277+
}
278+
269279
tracer.RelatedWarning("{0}: Config query failed with credentials: {1}", nameof(this.TryInitializeAndQueryGVFSConfig), errorMessage);
270280
return false;
271281
}

GVFS/GVFS.Common/ReturnCode.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@ public enum ReturnCode
1111
UnableToRegisterForOfflineIO = 6,
1212
DehydrateFolderFailures = 7,
1313
MountAlreadyRunning = 8,
14+
AuthenticationError = 9,
1415
}
1516
}

GVFS/GVFS.Mount/InProcessMount.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,11 @@ private void MountWithLockAcquired(EventLevel verbosity, Keywords keywords)
133133
Stopwatch sw = Stopwatch.StartNew();
134134
ServerGVFSConfig config;
135135
string authConfigError;
136+
bool isAuthFailure;
136137

137138
if (!this.enlistment.Authentication.TryInitializeAndQueryGVFSConfig(
138139
this.tracer, this.enlistment, this.retryConfig,
139-
out config, out authConfigError))
140+
out config, out authConfigError, out isAuthFailure))
140141
{
141142
if (this.cacheServer != null && !string.IsNullOrWhiteSpace(this.cacheServer.Url))
142143
{
@@ -145,7 +146,9 @@ private void MountWithLockAcquired(EventLevel verbosity, Keywords keywords)
145146
}
146147
else
147148
{
148-
this.FailMountAndExit("Unable to query /gvfs/config" + Environment.NewLine + authConfigError);
149+
this.FailMountAndExit(
150+
isAuthFailure ? ReturnCode.AuthenticationError : ReturnCode.GenericError,
151+
"Unable to query /gvfs/config" + Environment.NewLine + authConfigError);
149152
}
150153
}
151154

GVFS/GVFS.Platform.Windows/WindowsPlatform.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ public override string GetLogsDirectoryForGVFSComponent(string componentName)
137137
return WindowsPlatform.GetLogsDirectoryForGVFSComponentImplementation(componentName);
138138
}
139139

140-
public override void StartBackgroundVFS4GProcess(ITracer tracer, string programName, string[] args)
140+
public override Process StartBackgroundVFS4GProcess(ITracer tracer, string programName, string[] args)
141141
{
142142
string programArguments = string.Empty;
143143
try
@@ -156,6 +156,7 @@ public override void StartBackgroundVFS4GProcess(ITracer tracer, string programN
156156
Process executingProcess = new Process();
157157
executingProcess.StartInfo = processInfo;
158158
executingProcess.Start();
159+
return executingProcess;
159160
}
160161
catch (Exception ex)
161162
{

GVFS/GVFS.UnitTests/Mock/Common/MockPlatform.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using GVFS.UnitTests.Mock.Git;
77
using System;
88
using System.Collections.Generic;
9+
using System.Diagnostics;
910
using System.IO;
1011
using System.IO.Pipes;
1112
using System.Runtime.InteropServices;
@@ -152,7 +153,7 @@ public override bool TryGetDefaultLocalCacheRoot(string enlistmentRoot, out stri
152153
throw new NotImplementedException();
153154
}
154155

155-
public override void StartBackgroundVFS4GProcess(ITracer tracer, string programName, string[] args)
156+
public override Process StartBackgroundVFS4GProcess(ITracer tracer, string programName, string[] args)
156157
{
157158
throw new NotSupportedException();
158159
}

GVFS/GVFS/CommandLine/GVFSVerb.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,8 @@ protected bool TryAuthenticateAndQueryGVFSConfig(
243243
enlistment,
244244
retryConfig ?? new RetryConfig(),
245245
out config,
246-
out error),
246+
out error,
247+
out _),
247248
"Authenticating",
248249
enlistment.EnlistmentRoot);
249250

GVFS/GVFS/CommandLine/MountVerb.cs

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using GVFS.Common.Tracing;
55
using GVFS.DiskLayoutUpgrades;
66
using System;
7+
using System.Diagnostics;
78
using System.IO;
89
using System.Threading;
910

@@ -12,6 +13,7 @@ namespace GVFS.CommandLine
1213
public class MountVerb : GVFSVerb.ForExistingEnlistment
1314
{
1415
private const string MountVerbName = "mount";
16+
private Process mountProcess;
1517

1618
public string Verbosity { get; set; }
1719

@@ -197,9 +199,37 @@ protected override void Execute(GVFSEnlistment enlistment)
197199
() => { return this.TryMount(tracer, enlistment, mountExecutableLocation, out errorMessage); },
198200
"Mounting"))
199201
{
200-
this.ReportErrorAndExit(tracer, errorMessage);
202+
ReturnCode mountExitCode = ReturnCode.GenericError;
203+
if (this.mountProcess != null)
204+
{
205+
try
206+
{
207+
if (!this.mountProcess.HasExited)
208+
{
209+
this.mountProcess.WaitForExit(1000);
210+
}
211+
212+
if (this.mountProcess.HasExited)
213+
{
214+
mountExitCode = (ReturnCode)this.mountProcess.ExitCode;
215+
}
216+
}
217+
catch (InvalidOperationException)
218+
{
219+
}
220+
finally
221+
{
222+
this.mountProcess.Dispose();
223+
this.mountProcess = null;
224+
}
225+
}
226+
227+
this.ReportErrorAndExit(tracer, mountExitCode, errorMessage);
201228
}
202229

230+
this.mountProcess?.Dispose();
231+
this.mountProcess = null;
232+
203233
if (!this.Unattended)
204234
{
205235
tracer.RelatedInfo($"{nameof(this.Execute)}: Registering for automount");
@@ -229,7 +259,7 @@ private bool TryMount(ITracer tracer, GVFSEnlistment enlistment, string mountExe
229259

230260
tracer.RelatedInfo($"{nameof(this.TryMount)}: Launching background process('{mountExecutableLocation}') for {mountPath}");
231261

232-
GVFSPlatform.Instance.StartBackgroundVFS4GProcess(
262+
this.mountProcess = GVFSPlatform.Instance.StartBackgroundVFS4GProcess(
233263
tracer,
234264
mountExecutableLocation,
235265
new[]

0 commit comments

Comments
 (0)