<commit_before># # Usage
#
# ```powershell
# $ hab-studio [FLAGS] [OPTIONS] <SUBCOMMAND> [ARG ...]
# ```
#
# See the `Write-Help` function below for complete usage instructions.
#
# # Synopsis
#
# blah
#
# # License and Copyright
#
# ```
# Copyright: Copyright (c) 2016 Chef Software, Inc.
# License: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ```
#
#

param (
    [switch]$h,
    [switch]$n,
    [switch]$q,
    [switch]$v,
    [switch]$R,
    [switch]$w,
    [string]$command,
    [string]$commandVal,
    [string]$k,
    [string]$o,
    [string]$s
)

# # Internals

# ## Help/Usage functions

# **Internal** Prints help and usage information. Straight forward, no?
function Write-Help {
  Write-Host @"
$program $version

$author

Habitat Studios - Plan for success!

USAGE:
        $program [FLAGS] [OPTIONS] <SUBCOMMAND> [ARG ..]

COMMON FLAGS:
    -h  Prints this message
    -n  Do not mount the source path into the Studio (default: mount the path)
    -q  Prints less output for better use in scripts
    -v  Prints more verbose output
    -w  Use a Windows studio instead of a Docker Studio (only available on windows)

COMMON OPTIONS:
    -k <HAB_ORIGIN_KEYS>  Installs secret origin keys (default:\$HAB_ORIGIN )
    -o <HAB_STUDIO_ROOT>  Sets a Studio root (default: /hab/studios/<DIR_NAME>)
    -s <SRC_PATH>         Sets the source path (default: \$PWD)

SUBCOMMANDS:
    build     Build using a Studio
    enter     Interactively enter a Studio
    help      Prints this message
    new       Creates a new Studio
    rm        Destroys a Studio
    run       Run a command in a Studio
    version   Prints version information

ENVIRONMENT VARIABLES:
    HAB_ORIGIN        Propagates this variable into any studios
    HAB_ORIGIN_KEYS   Installs secret keys (\`-k' option overrides)
    HAB_STUDIOS_HOME  Sets a home path for all Studios (default: /hab/studios)
    HAB_STUDIO_ROOT   Sets a Studio root (\`-r' option overrides)
    NO_SRC_PATH       If set, do not mount source path (\`-n' flag overrides)
    QUIET             Prints less output (\`-q' flag overrides)
    SRC_PATH          Sets the source path (\`-s' option overrides)
    VERBOSE           Prints more verbose output (\`-v' flag overrides)

SUBCOMMAND HELP:
    $program <SUBCOMMAND> -h

EXAMPLES:

    # Create a new default Studio
    $program new

    # Enter the default Studio
    $program enter

    # Run a command in the default Studio
    $program run hab --version

    # Destroy the default Studio
    $program rm

    # Create and enter a Studio with a custom root
    $program -o /opt/slim

    # Run a command in the slim Studio, showing only the command output
    $program -q -o /opt/slim run busybox ls -l /

    # Verbosely destroy the slim Studio
    $program -v -o /opt/slim rm

"@
}

function Write-BuildHelp {
  Write-Host @"
${program}-build $version

$author

Habitat Studios - execute a build using a Studio

USAGE:
        $program [COMMON_FLAGS] [COMMON_OPTIONS] build [FLAGS] [PLAN_DIR]

FLAGS:
    -R  Reuse a previous Studio state (default: clean up before building)

EXAMPLES:

    # Build a Redis plan
    $program build plans/redis

    # Reuse previous Studio for a build
    $program build -R plans/glibc

"@
}

function Write-EnterHelp {
  Write-Host @"
${program}-enter $version

$author

Habitat Studios - interactively enter a Studio

USAGE:
        $program [COMMON_FLAGS] [COMMON_OPTIONS] enter

"@
}

function Write-NewHelp {
  Write-Host @"
${program}-new $version

$author

Habitat Studios - create a new Studio

USAGE:
        $program [COMMON_FLAGS] [COMMON_OPTIONS] new

"@
}

function Write-RmHelp {
  Write-Host @"
${program}-rm $version

$author

Habitat Studios - destroy a Studio

USAGE:
        $program [COMMON_FLAGS] [COMMON_OPTIONS] rm

"@
}

function Write-RunHelp {
  Write-Host @"
${program}-run $version

$author

Habitat Studios - run a command in a Studio

USAGE:
        $program [COMMON_FLAGS] [COMMON_OPTIONS] run [CMD] [ARG ..]

CMD:
    Command to run in the Studio

ARG:
    Arguments to the command

EXAMPLES:

    $program run wget --version

"@
}

function Write-HabInfo($Message) {
  if($quiet) { return }
  Write-Host "   ${program}: " -ForegroundColor Cyan -NoNewline
  Write-Host $Message
}

# ## Subcommand functions
#
# These are the implementations for each subcommand in the program.

function New-Studio {
  if($printHelp) {
    Write-NewHelp
    return
  }
  Write-HabInfo "Creating Studio at $HAB_STUDIO_ROOT"

  if(!(Test-Path $HAB_STUDIO_ROOT)) {
    mkdir $HAB_STUDIO_ROOT | Out-Null
  }

  Set-Location $HAB_STUDIO_ROOT
  if(!(Test-Path src) -and !($doNotMount)) {
    mkdir src | Out-Null
    New-Item -Name src -ItemType Junction -target $SRC_PATH.Path | Out-Null
  }

  $pathArray = @(
    "$PSScriptRoot\hab",
    "$PSScriptRoot\7zip",
    "$PSScriptRoot",
    "$env:WINDIR\system32",
    "$env:WINDIR"
  )

  $env:PATH = [String]::Join(";", $pathArray)

  if($env:HAB_ORIGIN_KEYS) {
    $secret_keys = @()
    $public_keys = @()
    $env:HAB_ORIGIN_KEYS.Split(" ") | % {
      $pk = & hab origin key export $_ --type=public | Out-String
      $sk = & hab origin key export $_ --type=secret | Out-String
      # hab key import does not like carriage returns
      $secret_keys += $sk.Replace("`r", "")
      $public_keys += $pk.Replace("`r", "")
    }

    $env:FS_ROOT=$HAB_STUDIO_ROOT
    $env:HAB_CACHE_KEY_PATH = Join-Path $env:FS_ROOT "hab\cache\keys"
    $public_keys | % { $_ | & hab origin key import }
    $secret_keys | % { $_ | & hab origin key import }
  }
  else {
    $env:FS_ROOT=$HAB_STUDIO_ROOT
    $env:HAB_CACHE_KEY_PATH = Join-Path $env:FS_ROOT "hab\cache\keys"
  }

  New-PSDrive -Name "Habitat" -PSProvider FileSystem -Root $HAB_STUDIO_ROOT -Scope Script | Out-Null
  Set-Location "Habitat:\src"
}

function Enter-Studio {
  if($printHelp) {
    Write-EnterHelp
    return
  }
  if(!(Test-Path $HAB_STUDIO_ROOT)) {
    mkdir $HAB_STUDIO_ROOT | Out-Null
  }
  $env:HAB_STUDIO_ENTER_ROOT = Resolve-Path $HAB_STUDIO_ROOT
  New-Studio
  Write-HabInfo "Entering Studio at $HAB_STUDIO_ROOT"
  $env:STUDIO_SCRIPT_ROOT = $PSScriptRoot
  & "$PSScriptRoot\powershell\pwsh.exe" -NoProfile -ExecutionPolicy bypass -NoLogo -NoExit -Command {
    function prompt {
      Write-Host "[HAB-STUDIO]" -NoNewLine -ForegroundColor Green
      " $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel +1)) "
    }
    function build {
      & "$env:STUDIO_SCRIPT_ROOT\hab-plan-build.ps1" @args
    }

    function Get-SupervisorLog {
      # If we are not running in a container then the powershell studio was
      # spawned by hab.exe and ctrl+c behaves poorly in this scenario. So
      # we work around the issue by tailing the log in a new window that can
      # simply be closed. If we are inside a container then we cannot launch 
      # new windows but thats ok because docker run launched the studio directly
      # from powershell so the ctrl+c issue is not a problem so we can do
      # a simple tail
      if ((Get-Service -Name cexecsvc -ErrorAction SilentlyContinue) -eq $null) {
        Start-Process "$env:STUDIO_SCRIPT_ROOT\powershell\pwsh.exe" -ArgumentList "-Command `"& {Get-Content $env:HAB_STUDIO_ENTER_ROOT\hab\sup\default\out.log -Tail 100 -Wait}`""
      }
      else {
        # Container studios run habitat as a service which logs to a 
        # configured file location
        $svcPath = Join-Path $env:SystemDrive "hab\svc\windows-service"
        [xml]$configXml = Get-Content (Join-Path $svcPath HabService.exe.config)
        $logPath = Join-Path $svcPath $configXml.configuration.log4net.appender.file.value

        Get-Content $logPath -Tail 100 -Wait
      }
    }

    function Stop-Supervisor {
      $habSvc = Get-Service Habitat -ErrorAction SilentlyContinue
      if($habSvc -and ($habSvc.Status -eq "Running")) {
        Stop-Service Habitat
      }
      elseif(Test-Path "$env:HAB_STUDIO_ENTER_ROOT\hab\sup\default\LOCK") {
        Stop-Process -Id (Get-Content "$env:HAB_STUDIO_ENTER_ROOT\hab\sup\default\LOCK")
        Remove-Item "$env:HAB_STUDIO_ENTER_ROOT\hab\sup\default\LOCK"
      }
    }

    New-PSDrive -Name "Habitat" -PSProvider FileSystem -Root $env:HAB_STUDIO_ENTER_ROOT | Out-Null
    mkdir $env:HAB_STUDIO_ENTER_ROOT\hab\sup\default -Force | Out-Null
    
    $habSvc = Get-Service Habitat -ErrorAction SilentlyContinue
    if(!$habSvc -or ($habSvc.Status -eq "Stopped")) {
      $pr = New-Object System.Diagnostics.Process
      $pr.StartInfo.UseShellExecute = $false
      $pr.StartInfo.CreateNoWindow = $true
      $pr.StartInfo.RedirectStandardOutput = $true
      $pr.StartInfo.RedirectStandardError = $true
      $pr.StartInfo.FileName = "hab.exe"
      $pr.StartInfo.Arguments = "sup run"
      Register-ObjectEvent -InputObject $pr -EventName OutputDataReceived -action {
        $Event.SourceEventArgs.Data | Out-File $env:HAB_STUDIO_ENTER_ROOT\hab\sup\default\out.log -Append -Encoding ascii
      } | Out-Null
      Register-ObjectEvent -InputObject $pr -EventName ErrorDataReceived -action {
        $Event.SourceEventArgs.Data | Out-File $env:HAB_STUDIO_ENTER_ROOT\hab\sup\default\out.log -Append -Encoding ascii
      } | Out-Null
      $pr.start() | Out-Null
      $pr.BeginErrorReadLine()
      
      # As an industry, this should make us all feel bad
      # without this stdin never seems to come back and the PS prompt
      # fails to appear and things look like they are hung
      Start-Sleep -Milliseconds 100
  
      $pr.BeginOutputReadLine()
    }
    
    Write-Host  "** The Habitat Supervisor has been started in the background." -ForegroundColor Cyan
    Write-Host  "** Use 'hab svc start' and 'hab svc stop' to start and stop services." -ForegroundColor Cyan
    Write-Host  "** Use the 'Get-SupervisorLog' command to stream the Supervisor log." -ForegroundColor Cyan
    Write-Host  "** Use the 'Stop-Supervisor' to terminate the Supervisor." -ForegroundColor Cyan
    Write-Host  ""

    Set-Location "Habitat:\src"
  }

  if(Test-Path "$env:HAB_STUDIO_ENTER_ROOT\hab\sup\default\LOCK") {
    Stop-Process -Id (Get-Content "$env:HAB_STUDIO_ENTER_ROOT\hab\sup\default\LOCK") -Force
  }
}

function Invoke-StudioRun($cmd) {
  if($printHelp -or ($cmd -eq $null)) {
    Write-RunHelp
    return
  }
  New-Studio
  Write-HabInfo "Running '$cmd' in Studio at $HAB_STUDIO_ROOT"
  New-PSDrive -Name "Habitat" -PSProvider FileSystem -Root $HAB_STUDIO_ROOT | Out-Null
  Set-Location "Habitat:\src"
  Invoke-Expression $cmd
}

function Invoke-StudioBuild($location, $reuse) {
  if($printHelp -or ($location -eq $null)) {
    Write-BuildHelp
    return
  }
  if(!$reuse) { Remove-Studio}

  New-Studio
  Write-HabInfo "Building '$location' in Studio at $HAB_STUDIO_ROOT"

  & "$PSScriptRoot\hab-plan-build.ps1" $location
}

function Remove-Studio {
  if($printHelp) {
    Write-RmHelp
    return
  }
  Write-HabInfo "Destroying Studio at $HAB_STUDIO_ROOT"

  if(Test-Path $HAB_STUDIO_ROOT) { Remove-Item $HAB_STUDIO_ROOT -Recurse -Force }
}

# The current version of Habitat Studio
$script:version='@version@'
# The author of this program<commit_msg>fix studio run in local windows container<commit_after># # Usage
#
# ```powershell
# $ hab-studio [FLAGS] [OPTIONS] <SUBCOMMAND> [ARG ...]
# ```
#
# See the `Write-Help` function below for complete usage instructions.
#
# # Synopsis
#
# blah
#
# # License and Copyright
#
# ```
# Copyright: Copyright (c) 2016 Chef Software, Inc.
# License: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ```
#
#

param (
    [switch]$h,
    [switch]$n,
    [switch]$q,
    [switch]$v,
    [switch]$R,
    [switch]$w,
    [string]$command,
    [string]$commandVal,
    [string]$k,
    [string]$o,
    [string]$s
)

# # Internals

# ## Help/Usage functions

# **Internal** Prints help and usage information. Straight forward, no?
function Write-Help {
  Write-Host @"
$program $version

$author

Habitat Studios - Plan for success!

USAGE:
        $program [FLAGS] [OPTIONS] <SUBCOMMAND> [ARG ..]

COMMON FLAGS:
    -h  Prints this message
    -n  Do not mount the source path into the Studio (default: mount the path)
    -q  Prints less output for better use in scripts
    -v  Prints more verbose output
    -w  Use a Windows studio instead of a Docker Studio (only available on windows)

COMMON OPTIONS:
    -k <HAB_ORIGIN_KEYS>  Installs secret origin keys (default:\$HAB_ORIGIN )
    -o <HAB_STUDIO_ROOT>  Sets a Studio root (default: /hab/studios/<DIR_NAME>)
    -s <SRC_PATH>         Sets the source path (default: \$PWD)

SUBCOMMANDS:
    build     Build using a Studio
    enter     Interactively enter a Studio
    help      Prints this message
    new       Creates a new Studio
    rm        Destroys a Studio
    run       Run a command in a Studio
    version   Prints version information

ENVIRONMENT VARIABLES:
    HAB_ORIGIN        Propagates this variable into any studios
    HAB_ORIGIN_KEYS   Installs secret keys (\`-k' option overrides)
    HAB_STUDIOS_HOME  Sets a home path for all Studios (default: /hab/studios)
    HAB_STUDIO_ROOT   Sets a Studio root (\`-r' option overrides)
    NO_SRC_PATH       If set, do not mount source path (\`-n' flag overrides)
    QUIET             Prints less output (\`-q' flag overrides)
    SRC_PATH          Sets the source path (\`-s' option overrides)
    VERBOSE           Prints more verbose output (\`-v' flag overrides)

SUBCOMMAND HELP:
    $program <SUBCOMMAND> -h

EXAMPLES:

    # Create a new default Studio
    $program new

    # Enter the default Studio
    $program enter

    # Run a command in the default Studio
    $program run hab --version

    # Destroy the default Studio
    $program rm

    # Create and enter a Studio with a custom root
    $program -o /opt/slim

    # Run a command in the slim Studio, showing only the command output
    $program -q -o /opt/slim run busybox ls -l /

    # Verbosely destroy the slim Studio
    $program -v -o /opt/slim rm

"@
}

function Write-BuildHelp {
  Write-Host @"
${program}-build $version

$author

Habitat Studios - execute a build using a Studio

USAGE:
        $program [COMMON_FLAGS] [COMMON_OPTIONS] build [FLAGS] [PLAN_DIR]

FLAGS:
    -R  Reuse a previous Studio state (default: clean up before building)

EXAMPLES:

    # Build a Redis plan
    $program build plans/redis

    # Reuse previous Studio for a build
    $program build -R plans/glibc

"@
}

function Write-EnterHelp {
  Write-Host @"
${program}-enter $version

$author

Habitat Studios - interactively enter a Studio

USAGE:
        $program [COMMON_FLAGS] [COMMON_OPTIONS] enter

"@
}

function Write-NewHelp {
  Write-Host @"
${program}-new $version

$author

Habitat Studios - create a new Studio

USAGE:
        $program [COMMON_FLAGS] [COMMON_OPTIONS] new

"@
}

function Write-RmHelp {
  Write-Host @"
${program}-rm $version

$author

Habitat Studios - destroy a Studio

USAGE:
        $program [COMMON_FLAGS] [COMMON_OPTIONS] rm

"@
}

function Write-RunHelp {
  Write-Host @"
${program}-run $version

$author

Habitat Studios - run a command in a Studio

USAGE:
        $program [COMMON_FLAGS] [COMMON_OPTIONS] run [CMD] [ARG ..]

CMD:
    Command to run in the Studio

ARG:
    Arguments to the command

EXAMPLES:

    $program run wget --version

"@
}

function Write-HabInfo($Message) {
  if($quiet) { return }
  Write-Host "   ${program}: " -ForegroundColor Cyan -NoNewline
  Write-Host $Message
}

# ## Subcommand functions
#
# These are the implementations for each subcommand in the program.

function New-Studio {
  if($printHelp) {
    Write-NewHelp
    return
  }
  Write-HabInfo "Creating Studio at $HAB_STUDIO_ROOT"

  if(!(Test-Path $HAB_STUDIO_ROOT)) {
    mkdir $HAB_STUDIO_ROOT | Out-Null
  }

  Set-Location $HAB_STUDIO_ROOT
  if(!(Test-Path src) -and !($doNotMount)) {
    mkdir src | Out-Null
    New-Item -Name src -ItemType Junction -target $SRC_PATH.Path | Out-Null
  }

  $pathArray = @(
    "$PSScriptRoot\hab",
    "$PSScriptRoot\7zip",
    "$PSScriptRoot",
    "$env:WINDIR\system32",
    "$env:WINDIR"
  )

  $env:PATH = [String]::Join(";", $pathArray)

  if($env:HAB_ORIGIN_KEYS) {
    $secret_keys = @()
    $public_keys = @()
    $env:HAB_ORIGIN_KEYS.Split(" ") | % {
      $pk = & hab origin key export $_ --type=public | Out-String
      $sk = & hab origin key export $_ --type=secret | Out-String
      # hab key import does not like carriage returns
      $secret_keys += $sk.Replace("`r", "")
      $public_keys += $pk.Replace("`r", "")
    }

    $env:FS_ROOT=$HAB_STUDIO_ROOT
    $env:HAB_CACHE_KEY_PATH = Join-Path $env:FS_ROOT "hab\cache\keys"
    $public_keys | % { $_ | & hab origin key import }
    $secret_keys | % { $_ | & hab origin key import }
  }
  else {
    $env:FS_ROOT=$HAB_STUDIO_ROOT
    $env:HAB_CACHE_KEY_PATH = Join-Path $env:FS_ROOT "hab\cache\keys"
  }

  New-PSDrive -Name "Habitat" -PSProvider FileSystem -Root $HAB_STUDIO_ROOT -Scope Script | Out-Null
  Set-Location "Habitat:\src"
}

function Enter-Studio {
  if($printHelp) {
    Write-EnterHelp
    return
  }
  if(!(Test-Path $HAB_STUDIO_ROOT)) {
    mkdir $HAB_STUDIO_ROOT | Out-Null
  }
  $env:HAB_STUDIO_ENTER_ROOT = Resolve-Path $HAB_STUDIO_ROOT
  New-Studio
  Write-HabInfo "Entering Studio at $HAB_STUDIO_ROOT"
  $env:STUDIO_SCRIPT_ROOT = $PSScriptRoot
  & "$PSScriptRoot\powershell\pwsh.exe" -NoProfile -ExecutionPolicy bypass -NoLogo -NoExit -Command {
    function prompt {
      Write-Host "[HAB-STUDIO]" -NoNewLine -ForegroundColor Green
      " $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel +1)) "
    }
    function build {
      & "$env:STUDIO_SCRIPT_ROOT\hab-plan-build.ps1" @args
    }

    function Get-SupervisorLog {
      # If we are not running in a container then the powershell studio was
      # spawned by hab.exe and ctrl+c behaves poorly in this scenario. So
      # we work around the issue by tailing the log in a new window that can
      # simply be closed. If we are inside a container then we cannot launch 
      # new windows but thats ok because docker run launched the studio directly
      # from powershell so the ctrl+c issue is not a problem so we can do
      # a simple tail
      if ((Get-Service -Name cexecsvc -ErrorAction SilentlyContinue) -eq $null) {
        Start-Process "$env:STUDIO_SCRIPT_ROOT\powershell\pwsh.exe" -ArgumentList "-Command `"& {Get-Content $env:HAB_STUDIO_ENTER_ROOT\hab\sup\default\out.log -Tail 100 -Wait}`""
      }
      else {
        # Container studios run habitat as a service which logs to a 
        # configured file location
        $svcPath = Join-Path $env:SystemDrive "hab\svc\windows-service"
        [xml]$configXml = Get-Content (Join-Path $svcPath HabService.exe.config)
        $logPath = Join-Path $svcPath $configXml.configuration.log4net.appender.file.value

        Get-Content $logPath -Tail 100 -Wait
      }
    }

    function Stop-Supervisor {
      $habSvc = Get-Service Habitat -ErrorAction SilentlyContinue
      if($habSvc -and ($habSvc.Status -eq "Running")) {
        Stop-Service Habitat
      }
      elseif(Test-Path "$env:HAB_STUDIO_ENTER_ROOT\hab\sup\default\LOCK") {
        Stop-Process -Id (Get-Content "$env:HAB_STUDIO_ENTER_ROOT\hab\sup\default\LOCK")
        Remove-Item "$env:HAB_STUDIO_ENTER_ROOT\hab\sup\default\LOCK"
      }
    }

    New-PSDrive -Name "Habitat" -PSProvider FileSystem -Root $env:HAB_STUDIO_ENTER_ROOT | Out-Null
    mkdir $env:HAB_STUDIO_ENTER_ROOT\hab\sup\default -Force | Out-Null
    
    $habSvc = Get-Service Habitat -ErrorAction SilentlyContinue
    if(!$habSvc -or ($habSvc.Status -eq "Stopped")) {
      $pr = New-Object System.Diagnostics.Process
      $pr.StartInfo.UseShellExecute = $false
      $pr.StartInfo.CreateNoWindow = $true
      $pr.StartInfo.RedirectStandardOutput = $true
      $pr.StartInfo.RedirectStandardError = $true
      $pr.StartInfo.FileName = "hab.exe"
      $pr.StartInfo.Arguments = "sup run"
      Register-ObjectEvent -InputObject $pr -EventName OutputDataReceived -action {
        $Event.SourceEventArgs.Data | Out-File $env:HAB_STUDIO_ENTER_ROOT\hab\sup\default\out.log -Append -Encoding ascii
      } | Out-Null
      Register-ObjectEvent -InputObject $pr -EventName ErrorDataReceived -action {
        $Event.SourceEventArgs.Data | Out-File $env:HAB_STUDIO_ENTER_ROOT\hab\sup\default\out.log -Append -Encoding ascii
      } | Out-Null
      $pr.start() | Out-Null
      $pr.BeginErrorReadLine()
      
      # As an industry, this should make us all feel bad
      # without this stdin never seems to come back and the PS prompt
      # fails to appear and things look like they are hung
      Start-Sleep -Milliseconds 100
  
      $pr.BeginOutputReadLine()
    }
    
    Write-Host  "** The Habitat Supervisor has been started in the background." -ForegroundColor Cyan
    Write-Host  "** Use 'hab svc start' and 'hab svc stop' to start and stop services." -ForegroundColor Cyan
    Write-Host  "** Use the 'Get-SupervisorLog' command to stream the Supervisor log." -ForegroundColor Cyan
    Write-Host  "** Use the 'Stop-Supervisor' to terminate the Supervisor." -ForegroundColor Cyan
    Write-Host  ""

    Set-Location "Habitat:\src"
  }

  if(Test-Path "$env:HAB_STUDIO_ENTER_ROOT\hab\sup\default\LOCK") {
    Stop-Process -Id (Get-Content "$env:HAB_STUDIO_ENTER_ROOT\hab\sup\default\LOCK") -Force
  }
}

function Invoke-StudioRun($cmd) {
  if($printHelp -or ($cmd -eq $null)) {
    Write-RunHelp
    return
  }
  New-Studio
  Write-HabInfo "Running '$cmd' in Studio at $HAB_STUDIO_ROOT"
  Invoke-Expression $cmd
}

function Invoke-StudioBuild($location, $reuse) {
  if($printHelp -or ($location -eq $null)) {
    Write-BuildHelp
    return
  }
  if(!$reuse) { Remove-Studio}

  New-Studio
  Write-HabInfo "Building '$location' in Studio at $HAB_STUDIO_ROOT"

  & "$PSScriptRoot\hab-plan-build.ps1" $location
}

function Remove-Studio {
  if($printHelp) {
    Write-RmHelp
    return
  }
  Write-HabInfo "Destroying Studio at $HAB_STUDIO_ROOT"

  if(Test-Path $HAB_STUDIO_ROOT) { Remove-Item $HAB_STUDIO_ROOT -Recurse -Force }
}

# The current version of Habitat Studio
$script:version='@version@'
# The author of this program
{'fraction_non_alphanumeric': 0.10787811062878755, 'fraction_numerical': 0.002234925001074483, 'mean_word_length': 3.0671211326691137, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4608747', 'n_tokens_mistral': 7911, 'n_tokens_neox': 7735, 'n_words': 2221}