mirror of
https://github.com/pnpm/pnpm.git
synced 2025-12-25 08:08:14 -05:00
fix: pnpm patch should ignore files that are not included in the patched package (#6596)
close #6565 --------- Co-authored-by: Zoltan Kochan <z@kochan.io>
This commit is contained in:
6
.changeset/blue-numbers-rest.md
Normal file
6
.changeset/blue-numbers-rest.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@pnpm/plugin-commands-patching": patch
|
||||
"pnpm": patch
|
||||
---
|
||||
|
||||
When patching a dependency, only consider files specified in the 'files' field of its package.json. Ignore all others [#6565](https://github.com/pnpm/pnpm/issues/6565)
|
||||
@@ -39,6 +39,7 @@
|
||||
"@pnpm/registry-mock": "3.8.0",
|
||||
"@pnpm/test-fixtures": "workspace:*",
|
||||
"@types/normalize-path": "^3.0.0",
|
||||
"@types/npm-packlist": "^3.0.0",
|
||||
"@types/ramda": "0.28.20",
|
||||
"@types/semver": "7.3.13",
|
||||
"write-yaml-file": "^5.0.0"
|
||||
@@ -60,7 +61,9 @@
|
||||
"@pnpm/store-connection-manager": "workspace:*",
|
||||
"enquirer": "^2.3.6",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"fast-glob": "^3.2.12",
|
||||
"normalize-path": "^3.0.0",
|
||||
"npm-packlist": "^5.1.3",
|
||||
"ramda": "npm:@pnpm/ramda@0.28.1",
|
||||
"realpath-missing": "^1.1.0",
|
||||
"render-help": "^1.0.3",
|
||||
|
||||
@@ -5,14 +5,17 @@ import { type 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'
|
||||
import glob from 'fast-glob'
|
||||
import normalizePath from 'normalize-path'
|
||||
import pick from 'ramda/src/pick'
|
||||
import equals from 'ramda/src/equals'
|
||||
import execa from 'safe-execa'
|
||||
import escapeStringRegexp from 'escape-string-regexp'
|
||||
import renderHelp from 'render-help'
|
||||
import tempy from 'tempy'
|
||||
import { writePackage } from './writePackage'
|
||||
import { parseWantedDependency } from '@pnpm/parse-wanted-dependency'
|
||||
import packlist from 'npm-packlist'
|
||||
|
||||
export const rcOptionsTypes = cliOptionsTypes
|
||||
|
||||
@@ -49,7 +52,10 @@ export async function handler (opts: install.InstallCommandOptions & Pick<Config
|
||||
const pkgNameAndVersion = `${patchedPkgManifest.name}@${patchedPkgManifest.version}`
|
||||
const srcDir = tempy.directory()
|
||||
await writePackage(parseWantedDependency(pkgNameAndVersion), srcDir, opts)
|
||||
const patchContent = await diffFolders(srcDir, userDir)
|
||||
|
||||
const patchedPkgDir = await preparePkgFilesForDiff(userDir)
|
||||
const patchContent = await diffFolders(srcDir, patchedPkgDir)
|
||||
|
||||
const patchFileName = pkgNameAndVersion.replace('/', '__')
|
||||
await fs.promises.writeFile(path.join(patchesDir, `${patchFileName}.patch`), patchContent, 'utf8')
|
||||
const { writeProjectManifest, manifest } = await tryReadProjectManifest(lockfileDir)
|
||||
@@ -129,3 +135,36 @@ function removeTrailingAndLeadingSlash (p: string) {
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
/**
|
||||
* Link files from the source directory to a new temporary directory,
|
||||
* but only if not all files in the source directory should be included in the package.
|
||||
* If all files should be included, return the original source directory without creating any links.
|
||||
* This is required in order for the diff to not include files that are not part of the package.
|
||||
*/
|
||||
async function preparePkgFilesForDiff (src: string): Promise<string> {
|
||||
const files = Array.from(new Set((await packlist({ path: src })).map((f) => path.join(f))))
|
||||
// If there are no extra files in the source directories, then there is no reason
|
||||
// to copy.
|
||||
if (await areAllFilesInPkg(files, src)) {
|
||||
return src
|
||||
}
|
||||
const dest = tempy.directory()
|
||||
await Promise.all(
|
||||
files.map(async (file) => {
|
||||
const srcFile = path.join(src, file)
|
||||
const destFile = path.join(dest, file)
|
||||
const destDir = path.dirname(destFile)
|
||||
await fs.promises.mkdir(destDir, { recursive: true })
|
||||
await fs.promises.link(srcFile, destFile)
|
||||
})
|
||||
)
|
||||
return dest
|
||||
}
|
||||
|
||||
async function areAllFilesInPkg (files: string[], basePath: string) {
|
||||
const allFiles = await glob('**', {
|
||||
cwd: basePath,
|
||||
})
|
||||
return equals(allFiles.sort(), files.sort())
|
||||
}
|
||||
|
||||
@@ -95,6 +95,34 @@ describe('patch and commit', () => {
|
||||
expect(fs.existsSync('node_modules/is-positive/license')).toBe(false)
|
||||
})
|
||||
|
||||
test('patch and commit with filtered files', async () => {
|
||||
const output = await patch.handler(defaultPatchOption, ['is-positive@1.0.0'])
|
||||
const patchDir = getPatchDirFromPatchOutput(output)
|
||||
const tempDir = os.tmpdir() // temp dir depends on the operating system (@see tempy)
|
||||
|
||||
// store patch files in a temporary directory when not given editDir option
|
||||
expect(patchDir).toContain(tempDir)
|
||||
expect(fs.existsSync(patchDir)).toBe(true)
|
||||
|
||||
// sanity check to ensure that the license file contains the expected string
|
||||
expect(fs.readFileSync(path.join(patchDir, 'license'), 'utf8')).toContain('The MIT License (MIT)')
|
||||
fs.writeFileSync(path.join(patchDir, 'ignore.txt'), '', 'utf8')
|
||||
|
||||
const { manifest } = await readProjectManifest(patchDir)
|
||||
expect(manifest?.files).toStrictEqual(['index.js'])
|
||||
|
||||
await patchCommit.handler({
|
||||
...DEFAULT_OPTS,
|
||||
cacheDir,
|
||||
dir: process.cwd(),
|
||||
frozenLockfile: false,
|
||||
fixLockfile: true,
|
||||
storeDir,
|
||||
}, [patchDir])
|
||||
|
||||
expect(fs.existsSync('node_modules/is-positive/ignore.txt')).toBe(false)
|
||||
})
|
||||
|
||||
test('patch and commit with a custom edit dir', async () => {
|
||||
const editDir = path.join(tempy.directory())
|
||||
|
||||
|
||||
9
pnpm-lock.yaml
generated
9
pnpm-lock.yaml
generated
@@ -2633,9 +2633,15 @@ importers:
|
||||
escape-string-regexp:
|
||||
specifier: ^4.0.0
|
||||
version: 4.0.0
|
||||
fast-glob:
|
||||
specifier: ^3.2.12
|
||||
version: 3.2.12
|
||||
normalize-path:
|
||||
specifier: ^3.0.0
|
||||
version: 3.0.0
|
||||
npm-packlist:
|
||||
specifier: ^5.1.3
|
||||
version: 5.1.3
|
||||
ramda:
|
||||
specifier: npm:@pnpm/ramda@0.28.1
|
||||
version: /@pnpm/ramda@0.28.1
|
||||
@@ -2673,6 +2679,9 @@ importers:
|
||||
'@types/normalize-path':
|
||||
specifier: ^3.0.0
|
||||
version: 3.0.0
|
||||
'@types/npm-packlist':
|
||||
specifier: ^3.0.0
|
||||
version: 3.0.0
|
||||
'@types/ramda':
|
||||
specifier: 0.28.20
|
||||
version: 0.28.20
|
||||
|
||||
Reference in New Issue
Block a user