Skip to content

Commit

Permalink
Merge 963bce6 into ba219da
Browse files Browse the repository at this point in the history
  • Loading branch information
rustdevbtw committed May 14, 2024
2 parents ba219da + 963bce6 commit bfcba30
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export default async function({ flags, ...opts }: Args, logger_prefix?: string)
case 'install':
try {
await ensure_pantry()
await install(await Promise.all(opts.args.map(x => parse_pkg_str(x, {latest: 'ok'}))))
await install(await Promise.all(opts.args.map(x => parse_pkg_str(x, {latest: 'ok'}))), flags.unsafe)
} catch (err) {
if (err instanceof AmbiguityError) {
err.ctx = 'install'
Expand Down
81 changes: 60 additions & 21 deletions src/modes/install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@ const { usePantry } = hooks

// * maybe impl `$XDG_BIN_HOME`

export default async function(pkgs: PackageRequirement[]) {
export function is_unsafe(unsafe: boolean): boolean {
// `--unsafe` takes precedence over the `$PKGX_UNSAFE_INSTALL` flag
const IS_UNSAFE = parseInt(Deno.env.get("PKGX_UNSAFE_INSTALL") || "0") ? true : unsafe
return IS_UNSAFE
}

export default async function(pkgs: PackageRequirement[], unsafe: boolean) {
const usrlocal = new Path("/usr/local/bin")
let n = 0

Expand All @@ -18,36 +24,73 @@ export default async function(pkgs: PackageRequirement[]) {
const bindir = Path.home().join(".local/bin")
await write(bindir, pkgs)
if (n > 0 && !Deno.env.get("PATH")?.split(":").includes(bindir.string)) {
console.warn("pkgx: %c`%s` is not in `PATH`", 'color: red', bindir)
console.warn("pkgx: %c`%s` is not in `PATH`", "color: red", bindir)
}
} else {
throw err
}
}

if (n == 0) {
console.error('pkgx: no programs provided by pkgs')
console.error("pkgx: no programs provided by pkgs")
}

async function write(dst: Path, pkgs: PackageRequirement[]) {
const UNSAFE = is_unsafe(unsafe)
for (const pkg of pkgs) {
const programs = await usePantry().project(pkg).provides()
program_loop:
for (const program of programs) {

// skip for now since we would require specific versions and we haven't really got that
if (program.includes("{{")) continue

const pkgstr = utils.pkg.str(pkg)
const exec = `exec pkgx +${pkgstr} -- ${program} "$@"`
const script = undent`
if [ "$PKGX_UNINSTALL" != 1 ]; then
${exec}
else
cd "$(dirname "$0")"
rm ${programs.join(' ')} && echo "uninstalled: ${pkgstr}" >&2
fi`
const f = dst.mkdir('p').join(program)

let script = ""

if (UNSAFE) {
const config = hooks.useConfig()
const parts = pkgstr.split("/")
parts.pop()
config.cache.join(`pkgx/envs/${parts.join("/")}`).mkdir("p")
//FIXME: doing `set -a` clears the args env
script = undent`
if [ "$PKGX_UNINSTALL" != 1 ]; then
ARGS="$*"
ENV_FILE="$\{XDG_CACHE_DIR:-$HOME/.cache\}/pkgx/envs/${pkgstr}.env"
PKGX_DIR="$\{PKGX_DIR:-$HOME/.pkgx\}"
pkgx_resolve() {
mkdir -p "$(dirname "$ENV_FILE")"
pkgx +${pkgstr} 1>"$ENV_FILE"
run
}
run() {
if test -e "$ENV_FILE" && test -e "$PKGX_DIR/${pkgstr}/v*/bin/${program}"; then
set -a
# shellcheck source=$ENV_FILE
. "$ENV_FILE"
set +a
exec "$PKGX_DIR/${pkgstr}/v*/bin/${program}" "$ARGS"
else
pkgx_resolve
fi
}
run
else
cd "$(dirname "$0")" || exit
rm ${programs.join(" ")} && echo "uninstalled: ${pkgstr}" >&2
fi`
} else {
const script = undent`
if [ "$PKGX_UNINSTALL" != 1 ]; then
exec pkgx +${pkgstr} -- ${program} "$@"
else
cd "$(dirname "$0")"
rm ${programs.join(" ")} && echo "uninstalled: ${pkgstr}" >&2
fi`
}
const f = dst.mkdir("p").join(program)

if (f.exists()) {
if (!f.isFile()) throw new PkgxError(`${f} already exists and is not a file`)
Expand All @@ -57,15 +100,11 @@ export default async function(pkgs: PackageRequirement[]) {

const lines = f.readLines()
const { value: shebang } = await lines.next()
if (shebang != "#!/bin/sh") {
throw new PkgxError(`${f} already exists and is not a pkgx installation`)
}
if (shebang != "#!/bin/sh") throw new PkgxError(`${f} already exists and is not a pkgx installation`)
while (true) {
const { value, done } = await lines.next()
if (done) {
throw new PkgxError(`${f} already exists and is not a pkgx installation`)
}
const found = value.match(/^\s*exec pkgx \+([^ ]+)/)?.[1]
if (done) throw new PkgxError(`${f} already exists and is not a pkgx installation`)
const found = value.match(/^\s*pkgx \+([^ ]+)/)?.[1]
if (found) {
n++
console.warn(`pkgx: already installed: ${blurple(program)} ${dim(`(${found})`)}`)
Expand All @@ -78,7 +117,7 @@ export default async function(pkgs: PackageRequirement[]) {
#!/bin/sh
${script}`
}).chmod(0o755)
console.error('pkgx: installed:', f)
console.error("pkgx: installed:", f)
n++
}
}
Expand Down
12 changes: 11 additions & 1 deletion src/modes/uninstall.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import parse_pkg_str from "../prefab/parse-pkg-str.ts"
import { hooks, PackageRequirement, Path, PkgxError } from "pkgx"
import { hooks, PackageRequirement, Path, PkgxError, utils } from "pkgx"

export default async function(pkgspecs: string[]) {
const pkgs = await Promise.all(pkgspecs.map(x => parse_pkg_str(x, {latest: 'ok'})))
Expand All @@ -11,6 +11,16 @@ export default async function(pkgspecs: string[]) {
async function uninstall(prefix: Path, pkgs: PackageRequirement[]) {
for (const pkg of pkgs) {
const programs = await hooks.usePantry().project(pkg).provides()
const pkgstr = utils.pkg.str(pkg)
const config = hooks.useConfig()
const parts = pkgstr.split("/")
parts.pop()
//FIXME: it removes the dir successfully. however, it still complains that it didn't delete that
try {
config.cache.join(`pkgx/envs/${parts.join("/")}`).rm({recursive: true})
} catch (e) {
console.warn(e);
}
for (const program of programs) {
const f = prefix.join(program)
if (f.isFile()) {
Expand Down
9 changes: 7 additions & 2 deletions src/parse-args.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ interface Flags {
sync: boolean
update: boolean
verbosity?: number
keepGoing: boolean
keepGoing: boolean,
unsafe: boolean
}

export default function(input: string[]): Args {
Expand All @@ -56,7 +57,8 @@ export default function(input: string[]): Args {
const flags: Flags = {
sync: false,
update: false,
keepGoing: false
keepGoing: false,
unsafe: false
}
let mode: string | undefined
let dryrun: boolean | undefined
Expand Down Expand Up @@ -89,6 +91,9 @@ export default function(input: string[]): Args {
case 'update':
flags.update = true
break
case 'unsafe':
flags.unsafe = true
break
case 'provides':
if (mode) throw new UsageError({msg: 'multiple modes specified'})
console.error("%cdeprecated: %cuse pkgx --provider instead", 'color: red', 'color: initial')
Expand Down

0 comments on commit bfcba30

Please sign in to comment.