Skip to content

Commit

Permalink
Work around Windows incompatibilities in shell-quote
Browse files Browse the repository at this point in the history
Fixes #143.

The nodejs library shell-quote does not escape Windows paths correctly.
An LGTM'd PR exists here[1]. Since we need it, we re-implement this for
Windows paths.

[1]: https://github.com/substack/node-shell-quote/pull/34/
  • Loading branch information
hausdorff committed Aug 22, 2018
1 parent 207f948 commit 8767f9e
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 21 deletions.
6 changes: 5 additions & 1 deletion Makefile
Expand Up @@ -49,12 +49,16 @@ install::
mkdir -p "$(PULUMI_NODE_MODULES)/$(NODE_MODULE_NAME)"
cp -r pack/nodejs/bin/. "$(PULUMI_NODE_MODULES)/$(NODE_MODULE_NAME)"
rm -rf "$(PULUMI_NODE_MODULES)/$(NODE_MODULE_NAME)/node_modules"
rm -rf "$(PULUMI_NODE_MODULES)/$(NODE_MODULE_NAME)/tests"
cd "$(PULUMI_NODE_MODULES)/$(NODE_MODULE_NAME)" && \
yarn install --offline --production && \
(yarn unlink > /dev/null 2>&1 || true) && \
yarn link

test_all::
test_fast::
./pack/nodejs/node_modules/mocha/bin/mocha ./pack/nodejs/bin/tests

test_all:: test_fast
PATH=$(PULUMI_BIN):$(PATH) $(GO) test -v -cover -timeout 1h -parallel ${TESTPARALLELISM} $(TESTABLE_PKGS)

.PHONY: publish_tgz
Expand Down
15 changes: 8 additions & 7 deletions pack/nodejs/helm.ts
Expand Up @@ -5,6 +5,7 @@ import * as k8s from "./index";
import * as pulumi from "@pulumi/pulumi";
import * as shell from "shell-quote";
import * as tmp from "tmp";
import * as path from "./path";

export namespace v2 {
export interface ChartOpts {
Expand Down Expand Up @@ -142,16 +143,16 @@ export function fetch(chart: string, opts?: FetchOpts) {
if(opts.untar !== false) { flags.push(`--untar`); }

if (opts.version !== undefined) { flags.push(`--version ${shell.quote([opts.version])}`); }
if (opts.caFile !== undefined) { flags.push(`--ca-file ${shell.quote([opts.caFile])}`); }
if (opts.certFile !== undefined) { flags.push(`--cert-file ${shell.quote([opts.certFile])}`); }
if (opts.keyFile !== undefined) { flags.push(`--key-file ${shell.quote([opts.keyFile])}`); }
if (opts.destination !== undefined) { flags.push(`--destination ${shell.quote([opts.destination])}`); }
if (opts.keyring !== undefined) { flags.push(`--keyring ${shell.quote([opts.keyring])}`); }
if (opts.caFile !== undefined) { flags.push(`--ca-file ${path.quotePath(opts.caFile)}`); }
if (opts.certFile !== undefined) { flags.push(`--cert-file ${path.quotePath(opts.certFile)}`); }
if (opts.keyFile !== undefined) { flags.push(`--key-file ${path.quotePath(opts.keyFile)}`); }
if (opts.destination !== undefined) { flags.push(`--destination ${path.quotePath(opts.destination)}`); }
if (opts.keyring !== undefined) { flags.push(`--keyring ${path.quotePath(opts.keyring)}`); }
if (opts.password !== undefined) { flags.push(`--password ${shell.quote([opts.password])}`); }
if (opts.repo !== undefined) { flags.push(`--repo ${shell.quote([opts.repo])}`); }
if (opts.untardir !== undefined) { flags.push(`--untardir ${shell.quote([opts.untardir])}`); }
if (opts.untardir !== undefined) { flags.push(`--untardir ${path.quotePath(opts.untardir)}`); }
if (opts.username !== undefined) { flags.push(`--username ${shell.quote([opts.username])}`); }
if (opts.home !== undefined) { flags.push(`--home ${shell.quote([opts.home])}`); }
if (opts.home !== undefined) { flags.push(`--home ${path.quotePath(opts.home)}`); }
if (opts.devel === true) { flags.push(`--devel`); }
if (opts.prov === true) { flags.push(`--prov`); }
if (opts.verify === true) { flags.push(`--verify`); }
Expand Down
4 changes: 3 additions & 1 deletion pack/nodejs/package.json
Expand Up @@ -20,7 +20,9 @@
"tmp": "^0.0.33",
"@types/tmp": "^0.0.33",
"glob": "^7.1.2",
"@types/glob": "^5.0.35"
"@types/glob": "^5.0.35",
"mocha": "^5.2.0",
"@types/mocha": "^5.2.5"
},
"devDependencies": {
"typescript": "^2.6.2",
Expand Down
19 changes: 19 additions & 0 deletions pack/nodejs/path.ts
@@ -0,0 +1,19 @@
import * as shell from "shell-quote";

export function quotePath(path: string): string {
if (process.platform === "win32") {
return quoteWindowsPath(path);
} else {
return shell.quote([path]);
}
}

export function quoteWindowsPath(path: string): string {
// Unescape paths for Windows. Taken directly from[1], an unmerged, but LGTM'd PR to the
// official library.
//
// [1]: https://github.com/substack/node-shell-quote/pull/34

path = String(path).replace(/([A-z]:)?([#!"$&'()*,:;<=>?@\[\\\]^`{|}])/g, "$1\\$2");
return path.replace(/\\\\/g, "\\");
}
17 changes: 17 additions & 0 deletions pack/nodejs/tests/path.ts
@@ -0,0 +1,17 @@
import * as assert from "assert";
import * as path from "../path";

describe("path.quoteWindowsPath", () => {
it("escapes Windows path with drive prefix correctly", () => {
const p = path.quoteWindowsPath("C:\\Users\\grace hopper\\AppData\\Local\\Temp");
assert.equal(p, "C:\\Users\\grace hopper\\AppData\\Local\\Temp");
});
it("escapes Windows path with no drive prefix correctly", () => {
const p = path.quoteWindowsPath("\\Users\\grace hopper\\AppData\\Local\\Temp");
assert.equal(p, "\\Users\\grace hopper\\AppData\\Local\\Temp");
});
it("escapes relative Windows path correctly", () => {
const p = path.quoteWindowsPath("Users\\grace hopper\\AppData\\Local\\Temp");
assert.equal(p, "Users\\grace hopper\\AppData\\Local\\Temp");
});
});
64 changes: 60 additions & 4 deletions pack/nodejs/yarn.lock
Expand Up @@ -83,6 +83,10 @@
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"

"@types/mocha@^5.2.5":
version "5.2.5"
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.5.tgz#8a4accfc403c124a0bafe8a9fc61a05ec1032073"

"@types/node@*":
version "10.5.8"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.5.8.tgz#6f14ccecad1d19332f063a6a764f8907801fece0"
Expand Down Expand Up @@ -166,6 +170,10 @@ brace-expansion@^1.1.7:
balanced-match "^1.0.0"
concat-map "0.0.1"

browser-stdout@1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"

buffer-from@^1.0.0, buffer-from@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
Expand Down Expand Up @@ -204,6 +212,10 @@ colour@~0.7.1:
version "0.7.1"
resolved "https://registry.yarnpkg.com/colour/-/colour-0.7.1.tgz#9cb169917ec5d12c0736d3e8685746df1cadf778"

commander@2.15.1:
version "2.15.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"

concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
Expand All @@ -216,6 +228,12 @@ core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"

debug@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
dependencies:
ms "2.0.0"

debug@^2.1.2:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
Expand Down Expand Up @@ -249,10 +267,14 @@ dezalgo@^1.0.0:
asap "^2.0.0"
wrappy "1"

diff@^3.1.0:
diff@3.5.0, diff@^3.1.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"

escape-string-regexp@1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"

esprima@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
Expand Down Expand Up @@ -280,7 +302,7 @@ gauge@~2.7.3:
strip-ansi "^3.0.1"
wide-align "^1.1.0"

glob@^7.0.5, glob@^7.1.1, glob@^7.1.2:
glob@7.1.2, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2:
version "7.1.2"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
dependencies:
Expand All @@ -299,6 +321,10 @@ graceful-fs@^4.1.2:
version "4.1.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"

growl@1.10.5:
version "1.10.5"
resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e"

grpc@^1.12.2:
version "1.14.0"
resolved "https://registry.yarnpkg.com/grpc/-/grpc-1.14.0.tgz#5aea131ef078285eff543301b99ba994e4db2c73"
Expand All @@ -308,10 +334,18 @@ grpc@^1.12.2:
node-pre-gyp "^0.10.0"
protobufjs "^5.0.3"

has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"

has-unicode@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"

he@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"

hosted-git-info@^2.1.4:
version "2.7.1"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047"
Expand Down Expand Up @@ -404,7 +438,7 @@ make-error@^1.1.1:
version "1.3.4"
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.4.tgz#19978ed575f9e9545d2ff8c13e33b5d18a67d535"

minimatch@^3.0.4:
minimatch@3.0.4, minimatch@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
dependencies:
Expand All @@ -431,12 +465,28 @@ minizlib@^1.1.0:
dependencies:
minipass "^2.2.1"

mkdirp@^0.5.0, mkdirp@^0.5.1:
mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
dependencies:
minimist "0.0.8"

mocha@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6"
dependencies:
browser-stdout "1.3.1"
commander "2.15.1"
debug "3.1.0"
diff "3.5.0"
escape-string-regexp "1.0.5"
glob "7.1.2"
growl "1.10.5"
he "1.1.1"
minimatch "3.0.4"
mkdirp "0.5.1"
supports-color "5.4.0"

ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
Expand Down Expand Up @@ -760,6 +810,12 @@ strip-json-comments@~2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"

supports-color@5.4.0:
version "5.4.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54"
dependencies:
has-flag "^3.0.0"

tar@^4:
version "4.4.6"
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.6.tgz#63110f09c00b4e60ac8bcfe1bf3c8660235fbc9b"
Expand Down
15 changes: 8 additions & 7 deletions pkg/gen/node-templates/helm.ts.mustache
Expand Up @@ -5,6 +5,7 @@ import * as k8s from "./index";
import * as pulumi from "@pulumi/pulumi";
import * as shell from "shell-quote";
import * as tmp from "tmp";
import * as path from "./path";

export namespace v2 {
export interface ChartOpts {
Expand Down Expand Up @@ -142,16 +143,16 @@ export function fetch(chart: string, opts?: FetchOpts) {
if(opts.untar !== false) { flags.push(`--untar`); }
if (opts.version !== undefined) { flags.push(`--version ${shell.quote([opts.version])}`); }
if (opts.caFile !== undefined) { flags.push(`--ca-file ${shell.quote([opts.caFile])}`); }
if (opts.certFile !== undefined) { flags.push(`--cert-file ${shell.quote([opts.certFile])}`); }
if (opts.keyFile !== undefined) { flags.push(`--key-file ${shell.quote([opts.keyFile])}`); }
if (opts.destination !== undefined) { flags.push(`--destination ${shell.quote([opts.destination])}`); }
if (opts.keyring !== undefined) { flags.push(`--keyring ${shell.quote([opts.keyring])}`); }
if (opts.caFile !== undefined) { flags.push(`--ca-file ${path.quotePath(opts.caFile)}`); }
if (opts.certFile !== undefined) { flags.push(`--cert-file ${path.quotePath(opts.certFile)}`); }
if (opts.keyFile !== undefined) { flags.push(`--key-file ${path.quotePath(opts.keyFile)}`); }
if (opts.destination !== undefined) { flags.push(`--destination ${path.quotePath(opts.destination)}`); }
if (opts.keyring !== undefined) { flags.push(`--keyring ${path.quotePath(opts.keyring)}`); }
if (opts.password !== undefined) { flags.push(`--password ${shell.quote([opts.password])}`); }
if (opts.repo !== undefined) { flags.push(`--repo ${shell.quote([opts.repo])}`); }
if (opts.untardir !== undefined) { flags.push(`--untardir ${shell.quote([opts.untardir])}`); }
if (opts.untardir !== undefined) { flags.push(`--untardir ${path.quotePath(opts.untardir)}`); }
if (opts.username !== undefined) { flags.push(`--username ${shell.quote([opts.username])}`); }
if (opts.home !== undefined) { flags.push(`--home ${shell.quote([opts.home])}`); }
if (opts.home !== undefined) { flags.push(`--home ${path.quotePath(opts.home)}`); }
if (opts.devel === true) { flags.push(`--devel`); }
if (opts.prov === true) { flags.push(`--prov`); }
if (opts.verify === true) { flags.push(`--verify`); }
Expand Down
4 changes: 3 additions & 1 deletion pkg/gen/node-templates/package.json.mustache
Expand Up @@ -20,7 +20,9 @@
"tmp": "^0.0.33",
"@types/tmp": "^0.0.33",
"glob": "^7.1.2",
"@types/glob": "^5.0.35"
"@types/glob": "^5.0.35",
"mocha": "^5.2.0",
"@types/mocha": "^5.2.5"
},
"devDependencies": {
"typescript": "^2.6.2",
Expand Down

0 comments on commit 8767f9e

Please sign in to comment.