+3
appview/pages/funcmap.go
+3
appview/pages/funcmap.go
···
29
29
"split": func(s string) []string {
30
30
return strings.Split(s, "\n")
31
31
},
32
+
"contains": func(s string, target string) bool {
33
+
return strings.Contains(s, target)
34
+
},
32
35
"resolve": func(s string) string {
33
36
identity, err := p.resolver.ResolveIdent(context.Background(), s)
34
37
-1
appview/pages/templates/repo/index.html
-1
appview/pages/templates/repo/index.html
+48
-12
appview/pages/templates/repo/needsUpgrade.html
+48
-12
appview/pages/templates/repo/needsUpgrade.html
···
1
1
{{ define "title" }}{{ .RepoInfo.FullName }}{{ end }}
2
-
3
2
{{ define "extrameta" }}
4
3
{{ template "repo/fragments/meta" . }}
5
4
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo) }}
6
5
{{ end }}
7
-
8
6
{{ define "repoContent" }}
9
7
<main>
10
-
<div class="w-full h-full flex place-content-center {{ if .LoggedInUser }} bg-yellow-100 dark:bg-yellow-900 {{ end }}">
11
-
<div class="py-6 w-fit flex flex-col gap-4 text-center">
12
-
{{ if .LoggedInUser }}
13
-
<p class=" text-yellow-800 dark:text-yellow-200 text-center">
14
-
Your knot needs an upgrade. This repository is currently unavailable to users.
15
-
</p>
8
+
<div class="relative w-full h-96 flex items-center justify-center">
9
+
<div class="w-full h-full grid grid-cols-1 md:grid-cols-2 gap-4 md:divide-x divide-gray-300 dark:divide-gray-600 text-gray-300 dark:text-gray-600">
10
+
<!-- mimic the repo view here, placeholders are LLM generated -->
11
+
<div id="file-list" class="flex flex-col gap-2 col-span-1 w-full h-full p-4 items-start justify-start text-left">
12
+
{{ $files :=
13
+
(list
14
+
"src"
15
+
"docs"
16
+
"config"
17
+
"lib"
18
+
"index.html"
19
+
"log.html"
20
+
"needsUpgrade.html"
21
+
"new.html"
22
+
"tags.html"
23
+
"tree.html")
24
+
}}
25
+
{{ range $files }}
26
+
<span>
27
+
{{ if (contains . ".") }}
28
+
{{ i "file" "size-4 inline-flex" }}
16
29
{{ else }}
17
-
<p class="text-gray-400 dark:text-gray-500 py-6 text-center">
18
-
The knot hosting this repository needs an upgrade. This repository is currently unavailable.
19
-
</p>
30
+
{{ i "folder" "size-4 inline-flex fill-current" }}
20
31
{{ end }}
21
-
</div>
32
+
33
+
{{ . }}
34
+
</span>
35
+
{{ end }}
36
+
</div>
37
+
<div id="commit-list" class="hidden md:flex md:flex-col gap-4 col-span-1 w-full h-full p-4 items-start justify-start text-left">
38
+
{{ $commits :=
39
+
(list
40
+
"Fix authentication bug in login flow"
41
+
"Add new dashboard widgets for metrics"
42
+
"Implement real-time notifications system")
43
+
}}
44
+
{{ range $commits }}
45
+
<div class="flex flex-col">
46
+
<span>{{ . }}</span>
47
+
<span class="text-xs">{{ . }}</span>
48
+
</div>
49
+
{{ end }}
50
+
</div>
22
51
</div>
52
+
<div class="absolute inset-0 flex items-center justify-center py-12 text-red-500 dark:text-red-400 backdrop-blur">
53
+
<div class="text-center">
54
+
{{ i "triangle-alert" "size-5 inline-flex items-center align-middle" }}
55
+
The knot hosting this repository needs an upgrade. This repository is currently unavailable.
56
+
</div>
57
+
</div>
58
+
</div>
23
59
</main>
24
60
{{ end }}
+22
-50
appview/repo/index.go
+22
-50
appview/repo/index.go
···
47
47
Host: host,
48
48
}
49
49
50
-
var needsKnotUpgrade bool
50
+
user := rp.oauth.GetUser(r)
51
+
repoInfo := f.RepoInfo(user)
52
+
51
53
// Build index response from multiple XRPC calls
52
54
result, err := rp.buildIndexResponse(r.Context(), xrpcc, f, ref)
53
-
if err != nil {
54
-
if errors.Is(err, xrpcclient.ErrXrpcUnsupported) {
55
+
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
56
+
if errors.Is(xrpcerr, xrpcclient.ErrXrpcUnsupported) {
55
57
log.Println("failed to call XRPC repo.index", err)
56
-
needsKnotUpgrade = true
58
+
rp.pages.RepoIndexPage(w, pages.RepoIndexParams{
59
+
LoggedInUser: user,
60
+
NeedsKnotUpgrade: true,
61
+
RepoInfo: repoInfo,
62
+
})
63
+
return
64
+
} else {
65
+
rp.pages.Error503(w)
66
+
log.Println("failed to build index response", err)
57
67
return
58
68
}
59
-
60
-
rp.pages.Error503(w)
61
-
log.Println("failed to build index response", err)
62
-
return
63
69
}
64
70
65
71
tagMap := make(map[string][]string)
···
119
125
log.Println(err)
120
126
}
121
127
122
-
user := rp.oauth.GetUser(r)
123
-
repoInfo := f.RepoInfo(user)
124
-
125
128
// TODO: a bit dirty
126
129
languageInfo, err := rp.getLanguageInfo(r.Context(), f, xrpcc, result.Ref, ref == "")
127
130
if err != nil {
···
141
144
142
145
rp.pages.RepoIndexPage(w, pages.RepoIndexParams{
143
146
LoggedInUser: user,
144
-
NeedsKnotUpgrade: needsKnotUpgrade,
145
147
RepoInfo: repoInfo,
146
148
TagMap: tagMap,
147
149
RepoIndexResponse: *result,
···
243
245
// first get branches to determine the ref if not specified
244
246
branchesBytes, err := tangled.RepoBranches(ctx, xrpcc, "", 0, repo)
245
247
if err != nil {
246
-
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
247
-
log.Println("failed to call XRPC repo.branches", xrpcerr)
248
-
return nil, xrpcerr
249
-
}
250
248
return nil, err
251
249
}
252
250
···
278
276
279
277
// now run the remaining queries in parallel
280
278
var wg sync.WaitGroup
281
-
var mu sync.Mutex
282
-
var errs []error
279
+
var errs error
283
280
284
281
var (
285
282
tagsResp types.RepoTagsResponse
···
295
292
defer wg.Done()
296
293
tagsBytes, err := tangled.RepoTags(ctx, xrpcc, "", 0, repo)
297
294
if err != nil {
298
-
mu.Lock()
299
-
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
300
-
log.Println("failed to call XRPC repo.tags", xrpcerr)
301
-
errs = append(errs, xrpcerr)
302
-
} else {
303
-
errs = append(errs, err)
304
-
}
305
-
mu.Unlock()
295
+
errs = errors.Join(errs, err)
306
296
return
307
297
}
308
298
309
299
if err := json.Unmarshal(tagsBytes, &tagsResp); err != nil {
310
-
mu.Lock()
311
-
errs = append(errs, err)
312
-
mu.Unlock()
300
+
errs = errors.Join(errs, err)
313
301
}
314
302
}()
315
303
···
319
307
defer wg.Done()
320
308
resp, err := tangled.RepoTree(ctx, xrpcc, "", ref, repo)
321
309
if err != nil {
322
-
mu.Lock()
323
-
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
324
-
log.Println("failed to call XRPC repo.tree", xrpcerr)
325
-
errs = append(errs, xrpcerr)
326
-
} else {
327
-
errs = append(errs, err)
328
-
}
329
-
mu.Unlock()
310
+
errs = errors.Join(errs, err)
330
311
return
331
312
}
332
313
treeResp = resp
···
338
319
defer wg.Done()
339
320
logBytes, err := tangled.RepoLog(ctx, xrpcc, "", 50, "", ref, repo)
340
321
if err != nil {
341
-
mu.Lock()
342
-
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
343
-
log.Println("failed to call XRPC repo.log", xrpcerr)
344
-
errs = append(errs, xrpcerr)
345
-
} else {
346
-
errs = append(errs, err)
347
-
}
348
-
mu.Unlock()
322
+
errs = errors.Join(errs, err)
349
323
return
350
324
}
351
325
352
326
if err := json.Unmarshal(logBytes, &logResp); err != nil {
353
-
mu.Lock()
354
-
errs = append(errs, err)
355
-
mu.Unlock()
327
+
errs = errors.Join(errs, err)
356
328
}
357
329
}()
358
330
···
378
350
379
351
wg.Wait()
380
352
381
-
if len(errs) > 0 {
382
-
return nil, errs[0] // return first error
353
+
if errs != nil {
354
+
return nil, errs
383
355
}
384
356
385
357
var files []types.NiceTree