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

Add option to output to a file instead of the console #100

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Usage: nuget-license [options]
| `-include-ignored\|--include-ignored-packages` | If this option is set, the packages that are ignored from validation are still included in the output. |
| `-exclude-projects\|--exclude-projects-matching <EXCLUDED_PROJECTS>` | This option allows to specify project name(s) to exclude from the analysis. This can be useful to exclude test projects from the analysis when supplying a solution file as input. Wildcard characters (*) are supported to specify ranges of ignored projects. The input can either be a file name containing a list of project names in json format or a plain string that is then used as a single entry. |
| `-f\|--target-framework <TARGET_FRAMEWORK>` | This option allows to select a Target framework moniker (https://learn.microsoft.com/en-us/dotnet/standard/frameworks) for which to analyze dependencies. |
| `-fo\|--file-output <DESTINATION_FILE>` | The destination file to put the valiation output to. If omitted, the output is printed to the console. |
| `-?\|-h\|--help` | Show help information. |

## Example tool commands
Expand Down
2 changes: 1 addition & 1 deletion src/NuGetUtility/NuGetUtility.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
<PackageReference Include="Microsoft.Build" ExcludeAssets="runtime" Version="17.11.*" />
<PackageReference Include="Microsoft.Build" ExcludeAssets="runtime" Version="17.12.*" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net472'">
Expand Down
73 changes: 53 additions & 20 deletions src/NuGetUtility/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,17 @@ public class Program
Description = "This option allows to select a Target framework moniker (https://learn.microsoft.com/en-us/dotnet/standard/frameworks) for which to analyze dependencies.")]
public string? TargetFramework { get; } = null;

[Option(LongName = "file-output",
ShortName = "fo",
Description = "The destination file to put the valiation output to. If omitted, the output is printed to the console.")]
public string? DestinationFile { get; } = null;

private static string GetVersion()
=> typeof(Program).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion ?? string.Empty;

#pragma warning disable S1144 // Unused private types or members should be removed
private async Task<int> OnExecuteAsync(CancellationToken cancellationToken)
#pragma warning restore S1144 // Unused private types or members should be removed
{
using var httpClient = new HttpClient();
string[] inputFiles = GetInputFiles();
Expand All @@ -119,45 +126,49 @@ private async Task<int> OnExecuteAsync(CancellationToken cancellationToken)
allowedLicenses,
urlLicenseFileDownloader,
ignoredPackages);
var projectReaderExceptions = new List<Exception>();

string[] excludedProjects = GetExcludedProjects();
IEnumerable<string> projects = inputFiles.SelectMany(projectCollector.GetProjects).Where(p => !Array.Exists(excludedProjects, ignored => p.Like(ignored)));
IEnumerable<ProjectWithReferencedPackages> packagesForProject = projects.Select(p =>
{
IEnumerable<PackageIdentity>? installedPackages = null;
try
{
installedPackages = projectReader.GetInstalledPackages(p, IncludeTransitive, TargetFramework);
}
catch (Exception e)
{
projectReaderExceptions.Add(e);
}
return new ProjectWithReferencedPackages(p, installedPackages ?? Enumerable.Empty<PackageIdentity>());
});
IEnumerable<ProjectWithReferencedPackages> packagesForProject = GetPackagesPerProject(projects, projectReader, out IReadOnlyCollection<Exception>? projectReaderExceptions);
IAsyncEnumerable<ReferencedPackageWithContext> downloadedLicenseInformation =
packagesForProject.SelectMany(p => GetPackageInformations(p, overridePackageInformation, cancellationToken));
var results = (await validator.Validate(downloadedLicenseInformation, cancellationToken)).ToList();

if (projectReaderExceptions.Any())
if (projectReaderExceptions.Count > 0)
{
await WriteValidationExceptions(projectReaderExceptions);

return -1;
}

using Stream outputStream = Console.OpenStandardOutput();
await output.Write(outputStream, results.OrderBy(r => r.PackageId).ThenBy(r => r.PackageVersion).ToList());
return results.Count(r => r.ValidationErrors.Any());
try
{
using Stream outputStream = GetOutputStream();
await output.Write(outputStream, results.OrderBy(r => r.PackageId).ThenBy(r => r.PackageVersion).ToList());
return results.Count(r => r.ValidationErrors.Any());
}
catch (Exception e)
{
await Console.Error.WriteLineAsync(e.ToString());
return -1;
}
}

private Stream GetOutputStream()
{
if (DestinationFile is null)
{
return Console.OpenStandardOutput();
}
return File.Open(Path.GetFullPath(DestinationFile), FileMode.Create, FileAccess.Write, FileShare.None);
}

private static IPackagesConfigReader GetPackagesConfigReader()
{
#if NETFRAMEWORK
return new WindowsPackagesConfigReader();
#else
return OperatingSystem.IsWindows() ? new WindowsPackagesConfigReader() : new FailingPackagesConfigReader();
return OperatingSystem.IsWindows() ? new WindowsPackagesConfigReader() : new FailingPackagesConfigReader();
#endif
}

Expand Down Expand Up @@ -202,7 +213,7 @@ private IFileDownloader GetFileDownloader(HttpClient httpClient)
return new FileDownloader(httpClient, DownloadLicenseInformation);
}

private static async Task WriteValidationExceptions(List<Exception> validationExceptions)
private static async Task WriteValidationExceptions(IReadOnlyCollection<Exception> validationExceptions)
{
foreach (Exception exception in validationExceptions)
{
Expand Down Expand Up @@ -286,5 +297,27 @@ private string[] GetInputFiles()

throw new FileNotFoundException("Please provide an input file");
}

private IReadOnlyCollection<ProjectWithReferencedPackages> GetPackagesPerProject(IEnumerable<string> projects, ReferencedPackageReader reader, out IReadOnlyCollection<Exception> exceptions)
{
var encounteredExceptions = new List<Exception>();
var result = new List<ProjectWithReferencedPackages>();
exceptions = encounteredExceptions;
foreach (string project in projects)
{

try
{
IEnumerable<PackageIdentity> installedPackages = reader.GetInstalledPackages(project, IncludeTransitive, TargetFramework);
result.Add(new ProjectWithReferencedPackages(project, installedPackages));
}
catch (Exception e)
{
encounteredExceptions.Add(e);
}
}

return result;
}
}
}
4 changes: 2 additions & 2 deletions src/NuGetUtility/Wrapper/HttpClientWrapper/FileDownloader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ public async Task DownloadFile(Uri url, string fileNameStem, CancellationToken t
}
}

#pragma warning disable S1172
#pragma warning disable S1172 // Unused parameter
private async Task<bool> TryDownload(string fileNameStem, Uri url, CancellationToken token)
#pragma warning restore S1172
#pragma warning restore S1172 // Unused parameter
{
var request = new HttpRequestMessage(HttpMethod.Get, url);

Expand Down
Loading