@@ -2,6 +2,7 @@ import { type ExecFileException, execFile, spawn } from "node:child_process";
22import { promisify } from "node:util" ;
33import * as vscode from "vscode" ;
44
5+ import { toError } from "../error/errorUtils" ;
56import {
67 type CliAuth ,
78 getGlobalFlags ,
@@ -22,6 +23,23 @@ const execFileAsync = promisify(execFile);
2223// and we have to make our own.
2324type ExecException = ExecFileException & { stdout ?: string ; stderr ?: string } ;
2425
26+ /** Prefer stderr over the default message which includes the full command line. */
27+ function cliError ( error : unknown ) : Error {
28+ const stderr = ( error as ExecException ) ?. stderr ?. trim ( ) ;
29+ if ( stderr ) {
30+ return new Error ( stderr , { cause : error } ) ;
31+ }
32+ return toError ( error ) ;
33+ }
34+
35+ /** Go duration regex: one or more {number}{unit} segments (e.g. 5s, 1h30m). */
36+ const GO_DURATION_RE = / ^ ( \d + ( \. \d + ) ? ( n s | u s | µ s | m s | s | m | h ) ) + $ / ;
37+
38+ /** Returns true if the string is a valid Go duration. */
39+ export function isGoDuration ( value : string ) : boolean {
40+ return GO_DURATION_RE . test ( value ) ;
41+ }
42+
2543/**
2644 * Return the version from the binary. Throw if unable to execute the binary or
2745 * find the version for any reason.
@@ -49,7 +67,7 @@ export async function version(binPath: string): Promise<string> {
4967 return v ;
5068 }
5169 }
52- throw error ;
70+ throw cliError ( error ) ;
5371 }
5472
5573 const json = JSON . parse ( stdout ) as { version ?: string } ;
@@ -73,8 +91,12 @@ export async function speedtest(
7391 if ( duration ) {
7492 args . push ( "-t" , duration ) ;
7593 }
76- const result = await execFileAsync ( env . binary , args , { signal } ) ;
77- return result . stdout ;
94+ try {
95+ const result = await execFileAsync ( env . binary , args , { signal } ) ;
96+ return result . stdout ;
97+ } catch ( error ) {
98+ throw cliError ( error ) ;
99+ }
78100}
79101
80102/**
@@ -232,7 +254,7 @@ export async function openAppStatusTerminal(
232254 const globalFlags = getGlobalShellFlags ( env . configs , env . auth ) ;
233255 const terminal = vscode . window . createTerminal ( app . name ) ;
234256 terminal . sendText (
235- `${ escapeCommandArg ( env . binary ) } ${ globalFlags . join ( " " ) } ssh ${ app . workspace_name } ` ,
257+ `${ escapeCommandArg ( env . binary ) } ${ globalFlags . join ( " " ) } ssh ${ escapeCommandArg ( app . workspace_name ) } ` ,
236258 ) ;
237259 await new Promise ( ( resolve ) => setTimeout ( resolve , 5000 ) ) ;
238260 terminal . sendText ( app . command ?? "" ) ;
0 commit comments