diff --git a/src/NuGetLicense/CommandLineOptions.cs b/src/NuGetLicense/CommandLineOptions.cs index 8d0ff57e..a5b6e3a6 100644 --- a/src/NuGetLicense/CommandLineOptions.cs +++ b/src/NuGetLicense/CommandLineOptions.cs @@ -13,6 +13,7 @@ public class CommandLineOptions public string? InputFile { get; set; } public string? InputJsonFile { get; set; } public bool IncludeTransitive { get; set; } + public bool SkipInvalidProjects { get; set; } public string? AllowedLicenses { get; set; } public string? IgnoredPackages { get; set; } public string? LicenseMapping { get; set; } diff --git a/src/NuGetLicense/LicenseValidationOrchestrator.cs b/src/NuGetLicense/LicenseValidationOrchestrator.cs index e00a8ac5..67d53d22 100644 --- a/src/NuGetLicense/LicenseValidationOrchestrator.cs +++ b/src/NuGetLicense/LicenseValidationOrchestrator.cs @@ -3,6 +3,7 @@ using System.Collections.Immutable; using System.IO.Abstractions; +using Microsoft.Build.Exceptions; using NuGet.Configuration; using NuGet.Protocol.Core.Types; using NuGetLicense.LicenseValidator; @@ -73,7 +74,7 @@ public async Task ValidateAsync(CommandLineOptions options, CancellationTok string[] excludedProjectsArray = _optionsParser.GetExcludedProjects(options.ExcludedProjects); IEnumerable projects = (await inputFiles.SelectManyAsync(projectCollector.GetProjectsAsync)).Where(p => !Array.Exists(excludedProjectsArray, ignored => p.Like(ignored))); - IEnumerable packagesForProject = GetPackagesPerProject(projects, projectReader, options.IncludeTransitive, options.TargetFramework, options.IncludeSharedProjects, out IReadOnlyCollection projectReaderExceptions); + IEnumerable packagesForProject = GetPackagesPerProject(projects, projectReader, options.IncludeTransitive, options.SkipInvalidProjects, options.TargetFramework, options.IncludeSharedProjects, out IReadOnlyCollection projectReaderExceptions); IAsyncEnumerable downloadedLicenseInformation = packagesForProject.SelectMany(p => GetPackageInformations(p, overridePackageInformationArray, cancellationToken)); var results = (await validator.Validate(downloadedLicenseInformation, cancellationToken)).ToList(); @@ -136,6 +137,7 @@ private static IReadOnlyCollection GetPackagesPer IEnumerable projects, ReferencedPackageReader reader, bool includeTransitive, + bool skipInvalidProjects, string? targetFramework, bool includeSharedProjects, out IReadOnlyCollection exceptions) @@ -152,6 +154,20 @@ private static IReadOnlyCollection GetPackagesPer IEnumerable installedPackages = reader.GetInstalledPackages(project, includeTransitive, targetFramework); result.Add(new ProjectWithReferencedPackages(project, installedPackages)); } + catch (InvalidProjectFileException ipfe) + { + if (!skipInvalidProjects) + { + encounteredExceptions.Add(ipfe); + } + } + catch (ReferencedPackageReaderException rpre) when (rpre.Message.Contains("not compatible with")) + { + if (!skipInvalidProjects) + { + encounteredExceptions.Add(rpre); + } + } catch (Exception e) { encounteredExceptions.Add(e); diff --git a/src/NuGetLicense/Program.cs b/src/NuGetLicense/Program.cs index 14b1953a..83a00f59 100644 --- a/src/NuGetLicense/Program.cs +++ b/src/NuGetLicense/Program.cs @@ -33,6 +33,11 @@ public static RootCommand CreateRootCommand() Description = "If set, the whole license tree is followed in order to determine all nuget's used by the projects" }; + var skipInvalidProjectsOption = new Option("-skip", "--skip-invalid-projects") + { + Description = "If set, will skip any invalid projects not supported (for example, .pyproj projects)" + }; + var allowedLicensesOption = new Option("-a", "--allowed-license-types") { Description = "Specifies allowed license types. You can provide either a JSON file containing an array of license types, or a semicolon-separated list of license identifiers (e.g., \"MIT;Apache-2.0;BSD-3-Clause\")." @@ -103,6 +108,7 @@ public static RootCommand CreateRootCommand() rootCommand.Options.Add(inputFileOption); rootCommand.Options.Add(inputJsonFileOption); rootCommand.Options.Add(includeTransitiveOption); + rootCommand.Options.Add(skipInvalidProjectsOption); rootCommand.Options.Add(allowedLicensesOption); rootCommand.Options.Add(ignoredPackagesOption); rootCommand.Options.Add(licenseMappingOption); @@ -138,6 +144,7 @@ public static RootCommand CreateRootCommand() InputFile = inputFile, InputJsonFile = inputJsonFile, IncludeTransitive = parseResult.GetValue(includeTransitiveOption), + SkipInvalidProjects = parseResult.GetValue(skipInvalidProjectsOption), AllowedLicenses = parseResult.GetValue(allowedLicensesOption), IgnoredPackages = parseResult.GetValue(ignoredPackagesOption), LicenseMapping = parseResult.GetValue(licenseMappingOption), diff --git a/tests/NuGetLicense.Test/LicenseValidationOrchestratorTest.cs b/tests/NuGetLicense.Test/LicenseValidationOrchestratorTest.cs index 82949a71..d0707cc0 100644 --- a/tests/NuGetLicense.Test/LicenseValidationOrchestratorTest.cs +++ b/tests/NuGetLicense.Test/LicenseValidationOrchestratorTest.cs @@ -216,6 +216,7 @@ public async Task ValidateAsync_UsesAllConfiguredOptions() { InputFile = "/test/project.csproj", IncludeTransitive = true, + SkipInvalidProjects = false, TargetFramework = "net8.0", IncludeSharedProjects = true, AllowedLicenses = "MIT",