Skip to content

Commit

Permalink
feat(backend): cache repos
Browse files Browse the repository at this point in the history
  • Loading branch information
aymanbagabas committed May 2, 2023
1 parent 8131a22 commit 0bff6ce
Showing 1 changed file with 73 additions and 16 deletions.
89 changes: 73 additions & 16 deletions server/backend/file/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ type FileBackend struct { // nolint:revive
// path is the path to the directory containing the repositories and config
// files.
path string

// repos is a map of repositories.
repos map[string]*Repo

// AdditionalAdmins additional admins to the server.
AdditionalAdmins []string
}
Expand Down Expand Up @@ -145,6 +149,11 @@ func NewFileBackend(path string) (*FileBackend, error) {
_ = f.Close()
}
}

if err := fb.initRepos(); err != nil {
return nil, err
}

return fb, nil
}

Expand Down Expand Up @@ -602,9 +611,10 @@ func (fb *FileBackend) SetPrivate(repo string, priv bool) error {
// Created repositories are always bare.
//
// It implements backend.Backend.
func (fb *FileBackend) CreateRepository(name string, private bool) (backend.Repository, error) {
name = sanatizeRepo(name) + ".git"
rp := filepath.Join(fb.reposPath(), name)
func (fb *FileBackend) CreateRepository(repo string, private bool) (backend.Repository, error) {
name := sanatizeRepo(repo)
repo = name + ".git"
rp := filepath.Join(fb.reposPath(), repo)
if _, err := os.Stat(rp); err == nil {
return nil, os.ErrExist
}
Expand All @@ -614,18 +624,23 @@ func (fb *FileBackend) CreateRepository(name string, private bool) (backend.Repo
return nil, err
}

fb.SetPrivate(name, private)
fb.SetDescription(name, "")
fb.SetPrivate(repo, private)
fb.SetDescription(repo, "")

return &Repo{path: rp, root: fb.reposPath()}, nil
r := &Repo{path: rp, root: fb.reposPath()}
// Add to cache.
fb.repos[name] = r
return r, nil
}

// DeleteRepository deletes the given repository.
//
// It implements backend.Backend.
func (fb *FileBackend) DeleteRepository(name string) error {
name = sanatizeRepo(name) + ".git"
return os.RemoveAll(filepath.Join(fb.reposPath(), name))
func (fb *FileBackend) DeleteRepository(repo string) error {
name := sanatizeRepo(repo)
delete(fb.repos, name)
repo = name + ".git"
return os.RemoveAll(filepath.Join(fb.reposPath(), repo))
}

// RenameRepository renames the given repository.
Expand All @@ -648,7 +663,12 @@ func (fb *FileBackend) RenameRepository(oldName string, newName string) error {
//
// It implements backend.Backend.
func (fb *FileBackend) Repository(repo string) (backend.Repository, error) {
repo = sanatizeRepo(repo) + ".git"
name := sanatizeRepo(repo)
if r, ok := fb.repos[name]; ok {
return r, nil
}

repo = name + ".git"
rp := filepath.Join(fb.reposPath(), repo)
_, err := os.Stat(rp)
if err != nil {
Expand All @@ -661,10 +681,31 @@ func (fb *FileBackend) Repository(repo string) (backend.Repository, error) {
return &Repo{path: rp, root: fb.reposPath()}, nil
}

// Repositories returns a list of all repositories.
//
// It implements backend.Backend.
func (fb *FileBackend) Repositories() ([]backend.Repository, error) {
// Returns true if path is a directory containing an `objects` directory and a
// `HEAD` file.
func isGitDir(path string) bool {
stat, err := os.Stat(filepath.Join(path, "objects"))
if err != nil {
return false
}
if !stat.IsDir() {
return false
}

stat, err = os.Stat(filepath.Join(path, "HEAD"))
if err != nil {
return false
}
if stat.IsDir() {
return false
}

return true
}

// initRepos initializes the repository cache.
func (fb *FileBackend) initRepos() error {
fb.repos = make(map[string]*Repo)
repos := make([]backend.Repository, 0)
err := filepath.WalkDir(fb.reposPath(), func(path string, d fs.DirEntry, _ error) error {
// Skip non-directories.
Expand All @@ -677,12 +718,28 @@ func (fb *FileBackend) Repositories() ([]backend.Repository, error) {
return nil
}

repos = append(repos, &Repo{path: path, root: fb.reposPath()})
if isGitDir(path) {
r := &Repo{path: path, root: fb.reposPath()}
fb.repos[r.Name()] = r
repos = append(repos, r)
}

return nil
})
if err != nil {
return nil, err
return err
}

return nil
}

// Repositories returns a list of all repositories.
//
// It implements backend.Backend.
func (fb *FileBackend) Repositories() ([]backend.Repository, error) {
repos := make([]backend.Repository, 0)
for _, r := range fb.repos {
repos = append(repos, r)
}

return repos, nil
Expand Down

0 comments on commit 0bff6ce

Please sign in to comment.