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

Document how to resolve Version Conflicts #513

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
41 changes: 32 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ You can learn more about NuGet here: [nuget.org](https://www.nuget.org/)

NuGetForUnity provides a visual editor window to see available packages on the server, see installed packages, and see available package updates. A visual interface is also provided to create and edit _.nuspec_ files in order to define and publish your own NuGet packages from within Unity.

![](screenshots/online.png?raw=true)
<img alt="Online Packages Tap" src="docs/screenshots/online.png" height="500px" />

# How do I install NuGetForUnity?

Expand Down Expand Up @@ -62,11 +62,11 @@ Download the `*.unitypackage` file. Right-click on it in File Explorer and choos

To launch, select **NuGet → Manage NuGet Packages**

![](docs/screenshots/menu_item.png?raw=true)
<img alt="Menu Items" src="docs/screenshots/menu_item.png" height="170px" />

After several seconds (it can take some time to query the server for packages), you should see a window like this:

![](docs/screenshots/online.png?raw=true)
<img alt="Online Packages Tap" src="docs/screenshots/online.png" height="500px" />

The **Online** tab shows the packages available on the NuGet server.

Expand All @@ -89,13 +89,13 @@ Note: If the package is already installed an **Uninstall** button will be displa

The **Installed** tabs shows the packages already installed in the current Unity project.

![](docs/screenshots/installed.png?raw=true)
<img alt="Installed Packages Tap" src="docs/screenshots/installed.png" height="500px" />

Click the **Uninstall** button to uninstall the package.

The **Updates** tab shows the packages currently installed that have updates available on the server.

![](docs/screenshots/updates.png?raw=true)
<img alt="Updates Packages Tap" src="docs/screenshots/updates.png" height="500px" />

The version in brackets on the left is the new version number. The version in brackets in the **Update** button is the currently installed version.

Expand Down Expand Up @@ -128,13 +128,13 @@ You can change this to any other NuGet server (such as NuGet.Server or ProGet -

See more information about _NuGet.config_ files here: [https://docs.nuget.org/consume/nuget-config-settings](https://docs.nuget.org/consume/nuget-config-settings)

![](docs/screenshots/menu_item.png?raw=true)
<img alt="Menu Items" src="docs/screenshots/menu_item.png" height="170px" />

NuGetForUnity installs packages into the local repository path defined in the _NuGet.config_ file (`repositoryPath`). By default, this is set to the `Assets/Packages` folder. In the _NuGet.config_ file, this can either be a full path, or it can be a relative path based on the project's Assets folder. Note: You'll probably want your Packages folder to be ignored by your version control software to prevent NuGet packages from being versioned in your repository.

When a package is installed, the _packages.config_ file in the project is automatically updated with the specific package information, as well as all of the dependencies that are also installed. This allows for the packages to be restored from scratch at any point. The `Restore` operation is automatically run every time the project is opened or the code is recompiled in the project. It can be run manually by selecting the **NuGet → Restore Packages** menu item.

![](docs/screenshots/menu_item.png?raw=true)
<img alt="Menu Items" src="docs/screenshots/menu_item.png" height="170px" />

Note: Depending on the size and number of packages you need to install, the `Restore` operation could take a _long_ time, so please be patient. If it appears the Unity isn't launching or responding, wait a few more minutes before attempting to kill the process.

Expand All @@ -161,11 +161,11 @@ When this setting is set to `false` the assemblies of the NuGet package are only

First, you'll need to create a _.nuspec_ file that defines your package. In your Project window, right click where you want the _.nuspec_ file to go and select **NuGet → Create Nuspec File**.

![](docs/screenshots/nuspec_menu.png?raw=true)
<img alt="Create Nuspec Menu" src="docs/screenshots/nuspec_menu.png" height="400px" />

Select the new _.nuspec_ file and you should see something like this:

![](docs/screenshots/nuspec_editor.png?raw=true)
<img alt="Nuspec editor" src="docs/screenshots/nuspec_editor.png" height="500px" />

Input the appropriate information for your package (ID, Version, Author, Description, etc). Be sure to include whatever dependencies are required by your package.

Expand All @@ -177,6 +177,8 @@ Press the **Push** button to push your package up to the server. Be sure to set

You can use [NuGet.Server](http://nugetserver.net/), [NuGet Gallery](https://github.com/NuGet/NuGetGallery), [ProGet](http://inedo.com/proget), etc to create your own NuGet server.

> **Note:** NuGetForUnity currently only supports NuGet Api version v1

Alternatively, you can use a "local feed" which is just a folder on your hard-drive or a network share.

Be sure to set the proper URL/path in the _NuGet.config_ file and you should be good to go!
Expand All @@ -197,3 +199,24 @@ For more information see [.Net Tool Documentaion](https://learn.microsoft.com/en
## Usage

Restore nuget packages of a single Unity Project: `dotnet nugetforunity restore <PROJECT_PATH>`. If installed as a global tool it can be called without the `dotnet` prefix: `nugetforunity restore <PROJECT_PATH>`.

# Common issues when installing NuGet packages

In the .Net ecosystem Unity is relatively special as it doesn't use the standard .Net runtime from Microsoft instead, it uses a fork of the [Mono](https://docs.unity3d.com/Manual/Mono.html) runtime. For some platforms Unity even uses [IL2CPP](https://docs.unity3d.com/Manual/IL2CPP.html) that compiles all C# code to C++ code. So Unity also uses a different build-system. This can lead to some issues with NuGet packages that heavily depend on the standard .Net build-system. NuGetForUnity tries to handle most of the changes needed to allow using NuGet packages inside Unity but it is not able to resolve all issues. This section contains some common issues and potential solutions.

## Version Conflicts

If two NuGet packages depend on the same package but reference different versions of it, Unity shows a error like:

```
Assembly 'Assets/Packages/System.Diagnostics.EventLog.4.7.0/lib/netstandard2.0/System.Diagnostics.EventLog.dll' will not be loaded due to errors:
System.Diagnostics.EventLog references strong named System.Security.Principal.Windows Assembly references: 4.1.1.0 Found in project: 4.1.3.0.
Assembly Version Validation can be disabled in Player Settings "Assembly Version Validation"
```

As mentioned in the message this error can be suppressed by changing a setting. Just go to Edit -> Project Settings -> Player -> Scroll down and expand "Other Settings" than uncheck "Assembly Version Validation" under the "Configuration" section.

<details>
<summary>Screenshot of Player Settings</summary>
<img als="Assembly Version Validation settings page" src="docs/screenshots/assembly-version-validation-setting.png" height="550px" />
</details>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/screenshots/installed.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/screenshots/menu_item.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/screenshots/nuspec_editor.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/screenshots/online.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/screenshots/preferences.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/screenshots/updates.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/screenshots/updates_all.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 7 additions & 2 deletions src/NuGetForUnity/Editor/NuGetPackageTextureHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,12 @@ internal static Task<Texture2D> DownloadImage(string url)
try
{
var fromCache = false;
if (ExistsInDiskCache(url))
if (url.StartsWith("file://"))
{
// we only cache images coming from a remote server.
fromCache = true;
}
else if (ExistsInDiskCache(url))
{
url = "file:///" + GetFilePath(url);
fromCache = true;
Expand All @@ -35,7 +40,7 @@ internal static Task<Texture2D> DownloadImage(string url)
var downloadHandler = new DownloadHandlerTexture(false);

request.downloadHandler = downloadHandler;
request.timeout = 1;
request.timeout = 1; // 1 second
var operation = request.SendWebRequest();
operation.completed += asyncOperation =>
{
Expand Down
12 changes: 11 additions & 1 deletion src/NuGetForUnity/Editor/NugetPackage.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using UnityEngine;

Expand Down Expand Up @@ -39,8 +40,11 @@ public class NugetPackage : NugetPackageIdentifier, IEquatable<NugetPackage>, IE
[SerializeField]
private Texture2D icon;

public Task<Texture2D> iconTask;
private Task<Texture2D> iconTask;

/// <summary>
/// Gets or sets the URL for the location of the icon of the NuGet package.
/// </summary>
public string IconUrl;

/// <summary>
Expand Down Expand Up @@ -194,6 +198,12 @@ public static NugetPackage FromNuspec(NuspecFile nuspec)

package.Dependencies = nuspec.Dependencies;

// handle local icon files, preferred if the file exists.
if (!string.IsNullOrEmpty(nuspec.IconFilePath) && (string.IsNullOrEmpty(nuspec.IconUrl) || File.Exists(nuspec.IconFilePath)))
{
package.IconUrl = $"file:///{nuspec.IconFilePath}";
}

return package;
}

Expand Down
6 changes: 6 additions & 0 deletions src/NuGetForUnity/Editor/NugetWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,12 @@ private void DrawPackage(NugetPackage package, GUIStyle packageStyle, GUIStyle c
// as this is called every frame we don't need to wait for the task we can just use the image if it is available
icon = package.IconTask.Result;
}
else if (installed != null && installed.IconTask != null && installed.IconTask.IsCompleted && installed.IconTask.Result != null)
{
// fallback to the icon of the already installed package (somehow there are cases where the update package has no icon URL)
// as this is called every frame we don't need to wait for the task we can just use the image if it is available
icon = installed.IconTask.Result;
}

if (icon != null)
{
Expand Down
39 changes: 29 additions & 10 deletions src/NuGetForUnity/Editor/NuspecFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,18 @@ public NuspecFile()
/// </summary>
public string IconUrl { get; set; }

/// <summary>
/// Gets the path to a icon file. The path is relative to the root folder of the package. This is a alternative to using a URL <see cref="IconUrl" />
/// .
/// </summary>
public string Icon { get; private set; }

/// <summary>
/// Gets the full path to a icon file. This is only set if the .nuspec file contains a <see cref="Icon" />. This is a alternative to using a URL
/// <see cref="IconUrl" />.
/// </summary>
public string IconFilePath { get; private set; }

/// <summary>
/// Gets or sets a value indicating whether the license of the NuGet package needs to be accepted in order to use it.
/// </summary>
Expand Down Expand Up @@ -124,9 +136,9 @@ public NuspecFile()
public string Authors { get; set; }

/// <summary>
/// Loads the .nuspec file inside the .nupkg file at the given filepath.
/// Loads the .nuspec file inside the .nupkg file at the given file path.
/// </summary>
/// <param name="nupkgFilepath">The filepath to the .nupkg file to load.</param>
/// <param name="nupkgFilepath">The file path to the .nupkg file to load.</param>
/// <returns>The .nuspec file loaded from inside the .nupkg file.</returns>
public static NuspecFile FromNupkgFile(string nupkgFilepath)
{
Expand All @@ -142,30 +154,27 @@ public static NuspecFile FromNupkgFile(string nupkgFilepath)

using (var stream = entry.Open())
{
nuspec = Load(stream);
nuspec = Load(stream).SetIconFilePath(nupkgFilepath);
}
}
}
else
{
Debug.LogErrorFormat("Package could not be read: {0}", nupkgFilepath);

//nuspec.Id = packageId;
//nuspec.Version = packageVersion;
nuspec.Description = string.Format("COULD NOT LOAD {0}", nupkgFilepath);
}

return nuspec;
}

/// <summary>
/// Loads a .nuspec file at the given filepath.
/// Loads a .nuspec file at the given file path.
/// </summary>
/// <param name="filePath">The full filepath to the .nuspec file to load.</param>
/// <param name="filePath">The full file path to the .nuspec file to load.</param>
/// <returns>The newly loaded <see cref="NuspecFile" />.</returns>
public static NuspecFile Load(string filePath)
{
return Load(XDocument.Load(filePath));
return Load(XDocument.Load(filePath)).SetIconFilePath(filePath);
}

/// <summary>
Expand Down Expand Up @@ -202,6 +211,7 @@ public static NuspecFile Load(XDocument nuspecDocument)
nuspec.LicenseUrl = (string)metadata.Element(XName.Get("licenseUrl", nuspecNamespace)) ?? string.Empty;
nuspec.ProjectUrl = (string)metadata.Element(XName.Get("projectUrl", nuspecNamespace)) ?? string.Empty;
nuspec.IconUrl = (string)metadata.Element(XName.Get("iconUrl", nuspecNamespace)) ?? string.Empty;
nuspec.Icon = (string)metadata.Element(XName.Get("icon", nuspecNamespace)) ?? string.Empty;
nuspec.RequireLicenseAcceptance = bool.Parse((string)metadata.Element(XName.Get("requireLicenseAcceptance", nuspecNamespace)) ?? "False");
nuspec.Description = (string)metadata.Element(XName.Get("description", nuspecNamespace)) ?? string.Empty;
nuspec.Summary = (string)metadata.Element(XName.Get("summary", nuspecNamespace)) ?? string.Empty;
Expand Down Expand Up @@ -259,7 +269,6 @@ public static NuspecFile Load(XDocument nuspecDocument)
var filesElement = package.Element(XName.Get("files", nuspecNamespace));
if (filesElement != null)
{
//UnityEngine.Debug.Log("Loading files!");
foreach (var fileElement in filesElement.Elements(XName.Get("file", nuspecNamespace)))
{
var file = new NuspecContentFile();
Expand Down Expand Up @@ -402,5 +411,15 @@ private static string ConvertFromNupkgTargetFrameworkName(string targetFramework

return convertedTargetFramework;
}

private NuspecFile SetIconFilePath(string containingFilePath)
{
if (!string.IsNullOrEmpty(Icon))
{
IconFilePath = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(containingFilePath)), Icon);
}

return this;
}
}
}