Skip to content

Commit

Permalink
Fixed checking for packages already installed in Unity
Browse files Browse the repository at this point in the history
  • Loading branch information
popara96 committed Mar 27, 2023
1 parent 8186e20 commit 83a38ce
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 74 deletions.
90 changes: 19 additions & 71 deletions Assets/NuGet/Editor/NugetHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -499,69 +499,12 @@ private static void Clean(NugetPackageIdentifier package)
private static bool IsAlreadyImportedInEngine(NugetPackageIdentifier package)
{
if (package.IsManuallyInstalled) return false;
HashSet<string> alreadyImportedLibs = GetAlreadyImportedLibs();
HashSet<string> alreadyImportedLibs = UnityPreImportedLibraryResolver.GetAlreadyImportedLibs();
bool isAlreadyImported = alreadyImportedLibs.Contains(package.Id);
LogVerbose("Is package '{0}' already imported? {1}", package.Id, isAlreadyImported);
return isAlreadyImported;
}

private static HashSet<string> alreadyImportedLibs = null;
private static HashSet<string> GetAlreadyImportedLibs()
{
if (alreadyImportedLibs != null) return alreadyImportedLibs;

var cachePath = Path.Combine(SystemProxy.CurrentDir, $"../Library/AllLibPaths{SystemProxy.UnityVersion}.txt");
if (File.Exists(cachePath))
{
alreadyImportedLibs = new HashSet<string>(File.ReadAllLines(cachePath));
}
else
{
string[] lookupPaths = GetAllLookupPaths();
IEnumerable<string> libNames = lookupPaths
.SelectMany(directory => Directory.EnumerateFiles(directory, "*.dll", SearchOption.AllDirectories))
.Select(Path.GetFileName)
.Select(p => Path.ChangeExtension(p, null));
alreadyImportedLibs = new HashSet<string>(libNames);
if (!Directory.Exists("../Library/")) Directory.CreateDirectory("../Library/");
File.WriteAllLines(cachePath, alreadyImportedLibs);
LogVerbose("Already imported libs: {0}", string.Join(", ", alreadyImportedLibs));
}

return alreadyImportedLibs;
}

private static string[] GetAllLookupPaths()
{
var executablePath = SystemProxy.AppDir;
var roots = new[] {
// MacOS directory layout
Path.Combine(executablePath, "Contents"),
Path.GetDirectoryName(Path.GetDirectoryName(executablePath)),
// Windows directory layout
Path.Combine(Directory.GetParent(executablePath).FullName, "Data")
};
var relativePaths = new[] {
Path.Combine("NetStandard", "compat"),
Path.Combine("MonoBleedingEdge", "lib", "mono")
};
var allPossiblePaths = roots
.SelectMany(root => relativePaths
.Select(relativePath => Path.Combine(root, relativePath)));
var existingPaths = allPossiblePaths
.Where(Directory.Exists)
.ToArray();
if (existingPaths.Length == 0)
{
LogVerbose("No existing path for dependency lookup found in roots: {0}", string.Join(", ", roots));
}
else
{
LogVerbose("All existing path to dependency lookup are: {0}", string.Join(", ", existingPaths));
}
return existingPaths;
}

public static NugetFrameworkGroup GetBestDependencyFrameworkGroupForCurrentSettings(NugetPackage package)
{
var targetFrameworks = package.Dependencies.Select(x => x.TargetFramework);
Expand Down Expand Up @@ -1462,21 +1405,24 @@ public static bool Install(NugetPackage package, bool refreshAssets = true)
// look to see if the package (any version) is already installed


SystemProxy.DisplayProgress($"Installing {package.Id} {package.Version}", "Installing Dependencies", 0.1f);

// install all dependencies for target framework
var frameworkGroup = GetBestDependencyFrameworkGroupForCurrentSettings(package);

LogVerbose("Installing dependencies for TargetFramework: {0}", frameworkGroup.TargetFramework);
foreach (var dependency in frameworkGroup.Dependencies)
if (InstallDependencies)
{
LogVerbose("Installing Dependency: {0} {1}", dependency.Id, dependency.Version);
SystemProxy.DisplayProgress($"Installing {package.Id} {package.Version}", "Installing Dependencies", 0.1f);

var installed = InstallIdentifier(dependency, false);
if (!installed)
// install all dependencies for target framework
var frameworkGroup = GetBestDependencyFrameworkGroupForCurrentSettings(package);

LogVerbose("Installing dependencies for TargetFramework: {0}", frameworkGroup.TargetFramework);
foreach (var dependency in frameworkGroup.Dependencies)
{
SystemProxy.LogError($"Failed to install dependency: {dependency.Id} {dependency.Version}.");
return false;
LogVerbose("Installing Dependency: {0} {1}", dependency.Id, dependency.Version);

var installed = InstallIdentifier(dependency, false);
if (!installed)
{
SystemProxy.LogError($"Failed to install dependency: {dependency.Id} {dependency.Version}.");
return false;
}
}
}

Expand Down Expand Up @@ -1627,7 +1573,9 @@ public static bool Install(NugetPackage package, bool refreshAssets = true)

return installSuccess;
}


internal static bool InstallDependencies { get; set; } = true;

private static string PackageIdToMethodName(string pkgId, string packageTitle = "")
{
pkgId = pkgId.Replace("nordeus.", "").Replace("unity.", "");
Expand Down
2 changes: 1 addition & 1 deletion Assets/NuGet/Editor/NugetPreferences.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public static class NugetPreferences
/// <summary>
/// The current version of NuGet for Unity.
/// </summary>
public const string NuGetForUnityVersion = "3.0.9";
public const string NuGetForUnityVersion = "3.0.10";

/// <summary>
/// The current position of the scroll bar in the GUI.
Expand Down
101 changes: 101 additions & 0 deletions Assets/NuGet/Editor/UnityPreImportedLibraryResolver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;

#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.Compilation;
#endif

namespace NugetForUnity
{
/// <summary>
/// Helper to resolve what libraries are already known / imported by unity.
/// </summary>
internal static class UnityPreImportedLibraryResolver
{
private static HashSet<string> alreadyImportedLibs;

private static HashSet<string> alreadyImportedEditorOnlyLibraries;

/// <summary>
/// Gets all libraries that are already imported by unity so we shouldn't / don't need to install them as NuGet packages.
/// </summary>
/// <returns>A set of all names of libraries that are already imported by unity.</returns>
internal static HashSet<string> GetAlreadyImportedLibs()
{
if (alreadyImportedLibs != null)
{
return alreadyImportedLibs;
}
#if UNITY_EDITOR
// Find all the assemblies already installed by NuGetForUnity
var alreadyInstalledDllFileNames = new HashSet<string>();

if (NugetHelper.NugetConfigFile != null && Directory.Exists(NugetHelper.NugetConfigFile.RepositoryPath))
{
alreadyInstalledDllFileNames = new HashSet<string>(
Directory.EnumerateFiles(NugetHelper.NugetConfigFile.RepositoryPath, "*.dll", SearchOption.AllDirectories)
.Select(Path.GetFileNameWithoutExtension));
}

// Search the all project assemblies that are not editor only.
// We only use player assemblies as we don't need to collect UnityEditor assemblies, we don't support installing NuGet packages with reference to UnityEditor.
#if UNITY_2019_3_OR_NEWER
const AssembliesType assemblieType = AssembliesType.PlayerWithoutTestAssemblies;
#else
const AssembliesType assemblieType = AssembliesType.Player;
#endif
var projectAssemblies = CompilationPipeline.GetAssemblies(assemblieType)
.Where(playerAssembly => playerAssembly.flags != AssemblyFlags.EditorAssembly);

// Collect all referenced assemblies but exclude all assemblies installed by NuGetForUnity.
var porojectReferences = projectAssemblies.SelectMany(playerAssembly => playerAssembly.allReferences);
alreadyImportedLibs = new HashSet<string>(
porojectReferences.Select(compiledAssemblyReference => Path.GetFileNameWithoutExtension(compiledAssemblyReference))
.Where(assemblyName => !alreadyInstalledDllFileNames.Contains(assemblyName)));

if (PlayerSettings.GetApiCompatibilityLevel(EditorUserBuildSettings.selectedBuildTargetGroup) == ApiCompatibilityLevel.NET_Standard_2_0)
{
// mark NuGet packages that contain the .net standard references as already imported
alreadyImportedLibs.Add("NETStandard.Library");
alreadyImportedLibs.Add("Microsoft.NETCore.Platforms");
}

// the compiler / language is available by default
alreadyImportedLibs.Add("Microsoft.CSharp");

var editorOnlyAssemblies = CompilationPipeline.GetAssemblies(AssembliesType.Editor)
.Where(assembly => assembly.flags == AssemblyFlags.EditorAssembly)
.ToList();
var editorReferences = editorOnlyAssemblies.SelectMany(editorOnlyAssembly => editorOnlyAssembly.allReferences);
alreadyImportedEditorOnlyLibraries = new HashSet<string>(
editorReferences.Select(Path.GetFileNameWithoutExtension).Where(assemblyName => !alreadyImportedLibs.Contains(assemblyName)));

// com.unity.visualscripting uses .net 4.8 so it implicitly has System.CodeDom
if (!alreadyImportedLibs.Contains("System.CodeDom") &&
editorOnlyAssemblies.Any(editorOnlyAssembly => editorOnlyAssembly.name == "Unity.VisualScripting.Shared.Editor"))
{
alreadyImportedEditorOnlyLibraries.Add("System.CodeDom");
}

NugetHelper.LogVerbose("Already imported libs: {0}", string.Join(", ", alreadyImportedLibs));
NugetHelper.LogVerbose("Already imported editor only libraries: {0}", string.Join(", ", alreadyImportedEditorOnlyLibraries));
#endif
return alreadyImportedLibs;
}

/// <summary>
/// </summary>
/// <returns></returns>
internal static HashSet<string> GetAlreadyImportedEditorOnlyLibraries()
{
if (alreadyImportedEditorOnlyLibraries == null)
{
GetAlreadyImportedLibs();
}

return alreadyImportedEditorOnlyLibraries;
}
}
}
11 changes: 11 additions & 0 deletions Assets/NuGet/Editor/UnityPreImportedLibraryResolver.cs.meta

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

3 changes: 3 additions & 0 deletions CLI/nugetfu/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ public static int Main(string[] args)
SystemProxy.AppDir = args[1].Replace("'", "").Replace("\"", "");
}

// need to disable dependency installation as UnityPreImportedLibraryResolver.GetAlreadyImportedLibs is not working outside Unity.
NugetHelper.InstallDependencies = false;

return NugetHelper.Restore() ? 0 : 1;
}

Expand Down
3 changes: 3 additions & 0 deletions CLI/nugetfu/nugetfu.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@
<Compile Include="..\..\Assets\NuGet\Editor\JunctionPoint.cs">
<Link>JunctionPoint.cs</Link>
</Compile>
<Compile Include="..\..\Assets\NuGet\Editor\UnityPreImportedLibraryResolver.cs">
<Link>UnityPreImportedLibraryResolver.cs</Link>
</Compile>
</ItemGroup>

</Project>
7 changes: 5 additions & 2 deletions CreateDLL/CreateDLL.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DefineConstants>DEBUG;TRACE;UNITY_EDITOR;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
Expand All @@ -29,7 +29,7 @@
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<DefineConstants>TRACE;UNITY_EDITOR;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
Expand Down Expand Up @@ -110,6 +110,9 @@
<Link>UnityAssetProcessor.cs</Link>
</Compile>
<EmbeddedResource Include=".Templates\EditorAppInitializer.cs" />
<Compile Include="..\Assets\NuGet\Editor\UnityPreImportedLibraryResolver.cs">
<Link>UnityPreImportedLibraryResolver.cs</Link>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
Expand Down
Binary file modified Packager/NuGetForUnity.unitypackage
Binary file not shown.

0 comments on commit 83a38ce

Please sign in to comment.