Files
NugetSecretCredential/Program.cs

145 lines
4.6 KiB
C#

using System;
using NuGet.Protocol.Plugins;
namespace NugetSecretCredential;
public static class Program
{
private static bool _shuttingDown = false;
public static bool IsShuttingDown => Volatile.Read(ref _shuttingDown);
public static async Task<int> Main(string[] args)
{
CancellationTokenSource tokenSource = new CancellationTokenSource();
List<ICredentialProvider> credentialProviders = new List<ICredentialProvider>
{
new GitTokenCredentialProvider(),
};
try
{
bool isPlugin = false;
bool isRetry = false;
bool isNonInteractive = false;
bool canShowDialog = false;
Uri? uri = null;
for (int i = 0; i < args.Length; i++)
switch (args[i].ToLower())
{
case "-p": case "-plugin": isPlugin = true; break;
case "-i": case "-isretry": isRetry = true; break;
case "-n": case "-noninteractive": isNonInteractive = true; break;
case "-c": case "-canshowdialog": canShowDialog = true; break;
case "-u": case "-uri":
if (i + 1 == args.Length)
throw new ArgumentException("Expected uri after -U");
if (!Uri.TryCreate(args[i + 1], UriKind.Absolute, out uri))
throw new ArgumentException("Invalid uri format");
break;
}
IRequestHandlers requestHandlers = new RequestHandlerCollection
{
{ MessageMethod.GetAuthenticationCredentials, new GetAuthenticationCredentialsRequestHandler(credentialProviders) },
{ MessageMethod.GetOperationClaims, new GetOperationClaimsRequestHandler() },
{ MessageMethod.Initialize, new InitializeRequestHandler() },
{ MessageMethod.SetLogLevel, new SetLogLevelRequestHandler() },
{ MessageMethod.SetCredentials, new SetCredentialsRequestHandler() },
};
if (isPlugin)
{
// Plugin mode
try
{
using (IPlugin plugin = await PluginFactory.CreateFromCurrentProcessAsync(requestHandlers, ConnectionOptions.CreateDefault(), tokenSource.Token))
{
await WaitForPluginExitAsync(plugin, TimeSpan.FromMinutes(2)).ConfigureAwait(continueOnCapturedContext: false);
}
}
catch (OperationCanceledException ex)
{
// When restoring from multiple sources, one of the sources will throw an unhandled TaskCanceledException
// if it has been restored successfully from a different source.
// This is probably more confusing than interesting to users, but may be helpful in debugging,
// so log the exception but not to the console.
}
return 0;
}
else
{
// Stand-alone mode
if (requestHandlers.TryGet(MessageMethod.GetAuthenticationCredentials, out IRequestHandler requestHandler) && requestHandler is GetAuthenticationCredentialsRequestHandler getAuthenticationCredentialsRequestHandler)
{
if (uri == null)
{
Console.WriteLine("Uri argument -U not provided");
return 1;
}
GetAuthenticationCredentialsRequest request = new GetAuthenticationCredentialsRequest(uri, isRetry: isRetry, isNonInteractive, canShowDialog);
GetAuthenticationCredentialsResponse response = await getAuthenticationCredentialsRequestHandler.HandleRequestAsync(request, default);
// Fail if credentials are not found
if (response?.ResponseCode != MessageResponseCode.Success)
{
return 2;
}
Console.WriteLine("username=" + response.Username);
Console.WriteLine("password=" + response.Password);
return 0;
}
return -1;
}
}
catch (Exception e)
{
Console.Error.WriteLine("Error " + e.GetType().Name + ": " + e.Message);
File.WriteAllText("/home/rv/temp/nsc.error.log", "Error " + e.GetType().Name + ": " + e.Message);
return 1;
}
}
internal static async Task WaitForPluginExitAsync(IPlugin plugin, TimeSpan shutdownTimeout)
{
var beginShutdownTaskSource = new TaskCompletionSource<object>();
var endShutdownTaskSource = new TaskCompletionSource<object>();
plugin.Connection.Faulted += (sender, a) =>
{
Console.WriteLine(a.Exception.ToString());
};
plugin.BeforeClose += (sender, args) =>
{
Volatile.Write(ref _shuttingDown, true);
beginShutdownTaskSource.TrySetResult(null);
};
plugin.Closed += (sender, a) =>
{
// beginShutdownTaskSource should already be set in BeforeClose, but just in case do it here too
beginShutdownTaskSource.TrySetResult(null);
endShutdownTaskSource.TrySetResult(null);
};
await beginShutdownTaskSource.Task;
using (new Timer(_ => endShutdownTaskSource.TrySetCanceled(), null, shutdownTimeout, TimeSpan.FromMilliseconds(-1)))
{
await endShutdownTaskSource.Task;
}
if (endShutdownTaskSource.Task.IsCanceled)
{
Console.WriteLine("Plugin timeout");
}
}
}