mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-28 11:01:30 -04:00
feat(workspace filtering): add support for filtering packages since last commit under git worktree (#10542)
support managing repo in git worktree for filtering for packages changed since last commit
This commit is contained in:
5
.changeset/every-impalas-change.md
Normal file
5
.changeset/every-impalas-change.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/filter-workspace-packages": minor
|
||||
---
|
||||
|
||||
Drop `directory` as required filetype for `findUp` to allow git-based filtering to work inside git worktrees, which store `.git` as a file rather than directory.
|
||||
@@ -287,6 +287,7 @@
|
||||
"testcase",
|
||||
"TLSV",
|
||||
"todomvc",
|
||||
"toplevel",
|
||||
"tsgo",
|
||||
"tsparticles",
|
||||
"typecheck",
|
||||
@@ -307,6 +308,8 @@
|
||||
"webcontainer",
|
||||
"winst",
|
||||
"workleap",
|
||||
"worktree",
|
||||
"worktrees",
|
||||
"wrappy",
|
||||
"xmarw",
|
||||
"yazl",
|
||||
|
||||
@@ -18,7 +18,13 @@ export async function getChangedPackages (
|
||||
commit: string,
|
||||
opts: { workspaceDir: string, testPattern?: string[], changedFilesIgnorePattern?: string[] }
|
||||
): Promise<[ProjectRootDir[], ProjectRootDir[]]> {
|
||||
const repoRoot = path.resolve(await findUp('.git', { cwd: opts.workspaceDir, type: 'directory' }) ?? opts.workspaceDir, '..')
|
||||
|
||||
// .git is a directory in regular repos, but a file in worktrees
|
||||
const gitPath = await findUp('.git', { cwd: opts.workspaceDir, type: 'directory' }) ??
|
||||
await findUp('.git', { cwd: opts.workspaceDir, type: 'file' })
|
||||
|
||||
const repoRoot = path.resolve(gitPath ?? opts.workspaceDir, '..')
|
||||
|
||||
const changedDirs = (await getChangedDirsSinceCommit(commit, opts.workspaceDir, opts.testPattern ?? [], opts.changedFilesIgnorePattern ?? []))
|
||||
.map(changedDir => ({ ...changedDir, dir: path.join(repoRoot, changedDir.dir) }))
|
||||
const pkgChangeTypes = new Map<ProjectRootDir, ChangeType | undefined>()
|
||||
|
||||
@@ -474,6 +474,79 @@ test('select changed packages', async () => {
|
||||
}
|
||||
})
|
||||
|
||||
test('select changed packages when operating under a git worktree', async () => {
|
||||
if (isCI && isWindows()) {
|
||||
return
|
||||
}
|
||||
|
||||
const mainRepoDir = temporaryDirectory()
|
||||
await execa('git', ['init', '--initial-branch=main'], { cwd: mainRepoDir })
|
||||
await execa('git', ['config', 'user.email', 'x@y.z'], { cwd: mainRepoDir })
|
||||
await execa('git', ['config', 'user.name', 'xyz'], { cwd: mainRepoDir })
|
||||
await execa('git', ['commit', '--allow-empty', '--allow-empty-message', '-m', '', '--no-gpg-sign'], { cwd: mainRepoDir })
|
||||
|
||||
const mainPkgADir = path.join(mainRepoDir, 'package-a')
|
||||
const mainPkgBDir = path.join(mainRepoDir, 'package-b')
|
||||
const mainPkgCDir = path.join(mainRepoDir, 'package-c')
|
||||
await mkdir(mainPkgADir)
|
||||
await mkdir(mainPkgBDir)
|
||||
await mkdir(mainPkgCDir)
|
||||
await touch(path.join(mainPkgADir, 'file.js'))
|
||||
await touch(path.join(mainPkgBDir, 'file.js'))
|
||||
await touch(path.join(mainPkgCDir, 'file.js'))
|
||||
await execa('git', ['add', '.'], { cwd: mainRepoDir })
|
||||
await execa('git', ['commit', '--allow-empty-message', '-m', '', '--no-gpg-sign'], { cwd: mainRepoDir })
|
||||
|
||||
const worktreeParent = temporaryDirectory()
|
||||
const worktreeDir = path.join(worktreeParent, 'worktree')
|
||||
await execa('git', ['worktree', 'add', '-b', 'worktree-branch', worktreeDir, 'main'], { cwd: mainRepoDir })
|
||||
|
||||
const worktreePkgADir = path.join(worktreeDir, 'package-a') as ProjectRootDir
|
||||
const worktreePkgBDir = path.join(worktreeDir, 'package-b') as ProjectRootDir
|
||||
const worktreePkgCDir = path.join(worktreeDir, 'package-c') as ProjectRootDir
|
||||
|
||||
await touch(path.join(worktreePkgADir, 'new-file.js'))
|
||||
await execa('git', ['add', '.'], { cwd: worktreeDir })
|
||||
await execa('git', ['commit', '--allow-empty-message', '-m', '', '--no-gpg-sign'], { cwd: worktreeDir })
|
||||
|
||||
const pkgsGraph: PackageGraph<Package> = {
|
||||
[worktreeDir as ProjectRootDir]: {
|
||||
dependencies: [],
|
||||
package: {
|
||||
rootDir: worktreeDir as ProjectRootDir,
|
||||
manifest: { name: 'root', version: '0.0.0' },
|
||||
},
|
||||
},
|
||||
[worktreePkgADir]: {
|
||||
dependencies: [],
|
||||
package: {
|
||||
rootDir: worktreePkgADir,
|
||||
manifest: { name: 'package-a', version: '0.0.0' },
|
||||
},
|
||||
},
|
||||
[worktreePkgBDir]: {
|
||||
dependencies: [],
|
||||
package: {
|
||||
rootDir: worktreePkgBDir,
|
||||
manifest: { name: 'package-b', version: '0.0.0' },
|
||||
},
|
||||
},
|
||||
[worktreePkgCDir]: {
|
||||
dependencies: [],
|
||||
package: {
|
||||
rootDir: worktreePkgCDir,
|
||||
manifest: { name: 'package-c', version: '0.0.0' },
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const { selectedProjectsGraph } = await filterWorkspacePackages(pkgsGraph, [{
|
||||
diff: 'HEAD~1',
|
||||
}], { workspaceDir: worktreeDir })
|
||||
|
||||
expect(Object.keys(selectedProjectsGraph)).toStrictEqual([worktreePkgADir])
|
||||
})
|
||||
|
||||
test('selection should fail when diffing to a branch that does not exist', async () => {
|
||||
let err!: PnpmError
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user