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 capability to add a framework switch and also make sure to return… #88

Merged
merged 3 commits into from
Sep 16, 2024
Merged
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
21 changes: 21 additions & 0 deletions NuGetUtility.sln
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EmptyCppProject", "tests\ta
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VersionRangesProject", "tests\targets\VersionRangesProject\VersionRangesProject.csproj", "{6C96D10E-6CB6-4387-922F-C7C97C037495}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MultiTargetProjectWithDifferentDependencies", "tests\targets\MultiTargetProjectWithDifferentDependencies\MultiTargetProjectWithDifferentDependencies.csproj", "{A19BF89A-8B1F-4612-A923-08F52B53DC84}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -285,6 +287,24 @@ Global
{6C96D10E-6CB6-4387-922F-C7C97C037495}.TestWindows|x64.Build.0 = Debug|Any CPU
{6C96D10E-6CB6-4387-922F-C7C97C037495}.TestWindows|x86.ActiveCfg = Debug|Any CPU
{6C96D10E-6CB6-4387-922F-C7C97C037495}.TestWindows|x86.Build.0 = Debug|Any CPU
{A19BF89A-8B1F-4612-A923-08F52B53DC84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A19BF89A-8B1F-4612-A923-08F52B53DC84}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A19BF89A-8B1F-4612-A923-08F52B53DC84}.Debug|x64.ActiveCfg = Debug|Any CPU
{A19BF89A-8B1F-4612-A923-08F52B53DC84}.Debug|x64.Build.0 = Debug|Any CPU
{A19BF89A-8B1F-4612-A923-08F52B53DC84}.Debug|x86.ActiveCfg = Debug|Any CPU
{A19BF89A-8B1F-4612-A923-08F52B53DC84}.Debug|x86.Build.0 = Debug|Any CPU
{A19BF89A-8B1F-4612-A923-08F52B53DC84}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A19BF89A-8B1F-4612-A923-08F52B53DC84}.Release|Any CPU.Build.0 = Release|Any CPU
{A19BF89A-8B1F-4612-A923-08F52B53DC84}.Release|x64.ActiveCfg = Release|Any CPU
{A19BF89A-8B1F-4612-A923-08F52B53DC84}.Release|x64.Build.0 = Release|Any CPU
{A19BF89A-8B1F-4612-A923-08F52B53DC84}.Release|x86.ActiveCfg = Release|Any CPU
{A19BF89A-8B1F-4612-A923-08F52B53DC84}.Release|x86.Build.0 = Release|Any CPU
{A19BF89A-8B1F-4612-A923-08F52B53DC84}.TestWindows|Any CPU.ActiveCfg = Debug|Any CPU
{A19BF89A-8B1F-4612-A923-08F52B53DC84}.TestWindows|Any CPU.Build.0 = Debug|Any CPU
{A19BF89A-8B1F-4612-A923-08F52B53DC84}.TestWindows|x64.ActiveCfg = Debug|Any CPU
{A19BF89A-8B1F-4612-A923-08F52B53DC84}.TestWindows|x64.Build.0 = Debug|Any CPU
{A19BF89A-8B1F-4612-A923-08F52B53DC84}.TestWindows|x86.ActiveCfg = Debug|Any CPU
{A19BF89A-8B1F-4612-A923-08F52B53DC84}.TestWindows|x86.Build.0 = Debug|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -304,6 +324,7 @@ Global
{01704839-219A-4CE2-93F4-DB3CB8773DCE} = {FFB2826C-17A3-4C18-8FFE-A34AB51592F7}
{9B107A91-87F9-420C-ADF8-732C77DAFB93} = {FA92392F-D895-4D1E-A5ED-E6DC3C08223E}
{6C96D10E-6CB6-4387-922F-C7C97C037495} = {FA92392F-D895-4D1E-A5ED-E6DC3C08223E}
{A19BF89A-8B1F-4612-A923-08F52B53DC84} = {FA92392F-D895-4D1E-A5ED-E6DC3C08223E}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {70887D40-0182-4C32-BFA1-B5A02E405F11}
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Usage: nuget-license [options]

**Options:**

| Option | Description |
| Option | Description |
| ------ | ------------------------- |
| `--version` | Show version information. |
| `-i\|--input <INPUT_FILE>` | The project (or solution) file for which to analyze dependency licenses |
Expand All @@ -38,6 +38,7 @@ Usage: nuget-license [options]
| `-err\|--error-only` | If this option is set and there are license validation errors, only the errors are returned as result. Otherwise all validation results are always returned. |
| `-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 mockier (https://learn.microsoft.com/en-us/dotnet/standard/frameworks) for which to analyze dependencies. |
| `-?\|-h\|--help` | Show help information. |

## Example tool commands
Expand Down
8 changes: 2 additions & 6 deletions src/NuGetUtility/NuGetUtility.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,14 @@
<PackageReference Include="Microsoft.Build" ExcludeAssets="runtime" Version="17.3.*" />
</ItemGroup>

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

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

<ItemGroup Condition="'$(TargetFramework)' == 'net472'">
<PackageReference Include="Microsoft.Bcl.HashCode" Version="1.1.1" />
<PackageReference Include="System.Collections.Immutable" Version="8.0.0" />
<PackageReference Include="Microsoft.Build" ExcludeAssets="runtime" Version="17.9.*" />
<PackageReference Include="Microsoft.Build" ExcludeAssets="runtime" Version="17.11.*" />
<PackageReference Include="PolySharp" Version="1.14.*">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
5 changes: 5 additions & 0 deletions src/NuGetUtility/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ public class Program
Description = "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.")]
public string? ExcludedProjects { get; } = null;

[Option(LongName = "target-framework",
ShortName = "f",
Description = "This option allows to select a Target framework mockier (https://learn.microsoft.com/en-us/dotnet/standard/frameworks) for which to analyze dependencies.")]
public string? TargetFramework { get; } = null;

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ public ReferencedPackageReader(IMsBuildAbstraction msBuild,
_packagesConfigReader = packagesConfigReader;
}

public IEnumerable<PackageIdentity> GetInstalledPackages(string projectPath, bool includeTransitive)
public IEnumerable<PackageIdentity> GetInstalledPackages(string projectPath, bool includeTransitive, string? targetFramework = null)
{
IProject project = _msBuild.GetProject(projectPath);

if (TryGetInstalledPackagesFromAssetsFile(includeTransitive, project, out IEnumerable<PackageIdentity>? dependencies))
if (TryGetInstalledPackagesFromAssetsFile(includeTransitive, project, targetFramework, out IEnumerable<PackageIdentity>? dependencies))
{
return dependencies;
}
Expand All @@ -44,6 +44,7 @@ public IEnumerable<PackageIdentity> GetInstalledPackages(string projectPath, boo

private bool TryGetInstalledPackagesFromAssetsFile(bool includeTransitive,
IProject project,
string? targetFramework,
[NotNullWhen(true)] out IEnumerable<PackageIdentity>? installedPackages)
{
installedPackages = null;
Expand All @@ -54,42 +55,37 @@ private bool TryGetInstalledPackagesFromAssetsFile(bool includeTransitive,

var referencedLibraries = new HashSet<ILockFileLibrary>();

foreach (ILockFileTarget target in assetsFile.Targets!)
if (targetFramework is not null)
{
IEnumerable<ILockFileLibrary> referencedLibrariesForTarget =
GetReferencedLibrariesForTarget(project, includeTransitive, assetsFile, target);
referencedLibraries.AddRange(referencedLibrariesForTarget);
ILockFileTarget target = (assetsFile.Targets?.FirstOrDefault(t => t.TargetFramework.Equals(targetFramework))) ??
throw new ReferencedPackageReaderException($"Target framework {targetFramework} not found.");

referencedLibraries.AddRange(GetReferencedLibrariesForTarget(includeTransitive, assetsFile, target));
}
else
{
foreach (ILockFileTarget target in assetsFile.Targets!)
{
referencedLibraries.AddRange(GetReferencedLibrariesForTarget(includeTransitive, assetsFile, target));
}
}

installedPackages = referencedLibraries.Select(r => new PackageIdentity(r.Name, r.Version));
return true;
}

private IEnumerable<ILockFileLibrary> GetReferencedLibrariesForTarget(IProject project,
bool includeTransitive,
private static IEnumerable<ILockFileLibrary> GetReferencedLibrariesForTarget(bool includeTransitive,
ILockFile assetsFile,
ILockFileTarget target)
{
IEnumerable<ILockFileLibrary> referencedLibrariesForTarget = assetsFile.Libraries.Where(l => l.Type != ProjectReferenceIdentifier);

IEnumerable<ILockFileLibrary> dependencies = target.Libraries.Where(l => l.Type != ProjectReferenceIdentifier);
if (!includeTransitive)
{
ITargetFrameworkInformation targetFrameworkInformation = GetTargetFrameworkInformation(target, assetsFile);
IEnumerable<string> directlyReferencedPackages = _msBuild.GetPackageReferencesFromProjectForFramework(project,
targetFrameworkInformation.FrameworkName.ToString()!);

referencedLibrariesForTarget =
referencedLibrariesForTarget.Where(l => IsDirectlyReferenced(l, directlyReferencedPackages));
IEnumerable<ILibraryDependency> directDependencies = targetFrameworkInformation.Dependencies;
return dependencies.Where(d => directDependencies.Any(direct => direct.Name == d.Name));
}

return referencedLibrariesForTarget;
}

private bool IsDirectlyReferenced(ILockFileLibrary library,
IEnumerable<string> directlyReferencedPackages)
{
return directlyReferencedPackages.Any(p =>
library.Name.Equals(p, StringComparison.OrdinalIgnoreCase));
return dependencies;
}

private static ITargetFrameworkInformation GetTargetFrameworkInformation(ILockFileTarget target,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ namespace NuGetUtility.Wrapper.MsBuildWrapper
{
public interface IMsBuildAbstraction
{
IEnumerable<string> GetPackageReferencesFromProjectForFramework(IProject project, string framework);
IProject GetProject(string projectPath);
IEnumerable<string> GetProjectsFromSolution(string inputPath);
}
Expand Down
30 changes: 0 additions & 30 deletions src/NuGetUtility/Wrapper/MsBuildWrapper/MsBuildAbstraction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,12 @@

using Microsoft.Build.Construction;
using Microsoft.Build.Evaluation;
using Microsoft.Build.Exceptions;
using Microsoft.Build.Execution;
using Microsoft.Build.Framework;
using Microsoft.Build.Locator;

namespace NuGetUtility.Wrapper.MsBuildWrapper
{
public class MsBuildAbstraction : IMsBuildAbstraction
{
private const string CollectPackageReferences = "CollectPackageReferences";
private ProjectCollection? _projects;

private ProjectCollection Projects => _projects ??= InitializeProjectCollection();
Expand All @@ -22,20 +18,6 @@ public MsBuildAbstraction()
RegisterMsBuildLocatorIfNeeded();
}

public IEnumerable<string> GetPackageReferencesFromProjectForFramework(IProject project,
string framework)
{
var globalProperties = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ "TargetFramework", framework }
};
var newProject = new ProjectInstance(project.FullPath, globalProperties, null);
newProject.Build(new[] { CollectPackageReferences }, new List<ILogger>(), out IDictionary<string, TargetResult>? targetOutputs);

return targetOutputs.First(e => e.Key.Equals(CollectPackageReferences))
.Value.Items.Select(p => p.ItemSpec);
}

public IProject GetProject(string projectPath)
{
#if !NETFRAMEWORK
Expand Down Expand Up @@ -65,18 +47,6 @@ private static void RegisterMsBuildLocatorIfNeeded()
}
}

private static ProjectRootElement TryGetProjectRootElement(string projectPath)
{
try
{
return ProjectRootElement.Open(projectPath, ProjectCollection.GlobalProjectCollection)!;
}
catch (InvalidProjectFileException e)
{
throw new MsBuildAbstractionException($"Failed to open project: {projectPath}", e);
}
}

private static ProjectCollection InitializeProjectCollection()
{
ProjectCollection collection = ProjectCollection.GlobalProjectCollection;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ namespace NuGetUtility.Wrapper.NuGetWrapper.Frameworks
public interface INuGetFramework
{
string? ToString();
bool Equals(string targetFramework);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ public override bool Equals(object? obj)
return false;
}

public bool Equals(string targetFramework)
{
var other = NuGetFramework.Parse(targetFramework);
return _framework.Equals(other);
}

public override int GetHashCode()
{
return _framework.GetHashCode();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Licensed to the projects contributors.
// The license conditions are provided in the LICENSE file located in the project root

namespace NuGetUtility.Wrapper.NuGetWrapper.ProjectModel
{
public interface ILibraryDependency
{
string Name { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,5 @@ public interface ILockFile
{
IPackageSpec PackageSpec { get; }
IEnumerable<ILockFileTarget>? Targets { get; }

IEnumerable<ILockFileLibrary> Libraries { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ namespace NuGetUtility.Wrapper.NuGetWrapper.ProjectModel
public interface ILockFileTarget
{
INuGetFramework TargetFramework { get; }
IEnumerable<ILockFileLibrary> Libraries { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ namespace NuGetUtility.Wrapper.NuGetWrapper.ProjectModel
public interface ITargetFrameworkInformation
{
INuGetFramework FrameworkName { get; }
IEnumerable<ILibraryDependency> Dependencies { get; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Licensed to the projects contributors.
// The license conditions are provided in the LICENSE file located in the project root

using NuGet.LibraryModel;

namespace NuGetUtility.Wrapper.NuGetWrapper.ProjectModel
{
internal class WrappedLibraryDependency : ILibraryDependency
{
private readonly LibraryDependency _dependency;

public WrappedLibraryDependency(LibraryDependency dependency)
{
_dependency = dependency;
}
public string Name => _dependency.Name;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,7 @@ public WrappedLockFileTarget(LockFileTarget target)
}

public INuGetFramework TargetFramework => new WrappedNuGetFramework(_target.TargetFramework);

public IEnumerable<ILockFileLibrary> Libraries => _target.Libraries.Select(l => new WrappedLockFileTargetLibrary(l));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Licensed to the projects contributors.
// The license conditions are provided in the LICENSE file located in the project root

using NuGet.ProjectModel;
using NuGetUtility.Wrapper.NuGetWrapper.Versioning;

namespace NuGetUtility.Wrapper.NuGetWrapper.ProjectModel
{
internal class WrappedLockFileTargetLibrary : ILockFileLibrary
{
public WrappedLockFileTargetLibrary(LockFileTargetLibrary library)
{
Type = library.Type ?? throw new ArgumentNullException(nameof(library), $"The field {nameof(library.Type)} on {nameof(library)} must not be null");
Name = library.Name ?? throw new ArgumentNullException(nameof(library), $"The field {nameof(library.Name)} on {nameof(library)} must not be null");
Version = new WrappedNuGetVersion(library.Version ?? throw new ArgumentNullException(nameof(library), $"The field {nameof(library.Version)} on {nameof(library)} must not be null"));
}

public string Type { get; }

public string Name { get; }

public INuGetVersion Version { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public WrappedTargetFrameworkInformation(TargetFrameworkInformation info)

public INuGetFramework FrameworkName => new WrappedNuGetFramework(_info.FrameworkName);

public IEnumerable<ILibraryDependency> Dependencies => _info.Dependencies.Select(library => new WrappedLibraryDependency(library));

public override string ToString()
{
return _info.ToString();
Expand Down
2 changes: 1 addition & 1 deletion tests/NuGetUtility.Test/NuGetUtility.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Selenium.WebDriver" Version="4.21.0" />
<PackageReference Include="Selenium.WebDriver" Version="4.24.0" />
<PackageReference Include="Verify.NUnit" Version="22.5.0" />
</ItemGroup>

Expand Down
Loading
Loading