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.

Sort the issue list by when it last moved

db4081ec934ddd9a7ce123b4d3cf6d6ea43a4537 · Keenan Nemetz · 5d ago · parent a32a859a

Sort the issue list by when it last moved

An issue queue is read for what changed, not for the order things were
filed. The list now shows the newest activity first and carries the columns
that answer the question: labels have their own column, assignees render like
authors do, and the creation time and author sit under the title.

The last column is "updated": the newest commit over the issue's directory,
which covers an edit, a comment, a label change, and a close or reopen. The
metadata branch has no such field on purpose — the commit carries the time —
so the index derives it from one `git log` per rebuild or one per refreshed
range, and stores it. An incremental refresh also reads the commits' paths, so
an edit reverted inside the range still counts as activity.

Bumps the index schema version, which drops the derived rows and rebuilds them
from the branch on the next read.

Closes #192

forge/index/index.go +12−5

@@ -135,10 +135,12 @@ CREATE TABLE IF NOT EXISTS issues (
135 135 // Assignees are denormalised onto the row the way labels are: the list page
136 136 // shows them without a join, and the filter table below is what queries use.
137 137 _, _ = db.Exec(`ALTER TABLE issues ADD COLUMN assignees TEXT NOT NULL DEFAULT ''`)
138 // The metadata format dropped its updated field (the commit carries the
139 // time), so the index has no column for it either. The index is derived: if
140 // this fails on some older file the table is rebuilt from the repos.
141 _, _ = db.Exec(`ALTER TABLE issues DROP COLUMN updated`)
138 // updated is when the metadata branch last touched the issue: an edit, a
139 // comment, or a state change. The branch keeps no such field — the commit
140 // carries the time — so the index derives it from `git log` and stores it,
141 // which is what lets the list sort by activity without walking history per
142 // page. The index is derived: a stale value is repaired by a rebuild.
143 _, _ = db.Exec(`ALTER TABLE issues ADD COLUMN updated INTEGER NOT NULL DEFAULT 0`)
142 144 if _, err := db.Exec(`
143 145 CREATE TABLE IF NOT EXISTS issue_labels (
144 146 repo_id TEXT NOT NULL,
@@ -328,7 +330,7 @@ CREATE VIRTUAL TABLE IF NOT EXISTS search USING fts5(
328 330 // and leaves every repo with an empty issues_sha, which makes the next read
329 331 // rebuild that repo from git. A stale row is worse than a rebuild, and a rebuild is the
330 332 // operation the index already has to survive.
331 const schemaVersion = 12
333 const schemaVersion = 13
332 334
333 335 func (s *Store) migrate() error {
334 336 var v int
@@ -375,6 +377,11 @@ type IssueRow struct {
375 377 Labels []string
376 378 Assignees []string
377 379 Comments int
380 // Updated is when the metadata branch last touched the issue: the newest
381 // commit over its directory, which covers an edit, a comment, a label change,
382 // and a close or reopen. It is at least Created, so a freshly filed issue
383 // reads as just updated rather than as never touched.
384 Updated time.Time
378 385 // Number is the `#42` alias from entity_numbers, or 0 when the branch has not
379 386 // been indexed yet. It is a display alias; ID remains the identity.
380 387 Number int