diff --git a/git/repo.go b/git/repo.go index 382f07ee0df1b9d0e2df26940ec37b8cf4b1a4e4..574284ac13a9f4f527d40ca753f5b75eb154dfbe 100644 --- a/git/repo.go +++ b/git/repo.go @@ -1,6 +1,7 @@ package git import ( + "io" "path/filepath" "strings" @@ -160,6 +161,19 @@ func (r *Repository) Patch(commit *Commit) (string, error) { return diff.Patch(), err } +// RawDiffFormat represents the format type for raw diffs. +type RawDiffFormat = git.RawDiffFormat + +const ( + RawDiffNormal RawDiffFormat = git.RawDiffNormal + RawDiffPatch RawDiffFormat = git.RawDiffPatch +) + +// RawDiff writes raw diff output to the provided writer. +func (r *Repository) RawDiff(rev string, diffType RawDiffFormat, w io.Writer, opts ...git.RawDiffOptions) error { + return r.Repository.RawDiff(rev, diffType, w, opts...) +} + // CountCommits returns the number of commits in the repository. func (r *Repository) CountCommits(ref *Reference) (int64, error) { return r.RevListCount([]string{ref.Name().String()}) diff --git a/pkg/web/webui.go b/pkg/web/webui.go index 742256810f676792ac1fe0bede2984b1ef56f6ab..e9653a8baa34603c4f47da946391503c77473298 100644 --- a/pkg/web/webui.go +++ b/pkg/web/webui.go @@ -278,6 +278,12 @@ func WebUIController(ctx context.Context, r *mux.Router) { r.Handle(basePrefix+"/commit/{hash:[0-9a-f]+}", withRepoVars(withWebUIAccess(http.HandlerFunc(repoCommit)))). Methods(http.MethodGet) + // Commit patch and diff routes + r.Handle(basePrefix+"/commit/{hash:[0-9a-f]+}.patch", withRepoVars(withWebUIAccess(http.HandlerFunc(repoCommitPatch)))). + Methods(http.MethodGet) + r.Handle(basePrefix+"/commit/{hash:[0-9a-f]+}.diff", withRepoVars(withWebUIAccess(http.HandlerFunc(repoCommitDiff)))). + Methods(http.MethodGet) + // Branches route r.Handle(basePrefix+"/branches", withRepoVars(withWebUIAccess(http.HandlerFunc(repoBranches)))). Methods(http.MethodGet) diff --git a/pkg/web/webui_commit.go b/pkg/web/webui_commit.go index 985bcbd4478ba223a070bc0096754842862ce0e7..869d759de13d730ca54aebae737e463aa035de5c 100644 --- a/pkg/web/webui_commit.go +++ b/pkg/web/webui_commit.go @@ -73,3 +73,57 @@ func repoCommit(w http.ResponseWriter, r *http.Request) { renderHTML(w, "commit.html", data) } + +func repoCommitPatch(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + logger := log.FromContext(ctx) + repo := proto.RepositoryFromContext(ctx) + vars := mux.Vars(r) + hash := vars["hash"] + + gr, err := openRepository(repo) + if err != nil { + logger.Debug("failed to open repository", "repo", repo.Name(), "err", err) + renderInternalServerError(w, r) + return + } + + _, err = gr.CatFileCommit(hash) + if err != nil { + logger.Debug("failed to get commit", "repo", repo.Name(), "hash", hash, "err", err) + renderNotFound(w, r) + return + } + + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + if err := gr.RawDiff(hash, git.RawDiffPatch, w); err != nil { + logger.Debug("failed to generate patch", "repo", repo.Name(), "hash", hash, "err", err) + } +} + +func repoCommitDiff(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + logger := log.FromContext(ctx) + repo := proto.RepositoryFromContext(ctx) + vars := mux.Vars(r) + hash := vars["hash"] + + gr, err := openRepository(repo) + if err != nil { + logger.Debug("failed to open repository", "repo", repo.Name(), "err", err) + renderInternalServerError(w, r) + return + } + + _, err = gr.CatFileCommit(hash) + if err != nil { + logger.Debug("failed to get commit", "repo", repo.Name(), "hash", hash, "err", err) + renderNotFound(w, r) + return + } + + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + if err := gr.RawDiff(hash, git.RawDiffNormal, w); err != nil { + logger.Debug("failed to generate diff", "repo", repo.Name(), "hash", hash, "err", err) + } +}