Skip to content

Commit bc3d3be

Browse files
committed
Handle unknown repo tracking state
1 parent 4974a2a commit bc3d3be

2 files changed

Lines changed: 70 additions & 3 deletions

File tree

macos/Sources/Features/Terminal/TerminalRepoPrompt.swift

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ enum TerminalRepoPromptResolution: Equatable {
118118
enum TerminalRepoPrompt {
119119
static func classify(snapshot: TerminalRepoPromptSnapshot) -> TerminalRepoPromptReadyState {
120120
let actionStates = actionStates(for: snapshot)
121-
let primaryAction = actionStates.first(where: \.isAvailable)?.action ?? .commit
121+
let primaryAction = primaryAction(for: snapshot)
122122
let shortcutAction = shortcutAction(for: snapshot, primaryAction: primaryAction)
123123

124124
return .init(
@@ -129,14 +129,32 @@ enum TerminalRepoPrompt {
129129
)
130130
}
131131

132+
private static func primaryAction(for snapshot: TerminalRepoPromptSnapshot) -> TerminalRepoPromptAction {
133+
if snapshot.hasDirtyChanges {
134+
return .commit
135+
}
136+
137+
let trackingKnown = snapshot.gitTracking != nil
138+
let hasUpstream = snapshot.gitTracking?.hasUpstream ?? false
139+
let aheadCount = snapshot.gitTracking?.ahead ?? 0
140+
let needsPush = trackingKnown && (!hasUpstream || aheadCount > 0)
141+
142+
if snapshot.openPR != nil {
143+
return needsPush ? .push : .updatePR
144+
}
145+
146+
return needsPush ? .push : .openPR
147+
}
148+
132149
private static func shortcutAction(
133150
for snapshot: TerminalRepoPromptSnapshot,
134151
primaryAction: TerminalRepoPromptAction
135152
) -> TerminalRepoPromptShortcutState? {
136153
let hasOpenPR = snapshot.openPR != nil
154+
let trackingKnown = snapshot.gitTracking != nil
137155
let hasUpstream = snapshot.gitTracking?.hasUpstream ?? false
138156
let aheadCount = snapshot.gitTracking?.ahead ?? 0
139-
let needsPush = !hasUpstream || aheadCount > 0
157+
let needsPush = trackingKnown && (!hasUpstream || aheadCount > 0)
140158

141159
switch primaryAction {
142160
case .commit:
@@ -167,9 +185,10 @@ enum TerminalRepoPrompt {
167185
) -> [TerminalRepoPromptActionState] {
168186
let hasDirtyChanges = snapshot.hasDirtyChanges
169187
let hasOpenPR = snapshot.openPR != nil
188+
let trackingKnown = snapshot.gitTracking != nil
170189
let hasUpstream = snapshot.gitTracking?.hasUpstream ?? false
171190
let aheadCount = snapshot.gitTracking?.ahead ?? 0
172-
let needsPush = !hasUpstream || aheadCount > 0
191+
let needsPush = trackingKnown && (!hasUpstream || aheadCount > 0)
173192

174193
return TerminalRepoPromptAction.menuActions.map { action in
175194
switch action {
@@ -197,6 +216,20 @@ enum TerminalRepoPrompt {
197216
)
198217
}
199218

219+
if !trackingKnown {
220+
let description = if hasOpenPR {
221+
"Push the current branch to the existing PR branch if needed."
222+
} else {
223+
"Push the current branch and set upstream if needed."
224+
}
225+
226+
return .init(
227+
action: action,
228+
isAvailable: true,
229+
description: description
230+
)
231+
}
232+
200233
if needsPush {
201234
let description = if hasOpenPR {
202235
"Push the current branch to the existing PR branch."

macos/Tests/TerminalRepoPromptTests.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,23 @@ struct TerminalRepoPromptTests {
118118
#expect(ready.state(for: .push)?.description == "Nothing to push.")
119119
}
120120

121+
@Test func cleanSnapshotWithoutTrackingResolvesToOpenPR() {
122+
let snapshot = TerminalRepoPromptSnapshot(
123+
repoRoot: "/tmp/repo",
124+
branch: "feature/repo-prompts",
125+
sessions: [session()],
126+
hasDirtyChanges: false,
127+
openPR: nil,
128+
gitTracking: nil
129+
)
130+
131+
let ready = TerminalRepoPrompt.classify(snapshot: snapshot)
132+
#expect(ready.primaryAction == .openPR)
133+
#expect(ready.shortcutAction == nil)
134+
#expect(ready.state(for: .openPR)?.isAvailable == true)
135+
#expect(ready.state(for: .push)?.isAvailable == true)
136+
}
137+
121138
@Test func cleanSnapshotWithOpenPRAndAheadResolvesToPush() {
122139
let snapshot = TerminalRepoPromptSnapshot(
123140
repoRoot: "/tmp/repo",
@@ -171,6 +188,23 @@ struct TerminalRepoPromptTests {
171188
#expect(ready.state(for: .push)?.description == "Nothing to push.")
172189
}
173190

191+
@Test func cleanSnapshotWithOpenPRAndUnknownTrackingResolvesToUpdatePR() {
192+
let snapshot = TerminalRepoPromptSnapshot(
193+
repoRoot: "/tmp/repo",
194+
branch: "feature/repo-prompts",
195+
sessions: [session()],
196+
hasDirtyChanges: false,
197+
openPR: openPR(),
198+
gitTracking: nil
199+
)
200+
201+
let ready = TerminalRepoPrompt.classify(snapshot: snapshot)
202+
#expect(ready.primaryAction == .updatePR)
203+
#expect(ready.shortcutAction == nil)
204+
#expect(ready.state(for: .updatePR)?.isAvailable == true)
205+
#expect(ready.state(for: .push)?.isAvailable == true)
206+
}
207+
174208
@Test func openPRPromptIsCompactAndIncludesHeaderRule() {
175209
let snapshot = TerminalRepoPromptSnapshot(
176210
repoRoot: "/tmp/repo",

0 commit comments

Comments
 (0)