Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

+windows #823

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 3 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,11 @@ jobs:
os:
- ubuntu-latest
- macos-latest
- windows-latest
steps:
- run: echo 'TMPDIR=/tmp' >> $GITHUB_ENV
if: ${{ matrix.os == 'ubuntu-latest' }}

- uses: actions/checkout@v4
- uses: denoland/setup-deno@v1 # using ourself to install deno could compromise the tests
- run: deno cache **/*.test.ts
- uses: denoland/setup-deno@v1 # using ourself to install deno could compromise the tests
- run: deno task test:cache
- run: deno task test --coverage=cov_profile --no-check
- run: deno coverage cov_profile --lcov --exclude=tests/ --output=cov_profile.lcov
- uses: coverallsapp/github-action@v2
Expand Down
15 changes: 6 additions & 9 deletions deno.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"run": "deno run --unstable -A ./entrypoint.ts",

// you can specify paths to specific tests if you need
"test": "deno test --allow-read=$PWD,$TMPDIR,$HOME,/ --allow-env --allow-write=$TMPDIR --allow-ffi --unstable",
"test": "deno test --allow-read --allow-env --allow-write=$(deno run --allow-env scripts/get-tmp.ts) --allow-ffi --unstable",
// ^^ ffi & unstable needed for execve.ts

// installs to /usr/local/bin/pkgx
Expand All @@ -17,13 +17,10 @@
//--------------------------------------- ci/cd/admin
"coverage" : "scripts/run-coverage.sh",
"typecheck": "deno check --unstable ./entrypoint.ts",
"compile": "deno compile --lock=deno.lock --allow-read --allow-write --allow-net --allow-run --allow-env --allow-ffi --unstable --output $INIT_CWD/pkgx ./entrypoint.ts"
},
"pkgx": {
"dependencies": {
"deno.land": "^1.33.3"
}
"compile": "deno compile --lock=deno.lock --allow-read --allow-write --allow-net --allow-run --allow-env --allow-ffi --unstable --output $INIT_CWD/pkgx ./entrypoint.ts",
"test:cache": "deno cache **/*.test.ts"
},
"pkgx": "deno.land^1.33.3",
"lint": {
"exclude": ["src/**/*.test.ts"]
},
Expand All @@ -32,8 +29,8 @@
},
"imports": {
"is-what": "https://deno.land/x/is_what@v4.1.15/src/index.ts",
"pkgx": "https://deno.land/x/libpkgx@v0.15.0/mod.ts",
"pkgx/": "https://deno.land/x/libpkgx@v0.15.0/src/",
"pkgx": "https://deno.land/x/libpkgx@v0.15.1/mod.ts",
"pkgx/": "https://deno.land/x/libpkgx@v0.15.1/src/",
"outdent": "https://deno.land/x/outdent@v0.8.0/mod.ts",
"cliffy/": "https://deno.land/x/cliffy@v1.0.0-rc.3/",
"deno/": "https://deno.land/std@0.204.0/"
Expand Down
46 changes: 46 additions & 0 deletions deno.lock
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,25 @@
"https://deno.land/std@0.204.0/assert/unreachable.ts": "4600dc0baf7d9c15a7f7d234f00c23bca8f3eba8b140286aaca7aa998cf9a536",
"https://deno.land/std@0.204.0/bytes/concat.ts": "d26d6f3d7922e6d663dacfcd357563b7bf4a380ce5b9c2bbe0c8586662f25ce2",
"https://deno.land/std@0.204.0/bytes/copy.ts": "939d89e302a9761dcf1d9c937c7711174ed74c59eef40a1e4569a05c9de88219",
"https://deno.land/std@0.204.0/crypto/_fnv/fnv32.ts": "e4649dfdefc5c987ed53c3c25db62db771a06d9d1b9c36d2b5cf0853b8e82153",
"https://deno.land/std@0.204.0/crypto/_fnv/fnv64.ts": "bfa0e4702061fdb490a14e6bf5f9168a22fb022b307c5723499469bfefca555e",
"https://deno.land/std@0.204.0/crypto/_fnv/mod.ts": "f956a95f58910f223e420340b7404702ecd429603acd4491fa77af84f746040c",
"https://deno.land/std@0.204.0/crypto/_fnv/util.ts": "accba12bfd80a352e32a872f87df2a195e75561f1b1304a4cb4f5a4648d288f9",
"https://deno.land/std@0.204.0/crypto/_wasm/lib/deno_std_wasm_crypto.generated.mjs": "e0e4f9952f7ad3cbcc63a04e49865e7f6355cb830c593c3f5a3fc731bebbfa7d",
"https://deno.land/std@0.204.0/crypto/_wasm/mod.ts": "c4386f0ee80968faa82079cc21066aba2147bd6ca74ae45f1478fca7dbca804a",
"https://deno.land/std@0.204.0/crypto/crypto.ts": "e040c130e22b6c8b416bf4073be1cc94c53c57a2a29f75ce8c29c37745d13cc3",
"https://deno.land/std@0.204.0/crypto/keystack.ts": "cec9ddf60e0c0c9970360e66c9402afb3c0c68bcd50ef19c68daf63f94e40863",
"https://deno.land/std@0.204.0/crypto/mod.ts": "ae384519e85eca9aeff4e7111ed153df8f3dbda7b35b70850ed4b3e9c8cec4d5",
"https://deno.land/std@0.204.0/crypto/timing_safe_equal.ts": "f6edc08d702f660b1ab3505b74d53a9d499e34a1351f6ab70f5ce8653fee8fb7",
"https://deno.land/std@0.204.0/crypto/to_hash_string.ts": "c78050f72a9d4a690d85e83a85a43c2951d23a04d5b2a4537b2ebc00854421be",
"https://deno.land/std@0.204.0/crypto/unstable/keystack.ts": "624c2f2d8fa6711d44fcb8fbca346e7fb56afa7aa3fcf2d8e6db32978e9fbac2",
"https://deno.land/std@0.204.0/encoding/_util.ts": "f368920189c4fe6592ab2e93bd7ded8f3065b84f95cd3e036a4a10a75649dcba",
"https://deno.land/std@0.204.0/encoding/base64.ts": "cc03110d6518170aeaa68ec97f89c6d6e2276294b30807e7332591d7ce2e4b72",
"https://deno.land/std@0.204.0/encoding/base64url.ts": "7608862858d28a003f9d6cb78dd61e645ecd1ae1f45faf0e09a306eafe66b16e",
"https://deno.land/std@0.204.0/encoding/hex.ts": "d41e9c3f7dd9d4738c40c2b9e6db5eb32e9dc103360291aff63a5c3fccdb45a6",
"https://deno.land/std@0.204.0/fmt/colors.ts": "c51c4642678eb690dcf5ffee5918b675bf01a33fba82acf303701ae1a4f8c8d9",
"https://deno.land/std@0.204.0/fs/_util.ts": "fbf57dcdc9f7bc8128d60301eece608246971a7836a3bb1e78da75314f08b978",
"https://deno.land/std@0.204.0/fs/move.ts": "b4f8f46730b40c32ea3c0bc8eb0fd0e8139249a698883c7b3756424cf19785c9",
"https://deno.land/std@0.204.0/io/buf_reader.ts": "f7a43953b05eecbaea56ebcb654035bc91e117d6986a0b2d346c1d0de1d4dac4",
"https://deno.land/std@0.204.0/io/buffer.ts": "2108faba32659e5a390bb59b1b4578ff0120b185d9310dd6fbf3b3a3d5775715",
"https://deno.land/std@0.204.0/io/read_lines.ts": "8d09daed983812ef4cee6e5333633e789673aeecbe109da09d281d4ceaf75d5c",
Expand Down Expand Up @@ -406,6 +424,34 @@
"https://deno.land/x/libpkgx@v0.15.0/src/utils/misc.ts": "a4d7944da07066e5dd2ef289af436dc7f1032aed4272811e9b19ceeed60b8491",
"https://deno.land/x/libpkgx@v0.15.0/src/utils/pkg.ts": "5ef9cc1955a5067489ac4d2af8615652505cb17a48745e811cb786ab89377547",
"https://deno.land/x/libpkgx@v0.15.0/src/utils/semver.ts": "defa0cc3f08059189d47e5c3600c640fdf16cc555c7c81c3b72de5d1f4180307",
"https://deno.land/x/libpkgx@v0.15.1/mod.ts": "14a69905ffad8064444c02d146008efeb6a0ddf0fe543483839af18e01684f5a",
"https://deno.land/x/libpkgx@v0.15.1/src/deps.ts": "6ce708d6ceed8617b7de363421f478aa48d913dc3d2b9b0fe67c7b9eef779213",
"https://deno.land/x/libpkgx@v0.15.1/src/hooks/useCache.ts": "9f3cc576fabae2caa6aedbf00ab12a59c732be1315471e5a475fef496c1e35ae",
"https://deno.land/x/libpkgx@v0.15.1/src/hooks/useCellar.ts": "c1e264fcb732423734f8c113fc7cb80c97befe8f13ed9d24906328bc5526c72d",
"https://deno.land/x/libpkgx@v0.15.1/src/hooks/useConfig.ts": "0fdb66b8e6f2827b2028f782df680482f5f1de2b708362f348c52d81e8debb48",
"https://deno.land/x/libpkgx@v0.15.1/src/hooks/useDownload.ts": "62b2043fcbc06a0925eb06fc5ed5f2f2ef3779e8ce10bc44b0163e9bd9b8cbc0",
"https://deno.land/x/libpkgx@v0.15.1/src/hooks/useFetch.ts": "ecf29342210b8eceed216e3bb73fcc7ea5b3ea5059686cf344ed190ca42ff682",
"https://deno.land/x/libpkgx@v0.15.1/src/hooks/useInventory.ts": "39b022ee12443bb0bc6c8755eda860a227dba131a439ea0e043bae6132ece34b",
"https://deno.land/x/libpkgx@v0.15.1/src/hooks/useMoustaches.ts": "417aeabd35096fd81c05b71b151b92049add2d3ead5036e0063b8c10ee682863",
"https://deno.land/x/libpkgx@v0.15.1/src/hooks/useOffLicense.ts": "9a7a35bd83a8dbb5a25d532e2ab885b5fb77101cc38fad10c5f3ea6a49a24e02",
"https://deno.land/x/libpkgx@v0.15.1/src/hooks/usePantry.ts": "7535fb2bb9997fcb08f150381ca713b340c2db4742020908a5dbbe906d630e6a",
"https://deno.land/x/libpkgx@v0.15.1/src/hooks/useShellEnv.ts": "14d29f23b8e256590318cfd5fb840955038429c4cac8f71dfbf8deb46b7d88ec",
"https://deno.land/x/libpkgx@v0.15.1/src/hooks/useSync.ts": "c098321da6c59126a3b8150bcea5e6fc43348c00810ba6db88ce4f5de0fdb556",
"https://deno.land/x/libpkgx@v0.15.1/src/plumbing/hydrate.ts": "74f295585c4760005cc7676db9f3d9eb67d92b78e197e02445f42823d1643884",
"https://deno.land/x/libpkgx@v0.15.1/src/plumbing/install.ts": "19244fb150e80a0bbbed90e4a3f47e2c5aa3e0919ff060cec1db0b789730b560",
"https://deno.land/x/libpkgx@v0.15.1/src/plumbing/link.ts": "acb98bf014414208f14c5f57fa36e2aa66ae9bee69d763120c3ddb656e244063",
"https://deno.land/x/libpkgx@v0.15.1/src/plumbing/resolve.ts": "9425e0d201ee440a8dc011940046f0bb6d94aa29cd738e1a8c39ca86e55aad41",
"https://deno.land/x/libpkgx@v0.15.1/src/plumbing/which.ts": "24778f645c9aaea67df51b671474fffe01c1d3b188552943e24d61d51fa6b80d",
"https://deno.land/x/libpkgx@v0.15.1/src/porcelain/install.ts": "6e41d94226b8eb33a9fbb591e5ddd95e2c5e0c2449cc617ac5f365746d1e4592",
"https://deno.land/x/libpkgx@v0.15.1/src/porcelain/run.ts": "20c60bebeca51daf12d9e5baefe8670844162308734f8a189a1f484c4155d671",
"https://deno.land/x/libpkgx@v0.15.1/src/types.ts": "dc1a4e6458d11454282f832909838c56f786a26eed54fb8ab5675d6691ebf534",
"https://deno.land/x/libpkgx@v0.15.1/src/utils/Path.ts": "72bbb8afa6a40e3cfbf01d4d9069e0818e7abaf0021703a20b0677f06c01e883",
"https://deno.land/x/libpkgx@v0.15.1/src/utils/error.ts": "b0d3130f5cdfc0cc8ea10f93fea0e7e97d4473ddc9bc527156b0fcf24c7b939c",
"https://deno.land/x/libpkgx@v0.15.1/src/utils/flock.deno.ts": "f91792244734befb21c1caa10ac4908694dd37b44f0e9748c78c4f1aa003eb7a",
"https://deno.land/x/libpkgx@v0.15.1/src/utils/host.ts": "3b9e0d4cb05f9bde0ee8bcb0f8557b0a339f6ef56dfb1f08b2cfa63b44db91ee",
"https://deno.land/x/libpkgx@v0.15.1/src/utils/misc.ts": "a4d7944da07066e5dd2ef289af436dc7f1032aed4272811e9b19ceeed60b8491",
"https://deno.land/x/libpkgx@v0.15.1/src/utils/pkg.ts": "5ef9cc1955a5067489ac4d2af8615652505cb17a48745e811cb786ab89377547",
"https://deno.land/x/libpkgx@v0.15.1/src/utils/semver.ts": "defa0cc3f08059189d47e5c3600c640fdf16cc555c7c81c3b72de5d1f4180307",
"https://deno.land/x/outdent@v0.8.0/mod.ts": "72630e680dcc36d5ae556fbff6900b12706c81a6fd592345fc98bcc0878fb3ca",
"https://deno.land/x/outdent@v0.8.0/src/index.ts": "6dc3df4108d5d6fedcdb974844d321037ca81eaaa16be6073235ff3268841a22",
"https://deno.land/x/semver@v1.4.1/mod.ts": "0b79c87562eb8a1f008ab0d98f8bb60076dd65bc06f1f8fdfac2d2dab162c27b",
Expand Down
3 changes: 3 additions & 0 deletions scripts/get-tmp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const { TMP, TMPDIR } = Deno.env.toObject()
const { os } = Deno.build
console.log(TMP || TMPDIR || (os == 'windows' ? 'c:\\windows\\temp' : '/tmp'))
15 changes: 14 additions & 1 deletion src/modes/internal.activate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default async function(dir: Path, { powder, ...opts }: { powder: PackageR
}

/// indicate to our shell scripts that this devenv is activated
const persistence = datadir().join("dev", dir.string.slice(1)).mkdir('p').join("dev.pkgx.activated").touch()
const persistence = datadir().join("dev", stem(dir)).mkdir('p').join("dev.pkgx.activated").touch()

const installations = await install(pkgs, { update: false, ...opts })
const env = await construct_env(installations)
Expand Down Expand Up @@ -136,3 +136,16 @@ export const _internals = {
getenv: Deno.env.get,
apply_userenv
}

function stem(path: Path) {
if (Deno.build.os == 'windows') {
const str = path.string
if (/^[a-zA-Z]:/.test(str)) {
return str.slice(0, 1) + "/" + str.slice(2)
} else {
return str // network drive
}
} else {
return path.string.slice(1)
}
}
8 changes: 4 additions & 4 deletions src/modes/run.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Deno.test("run.ts", async runner => {
return { installations, pkgenv: [] }
})
const stub4 = mock.stub(_internals, "construct_env", () => (Promise.resolve({})))
const stub5 = mock.stub(_internals, "chdir", dir => assertEquals(dir, "/opt/foo.com/v2.3.4"))
const stub5 = mock.stub(_internals, "chdir", dir => assertEquals(dir, new Path("/opt/foo.com/v2.3.4").string))
const stub6 = stub_execve(args)

try {
Expand Down Expand Up @@ -52,11 +52,11 @@ Deno.test("run.ts", async runner => {
}
})

await runner.step("coverage++", () => {
await runner.step("coverage++", async () => {
if (hooks.usePantry().missing()) {
assertThrows(() => _internals.get_entrypoint({project: "github.com/ggerganov/llama.cpp"}))
await assertRejects(async () => await _internals.get_entrypoint({project: "github.com/ggerganov/llama.cpp"}))
} else {
_internals.get_entrypoint({project: "github.com/ggerganov/llama.cpp"})
await _internals.get_entrypoint({project: "github.com/ggerganov/llama.cpp"})
}
})
})
Expand Down
13 changes: 11 additions & 2 deletions src/modes/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,27 @@ export default async function(args: string[], opts: {

chdir(path!.string)

exec({ cmd: args, env })
await exec({ cmd: args, env })
}

export const _internals = {
install,
exec: execve,
exec,
parse_pkg_str,
construct_env,
chdir: Deno.chdir,
get_entrypoint: (pkg: { project: string }) => hooks.usePantry().project(pkg).yaml().then(x => x?.['entrypoint'])
}

function exec({ cmd, env }: {cmd: string[], env: Record<string, string>}) {
if (Deno.build.os == 'windows') {
// deno-lint-ignore no-deprecated-deno-api
return Deno.run({ cmd, env, stdout: 'inherit', stderr: 'inherit' }).status()
} else {
return execve({ cmd, env })
}
}

export class NoEntrypointError extends PkgxError {
constructor(pkg: {project: string}) {
super(`no entrypoint for: ${pkg.project}`)
Expand Down
2 changes: 1 addition & 1 deletion src/modes/x.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ Deno.test("x.ts", async runner => {
const stub2 = mock.stub(_internals, "useSync", async () => { fail() })
try {
await assertRejects(
() => specimen({args: ["/foo/bar"], ...opts}),
() => specimen({args: [Path.root.join("/foo/bar").string], ...opts}),
PkgxError)
} finally {
stub1.restore()
Expand Down
3 changes: 2 additions & 1 deletion src/modes/x.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import resolve_arg0 from "../prefab/resolve-arg0.ts"
import { ProvidesError } from "../utils/error.ts"
import get_shebang from "../utils/get-shebang.ts"
import execve from "../utils/execve.ts"
import { SEP } from "deno/path/mod.ts"
import host from "pkgx/utils/host.ts"
const { usePantry, useSync } = hooks

Expand Down Expand Up @@ -60,7 +61,7 @@ export function barf(fn: () => Error): never {
}

async function find_it(args: string[], dry: PackageRequirement[]) {
if (args[0].includes('/')) {
if (args[0].includes(SEP)) {
return await find_file(args, dry) ?? barf(() => new PkgxError(`no such file: ${args[0]}`))
}

Expand Down
5 changes: 3 additions & 2 deletions src/parse-args.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,11 @@ Deno.test("parse_args.ts", async runner => {
})

await runner.step("--internal.activate", () => {
const args = ['/foo/bar', ...faker_args()]
const arg0 = Deno.build.os == 'windows' ? "C:\\foo\\bar" : "/foo/bar"
const args = [arg0, ...faker_args()]
const rv = parse_args(['--internal.activate', ...args])
if (rv.mode != 'internal.activate') fail()
assertEquals(rv.dir.string, args[0])
assertEquals(rv.dir.string, arg0)
})

await runner.step("multiple modes", () => {
Expand Down
8 changes: 4 additions & 4 deletions src/prefab/construct-env.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { assertEquals, assertThrows } from "deno/assert/mod.ts"
import { assertEquals, assertRejects, assertThrows } from "deno/assert/mod.ts"
import specimen, { _internals } from "./construct-env.ts"
import { Path, SemVer, semver, hooks } from "pkgx"
import * as mock from "deno/testing/mock.ts"
Expand Down Expand Up @@ -34,12 +34,12 @@ Deno.test("construct_env.ts", async runner => {
}
})

await runner.step("coverage++", () => {
await runner.step("coverage++", async () => {
const pkg = { project: "bytereef.org/mpdecimal", version: new SemVer("2.1.2") }
if (hooks.usePantry().missing()) {
assertThrows(() => _internals.runtime_env(pkg, []))
await assertRejects(async () => await _internals.runtime_env(pkg, []))
} else {
_internals.runtime_env(pkg, [])
await _internals.runtime_env(pkg, [])
}
})
})
103 changes: 103 additions & 0 deletions src/utils/execve.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { assertThrows } from "deno/assert/assert_throws.ts"
import execve, { _internals } from "./execve.ts"
import faker, { faker_args } from "./test-utils.ts"
import * as mock from "deno/testing/mock.ts"
import { Path } from "pkgx"

Deno.test({
name: "execve.ts",
ignore: Deno.build.os == "windows", // windows has no equivalent to execve
async fn(runner) {
await runner.step("happy path", () => {
const stub = mock.stub(_internals, "execve", () => { return 0 })
try {
assertThrows(
() => execve({ cmd: faker_args(), env: {} }),
"execve (0)"
)
} finally {
stub.restore()
}
})

await runner.step("relative path", () => {
const stub = mock.stub(_internals, "execve", () => { return 0 })
try {
assertThrows(
() => execve({ cmd: ["./ls"], env: {} }),
"execve (0)"
)
} finally {
stub.restore()
}
})

await runner.step("PATH parser", async () => {
const stub = mock.stub(_internals, "execve", () => { return 0 })
const file = new Path(await Deno.makeTempFile()).chmod(0o700)
try {
assertThrows(
() => execve({ cmd: [file.basename()], env: {PATH: `.:~:~/foo:${file.parent()}`, "HOME": "/home/test"} }),
"execve (0)"
)
} finally {
file.rm()
stub.restore()
}
})


await runner.step("file doesn’t exist", () => {
assertThrows(
() => execve({ cmd: faker_args(), env: {} }),
Deno.errors.NotFound
)
})

await runner.step("file is not executable", () => {
const args = faker_args()
const f = Path.mktemp().join(args[0]).touch()
args[0] = f.string

assertThrows(
() => execve({ cmd: args, env: {} }),
Deno.errors.PermissionDenied
)
})

await runner.step("no working directory", () => {
const stub = mock.stub(_internals, "getcwd", () => { throw new Error() })
try {
assertThrows(() => execve({ cmd: ["foo", ...faker_args()], env: {} }))
} finally {
stub.restore()
}
})

const thisfile = new Path(new URL(import.meta.url).pathname)

await runner.step("file exists but is not executable", () => {
const cmd = [thisfile.string, ...faker_args()]
assertThrows(
() => execve({ cmd, env: {} }),
Deno.errors.PermissionDenied
)
})

await runner.step("file exists but is a directory", () => {
const cmd = [thisfile.parent().string, ...faker_args()]
assertThrows(
() => execve({ cmd, env: {} }),
Deno.errors.PermissionDenied
)
})

await runner.step("ENAMETOOLONG", () => {
const cmd = [faker.string.alphanumeric({length: 1024*5})]
assertThrows(
() => execve({ cmd, env: {} }),
"execve (63)"
)
})
}
})