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.
Resolve a change request's head on the remote, not the clone
6755b7515c2e3e404e8325eabc0b1e0b74ab901f · Keenan Nemetz · 10d ago · parent 26c9be33
Resolve a change request's head on the remote, not the clone `change new --head <branch>` resolved the branch in the local clone. A clone that was behind recorded the old commit, and when that commit was already in the base the request contained nothing — which is how #117 merged nothing, closed its issue, and left the work on a side branch. - A branch's head is resolved with `git ls-remote` against the remote the metadata write pushes to, so the recorded commit is the forge's tip. If local and remote differ, the remote tip is recorded and stderr says so; a local-only branch is recorded with a note; `--no-push` may fall back to the local ref when the remote cannot be reached. - A request whose head is already in the base (the same commit, or an ancestor) is refused before anything is written, for `change new` and `change update --head`. The base is resolved on the remote too: a feature worktree commits on its local base branch, so the local base can be the head itself and would call every request empty. - The tag/commit path is unchanged: it still pins the request to that commit with no branch. Tests cover a branch that moved after the clone, a local-only branch, a head equal to the base, a head that is an ancestor of the base, and the `change update --head` refusal. The head-resolution note is documented in docs/change-requests.md.
client/review.go −13
| @@ -8,19 +8,6 @@ import ( | |||
| 8 | 8 | "github.com/rodent-software/vole/metadata" | |
| 9 | 9 | ) | |
| 10 | 10 | ||
| 11 | // ResolveHead turns a branch, tag or commit into the full id an approval will | ||
| 12 | // name. Ambiguous short ids are refused rather than guessed. | ||
| 13 | func ResolveHead(b *Branch, rev string) (string, error) { | ||
| 14 | if rev == "" { | ||
| 15 | rev = "HEAD" | ||
| 16 | } | ||
| 17 | out, err := b.Repo.RevParseFull(rev) | ||
| 18 | if err != nil || out == "" { | ||
| 19 | return "", fmt.Errorf("%q does not name a commit", rev) | ||
| 20 | } | ||
| 21 | return out, nil | ||
| 22 | } | ||
| 23 | |||
| 24 | 11 | // ResolveRequestCommentID resolves a typed comment id against one request's | |
| 25 | 12 | // thread, the way issue and comment ids are resolved: a prefix is enough, and an | |
| 26 | 13 | // ambiguous one names its matches instead of guessing. | |