@sparkelf/dsh-patch-wsl-native-open 0.2.0-rc.21 → 0.2.0-rc.23
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/package.json +3 -3
- package/patches/wsl-native-open.patch +29 -49
package/package.json
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
"formatVersion": 1,
|
|
5
5
|
"variants": [
|
|
6
6
|
{
|
|
7
|
-
"dsh": ">=0.1.7-
|
|
7
|
+
"dsh": ">=0.1.7-rc.1",
|
|
8
8
|
"file": "./patches/wsl-native-open.patch",
|
|
9
9
|
"id": "wsl-native-path-translation",
|
|
10
10
|
"target": {
|
|
11
|
-
"baseRevision": "
|
|
11
|
+
"baseRevision": "46a7f68b0922371ce7144b668b90e377d8e799f4",
|
|
12
12
|
"kind": "dsh-source",
|
|
13
13
|
"paths": [
|
|
14
14
|
"packages/host/open-in-app/",
|
|
@@ -32,5 +32,5 @@
|
|
|
32
32
|
"url": "git+https://github.com/SparkElf/deepseek-harness-plus.git"
|
|
33
33
|
},
|
|
34
34
|
"type": "module",
|
|
35
|
-
"version": "0.2.0-rc.
|
|
35
|
+
"version": "0.2.0-rc.23"
|
|
36
36
|
}
|
|
@@ -73,7 +73,7 @@ index 4b07441c8c..519ba1344b 100644
|
|
|
73
73
|
return desktopId === undefined ? null : extractLinuxIcon(desktopId, completed)
|
|
74
74
|
}
|
|
75
75
|
diff --git a/packages/host/open-in-app/src/resolver.ts b/packages/host/open-in-app/src/resolver.ts
|
|
76
|
-
index
|
|
76
|
+
index 970118e22a..ad8d176da4 100644
|
|
77
77
|
--- a/packages/host/open-in-app/src/resolver.ts
|
|
78
78
|
+++ b/packages/host/open-in-app/src/resolver.ts
|
|
79
79
|
@@ -14,10 +14,11 @@
|
|
@@ -177,21 +177,13 @@ index 9ad8e0883c..3377ddcb6f 100644
|
|
|
177
177
|
nativeFileManager,
|
|
178
178
|
revealNativePath,
|
|
179
179
|
diff --git a/packages/util/native-command/src/path-opener.ts b/packages/util/native-command/src/path-opener.ts
|
|
180
|
-
index
|
|
180
|
+
index 67bbc35902..dd062cc003 100644
|
|
181
181
|
--- a/packages/util/native-command/src/path-opener.ts
|
|
182
182
|
+++ b/packages/util/native-command/src/path-opener.ts
|
|
183
|
-
@@ -
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
-import { pathToFileURL } from 'node:url'
|
|
188
|
-
import { runNativeCommand, type NativeCommandRunner } from './runner.ts'
|
|
189
|
-
|
|
190
|
-
/** Testable command boundary; native implementations never invoke a shell. */
|
|
191
|
-
@@ -99,13 +98,49 @@ function isWsl(internals: PathOpenerInternals): boolean {
|
|
192
|
-
return (internals.osRelease ?? osRelease()).toLowerCase().includes('microsoft')
|
|
193
|
-
}
|
|
194
|
-
|
|
183
|
+
@@ -150,8 +150,55 @@ async function runExplorer(args: readonly string[], signal: AbortSignal, run: Pa
|
|
184
|
+
* @param signal - caller lifetime; abort terminates the command.
|
|
185
|
+
* @param run - shell-free command runner.
|
|
186
|
+
*/
|
|
195
187
|
+/**
|
|
196
188
|
+ * Windows PowerShell locations to try when PATH carries no Windows entry.
|
|
197
189
|
+ *
|
|
@@ -201,37 +193,42 @@ index 618efa31b1..1356281211 100644
|
|
|
201
193
|
+ * the volume the distribution mounts, and naming it there is what keeps the Windows
|
|
202
194
|
+ * desktop reachable from those processes.
|
|
203
195
|
+ */
|
|
204
|
-
+const
|
|
205
|
-
+ '/mnt/c/Windows/
|
|
206
|
-
+ '/c/Windows/
|
|
196
|
+
+const WINDOWS_EXPLORER_CANDIDATES = [
|
|
197
|
+
+ '/mnt/c/Windows/explorer.exe',
|
|
198
|
+
+ '/c/Windows/explorer.exe',
|
|
207
199
|
+] as const
|
|
208
200
|
+
|
|
209
|
-
|
|
201
|
+
+/**
|
|
202
|
+
+ * Open one Windows-resolvable path through its registered desktop application.
|
|
203
|
+
+ *
|
|
204
|
+
+ * Explorer resolves the association, but a process whose PATH lost its Windows entries
|
|
205
|
+
+ * cannot name the shell. WSL injects those entries only for the processes it starts
|
|
206
|
+
+ * interactively, so a service or scheduled job resolves nothing by name; naming the
|
|
207
|
+
+ * shell on the volume the distribution mounts keeps the Windows desktop reachable.
|
|
208
|
+
+ * @param path - Windows-resolvable path.
|
|
209
|
+
+ * @param signal - caller lifetime; abort terminates the command.
|
|
210
|
+
+ * @param run - shell-free command runner.
|
|
211
|
+
+ */
|
|
210
212
|
async function openWindowsPath(path: string, signal: AbortSignal, run: PathOpenerRunner): Promise<void> {
|
|
211
|
-
- await
|
|
212
|
-
+ const
|
|
213
|
-
'-NoProfile',
|
|
214
|
-
'-Command',
|
|
215
|
-
`Invoke-Item -LiteralPath ${powershellLiteral(path)}`,
|
|
216
|
-
- ], signal)
|
|
217
|
-
+ ]
|
|
213
|
+
- await runExplorer([explorerTarget(path)], signal, run)
|
|
214
|
+
+ const target = explorerTarget(path)
|
|
218
215
|
+ try {
|
|
219
|
-
+ await
|
|
216
|
+
+ await runExplorer([target], signal, run)
|
|
220
217
|
+ return
|
|
221
218
|
+ } catch (error) {
|
|
222
|
-
+ // A missing executable is the one failure a mounted path can answer;
|
|
223
|
-
+ //
|
|
219
|
+
+ // A missing executable is the one failure a mounted path can answer; any other
|
|
220
|
+
+ // failure is Explorer's own and must stay reported.
|
|
224
221
|
+ if (!isMissingExecutable(error)) throw error
|
|
225
222
|
+ }
|
|
226
|
-
+ for (const candidate of
|
|
223
|
+
+ for (const candidate of WINDOWS_EXPLORER_CANDIDATES) {
|
|
227
224
|
+ try {
|
|
228
|
-
+ await run(candidate,
|
|
225
|
+
+ await run(candidate, [target], signal)
|
|
229
226
|
+ return
|
|
230
227
|
+ } catch (error) {
|
|
231
228
|
+ if (!isMissingExecutable(error)) throw error
|
|
232
229
|
+ }
|
|
233
230
|
+ }
|
|
234
|
-
+ throw new Error('Windows
|
|
231
|
+
+ throw new Error('Windows Explorer is not reachable from this WSL mount')
|
|
235
232
|
+}
|
|
236
233
|
+
|
|
237
234
|
+/** Whether a spawn failed because the executable could not be found at all. */
|
|
@@ -240,7 +237,7 @@ index 618efa31b1..1356281211 100644
|
|
|
240
237
|
}
|
|
241
238
|
|
|
242
239
|
/** Translate a WSL path before handing it to the Windows desktop. */
|
|
243
|
-
@@ -
|
|
240
|
+
@@ -200,6 +247,25 @@ async function openNativePathWithIntent(
|
|
244
241
|
throw new Error(`native path opener is unsupported on ${platform}`)
|
|
245
242
|
}
|
|
246
243
|
|
|
@@ -266,20 +263,3 @@ index 618efa31b1..1356281211 100644
|
|
|
266
263
|
/**
|
|
267
264
|
* Whether {@link openNativePath} plausibly reaches a desktop on this host.
|
|
268
265
|
*
|
|
269
|
-
@@ -257,10 +311,13 @@ export async function revealNativePath(
|
|
270
|
-
windowsPath = translated.stdout.replace(/[\r\n]+$/, '')
|
|
271
|
-
if (windowsPath === '') throw new Error('wslpath returned no Windows path')
|
|
272
|
-
}
|
|
273
|
-
- // Explorer parses commas itself; a file URI preserves commas and whitespace in the path.
|
|
274
|
-
- const target = pathToFileURL(windowsPath, { windows: true }).href.replaceAll(',', '%2C')
|
|
275
|
-
+ // Explorer takes the path itself: `wslpath -w` already produced the spelling it reads.
|
|
276
|
-
+ // A `file://` URL is not interchangeable here — a percent-encoded non-ASCII path (a CJK
|
|
277
|
-
+ // directory such as 题库) fails to resolve, and Explorer then opens its default location
|
|
278
|
-
+ // instead of selecting the file. Measured with a directory it had never opened: the native
|
|
279
|
-
+ // path selected 子目录/测试文件.txt, the URL form changed nothing.
|
|
280
|
-
try {
|
|
281
|
-
- await run('explorer.exe', ['/select,', target], signal)
|
|
282
|
-
+ await run('explorer.exe', ['/select,', windowsPath], signal)
|
|
283
|
-
} catch (error) {
|
|
284
|
-
signal.throwIfAborted()
|
|
285
|
-
// Explorer can exit 1 after delegating to the existing desktop process.
|