| @@ -29,8 +29,11 @@ type MR struct { |
| 29 | 29 | MergedBy string // "" when unknown (imports) or the account is gone |
| 30 | 30 | ClosedAt string // "" unless closed without merging |
| 31 | 31 | ClosedBy string |
| 32 | | CreatedAt string |
| 33 | | UpdatedAt string |
| 32 | // SupersededBy is the number, within this repository, of the merge |
| 33 | // request this one was closed in favour of. 0 means none. |
| 34 | SupersededBy int64 |
| 35 | CreatedAt string |
| 36 | UpdatedAt string |
| 34 | 37 | // ReviewRequests is who has been asked, directly, for a review — the |
| 35 | 38 | // mr review request counterpart of Issue.Assignees. |
| 36 | 39 | ReviewRequests []string |
| @@ -92,7 +95,7 @@ const mrSelect = ` |
| 92 | 95 | m.source_ref, m.target_ref, m.title, m.body, m.body_format, m.state, m.draft, |
| 93 | 96 | COALESCE(ms.title, ''), m.head_sha, |
| 94 | 97 | m.merged_base, m.merged_at, COALESCE(mu.username, ''), |
| 95 | | m.closed_at, COALESCE(cu.username, ''), m.created_at, m.updated_at |
| 98 | m.closed_at, COALESCE(cu.username, ''), COALESCE(m.superseded_by, 0), m.created_at, m.updated_at |
| 96 | 99 | FROM merge_requests m |
| 97 | 100 | JOIN users u ON u.id = m.author_id |
| 98 | 101 | LEFT JOIN users mu ON mu.id = m.merged_by |
| @@ -106,7 +109,7 @@ func scanMR(row interface{ Scan(...any) error }) (MR, error) { |
| 106 | 109 | var m MR |
| 107 | 110 | err := row.Scan(&m.ID, &m.RepoID, &m.Number, &m.Author, &m.SourceRepoID, &m.SourcePath, |
| 108 | 111 | &m.SourceRef, &m.TargetRef, &m.Title, &m.Body, &m.BodyFormat, &m.State, &m.Draft, &m.Milestone, &m.HeadSHA, &m.MergedBase, |
| 109 | | &m.MergedAt, &m.MergedBy, &m.ClosedAt, &m.ClosedBy, &m.CreatedAt, &m.UpdatedAt) |
| 112 | &m.MergedAt, &m.MergedBy, &m.ClosedAt, &m.ClosedBy, &m.SupersededBy, &m.CreatedAt, &m.UpdatedAt) |
| 110 | 113 | return m, err |
| 111 | 114 | } |
| 112 | 115 | |
| @@ -265,6 +268,37 @@ func (s *Store) MarkClosed(mrID, actorID int64, at string) error { |
| 265 | 268 | return err |
| 266 | 269 | } |
| 267 | 270 | |
| 271 | // SetSupersededBy records which merge request, by number within the same |
| 272 | // repository, this one was closed in favour of. n of 0 clears it. |
| 273 | func (s *Store) SetSupersededBy(mrID, n int64) error { |
| 274 | var v any |
| 275 | if n != 0 { |
| 276 | v = n |
| 277 | } |
| 278 | _, err := s.DB.Exec("UPDATE merge_requests SET superseded_by = ? WHERE id = ?", v, mrID) |
| 279 | return err |
| 280 | } |
| 281 | |
| 282 | // MRsSuperseding returns the merge requests in a repository whose |
| 283 | // superseded_by names number, oldest first — the reverse of |
| 284 | // MR.SupersededBy. |
| 285 | func (s *Store) MRsSuperseding(repoID, number int64) ([]MR, error) { |
| 286 | rows, err := s.DB.Query(mrSelect+" WHERE m.repo_id = ? AND m.superseded_by = ? ORDER BY m.number ASC", repoID, number) |
| 287 | if err != nil { |
| 288 | return nil, err |
| 289 | } |
| 290 | defer rows.Close() |
| 291 | var out []MR |
| 292 | for rows.Next() { |
| 293 | m, err := scanMR(rows) |
| 294 | if err != nil { |
| 295 | return nil, err |
| 296 | } |
| 297 | out = append(out, m) |
| 298 | } |
| 299 | return out, rows.Err() |
| 300 | } |
| 301 | |
| 268 | 302 | // SetMRState moves an MR between states that carry no resolution stamp. |
| 269 | 303 | // Returning to open (a source branch that came back) clears one. |
| 270 | 304 | func (s *Store) SetMRState(mrID int64, state string) error { |