feat!: installation only from a release, into an empty folder; upstream merge/verify and private-instance.md removed, dist adopt, shell-neutral instructions (#153)
Files changed: - .gitea/workflows/ci.yml - .gitea/workflows/release.yml - AGENTS.md - CHANGES.md - DEVELOPMENT.md - EVALS.md - INSTALL.md - README.md - VERSION - docs/ownership-and-templates.md - instructions/CONTRACT.md - instructions/bootstrap.md - instructions/dev/dev-setup.md - instructions/dev/stack-dev/SKILL.md - instructions/gates.md - instructions/ingest-large-tree.md - instructions/kb-profiles.md - instructions/mcp-read-server.md - instructions/migrations/3.0.0-authoring-conventions.md - instructions/preflight.md - instructions/private-instance.md - instructions/session-setup.md - instructions/setup-instance.md - instructions/upgrade-instance.md - tools/CONTRACT.md - tools/README.md - tools/chemenu/cli.py - tools/chemenu/cli_contract.py - tools/chemenu/commands/dist_cmd.py - tools/chemenu/commands/docs_verify.py - tools/chemenu/commands/doctor.py - tools/chemenu/commands/git_publish.py - tools/chemenu/commands/upstream_cmd.py - tools/chemenu/commands/work_cmd.py - tools/chemenu/config.py - tools/chemenu/ownership.py - tools/chemenu/tests/test_cli.py - tools/chemenu/tests/test_dist_cmd.py - tools/chemenu/tests/test_instructions_shell.py - tools/chemenu/tests/test_preflight.py - tools/chemenu/tests/test_preflight_pwsh.py - tools/chemenu/tests/test_run_budget.py - tools/chemenu/tests/test_upstream_cmd.py - tools/chemenu/toc.py - tools/preflight.ps1 - tools/preflight.sh
This commit is contained in:
1 parent
d0f08d1fba
commit
a6d07f97c4
46 files changed
+1314
-1936
No files matched your search
+53
-14
@@ -8,8 +8,10 @@
|
||||
# As the release asset `preflight.ps1` - a copy with no tools/prerequisites.txt next
|
||||
# to it - the script is the first install step instead: it downloads the stack
|
||||
# release named in $ReleaseArchiveUrl / $ReleaseChecksumUrl, checks the sha256,
|
||||
# unpacks it into <script folder>\chemenu (or --into <path>), and runs the copy of
|
||||
# this script inside the unpacked tree, which does everything above.
|
||||
# unpacks it into the folder it lies in (or --into <path>), removes itself there, and
|
||||
# runs the copy of this script inside the unpacked tree, which does everything above.
|
||||
# That folder has to be empty apart from this script and a .git (an empty clone of the
|
||||
# instance's own repository).
|
||||
#
|
||||
# pwsh -NoProfile -ExecutionPolicy Bypass -File preflight.ps1 [--into <path>] [--archive <tarball>]
|
||||
#
|
||||
@@ -108,8 +110,8 @@ while ($index -lt $args.Count) {
|
||||
Write-Line 'means the user has to act - the output says how.'
|
||||
Write-Line ''
|
||||
Write-Line 'The second form is the release asset: it downloads the release (or takes'
|
||||
Write-Line '--archive), checks its sha256, unpacks it into <script folder>\chemenu or --into,'
|
||||
Write-Line 'and runs the preflight inside it.'
|
||||
Write-Line '--archive), checks its sha256, unpacks it into its own folder or --into (empty,'
|
||||
Write-Line 'or holding only .git), and runs the preflight inside it.'
|
||||
exit 0
|
||||
} else {
|
||||
Write-ErrorLine "preflight: unknown argument: $arg"
|
||||
@@ -235,10 +237,33 @@ function Resolve-AssetPath {
|
||||
return [IO.Path]::GetFullPath($Path).TrimEnd('\', '/')
|
||||
}
|
||||
|
||||
# Whether the install folder holds anything besides this script and a .git - the two
|
||||
# things an empty folder may already carry: the script was downloaded into it, and the
|
||||
# user may have cloned the instance's own, still empty repository there.
|
||||
function Test-TargetOccupied {
|
||||
param([string]$Target)
|
||||
$selfName = Split-Path -Leaf $PSCommandPath
|
||||
$isOwnFolder = [IO.Path]::GetFullPath($Target).TrimEnd('\', '/') -eq [IO.Path]::GetFullPath($Dir).TrimEnd('\', '/')
|
||||
foreach ($entry in @(Get-ChildItem -LiteralPath $Target -Force)) {
|
||||
if ($entry.Name -eq '.git') {
|
||||
continue
|
||||
}
|
||||
if ($isOwnFolder -and $entry.Name -eq $selfName) {
|
||||
continue
|
||||
}
|
||||
return $true
|
||||
}
|
||||
return $false
|
||||
}
|
||||
|
||||
function Invoke-AssetMode {
|
||||
$target = if ($Into) { Resolve-AssetPath $Into } else { Join-Path $Dir 'chemenu' }
|
||||
if ($null -ne (Get-Item -LiteralPath $target -Force -ErrorAction SilentlyContinue)) {
|
||||
Exit-Asset "$target already exists - nothing was unpacked. Choose another folder with --into <path>, or move the existing one away."
|
||||
$target = if ($Into) { Resolve-AssetPath $Into } else { $Dir.TrimEnd('\', '/') }
|
||||
$existing = Get-Item -LiteralPath $target -Force -ErrorAction SilentlyContinue
|
||||
if ($null -ne $existing -and -not $existing.PSIsContainer) {
|
||||
Exit-Asset "$target exists and is not a folder - nothing was unpacked."
|
||||
}
|
||||
if ($null -ne $existing -and (Test-TargetOccupied $target)) {
|
||||
Exit-Asset "$target is not empty - nothing was unpacked. The wiki installs into an empty folder (an empty git clone is fine): put this script into one and run it there, or pass --into <path>."
|
||||
}
|
||||
|
||||
if (-not $Archive -and (-not $ReleaseArchiveUrl -or -not $ReleaseChecksumUrl)) {
|
||||
@@ -327,20 +352,28 @@ function Invoke-AssetMode {
|
||||
if ($length -gt $limit) {
|
||||
Add-Problem "The folder this wiki would be installed in is too long ($length characters, at most $limit): $target" `
|
||||
"Windows on this computer only allows paths of up to 259 characters, and the wiki's own files need the rest" `
|
||||
"Run this again with a shorter folder, for example: --into C:\Chemenu`nAlternatively, someone with administrator rights can turn on long paths in Windows."
|
||||
"Use a shorter folder such as C:\Chemenu - put this script there and run it again,`nor pass --into C:\Chemenu.`nAlternatively, someone with administrator rights can turn on long paths in Windows."
|
||||
Exit-WithGuide
|
||||
}
|
||||
}
|
||||
|
||||
$parent = Split-Path -Parent $target
|
||||
$null = New-Item -ItemType Directory -Path $parent -Force
|
||||
$unpack = Join-Path $parent ".chemenu-unpack.$PID"
|
||||
# Unpacked inside the target rather than beside it: the folder above may be a drive
|
||||
# root nobody can write to. Only then are the entries moved up, one by one.
|
||||
$null = New-Item -ItemType Directory -Path $target -Force
|
||||
$unpack = Join-Path $target ".chemenu-unpack.$PID"
|
||||
$null = New-Item -ItemType Directory -Path $unpack
|
||||
$null = Invoke-NativeVerbose $tar.Source @('-xzf', $archivePath, '-C', $unpack)
|
||||
if (-not (Test-Path -LiteralPath (Join-Path $unpack $top) -PathType Container)) {
|
||||
Exit-Asset "unpacking failed - the target was not created."
|
||||
$unpacked = Join-Path $unpack $top
|
||||
if (-not (Test-Path -LiteralPath $unpacked -PathType Container)) {
|
||||
Exit-Asset 'unpacking failed - nothing was installed.'
|
||||
}
|
||||
foreach ($entry in @(Get-ChildItem -LiteralPath $unpacked -Force)) {
|
||||
try {
|
||||
Move-Item -LiteralPath $entry.FullName -Destination $target
|
||||
} catch {
|
||||
Exit-Asset "could not move $($entry.Name) into $target - the folder holds part of the stack now; empty it (keep .git) and run this again."
|
||||
}
|
||||
}
|
||||
Move-Item -LiteralPath (Join-Path $unpack $top) -Destination $target
|
||||
} finally {
|
||||
foreach ($leftover in @($work, $unpack)) {
|
||||
if ($leftover -and (Test-Path -LiteralPath $leftover)) {
|
||||
@@ -353,6 +386,12 @@ function Invoke-AssetMode {
|
||||
if (-not (Test-Path -LiteralPath $treeScript -PathType Leaf)) {
|
||||
Exit-Asset 'the unpacked stack has no tools/preflight.ps1.'
|
||||
}
|
||||
# The release asset is not part of the stack; left in the folder, it would end up in
|
||||
# the instance's first commit beside the tree's own tools/preflight.ps1. PowerShell has
|
||||
# read the whole script before running it, so removing the file is safe here.
|
||||
if ($target -eq $Dir.TrimEnd('\', '/')) {
|
||||
Remove-Item -LiteralPath $PSCommandPath -Force
|
||||
}
|
||||
Write-Line "Unpacked into $target."
|
||||
Write-Line 'If a later step stops, run tools/preflight.ps1 from inside that folder.'
|
||||
Write-Line ''
|
||||
|
||||
Reference in new issue
Block a user