1package database
2
3import (
4 "context"
5 "strconv"
6 "strings"
7
8 "github.com/charmbracelet/soft-serve/server/db"
9 "github.com/charmbracelet/soft-serve/server/db/models"
10 "github.com/charmbracelet/soft-serve/server/store"
11)
12
13type lfsStore struct{}
14
15var _ store.LFSStore = (*lfsStore)(nil)
16
17func sanitizePath(path string) string {
18 path = strings.TrimSpace(path)
19 path = strings.TrimPrefix(path, "/")
20 return path
21}
22
23// CreateLFSLockForUser implements store.LFSStore.
24func (*lfsStore) CreateLFSLockForUser(ctx context.Context, tx db.Handler, repoID int64, userID int64, path string, refname string) error {
25 path = sanitizePath(path)
26 query := tx.Rebind(`INSERT INTO lfs_locks (repo_id, user_id, path, refname, updated_at)
27 VALUES (
28 ?,
29 ?,
30 ?,
31 ?,
32 CURRENT_TIMESTAMP
33 );
34 `)
35 _, err := tx.ExecContext(ctx, query, repoID, userID, path, refname)
36 return db.WrapError(err)
37}
38
39// GetLFSLocks implements store.LFSStore.
40func (*lfsStore) GetLFSLocks(ctx context.Context, tx db.Handler, repoID int64) ([]models.LFSLock, error) {
41 var locks []models.LFSLock
42 query := tx.Rebind(`
43 SELECT *
44 FROM lfs_locks
45 WHERE repo_id = ?;
46 `)
47 err := tx.SelectContext(ctx, &locks, query, repoID)
48 return locks, db.WrapError(err)
49}
50
51// GetLFSLocksForUser implements store.LFSStore.
52func (*lfsStore) GetLFSLocksForUser(ctx context.Context, tx db.Handler, repoID int64, userID int64) ([]models.LFSLock, error) {
53 var locks []models.LFSLock
54 query := tx.Rebind(`
55 SELECT *
56 FROM lfs_locks
57 WHERE repo_id = ? AND user_id = ?;
58 `)
59 err := tx.SelectContext(ctx, &locks, query, repoID, userID)
60 return locks, db.WrapError(err)
61}
62
63// GetLFSLocksForPath implements store.LFSStore.
64func (*lfsStore) GetLFSLocksForPath(ctx context.Context, tx db.Handler, repoID int64, path string) ([]models.LFSLock, error) {
65 path = sanitizePath(path)
66 var locks []models.LFSLock
67 query := tx.Rebind(`
68 SELECT *
69 FROM lfs_locks
70 WHERE repo_id = ? AND path = ?;
71 `)
72 err := tx.SelectContext(ctx, &locks, query, repoID, path)
73 return locks, db.WrapError(err)
74}
75
76// GetLFSLockForUserPath implements store.LFSStore.
77func (*lfsStore) GetLFSLockForUserPath(ctx context.Context, tx db.Handler, repoID int64, userID int64, path string) (models.LFSLock, error) {
78 path = sanitizePath(path)
79 var lock models.LFSLock
80 query := tx.Rebind(`
81 SELECT *
82 FROM lfs_locks
83 WHERE repo_id = ? AND user_id = ? AND path = ?;
84 `)
85 err := tx.GetContext(ctx, &lock, query, repoID, userID, path)
86 return lock, db.WrapError(err)
87}
88
89// GetLFSLockByID implements store.LFSStore.
90func (*lfsStore) GetLFSLockByID(ctx context.Context, tx db.Handler, id string) (models.LFSLock, error) {
91 iid, err := strconv.Atoi(id)
92 if err != nil {
93 return models.LFSLock{}, err
94 }
95
96 var lock models.LFSLock
97 query := tx.Rebind(`
98 SELECT *
99 FROM lfs_locks
100 WHERE lfs_locks.id = ?;
101 `)
102 err = tx.GetContext(ctx, &lock, query, iid)
103 return lock, db.WrapError(err)
104}
105
106// GetLFSLockForUserByID implements store.LFSStore.
107func (*lfsStore) GetLFSLockForUserByID(ctx context.Context, tx db.Handler, userID int64, id string) (models.LFSLock, error) {
108 iid, err := strconv.Atoi(id)
109 if err != nil {
110 return models.LFSLock{}, err
111 }
112
113 var lock models.LFSLock
114 query := tx.Rebind(`
115 SELECT *
116 FROM lfs_locks
117 WHERE id = ? AND user_id = ?;
118 `)
119 err = tx.GetContext(ctx, &lock, query, iid, userID)
120 return lock, db.WrapError(err)
121}
122
123// DeleteLFSLockForUserByID implements store.LFSStore.
124func (*lfsStore) DeleteLFSLockForUserByID(ctx context.Context, tx db.Handler, userID int64, id string) error {
125 iid, err := strconv.Atoi(id)
126 if err != nil {
127 return err
128 }
129
130 query := tx.Rebind(`
131 DELETE FROM lfs_locks
132 WHERE user_id = ? AND id = ?;
133 `)
134 _, err = tx.ExecContext(ctx, query, userID, iid)
135 return db.WrapError(err)
136}
137
138// CreateLFSObject implements store.LFSStore.
139func (*lfsStore) CreateLFSObject(ctx context.Context, tx db.Handler, repoID int64, oid string, size int64) error {
140 query := tx.Rebind(`INSERT INTO lfs_objects (repo_id, oid, size, updated_at) VALUES (?, ?, ?, CURRENT_TIMESTAMP);`)
141 _, err := tx.ExecContext(ctx, query, repoID, oid, size)
142 return db.WrapError(err)
143}
144
145// DeleteLFSObjectByOid implements store.LFSStore.
146func (*lfsStore) DeleteLFSObjectByOid(ctx context.Context, tx db.Handler, repoID int64, oid string) error {
147 query := tx.Rebind(`DELETE FROM lfs_objects WHERE repo_id = ? AND oid = ?;`)
148 _, err := tx.ExecContext(ctx, query, repoID, oid)
149 return db.WrapError(err)
150}
151
152// GetLFSObjectByOid implements store.LFSStore.
153func (*lfsStore) GetLFSObjectByOid(ctx context.Context, tx db.Handler, repoID int64, oid string) (models.LFSObject, error) {
154 var obj models.LFSObject
155 query := tx.Rebind(`SELECT * FROM lfs_objects WHERE repo_id = ? AND oid = ?;`)
156 err := tx.GetContext(ctx, &obj, query, repoID, oid)
157 return obj, db.WrapError(err)
158}
159
160// GetLFSObjects implements store.LFSStore.
161func (*lfsStore) GetLFSObjects(ctx context.Context, tx db.Handler, repoID int64) ([]models.LFSObject, error) {
162 var objs []models.LFSObject
163 query := tx.Rebind(`SELECT * FROM lfs_objects WHERE repo_id = ?;`)
164 err := tx.SelectContext(ctx, &objs, query, repoID)
165 return objs, db.WrapError(err)
166}
167
168// GetLFSObjectsByName implements store.LFSStore.
169func (*lfsStore) GetLFSObjectsByName(ctx context.Context, tx db.Handler, name string) ([]models.LFSObject, error) {
170 var objs []models.LFSObject
171 query := tx.Rebind(`
172 SELECT lfs_objects.*
173 FROM lfs_objects
174 INNER JOIN repos ON lfs_objects.repo_id = repos.id
175 WHERE repos.name = ?;
176 `)
177 err := tx.SelectContext(ctx, &objs, query, name)
178 return objs, db.WrapError(err)
179}