Home

ugit @main - refs - log -
-
https://git.jolheiser.com/ugit.git
The code powering this h*ckin' site
tree log patch
permalink
Signature
-----BEGIN SSH SIGNATURE----- U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgBTEvCQk6VqUAdN2RuH6bj1dNkY oOpbPWj+jw4ua1B1cAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5 AAAAQPW9psQUP3wp6eDQrcRajOVpvNxQsByjxxI6yiEqrl0uIu8Yozhw9ZHtWr/xIxivfg YMrbnfrCfMucg3brN9RwM= -----END SSH SIGNATURE-----
jolheiser <git@jolheiser.com>
1 month ago
4 changed files, 43 additions(+), 4 deletions(-)
internal/git/git.gointernal/html/repo_file.gointernal/html/repo_file.jsinternal/http/repo.go
M internal/git/git.gointernal/git/git.go
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
diff --git a/internal/git/git.go b/internal/git/git.go
index 72140d8bf1ba6099128f5716b2ac525422891cc8..fcdb9e3b5cdcc77415c2cb001c2c5f6294cce189 100644
--- a/internal/git/git.go
+++ b/internal/git/git.go
@@ -127,6 +127,21 @@
 	return fis, nil
 }
 
+// GetCommitFromRef returns the commit object for a given ref
+func (r Repo) GetCommitFromRef(ref string) (*object.Commit, error) {
+	g, err := r.Git()
+	if err != nil {
+		return nil, err
+	}
+
+	hash, err := g.ResolveRevision(plumbing.Revision(ref))
+	if err != nil {
+		return nil, err
+	}
+
+	return g.CommitObject(*hash)
+}
+
 // FileContent returns the content of a file in the git tree at a given ref/rev
 func (r Repo) FileContent(ref, file string) (string, error) {
 	t, err := r.Tree(ref)
M internal/html/repo_file.gointernal/html/repo_file.go
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
diff --git a/internal/html/repo_file.go b/internal/html/repo_file.go
index 6dd3cb13080a68e45577f5b11ef5ae2f27836dd4..981121c907f7f14da2dc9c20dba1b5eba9bb1f94 100644
--- a/internal/html/repo_file.go
+++ b/internal/html/repo_file.go
@@ -2,6 +2,7 @@ package html
 
 import (
 	_ "embed"
+	"fmt"
 
 	. "maragu.dev/gomponents"
 	. "maragu.dev/gomponents/html"
@@ -11,19 +12,24 @@ type RepoFileContext struct {
 	BaseContext
 	RepoHeaderComponentContext
 	RepoBreadcrumbComponentContext
-	Code string
+	Code   string
+	Commit string
+	Path   string
 }
 
 //go:embed repo_file.js
 var repoFileJS string
 
 func RepoFileTemplate(rfc RepoFileContext) Node {
+	permalink := fmt.Sprintf("/%s/tree/%s/%s", rfc.RepoBreadcrumbComponentContext.Repo, rfc.Commit, rfc.Path)
 	return base(rfc.BaseContext, []Node{
 		repoHeaderComponent(rfc.RepoHeaderComponentContext),
 		Div(Class("mt-2 text-text"),
 			repoBreadcrumbComponent(rfc.RepoBreadcrumbComponentContext),
 			Text(" - "),
 			A(Class("text-text underline decoration-text/50 decoration-dashed hover:decoration-solid"), Href("?raw"), Text("raw")),
+			Text(" - "),
+			A(Class("text-text underline decoration-text/50 decoration-dashed hover:decoration-solid"), ID("permalink"), Data("permalink", permalink), Href(permalink), Text("permalink")),
 			Div(Class("code relative"),
 				Raw(rfc.Code),
 				Button(ID("copy"), Class("absolute top-0 right-0 rounded bg-base hover:bg-surface0")),
M internal/html/repo_file.jsinternal/html/repo_file.js
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
diff --git a/internal/html/repo_file.js b/internal/html/repo_file.js
index 42d5a24594d926585c205b6ad21083156b0717a3..9dd234f3506d5b585302801b09f0f5fff9da75e3 100644
--- a/internal/html/repo_file.js
+++ b/internal/html/repo_file.js
@@ -2,6 +2,7 @@ const lineRe = /#L(\d+)(?:-L(\d+))?/g
 const $lineLines = document.querySelectorAll(".chroma .lntable .lnt");
 const $codeLines = document.querySelectorAll(".chroma .lntable .line");
 const $copyButton = document.getElementById('copy');
+const $permalink = document.getElementById('permalink');
 const $copyIcon = "📋";
 const $copiedIcon = "✅";
 let $code = ""
@@ -13,9 +14,12 @@ if (0 in results) {
     start = results[0][1] !== undefined ? parseInt(results[0][1]) : 0;
     end = results[0][2] !== undefined ? parseInt(results[0][2]) : 0;
 }
-if (start != 0) {
+if (start !== 0) {
     deactivateLines();
     activateLines(start, end);
+    let anchor = `#${start}`;
+    if (end !== 0) anchor += `-${end}`;
+    if (anchor !== "") $permalink.href = $permalink.dataset.permalink + anchor;
     $lineLines[start - 1].scrollIntoView(true);
 }
 for (let line of $lineLines) {
@@ -27,13 +31,17 @@         let anchor = "";
         if (event.shiftKey) {
             end = n;
             anchor = `#L${start}-L${end}`;
+        } else if (start === n) {
+            start = 0;
+            end = 0;
         } else {
             start = n;
             end = 0;
             anchor = `#L${start}`;
         }
-        history.replaceState(null, null, anchor);
-        activateLines(start, end);
+        history.replaceState(null, null, window.location.pathname + anchor);
+        $permalink.href = $permalink.dataset.permalink + anchor;
+        if (start !== 0) activateLines(start, end);
     });
 }
 if (navigator.clipboard && navigator.clipboard.writeText) {
M internal/http/repo.gointernal/http/repo.go
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
diff --git a/internal/http/repo.go b/internal/http/repo.go
index 5382b7df068dc84b7d2a2482a9bb901361b52667..c47811a32038309bdf8c543677496195ff195114 100644
--- a/internal/http/repo.go
+++ b/internal/http/repo.go
@@ -92,11 +92,21 @@ 	if err := markup.Convert([]byte(content), filepath.Base(path), "L", &buf); err != nil {
 		return httperr.Error(err)
 	}
 
+	commit := ref
+	if len(ref) < 40 {
+		commitObj, err := repo.GetCommitFromRef(ref)
+		if err == nil {
+			commit = commitObj.Hash.String()
+		}
+	}
+
 	if err := html.RepoFileTemplate(html.RepoFileContext{
 		BaseContext:                    rh.baseContext(),
 		RepoHeaderComponentContext:     rh.repoHeaderContext(repo, r),
 		RepoBreadcrumbComponentContext: rh.repoBreadcrumbContext(repo, r, path),
 		Code:                           buf.String(),
+		Commit:                         commit,
+		Path:                           path,
 	}).Render(w); err != nil {
 		return httperr.Error(err)
 	}