大改版,可以针对不同项目引擎进行初始化
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# Changelog sync guard: compare Godot source/config mtimes against this session and changelog.
|
||||
# Changelog sync guard: require Git changes newer than this session and changelog.
|
||||
$utf8 = New-Object System.Text.UTF8Encoding($false)
|
||||
[Console]::InputEncoding = $utf8
|
||||
[Console]::OutputEncoding = $utf8
|
||||
@@ -20,8 +20,15 @@ $repoRoot = Split-Path -Parent $cursorDir
|
||||
$changelog = Join-Path $cursorDir 'changelog\changelog-headlines.md'
|
||||
$ackFile = Join-Path $cursorDir 'changelog\.changelog-ack'
|
||||
$sessionMarker = Join-Path $cursorDir 'changelog\.session-start'
|
||||
$scanConfigPath = Join-Path $PSScriptRoot 'changelog-scan.json'
|
||||
|
||||
if (-not (Test-Path -LiteralPath $changelog -PathType Leaf)) {
|
||||
if (-not (Test-Path -LiteralPath $changelog -PathType Leaf) -or
|
||||
-not (Test-Path -LiteralPath $scanConfigPath -PathType Leaf)) {
|
||||
Write-EmptyHookResult
|
||||
exit 0
|
||||
}
|
||||
|
||||
if (-not (Test-Path -LiteralPath $sessionMarker -PathType Leaf)) {
|
||||
Write-EmptyHookResult
|
||||
exit 0
|
||||
}
|
||||
@@ -33,51 +40,50 @@ if ((Test-Path -LiteralPath $ackFile -PathType Leaf) -and
|
||||
exit 0
|
||||
}
|
||||
|
||||
$comparisonMtime = $changelogMtime
|
||||
if ((Test-Path -LiteralPath $sessionMarker -PathType Leaf)) {
|
||||
$sessionMtime = (Get-Item -LiteralPath $sessionMarker).LastWriteTimeUtc
|
||||
if ($sessionMtime -gt $comparisonMtime) {
|
||||
$comparisonMtime = $sessionMtime
|
||||
}
|
||||
$gitStatus = @(& git -C $repoRoot status --porcelain=v1 --untracked-files=all -- 2>$null)
|
||||
if ($LASTEXITCODE -ne 0 -or $gitStatus.Count -eq 0) {
|
||||
Write-EmptyHookResult
|
||||
exit 0
|
||||
}
|
||||
|
||||
$includedNames = @('project.godot')
|
||||
$includedExtensions = @(
|
||||
'.gd',
|
||||
'.tscn',
|
||||
'.tres',
|
||||
'.res',
|
||||
'.gdshader',
|
||||
'.cfg',
|
||||
'.json',
|
||||
'.cs',
|
||||
'.csproj',
|
||||
'.py',
|
||||
'.ps1',
|
||||
'.sh'
|
||||
)
|
||||
$excludedDirectoryNames = @(
|
||||
'.git',
|
||||
'.cursor',
|
||||
'.godot',
|
||||
'node_modules',
|
||||
'__pycache__',
|
||||
'venv',
|
||||
'.venv',
|
||||
'dist',
|
||||
'build',
|
||||
'out',
|
||||
'bin',
|
||||
'obj',
|
||||
'export',
|
||||
'exports',
|
||||
'coverage',
|
||||
'tmp',
|
||||
'temp'
|
||||
)
|
||||
try {
|
||||
$scanConfig = Get-Content -LiteralPath $scanConfigPath -Raw -Encoding UTF8 |
|
||||
ConvertFrom-Json
|
||||
if ($scanConfig.schema_version -ne 1) {
|
||||
throw "Unsupported changelog scan schema."
|
||||
}
|
||||
$includedNames = @(
|
||||
$scanConfig.included_names |
|
||||
Where-Object { $_ -is [string] -and -not [string]::IsNullOrWhiteSpace($_) }
|
||||
)
|
||||
$includedExtensions = @(
|
||||
$scanConfig.included_extensions |
|
||||
Where-Object { $_ -is [string] -and -not [string]::IsNullOrWhiteSpace($_) }
|
||||
)
|
||||
$excludedDirectoryNames = @(
|
||||
$scanConfig.excluded_directories |
|
||||
Where-Object { $_ -is [string] -and -not [string]::IsNullOrWhiteSpace($_) }
|
||||
)
|
||||
} catch {
|
||||
Write-EmptyHookResult
|
||||
exit 0
|
||||
}
|
||||
|
||||
if ($includedNames.Count -eq 0 -and $includedExtensions.Count -eq 0) {
|
||||
Write-EmptyHookResult
|
||||
exit 0
|
||||
}
|
||||
|
||||
$comparisonMtime = $changelogMtime
|
||||
$sessionMtime = (Get-Item -LiteralPath $sessionMarker).LastWriteTimeUtc
|
||||
if ($sessionMtime -gt $comparisonMtime) {
|
||||
$comparisonMtime = $sessionMtime
|
||||
}
|
||||
|
||||
$newerFile = $null
|
||||
$newerRelativePath = $null
|
||||
$rootItem = Get-Item -LiteralPath $repoRoot
|
||||
$rootPrefix = $repoRoot.TrimEnd('\', '/') + [System.IO.Path]::DirectorySeparatorChar
|
||||
$directories = New-Object 'System.Collections.Generic.Stack[System.IO.DirectoryInfo]'
|
||||
$directories.Push($rootItem)
|
||||
|
||||
@@ -101,20 +107,29 @@ while ($directories.Count -gt 0 -and -not $newerFile) {
|
||||
$isIncluded = ($includedNames -contains $entry.Name) -or
|
||||
($includedExtensions -contains $entry.Extension)
|
||||
if ($isIncluded -and $entry.LastWriteTimeUtc -gt $comparisonMtime) {
|
||||
$newerFile = $entry
|
||||
break
|
||||
$relativePath = if ($entry.FullName.StartsWith(
|
||||
$rootPrefix,
|
||||
[System.StringComparison]::OrdinalIgnoreCase
|
||||
)) {
|
||||
$entry.FullName.Substring($rootPrefix.Length)
|
||||
} else {
|
||||
$entry.Name
|
||||
}
|
||||
$gitPath = $relativePath -replace '\\', '/'
|
||||
$pathStatus = @(
|
||||
& git -C $repoRoot status --porcelain=v1 --untracked-files=all -- $gitPath 2>$null
|
||||
)
|
||||
if ($LASTEXITCODE -eq 0 -and $pathStatus.Count -gt 0) {
|
||||
$newerFile = $entry
|
||||
$newerRelativePath = $relativePath
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($newerFile) {
|
||||
$rootPrefix = $repoRoot.TrimEnd('\', '/') + [System.IO.Path]::DirectorySeparatorChar
|
||||
$relativePath = if ($newerFile.FullName.StartsWith($rootPrefix, [System.StringComparison]::OrdinalIgnoreCase)) {
|
||||
$newerFile.FullName.Substring($rootPrefix.Length)
|
||||
} else {
|
||||
$newerFile.Name
|
||||
}
|
||||
$message = "[Hook] Godot source/config is newer than the changelog (e.g. $relativePath). Run dev-changelog Skill operation A now: add a fragment under .cursor/changelog/entries/ and rebuild the changelog views."
|
||||
$message = "[Hook] Project source/config has an uncommitted change newer than this session and the changelog (e.g. $newerRelativePath). Run dev-changelog Skill operation A now: add a fragment under .cursor/changelog/entries/ and rebuild the changelog views."
|
||||
$result = [ordered]@{ followup_message = $message }
|
||||
[Console]::Out.WriteLine(($result | ConvertTo-Json -Compress -Depth 3))
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user