repos / git-pr

a self-hosted git collaboration server
git clone https://github.com/picosh/git-pr.git

commit
2ee7b51
parent
088df6f
author
Eric Bower
date
2024-06-24 23:11:27 -0400 EDT
chore: db migrations
2 files changed,  +52, -7
M db.go
M ssh.go
M db.go
+52, -6
 1@@ -1,6 +1,7 @@
 2 package git
 3 
 4 import (
 5+	"fmt"
 6 	"log/slog"
 7 	"time"
 8 
 9@@ -132,6 +133,10 @@ CREATE TABLE IF NOT EXISTS event_logs (
10 );
11 `
12 
13+var sqliteMigrations = []string{
14+	"", // migration #0 is reserved for schema initialization
15+}
16+
17 // Open opens a database connection.
18 func Open(dsn string, logger *slog.Logger) (*DB, error) {
19 	db, err := sqlx.Connect("sqlite", dsn)
20@@ -144,16 +149,57 @@ func Open(dsn string, logger *slog.Logger) (*DB, error) {
21 		logger: logger,
22 	}
23 
24-	return d, nil
25-}
26+	err = d.upgrade()
27+	if err != nil {
28+		d.Close()
29+		return nil, err
30+	}
31 
32-func (d *DB) Migrate() {
33-	// exec the schema or fail; multi-statement Exec behavior varies between
34-	// database drivers;  pq will exec them all, sqlite3 won't, ymmv
35-	d.DB.MustExec(schema)
36+	return d, nil
37 }
38 
39 // Close implements db.DB.
40 func (d *DB) Close() error {
41 	return d.DB.Close()
42 }
43+
44+func (db *DB) upgrade() error {
45+	var version int
46+	if err := db.QueryRow("PRAGMA user_version").Scan(&version); err != nil {
47+		return fmt.Errorf("failed to query schema version: %v", err)
48+	}
49+
50+	if version == len(sqliteMigrations) {
51+		return nil
52+	} else if version > len(sqliteMigrations) {
53+		return fmt.Errorf("git-pr (version %d) older than schema (version %d)", len(sqliteMigrations), version)
54+	}
55+
56+	tx, err := db.Begin()
57+	if err != nil {
58+		return err
59+	}
60+	defer func() {
61+		_ = tx.Rollback()
62+	}()
63+
64+	if version == 0 {
65+		if _, err := tx.Exec(schema); err != nil {
66+			return fmt.Errorf("failed to initialize schema: %v", err)
67+		}
68+	} else {
69+		for i := version; i < len(sqliteMigrations); i++ {
70+			if _, err := tx.Exec(sqliteMigrations[i]); err != nil {
71+				return fmt.Errorf("failed to execute migration #%v: %v", i, err)
72+			}
73+		}
74+	}
75+
76+	// For some reason prepared statements don't work here
77+	_, err = tx.Exec(fmt.Sprintf("PRAGMA user_version = %d", len(sqliteMigrations)))
78+	if err != nil {
79+		return fmt.Errorf("failed to bump schema version: %v", err)
80+	}
81+
82+	return tx.Commit()
83+}
M ssh.go
+0, -1
1@@ -29,7 +29,6 @@ func GitSshServer(cfg *GitCfg) {
2 	if err != nil {
3 		panic(err)
4 	}
5-	dbh.Migrate()
6 
7 	keys, err := getAuthorizedKeys(filepath.Join(cfg.DataPath, "authorized_keys"))
8 	if err == nil {