From 897578676de3d47546272b1c45735b4ba3cdbc48 Mon Sep 17 00:00:00 2001 From: Craigory Coppola Date: Mon, 13 May 2024 16:33:06 -0400 Subject: [PATCH] feat(core): support finding matching projects with only negative patterns (#22743) ## Current Behavior Passing `--projects !tag:someTag` would select 0 projects, since the only pattern is negative ## Expected Behavior Passing `--projects !tag:someTag` would select X projects, where X is the number of projects without someTag. ## Related Issue(s) Fixes # --- .../nx/src/utils/find-matching-projects.spec.ts | 16 ++++++++++++++++ packages/nx/src/utils/find-matching-projects.ts | 16 +++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/packages/nx/src/utils/find-matching-projects.spec.ts b/packages/nx/src/utils/find-matching-projects.spec.ts index 99272de67ea92..7420b22faa470 100644 --- a/packages/nx/src/utils/find-matching-projects.spec.ts +++ b/packages/nx/src/utils/find-matching-projects.spec.ts @@ -162,6 +162,22 @@ describe('findMatchingProjects', () => { 'nested', ]); }); + + it('should support "all except" style patterns', () => { + expect(findMatchingProjects(['!a'], projectGraph)).toEqual([ + 'test-project', + 'b', + 'c', + 'nested', + ]); + expect(findMatchingProjects(['!tag:api'], projectGraph)).toEqual([ + 'b', + 'nested', + ]); + expect( + findMatchingProjects(['!tag:api', 'test-project'], projectGraph) + ).toEqual(['b', 'nested', 'test-project']); + }); }); const projects = [ diff --git a/packages/nx/src/utils/find-matching-projects.ts b/packages/nx/src/utils/find-matching-projects.ts index bdef3dd085353..2b17d8703c63d 100644 --- a/packages/nx/src/utils/find-matching-projects.ts +++ b/packages/nx/src/utils/find-matching-projects.ts @@ -39,6 +39,16 @@ export function findMatchingProjects( const matchedProjects: Set = new Set(); + // If the first pattern is an exclude pattern, + // we add a wildcard pattern at the first to select + // all projects, except the ones that match the exclude pattern. + // e.g. ['!tag:someTag', 'project2'] will match all projects except + // the ones with the tag 'someTag', and also match the project 'project2', + // regardless of its tags. + if (isExcludePattern(patterns[0])) { + patterns.unshift('*'); + } + for (const stringPattern of patterns) { if (!stringPattern.length) { continue; @@ -205,11 +215,15 @@ function addMatchingProjectsByTag( } } +function isExcludePattern(pattern: string): boolean { + return pattern.startsWith('!'); +} + function parseStringPattern( pattern: string, projects: Record ): ProjectPattern { - const isExclude = pattern.startsWith('!'); + const isExclude = isExcludePattern(pattern); // Support for things like: `!{type}:value` if (isExclude) {