- commit
- 04302e8
- parent
- 95ace53
- author
- Eric Bower
- date
- 2024-05-01 16:03:05 -0400 EDT
changes
M
db.go
+100,
-51
1@@ -1,65 +1,114 @@
2 package git
3
4 import (
5- "database/sql"
6- "time"
7+ "log/slog"
8+
9+ "github.com/jmoiron/sqlx"
10+ _ "modernc.org/sqlite" // sqlite driver
11 )
12
13-// User is the entity repesenting a pubkey authenticated user
14-// A user and a single ssh key-pair are synonymous in this context
15-type User struct {
16- ID int64 `db:"id"`
17- Name string `db:"name"`
18- Pubkey string `db:"pubkey"`
19- CreatedAt time.Time `db:"created_at"`
20- UpdatedAt time.Time `db:"updated_at"`
21+// DB is the interface for a pico/git database.
22+type DB struct {
23+ *sqlx.DB
24+ logger *slog.Logger
25 }
26
27-// PatchRequest is a database model for patches submitted to a Repo
28-type PatchRequest struct {
29- ID int64 `db:"id"`
30- UserID int64 `db:"user_id"`
31- RepoID int64 `db:"repo_id"`
32- Name string `db:"name"`
33- CreatedAt time.Time `db:"created_at"`
34- UpdatedAt time.Time `db:"updated_at"`
35-}
36+var schema = `
37+CREATE TABLE IF NOT EXISTS users (
38+ id INTEGER PRIMARY KEY AUTOINCREMENT,
39+ name TEXT NOT NULL UNIQUE,
40+ admin BOOLEAN NOT NULL,
41+ public_key TEXT NOT NULL UNIQUE,
42+ created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
43+ updated_at DATETIME NOT NULL
44+);
45
46-// Patch is a database model for a single entry in a patchset
47-// This usually corresponds to a git commit.
48-type Patch struct {
49- ID int64 `db:"id"`
50- UserID int64 `db:"user_id"`
51- PatchRequestID int64 `db:"patch_request_id"`
52- FromName string `db:"from_name"`
53- FromEmail string `db:"from_email"`
54- Subject string `db:"subject"`
55- Text string `db:"text"`
56- Date time.Time `db:"date"`
57- CreatedAt time.Time `db:"created_at"`
58-}
59+CREATE TABLE IF NOT EXISTS repos (
60+ id INTEGER PRIMARY KEY AUTOINCREMENT,
61+ name TEXT NOT NULL UNIQUE,
62+ description TEXT NOT NULL UNIQUE,
63+ private BOOLEAN NOT NULL,
64+ created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
65+ updated_at DATETIME NOT NULL
66+);
67+
68+CREATE TABLE IF NOT EXISTS patch_requests (
69+ id INTEGER PRIMARY KEY AUTOINCREMENT,
70+ user_id INTEGER NOT NULL,
71+ repo_id INTEGER NOT NULL,
72+ name TEXT NOT NULL,
73+ created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
74+ updated_at DATETIME NOT NULL,
75+ CONSTRAINT user_id_fk
76+ FOREIGN KEY(user_id) REFERENCES users(id)
77+ ON DELETE CASCADE
78+ ON UPDATE CASCADE,
79+ CONSTRAINT repo_id_fk
80+ FOREIGN KEY(repo_id) REFERENCES repos(id)
81+ ON DELETE CASCADE
82+ ON UPDATE CASCADE
83+);
84+
85+CREATE TABLE IF NOT EXISTS patches (
86+ id INTEGER PRIMARY KEY AUTOINCREMENT,
87+ user_id INTEGER NOT NULL,
88+ patch_request_id INTEGER NOT NULL,
89+ from_name TEXT NOT NULL,
90+ from_email TEXT NOT NULL,
91+ subject TEXT NOT NULL,
92+ text TEXT NOT NULL,
93+ date DATETIME NOT NULL,
94+ created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
95+ CONSTRAINT user_id_fk
96+ FOREIGN KEY(user_id) REFERENCES users(id)
97+ ON DELETE CASCADE
98+ ON UPDATE CASCADE,
99+ CONSTRAINT pr_id_fk
100+ FOREIGN KEY(patch_request_id) REFERENCES patch_requests(id)
101+ ON DELETE CASCADE
102+ ON UPDATE CASCADE
103+);
104+
105+CREATE TABLE IF NOT EXISTS comments (
106+ id INTEGER PRIMARY KEY AUTOINCREMENT,
107+ user_id INTEGER NOT NULL,
108+ patch_request_id INTEGER NOT NULL,
109+ text TEXT NOT NULL,
110+ created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
111+ updated_at DATETIME NOT NULL,
112+ CONSTRAINT user_id_fk
113+ FOREIGN KEY(user_id) REFERENCES users(id)
114+ ON DELETE CASCADE
115+ ON UPDATE CASCADE,
116+ CONSTRAINT pr_id_fk
117+ FOREIGN KEY(patch_request_id) REFERENCES patch_requests(id)
118+ ON DELETE CASCADE
119+ ON UPDATE CASCADE
120+);
121+`
122+
123+// Open opens a database connection.
124+func Open(dsn string, logger *slog.Logger) (*DB, error) {
125+ db, err := sqlx.Connect("sqlite", dsn)
126+ if err != nil {
127+ return nil, err
128+ }
129+
130+ d := &DB{
131+ DB: db,
132+ logger: logger,
133+ }
134
135-// Comment is a database model for a non-patch comment within a PatchRequest
136-type Comment struct {
137- ID int64 `db:"id"`
138- UserID int64 `db:"user_id"`
139- PatchRequestID int64 `db:"patch_request_id"`
140- Text string `db:"text"`
141- CreatedAt time.Time `db:"created_at"`
142- UpdatedAt time.Time `db:"updated_at"`
143+ return d, nil
144 }
145
146-// Repo is a database model for a repository.
147-type Repo struct {
148- ID int64 `db:"id"`
149- Name string `db:"name"`
150- ProjectName string `db:"project_name"`
151- Description string `db:"description"`
152- Private bool `db:"private"`
153- UserID sql.NullInt64 `db:"user_id"`
154- CreatedAt time.Time `db:"created_at"`
155- UpdatedAt time.Time `db:"updated_at"`
156+func (d *DB) Migrate() {
157+ // exec the schema or fail; multi-statement Exec behavior varies between
158+ // database drivers; pq will exec them all, sqlite3 won't, ymmv
159+ d.DB.MustExec(schema)
160 }
161
162-type GitDB interface {
163+// Close implements db.DB.
164+func (d *DB) Close() error {
165+ return d.DB.Close()
166 }
M
mdw.go
+25,
-1
1@@ -4,6 +4,7 @@ import (
2 "fmt"
3 "path/filepath"
4
5+ ssgit "github.com/charmbracelet/soft-serve/git"
6 "github.com/charmbracelet/soft-serve/pkg/git"
7 "github.com/charmbracelet/soft-serve/pkg/utils"
8 "github.com/charmbracelet/ssh"
9@@ -44,7 +45,22 @@ func gitServiceCommands(sesh ssh.Session, cfg *GitCfg, cmd, repo string) error {
10 return nil
11 }
12
13-func GitServerMiddleware(cfg *GitCfg) wish.Middleware {
14+func createRepo(cfg *GitCfg, rawName string) (*Repo, error) {
15+ name := utils.SanitizeRepo(rawName)
16+ if err := utils.ValidateRepo(name); err != nil {
17+ return nil, err
18+ }
19+ reposDir := filepath.Join(cfg.DataPath, "repos")
20+
21+ repo := name + ".git"
22+ rp := filepath.Join(reposDir, repo)
23+ _, err := ssgit.Init(rp, true)
24+ if err != nil {
25+ return nil, err
26+ }
27+}
28+
29+func GitServerMiddleware(cfg *GitCfg, dbh *DB) wish.Middleware {
30 return func(next ssh.Handler) ssh.Handler {
31 return func(sesh ssh.Session) {
32 args := sesh.Command()
33@@ -60,6 +76,14 @@ func GitServerMiddleware(cfg *GitCfg) wish.Middleware {
34 }
35 } else if cmd == "help" {
36 wish.Println(sesh, "commands: [help, git-receive-pack, git-upload-pack]")
37+ } else if cmd == "pr" {
38+ repoName := args[1]
39+ fmt.Println(repoName)
40+ // dbpool.GetRepoByName(repoName)
41+ // pr, err := dbpool.InsertPatchRequest(userID, repoID, name)
42+ // dbpool.InsertPatches(userID, pr.ID, patches)
43+ // id := fmt.Sprintf("%s/%s", repoName, pr.ID)
44+ // wish.Printf("Patch Request ID: %s", id)
45 } else {
46 fmt.Println("made it here")
47 next(sesh)
+64,
-0
1@@ -0,0 +1,64 @@
2+package git
3+
4+import (
5+ "database/sql"
6+ "time"
7+)
8+
9+// User is the entity repesenting a pubkey authenticated user
10+// A user and a single ssh key-pair are synonymous in this context
11+type User struct {
12+ ID int64 `db:"id"`
13+ Name string `db:"name"`
14+ Pubkey string `db:"pubkey"`
15+ CreatedAt time.Time `db:"created_at"`
16+ UpdatedAt time.Time `db:"updated_at"`
17+}
18+
19+// Repo is a database model for a repository.
20+type Repo struct {
21+ ID int64 `db:"id"`
22+ Name string `db:"name"`
23+ Description string `db:"description"`
24+ Private bool `db:"private"`
25+ UserID sql.NullInt64 `db:"user_id"`
26+ CreatedAt time.Time `db:"created_at"`
27+ UpdatedAt time.Time `db:"updated_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 int64 `db:"repo_id"`
35+ Name string `db:"name"`
36+ CreatedAt time.Time `db:"created_at"`
37+ UpdatedAt time.Time `db:"updated_at"`
38+}
39+
40+// Patch is a database model for a single entry in a patchset
41+// This usually corresponds to a git commit.
42+type Patch struct {
43+ ID int64 `db:"id"`
44+ UserID int64 `db:"user_id"`
45+ PatchRequestID int64 `db:"patch_request_id"`
46+ FromName string `db:"from_name"`
47+ FromEmail string `db:"from_email"`
48+ Subject string `db:"subject"`
49+ Text string `db:"text"`
50+ Date time.Time `db:"date"`
51+ CreatedAt time.Time `db:"created_at"`
52+}
53+
54+// Comment is a database model for a non-patch comment within a PatchRequest
55+type Comment struct {
56+ ID int64 `db:"id"`
57+ UserID int64 `db:"user_id"`
58+ PatchRequestID int64 `db:"patch_request_id"`
59+ Text string `db:"text"`
60+ CreatedAt time.Time `db:"created_at"`
61+ UpdatedAt time.Time `db:"updated_at"`
62+}
63+
64+type GitDB interface {
65+}
M
ssh.go
+6,
-1
1@@ -34,6 +34,11 @@ func GitSshServer() {
2 cfg := NewGitCfg()
3 logger := slog.Default()
4 handler := NewUploadHandler(cfg, logger)
5+ dbh, err := Open(":memory:", logger)
6+ if err != nil {
7+ panic(err)
8+ }
9+ dbh.Migrate()
10
11 s, err := wish.NewServer(
12 wish.WithAddress(
13@@ -47,7 +52,7 @@ func GitSshServer() {
14 wish.WithMiddleware(
15 scp.Middleware(handler),
16 wishrsync.Middleware(handler),
17- GitServerMiddleware(cfg),
18+ GitServerMiddleware(cfg, dbh),
19 ),
20 )
21