🐛 fix(vscode): 代码阅读工作区索引跳过嵌套的 checkout 和忽略文件忽略的,任务名不再查到两处
This commit is contained in:
1 parent
de355661f0
commit
113b02657c
7 files changed
+202
-12
No files matched your search
@@ -0,0 +1,84 @@
|
||||
import type { FolderReader } from './workspaceScope'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { folderScope } from './workspaceScope'
|
||||
|
||||
/** 内存里的工作区文件夹:路径 → 内容(目录不用列,列出来的文件所在的目录都算有);记下读过哪些。 */
|
||||
function memoryFolder(files: Record<string, string>): FolderReader & { asked: string[] } {
|
||||
const asked: string[] = []
|
||||
const directories = new Set(Object.keys(files).flatMap((file) => {
|
||||
const parts = file.split('/')
|
||||
return parts.slice(0, -1).map((_, i) => parts.slice(0, i + 1).join('/'))
|
||||
}))
|
||||
return {
|
||||
asked,
|
||||
exists: async (path) => {
|
||||
asked.push(path)
|
||||
return path in files || directories.has(path)
|
||||
},
|
||||
read: async (path) => {
|
||||
asked.push(path)
|
||||
return files[path]
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
async function kept(files: Record<string, string>, paths: string[], useIgnoreFiles = true): Promise<string[]> {
|
||||
const scope = folderScope(memoryFolder(files), useIgnoreFiles)
|
||||
const skipped = await Promise.all(paths.map(path => scope.skips(path)))
|
||||
return paths.filter((_, i) => !skipped[i])
|
||||
}
|
||||
|
||||
const TASKS = 'backend/src/luffy_agent/commerce/tasks.py'
|
||||
const WORKTREE = '.claude/worktrees/agent-aa35211c29ea9e068'
|
||||
|
||||
describe('工作区扫描还要跳过的文件', () => {
|
||||
it('嵌套的 git worktree(子目录里的 .git 是个文件)整个跳过,工作区自己的 .git 不算', async () => {
|
||||
const files = {
|
||||
'.git/HEAD': 'ref: refs/heads/main',
|
||||
[TASKS]: '',
|
||||
[`${WORKTREE}/.git`]: 'gitdir: /repo/.git/worktrees/agent-aa35211c29ea9e068',
|
||||
[`${WORKTREE}/${TASKS}`]: '',
|
||||
}
|
||||
expect(await kept(files, [TASKS, `${WORKTREE}/${TASKS}`], false)).toEqual([TASKS])
|
||||
})
|
||||
|
||||
it('嵌套的仓库(子目录里的 .git 是个目录)也跳过', async () => {
|
||||
expect(await kept({ 'vendor/lib/.git/HEAD': '', 'vendor/lib/a.py': '', 'vendor/b.py': '' }, ['vendor/lib/a.py', 'vendor/b.py'])).toEqual(['vendor/b.py'])
|
||||
})
|
||||
|
||||
it('.gitignore 忽略的目录跳过;每层的规则相对那一层,取反照 gitignore 写法;.ignore 也读', async () => {
|
||||
const files = {
|
||||
'.gitignore': '.claude/worktrees/\nbuild/\n*.log\n!keep.log\n',
|
||||
'pkg/.gitignore': 'generated/\n',
|
||||
'tools/.ignore': 'scratch.py\n',
|
||||
[`${WORKTREE}/${TASKS}`]: '',
|
||||
}
|
||||
const paths = [
|
||||
TASKS,
|
||||
`${WORKTREE}/${TASKS}`,
|
||||
'build/out/a.py',
|
||||
'src/build.py',
|
||||
'pkg/generated/a.py',
|
||||
'generated/a.py',
|
||||
'logs/x.log',
|
||||
'logs/keep.log',
|
||||
'tools/scratch.py',
|
||||
'tools/run.py',
|
||||
]
|
||||
expect(await kept(files, paths)).toEqual([TASKS, 'src/build.py', 'generated/a.py', 'logs/keep.log', 'tools/run.py'])
|
||||
})
|
||||
|
||||
it('search.useIgnoreFiles 关着时不读忽略文件,嵌套的 checkout 照样跳过', async () => {
|
||||
const files = { '.gitignore': 'build/\n', 'sub/.git': 'gitdir: x', 'sub/a.py': '' }
|
||||
expect(await kept(files, ['build/a.py', 'sub/a.py'], false)).toEqual(['build/a.py'])
|
||||
})
|
||||
|
||||
it('同一个目录只查一次', async () => {
|
||||
const folder = memoryFolder({ 'a/b/c.py': '', 'a/b/d.py': '' })
|
||||
const scope = folderScope(folder, true)
|
||||
await scope.skips('a/b/c.py')
|
||||
await scope.skips('a/b/d.py')
|
||||
expect(folder.asked.filter(path => path === 'a/b/.git')).toEqual(['a/b/.git'])
|
||||
expect(folder.asked.filter(path => path === 'a/.gitignore')).toEqual(['a/.gitignore'])
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user