mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-12 07:04:52 +09:00
Use .tmp before the file extension (#529)
When creating temporary files use the pattern `.tmp.ext` instead of `.ext.tmp` to be consistent with Factorio which creates `.tmp.zip` files during saving. If patching fails this will leave a `.tmp.zip` file in the instance saves directory which is ignored by the default save selector. Resolves #486.
This commit is contained in:
1 parent
faadf873fb
commit
d5bcd34cdb
6 files changed
+28
-12
No files matched your search
@@ -449,7 +449,7 @@ export default class Controller {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry.name.toLowerCase().endsWith("tmp.zip")) {
|
||||
if (entry.name.toLowerCase().endsWith(".tmp.zip")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,8 @@ class InstallError extends Error { }
|
||||
|
||||
|
||||
async function safeOutputFile(file, data, options={}) {
|
||||
let temporary = `${file}.tmp`;
|
||||
let { dir, name, ext } = path.parse(file);
|
||||
let temporary = `${dir}${name}.tmp${ext}`;
|
||||
await fs.outputFile(temporary, data, options);
|
||||
await fs.rename(temporary, file);
|
||||
}
|
||||
|
||||
@@ -417,7 +417,7 @@ export async function patch(savePath: string, modules: SaveModule[]) {
|
||||
root.file("clusterio.json", JSON.stringify(patchInfo, null, "\t"));
|
||||
|
||||
// Write back the save
|
||||
let tempSavePath = `${savePath}.tmp`;
|
||||
let tempSavePath = savePath.replace(/(\.zip)?$/, ".tmp.zip");
|
||||
let stream = zip.generateNodeStream({ compression: "DEFLATE" });
|
||||
let fd = await fs.open(tempSavePath, "w");
|
||||
try {
|
||||
|
||||
@@ -126,7 +126,8 @@ export async function getTempFile(prefix = "tmp.", suffix = "", tmpdir = "./") {
|
||||
*
|
||||
* Same as fs-extra.outputFile except the data is written to a temporary
|
||||
* file that's renamed over the target file. The name of the temporary file
|
||||
* is the same as the target file with the suffix `.tmp` added.
|
||||
* is the same as the target file with the suffix `.tmp` added before the
|
||||
* extension.
|
||||
*
|
||||
* If the operation fails it may leave behind the temporary file. This
|
||||
* should not be too much of an issue as the next time the same file is
|
||||
@@ -137,11 +138,11 @@ export async function getTempFile(prefix = "tmp.", suffix = "", tmpdir = "./") {
|
||||
* @param options - see fs.writeFile, `flag` must not be set.
|
||||
*/
|
||||
export async function safeOutputFile(file: string, data: string | Buffer, options: fs.WriteFileOptions ={}) {
|
||||
let directory = path.dirname(file);
|
||||
if (!await fs.pathExists(directory)) {
|
||||
await fs.mkdirs(directory);
|
||||
let { dir, name, ext } = path.parse(file);
|
||||
if (dir && !await fs.pathExists(dir)) {
|
||||
await fs.mkdirs(dir);
|
||||
}
|
||||
let temporary = `${file}.tmp`;
|
||||
let temporary = `${dir}${name}.tmp${ext}`;
|
||||
let fd = await fs.open(temporary, "w");
|
||||
try {
|
||||
await fs.writeFile(fd, data, options);
|
||||
|
||||
+2
-2
@@ -15,11 +15,11 @@ describe("host/patch", function() {
|
||||
const mappings = [
|
||||
["locale/en/foo.cfg", "locale/en/test-foo.cfg"],
|
||||
["locale/en/foo.txt", "locale/en/test-foo.txt"],
|
||||
["locale/en/foo.txt.tmp", "locale/en/test-foo.txt.tmp"],
|
||||
["locale/en/foo.tmp.txt", "locale/en/test-foo.tmp.txt"],
|
||||
["locale/en/foo", "locale/en/test-foo"],
|
||||
["locale/en.cfg", "locale/en/test.cfg"],
|
||||
["locale/en.txt", "locale/en/test.txt"],
|
||||
["locale/en.txt.tmp", "locale/en/test.txt.tmp"],
|
||||
["locale/en.tmp.txt", "locale/en/test.tmp.txt"],
|
||||
["locale/en", "locale/en/test"],
|
||||
["locale/en/bar/foo.cfg", "locale/en/test-bar/foo.cfg"],
|
||||
];
|
||||
|
||||
+16
-2
@@ -88,16 +88,30 @@ describe("lib/file_ops", function() {
|
||||
it("should write new target file", async function() {
|
||||
let target = path.join(baseDir, "safe", "simple.txt");
|
||||
await lib.safeOutputFile(target, "a text file", "utf8");
|
||||
assert(!await fs.pathExists(`${target}.tmp`), "temporary was left behind");
|
||||
assert(!await fs.pathExists(target.replace(".txt", ".tmp.txt")), "temporary was left behind");
|
||||
assert.equal(await fs.readFile(target, "utf8"), "a text file");
|
||||
});
|
||||
it("should overwrite existing target file", async function() {
|
||||
let target = path.join(baseDir, "safe", "exists.txt");
|
||||
await fs.outputFile(target, "previous", "utf8");
|
||||
await lib.safeOutputFile(target, "current", "utf8");
|
||||
assert(!await fs.pathExists(`${target}.tmp`), "temporary was left behind");
|
||||
assert(!await fs.pathExists(target.replace(".txt", ".tmp.txt")), "temporary was left behind");
|
||||
assert.equal(await fs.readFile(target, "utf8"), "current");
|
||||
});
|
||||
it("should handle creating file in current working directory", async function() {
|
||||
let target = "temporary-file-made-to-test-cwd.txt";
|
||||
try {
|
||||
await lib.safeOutputFile(target, "a text file", "utf8");
|
||||
} finally {
|
||||
try {
|
||||
await fs.unlink(target);
|
||||
} catch (err) {
|
||||
if (err.code !== "ENOENT") {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("checkFilename()", function() {
|
||||
|
||||
Reference in new issue
Block a user