1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
package internalgitaly
import (
"context"
"os"
"path/filepath"
"gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/storage"
"gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/timestamppb"
)
func (s *server) WalkRepos(req *gitalypb.WalkReposRequest, stream gitalypb.InternalGitaly_WalkReposServer) error {
sPath, err := s.storagePath(req.GetStorageName())
if err != nil {
return err
}
return walkStorage(stream.Context(), sPath, stream)
}
func (s *server) storagePath(storageName string) (string, error) {
for _, storage := range s.storages {
if storage.Name == storageName {
return storage.Path, nil
}
}
return "", status.Errorf(
codes.NotFound,
"storage name %q not found", storageName,
)
}
func walkStorage(ctx context.Context, storagePath string, stream gitalypb.InternalGitaly_WalkReposServer) error {
return filepath.Walk(storagePath, func(path string, info os.FileInfo, err error) error {
if err != nil {
if os.IsNotExist(err) {
return nil
}
return err
}
select {
case <-ctx.Done():
return ctx.Err()
default:
// keep walking
}
if storage.IsGitDirectory(path) {
relPath, err := filepath.Rel(storagePath, path)
if err != nil {
return err
}
gitDirInfo, err := os.Stat(path)
if err != nil {
return err
}
if err := stream.Send(&gitalypb.WalkReposResponse{
RelativePath: relPath,
ModificationTime: timestamppb.New(gitDirInfo.ModTime()),
}); err != nil {
return err
}
// once we know we are inside a git directory, we don't
// want to continue walking inside since that is
// resource intensive and unnecessary
return filepath.SkipDir
}
return nil
})
}
|