From 8af064c9a4c719a2c0a75eceef494282c00e3caa Mon Sep 17 00:00:00 2001 From: shmck Date: Sat, 20 Jun 2020 11:37:24 -0700 Subject: [PATCH 1/4] setup arg tests Signed-off-by: shmck --- tests/args.test.ts | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 tests/args.test.ts diff --git a/tests/args.test.ts b/tests/args.test.ts new file mode 100644 index 0000000..454c0ae --- /dev/null +++ b/tests/args.test.ts @@ -0,0 +1,42 @@ +import { getArg } from "../src/utils/args"; + +describe("args", () => { + it("should capture an arg name from text", () => { + const args = ["--name", "value"]; + const result = getArg(args, { name: "name" }); + expect(result).toBe("value"); + }); + it("should capture an arg alias from text", () => { + const args = ["-n", "value"]; + const result = getArg(args, { name: "name", alias: "n" }); + expect(result).toBe("value"); + }); + it("should capture an arg name from text when starting values", () => { + const args = ["dir", "--name", "value"]; + const result = getArg(args, { name: "name" }); + expect(result).toBe("value"); + }); + it("should capture an arg alias from text", () => { + const args = ["dir", "-n", "value"]; + const result = getArg(args, { name: "name", alias: "n" }); + expect(result).toBe("value"); + }); + it("should default value to true if no next value", () => { + const args = ["--someBool"]; + const result = getArg(args, { + name: "someBool", + alias: "sb", + type: "bool", + }); + expect(result).toBe(true); + }); + it("should default value to true if next value is param", () => { + const args = ["--someBool", "--someOtherBool"]; + const result = getArg(args, { + name: "someBool", + alias: "sb", + type: "bool", + }); + expect(result).toBe(true); + }); +}); From 3dbbd46ee1918ef21d49d0c3815888540b4aba48 Mon Sep 17 00:00:00 2001 From: shmck Date: Sat, 20 Jun 2020 11:41:23 -0700 Subject: [PATCH 2/4] fix up arg validation Signed-off-by: shmck --- src/utils/args.ts | 68 ++++++++++++++++++++++++++++++++++------------ src/validate.ts | 24 +++++++++++++--- tests/args.test.ts | 29 +++++++++++++++++++- 3 files changed, 98 insertions(+), 23 deletions(-) diff --git a/src/utils/args.ts b/src/utils/args.ts index e9688c9..3a157fb 100644 --- a/src/utils/args.ts +++ b/src/utils/args.ts @@ -1,32 +1,64 @@ -type ArgValueParams = { name: string; alias?: string; param?: boolean }; +type ArgValueParams = { + name: string; + alias?: string; + type?: "string" | "bool" | "number"; +}; -const checkValue = ( +function checkValue( args: string[], string: string, - options: ArgValueParams -) => { + isBool: boolean +): string | null { const nameIndex = args.indexOf(string); - if (nameIndex > -1) { - if (options.param) { - const value = args[nameIndex + 1]; - if (!value) { - throw new Error(`Argument ${string} is missing a parameter value`); + if (nameIndex >= 0) { + const nextArg = args[nameIndex + 1]; + + if (nextArg !== undefined) { + const nextIsCommand = !!nextArg.match(/^\-/); + if (nextIsCommand) { + return isBool ? "true" : null; } - return value; + return nextArg; + } else { + // no secondary set value + return isBool ? "true" : null; } } return null; -}; +} -export function getArg(args: string[], options: ArgValueParams): string | null { - let value: null | string = null; +export function getArg( + args: string[], + options: ArgValueParams +): string | boolean | number | null { + let stringValue: null | string = null; + const isBool = options.type === "bool"; - const aliasString = `-${options.alias}`; - value = checkValue(args, aliasString, options); - if (!value) { + if (options.alias) { + const aliasString = `-${options.alias}`; + stringValue = checkValue(args, aliasString, isBool); + } + if (!stringValue) { const nameString = `--${options.name}`; - value = checkValue(args, nameString, options); + stringValue = checkValue(args, nameString, isBool); + } + + if (stringValue === null) { + return null; } - return value; + if (!options.type) { + options.type = "string"; + } + + // coerce type + switch (options.type) { + case "bool": + return (stringValue || "").toLowerCase() !== "false"; + case "number": + return Number(stringValue); + case "string": + default: + return stringValue; + } } diff --git a/src/validate.ts b/src/validate.ts index e5ed11e..ae0cf4b 100644 --- a/src/validate.ts +++ b/src/validate.ts @@ -10,17 +10,30 @@ import { } from "./utils/exec"; import { getCommits, CommitLogObject } from "./utils/commits"; +interface Options { + yaml: string; + clean: boolean; +} + async function validate(args: string[]) { // dir - default . const dir = !args.length || args[0].match(/^-/) ? "." : args[0]; const localDir = path.join(process.cwd(), dir); // -y --yaml - default coderoad-config.yml - const options = { - yaml: getArg(args, { name: "yaml", alias: "y" }) || "coderoad.yaml", + const options: Options = { + // @ts-ignore + yaml: + getArg(args, { name: "yaml", alias: "y", type: "string" }) || + "coderoad.yaml", + // @ts-ignore + clean: getArg(args, { name: "clean", alias: "c", type: "bool" }), }; - const _yaml = await fs.readFile(path.join(localDir, options.yaml), "utf8"); + const _yaml: string = await fs.readFile( + path.join(localDir, options.yaml), + "utf8" + ); // parse yaml config let skeleton; @@ -158,7 +171,10 @@ async function validate(args: string[]) { console.error(e.message); } finally { // cleanup - await fs.emptyDir(tmpDir); + console.log("options.clean", options.clean); + if (options.clean) { + await fs.emptyDir(tmpDir); + } } } diff --git a/tests/args.test.ts b/tests/args.test.ts index 454c0ae..8d687f4 100644 --- a/tests/args.test.ts +++ b/tests/args.test.ts @@ -21,6 +21,24 @@ describe("args", () => { const result = getArg(args, { name: "name", alias: "n" }); expect(result).toBe("value"); }); + it("should convert bool string to true", () => { + const args = ["--someBool", "true"]; + const result = getArg(args, { + name: "someBool", + alias: "sb", + type: "bool", + }); + expect(result).toBe(true); + }); + it("should convert bool string to false", () => { + const args = ["--someBool", "false"]; + const result = getArg(args, { + name: "someBool", + alias: "sb", + type: "bool", + }); + expect(result).toBe(false); + }); it("should default value to true if no next value", () => { const args = ["--someBool"]; const result = getArg(args, { @@ -30,7 +48,7 @@ describe("args", () => { }); expect(result).toBe(true); }); - it("should default value to true if next value is param", () => { + it("should default value to true if next value is --name", () => { const args = ["--someBool", "--someOtherBool"]; const result = getArg(args, { name: "someBool", @@ -39,4 +57,13 @@ describe("args", () => { }); expect(result).toBe(true); }); + it("should default value to true if next value is -alias", () => { + const args = ["--someBool", "-a"]; + const result = getArg(args, { + name: "someBool", + alias: "sb", + type: "bool", + }); + expect(result).toBe(true); + }); }); From ff789c48cd9e4991fae64876b8dfac5d88c9bbd4 Mon Sep 17 00:00:00 2001 From: shmck Date: Sat, 20 Jun 2020 11:41:34 -0700 Subject: [PATCH 3/4] log cherry-pick warnings Signed-off-by: shmck --- src/utils/exec.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/utils/exec.ts b/src/utils/exec.ts index a209b2d..1ebc29c 100644 --- a/src/utils/exec.ts +++ b/src/utils/exec.ts @@ -22,14 +22,18 @@ export function createCherryPick(cwd: string) { return async function cherryPick(commits: string[]): Promise { for (const commit of commits) { try { - const { stdout } = await createExec(cwd)( + const { stdout, stderr } = await createExec(cwd)( `git cherry-pick -X theirs ${commit}` ); + if (stderr) { + console.warn(stderr); + } if (!stdout) { console.warn(`No cherry-pick output for ${commit}`); } } catch (e) { console.warn(`Cherry-pick failed for ${commit}`); + console.error(e.message); } } }; @@ -50,6 +54,7 @@ export function createCommandRunner(cwd: string) { } const { stdout, stderr } = await createExec(cwdDir)(command); + console.log(stdout); console.warn(stderr); } catch (e) { console.error(`Command failed: "${command}"`); From ea6756f6b69dbd88d85d3a6f8c3af2ee67a71e2b Mon Sep 17 00:00:00 2001 From: shmck Date: Sat, 20 Jun 2020 11:43:47 -0700 Subject: [PATCH 4/4] add "clean" option to validate help Signed-off-by: shmck --- src/help.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/help.ts b/src/help.ts index dbf7c23..f61a301 100644 --- a/src/help.ts +++ b/src/help.ts @@ -47,6 +47,7 @@ Usage: coderoad validate [path] [options] Options: --help (-h) display these help docs +--clean (-c) set to false to preserve .tmp folder. Helpful for debugging More docs at https://github.com/coderoad/coderoad-cli`); }