167 lines
5.1 KiB
PowerShell
167 lines
5.1 KiB
PowerShell
<#
|
|||
|
|
.SYNOPSIS
|
||
|
|
Install a built CMBot release into the local launcher layout.
|
||
|
|
|
||
|
|
.DESCRIPTION
|
||
|
|
Creates or updates this structure:
|
||
|
|
|
||
|
|
%LOCALAPPDATA%\CMBot\
|
||
|
|
update.ps1
|
||
|
|
app\
|
||
|
|
app.old\
|
||
|
|
data\
|
||
|
|
config\
|
||
|
|
logs\
|
||
|
|
output\
|
||
|
|
staging\
|
||
|
|
|
||
|
|
The script copies a built release directory (release\CMBot-x.y.z by default)
|
||
|
|
into app\, copies scripts\update.ps1 to the install root, and migrates
|
||
|
|
config files into data\config without overwriting existing user config.
|
||
|
|
|
||
|
|
.PARAMETER ReleaseDir
|
||
|
|
Built release directory to install. Defaults to release\CMBot-APP_VERSION.
|
||
|
|
|
||
|
|
.PARAMETER InstallRoot
|
||
|
|
Local install root. Defaults to %LOCALAPPDATA%\CMBot.
|
||
|
|
|
||
|
|
.PARAMETER LegacyDataDir
|
||
|
|
Optional old flat install/data root. When provided, config files are copied
|
||
|
|
from LegacyDataDir\config before falling back to app.old\config or release
|
||
|
|
defaults.
|
||
|
|
|
||
|
|
.PARAMETER Force
|
||
|
|
Allows replacing an existing app.old directory.
|
||
|
|
#>
|
||
|
|
[CmdletBinding()]
|
||
|
|
param(
|
||
|
|
[string]$ReleaseDir = "",
|
||
|
|
[string]$InstallRoot = (Join-Path $env:LOCALAPPDATA "CMBot"),
|
||
|
|
[string]$LegacyDataDir = "",
|
||
|
|
[switch]$Force
|
||
|
|
)
|
||
|
|
|
||
|
|
$ErrorActionPreference = "Stop"
|
||
|
|
|
||
|
|
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||
|
|
$RootDir = Split-Path -Parent $ScriptDir
|
||
|
|
$VersionFile = Join-Path $RootDir "src\version.py"
|
||
|
|
$ReleaseRoot = Join-Path $RootDir "release"
|
||
|
|
$LauncherScript = Join-Path $ScriptDir "update.ps1"
|
||
|
|
$AppExeName = "CMBot"
|
||
|
|
$AppExe = "$AppExeName.exe"
|
||
|
|
|
||
|
|
function Read-VersionValue {
|
||
|
|
param(
|
||
|
|
[string]$Path,
|
||
|
|
[string]$Name
|
||
|
|
)
|
||
|
|
|
||
|
|
$pattern = "^\s*$Name\s*=\s*`"([^`"]+)`""
|
||
|
|
foreach ($line in Get-Content -LiteralPath $Path -Encoding UTF8) {
|
||
|
|
if ($line -match $pattern) {
|
||
|
|
return $Matches[1]
|
||
|
|
}
|
||
|
|
}
|
||
|
|
throw "Cannot find $Name in $Path"
|
||
|
|
}
|
||
|
|
|
||
|
|
function Resolve-ExistingPath {
|
||
|
|
param(
|
||
|
|
[string]$Path,
|
||
|
|
[string]$Name
|
||
|
|
)
|
||
|
|
if (-not (Test-Path -LiteralPath $Path)) {
|
||
|
|
throw "$Name not found: $Path"
|
||
|
|
}
|
||
|
|
return (Resolve-Path -LiteralPath $Path).Path
|
||
|
|
}
|
||
|
|
|
||
|
|
function Assert-Release {
|
||
|
|
param([string]$Path)
|
||
|
|
$exe = Join-Path $Path $AppExe
|
||
|
|
$version = Join-Path $Path "version.txt"
|
||
|
|
if (-not (Test-Path -LiteralPath $exe)) {
|
||
|
|
throw "Release missing executable: $exe"
|
||
|
|
}
|
||
|
|
if (-not (Test-Path -LiteralPath $version)) {
|
||
|
|
throw "Release missing version.txt: $version"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function Copy-ConfigIfMissing {
|
||
|
|
param(
|
||
|
|
[string]$SourceConfigDir,
|
||
|
|
[string]$TargetConfigDir,
|
||
|
|
[string]$FileName
|
||
|
|
)
|
||
|
|
if (-not $SourceConfigDir) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
$source = Join-Path $SourceConfigDir $FileName
|
||
|
|
$target = Join-Path $TargetConfigDir $FileName
|
||
|
|
if ((Test-Path -LiteralPath $source) -and -not (Test-Path -LiteralPath $target)) {
|
||
|
|
Copy-Item -LiteralPath $source -Destination $target
|
||
|
|
Write-Host "Migrated config: $FileName"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (-not $ReleaseDir) {
|
||
|
|
$appVersion = Read-VersionValue -Path $VersionFile -Name "APP_VERSION"
|
||
|
|
$ReleaseDir = Join-Path $ReleaseRoot "$AppExeName-$appVersion"
|
||
|
|
}
|
||
|
|
|
||
|
|
$ReleaseDir = Resolve-ExistingPath -Path $ReleaseDir -Name "Release directory"
|
||
|
|
$LauncherScript = Resolve-ExistingPath -Path $LauncherScript -Name "Launcher script"
|
||
|
|
Assert-Release -Path $ReleaseDir
|
||
|
|
|
||
|
|
$InstallRoot = [System.IO.Path]::GetFullPath($InstallRoot)
|
||
|
|
$AppDir = Join-Path $InstallRoot "app"
|
||
|
|
$OldAppDir = Join-Path $InstallRoot "app.old"
|
||
|
|
$DataDir = Join-Path $InstallRoot "data"
|
||
|
|
$ConfigDir = Join-Path $DataDir "config"
|
||
|
|
$LogsDir = Join-Path $DataDir "logs"
|
||
|
|
$OutputDir = Join-Path $DataDir "output"
|
||
|
|
$StagingDir = Join-Path $InstallRoot "staging"
|
||
|
|
|
||
|
|
New-Item -ItemType Directory -Force -Path $InstallRoot | Out-Null
|
||
|
|
New-Item -ItemType Directory -Force -Path $ConfigDir | Out-Null
|
||
|
|
New-Item -ItemType Directory -Force -Path $LogsDir | Out-Null
|
||
|
|
New-Item -ItemType Directory -Force -Path $OutputDir | Out-Null
|
||
|
|
New-Item -ItemType Directory -Force -Path $StagingDir | Out-Null
|
||
|
|
|
||
|
|
if (Test-Path -LiteralPath $AppDir) {
|
||
|
|
if (Test-Path -LiteralPath $OldAppDir) {
|
||
|
|
if (-not $Force) {
|
||
|
|
throw "app.old already exists: $OldAppDir. Re-run with -Force to replace it."
|
||
|
|
}
|
||
|
|
Remove-Item -LiteralPath $OldAppDir -Recurse -Force
|
||
|
|
}
|
||
|
|
Move-Item -LiteralPath $AppDir -Destination $OldAppDir
|
||
|
|
}
|
||
|
|
|
||
|
|
Copy-Item -LiteralPath $ReleaseDir -Destination $AppDir -Recurse
|
||
|
|
Copy-Item -LiteralPath $LauncherScript -Destination (Join-Path $InstallRoot "update.ps1") -Force
|
||
|
|
|
||
|
|
$configSources = @()
|
||
|
|
if ($LegacyDataDir) {
|
||
|
|
$configSources += Join-Path ([System.IO.Path]::GetFullPath($LegacyDataDir)) "config"
|
||
|
|
}
|
||
|
|
if (Test-Path -LiteralPath $OldAppDir) {
|
||
|
|
$configSources += Join-Path $OldAppDir "config"
|
||
|
|
}
|
||
|
|
$configSources += Join-Path $AppDir "config"
|
||
|
|
|
||
|
|
foreach ($sourceConfig in $configSources) {
|
||
|
|
Copy-ConfigIfMissing -SourceConfigDir $sourceConfig -TargetConfigDir $ConfigDir -FileName "app_config.json"
|
||
|
|
Copy-ConfigIfMissing -SourceConfigDir $sourceConfig -TargetConfigDir $ConfigDir -FileName "templates.json"
|
||
|
|
}
|
||
|
|
|
||
|
|
Write-Host "Installed CMBot launcher layout:"
|
||
|
|
Write-Host " Root: $InstallRoot"
|
||
|
|
Write-Host " App: $AppDir"
|
||
|
|
Write-Host " Data: $DataDir"
|
||
|
|
Write-Host ""
|
||
|
|
Write-Host "Start with:"
|
||
|
|
Write-Host " powershell -ExecutionPolicy Bypass -File `"$InstallRoot\update.ps1`""
|