feat(i18n): compose pairing records during merges

This commit is contained in:
Tianyi Cui
2026-08-08 21:11:19 +08:00
parent 05cbc185f0
commit 542c029c80
13 changed files with 1049 additions and 77 deletions

View File

@@ -27,6 +27,13 @@ const INSTALL_LOCK_INITIALIZATION_TIMEOUT_MS = 1_000
const INSTALL_LOCK_POLL_MS = 50
const ALLOW_HOOKS_PATH_OVERRIDE = 'DSH_LEFTHOOK_ALLOW_HOOKS_PATH_OVERRIDE'
const REPOSITORY_EXTENSION_PATTERN = '^extensions\\.'
const PAIRING_MERGE_DRIVER_CONFIG = [
['merge.dsh-translation-pairing.name', 'DeepSeek Harness bilingual pairing records'],
[
'merge.dsh-translation-pairing.driver',
'node --import tsx/esm scripts/merge-translation-pairing.ts %O %A %B %P',
],
]
function errorCode(error) {
return typeof error === 'object' && error !== null && 'code' in error
@@ -595,6 +602,82 @@ function refuseScopedHooksPath(entry) {
)
}
function installPairingMergeDriver(root, worktreeConfigPath) {
const added = []
try {
for (const [key, expected] of PAIRING_MERGE_DRIVER_CONFIG) {
const entries = includedFileConfigEntries(root, worktreeConfigPath, key)
const includedEntry = entries.find(entry => !originIsFile(entry.origin, root, worktreeConfigPath))
if (includedEntry !== undefined) {
throw new Error(
`refusing pairing merge-driver config from an included worktree file (${configSource(includedEntry)})`,
)
}
const existing = assertSingle(entries.map(entry => entry.value), `worktree ${key}`)
const effectiveBefore = effectiveConfigEntry(root, key)
if (effectiveBefore?.scope === 'command') {
throw new Error(
`refusing command-scoped ${key} (${configSource(effectiveBefore)}); `
+ 'transient configuration cannot be replaced by the worktree installer',
)
}
if (existing === undefined && effectiveBefore !== undefined && effectiveBefore.value !== expected) {
throw new Error(
`refusing to mask inherited ${key} (${configSource(effectiveBefore)}); `
+ 'remove or integrate the custom pairing merge driver explicitly',
)
}
if (existing !== undefined && existing !== expected) {
throw new Error(
`refusing to replace worktree ${key} value ${JSON.stringify(existing)}; `
+ 'remove or integrate the custom pairing merge driver explicitly',
)
}
if (existing === undefined) {
git(['config', '--worktree', key, expected], root)
added.push(key)
}
const installed = includedFileConfigEntries(root, worktreeConfigPath, key)
if (
installed.length !== 1
|| installed[0]?.value !== expected
|| !originIsFile(installed[0].origin, root, worktreeConfigPath)
) {
throw new Error(`new worktree-local ${key} did not become the direct worktree value`)
}
const effectiveAfter = effectiveConfigEntry(root, key)
if (
effectiveAfter === undefined
|| effectiveAfter.scope !== 'worktree'
|| effectiveAfter.value !== expected
|| !originIsFile(effectiveAfter.origin, root, worktreeConfigPath)
) {
throw new Error(`new worktree-local ${key} did not become the effective direct worktree value`)
}
}
} catch (error) {
const rollbackErrors = []
for (const key of added.reverse()) {
try {
git(['config', '--worktree', '--unset-all', key], root)
} catch (rollbackError) {
rollbackErrors.push(rollbackError)
}
}
if (rollbackErrors.length > 0) {
throw new AggregateError(
[error, ...rollbackErrors],
`Pairing merge-driver configuration failed: ${String(error)}; `
+ `rollback also failed: ${rollbackErrors.map(String).join('; ')}`,
)
}
throw error
}
return () => {
for (const key of added.reverse()) git(['config', '--worktree', '--unset-all', key], root)
}
}
async function main() {
if (process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true') return
if (typeof lefthookPackage.bin?.lefthook !== 'string') return
@@ -682,7 +765,9 @@ async function main() {
applyWorktreeConfigMigration(root, commonConfigPath, migration)
let pathChanged = false
let rollbackPairingMergeDriver = () => {}
try {
rollbackPairingMergeDriver = installPairingMergeDriver(root, worktreeConfigPath)
git(['config', '--worktree', 'core.hooksPath', hooksPath], root)
pathChanged = worktreePath !== hooksPath
const installedEntry = effectiveConfigEntry(root, 'core.hooksPath')
@@ -697,6 +782,7 @@ async function main() {
runLefthook(root, lefthook)
updateOwnershipMarker(ownedHooksDirectory.markerPath, hooksPath)
} catch (error) {
const rollbackErrors = []
if (pathChanged) {
try {
if (worktreePath === undefined) {
@@ -705,13 +791,21 @@ async function main() {
git(['config', '--worktree', 'core.hooksPath', worktreePath], root)
}
} catch (rollbackError) {
throw new AggregateError(
[error, rollbackError],
`Lefthook installation failed: ${String(error)}; `
+ `worktree hook rollback also failed: ${String(rollbackError)}`,
)
rollbackErrors.push(rollbackError)
}
}
try {
rollbackPairingMergeDriver()
} catch (rollbackError) {
rollbackErrors.push(rollbackError)
}
if (rollbackErrors.length > 0) {
throw new AggregateError(
[error, ...rollbackErrors],
`Lefthook installation failed: ${String(error)}; `
+ `worktree integration rollback also failed: ${rollbackErrors.map(String).join('; ')}`,
)
}
throw error
}
} catch (error) {