Signed-off-by: Will did:plc:dadhhalkfcq3gucaq25hjqon
+615
-9
Diff
round #1
+510
appview/db/repos.go
+510
appview/db/repos.go
···
301
301
return nil, fmt.Errorf("failed to execute pulls-count query: %w", err)
302
302
}
303
303
304
+
// get forks
305
+
forksInClause := strings.TrimSuffix(strings.Repeat("?, ", len(repoMap)), ", ")
306
+
forkArgs := make([]any, len(repoMap))
307
+
i = 0
308
+
for _, r := range repoMap {
309
+
forkArgs[i] = r.RepoDid
310
+
i++
311
+
}
312
+
313
+
forksCountQuery := fmt.Sprintf(
314
+
`select source, count(1) from repos where source in (%s) group by source`,
315
+
forksInClause,
316
+
)
317
+
318
+
rows, err = e.Query(forksCountQuery, forkArgs...)
319
+
if err != nil {
320
+
return nil, fmt.Errorf("failed to execute fork-count query: %w", err)
321
+
}
322
+
defer rows.Close()
323
+
324
+
for rows.Next() {
325
+
var repodid string
326
+
var count int
327
+
if err := rows.Scan(&repodid, &count); err != nil {
328
+
log.Println("err", "err", err)
329
+
continue
330
+
}
331
+
332
+
for _, r := range repoMap {
333
+
if r.RepoDid == repodid {
334
+
r.RepoStats.ForkCount = count
335
+
break
336
+
}
337
+
}
338
+
}
339
+
if err = rows.Err(); err != nil {
340
+
return nil, fmt.Errorf("failed to execute fork-count query: %w", err)
341
+
}
342
+
304
343
var repos []models.Repo
305
344
for _, r := range repoMap {
306
345
repos = append(repos, *r)
346
+
347
+
348
+
349
+
350
+
351
+
352
+
353
+
354
+
355
+
356
+
357
+
358
+
359
+
360
+
361
+
362
+
363
+
364
+
365
+
366
+
367
+
368
+
369
+
370
+
371
+
372
+
373
+
374
+
375
+
376
+
377
+
378
+
379
+
380
+
381
+
382
+
383
+
384
+
385
+
386
+
387
+
388
+
389
+
390
+
391
+
392
+
393
+
394
+
395
+
396
+
397
+
398
+
399
+
400
+
401
+
402
+
403
+
404
+
405
+
406
+
407
+
408
+
409
+
410
+
411
+
412
+
413
+
414
+
415
+
416
+
417
+
418
+
419
+
420
+
421
+
422
+
423
+
424
+
425
+
426
+
427
+
428
+
429
+
430
+
431
+
432
+
433
+
434
+
435
+
436
+
437
+
438
+
439
+
440
+
441
+
442
+
443
+
444
+
445
+
446
+
447
+
448
+
449
+
450
+
451
+
452
+
453
+
454
+
455
+
456
+
457
+
458
+
459
+
460
+
461
+
462
+
463
+
464
+
465
+
466
+
467
+
468
+
469
+
470
+
471
+
472
+
473
+
474
+
475
+
476
+
477
+
478
+
479
+
480
+
481
+
482
+
483
+
484
+
485
+
486
+
487
+
488
+
489
+
490
+
491
+
492
+
493
+
494
+
495
+
496
+
497
+
498
+
499
+
500
+
501
+
502
+
503
+
504
+
505
+
506
+
507
+
508
+
509
+
510
+
511
+
512
+
513
+
514
+
515
+
516
+
517
+
518
+
519
+
520
+
521
+
522
+
523
+
524
+
525
+
526
+
527
+
528
+
529
+
530
+
531
+
532
+
533
+
534
+
535
+
536
+
537
+
538
+
539
+
540
+
541
+
542
+
543
+
544
+
545
+
546
+
547
+
548
+
549
+
550
+
551
+
552
+
553
+
554
+
555
+
556
+
557
+
558
+
559
+
560
+
561
+
562
+
563
+
564
+
565
+
566
+
567
+
568
+
569
+
570
+
571
+
572
+
573
+
574
+
575
+
576
+
577
+
578
+
579
+
580
+
581
+
582
+
583
+
584
+
585
+
586
+
587
+
588
+
589
+
590
+
591
+
592
+
593
+
594
+
595
+
596
+
597
+
598
+
599
+
600
+
601
+
602
+
603
+
604
+
605
+
606
+
607
+
608
+
609
+
610
+
611
+
612
+
613
+
614
+
615
+
616
+
617
+
618
+
619
+
620
+
621
+
622
+
623
+
624
+
625
+
626
+
627
+
628
+
629
+
630
+
631
+
632
+
633
+
634
+
635
+
636
+
637
+
638
+
639
+
640
+
641
+
642
+
643
+
644
+
645
+
646
+
647
+
648
+
649
+
650
+
651
+
652
+
653
+
654
+
655
+
656
+
657
+
658
+
659
+
660
+
661
+
662
+
663
+
664
+
665
+
666
+
667
+
668
+
669
+
670
+
671
+
672
+
673
+
674
+
675
+
676
+
677
+
678
+
679
+
680
+
681
+
682
+
683
+
684
+
685
+
686
+
687
+
688
+
689
+
690
+
691
+
692
+
693
+
694
+
695
+
696
+
697
+
698
+
699
+
700
+
701
+
702
+
703
+
704
+
705
+
706
+
707
+
708
+
709
+
710
+
711
+
712
+
713
+
714
+
715
+
716
+
717
+
718
+
719
+
720
+
721
+
722
+
723
+
724
+
725
+
726
+
727
+
728
+
729
+
730
+
731
+
732
+
733
+
734
+
735
+
736
+
737
+
738
+
739
+
740
+
741
+
742
+
743
+
744
+
745
+
746
+
747
+
748
+
749
+
750
+
751
+
752
+
753
+
754
+
755
+
756
+
757
+
758
+
759
+
760
+
761
+
762
+
763
+
764
+
765
+
766
+
767
+
768
+
769
+
770
+
771
+
772
+
773
+
774
+
775
+
776
+
777
+
778
+
779
+
780
+
781
+
782
+
783
+
784
+
785
+
786
+
787
+
788
+
789
+
790
+
791
+
792
+
793
+
794
+
795
+
796
+
797
+
798
+
799
+
800
+
801
+
802
+
803
+
804
+
805
+
return labels, nil
806
+
}
807
+
808
+
func GetForkCount(e Execer, sourceDID string) (int, error) {
809
+
forks := 0
810
+
err := e.QueryRow(
811
+
`select count(source) from repos where source = ?`, sourceDID).Scan(&forks)
812
+
if err != nil {
813
+
return 0, err
814
+
}
815
+
return forks, nil
816
+
}
+1
appview/models/repo.go
+1
appview/models/repo.go
+35
appview/pages/templates/repo/forks.html
+35
appview/pages/templates/repo/forks.html
···
1
+
{{ define "title" }}forks · {{ .RepoInfo.FullName }}{{ end }}
2
+
{{ define "repoContent" }}
3
+
<div class="flex flex-col gap-4">
4
+
<h2 class="text-sm uppercase font-bold">Forked by</h2>
5
+
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
6
+
{{ range .Forks }}
7
+
{{ $handle := resolve .Did }}
8
+
{{ $name := .Name}}
9
+
<div class="border border-gray-200 dark:border-gray-700 rounded p-4">
10
+
<div class="flex items-center gap-3">
11
+
{{ template "user/fragments/picLink" (list .Did "size-10") }}
12
+
<div class="flex-1 min-w-0">
13
+
<a href="/{{ $handle }}" class="block truncate">{{ $handle }}</a>
14
+
<a href="/{{ $handle }}/{{ $name }}" class="block truncate">{{ $name }}</a>
15
+
<p class="text-sm text-gray-500 dark:text-gray-400">
16
+
forked {{ .Created | relTimeFmt }}
17
+
</p>
18
+
</div>
19
+
</div>
20
+
</div>
21
+
{{ end }}
22
+
{{ if eq .TotalCount 0 }}
23
+
<p class="text-gray-500 dark:text-gray-400 col-span-3">No forks yet.</p>
24
+
{{ end }}
25
+
</div>
26
+
{{ if gt .TotalCount .Page.Limit }}
27
+
{{ template "fragments/pagination" (dict
28
+
"Page" .Page
29
+
"TotalCount" .TotalCount
30
+
"BasePath" (printf "/%s/forks" .RepoInfo.FullName)
31
+
"QueryParams" (queryParams)
32
+
) }}
33
+
{{ end }}
34
+
</div>
35
+
{{ end }}
+14
appview/pages/pages.go
+14
appview/pages/pages.go
···
1557
1557
return p.executeRepo("repo/stars", w, params)
1558
1558
}
1559
1559
1560
+
type RepoForksParams struct {
1561
+
LoggedInUser *oauth.MultiAccountUser
1562
+
RepoInfo repoinfo.RepoInfo
1563
+
Active string
1564
+
Forks []models.Repo
1565
+
Page pagination.Page
1566
+
TotalCount int
1567
+
}
1568
+
1569
+
func (p *Pages) RepoForks(w io.Writer, params RepoForksParams) error {
1570
+
params.Active = "overview"
1571
+
return p.executeRepo("repo/forks", w, params)
1572
+
}
1573
+
1560
1574
type PipelinesParams struct {
1561
1575
LoggedInUser *oauth.MultiAccountUser
1562
1576
RepoInfo repoinfo.RepoInfo
+18
-9
appview/pages/templates/layouts/repobase.html
+18
-9
appview/pages/templates/layouts/repobase.html
···
117
117
"IsStarred" .RepoInfo.IsStarred
118
118
"StarCount" .RepoInfo.Stats.StarCount
119
119
"RepoName" .RepoInfo.Name) }}
120
-
<a
121
-
class="btn text-sm no-underline hover:no-underline flex items-center gap-2 group"
122
-
hx-boost="true"
123
-
href="/{{ .RepoInfo.FullName }}/fork"
124
-
>
125
-
{{ i "git-fork" "w-4 h-4" }}
126
-
fork
127
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
128
-
</a>
120
+
<div class="flex w-full min-h-[30px] items-stretch overflow-hidden rounded border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 shadow-sm">
121
+
<a
122
+
class="btn text-sm no-underline hover:no-underline flex items-center gap-2 group"
123
+
hx-boost="true"
124
+
href="/{{ .RepoInfo.FullName }}/fork"
125
+
>
126
+
{{ i "git-fork" "w-4 h-4" }}
127
+
fork
128
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
129
+
</a>
130
+
<a
131
+
href="/{{ .RepoInfo.OwnerHandle }}/{{ .RepoInfo.Name }}/forks"
132
+
class="flex items-center px-2 text-sm no-underline hover:no-underline border-l border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-700"
133
+
title="Starred by"
134
+
>
135
+
{{ .RepoInfo.Stats.ForkCount }}
136
+
</a>
137
+
</div>
129
138
{{ template "repo/fragments/feedDropdown" . }}
130
139
</div>
131
140
{{ end }}
+36
appview/repo/repo.go
+36
appview/repo/repo.go
···
1297
1297
})
1298
1298
}
1299
1299
1300
+
func (rp *Repo) Forks(w http.ResponseWriter, r *http.Request) {
1301
+
l := rp.logger.With("handler", "Forks")
1302
+
1303
+
user := rp.oauth.GetMultiAccountUser(r)
1304
+
f, err := rp.repoResolver.Resolve(r)
1305
+
if err != nil {
1306
+
l.Error("failed to resolve source repo", "err", err)
1307
+
return
1308
+
}
1309
+
1310
+
page := pagination.FromContext(r.Context())
1311
+
if page.Limit > 30 || page.Limit <= 0 {
1312
+
page.Limit = 30
1313
+
}
1314
+
1315
+
forks, err := db.GetReposPaginated(rp.db, page, orm.FilterEq("source", f.RepoDid))
1316
+
if err != nil {
1317
+
l.Error("failed to fetch forks", "err", err, "repoAt", f.RepoAt())
1318
+
return
1319
+
}
1320
+
1321
+
totalCount, err := db.GetForkCount(rp.db, f.RepoDid)
1322
+
if err != nil {
1323
+
l.Error("failed to fetch fork count", "err", err, "repoAt", f.RepoAt())
1324
+
return
1325
+
}
1326
+
1327
+
rp.pages.RepoForks(w, pages.RepoForksParams{
1328
+
LoggedInUser: user,
1329
+
RepoInfo: rp.repoResolver.GetRepoInfo(r, user),
1330
+
Forks: forks,
1331
+
Page: page,
1332
+
TotalCount: totalCount,
1333
+
})
1334
+
}
1335
+
1300
1336
// this is used to rollback changes made to the PDS
1301
1337
//
1302
1338
// it is a no-op if the provided ATURI is empty
History
2 rounds
0 comments
willdot.net
submitted
#1
2 commits
expand
collapse
appview/db/repos: calculate the fork count of a repo
Signed-off-by: Will <did:plc:dadhhalkfcq3gucaq25hjqon>
appview/repo: show number of forks on repo and link to page of forks
Signed-off-by: Will <did:plc:dadhhalkfcq3gucaq25hjqon>
merge conflicts detected
expand
collapse
expand
collapse
- appview/db/repos.go:301
- appview/models/repo.go:97
expand 0 comments
willdot.net
submitted
#0
1 commit
expand
collapse
appview/db/repos: calculate the fork count of a repo
Signed-off-by: Will <did:plc:dadhhalkfcq3gucaq25hjqon>