back interdiff of round #1 and #0

feat: add language statistics to repo page #208

files
appview
knotserver
types
REVERTED
appview/pages/pages.go
···
Raw bool
EmailToDidOrHandle map[string]string
VerifiedCommits map[string]bool
+
Languages *types.RepoLanguageResponse
-
Languages []types.RepoLanguageDetails
types.RepoIndexResponse
}
ERROR
appview/repo/repo.go

Failed to calculate interdiff for this file.

ERROR
knotserver/routes.go

Failed to calculate interdiff for this file.

ERROR
types/repo.go

Failed to calculate interdiff for this file.

ERROR
appview/pages/templates/layouts/repobase.html

Failed to calculate interdiff for this file.

REVERTED
appview/pages/templates/repo/index.html
···
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo) }}
{{ end }}
-
{{ define "repoLanguages" }}
-
<div class="flex gap-[3px]">
-
{{ range $value := .Languages }}
-
<div
-
title="{{ $value.Name }} {{ printf "%.1f" $value.Percentage }}%"
-
class="h-2"
-
style="background-color: {{ $value.Color }}; width: {{ $value.Percentage }}%"
-
></div>
-
{{ end }}
-
</div>
-
{{ end }}
{{ define "repoContent" }}
<main>
NEW
appview/pages/templates/settings.html
···
<form
hx-delete="/settings/emails"
hx-confirm="Are you sure you wish to delete the email '{{ .Address }}'?"
-
hx-indicator="#delete-email-{{ .Address }}-spinner"
+
hx-indicator="#delete-email-{{ $index }}-spinner"
>
<input type="hidden" name="email" value="{{ .Address }}">
<button
···
>
{{ i "trash-2" "w-5 h-5" }}
<span class="hidden md:inline">delete</span>
-
<span id="delete-email-{{ .Address }}-spinner" class="group">
+
<span id="delete-email-{{ $index }}-spinner" class="group">
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
</span>
</button>
NEW
appview/repo/repo_util.go
···
"context"
"crypto/rand"
"fmt"
-
"log"
"math/big"
"github.com/go-git/go-git/v5/plumbing/object"
-
"tangled.sh/tangled.sh/core/appview/db"
-
"tangled.sh/tangled.sh/core/crypto"
-
"tangled.sh/tangled.sh/core/types"
)
func uniqueEmails(commits []*object.Commit) []string {
···
return emailToDidOrHandle
}
-
func verifiedObjectCommits(r *Repo, emailToDid map[string]string, commits []*object.Commit) (map[string]bool, error) {
-
ndCommits := []types.NiceDiff{}
-
for _, commit := range commits {
-
ndCommits = append(ndCommits, types.ObjectCommitToNiceDiff(commit))
-
}
-
return verifiedCommits(r, emailToDid, ndCommits)
-
}
-
-
func verifiedCommits(r *Repo, emailToDid map[string]string, ndCommits []types.NiceDiff) (map[string]bool, error) {
-
hashToVerified := make(map[string]bool)
-
-
didPubkeyCache := make(map[string][]db.PublicKey)
-
-
for _, commit := range ndCommits {
-
c := commit.Commit
-
-
committerEmail := c.Committer.Email
-
if did, exists := emailToDid[committerEmail]; exists {
-
// check if we've already fetched public keys for this did
-
pubKeys, ok := didPubkeyCache[did]
-
if !ok {
-
// fetch and cache public keys
-
keys, err := db.GetPublicKeysForDid(r.db, did)
-
if err != nil {
-
log.Printf("failed to fetch pubkey for %s: %v", committerEmail, err)
-
continue
-
}
-
pubKeys = keys
-
didPubkeyCache[did] = pubKeys
-
}
-
-
verified := false
-
-
// try to verify with any associated pubkeys
-
for _, pk := range pubKeys {
-
if _, ok := crypto.VerifyCommitSignature(pk.Key, commit); ok {
-
verified = true
-
break
-
}
-
}
-
-
hashToVerified[c.This] = verified
-
}
-
}
-
-
return hashToVerified, nil
-
}
-
func randomString(n int) string {
const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
result := make([]byte, n)
NEW
types/diff.go
···
return files
}
-
-
// ObjectCommitToNiceDiff is a compatibility function to convert a
-
// commit object into a NiceDiff structure.
-
func ObjectCommitToNiceDiff(c *object.Commit) NiceDiff {
-
var niceDiff NiceDiff
-
-
// set commit information
-
niceDiff.Commit.Message = c.Message
-
niceDiff.Commit.Author = c.Author
-
niceDiff.Commit.This = c.Hash.String()
-
niceDiff.Commit.Committer = c.Committer
-
niceDiff.Commit.Tree = c.TreeHash.String()
-
niceDiff.Commit.PGPSignature = c.PGPSignature
-
-
changeId, ok := c.ExtraHeaders["change-id"]
-
if ok {
-
niceDiff.Commit.ChangedId = string(changeId)
-
}
-
-
// set parent hash if available
-
if len(c.ParentHashes) > 0 {
-
niceDiff.Commit.Parent = c.ParentHashes[0].String()
-
}
-
-
// XXX: Stats and Diff fields are typically populated
-
// after fetching the actual diff information, which isn't
-
// directly available in the commit object itself.
-
-
return niceDiff
-
}
NEW
appview/pages/templates/repo/log.html
···
{{ define "extrameta" }}
{{ $title := printf "commits &middot; %s" .RepoInfo.FullName }}
{{ $url := printf "https://tangled.sh/%s/commits" .RepoInfo.FullName }}
-
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
{{ end }}
{{ define "repoContent" }}
<section id="commit-table" class="overflow-x-auto">
<h2 class="font-bold text-sm mb-4 uppercase dark:text-white">
-
commits
+
commits
</h2>
<!-- desktop view (hidden on small screens) -->
···
{{ end }}
</td>
<td class="py-3 align-top font-mono flex items-center">
-
{{ $verified := false }}
-
{{ $verified = index $.VerifiedCommits $commit.Hash.String }}
+
{{ $verified := $.VerifiedCommits.IsVerified $commit.Hash.String }}
{{ $hashStyle := "text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-900" }}
{{ if $verified }}
{{ $hashStyle = "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 px-2 rounded" }}
···
{{ end }}
</a>
<div class="{{ if not $verified }} ml-6 {{ end }}inline-flex">
-
<button class="p-1 mx-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded"
+
<button class="p-1 mx-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded"
title="Copy SHA"
onclick="navigator.clipboard.writeText('{{ $commit.Hash.String }}'); this.innerHTML=`{{ i "copy-check" "w-4 h-4" }}`; setTimeout(() => this.innerHTML=`{{ i "copy" "w-4 h-4" }}`, 1500)">
{{ i "copy" "w-4 h-4" }}
···
<div>
<div class="flex items-center justify-start">
<a href="/{{ $.RepoInfo.FullName }}/commit/{{ $commit.Hash.String }}" class="dark:text-white no-underline hover:underline">{{ index $messageParts 0 }}</a>
-
{{ if gt (len $messageParts) 1 }}
+
{{ if gt (len $messageParts) 1 }}
<button class="ml-2 py-1/2 px-1 bg-gray-200 hover:bg-gray-400 dark:bg-gray-700 dark:hover:bg-gray-600 rounded" hx-on:click="this.parentElement.nextElementSibling.classList.toggle('hidden')">{{ i "ellipsis" "w-3 h-3" }}</button>
{{ end }}
-
+
{{ if index $.TagMap $commit.Hash.String }}
{{ range $tag := index $.TagMap $commit.Hash.String }}
<span class="ml-2 text-xs rounded bg-gray-100 dark:bg-gray-700 text-black dark:text-white font-mono px-2 inline-flex items-center">
···
</span>
{{ end }}
{{ end }}
-
+
</div>
-
+
{{ if gt (len $messageParts) 1 }}
<p class="hidden mt-1 text-sm text-gray-600 dark:text-gray-400">{{ nl2br (index $messageParts 1) }}</p>
{{ end }}
···
<div class="flex items-center justify-between">
<div class="flex-1">
<div class="inline">
-
<a href="/{{ $.RepoInfo.FullName }}/commit/{{ $commit.Hash.String }}"
+
<a href="/{{ $.RepoInfo.FullName }}/commit/{{ $commit.Hash.String }}"
class="inline no-underline hover:underline dark:text-white">
{{ index $messageParts 0 }}
</a>
{{ if gt (len $messageParts) 1 }}
-
<button
+
<button
class="py-1/2 px-1 bg-gray-200 hover:bg-gray-400 rounded dark:bg-gray-700 dark:hover:bg-gray-600 ml-2"
hx-on:click="this.parentElement.nextElementSibling.classList.toggle('hidden')">
{{ i "ellipsis" "w-3 h-3" }}
···
</p>
{{ end }}
</div>
-
<a href="/{{ $.RepoInfo.FullName }}/tree/{{ $commit.Hash.String }}"
-
class="p-1 mr-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded"
+
<a href="/{{ $.RepoInfo.FullName }}/tree/{{ $commit.Hash.String }}"
+
class="p-1 mr-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded"
title="Browse repository at this commit">
{{ i "folder-code" "w-4 h-4" }}
</a>
···
</div>
<div class="text-xs mt-2 text-gray-500 dark:text-gray-400 flex items-center">
-
{{ $verified := false }}
-
{{ $verified = index $.VerifiedCommits $commit.Hash.String }}
+
{{ $verified := $.VerifiedCommits.IsVerified $commit.Hash.String }}
{{ $hashStyle := "text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-900" }}
{{ if $verified }}
{{ $hashStyle = "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 px-2 rounded" }}
NEW
appview/config/config.go
···
}
type ResendConfig struct {
-
ApiKey string `env:"API_KEY"`
+
ApiKey string `env:"API_KEY"`
+
SentFrom string `env:"SENT_FROM, default=noreply@notifs.tangled.sh"`
}
type CamoConfig struct {
NEW
appview/settings/settings.go
···
return email.Email{
APIKey: s.Config.Resend.ApiKey,
-
From: "noreply@notifs.tangled.sh",
+
From: s.Config.Resend.SentFrom,
To: emailAddr,
Subject: "Verify your Tangled email",
Text: `Click the link below (or copy and paste it into your browser) to verify your email address.
NEW
go.mod
···
github.com/go-git/go-git/v5 v5.14.0
github.com/google/uuid v1.6.0
github.com/gorilla/sessions v1.4.0
+
github.com/gorilla/websocket v1.5.3
github.com/hiddeco/sshsig v0.2.0
github.com/ipfs/go-cid v0.5.0
github.com/lestrrat-go/jwx/v2 v2.1.6
···
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/gorilla/css v1.0.1 // indirect
github.com/gorilla/securecookie v1.1.2 // indirect
-
github.com/gorilla/websocket v1.5.3 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
github.com/hashicorp/golang-lru v1.0.2 // indirect
···
replace github.com/bluekeyes/go-gitdiff => tangled.sh/oppi.li/go-gitdiff v0.8.2
-
replace github.com/alecthomas/chroma/v2 => github.com/oppiliappan/chroma/v2 v2.17.0
+
replace github.com/alecthomas/chroma/v2 => github.com/oppiliappan/chroma/v2 v2.19.0
// from bluesky-social/indigo
replace github.com/gocql/gocql => github.com/scylladb/gocql v1.14.4
NEW
go.sum
···
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
-
github.com/oppiliappan/chroma/v2 v2.17.0 h1:Qi8qnCvhCn8VxwD+BGpt7n5BdLX32/2kRBlT7hAR5Ko=
-
github.com/oppiliappan/chroma/v2 v2.17.0/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk=
+
github.com/oppiliappan/chroma/v2 v2.19.0 h1:PN7/pb+6JRKCva30NPTtRJMlrOyzgpPpIroNzy4ekHU=
+
github.com/oppiliappan/chroma/v2 v2.19.0/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk=
github.com/oppiliappan/go-git/v5 v5.17.0 h1:CuJnpcIDxr0oiNaSHMconovSWnowHznVDG+AhjGuSEo=
github.com/oppiliappan/go-git/v5 v5.17.0/go.mod h1:q/FE8C3SPMoRN7LoH9vRFiBzidAOBWJPS1CqVS8DN+w=
github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4=