feat(cli): install tht as a system command
This commit is contained in:
@@ -5,6 +5,36 @@ export DOCKER_BUILDKIT=1
|
|||||||
repository_root=$(cd "$(dirname "$0")/.." && pwd)
|
repository_root=$(cd "$(dirname "$0")/.." && pwd)
|
||||||
output_directory="${THT_THT_OUTPUT_DIRECTORY:-$repository_root/dist/tht}"
|
output_directory="${THT_THT_OUTPUT_DIRECTORY:-$repository_root/dist/tht}"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<'EOF'
|
||||||
|
Usage: bash scripts/build-tht.sh [--all] [--output ABSOLUTE_DIRECTORY]
|
||||||
|
|
||||||
|
Build every supported native tht binary with the repository-pinned Docker builder.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--all)
|
||||||
|
;;
|
||||||
|
--output)
|
||||||
|
[[ $# -ge 2 ]] || { echo "--output requires an absolute directory" >&2; exit 2; }
|
||||||
|
output_directory=$2
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--help|-h)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "unknown argument: $1" >&2
|
||||||
|
usage >&2
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
if [[ "$output_directory" != /* || "$output_directory" == / || "$output_directory" == */ ||
|
if [[ "$output_directory" != /* || "$output_directory" == / || "$output_directory" == */ ||
|
||||||
"$output_directory" == *//* || "/$output_directory/" == */../* ||
|
"$output_directory" == *//* || "/$output_directory/" == */../* ||
|
||||||
"/$output_directory/" == */./* ]]; then
|
"/$output_directory/" == */./* ]]; then
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
[CmdletBinding()]
|
||||||
|
param()
|
||||||
|
|
||||||
|
Set-StrictMode -Version Latest
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
|
function Get-Sha256([string]$Path) {
|
||||||
|
return (Get-FileHash -Algorithm SHA256 -LiteralPath $Path).Hash.ToLowerInvariant()
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-UserPathValue {
|
||||||
|
if ($env:THT_USER_PATH_FILE) {
|
||||||
|
if (Test-Path -LiteralPath $env:THT_USER_PATH_FILE) {
|
||||||
|
return [System.IO.File]::ReadAllText($env:THT_USER_PATH_FILE)
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
return [Environment]::GetEnvironmentVariable('Path', 'User')
|
||||||
|
}
|
||||||
|
|
||||||
|
function Set-UserPathValue([string]$Value) {
|
||||||
|
if ($env:THT_USER_PATH_FILE) {
|
||||||
|
[System.IO.File]::WriteAllText($env:THT_USER_PATH_FILE, $Value)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
[Environment]::SetEnvironmentVariable('Path', $Value, 'User')
|
||||||
|
}
|
||||||
|
|
||||||
|
function Add-InstallDirectoryToUserPath([string]$InstallDirectory) {
|
||||||
|
$currentPath = Get-UserPathValue
|
||||||
|
$entries = @($currentPath -split ';' | Where-Object { $_ -ne '' })
|
||||||
|
if ($entries | Where-Object { $_.TrimEnd('\\') -ieq $InstallDirectory.TrimEnd('\\') }) {
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
$newPath = (@($entries) + $InstallDirectory) -join ';'
|
||||||
|
Set-UserPathValue $newPath
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
|
||||||
|
$repositoryRoot = Split-Path -Parent $PSScriptRoot
|
||||||
|
$buildOutput = $null
|
||||||
|
$sourceArtifactForInstall = $null
|
||||||
|
$installDirectory = if ($env:THT_INSTALL_DIRECTORY) {
|
||||||
|
$env:THT_INSTALL_DIRECTORY
|
||||||
|
} else {
|
||||||
|
Join-Path $env:LOCALAPPDATA 'ThothII\bin'
|
||||||
|
}
|
||||||
|
$installDirectory = [System.IO.Path]::GetFullPath($installDirectory)
|
||||||
|
|
||||||
|
if ($env:THT_BUILD_ARTIFACT) {
|
||||||
|
$sourceArtifact = $env:THT_BUILD_ARTIFACT
|
||||||
|
if (-not (Test-Path -LiteralPath $sourceArtifact -PathType Leaf)) {
|
||||||
|
throw 'THT_BUILD_ARTIFACT is not a regular file'
|
||||||
|
}
|
||||||
|
if (-not $env:THT_BUILD_ARTIFACT_SHA256 -or $env:THT_BUILD_ARTIFACT_SHA256 -notmatch '^[0-9A-Fa-f]{64}$') {
|
||||||
|
throw 'THT_BUILD_ARTIFACT_SHA256 must be a 64-character SHA-256 digest'
|
||||||
|
}
|
||||||
|
if ((Get-Sha256 $sourceArtifact) -ne $env:THT_BUILD_ARTIFACT_SHA256.ToLowerInvariant()) {
|
||||||
|
throw 'packaged tht artifact checksum does not match'
|
||||||
|
}
|
||||||
|
$sourceArtifactForInstall = $sourceArtifact
|
||||||
|
} else {
|
||||||
|
if ($env:PROCESSOR_ARCHITECTURE -notin @('AMD64', 'x86_64')) {
|
||||||
|
throw "unsupported Windows processor architecture: $env:PROCESSOR_ARCHITECTURE (supported: AMD64)"
|
||||||
|
}
|
||||||
|
$buildOutput = Join-Path ([System.IO.Path]::GetTempPath()) ("tht-build-" + [guid]::NewGuid())
|
||||||
|
New-Item -ItemType Directory -Path $buildOutput -Force | Out-Null
|
||||||
|
$previousOutput = $env:THT_THT_OUTPUT_DIRECTORY
|
||||||
|
$env:THT_THT_OUTPUT_DIRECTORY = $buildOutput
|
||||||
|
try {
|
||||||
|
& bash (Join-Path $repositoryRoot 'scripts/build-tht.sh') --all
|
||||||
|
if ($LASTEXITCODE -ne 0) { throw 'the repository-pinned Docker build failed' }
|
||||||
|
} finally {
|
||||||
|
$env:THT_THT_OUTPUT_DIRECTORY = $previousOutput
|
||||||
|
}
|
||||||
|
$sourceArtifactForInstall = Join-Path $buildOutput 'tht-windows-amd64.exe'
|
||||||
|
if (-not (Test-Path -LiteralPath $sourceArtifactForInstall -PathType Leaf)) {
|
||||||
|
throw 'the repository-pinned Docker build did not produce tht-windows-amd64.exe'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((Get-Item -LiteralPath $sourceArtifactForInstall).Length -eq 0) { throw 'native artifact is empty' }
|
||||||
|
New-Item -ItemType Directory -Path $installDirectory -Force | Out-Null
|
||||||
|
$stagedBinary = Join-Path $installDirectory ('.tht-' + [guid]::NewGuid() + '.exe')
|
||||||
|
try {
|
||||||
|
Copy-Item -LiteralPath $sourceArtifactForInstall -Destination $stagedBinary -Force
|
||||||
|
& $stagedBinary --help | Out-Null
|
||||||
|
if ($LASTEXITCODE -ne 0) { throw 'native artifact did not pass its help check' }
|
||||||
|
Move-Item -LiteralPath $stagedBinary -Destination (Join-Path $installDirectory 'tht.exe') -Force
|
||||||
|
} finally {
|
||||||
|
Remove-Item -LiteralPath $stagedBinary -Force -ErrorAction SilentlyContinue
|
||||||
|
if ($buildOutput) { Remove-Item -LiteralPath $buildOutput -Recurse -Force -ErrorAction SilentlyContinue }
|
||||||
|
}
|
||||||
|
|
||||||
|
$pathChanged = Add-InstallDirectoryToUserPath $installDirectory
|
||||||
|
if ($env:Path -notlike "*$installDirectory*") {
|
||||||
|
$env:Path = "$installDirectory;$env:Path"
|
||||||
|
}
|
||||||
|
& (Join-Path $installDirectory 'tht.exe') --help | Out-Null
|
||||||
|
if ($LASTEXITCODE -ne 0) { throw 'installed tht did not pass its help check' }
|
||||||
|
Write-Output "Installed tht at $(Join-Path $installDirectory 'tht.exe')"
|
||||||
|
if ($pathChanged) {
|
||||||
|
Write-Output 'Added ThothII to your user PATH. Open a new terminal before using tht there.'
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
repository_root=$(cd "$(dirname "$0")/.." && pwd)
|
||||||
|
install_directory="${THT_INSTALL_DIRECTORY:-/usr/local/bin}"
|
||||||
|
staging_root=$(mktemp -d)
|
||||||
|
trap 'rm -rf "$staging_root"' EXIT HUP INT TERM
|
||||||
|
|
||||||
|
fail() {
|
||||||
|
echo "install-tht.sh: $*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
sha256() {
|
||||||
|
if command -v sha256sum >/dev/null 2>&1; then
|
||||||
|
sha256sum "$1" | awk '{print $1}'
|
||||||
|
elif command -v shasum >/dev/null 2>&1; then
|
||||||
|
shasum -a 256 "$1" | awk '{print $1}'
|
||||||
|
else
|
||||||
|
fail "SHA-256 verification requires sha256sum or shasum"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
platform_artifact_name() {
|
||||||
|
local system architecture
|
||||||
|
system=$(uname -s)
|
||||||
|
architecture=$(uname -m)
|
||||||
|
case "$system" in
|
||||||
|
Darwin) system=darwin ;;
|
||||||
|
Linux) system=linux ;;
|
||||||
|
*) fail "unsupported operating system: $system (supported: macOS and Linux)" ;;
|
||||||
|
esac
|
||||||
|
case "$architecture" in
|
||||||
|
x86_64|amd64) architecture=amd64 ;;
|
||||||
|
arm64|aarch64) architecture=arm64 ;;
|
||||||
|
*) fail "unsupported processor architecture: $architecture (supported: amd64 and arm64)" ;;
|
||||||
|
esac
|
||||||
|
printf 'tht-%s-%s\n' "$system" "$architecture"
|
||||||
|
}
|
||||||
|
|
||||||
|
validate_packaged_artifact() {
|
||||||
|
local artifact=$1 expected actual
|
||||||
|
expected=${THT_BUILD_ARTIFACT_SHA256:-}
|
||||||
|
[[ "$expected" =~ ^[[:xdigit:]]{64}$ ]] || fail "THT_BUILD_ARTIFACT_SHA256 must be a 64-character SHA-256 digest"
|
||||||
|
actual=$(sha256 "$artifact")
|
||||||
|
[[ "${actual,,}" == "${expected,,}" ]] || fail "packaged tht artifact checksum does not match"
|
||||||
|
}
|
||||||
|
|
||||||
|
build_artifact() {
|
||||||
|
local build_output="$staging_root/build"
|
||||||
|
mkdir -p "$build_output"
|
||||||
|
THT_THT_OUTPUT_DIRECTORY="$build_output" bash "$repository_root/scripts/build-tht.sh" --all >&2
|
||||||
|
printf '%s/%s\n' "$build_output" "$(platform_artifact_name)"
|
||||||
|
}
|
||||||
|
|
||||||
|
install_atomically() {
|
||||||
|
local destination_directory=$1 source_file=$2
|
||||||
|
local temporary_destination
|
||||||
|
if mkdir -p "$destination_directory" 2>/dev/null && [[ -w "$destination_directory" ]]; then
|
||||||
|
temporary_destination=$(mktemp "$destination_directory/.tht.XXXXXX")
|
||||||
|
cp "$source_file" "$temporary_destination"
|
||||||
|
chmod 0755 "$temporary_destination"
|
||||||
|
mv -f "$temporary_destination" "$destination_directory/tht"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
command -v sudo >/dev/null 2>&1 || fail "cannot write to $destination_directory and sudo is unavailable"
|
||||||
|
sudo sh -c '
|
||||||
|
set -eu
|
||||||
|
destination_directory=$1
|
||||||
|
source_file=$2
|
||||||
|
mkdir -p "$destination_directory"
|
||||||
|
temporary_destination=$(mktemp "$destination_directory/.tht.XXXXXX")
|
||||||
|
trap "rm -f \"$temporary_destination\"" EXIT HUP INT TERM
|
||||||
|
cp "$source_file" "$temporary_destination"
|
||||||
|
chmod 0755 "$temporary_destination"
|
||||||
|
mv -f "$temporary_destination" "$destination_directory/tht"
|
||||||
|
' sh "$destination_directory" "$source_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
[[ "$install_directory" == /* ]] || fail "THT_INSTALL_DIRECTORY must be an absolute path"
|
||||||
|
artifact_name=$(platform_artifact_name)
|
||||||
|
if [[ -n "${THT_BUILD_ARTIFACT:-}" ]]; then
|
||||||
|
source_artifact=$THT_BUILD_ARTIFACT
|
||||||
|
[[ -f "$source_artifact" ]] || fail "THT_BUILD_ARTIFACT is not a regular file"
|
||||||
|
validate_packaged_artifact "$source_artifact"
|
||||||
|
else
|
||||||
|
source_artifact=$(build_artifact)
|
||||||
|
fi
|
||||||
|
|
||||||
|
[[ -s "$source_artifact" ]] || fail "native artifact is missing: $artifact_name"
|
||||||
|
staged_binary="$staging_root/tht"
|
||||||
|
cp "$source_artifact" "$staged_binary"
|
||||||
|
chmod 0755 "$staged_binary"
|
||||||
|
"$staged_binary" --help >/dev/null || fail "native artifact did not pass its help check"
|
||||||
|
|
||||||
|
install_atomically "$install_directory" "$staged_binary"
|
||||||
|
resolved_command=$(command -v tht || true)
|
||||||
|
[[ "$resolved_command" == "$install_directory/tht" ]] || fail "installed tht is not resolvable at $install_directory/tht; add $install_directory to PATH and open a new terminal"
|
||||||
|
"$install_directory/tht" --help >/dev/null || fail "installed tht did not pass its help check"
|
||||||
|
printf 'Installed tht at %s/tht\n' "$install_directory"
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
|
$repositoryRoot = Split-Path -Parent $PSScriptRoot
|
||||||
|
$installer = Join-Path $repositoryRoot 'scripts/install-tht.ps1'
|
||||||
|
if (-not (Test-Path -LiteralPath $installer)) {
|
||||||
|
throw "installer is missing: $installer"
|
||||||
|
}
|
||||||
|
|
||||||
|
$isWindowsHost = $env:OS -eq 'Windows_NT'
|
||||||
|
if (-not $isWindowsHost) {
|
||||||
|
$installerText = Get-Content -LiteralPath $installer -Raw
|
||||||
|
foreach ($requiredText in @('THT_INSTALL_DIRECTORY', 'LOCALAPPDATA', 'SetEnvironmentVariable', 'build-tht.sh', 'Move-Item')) {
|
||||||
|
if (-not $installerText.Contains($requiredText)) {
|
||||||
|
throw "Windows installer is missing required behavior: $requiredText"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Write-Output 'PowerShell installer behavior test skipped: requires Windows.'
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
$temporaryRoot = Join-Path ([System.IO.Path]::GetTempPath()) ("tht installer test {0}" -f [guid]::NewGuid())
|
||||||
|
$installDirectory = Join-Path $temporaryRoot 'command directory'
|
||||||
|
$artifact = Join-Path $temporaryRoot 'tht.exe'
|
||||||
|
$userPathStore = Join-Path $temporaryRoot 'user-path.txt'
|
||||||
|
New-Item -ItemType Directory -Path $temporaryRoot -Force | Out-Null
|
||||||
|
try {
|
||||||
|
$program = @'
|
||||||
|
using System;
|
||||||
|
public static class Program {
|
||||||
|
public static void Main(string[] args) {
|
||||||
|
if (args.Length == 1 && args[0] == "--help") { Console.WriteLine("Usage: tht"); return; }
|
||||||
|
if (args.Length == 1 && args[0] == "version") { Console.WriteLine("tht test version"); return; }
|
||||||
|
Environment.Exit(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'@
|
||||||
|
Add-Type -TypeDefinition $program -OutputAssembly $artifact -OutputType ConsoleApplication
|
||||||
|
[System.IO.File]::WriteAllText($userPathStore, 'C:\Existing Bin')
|
||||||
|
|
||||||
|
$env:THT_INSTALL_DIRECTORY = $installDirectory
|
||||||
|
$env:THT_BUILD_ARTIFACT = $artifact
|
||||||
|
$env:THT_BUILD_ARTIFACT_SHA256 = (Get-FileHash -Algorithm SHA256 -LiteralPath $artifact).Hash.ToLowerInvariant()
|
||||||
|
$env:THT_USER_PATH_FILE = $userPathStore
|
||||||
|
& $installer
|
||||||
|
|
||||||
|
$installed = Join-Path $installDirectory 'tht.exe'
|
||||||
|
if (-not (Test-Path -LiteralPath $installed)) { throw 'installer did not create tht.exe' }
|
||||||
|
if ((& $installed version) -ne 'tht test version') { throw 'installed tht.exe did not return version' }
|
||||||
|
$firstBytes = [System.IO.File]::ReadAllBytes($installed)
|
||||||
|
|
||||||
|
& $installer
|
||||||
|
if ((& $installed version) -ne 'tht test version') { throw 'installer was not idempotent' }
|
||||||
|
if (-not ([System.IO.File]::ReadAllBytes($installed).Length -eq $firstBytes.Length)) { throw 'replacement changed the unexpected binary' }
|
||||||
|
|
||||||
|
$storedPath = [System.IO.File]::ReadAllText($userPathStore)
|
||||||
|
$segments = $storedPath -split ';' | Where-Object { $_ -ne '' }
|
||||||
|
if ((@($segments | Where-Object { $_ -ieq $installDirectory }).Count) -ne 1) {
|
||||||
|
throw 'installer did not preserve a single destination PATH entry'
|
||||||
|
}
|
||||||
|
if (-not ($segments | Where-Object { $_ -ieq 'C:\Existing Bin' })) { throw 'installer did not preserve existing user PATH entries' }
|
||||||
|
Write-Output 'PowerShell tht installer tests passed.'
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
Remove-Item Env:THT_INSTALL_DIRECTORY -ErrorAction SilentlyContinue
|
||||||
|
Remove-Item Env:THT_BUILD_ARTIFACT -ErrorAction SilentlyContinue
|
||||||
|
Remove-Item Env:THT_BUILD_ARTIFACT_SHA256 -ErrorAction SilentlyContinue
|
||||||
|
Remove-Item Env:THT_USER_PATH_FILE -ErrorAction SilentlyContinue
|
||||||
|
Remove-Item -LiteralPath $temporaryRoot -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
repository_root=$(cd "$(dirname "$0")/.." && pwd)
|
||||||
|
installer="$repository_root/scripts/install-tht.sh"
|
||||||
|
temporary_root=$(mktemp -d)
|
||||||
|
trap 'rm -rf "$temporary_root"' EXIT HUP INT TERM
|
||||||
|
|
||||||
|
fail() {
|
||||||
|
echo "test-install-tht.sh: $*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
sha256() {
|
||||||
|
if command -v sha256sum >/dev/null 2>&1; then
|
||||||
|
sha256sum "$1" | awk '{print $1}'
|
||||||
|
else
|
||||||
|
shasum -a 256 "$1" | awk '{print $1}'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
write_artifact() {
|
||||||
|
local path=$1
|
||||||
|
local version=$2
|
||||||
|
cat >"$path" <<EOF
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
case "\${1:-}" in
|
||||||
|
--help|-h) echo "Usage: tht" ;;
|
||||||
|
version) echo "$version" ;;
|
||||||
|
*) echo "unexpected argument: \${1:-}" >&2; exit 2 ;;
|
||||||
|
esac
|
||||||
|
EOF
|
||||||
|
chmod 0644 "$path"
|
||||||
|
}
|
||||||
|
|
||||||
|
test_directory="$temporary_root/command directory"
|
||||||
|
artifact_one="$temporary_root/tht-one"
|
||||||
|
artifact_two="$temporary_root/tht-two"
|
||||||
|
write_artifact "$artifact_one" "tht test version one"
|
||||||
|
write_artifact "$artifact_two" "tht test version two"
|
||||||
|
|
||||||
|
system_path=$PATH
|
||||||
|
run_installer() {
|
||||||
|
local artifact=$1
|
||||||
|
THT_INSTALL_DIRECTORY="$test_directory" \
|
||||||
|
THT_BUILD_ARTIFACT="$artifact" \
|
||||||
|
THT_BUILD_ARTIFACT_SHA256="$(sha256 "$artifact")" \
|
||||||
|
PATH="$test_directory:$system_path" \
|
||||||
|
bash "$installer"
|
||||||
|
}
|
||||||
|
|
||||||
|
run_installer "$artifact_one"
|
||||||
|
|
||||||
|
test -x "$test_directory/tht" || fail "installed tht is not executable"
|
||||||
|
first_inode=$(stat -f '%i' "$test_directory/tht" 2>/dev/null || stat -c '%i' "$test_directory/tht")
|
||||||
|
first_version=$(PATH="$test_directory:$system_path" tht version)
|
||||||
|
test "$first_version" = "tht test version one" || fail "installed command did not run version one"
|
||||||
|
|
||||||
|
run_installer "$artifact_two"
|
||||||
|
second_inode=$(stat -f '%i' "$test_directory/tht" 2>/dev/null || stat -c '%i' "$test_directory/tht")
|
||||||
|
second_version=$(PATH="$test_directory:$system_path" tht version)
|
||||||
|
test "$second_version" = "tht test version two" || fail "replacement did not install version two"
|
||||||
|
test "$first_inode" != "$second_inode" || fail "replacement did not atomically replace the destination"
|
||||||
|
|
||||||
|
run_installer "$artifact_two"
|
||||||
|
third_version=$(PATH="$test_directory:$system_path" tht version)
|
||||||
|
test "$third_version" = "tht test version two" || fail "re-running installer was not idempotent"
|
||||||
|
|
||||||
|
if THT_INSTALL_DIRECTORY="$test_directory" \
|
||||||
|
THT_BUILD_ARTIFACT="$artifact_one" \
|
||||||
|
THT_BUILD_ARTIFACT_SHA256="not-a-checksum" \
|
||||||
|
PATH="$test_directory:$system_path" \
|
||||||
|
bash "$installer" >/dev/null 2>&1; then
|
||||||
|
fail "installer accepted a checksum mismatch"
|
||||||
|
fi
|
||||||
|
|
||||||
|
after_failed_checksum=$(PATH="$test_directory:$system_path" tht version)
|
||||||
|
test "$after_failed_checksum" = "tht test version two" || fail "failed install replaced the existing command"
|
||||||
|
|
||||||
|
echo "shell tht installer tests passed."
|
||||||
Reference in New Issue
Block a user