From dd287cc3072ae1a5ce14a4ae701cbed9689e349f Mon Sep 17 00:00:00 2001 From: Darshan Sen Date: Mon, 28 Mar 2022 09:28:09 +0530 Subject: [PATCH] test,fs: add fs.rm() tests for .git directories Git for Windows creates read-only files inside the .git directory. fs.rm() was built in a way, to work around any EPERM error that can happen while deleting the .git directory by turning the directory into a writable one. This change adds a regression test for that. Refs: https://github.com/isaacs/rimraf/issues/21 Refs: https://github.com/nodejs/node/pull/38810#issuecomment-1073152001 Signed-off-by: Darshan Sen PR-URL: https://github.com/nodejs/node/pull/42410 Reviewed-By: Ben Coe Reviewed-By: Richard Lau Reviewed-By: Luigi Pinca Reviewed-By: James M Snell --- test/parallel/test-fs-rm.js | 40 +++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/parallel/test-fs-rm.js b/test/parallel/test-fs-rm.js index 14a67345fbf..4cb7b46b67a 100644 --- a/test/parallel/test-fs-rm.js +++ b/test/parallel/test-fs-rm.js @@ -6,6 +6,7 @@ const assert = require('assert'); const fs = require('fs'); const path = require('path'); const { pathToFileURL } = require('url'); +const { execSync } = require('child_process'); const { validateRmOptionsSync } = require('internal/fs/utils'); @@ -15,6 +16,15 @@ let count = 0; const nextDirPath = (name = 'rm') => path.join(tmpdir.path, `${name}-${count++}`); +const isGitPresent = (() => { + try { execSync('git --version'); return true; } catch { return false; } +})(); + +function gitInit(gitDirectory) { + fs.mkdirSync(gitDirectory); + execSync('git init', { cwd: gitDirectory }); +} + function makeNonEmptyDirectory(depth, files, folders, dirname, createSymLinks) { fs.mkdirSync(dirname, { recursive: true }); fs.writeFileSync(path.join(dirname, 'text.txt'), 'hello', 'utf8'); @@ -129,6 +139,16 @@ function removeAsync(dir) { })); } +// Removing a .git directory should not throw an EPERM. +// Refs: https://github.com/isaacs/rimraf/issues/21. +if (isGitPresent) { + const gitDirectory = nextDirPath(); + gitInit(gitDirectory); + fs.rm(gitDirectory, { recursive: true }, common.mustSucceed(() => { + assert.strictEqual(fs.existsSync(gitDirectory), false); + })); +} + // Test the synchronous version. { const dir = nextDirPath(); @@ -178,6 +198,15 @@ function removeAsync(dir) { assert.throws(() => fs.rmSync(dir), { syscall: 'stat' }); } +// Removing a .git directory should not throw an EPERM. +// Refs: https://github.com/isaacs/rimraf/issues/21. +if (isGitPresent) { + const gitDirectory = nextDirPath(); + gitInit(gitDirectory); + fs.rmSync(gitDirectory, { recursive: true }); + assert.strictEqual(fs.existsSync(gitDirectory), false); +} + // Test the Promises based version. (async () => { const dir = nextDirPath(); @@ -229,6 +258,17 @@ function removeAsync(dir) { } })().then(common.mustCall()); +// Removing a .git directory should not throw an EPERM. +// Refs: https://github.com/isaacs/rimraf/issues/21. +if (isGitPresent) { + (async () => { + const gitDirectory = nextDirPath(); + gitInit(gitDirectory); + await fs.promises.rm(gitDirectory, { recursive: true }); + assert.strictEqual(fs.existsSync(gitDirectory), false); + })().then(common.mustCall()); +} + // Test input validation. { const dir = nextDirPath();