pinokiod 7.2.10 → 7.2.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/kernel/environment.js +119 -90
- package/package.json +1 -1
package/kernel/environment.js
CHANGED
|
@@ -5,136 +5,165 @@ const fs = require('fs')
|
|
|
5
5
|
const Util = require('./util')
|
|
6
6
|
const TEMP_ENV_KEYS = ["TMP", "TEMP", "TMPDIR", "PIP_TMPDIR"]
|
|
7
7
|
const CACHE_ENV_KEYS = ["UV_CACHE_DIR", "PIP_CACHE_DIR"]
|
|
8
|
+
const CACHE_PREFLIGHT_KEYS = TEMP_ENV_KEYS.concat(CACHE_ENV_KEYS)
|
|
8
9
|
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const setEnv = (env, key, value) => {
|
|
14
|
-
for (const candidate of Object.keys(env)) {
|
|
15
|
-
if (candidate.toLowerCase() === key.toLowerCase() && candidate !== key) {
|
|
16
|
-
delete env[candidate]
|
|
17
|
-
}
|
|
10
|
+
const formatCachePreflightError = (error) => {
|
|
11
|
+
if (!error) {
|
|
12
|
+
return ""
|
|
18
13
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
if (typeof
|
|
24
|
-
|
|
14
|
+
const parts = []
|
|
15
|
+
if (error.code) {
|
|
16
|
+
parts.push(`code=${error.code}`)
|
|
17
|
+
}
|
|
18
|
+
if (typeof error.errno !== "undefined") {
|
|
19
|
+
parts.push(`errno=${error.errno}`)
|
|
25
20
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return null
|
|
21
|
+
if (error.syscall) {
|
|
22
|
+
parts.push(`syscall=${error.syscall}`)
|
|
29
23
|
}
|
|
30
|
-
if (path
|
|
31
|
-
|
|
24
|
+
if (error.path) {
|
|
25
|
+
parts.push(`path=${error.path}`)
|
|
32
26
|
}
|
|
33
|
-
if (
|
|
34
|
-
|
|
27
|
+
if (error.dest) {
|
|
28
|
+
parts.push(`dest=${error.dest}`)
|
|
35
29
|
}
|
|
36
|
-
|
|
30
|
+
if (error.message) {
|
|
31
|
+
parts.push(`message=${error.message}`)
|
|
32
|
+
}
|
|
33
|
+
return parts.join(" ")
|
|
37
34
|
}
|
|
38
35
|
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
return rel === "" || (!!rel && !rel.startsWith("..") && !path.isAbsolute(rel))
|
|
36
|
+
const logCachePreflight = (message) => {
|
|
37
|
+
console.log(`[Pinokio cache preflight] ${message}`)
|
|
42
38
|
}
|
|
43
39
|
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
return false
|
|
47
|
-
}
|
|
48
|
-
const testDir = path.resolve(
|
|
40
|
+
const probeCacheDir = async (dirPath) => {
|
|
41
|
+
const probeDir = path.resolve(
|
|
49
42
|
dirPath,
|
|
50
|
-
`.pinokio-
|
|
43
|
+
`.pinokio-cache-probe-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`
|
|
51
44
|
)
|
|
52
|
-
const
|
|
53
|
-
const renamedFile = path.resolve(
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
45
|
+
const probeFile = path.resolve(probeDir, "probe.tmp")
|
|
46
|
+
const renamedFile = path.resolve(probeDir, "probe-renamed.tmp")
|
|
47
|
+
const steps = [
|
|
48
|
+
["create probe directory", () => fs.promises.mkdir(probeDir, { recursive: false })],
|
|
49
|
+
["write probe file", () => fs.promises.writeFile(probeFile, "pinokio")],
|
|
50
|
+
["append probe file", () => fs.promises.appendFile(probeFile, "-cache-probe")],
|
|
51
|
+
["rename probe file", () => fs.promises.rename(probeFile, renamedFile)],
|
|
52
|
+
["delete probe file", () => fs.promises.unlink(renamedFile)],
|
|
53
|
+
["remove probe directory", () => fs.promises.rmdir(probeDir)]
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
for (const [step, run] of steps) {
|
|
57
|
+
try {
|
|
58
|
+
await run()
|
|
59
|
+
} catch (error) {
|
|
60
|
+
await fs.promises.rm(probeDir, { recursive: true, force: true }).catch(() => {})
|
|
61
|
+
return { ok: false, step, error }
|
|
62
|
+
}
|
|
65
63
|
}
|
|
64
|
+
return { ok: true }
|
|
66
65
|
}
|
|
67
66
|
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
const managedCacheEnvDefaults = () => {
|
|
68
|
+
const defaults = {}
|
|
69
|
+
for (const key of CACHE_PREFLIGHT_KEYS) {
|
|
70
|
+
defaults[key] = `./cache/${key}`
|
|
71
71
|
}
|
|
72
|
-
|
|
72
|
+
return defaults
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const ensureCachePreflightDir = async (key, targetPath) => {
|
|
76
|
+
logCachePreflight(`${key}: target=${targetPath}`)
|
|
73
77
|
try {
|
|
74
|
-
await fs.promises.mkdir(
|
|
78
|
+
await fs.promises.mkdir(targetPath, { recursive: true })
|
|
79
|
+
logCachePreflight(`${key}: mkdir ok`)
|
|
75
80
|
} catch (error) {
|
|
76
|
-
|
|
77
|
-
return false
|
|
78
|
-
}
|
|
79
|
-
await fs.promises.rm(dirPath, { recursive: true, force: true }).catch(() => {})
|
|
80
|
-
try {
|
|
81
|
-
await fs.promises.mkdir(dirPath, { recursive: true })
|
|
82
|
-
} catch (mkdirError) {
|
|
83
|
-
return false
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
if (await canWriteDirectory(dirPath)) {
|
|
87
|
-
return true
|
|
81
|
+
logCachePreflight(`${key}: mkdir failed ${formatCachePreflightError(error)}`)
|
|
88
82
|
}
|
|
89
|
-
|
|
90
|
-
|
|
83
|
+
|
|
84
|
+
const firstProbe = await probeCacheDir(targetPath)
|
|
85
|
+
if (firstProbe.ok) {
|
|
86
|
+
logCachePreflight(`${key}: probe ok`)
|
|
87
|
+
return { key, path: targetPath, repaired: false, ok: true }
|
|
91
88
|
}
|
|
92
|
-
|
|
89
|
+
|
|
90
|
+
logCachePreflight(`${key}: probe failed step="${firstProbe.step}" ${formatCachePreflightError(firstProbe.error)}`)
|
|
91
|
+
logCachePreflight(`${key}: repair delete start path=${targetPath}`)
|
|
92
|
+
|
|
93
93
|
try {
|
|
94
|
-
await fs.promises.
|
|
94
|
+
await fs.promises.rm(targetPath, { recursive: true, force: true })
|
|
95
|
+
logCachePreflight(`${key}: repair delete ok`)
|
|
95
96
|
} catch (error) {
|
|
96
|
-
|
|
97
|
+
logCachePreflight(`${key}: repair delete failed ${formatCachePreflightError(error)}`)
|
|
98
|
+
return { key, path: targetPath, repaired: false, ok: false, step: "repair delete", error }
|
|
97
99
|
}
|
|
98
|
-
return canWriteDirectory(dirPath)
|
|
99
|
-
}
|
|
100
100
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
101
|
+
try {
|
|
102
|
+
await fs.promises.mkdir(targetPath, { recursive: true })
|
|
103
|
+
logCachePreflight(`${key}: repair mkdir ok`)
|
|
104
|
+
} catch (error) {
|
|
105
|
+
logCachePreflight(`${key}: repair mkdir failed ${formatCachePreflightError(error)}`)
|
|
106
|
+
return { key, path: targetPath, repaired: true, ok: false, step: "repair mkdir", error }
|
|
107
|
+
}
|
|
105
108
|
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
109
|
+
const secondProbe = await probeCacheDir(targetPath)
|
|
110
|
+
if (secondProbe.ok) {
|
|
111
|
+
logCachePreflight(`${key}: repair probe ok`)
|
|
112
|
+
return { key, path: targetPath, repaired: true, ok: true }
|
|
110
113
|
}
|
|
111
|
-
|
|
114
|
+
|
|
115
|
+
logCachePreflight(`${key}: repair probe failed step="${secondProbe.step}" ${formatCachePreflightError(secondProbe.error)}`)
|
|
116
|
+
return { key, path: targetPath, repaired: true, ok: false, step: secondProbe.step, error: secondProbe.error }
|
|
112
117
|
}
|
|
113
118
|
|
|
114
|
-
const ensurePinokioCacheDirs = async (kernel) => {
|
|
119
|
+
const ensurePinokioCacheDirs = async (kernel, options = {}) => {
|
|
115
120
|
if (!kernel || !kernel.homedir) {
|
|
116
121
|
return {}
|
|
117
122
|
}
|
|
123
|
+
const throwOnFailure = !!options.throwOnFailure
|
|
118
124
|
const root = path.resolve(kernel.homedir)
|
|
119
125
|
const cacheRoot = path.resolve(root, "cache")
|
|
120
126
|
const envPath = path.resolve(root, "ENVIRONMENT")
|
|
121
127
|
const defaults = managedCacheEnvDefaults()
|
|
128
|
+
logCachePreflight(`start root=${root}`)
|
|
122
129
|
await Util.update_env(envPath, defaults)
|
|
123
|
-
|
|
130
|
+
logCachePreflight(`ENVIRONMENT updated keys=${CACHE_PREFLIGHT_KEYS.join(",")}`)
|
|
131
|
+
try {
|
|
132
|
+
await fs.promises.mkdir(cacheRoot, { recursive: true })
|
|
133
|
+
logCachePreflight(`cache root mkdir ok path=${cacheRoot}`)
|
|
134
|
+
} catch (error) {
|
|
135
|
+
logCachePreflight(`cache root mkdir failed path=${cacheRoot} ${formatCachePreflightError(error)}`)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const errors = []
|
|
139
|
+
const results = []
|
|
124
140
|
|
|
125
|
-
for (const key of
|
|
126
|
-
const
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
if (!repair || !(await ensureWritableDirectory(targetPath, { repair: true }))) {
|
|
132
|
-
throw new Error(`Pinokio could not create a writable ${key} directory: ${targetPath}`)
|
|
141
|
+
for (const key of CACHE_PREFLIGHT_KEYS) {
|
|
142
|
+
const targetPath = path.resolve(cacheRoot, key)
|
|
143
|
+
const result = await ensureCachePreflightDir(key, targetPath)
|
|
144
|
+
results.push(result)
|
|
145
|
+
if (!result.ok) {
|
|
146
|
+
errors.push(result)
|
|
133
147
|
}
|
|
134
|
-
setEnv(env, key, targetPath)
|
|
135
148
|
}
|
|
136
149
|
|
|
137
|
-
|
|
150
|
+
if (errors.length > 0) {
|
|
151
|
+
kernel.cacheDirErrors = errors
|
|
152
|
+
const message = errors
|
|
153
|
+
.map((error) => `${error.key}: ${error.path} (${error.step || "unknown"} ${formatCachePreflightError(error.error)})`)
|
|
154
|
+
.join(", ")
|
|
155
|
+
logCachePreflight(`failed ${message}`)
|
|
156
|
+
if (throwOnFailure) {
|
|
157
|
+
throw new Error(`Pinokio could not create writable cache directories: ${message}`)
|
|
158
|
+
}
|
|
159
|
+
} else {
|
|
160
|
+
kernel.cacheDirErrors = []
|
|
161
|
+
logCachePreflight(`complete ok checked=${results.length} repaired=${results.filter((result) => result.repaired).length}`)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
kernel.cacheDirPreflight = results
|
|
165
|
+
const env = await get(root, kernel)
|
|
166
|
+
return { env, errors, results }
|
|
138
167
|
}
|
|
139
168
|
const ENVS = async () => {
|
|
140
169
|
// const primary_port = 80
|