mirror of
https://github.com/go-gitea/gitea
synced 2024-11-07 09:15:53 +01:00
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>
This commit is contained in:
parent
c766140dad
commit
ed64f1c2b8
38
docs/content/usage/blame.en-us.md
Normal file
38
docs/content/usage/blame.en-us.md
Normal file
@ -0,0 +1,38 @@
|
||||
---
|
||||
date: "2023-08-14T00:00:00+00:00"
|
||||
title: "Blame File View"
|
||||
slug: "blame"
|
||||
sidebar_position: 13
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /en-us/blame
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "usage"
|
||||
name: "Blame"
|
||||
sidebar_position: 13
|
||||
identifier: "blame"
|
||||
---
|
||||
|
||||
# Blame File View
|
||||
|
||||
Gitea supports viewing the line-by-line revision history for a file also known as blame view.
|
||||
You can also use [`git blame`](https://git-scm.com/docs/git-blame) on the command line to view the revision history of lines within a file.
|
||||
|
||||
1. Navigate to and open the file whose line history you want to view.
|
||||
1. Click the `Blame` button in the file header bar.
|
||||
1. The new view shows the line-by-line revision history for a file with author and commit information on the left side.
|
||||
1. To navigate to an older commit, click the ![versions](/octicon-versions.svg) icon.
|
||||
|
||||
## Ignore commits in the blame view
|
||||
|
||||
All revisions specified in the `.git-blame-ignore-revs` file are hidden from the blame view.
|
||||
This is especially useful to hide reformatting changes and keep the benefits of `git blame`.
|
||||
Lines that were changed or added by an ignored commit will be blamed on the previous commit that changed that line or nearby lines.
|
||||
The `.git-blame-ignore-revs` file must be located in the root directory of the repository.
|
||||
For more information like the file format, see [the `git blame --ignore-revs-file` documentation](https://git-scm.com/docs/git-blame#Documentation/git-blame.txt---ignore-revs-fileltfilegt).
|
||||
|
||||
### Bypassing `.git-blame-ignore-revs` in the blame view
|
||||
|
||||
If the blame view for a file shows a message about ignored revisions, you can see the normal blame view by appending the url parameter `?bypass-blame-ignore=true`.
|
1
docs/static/octicon-versions.svg
vendored
Normal file
1
docs/static/octicon-versions.svg
vendored
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path d="M7.75 14A1.75 1.75 0 0 1 6 12.25v-8.5C6 2.784 6.784 2 7.75 2h6.5c.966 0 1.75.784 1.75 1.75v8.5A1.75 1.75 0 0 1 14.25 14Zm-.25-1.75c0 .138.112.25.25.25h6.5a.25.25 0 0 0 .25-.25v-8.5a.25.25 0 0 0-.25-.25h-6.5a.25.25 0 0 0-.25.25ZM4.9 3.508a.75.75 0 0 1-.274 1.025.249.249 0 0 0-.126.217v6.5c0 .09.048.173.126.217a.75.75 0 0 1-.752 1.298A1.75 1.75 0 0 1 3 11.25v-6.5c0-.649.353-1.214.874-1.516a.75.75 0 0 1 1.025.274ZM1.625 5.533h.001a.249.249 0 0 0-.126.217v4.5c0 .09.048.173.126.217a.75.75 0 0 1-.752 1.298A1.748 1.748 0 0 1 0 10.25v-4.5a1.748 1.748 0 0 1 .873-1.516.75.75 0 1 1 .752 1.299Z"></path></svg>
|
After Width: | Height: | Size: 696 B |
@ -13,6 +13,7 @@ import (
|
||||
"regexp"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
// BlamePart represents block of blame - continuous lines with one sha
|
||||
@ -23,12 +24,16 @@ type BlamePart struct {
|
||||
|
||||
// BlameReader returns part of file blame one by one
|
||||
type BlameReader struct {
|
||||
cmd *Command
|
||||
output io.WriteCloser
|
||||
reader io.ReadCloser
|
||||
bufferedReader *bufio.Reader
|
||||
done chan error
|
||||
lastSha *string
|
||||
ignoreRevsFile *string
|
||||
}
|
||||
|
||||
func (r *BlameReader) UsesIgnoreRevs() bool {
|
||||
return r.ignoreRevsFile != nil
|
||||
}
|
||||
|
||||
var shaLineRegex = regexp.MustCompile("^([a-z0-9]{40})")
|
||||
@ -101,28 +106,44 @@ func (r *BlameReader) Close() error {
|
||||
r.bufferedReader = nil
|
||||
_ = r.reader.Close()
|
||||
_ = r.output.Close()
|
||||
if r.ignoreRevsFile != nil {
|
||||
_ = util.Remove(*r.ignoreRevsFile)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// CreateBlameReader creates reader for given repository, commit and file
|
||||
func CreateBlameReader(ctx context.Context, repoPath, commitID, file string) (*BlameReader, error) {
|
||||
cmd := NewCommandContextNoGlobals(ctx, "blame", "--porcelain").
|
||||
AddDynamicArguments(commitID).
|
||||
func CreateBlameReader(ctx context.Context, repoPath string, commit *Commit, file string, bypassBlameIgnore bool) (*BlameReader, error) {
|
||||
var ignoreRevsFile *string
|
||||
if CheckGitVersionAtLeast("2.23") == nil && !bypassBlameIgnore {
|
||||
ignoreRevsFile = tryCreateBlameIgnoreRevsFile(commit)
|
||||
}
|
||||
|
||||
cmd := NewCommandContextNoGlobals(ctx, "blame", "--porcelain")
|
||||
if ignoreRevsFile != nil {
|
||||
// Possible improvement: use --ignore-revs-file /dev/stdin on unix
|
||||
// There is no equivalent on Windows. May be implemented if Gitea uses an external git backend.
|
||||
cmd.AddOptionValues("--ignore-revs-file", *ignoreRevsFile)
|
||||
}
|
||||
cmd.AddDynamicArguments(commit.ID.String()).
|
||||
AddDashesAndList(file).
|
||||
SetDescription(fmt.Sprintf("GetBlame [repo_path: %s]", repoPath))
|
||||
reader, stdout, err := os.Pipe()
|
||||
if err != nil {
|
||||
if ignoreRevsFile != nil {
|
||||
_ = util.Remove(*ignoreRevsFile)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
done := make(chan error, 1)
|
||||
|
||||
go func(cmd *Command, dir string, stdout io.WriteCloser, done chan error) {
|
||||
go func() {
|
||||
stderr := bytes.Buffer{}
|
||||
// TODO: it doesn't work for directories (the directories shouldn't be "blamed"), and the "err" should be returned by "Read" but not by "Close"
|
||||
err := cmd.Run(&RunOpts{
|
||||
UseContextTimeout: true,
|
||||
Dir: dir,
|
||||
Dir: repoPath,
|
||||
Stdout: stdout,
|
||||
Stderr: &stderr,
|
||||
})
|
||||
@ -131,15 +152,42 @@ func CreateBlameReader(ctx context.Context, repoPath, commitID, file string) (*B
|
||||
if err != nil {
|
||||
log.Error("Error running git blame (dir: %v): %v, stderr: %v", repoPath, err, stderr.String())
|
||||
}
|
||||
}(cmd, repoPath, stdout, done)
|
||||
}()
|
||||
|
||||
bufferedReader := bufio.NewReader(reader)
|
||||
|
||||
return &BlameReader{
|
||||
cmd: cmd,
|
||||
output: stdout,
|
||||
reader: reader,
|
||||
bufferedReader: bufferedReader,
|
||||
done: done,
|
||||
ignoreRevsFile: ignoreRevsFile,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func tryCreateBlameIgnoreRevsFile(commit *Commit) *string {
|
||||
entry, err := commit.GetTreeEntryByPath(".git-blame-ignore-revs")
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
r, err := entry.Blob().DataAsync()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
f, err := os.CreateTemp("", "gitea_git-blame-ignore-revs")
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err = io.Copy(f, r)
|
||||
_ = f.Close()
|
||||
if err != nil {
|
||||
_ = util.Remove(f.Name())
|
||||
return nil
|
||||
}
|
||||
|
||||
return util.ToPointer(f.Name())
|
||||
}
|
||||
|
@ -14,27 +14,127 @@ func TestReadingBlameOutput(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
blameReader, err := CreateBlameReader(ctx, "./tests/repos/repo5_pulls", "f32b0a9dfd09a60f616f29158f772cedd89942d2", "README.md")
|
||||
assert.NoError(t, err)
|
||||
defer blameReader.Close()
|
||||
|
||||
parts := []*BlamePart{
|
||||
{
|
||||
"72866af952e98d02a73003501836074b286a78f6",
|
||||
[]string{
|
||||
"# test_repo",
|
||||
"Test repository for testing migration from github to gitea",
|
||||
},
|
||||
},
|
||||
{
|
||||
"f32b0a9dfd09a60f616f29158f772cedd89942d2",
|
||||
[]string{"", "Do not make any changes to this repo it is used for unit testing"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, part := range parts {
|
||||
actualPart, err := blameReader.NextPart()
|
||||
t.Run("Without .git-blame-ignore-revs", func(t *testing.T) {
|
||||
repo, err := OpenRepository(ctx, "./tests/repos/repo5_pulls")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, part, actualPart)
|
||||
}
|
||||
defer repo.Close()
|
||||
|
||||
commit, err := repo.GetCommit("f32b0a9dfd09a60f616f29158f772cedd89942d2")
|
||||
assert.NoError(t, err)
|
||||
|
||||
parts := []*BlamePart{
|
||||
{
|
||||
"72866af952e98d02a73003501836074b286a78f6",
|
||||
[]string{
|
||||
"# test_repo",
|
||||
"Test repository for testing migration from github to gitea",
|
||||
},
|
||||
},
|
||||
{
|
||||
"f32b0a9dfd09a60f616f29158f772cedd89942d2",
|
||||
[]string{"", "Do not make any changes to this repo it is used for unit testing"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, bypass := range []bool{false, true} {
|
||||
blameReader, err := CreateBlameReader(ctx, "./tests/repos/repo5_pulls", commit, "README.md", bypass)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, blameReader)
|
||||
defer blameReader.Close()
|
||||
|
||||
assert.False(t, blameReader.UsesIgnoreRevs())
|
||||
|
||||
for _, part := range parts {
|
||||
actualPart, err := blameReader.NextPart()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, part, actualPart)
|
||||
}
|
||||
|
||||
// make sure all parts have been read
|
||||
actualPart, err := blameReader.NextPart()
|
||||
assert.Nil(t, actualPart)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("With .git-blame-ignore-revs", func(t *testing.T) {
|
||||
repo, err := OpenRepository(ctx, "./tests/repos/repo6_blame")
|
||||
assert.NoError(t, err)
|
||||
defer repo.Close()
|
||||
|
||||
full := []*BlamePart{
|
||||
{
|
||||
"af7486bd54cfc39eea97207ca666aa69c9d6df93",
|
||||
[]string{"line", "line"},
|
||||
},
|
||||
{
|
||||
"45fb6cbc12f970b04eacd5cd4165edd11c8d7376",
|
||||
[]string{"changed line"},
|
||||
},
|
||||
{
|
||||
"af7486bd54cfc39eea97207ca666aa69c9d6df93",
|
||||
[]string{"line", "line", ""},
|
||||
},
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
CommitID string
|
||||
UsesIgnoreRevs bool
|
||||
Bypass bool
|
||||
Parts []*BlamePart
|
||||
}{
|
||||
{
|
||||
CommitID: "544d8f7a3b15927cddf2299b4b562d6ebd71b6a7",
|
||||
UsesIgnoreRevs: true,
|
||||
Bypass: false,
|
||||
Parts: []*BlamePart{
|
||||
{
|
||||
"af7486bd54cfc39eea97207ca666aa69c9d6df93",
|
||||
[]string{"line", "line", "changed line", "line", "line", ""},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CommitID: "544d8f7a3b15927cddf2299b4b562d6ebd71b6a7",
|
||||
UsesIgnoreRevs: false,
|
||||
Bypass: true,
|
||||
Parts: full,
|
||||
},
|
||||
{
|
||||
CommitID: "45fb6cbc12f970b04eacd5cd4165edd11c8d7376",
|
||||
UsesIgnoreRevs: false,
|
||||
Bypass: false,
|
||||
Parts: full,
|
||||
},
|
||||
{
|
||||
CommitID: "45fb6cbc12f970b04eacd5cd4165edd11c8d7376",
|
||||
UsesIgnoreRevs: false,
|
||||
Bypass: false,
|
||||
Parts: full,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
commit, err := repo.GetCommit(c.CommitID)
|
||||
assert.NoError(t, err)
|
||||
|
||||
blameReader, err := CreateBlameReader(ctx, "./tests/repos/repo6_blame", commit, "blame.txt", c.Bypass)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, blameReader)
|
||||
defer blameReader.Close()
|
||||
|
||||
assert.Equal(t, c.UsesIgnoreRevs, blameReader.UsesIgnoreRevs())
|
||||
|
||||
for _, part := range c.Parts {
|
||||
actualPart, err := blameReader.NextPart()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, part, actualPart)
|
||||
}
|
||||
|
||||
// make sure all parts have been read
|
||||
actualPart, err := blameReader.NextPart()
|
||||
assert.Nil(t, actualPart)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
1
modules/git/tests/repos/repo6_blame/HEAD
Normal file
1
modules/git/tests/repos/repo6_blame/HEAD
Normal file
@ -0,0 +1 @@
|
||||
ref: refs/heads/master
|
4
modules/git/tests/repos/repo6_blame/config
Normal file
4
modules/git/tests/repos/repo6_blame/config
Normal file
@ -0,0 +1,4 @@
|
||||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = true
|
||||
bare = true
|
BIN
modules/git/tests/repos/repo6_blame/objects/31/bb4b42cecf0a98fc9a32fc5aaeaf53ec52643c
Normal file
BIN
modules/git/tests/repos/repo6_blame/objects/31/bb4b42cecf0a98fc9a32fc5aaeaf53ec52643c
Normal file
Binary file not shown.
BIN
modules/git/tests/repos/repo6_blame/objects/3b/0f66d8b065f8adbf2fef7d986528c655b98cb1
Normal file
BIN
modules/git/tests/repos/repo6_blame/objects/3b/0f66d8b065f8adbf2fef7d986528c655b98cb1
Normal file
Binary file not shown.
BIN
modules/git/tests/repos/repo6_blame/objects/45/fb6cbc12f970b04eacd5cd4165edd11c8d7376
Normal file
BIN
modules/git/tests/repos/repo6_blame/objects/45/fb6cbc12f970b04eacd5cd4165edd11c8d7376
Normal file
Binary file not shown.
BIN
modules/git/tests/repos/repo6_blame/objects/49/7701e5bb8676e419b93875d8f0808c7b31aed9
Normal file
BIN
modules/git/tests/repos/repo6_blame/objects/49/7701e5bb8676e419b93875d8f0808c7b31aed9
Normal file
Binary file not shown.
BIN
modules/git/tests/repos/repo6_blame/objects/54/4d8f7a3b15927cddf2299b4b562d6ebd71b6a7
Normal file
BIN
modules/git/tests/repos/repo6_blame/objects/54/4d8f7a3b15927cddf2299b4b562d6ebd71b6a7
Normal file
Binary file not shown.
BIN
modules/git/tests/repos/repo6_blame/objects/a8/9199e8dea077e4a8ba0bc01bc155275cfdd044
Normal file
BIN
modules/git/tests/repos/repo6_blame/objects/a8/9199e8dea077e4a8ba0bc01bc155275cfdd044
Normal file
Binary file not shown.
BIN
modules/git/tests/repos/repo6_blame/objects/af/7486bd54cfc39eea97207ca666aa69c9d6df93
Normal file
BIN
modules/git/tests/repos/repo6_blame/objects/af/7486bd54cfc39eea97207ca666aa69c9d6df93
Normal file
Binary file not shown.
BIN
modules/git/tests/repos/repo6_blame/objects/b8/d1ba1ccb58ee3744b3d1434aae7d26ce2d9421
Normal file
BIN
modules/git/tests/repos/repo6_blame/objects/b8/d1ba1ccb58ee3744b3d1434aae7d26ce2d9421
Normal file
Binary file not shown.
BIN
modules/git/tests/repos/repo6_blame/objects/ca/411a3b842c3caec045772da42de16b3ffdafe8
Normal file
BIN
modules/git/tests/repos/repo6_blame/objects/ca/411a3b842c3caec045772da42de16b3ffdafe8
Normal file
Binary file not shown.
1
modules/git/tests/repos/repo6_blame/refs/heads/master
Normal file
1
modules/git/tests/repos/repo6_blame/refs/heads/master
Normal file
@ -0,0 +1 @@
|
||||
544d8f7a3b15927cddf2299b4b562d6ebd71b6a7
|
@ -1007,6 +1007,8 @@ delete_preexisting = Delete pre-existing files
|
||||
delete_preexisting_content = Delete files in %s
|
||||
delete_preexisting_success = Deleted unadopted files in %s
|
||||
blame_prior = View blame prior to this change
|
||||
blame.ignore_revs = Ignoring revisions in <a href="%s">.git-blame-ignore-revs</a>. Click <a href="%s">here to bypass</a> and see the normal blame view.
|
||||
blame.ignore_revs.failed = Failed to ignore revisions in <a href="%s">.git-blame-ignore-revs</a>.
|
||||
author_search_tooltip = Shows a maximum of 30 users
|
||||
|
||||
transfer.accept = Accept Transfer
|
||||
|
@ -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)
|
||||
|
@ -1,3 +1,15 @@
|
||||
{{if or .UsesIgnoreRevs .FaultyIgnoreRevsFile}}
|
||||
{{$revsFileLink := URLJoin .RepoLink "src" .BranchNameSubURL "/.git-blame-ignore-revs"}}
|
||||
{{if .UsesIgnoreRevs}}
|
||||
<div class="ui info message">
|
||||
<p>{{.locale.Tr "repo.blame.ignore_revs" $revsFileLink (print $revsFileLink "?bypass-blame-ignore=true") | Str2html}}</p>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="ui error message">
|
||||
<p>{{.locale.Tr "repo.blame.ignore_revs.failed" $revsFileLink | Str2html}}</p>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
<div class="{{TabSizeClass .Editorconfig .FileName}} non-diff-file-content">
|
||||
<h4 class="file-header ui top attached header gt-df gt-ac gt-sb gt-fw">
|
||||
<div class="file-header-left gt-df gt-ac gt-py-3 gt-pr-4">
|
||||
|
Loading…
Reference in New Issue
Block a user