-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathuseConfig.ts
More file actions
133 lines (111 loc) · 3.94 KB
/
useConfig.ts
File metadata and controls
133 lines (111 loc) · 3.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import { flatmap } from "../utils/misc.ts"
import host from "../utils/host.ts"
import Path from "../utils/Path.ts"
export interface Config {
prefix: Path
pantries: Path[]
cache: Path
data: Path
options: {
/// prefer xz or gz for bottle downloads
compression: 'xz' | 'gz'
}
UserAgent?: string
git?: Path
}
function platform_cache_default() {
if (host().platform == 'darwin') {
return Path.home().join('Library/Caches')
} else {
return Path.home().join('.cache')
}
}
const SEP = Deno.build.os == 'windows' ? ';' : ':'
export function ConfigDefault(env = Deno.env.toObject()): Config {
const prefix = flatmap(env['PKGX_DIR']?.trim(), x => new Path(x)) ?? Path.home().join('.pkgx')
const pantries = env['PKGX_PANTRY_PATH']?.split(SEP).compact(x => flatmap(x.trim(), x => Path.abs(x) ?? Path.cwd().join(x))) ?? []
const cache = (flatmap(env["XDG_CACHE_HOME"], x => new Path(x)) ?? platform_cache_default()).join("pkgx")
const isCI = boolize(env['CI']) ?? false
const UserAgent = flatmap(getv(), v => `libpkgx/${v}`) ?? 'libpkgx'
const data = (() => {
const xdg = env["XDG_DATA_HOME"]
if (xdg) {
return new Path(xdg)
} else if (host().platform == "darwin") {
return Path.home().join("Library/Application Support")
} else {
return Path.home().join(".local/share")
}
})().join("pkgx")
//TODO prefer 'xz' on Linux (as well) if supported
const compression = !isCI && host().platform == 'darwin' ? 'xz' : 'gz'
return {
prefix,
pantries,
cache,
data,
UserAgent,
options: {
compression,
},
git: git(prefix, env.PATH)
}
}
function getv(): string | undefined {
if (typeof Deno === 'undefined') {
const url = new URL(import.meta.url)
const path = new Path(url.pathname).parent().parent().parent().join("package.json")
const blob = Deno.readFileSync(path.string)
const txt = new TextDecoder().decode(blob)
const { version } = JSON.parse(txt)
return typeof version == 'string' ? version : undefined
}
}
const gt = globalThis as unknown as {sh_pkgx_config?: Config}
export default function useConfig(input?: Config): Config {
// storing on globalThis so our config is shared across
// potentially multiple versions of libpkgx being loaded in the same process
if (!gt.sh_pkgx_config || input) {
gt.sh_pkgx_config = input ?? ConfigDefault()
}
return {...gt.sh_pkgx_config} // copy to prevent mutation
}
function boolize(input: string | undefined): boolean | undefined {
switch (input?.trim()?.toLowerCase()) {
case '0':
case 'false':
case 'no':
return false
case '1':
case 'true':
case 'yes':
return true
}
}
function reset() {
return delete gt.sh_pkgx_config
}
function initialized() {
return gt.sh_pkgx_config !== undefined
}
export const _internals = { reset, initialized, boolize }
/// we support a pkgx installed or system installed git, nothing else
/// eg. `git` could be a symlink in `PATH` to pkgx, which would cause a fork bomb
/// on darwin if xcode or xcode/clt is not installed this will fail to our http fallback above
//TODO be able to use our own git if installed
//NOTE however we don’t want to have to fully hydrate its env when libpkgx is initialized only when needed so…
function git(_prefix: Path, PATH?: string): Path | undefined {
return usr()
function usr() {
// only return /usr/bin if in the PATH so user can explicitly override this
const rv = PATH?.split(":")?.includes("/usr/bin") ? new Path("/usr") : undefined
/// don’t cause macOS to abort and then prompt the user to install the XcodeCLT
//FIXME test! but this is hard to test without docker images or something!
if (host().platform == 'darwin') {
if (new Path("/Library/Developer/CommandLineTools/usr/bin/git").isExecutableFile()) return rv
if (new Path("/Applications/Xcode.app").isDirectory()) return rv
return // don’t use `git`
}
return rv?.join("bin/git")
}
}