@@ -427,101 +427,275 @@ function Find-UnitySetupInstaller {
427
427
} | Sort-Object - Property ComponentType
428
428
}
429
429
430
+ function Test-UnitySetupInstance {
431
+ [CmdletBinding ()]
432
+ param (
433
+ [parameter (Mandatory = $false )]
434
+ [UnityVersion ] $Version ,
435
+
436
+ [parameter (Mandatory = $false )]
437
+ [string ] $Path
438
+ )
439
+
440
+ $instance = Get-UnitySetupInstance | Select-UnitySetupInstance - Version $Version - Path $Path
441
+ return $null -ne $instance
442
+ }
443
+
444
+ <#
445
+ . Synopsis
446
+ Select installers by a version and/or components.
447
+ . DESCRIPTION
448
+ Filters a list of `UnitySetupInstaller` down to a specific version and/or specific components.
449
+ . PARAMETER Installers
450
+ List of installers that needs to be reduced.
451
+ . PARAMETER Version
452
+ What version of UnitySetupInstaller that you want to keep.
453
+ . PARAMETER Components
454
+ What components should be maintained.
455
+ . EXAMPLE
456
+ $installers = Find-UnitySetupInstaller -Version 2017.3.0f3
457
+ $installers += Find-UnitySetupInstaller -Version 2018.2.5f1
458
+ $installers | Select-UnitySetupInstaller -Component Windows,Linux,Mac
459
+ #>
460
+ function Select-UnitySetupInstaller {
461
+ [CmdletBinding ()]
462
+ param (
463
+ [parameter (ValueFromPipeline = $true )]
464
+ [UnitySetupInstaller []] $Installers ,
465
+
466
+ [parameter (Mandatory = $false )]
467
+ [UnityVersion ] $Version ,
468
+
469
+ [parameter (Mandatory = $false )]
470
+ [UnitySetupComponent ] $Components = [UnitySetupComponent ]::All
471
+ )
472
+ begin {
473
+ $selectedInstallers = @ ()
474
+ }
475
+ process {
476
+ # Keep only the matching version specified.
477
+ if ( $PSBoundParameters.ContainsKey (' Version' ) ) {
478
+ $Installers = $Installers | Where-Object { [UnityVersion ]::Compare($_.Version , $Version ) -eq 0 }
479
+ }
480
+
481
+ # Keep only the matching component(s).
482
+ $Installers = $Installers | Where-Object { $Components -band $_.ComponentType } | ForEach-Object { $_ }
483
+
484
+ $selectedInstallers += $Installers
485
+ }
486
+ end {
487
+ return $selectedInstallers
488
+ }
489
+ }
490
+
491
+ function Request-UnitySetupInstaller {
492
+ [CmdletBinding ()]
493
+ param (
494
+ [parameter (ValueFromPipeline = $true )]
495
+ [UnitySetupInstaller []] $Installers ,
496
+
497
+ [parameter (Mandatory = $false )]
498
+ [string ]$Cache = [io.Path ]::Combine(" ~" , " .unitysetup" )
499
+ )
500
+ begin {
501
+ # Note that this has to happen before calculating the full path since
502
+ # Resolve-Path throws an exception on missing paths.
503
+ if (! (Test-Path $Cache - PathType Container)) {
504
+ New-Item $Cache - ItemType Directory - ErrorAction Stop | Out-Null
505
+ }
506
+
507
+ # Expanding '~' to the absolute path on the system. `WebClient` on macOS asumes
508
+ # relative path. macOS also treats alt directory separators as part of the file
509
+ # name and this corrects the separators to current environment.
510
+ $fullCachePath = (Resolve-Path - Path $Cache ).Path
511
+
512
+ $downloads = @ ()
513
+ }
514
+ process {
515
+ $Installers | ForEach-Object {
516
+ $installerFileName = [io.Path ]::GetFileName($_.DownloadUrl )
517
+ $destination = [io.Path ]::Combine($fullCachePath , " Installers" , " Unity-$ ( $_.Version ) " , " $installerFileName " )
518
+
519
+ # Already downloaded?
520
+ if ( Test-Path $destination ) {
521
+ $destinationItem = Get-Item $destination
522
+ if ( ($destinationItem.Length -eq $_.Length ) -and
523
+ ($destinationItem.LastWriteTime -eq $_.LastModified ) ) {
524
+ Write-Verbose " Skipping download because it's already in the cache: $ ( $_.DownloadUrl ) "
525
+
526
+ $downloads += , $destination
527
+ return
528
+ }
529
+ }
530
+
531
+ $destinationDirectory = [io.path ]::GetDirectoryName($destination )
532
+ if (! (Test-Path $destinationDirectory - PathType Container)) {
533
+ New-Item " $destinationDirectory " - ItemType Directory | Out-Null
534
+ }
535
+
536
+ try
537
+ {
538
+ Write-Verbose " Downloading $ ( $_.DownloadUrl ) to $destination "
539
+ (New-Object System.Net.WebClient).DownloadFile($_.DownloadUrl , $destination )
540
+
541
+ # Re-writes the last modified time for ensuring downloads cache.
542
+ $downloadedFile = Get-Item $destination
543
+ $downloadedFile.LastWriteTime = $_.LastModified
544
+
545
+ $downloads += , $destination
546
+ }
547
+ catch [System.Net.WebException ]
548
+ {
549
+ Write-Error " Failed downloading $ ( $installerFileName ) : $ ( $_.Exception.Message ) "
550
+ }
551
+ }
552
+ }
553
+ end {
554
+ return $downloads
555
+ }
556
+ }
557
+
430
558
<#
431
559
. Synopsis
432
560
Installs a UnitySetup instance.
433
561
. DESCRIPTION
434
562
Downloads and installs UnitySetup installers found via Find-UnitySetupInstaller.
435
563
. PARAMETER Installers
436
564
What installers would you like to download and execute?
565
+ . PARAMETER BasePath
566
+ Under what base patterns is Unity customly installed at.
437
567
. PARAMETER Destination
438
568
Where would you like the UnitySetup instance installed?
439
569
. PARAMETER Cache
440
- Where should the installers be cached. This defaults to $env:USERPROFILE \.unitysetup.
570
+ Where should the installers be cached. This defaults to ~ \.unitysetup.
441
571
. EXAMPLE
442
572
Find-UnitySetupInstaller -Version 2017.3.0f3 | Install-UnitySetupInstance
443
573
. EXAMPLE
444
574
Find-UnitySetupInstaller -Version 2017.3.0f3 | Install-UnitySetupInstance -Destination D:\Unity-2017.3.0f3
575
+ . EXAMPLE
576
+ Find-UnitySetupInstaller -Version 2017.3.0f3 | Install-UnitySetupInstance -BasePath D:\UnitySetup\
577
+ . EXAMPLE
578
+ Find-UnitySetupInstaller -Version 2017.3.0f3 | Install-UnitySetupInstance -BasePath D:\UnitySetup\ -Destination Unity-2017
445
579
#>
446
580
function Install-UnitySetupInstance {
447
581
[CmdletBinding ()]
448
582
param (
449
583
[parameter (ValueFromPipeline = $true )]
450
584
[UnitySetupInstaller []] $Installers ,
451
585
586
+ [parameter (Mandatory = $false )]
587
+ [string ]$BasePath ,
588
+
452
589
[parameter (Mandatory = $false )]
453
590
[string ]$Destination ,
454
591
455
592
[parameter (Mandatory = $false )]
456
- [string ]$Cache = [io.Path ]::Combine($ env: USERPROFILE , " .unitysetup" )
593
+ [string ]$Cache = [io.Path ]::Combine(" ~ " , " .unitysetup" )
457
594
)
595
+ begin {
596
+ $currentOS = Get-OperatingSystem
597
+ if ($currentOS == [OperatingSystem ]::Linux) {
598
+ throw " Install-UnitySetupInstance has not been implemented on the Linux platform. Contributions welcomed!" ;
599
+ }
600
+
601
+ if ( -not $PSBoundParameters.ContainsKey (' BasePath' ) ) {
602
+ $defaultInstallPath = switch ($currentOS ) {
603
+ ([OperatingSystem ]::Windows) { ' C:\Program Files\Unity' }
604
+ ([OperatingSystem ]::Linux) { throw " Install-UnitySetupInstance has not been implemented on the Linux platform. Contributions welcomed!" ; }
605
+ ([OperatingSystem ]::Mac) { ' /Applications/Unity' }
606
+ }
607
+ }
608
+ else {
609
+ $defaultInstallPath = $BasePath
610
+ }
611
+
612
+ $unitySetupInstances = Get-UnitySetupInstance - BasePath $BasePath
458
613
614
+ $versionInstallers = @ {}
615
+ }
459
616
process {
460
- if (! (Test-Path $Cache - PathType Container)) {
461
- New-Item $Cache - ItemType Directory - ErrorAction Stop | Out-Null
617
+ # Sort each installer received from the pipe into versions
618
+ $Installers | ForEach-Object {
619
+ $versionInstallers [$_.Version ] += , $_
462
620
}
621
+ }
622
+ end {
623
+ # foreach unity version
624
+ # If macOS, move previous install back to default directory
625
+ # Install main Unity setup installer first
626
+ # Install all components to default Unity version
627
+ # If macOS, move install to versioned directory
628
+ $versionInstallers.Keys | ForEach-Object {
629
+ $installVersion = $_
630
+ $installerInstances = $versionInstallers [$installVersion ]
631
+
632
+ if ($currentOS == [OperatingSystem ]::Mac) {
633
+ # On macOS we must notify the user to take an action if the default location
634
+ # is currently in use. Either there's a previous version of Unity installed
635
+ # manually or another install through UnitySetup possibly failed.
636
+ if (Test-UnitySetupInstance - Path / Applications/ Unity/ ) {
637
+ # TODO: Work in a `$host.ui.PromptForChoice` / -Force param for resolving this.
638
+ throw " Install-UnitySetupInstance has not yet handled working around the base install directory already existing. Please move this manually and try again. Contributions welcomed!" ;
639
+ }
463
640
464
- $localInstallers = @ ()
465
- $localDestinations = @ ()
466
641
467
- $downloadSource = @ ()
468
- $downloadDest = @ ()
469
- foreach ( $i in $Installers ) {
470
- $fileName = [io.Path ]::GetFileName($i.DownloadUrl )
471
- $destPath = [io.Path ]::Combine($Cache , " Installers\Unity-$ ( $i.Version ) \$fileName " )
642
+ }
472
643
473
- $localInstallers += , $destPath
474
- if ($Destination ) {
475
- $localDestinations += , $Destination
644
+ if ( $PSBoundParameters.ContainsKey (' Destination' ) ) {
645
+ # Slight API change here. If BasePath is also provided treat Destination as a relative path.
646
+ if ( $PSBoundParameters.ContainsKey (' BasePath' ) ) {
647
+ $installPath = $Destination
648
+ }
649
+ else {
650
+ $installPath = [io.path ]::Combine($BasePath , $Destination )
651
+ }
476
652
}
477
653
else {
478
- $localDestinations += , " C:\Program Files\Unity- $ ( $i .Version ) "
654
+ $installPath = " $defaultInstallPath - $installVersion "
479
655
}
480
656
481
- if ( Test-Path $destPath ) {
482
- $destItem = Get-Item $destPath
483
- if ( ($destItem.Length -eq $i.Length ) -and ($destItem.LastWriteTime -eq $i.LastModified ) ) {
484
- Write-Verbose " Skipping download because it's already in the cache: $ ( $i.DownloadUrl ) "
485
- continue
486
- }
487
- }
657
+ $installerPaths = $installerInstances | Request-UnitySetupInstaller - Cache $Cache
488
658
489
- $downloadSource += $i.DownloadUrl
490
- $downloadDest += $destPath
491
- }
659
+ # TODO: Install Unity component first
492
660
493
- if ( $downloadSource.Length -gt 0 ) {
494
- for ($i = 0 ; $i -lt $downloadSource.Length ; $i ++ ) {
495
- Write-Verbose " Downloading $ ( $downloadSource [$i ]) to $ ( $downloadDest [$i ]) "
496
- $destDirectory = [io.path ]::GetDirectoryName($downloadDest [$i ])
497
- if (! (Test-Path $destDirectory - PathType Container)) {
498
- New-Item " $destDirectory " - ItemType Directory | Out-Null
661
+ foreach ($componentInstallerPath in $installerPaths ) {
662
+ switch ($currentOS ) {
663
+ ([OperatingSystem ]::Windows) {
664
+ $startProcessArgs = @ {
665
+ ' FilePath' = $_ ;
666
+ ' ArgumentList' = @ (" /S" , " /D=$installPath " );
667
+ ' PassThru' = $true ;
668
+ ' Wait' = $true ;
669
+ }
670
+ }
671
+ ([OperatingSystem ]::Linux) {
672
+ throw " Install-UnitySetupInstance has not been implemented on the Linux platform. Contributions welcomed!" ;
673
+ }
674
+ ([OperatingSystem ]::Mac) {
675
+ $startProcessArgs = @ {
676
+ ' FilePath' = $installer ;
677
+ ' ArgumentList' = @ (" /S" , " /D=$destination " );
678
+ ' PassThru' = $true ;
679
+ ' Wait' = $true ;
680
+ }
681
+ }
682
+ }
683
+
684
+ Write-Verbose " $ ( Get-Date ) : Installing $installer to $destination ."
685
+ $process = Start-Process @startProcessArgs
686
+ if ( $process ) {
687
+ if ( $process.ExitCode -ne 0 ) {
688
+ Write-Error " $ ( Get-Date ) : Failed with exit code: $ ( $process.ExitCode ) "
689
+ }
690
+ else {
691
+ Write-Verbose " $ ( Get-Date ) : Succeeded."
692
+ }
499
693
}
500
-
501
- (New-Object System.Net.WebClient).DownloadFile($downloadSource [$i ], $downloadDest [$i ])
502
694
}
503
- }
504
-
505
- for ($i = 0 ; $i -lt $localInstallers.Length ; $i ++ ) {
506
- $installer = $localInstallers [$i ]
507
- $destination = $localDestinations [$i ]
508
695
509
- $startProcessArgs = @ {
510
- ' FilePath' = $installer ;
511
- ' ArgumentList' = @ (" /S" , " /D=$destination " );
512
- ' PassThru' = $true ;
513
- ' Wait' = $true ;
514
- }
515
-
516
- Write-Verbose " $ ( Get-Date ) : Installing $installer to $destination ."
517
- $process = Start-Process @startProcessArgs
518
- if ( $process ) {
519
- if ( $process.ExitCode -ne 0 ) {
520
- Write-Error " $ ( Get-Date ) : Failed with exit code: $ ( $process.ExitCode ) "
521
- }
522
- else {
523
- Write-Verbose " $ ( Get-Date ) : Succeeded."
524
- }
696
+ # Move the install from the staging area to the desired destination
697
+ if ($currentOS == [OperatingSystem ]::Mac) {
698
+ Move-Item - Path / Applications/ Unity/ - Destination $installPath
525
699
}
526
700
}
527
701
}
@@ -626,14 +800,16 @@ function Get-UnitySetupInstance {
626
800
Select the latest version available.
627
801
. PARAMETER Version
628
802
Select only instances matching Version.
629
- . PARAMETER Project
630
- Select only instances matching the version of the project at Project .
803
+ . PARAMETER Path
804
+ Select only instances matching the project at the provided path .
631
805
. PARAMETER instances
632
806
The list of instances to Select from.
633
807
. EXAMPLE
634
808
Get-UnitySetupInstance | Select-UnitySetupInstance -Latest
635
809
. EXAMPLE
636
810
Get-UnitySetupInstance | Select-UnitySetupInstance -Version 2017.1.0f3
811
+ . EXAMPLE
812
+ Get-UnitySetupInstance | Select-UnitySetupInstance -Path (Get-Item /Applications/Unity*)
637
813
#>
638
814
function Select-UnitySetupInstance {
639
815
[CmdletBinding ()]
@@ -644,11 +820,21 @@ function Select-UnitySetupInstance {
644
820
[parameter (Mandatory = $false )]
645
821
[UnityVersion ] $Version ,
646
822
823
+ [parameter (Mandatory = $false )]
824
+ [string ] $Path ,
825
+
647
826
[parameter (Mandatory = $true , ValueFromPipeline = $true )]
648
827
[UnitySetupInstance []] $Instances
649
828
)
650
829
651
830
process {
831
+ if ( $PSBoundParameters.ContainsKey (' Path' ) ) {
832
+ $Path = $Path.TrimEnd ([io.path ]::DirectorySeparatorChar)
833
+ $Instances = $Instances | Where-Object {
834
+ $Path -eq (Get-Item $_.Path ).FullName.TrimEnd([io.path ]::DirectorySeparatorChar)
835
+ }
836
+ }
837
+
652
838
if ( $Version ) {
653
839
$Instances = $Instances | Where-Object { [UnityVersion ]::Compare($_.Version , $Version ) -eq 0 }
654
840
}
0 commit comments