Let issue-tracker.list take numbers and worker (issue 1070)

This commit is contained in:
jochen
2026-10-17 22:50:09 +02:00
parent 01c9ab0cf5
commit 1124f17912
4 changed files with 140 additions and 9 deletions
+44 -3
View File
@@ -699,8 +699,17 @@ type ListAsk struct {
Search string
// Before keeps only the issues numbered below it: the cursor that pages the newest-first list.
Before uint64
// Numbers keeps only these issues, rows in the order given, combined with the other filters as AND; a
// number that is not an issue is named in the answer's Missing (novox/hq issue 1070).
Numbers []uint64
// Worker keeps only the issues in diagnosing or fixing whose worker is exactly this, who@node (novox/hq
// issue 1070).
Worker string
}
// MostNumbers is the most `numbers` may name in one list.
const MostNumbers = 200
// Row is one issue in a list: short enough to read in a chat.
type Row struct {
Number uint64 `json:"number"`
@@ -731,7 +740,10 @@ type Listed struct {
Matched int `json:"matched"`
// Next is the before that continues the list where this page ends; 0 when nothing more matches.
Next uint64 `json:"next,omitempty"`
Said string `json:"said"`
// Missing is each number asked for (in Numbers) that is not an issue, in the order given (novox/hq issue
// 1070).
Missing []uint64 `json:"missing,omitempty"`
Said string `json:"said"`
}
// List is the issues that match, newest first, or ranked by a search: from memory once it is loaded on start
@@ -783,6 +795,15 @@ func (t *Tracker) List(a ListAsk) (*Listed, error) {
"or more words, instead")
}
}
if len(a.Numbers) > MostNumbers {
return nil, fmt.Errorf("numbers names %d entries; at most %d", len(a.Numbers), MostNumbers)
}
worker := ""
if strings.TrimSpace(a.Worker) != "" {
if worker, err = checkWorkerField("worker", a.Worker); err != nil {
return nil, err
}
}
limit := a.Limit
if limit <= 0 {
limit = 50
@@ -793,8 +814,11 @@ func (t *Tracker) List(a ListAsk) (*Listed, error) {
return nil, err
}
now, staleAfter := t.now(), t.workerStaleAfter()
var numbers []uint64
if search != "" {
usingNumbers := len(a.Numbers) > 0
var numbers, missing []uint64
if usingNumbers {
numbers = a.Numbers
} else if search != "" {
var hits []hit
if v := t.view(); v.ready() {
hits = v.search(search)
@@ -822,6 +846,12 @@ func (t *Tracker) List(a ListAsk) (*Listed, error) {
lower := strings.ToLower(phrase)
for _, n := range numbers {
is := all[n]
if is == nil {
if usingNumbers {
missing = append(missing, n)
}
continue
}
if status != "" && is.Status != status {
continue
}
@@ -841,6 +871,9 @@ func (t *Tracker) List(a ListAsk) (*Listed, error) {
if owner != "" && !locatedUnder(is.LocatedIn, owner) {
continue
}
if worker != "" && (is.Worker == nil || is.Worker.By != worker) {
continue
}
if lower != "" && !strings.Contains(strings.ToLower(is.Title), lower) && !strings.Contains(strings.ToLower(is.Report), lower) {
continue
}
@@ -857,11 +890,19 @@ func (t *Tracker) List(a ListAsk) (*Listed, error) {
out.Rows = append(out.Rows, row)
}
}
out.Missing = missing
below := ""
if a.Before != 0 {
below = fmt.Sprintf(" below %d", a.Before)
}
switch {
case usingNumbers && out.Matched == 0 && len(missing) == 0:
out.Said = "No issue asked matches."
case usingNumbers:
out.Said = fmt.Sprintf("%d of %d asked match, in the order given.", out.Matched, len(a.Numbers))
if len(missing) > 0 {
out.Said += fmt.Sprintf(" %d of the numbers asked are not an issue.", len(missing))
}
case out.Matched == 0:
out.Said = "No issue matches" + below + "."
case search != "" && out.Matched > len(out.Rows):