| ... | @@ -33,6 +33,7 @@ export type SourceControlCliDiscoverySpec = SourceControlDiscoverySpecBase & { | ... | @@ -33,6 +33,7 @@ export type SourceControlCliDiscoverySpec = SourceControlDiscoverySpecBase & { |
| 33 | readonly executable: string; | 33 | readonly executable: string; |
| 34 | readonly versionArgs: ReadonlyArray<string>; | 34 | readonly versionArgs: ReadonlyArray<string>; |
| 35 | readonly authArgs: ReadonlyArray<string>; | 35 | readonly authArgs: ReadonlyArray<string>; |
| | 36 | readonly probeTimeoutMs?: number; |
| 36 | readonly parseAuth: (input: SourceControlAuthProbeInput) => SourceControlProviderAuth; | 37 | readonly parseAuth: (input: SourceControlAuthProbeInput) => SourceControlProviderAuth; |
| 37 | readonly refineUnknownRemote?: ( | 38 | readonly refineUnknownRemote?: ( |
| 38 | input: SourceControlUnknownRemoteRefinementInput, | 39 | input: SourceControlUnknownRemoteRefinementInput, |
| ... | @@ -52,6 +53,14 @@ type SourceControlCliRemoteRefinementSpec = SourceControlCliDiscoverySpec & { | ... | @@ -52,6 +53,14 @@ type SourceControlCliRemoteRefinementSpec = SourceControlCliDiscoverySpec & { |
| 52 | readonly refineUnknownRemote: NonNullable<SourceControlCliDiscoverySpec["refineUnknownRemote"]>; | 53 | readonly refineUnknownRemote: NonNullable<SourceControlCliDiscoverySpec["refineUnknownRemote"]>; |
| 53 | }; | 54 | }; |
| 54 | | 55 | |
| | 56 | // Most provider CLIs answer `--version` in well under a second, so a short budget keeps |
| | 57 | // discovery snappy. Specs whose CLI is known to be slower can raise it via probeTimeoutMs. |
| | 58 | const DEFAULT_PROBE_TIMEOUT_MS = 5_000; |
| | 59 | |
| | 60 | function probeTimeoutMs(spec: SourceControlCliDiscoverySpec): number { |
| | 61 | return spec.probeTimeoutMs ?? DEFAULT_PROBE_TIMEOUT_MS; |
| | 62 | } |
| | 63 | |
| 55 | interface DiscoveryProbeResult { | 64 | interface DiscoveryProbeResult { |
| 56 | readonly kind: SourceControlProviderKind; | 65 | readonly kind: SourceControlProviderKind; |
| 57 | readonly label: string; | 66 | readonly label: string; |
| ... | @@ -167,7 +176,7 @@ function probeCli(input: { | ... | @@ -167,7 +176,7 @@ function probeCli(input: { |
| 167 | command: input.spec.executable, | 176 | command: input.spec.executable, |
| 168 | args: input.spec.versionArgs, | 177 | args: input.spec.versionArgs, |
| 169 | cwd: input.cwd, | 178 | cwd: input.cwd, |
| 170 | timeoutMs: 5_000, | 179 | timeoutMs: probeTimeoutMs(input.spec), |
| 171 | maxOutputBytes: 8_000, | 180 | maxOutputBytes: 8_000, |
| 172 | appendTruncationMarker: true, | 181 | appendTruncationMarker: true, |
| 173 | }) | 182 | }) |
| ... | @@ -244,7 +253,7 @@ export function probeSourceControlProvider(input: { | ... | @@ -244,7 +253,7 @@ export function probeSourceControlProvider(input: { |
| 244 | args: spec.authArgs, | 253 | args: spec.authArgs, |
| 245 | cwd: input.cwd, | 254 | cwd: input.cwd, |
| 246 | allowNonZeroExit: true, | 255 | allowNonZeroExit: true, |
| 247 | timeoutMs: 5_000, | 256 | timeoutMs: probeTimeoutMs(spec), |
| 248 | maxOutputBytes: 8_000, | 257 | maxOutputBytes: 8_000, |
| 249 | appendTruncationMarker: true, | 258 | appendTruncationMarker: true, |
| 250 | }) | 259 | }) |
| ... | @@ -287,7 +296,7 @@ export const refineUnknownRemoteProvider = Effect.fn("refineUnknownRemoteProvide | ... | @@ -287,7 +296,7 @@ export const refineUnknownRemoteProvider = Effect.fn("refineUnknownRemoteProvide |
| 287 | args: spec.authArgs, | 296 | args: spec.authArgs, |
| 288 | cwd: input.cwd, | 297 | cwd: input.cwd, |
| 289 | allowNonZeroExit: true, | 298 | allowNonZeroExit: true, |
| 290 | timeoutMs: 5_000, | 299 | timeoutMs: probeTimeoutMs(spec), |
| 291 | maxOutputBytes: 8_000, | 300 | maxOutputBytes: 8_000, |
| 292 | appendTruncationMarker: true, | 301 | appendTruncationMarker: true, |
| 293 | }) | 302 | }) |