pinokiod 7.2.10 → 7.2.12
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 +136 -88
- package/kernel/index.js +57 -1
- package/package.json +1 -1
- package/server/index.js +10 -0
package/kernel/environment.js
CHANGED
|
@@ -5,136 +5,184 @@ 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(
|
|
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
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return { ok: true }
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const managedCacheEnvDefaults = () => {
|
|
68
|
+
const defaults = {}
|
|
69
|
+
for (const key of CACHE_PREFLIGHT_KEYS) {
|
|
70
|
+
defaults[key] = `./cache/${key}`
|
|
71
|
+
}
|
|
72
|
+
return defaults
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const ensureCachePreflightDir = async (key, targetPath, options = {}) => {
|
|
76
|
+
logCachePreflight(`${key}: target=${targetPath}`)
|
|
54
77
|
try {
|
|
55
|
-
await fs.promises.mkdir(
|
|
56
|
-
|
|
57
|
-
await fs.promises.appendFile(testFile, "-probe")
|
|
58
|
-
await fs.promises.rename(testFile, renamedFile)
|
|
59
|
-
await fs.promises.unlink(renamedFile)
|
|
60
|
-
await fs.promises.rmdir(testDir)
|
|
61
|
-
return true
|
|
78
|
+
await fs.promises.mkdir(targetPath, { recursive: true })
|
|
79
|
+
logCachePreflight(`${key}: mkdir ok`)
|
|
62
80
|
} catch (error) {
|
|
63
|
-
|
|
64
|
-
return false
|
|
81
|
+
logCachePreflight(`${key}: mkdir failed ${formatCachePreflightError(error)}`)
|
|
65
82
|
}
|
|
66
|
-
}
|
|
67
83
|
|
|
68
|
-
const
|
|
69
|
-
if (
|
|
70
|
-
|
|
84
|
+
const firstProbe = await probeCacheDir(targetPath)
|
|
85
|
+
if (firstProbe.ok) {
|
|
86
|
+
logCachePreflight(`${key}: probe ok`)
|
|
87
|
+
return { key, path: targetPath, repaired: false, ok: true }
|
|
71
88
|
}
|
|
72
|
-
|
|
89
|
+
|
|
90
|
+
logCachePreflight(`${key}: probe failed step="${firstProbe.step}" ${formatCachePreflightError(firstProbe.error)}`)
|
|
91
|
+
logCachePreflight(`${key}: repair delete start path=${targetPath}`)
|
|
92
|
+
|
|
73
93
|
try {
|
|
74
|
-
await fs.promises.
|
|
94
|
+
await fs.promises.rm(targetPath, { recursive: true, force: true })
|
|
95
|
+
logCachePreflight(`${key}: repair delete ok`)
|
|
75
96
|
} catch (error) {
|
|
76
|
-
|
|
77
|
-
|
|
97
|
+
logCachePreflight(`${key}: repair delete failed ${formatCachePreflightError(error)}`)
|
|
98
|
+
if (typeof options.elevatedRepair !== "function") {
|
|
99
|
+
return { key, path: targetPath, repaired: false, ok: false, step: "repair delete", error }
|
|
78
100
|
}
|
|
79
|
-
|
|
101
|
+
logCachePreflight(`${key}: elevated repair start path=${targetPath}`)
|
|
102
|
+
let elevatedRepair
|
|
80
103
|
try {
|
|
81
|
-
await
|
|
82
|
-
} catch (
|
|
83
|
-
|
|
104
|
+
elevatedRepair = await options.elevatedRepair(targetPath, logCachePreflight)
|
|
105
|
+
} catch (repairError) {
|
|
106
|
+
elevatedRepair = { ok: false, error: repairError }
|
|
84
107
|
}
|
|
108
|
+
if (!elevatedRepair || !elevatedRepair.ok) {
|
|
109
|
+
return { key, path: targetPath, repaired: false, elevated: true, ok: false, step: "elevated repair", error: elevatedRepair && elevatedRepair.error ? elevatedRepair.error : error }
|
|
110
|
+
}
|
|
111
|
+
const elevatedProbe = await probeCacheDir(targetPath)
|
|
112
|
+
if (elevatedProbe.ok) {
|
|
113
|
+
logCachePreflight(`${key}: elevated repair probe ok`)
|
|
114
|
+
return { key, path: targetPath, repaired: true, elevated: true, ok: true }
|
|
115
|
+
}
|
|
116
|
+
logCachePreflight(`${key}: elevated repair probe failed step="${elevatedProbe.step}" ${formatCachePreflightError(elevatedProbe.error)}`)
|
|
117
|
+
return { key, path: targetPath, repaired: true, elevated: true, ok: false, step: elevatedProbe.step, error: elevatedProbe.error }
|
|
85
118
|
}
|
|
86
|
-
|
|
87
|
-
return true
|
|
88
|
-
}
|
|
89
|
-
if (!repair) {
|
|
90
|
-
return false
|
|
91
|
-
}
|
|
92
|
-
await fs.promises.rm(dirPath, { recursive: true, force: true }).catch(() => {})
|
|
119
|
+
|
|
93
120
|
try {
|
|
94
|
-
await fs.promises.mkdir(
|
|
121
|
+
await fs.promises.mkdir(targetPath, { recursive: true })
|
|
122
|
+
logCachePreflight(`${key}: repair mkdir ok`)
|
|
95
123
|
} catch (error) {
|
|
96
|
-
|
|
124
|
+
logCachePreflight(`${key}: repair mkdir failed ${formatCachePreflightError(error)}`)
|
|
125
|
+
return { key, path: targetPath, repaired: true, ok: false, step: "repair mkdir", error }
|
|
97
126
|
}
|
|
98
|
-
return canWriteDirectory(dirPath)
|
|
99
|
-
}
|
|
100
127
|
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const managedCacheEnvDefaults = () => {
|
|
107
|
-
const defaults = {}
|
|
108
|
-
for (const key of TEMP_ENV_KEYS.concat(CACHE_ENV_KEYS)) {
|
|
109
|
-
defaults[key] = `./cache/${key}`
|
|
128
|
+
const secondProbe = await probeCacheDir(targetPath)
|
|
129
|
+
if (secondProbe.ok) {
|
|
130
|
+
logCachePreflight(`${key}: repair probe ok`)
|
|
131
|
+
return { key, path: targetPath, repaired: true, ok: true }
|
|
110
132
|
}
|
|
111
|
-
|
|
133
|
+
|
|
134
|
+
logCachePreflight(`${key}: repair probe failed step="${secondProbe.step}" ${formatCachePreflightError(secondProbe.error)}`)
|
|
135
|
+
return { key, path: targetPath, repaired: true, ok: false, step: secondProbe.step, error: secondProbe.error }
|
|
112
136
|
}
|
|
113
137
|
|
|
114
|
-
const ensurePinokioCacheDirs = async (kernel) => {
|
|
138
|
+
const ensurePinokioCacheDirs = async (kernel, options = {}) => {
|
|
115
139
|
if (!kernel || !kernel.homedir) {
|
|
116
140
|
return {}
|
|
117
141
|
}
|
|
142
|
+
const throwOnFailure = !!options.throwOnFailure
|
|
118
143
|
const root = path.resolve(kernel.homedir)
|
|
119
144
|
const cacheRoot = path.resolve(root, "cache")
|
|
120
145
|
const envPath = path.resolve(root, "ENVIRONMENT")
|
|
121
146
|
const defaults = managedCacheEnvDefaults()
|
|
147
|
+
logCachePreflight(`start root=${root}`)
|
|
122
148
|
await Util.update_env(envPath, defaults)
|
|
123
|
-
|
|
149
|
+
logCachePreflight(`ENVIRONMENT updated keys=${CACHE_PREFLIGHT_KEYS.join(",")}`)
|
|
150
|
+
try {
|
|
151
|
+
await fs.promises.mkdir(cacheRoot, { recursive: true })
|
|
152
|
+
logCachePreflight(`cache root mkdir ok path=${cacheRoot}`)
|
|
153
|
+
} catch (error) {
|
|
154
|
+
logCachePreflight(`cache root mkdir failed path=${cacheRoot} ${formatCachePreflightError(error)}`)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const errors = []
|
|
158
|
+
const results = []
|
|
124
159
|
|
|
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}`)
|
|
160
|
+
for (const key of CACHE_PREFLIGHT_KEYS) {
|
|
161
|
+
const targetPath = path.resolve(cacheRoot, key)
|
|
162
|
+
const result = await ensureCachePreflightDir(key, targetPath, options)
|
|
163
|
+
results.push(result)
|
|
164
|
+
if (!result.ok) {
|
|
165
|
+
errors.push(result)
|
|
133
166
|
}
|
|
134
|
-
setEnv(env, key, targetPath)
|
|
135
167
|
}
|
|
136
168
|
|
|
137
|
-
|
|
169
|
+
if (errors.length > 0) {
|
|
170
|
+
kernel.cacheDirErrors = errors
|
|
171
|
+
const message = errors
|
|
172
|
+
.map((error) => `${error.key}: ${error.path} (${error.step || "unknown"} ${formatCachePreflightError(error.error)})`)
|
|
173
|
+
.join(", ")
|
|
174
|
+
logCachePreflight(`failed ${message}`)
|
|
175
|
+
if (throwOnFailure) {
|
|
176
|
+
throw new Error(`Pinokio could not create writable cache directories: ${message}`)
|
|
177
|
+
}
|
|
178
|
+
} else {
|
|
179
|
+
kernel.cacheDirErrors = []
|
|
180
|
+
logCachePreflight(`complete ok checked=${results.length} repaired=${results.filter((result) => result.repaired).length}`)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
kernel.cacheDirPreflight = results
|
|
184
|
+
const env = await get(root, kernel)
|
|
185
|
+
return { env, errors, results }
|
|
138
186
|
}
|
|
139
187
|
const ENVS = async () => {
|
|
140
188
|
// const primary_port = 80
|
package/kernel/index.js
CHANGED
|
@@ -44,6 +44,7 @@ const WatchManager = require('./watch')
|
|
|
44
44
|
const { DownloaderHelper } = require('node-downloader-helper');
|
|
45
45
|
const { ProxyAgent } = require('proxy-agent');
|
|
46
46
|
const fakeUa = require('fake-useragent');
|
|
47
|
+
const sudo = process.platform === "win32" ? require("sudo-prompt-programfiles-x86") : null
|
|
47
48
|
//const kill = require('./tree-kill');
|
|
48
49
|
const kill = require('kill-sync')
|
|
49
50
|
const ejs = require('ejs');
|
|
@@ -55,6 +56,34 @@ const VARS = {
|
|
|
55
56
|
}
|
|
56
57
|
}
|
|
57
58
|
|
|
59
|
+
const powershellSingleQuote = (value) => {
|
|
60
|
+
return `'${String(value).replace(/'/g, "''")}'`
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const windowsCacheRepairCommand = (targetPath) => {
|
|
64
|
+
const psPath = powershellSingleQuote(targetPath)
|
|
65
|
+
return [
|
|
66
|
+
"powershell.exe",
|
|
67
|
+
"-NoProfile",
|
|
68
|
+
"-ExecutionPolicy Bypass",
|
|
69
|
+
"-Command",
|
|
70
|
+
`"`,
|
|
71
|
+
"$ErrorActionPreference = 'Stop';",
|
|
72
|
+
`$p = ${psPath};`,
|
|
73
|
+
"$account = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name;",
|
|
74
|
+
"$grant = $account + ':(OI)(CI)F';",
|
|
75
|
+
"if (Test-Path -LiteralPath $p) {",
|
|
76
|
+
" & takeown.exe /F $p /R /D Y;",
|
|
77
|
+
" & icacls.exe $p /reset /T /C;",
|
|
78
|
+
" & icacls.exe $p /grant $grant /T /C;",
|
|
79
|
+
" Remove-Item -LiteralPath $p -Recurse -Force;",
|
|
80
|
+
"}",
|
|
81
|
+
"New-Item -ItemType Directory -Force -Path $p | Out-Null;",
|
|
82
|
+
"& icacls.exe $p /grant $grant /T /C;",
|
|
83
|
+
`"`
|
|
84
|
+
].join(" ")
|
|
85
|
+
}
|
|
86
|
+
|
|
58
87
|
//const memwatch = require('@airbnb/node-memwatch');
|
|
59
88
|
class Kernel {
|
|
60
89
|
schema = "<=7.0.0"
|
|
@@ -465,6 +494,30 @@ class Kernel {
|
|
|
465
494
|
return ''
|
|
466
495
|
}
|
|
467
496
|
}
|
|
497
|
+
async elevatedCacheRepair(targetPath, log = console.log) {
|
|
498
|
+
if (this.platform !== "win32" || !sudo) {
|
|
499
|
+
return { ok: false, error: new Error("Elevated cache repair is only available on Windows") }
|
|
500
|
+
}
|
|
501
|
+
const command = windowsCacheRepairCommand(targetPath)
|
|
502
|
+
log(`elevated repair command=${command}`)
|
|
503
|
+
return new Promise((resolve) => {
|
|
504
|
+
sudo.exec(command, { name: "Pinokio" }, (error, stdout, stderr) => {
|
|
505
|
+
if (stdout && stdout.trim()) {
|
|
506
|
+
log(`elevated repair stdout ${stdout.trim()}`)
|
|
507
|
+
}
|
|
508
|
+
if (stderr && stderr.trim()) {
|
|
509
|
+
log(`elevated repair stderr ${stderr.trim()}`)
|
|
510
|
+
}
|
|
511
|
+
if (error) {
|
|
512
|
+
log(`elevated repair failed ${error.message || error}`)
|
|
513
|
+
resolve({ ok: false, error, stdout, stderr })
|
|
514
|
+
} else {
|
|
515
|
+
log(`elevated repair ok path=${targetPath}`)
|
|
516
|
+
resolve({ ok: true, stdout, stderr })
|
|
517
|
+
}
|
|
518
|
+
})
|
|
519
|
+
})
|
|
520
|
+
}
|
|
468
521
|
async ensureRouterMode() {
|
|
469
522
|
const domain = await this.resolvePinokioDomain()
|
|
470
523
|
const shouldUseCustom = domain.length > 0
|
|
@@ -1053,7 +1106,10 @@ class Kernel {
|
|
|
1053
1106
|
|
|
1054
1107
|
// 2. mkdir all the folders if not already created
|
|
1055
1108
|
await Environment.init_folders(this.homedir, this)
|
|
1056
|
-
await Environment.ensurePinokioCacheDirs(this
|
|
1109
|
+
await Environment.ensurePinokioCacheDirs(this, {
|
|
1110
|
+
throwOnFailure: true,
|
|
1111
|
+
elevatedRepair: this.elevatedCacheRepair.bind(this)
|
|
1112
|
+
})
|
|
1057
1113
|
|
|
1058
1114
|
// if key.json doesn't exist, create an empty json file
|
|
1059
1115
|
let ee = await this.exists(this.homedir, "key.json")
|
package/package.json
CHANGED
package/server/index.js
CHANGED
|
@@ -5707,6 +5707,16 @@ class Server {
|
|
|
5707
5707
|
|
|
5708
5708
|
needsManagedRefresh = true
|
|
5709
5709
|
console.log("[TRY] Updating to the new version")
|
|
5710
|
+
let envPath = path.resolve(home, "ENVIRONMENT")
|
|
5711
|
+
let envExists = await this.kernel.exists(envPath)
|
|
5712
|
+
if (!envExists) {
|
|
5713
|
+
let str = await Environment.ENV("system", home, this.kernel)
|
|
5714
|
+
await fs.promises.writeFile(envPath, str)
|
|
5715
|
+
}
|
|
5716
|
+
await Environment.ensurePinokioCacheDirs(this.kernel, {
|
|
5717
|
+
throwOnFailure: true,
|
|
5718
|
+
elevatedRepair: this.kernel.elevatedCacheRepair.bind(this.kernel)
|
|
5719
|
+
})
|
|
5710
5720
|
this.kernel.store.set("version", this.version.pinokiod)
|
|
5711
5721
|
console.log("[DONE] Updating to the new version")
|
|
5712
5722
|
console.log("not up to date. update py.")
|