1- #!/usr/bin/env -S pkgx --quiet deno^2.1 run --ext=ts --allow-sys=uid --allow-run --allow-env=PKGX_DIR,HOMEBREW_PREFIX,HOME --allow-read=/usr/local/pkgs
1+ #!/usr/bin/env -S pkgx --quiet deno^2.1 run --ext=ts --allow-sys=uid --allow-run --allow-env=PKGX_DIR,HOMEBREW_PREFIX,HOME --allow-read=/usr/local/pkgs,${HOME}/.local/pkgs
22import { dirname , fromFileUrl , join } from "jsr:@std/path@^1" ;
33import { ensureDir , existsSync } from "jsr:@std/fs@^1" ;
44import { parseArgs } from "jsr:@std/cli@^1" ;
@@ -46,7 +46,11 @@ if (parsedArgs.help) {
4646 switch ( parsedArgs . _ [ 0 ] ) {
4747 case "install" :
4848 case "i" :
49- await install ( args ) ;
49+ await install ( args , "/usr/local" ) ;
50+ break ;
51+ case "local-install" :
52+ case "li" :
53+ await install ( args , `${ Deno . env . get ( "HOME" ) ! } /.local` ) ;
5054 break ;
5155 case "uninstall" :
5256 case "rm" :
@@ -61,12 +65,12 @@ if (parsedArgs.help) {
6165 Deno . exit ( 1 ) ;
6266 break ;
6367 case "sudo-install" : {
64- const [ pkgx_dir , runtime_env , ...paths ] = args ;
68+ const [ pkgx_dir , runtime_env , basePath , ...paths ] = args ;
6569 const parsed_runtime_env = JSON . parse ( runtime_env ) as Record <
6670 string ,
6771 Record < string , string >
6872 > ;
69- await sudo_install ( pkgx_dir , paths , parsed_runtime_env ) ;
73+ await sudo_install ( pkgx_dir , paths , parsed_runtime_env , basePath ) ;
7074 break ;
7175 }
7276 default :
@@ -79,7 +83,7 @@ if (parsedArgs.help) {
7983 }
8084}
8185
82- async function install ( args : string [ ] ) {
86+ async function install ( args : string [ ] , basePath : string ) {
8387 if ( args . length === 0 ) {
8488 console . error ( "no packages specified" ) ;
8589 Deno . exit ( 1 ) ;
@@ -118,7 +122,7 @@ async function install(args: string[]) {
118122
119123 const to_install = [ ] ;
120124 for ( const prefix of pkg_prefixes ) {
121- if ( ! existsSync ( join ( "/usr/local/ pkgs" , prefix ) ) ) {
125+ if ( ! existsSync ( join ( ` ${ basePath } / pkgs` , prefix ) ) ) {
122126 to_install . push ( prefix ) ;
123127 }
124128 }
@@ -129,10 +133,10 @@ async function install(args: string[]) {
129133 }
130134
131135 const self = fromFileUrl ( import . meta. url ) ;
132- const pkgx_dir = Deno . env . get ( "PKGX_DIR" ) ?? `${ Deno . env . get ( "HOME" ) } /.pkgx` ;
133- const needs_sudo = Deno . uid ( ) != 0 ;
136+ const pkgx_dir = Deno . env . get ( "PKGX_DIR" ) || `${ Deno . env . get ( "HOME" ) } /.pkgx` ;
137+ const needs_sudo = Deno . uid ( ) != 0 && basePath === "/usr/local" ;
134138
135- const runtime_env = expand_runtime_env ( json . runtime_env ) ;
139+ const runtime_env = expand_runtime_env ( json . runtime_env , basePath ) ;
136140
137141 args = [
138142 "pkgx" ,
@@ -145,6 +149,7 @@ async function install(args: string[]) {
145149 "sudo-install" ,
146150 pkgx_dir ,
147151 runtime_env ,
152+ basePath ,
148153 ...to_install ,
149154 ] ;
150155 let cmd = "" ;
@@ -167,12 +172,13 @@ async function sudo_install(
167172 pkgx_dir : string ,
168173 pkg_prefixes : string [ ] ,
169174 runtime_env : Record < string , Record < string , string > > ,
175+ basePath : string ,
170176) {
171- const dst = "/usr/local" ;
177+ const dst = basePath ;
172178 for ( const pkg_prefix of pkg_prefixes ) {
173- // create /usr/local /pkgs/${prefix}
179+ // create ${dst} /pkgs/${prefix}
174180 await mirror_directory ( join ( dst , "pkgs" ) , pkgx_dir , pkg_prefix ) ;
175- // symlink /usr/local/ pkgs/${prefix} to /usr/local
181+ // symlink ${dst}/ pkgs/${prefix} to ${dst}
176182 if ( ! pkg_prefix . startsWith ( "pkgx.sh/v" ) ) {
177183 // ^^ don’t overwrite ourselves
178184 // ^^ * https://github.com/pkgxdev/pkgm/issues/14
@@ -191,14 +197,14 @@ async function sudo_install(
191197 if ( ! pkg_prefix ) continue ; //FIXME wtf?
192198
193199 for ( const bin of [ "bin" , "sbin" ] ) {
194- const bin_prefix = join ( "/usr/local/ pkgs" , pkg_prefix , bin ) ;
200+ const bin_prefix = join ( ` ${ dst } / pkgs` , pkg_prefix , bin ) ;
195201
196202 if ( ! existsSync ( bin_prefix ) ) continue ;
197203
198204 for await ( const entry of Deno . readDir ( bin_prefix ) ) {
199205 if ( ! entry . isFile ) continue ;
200206
201- const to_stub = join ( "/usr/local" , bin , entry . name ) ;
207+ const to_stub = join ( dst , bin , entry . name ) ;
202208
203209 let sh = `#!/bin/sh\n` ;
204210 for ( const [ key , value ] of Object . entries ( env ) ) {
@@ -310,12 +316,13 @@ async function create_v_symlinks(prefix: string) {
310316
311317function expand_runtime_env (
312318 runtime_env : Record < string , Record < string , string > > ,
319+ basePath : string ,
313320) {
314321 const expanded : Record < string , Record < string , string > > = { } ;
315322 for ( const [ project , env ] of Object . entries ( runtime_env ) ) {
316323 const expanded_env : Record < string , string > = { } ;
317324 for ( const [ key , value ] of Object . entries ( env ) ) {
318- const new_value = value . replaceAll ( / \$ ? { { .* p r e f i x } } / g, "/usr/local" ) ;
325+ const new_value = value . replaceAll ( / \$ ? { { .* p r e f i x } } / g, basePath ) ;
319326 expanded_env [ key ] = new_value ;
320327 }
321328 expanded [ project ] = expanded_env ;
0 commit comments