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