Skip to content
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ A terminal command to open Unity projects quickly from the command line.

- macOS
- Windows
- Linux
- Linux (TBD)

## Commands

Expand Down
29 changes: 10 additions & 19 deletions src/ucll.tests/PlatformSupportTests.cs
Original file line number Diff line number Diff line change
@@ -1,25 +1,16 @@
using System.Runtime.InteropServices;

public class PlatformSupportTests
{
[Fact_PlatformOSX]
public void FindInstallationRootReturnsValidRoot()
[Theory]
[InlineData(typeof(MacSupport),
"/Applications/Unity/Hub/Editor/2022.3.10f1/Unity.app/Contents/MacOS/Unity",
"/Applications/Unity/Hub/Editor/2022.3.10f1")]
[InlineData(typeof(WindowsSupport),
@"C:\Program Files\Unity\Hub\Editor\6000.0.59f2\Editor\Unity.exe",
@"C:\Program Files\Unity\Hub\Editor\6000.0.59f2")]
public void FindInstallationRootReturnsValidRoot(Type platformSupportType, string editorPath, string expectedRoot)
{
PlatformSupport platformSupport = PlatformSupport.Create();
const string editorPath = "/Applications/Unity/Hub/Editor/2022.3.10f1/Unity.app/Contents/MacOS/Unity";
PlatformSupport platformSupport = (Activator.CreateInstance(platformSupportType) as PlatformSupport)!;
string root = platformSupport.FindInstallationRoot(editorPath);
Assert.Equal("/Applications/Unity/Hub/Editor/2022.3.10f1", root);
}

// ReSharper disable once InconsistentNaming
private sealed class Fact_PlatformOSX : FactAttribute
{
public Fact_PlatformOSX()
{
if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
Skip = "Test only runs on macOS";
}
}
Assert.Equal(expectedRoot, root);
}
}
7 changes: 5 additions & 2 deletions src/ucll/Shared/Platform/LinuxSupport.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
internal sealed class LinuxSupport : PlatformSupport
{
public override string FindInstallationRoot(string editorPath)
{
throw new NotImplementedException();
}

public override string FormatHubArgs(string args)
=> args; // Linux doesn't need the "--" prefix

Expand All @@ -11,8 +16,6 @@ public override ProcessStartInfo OpenFileWithApp(string filePath, string applica
return new ProcessStartInfo(applicationPath, filePath);
}

public override string RelativeEditorPathToExecutable => "Editor/Unity";

public override string UnityHubConfigDirectory => Path.Combine(UserHome, ".config/UnityHub");

public override ProcessStartInfo GetUnityProjectSearchProcess()
Expand Down
10 changes: 9 additions & 1 deletion src/ucll/Shared/Platform/MacSupport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,15 @@ public override ProcessStartInfo OpenFileWithApp(string filePath, string applica
return new ProcessStartInfo("open", $"-a \"{applicationPath}\" \"{filePath}\"");
}

public override string RelativeEditorPathToExecutable => "Contents/MacOS/Unity";
public override string FindInstallationRoot(string editorPath)
{
return editorPath.Replace("/Unity.app/Contents/MacOS/Unity", string.Empty);
}

public override string GetUnityExecutablePath(string path)
{
return Path.Combine(path, "Contents/MacOS/Unity");
}

public override string UnityHubConfigDirectory => Path.Combine(UserHome, "Library/Application Support/UnityHub");

Expand Down
7 changes: 3 additions & 4 deletions src/ucll/Shared/Platform/PlatformSupport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ public static PlatformSupport Create()
/// <summary>
/// Given the path to an editor executable, returns the root directory path of the installation.
/// </summary>
public string FindInstallationRoot(string editorPath)
=> new DirectoryInfo(editorPath.Replace(RelativeEditorPathToExecutable, string.Empty)).Parent!.FullName;
public abstract string FindInstallationRoot(string editorPath);

/// <summary>
/// Path to the Unity Hub executable or null if it doesn't exist (or couldn't be found).
Expand Down Expand Up @@ -69,9 +68,9 @@ public string FindInstallationRoot(string editorPath)
public abstract ProcessStartInfo OpenFileWithApp(string filePath, string applicationPath);

/// <summary>
/// The path from the installation bundle (macOS) or root (Windows) to the executable.
/// Converts an installation bundle path (macOS) to a path to the binary, if needed.
/// </summary>
public abstract string RelativeEditorPathToExecutable { get; }
public virtual string GetUnityExecutablePath(string path) => path;

/// <summary>
/// The path to the directory that contains Unity Hub config files.
Expand Down
5 changes: 4 additions & 1 deletion src/ucll/Shared/Platform/WindowsSupport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ public override ProcessStartInfo OpenFileWithApp(string filePath, string applica
return new ProcessStartInfo(applicationPath, $"\"{filePath}\"");
}

public override string RelativeEditorPathToExecutable => @"Editor\Unity.exe";
public override string FindInstallationRoot(string editorPath)
{
return editorPath.Replace(@"Editor\Unity.exe", string.Empty).TrimEnd('\\');
}

public override string UnityHubConfigDirectory =>
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "UnityHub");
Expand Down
13 changes: 7 additions & 6 deletions src/ucll/Shared/UnityHub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,19 @@ internal class UnityHub(PlatformSupport platformSupport)
public string GetEditorPath(string version)
{
// Fast: try the default install location first.
string? executablePath = platformSupport.FindDefaultEditorPath(version);
if (executablePath != null)
return executablePath;
string? editorPathDefault = platformSupport.FindDefaultEditorPath(version);
if (editorPathDefault != null)
return editorPathDefault;

// Fallback: query Unity Hub for custom installation locations.
var editors = ListInstalledEditors();
string? appBundlePath = editors.FirstOrDefault(p => p.Version == version).Path;
string? editorPathHub = editors.FirstOrDefault(p => p.Version == version).Path;

if (appBundlePath == null)
if (editorPathHub == null)
throw new UserException($"Unity version {version} is not installed.");

return Path.Combine(appBundlePath, platformSupport.RelativeEditorPathToExecutable);
// On macOS, the Unity Hub returns a path to the app bundle (Unity.app), but we need the binary within.
return platformSupport.GetUnityExecutablePath(editorPathHub);
}

public IEnumerable<string> GetRecentProjects(bool favoriteOnly = false)
Expand Down