Skip to content

Commit

Permalink
support cancellation token, pass resolver options and cancellation to…
Browse files Browse the repository at this point in the history
…ken to all resolvers
  • Loading branch information
danielklecha committed Mar 17, 2024
1 parent 2ea7bd0 commit 6f83a03
Show file tree
Hide file tree
Showing 11 changed files with 96 additions and 77 deletions.
24 changes: 16 additions & 8 deletions DotnetThirdPartyNotices/Commands/ScanCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ internal class ScanCommand : Command
AddOption(new Option<string>("--configuration", () => "Release", "Project configuration to use"));
}

internal new class Handler(ILogger<Handler> logger, IProjectService projectService, ILicenseService licenseService, DynamicSettings dynamicSettings) : ICommandHandler
internal new class Handler(ILogger<Handler> logger, IProjectService projectService, ILicenseService licenseService) : ICommandHandler
{
public string? ScanDir { get; set; }
public string? OutputFilename { get; set; }
Expand All @@ -47,9 +47,9 @@ public int Invoke(InvocationContext context)

public async Task<int> InvokeAsync(InvocationContext context)
{
var cancellationToken = context.GetCancellationToken();
MSBuildLocator.RegisterDefaults();
ScanDir ??= Directory.GetCurrentDirectory();
dynamicSettings.GitHubToken = GithubToken;
var projectFilePaths = projectService.GetProjectFilePaths(ScanDir);
projectFilePaths = GetFilteredProjectPathes(projectFilePaths);
if (projectFilePaths.Length == 0)
Expand All @@ -58,9 +58,9 @@ public async Task<int> InvokeAsync(InvocationContext context)
return 0;
}
foreach (var projectFilePath in projectFilePaths)
await ScanProjectAsync(projectFilePath);
await ScanProjectAsync(projectFilePath, cancellationToken);
if (!CopyToOutDir)
await GenerateOutputFileAsync(OutputFilename);
await GenerateOutputFileAsync(OutputFilename, cancellationToken);
return 0;
}

Expand All @@ -72,8 +72,9 @@ private string[] GetFilteredProjectPathes(string[] projectPathes)
return projectPathes.Where(x => filterRegex.IsMatch(x)).ToArray();
}

private async Task ScanProjectAsync(string projectFilePath)
private async Task ScanProjectAsync(string projectFilePath, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
var stopWatch = new Stopwatch();
stopWatch.Start();
logger.LogInformation("Resolving files for {ProjectName} using {configuration} configuration...", Path.GetFileName(projectFilePath), Configuration ?? "Release");
Expand All @@ -84,6 +85,7 @@ private async Task ScanProjectAsync(string projectFilePath)
logger.LogInformation("Resolved files count: {ResolvedFilesCount}", resolvedFiles.Count);
foreach (var resolvedFileInfo in resolvedFiles)
{
cancellationToken.ThrowIfCancellationRequested();
logger.LogInformation("Resolving license for {RelativeOutputPath}", resolvedFileInfo.RelativeOutputPath);
if (resolvedFileInfo.NuSpec != null)
{
Expand All @@ -93,7 +95,11 @@ private async Task ScanProjectAsync(string projectFilePath)
{
logger.LogWarning("Package not found");
}
var licenseContent = await licenseService.ResolveFromResolvedFileInfo(resolvedFileInfo);
var resolverOptions = new ResolverOptions
{
GitHubToken = GithubToken
};
var licenseContent = await licenseService.ResolveFromResolvedFileInfoAsync(resolvedFileInfo, resolverOptions, cancellationToken);
if (licenseContent == null)
{
_unresolvedFiles.Add(resolvedFileInfo);
Expand All @@ -107,11 +113,12 @@ private async Task ScanProjectAsync(string projectFilePath)
stopWatch.Stop();
logger.LogInformation("Project {ProjectName} resolved in {StopwatchElapsedMilliseconds}ms", Path.GetFileName(projectFilePath), stopWatch.ElapsedMilliseconds);
if (CopyToOutDir && !string.IsNullOrEmpty(ScanDir) && !string.IsNullOrEmpty(OutputFilename))
await GenerateOutputFileAsync(Path.Combine(ScanDir, project.GetPropertyValue("OutDir"), Path.GetFileName(OutputFilename)));
await GenerateOutputFileAsync(Path.Combine(ScanDir, project.GetPropertyValue("OutDir"), Path.GetFileName(OutputFilename)), cancellationToken);
}

private async Task GenerateOutputFileAsync(string? outputFilePath)
private async Task GenerateOutputFileAsync(string? outputFilePath, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
if (outputFilePath == null)
return;
var uniqueResolvedFilesCount = _licenseContents.Values.Sum(v => v.GroupBy(x => x.SourcePath).Count());
Expand Down Expand Up @@ -139,6 +146,7 @@ private async Task GenerateOutputFileAsync(string? outputFilePath)
logger.LogInformation("Generate licenses in {StopwatchElapsedMilliseconds}ms", stopWatch.ElapsedMilliseconds);
if (stringBuilder.Length == 0)
return;
cancellationToken.ThrowIfCancellationRequested();
logger.LogInformation("Writing to {OutputFilename}...", outputFilePath);
await System.IO.File.WriteAllTextAsync(outputFilePath, stringBuilder.ToString());
_licenseContents.Clear();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace DotnetThirdPartyNotices.Models;

internal class DynamicSettings
internal class ResolverOptions
{
public string? GitHubToken { get; set; }
}
1 change: 0 additions & 1 deletion DotnetThirdPartyNotices/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
x.AddSingleton<ILicenseService, LicenseService>();
x.AddSingleton<ILocalPackageService, LocalPackageService>();
x.AddSingleton<IProjectService, ProjectService>();
x.AddSingleton<DynamicSettings>();
x.AddHttpClient();
var assembly = Assembly.GetExecutingAssembly();
var types = assembly.GetTypes();
Expand Down
14 changes: 7 additions & 7 deletions DotnetThirdPartyNotices/Services/GithubRawLicenseResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@

namespace DotnetThirdPartyNotices.Services;

internal class GithubRawLicenseResolver(IHttpClientFactory httpClientFactory, DynamicSettings dynamicSettings) : ILicenseUriLicenseResolver
internal class GithubRawLicenseResolver(IHttpClientFactory httpClientFactory) : ILicenseUriLicenseResolver
{
public bool CanResolve(Uri uri) => uri.Host == "github.com";
public Task<bool> CanResolveAsync(Uri uri, ResolverOptions resolverOptions, CancellationToken cancellationToken) => Task.FromResult(uri.Host == "github.com");

public async Task<string?> Resolve(Uri uri)
public async Task<string?> ResolveAsync(Uri uri, ResolverOptions resolverOptions, CancellationToken cancellationToken)
{
var uriBuilder = new UriBuilder(uri) { Host = "raw.githubusercontent.com" };
uriBuilder.Path = uriBuilder.Path.Replace("/blob", string.Empty);
var httpClient = httpClientFactory.CreateClient();
// https://developer.github.com/v3/#user-agent-required
httpClient.DefaultRequestHeaders.Add("User-Agent", "DotnetLicense");
if (!string.IsNullOrEmpty(dynamicSettings.GitHubToken))
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", dynamicSettings.GitHubToken);
var httpResponseMessage = await httpClient.GetAsync(uriBuilder.Uri);
if (!string.IsNullOrEmpty(resolverOptions.GitHubToken))
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", resolverOptions.GitHubToken);
var httpResponseMessage = await httpClient.GetAsync(uriBuilder.Uri, cancellationToken);
if (!httpResponseMessage.IsSuccessStatusCode
|| httpResponseMessage.Content.Headers.ContentType?.MediaType != "text/plain")
return null;
return await httpResponseMessage.Content.ReadAsStringAsync();
return await httpResponseMessage.Content.ReadAsStringAsync(cancellationToken);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@

namespace DotnetThirdPartyNotices.Services;

internal class GithubRepositoryLicenseResolver(IHttpClientFactory httpClientFactory, DynamicSettings dynamicSettings) : IProjectUriLicenseResolver, IRepositoryUriLicenseResolver
internal class GithubRepositoryLicenseResolver(IHttpClientFactory httpClientFactory) : IProjectUriLicenseResolver, IRepositoryUriLicenseResolver
{
public bool CanResolve(Uri uri) => uri.Host == "github.com";
public Task<bool> CanResolveAsync(Uri uri, ResolverOptions resolverOptions, CancellationToken cancellationToken) => Task.FromResult(uri.Host == "github.com");

public async Task<string?> Resolve(Uri licenseUri)
public async Task<string?> ResolveAsync(Uri licenseUri, ResolverOptions resolverOptions, CancellationToken cancellationToken)
{
var repositoryPath = licenseUri.AbsolutePath.TrimEnd('/');
if (repositoryPath.EndsWith(".git"))
Expand All @@ -24,12 +24,12 @@ internal class GithubRepositoryLicenseResolver(IHttpClientFactory httpClientFact
};
// https://developer.github.com/v3/#user-agent-required
httpClient.DefaultRequestHeaders.Add("User-Agent", "DotnetLicense");
if (!string.IsNullOrEmpty(dynamicSettings.GitHubToken))
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", dynamicSettings.GitHubToken);
var response = await httpClient.GetAsync(uriBuilder.Uri);
if (!string.IsNullOrEmpty(resolverOptions.GitHubToken))
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", resolverOptions.GitHubToken);
var response = await httpClient.GetAsync(uriBuilder.Uri, cancellationToken);
if (!response.IsSuccessStatusCode)
return null;
var json = await response.Content.ReadAsStringAsync();
var json = await response.Content.ReadAsStringAsync(cancellationToken);
var jsonDocument = JsonDocument.Parse(json);
var rootElement = jsonDocument.RootElement;
var encoding = rootElement.GetProperty("encoding").GetString();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
using DotnetThirdPartyNotices.Models;
using System.Diagnostics;
using System.Threading.Tasks;

namespace DotnetThirdPartyNotices.Services;

internal interface IFileVersionInfoLicenseResolver : ILicenseResolver
{
bool CanResolve(FileVersionInfo fileVersionInfo);
Task<string?> Resolve(FileVersionInfo fileVersionInfo);
Task<bool> CanResolveAsync(FileVersionInfo fileVersionInfo, CancellationToken cancellationToken);
Task<string?> ResolveAsync(FileVersionInfo fileVersionInfo, ResolverOptions resolverOptions, CancellationToken cancellationToken);
}
2 changes: 1 addition & 1 deletion DotnetThirdPartyNotices/Services/ILicenseService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ namespace DotnetThirdPartyNotices.Services;

internal interface ILicenseService
{
Task<string?> ResolveFromResolvedFileInfo(ResolvedFileInfo resolvedFileInfo);
Task<string?> ResolveFromResolvedFileInfoAsync(ResolvedFileInfo resolvedFileInfo, ResolverOptions resolverOptions, CancellationToken cancellationToken);
}
8 changes: 5 additions & 3 deletions DotnetThirdPartyNotices/Services/IUriLicenseResolver.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
namespace DotnetThirdPartyNotices.Services;
using DotnetThirdPartyNotices.Models;

namespace DotnetThirdPartyNotices.Services;

internal interface IUriLicenseResolver
{
bool CanResolve(Uri licenseUri);
Task<string?> Resolve(Uri licenseUri);
Task<bool> CanResolveAsync(Uri licenseUri, ResolverOptions resolverOptions, CancellationToken cancellationToken);
Task<string?> ResolveAsync(Uri licenseUri, ResolverOptions resolverOptions, CancellationToken cancellationToken);
}
Loading

0 comments on commit 6f83a03

Please sign in to comment.