Skip to content

Commit fda9dc3

Browse files
authored
Release 0.17.1 (#853)
Backport PRs to 0.17 branch: - #830 - #831 - #852 Primarily, this is to release a bugfix that may fix #849, but also pulling in other bugfixes while at it.
1 parent e3aad17 commit fda9dc3

File tree

22 files changed

+661
-287
lines changed

22 files changed

+661
-287
lines changed

.changes/v0.17.1.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
## <a name="v0.17.1">v0.17.1</a> - 2025-09-13
2+
### Fixed
3+
- log: When used without `--all`, query only requested branches internally. This was wasted work and slowed the command down in repositories with many branches.
4+
- log: List all tracked branches when run from an untracked branch or detached HEAD. Previously, this behavior was undefined.
5+
- Fix incorrect paths being logged when autostashed changes fail to reapply after a rebase operation.

.github/workflows/ci.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ on:
44
push:
55
branches: [ main ]
66
pull_request:
7-
branches: [ '*' ]
87
workflow_dispatch:
98

109
concurrency:

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ 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.17.1">v0.17.1</a> - 2025-09-13
9+
### Fixed
10+
- log: When used without `--all`, query only requested branches internally. This was wasted work and slowed the command down in repositories with many branches.
11+
- log: List all tracked branches when run from an untracked branch or detached HEAD. Previously, this behavior was undefined.
12+
- Fix incorrect paths being logged when autostashed changes fail to reapply after a rebase operation.
13+
814
## <a name="v0.17.0">v0.17.0</a> - 2025-08-25
915
### Added
1016
- submit: Add 'spice.submit.updateOnly' configuration option to default to --update-only for upstack, downstack, and stack submit operations.

doc/mise.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/forge/github/label.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,7 @@ func (r *Repository) ensureLabels(ctx context.Context, labelNames []string) ([]g
6565
// One query instead of many.
6666
labelIDs := make([]githubv4.ID, len(labelNames)) // pre-allocate to fill without locking
6767
for range runtime.GOMAXPROCS(0) {
68-
wg.Add(1)
69-
go func() {
70-
defer wg.Done()
71-
68+
wg.Go(func() {
7269
for idx := range idxc {
7370
labelName := labelNames[idx]
7471

@@ -83,7 +80,7 @@ func (r *Repository) ensureLabels(ctx context.Context, labelNames []string) ([]g
8380
r.log.Debug("Resolved label ID", "name", labelName, "id", labelID)
8481
labelIDs[idx] = labelID
8582
}
86-
}()
83+
})
8784
}
8885

8986
for idx := range labelNames {

internal/git/files_wt.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"context"
66
"fmt"
77
"iter"
8+
9+
"go.abhg.dev/gs/internal/scanutil"
810
)
911

1012
// ListFilesOptions shows information about files
@@ -18,15 +20,15 @@ type ListFilesOptions struct {
1820
// using the given options to filter.
1921
func (w *Worktree) ListFilesPaths(ctx context.Context, opts *ListFilesOptions) iter.Seq2[string, error] {
2022
opts = cmp.Or(opts, &ListFilesOptions{})
21-
args := []string{"ls-files", "--format=%(path)"}
23+
args := []string{"ls-files", "-z", "--format=%(path)"}
2224
if opts.Unmerged {
2325
args = append(args, "--unmerged")
2426
}
2527

2628
shown := make(map[string]struct{})
2729
return func(yield func(string, error) bool) {
2830
cmd := w.gitCmd(ctx, args...)
29-
for line, err := range cmd.ScanLines(w.exec) {
31+
for line, err := range cmd.Scan(w.exec, scanutil.SplitNull) {
3032
if err != nil {
3133
yield("", fmt.Errorf("git ls-files: %w", err))
3234
continue

internal/git/files_wt_test.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package git_test
22

33
import (
4+
"runtime"
45
"testing"
56

67
"github.com/stretchr/testify/assert"
@@ -101,3 +102,70 @@ func TestListFilesPaths_unmerged(t *testing.T) {
101102
assert.Equal(t, []string{"conflict.txt"}, paths)
102103
})
103104
}
105+
106+
func TestListFilesPaths_specialCharacters(t *testing.T) {
107+
t.Parallel()
108+
109+
// Windows doesn't like files with some of these names.
110+
// Skip this test on Windows.
111+
if runtime.GOOS == "windows" {
112+
t.Skip("skipping test on Windows")
113+
}
114+
115+
fixture, err := gittest.LoadFixtureScript([]byte(text.Dedent(`
116+
as 'Test <[email protected]>'
117+
at '2025-06-21T09:27:19Z'
118+
119+
git init
120+
mv just-blank.txt ' '
121+
git add ' '
122+
git add *.txt
123+
git commit -m 'Add files with special characters'
124+
125+
-- just-blank.txt --
126+
file with a name that's just " ".
127+
128+
-- file with spaces.txt --
129+
Contents with spaces
130+
131+
-- file"quotes".txt --
132+
Contents with double quotes
133+
134+
-- file'single'.txt --
135+
Contents with single quotes
136+
137+
-- file (parens).txt --
138+
Contents with parentheses
139+
140+
-- file[brackets].txt --
141+
Contents with brackets
142+
143+
-- file&ampersand.txt --
144+
Contents with ampersand
145+
146+
-- файл.txt --
147+
Unicode content
148+
`)))
149+
require.NoError(t, err)
150+
t.Cleanup(fixture.Cleanup)
151+
152+
wt, err := git.OpenWorktree(t.Context(), fixture.Dir(), git.OpenOptions{
153+
Log: silogtest.New(t),
154+
})
155+
require.NoError(t, err)
156+
157+
paths, err := sliceutil.CollectErr(wt.ListFilesPaths(t.Context(), nil))
158+
require.NoError(t, err)
159+
160+
expected := []string{
161+
"file with spaces.txt",
162+
`file"quotes".txt`,
163+
"file'single'.txt",
164+
"file (parens).txt",
165+
"file[brackets].txt",
166+
"file&ampersand.txt",
167+
"файл.txt",
168+
" ",
169+
}
170+
assert.ElementsMatch(t, expected, paths)
171+
}

internal/git/rebase_wt.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ func (w *Worktree) Rebase(ctx context.Context, req RebaseRequest) (err error) {
131131
w.log.Error("Dirty changes in the worktree were stashed, but could not be re-applied.")
132132
w.log.Error("The following files were left unmerged:")
133133
for _, file := range unmergedFiles {
134-
w.log.Error(" - " + file)
134+
w.log.Error(" - " + silog.MaybeQuote(file))
135135
}
136136
w.log.Error("Resolve the conflict and run 'git stash drop' to remove the stash entry.")
137137
w.log.Error("Or change to a branch where the stash can apply, and run 'git stash pop'.")

internal/git/remote_test.go

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,12 @@ func TestRepositoryListRemoteRefs(t *testing.T) {
2424
mockExecer.EXPECT().
2525
Start(gomock.Any()).
2626
Do(func(cmd *exec.Cmd) error {
27-
wg.Add(1)
28-
go func() {
29-
defer wg.Done()
30-
27+
wg.Go(func() {
3128
_, _ = io.WriteString(cmd.Stdout, "abc123\trefs/heads/main\n")
3229
_, _ = io.WriteString(cmd.Stdout, "malformed entry is ignored\n")
3330
_, _ = io.WriteString(cmd.Stdout, "def456\trefs/heads/feature\n")
3431
assert.NoError(t, cmd.Stdout.(io.Closer).Close())
35-
}()
32+
})
3633
return nil
3734
})
3835
mockExecer.EXPECT().
@@ -70,15 +67,12 @@ func TestRepositoryListRemoteRefsOptions(t *testing.T) {
7067
"--heads", "origin", "refs/heads/feat*",
7168
}, cmd.Args[1:])
7269

73-
wg.Add(1)
74-
go func() {
75-
defer wg.Done()
76-
70+
wg.Go(func() {
7771
_, _ = io.WriteString(cmd.Stdout, "abc123\trefs/heads/feat1\n")
7872
_, _ = io.WriteString(cmd.Stdout, "def456\trefs/heads/feat2\n")
7973
_, _ = io.WriteString(cmd.Stdout, "ghi789\trefs/heads/feat3\n")
8074
assert.NoError(t, cmd.Stdout.(io.Closer).Close())
81-
}()
75+
})
8276
return nil
8377
})
8478
mockExecer.EXPECT().

0 commit comments

Comments
 (0)