Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(matcher): should ignore successfully with multiple ignore patterns #5643

Merged
merged 4 commits into from Nov 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/curly-penguins-perform.md
@@ -0,0 +1,6 @@
---
"@pnpm/plugin-commands-installation": patch
"pnpm": patch
---

`pnpm update --latest !foo` should not update anything if the only dependency in the project is the ignored one [#5643](https://github.com/pnpm/pnpm/pull/5643).
6 changes: 6 additions & 0 deletions .changeset/weak-spies-thank.md
@@ -0,0 +1,6 @@
---
"@pnpm/matcher": patch
"pnpm": patch
---

The `pnpm.updateConfig.ignoreDependencies` setting should work with multiple dependencies in the array [#5639](https://github.com/pnpm/pnpm/issues/5639).
11 changes: 9 additions & 2 deletions packages/matcher/src/index.ts
Expand Up @@ -20,17 +20,22 @@ export function createMatcherWithIndex (patterns: string[]): MatcherWithIndex {
}
const matchArr: MatcherFunction[] = []
let hasIgnore = false
let hasInclude = false
for (const pattern of patterns) {
if (isIgnorePattern(pattern)) {
hasIgnore = true
matchArr.push({ ignore: true, match: matcherFromPattern(pattern.substring(1)) })
} else {
hasInclude = true
matchArr.push({ ignore: false, match: matcherFromPattern(pattern) })
}
}
if (!hasIgnore) {
return matchInputWithNonIgnoreMatchers.bind(null, matchArr)
}
if (!hasInclude) {
return matchInputWithoutIgnoreMatchers.bind(null, matchArr)
}
return matchInputWithMatchersArray.bind(null, matchArr)
}

Expand All @@ -41,15 +46,17 @@ function matchInputWithNonIgnoreMatchers (matchArr: MatcherFunction[], input: st
return -1
}

function matchInputWithoutIgnoreMatchers (matchArr: MatcherFunction[], input: string): number {
return matchArr.some(({ match }) => match(input)) ? -1 : 0
}

function matchInputWithMatchersArray (matchArr: MatcherFunction[], input: string): number {
let matchedPatternIndex = -1
for (let i = 0; i < matchArr.length; i++) {
const { ignore, match } = matchArr[i]
if (ignore) {
if (match(input)) {
matchedPatternIndex = -1
} else if (matchedPatternIndex === -1) {
matchedPatternIndex = i
}
} else if (matchedPatternIndex === -1 && match(input)) {
matchedPatternIndex = i
Expand Down
14 changes: 13 additions & 1 deletion packages/matcher/test/index.ts
Expand Up @@ -85,7 +85,7 @@ test('createMatcherWithIndex()', () => {
}
{
const match = createMatcherWithIndex(['!eslint-plugin-bar', 'eslint-*'])
expect(match('eslint-plugin-foo')).toBe(0)
expect(match('eslint-plugin-foo')).toBe(1)
expect(match('eslint-plugin-bar')).toBe(1)
}
{
Expand All @@ -98,4 +98,16 @@ test('createMatcherWithIndex()', () => {
const match = createMatcherWithIndex(['!@pnpm.e2e/peer-*'])
expect(match('@pnpm.e2e/foo')).toBe(0)
}
{
const match = createMatcherWithIndex(['!foo', '!bar'])
expect(match('foo')).toBe(-1)
expect(match('bar')).toBe(-1)
expect(match('baz')).toBe(0)
}
{
const match = createMatcherWithIndex(['!foo', '!bar', 'qar'])
expect(match('foo')).toBe(-1)
expect(match('bar')).toBe(-1)
expect(match('baz')).toBe(-1)
}
})
9 changes: 6 additions & 3 deletions packages/plugin-commands-installation/src/installDeps.ts
Expand Up @@ -214,9 +214,12 @@ when running add/update with the --workspace option')
}
if (updateMatch != null) {
params = matchDependencies(updateMatch, manifest, includeDirect)
if (params.length === 0 && opts.depth === 0) {
throw new PnpmError('NO_PACKAGE_IN_DEPENDENCIES',
'None of the specified packages were found in the dependencies.')
if (params.length === 0) {
if (opts.latest) return
if (opts.depth === 0) {
throw new PnpmError('NO_PACKAGE_IN_DEPENDENCIES',
'None of the specified packages were found in the dependencies.')
}
}
}

Expand Down
39 changes: 38 additions & 1 deletion packages/plugin-commands-installation/test/update/update.ts
Expand Up @@ -217,16 +217,19 @@ test('update should work normal when set empty string version', async () => {
test('ignore packages in package.json > updateConfig.ignoreDependencies fields in update command', async () => {
await addDistTag({ package: '@pnpm.e2e/foo', version: '100.0.0', distTag: 'latest' })
await addDistTag({ package: '@pnpm.e2e/bar', version: '100.0.0', distTag: 'latest' })
await addDistTag({ package: '@pnpm.e2e/qar', version: '100.0.0', distTag: 'latest' })

const project = prepare({
dependencies: {
'@pnpm.e2e/foo': '100.0.0',
'@pnpm.e2e/bar': '100.0.0',
'@pnpm.e2e/qar': '100.0.0',
},
pnpm: {
updateConfig: {
ignoreDependencies: [
'@pnpm.e2e/foo',
'@pnpm.e2e/bar',
],
},
},
Expand All @@ -241,9 +244,11 @@ test('ignore packages in package.json > updateConfig.ignoreDependencies fields i

expect(lockfile.packages['/@pnpm.e2e/foo/100.0.0']).toBeTruthy()
expect(lockfile.packages['/@pnpm.e2e/bar/100.0.0']).toBeTruthy()
expect(lockfile.packages['/@pnpm.e2e/qar/100.0.0']).toBeTruthy()

await addDistTag({ package: '@pnpm.e2e/foo', version: '100.1.0', distTag: 'latest' })
await addDistTag({ package: '@pnpm.e2e/bar', version: '100.1.0', distTag: 'latest' })
await addDistTag({ package: '@pnpm.e2e/qar', version: '100.1.0', distTag: 'latest' })

await update.handler({
...DEFAULT_OPTS,
Expand All @@ -254,7 +259,8 @@ test('ignore packages in package.json > updateConfig.ignoreDependencies fields i
const lockfileUpdated = await project.readLockfile()

expect(lockfileUpdated.packages['/@pnpm.e2e/foo/100.0.0']).toBeTruthy()
expect(lockfileUpdated.packages['/@pnpm.e2e/bar/100.1.0']).toBeTruthy()
expect(lockfileUpdated.packages['/@pnpm.e2e/bar/100.0.0']).toBeTruthy()
expect(lockfileUpdated.packages['/@pnpm.e2e/qar/100.1.0']).toBeTruthy()
})

test('not ignore packages if these are specified in parameter even if these are listed in package.json > pnpm.update.ignoreDependencies fields in update command', async () => {
Expand Down Expand Up @@ -298,3 +304,34 @@ test('not ignore packages if these are specified in parameter even if these are
expect(lockfileUpdated.packages['/@pnpm.e2e/foo/100.1.0']).toBeTruthy()
expect(lockfileUpdated.packages['/@pnpm.e2e/bar/100.1.0']).toBeTruthy()
})

test('do not update anything if all the dependencies are ignored and trying to update to latest', async () => {
await addDistTag({ package: '@pnpm.e2e/foo', version: '100.1.0', distTag: 'latest' })

const project = prepare({
dependencies: {
'@pnpm.e2e/foo': '100.0.0',
},
pnpm: {
updateConfig: {
ignoreDependencies: [
'@pnpm.e2e/foo',
],
},
},
})

await install.handler({
...DEFAULT_OPTS,
dir: process.cwd(),
})

await update.handler({
...DEFAULT_OPTS,
dir: process.cwd(),
latest: true,
}, [])

const lockfileUpdated = await project.readLockfile()
expect(lockfileUpdated.packages['/@pnpm.e2e/foo/100.0.0']).toBeTruthy()
})