- commit
- 7b83c3e
- parent
- 966a19a
- author
- Eric Bower
- date
- 2024-10-21 13:25:30 -0400 EDT
refactor: separate models from sqlite db We will likely want to support postgresql so this change will make that easier.
5 files changed,
+96,
-106
+2,
-1
1@@ -8,12 +8,13 @@ import (
2
3 "github.com/charmbracelet/soft-serve/pkg/utils"
4 "github.com/charmbracelet/ssh"
5+ "github.com/jmoiron/sqlx"
6 gossh "golang.org/x/crypto/ssh"
7 )
8
9 type Backend struct {
10 Logger *slog.Logger
11- DB *DB
12+ DB *sqlx.DB
13 Cfg *GitCfg
14 }
15
+85,
-0
1@@ -0,0 +1,85 @@
2+package git
3+
4+import (
5+ "database/sql"
6+ "time"
7+
8+ "github.com/bluekeyes/go-gitdiff/gitdiff"
9+ _ "modernc.org/sqlite"
10+)
11+
12+// User is a db model for users.
13+type User struct {
14+ ID int64 `db:"id"`
15+ Pubkey string `db:"pubkey"`
16+ Name string `db:"name"`
17+ CreatedAt time.Time `db:"created_at"`
18+ UpdatedAt time.Time `db:"updated_at"`
19+}
20+
21+// Acl is a db model for access control.
22+type Acl struct {
23+ ID int64 `db:"id"`
24+ Pubkey sql.NullString `db:"pubkey"`
25+ IpAddress sql.NullString `db:"ip_address"`
26+ Permission string `db:"permission"`
27+ CreatedAt time.Time `db:"created_at"`
28+}
29+
30+// PatchRequest is a database model for patches submitted to a Repo.
31+type PatchRequest struct {
32+ ID int64 `db:"id"`
33+ UserID int64 `db:"user_id"`
34+ RepoID string `db:"repo_id"`
35+ Name string `db:"name"`
36+ Text string `db:"text"`
37+ Status string `db:"status"`
38+ CreatedAt time.Time `db:"created_at"`
39+ UpdatedAt time.Time `db:"updated_at"`
40+ // only used for aggregate queries
41+ LastUpdated string `db:"last_updated"`
42+}
43+
44+type Patchset struct {
45+ ID int64 `db:"id"`
46+ UserID int64 `db:"user_id"`
47+ PatchRequestID int64 `db:"patch_request_id"`
48+ Review bool `db:"review"`
49+ CreatedAt time.Time `db:"created_at"`
50+}
51+
52+// Patch is a database model for a single entry in a patchset.
53+// This usually corresponds to a git commit.
54+type Patch struct {
55+ ID int64 `db:"id"`
56+ UserID int64 `db:"user_id"`
57+ PatchsetID int64 `db:"patchset_id"`
58+ AuthorName string `db:"author_name"`
59+ AuthorEmail string `db:"author_email"`
60+ AuthorDate time.Time `db:"author_date"`
61+ Title string `db:"title"`
62+ Body string `db:"body"`
63+ BodyAppendix string `db:"body_appendix"`
64+ CommitSha string `db:"commit_sha"`
65+ ContentSha string `db:"content_sha"`
66+ BaseCommitSha sql.NullString `db:"base_commit_sha"`
67+ RawText string `db:"raw_text"`
68+ CreatedAt time.Time `db:"created_at"`
69+ Files []*gitdiff.File
70+}
71+
72+func (p *Patch) CalcDiff() string {
73+ return p.RawText
74+}
75+
76+// EventLog is a event log for RSS or other notification systems.
77+type EventLog struct {
78+ ID int64 `db:"id"`
79+ UserID int64 `db:"user_id"`
80+ RepoID string `db:"repo_id"`
81+ PatchRequestID sql.NullInt64 `db:"patch_request_id"`
82+ PatchsetID sql.NullInt64 `db:"patchset_id"`
83+ Event string `db:"event"`
84+ Data string `db:"data"`
85+ CreatedAt time.Time `db:"created_at"`
86+}
R db.go =>
sqlite.go
+7,
-103
1@@ -1,99 +1,13 @@
2 package git
3
4 import (
5- "database/sql"
6 "fmt"
7 "log/slog"
8- "time"
9
10- "github.com/bluekeyes/go-gitdiff/gitdiff"
11 "github.com/jmoiron/sqlx"
12- _ "modernc.org/sqlite"
13 )
14
15-// User is a db model for users.
16-type User struct {
17- ID int64 `db:"id"`
18- Pubkey string `db:"pubkey"`
19- Name string `db:"name"`
20- CreatedAt time.Time `db:"created_at"`
21- UpdatedAt time.Time `db:"updated_at"`
22-}
23-
24-// Acl is a db model for access control.
25-type Acl struct {
26- ID int64 `db:"id"`
27- Pubkey sql.NullString `db:"pubkey"`
28- IpAddress sql.NullString `db:"ip_address"`
29- Permission string `db:"permission"`
30- CreatedAt time.Time `db:"created_at"`
31-}
32-
33-// PatchRequest is a database model for patches submitted to a Repo.
34-type PatchRequest struct {
35- ID int64 `db:"id"`
36- UserID int64 `db:"user_id"`
37- RepoID string `db:"repo_id"`
38- Name string `db:"name"`
39- Text string `db:"text"`
40- Status string `db:"status"`
41- CreatedAt time.Time `db:"created_at"`
42- UpdatedAt time.Time `db:"updated_at"`
43- // only used for aggregate queries
44- LastUpdated string `db:"last_updated"`
45-}
46-
47-type Patchset struct {
48- ID int64 `db:"id"`
49- UserID int64 `db:"user_id"`
50- PatchRequestID int64 `db:"patch_request_id"`
51- Review bool `db:"review"`
52- CreatedAt time.Time `db:"created_at"`
53-}
54-
55-// Patch is a database model for a single entry in a patchset.
56-// This usually corresponds to a git commit.
57-type Patch struct {
58- ID int64 `db:"id"`
59- UserID int64 `db:"user_id"`
60- PatchsetID int64 `db:"patchset_id"`
61- AuthorName string `db:"author_name"`
62- AuthorEmail string `db:"author_email"`
63- AuthorDate time.Time `db:"author_date"`
64- Title string `db:"title"`
65- Body string `db:"body"`
66- BodyAppendix string `db:"body_appendix"`
67- CommitSha string `db:"commit_sha"`
68- ContentSha string `db:"content_sha"`
69- BaseCommitSha sql.NullString `db:"base_commit_sha"`
70- RawText string `db:"raw_text"`
71- CreatedAt time.Time `db:"created_at"`
72- Files []*gitdiff.File
73-}
74-
75-func (p *Patch) CalcDiff() string {
76- return p.RawText
77-}
78-
79-// EventLog is a event log for RSS or other notification systems.
80-type EventLog struct {
81- ID int64 `db:"id"`
82- UserID int64 `db:"user_id"`
83- RepoID string `db:"repo_id"`
84- PatchRequestID sql.NullInt64 `db:"patch_request_id"`
85- PatchsetID sql.NullInt64 `db:"patchset_id"`
86- Event string `db:"event"`
87- Data string `db:"data"`
88- CreatedAt time.Time `db:"created_at"`
89-}
90-
91-// DB is the interface for a pico/git database.
92-type DB struct {
93- *sqlx.DB
94- logger *slog.Logger
95-}
96-
97-var schema = `
98+var sqliteSchema = `
99 CREATE TABLE IF NOT EXISTS app_users (
100 id INTEGER PRIMARY KEY AUTOINCREMENT,
101 pubkey TEXT NOT NULL UNIQUE,
102@@ -198,33 +112,23 @@ var sqliteMigrations = []string{
103 }
104
105 // Open opens a database connection.
106-func Open(dsn string, logger *slog.Logger) (*DB, error) {
107+func SqliteOpen(dsn string, logger *slog.Logger) (*sqlx.DB, error) {
108 logger.Info("opening db file", "dsn", dsn)
109 db, err := sqlx.Connect("sqlite", dsn)
110 if err != nil {
111 return nil, err
112 }
113
114- d := &DB{
115- DB: db,
116- logger: logger,
117- }
118-
119- err = d.upgrade()
120+ err = sqliteUpgrade(db)
121 if err != nil {
122- d.Close()
123+ db.Close()
124 return nil, err
125 }
126
127- return d, nil
128-}
129-
130-// Close implements db.DB.
131-func (d *DB) Close() error {
132- return d.DB.Close()
133+ return db, nil
134 }
135
136-func (db *DB) upgrade() error {
137+func sqliteUpgrade(db *sqlx.DB) error {
138 var version int
139 if err := db.QueryRow("PRAGMA user_version").Scan(&version); err != nil {
140 return fmt.Errorf("failed to query schema version: %v", err)
141@@ -245,7 +149,7 @@ func (db *DB) upgrade() error {
142 }()
143
144 if version == 0 {
145- if _, err := tx.Exec(schema); err != nil {
146+ if _, err := tx.Exec(sqliteSchema); err != nil {
147 return fmt.Errorf("failed to initialize schema: %v", err)
148 }
149 } else {
M
ssh.go
+1,
-1
1@@ -33,7 +33,7 @@ func authHandler(pr *PrCmd) func(ctx ssh.Context, key ssh.PublicKey) bool {
2
3 func GitSshServer(cfg *GitCfg) {
4 dbpath := filepath.Join(cfg.DataDir, "pr.db")
5- dbh, err := Open(dbpath, cfg.Logger)
6+ dbh, err := SqliteOpen(dbpath, cfg.Logger)
7 if err != nil {
8 panic(fmt.Sprintf("cannot find database file, check folder and perms: %s: %s", dbpath, err))
9 }
M
web.go
+1,
-1
1@@ -703,7 +703,7 @@ func StartWebServer(cfg *GitCfg) {
2 addr := fmt.Sprintf("%s:%s", cfg.Host, cfg.WebPort)
3
4 dbpath := filepath.Join(cfg.DataDir, "pr.db")
5- dbh, err := Open(dbpath, cfg.Logger)
6+ dbh, err := SqliteOpen(dbpath, cfg.Logger)
7 if err != nil {
8 panic(fmt.Sprintf("cannot find database file, check folder and perms: %s: %s", dbpath, err))
9 }