Show git-notes (#6984)
* Show git-notes * Make git-notes heading text localizable * Refactor git-notes data fetching to a separate function * Display the author and time of git notes * Move note bubble inside the commit bubble * Revert "Move note bubble inside the commit bubble" This reverts commit c0951fe0e3b4dea38064515546b1825c1bcf19e1. * Add test for git-notes * testing ui * Polish CSS * Apply suggestions from code review Co-Authored-By: Lauris BH <lauris@nix.lv>
This commit is contained in:
parent
d5a98a2969
commit
a98e085031
13 changed files with 146 additions and 1 deletions
60
modules/git/notes.go
Normal file
60
modules/git/notes.go
Normal file
|
@ -0,0 +1,60 @@
|
|||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
|
||||
"gopkg.in/src-d/go-git.v4/plumbing"
|
||||
)
|
||||
|
||||
// NotesRef is the git ref where Gitea will look for git-notes data.
|
||||
// The value ("refs/notes/commits") is the default ref used by git-notes.
|
||||
const NotesRef = "refs/notes/commits"
|
||||
|
||||
// Note stores information about a note created using git-notes.
|
||||
type Note struct {
|
||||
Message []byte
|
||||
Commit *Commit
|
||||
}
|
||||
|
||||
// GetNote retrieves the git-notes data for a given commit.
|
||||
func GetNote(repo *Repository, commitID string, note *Note) error {
|
||||
notes, err := repo.GetCommit(NotesRef)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
entry, err := notes.GetTreeEntryByPath(commitID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
blob := entry.Blob()
|
||||
dataRc, err := blob.DataAsync()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer dataRc.Close()
|
||||
d, err := ioutil.ReadAll(dataRc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
note.Message = d
|
||||
|
||||
commit, err := repo.gogitRepo.CommitObject(plumbing.Hash(notes.ID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
lastCommits, err := getLastCommitForPaths(commit, "", []string{commitID})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
note.Commit = convertCommit(lastCommits[commitID])
|
||||
|
||||
return nil
|
||||
}
|
24
modules/git/notes_test.go
Normal file
24
modules/git/notes_test.go
Normal file
|
@ -0,0 +1,24 @@
|
|||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGetNotes(t *testing.T) {
|
||||
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
|
||||
bareRepo1, err := OpenRepository(bareRepo1Path)
|
||||
assert.NoError(t, err)
|
||||
|
||||
note := Note{}
|
||||
err = GetNote(bareRepo1, "95bb4d39648ee7e325106df01a621c530863a653", ¬e)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte("Note contents\n"), note.Message)
|
||||
assert.Equal(t, "Vladimir Panteleev", note.Commit.Author.Name)
|
||||
}
|
|
@ -19,13 +19,14 @@ func TestRepository_GetRefs(t *testing.T) {
|
|||
refs, err := bareRepo1.GetRefs()
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, refs, 4)
|
||||
assert.Len(t, refs, 5)
|
||||
|
||||
expectedRefs := []string{
|
||||
BranchPrefix + "branch1",
|
||||
BranchPrefix + "branch2",
|
||||
BranchPrefix + "master",
|
||||
TagPrefix + "test",
|
||||
NotesRef,
|
||||
}
|
||||
|
||||
for _, ref := range refs {
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,4 @@
|
|||
x¥ŽM
|
||||
Â0F]ç³ëB<C3AB>&&m"ž@\¹Of¦6ÐHG¥··ô
|
||||
~Ë·xïÃy³€Ñþ …Œ?[—Œ¶èBÓ&
|
||||
H<bÛyß™NGtåÚ¨ø–~.ð"å1xÄIx`þÀå•å&=㚸,}¤ù{šX® <C2AE>ó¶ <09>p¬·)ÜãÂjÔ}^ 1AZ¡ÚÀ´3¦,•ú½ÀI0
|
1
modules/git/tests/repos/repo1_bare/refs/notes/commits
Normal file
1
modules/git/tests/repos/repo1_bare/refs/notes/commits
Normal file
|
@ -0,0 +1 @@
|
|||
ca6b5ddf303169a72d2a2971acde4f6eea194e5c
|
|
@ -125,6 +125,7 @@ func NewFuncMap() []template.FuncMap {
|
|||
"RenderCommitMessage": RenderCommitMessage,
|
||||
"RenderCommitMessageLink": RenderCommitMessageLink,
|
||||
"RenderCommitBody": RenderCommitBody,
|
||||
"RenderNote": RenderNote,
|
||||
"IsMultilineCommitMessage": IsMultilineCommitMessage,
|
||||
"ThemeColorMetaTag": func() string {
|
||||
return setting.UI.ThemeColorMetaTag
|
||||
|
@ -392,6 +393,17 @@ func RenderCommitBody(msg, urlPrefix string, metas map[string]string) template.H
|
|||
return template.HTML(strings.Join(body[1:], "\n"))
|
||||
}
|
||||
|
||||
// RenderNote renders the contents of a git-notes file as a commit message.
|
||||
func RenderNote(msg, urlPrefix string, metas map[string]string) template.HTML {
|
||||
cleanMsg := template.HTMLEscapeString(msg)
|
||||
fullMessage, err := markup.RenderCommitMessage([]byte(cleanMsg), urlPrefix, "", metas)
|
||||
if err != nil {
|
||||
log.Error("RenderNote: %v", err)
|
||||
return ""
|
||||
}
|
||||
return template.HTML(string(fullMessage))
|
||||
}
|
||||
|
||||
// IsMultilineCommitMessage checks to see if a commit message contains multiple lines.
|
||||
func IsMultilineCommitMessage(msg string) bool {
|
||||
return strings.Count(strings.TrimSpace(msg), "\n") >= 1
|
||||
|
|
|
@ -1314,6 +1314,7 @@ settings.unarchive.error = An error occured while trying to un-archive the repo.
|
|||
diff.browse_source = Browse Source
|
||||
diff.parent = parent
|
||||
diff.commit = commit
|
||||
diff.git-notes = Notes
|
||||
diff.data_not_available = Diff Content Not Available
|
||||
diff.show_diff_stats = Show Diff Stats
|
||||
diff.show_split_view = Split View
|
||||
|
|
|
@ -803,6 +803,8 @@ footer .ui.left,footer .ui.right{line-height:40px}
|
|||
.stats-table .table-cell.tiny{height:.5em}
|
||||
tbody.commit-list{vertical-align:baseline}
|
||||
.commit-body{white-space:pre-wrap}
|
||||
.git-notes.top{text-align:left}
|
||||
.git-notes .commit-body{margin:0}
|
||||
@media only screen and (max-width:767px){.ui.stackable.menu.mobile--margin-between-items>.item{margin-top:5px;margin-bottom:5px}
|
||||
.ui.stackable.menu.mobile--no-negative-margins{margin-left:0;margin-right:0}
|
||||
}
|
||||
|
|
|
@ -2219,6 +2219,15 @@ tbody.commit-list {
|
|||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.git-notes {
|
||||
&.top {
|
||||
text-align: left;
|
||||
}
|
||||
.commit-body {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 767px) {
|
||||
.ui.stackable.menu {
|
||||
&.mobile--margin-between-items > .item {
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/templates"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -246,6 +247,15 @@ func Diff(ctx *context.Context) {
|
|||
ctx.Data["Parents"] = parents
|
||||
ctx.Data["DiffNotAvailable"] = diff.NumFiles() == 0
|
||||
ctx.Data["SourcePath"] = setting.AppSubURL + "/" + path.Join(userName, repoName, "src", "commit", commitID)
|
||||
|
||||
note := &git.Note{}
|
||||
err = git.GetNote(ctx.Repo.GitRepo, commitID, note)
|
||||
if err == nil {
|
||||
ctx.Data["Note"] = string(templates.ToUTF8WithFallback(note.Message))
|
||||
ctx.Data["NoteCommit"] = note.Commit
|
||||
ctx.Data["NoteAuthor"] = models.ValidateCommitWithEmail(note.Commit)
|
||||
}
|
||||
|
||||
if commit.ParentCount() > 0 {
|
||||
ctx.Data["BeforeSourcePath"] = setting.AppSubURL + "/" + path.Join(userName, repoName, "src", "commit", parents[0])
|
||||
}
|
||||
|
|
|
@ -65,6 +65,27 @@
|
|||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{if .Note}}
|
||||
<div class="ui top attached info segment message git-notes">
|
||||
<i class="sticky note icon"></i>
|
||||
{{.i18n.Tr "repo.diff.git-notes"}}:
|
||||
{{if .NoteAuthor}}
|
||||
<a href="{{.NoteAuthor.HomeLink}}">
|
||||
{{if .NoteAuthor.FullName}}
|
||||
<strong>{{.NoteAuthor.FullName}}</strong>
|
||||
{{else}}
|
||||
<strong>{{.NoteCommit.Author.Name}}</strong>
|
||||
{{end}}
|
||||
</a>
|
||||
{{else}}
|
||||
<strong>{{.NoteCommit.Author.Name}}</strong>
|
||||
{{end}}
|
||||
<span class="text grey" id="note-authored-time">{{TimeSince .NoteCommit.Author.When $.Lang}}</span>
|
||||
</div>
|
||||
<div class="ui bottom attached info segment git-notes">
|
||||
<pre class="commit-body">{{RenderNote .Note $.RepoLink $.Repository.ComposeMetas}}</pre>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{template "repo/diff/box" .}}
|
||||
|
|
Reference in a new issue