fix(repo): make the remote .git probe verdict a discriminated union

Promise<string | null | 'unverifiable'> collapses: the literal is subsumed by
string, so callers got no type help distinguishing 'could not look' from a
real signature. The three outcomes are now structurally distinct.
This commit is contained in:
Brennan Benson
2026-08-20 18:28:17 -07:00
parent 5e0d243126
commit a7d93aefb7
2 changed files with 22 additions and 13 deletions
+19 -6
View File
@@ -103,27 +103,40 @@ function isRemoteMissingPathError(error: unknown): boolean {
return /\bENOENT\b|no such file|not found/i.test(message)
}
/**
* Remote `.git` probe verdict. A bare `string | 'unverifiable'` union collapses —
* the literal is subsumed by `string`, so callers get no type help distinguishing
* "could not look" from a signature. Keep the three outcomes structurally distinct.
*/
export type RemoteGitMarkerSignature =
| { status: 'present'; signature: string }
| { status: 'absent' }
| { status: 'unverifiable' }
export async function readRemoteGitMarkerSignature(
repo: Pick<Repo, 'path' | 'connectionId'>
): Promise<string | null | 'unverifiable'> {
): Promise<RemoteGitMarkerSignature> {
const connectionId = repo.connectionId
if (!connectionId) {
return 'unverifiable'
return { status: 'unverifiable' }
}
const filesystem = getSshFilesystemProvider(connectionId)
const git = getSshGitProvider(connectionId)
const host = git?.getHostPlatform()
if (!filesystem || !git || !host) {
return 'unverifiable'
return { status: 'unverifiable' }
}
try {
const marker = await filesystem.stat(joinRemotePath(host, repo.path, '.git'))
return `${marker.mtimeMs ?? marker.mtime}:${marker.ino ?? 0}:${marker.type}`
return {
status: 'present',
signature: `${marker.mtimeMs ?? marker.mtime}:${marker.ino ?? 0}:${marker.type}`
}
} catch (error) {
if (isRemoteMissingPathError(error)) {
return null
return { status: 'absent' }
}
return 'unverifiable'
return { status: 'unverifiable' }
}
}
+3 -7
View File
@@ -152,16 +152,12 @@ async function pollOnce(watch: UpgradeWatch): Promise<void> {
const key = candidateKey(repo)
liveKeys.add(key)
if (isSshCandidate(repo)) {
const signature = await readRemoteGitMarkerSignature(repo)
if (
signature === 'unverifiable' ||
signature === null ||
rejectedMarkers.get(key) === signature
) {
const marker = await readRemoteGitMarkerSignature(repo)
if (marker.status !== 'present' || rejectedMarkers.get(key) === marker.signature) {
continue
}
if ((await upgradeSshFolderRepo(watch, repo)) === 'rejected') {
rejectedMarkers.set(key, signature)
rejectedMarkers.set(key, marker.signature)
}
continue
}