From 78f33bc002816dd690047a7a38077b6ac6617d44 Mon Sep 17 00:00:00 2001
From: "John W. Parent" <45471568+johnwparent@users.noreply.github.com>
Date: Tue, 27 Jun 2023 21:26:51 -0400
Subject: Windows: Add PowerShell env support (#37951)

PowerShell requires explicit shell and env support in Spack.
This is due to the distinct differences in shell interactions between
cmd and pwsh. Add a doskey in pwsh piping 'spack' commands to a
powershell script similar to the sh function 'spack'. Add
support for PowerShell-specific shell interactions from Spack
(set/unset shell variables).
---
 bin/spack.bat |   2 +-
 bin/spack.ps1 | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 133 insertions(+), 1 deletion(-)
 create mode 100644 bin/spack.ps1

(limited to 'bin')

diff --git a/bin/spack.bat b/bin/spack.bat
index 514c2706d7..9aff863a90 100644
--- a/bin/spack.bat
+++ b/bin/spack.bat
@@ -214,7 +214,7 @@ goto :end_switch
 if defined _sp_args (
     if NOT "%_sp_args%"=="%_sp_args:--help=%" (
         goto :default_case
-    ) else if NOT "%_sp_args%"=="%_sp_args: -h=%" (
+    ) else if NOT "%_sp_args%"=="%_sp_args:-h=%" (
         goto :default_case
     ) else if NOT "%_sp_args%"=="%_sp_args:--bat=%" (
         goto :default_case
diff --git a/bin/spack.ps1 b/bin/spack.ps1
new file mode 100644
index 0000000000..39fe0167ca
--- /dev/null
+++ b/bin/spack.ps1
@@ -0,0 +1,132 @@
+#  Copyright 2013-2023 Lawrence Livermore National Security, LLC and other
+#  Spack Project Developers. See the top-level COPYRIGHT file for details.
+
+#  SPDX-License-Identifier: (Apache-2.0 OR MIT)
+# #######################################################################
+
+function Compare-CommonArgs {
+    $CMDArgs = $args[0]
+    # These aruments take precedence and call for no futher parsing of arguments
+    # invoke actual Spack entrypoint with that context and exit after
+    "--help", "-h", "--version", "-V" | ForEach-Object {
+        $arg_opt = $_
+        if(($CMDArgs) -and ([bool]($CMDArgs.Where({$_ -eq $arg_opt})))) {
+            return $true
+        }
+    }
+    return $false
+}
+
+function Read-SpackArgs {
+    $SpackCMD_params = @()
+    $SpackSubCommand = $NULL
+    $SpackSubCommandArgs = @()
+    $args_ = $args[0]
+    $args_ | ForEach-Object {
+        if (!$SpackSubCommand) {
+            if($_.SubString(0,1) -eq "-")
+            {
+                $SpackCMD_params += $_
+            }
+            else{
+                $SpackSubCommand = $_
+            }
+        }
+        else{
+            $SpackSubCommandArgs += $_
+        }
+    }
+    return $SpackCMD_params, $SpackSubCommand, $SpackSubCommandArgs
+}
+
+function Invoke-SpackCD {
+    if (Compare-CommonArgs $SpackSubCommandArgs) {
+        python $Env:SPACK_ROOT/bin/spack cd -h
+    }
+    else {
+        $LOC = $(python $Env:SPACK_ROOT/bin/spack location $SpackSubCommandArgs)
+        if (($NULL -ne $LOC)){
+            if ( Test-Path -Path $LOC){
+                Set-Location $LOC
+            }
+            else{
+                exit 1
+            }
+        }
+        else {
+            exit 1
+        }
+    }
+}
+
+function Invoke-SpackEnv {
+    if (Compare-CommonArgs $SpackSubCommandArgs[0]) {
+        python $Env:SPACK_ROOT/bin/spack env -h
+    }
+    else {
+        $SubCommandSubCommand = $SpackSubCommandArgs[0]
+        $SubCommandSubCommandArgs = $SpackSubCommandArgs[1..$SpackSubCommandArgs.Count]
+        switch ($SubCommandSubCommand) {
+            "activate" {
+                if (Compare-CommonArgs $SubCommandSubCommandArgs) {
+                    python $Env:SPACK_ROOT/bin/spack env activate $SubCommandSubCommandArgs
+                }
+                elseif ([bool]($SubCommandSubCommandArgs.Where({$_ -eq "--pwsh"}))) {
+                    python $Env:SPACK_ROOT/bin/spack env activate $SubCommandSubCommandArgs
+                }
+                elseif (!$SubCommandSubCommandArgs) {
+                    python $Env:SPACK_ROOT/bin/spack env activate $SubCommandSubCommandArgs
+                }
+                else {
+                    $SpackEnv = $(python $Env:SPACK_ROOT/bin/spack $SpackCMD_params env activate "--pwsh" $SubCommandSubCommandArgs)
+                    $ExecutionContext.InvokeCommand($SpackEnv)
+                }
+            }
+            "deactivate" {
+                if ([bool]($SubCommandSubCommandArgs.Where({$_ -eq "--pwsh"}))) {
+                    python $Env:SPACK_ROOT/bin/spack env deactivate $SubCommandSubCommandArgs
+                }
+                elseif($SubCommandSubCommandArgs) {
+                    python $Env:SPACK_ROOT/bin/spack env deactivate -h
+                }
+                else {
+                    $SpackEnv = $(python $Env:SPACK_ROOT/bin/spack $SpackCMD_params env deactivate --pwsh)
+                    $ExecutionContext.InvokeCommand($SpackEnv)
+                }
+            }
+            default {python $Env:SPACK_ROOT/bin/spack $SpackCMD_params $SpackSubCommand $SpackSubCommandArgs}
+        }
+    }
+}
+
+function Invoke-SpackLoad {
+    if (Compare-CommonArgs $SpackSubCommandArgs) {
+        python $Env:SPACK_ROOT/bin/spack $SpackCMD_params $SpackSubCommand $SpackSubCommandArgs
+    }
+    elseif ([bool]($SpackSubCommandArgs.Where({($_ -eq "--pwsh") -or ($_ -eq "--list")}))) {
+        python $Env:SPACK_ROOT/bin/spack $SpackCMD_params $SpackSubCommand $SpackSubCommandArgs
+    }
+    else {
+        $SpackEnv = $(python $Env:SPACK_ROOT/bin/spack $SpackCMD_params $SpackSubCommand "--pwsh" $SpackSubCommandArgs)
+        $ExecutionContext.InvokeCommand($SpackEnv)
+    }
+}
+
+
+$SpackCMD_params, $SpackSubCommand, $SpackSubCommandArgs = Read-SpackArgs $args
+
+if (Compare-CommonArgs $SpackCMD_params) {
+    python $Env:SPACK_ROOT/bin/spack $SpackCMD_params $SpackSubCommand $SpackSubCommandArgs
+    exit $LASTEXITCODE
+}
+
+# Process Spack commands with special conditions
+# all other commands are piped directly to Spack
+switch($SpackSubCommand)
+{
+    "cd"     {Invoke-SpackCD}
+    "env"    {Invoke-SpackEnv}
+    "load"   {Invoke-SpackLoad}
+    "unload" {Invoke-SpackLoad}
+    default  {python $Env:SPACK_ROOT/bin/spack $SpackCMD_params $SpackSubCommand $SpackSubCommandArgs}
+}
-- 
cgit v1.2.3-70-g09d2