aboutsummaryrefslogtreecommitdiffstats
path: root/routers/web/repo/blame.go
diff options
context:
space:
mode:
authorKN4CK3R <admin@oldschoolhack.me>2023-09-16 19:42:34 +0200
committerGitHub <noreply@github.com>2023-09-16 17:42:34 +0000
commited64f1c2b835bf9332bf8347be9675ef29c8274b (patch)
treed549801f35652496808d7307403f86e2f3f1ff39 /routers/web/repo/blame.go
parentc766140dad3408048ad843d0e7b4ab5d9f5777c6 (diff)
downloadgitea-ed64f1c2b835bf9332bf8347be9675ef29c8274b.tar.gz
gitea-ed64f1c2b835bf9332bf8347be9675ef29c8274b.zip
Support `.git-blame-ignore-revs` file (#26395)
Closes #26329 This PR adds the ability to ignore revisions specified in the `.git-blame-ignore-revs` file in the root of the repository. ![grafik](https://github.com/go-gitea/gitea/assets/1666336/9e91be0c-6e9c-431c-bbe9-5f80154251c8) The banner is displayed in this case. I intentionally did not add a UI way to bypass the ignore file (same behaviour as Github) but you can add `?bypass-blame-ignore=true` to the url manually. --------- Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Diffstat (limited to 'routers/web/repo/blame.go')
-rw-r--r--routers/web/repo/blame.go91
1 files changed, 69 insertions, 22 deletions
diff --git a/routers/web/repo/blame.go b/routers/web/repo/blame.go
index b1cb42297c..e4506a857e 100644
--- a/routers/web/repo/blame.go
+++ b/routers/web/repo/blame.go
@@ -8,9 +8,9 @@ import (
gotemplate "html/template"
"net/http"
"net/url"
+ "strconv"
"strings"
- repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/charset"
"code.gitea.io/gitea/modules/context"
@@ -45,10 +45,6 @@ func RefBlame(ctx *context.Context) {
return
}
- userName := ctx.Repo.Owner.Name
- repoName := ctx.Repo.Repository.Name
- commitID := ctx.Repo.CommitID
-
branchLink := ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL()
treeLink := branchLink
rawLink := ctx.Repo.RepoLink + "/raw/" + ctx.Repo.BranchNameSubURL()
@@ -101,26 +97,16 @@ func RefBlame(ctx *context.Context) {
return
}
- blameReader, err := git.CreateBlameReader(ctx, repo_model.RepoPath(userName, repoName), commitID, fileName)
+ bypassBlameIgnore, _ := strconv.ParseBool(ctx.FormString("bypass-blame-ignore"))
+
+ result, err := performBlame(ctx, ctx.Repo.Repository.RepoPath(), ctx.Repo.Commit, fileName, bypassBlameIgnore)
if err != nil {
ctx.NotFound("CreateBlameReader", err)
return
}
- defer blameReader.Close()
-
- blameParts := make([]git.BlamePart, 0)
- for {
- blamePart, err := blameReader.NextPart()
- if err != nil {
- ctx.NotFound("NextPart", err)
- return
- }
- if blamePart == nil {
- break
- }
- blameParts = append(blameParts, *blamePart)
- }
+ ctx.Data["UsesIgnoreRevs"] = result.UsesIgnoreRevs
+ ctx.Data["FaultyIgnoreRevsFile"] = result.FaultyIgnoreRevsFile
// Get Topics of this repo
renderRepoTopics(ctx)
@@ -128,16 +114,77 @@ func RefBlame(ctx *context.Context) {
return
}
- commitNames, previousCommits := processBlameParts(ctx, blameParts)
+ commitNames, previousCommits := processBlameParts(ctx, result.Parts)
if ctx.Written() {
return
}
- renderBlame(ctx, blameParts, commitNames, previousCommits)
+ renderBlame(ctx, result.Parts, commitNames, previousCommits)
ctx.HTML(http.StatusOK, tplRepoHome)
}
+type blameResult struct {
+ Parts []git.BlamePart
+ UsesIgnoreRevs bool
+ FaultyIgnoreRevsFile bool
+}
+
+func performBlame(ctx *context.Context, repoPath string, commit *git.Commit, file string, bypassBlameIgnore bool) (*blameResult, error) {
+ blameReader, err := git.CreateBlameReader(ctx, repoPath, commit, file, bypassBlameIgnore)
+ if err != nil {
+ return nil, err
+ }
+
+ r := &blameResult{}
+ if err := fillBlameResult(blameReader, r); err != nil {
+ _ = blameReader.Close()
+ return nil, err
+ }
+
+ err = blameReader.Close()
+ if err != nil {
+ if len(r.Parts) == 0 && r.UsesIgnoreRevs {
+ // try again without ignored revs
+
+ blameReader, err = git.CreateBlameReader(ctx, repoPath, commit, file, true)
+ if err != nil {
+ return nil, err
+ }
+
+ r := &blameResult{
+ FaultyIgnoreRevsFile: true,
+ }
+ if err := fillBlameResult(blameReader, r); err != nil {
+ _ = blameReader.Close()
+ return nil, err
+ }
+
+ return r, blameReader.Close()
+ }
+ return nil, err
+ }
+ return r, nil
+}
+
+func fillBlameResult(br *git.BlameReader, r *blameResult) error {
+ r.UsesIgnoreRevs = br.UsesIgnoreRevs()
+
+ r.Parts = make([]git.BlamePart, 0, 5)
+ for {
+ blamePart, err := br.NextPart()
+ if err != nil {
+ return fmt.Errorf("BlameReader.NextPart failed: %w", err)
+ }
+ if blamePart == nil {
+ break
+ }
+ r.Parts = append(r.Parts, *blamePart)
+ }
+
+ return nil
+}
+
func processBlameParts(ctx *context.Context, blameParts []git.BlamePart) (map[string]*user_model.UserCommit, map[string]string) {
// store commit data by SHA to look up avatar info etc
commitNames := make(map[string]*user_model.UserCommit)