fix: patch-commit should auto apply patches in workspaces (#6120)

close #6048
This commit is contained in:
await-ovo
2023-02-23 04:56:35 +08:00
committed by GitHub
parent 98d15f03d3
commit 6f56cc16e3
7 changed files with 144 additions and 15 deletions

View File

@@ -0,0 +1,6 @@
---
"@pnpm/plugin-commands-patching": patch
"pnpm": patch
---
`patch-commit` should auto apply patches in workspaces [#6048](https://github.com/pnpm/pnpm/issues/6048)

View File

@@ -34,9 +34,11 @@
"homepage": "https://github.com/pnpm/pnpm/blob/main/patching/plugin-commands-patching#readme",
"devDependencies": {
"@pnpm/plugin-commands-patching": "workspace:*",
"@pnpm/filter-workspace-packages": "workspace:*",
"@pnpm/prepare": "workspace:*",
"@pnpm/registry-mock": "3.4.0",
"@types/ramda": "0.28.20"
"@types/ramda": "0.28.20",
"write-yaml-file": "^4.2.0"
},
"dependencies": {
"@pnpm/cli-utils": "workspace:*",

View File

@@ -1,7 +1,7 @@
import fs from 'fs'
import path from 'path'
import { docsUrl } from '@pnpm/cli-utils'
import { types as allTypes } from '@pnpm/config'
import { Config, types as allTypes } from '@pnpm/config'
import { install } from '@pnpm/plugin-commands-installation'
import { readPackageJsonFromDir } from '@pnpm/read-package-json'
import { tryReadProjectManifest } from '@pnpm/read-project-manifest'
@@ -29,7 +29,7 @@ export function help () {
})
}
export async function handler (opts: install.InstallCommandOptions, params: string[]) {
export async function handler (opts: install.InstallCommandOptions & Pick<Config, 'rootProjectManifest'>, params: string[]) {
const userDir = params[0]
const lockfileDir = opts.lockfileDir ?? opts.dir ?? process.cwd()
const patchesDir = path.join(lockfileDir, 'patches')
@@ -41,19 +41,28 @@ export async function handler (opts: install.InstallCommandOptions, params: stri
const patchContent = await diffFolders(srcDir, userDir)
const patchFileName = pkgNameAndVersion.replace('/', '__')
await fs.promises.writeFile(path.join(patchesDir, `${patchFileName}.patch`), patchContent, 'utf8')
let { manifest, writeProjectManifest } = await tryReadProjectManifest(lockfileDir)
if (!manifest) {
manifest = {}
}
if (!manifest.pnpm) {
manifest.pnpm = {
const { writeProjectManifest, manifest } = await tryReadProjectManifest(lockfileDir)
const rootProjectManifest = opts.rootProjectManifest ?? manifest ?? {}
if (!rootProjectManifest.pnpm) {
rootProjectManifest.pnpm = {
patchedDependencies: {},
}
} else if (!manifest.pnpm.patchedDependencies) {
manifest.pnpm.patchedDependencies = {}
} else if (!rootProjectManifest.pnpm.patchedDependencies) {
rootProjectManifest.pnpm.patchedDependencies = {}
}
manifest.pnpm.patchedDependencies![pkgNameAndVersion] = `patches/${patchFileName}.patch`
await writeProjectManifest(manifest)
rootProjectManifest.pnpm.patchedDependencies![pkgNameAndVersion] = `patches/${patchFileName}.patch`
await writeProjectManifest(rootProjectManifest)
if (opts?.selectedProjectsGraph?.[lockfileDir]) {
opts.selectedProjectsGraph[lockfileDir].package.manifest = rootProjectManifest
}
if (opts?.allProjectsGraph?.[lockfileDir].package.manifest) {
opts.allProjectsGraph[lockfileDir].package.manifest = rootProjectManifest
}
return install.handler(opts)
}

View File

@@ -1,7 +1,10 @@
import fs from 'fs'
import os from 'os'
import path from 'path'
import { prepare } from '@pnpm/prepare'
import { prepare, preparePackages } from '@pnpm/prepare'
import { install } from '@pnpm/plugin-commands-installation'
import { readProjects } from '@pnpm/filter-workspace-packages'
import writeYamlFile from 'write-yaml-file'
import tempy from 'tempy'
import { patch, patchCommit } from '@pnpm/plugin-commands-patching'
import { readProjectManifest } from '@pnpm/read-project-manifest'
@@ -263,6 +266,106 @@ describe('patching should work when there is a no EOL in the patched file', () =
})
})
describe('patch and commit in workspaces', () => {
let defaultPatchOption: patch.PatchCommandOptions
let cacheDir: string
let storeDir: string
beforeEach(() => {
preparePackages([
{
location: '.',
package: {
name: 'patch-commit-workspaces',
},
},
{
name: 'project-1',
version: '1.0.0',
dependencies: {
'is-positive': '1.0.0',
},
},
{
name: 'project-2',
version: '1.0.0',
dependencies: {
'is-positive': '1.0.0',
'project-1': '1',
},
},
])
cacheDir = path.resolve('cache')
storeDir = path.resolve('store')
defaultPatchOption = {
cacheDir,
dir: process.cwd(),
pnpmHomeDir: '',
rawConfig: {
registry: `http://localhost:${REGISTRY_MOCK_PORT}/`,
},
registries: { default: `http://localhost:${REGISTRY_MOCK_PORT}/` },
storeDir,
userConfig: {},
}
})
test('patch commit should work in workspaces', async () => {
await writeYamlFile('pnpm-workspace.yaml', { packages: ['project-1', 'project-2'] })
const { allProjects, allProjectsGraph, selectedProjectsGraph } = await readProjects(process.cwd(), [])
await install.handler({
...DEFAULT_OPTS,
cacheDir,
storeDir,
allProjects,
allProjectsGraph,
dir: process.cwd(),
selectedProjectsGraph,
workspaceDir: process.cwd(),
saveLockfile: true,
})
const output = await patch.handler(defaultPatchOption, ['is-positive@1.0.0'])
const patchDir = getPatchDirFromPatchOutput(output)
const tempDir = os.tmpdir()
expect(patchDir).toContain(tempDir)
expect(fs.existsSync(patchDir)).toBe(true)
expect(fs.readFileSync(path.join(patchDir, 'license'), 'utf8')).toContain('The MIT License (MIT)')
fs.appendFileSync(path.join(patchDir, 'index.js'), '// test patching', 'utf8')
fs.unlinkSync(path.join(patchDir, 'license'))
await patchCommit.handler({
...DEFAULT_OPTS,
allProjects,
allProjectsGraph,
selectedProjectsGraph,
dir: process.cwd(),
cacheDir,
storeDir,
lockfileDir: process.cwd(),
workspaceDir: process.cwd(),
saveLockfile: true,
}, [patchDir])
const { manifest } = await readProjectManifest(process.cwd())
expect(manifest.pnpm?.patchedDependencies).toStrictEqual({
'is-positive@1.0.0': 'patches/is-positive@1.0.0.patch',
})
const patchContent = fs.readFileSync('patches/is-positive@1.0.0.patch', 'utf8')
expect(patchContent).toContain('diff --git')
expect(patchContent).toContain('// test patching')
expect(fs.readFileSync('project-1/node_modules/is-positive/index.js', 'utf8')).toContain('// test patching')
expect(fs.existsSync('project-1/node_modules/is-positive/license')).toBe(false)
expect(fs.readFileSync('project-2/node_modules/is-positive/index.js', 'utf8')).toContain('// test patching')
expect(fs.existsSync('project-2/node_modules/is-positive/license')).toBe(false)
})
})
function getPatchDirFromPatchOutput (output: string) {
const [firstLine] = output.split('\n')
return firstLine.substring(firstLine.indexOf(':') + 1).trim()

View File

@@ -39,6 +39,9 @@
{
"path": "../../store/store-connection-manager"
},
{
"path": "../../workspace/filter-workspace-packages"
},
{
"path": "../apply-patch"
}

6
pnpm-lock.yaml generated
View File

@@ -2519,6 +2519,9 @@ importers:
specifier: ^1.0.1
version: 1.0.1
devDependencies:
'@pnpm/filter-workspace-packages':
specifier: workspace:*
version: link:../../workspace/filter-workspace-packages
'@pnpm/plugin-commands-patching':
specifier: workspace:*
version: 'link:'
@@ -2531,6 +2534,9 @@ importers:
'@types/ramda':
specifier: 0.28.20
version: 0.28.20
write-yaml-file:
specifier: ^4.2.0
version: 4.2.0
pkg-manager/client:
dependencies:

View File

@@ -168,7 +168,7 @@ export async function main (inputArgv: string[]) {
}
if (
(cmd === 'install' || cmd === 'import' || cmd === "dedupe") &&
(cmd === 'install' || cmd === 'import' || cmd === 'dedupe' || cmd === 'patch-commit') &&
typeof workspaceDir === 'string'
) {
cliOptions['recursive'] = true