diff --git a/packages/ctl/ctl.js b/packages/ctl/ctl.js index b4cc3e5d..1c651140 100755 --- a/packages/ctl/ctl.js +++ b/packages/ctl/ctl.js @@ -533,8 +533,11 @@ async function loadMapSettings(args) { }; } -instanceCommands.add(new libCommand.Command({ - definition: ["list-saves ", "list saves on an instance", (yargs) => { +const instanceSaveCommands = new libCommand.CommandTree({ + name: "save", alias: ["s"], description: "Instance save management", +}); +instanceSaveCommands.add(new libCommand.Command({ + definition: ["list ", "list saves on an instance", (yargs) => { yargs.positional("instance", { describe: "Instance to list saves on", type: "string" }); }], handler: async function(args, control) { @@ -548,8 +551,8 @@ instanceCommands.add(new libCommand.Command({ }, })); -instanceCommands.add(new libCommand.Command({ - definition: ["create-save [name]", "Create a new save on an instance", (yargs) => { +instanceSaveCommands.add(new libCommand.Command({ + definition: ["create [name]", "Create a new save on an instance", (yargs) => { yargs.positional("instance", { describe: "Instance to create on", type: "string" }); yargs.positional("name", { describe: "Name of save to create.", type: "string", default: "world.zip" }); yargs.options({ @@ -573,8 +576,8 @@ instanceCommands.add(new libCommand.Command({ }, })); -instanceCommands.add(new libCommand.Command({ - definition: ["upload-save ", "Upload a save to an instance", (yargs) => { +instanceSaveCommands.add(new libCommand.Command({ + definition: ["upload ", "Upload a save to an instance", (yargs) => { yargs.positional("instance", { describe: "Instance to upload to", type: "string" }); yargs.positional("filepath", { describe: "Path to save to upload", type: "string" }); yargs.options({ @@ -624,8 +627,8 @@ instanceCommands.add(new libCommand.Command({ }, })); -instanceCommands.add(new libCommand.Command({ - definition: ["download-save ", "Download a save from an instance", (yargs) => { +instanceSaveCommands.add(new libCommand.Command({ + definition: ["download ", "Download a save from an instance", (yargs) => { yargs.positional("instance", { describe: "Instance to download save from", type: "string" }); yargs.positional("save", { describe: "Save to download", type: "string" }); }], @@ -669,8 +672,8 @@ instanceCommands.add(new libCommand.Command({ }, })); -instanceCommands.add(new libCommand.Command({ - definition: ["delete-save ", "Delete a save from an instance", (yargs) => { +instanceSaveCommands.add(new libCommand.Command({ + definition: ["delete ", "Delete a save from an instance", (yargs) => { yargs.positional("instance", { describe: "Instance to delete save from", type: "string" }); yargs.positional("save", { describe: "Save to delete", type: "string" }); }], @@ -682,6 +685,7 @@ instanceCommands.add(new libCommand.Command({ }); }, })); +instanceCommands.add(instanceSaveCommands); instanceCommands.add(new libCommand.Command({ definition: ["export-data ", "Export item icons and locale from instance", (yargs) => { diff --git a/test/integration/clusterio.js b/test/integration/clusterio.js index b066d15f..77c51b39 100644 --- a/test/integration/clusterio.js +++ b/test/integration/clusterio.js @@ -250,11 +250,11 @@ describe("Integration of Clusterio", function() { }); }); - describe("instance create-save", function() { + describe("instance save create", function() { it("creates a save", async function() { slowTest(this); getControl().saveListUpdates = []; - await execCtl("instance create-save test"); + await execCtl("instance save create test"); await checkInstanceStatus(44, "stopped"); }); }); @@ -266,10 +266,10 @@ describe("Integration of Clusterio", function() { }); }); - describe("instance list-saves", function() { + describe("instance save list", function() { it("lists the created save", async function() { slowTest(this); - let result = await execCtl("instance list-saves test"); + let result = await execCtl("instance save list test"); assert(/world\.zip/.test(result.stdout), "world.zip not present in list save output"); }); }); @@ -530,10 +530,10 @@ describe("Integration of Clusterio", function() { }); }); - describe("instance upload-save", function() { + describe("instance save upload", function() { it("should upload a zip file", async function() { await fs.outputFile(path.join("temp", "test", "upload.zip"), "a test"); - await execCtl("instance upload-save 44 upload.zip"); + await execCtl("instance save upload 44 upload.zip"); assert( await fs.pathExists(path.join("temp", "test", "instances", "test", "saves", "upload.zip")), "file not uploaded to saves directory" @@ -541,42 +541,42 @@ describe("Integration of Clusterio", function() { }); it("should reject non-zip files", async function() { await fs.outputFile(path.join("temp", "test", "invalid"), "a test"); - await assert.rejects(execCtl("instance upload-save 44 invalid")); + await assert.rejects(execCtl("instance save upload 44 invalid")); }); it("should reject path traversal attacks", async function() { await fs.outputFile(path.join("temp", "test", "upload.zip"), "a test"); - await assert.rejects(execCtl("instance upload-save 44 upload.zip --name ../traversal.zip")); + await assert.rejects(execCtl("instance save upload 44 upload.zip --name ../traversal.zip")); }); }); - describe("instance download-save", function() { + describe("instance save download", function() { it("should download a save", async function() { await fs.remove(path.join("temp", "test", "upload.zip")); - await execCtl("instance download-save 44 upload.zip"); + await execCtl("instance save download 44 upload.zip"); assert(await fs.pathExists(path.join("temp", "test", "upload.zip"))); }); it("should error if save does not exist", async function() { - await assert.rejects(execCtl("instance download-save 44 invalid")); + await assert.rejects(execCtl("instance save download 44 invalid")); }); it("should error on path traversal attacks", async function() { - await assert.rejects(execCtl("instance download-save 44 ../factorio-current.log")); + await assert.rejects(execCtl("instance save download 44 ../factorio-current.log")); }); }); - describe("instance delete-save", function() { + describe("instance save delete", function() { it("should delete a save", async function() { - await execCtl("instance delete-save 44 upload.zip"); + await execCtl("instance save delete 44 upload.zip"); assert( !await fs.pathExists(path.join("temp", "test", "instances", "test", "saves", "upload.zip")), "file not deleted" ); }); it("should error if save does not exist", async function() { - await assert.rejects(execCtl("instance delete-save 44 upload.zip")); + await assert.rejects(execCtl("instance save delete 44 upload.zip")); }); it("should error on path traversal attacks", async function() { await fs.outputFile(path.join("temp", "test", "upload.zip"), "a test"); - await assert.rejects(execCtl("instance delete-save 44 ../../upload.zip")); + await assert.rejects(execCtl("instance save delete 44 ../../upload.zip")); }); });