Skip to content

Commit 57fe0e5

Browse files
committed
Use path stream reader for jujutsu walker
Run jj file list from the tree root and parse its output with the shared path stream reader. Pass requested paths to jj after -- so paths that start with dashes are handled as path filters. Remove the generic CompositeReader now that all built-in walkers consume the same validated path-filter list.
1 parent f4b79f9 commit 57fe0e5

5 files changed

Lines changed: 75 additions & 315 deletions

File tree

cmd/format/format.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ func Run(v *viper.Viper, statz *stats.Stats, cmd *cobra.Command, paths []string)
125125
}
126126

127127
// create a new walker for traversing the paths
128-
walker, err := walk.NewCompositeReader(walkType, cfg.TreeRoot, paths, db, statz)
128+
walker, err := walk.NewReader(walkType, cfg.TreeRoot, paths, db, statz)
129129
if err != nil {
130130
return fmt.Errorf("failed to create walker: %w", err)
131131
}

walk/git.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package walk
33
import (
44
"fmt"
55

6-
"charm.land/log/v2"
76
"github.com/numtide/treefmt/v2/git"
87
"github.com/numtide/treefmt/v2/stats"
98
)

walk/jujutsu.go

Lines changed: 7 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1,109 +1,17 @@
11
package walk
22

33
import (
4-
"bufio"
5-
"context"
64
"fmt"
7-
"io"
8-
"os"
9-
"os/exec"
10-
"path/filepath"
115

12-
"charm.land/log/v2"
136
"github.com/numtide/treefmt/v2/jujutsu"
147
"github.com/numtide/treefmt/v2/stats"
15-
"golang.org/x/sync/errgroup"
168
)
179

18-
type JujutsuReader struct {
19-
root string
20-
path string
21-
22-
log *log.Logger
23-
stats *stats.Stats
24-
25-
eg *errgroup.Group
26-
scanner *bufio.Scanner
27-
}
28-
29-
func (j *JujutsuReader) Read(ctx context.Context, files []*File) (n int, err error) {
30-
// ensure we record how many files we traversed
31-
defer func() {
32-
j.stats.Add(stats.Traversed, n)
33-
}()
34-
35-
nextLine := func() string {
36-
line := j.scanner.Text()
37-
38-
return line
39-
}
40-
41-
LOOP:
42-
43-
for n < len(files) {
44-
select {
45-
// exit early if the context was cancelled
46-
case <-ctx.Done():
47-
return n, ctx.Err() //nolint:wrapcheck
48-
49-
default:
50-
// read the next file
51-
if j.scanner.Scan() {
52-
entry := nextLine()
53-
54-
path := filepath.Join(j.root, entry)
55-
56-
j.log.Debugf("processing file: %s", path)
57-
58-
info, err := os.Lstat(path)
59-
60-
switch {
61-
case os.IsNotExist(err):
62-
// the underlying file might have been removed
63-
j.log.Warnf(
64-
"Path %s is in the worktree but appears to have been removed from the filesystem", path,
65-
)
66-
67-
continue
68-
case err != nil:
69-
return n, fmt.Errorf("failed to stat %s: %w", path, err)
70-
case info.Mode()&os.ModeSymlink == os.ModeSymlink:
71-
// we skip reporting symlinks stored in Jujutsu, they should
72-
// point to local files which we would list anyway.
73-
continue
74-
}
75-
76-
files[n] = &File{
77-
Path: path,
78-
RelPath: entry,
79-
Info: info,
80-
}
81-
82-
n++
83-
} else {
84-
// nothing more to read
85-
err = io.EOF
86-
87-
break LOOP
88-
}
89-
}
90-
}
91-
92-
return n, err
93-
}
94-
95-
func (j *JujutsuReader) Close() error {
96-
err := j.eg.Wait()
97-
if err != nil {
98-
return fmt.Errorf("failed to wait for jujutsu command to complete: %w", err)
99-
}
100-
101-
return nil
102-
}
10+
type JujutsuReader = PathStreamReader
10311

10412
func NewJujutsuReader(
10513
root string,
106-
path string,
14+
pathFilters []string,
10715
statz *stats.Stats,
10816
) (*JujutsuReader, error) {
10917
// check if the root is a jujutsu repository
@@ -116,42 +24,13 @@ func NewJujutsuReader(
11624
return nil, fmt.Errorf("%s is not a jujutsu repository", root)
11725
}
11826

119-
// create an errgroup for async list task
120-
eg := &errgroup.Group{}
121-
122-
// create a pipe to capture the command output
123-
r, w := io.Pipe()
124-
125-
// create a command which will execute from root
12627
// --ignore-working-copy: Don't snapshot the working copy, and don't update it. This prevents that the user has to
12728
// enter a password for signing the commit. New files also won't be added to the index and not displayed in the
12829
// output.
129-
// Add the subpath as a fileset displaying only files matching this prefix. If
130-
// the subpath is empty ignore it since it interferes with the command
131-
args := []string{"file", "list", "--ignore-working-copy"}
132-
if path != "" {
133-
args = append(args, path)
134-
}
135-
136-
// create the jj command
137-
cmd := exec.CommandContext(context.Background(), "jj", args...)
138-
cmd.Dir = root
139-
cmd.Stdout = w
140-
141-
// execute the command in the background
142-
eg.Go(func() error {
143-
return w.CloseWithError(cmd.Run())
30+
return NewPathStreamReader(root, statz, PathStreamConfig{
31+
Name: "jujutsu",
32+
Command: "jj",
33+
Options: []string{"file", "list", "--ignore-working-copy", "--"},
34+
PathFilters: pathFilters,
14435
})
145-
146-
// create a new scanner for reading the output
147-
scanner := bufio.NewScanner(r)
148-
149-
return &JujutsuReader{
150-
eg: eg,
151-
root: root,
152-
path: path,
153-
stats: statz,
154-
scanner: scanner,
155-
log: log.WithPrefix("walk | jujutsu"),
156-
}, nil
15736
}

walk/jujutsu_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func TestJujutsuReader(t *testing.T) {
2727

2828
// read empty worktree
2929
statz := stats.New()
30-
reader, err := walk.NewJujutsuReader(tempDir, "", &statz)
30+
reader, err := walk.NewJujutsuReader(tempDir, nil, &statz)
3131
as.NoError(err)
3232

3333
files := make([]*walk.File, 33) // The number of files in `test/examples` used for testing
@@ -47,7 +47,7 @@ func TestJujutsuReader(t *testing.T) {
4747
as.NoError(cmd.Run(), "failed to update the index")
4848

4949
statz = stats.New()
50-
reader, err = walk.NewJujutsuReader(tempDir, "", &statz)
50+
reader, err = walk.NewJujutsuReader(tempDir, nil, &statz)
5151
as.NoError(err)
5252

5353
count := 0

0 commit comments

Comments
 (0)