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="newInstallLocation">New placement for configs.</param>
internal static void MoveConfig(PackageInstallLocation newInstallLocation)
{
NugetConfigFile.ChangeInstallLocation(newInstallLocation);
var newConfigsPath = newInstallLocation == PackageInstallLocation.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;
}
}
}
113 changes: 92 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 @@ public class NugetConfigFile

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 @@ -87,7 +93,35 @@ public class NugetConfigFile
/// 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 => InstallLocation == PackageInstallLocation.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 +155,15 @@ public class NugetConfigFile
/// Gets or sets absolute path to directory containing packages.config file.
/// </summary>
[NotNull]
public string PackagesConfigDirectoryPath { get; set; } = Application.dataPath;
public string PackagesConfigDirectoryPath
{
get =>
InstallLocation == PackageInstallLocation.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 All @@ -144,6 +186,11 @@ public string RelativePackagesConfigDirectoryPath
/// </summary>
public int RequestTimeoutSeconds { get; set; } = DefaultRequestTimeout;

/// <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>
internal PackageInstallLocation InstallLocation { get; private set; }

/// <summary>
/// Gets the list of enabled plugins.
/// </summary>
Expand Down Expand Up @@ -297,18 +344,13 @@ public static NugetConfigFile Load([NotNull] string filePath)
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, "packageInstallLocation", 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.InstallLocation = (PackageInstallLocation)Enum.Parse(typeof(PackageInstallLocation), 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 +404,7 @@ public static NugetConfigFile CreateDefaultFile([NotNull] string filePath)
<add key=""All"" value=""(Aggregate source)"" />
</activePackageSource>
<config>
<add key=""packageInstallLocation"" value=""CustomWithinAssets"" />
<add key=""repositoryPath"" value=""./Packages"" />
<add key=""PackagesConfigDirectoryPath"" value=""."" />
<add key=""slimRestore"" value=""true"" />
Expand Down Expand Up @@ -454,18 +497,23 @@ public void Save([NotNull] string filePath)

var config = new XElement("config");

if (!string.IsNullOrEmpty(savedRepositoryPath))
addElement = new XElement("add");
addElement.Add(new XAttribute("key", "packageInstallLocation"));
addElement.Add(new XAttribute("value", InstallLocation.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 Expand Up @@ -553,5 +601,28 @@ public void Save([NotNull] string filePath)

configFile.Save(filePath);
}

/// <summary>
/// Changes the package install location config and also moves the packages.config to the new location.
/// </summary>
/// <param name="newInstallLocation">New install location to set.</param>
internal void ChangeInstallLocation(PackageInstallLocation newInstallLocation)
{
if (newInstallLocation == InstallLocation)
{
return;
}

var oldPackagesConfigPath = PackagesConfigFilePath;
InstallLocation = newInstallLocation;
UnityPathHelper.EnsurePackageInstallDirectoryIsSetup();
var newConfigPath = PackagesConfigFilePath;
File.Move(oldPackagesConfigPath, newConfigPath);
var configMeta = oldPackagesConfigPath + ".meta";
if (File.Exists(configMeta))
{
File.Move(configMeta, newConfigPath + ".meta");
}
}
}
}
22 changes: 22 additions & 0 deletions src/NuGetForUnity/Editor/Configuration/PackageInstallLocation.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>
internal enum PackageInstallLocation
{
/// <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>
/// .
InPackagesFolder,
}
}

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(AbsoluteAssetsPath, "../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 EnsurePackageInstallDirectoryIsSetup()
{
Directory.CreateDirectory(ConfigurationManager.NugetConfigFile.RepositoryPath);

if (ConfigurationManager.NugetConfigFile.InstallLocation == PackageInstallLocation.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