0.1 5d00907

sqliteinit.go RawHistoryFolder

1package server
2
3import (
4	"database/sql"
5	"fmt"
6	"os"
7	"path/filepath"
8
9	"github.com/bnema/gordon/internal/db"
10	pkgsqlite "github.com/bnema/gordon/pkg/sqlite"
11	_ "modernc.org/sqlite"
12)
13
14const (
15	DBFilename = "sqlite.db"
16)
17
18func (a *App) getDiskDBFilePath() string {
19	DiskDBfilepath := filepath.Join(a.DBDir, a.DBFilename)
20	return DiskDBfilepath
21}
22
23// ensureDBDir ensures that the database directory exists.
24func (a *App) ensureDBDir() error {
25	if _, err := os.Stat(a.DBDir); os.IsNotExist(err) {
26		if err := os.MkdirAll(a.DBDir, 0755); err != nil {
27			return err
28		}
29	}
30	return nil
31}
32
33// checkDBFile checks if the database file exists.
34func (a *App) checkDBFile(dbPath string) (bool, error) {
35	if _, err := os.Stat(dbPath); os.IsNotExist(err) {
36		return false, nil
37	} else if err != nil {
38		return false, err
39	}
40	return true, nil
41}
42
43// InitializeDB initializes the database
44func InitializeDB(a *App) (*sql.DB, error) {
45	if err := a.ensureDBDir(); err != nil {
46		return nil, fmt.Errorf("failed to ensure DB directory: %w", err)
47	}
48
49	dbPath := a.getDiskDBFilePath()
50
51	dbExists, err := a.checkDBFile(dbPath)
52	if err != nil {
53		return nil, fmt.Errorf("failed to check DB file: %w", err)
54	}
55
56	if !dbExists {
57		if err := bootstrapDB(dbPath, a); err != nil {
58			return nil, fmt.Errorf("failed to bootstrap DB: %w", err)
59		}
60	}
61
62	// Change here from "sqlite3" to "sqlite"
63	db, err := sql.Open("sqlite", dbPath)
64	if err != nil {
65		return nil, fmt.Errorf("failed to open disk DB: %w", err)
66	}
67
68	a.DB = db
69
70	if dbExists {
71		// Populate the struct tables from the database
72		if err := PopulateStructWithTables(a); err != nil {
73			return nil, err
74		}
75	}
76
77	return db, nil
78}
79
80func bootstrapDB(dbPath string, app *App) error {
81	// Change here from "sqlite3" to "sqlite"
82	db, err := sql.Open("sqlite", dbPath)
83	if err != nil {
84		return err
85	}
86	defer db.Close()
87
88	tables := app.DBTables
89
90	if err := pkgsqlite.CreateTable(db, tables.User, "user"); err != nil {
91		return err
92	}
93	if err := pkgsqlite.CreateTable(db, tables.Account, "account"); err != nil {
94		return err
95	}
96	if err := pkgsqlite.CreateTable(db, tables.Sessions, "sessions"); err != nil {
97		return err
98	}
99	if err := pkgsqlite.CreateTable(db, tables.Provider, "provider"); err != nil {
100		return err
101	}
102
103	if err := pkgsqlite.CreateTable(db, tables.Clients, "clients"); err != nil {
104		return err
105	}
106
107	return nil
108}
109
110type DBTable interface {
111	ScanFromRows(rows *sql.Rows) error
112}
113
114type UserWrapper struct {
115	*db.User
116}
117
118type AccountWrapper struct {
119	*db.Account
120}
121
122type ProviderWrapper struct {
123	*db.Provider
124}
125
126type SessionsWrapper struct {
127	*db.Sessions
128}
129
130type ClientsWrapper struct {
131	*db.Clients
132}
133
134func populateTableFromDB(a *App, query string, table DBTable) error {
135	rows, err := a.DB.Query(query)
136	if err != nil {
137		return err
138	}
139	defer rows.Close()
140
141	for rows.Next() {
142		if err := table.ScanFromRows(rows); err != nil {
143			return err
144		}
145	}
146	return rows.Err()
147}
148
149// Implementation of DBTable for User, Account, Provider, Sessions
150func (u *UserWrapper) ScanFromRows(rows *sql.Rows) error {
151	return rows.Scan(&u.ID, &u.Name, &u.Email)
152}
153
154func (a *AccountWrapper) ScanFromRows(rows *sql.Rows) error {
155	return rows.Scan(&a.ID, &a.UserID)
156}
157
158func (p *ProviderWrapper) ScanFromRows(rows *sql.Rows) error {
159	return rows.Scan(&p.ID, &p.AccountID, &p.Name, &p.Login, &p.AvatarURL, &p.ProfileURL, &p.Email)
160}
161
162func (s *SessionsWrapper) ScanFromRows(rows *sql.Rows) error {
163	return rows.Scan(&s.ID, &s.AccountID, &s.AccessToken, &s.BrowserInfo, &s.Expires, &s.IsOnline)
164}
165
166func (c *ClientsWrapper) ScanFromRows(rows *sql.Rows) error {
167	return rows.Scan(&c.ID, &c.AccountID, &c.OS, &c.IP, &c.Hostname, &c.Expires)
168}
169
170// PopulateStructWithTables updates db struct with tables
171func PopulateStructWithTables(a *App) error {
172	tables := map[string]DBTable{
173		"SELECT id, name, email FROM user":                                                    &UserWrapper{&a.DBTables.User},
174		"SELECT id, user_id FROM account":                                                     &AccountWrapper{&a.DBTables.Account},
175		"SELECT id, account_id, name, login, avatar_url, profile_url, email FROM provider":    &ProviderWrapper{&a.DBTables.Provider},
176		"SELECT id, account_id, access_token, browser_info, expires, is_online FROM sessions": &SessionsWrapper{&a.DBTables.Sessions},
177		"SELECT id, account_id, os, ip, hostname, expires FROM clients":                       &ClientsWrapper{&a.DBTables.Clients},
178	}
179
180	for query, table := range tables {
181		if err := populateTableFromDB(a, query, table); err != nil {
182			return err
183		}
184	}
185
186	return nil
187}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close