diff --git a/README.md b/README.md index a4c5c01..80e788b 100644 --- a/README.md +++ b/README.md @@ -31,19 +31,19 @@ unity-cli [command] [options] - `unity-cli hub-install`: Install Unity Hub - `unity-cli hub-version`: Print Unity Hub version - `unity-cli hub-path`: Print Unity Hub executable path -- `unity-cli hub [args...]`: Run Unity Hub commands directly -- `unity-cli activate-license`: Activate a Unity license -- `unity-cli return-license`: Return a Unity license +- `unity-cli hub [options] `: Run [Unity Hub command line arguments](https://docs.unity3d.com/hub/manual/HubCLI.html) +- `unity-cli activate-license [options]`: Activate a Unity license +- `unity-cli return-license [options]`: Return a Unity license - `unity-cli license-version`: Print Unity License Client version -- `unity-cli setup-unity`: Find or install Unity Editor for a project/version -- `unity-cli create-project`: Create a new Unity project from a template -- `unity-cli run [args...]`: Run commands in [Unity Editor Command Line Arguments](https://docs.unity3d.com/Manual/EditorCommandLineArguments.html) +- `unity-cli setup-unity [options]`: Find or install Unity Editor for a project/version +- `unity-cli create-project [options]`: Create a new Unity project from a [template](https://docs.unity3d.com/hub/manual/Templates.html) +- `unity-cli run [options] `: Run [Unity Editor Command Line Arguments](https://docs.unity3d.com/Manual/EditorCommandLineArguments.html) #### Install Unity Hub and Editor ```bash unity-cli hub-install -unity-cli setup-unity --unity-version 2022.3.x --modules android,ios --json +unity-cli setup-unity --unity-version 2022.3.x --modules android,ios ``` #### Activate a Unity License @@ -61,5 +61,5 @@ unity-cli create-project --name "MyGame" --template com.unity.template.3d --unit #### Build a Project ```bash -unity-cli run --unity-editor --unity-project -quit -batchmode -executeMethod Utilities.Editor.BuildPipeline.UnityPlayerBuildTools.StartCommandLineBuild +unity-cli run --unity-editor --unity-project -quit -batchmode -executeMethod StartCommandLineBuild ``` diff --git a/package-lock.json b/package-lock.json index b3700a0..22019dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@rage-against-the-pixel/unity-cli", - "version": "1.0.4", + "version": "1.0.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@rage-against-the-pixel/unity-cli", - "version": "1.0.4", + "version": "1.0.5", "license": "MIT", "dependencies": { "@electron/asar": "^4.0.1", diff --git a/package.json b/package.json index 17a1be0..115cb7d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@rage-against-the-pixel/unity-cli", - "version": "1.0.4", + "version": "1.0.5", "description": "A command line utility for the Unity Game Engine.", "author": "RageAgainstThePixel", "license": "MIT", diff --git a/src/cli.ts b/src/cli.ts index b7e9b36..408d1c3 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -214,17 +214,17 @@ program.command('setup-unity') } const unityHub = new UnityHub(); - const editorPath = await unityHub.GetEditor(unityVersion, modules); + const unityEditor = await unityHub.GetEditor(unityVersion, modules); const output: { [key: string]: string } = { 'UNITY_HUB_PATH': unityHub.executable, - 'UNITY_EDITOR': editorPath + 'UNITY_EDITOR': unityEditor.editorPath }; if (unityProject) { output['UNITY_PROJECT_PATH'] = unityProject.projectPath; if (modules.includes('android')) { - await CheckAndroidSdkInstalled(editorPath, unityProject.projectPath); + await CheckAndroidSdkInstalled(unityEditor.editorPath, unityProject.projectPath); } } diff --git a/src/unity-editor.ts b/src/unity-editor.ts index d4b02d1..fec4347 100644 --- a/src/unity-editor.ts +++ b/src/unity-editor.ts @@ -12,6 +12,7 @@ import { spawn, ChildProcessByStdio, } from 'child_process'; +import { UnityVersion } from './unity-version'; export interface EditorCommand { args: string[]; @@ -31,7 +32,10 @@ export class UnityEditor { * @param editorPath The path to the Unity Editor installation. * @throws Will throw an error if the editor path is invalid or not executable. */ - constructor(public readonly editorPath: string) { + constructor( + public readonly editorPath: string, + public readonly version: UnityVersion | undefined = undefined + ) { if (!fs.existsSync(editorPath)) { throw new Error(`The Unity Editor path does not exist: ${editorPath}`); } @@ -39,19 +43,25 @@ export class UnityEditor { fs.accessSync(editorPath, fs.constants.X_OK); this.editorRootPath = UnityEditor.GetEditorRootPath(editorPath); - const match = editorPath.match(/(?\d+)\.(?\d+)\.(?\d+)/); + if (!version) { + const match = editorPath.match(/(?\d+)\.(?\d+)\.(?\w+)/); - if (!match) { - throw Error(`Invalid Unity Editor Path: ${editorPath}`); - } + if (!match || !match.groups) { + throw Error(`Invalid Unity Editor Path: ${editorPath}`); + } - const unityMajorVersion = match.groups?.major; + const unityMajorVersion = match.groups!.major; - if (!unityMajorVersion) { - throw Error(`Invalid Unity Major Version: ${editorPath}`); + if (!unityMajorVersion) { + throw Error(`Invalid Unity Major Version: ${editorPath}`); + } + + this.version = new UnityVersion(`${match.groups!.major}.${match.groups!.minor}.${match.groups!.patch}`); + } else { + this.version = version; } - this.autoAddNoGraphics = parseInt(unityMajorVersion, 10) > 2018; + this.autoAddNoGraphics = this.version.satisfies('>2018.0.0'); } /** diff --git a/src/unity-hub.ts b/src/unity-hub.ts index 908ed6c..a9aae4e 100644 --- a/src/unity-hub.ts +++ b/src/unity-hub.ts @@ -402,7 +402,7 @@ chmod -R 777 "$hubPath"`]); * @param modules The modules to install alongside the editor. * @returns The path to the Unity Editor executable. */ - public async GetEditor(unityVersion: UnityVersion, modules: string[]): Promise { + public async GetEditor(unityVersion: UnityVersion, modules: string[]): Promise { const retryErrorMessages = [ 'Editor already installed in this location', 'failed to download. Error given: Request timeout' @@ -442,6 +442,7 @@ chmod -R 777 "$hubPath"`]); if (installPath) { await DeleteDirectory(installPath); } + installPath = await this.installUnity(unityVersion, modules); } else { throw error; @@ -459,7 +460,7 @@ chmod -R 777 "$hubPath"`]); await this.patchBeeBackend(editorPath); if (unityVersion.isLegacy() || modules.length === 0) { - return editorPath; + return new UnityEditor(path.normalize(editorPath), unityVersion); } try { @@ -487,7 +488,7 @@ chmod -R 777 "$hubPath"`]); } } - return path.normalize(editorPath); + return new UnityEditor(path.normalize(editorPath), unityVersion); } /** @@ -503,6 +504,7 @@ chmod -R 777 "$hubPath"`]); private async checkInstalledEditors(unityVersion: UnityVersion, failOnEmpty: boolean, installPath: string | undefined = undefined): Promise { let editorPath = undefined; + if (!installPath) { const paths: string[] = await this.ListInstalledEditors(); @@ -578,7 +580,7 @@ chmod -R 777 "$hubPath"`]); throw new Error(`Failed to find installed Unity Editor: ${unityVersion.toString()}\n > ${error}`); } - this.logger.ci(`Found installed Unity Editor: ${editorPath}`); + this.logger.debug(`Found installed editor: "${editorPath}"`); return editorPath; } @@ -799,6 +801,8 @@ done } private async installUnity(unityVersion: UnityVersion, modules: string[]): Promise { + this.logger.ci(`Installing Unity ${unityVersion.toString()}...`); + if (unityVersion.isLegacy()) { return await this.installUnity4x(unityVersion); } @@ -848,7 +852,6 @@ done args.push('--cm'); } - this.logger.info(`Installing Unity ${unityVersion.toString()}...`); const output = await this.Exec(args, { showCommand: true, silent: false }); if (output.includes(`Error while installing an editor or a module from changeset`)) { @@ -871,7 +874,7 @@ done this.logger.info(`Running Unity ${unityVersion.toString()} installer...`); try { - await Exec(installerPath, ['/S', `/D=${installPath}`, '-Wait', '-NoNewWindow'], { silent: true, showCommand: true }); + await Exec('powershell', ['-Command', `Start-Process -FilePath \"${installerPath}\" -ArgumentList \"/S /D=${installPath}\" -Wait -NoNewWindow`], { silent: true, showCommand: true }); } catch (error) { this.logger.error(`Failed to install Unity ${unityVersion.toString()}: ${error}`); } finally { diff --git a/src/utilities.ts b/src/utilities.ts index efa160a..3c701b8 100644 --- a/src/utilities.ts +++ b/src/utilities.ts @@ -236,7 +236,7 @@ export async function TryKillProcess(procInfo: ProcInfo): Promise { logger.debug(`Killing child processes of ${procInfo.name} with pid: ${procInfo.pid}...`); try { if (process.platform === 'win32') { - const pwshCommand = 'powershell -Command "Get-CimInstance Win32_Process -Filter \'ParentProcessId=' + procInfo.pid + '\' | ForEach-Object { Stop-Process -Id $_.ProcessId -Force }"'; - await Exec('cmd', ['/c', pwshCommand], { silent: true }); + const command = `Get-CimInstance Win32_Process -Filter "ParentProcessId=${procInfo.pid}" | ForEach-Object { Stop-Process -Id $_.ProcessId -Force }`; + await Exec('powershell', ['-Command', command], { silent: true, showCommand: true }); } else { // linux and macos - const psOutput = await Exec('ps', ['-eo', 'pid,ppid,comm'], { silent: true }); + const psOutput = await Exec('ps', ['-eo', 'pid,ppid,comm'], { silent: true, showCommand: false }); const lines = psOutput.split('\n').slice(1); // Skip header line for (const line of lines) {