Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

A free and open-source forge that lives in your Git repo.

Add repository settings for description, branch, and visibility

1948358f9719cd0e5a15bd75a5d5dd3640e4ea82 · Keenan Nemetz · 15d ago · parent e84a66f5

Add repository settings for description, branch, and visibility

The Settings tab is shown only to repository admins and edits the facts that
repository owns: description, default branch (validated and required to exist),
and public/private visibility. Visibility toggles the ACL default between none
and read and leaves explicit entries alone; access rules stay an instance-admin
operation.

The page is read-gated before it is admin-gated, so a private repository still
answers 404 rather than confirming that settings exist. Saves carry CSRF, are
audited, and refresh the repository index. Adds Meta setters for the description
file and HEAD, plus git helpers to validate a branch and point HEAD at it.

forge/repo/repo.go +38

@@ -148,6 +148,44 @@ func (s *Store) Open(name string) (*Meta, error) {
148 148 return m, nil
149 149 }
150 150
151 // SetDescription writes the repository's description beside the bare repo. An
152 // empty description removes the file, so a later Open cannot resurrect a value
153 // the operator cleared.
154 func (m *Meta) SetDescription(description string) error {
155 description = strings.TrimSpace(description)
156 path := filepath.Join(m.Dir, descFile)
157 if description == "" {
158 if err := os.Remove(path); err != nil && !os.IsNotExist(err) {
159 return err
160 }
161 } else if err := os.WriteFile(path, []byte(description+"\n"), 0o644); err != nil {
162 return err
163 }
164 m.Description = description
165 return nil
166 }
167
168 // SetDefaultBranch points HEAD at a branch that already exists. It validates the
169 // name and the ref before touching HEAD, so a rejected branch changes nothing.
170 func (m *Meta) SetDefaultBranch(branch string) error {
171 branch = strings.TrimSpace(branch)
172 if branch == "" {
173 return fmt.Errorf("default branch is required")
174 }
175 g := m.Git()
176 if !g.ValidBranch(branch) {
177 return fmt.Errorf("%q is not a valid branch name", branch)
178 }
179 if sha, err := g.RevParse("refs/heads/" + branch); err != nil || sha == "" {
180 return fmt.Errorf("branch %q does not exist", branch)
181 }
182 if err := g.SetHEAD(branch); err != nil {
183 return err
184 }
185 m.DefaultBranch = branch
186 return nil
187 }
188
151 189 // List returns every repo in the store, sorted by name.
152 190 func (s *Store) List() ([]*Meta, error) {
153 191 ents, err := os.ReadDir(s.Root)