mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-23 16:36:23 +00:00
simple-git's custom-binary validation rejects paths containing spaces, so the default Windows Git install (C:\Program Files\Git\cmd\git.exe) made every Review pane git call throw and the pane silently showed 'No diffs'. The binary is resolved inside the Electron main process from known install locations or PATH — never renderer/user input — so for spaced paths we opt into simple-git's supported unsafe.allowUnsafeCustomBinary escape hatch rather than falling back to PATH (often absent in GUI-launched apps). Simplified from PR #64713 by @unsupportedpastels; supersedes the 8.3 short-path approaches in #55337/#60156. Fixes #54888
89 lines
2.7 KiB
TypeScript
89 lines
2.7 KiB
TypeScript
import assert from 'node:assert/strict'
|
|
import { execFileSync } from 'node:child_process'
|
|
import fs from 'node:fs'
|
|
import os from 'node:os'
|
|
import path from 'node:path'
|
|
|
|
import { afterEach, test } from 'vitest'
|
|
|
|
import { gitFor, repoStatus, resolveRenamePath } from './git-review-ops'
|
|
|
|
const tempDirs: string[] = []
|
|
|
|
afterEach(() => {
|
|
for (const dir of tempDirs.splice(0)) {
|
|
fs.rmSync(dir, { force: true, recursive: true })
|
|
}
|
|
})
|
|
|
|
function makeRepo() {
|
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'hermes-desktop-git-status-'))
|
|
|
|
tempDirs.push(dir)
|
|
execFileSync('git', ['init', '-q'], { cwd: dir })
|
|
execFileSync('git', ['config', 'user.email', 'hermes-test@example.com'], { cwd: dir })
|
|
execFileSync('git', ['config', 'user.name', 'Hermes Test'], { cwd: dir })
|
|
fs.writeFileSync(path.join(dir, 'tracked.txt'), 'tracked\n')
|
|
execFileSync('git', ['add', 'tracked.txt'], { cwd: dir })
|
|
execFileSync('git', ['commit', '-qm', 'initial'], { cwd: dir })
|
|
|
|
return dir
|
|
}
|
|
|
|
test('resolveRenamePath: plain path is unchanged', () => {
|
|
assert.equal(resolveRenamePath('src/a.ts'), 'src/a.ts')
|
|
})
|
|
|
|
test('gitFor accepts an internally resolved git binary path containing spaces', () => {
|
|
assert.doesNotThrow(() => gitFor(process.cwd(), 'C:\\Program Files\\Git\\cmd\\git.exe'))
|
|
})
|
|
|
|
test('gitFor runs git through a spaced binary path', async () => {
|
|
if (process.platform !== 'win32') {
|
|
return
|
|
}
|
|
|
|
const gitBin = path.join(process.env.ProgramFiles || String.raw`C:\Program Files`, 'Git', 'cmd', 'git.exe')
|
|
|
|
if (!fs.existsSync(gitBin)) {
|
|
return
|
|
}
|
|
|
|
const repo = makeRepo()
|
|
|
|
fs.writeFileSync(path.join(repo, 'changed.txt'), 'review me\n')
|
|
|
|
const status = await gitFor(repo, gitBin).status()
|
|
|
|
assert.equal(status.not_added.includes('changed.txt'), true)
|
|
})
|
|
|
|
test('resolveRenamePath: simple rename resolves to the new path', () => {
|
|
assert.equal(resolveRenamePath('old.ts => new.ts'), 'new.ts')
|
|
})
|
|
|
|
test('resolveRenamePath: brace rename resolves to the new path', () => {
|
|
assert.equal(resolveRenamePath('src/{old => new}/file.ts'), 'src/new/file.ts')
|
|
})
|
|
|
|
test('resolveRenamePath: brace rename collapsing a segment', () => {
|
|
assert.equal(resolveRenamePath('src/{lib => }/file.ts'), 'src/file.ts')
|
|
})
|
|
|
|
test('repoStatus reports an untracked directory without recursively listing its contents', async () => {
|
|
const dir = makeRepo()
|
|
const nested = path.join(dir, 'generated', 'deep')
|
|
|
|
fs.mkdirSync(nested, { recursive: true })
|
|
fs.writeFileSync(path.join(nested, 'large-output.txt'), 'generated\n')
|
|
|
|
const status = await repoStatus(dir, 'git')
|
|
|
|
assert.ok(status)
|
|
assert.equal(status.untracked, 1)
|
|
assert.equal(status.changed, 1)
|
|
assert.deepEqual(
|
|
status.files.map(file => file.path),
|
|
['generated/']
|
|
)
|
|
})
|