Diff
1diff --git a/server/backend/file/file.go b/server/backend/file/file.go
2index cc0281f5e7699686d02ebab61f90e5b8d5d0b6e7..2bc66b3ac458c94724e5c46ef49f0868ea7e89b2 100644
3--- a/server/backend/file/file.go
4+++ b/server/backend/file/file.go
5@@ -48,7 +48,7 @@ const (
6 repos = "repos"
7 collabs = "collaborators"
8 description = "description"
9- private = "private"
10+ exportOk = "git-daemon-export-ok"
11 settings = "settings"
12 )
13
14@@ -264,7 +264,7 @@ func (fb *FileBackend) AnonAccess() backend.AccessLevel {
15 // It implements backend.Backend.
16 func (fb *FileBackend) Description(repo string) string {
17 repo = sanatizeRepo(repo) + ".git"
18- r := &Repo{path: filepath.Join(fb.reposPath(), repo)}
19+ r := &Repo{path: filepath.Join(fb.reposPath(), repo), root: fb.reposPath()}
20 return r.Description()
21 }
22
23@@ -307,7 +307,15 @@ func (fb *FileBackend) IsAdmin(pk gossh.PublicKey) bool {
24 // It implements backend.Backend.
25 func (fb *FileBackend) IsCollaborator(pk gossh.PublicKey, repo string) bool {
26 repo = sanatizeRepo(repo) + ".git"
27+ _, err := os.Stat(filepath.Join(fb.reposPath(), repo))
28+ if errors.Is(err, os.ErrNotExist) {
29+ return false
30+ }
31+
32 f, err := os.Open(fb.collabsPath(repo))
33+ if err != nil && errors.Is(err, os.ErrNotExist) {
34+ return false
35+ }
36 if err != nil {
37 logger.Debug("failed to open collaborators file", "err", err, "path", fb.collabsPath(repo))
38 return false
39@@ -333,7 +341,7 @@ func (fb *FileBackend) IsCollaborator(pk gossh.PublicKey, repo string) bool {
40 // It implements backend.Backend.
41 func (fb *FileBackend) IsPrivate(repo string) bool {
42 repo = sanatizeRepo(repo) + ".git"
43- r := &Repo{path: filepath.Join(fb.reposPath(), repo)}
44+ r := &Repo{path: filepath.Join(fb.reposPath(), repo), root: fb.reposPath()}
45 return r.IsPrivate()
46 }
47
48@@ -428,15 +436,9 @@ func (fb *FileBackend) SetDescription(repo string, desc string) error {
49 // It implements backend.Backend.
50 func (fb *FileBackend) SetPrivate(repo string, priv bool) error {
51 repo = sanatizeRepo(repo) + ".git"
52- daemonExport := filepath.Join(fb.reposPath(), repo, "git-daemon-export-ok")
53+ daemonExport := filepath.Join(fb.reposPath(), repo, exportOk)
54 if priv {
55 _ = os.Remove(daemonExport)
56- f, err := os.Create(filepath.Join(fb.reposPath(), repo, private))
57- if err != nil {
58- return fmt.Errorf("failed to create private file: %w", err)
59- }
60-
61- _ = f.Close() //nolint:errcheck
62 } else {
63 // Create git-daemon-export-ok file if repo is public.
64 f, err := os.Create(daemonExport)
65@@ -505,8 +507,9 @@ func (fb *FileBackend) CreateRepository(name string, private bool) (backend.Repo
66 }
67
68 fb.SetPrivate(name, private)
69+ fb.SetDescription(name, "")
70
71- return &Repo{path: rp}, nil
72+ return &Repo{path: rp, root: fb.reposPath()}, nil
73 }
74
75 // DeleteRepository deletes the given repository.
76@@ -537,7 +540,7 @@ func (fb *FileBackend) Repository(repo string) (backend.Repository, error) {
77 return nil, err
78 }
79
80- return &Repo{path: rp}, nil
81+ return &Repo{path: rp, root: fb.reposPath()}, nil
82 }
83
84 // Repositories returns a list of all repositories.
85@@ -556,7 +559,7 @@ func (fb *FileBackend) Repositories() ([]backend.Repository, error) {
86 return nil
87 }
88
89- repos = append(repos, &Repo{path: path})
90+ repos = append(repos, &Repo{path: path, root: fb.reposPath()})
91
92 return nil
93 })
94diff --git a/server/backend/file/repo.go b/server/backend/file/repo.go
95index 6764f5fe3164fa5518712159b5f140d895c6bfa3..2a8c3c9d2367b8cb36630567ef31f5dd8cc955d5 100644
96--- a/server/backend/file/repo.go
97+++ b/server/backend/file/repo.go
98@@ -16,6 +16,7 @@ var _ backend.Repository = (*Repo)(nil)
99 //
100 // It implemenets backend.Repository.
101 type Repo struct {
102+ root string
103 path string
104 }
105
106@@ -23,14 +24,15 @@ type Repo struct {
107 //
108 // It implements backend.Repository.
109 func (r *Repo) Name() string {
110- return strings.TrimSuffix(filepath.Base(r.path), ".git")
111+ name := strings.TrimSuffix(strings.TrimPrefix(r.path, r.root), ".git")
112+ return strings.TrimPrefix(name, "/")
113 }
114
115 // Description returns the repository's description.
116 //
117 // It implements backend.Repository.
118 func (r *Repo) Description() string {
119- desc, err := readAll(r.path)
120+ desc, err := readAll(filepath.Join(r.path, description))
121 if err != nil {
122 logger.Debug("failed to read description file", "err", err,
123 "path", filepath.Join(r.path, description))
124@@ -44,7 +46,7 @@ func (r *Repo) Description() string {
125 //
126 // It implements backend.Repository.
127 func (r *Repo) IsPrivate() bool {
128- _, err := os.Stat(filepath.Join(r.path, private))
129+ _, err := os.Stat(filepath.Join(r.path, exportOk))
130 return errors.Is(err, os.ErrExist)
131 }
132
133diff --git a/server/config/config.go b/server/config/config.go
134index 05f008e57ff29a4ecadf20fb5ad411703d040fd7..8a3de7e1c5313333245a07b0fde349a1281d1e66 100644
135--- a/server/config/config.go
136+++ b/server/config/config.go
137@@ -76,6 +76,8 @@ func DefaultConfig() *Config {
138 if err != nil {
139 log.Fatal(err)
140 }
141+ // Add the initial admin keys to the list of admins.
142+ fb.AdditionalAdmins = cfg.InitialAdminKeys
143 return cfg.WithBackend(fb).WithAccessMethod(fb)
144 }
145