Monorepo for Tangled tangled.org

appview: repo commit

Moves the NiceDiff type to the shared types package.

anirudh.fi 0f393855 500665c2

verified
Changed files
+221 -141
.zed
appview
pages
state
knotserver
types
+15
.zed/settings.json
··· 1 + // Folder-specific settings 2 + // 3 + // For a full list of overridable settings, and general information on folder-specific settings, 4 + // see the documentation: https://zed.dev/docs/configuring-zed#settings-files 5 + { 6 + "languages": { 7 + "HTML": { 8 + "prettier": { 9 + "allowed": true, 10 + "parser": "go-template", 11 + "plugins": ["prettier-plugin-go-template"] 12 + } 13 + } 14 + } 15 + }
+10
appview/pages/pages.go
··· 160 160 func (p *Pages) RepoLog(w io.Writer, params RepoLogParams) error { 161 161 return p.execute("repo/log", w, params) 162 162 } 163 + 164 + type RepoCommitParams struct { 165 + LoggedInUser *auth.User 166 + RepoInfo RepoInfo 167 + types.RepoCommitResponse 168 + } 169 + 170 + func (p *Pages) RepoCommit(w io.Writer, params RepoCommitParams) error { 171 + return p.execute("repo/commit", w, params) 172 + }
+96 -96
appview/pages/templates/repo/commit.html
··· 1 - <html> 2 - {{ template "layouts/head" . }} 1 + {{ define "title" }} commit {{ .Diff.Commit.This }} {{ end }} 3 2 4 - {{ template "layouts/repo-header" . }} 5 - <body> 6 - {{ template "layouts/nav" . }} 7 - <main> 8 - <section class="commit"> 9 - <pre>{{- .commit.Message -}}</pre> 10 - <div class="commit-info"> 11 - {{ .commit.Author.Name }} <a href="mailto:{{ .commit.Author.Email }}" class="commit-email">{{ .commit.Author.Email}}</a> 12 - <div>{{ .commit.Author.When.Format "Mon, 02 Jan 2006 15:04:05 -0700" }}</div> 13 - </div> 3 + {{ define "content" }} 14 4 15 - <div> 16 - <strong>commit</strong> 17 - <p><a href="/{{ .name }}/commit/{{ .commit.This }}" class="commit-hash"> 18 - {{ .commit.This }} 19 - </a> 20 - </p> 21 - </div> 5 + {{ $repo := .RepoInfo.Name }} 6 + {{ $commit := .Diff.Commit }} 7 + {{ $stat := .Diff.Stat }} 8 + {{ $diff := .Diff.Diff }} 22 9 23 - {{ if .commit.Parent }} 24 - <div> 25 - <strong>parent</strong> 26 - <p><a href="/{{ .name }}/commit/{{ .commit.Parent }}" class="commit-hash"> 27 - {{ .commit.Parent }} 28 - </a></p> 29 - </div> 10 + <section class="commit"> 11 + <pre>{{- $commit.Message -}}</pre> 12 + <div class="commit-info"> 13 + {{ $commit.Author.Name }} <a href="mailto:{{ $commit.Author.Email }}" class="commit-email">{{ $commit.Author.Email}}</a> 14 + <div>{{ $commit.Author.When.Format "Mon, 02 Jan 2006 15:04:05 -0700" }}</div> 15 + </div> 30 16 31 - {{ end }} 32 - <div class="diff-stat"> 33 - <div> 34 - {{ .stat.FilesChanged }} files changed, 35 - {{ .stat.Insertions }} insertions(+), 36 - {{ .stat.Deletions }} deletions(-) 37 - </div> 38 - <div> 39 - <br> 40 - <strong>jump to</strong> 41 - {{ range .diff }} 42 - <ul> 43 - <li><a href="#{{ .Name.New }}">{{ .Name.New }}</a></li> 44 - </ul> 45 - {{ end }} 46 - </div> 47 - </div> 48 - </section> 49 - <section> 50 - {{ $repo := .name }} 51 - {{ $this := .commit.This }} 52 - {{ $parent := .commit.Parent }} 53 - {{ range .diff }} 54 - <div id="{{ .Name.New }}"> 55 - <div class="diff"> 56 - {{ if .IsNew }} 57 - <span class="diff-type">A</span> 58 - {{ end }} 59 - {{ if .IsDelete }} 60 - <span class="diff-type">D</span> 61 - {{ end }} 62 - {{ if not (or .IsNew .IsDelete) }} 63 - <span class="diff-type">M</span> 64 - {{ end }} 65 - {{ if .Name.Old }} 66 - <a href="/{{ $repo }}/blob/{{ $parent }}/{{ .Name.Old }}">{{ .Name.Old }}</a> 67 - {{ if .Name.New }} 68 - &#8594; 69 - <a href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.New }}">{{ .Name.New }}</a> 70 - {{ end }} 71 - {{ else }} 72 - <a href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.New }}">{{ .Name.New }}</a> 73 - {{- end -}} 74 - {{ if .IsBinary }} 75 - <p>Not showing binary file.</p> 76 - {{ else }} 77 - <pre> 78 - {{- range .TextFragments -}} 79 - <p>{{- .Header -}}</p> 80 - {{- range .Lines -}} 81 - {{- if eq .Op.String "+" -}} 82 - <span class="diff-add">{{ .String }}</span> 83 - {{- end -}} 84 - {{- if eq .Op.String "-" -}} 85 - <span class="diff-del">{{ .String }}</span> 86 - {{- end -}} 87 - {{- if eq .Op.String " " -}} 88 - <span class="diff-noop">{{ .String }}</span> 89 - {{- end -}} 90 - {{- end -}} 91 - {{- end -}} 92 - {{- end -}} 93 - </pre> 94 - </div> 95 - </div> 96 - {{ end }} 97 - </section> 98 - </main> 99 - </body> 100 - </html> 17 + <div> 18 + <strong>commit</strong> 19 + <p><a href="/{{ $repo }}/commit/{{ $commit.This }}" class="commit-hash"> 20 + {{ $commit.This }} 21 + </a> 22 + </p> 23 + </div> 24 + 25 + {{ if $commit.Parent }} 26 + <div> 27 + <strong>parent</strong> 28 + <p><a href="/{{ $repo }}/commit/{{ $commit.Parent }}" class="commit-hash"> 29 + {{ $commit.Parent }} 30 + </a></p> 31 + </div> 32 + 33 + {{ end }} 34 + <div class="diff-stat"> 35 + <div> 36 + {{ $stat.FilesChanged }} files changed, 37 + {{ $stat.Insertions }} insertions(+), 38 + {{ $stat.Deletions }} deletions(-) 39 + </div> 40 + <div> 41 + <br> 42 + <strong>jump to</strong> 43 + {{ range $diff }} 44 + <ul> 45 + <li><a href="#{{ .Name.New }}">{{ .Name.New }}</a></li> 46 + </ul> 47 + {{ end }} 48 + </div> 49 + </div> 50 + </section> 51 + <section> 52 + {{ $this := $commit.This }} 53 + {{ $parent := $commit.Parent }} 54 + {{ range $diff }} 55 + <div id="{{ .Name.New }}"> 56 + <div class="diff"> 57 + {{ if .IsNew }} 58 + <span class="diff-type">A</span> 59 + {{ end }} 60 + {{ if .IsDelete }} 61 + <span class="diff-type">D</span> 62 + {{ end }} 63 + {{ if not (or .IsNew .IsDelete) }} 64 + <span class="diff-type">M</span> 65 + {{ end }} 66 + {{ if .Name.Old }} 67 + <a href="/{{ $repo }}/blob/{{ $parent }}/{{ .Name.Old }}">{{ .Name.Old }}</a> 68 + {{ if .Name.New }} 69 + &#8594; 70 + <a href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.New }}">{{ .Name.New }}</a> 71 + {{ end }} 72 + {{ else }} 73 + <a href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.New }}">{{ .Name.New }}</a> 74 + {{- end -}} 75 + {{ if .IsBinary }} 76 + <p>Not showing binary file.</p> 77 + {{ else }} 78 + <pre> 79 + {{- range .TextFragments -}} 80 + <p>{{- .Header -}}</p> 81 + {{- range .Lines -}} 82 + {{- if eq .Op.String "+" -}} 83 + <span class="diff-add">{{ .String }}</span> 84 + {{- end -}} 85 + {{- if eq .Op.String "-" -}} 86 + <span class="diff-del">{{ .String }}</span> 87 + {{- end -}} 88 + {{- if eq .Op.String " " -}} 89 + <span class="diff-noop">{{ .String }}</span> 90 + {{- end -}} 91 + {{- end -}} 92 + {{- end -}} 93 + {{- end -}} 94 + </pre> 95 + </div> 96 + </div> 97 + {{ end }} 98 + </section> 99 + 100 + {{end}}
+1 -1
appview/pages/templates/repo/empty.html
··· 2 2 {{ template "layouts/head" . }} 3 3 4 4 <body> 5 - <main> 5 + <main></main> 6 6 <p>This is an empty Git repository. Push some commits here.</p> 7 7 </main> 8 8 </body>
+39
appview/state/repo.go
··· 94 94 return 95 95 } 96 96 97 + func (s *State) RepoCommit(w http.ResponseWriter, r *http.Request) { 98 + repoName, knot, id, err := repoKnotAndId(r) 99 + if err != nil { 100 + log.Println("failed to get repo and knot", err) 101 + return 102 + } 103 + 104 + ref := chi.URLParam(r, "ref") 105 + resp, err := http.Get(fmt.Sprintf("http://%s/%s/%s/commit/%s", knot, id.DID.String(), repoName, ref)) 106 + if err != nil { 107 + log.Println("failed to reach knotserver", err) 108 + return 109 + } 110 + 111 + body, err := io.ReadAll(resp.Body) 112 + if err != nil { 113 + log.Fatalf("Error reading response body: %v", err) 114 + return 115 + } 116 + 117 + var result types.RepoCommitResponse 118 + err = json.Unmarshal(body, &result) 119 + if err != nil { 120 + log.Println("failed to parse response:", err) 121 + return 122 + } 123 + 124 + s.pages.RepoCommit(w, pages.RepoCommitParams{ 125 + LoggedInUser: s.auth.GetUser(r), 126 + RepoInfo: pages.RepoInfo{ 127 + OwnerDid: id.DID.String(), 128 + OwnerHandle: id.Handle.String(), 129 + Name: repoName, 130 + }, 131 + RepoCommitResponse: result, 132 + }) 133 + return 134 + } 135 + 97 136 func repoKnotAndId(r *http.Request) (string, string, identity.Identity, error) { 98 137 repoName := chi.URLParam(r, "repo") 99 138 knot, ok := r.Context().Value("knot").(string)
+1
appview/state/state.go
··· 602 602 r.With(ResolveRepoKnot(s)).Route("/{repo}", func(r chi.Router) { 603 603 r.Get("/", s.RepoIndex) 604 604 r.Get("/log/{ref}", s.RepoLog) 605 + r.Get("/commit/{ref}", s.RepoCommit) 605 606 606 607 // These routes get proxied to the knot 607 608 r.Get("/info/refs", s.InfoRefs)
+5 -36
knotserver/git/diff.go
··· 7 7 8 8 "github.com/bluekeyes/go-gitdiff/gitdiff" 9 9 "github.com/go-git/go-git/v5/plumbing/object" 10 + "github.com/sotangled/tangled/types" 10 11 ) 11 12 12 - type TextFragment struct { 13 - Header string 14 - Lines []gitdiff.Line 15 - } 16 - 17 - type Diff struct { 18 - Name struct { 19 - Old string 20 - New string 21 - } 22 - TextFragments []TextFragment 23 - IsBinary bool 24 - IsNew bool 25 - IsDelete bool 26 - } 27 - 28 - // A nicer git diff representation. 29 - type NiceDiff struct { 30 - Commit struct { 31 - Message string 32 - Author object.Signature 33 - This string 34 - Parent string 35 - } 36 - Stat struct { 37 - FilesChanged int 38 - Insertions int 39 - Deletions int 40 - } 41 - Diff []Diff 42 - } 43 - 44 - func (g *GitRepo) Diff() (*NiceDiff, error) { 13 + func (g *GitRepo) Diff() (*types.NiceDiff, error) { 45 14 c, err := g.r.CommitObject(g.h) 46 15 if err != nil { 47 16 return nil, fmt.Errorf("commit object: %w", err) ··· 76 45 log.Println(err) 77 46 } 78 47 79 - nd := NiceDiff{} 48 + nd := types.NiceDiff{} 80 49 nd.Commit.This = c.Hash.String() 81 50 82 51 if parent.Hash.IsZero() { ··· 88 57 nd.Commit.Message = c.Message 89 58 90 59 for _, d := range diffs { 91 - ndiff := Diff{} 60 + ndiff := types.Diff{} 92 61 ndiff.Name.New = d.NewName 93 62 ndiff.Name.Old = d.OldName 94 63 ndiff.IsBinary = d.IsBinary ··· 96 65 ndiff.IsDelete = d.IsDelete 97 66 98 67 for _, tf := range d.TextFragments { 99 - ndiff.TextFragments = append(ndiff.TextFragments, TextFragment{ 68 + ndiff.TextFragments = append(ndiff.TextFragments, types.TextFragment{ 100 69 Header: tf.Header(), 101 70 Lines: tf.Lines, 102 71 })
+5 -8
knotserver/routes.go
··· 299 299 return 300 300 } 301 301 302 - data := make(map[string]interface{}) 302 + resp := types.RepoCommitResponse{ 303 + Ref: ref, 304 + Diff: diff, 305 + } 303 306 304 - data["commit"] = diff.Commit 305 - data["stat"] = diff.Stat 306 - data["diff"] = diff.Diff 307 - data["ref"] = ref 308 - data["desc"] = getDescription(path) 309 - 310 - writeJSON(w, data) 307 + writeJSON(w, resp) 311 308 return 312 309 } 313 310
+38
types/diff.go
··· 1 + package types 2 + 3 + import ( 4 + "github.com/bluekeyes/go-gitdiff/gitdiff" 5 + "github.com/go-git/go-git/v5/plumbing/object" 6 + ) 7 + 8 + type TextFragment struct { 9 + Header string `json:"header"` 10 + Lines []gitdiff.Line `json:"lines"` 11 + } 12 + 13 + type Diff struct { 14 + Name struct { 15 + Old string `json:"old"` 16 + New string `json:"new"` 17 + } `json:"name"` 18 + TextFragments []TextFragment `json:"text_fragments"` 19 + IsBinary bool `json:"is_binary"` 20 + IsNew bool `json:"is_new"` 21 + IsDelete bool `json:"is_delete"` 22 + } 23 + 24 + // A nicer git diff representation. 25 + type NiceDiff struct { 26 + Commit struct { 27 + Message string `json:"message"` 28 + Author object.Signature `json:"author"` 29 + This string `json:"this"` 30 + Parent string `json:"parent"` 31 + } `json:"commit"` 32 + Stat struct { 33 + FilesChanged int `json:"files_changed"` 34 + Insertions int `json:"insertions"` 35 + Deletions int `json:"deletions"` 36 + } `json:"stat"` 37 + Diff []Diff `json:"diff"` 38 + }
+11
types/repo.go
··· 23 23 Page int `json:"page,omitempty"` 24 24 PerPage int `json:"per_page,omitempty"` 25 25 } 26 + 27 + // data["commit"] = diff.Commit 28 + // 29 + // data["stat"] = diff.Stat 30 + // data["diff"] = diff.Diff 31 + // data["ref"] = ref 32 + // data["desc"] = getDescription(path) 33 + type RepoCommitResponse struct { 34 + Ref string `json:"ref,omitempty"` 35 + Diff *NiceDiff `json:"diff,omitempty"` 36 + }