Skip to content

Commit 1bf9177

Browse files
authored
[0.16] fix(submit): panic when there are merged downstack nodes (#790)
Cherry picks #789 from main. When the 'spice.submit.navigationCommentSync' is set to 'downstack', we traverse the downstack nodes to update their navigation comments. This logic did not account for the possibility of some downstack nodes being already merged, which means they do not have corresponding infos entries. Resolves #788
1 parent 06c4d74 commit 1bf9177

File tree

5 files changed

+87
-4
lines changed

5 files changed

+87
-4
lines changed

.changes/v0.16.1.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## <a name="v0.16.1">v0.16.1</a> - 2025-08-08
2+
### Fixed
3+
- Fix panic when the 'spice.submit.navigationCommentSync' configuration option is set to 'downstack', and one of the downstacks has already been merged.

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html),
66
and is generated by [Changie](https://github.com/miniscruff/changie).
77

8+
## <a name="v0.16.1">v0.16.1</a> - 2025-08-08
9+
### Fixed
10+
- Fix panic when the 'spice.submit.navigationCommentSync' configuration option is set to 'downstack', and one of the downstacks has already been merged.
11+
812
## <a name="v0.16.0">v0.16.0</a> - 2025-08-02
913

1014
This release contains a number of improvements.

internal/handler/submit/nav_comment.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,13 @@ func updateNavigationComments(
224224

225225
baseIdx := nodes[nodeIdx].Base
226226
for baseIdx != -1 {
227-
updateBranches[baseIdx] = struct{}{}
227+
// Only add tracked branches
228+
// that have corresponding infos entries.
229+
// Merged downstack nodes don't have info
230+
// and can't be commented on.
231+
if baseIdx < len(infos) {
232+
updateBranches[baseIdx] = struct{}{}
233+
}
228234
baseIdx = nodes[baseIdx].Base
229235
}
230236
}

internal/handler/submit/nav_comment_test.go

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ import (
2222

2323
func TestUpdateNavigationComments(t *testing.T) {
2424
type trackedBranch struct {
25-
Name string
26-
Base string // empty = trunk
27-
ChangeID int // 0 = unsubmitted
25+
Name string
26+
Base string // empty = trunk
27+
ChangeID int // 0 = unsubmitted
28+
MergedDownstack []int // list of merged downstack change IDs
2829
}
2930

3031
tests := []struct {
@@ -273,6 +274,42 @@ func TestUpdateNavigationComments(t *testing.T) {
273274
),
274275
},
275276
},
277+
{
278+
// Regression test for https://github.com/abhinav/git-spice/issues/788
279+
name: "MergedDownstack",
280+
trackedBranches: []trackedBranch{
281+
{Name: "feat1", ChangeID: 123, MergedDownstack: []int{100, 101}},
282+
{Name: "feat2", Base: "feat1", ChangeID: 124},
283+
{Name: "feat3", Base: "feat2", ChangeID: 125},
284+
},
285+
sync: NavCommentSyncDownstack,
286+
submit: []string{"feat3"},
287+
// This should not panic when accessing infos[idx]
288+
// where idx corresponds to merged downstack nodes
289+
wantComments: map[int]string{
290+
123: joinLines(
291+
"- #100",
292+
" - #101",
293+
" - #123 ◀",
294+
" - #124",
295+
" - #125",
296+
),
297+
124: joinLines(
298+
"- #100",
299+
" - #101",
300+
" - #123",
301+
" - #124 ◀",
302+
" - #125",
303+
),
304+
125: joinLines(
305+
"- #100",
306+
" - #101",
307+
" - #123",
308+
" - #124",
309+
" - #125 ◀",
310+
),
311+
},
312+
},
276313
}
277314

278315
for _, tt := range tests {
@@ -301,6 +338,14 @@ func TestUpdateNavigationComments(t *testing.T) {
301338
}
302339
}
303340

341+
// Add merged downstack entries if any
342+
for _, mergedID := range b.MergedDownstack {
343+
mergedMeta := &shamhub.ChangeMetadata{Number: mergedID}
344+
mergedJSON, err := json.Marshal(mergedMeta)
345+
require.NoError(t, err)
346+
item.MergedDownstack = append(item.MergedDownstack, mergedJSON)
347+
}
348+
304349
items[i] = item
305350
}
306351

@@ -318,6 +363,16 @@ func TestUpdateNavigationComments(t *testing.T) {
318363
return json.Marshal(md)
319364
}).
320365
AnyTimes()
366+
mockForge.EXPECT().
367+
UnmarshalChangeID(gomock.Any()).
368+
DoAndReturn(func(data json.RawMessage) (forge.ChangeID, error) {
369+
var md shamhub.ChangeMetadata
370+
if err := json.Unmarshal(data, &md); err != nil {
371+
return nil, err
372+
}
373+
return shamhub.ChangeID(md.Number), nil
374+
}).
375+
AnyTimes()
321376

322377
mockRemoteRepo := forgetest.NewMockRepository(ctrl)
323378
mockRemoteRepo.EXPECT().Forge().Return(mockForge).AnyTimes()

testdata/script/branch_submit_navigation_comment_sync_downstack.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,21 @@ gs bs --fill
4040
shamhub dump comments
4141
cmp stdout $WORK/golden/all-comments.txt
4242

43+
# Merge a change and update.
44+
shamhub merge alice/example 1
45+
gs repo sync
46+
gs stack restack
47+
48+
# Re-submit each branch
49+
gs bco feature2
50+
gs branch submit
51+
gs bco feature3
52+
gs branch submit
53+
54+
# Comments are the same.
55+
shamhub dump comments
56+
cmp stdout $WORK/golden/all-comments.txt
57+
4358
-- repo/feature1.txt --
4459
feature 1
4560

0 commit comments

Comments
 (0)