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.

Search for an issue when linking it to a change

838f282eebf7e68f61318eae93d03263df1341df · Keenan Nemetz · 11d ago · parent 267feec2

Search for an issue when linking it to a change

The link field only accepted an id that the author already knew. It is now a search box over the issue index that matches a title, a #number, or a ULID prefix. A matching issue is a button: picking one posts the same link write and replaces the Issues section with the new list. Issues already linked are left out of the results.

forge/index/index_test.go +60

@@ -7,9 +7,69 @@ package index
7 7
8 8 import (
9 9 "path/filepath"
10 "slices"
10 11 "testing"
11 12 )
12 13
14 func TestSearchIssuesMatchesTitleNumberAndIDPrefix(t *testing.T) {
15 t.Parallel()
16 s, err := Open(filepath.Join(t.TempDir(), "index.db"))
17 if err != nil {
18 t.Fatal(err)
19 }
20 defer s.Close()
21
22 const (
23 first = "01M5JR2JK29KKMAA1T9MDNTPBP"
24 second = "01M5JR2JK29KKMAA1T9MDNTRBZ"
25 )
26 for _, issue := range []struct {
27 id string
28 title string
29 number int
30 }{
31 {first, "Quick retry on timeout", 42},
32 {second, "Slow parser", 43},
33 } {
34 if _, err := s.db.Exec(
35 `INSERT INTO issues(repo_id, id, title, state, author, created) VALUES('r1',?,?,'open','keenan',0)`,
36 issue.id, issue.title); err != nil {
37 t.Fatal(err)
38 }
39 if _, err := s.db.Exec(
40 `INSERT INTO entity_numbers(repo_id, number, kind, id) VALUES('r1',?,'issue',?)`,
41 issue.number, issue.id); err != nil {
42 t.Fatal(err)
43 }
44 }
45
46 for _, test := range []struct {
47 term string
48 want []string
49 }{
50 {"quick", []string{first}},
51 {"Quick", []string{first}},
52 {"#42", []string{first}},
53 {"42", []string{first}},
54 {"01M5JR2JK29KKMAA1T9MDNTR", []string{second}},
55 {first, []string{first}},
56 {"nothing", nil},
57 {"", nil},
58 } {
59 got, err := s.SearchIssues("r1", test.term, 8)
60 if err != nil {
61 t.Fatalf("SearchIssues(%q): %v", test.term, err)
62 }
63 ids := make([]string, len(got))
64 for i, issue := range got {
65 ids[i] = issue.ID
66 }
67 if !slices.Equal(ids, test.want) {
68 t.Fatalf("SearchIssues(%q) = %v, want %v", test.term, ids, test.want)
69 }
70 }
71 }
72
13 73 func TestSchemaVersionDropsRowsFromAnOlderShape(t *testing.T) {
14 74 t.Parallel()
15 75 path := filepath.Join(t.TempDir(), "index.db")