pinokiod 7.5.29 → 7.5.31
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/bin/conda-meta.js +18 -5
- package/kernel/bin/conda.js +93 -30
- package/kernel/bin/index.js +5 -2
- package/package.json +1 -1
- package/server/index.js +7 -0
- package/server/public/style.css +4 -0
- package/test/conda-bin.test.js +138 -6
package/kernel/bin/conda-meta.js
CHANGED
|
@@ -69,15 +69,27 @@ async function runCondaList(minicondaPath) {
|
|
|
69
69
|
})
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
function
|
|
73
|
-
|
|
72
|
+
async function managedCondaRuns(minicondaPath, platform = process.platform) {
|
|
73
|
+
const condaBinary = resolveCondaBinary(minicondaPath, platform, false)
|
|
74
|
+
if (!condaBinary) {
|
|
75
|
+
return false
|
|
76
|
+
}
|
|
77
|
+
return await new Promise((resolve) => {
|
|
78
|
+
execFile(condaBinary, ['--version'], { windowsHide: true, timeout: 15000 }, (err) => {
|
|
79
|
+
resolve(!err)
|
|
80
|
+
})
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function resolveCondaBinary(minicondaPath, platform = process.platform, allowFallback = true) {
|
|
85
|
+
if (platform === 'win32') {
|
|
74
86
|
if (minicondaPath) {
|
|
75
87
|
const scriptPath = path.join(minicondaPath, 'Scripts', 'conda.exe')
|
|
76
88
|
if (fs.existsSync(scriptPath)) {
|
|
77
89
|
return scriptPath
|
|
78
90
|
}
|
|
79
91
|
}
|
|
80
|
-
return 'conda'
|
|
92
|
+
return allowFallback ? 'conda' : null
|
|
81
93
|
}
|
|
82
94
|
if (minicondaPath) {
|
|
83
95
|
const binPath = path.join(minicondaPath, 'bin', 'conda')
|
|
@@ -85,9 +97,10 @@ function resolveCondaBinary(minicondaPath) {
|
|
|
85
97
|
return binPath
|
|
86
98
|
}
|
|
87
99
|
}
|
|
88
|
-
return 'conda'
|
|
100
|
+
return allowFallback ? 'conda' : null
|
|
89
101
|
}
|
|
90
102
|
|
|
91
103
|
module.exports = {
|
|
92
|
-
buildCondaListFromMeta
|
|
104
|
+
buildCondaListFromMeta,
|
|
105
|
+
managedCondaRuns,
|
|
93
106
|
}
|
package/kernel/bin/conda.js
CHANGED
|
@@ -2,7 +2,7 @@ const fs = require('fs')
|
|
|
2
2
|
const path = require('path')
|
|
3
3
|
const { glob } = require('glob')
|
|
4
4
|
const semver = require('semver')
|
|
5
|
-
const { buildCondaListFromMeta } = require('./conda-meta')
|
|
5
|
+
const { buildCondaListFromMeta, managedCondaRuns } = require('./conda-meta')
|
|
6
6
|
const {
|
|
7
7
|
CONDA_PIN_VERSION,
|
|
8
8
|
PYTHON_INSTALL_SPEC,
|
|
@@ -14,6 +14,61 @@ const MINIFORGE_RELEASE = "26.3.2-3"
|
|
|
14
14
|
const MINIFORGE_BASE_URL = `https://github.com/conda-forge/miniforge/releases/download/${MINIFORGE_RELEASE}`
|
|
15
15
|
const CONDA_ROOT_DIR = "miniforge"
|
|
16
16
|
const LEGACY_CONDA_ROOT_DIR = "miniconda"
|
|
17
|
+
const WINDOWS_OPENSSL_HOOKS = {
|
|
18
|
+
activate: {
|
|
19
|
+
"openssl_activate-win.bat": [
|
|
20
|
+
"@echo off",
|
|
21
|
+
'if "%SSL_CERT_FILE%"=="" (',
|
|
22
|
+
' set "SSL_CERT_FILE=%CONDA_PREFIX%\\Library\\ssl\\cacert.pem"',
|
|
23
|
+
' set "__CONDA_OPENSSL_CERT_FILE_SET=1"',
|
|
24
|
+
")",
|
|
25
|
+
"",
|
|
26
|
+
].join("\r\n"),
|
|
27
|
+
"openssl_activate-win.ps1": [
|
|
28
|
+
"if (-not $Env:SSL_CERT_FILE) {",
|
|
29
|
+
' $Env:SSL_CERT_FILE = "$Env:CONDA_PREFIX\\Library\\ssl\\cacert.pem"',
|
|
30
|
+
' $Env:__CONDA_OPENSSL_CERT_FILE_SET = "1"',
|
|
31
|
+
"}",
|
|
32
|
+
"",
|
|
33
|
+
].join("\r\n"),
|
|
34
|
+
"openssl_activate-win.sh": [
|
|
35
|
+
'if [[ "${SSL_CERT_FILE:-}" == "" ]]; then',
|
|
36
|
+
' export SSL_CERT_FILE="${CONDA_PREFIX}\\\\Library\\\\ssl\\\\cacert.pem"',
|
|
37
|
+
' export __CONDA_OPENSSL_CERT_FILE_SET="1"',
|
|
38
|
+
"fi",
|
|
39
|
+
"",
|
|
40
|
+
].join("\n"),
|
|
41
|
+
},
|
|
42
|
+
deactivate: {
|
|
43
|
+
"openssl_deactivate-win.bat": [
|
|
44
|
+
"@echo off",
|
|
45
|
+
'if "%__CONDA_OPENSSL_CERT_FILE_SET%" == "1" (',
|
|
46
|
+
" set SSL_CERT_FILE=",
|
|
47
|
+
" set __CONDA_OPENSSL_CERT_FILE_SET=",
|
|
48
|
+
")",
|
|
49
|
+
"",
|
|
50
|
+
].join("\r\n"),
|
|
51
|
+
"openssl_deactivate-win.ps1": [
|
|
52
|
+
'if ($Env:__CONDA_OPENSSL_CERT_FILE_SET -eq "1") {',
|
|
53
|
+
" Remove-Item -Path Env:\\SSL_CERT_FILE",
|
|
54
|
+
" Remove-Item -Path Env:\\__CONDA_OPENSSL_CERT_FILE_SET",
|
|
55
|
+
"}",
|
|
56
|
+
"",
|
|
57
|
+
].join("\r\n"),
|
|
58
|
+
"openssl_deactivate-win.sh": [
|
|
59
|
+
'if [[ "${__CONDA_OPENSSL_CERT_FILE_SET:-}" == "1" ]]; then',
|
|
60
|
+
" unset SSL_CERT_FILE",
|
|
61
|
+
" unset __CONDA_OPENSSL_CERT_FILE_SET",
|
|
62
|
+
"fi",
|
|
63
|
+
"",
|
|
64
|
+
].join("\n"),
|
|
65
|
+
},
|
|
66
|
+
}
|
|
67
|
+
const LEGACY_SSL_CERT_DIR_HOOK_FILES = [
|
|
68
|
+
"zz_pinokio_unset_ssl_cert_dir-win.bat",
|
|
69
|
+
"zz_pinokio_unset_ssl_cert_dir-win.ps1",
|
|
70
|
+
"zz_pinokio_unset_ssl_cert_dir-win.sh",
|
|
71
|
+
]
|
|
17
72
|
|
|
18
73
|
class Conda {
|
|
19
74
|
description = "Pinokio uses Conda to install various useful programs in an isolated manner."
|
|
@@ -69,37 +124,42 @@ class Conda {
|
|
|
69
124
|
}
|
|
70
125
|
return base
|
|
71
126
|
}
|
|
72
|
-
async
|
|
127
|
+
async ensureWindowsOpenSslHooks() {
|
|
73
128
|
if (this.kernel.platform !== "win32") {
|
|
74
129
|
return
|
|
75
130
|
}
|
|
76
|
-
|
|
131
|
+
const condaRootDirs = []
|
|
132
|
+
for (const rootDir of [CONDA_ROOT_DIR, LEGACY_CONDA_ROOT_DIR]) {
|
|
133
|
+
if (await this.kernel.exists(`bin/${rootDir}/conda-meta`)) {
|
|
134
|
+
condaRootDirs.push(rootDir)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (condaRootDirs.length === 0) {
|
|
77
138
|
return
|
|
78
139
|
}
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
)
|
|
140
|
+
for (const rootDir of condaRootDirs) {
|
|
141
|
+
const activateDir = this.kernel.bin.path(`${rootDir}/etc/conda/activate.d`)
|
|
142
|
+
const deactivateDir = this.kernel.bin.path(`${rootDir}/etc/conda/deactivate.d`)
|
|
143
|
+
for (const hookDir of [activateDir, deactivateDir]) {
|
|
144
|
+
for (const filename of LEGACY_SSL_CERT_DIR_HOOK_FILES) {
|
|
145
|
+
await fs.promises.rm(path.resolve(hookDir, filename), { force: true }).catch(() => {})
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
for (const [filename, content] of Object.entries(WINDOWS_OPENSSL_HOOKS.activate)) {
|
|
149
|
+
const hookPath = path.resolve(activateDir, filename)
|
|
150
|
+
const exists = await fs.promises.access(hookPath).then(() => true).catch(() => false)
|
|
151
|
+
if (exists) {
|
|
152
|
+
await fs.promises.writeFile(hookPath, content)
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
for (const [filename, content] of Object.entries(WINDOWS_OPENSSL_HOOKS.deactivate)) {
|
|
156
|
+
const hookPath = path.resolve(deactivateDir, filename)
|
|
157
|
+
const exists = await fs.promises.access(hookPath).then(() => true).catch(() => false)
|
|
158
|
+
if (exists) {
|
|
159
|
+
await fs.promises.writeFile(hookPath, content)
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
103
163
|
}
|
|
104
164
|
async init() {
|
|
105
165
|
if (this.kernel.homedir) {
|
|
@@ -120,9 +180,9 @@ report_errors: false`)
|
|
|
120
180
|
let pinned_exists = await this.hasCondaMeta()
|
|
121
181
|
if (pinned_exists) {
|
|
122
182
|
await fs.promises.writeFile(this.kernel.path(`bin/${CONDA_ROOT_DIR}/conda-meta/pinned`), this.pinnedPackages())
|
|
123
|
-
await this.ensureSslCertDirOverride()
|
|
124
183
|
await this.ensureCompatibilityAlias()
|
|
125
184
|
}
|
|
185
|
+
await this.ensureWindowsOpenSslHooks()
|
|
126
186
|
}
|
|
127
187
|
}
|
|
128
188
|
async check() {
|
|
@@ -170,7 +230,10 @@ report_errors: false`)
|
|
|
170
230
|
this.kernel.bin.installed.conda = conda
|
|
171
231
|
this.kernel.bin.installed.conda_versions = conda_versions
|
|
172
232
|
this.kernel.bin.installed.conda_builds = conda_builds
|
|
173
|
-
|
|
233
|
+
if (!(conda_check.conda && conda_check.mamba && conda_check.python)) {
|
|
234
|
+
return false
|
|
235
|
+
}
|
|
236
|
+
return await managedCondaRuns(this.kernel.bin.path(CONDA_ROOT_DIR), this.kernel.platform)
|
|
174
237
|
}
|
|
175
238
|
async install(req, ondata) {
|
|
176
239
|
for(let i=0; i<5; i++) {
|
|
@@ -267,7 +330,7 @@ report_errors: false`)
|
|
|
267
330
|
this.kernel.bin.path(CONDA_ROOT_DIR, "python3.exe"),
|
|
268
331
|
)
|
|
269
332
|
}
|
|
270
|
-
await this.
|
|
333
|
+
await this.ensureWindowsOpenSslHooks()
|
|
271
334
|
await this.ensureCompatibilityAlias()
|
|
272
335
|
ondata({ raw: `Install finished\r\n` })
|
|
273
336
|
await this.kernel.bin.rm(installer, ondata)
|
package/kernel/bin/index.js
CHANGED
|
@@ -21,7 +21,7 @@ const LLVM = require('./llvm')
|
|
|
21
21
|
const VS = require("./vs")
|
|
22
22
|
const Cuda = require("./cuda")
|
|
23
23
|
const Torch = require("./torch")
|
|
24
|
-
const { buildCondaListFromMeta } = require('./conda-meta')
|
|
24
|
+
const { buildCondaListFromMeta, managedCondaRuns } = require('./conda-meta')
|
|
25
25
|
const {
|
|
26
26
|
isExpectedPythonPinned,
|
|
27
27
|
} = require('./conda-pins')
|
|
@@ -412,7 +412,7 @@ class Bin {
|
|
|
412
412
|
}
|
|
413
413
|
|
|
414
414
|
if (conda_check.conda && conda_check.mamba && conda_check.python) {
|
|
415
|
-
this.correct_conda =
|
|
415
|
+
this.correct_conda = await managedCondaRuns(this.kernel.bin.path("miniforge"), this.platform)
|
|
416
416
|
}
|
|
417
417
|
}
|
|
418
418
|
this.installed.conda = conda
|
|
@@ -448,6 +448,9 @@ class Bin {
|
|
|
448
448
|
break
|
|
449
449
|
}
|
|
450
450
|
}
|
|
451
|
+
if (this.mod && this.mod.conda && this.mod.conda.ensureWindowsOpenSslHooks) {
|
|
452
|
+
await this.mod.conda.ensureWindowsOpenSslHooks()
|
|
453
|
+
}
|
|
451
454
|
}
|
|
452
455
|
|
|
453
456
|
if (this.platform === "darwin") {
|
package/package.json
CHANGED
package/server/index.js
CHANGED
|
@@ -6041,6 +6041,13 @@ class Server {
|
|
|
6041
6041
|
if (version === this.version.pinokiod) {
|
|
6042
6042
|
console.log("version up to date")
|
|
6043
6043
|
} else if (!(await fse.pathExists(path.resolve(home, "bin/miniforge/conda-meta")))) {
|
|
6044
|
+
// if miniconda => miniforge migration hasn't happened yet
|
|
6045
|
+
if (!(await fse.pathExists(path.resolve(home, "bin/miniconda/conda-meta")))) {
|
|
6046
|
+
// if miniconda folder does NOT exist (new user), set version
|
|
6047
|
+
// if miniconda folder exists (existing user), don't set version yet
|
|
6048
|
+
// => version only set after miniconda => miniforge migration has happened
|
|
6049
|
+
this.kernel.store.set("version", this.version.pinokiod)
|
|
6050
|
+
}
|
|
6044
6051
|
console.warn("[WARN] Managed home refresh deferred until Miniforge is installed")
|
|
6045
6052
|
} else {
|
|
6046
6053
|
// For every update, this gets triggered exactly once.
|
package/server/public/style.css
CHANGED
|
@@ -1284,6 +1284,10 @@ body.main-sidebar-page .navheader {
|
|
|
1284
1284
|
box-shadow: none;
|
|
1285
1285
|
isolation: isolate;
|
|
1286
1286
|
}
|
|
1287
|
+
body.main-sidebar-page > header.navheader h1,
|
|
1288
|
+
body.app-page > header.navheader h1 {
|
|
1289
|
+
gap: 6px;
|
|
1290
|
+
}
|
|
1287
1291
|
body.main-sidebar-page .navheader .sidebar-toggle {
|
|
1288
1292
|
color: #0f172a;
|
|
1289
1293
|
position: relative;
|
package/test/conda-bin.test.js
CHANGED
|
@@ -25,12 +25,38 @@ function createKernel(root, platform = 'win32') {
|
|
|
25
25
|
exists: async (...parts) => pathExists(path.join(root, ...parts)),
|
|
26
26
|
bin: {
|
|
27
27
|
correct_conda: true,
|
|
28
|
+
installed: {},
|
|
28
29
|
path: (...parts) => path.join(root, 'bin', ...parts),
|
|
29
30
|
exists: async (target) => pathExists(path.join(root, 'bin', target)),
|
|
30
31
|
},
|
|
31
32
|
}
|
|
32
33
|
}
|
|
33
34
|
|
|
35
|
+
async function writeCondaMeta(root, name, version, build = 'py_0') {
|
|
36
|
+
const metaDir = path.join(root, 'bin', 'miniforge', 'conda-meta')
|
|
37
|
+
await fs.mkdir(metaDir, { recursive: true })
|
|
38
|
+
await fs.writeFile(
|
|
39
|
+
path.join(metaDir, `${name}-${version}.json`),
|
|
40
|
+
JSON.stringify({ name, version, build_string: build, channel: 'conda-forge' })
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function writeHealthyCondaMeta(root, platform = 'win32') {
|
|
45
|
+
await writeCondaMeta(root, 'conda', '26.3.2', 'py310')
|
|
46
|
+
await writeCondaMeta(root, 'conda-libmamba-solver', '25.4.0', 'pyhd3eb1b0_0')
|
|
47
|
+
await writeCondaMeta(root, 'python', '3.10.20', platform === 'win32' ? 'h4de0772_1_cpython' : 'cpython')
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function writeFakeManagedConda(root, platform = 'win32') {
|
|
51
|
+
const condaPath = platform === 'win32'
|
|
52
|
+
? path.join(root, 'bin', 'miniforge', 'Scripts', 'conda.exe')
|
|
53
|
+
: path.join(root, 'bin', 'miniforge', 'bin', 'conda')
|
|
54
|
+
await fs.mkdir(path.dirname(condaPath), { recursive: true })
|
|
55
|
+
await fs.copyFile(process.execPath, condaPath)
|
|
56
|
+
await fs.chmod(condaPath, 0o755)
|
|
57
|
+
return condaPath
|
|
58
|
+
}
|
|
59
|
+
|
|
34
60
|
async function createCondaRoot(root, name) {
|
|
35
61
|
const condaRoot = path.join(root, 'bin', name)
|
|
36
62
|
await fs.mkdir(path.join(condaRoot, 'Scripts'), { recursive: true })
|
|
@@ -52,6 +78,88 @@ function createConda(kernel) {
|
|
|
52
78
|
return conda
|
|
53
79
|
}
|
|
54
80
|
|
|
81
|
+
const EXPECTED_WINDOWS_OPENSSL_HOOKS = {
|
|
82
|
+
[path.join('activate.d', 'openssl_activate-win.bat')]: [
|
|
83
|
+
'@echo off',
|
|
84
|
+
'if "%SSL_CERT_FILE%"=="" (',
|
|
85
|
+
' set "SSL_CERT_FILE=%CONDA_PREFIX%\\Library\\ssl\\cacert.pem"',
|
|
86
|
+
' set "__CONDA_OPENSSL_CERT_FILE_SET=1"',
|
|
87
|
+
')',
|
|
88
|
+
'',
|
|
89
|
+
].join('\r\n'),
|
|
90
|
+
[path.join('activate.d', 'openssl_activate-win.ps1')]: [
|
|
91
|
+
'if (-not $Env:SSL_CERT_FILE) {',
|
|
92
|
+
' $Env:SSL_CERT_FILE = "$Env:CONDA_PREFIX\\Library\\ssl\\cacert.pem"',
|
|
93
|
+
' $Env:__CONDA_OPENSSL_CERT_FILE_SET = "1"',
|
|
94
|
+
'}',
|
|
95
|
+
'',
|
|
96
|
+
].join('\r\n'),
|
|
97
|
+
[path.join('activate.d', 'openssl_activate-win.sh')]: [
|
|
98
|
+
'if [[ "${SSL_CERT_FILE:-}" == "" ]]; then',
|
|
99
|
+
' export SSL_CERT_FILE="${CONDA_PREFIX}\\\\Library\\\\ssl\\\\cacert.pem"',
|
|
100
|
+
' export __CONDA_OPENSSL_CERT_FILE_SET="1"',
|
|
101
|
+
'fi',
|
|
102
|
+
'',
|
|
103
|
+
].join('\n'),
|
|
104
|
+
[path.join('deactivate.d', 'openssl_deactivate-win.bat')]: [
|
|
105
|
+
'@echo off',
|
|
106
|
+
'if "%__CONDA_OPENSSL_CERT_FILE_SET%" == "1" (',
|
|
107
|
+
' set SSL_CERT_FILE=',
|
|
108
|
+
' set __CONDA_OPENSSL_CERT_FILE_SET=',
|
|
109
|
+
')',
|
|
110
|
+
'',
|
|
111
|
+
].join('\r\n'),
|
|
112
|
+
[path.join('deactivate.d', 'openssl_deactivate-win.ps1')]: [
|
|
113
|
+
'if ($Env:__CONDA_OPENSSL_CERT_FILE_SET -eq "1") {',
|
|
114
|
+
' Remove-Item -Path Env:\\SSL_CERT_FILE',
|
|
115
|
+
' Remove-Item -Path Env:\\__CONDA_OPENSSL_CERT_FILE_SET',
|
|
116
|
+
'}',
|
|
117
|
+
'',
|
|
118
|
+
].join('\r\n'),
|
|
119
|
+
[path.join('deactivate.d', 'openssl_deactivate-win.sh')]: [
|
|
120
|
+
'if [[ "${__CONDA_OPENSSL_CERT_FILE_SET:-}" == "1" ]]; then',
|
|
121
|
+
' unset SSL_CERT_FILE',
|
|
122
|
+
' unset __CONDA_OPENSSL_CERT_FILE_SET',
|
|
123
|
+
'fi',
|
|
124
|
+
'',
|
|
125
|
+
].join('\n'),
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function seedWindowsOpenSslHooks(root, condaRootName) {
|
|
129
|
+
const condaHookRoot = path.join(root, 'bin', condaRootName, 'etc', 'conda')
|
|
130
|
+
for (const hookRelativePath of Object.keys(EXPECTED_WINDOWS_OPENSSL_HOOKS)) {
|
|
131
|
+
const hookPath = path.join(condaHookRoot, hookRelativePath)
|
|
132
|
+
await fs.mkdir(path.dirname(hookPath), { recursive: true })
|
|
133
|
+
await fs.writeFile(hookPath, 'upstream hook with SSL_CERT_DIR\n')
|
|
134
|
+
}
|
|
135
|
+
for (const hookDirName of ['activate.d', 'deactivate.d']) {
|
|
136
|
+
for (const filename of [
|
|
137
|
+
'zz_pinokio_unset_ssl_cert_dir-win.bat',
|
|
138
|
+
'zz_pinokio_unset_ssl_cert_dir-win.ps1',
|
|
139
|
+
'zz_pinokio_unset_ssl_cert_dir-win.sh',
|
|
140
|
+
]) {
|
|
141
|
+
await fs.writeFile(path.join(condaHookRoot, hookDirName, filename), 'legacy hook\n')
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
async function assertWindowsOpenSslHooksPatched(root, condaRootName) {
|
|
147
|
+
const condaHookRoot = path.join(root, 'bin', condaRootName, 'etc', 'conda')
|
|
148
|
+
for (const [hookRelativePath, expectedContent] of Object.entries(EXPECTED_WINDOWS_OPENSSL_HOOKS)) {
|
|
149
|
+
const hookPath = path.join(condaHookRoot, hookRelativePath)
|
|
150
|
+
assert.equal(await fs.readFile(hookPath, 'utf8'), expectedContent)
|
|
151
|
+
}
|
|
152
|
+
for (const hookDirName of ['activate.d', 'deactivate.d']) {
|
|
153
|
+
for (const filename of [
|
|
154
|
+
'zz_pinokio_unset_ssl_cert_dir-win.bat',
|
|
155
|
+
'zz_pinokio_unset_ssl_cert_dir-win.ps1',
|
|
156
|
+
'zz_pinokio_unset_ssl_cert_dir-win.sh',
|
|
157
|
+
]) {
|
|
158
|
+
assert.equal(await pathExists(path.join(condaHookRoot, hookDirName, filename)), false)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
55
163
|
test('Conda uses Miniforge assets and writes conda-forge-only config', async () => {
|
|
56
164
|
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'pinokio-conda-miniforge-config-'))
|
|
57
165
|
const conda = createConda(createKernel(root))
|
|
@@ -73,17 +181,26 @@ test('Conda uses Miniforge assets and writes conda-forge-only config', async ()
|
|
|
73
181
|
assert.equal(await pathExists(path.join(root, 'bin', 'miniforge')), false)
|
|
74
182
|
})
|
|
75
183
|
|
|
76
|
-
test('Conda init
|
|
77
|
-
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'pinokio-conda-
|
|
184
|
+
test('Conda init patches Windows OpenSSL hooks and removes legacy SSL_CERT_DIR hooks', async () => {
|
|
185
|
+
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'pinokio-conda-openssl-hooks-'))
|
|
78
186
|
await fs.mkdir(path.join(root, 'bin', 'miniforge', 'conda-meta'), { recursive: true })
|
|
187
|
+
await seedWindowsOpenSslHooks(root, 'miniforge')
|
|
79
188
|
const conda = createConda(createKernel(root))
|
|
80
189
|
|
|
81
190
|
await conda.init()
|
|
82
191
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
192
|
+
await assertWindowsOpenSslHooksPatched(root, 'miniforge')
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
test('Conda init patches Windows OpenSSL hooks for legacy Miniconda roots', async () => {
|
|
196
|
+
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'pinokio-conda-legacy-openssl-hooks-'))
|
|
197
|
+
await fs.mkdir(path.join(root, 'bin', 'miniconda', 'conda-meta'), { recursive: true })
|
|
198
|
+
await seedWindowsOpenSslHooks(root, 'miniconda')
|
|
199
|
+
const conda = createConda(createKernel(root))
|
|
200
|
+
|
|
201
|
+
await conda.init()
|
|
202
|
+
|
|
203
|
+
await assertWindowsOpenSslHooksPatched(root, 'miniconda')
|
|
87
204
|
})
|
|
88
205
|
|
|
89
206
|
test('Conda pins Python 3.10.20 consistently across platforms', async () => {
|
|
@@ -207,6 +324,21 @@ test('Conda installed stays false when metadata check already marked Conda inval
|
|
|
207
324
|
assert.equal(await createConda(kernel).installed(), false)
|
|
208
325
|
})
|
|
209
326
|
|
|
327
|
+
test('Conda check rejects metadata-only Windows installs', async () => {
|
|
328
|
+
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'pinokio-conda-smoke-missing-'))
|
|
329
|
+
await writeHealthyCondaMeta(root, 'win32')
|
|
330
|
+
|
|
331
|
+
assert.equal(await createConda(createKernel(root, 'win32')).check(), false)
|
|
332
|
+
})
|
|
333
|
+
|
|
334
|
+
test('Conda check accepts a runnable managed Windows conda executable', async () => {
|
|
335
|
+
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'pinokio-conda-smoke-runnable-'))
|
|
336
|
+
await writeHealthyCondaMeta(root, 'win32')
|
|
337
|
+
await writeFakeManagedConda(root, 'win32')
|
|
338
|
+
|
|
339
|
+
assert.equal(await createConda(createKernel(root, 'win32')).check(), true)
|
|
340
|
+
})
|
|
341
|
+
|
|
210
342
|
test('Conda install keeps the old runtime when the replacement installer download fails', async () => {
|
|
211
343
|
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'pinokio-conda-download-fails-'))
|
|
212
344
|
const miniconda = await createLegacyMiniconda(root)
|