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

Avoid unzipping .nupkg every time we need to read from .nuspec by saving .nuspec inside the package folder instead of .nupkg #570

Merged
merged 5 commits into from
Sep 29, 2023
Merged
Show file tree
Hide file tree
Changes from 4 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
14 changes: 9 additions & 5 deletions src/NuGetForUnity.Tests/Assets/Tests/Editor/NuGetTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -317,21 +317,25 @@ public void InstallAndSearchLocalPackageSource([Values] bool hierarchical)
// get the package file by installing it
NugetPackageInstaller.InstallIdentifier(package);
Assert.IsTrue(InstalledPackagesManager.IsInstalled(package), "The package was NOT installed: {0} {1}", package.Id, package.Version);
var packageFilePath = Path.Combine(
var nuspecFilePath = Path.Combine(
ConfigurationManager.NugetConfigFile.RepositoryPath,
$"{package.Id}.{package.Version}",
package.PackageFileName);
Assert.That(packageFilePath, Does.Exist.IgnoreDirectories);
package.SpecificationFileName);
Assert.That(nuspecFilePath, Does.Exist.IgnoreDirectories);

var nupkgFileName = $"{package.Id}.{package.Version}.nupkg";
var nupkgFilePath = Path.Combine(PackageCacheManager.CacheOutputDirectory, nupkgFileName);
Assert.That(nupkgFilePath, Does.Exist.IgnoreDirectories);

JoC0de marked this conversation as resolved.
Show resolved Hide resolved
// Hierarchical folder structures are supported in NuGet 3.3+.
// └─<packageID>
// └─<version>
// └─<packageID>.<version>.nupkg
// └─<packageID>.<packageVersion>.nupkg
var targetDirectory = Path.Combine(
tempDirectoryPath,
hierarchical ? $"{package.Id}{Path.DirectorySeparatorChar}{package.Version}" : string.Empty);
Directory.CreateDirectory(targetDirectory);
File.Copy(packageFilePath, Path.Combine(targetDirectory, Path.GetFileName(packageFilePath)));
File.Copy(nupkgFilePath, Path.Combine(targetDirectory, nupkgFileName));
NugetPackageUninstaller.UninstallAll(InstalledPackagesManager.InstalledPackages.ToList());
Assert.IsFalse(InstalledPackagesManager.IsInstalled(package), "The package is STILL installed: {0} {1}", package.Id, package.Version);

Expand Down
42 changes: 31 additions & 11 deletions src/NuGetForUnity/Editor/InstalledPackagesManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using NugetForUnity.Configuration;
using NugetForUnity.Helper;
Expand Down Expand Up @@ -170,14 +171,33 @@ internal static void UpdateInstalledPackages()
var stopwatch = Stopwatch.StartNew();
var manuallyInstalledPackagesNumber = 0;

// a package that was installed via NuGet will have the .nupkg it came from inside the folder
// a package that was installed via a old version of NuGetForUnity will have the .nupkg it came from inside the folder,
// as we updated the behavior to only keep the .nuspec. So we need to extract the .nuspec from the .nupkg
var nupkgFiles = Directory.GetFiles(ConfigurationManager.NugetConfigFile.RepositoryPath, "*.nupkg", SearchOption.AllDirectories);
foreach (var nupkgFile in nupkgFiles)
{
var package = NugetPackageLocal.FromNupkgFile(
nupkgFile,
new NugetPackageSourceLocal("Nupkg file from Project", Path.GetDirectoryName(nupkgFile)));
AddPackageToInstalledInternal(package, ref manuallyInstalledPackagesNumber);
using (var zip = ZipFile.OpenRead(nupkgFile))
{
foreach (var entry in zip.Entries)
{
var entryFullName = entry.FullName;

// extract only .nuspec and .nuspec.meta files
if (entryFullName.EndsWith(".nuspec.meta", StringComparison.Ordinal) ||
entryFullName.EndsWith(".nuspec", StringComparison.Ordinal))
{
PackageContentManager.ExtractPackageEntry(entry, Path.GetDirectoryName(nupkgFile));
}
}
}

// delete .nupkg and its .meta file to sync compatibility
File.Delete(nupkgFile);
var metaFile = $"{nupkgFile}.meta";
if (File.Exists(metaFile))
{
File.Delete($"{nupkgFile}.meta");
}
}

// if the source code & assets for a package are pulled directly into the project (ex: via a symlink/junction) it should have a .nuspec defining the package
popara96 marked this conversation as resolved.
Show resolved Hide resolved
Expand Down Expand Up @@ -226,16 +246,16 @@ internal static bool RemoveUnnecessaryPackages()
continue;
}

var pkgPath = Path.Combine(folder, $"{folderName}.nupkg");
if (!File.Exists(pkgPath))
var nuspecPath = Directory.GetFiles(folder, "*.nuspec").FirstOrDefault();
if (!File.Exists(nuspecPath))
{
// ignore folder not containing a nuget-package
// ignore folder not containing a nuspec file
continue;
}

var package = NugetPackageLocal.FromNupkgFile(
pkgPath,
new NugetPackageSourceLocal("Nupkg file already installed", Path.GetDirectoryName(pkgPath)));
var package = NugetPackageLocal.FromNuspecFile(
nuspecPath,
new NugetPackageSourceLocal("Nuspec file already installed", Path.GetDirectoryName(nuspecPath)));

var installed = PackagesConfigFile.Packages.Any(packageId => packageId.Equals(package));

Expand Down
2 changes: 1 addition & 1 deletion src/NuGetForUnity/Editor/Models/NugetPackageIdentifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public string Version
public string PackageFileName => $"{Id}.{Version}.nupkg";

/// <inheritdoc />
public string SpecificationFileName => $"{Id}.{Version}.nuspec";
public string SpecificationFileName => $"{Id}.nuspec";

/// <inheritdoc />
public bool IsPrerelease => PackageVersion.IsPrerelease;
Expand Down
13 changes: 13 additions & 0 deletions src/NuGetForUnity/Editor/Models/NugetPackageLocal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,18 @@ public static NugetPackageLocal FromNupkgFile(string nupkgFilePath, NugetPackage
package.DownloadUrl = nupkgFilePath;
return package;
}

/// <summary>
/// Loads a <see cref="NugetPackageLocal" /> from the .nuspec file at the given file-path.
/// </summary>
/// <param name="nuspecFilePath">The file-path to the .nuspec file to load.</param>
/// <param name="packageSource">The source this package was downloaded with / provided by.</param>
/// <returns>The <see cref="NugetPackageLocal" /> loaded from the .nuspec file.</returns>
public static NugetPackageLocal FromNuspecFile(string nuspecFilePath, NugetPackageSourceLocal packageSource)
{
var package = FromNuspec(NuspecFile.Load(nuspecFilePath), packageSource);
package.DownloadUrl = nuspecFilePath;
return package;
}
}
}
13 changes: 0 additions & 13 deletions src/NuGetForUnity/Editor/Models/NugetPackageV2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,5 @@ public static NugetPackageV2 FromNuspec(NuspecFile nuspec, NugetPackageSourceV2
FillFromNuspec(nuspec, package);
return package;
}

/// <summary>
/// Loads a <see cref="NugetPackageV2" /> from the .nupkg file at the given file-path.
/// </summary>
/// <param name="nupkgFilePath">The file-path to the .nupkg file to load.</param>
/// <param name="packageSource">The source this package was downloaded with / provided by.</param>
/// <returns>The <see cref="NugetPackageV2" /> loaded from the .nupkg file.</returns>
public static NugetPackageV2 FromNupkgFile(string nupkgFilePath, NugetPackageSourceV2 packageSource)
{
var package = FromNuspec(NuspecFile.FromNupkgFile(nupkgFilePath), packageSource);
package.DownloadUrl = nupkgFilePath;
return package;
}
}
}
5 changes: 1 addition & 4 deletions src/NuGetForUnity/Editor/NugetPackageInstaller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ private static bool Install(INugetPackage package, bool refreshAssets, bool inst
foreach (var entry in zip.Entries)
{
var entryFullName = entry.FullName;
if (PackageContentManager.ShouldSkipUnpackingOnPath(entryFullName, package.Id))
if (PackageContentManager.ShouldSkipUnpackingOnPath(entryFullName))
{
continue;
}
Expand Down Expand Up @@ -227,9 +227,6 @@ private static bool Install(INugetPackage package, bool refreshAssets, bool inst
Debug.LogWarningFormat("Couldn't find a library folder with a supported target-framework for the package {0}", package);
}
}

// copy the .nupkg inside the Unity project
File.Copy(cachedPackagePath, Path.Combine(baseDirectory, package.PackageFileName), true);
}
else
{
Expand Down
5 changes: 3 additions & 2 deletions src/NuGetForUnity/Editor/NuspecFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ public static NuspecFile FromNupkgFile(string nupkgFilePath)
{
var nuspec = new NuspecFile();

if (File.Exists(nupkgFilePath))
try
{
// get the .nuspec file from inside the .nupkg
using (var zip = ZipFile.OpenRead(nupkgFilePath))
Expand All @@ -152,8 +152,9 @@ public static NuspecFile FromNupkgFile(string nupkgFilePath)
}
}
}
else
catch (Exception e)
{
Debug.LogException(e);
Debug.LogErrorFormat("Package could not be read: {0}", nupkgFilePath);
nuspec.Description = $"COULD NOT LOAD {nupkgFilePath}";
}
Expand Down
13 changes: 1 addition & 12 deletions src/NuGetForUnity/Editor/PackageContentManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,8 @@ internal static void CleanInstallationDirectory(INugetPackageIdentifier package)
/// </param>
/// <param name="packageId">The id of the package that is extracted.</param>
/// <returns>True if the file can be skipped, is not needed.</returns>
internal static bool ShouldSkipUnpackingOnPath(string path, string packageId)
internal static bool ShouldSkipUnpackingOnPath(string path)
{
// skip a remnant .meta file that may exist from packages created by Unity
if (path.EndsWith($"{packageId}.nuspec.meta", StringComparison.Ordinal))
{
return true;
}

// skip directories & files that NuGet normally deletes
if (path.StartsWith("_rels/", StringComparison.Ordinal) || path.Contains("/_rels/"))
{
Expand All @@ -127,11 +121,6 @@ internal static bool ShouldSkipUnpackingOnPath(string path, string packageId)
return true;
}

if (path.EndsWith($"{packageId}.nuspec", StringComparison.Ordinal))
{
return true;
}

if (path.EndsWith("[Content_Types].xml", StringComparison.Ordinal))
{
return true;
Expand Down
Loading