- reduce duplicated codes
- possibly remove/refactor
ResolvedRepoin future - allow accessing
db.Repoafter it is resolved
+19
-19
appview/issues/issues.go
+19
-19
appview/issues/issues.go
···
73
73
return
74
74
}
75
75
76
-
issue, comments, err := db.GetIssueWithComments(rp.db, f.RepoAt, issueIdInt)
76
+
issue, comments, err := db.GetIssueWithComments(rp.db, f.RepoAt(), issueIdInt)
77
77
if err != nil {
78
78
log.Println("failed to get issue and comments", err)
79
79
rp.pages.Notice(w, "issues", "Failed to load issue. Try again later.")
···
142
142
return
143
143
}
144
144
145
-
issue, err := db.GetIssue(rp.db, f.RepoAt, issueIdInt)
145
+
issue, err := db.GetIssue(rp.db, f.RepoAt(), issueIdInt)
146
146
if err != nil {
147
147
log.Println("failed to get issue", err)
148
148
rp.pages.Notice(w, "issue-action", "Failed to close issue. Try again later.")
···
186
186
return
187
187
}
188
188
189
-
err = db.CloseIssue(rp.db, f.RepoAt, issueIdInt)
189
+
err = db.CloseIssue(rp.db, f.RepoAt(), issueIdInt)
190
190
if err != nil {
191
191
log.Println("failed to close issue", err)
192
192
rp.pages.Notice(w, "issue-action", "Failed to close issue. Try again later.")
···
218
218
return
219
219
}
220
220
221
-
issue, err := db.GetIssue(rp.db, f.RepoAt, issueIdInt)
221
+
issue, err := db.GetIssue(rp.db, f.RepoAt(), issueIdInt)
222
222
if err != nil {
223
223
log.Println("failed to get issue", err)
224
224
rp.pages.Notice(w, "issue-action", "Failed to close issue. Try again later.")
···
235
235
isIssueOwner := user.Did == issue.OwnerDid
236
236
237
237
if isCollaborator || isIssueOwner {
238
-
err := db.ReopenIssue(rp.db, f.RepoAt, issueIdInt)
238
+
err := db.ReopenIssue(rp.db, f.RepoAt(), issueIdInt)
239
239
if err != nil {
240
240
log.Println("failed to reopen issue", err)
241
241
rp.pages.Notice(w, "issue-action", "Failed to reopen issue. Try again later.")
···
279
279
280
280
err := db.NewIssueComment(rp.db, &db.Comment{
281
281
OwnerDid: user.Did,
282
-
RepoAt: f.RepoAt,
282
+
RepoAt: f.RepoAt(),
283
283
Issue: issueIdInt,
284
284
CommentId: commentId,
285
285
Body: body,
···
294
294
createdAt := time.Now().Format(time.RFC3339)
295
295
commentIdInt64 := int64(commentId)
296
296
ownerDid := user.Did
297
-
issueAt, err := db.GetIssueAt(rp.db, f.RepoAt, issueIdInt)
297
+
issueAt, err := db.GetIssueAt(rp.db, f.RepoAt(), issueIdInt)
298
298
if err != nil {
299
299
log.Println("failed to get issue at", err)
300
300
rp.pages.Notice(w, "issue-comment", "Failed to create comment.")
301
301
return
302
302
}
303
303
304
-
atUri := f.RepoAt.String()
304
+
atUri := f.RepoAt().String()
305
305
client, err := rp.oauth.AuthorizedClient(r)
306
306
if err != nil {
307
307
log.Println("failed to get authorized client", err)
···
358
358
return
359
359
}
360
360
361
-
issue, err := db.GetIssue(rp.db, f.RepoAt, issueIdInt)
361
+
issue, err := db.GetIssue(rp.db, f.RepoAt(), issueIdInt)
362
362
if err != nil {
363
363
log.Println("failed to get issue", err)
364
364
rp.pages.Notice(w, "issues", "Failed to load issue. Try again later.")
365
365
return
366
366
}
367
367
368
-
comment, err := db.GetComment(rp.db, f.RepoAt, issueIdInt, commentIdInt)
368
+
comment, err := db.GetComment(rp.db, f.RepoAt(), issueIdInt, commentIdInt)
369
369
if err != nil {
370
370
http.Error(w, "bad comment id", http.StatusBadRequest)
371
371
return
···
417
417
return
418
418
}
419
419
420
-
issue, err := db.GetIssue(rp.db, f.RepoAt, issueIdInt)
420
+
issue, err := db.GetIssue(rp.db, f.RepoAt(), issueIdInt)
421
421
if err != nil {
422
422
log.Println("failed to get issue", err)
423
423
rp.pages.Notice(w, "issues", "Failed to load issue. Try again later.")
424
424
return
425
425
}
426
426
427
-
comment, err := db.GetComment(rp.db, f.RepoAt, issueIdInt, commentIdInt)
427
+
comment, err := db.GetComment(rp.db, f.RepoAt(), issueIdInt, commentIdInt)
428
428
if err != nil {
429
429
http.Error(w, "bad comment id", http.StatusBadRequest)
430
430
return
···
539
539
return
540
540
}
541
541
542
-
issue, err := db.GetIssue(rp.db, f.RepoAt, issueIdInt)
542
+
issue, err := db.GetIssue(rp.db, f.RepoAt(), issueIdInt)
543
543
if err != nil {
544
544
log.Println("failed to get issue", err)
545
545
rp.pages.Notice(w, "issues", "Failed to load issue. Try again later.")
···
554
554
return
555
555
}
556
556
557
-
comment, err := db.GetComment(rp.db, f.RepoAt, issueIdInt, commentIdInt)
557
+
comment, err := db.GetComment(rp.db, f.RepoAt(), issueIdInt, commentIdInt)
558
558
if err != nil {
559
559
http.Error(w, "bad comment id", http.StatusBadRequest)
560
560
return
···
572
572
573
573
// optimistic deletion
574
574
deleted := time.Now()
575
-
err = db.DeleteComment(rp.db, f.RepoAt, issueIdInt, commentIdInt)
575
+
err = db.DeleteComment(rp.db, f.RepoAt(), issueIdInt, commentIdInt)
576
576
if err != nil {
577
577
log.Println("failed to delete comment")
578
578
rp.pages.Notice(w, fmt.Sprintf("comment-%s-status", commentId), "failed to delete comment")
···
641
641
return
642
642
}
643
643
644
-
issues, err := db.GetIssues(rp.db, f.RepoAt, isOpen, page)
644
+
issues, err := db.GetIssues(rp.db, f.RepoAt(), isOpen, page)
645
645
if err != nil {
646
646
log.Println("failed to get issues", err)
647
647
rp.pages.Notice(w, "issues", "Failed to load issues. Try again later.")
···
704
704
}
705
705
706
706
issue := &db.Issue{
707
-
RepoAt: f.RepoAt,
707
+
RepoAt: f.RepoAt(),
708
708
Title: title,
709
709
Body: body,
710
710
OwnerDid: user.Did,
···
722
722
rp.pages.Notice(w, "issues", "Failed to create issue.")
723
723
return
724
724
}
725
-
atUri := f.RepoAt.String()
725
+
atUri := f.RepoAt().String()
726
726
resp, err := client.RepoPutRecord(r.Context(), &comatproto.RepoPutRecord_Input{
727
727
Collection: tangled.RepoIssueNSID,
728
728
Repo: user.Did,
···
743
743
return
744
744
}
745
745
746
-
err = db.SetIssueAt(rp.db, f.RepoAt, issue.IssueId, resp.Uri)
746
+
err = db.SetIssueAt(rp.db, f.RepoAt(), issue.IssueId, resp.Uri)
747
747
if err != nil {
748
748
log.Println("failed to set issue at", err)
749
749
rp.pages.Notice(w, "issues", "Failed to create issue.")
+3
-8
appview/middleware/middleware.go
+3
-8
appview/middleware/middleware.go
···
8
8
"slices"
9
9
"strconv"
10
10
"strings"
11
-
"time"
12
11
13
12
"github.com/bluesky-social/indigo/atproto/identity"
14
13
"github.com/go-chi/chi/v5"
···
222
221
return
223
222
}
224
223
225
-
ctx := context.WithValue(req.Context(), "knot", repo.Knot)
226
-
ctx = context.WithValue(ctx, "repoAt", repo.AtUri)
227
-
ctx = context.WithValue(ctx, "repoDescription", repo.Description)
228
-
ctx = context.WithValue(ctx, "repoSpindle", repo.Spindle)
229
-
ctx = context.WithValue(ctx, "repoAddedAt", repo.Created.Format(time.RFC3339))
224
+
ctx := context.WithValue(req.Context(), "repo", repo)
230
225
next.ServeHTTP(w, req.WithContext(ctx))
231
226
})
232
227
}
···
251
246
return
252
247
}
253
248
254
-
pr, err := db.GetPull(mw.db, f.RepoAt, prIdInt)
249
+
pr, err := db.GetPull(mw.db, f.RepoAt(), prIdInt)
255
250
if err != nil {
256
251
log.Println("failed to get pull and comments", err)
257
252
return
···
292
287
return
293
288
}
294
289
295
-
fullName := f.OwnerHandle() + "/" + f.RepoName
290
+
fullName := f.OwnerHandle() + "/" + f.Name
296
291
297
292
if r.Header.Get("User-Agent") == "Go-http-client/1.1" {
298
293
if r.URL.Query().Get("go-get") == "1" {
+6
-6
appview/repo/artifact.go
+6
-6
appview/repo/artifact.go
···
76
76
Artifact: uploadBlobResp.Blob,
77
77
CreatedAt: createdAt.Format(time.RFC3339),
78
78
Name: handler.Filename,
79
-
Repo: f.RepoAt.String(),
79
+
Repo: f.RepoAt().String(),
80
80
Tag: tag.Tag.Hash[:],
81
81
},
82
82
},
···
100
100
artifact := db.Artifact{
101
101
Did: user.Did,
102
102
Rkey: rkey,
103
-
RepoAt: f.RepoAt,
103
+
RepoAt: f.RepoAt(),
104
104
Tag: tag.Tag.Hash,
105
105
CreatedAt: createdAt,
106
106
BlobCid: cid.Cid(uploadBlobResp.Blob.Ref),
···
155
155
156
156
artifacts, err := db.GetArtifact(
157
157
rp.db,
158
-
db.FilterEq("repo_at", f.RepoAt),
158
+
db.FilterEq("repo_at", f.RepoAt()),
159
159
db.FilterEq("tag", tag.Tag.Hash[:]),
160
160
db.FilterEq("name", filename),
161
161
)
···
197
197
198
198
artifacts, err := db.GetArtifact(
199
199
rp.db,
200
-
db.FilterEq("repo_at", f.RepoAt),
200
+
db.FilterEq("repo_at", f.RepoAt()),
201
201
db.FilterEq("tag", tag[:]),
202
202
db.FilterEq("name", filename),
203
203
)
···
239
239
defer tx.Rollback()
240
240
241
241
err = db.DeleteArtifact(tx,
242
-
db.FilterEq("repo_at", f.RepoAt),
242
+
db.FilterEq("repo_at", f.RepoAt()),
243
243
db.FilterEq("tag", artifact.Tag[:]),
244
244
db.FilterEq("name", filename),
245
245
)
···
270
270
return nil, err
271
271
}
272
272
273
-
result, err := us.Tags(f.OwnerDid(), f.RepoName)
273
+
result, err := us.Tags(f.OwnerDid(), f.Name)
274
274
if err != nil {
275
275
log.Println("failed to reach knotserver", err)
276
276
return nil, err
+5
-5
appview/repo/index.go
+5
-5
appview/repo/index.go
···
37
37
return
38
38
}
39
39
40
-
result, err := us.Index(f.OwnerDid(), f.RepoName, ref)
40
+
result, err := us.Index(f.OwnerDid(), f.Name, ref)
41
41
if err != nil {
42
42
rp.pages.Error503(w)
43
43
log.Println("failed to reach knotserver", err)
···
166
166
// first attempt to fetch from db
167
167
langs, err := db.GetRepoLanguages(
168
168
rp.db,
169
-
db.FilterEq("repo_at", f.RepoAt),
169
+
db.FilterEq("repo_at", f.RepoAt()),
170
170
db.FilterEq("ref", f.Ref),
171
171
)
172
172
173
173
if err != nil || langs == nil {
174
174
// non-fatal, fetch langs from ks
175
-
ls, err := signedClient.RepoLanguages(f.OwnerDid(), f.RepoName, f.Ref)
175
+
ls, err := signedClient.RepoLanguages(f.OwnerDid(), f.Name, f.Ref)
176
176
if err != nil {
177
177
return nil, err
178
178
}
···
182
182
183
183
for l, s := range ls.Languages {
184
184
langs = append(langs, db.RepoLanguage{
185
-
RepoAt: f.RepoAt,
185
+
RepoAt: f.RepoAt(),
186
186
Ref: f.Ref,
187
187
IsDefaultRef: isDefaultRef,
188
188
Language: l,
···
279
279
hiddenRef := fmt.Sprintf("hidden/%s/%s", f.Ref, f.Ref)
280
280
281
281
var status types.AncestorCheckResponse
282
-
forkSyncableResp, err := signedClient.RepoForkAheadBehind(user.Did, string(f.RepoAt), repoInfo.Name, f.Ref, hiddenRef)
282
+
forkSyncableResp, err := signedClient.RepoForkAheadBehind(user.Did, string(f.RepoAt()), repoInfo.Name, f.Ref, hiddenRef)
283
283
if err != nil {
284
284
log.Printf("failed to check if fork is ahead/behind: %s", err)
285
285
return nil, err
+25
-58
appview/reporesolver/resolver.go
+25
-58
appview/reporesolver/resolver.go
···
12
12
"strings"
13
13
14
14
"github.com/bluesky-social/indigo/atproto/identity"
15
-
"github.com/bluesky-social/indigo/atproto/syntax"
16
15
securejoin "github.com/cyphar/filepath-securejoin"
17
16
"github.com/go-chi/chi/v5"
18
17
"tangled.sh/tangled.sh/core/appview/config"
···
26
25
)
27
26
28
27
type ResolvedRepo struct {
29
-
Knot string
28
+
db.Repo
30
29
OwnerId identity.Identity
31
-
RepoName string
32
-
RepoAt syntax.ATURI
33
-
Description string
34
-
Spindle string
35
-
CreatedAt string
36
30
Ref string
37
31
CurrentDir string
38
32
···
51
45
}
52
46
53
47
func (rr *RepoResolver) Resolve(r *http.Request) (*ResolvedRepo, error) {
54
-
repoName := chi.URLParam(r, "repo")
55
-
knot, ok := r.Context().Value("knot").(string)
48
+
repo, ok := r.Context().Value("repo").(*db.Repo)
56
49
if !ok {
57
-
log.Println("malformed middleware")
50
+
log.Println("malformed middleware: `repo` not exist in context")
58
51
return nil, fmt.Errorf("malformed middleware")
59
52
}
60
53
id, ok := r.Context().Value("resolvedId").(identity.Identity)
···
63
56
return nil, fmt.Errorf("malformed middleware")
64
57
}
65
58
66
-
repoAt, ok := r.Context().Value("repoAt").(string)
67
-
if !ok {
68
-
log.Println("malformed middleware")
69
-
return nil, fmt.Errorf("malformed middleware")
70
-
}
71
-
72
-
parsedRepoAt, err := syntax.ParseATURI(repoAt)
73
-
if err != nil {
74
-
log.Println("malformed repo at-uri")
75
-
return nil, fmt.Errorf("malformed middleware")
76
-
}
77
-
78
59
ref := chi.URLParam(r, "ref")
79
60
80
61
if ref == "" {
81
-
us, err := knotclient.NewUnsignedClient(knot, rr.config.Core.Dev)
62
+
us, err := knotclient.NewUnsignedClient(repo.Knot, rr.config.Core.Dev)
82
63
if err != nil {
83
64
return nil, err
84
65
}
85
66
86
-
defaultBranch, err := us.DefaultBranch(id.DID.String(), repoName)
67
+
defaultBranch, err := us.DefaultBranch(id.DID.String(), repo.Name)
87
68
if err != nil {
88
69
return nil, err
89
70
}
···
93
74
94
75
currentDir := path.Dir(extractPathAfterRef(r.URL.EscapedPath(), ref))
95
76
96
-
// pass through values from the middleware
97
-
description, ok := r.Context().Value("repoDescription").(string)
98
-
addedAt, ok := r.Context().Value("repoAddedAt").(string)
99
-
spindle, ok := r.Context().Value("repoSpindle").(string)
100
-
101
77
return &ResolvedRepo{
102
-
Knot: knot,
103
-
OwnerId: id,
104
-
RepoName: repoName,
105
-
RepoAt: parsedRepoAt,
106
-
Description: description,
107
-
CreatedAt: addedAt,
108
-
Ref: ref,
109
-
CurrentDir: currentDir,
110
-
Spindle: spindle,
78
+
Repo: *repo,
79
+
OwnerId: id,
80
+
Ref: ref,
81
+
CurrentDir: currentDir,
111
82
112
83
rr: rr,
113
84
}, nil
···
126
97
127
98
var p string
128
99
if handle != "" && !handle.IsInvalidHandle() {
129
-
p, _ = securejoin.SecureJoin(fmt.Sprintf("@%s", handle), f.RepoName)
100
+
p, _ = securejoin.SecureJoin(fmt.Sprintf("@%s", handle), f.Name)
130
101
} else {
131
-
p, _ = securejoin.SecureJoin(f.OwnerDid(), f.RepoName)
102
+
p, _ = securejoin.SecureJoin(f.OwnerDid(), f.Name)
132
103
}
133
104
134
105
return p
135
106
}
136
107
137
-
func (f *ResolvedRepo) DidSlashRepo() string {
138
-
p, _ := securejoin.SecureJoin(f.OwnerDid(), f.RepoName)
139
-
return p
140
-
}
141
-
142
108
func (f *ResolvedRepo) Collaborators(ctx context.Context) ([]pages.Collaborator, error) {
143
109
repoCollaborators, err := f.rr.enforcer.E.GetImplicitUsersForResourceByDomain(f.DidSlashRepo(), f.Knot)
144
110
if err != nil {
···
186
152
// this function is a bit weird since it now returns RepoInfo from an entirely different
187
153
// package. we should refactor this or get rid of RepoInfo entirely.
188
154
func (f *ResolvedRepo) RepoInfo(user *oauth.User) repoinfo.RepoInfo {
155
+
repoAt := f.RepoAt()
189
156
isStarred := false
190
157
if user != nil {
191
-
isStarred = db.GetStarStatus(f.rr.execer, user.Did, syntax.ATURI(f.RepoAt))
158
+
isStarred = db.GetStarStatus(f.rr.execer, user.Did, repoAt)
192
159
}
193
160
194
-
starCount, err := db.GetStarCount(f.rr.execer, f.RepoAt)
161
+
starCount, err := db.GetStarCount(f.rr.execer, repoAt)
195
162
if err != nil {
196
-
log.Println("failed to get star count for ", f.RepoAt)
163
+
log.Println("failed to get star count for ", repoAt)
197
164
}
198
-
issueCount, err := db.GetIssueCount(f.rr.execer, f.RepoAt)
165
+
issueCount, err := db.GetIssueCount(f.rr.execer, repoAt)
199
166
if err != nil {
200
-
log.Println("failed to get issue count for ", f.RepoAt)
167
+
log.Println("failed to get issue count for ", repoAt)
201
168
}
202
-
pullCount, err := db.GetPullCount(f.rr.execer, f.RepoAt)
169
+
pullCount, err := db.GetPullCount(f.rr.execer, repoAt)
203
170
if err != nil {
204
-
log.Println("failed to get issue count for ", f.RepoAt)
171
+
log.Println("failed to get issue count for ", repoAt)
205
172
}
206
-
source, err := db.GetRepoSource(f.rr.execer, f.RepoAt)
173
+
source, err := db.GetRepoSource(f.rr.execer, repoAt)
207
174
if errors.Is(err, sql.ErrNoRows) {
208
175
source = ""
209
176
} else if err != nil {
210
-
log.Println("failed to get repo source for ", f.RepoAt, err)
177
+
log.Println("failed to get repo source for ", repoAt, err)
211
178
}
212
179
213
180
var sourceRepo *db.Repo
···
232
199
if err != nil {
233
200
log.Printf("failed to create unsigned client for %s: %v", knot, err)
234
201
} else {
235
-
result, err := us.Branches(f.OwnerDid(), f.RepoName)
202
+
result, err := us.Branches(f.OwnerDid(), f.Name)
236
203
if err != nil {
237
-
log.Printf("failed to get branches for %s/%s: %v", f.OwnerDid(), f.RepoName, err)
204
+
log.Printf("failed to get branches for %s/%s: %v", f.OwnerDid(), f.Name, err)
238
205
}
239
206
240
207
if len(result.Branches) == 0 {
···
245
212
repoInfo := repoinfo.RepoInfo{
246
213
OwnerDid: f.OwnerDid(),
247
214
OwnerHandle: f.OwnerHandle(),
248
-
Name: f.RepoName,
249
-
RepoAt: f.RepoAt,
215
+
Name: f.Name,
216
+
RepoAt: repoAt,
250
217
Description: f.Description,
251
218
Ref: f.Ref,
252
219
IsStarred: isStarred,
+7
-4
appview/db/repos.go
+7
-4
appview/db/repos.go
···
391
391
var description, spindle sql.NullString
392
392
393
393
row := e.QueryRow(`
394
-
select did, name, knot, created, at_uri, description, spindle
394
+
select did, name, knot, created, at_uri, description, spindle, rkey
395
395
from repos
396
396
where did = ? and name = ?
397
397
`,
···
400
400
)
401
401
402
402
var createdAt string
403
-
if err := row.Scan(&repo.Did, &repo.Name, &repo.Knot, &createdAt, &repo.AtUri, &description, &spindle); err != nil {
403
+
if err := row.Scan(&repo.Did, &repo.Name, &repo.Knot, &createdAt, &repo.AtUri, &description, &spindle, &repo.Rkey); err != nil {
404
404
return nil, err
405
405
}
406
406
createdAtTime, _ := time.Parse(time.RFC3339, createdAt)
···
421
421
var repo Repo
422
422
var nullableDescription sql.NullString
423
423
424
-
row := e.QueryRow(`select did, name, knot, created, at_uri, description from repos where at_uri = ?`, atUri)
424
+
row := e.QueryRow(`select did, name, knot, created, at_uri, rkey, description from repos where at_uri = ?`, atUri)
425
425
426
426
var createdAt string
427
-
if err := row.Scan(&repo.Did, &repo.Name, &repo.Knot, &createdAt, &repo.AtUri, &nullableDescription); err != nil {
427
+
if err := row.Scan(&repo.Did, &repo.Name, &repo.Knot, &createdAt, &repo.AtUri, &repo.Rkey, &nullableDescription); err != nil {
428
428
return nil, err
429
429
}
430
430
createdAtTime, _ := time.Parse(time.RFC3339, createdAt)
···
440
440
}
441
441
442
442
func AddRepo(e Execer, repo *Repo) error {
443
+
if repo.AtUri == "" {
444
+
repo.AtUri = repo.RepoAt().String()
445
+
}
443
446
_, err := e.Exec(
444
447
`insert into repos
445
448
(did, name, knot, rkey, at_uri, description, source)