main models.go
Eric Bower  ·  2026-02-25
  1package patchbin
  2
  3import (
  4	"database/sql"
  5	"database/sql/driver"
  6	"encoding/json"
  7	"fmt"
  8	"time"
  9
 10	"github.com/bluekeyes/go-gitdiff/gitdiff"
 11)
 12
 13type Status string
 14
 15const (
 16	StatusDraft Status = "draft"
 17	StatusOpen  Status = "open"
 18)
 19
 20// User is a db model for users.
 21type User struct {
 22	ID        int64     `db:"id"`
 23	Pubkey    string    `db:"pubkey"`
 24	Name      string    `db:"name"`
 25	CreatedAt time.Time `db:"created_at"`
 26	UpdatedAt time.Time `db:"updated_at"`
 27}
 28
 29// Acl is a db model for access control.
 30type Acl struct {
 31	ID         int64          `db:"id"`
 32	Pubkey     sql.NullString `db:"pubkey"`
 33	IpAddress  sql.NullString `db:"ip_address"`
 34	Permission string         `db:"permission"`
 35	CreatedAt  time.Time      `db:"created_at"`
 36}
 37
 38// PatchRequest is a database model for patches submitted to a Repo.
 39type PatchRequest struct {
 40	ID           int64     `db:"id"`
 41	UserID       int64     `db:"user_id"`
 42	RepoName     string    `db:"repo_name"` // Plain string namespace
 43	Name         string    `db:"name"`
 44	Text         string    `db:"text"`
 45	Status       Status    `db:"status"`
 46	CreatedAt    time.Time `db:"created_at"`
 47	UpdatedAt    time.Time `db:"updated_at"`
 48	LastActivity time.Time `db:"last_activity"`
 49}
 50
 51type Patchset struct {
 52	ID             int64     `db:"id"`
 53	UserID         int64     `db:"user_id"`
 54	PatchRequestID int64     `db:"patch_request_id"`
 55	Review         bool      `db:"review"`
 56	CreatedAt      time.Time `db:"created_at"`
 57}
 58
 59// Patch is a database model for a single entry in a patchset.
 60// This usually corresponds to a git commit.
 61type Patch struct {
 62	ID            int64          `db:"id"`
 63	UserID        int64          `db:"user_id"`
 64	PatchsetID    int64          `db:"patchset_id"`
 65	AuthorName    string         `db:"author_name"`
 66	AuthorEmail   string         `db:"author_email"`
 67	AuthorDate    time.Time      `db:"author_date"`
 68	Title         string         `db:"title"`
 69	Body          string         `db:"body"`
 70	BodyAppendix  string         `db:"body_appendix"`
 71	CommitSha     string         `db:"commit_sha"`
 72	ContentSha    string         `db:"content_sha"`
 73	BaseCommitSha sql.NullString `db:"base_commit_sha"`
 74	RawText       string         `db:"raw_text"`
 75	CreatedAt     time.Time      `db:"created_at"`
 76	Files         []*gitdiff.File
 77}
 78
 79func (p *Patch) CalcDiff() string {
 80	return p.RawText
 81}
 82
 83// EventLog is a event log for RSS or other notification systems.
 84type EventLog struct {
 85	ID             int64         `db:"id"`
 86	UserID         int64         `db:"user_id"`
 87	PatchRequestID sql.NullInt64 `db:"patch_request_id"`
 88	PatchsetID     sql.NullInt64 `db:"patchset_id"`
 89	Event          string        `db:"event"`
 90	CreatedAt      time.Time     `db:"created_at"`
 91	Data           EventData     `db:"data"`
 92}
 93
 94type EventData struct {
 95	Name    string `json:"name,omitempty"`
 96	Status  Status `json:"status,omitempty"`
 97	Comment string `json:"comment,omitempty"`
 98}
 99
100func (e EventData) String() string {
101	b, _ := json.Marshal(e)
102	bs := string(b)
103	if bs == "{}" {
104		return ""
105	}
106	return bs
107}
108
109func (e *EventData) Scan(value any) error {
110	if value == nil || value == "" {
111		return nil
112	}
113
114	var byt []byte
115	switch v := value.(type) {
116	case []byte:
117		byt = v
118	case string:
119		byt = []byte(v)
120	default:
121		return fmt.Errorf("cannot scan %T into EventData", value)
122	}
123
124	if len(byt) == 0 {
125		return nil
126	}
127
128	return json.Unmarshal(byt, e)
129}
130
131func (e EventData) Value() (driver.Value, error) {
132	return json.Marshal(e)
133}