From 4e022c68e96dfa6d6d3a6645508528f921aa1866 Mon Sep 17 00:00:00 2001 From: theit8514 Date: Thu, 18 Nov 2021 22:15:26 -0500 Subject: [PATCH 1/2] Add support for relative paths in cp Fix cp error messages Add support for directory destinations (e.g. copy file.js directory) --- src/Terminal/DirectoryHelpers.ts | 39 ++++++++++++++++++++++++++++++++ src/Terminal/commands/cp.ts | 27 +++++++++++++++++----- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/src/Terminal/DirectoryHelpers.ts b/src/Terminal/DirectoryHelpers.ts index 7976e7415..00599feac 100644 --- a/src/Terminal/DirectoryHelpers.ts +++ b/src/Terminal/DirectoryHelpers.ts @@ -169,6 +169,45 @@ export function getAllParentDirectories(path: string): string { return t_path.slice(0, lastSlash + 1); } +/** + * Given a destination that only contains a directory part, returns the + * path to the source filename inside the new destination directory. + * Otherwise, returns the path to the destination file. + * @param destination The destination path or file name + * @param source The source path + * @param cwd The current working directory + * @returns A file path which may be absolute or relative + */ +export function getDestinationFilepath(destination: string, source: string, cwd: string) { + const dstDir = evaluateDirectoryPath(destination, cwd); + // If evaluating the directory for this destination fails, we have a filename or full path. + if (dstDir === null) { + return destination; + } else { + // Append the filename to the directory provided. + let t_path = removeTrailingSlash(dstDir); + const fileName = getFileName(source); + return t_path + "/" + fileName; + } +} + +/** + * Given a filepath, returns the file name (e.g. without directory parts) + * For example: + * /home/var/test.js -> test.js + * ./var/test.js -> test.js + * test.js -> test.js + */ +export function getFileName(path: string): string { + const t_path = path; + const lastSlash = t_path.lastIndexOf("/"); + if (lastSlash === -1) { + return t_path; + } + + return t_path.slice(lastSlash + 1); +} + /** * Checks if a file path refers to a file in the root directory. */ diff --git a/src/Terminal/commands/cp.ts b/src/Terminal/commands/cp.ts index bd637763e..9f2e48c61 100644 --- a/src/Terminal/commands/cp.ts +++ b/src/Terminal/commands/cp.ts @@ -3,6 +3,7 @@ import { IRouter } from "../../ui/Router"; import { IPlayer } from "../../PersonObjects/IPlayer"; import { BaseServer } from "../../Server/BaseServer"; import { isScriptFilename } from "../../Script/isScriptFilename"; +import { getDestinationFilepath, areFilesEqual } from "../DirectoryHelpers"; export function cp( terminal: ITerminal, @@ -16,9 +17,23 @@ export function cp( terminal.error("Incorrect usage of cp command. Usage: cp [src] [dst]"); return; } - const src = args[0] + ""; - const dst = args[1] + ""; - if (src === dst) { + // Convert a relative path source file to the absolute path. + const src = terminal.getFilepath(args[0] + ""); + if (src === null) { + terminal.error("src cannot be a directory"); + return; + } + + // Get the destination based on the source file and the current directory + const t_dst = getDestinationFilepath(args[1] + "", src, terminal.cwd()); + if (t_dst === null) { + terminal.error("error parsing dst file"); + return; + } + + // Convert a relative path destination file to the absolute path. + const dst = terminal.getFilepath(t_dst); + if (areFilesEqual(src, dst)) { terminal.error("src and dst cannot be the same"); return; } @@ -50,7 +65,7 @@ export function cp( const tRes = server.writeToTextFile(dst, txtFile.text); if (!tRes.success) { - terminal.error("scp failed"); + terminal.error("cp failed"); return; } if (tRes.overwritten) { @@ -71,13 +86,13 @@ export function cp( } } if (sourceScript == null) { - terminal.error("cp() failed. No such script exists"); + terminal.error("cp failed. No such script exists"); return; } const sRes = server.writeToScriptFile(dst, sourceScript.code); if (!sRes.success) { - terminal.error(`scp failed`); + terminal.error(`cp failed`); return; } if (sRes.overwritten) { From 8ef227595ad6cd4e491cb1da29282432c336040d Mon Sep 17 00:00:00 2001 From: theit8514 Date: Wed, 1 Dec 2021 12:27:39 -0500 Subject: [PATCH 2/2] Add support for relative paths in mv Fixes mv command deleting file on overwrite --- src/Terminal/commands/mv.ts | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/Terminal/commands/mv.ts b/src/Terminal/commands/mv.ts index 0ed723987..449f92cc8 100644 --- a/src/Terminal/commands/mv.ts +++ b/src/Terminal/commands/mv.ts @@ -5,6 +5,7 @@ import { BaseServer } from "../../Server/BaseServer"; import { isScriptFilename } from "../../Script/isScriptFilename"; import { TextFile } from "../../TextFile"; import { Script } from "../../Script/Script"; +import { getDestinationFilepath, areFilesEqual } from "../DirectoryHelpers"; export function mv( terminal: ITerminal, @@ -20,7 +21,7 @@ export function mv( try { const source = args[0] + ""; - const dest = args[1] + ""; + const t_dest = args[1] + ""; if (!isScriptFilename(source) && !source.endsWith(".txt")) { terminal.error(`'mv' can only be used on scripts and text files (.txt)`); @@ -34,9 +35,19 @@ export function mv( } const sourcePath = terminal.getFilepath(source); - const destPath = terminal.getFilepath(dest); + // Get the destination based on the source file and the current directory + const dest = getDestinationFilepath(t_dest, source, terminal.cwd()); + if (dest === null) { + terminal.error("error parsing dst file"); + return; + } const destFile = terminal.getFile(player, dest); + const destPath = terminal.getFilepath(dest); + if (areFilesEqual(sourcePath, destPath)) { + terminal.error(`Source and destination files are the same file`); + return; + } // 'mv' command only works on scripts and txt files. // Also, you can't convert between different file types @@ -55,7 +66,7 @@ export function mv( if (destFile != null) { // Already exists, will be overwritten, so we'll delete it - const status = server.removeFile(destPath); + const status = server.removeFile(dest); if (!status.res) { terminal.error(`Something went wrong...please contact game dev (probably a bug)`); return;