diff --git a/src/NuGetForUnity.Cli/Program.cs b/src/NuGetForUnity.Cli/Program.cs
index eceb94f6..7b82b515 100644
--- a/src/NuGetForUnity.Cli/Program.cs
+++ b/src/NuGetForUnity.Cli/Program.cs
@@ -52,8 +52,7 @@ public static int Main(string[] args)
Application.SetUnityProjectPath(projectPath);
// need to disable dependency installation as UnityPreImportedLibraryResolver.GetAlreadyImportedLibs is not working outside Unity.
- NugetHelper.InstallDependencies = false;
- NugetHelper.Restore();
+ NugetHelper.Restore(false);
FixRoslynAnalyzerImportSettings();
return Debug.HasError ? 1 : 0;
}
diff --git a/src/NuGetForUnity.Tests/Assets/Tests/Editor/NuGetTests.cs b/src/NuGetForUnity.Tests/Assets/Tests/Editor/NuGetTests.cs
index 5329ade0..e5e77278 100644
--- a/src/NuGetForUnity.Tests/Assets/Tests/Editor/NuGetTests.cs
+++ b/src/NuGetForUnity.Tests/Assets/Tests/Editor/NuGetTests.cs
@@ -172,6 +172,24 @@ public void InstallStyleCopTest()
Assert.IsFalse(NugetHelper.IsInstalled(styleCopId), "The package is STILL installed: {0} {1}", styleCopId.Id, styleCopId.Version);
}
+ [Test]
+ public void InstallStyleCopWithoutDependenciesTest()
+ {
+ var styleCopPlusId = new NugetPackageIdentifier("StyleCopPlus.MSBuild", "4.7.49.5");
+ var styleCopId = new NugetPackageIdentifier("StyleCop.MSBuild", "4.7.49.0");
+
+ NugetHelper.InstallIdentifier(styleCopPlusId, installDependencies: false);
+
+ // StyleCopPlus depends on StyleCop, so they should both be installed
+ // it depends on version 4.7.49.0, so ensure it is also installed
+ Assert.IsTrue(NugetHelper.IsInstalled(styleCopPlusId), "The package was NOT installed: {0} {1}", styleCopPlusId.Id, styleCopPlusId.Version);
+ Assert.IsFalse(NugetHelper.IsInstalled(styleCopId), "The package SHOULD NOT be installed: {0} {1}", styleCopId.Id, styleCopId.Version);
+
+ // cleanup and uninstall everything
+ NugetHelper.UninstallAll(NugetHelper.InstalledPackages.ToList());
+ Assert.IsFalse(NugetHelper.IsInstalled(styleCopPlusId), "The package is STILL installed: {0} {1}", styleCopPlusId.Id, styleCopPlusId.Version);
+ }
+
[Test]
public void InstallSignalRClientTest()
{
@@ -604,8 +622,7 @@ public void TestPostprocessUninstall(string packageId, string packageVersion)
var assetsIndex = filepath.LastIndexOf("Assets", StringComparison.Ordinal);
filepath = filepath.Substring(assetsIndex);
- NugetPackageAssetPostprocessor.OnPostprocessAllAssets(new[]{filepath},
- null, null, null);
+ NugetPackageAssetPostprocessor.OnPostprocessAllAssets(new[] { filepath }, null, null, null);
Assert.IsFalse(NugetHelper.IsInstalled(package), "The package is STILL installed: {0} {1}", package.Id, package.Version);
}
diff --git a/src/NuGetForUnity/Editor/NugetConfigFile.cs b/src/NuGetForUnity/Editor/NugetConfigFile.cs
index e5ed037e..d6c6e2e4 100644
--- a/src/NuGetForUnity/Editor/NugetConfigFile.cs
+++ b/src/NuGetForUnity/Editor/NugetConfigFile.cs
@@ -20,6 +20,15 @@ public class NugetConfigFile
///
public const string FileName = "NuGet.config";
+ ///
+ /// Default timeout in seconds for all web requests.
+ ///
+ private const int DefaultRequestTimeout = 10;
+
+ private const string RequestTimeoutSecondsConfigKey = "RequestTimeoutSeconds";
+
+ private const string LockPackagesOnRestoreConfigKey = "LockPackagesOnRestore";
+
///
/// The incomplete path that is saved. The path is expanded and made public via the property above.
///
@@ -47,7 +56,7 @@ public class NugetConfigFile
public string DefaultPushSource { get; private set; }
///
- /// True to output verbose log messages to the console. False to output the normal level of messages.
+ /// Gets or sets a value indicating whether to output verbose log messages to the console. False to output the normal level of messages.
///
public bool Verbose { get; set; }
@@ -62,11 +71,22 @@ public class NugetConfigFile
///
public bool ReadOnlyPackageFiles { get; set; }
+ ///
+ /// Gets or sets the timeout in seconds used for all web requests to NuGet sources.
+ ///
+ public int RequestTimeoutSeconds { get; set; } = DefaultRequestTimeout;
+
+ ///
+ /// Gets or sets a value indicating whether the installed packages should be fixed, so only the packages that are configure inside the
+ /// 'package.config' are installed without installing the dependencies of them.
+ ///
+ public bool LockPackagesOnRestore { get; set; }
+
///
/// Saves this NuGet.config file to disk.
///
- /// The file-path to where this NuGet.config will be saved.
- public void Save(string filepath)
+ /// The file-path to where this NuGet.config will be saved.
+ public void Save(string filePath)
{
var configFile = new XDocument();
@@ -157,6 +177,22 @@ public void Save(string filepath)
config.Add(addElement);
}
+ if (RequestTimeoutSeconds != DefaultRequestTimeout)
+ {
+ addElement = new XElement("add");
+ addElement.Add(new XAttribute("key", RequestTimeoutSecondsConfigKey));
+ addElement.Add(new XAttribute("value", RequestTimeoutSeconds));
+ config.Add(addElement);
+ }
+
+ if (LockPackagesOnRestore)
+ {
+ addElement = new XElement("add");
+ addElement.Add(new XAttribute("key", LockPackagesOnRestoreConfigKey));
+ addElement.Add(new XAttribute("value", LockPackagesOnRestore.ToString().ToLower()));
+ config.Add(addElement);
+ }
+
var configuration = new XElement("configuration");
configuration.Add(packageSources);
configuration.Add(disabledPackageSources);
@@ -166,21 +202,21 @@ public void Save(string filepath)
configFile.Add(configuration);
- var fileExists = File.Exists(filepath);
+ var fileExists = File.Exists(filePath);
// remove the read only flag on the file, if there is one.
if (fileExists)
{
- var attributes = File.GetAttributes(filepath);
+ var attributes = File.GetAttributes(filePath);
if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
{
attributes &= ~FileAttributes.ReadOnly;
- File.SetAttributes(filepath, attributes);
+ File.SetAttributes(filePath, attributes);
}
}
- configFile.Save(filepath);
+ configFile.Save(filePath);
}
///
@@ -304,6 +340,14 @@ public static NugetConfigFile Load(string filePath)
{
configFile.ReadOnlyPackageFiles = bool.Parse(value);
}
+ else if (string.Equals(key, RequestTimeoutSecondsConfigKey, StringComparison.OrdinalIgnoreCase))
+ {
+ configFile.RequestTimeoutSeconds = int.Parse(value);
+ }
+ else if (string.Equals(key, LockPackagesOnRestoreConfigKey, StringComparison.OrdinalIgnoreCase))
+ {
+ configFile.LockPackagesOnRestore = bool.Parse(value);
+ }
}
}
@@ -311,9 +355,9 @@ public static NugetConfigFile Load(string filePath)
}
///
- /// Creates a NuGet.config file with the default settings at the given full filepath.
+ /// Creates a NuGet.config file with the default settings at the given full file-path.
///
- /// The full filepath where to create the NuGet.config file.
+ /// The full file-path where to create the NuGet.config file.
/// The loaded loaded off of the newly created default file.
public static NugetConfigFile CreateDefaultFile(string filePath)
{
diff --git a/src/NuGetForUnity/Editor/NugetHelper.cs b/src/NuGetForUnity/Editor/NugetHelper.cs
index 32c32a49..3f4d107b 100644
--- a/src/NuGetForUnity/Editor/NugetHelper.cs
+++ b/src/NuGetForUnity/Editor/NugetHelper.cs
@@ -102,14 +102,6 @@ static NugetHelper()
Directory.CreateDirectory(PackOutputDirectory);
}
- ///
- /// Gets or sets a value indicating whether when installing a NuGet package we also install its dependencies.
- /// This is required by the NuGetForUnity.Cli as the CLI only installs packages listed explicitly inside
- /// the because dependency resolution wouldn't work seamlessly
- /// as it can't detect libraries imported by Unity .
- ///
- internal static bool InstallDependencies { get; set; } = true;
-
///
/// The loaded NuGet.config file that holds the settings for NuGet.
///
@@ -131,14 +123,6 @@ public static PackagesConfigFile PackagesConfigFile
}
}
- ///
- /// Invalidates the currently loaded 'packages.config' so it is reloaded when it is accessed the next time.
- ///
- internal static void ReloadPackagesConfig()
- {
- packagesConfigFile = null;
- }
-
///
/// Gets the packages that are actually installed in the project.
///
@@ -160,6 +144,14 @@ private static Dictionary InstalledPackagesDictionary
}
}
+ ///
+ /// Invalidates the currently loaded 'packages.config' so it is reloaded when it is accessed the next time.
+ ///
+ internal static void ReloadPackagesConfig()
+ {
+ packagesConfigFile = null;
+ }
+
///
/// Loads the NuGet.config file.
///
@@ -905,13 +897,13 @@ void AddPackageToInstalled(NugetPackage package)
{
// set root packages as manually installed if none are marked as such
foreach (var rootPackage in GetInstalledRootPackages())
- {
- PackagesConfigFile.SetManuallyInstalledFlag(rootPackage);
- }
-
- PackagesConfigFile.Save(PackagesConfigFilePath);
+ {
+ PackagesConfigFile.SetManuallyInstalledFlag(rootPackage);
}
+
+ PackagesConfigFile.Save(PackagesConfigFilePath);
}
+ }
stopwatch.Stop();
LogVerbose("Getting installed packages took {0} ms", stopwatch.ElapsedMilliseconds);
@@ -1163,7 +1155,11 @@ private static void CopyStream(Stream input, Stream output)
/// The identifier of the package to install.
/// True to refresh the Unity asset database. False to ignore the changes (temporarily).
/// True to indicate we're calling method as result of Update and don't want to go through IsAlreadyImportedInEngine
- internal static bool InstallIdentifier(NugetPackageIdentifier package, bool refreshAssets = true, bool isUpdate = false)
+ /// True to also install all dependencies of the .
+ internal static bool InstallIdentifier(NugetPackageIdentifier package,
+ bool refreshAssets = true,
+ bool isUpdate = false,
+ bool installDependencies = true)
{
if (!isUpdate && IsAlreadyImportedInEngine(package, false))
{
@@ -1173,14 +1169,14 @@ internal static bool InstallIdentifier(NugetPackageIdentifier package, bool refr
var foundPackage = GetSpecificPackage(package);
- if (foundPackage != null)
+ if (foundPackage == null)
{
- foundPackage.IsManuallyInstalled = package.IsManuallyInstalled;
- return Install(foundPackage, refreshAssets, isUpdate);
+ Debug.LogErrorFormat("Could not find {0} {1} or greater.", package.Id, package.Version);
+ return false;
}
- Debug.LogErrorFormat("Could not find {0} {1} or greater.", package.Id, package.Version);
- return false;
+ foundPackage.IsManuallyInstalled = package.IsManuallyInstalled;
+ return Install(foundPackage, refreshAssets, isUpdate, installDependencies);
}
///
@@ -1204,8 +1200,9 @@ public static void LogVerbose(string format, params object[] args)
///
/// The package to install.
/// True to refresh the Unity asset database. False to ignore the changes (temporarily).
- /// True to indicate we're calling method as result of Update and don't want to go through IsAlreadyImportedInEngine
- public static bool Install(NugetPackage package, bool refreshAssets = true, bool isUpdate = false)
+ /// True to indicate we're calling method as result of Update and don't want to go through IsAlreadyImportedInEngine.
+ /// True to also install all dependencies of the .
+ public static bool Install(NugetPackage package, bool refreshAssets = true, bool isUpdate = false, bool installDependencies = true)
{
if (!isUpdate && IsAlreadyImportedInEngine(package, false))
{
@@ -1238,6 +1235,7 @@ public static bool Install(NugetPackage package, bool refreshAssets = true, bool
package.Version);
return Update(installedPackage, package, false);
}
+
LogVerbose(
"{0} {1} is installed. {2} or greater is needed, so using installed version.",
installedPackage.Id,
@@ -1266,7 +1264,7 @@ public static bool Install(NugetPackage package, bool refreshAssets = true, bool
0.1f);
}
- if (InstallDependencies)
+ if (installDependencies)
{
// install all dependencies for target framework
var frameworkGroup = GetNullableBestDependencyFrameworkGroupForCurrentSettings(package);
@@ -1285,7 +1283,7 @@ public static bool Install(NugetPackage package, bool refreshAssets = true, bool
foreach (var dependency in frameworkGroup.Dependencies)
{
LogVerbose("Installing Dependency: {0} {1}", dependency.Id, dependency.Version);
- var installed = InstallIdentifier(dependency);
+ var installed = InstallIdentifier(dependency, refreshAssets, installDependencies);
if (!installed)
{
throw new Exception(string.Format("Failed to install dependency: {0} {1}.", dependency.Id, dependency.Version));
@@ -1424,6 +1422,7 @@ private static void WarnIfDotNetAuthenticationIssue(Exception e)
/// Get the specified URL from the web. Throws exceptions if the request fails.
///
/// URL that will be loaded.
+ /// UserName that will be passed in the Authorization header or the request. If null, authorization is omitted.
/// Password that will be passed in the Authorization header or the request. If null, authorization is omitted.
/// Timeout in milliseconds or null to use the default timeout values of HttpWebRequest.
/// Stream containing the result.
@@ -1437,11 +1436,7 @@ public static Stream RequestUrl(string url, string userName, string password, in
var getRequest = (HttpWebRequest)WebRequest.Create(url);
#pragma warning restore SYSLIB0014 // Type or member is obsolete
getRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.None;
- if (timeOut.HasValue)
- {
- getRequest.Timeout = timeOut.Value;
- getRequest.ReadWriteTimeout = timeOut.Value;
- }
+ getRequest.Timeout = timeOut ?? NugetConfigFile.RequestTimeoutSeconds * 1000;
if (string.IsNullOrEmpty(password))
{
@@ -1471,7 +1466,8 @@ public static Stream RequestUrl(string url, string userName, string password, in
///
/// Restores all packages defined in packages.config.
///
- public static void Restore()
+ /// True to also install all dependencies of the packages listed in the .
+ public static void Restore(bool installDependencies = true)
{
UpdateInstalledPackages();
@@ -1498,7 +1494,7 @@ public static void Restore()
string.Format("Restoring {0} {1}", package.Id, package.Version),
currentProgress);
LogVerbose("---Restoring {0} {1}", package.Id, package.Version);
- InstallIdentifier(package);
+ InstallIdentifier(package, installDependencies: installDependencies);
somethingChanged = true;
}
diff --git a/src/NuGetForUnity/Editor/NugetPackageSource.cs b/src/NuGetForUnity/Editor/NugetPackageSource.cs
index db96eca9..ae1d0cfd 100644
--- a/src/NuGetForUnity/Editor/NugetPackageSource.cs
+++ b/src/NuGetForUnity/Editor/NugetPackageSource.cs
@@ -376,11 +376,12 @@ private List GetLocalPackages(string searchTerm = "",
///
/// Builds a list of NugetPackages from the XML returned from the HTTP GET request issued at the given URL.
/// Note that NuGet uses an Atom-feed (XML Syndicaton) superset called OData.
- /// See here http://www.odata.org/documentation/odata-version-2-0/uri-conventions/
+ /// See here http://www.odata.org/documentation/odata-version-2-0/uri-conventions/.
///
- ///
- ///
- ///
+ /// The url of the package to download.
+ /// The user-name credentials for the registry.
+ /// The credentials for the registry.
+ /// The information about the packages from the registry.
private List GetPackagesFromUrl(string url, string username, string password)
{
NugetHelper.LogVerbose("Getting packages from: {0}", url);
@@ -389,7 +390,7 @@ private List GetPackagesFromUrl(string url, string username, strin
stopwatch.Start();
var packages = new List();
- using (var responseStream = NugetHelper.RequestUrl(url, username, password, 10000))
+ using (var responseStream = NugetHelper.RequestUrl(url, username, password, null))
{
using (var streamReader = new StreamReader(responseStream))
{
@@ -445,13 +446,13 @@ private List GetLocalUpdates(IEnumerable installedPa
/// True to include prerelease packages (alpha, beta, etc).
/// True to include older versions that are not the latest version.
/// The specific frameworks to target?
- /// The version constraints?
+ /// The version constraints?
/// A list of all updates available.
public List GetUpdates(IEnumerable installedPackages,
bool includePrerelease = false,
bool includeAllVersions = false,
string targetFrameworks = "",
- string versionContraints = "")
+ string versionConstraints = "")
{
if (IsLocalPath)
{
@@ -497,7 +498,7 @@ public List GetUpdates(IEnumerable installedPackages
includePrerelease.ToString().ToLower(),
includeAllVersions.ToString().ToLower(),
targetFrameworks,
- versionContraints);
+ versionConstraints);
try
{
@@ -512,7 +513,7 @@ public List GetUpdates(IEnumerable installedPackages
{
// Some web services, such as VSTS don't support the GetUpdates API. Attempt to retrieve updates via FindPackagesById.
NugetHelper.LogVerbose("{0} not found. Falling back to FindPackagesById.", url);
- return GetUpdatesFallback(installedPackages, includePrerelease, includeAllVersions, targetFrameworks, versionContraints);
+ return GetUpdatesFallback(installedPackages, includePrerelease, includeAllVersions, targetFrameworks, versionConstraints);
}
Debug.LogErrorFormat("Unable to retrieve package list from {0}\n{1}", url, e);
diff --git a/src/NuGetForUnity/Editor/NugetPreferences.cs b/src/NuGetForUnity/Editor/NugetPreferences.cs
index cea39d2f..e8b141c3 100644
--- a/src/NuGetForUnity/Editor/NugetPreferences.cs
+++ b/src/NuGetForUnity/Editor/NugetPreferences.cs
@@ -71,6 +71,28 @@ public override void OnGUI(string searchContext)
NugetHelper.NugetConfigFile.Verbose = verbose;
}
+ var requestTimeout = EditorGUILayout.IntField(
+ new GUIContent(
+ "Request Timeout in seconds",
+ "Timeout used for web requests to the package source. A value of -1 can be used to disable timeout."),
+ NugetHelper.NugetConfigFile.RequestTimeoutSeconds);
+ if (requestTimeout != NugetHelper.NugetConfigFile.RequestTimeoutSeconds)
+ {
+ preferencesChangedThisFrame = true;
+ NugetHelper.NugetConfigFile.RequestTimeoutSeconds = requestTimeout;
+ }
+
+ var lockPackagesOnRestore = EditorGUILayout.Toggle(
+ new GUIContent(
+ "Lock Packages on Restore",
+ "When lock packages on restore is enabled only packages explicitly listed inside the 'packages.config' file will be installed. No dependencies are installed. This feature should only be used when having issues that unneeded or broken packages are installed."),
+ NugetHelper.NugetConfigFile.LockPackagesOnRestore);
+ if (lockPackagesOnRestore != NugetHelper.NugetConfigFile.LockPackagesOnRestore)
+ {
+ preferencesChangedThisFrame = true;
+ NugetHelper.NugetConfigFile.LockPackagesOnRestore = lockPackagesOnRestore;
+ }
+
EditorGUILayout.LabelField("Package Sources:");
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
diff --git a/src/NuGetForUnity/Editor/NugetWindow.cs b/src/NuGetForUnity/Editor/NugetWindow.cs
index 29357901..64852543 100644
--- a/src/NuGetForUnity/Editor/NugetWindow.cs
+++ b/src/NuGetForUnity/Editor/NugetWindow.cs
@@ -203,7 +203,7 @@ protected static void DisplayNugetWindow()
[MenuItem("NuGet/Restore Packages", false, 1)]
protected static void RestorePackages()
{
- NugetHelper.Restore();
+ NugetHelper.Restore(!NugetHelper.NugetConfigFile.LockPackagesOnRestore);
foreach (var nugetWindow in Resources.FindObjectsOfTypeAll())
{
nugetWindow.ClearViewCache();
diff --git a/src/NuGetForUnity/Editor/OnLoadNuGetPackageRestorer.cs b/src/NuGetForUnity/Editor/OnLoadNuGetPackageRestorer.cs
index 43b1f894..c867a1bc 100644
--- a/src/NuGetForUnity/Editor/OnLoadNuGetPackageRestorer.cs
+++ b/src/NuGetForUnity/Editor/OnLoadNuGetPackageRestorer.cs
@@ -2,10 +2,14 @@
namespace NugetForUnity
{
+ ///
+ /// Automatically restores NuGet packages when Unity opens the project.
+ ///
[InitializeOnLoad]
public static class OnLoadNuGetPackageRestorer
{
///
+ /// Initializes static members of the class.
/// Static constructor used by Unity to initialize NuGet and restore packages defined in packages.config.
///
static OnLoadNuGetPackageRestorer()
@@ -26,8 +30,8 @@ static OnLoadNuGetPackageRestorer()
// Load the NuGet.config file
NugetHelper.LoadNugetConfigFile();
- // restore packages - this will be called EVERY time the project is loaded or a code-file changes
- NugetHelper.Restore();
+ // restore packages - this will be called EVERY time the project is loaded
+ NugetHelper.Restore(!NugetHelper.NugetConfigFile.LockPackagesOnRestore);
}
}
}