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