From 3893f7a4d0456d432241311fe8a3593b6052f6aa Mon Sep 17 00:00:00 2001 From: IX-BOT <137874481+IX-BOT@users.noreply.github.com> Date: Fri, 15 Sep 2023 12:28:22 +0200 Subject: [PATCH] [NEW-FEATURE] Support central package management in ixc (#224) * Create draft PR for #223 * adds support for Central Package Management --------- Co-authored-by: PTKu Co-authored-by: Peter <61538034+PTKu@users.noreply.github.com> --- .../src/AXSharp.Compiler/AXSharpProject.cs | 2 +- .../src/AXSharp.Compiler/AxProject.cs | 8 ++- .../AXSharp.Cs.Compiler/PackageReference.cs | 63 +++++++++++++++++-- .../src/ixc/Properties/launchSettings.json | 4 +- 4 files changed, 69 insertions(+), 8 deletions(-) diff --git a/src/AXSharp.compiler/src/AXSharp.Compiler/AXSharpProject.cs b/src/AXSharp.compiler/src/AXSharp.Compiler/AXSharpProject.cs index c31451c7..5f4fa698 100644 --- a/src/AXSharp.compiler/src/AXSharp.Compiler/AXSharpProject.cs +++ b/src/AXSharp.compiler/src/AXSharp.Compiler/AXSharpProject.cs @@ -202,7 +202,7 @@ private IEnumerable GetReferences() private void CompileProjectReferences(IEnumerable referencedDependencies) { - foreach (var ixProjectReference in AxProject.IxReferences) + foreach (var ixProjectReference in AxProject.AXSharpReferences) { string apaxFolder = ixProjectReference.AxProjectFolder == null ? referencedDependencies diff --git a/src/AXSharp.compiler/src/AXSharp.Compiler/AxProject.cs b/src/AXSharp.compiler/src/AXSharp.Compiler/AxProject.cs index be245c67..33f279f2 100644 --- a/src/AXSharp.compiler/src/AXSharp.Compiler/AxProject.cs +++ b/src/AXSharp.compiler/src/AXSharp.Compiler/AxProject.cs @@ -83,7 +83,7 @@ public AxProject(string axProjectFolder, string[] sourceFiles) /// /// Gets paths of this project's references to other ix projects. /// - public IEnumerable IxReferences + public IEnumerable AXSharpReferences { get { @@ -99,6 +99,12 @@ public IEnumerable IxReferences .Select(p => Directory.EnumerateFiles(p.LinkTarget ?? p.FullName, AXSharpConfig.CONFIG_FILE_NAME, SearchOption.TopDirectoryOnly)) .SelectMany(p => p).Select(c => AXSharpConfig.RetrieveIxConfig(c)); + if (retVal.Count() == 0) + { + Log.Logger.Information("Retrieving possible project references from .apax packages did not produce results. " + + "If you have referenced AX# projects, the packages must be previously installed by 'apax install'"); + } + return retVal; } } diff --git a/src/AXSharp.compiler/src/AXSharp.Cs.Compiler/PackageReference.cs b/src/AXSharp.compiler/src/AXSharp.Cs.Compiler/PackageReference.cs index fe1c3e78..267d716f 100644 --- a/src/AXSharp.compiler/src/AXSharp.Cs.Compiler/PackageReference.cs +++ b/src/AXSharp.compiler/src/AXSharp.Cs.Compiler/PackageReference.cs @@ -20,6 +20,40 @@ public class PackageReference : IPackageReference private static readonly string NugetDir = SettingsUtility.GetGlobalPackagesFolder(Settings.LoadDefaultSettings(null)); + private static IEnumerable<(string? include, string? version)> GetVersionFromCentralPackageManagement(string csprojFile) + { + var scFile = new FileInfo(csprojFile); + string? currentDirectory = scFile.DirectoryName; + string targetFile = null; + + // Search for the file in the directory tree upstream + while (currentDirectory != null) + { + var potentialFile = Path.Combine(currentDirectory, "Directory.Packages.props"); + if (File.Exists(potentialFile)) + { + targetFile = potentialFile; + break; + } + + currentDirectory = Directory.GetParent(currentDirectory)?.FullName; + } + + if (targetFile == null) + { + return new List<(string?, string?)>(); + } + + XDocument xdoc = XDocument.Load(targetFile); + var packageElements = xdoc.Descendants().Where(e => e.Name == "PackageVersion" || e.Name == "GlobalPackageReference"); + + return packageElements.Select(pv => + ( + pv.Attribute("Include")?.Value, + pv.Attribute("Version")?.Value + )); + } + /// /// Creates new instance of /// @@ -32,16 +66,37 @@ public static PackageReference CreateFromReferenceNode(XElement packageReference try { include = (packageReferenceNode.Attribute(XName.Get(nameof(Include)))?.Value ?? packageReferenceNode.Attribute(XName.Get("Update"))?.Value)!; - var version = packageReferenceNode.Attribute(XName.Get(nameof(Version)))!.Value; + var version = packageReferenceNode.Attribute(XName.Get(nameof(Version)))?.Value ?? + packageReferenceNode.Attribute(XName.Get("VersionOverride"))?.Value; + + version = version ?? + GetVersionFromCentralPackageManagement(projectFile).FirstOrDefault(p => p.include == include).version; + + + + if (include == null) + { + throw new FailedToRetrievePackageReferenceException( + $"We were unable to determine package id of one of the packages referenced in project {projectFile}\n" + + $"The package id must be in 'Include' or 'Update' attribute of 'PackageReference' element." + + $"Make sure your csproj file is valid", null); + } + + if (version == null) + { + throw new FailedToRetrievePackageReferenceException( + $"We were unable to determine version of the package '{include}' referenced in project {projectFile}\n" + + $"Make sure you have the version defined either in the project file or in central package management file 'Directory.Packages.props'\n" + + $"upstream in your projects' directory structure.", null); + } + var referencePath = PackageReferenceNugetPath(include, version); return new PackageReference(referencePath, include, version); } catch (Exception ex) { - throw new FailedToRetrievePackageReferenceException( - $"Could not parse 'Name' or 'Version' of the package '{include}' reference in project {projectFile}", - ex); + throw new FailedToRetrievePackageReferenceException($"Failed to retrieve package reference {ex.Message}", ex); } } diff --git a/src/AXSharp.compiler/src/ixc/Properties/launchSettings.json b/src/AXSharp.compiler/src/ixc/Properties/launchSettings.json index d2dcbd3b..576682ef 100644 --- a/src/AXSharp.compiler/src/ixc/Properties/launchSettings.json +++ b/src/AXSharp.compiler/src/ixc/Properties/launchSettings.json @@ -6,11 +6,11 @@ }, "integration_plc": { "commandName": "Project", - "workingDirectory": "c:\\W\\Develop\\gh\\ix-ax\\axsharp\\src\\sanbox\\integration\\ix-integration-plc\\" + "workingDirectory": "c:\\W\\Develop\\gh\\ix-ax\\axopen\\src\\integrations\\ctrl\\" }, "ixc-simple-template": { "commandName": "Project", - "workingDirectory": "C:\\W\\Develop\\gh\\ix-ax\\ix.framework\\src\\templates.simple\\ctrl\\" + "workingDirectory": "C:\\W\\Develop\\gh\\ix-ax\\axopen\\src\\templates.simple\\ctrl\\" }, "ixc-template-ref": { "commandName": "Project",