internal/store/stack.go
59 lines · 1838 bytes
3 symbols in this file
1package store
2
3import (
4 "database/sql"
5 "errors"
6)
7
8// Stacked merge requests: B is stacked on A when B's target branch is A's
9// source branch, both open, in the same repository. Nothing is stored;
10// these two reads derive it.
11
12// OpenMRsByTarget lists the open merge requests in repoID targeting
13// targetRef, oldest first.
14func (s *Store) OpenMRsByTarget(repoID int64, targetRef string) ([]MR, error) {
15 rows, err := s.DB.Query(
16 mrSelect+" WHERE m.repo_id = ? AND m.target_ref = ? AND m.state = 'open' ORDER BY m.number",
17 repoID, targetRef)
18 if err != nil {
19 return nil, err
20 }
21 defer rows.Close()
22 var out []MR
23 for rows.Next() {
24 m, err := scanMR(rows)
25 if err != nil {
26 return nil, err
27 }
28 out = append(out, m)
29 }
30 return out, rows.Err()
31}
32
33// OpenMRBySource finds the open merge request in repoID whose source is
34// the repository's own branch sourceRef. ok is false when there is none.
35func (s *Store) OpenMRBySource(repoID int64, sourceRef string) (MR, bool, error) {
36 m, err := scanMR(s.DB.QueryRow(
37 mrSelect+" WHERE m.repo_id = ? AND m.source_repo_id = ? AND m.source_ref = ? AND m.state = 'open' ORDER BY m.number LIMIT 1",
38 repoID, repoID, sourceRef))
39 if errors.Is(err, sql.ErrNoRows) {
40 return MR{}, false, nil
41 }
42 return m, err == nil, err
43}
44
45// RetargetKeepingReviews moves a merge request onto a new target without
46// staling its reviews: used when the branch it was stacked on has merged,
47// so the diff against the new target is the diff the reviews were of.
48func (s *Store) RetargetKeepingReviews(mrID int64, targetRef string) error {
49 res, err := s.DB.Exec(
50 "UPDATE merge_requests SET target_ref = ?, updated_at = strftime('%Y-%m-%dT%H:%M:%fZ','now') WHERE id = ?",
51 targetRef, mrID)
52 if err != nil {
53 return err
54 }
55 if n, _ := res.RowsAffected(); n == 0 {
56 return ErrNotFound
57 }
58 return nil
59}