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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
package config
import (
"os"
"path/filepath"
"gitlab.com/gitlab-org/gitaly/v15/internal/git/repository"
"gitlab.com/gitlab-org/gitaly/v15/internal/gitaly/storage"
"gitlab.com/gitlab-org/gitaly/v15/internal/helper"
)
const (
// tmpRootPrefix is the directory in which we store temporary
// directories.
tmpRootPrefix = GitalyDataPrefix + "/tmp"
// cachePrefix is the directory where all cache data is stored on a
// storage location.
cachePrefix = GitalyDataPrefix + "/cache"
// statePrefix is the directory where all state data is stored on a
// storage location.
statePrefix = GitalyDataPrefix + "/state"
)
// NewLocator returns locator based on the provided configuration struct.
// As it creates a shallow copy of the provided struct changes made into provided struct
// may affect result of methods implemented by it.
func NewLocator(conf Cfg) storage.Locator {
return &configLocator{conf: conf}
}
type configLocator struct {
conf Cfg
}
// GetRepoPath returns the full path of the repository referenced by an
// RPC Repository message. It verifies the path is an existing git directory.
// The errors returned are gRPC errors with relevant error codes and should
// be passed back to gRPC without further decoration.
func (l *configLocator) GetRepoPath(repo repository.GitRepo) (string, error) {
repoPath, err := l.GetPath(repo)
if err != nil {
return "", err
}
if storage.IsGitDirectory(repoPath) {
return repoPath, nil
}
return "", helper.ErrNotFoundf("GetRepoPath: not a git repository: %q", repoPath)
}
// GetPath returns the path of the repo passed as first argument. An error is
// returned when either the storage can't be found or the path includes
// constructs trying to perform directory traversal.
func (l *configLocator) GetPath(repo repository.GitRepo) (string, error) {
storagePath, err := l.GetStorageByName(repo.GetStorageName())
if err != nil {
return "", err
}
if _, err := os.Stat(storagePath); err != nil {
if os.IsNotExist(err) {
return "", helper.ErrNotFoundf("GetPath: does not exist: %v", err)
}
return "", helper.ErrInternalf("GetPath: storage path: %v", err)
}
relativePath := repo.GetRelativePath()
if len(relativePath) == 0 {
err := helper.ErrInvalidArgumentf("GetPath: relative path missing from %+v", repo)
return "", err
}
if _, err := storage.ValidateRelativePath(storagePath, relativePath); err != nil {
return "", helper.ErrInvalidArgumentf("GetRepoPath: %s", err)
}
return filepath.Join(storagePath, relativePath), nil
}
// GetStorageByName will return the path for the storage, which is fetched by
// its key. An error is return if it cannot be found.
func (l *configLocator) GetStorageByName(storageName string) (string, error) {
storagePath, ok := l.conf.StoragePath(storageName)
if !ok {
return "", helper.ErrInvalidArgumentf("GetStorageByName: no such storage: %q", storageName)
}
return storagePath, nil
}
// CacheDir returns the path to the cache dir for a storage.
func (l *configLocator) CacheDir(storageName string) (string, error) {
return l.getPath(storageName, cachePrefix)
}
// StateDir returns the path to the state dir for a storage.
func (l *configLocator) StateDir(storageName string) (string, error) {
return l.getPath(storageName, statePrefix)
}
// TempDir returns the path to the temp dir for a storage.
func (l *configLocator) TempDir(storageName string) (string, error) {
return l.getPath(storageName, tmpRootPrefix)
}
func (l *configLocator) getPath(storageName, prefix string) (string, error) {
storagePath, ok := l.conf.StoragePath(storageName)
if !ok {
return "", helper.ErrInvalidArgumentf("%s dir: no such storage: %q",
filepath.Base(prefix), storageName)
}
return filepath.Join(storagePath, prefix), nil
}
|