nuget-extensions/nuget-plugin/Program.cs (150 lines of code) (raw):
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.TeamCity.NuGet.Logging;
using JetBrains.TeamCity.NuGet.RequestHandlers;
using NuGet.Common;
using NuGet.Protocol.Plugins;
using ILogger = JetBrains.TeamCity.NuGet.Logging.ILogger;
namespace JetBrains.TeamCity.NuGet
{
internal static class Program
{
public static int Main(string[] args)
{
DebugBreakIfPluginDebuggingIsEnabled();
var tokenSource = new CancellationTokenSource();
var multiLogger = new MultiLogger();
var fileLogger = GetFileLogger();
if (fileLogger != null)
{
multiLogger.Add(fileLogger);
}
multiLogger.Log(LogLevel.Verbose, "Entered nuget credentials plugin");
Console.CancelKeyPress += (sender, eventArgs) =>
{
tokenSource.Cancel();
eventArgs.Cancel = true;
};
try
{
return MainInternal(tokenSource, multiLogger, args).GetAwaiter().GetResult();
}
catch (OperationCanceledException e)
{
// Multiple source restoration. Request will be cancelled if a package has been successfully restored from another source
multiLogger.Log(LogLevel.Verbose, $"Request to credential provider was cancelled. Message: {e.Message}");
return 0;
}
}
private static async Task<int> MainInternal(CancellationTokenSource tokenSource, MultiLogger multiLogger, string[] args)
{
var credentialProvider = new TeamCityCredentialProvider(multiLogger);
var sdkInfo = new SdkInfo();
var requestHandlers = new RequestHandlerCollection
{
{
MessageMethod.GetAuthenticationCredentials,
new GetAuthenticationCredentialsRequestHandler(multiLogger, credentialProvider)
},
{
MessageMethod.GetOperationClaims,
new GetOperationClaimsRequestHandler(multiLogger, credentialProvider, sdkInfo)
},
{
MessageMethod.SetLogLevel,
new SetLogLevelHandler(multiLogger)
},
{
MessageMethod.Initialize,
new InitializeRequestHandler(multiLogger)
},
{
MessageMethod.SetCredentials,
new SetCredentialsRequestHandler(multiLogger)
}
};
if (String.Equals(args.SingleOrDefault(), "-plugin", StringComparison.OrdinalIgnoreCase))
{
multiLogger.Log(LogLevel.Verbose, "Running in plug-in mode");
try
{
using (IPlugin plugin = await PluginFactory
.CreateFromCurrentProcessAsync(requestHandlers, ConnectionOptions.CreateDefault(), CancellationToken.None)
.ConfigureAwait(continueOnCapturedContext: false))
{
multiLogger.Add(new PluginConnectionLogger(plugin.Connection));
await RunNuGetPluginsAsync(plugin, multiLogger, tokenSource.Token).ConfigureAwait(continueOnCapturedContext: false);
}
}
catch (OperationCanceledException e)
{
// Multiple source restoration. Request will be cancelled if a package has been successfully restored from another source
multiLogger.Log(LogLevel.Verbose, $"Request to credential provider was cancelled. Message: {e.Message}");
}
return 0;
}
if (requestHandlers.TryGet(MessageMethod.GetAuthenticationCredentials, out IRequestHandler requestHandler) &&
requestHandler is GetAuthenticationCredentialsRequestHandler getAuthenticationCredentialsRequestHandler)
{
multiLogger.Log(LogLevel.Verbose, "Running in stand-alone mode");
if (args.Length == 0)
{
Console.WriteLine("Usage: CredentialProvider.TeamCity.exe <NuGetFeedUrl>");
return 1;
}
var request = new GetAuthenticationCredentialsRequest(
uri: new Uri(args[0]),
isRetry: false,
isNonInteractive: true,
canShowDialog: false
);
var response = getAuthenticationCredentialsRequestHandler.HandleRequestAsync(request).GetAwaiter().GetResult();
Console.WriteLine(response?.Username);
Console.WriteLine(response?.Password);
Console.WriteLine(response?.Password.ToJsonWebTokenString());
return 0;
}
return -1;
}
private static async Task RunNuGetPluginsAsync(IPlugin plugin, ILogger logger, CancellationToken cancellationToken)
{
SemaphoreSlim semaphore = new SemaphoreSlim(0);
plugin.Connection.Faulted += (sender, a) =>
{
logger.Log(LogLevel.Error, $"Faulted on message: {a.Message?.Type} {a.Message?.Method} {a.Message?.RequestId}");
logger.Log(LogLevel.Error, a.Exception.ToString());
};
plugin.Closed += (sender, a) => semaphore.Release();
bool complete = await semaphore.WaitAsync(TimeSpan.FromDays(1), cancellationToken)
.ConfigureAwait(continueOnCapturedContext: false);
if (!complete)
{
logger.Log(LogLevel.Error, "Timed out waiting for plug-in operations to complete");
}
}
private static void DebugBreakIfPluginDebuggingIsEnabled()
{
if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("NUGET_PLUGIN_DEBUG")))
{
while (!Debugger.IsAttached)
{
Thread.Sleep(100);
}
}
}
private static FileLogger GetFileLogger()
{
var location = Environment.GetEnvironmentVariable("NUGET_PLUGIN_LOG_PATH");
if (string.IsNullOrEmpty(location))
{
return null;
}
Directory.CreateDirectory(Path.GetDirectoryName(location));
var fileLogger = new FileLogger(location);
fileLogger.SetLogLevel(LogLevel.Verbose);
return fileLogger;
}
}
}