diff --git a/.changeset/five-chefs-report.md b/.changeset/five-chefs-report.md new file mode 100644 index 0000000000..2954415d26 --- /dev/null +++ b/.changeset/five-chefs-report.md @@ -0,0 +1,5 @@ +--- +"@pnpm/plugin-commands-patching": minor +--- + +`pnpm patch-remove` removes the directory containing the patch file if it is empty. diff --git a/patching/plugin-commands-patching/src/patchRemove.ts b/patching/plugin-commands-patching/src/patchRemove.ts index 3bdf0cc489..33dd8339d0 100644 --- a/patching/plugin-commands-patching/src/patchRemove.ts +++ b/patching/plugin-commands-patching/src/patchRemove.ts @@ -57,9 +57,11 @@ export async function handler (opts: PatchRemoveCommandOptions, params: string[] throw new PnpmError('NO_PATCHES_TO_REMOVE', 'There are no patches that need to be removed') } + const patchesDirs = new Set() await Promise.all(patchesToRemove.map(async (patch) => { if (Object.prototype.hasOwnProperty.call(patchedDependencies, patch)) { const patchFile = path.join(lockfileDir, patchedDependencies[patch]) + patchesDirs.add(path.dirname(patchFile)) await fs.rm(patchFile, { force: true }) delete rootProjectManifest.pnpm!.patchedDependencies![patch] if (!Object.keys(rootProjectManifest.pnpm!.patchedDependencies!).length) { @@ -71,6 +73,15 @@ export async function handler (opts: PatchRemoveCommandOptions, params: string[] } })) + await Promise.all(Array.from(patchesDirs).map(async (dir) => { + try { + const files = await fs.readdir(dir) + if (!files.length) { + await fs.rmdir(dir) + } + } catch {} + })) + await writeProjectManifest(rootProjectManifest) if (opts?.selectedProjectsGraph?.[lockfileDir]) { diff --git a/patching/plugin-commands-patching/test/patch.test.ts b/patching/plugin-commands-patching/test/patch.test.ts index 2393371873..225aee3f99 100644 --- a/patching/plugin-commands-patching/test/patch.test.ts +++ b/patching/plugin-commands-patching/test/patch.test.ts @@ -898,6 +898,7 @@ describe('patch-remove', () => { const { manifest: newManifest } = await readProjectManifest(process.cwd()) expect(newManifest!.pnpm!).toBeUndefined() expect(fs.existsSync(path.join(process.cwd(), 'patches/is-positive@1.0.0.patch'))).toBe(false) + expect(fs.existsSync(path.join(process.cwd(), 'patches'))).toBe(false) }) test('prompt to select patches that to be removed', async () => {