$ErrorActionPreference = 'Stop' $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path $Root = Split-Path -Parent $ScriptDir $SingBox = Join-Path $Root 'works/sing-box' $PatchDir = Join-Path $Root 'works/patch' $Core = Join-Path $Root 'works/core' if (-not (Test-Path (Join-Path $SingBox '.git'))) { Write-Error 'works/sing-box not found. Run update first.' exit 1 } if (-not (Test-Path $Core)) { Write-Error 'works/core not found. Run generate first.' exit 1 } $IgnoreFile = Join-Path $Root 'works/ignore' $IgnorePatterns = @() if (Test-Path $IgnoreFile) { $IgnorePatterns = Get-Content $IgnoreFile | Where-Object { $_ -ne '' -and $_ -notmatch '^\s*#' } } function Test-Ignored { param([string]$RelPath) foreach ($pattern in $IgnorePatterns) { if ($pattern -match '/') { if ($RelPath -like $pattern) { return $true } } else { if ((Split-Path -Leaf $RelPath) -like $pattern) { return $true } } } return $false } Write-Host 'Clearing existing patches...' if (Test-Path $PatchDir) { Remove-Item -Recurse -Force $PatchDir } New-Item -ItemType Directory -Path $PatchDir -Force | Out-Null Write-Host 'Generating patches for modified/new files...' Get-ChildItem -Path $Core -Recurse -File | Where-Object { $_.FullName -notmatch [regex]::Escape((Join-Path $Core '.git')) } | Sort-Object FullName | ForEach-Object { $rel = $_.FullName.Substring($Core.Length + 1) -replace '\\', '/' if (Test-Ignored $rel) { return } $srcFile = Join-Path $SingBox $rel $patchFile = Join-Path $PatchDir "$rel.patch" $patchFileDir = Split-Path -Parent $patchFile if (-not (Test-Path $patchFileDir)) { New-Item -ItemType Directory -Path $patchFileDir -Force | Out-Null } if (Test-Path $srcFile) { $srcHash = (Get-FileHash $srcFile -Algorithm MD5).Hash $dstHash = (Get-FileHash $_.FullName -Algorithm MD5).Hash if ($srcHash -ne $dstHash) { diff -u $srcFile $_.FullName | Out-File -FilePath $patchFile -Encoding utf8 Write-Host " Modified: $rel" } } else { diff -u /dev/null $_.FullName | Out-File -FilePath $patchFile -Encoding utf8 Write-Host " New: $rel" } } Write-Host 'Generating patches for deleted files...' Get-ChildItem -Path $SingBox -Recurse -File | Where-Object { $_.FullName -notmatch [regex]::Escape((Join-Path $SingBox '.git')) } | Sort-Object FullName | ForEach-Object { $rel = $_.FullName.Substring($SingBox.Length + 1) -replace '\\', '/' if (Test-Ignored $rel) { return } $dstFile = Join-Path $Core $rel $patchFile = Join-Path $PatchDir "$rel.patch" if (-not (Test-Path $dstFile)) { $patchFileDir = Split-Path -Parent $patchFile if (-not (Test-Path $patchFileDir)) { New-Item -ItemType Directory -Path $patchFileDir -Force | Out-Null } diff -u $_.FullName /dev/null | Out-File -FilePath $patchFile -Encoding utf8 Write-Host " Deleted: $rel" } } Write-Host 'Done.'