Skip to content

Commit

Permalink
read packages from packages.config
Browse files Browse the repository at this point in the history
  • Loading branch information
notofug committed Dec 22, 2023
1 parent beae98c commit dd12eff
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 15 deletions.
5 changes: 5 additions & 0 deletions src/NuGetUtility/Extensions/ProjectExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ public static bool IsPackageReferenceProject(this IProject project)
!project.HasPackagesConfigFile();
}

public static string GetPackagesConfigPath(this IProject project)
{
return Path.Join(Path.GetDirectoryName(project.FullPath), PackagesConfigFileName);
}

private static bool HasPackagesConfigFile(this IProject project)
{
return project.GetEvaluatedIncludes().Any(include => include?.Equals(PackagesConfigFileName) ?? false);
Expand Down
1 change: 1 addition & 0 deletions src/NuGetUtility/NuGetUtility.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
<PackageReference Include="Microsoft.Build.Locator" Version="1.6.10" />
<PackageReference Include="NuGet.Commands" Version="6.8.0" />
<PackageReference Include="NuGet.Packaging" Version="6.8.0" />
<PackageReference Include="System.Management" Version="8.0.0" />
<PackageReference Include="System.Text.Json" Version="8.0.0" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System.Xml.Linq;
using NuGetUtility.Extensions;
using NuGetUtility.Wrapper.MsBuildWrapper;
using NuGetUtility.Wrapper.NuGetWrapper.Packaging.Core;
using NuGetUtility.Wrapper.NuGetWrapper.ProjectModel;
using NuGetUtility.Wrapper.NuGetWrapper.Versioning;

namespace NuGetUtility.ReferencedPackagesReader
{
Expand All @@ -27,9 +29,26 @@ public IEnumerable<PackageIdentity> GetInstalledPackages(string projectPath, boo
return Enumerable.Empty<PackageIdentity>();
}

return GetInstalledPackagesFromAssetsFile(includeTransitive, project);
if (project.IsPackageReferenceProject())
return GetInstalledPackagesFromAssetsFile(includeTransitive, project);

return GetInstalledPackagesFromPackagesConfig(project);
}

private IEnumerable<PackageIdentity> GetInstalledPackagesFromPackagesConfig(IProject project)
{
var xml = XElement.Load(project.GetPackagesConfigPath());

return xml.Descendants("package").Select(p => ToPackageIdentity(p));
}
private PackageIdentity ToPackageIdentity(XElement xlm)
{
var packageid = (string) xlm.Attribute("id");

var version = (string) xlm.Attribute("version");

return new PackageIdentity(packageid, new WrappedNuGetVersion(version));
}
private IEnumerable<PackageIdentity> GetInstalledPackagesFromAssetsFile(bool includeTransitive,
IProject project)
{
Expand Down
45 changes: 36 additions & 9 deletions src/NuGetUtility/Wrapper/MsBuildWrapper/MsBuildAbstraction.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Management;
using Microsoft.Build.Construction;
using Microsoft.Build.Evaluation;
using Microsoft.Build.Exceptions;
Expand All @@ -12,10 +13,17 @@ namespace NuGetUtility.Wrapper.MsBuildWrapper
public class MsBuildAbstraction : IMsBuildAbstraction
{
private const string CollectPackageReferences = "CollectPackageReferences";
private readonly Dictionary<string, string> _project_props = new ();

public MsBuildAbstraction()
{
RegisterMsBuildLocatorIfNeeded();

// to support VC-projects we need to workaround : https://github.com/3F/MvsSln/issues/1
// adding 'VCTargetsPath' to Project::GlobalProperties seem to be enough

if (GetBestVCTargetsPath() is string path)
_project_props.Add("VCTargetsPath", $"{path}\\");
}

public IEnumerable<PackageReference> GetPackageReferencesFromProjectForFramework(IProject project,
Expand All @@ -40,16 +48,9 @@ public IProject GetProject(string projectPath)
{
ProjectRootElement rootElement = TryGetProjectRootElement(projectPath);

var project = new Project(rootElement);
var projectWrapper = new ProjectWrapper(project);

if (!projectWrapper.IsPackageReferenceProject())
{
throw new MsBuildAbstractionException(
$"Invalid project structure detected. Currently only PackageReference projects are supported (Project: {project.FullPath})");
}
var project = new Project(rootElement, _project_props, null);

return projectWrapper;
return new ProjectWrapper(project);
}

public IEnumerable<string> GetProjectsFromSolution(string inputPath)
Expand All @@ -59,6 +60,32 @@ public IEnumerable<string> GetProjectsFromSolution(string inputPath)
return sln.ProjectsInOrder.Select(p => p.AbsolutePath);
}

private static string? GetBestVCTargetsPath()
{
var cpp_props = new List<FileInfo>();

foreach (string path in GetVisualStudioInstallPaths())
cpp_props.AddRange(new DirectoryInfo(path).GetFiles("Microsoft.Cpp.Default.props", SearchOption.AllDirectories));

// if multiple, assume most recent 'LastWriteTime' property is 'best'
return cpp_props.OrderBy(f => f.LastWriteTime).LastOrDefault()?.DirectoryName;
}

private static IEnumerable<string> GetVisualStudioInstallPaths()
{
// https://learn.microsoft.com/en-us/visualstudio/install/tools-for-managing-visual-studio-instances?view=vs-2022#using-windows-management-instrumentation-wmi

var result = new List<string>();

var mmc = new ManagementClass("root/cimv2/vs:MSFT_VSInstance");

foreach (var vs_instance in mmc.GetInstances())
if (vs_instance["InstallLocation"] is string install_path)
result.Add(install_path);

return result;
}

private static void RegisterMsBuildLocatorIfNeeded()
{
if (!MSBuildLocator.IsRegistered)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,13 @@ public void GetInstalledPackagesShould_ReturnEmptyEnumerableForProjectsWithoutPa

[Test]
[Platform(Include = "Win")]
public void GetInstalledPackagesShould_ThrowMsBuildAbstractionException_If_ProjectUsesPackagesConfig()
public void GetInstalledPackagesShould_ReturnPackagesForPackagesConfigProject()
{
string path = Path.GetFullPath("../../../../targets/PackagesConfigProject/PackagesConfigProject.csproj");

MsBuildAbstractionException? exception = Assert.Throws<MsBuildAbstractionException>(() => _uut!.GetInstalledPackages(path, false));
Assert.AreEqual(
$"Invalid project structure detected. Currently only PackageReference projects are supported (Project: {path})",
exception?.Message);
IEnumerable<PackageIdentity> result = _uut!.GetInstalledPackages(path, false);

Assert.That(result.Count, Is.EqualTo(1));
}
}
}

0 comments on commit dd12eff

Please sign in to comment.