further deployment implementation to .config directory
This commit is contained in:
File diff suppressed because it is too large
Load Diff
153
ConfigLoader.ps1
153
ConfigLoader.ps1
@@ -186,28 +186,149 @@ function Get-ZipCompressionLevel {
|
|||||||
if ($MyInvocation.InvocationName -ne '.') {
|
if ($MyInvocation.InvocationName -ne '.') {
|
||||||
$projectPath = Get-ProjectPathFromUser
|
$projectPath = Get-ProjectPathFromUser
|
||||||
if ($null -ne $projectPath) {
|
if ($null -ne $projectPath) {
|
||||||
Write-Host "`nDeploying to: $projectPath" -ForegroundColor Cyan
|
# Deploy batch files and config to the project
|
||||||
|
$structDir = Get-StructDirectory
|
||||||
|
if (-not (Test-Path -LiteralPath $structDir -PathType Container)) {
|
||||||
|
Write-Error "Configured structDir not found: $structDir"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
# Find UpdateProjectBatches.ps1 in the same directory as ConfigLoader.ps1
|
try {
|
||||||
$updateScript = Join-Path -Path $script:LoaderRoot -ChildPath 'UpdateProjectBatches.ps1'
|
$resolvedProject = (Resolve-Path -LiteralPath $projectPath -ErrorAction Stop).Path
|
||||||
if (Test-Path -LiteralPath $updateScript) {
|
|
||||||
Write-Host "Running UpdateProjectBatches.ps1...`n" -ForegroundColor Yellow
|
|
||||||
& powershell -NoProfile -ExecutionPolicy Bypass -File $updateScript -ProjectPath $projectPath
|
|
||||||
$exitCode = $LASTEXITCODE
|
|
||||||
if ($exitCode -eq 0) {
|
|
||||||
Write-Host "`nDeployment completed successfully." -ForegroundColor Green
|
|
||||||
}
|
}
|
||||||
else {
|
catch {
|
||||||
Write-Host "`nDeployment completed with errors (exit code: $exitCode)." -ForegroundColor Red
|
Write-Error "Unable to resolve project directory: $($_.Exception.Message)"
|
||||||
|
exit 1
|
||||||
}
|
}
|
||||||
exit $exitCode
|
|
||||||
|
if (-not (Test-Path -LiteralPath $resolvedProject -PathType Container)) {
|
||||||
|
Write-Error "Project path is not a directory: $resolvedProject"
|
||||||
|
exit 1
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
Write-Warning "UpdateProjectBatches.ps1 not found in $script:LoaderRoot"
|
Write-Host "`nDeploying to: $resolvedProject" -ForegroundColor Cyan
|
||||||
Write-Host "Project path: $projectPath" -ForegroundColor Green
|
Write-Host "Struct directory: $structDir" -ForegroundColor Cyan
|
||||||
return $projectPath
|
|
||||||
|
$specs = @(
|
||||||
|
@{ Name = 'UpdateSequences.bat'; Source = Join-Path -Path $structDir -ChildPath 'UpdateSequences.bat' },
|
||||||
|
@{ Name = 'UpdateAllSequences.bat'; Source = Join-Path -Path $structDir -ChildPath 'UpdateAllSequences.bat' },
|
||||||
|
@{ Name = 'ZipSeqArchv.bat'; Source = Join-Path -Path $structDir -ChildPath 'ZipSeqArchv.bat' },
|
||||||
|
@{ Name = 'UnzipSeqArchv.bat'; Source = Join-Path -Path $structDir -ChildPath 'UnzipSeqArchv.bat' },
|
||||||
|
@{ Name = 'NewDaily.bat'; Source = Join-Path -Path $structDir -ChildPath 'NewDaily.bat' }
|
||||||
|
)
|
||||||
|
|
||||||
|
# Config files to deploy to projectroot\.config\
|
||||||
|
$configAssets = @(
|
||||||
|
@{ Name = 'config.json'; Source = Join-Path -Path $structDir -ChildPath 'config.json' },
|
||||||
|
@{ Name = 'GetStructDir.ps1'; Source = Join-Path -Path $structDir -ChildPath 'GetStructDir.ps1' }
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach ($spec in $specs) {
|
||||||
|
if (-not (Test-Path -LiteralPath $spec.Source -PathType Leaf)) {
|
||||||
|
Write-Error "Source file not found: $($spec.Source)"
|
||||||
|
exit 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach ($asset in $configAssets) {
|
||||||
|
if (-not (Test-Path -LiteralPath $asset.Source -PathType Leaf)) {
|
||||||
|
Write-Error "Config asset not found: $($asset.Source)"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ensure .config directory exists in project root and is hidden
|
||||||
|
$projectConfigDir = Join-Path -Path $resolvedProject -ChildPath '.config'
|
||||||
|
if (-not (Test-Path -LiteralPath $projectConfigDir -PathType Container)) {
|
||||||
|
New-Item -Path $projectConfigDir -ItemType Directory -Force | Out-Null
|
||||||
|
Write-Host "Created .config directory: $projectConfigDir" -ForegroundColor Cyan
|
||||||
|
}
|
||||||
|
# Set hidden attribute on .config directory
|
||||||
|
$folder = Get-Item -LiteralPath $projectConfigDir -Force
|
||||||
|
$folder.Attributes = $folder.Attributes -bor [System.IO.FileAttributes]::Hidden
|
||||||
|
|
||||||
|
$touchedDirs = @{}
|
||||||
|
$summary = @()
|
||||||
|
|
||||||
|
foreach ($spec in $specs) {
|
||||||
|
Write-Host "`n=== Updating $($spec.Name) ===" -ForegroundColor Magenta
|
||||||
|
|
||||||
|
$targets = Get-ChildItem -LiteralPath $resolvedProject -Recurse -Filter $spec.Name -File -ErrorAction SilentlyContinue
|
||||||
|
$targets = $targets | Where-Object { $_.FullName -ne $spec.Source }
|
||||||
|
|
||||||
|
if (-not $targets) {
|
||||||
|
Write-Host "No targets found." -ForegroundColor Yellow
|
||||||
|
$summary += [pscustomobject]@{
|
||||||
|
Name = $spec.Name
|
||||||
|
Updated = 0
|
||||||
|
Failed = 0
|
||||||
|
Skipped = 0
|
||||||
|
Total = 0
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
$updated = 0
|
||||||
|
$failed = 0
|
||||||
|
|
||||||
|
foreach ($target in $targets) {
|
||||||
|
try {
|
||||||
|
Copy-Item -Path $spec.Source -Destination $target.FullName -Force
|
||||||
|
Write-Host "[OK] $($target.FullName)" -ForegroundColor Green
|
||||||
|
$updated++
|
||||||
|
|
||||||
|
$targetDir = $target.Directory.FullName
|
||||||
|
if (-not $touchedDirs.ContainsKey($targetDir)) {
|
||||||
|
$touchedDirs[$targetDir] = $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Host "[FAIL] $($target.FullName)" -ForegroundColor Red
|
||||||
|
Write-Host " $($_.Exception.Message)" -ForegroundColor DarkRed
|
||||||
|
$failed++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$summary += [pscustomobject]@{
|
||||||
|
Name = $spec.Name
|
||||||
|
Updated = $updated
|
||||||
|
Failed = $failed
|
||||||
|
Skipped = 0
|
||||||
|
Total = @($targets).Count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "`n=== Summary ===" -ForegroundColor Cyan
|
||||||
|
foreach ($item in $summary) {
|
||||||
|
Write-Host ("{0,-22} Updated: {1,3} Failed: {2,3} Total: {3,3}" -f $item.Name, $item.Updated, $item.Failed, $item.Total)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($summary | Measure-Object -Property Failed -Sum).Sum -gt 0) {
|
||||||
|
Write-Host "Completed with errors." -ForegroundColor Yellow
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "All batch files refreshed successfully." -ForegroundColor Green
|
||||||
|
|
||||||
|
# Deploy config files to projectroot\.config\
|
||||||
|
Write-Host "`n=== Deploying config files to .config\ ===" -ForegroundColor Magenta
|
||||||
|
foreach ($asset in $configAssets) {
|
||||||
|
$targetPath = Join-Path -Path $projectConfigDir -ChildPath $asset.Name
|
||||||
|
try {
|
||||||
|
Copy-Item -Path $asset.Source -Destination $targetPath -Force
|
||||||
|
Write-Host "[OK] $targetPath" -ForegroundColor Green
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Host "[FAIL] $targetPath" -ForegroundColor Red
|
||||||
|
Write-Host " $($_.Exception.Message)" -ForegroundColor DarkRed
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "`nConfig files deployed successfully." -ForegroundColor Green
|
||||||
|
Write-Host "Deployment completed successfully." -ForegroundColor Green
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
Write-Host "No project path provided." -ForegroundColor Yellow
|
Write-Host "No project path provided." -ForegroundColor Yellow
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
68
GetStructDir.ps1
Normal file
68
GetStructDir.ps1
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
# Simple helper script to get structDir from project config.json
|
||||||
|
# Reads config.json from .config folder in project root
|
||||||
|
|
||||||
|
param(
|
||||||
|
[string]$ProjectRoot
|
||||||
|
)
|
||||||
|
|
||||||
|
Set-StrictMode -Version Latest
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
|
if ([string]::IsNullOrWhiteSpace($ProjectRoot)) {
|
||||||
|
# Try to determine project root from script location
|
||||||
|
if ($PSScriptRoot) {
|
||||||
|
$ProjectRoot = Split-Path -Parent $PSScriptRoot
|
||||||
|
}
|
||||||
|
elseif ($MyInvocation.MyCommand.Path) {
|
||||||
|
$ProjectRoot = Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Error "Unable to determine project root. Please provide -ProjectRoot parameter."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$configPath = Join-Path -Path $ProjectRoot -ChildPath '.config\config.json'
|
||||||
|
|
||||||
|
if (-not (Test-Path -LiteralPath $configPath -PathType Leaf)) {
|
||||||
|
Write-Error "config.json not found at: $configPath"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$config = Get-Content -LiteralPath $configPath -Raw -ErrorAction Stop | ConvertFrom-Json
|
||||||
|
|
||||||
|
if ($config.PSObject.Properties.Name -contains 'structDir') {
|
||||||
|
$structDir = $config.structDir
|
||||||
|
if ($null -ne $structDir -and ($structDir -isnot [string] -or $structDir.Trim().Length -gt 0)) {
|
||||||
|
# If it's an absolute path, resolve it
|
||||||
|
if ([System.IO.Path]::IsPathRooted($structDir)) {
|
||||||
|
$resolved = Resolve-Path -LiteralPath $structDir -ErrorAction SilentlyContinue
|
||||||
|
if ($null -ne $resolved) {
|
||||||
|
Write-Output $resolved.Path
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
Write-Output $structDir
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
# Relative path - resolve relative to config location
|
||||||
|
$candidate = Join-Path -Path (Split-Path -Parent $configPath) -ChildPath $structDir
|
||||||
|
$resolvedCandidate = Resolve-Path -LiteralPath $candidate -ErrorAction SilentlyContinue
|
||||||
|
if ($null -ne $resolvedCandidate) {
|
||||||
|
Write-Output $resolvedCandidate.Path
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
Write-Output $candidate
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Default: return the directory containing config.json (project root)
|
||||||
|
Write-Output $ProjectRoot
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Error "Failed to read or parse config.json: $($_.Exception.Message)"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
@@ -4,23 +4,24 @@ setlocal EnableExtensions
|
|||||||
set "REN_DIR=%~dp0"
|
set "REN_DIR=%~dp0"
|
||||||
for %%I in ("%REN_DIR%..") do set "PROJ_ROOT=%%~fI"
|
for %%I in ("%REN_DIR%..") do set "PROJ_ROOT=%%~fI"
|
||||||
|
|
||||||
set "CONFIG_LOADER=%REN_DIR%ConfigLoader.ps1"
|
set "CONFIG_DIR=%PROJ_ROOT%\.config"
|
||||||
set "CONFIG_PATH=%REN_DIR%config.json"
|
set "CONFIG_PATH=%CONFIG_DIR%\config.json"
|
||||||
|
set "GET_STRUCT_DIR=%CONFIG_DIR%\GetStructDir.ps1"
|
||||||
|
|
||||||
if not exist "%CONFIG_LOADER%" (
|
if not exist "%CONFIG_PATH%" (
|
||||||
echo [ERROR] ConfigLoader.ps1 not found next to UnzipSeqArchv.bat.
|
echo [ERROR] config.json not found at %CONFIG_PATH%
|
||||||
echo Please run UpdateProjectBatches.ps1 to refresh helper files.
|
echo Please run UpdateProjectBatches.ps1 to refresh helper files.
|
||||||
exit /b 1
|
exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
if not exist "%CONFIG_PATH%" (
|
if not exist "%GET_STRUCT_DIR%" (
|
||||||
echo [ERROR] config.json not found next to UnzipSeqArchv.bat.
|
echo [ERROR] GetStructDir.ps1 not found at %GET_STRUCT_DIR%
|
||||||
echo Please run UpdateProjectBatches.ps1 to refresh helper files.
|
echo Please run UpdateProjectBatches.ps1 to refresh helper files.
|
||||||
exit /b 1
|
exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
for /f "usebackq delims=" %%I in (`powershell -NoProfile -ExecutionPolicy Bypass -Command ^
|
for /f "usebackq delims=" %%I in (`powershell -NoProfile -ExecutionPolicy Bypass -Command ^
|
||||||
"Set-StrictMode -Version Latest; $loader = Resolve-Path -LiteralPath '%CONFIG_LOADER%' -ErrorAction Stop; . $loader.Path; $pyPath = Join-Path (Get-StructDirectory) 'zip_sequences.py'; if (-not (Test-Path -LiteralPath $pyPath)) { throw \"zip_sequences.py not found at $pyPath\" }; Write-Output $pyPath"`) do set "PY_SCRIPT=%%I"
|
"Set-StrictMode -Version Latest; $structDir = & '%GET_STRUCT_DIR%' -ProjectRoot '%PROJ_ROOT%'; if (-not $structDir) { throw \"Failed to get structDir from GetStructDir.ps1\" }; $pyPath = Join-Path $structDir 'zip_sequences.py'; if (-not (Test-Path -LiteralPath $pyPath)) { throw \"zip_sequences.py not found at $pyPath\" }; Write-Output $pyPath"`) do set "PY_SCRIPT=%%I"
|
||||||
|
|
||||||
if not defined PY_SCRIPT (
|
if not defined PY_SCRIPT (
|
||||||
echo [ERROR] Unable to resolve zip_sequences.py path from config.
|
echo [ERROR] Unable to resolve zip_sequences.py path from config.
|
||||||
|
|||||||
@@ -55,9 +55,10 @@ $specs = @(
|
|||||||
@{ Name = 'NewDaily.bat'; Source = Join-Path -Path $structDir -ChildPath 'NewDaily.bat' }
|
@{ Name = 'NewDaily.bat'; Source = Join-Path -Path $structDir -ChildPath 'NewDaily.bat' }
|
||||||
)
|
)
|
||||||
|
|
||||||
$sharedAssets = @(
|
# Config files to deploy to projectroot\.config\
|
||||||
@{ Name = 'ConfigLoader.ps1'; Source = Join-Path -Path $structDir -ChildPath 'ConfigLoader.ps1' },
|
$configAssets = @(
|
||||||
@{ Name = 'config.json'; Source = Join-Path -Path $structDir -ChildPath 'config.json' }
|
@{ Name = 'config.json'; Source = Join-Path -Path $structDir -ChildPath 'config.json' },
|
||||||
|
@{ Name = 'GetStructDir.ps1'; Source = Join-Path -Path $structDir -ChildPath 'GetStructDir.ps1' }
|
||||||
)
|
)
|
||||||
|
|
||||||
foreach ($spec in $specs) {
|
foreach ($spec in $specs) {
|
||||||
@@ -67,13 +68,20 @@ foreach ($spec in $specs) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($asset in $sharedAssets) {
|
foreach ($asset in $configAssets) {
|
||||||
if (-not (Test-Path -LiteralPath $asset.Source -PathType Leaf)) {
|
if (-not (Test-Path -LiteralPath $asset.Source -PathType Leaf)) {
|
||||||
Write-Error "Shared asset not found: $($asset.Source)"
|
Write-Error "Config asset not found: $($asset.Source)"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Ensure .config directory exists in project root
|
||||||
|
$projectConfigDir = Join-Path -Path $resolvedProject -ChildPath '.config'
|
||||||
|
if (-not (Test-Path -LiteralPath $projectConfigDir -PathType Container)) {
|
||||||
|
New-Item -Path $projectConfigDir -ItemType Directory -Force | Out-Null
|
||||||
|
Write-Host "Created .config directory: $projectConfigDir" -ForegroundColor Cyan
|
||||||
|
}
|
||||||
|
|
||||||
$touchedDirs = @{}
|
$touchedDirs = @{}
|
||||||
$summary = @()
|
$summary = @()
|
||||||
|
|
||||||
@@ -106,14 +114,6 @@ foreach ($spec in $specs) {
|
|||||||
|
|
||||||
$targetDir = $target.Directory.FullName
|
$targetDir = $target.Directory.FullName
|
||||||
if (-not $touchedDirs.ContainsKey($targetDir)) {
|
if (-not $touchedDirs.ContainsKey($targetDir)) {
|
||||||
foreach ($asset in $sharedAssets) {
|
|
||||||
try {
|
|
||||||
Copy-Item -Path $asset.Source -Destination (Join-Path -Path $targetDir -ChildPath $asset.Name) -Force
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Host " [FAIL] Failed to copy $($asset.Name) into ${targetDir}: $($_.Exception.Message)" -ForegroundColor Red
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$touchedDirs[$targetDir] = $true
|
$touchedDirs[$targetDir] = $true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -145,3 +145,20 @@ if (($summary | Measure-Object -Property Failed -Sum).Sum -gt 0) {
|
|||||||
|
|
||||||
Write-Host "All batch files refreshed successfully." -ForegroundColor Green
|
Write-Host "All batch files refreshed successfully." -ForegroundColor Green
|
||||||
|
|
||||||
|
# Deploy config files to projectroot\.config\
|
||||||
|
Write-Host "`n=== Deploying config files to .config\ ===" -ForegroundColor Magenta
|
||||||
|
foreach ($asset in $configAssets) {
|
||||||
|
$targetPath = Join-Path -Path $projectConfigDir -ChildPath $asset.Name
|
||||||
|
try {
|
||||||
|
Copy-Item -Path $asset.Source -Destination $targetPath -Force
|
||||||
|
Write-Host "[OK] $targetPath" -ForegroundColor Green
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Host "[FAIL] $targetPath" -ForegroundColor Red
|
||||||
|
Write-Host " $($_.Exception.Message)" -ForegroundColor DarkRed
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Config files deployed successfully." -ForegroundColor Green
|
||||||
|
|
||||||
|
|||||||
@@ -2,23 +2,26 @@
|
|||||||
setlocal EnableExtensions
|
setlocal EnableExtensions
|
||||||
|
|
||||||
set "script_dir=%~dp0"
|
set "script_dir=%~dp0"
|
||||||
set "config_loader=%script_dir%ConfigLoader.ps1"
|
for %%I in ("%script_dir%..") do set "PROJ_ROOT=%%~fI"
|
||||||
set "config_path=%script_dir%config.json"
|
|
||||||
|
|
||||||
if not exist "%config_loader%" (
|
set "CONFIG_DIR=%PROJ_ROOT%\.config"
|
||||||
echo [ERROR] ConfigLoader.ps1 not found next to UpdateSequences.bat.
|
set "CONFIG_PATH=%CONFIG_DIR%\config.json"
|
||||||
|
set "GET_STRUCT_DIR=%CONFIG_DIR%\GetStructDir.ps1"
|
||||||
|
|
||||||
|
if not exist "%CONFIG_PATH%" (
|
||||||
|
echo [ERROR] config.json not found at %CONFIG_PATH%
|
||||||
echo Please run UpdateProjectBatches.ps1 to refresh helper files.
|
echo Please run UpdateProjectBatches.ps1 to refresh helper files.
|
||||||
exit /b 1
|
exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
if not exist "%config_path%" (
|
if not exist "%GET_STRUCT_DIR%" (
|
||||||
echo [ERROR] config.json not found next to UpdateSequences.bat.
|
echo [ERROR] GetStructDir.ps1 not found at %GET_STRUCT_DIR%
|
||||||
echo Please run UpdateProjectBatches.ps1 to refresh helper files.
|
echo Please run UpdateProjectBatches.ps1 to refresh helper files.
|
||||||
exit /b 1
|
exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
for /f "usebackq delims=" %%I in (`powershell -NoProfile -ExecutionPolicy Bypass -Command ^
|
for /f "usebackq delims=" %%I in (`powershell -NoProfile -ExecutionPolicy Bypass -Command ^
|
||||||
"Set-StrictMode -Version Latest; $loader = Resolve-Path -LiteralPath '%config_loader%' -ErrorAction Stop; . $loader.Path; $ps1Path = Join-Path (Get-StructDirectory) 'UpdateSequences.ps1'; if (-not (Test-Path -LiteralPath $ps1Path)) { throw \"UpdateSequences.ps1 not found at $ps1Path\" }; Write-Output $ps1Path"`) do set "ps1=%%I"
|
"Set-StrictMode -Version Latest; $structDir = & '%GET_STRUCT_DIR%' -ProjectRoot '%PROJ_ROOT%'; if (-not $structDir) { throw \"Failed to get structDir from GetStructDir.ps1\" }; $ps1Path = Join-Path $structDir 'UpdateSequences.ps1'; if (-not (Test-Path -LiteralPath $ps1Path)) { throw \"UpdateSequences.ps1 not found at $ps1Path\" }; Write-Output $ps1Path"`) do set "ps1=%%I"
|
||||||
|
|
||||||
if not defined ps1 (
|
if not defined ps1 (
|
||||||
echo [ERROR] Unable to resolve UpdateSequences.ps1 path from config.
|
echo [ERROR] Unable to resolve UpdateSequences.ps1 path from config.
|
||||||
|
|||||||
@@ -4,23 +4,24 @@ setlocal EnableExtensions
|
|||||||
set "REN_DIR=%~dp0"
|
set "REN_DIR=%~dp0"
|
||||||
for %%I in ("%REN_DIR%..") do set "PROJ_ROOT=%%~fI"
|
for %%I in ("%REN_DIR%..") do set "PROJ_ROOT=%%~fI"
|
||||||
|
|
||||||
set "CONFIG_LOADER=%REN_DIR%ConfigLoader.ps1"
|
set "CONFIG_DIR=%PROJ_ROOT%\.config"
|
||||||
set "CONFIG_PATH=%REN_DIR%config.json"
|
set "CONFIG_PATH=%CONFIG_DIR%\config.json"
|
||||||
|
set "GET_STRUCT_DIR=%CONFIG_DIR%\GetStructDir.ps1"
|
||||||
|
|
||||||
if not exist "%CONFIG_LOADER%" (
|
if not exist "%CONFIG_PATH%" (
|
||||||
echo [ERROR] ConfigLoader.ps1 not found next to ZipSeqArchv.bat.
|
echo [ERROR] config.json not found at %CONFIG_PATH%
|
||||||
echo Please run UpdateProjectBatches.ps1 to refresh helper files.
|
echo Please run UpdateProjectBatches.ps1 to refresh helper files.
|
||||||
exit /b 1
|
exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
if not exist "%CONFIG_PATH%" (
|
if not exist "%GET_STRUCT_DIR%" (
|
||||||
echo [ERROR] config.json not found next to ZipSeqArchv.bat.
|
echo [ERROR] GetStructDir.ps1 not found at %GET_STRUCT_DIR%
|
||||||
echo Please run UpdateProjectBatches.ps1 to refresh helper files.
|
echo Please run UpdateProjectBatches.ps1 to refresh helper files.
|
||||||
exit /b 1
|
exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
for /f "usebackq delims=" %%I in (`powershell -NoProfile -ExecutionPolicy Bypass -Command ^
|
for /f "usebackq delims=" %%I in (`powershell -NoProfile -ExecutionPolicy Bypass -Command ^
|
||||||
"Set-StrictMode -Version Latest; $loader = Resolve-Path -LiteralPath '%CONFIG_LOADER%' -ErrorAction Stop; . $loader.Path; $pyPath = Join-Path (Get-StructDirectory) 'zip_sequences.py'; if (-not (Test-Path -LiteralPath $pyPath)) { throw \"zip_sequences.py not found at $pyPath\" }; Write-Output $pyPath"`) do set "PY_SCRIPT=%%I"
|
"Set-StrictMode -Version Latest; $structDir = & '%GET_STRUCT_DIR%' -ProjectRoot '%PROJ_ROOT%'; if (-not $structDir) { throw \"Failed to get structDir from GetStructDir.ps1\" }; $pyPath = Join-Path $structDir 'zip_sequences.py'; if (-not (Test-Path -LiteralPath $pyPath)) { throw \"zip_sequences.py not found at $pyPath\" }; Write-Output $pyPath"`) do set "PY_SCRIPT=%%I"
|
||||||
|
|
||||||
if not defined PY_SCRIPT (
|
if not defined PY_SCRIPT (
|
||||||
echo [ERROR] Unable to resolve zip_sequences.py path from config.
|
echo [ERROR] Unable to resolve zip_sequences.py path from config.
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import shutil
|
|||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
|
import time
|
||||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Iterator, Sequence
|
from typing import Iterator, Sequence
|
||||||
@@ -195,27 +196,50 @@ def zip_sequence(seq_dir: Path, zip_path: Path) -> None:
|
|||||||
if SEVEN_Z_EXE is None:
|
if SEVEN_Z_EXE is None:
|
||||||
raise RuntimeError("7z compression requested but 7z executable not found in PATH")
|
raise RuntimeError("7z compression requested but 7z executable not found in PATH")
|
||||||
zip_path.parent.mkdir(parents=True, exist_ok=True)
|
zip_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
# Remove existing zip file if it exists to avoid corruption issues
|
||||||
|
if zip_path.exists():
|
||||||
|
try:
|
||||||
|
zip_path.unlink()
|
||||||
|
except OSError:
|
||||||
|
# If deletion fails, try to overwrite with -aoa flag
|
||||||
|
pass
|
||||||
|
|
||||||
# Build list of files to archive with relative paths
|
# Build list of files to archive with relative paths
|
||||||
file_list = []
|
file_list = []
|
||||||
for file_path in iter_sequence_files(seq_dir):
|
for file_path in iter_sequence_files(seq_dir):
|
||||||
rel_path = file_path.relative_to(seq_dir).as_posix()
|
rel_path = file_path.relative_to(seq_dir).as_posix()
|
||||||
file_list.append(rel_path)
|
file_list.append(rel_path)
|
||||||
|
|
||||||
|
if not file_list:
|
||||||
|
raise RuntimeError(f"No files found to archive in {seq_dir}")
|
||||||
|
|
||||||
# Use a temporary list file to avoid Windows command line length limits
|
# Use a temporary list file to avoid Windows command line length limits
|
||||||
with tempfile.NamedTemporaryFile(mode="w", suffix=".lst", delete=False, encoding="utf-8") as list_file:
|
list_file_path = None
|
||||||
list_file_path = Path(list_file.name)
|
try:
|
||||||
|
# Create list file with absolute path
|
||||||
|
fd, temp_path = tempfile.mkstemp(suffix=".lst", text=True)
|
||||||
|
list_file_path = Path(temp_path)
|
||||||
|
with os.fdopen(fd, "w", encoding="utf-8") as list_file:
|
||||||
for rel_path in file_list:
|
for rel_path in file_list:
|
||||||
list_file.write(rel_path + "\n")
|
list_file.write(rel_path + "\n")
|
||||||
|
list_file.flush()
|
||||||
|
os.fsync(list_file.fileno()) # Ensure data is written to disk
|
||||||
|
# File is closed here by context manager, small delay to ensure OS releases handle
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
try:
|
# Use absolute path for list file in 7z command
|
||||||
|
list_file_abs = list_file_path.resolve()
|
||||||
|
# Use -aoa to overwrite all files, -bb0 to suppress progress output
|
||||||
cmd = [
|
cmd = [
|
||||||
SEVEN_Z_EXE,
|
SEVEN_Z_EXE,
|
||||||
"a",
|
"a",
|
||||||
"-y",
|
"-y",
|
||||||
|
"-aoa", # Overwrite all existing files
|
||||||
|
"-bb0", # Suppress progress output
|
||||||
f"-mx={COMPRESSION_LEVEL}",
|
f"-mx={COMPRESSION_LEVEL}",
|
||||||
"-tzip",
|
"-tzip",
|
||||||
str(zip_path),
|
str(zip_path),
|
||||||
f"@{list_file_path}",
|
f"@{list_file_abs}",
|
||||||
]
|
]
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
cmd,
|
cmd,
|
||||||
@@ -226,9 +250,24 @@ def zip_sequence(seq_dir: Path, zip_path: Path) -> None:
|
|||||||
text=True,
|
text=True,
|
||||||
)
|
)
|
||||||
if result.returncode != 0:
|
if result.returncode != 0:
|
||||||
raise RuntimeError(f"7z compression failed: {result.stderr}")
|
error_msg = result.stderr.strip() if result.stderr else "Unknown error"
|
||||||
|
if result.stdout:
|
||||||
|
error_msg += f"\nstdout: {result.stdout.strip()}"
|
||||||
|
raise RuntimeError(f"7z compression failed: {error_msg}")
|
||||||
finally:
|
finally:
|
||||||
|
# Clean up list file, with retry in case 7z still has it open
|
||||||
|
if list_file_path and list_file_path.exists():
|
||||||
|
for attempt in range(3):
|
||||||
|
try:
|
||||||
list_file_path.unlink(missing_ok=True)
|
list_file_path.unlink(missing_ok=True)
|
||||||
|
break
|
||||||
|
except PermissionError:
|
||||||
|
if attempt < 2:
|
||||||
|
time.sleep(0.1) # Wait 100ms before retry
|
||||||
|
else:
|
||||||
|
# Last attempt failed, just log and continue
|
||||||
|
# The temp file will be cleaned up by the OS eventually
|
||||||
|
pass
|
||||||
return
|
return
|
||||||
|
|
||||||
# Use zipfile (ZIPPER_TYPE == "zip" or fallback)
|
# Use zipfile (ZIPPER_TYPE == "zip" or fallback)
|
||||||
|
|||||||
Reference in New Issue
Block a user