109 lines
3.8 KiB
PowerShell
109 lines
3.8 KiB
PowerShell
[CmdletBinding()]
|
|
param(
|
|
[switch]$BuildOnly,
|
|
[switch]$SyncOnly,
|
|
[string]$WorkRoot
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
Set-StrictMode -Version Latest
|
|
|
|
$repositoryRoot = Split-Path -Parent $PSScriptRoot
|
|
$sourceApp = Join-Path $repositoryRoot 'flutter_app'
|
|
if (-not (Test-Path -LiteralPath (Join-Path $sourceApp 'pubspec.yaml') -PathType Leaf)) {
|
|
throw "Flutter project was not found under '$sourceApp'."
|
|
}
|
|
|
|
$localAppData = [IO.Path]::GetFullPath($env:LOCALAPPDATA).TrimEnd('\')
|
|
$tempDirectory = [IO.Path]::GetFullPath($env:TEMP).TrimEnd('\')
|
|
if ([string]::IsNullOrWhiteSpace($WorkRoot)) {
|
|
$WorkRoot = Join-Path $localAppData 'SovereignAI-Starter\windows-dev\flutter_app'
|
|
}
|
|
$workRootPath = [IO.Path]::GetFullPath($WorkRoot).TrimEnd('\')
|
|
$allowedRoots = @($localAppData, $tempDirectory)
|
|
$isAllowedRoot = $false
|
|
foreach ($allowedRoot in $allowedRoots) {
|
|
if ($workRootPath.StartsWith($allowedRoot + '\', [StringComparison]::OrdinalIgnoreCase)) {
|
|
$isAllowedRoot = $true
|
|
break
|
|
}
|
|
}
|
|
if (-not $isAllowedRoot) {
|
|
throw 'WorkRoot must be a child directory of LOCALAPPDATA or TEMP.'
|
|
}
|
|
|
|
if (Test-Path -LiteralPath $workRootPath) {
|
|
$workRootItem = Get-Item -LiteralPath $workRootPath -Force
|
|
if (($workRootItem.Attributes -band [IO.FileAttributes]::ReparsePoint) -ne 0) {
|
|
throw "Refusing to use a reparse-point work directory: $workRootPath"
|
|
}
|
|
} else {
|
|
New-Item -ItemType Directory -Path $workRootPath | Out-Null
|
|
}
|
|
|
|
$destinationAppPath = $workRootPath
|
|
if (-not (Test-Path -LiteralPath $destinationAppPath)) {
|
|
New-Item -ItemType Directory -Path $destinationAppPath | Out-Null
|
|
}
|
|
$destinationAppPath = (Resolve-Path -LiteralPath $destinationAppPath).Path
|
|
$destinationItem = Get-Item -LiteralPath $destinationAppPath -Force
|
|
if (($destinationItem.Attributes -band [IO.FileAttributes]::ReparsePoint) -ne 0) {
|
|
throw "Refusing to mirror source into a reparse-point directory: $destinationAppPath"
|
|
}
|
|
|
|
if (-not $SyncOnly) {
|
|
$runningApps = @(Get-Process -Name 'flutter_app' -ErrorAction SilentlyContinue)
|
|
if ($BuildOnly) {
|
|
$runningApps = @($runningApps | Where-Object { $_.Path -and $_.Path.StartsWith($workRootPath + '\', [StringComparison]::OrdinalIgnoreCase) })
|
|
}
|
|
if ($runningApps.Count -gt 0) {
|
|
$processIds = ($runningApps | ForEach-Object Id) -join ', '
|
|
throw "Close the running Mithqal AI Debug window(s) first (PID: $processIds), then run this script again."
|
|
}
|
|
}
|
|
|
|
# Keep native build outputs and package caches in the local copy for fast,
|
|
# incremental rebuilds. They are deliberately excluded from mirroring.
|
|
$excludedDirectories = @(
|
|
(Join-Path $sourceApp 'build'),
|
|
(Join-Path $sourceApp '.dart_tool'),
|
|
(Join-Path $sourceApp 'windows\flutter\ephemeral'),
|
|
(Join-Path $sourceApp 'linux\flutter\ephemeral'),
|
|
(Join-Path $sourceApp 'macos\Flutter\ephemeral')
|
|
)
|
|
$excludedFiles = @(
|
|
'.flutter-plugins',
|
|
'.flutter-plugins-dependencies',
|
|
'.packages',
|
|
'.env',
|
|
'.env.*'
|
|
)
|
|
& robocopy $sourceApp $destinationAppPath /MIR /XJ /R:1 /W:1 /NFL /NDL /NJH /NJS /NP /XD $excludedDirectories /XF $excludedFiles
|
|
if ($LASTEXITCODE -ge 8) {
|
|
throw "Could not sync Flutter sources to the local build directory (robocopy $LASTEXITCODE)."
|
|
}
|
|
Write-Host "Local Windows build workspace: $destinationAppPath"
|
|
|
|
if ($SyncOnly) {
|
|
exit 0
|
|
}
|
|
|
|
Push-Location $destinationAppPath
|
|
try {
|
|
& flutter pub get --offline
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw 'Flutter dependencies are not available in the local pub cache. Run flutter pub get once with network access, then retry.'
|
|
}
|
|
|
|
if ($BuildOnly) {
|
|
& flutter build windows --debug --no-pub
|
|
} else {
|
|
& flutter run -d windows --debug --no-pub
|
|
}
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "Flutter exited with code $LASTEXITCODE."
|
|
}
|
|
} finally {
|
|
Pop-Location
|
|
}
|