-
Notifications
You must be signed in to change notification settings - Fork 123
/
repository_pool.go
145 lines (119 loc) · 2.98 KB
/
repository_pool.go
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package gitbase
import (
"fmt"
"io"
"github.com/src-d/go-borges"
billy "gopkg.in/src-d/go-billy.v4"
errors "gopkg.in/src-d/go-errors.v1"
git "gopkg.in/src-d/go-git.v4"
"gopkg.in/src-d/go-git.v4/plumbing/cache"
"gopkg.in/src-d/go-git.v4/storage/filesystem"
)
var (
errRepoAlreadyRegistered = errors.NewKind("the repository is already registered: %s")
gitStorerOptions = filesystem.Options{
ExclusiveAccess: true,
KeepDescriptors: true,
}
)
type Repository struct {
*git.Repository
cache cache.Object
repo borges.Repository
lib borges.Library
}
func NewRepository(
lib borges.Library,
repo borges.Repository,
cache cache.Object,
) *Repository {
return &Repository{
Repository: repo.R(),
lib: lib,
repo: repo,
cache: cache,
}
}
func (r *Repository) ID() string {
return r.repo.ID().String()
}
func (r *Repository) FS() (billy.Filesystem, error) {
fs := r.repo.FS()
if fs == nil {
return nil, fmt.Errorf("filesystem inaccesible")
}
return fs, nil
}
func (r *Repository) Cache() cache.Object {
return r.cache
}
func (r *Repository) Close() error {
if r != nil && r.repo != nil {
if closer, ok := r.repo.(io.Closer); ok {
return closer.Close()
}
}
return nil
}
// RepositoryPool holds a pool git repository paths and
// functionality to open and iterate them.
type RepositoryPool struct {
cache cache.Object
library borges.Library
}
// NewRepositoryPool holds a repository library and a shared object cache.
func NewRepositoryPool(
c cache.Object,
lib borges.Library,
) *RepositoryPool {
return &RepositoryPool{
cache: c,
library: lib,
}
}
// ErrPoolRepoNotFound is returned when a repository id is not present in the pool.
var ErrPoolRepoNotFound = errors.NewKind("repository id %s not found in the pool")
// GetRepo returns a repository with the given id from the pool.
func (p *RepositoryPool) GetRepo(id string) (*Repository, error) {
i := borges.RepositoryID(id)
repo, err := p.library.Get(i, borges.ReadOnlyMode)
if err != nil {
if borges.ErrRepositoryNotExists.Is(err) {
return nil, ErrPoolRepoNotFound.New(id)
}
return nil, err
}
r := NewRepository(p.library, repo, p.cache)
return r, nil
}
// RepoIter creates a new Repository iterator
func (p *RepositoryPool) RepoIter() (*RepositoryIter, error) {
it, err := p.library.Repositories(borges.ReadOnlyMode)
if err != nil {
return nil, err
}
iter := &RepositoryIter{
pool: p,
iter: it,
}
return iter, nil
}
// RepositoryIter iterates over all repositories in the pool
type RepositoryIter struct {
pool *RepositoryPool
iter borges.RepositoryIterator
}
// Next retrieves the next Repository. It returns io.EOF as error
// when there are no more Repositories to retrieve.
func (i *RepositoryIter) Next() (*Repository, error) {
repo, err := i.iter.Next()
if err != nil {
return nil, err
}
r := NewRepository(i.pool.library, repo, i.pool.cache)
return r, nil
}
// Close finished iterator. It's no-op.
func (i *RepositoryIter) Close() error {
return nil
}