From 4e022c68e96dfa6d6d3a6645508528f921aa1866 Mon Sep 17 00:00:00 2001 From: theit8514 Date: Thu, 18 Nov 2021 22:15:26 -0500 Subject: [PATCH] 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) {