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.

Create the instance repository on init and list it normally

3e7c5e6797105f87fe593bb4c34743d3615ab598 · Keenan Nemetz · 1d ago · parent 6ce635a8

Create the instance repository on init and list it normally

`vole admin init` now creates the configured instance repository with the starter tree and indexes it, so a new instance starts with it. The repository is no longer hidden from the home page or activity feed: it has the same pages, history, and settings as any other, and its visibility is its own.

The Admin page's create button remains as the repair path for an instance that predates this, using the same starter tree from the instancerepo package.

forge/instancerepo/seed.go +111

@@ -0,0 +1,111 @@
1 package instancerepo
2
3 // Creating the repository Vole reads for its presentation. `vole admin init`
4 // calls Ensure so a new instance starts with a repository an admin can open,
5 // edit, and push to like any other. The Admin page calls the same function, so
6 // an instance that predates this behaviour has the same repair path.
7
8 import (
9 "errors"
10 "os"
11 "strings"
12
13 "github.com/rodent-software/vole/core/git"
14 "github.com/rodent-software/vole/forge/repo"
15 )
16
17 // DefaultDescription is what the repository list shows before an admin edits
18 // it.
19 const DefaultDescription = "Instance customization: profile README, custom CSS, favicon, and assets"
20
21 // Ensure creates name when it is missing and seeds the starter tree when it has
22 // no commits. An existing repository with history is left alone. owner may be
23 // empty, which creates a private repository that instance admins can still
24 // administer; author names the commit when the starter files are written.
25 //
26 // It reports whether it wrote anything, so a caller can audit a creation
27 // without inventing its own answer to "was this new?".
28 func Ensure(repos *repo.Store, name, owner, author, instanceName string) (*repo.Meta, bool, error) {
29 name = strings.TrimSpace(name)
30 if name == "" || repos == nil {
31 return nil, false, nil
32 }
33 created := false
34 m, err := repos.Meta(name)
35 if err != nil {
36 if !errors.Is(err, os.ErrNotExist) {
37 return nil, false, err
38 }
39 m, err = repos.Create(name, owner, DefaultDescription)
40 if err != nil {
41 return nil, false, err
42 }
43 created = true
44 }
45 g := m.Git()
46 tip, err := g.RevParseRaw("refs/heads/" + m.DefaultBranch)
47 if err != nil {
48 return nil, created, err
49 }
50 if tip != "" {
51 return m, created, nil
52 }
53 tree, err := git.WriteFlatTree(g, Template(instanceName))
54 if err != nil {
55 return nil, created, err
56 }
57 commit, err := g.CommitTreeAs(tree, "", "Create the instance repository", author)
58 if err != nil {
59 return nil, created, err
60 }
61 if err := g.UpdateRef("refs/heads/"+m.DefaultBranch, commit); err != nil {
62 return nil, created, err
63 }
64 return m, true, nil
65 }
66
67 // Template is the starter tree. The root README explains the fixed paths; the
68 // profile files give an admin something to edit rather than a blank page, and
69 // the CSS names the variables worth overriding.
70 func Template(instanceName string) map[string][]byte {
71 name := strings.TrimSpace(instanceName)
72 if name == "" {
73 name = "Vole"
74 }
75 return map[string][]byte{
76 "README.md": []byte(`# Instance customization
77
78 This repository customizes the Vole instance. Vole creates it with ` + "`vole admin init`" + ` and
79 reloads it on a short timer, so a push is live within a couple of seconds.
80
81 Only these paths are read; other files are ignored, so this README and any
82 notes can live here too.
83
84 profile/README.md the landing page introduction (markdown)
85 profile/private/README.md replaces it for signed-in viewers
86 profile/custom.css appended after the built-in stylesheets
87 profile/favicon.svg replaces the built-in favicon
88 assets/ served at /static/custom/assets/
89
90 Edit a file here and push, or open it in the web interface and use the editor.
91 This repository has the usual pages, history, issues, and change requests. Its
92 visibility is a repository setting, so an instance admin can publish it or keep
93 it private.
94
95 The files above are served to visitors (the private README only to signed-in
96 viewers), even when the repository itself is private.
97 `),
98 "profile/README.md": []byte("# " + name + "\n\nTell people what this forge is for. This file is the landing page introduction.\n"),
99 "profile/custom.css": []byte(`/* Custom styles, loaded after the built-in stylesheets.
100 *
101 * The palette is CSS variables; override them here rather than copying rules:
102 * :root {
103 * --accent: #7fbbb3;
104 * --bg: #1e2326;
105 * }
106 *
107 * The layout is grid and flex, so most re-skins need only values, not selectors.
108 */
109 `),
110 }
111 }