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

Packages install path can again be edited from preferences window #619

Merged
merged 9 commits into from
Apr 1, 2024
39 changes: 35 additions & 4 deletions src/NuGetForUnity/Editor/Configuration/ConfigurationManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,16 @@ public static class ConfigurationManager

static ConfigurationManager()
{
NugetConfigFileDirectoryPath = UnityPathHelper.AbsoluteAssetsPath;
NugetConfigFilePath = Path.Combine(NugetConfigFileDirectoryPath, NugetConfigFile.FileName);
NugetConfigFilePath = Path.Combine(UnityPathHelper.AbsoluteUnityPackagesNugetPath, NugetConfigFile.FileName);
if (File.Exists(NugetConfigFilePath))
{
NugetConfigFileDirectoryPath = UnityPathHelper.AbsoluteUnityPackagesNugetPath;
}
else
{
NugetConfigFilePath = Path.Combine(UnityPathHelper.AbsoluteAssetsPath, NugetConfigFile.FileName);
NugetConfigFileDirectoryPath = UnityPathHelper.AbsoluteAssetsPath;
}
}

/// <summary>
Expand All @@ -45,7 +53,7 @@ static ConfigurationManager()
/// <see cref="NugetConfigFile" />.
/// </remarks>
[NotNull]
public static string NugetConfigFilePath { get; }
public static string NugetConfigFilePath { get; private set; }

/// <summary>
/// Gets the loaded NuGet.config file that holds the settings for NuGet.
Expand All @@ -69,7 +77,7 @@ public static NugetConfigFile NugetConfigFile
/// Gets the path to the directory containing the NuGet.config file.
/// </summary>
[NotNull]
internal static string NugetConfigFileDirectoryPath { get; }
internal static string NugetConfigFileDirectoryPath { get; private set; }

/// <summary>
/// Gets a value indicating whether verbose logging is enabled.
Expand Down Expand Up @@ -207,5 +215,28 @@ public static INugetPackage GetSpecificPackage([NotNull] INugetPackageIdentifier
{
return ActivePackageSource.GetSpecificPackage(nugetPackageIdentifier);
}

/// <summary>
/// Moves the Nuget.config under newPlacement and updated local properties to point to it.
/// </summary>
/// <param name="newPlacement">New placement for configs.</param>
public static void MoveConfig(NugetPlacement newPlacement)
{
NugetConfigFile.ChangePlacement(newPlacement);
var newConfigsPath = newPlacement == NugetPlacement.InPackagesFolder ?
UnityPathHelper.AbsoluteUnityPackagesNugetPath :
UnityPathHelper.AbsoluteAssetsPath;
var newConfigFilePath = Path.Combine(newConfigsPath, NugetConfigFile.FileName);

File.Move(NugetConfigFilePath, newConfigFilePath);
var configMeta = NugetConfigFilePath + ".meta";
if (File.Exists(configMeta))
{
File.Move(configMeta, newConfigFilePath + ".meta");
}

NugetConfigFilePath = newConfigFilePath;
NugetConfigFileDirectoryPath = newConfigsPath;
}
}
}
110 changes: 89 additions & 21 deletions src/NuGetForUnity/Editor/Configuration/NugetConfigFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,17 @@

private const string SupportsPackageIdSearchFilterAttributeName = "supportsPackageIdSearchFilter";

/// <summary>
/// The incomplete path that is saved. The path is expanded and made public via the property above.
/// </summary>
[CanBeNull]
private string savedRepositoryPath;
[NotNull]
private readonly string unityPackagesNugetInstallPath = Path.Combine(UnityPathHelper.AbsoluteUnityPackagesNugetPath, "InstalledPackages");

[NotNull]
private string configuredRepositoryPath = "Packages";

[NotNull]
private string packagesConfigDirectoryPath = Application.dataPath;

[NotNull]
private string repositoryPath = Path.GetFullPath(Path.Combine(Application.dataPath, "Packages"));

/// <summary>
/// Gets the list of package sources that are defined in the NuGet.config file.
Expand All @@ -83,11 +89,44 @@
[CanBeNull]
public INugetPackageSource ActivePackageSource { get; private set; }

/// <summary>
/// Gets the value that tells the system how to determine where the packages are to be installed and configurations are to be stored.
/// </summary>
public NugetPlacement Placement { get; private set; }

/// <summary>
/// Gets the absolute path where packages are to be installed.
/// </summary>
[NotNull]
public string RepositoryPath { get; private set; } = Path.GetFullPath(Path.Combine(Application.dataPath, "Packages"));
public string RepositoryPath
{
get => Placement == NugetPlacement.InPackagesFolder ? unityPackagesNugetInstallPath : repositoryPath;

private set => repositoryPath = value;
}

/// <summary>
/// Gets or sets the incomplete path that is saved. The path is expanded and made public via the property above.
/// </summary>
[NotNull]
public string ConfiguredRepositoryPath
{
get => configuredRepositoryPath;

set
{
configuredRepositoryPath = value;

var expandedPath = Environment.ExpandEnvironmentVariables(value);

if (!Path.IsPathRooted(expandedPath))
{
expandedPath = Path.Combine(Application.dataPath, expandedPath);
}

RepositoryPath = Path.GetFullPath(expandedPath.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar));
}
}

/// <summary>
/// Gets the default package source to push NuGet packages to.
Expand Down Expand Up @@ -121,7 +160,12 @@
/// Gets or sets absolute path to directory containing packages.config file.
/// </summary>
[NotNull]
public string PackagesConfigDirectoryPath { get; set; } = Application.dataPath;
public string PackagesConfigDirectoryPath
{
get => Placement == NugetPlacement.InPackagesFolder ? UnityPathHelper.AbsoluteUnityPackagesNugetPath : packagesConfigDirectoryPath;

set => packagesConfigDirectoryPath = value;
}

/// <summary>
/// Gets the relative path to directory containing packages.config file. The path is relative to the folder containing the 'NuGet.config' file.
Expand Down Expand Up @@ -149,13 +193,36 @@
/// </summary>
internal List<NugetForUnityPluginId> EnabledPlugins { get; } = new List<NugetForUnityPluginId>();

/// <summary>
/// Changes the placement config and also moves the packages.config to the new location.
/// </summary>
/// <param name="newPlacement">New placement to set.</param>
public void ChangePlacement(NugetPlacement newPlacement)
{
if (newPlacement == Placement)
{
return;
}

var oldPackagesConfigPath = PackagesConfigFilePath;
Placement = newPlacement;
UnityPathHelper.EnsurePackageInstallDirIsSetup();
var newConfigPath = PackagesConfigFilePath;
File.Move(oldPackagesConfigPath, newConfigPath);
var configMeta = oldPackagesConfigPath + ".meta";
if (File.Exists(configMeta))
{
File.Move(configMeta, newConfigPath + ".meta");
}
}

/// <summary>
/// Loads a NuGet.config file at the given file-path.
/// </summary>
/// <param name="filePath">The full file-path to the NuGet.config file to load.</param>
/// <returns>The newly loaded <see cref="NugetConfigFile" />.</returns>
[NotNull]
public static NugetConfigFile Load([NotNull] string filePath)

Check warning on line 225 in src/NuGetForUnity/Editor/Configuration/NugetConfigFile.cs

View workflow job for this annotation

GitHub Actions / Pack .NET Core Global Tool (CLI) and PluginAPI

{
var configFile = new NugetConfigFile
{
Expand Down Expand Up @@ -297,18 +364,13 @@
var key = add.Attribute("key")?.Value;
var value = add.Attribute("value")?.Value ?? throw new InvalidOperationException($"config misses 'value' attribute. Element:\n{add}");

if (string.Equals(key, "repositoryPath", StringComparison.OrdinalIgnoreCase))
if (string.Equals(key, "Placement", StringComparison.OrdinalIgnoreCase))
{
configFile.savedRepositoryPath = value;
configFile.RepositoryPath = Environment.ExpandEnvironmentVariables(value);

if (!Path.IsPathRooted(configFile.RepositoryPath))
{
configFile.RepositoryPath = Path.Combine(Application.dataPath, configFile.RepositoryPath);
}

configFile.RepositoryPath = Path.GetFullPath(
configFile.RepositoryPath.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar));
configFile.Placement = (NugetPlacement)Enum.Parse(typeof(NugetPlacement), value);
}
else if (string.Equals(key, "repositoryPath", StringComparison.OrdinalIgnoreCase))
{
configFile.ConfiguredRepositoryPath = value;
}
else if (string.Equals(key, "DefaultPushSource", StringComparison.OrdinalIgnoreCase))
{
Expand Down Expand Up @@ -362,6 +424,7 @@
<add key=""All"" value=""(Aggregate source)"" />
</activePackageSource>
<config>
<add key=""Placement"" value=""CustomWithinAssets"" />
<add key=""repositoryPath"" value=""./Packages"" />
<add key=""PackagesConfigDirectoryPath"" value=""."" />
<add key=""slimRestore"" value=""true"" />
Expand Down Expand Up @@ -454,18 +517,23 @@

var config = new XElement("config");

if (!string.IsNullOrEmpty(savedRepositoryPath))
addElement = new XElement("add");
addElement.Add(new XAttribute("key", "Placement"));
addElement.Add(new XAttribute("value", Placement.ToString()));
config.Add(addElement);

if (!string.IsNullOrEmpty(ConfiguredRepositoryPath))
{
// save the un-expanded repository path
addElement = new XElement("add");
addElement.Add(new XAttribute("key", "repositoryPath"));
addElement.Add(new XAttribute("value", savedRepositoryPath));
addElement.Add(new XAttribute("value", ConfiguredRepositoryPath));
config.Add(addElement);
}

addElement = new XElement("add");
addElement.Add(new XAttribute("key", PackagesConfigDirectoryPathConfigKey));
addElement.Add(new XAttribute("value", RelativePackagesConfigDirectoryPath));
addElement.Add(new XAttribute("value", PathHelper.GetRelativePath(Application.dataPath, packagesConfigDirectoryPath)));
config.Add(addElement);

// save the default push source
Expand Down
22 changes: 22 additions & 0 deletions src/NuGetForUnity/Editor/Configuration/NugetPlacement.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace NugetForUnity.Configuration
{
/// <summary>
/// Tells the system how to determine where the packages are to be installed and configurations are to be stored.
/// </summary>
public enum NugetPlacement
JoC0de marked this conversation as resolved.
Show resolved Hide resolved
JoC0de marked this conversation as resolved.
Show resolved Hide resolved
{
/// <summary>
/// This option will place Nuget.config into the Assets folder and will allow the user to
/// specify custom location within Assets folder for packages.config and package installation
/// folder.
/// </summary>
CustomWithinAssets,

/// <summary>
/// This options will place the Nuget.config and packages.config under Packages/nuget-packages
/// and will install the packages under Packages/nuget-packages/InstalledPackages.
/// </summary>
/// .
JoC0de marked this conversation as resolved.
Show resolved Hide resolved
InPackagesFolder,
}
}
3 changes: 3 additions & 0 deletions src/NuGetForUnity/Editor/Configuration/NugetPlacement.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion src/NuGetForUnity/Editor/Configuration/PackagesConfigFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,9 @@ internal static void Move([NotNull] string newPath)
var nugetConfig = ConfigurationManager.NugetConfigFile;
var oldFilePath = nugetConfig.PackagesConfigFilePath;
var oldPath = nugetConfig.PackagesConfigDirectoryPath;
nugetConfig.PackagesConfigDirectoryPath = newPath;

// We need to make sure saved path is using forward slashes so it works on all systems
nugetConfig.PackagesConfigDirectoryPath = newPath.Replace("\\", "/");
var newFilePath = Path.GetFullPath(Path.Combine(newPath, FileName));
try
{
Expand Down
42 changes: 41 additions & 1 deletion src/NuGetForUnity/Editor/Helper/UnityPathHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System;
using System.IO;
using JetBrains.Annotations;
using NugetForUnity.Configuration;
using UnityEngine;

#region No ReShaper
Expand All @@ -28,8 +29,15 @@ static UnityPathHelper()
{
AbsoluteAssetsPath = Path.GetFullPath(Application.dataPath);
AbsoluteProjectPath = Path.GetDirectoryName(AbsoluteAssetsPath) ?? throw new InvalidOperationException("Can't detect project root.");
AbsoluteUnityPackagesNugetPath = Path.GetFullPath(Path.Combine(Application.dataPath, "../Packages/nuget-packages"));
}

/// <summary>
/// Gets the absolute path to 'project root'/Packages/nuget-packages.
/// </summary>
[NotNull]
internal static string AbsoluteUnityPackagesNugetPath { get; }

/// <summary>
/// Gets the absolute path to the Unity-Project 'Assets' directory.
/// </summary>
Expand All @@ -53,10 +61,42 @@ internal static bool IsPathInAssets([NotNull] string path)
return !Path.IsPathRooted(assetsRelativePath) && !assetsRelativePath.StartsWith("..", StringComparison.Ordinal);
}

/// <summary>
/// Checks if given relative path is a valid for packages installations.
/// </summary>
/// <param name="path">Relative path to check.</param>
/// <returns>True if path is within Assets folder or Packages subfolder, false otherwise.</returns>
internal static bool IsValidInstallPath([NotNull] string path)
{
return !Path.IsPathRooted(path) && !path.StartsWith("..", StringComparison.Ordinal);
}

/// <summary>
/// Ensures that the package install directory exists and in case it is under Unity's
/// Packages folder that it contains a dummy package.json file so that Unity can see it.
/// </summary>
internal static void EnsurePackageInstallDirIsSetup()
JoC0de marked this conversation as resolved.
Show resolved Hide resolved
{
Directory.CreateDirectory(ConfigurationManager.NugetConfigFile.RepositoryPath);

if (ConfigurationManager.NugetConfigFile.Placement == NugetPlacement.CustomWithinAssets)
{
return;
}

var jsonPath = Path.Combine(AbsoluteUnityPackagesNugetPath, "package.json");
if (!File.Exists(jsonPath))
{
File.WriteAllText(
jsonPath,
@"{ ""name"": ""nuget-packages"",""version"": ""1.0.0"",""displayName"": ""NuGetPackages"", ""description"": ""NuGetPackages"", ""dependencies"": {}}");
}
}

/// <summary>
/// Returns the path relative to Assets directory, or <c>"."</c> if it is the Assets directory.
/// </summary>
/// <param name="path">The path of witch we calculate the relative path of.</param>
/// <param name="path">The path of which we calculate the relative path of.</param>
/// <returns>The path relative to Assets directory, or <c>"."</c> if it is the Assets directory.</returns>
[NotNull]
private static string GetAssetsRelativePath([NotNull] string path)
Expand Down
2 changes: 1 addition & 1 deletion src/NuGetForUnity/Editor/NugetPackageInstaller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ private static bool Install([NotNull] INugetPackage package, bool refreshAssets,

if (File.Exists(cachedPackagePath))
{
var baseDirectory = Path.Combine(ConfigurationManager.NugetConfigFile.RepositoryPath, $"{package.Id}.{package.Version}");
var baseDirectory = package.GetPackageInstallPath();

// unzip the package
using (var zip = ZipFile.OpenRead(cachedPackagePath))
Expand Down
Loading
Loading