all repos — elgit @ 59ba5ba7dd66f7bf537d1f17a9d588acce6b5e16

fork of legit: web frontend for git, written in go

feat: Add route handler for file-specific commit diffs

Alan Pearce
commit

59ba5ba7dd66f7bf537d1f17a9d588acce6b5e16

parent

13e02db54aaa6d9fc5198a884e6dd8b4bee7e13f

4 files changed, 111 insertions(+), 2 deletions(-)

jump to
M git/diff.gogit/diff.go
@@ -45,6 +45,61 @@ Stat Stat
Diff []Diff } +// DiffFile returns a diff for a specific file in the current commit +func (g *GitRepo) DiffFile(filePath string) (*NiceDiff, error) { + niceDiff, err := g.Diff() + if err != nil { + return nil, err + } + + // Filter diffs to only include the specified file + var filteredDiffs []Diff + for _, d := range niceDiff.Diff { + if d.Name.New == filePath || d.Name.Old == filePath { + filteredDiffs = append(filteredDiffs, d) + } + } + + // If no matching files were found, return an empty diff + if len(filteredDiffs) == 0 { + return &NiceDiff{ + Commit: niceDiff.Commit, + Stat: Stat{ + FilesChanged: 0, + Insertions: 0, + Deletions: 0, + }, + Diff: []Diff{}, + }, nil + } + + // Recalculate stats for the filtered diffs + stat := Stat{ + FilesChanged: len(filteredDiffs), + Insertions: 0, + Deletions: 0, + } + + for _, d := range filteredDiffs { + for _, tf := range d.TextFragments { + for _, l := range tf.Lines { + switch l.Op { + case gitdiff.OpAdd: + stat.Insertions++ + case gitdiff.OpDelete: + stat.Deletions++ + } + } + } + } + + return &NiceDiff{ + Commit: niceDiff.Commit, + Stat: stat, + Diff: filteredDiffs, + }, nil +} + func (g *GitRepo) Diff() (*NiceDiff, error) { c, err := g.r.CommitObject(g.h) if err != nil {
M routes/handler.goroutes/handler.go
@@ -80,6 +80,7 @@ mux.GET("/:name/blob/:ref/", d.FileContent)
mux.GET("/:name/log/:ref", d.Log) mux.GET("/:name/archive/:file", d.Archive) mux.GET("/:name/commit/:ref", d.Diff) + mux.GET("/:name/commit/:ref/*file", d.FileDiff) mux.GET("/:name/refs/", d.Refs) mux.GET("/:name", d.Multiplex) mux.POST("/:name", d.Multiplex)
@@ -95,6 +96,7 @@ mux.GET("/:category/:name/blob/:ref/", d.FileContent)
mux.GET("/:category/:name/log/:ref", d.Log) mux.GET("/:category/:name/archive/:file", d.Archive) mux.GET("/:category/:name/commit/:ref", d.Diff) + mux.GET("/:category/:name/commit/:ref/*file", d.FileDiff) mux.GET("/:category/:name/refs/", d.Refs) mux.GET("/:category/:name", d.Multiplex) mux.POST("/:category/:name", d.Multiplex)
M routes/routes.goroutes/routes.go
@@ -347,6 +347,53 @@ return
} } +// FileDiff shows the changes to a specific file in a commit +func (d *deps) FileDiff(w http.ResponseWriter, r *http.Request, params map[string]string) { + name := path.Join(params["category"], params["name"]) + if d.isNotAllowed(name) { + d.Write404(w) + return + } + ref := params["ref"] + filePath := strings.TrimSuffix(params["file"], "/") + + path, err := d.GetCleanPath(name) + if err != nil { + log.Printf("getcleanpath error: %v", err) + d.Write404(w) + return + } + + g, err := git.Open(path, ref) + if err != nil { + log.Printf("git open error: %v", err) + d.Write404(w) + return + } + + diff, err := g.DiffFile(filePath) + if err != nil { + log.Printf("git diff error: %v", err) + d.Write500(w) + return + } + + pageData := templates.PageData{ + Meta: d.c.Meta, + DisplayName: getDisplayName(name), + Name: name, + Ref: ref, + Description: getDescription(path), + Path: filePath, + Diff: diff.Diff, + } + + if err := templates.CommitPage(pageData, diff).Render(w); err != nil { + log.Printf("diff template: %s", err) + d.Write500(w) + } +} + func (d *deps) Refs(w http.ResponseWriter, r *http.Request, params map[string]string) { name := path.Join(params["category"], params["name"]) if d.isNotAllowed(name) {
M templates/commit.gotemplates/commit.go
@@ -44,9 +44,14 @@ diff.Stat.Insertions, pluralise(diff.Stat.Insertions),
diff.Stat.Deletions, pluralise(diff.Stat.Deletions))), Div( Br(), - Strong(g.Text("jump to")), + Strong(g.Text("changed files")), Ul(g.Map(diff.Diff, func(d git.Diff) g.Node { - return Li(A(Href("#"+d.Name.New), g.Text(d.Name.New))) + return Li( + A( + Href(fmt.Sprintf("/%s/commit/%s/%s", data.Name, diff.Commit.This, d.Name.New)), + g.Text(d.Name.New), + ), + ) })), ), ),