vole
Clone
Read only, no credentials:
https://rodent.software/git/vole.git
Write over SSH with a registered key:
git clone ssh://git@0.0.0.0:2222/vole.git
A free and open-source forge that lives in your Git repo.
Merge change request 01M70WES5ZZDJ6RP226WB11BBZ: Let people rename and remove their own passkeys
keenan · 1h ago
4b8c9e1d
| 1 | package index |
| 2 | |
| 3 | // Release artifacts on the metadata branch: releases/<tag>/<name> holds a git-lfs |
| 4 | // pointer, and the pointer is the record. The index stores the pointer's name, |
| 5 | // object id and size, which is what a release page lists and what a download |
| 6 | // needs before it asks the LFS store for the bytes. |
| 7 | // |
| 8 | // This is the one part of the branch whose authoritative copy is a tag, not a |
| 9 | // file: a tag can be deleted and recreated. The rows are replaced from the tree |
| 10 | // whenever the releases/ path changes, so they always describe the current |
| 11 | // branch. |
| 12 | |
| 13 | import ( |
| 14 | "rodent.software/vole/metadata" |
| 15 | ) |
| 16 | |
| 17 | // replaceArtifacts replaces every artifact row for a repository. Artifacts are a |
| 18 | // small, whole set: a release page shows a tag's files and the cost of rewriting |
| 19 | // the set is one statement when releases/ changes. |
| 20 | func replaceArtifacts(tx execer, repoID string, byTag map[string][]metadata.Artifact) error { |
| 21 | if _, err := tx.Exec(`DELETE FROM artifacts WHERE repo_id=?`, repoID); err != nil { |
| 22 | return err |
| 23 | } |
| 24 | for tag, list := range byTag { |
| 25 | for _, a := range list { |
| 26 | if _, err := tx.Exec( |
| 27 | `INSERT OR REPLACE INTO artifacts(repo_id, tag, name, oid, size) VALUES(?,?,?,?,?)`, |
| 28 | repoID, tag, a.Name, a.OID, a.Size); err != nil { |
| 29 | return err |
| 30 | } |
| 31 | } |
| 32 | } |
| 33 | return nil |
| 34 | } |
| 35 | |
| 36 | // Artifacts returns the files attached to one tag, sorted by name. A tag with |
| 37 | // nothing attached is an empty list, which is also what a tag that predates the |
| 38 | // index's first read returns; the release page shows the same "no artifacts" |
| 39 | // state either way. |
| 40 | func (s *Store) Artifacts(repoID, tag string) ([]metadata.Artifact, error) { |
| 41 | rows, err := s.db.Query( |
| 42 | `SELECT name, oid, size FROM artifacts WHERE repo_id=? AND tag=? ORDER BY name`, |
| 43 | repoID, tag) |
| 44 | if err != nil { |
| 45 | return nil, err |
| 46 | } |
| 47 | defer rows.Close() |
| 48 | var out []metadata.Artifact |
| 49 | for rows.Next() { |
| 50 | var a metadata.Artifact |
| 51 | if err := rows.Scan(&a.Name, &a.OID, &a.Size); err != nil { |
| 52 | return nil, err |
| 53 | } |
| 54 | out = append(out, a) |
| 55 | } |
| 56 | return out, rows.Err() |
| 57 | } |
| 58 |