Add findUnusedName to file_ops.js

Add function to find an unused name in a directory to lib/file_ops and
use it for finding an unused instance directory.
This commit is contained in:
Hornwitser committed 2021-06-01 11:22:22 +02:00
1 parent 544d8deb81
commit 0066a06107
3 files changed
+75 -7

No files matched your search

+38
View File
@@ -32,6 +32,44 @@ async function getNewestFile(directory, filter = (name) => true) {
return newestFile;
}
/**
* Modifies name in case it already exisist at the given directory
*
* Checks the directory passed if it already contains a file or folder with
* the given name, if it does not returns name unmodified, otherwise it
* returns a modified name that does not exist in the directory.
*
* Warning: this function should not be relied upon to be accurate for
* security sensitive applications. The selection process is inherently
* racy and a file or folder may have been created in the folder by the time
* this function returns.
*
* @param {string} directory - directory to check in.
* @param {string} name - file name to check for, may have extension.
* @param {string} extension - dot extension used for the file name.
* @returns {string} modified name with extension that likely does not exist
* in the folder
*/
async function findUnusedName(directory, name, extension = "") {
if (extension && name.endsWith(extension)) {
name = name.slice(0, -extension.length);
}
while (true) {
if (!await fs.pathExists(path.join(directory, `${name}${extension}`))) {
return `${name}${extension}`;
}
let match = /^(.*?)(-(\d+))?$/.exec(name);
if (!match[2]) {
name = `${match[1]}-2`;
} else {
name = `${match[1]}-${Number.parseInt(match[3], 10) + 1}`;
}
}
}
module.exports = {
getNewestFile,
findUnusedName,
};
+2 -7
View File
@@ -1102,13 +1102,8 @@ class Slave extends libLink.Link {
throw new Error(`Instance name ${err.message}`);
}
// For now add dashes until an unused directory name is found
let dir = path.join(this.config.get("slave.instances_directory"), name);
while (await fs.pathExists(dir)) {
dir += "-";
}
return dir;
let instancesDir = this.config.get("slave.instances_directory");
return path.join(instancesDir, await libFileOps.findUnusedName(instancesDir, name));
}
async forwardRequestToInstance(message, request) {
+35
View File
@@ -13,6 +13,13 @@ describe("lib/file_ops", function() {
await fs.outputFile(path.join(baseDir, "test", "file.txt"), "contents");
await fs.outputFile(path.join(baseDir, "test", "another file.txt"), "more contents");
await fs.outputFile(path.join(baseDir, "find", "file"), "contents");
await fs.outputFile(path.join(baseDir, "find", "file.txt"), "contents");
await fs.outputFile(path.join(baseDir, "find", "foo-1"), "contents");
await fs.outputFile(path.join(baseDir, "find", "foo-2"), "contents");
await fs.outputFile(path.join(baseDir, "find", "bar-1.txt"), "contents");
await fs.outputFile(path.join(baseDir, "find", "bar-2.txt"), "contents");
}
before(setupTestingEnv);
@@ -31,4 +38,32 @@ describe("lib/file_ops", function() {
assert.equal(newest, null);
});
});
describe("findUnusedName()", function() {
it("should return named unchanged if it does not exist", async function() {
let cases = [
[["file"], "file"],
[["file", ".txt"], "file.txt"],
[["file.txt", ".txt"], "file.txt"],
];
for (let [args, expected] of cases) {
let actual = await libFileOps.findUnusedName(path.join(baseDir, "test", "folder"), ...args);
assert.equal(actual, expected);
}
});
it("should return changed name if it does exist", async function() {
let cases = [
[["file"], "file-2"],
[["file", ".txt"], "file-2.txt"],
[["file.txt", ".txt"], "file-2.txt"],
[["foo-1"], "foo-3"],
[["bar-1", ".txt"], "bar-3.txt"],
[["bar-1.txt", ".txt"], "bar-3.txt"],
];
for (let [args, expected] of cases) {
let actual = await libFileOps.findUnusedName(path.join(baseDir, "find"), ...args);
assert.equal(actual, expected);
}
});
});
});