"github.com/go-git/go-git/v5/plumbing"
)
+// IsObjectExist returns true if given reference exists in the repository.
+func (repo *Repository) IsObjectExist(name string) bool {
+ if name == "" {
+ return false
+ }
+
+ _, err := repo.gogitRepo.ResolveRevision(plumbing.Revision(name))
+
+ return err == nil
+}
+
+// IsReferenceExist returns true if given reference exists in the repository.
+func (repo *Repository) IsReferenceExist(name string) bool {
+ if name == "" {
+ return false
+ }
+
+ reference, err := repo.gogitRepo.Reference(plumbing.ReferenceName(name), true)
+ if err != nil {
+ return false
+ }
+ return reference.Type() != plumbing.InvalidReference
+}
+
// IsBranchExist returns true if given branch exists in current repository.
func (repo *Repository) IsBranchExist(name string) bool {
if name == "" {
import (
"bufio"
+ "bytes"
"io"
"strings"
)
+// IsObjectExist returns true if given reference exists in the repository.
+func (repo *Repository) IsObjectExist(name string) bool {
+ if name == "" {
+ return false
+ }
+
+ wr, rd, cancel := repo.CatFileBatchCheck()
+ defer cancel()
+ _, err := wr.Write([]byte(name + "\n"))
+ if err != nil {
+ log("Error writing to CatFileBatchCheck %v", err)
+ return false
+ }
+ sha, _, _, err := ReadBatchLine(rd)
+ return err == nil && bytes.HasPrefix(sha, []byte(strings.TrimSpace(name)))
+}
+
// IsReferenceExist returns true if given reference exists in the repository.
func (repo *Repository) IsReferenceExist(name string) bool {
if name == "" {
var nulCleaner = strings.NewReplacer("\000", "")
func postProcess(ctx *RenderContext, procs []processor, input io.Reader, output io.Writer) error {
+ defer ctx.Cancel()
// FIXME: don't read all content to memory
rawHTML, err := ioutil.ReadAll(input)
if err != nil {
start := 0
next := node.NextSibling
+ if ctx.ShaExistCache == nil {
+ ctx.ShaExistCache = make(map[string]bool)
+ }
for node != nil && node != next && start < len(node.Data) {
m := sha1CurrentPattern.FindStringSubmatchIndex(node.Data[start:])
if m == nil {
// as used by git and github for linking and thus we have to do similar.
// Because of this, we check to make sure that a matched hash is actually
// a commit in the repository before making it a link.
- if _, err := git.NewCommand("rev-parse", "--verify", hash).RunInDirBytes(ctx.Metas["repoPath"]); err != nil {
- if !strings.Contains(err.Error(), "fatal: Needed a single revision") {
- log.Debug("sha1CurrentPatternProcessor git rev-parse: %v", err)
+
+ // check cache first
+ exist, inCache := ctx.ShaExistCache[hash]
+ if !inCache {
+ if ctx.GitRepo == nil {
+ var err error
+ ctx.GitRepo, err = git.OpenRepository(ctx.Metas["repoPath"])
+ if err != nil {
+ log.Error("unable to open repository: %s Error: %v", ctx.Metas["repoPath"], err)
+ return
+ }
+ ctx.AddCancel(func() {
+ ctx.GitRepo.Close()
+ ctx.GitRepo = nil
+ })
}
+
+ exist = ctx.GitRepo.IsObjectExist(hash)
+ ctx.ShaExistCache[hash] = exist
+ }
+
+ if !exist {
start = m[3]
continue
}
"strings"
"sync"
+ "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/setting"
)
// RenderContext represents a render context
type RenderContext struct {
- Ctx context.Context
- Filename string
- Type string
- IsWiki bool
- URLPrefix string
- Metas map[string]string
- DefaultLink string
+ Ctx context.Context
+ Filename string
+ Type string
+ IsWiki bool
+ URLPrefix string
+ Metas map[string]string
+ DefaultLink string
+ GitRepo *git.Repository
+ ShaExistCache map[string]bool
+ cancelFn func()
+}
+
+// Cancel runs any cleanup functions that have been registered for this Ctx
+func (ctx *RenderContext) Cancel() {
+ if ctx == nil {
+ return
+ }
+ ctx.ShaExistCache = map[string]bool{}
+ if ctx.cancelFn == nil {
+ return
+ }
+ ctx.cancelFn()
+}
+
+// AddCancel adds the provided fn as a Cleanup for this Ctx
+func (ctx *RenderContext) AddCancel(fn func()) {
+ if ctx == nil {
+ return
+ }
+ oldCancelFn := ctx.cancelFn
+ if oldCancelFn == nil {
+ ctx.cancelFn = fn
+ return
+ }
+ ctx.cancelFn = func() {
+ defer oldCancelFn()
+ fn()
+ }
}
// Renderer defines an interface for rendering markup file to HTML
desc, err := markdown.RenderString(&markup.RenderContext{
URLPrefix: ctx.Repo.RepoLink,
Metas: map[string]string{"mode": "document"},
+ GitRepo: ctx.Repo.GitRepo,
}, org.Description)
if err != nil {
ctx.ServerError("RenderString", err)
issue.RenderedContent, err = markdown.RenderString(&markup.RenderContext{
URLPrefix: ctx.Repo.RepoLink,
Metas: ctx.Repo.Repository.ComposeMetas(),
+ GitRepo: ctx.Repo.GitRepo,
}, issue.Content)
if err != nil {
ctx.ServerError("RenderString", err)
comment.RenderedContent, err = markdown.RenderString(&markup.RenderContext{
URLPrefix: ctx.Repo.RepoLink,
Metas: ctx.Repo.Repository.ComposeMetas(),
+ GitRepo: ctx.Repo.GitRepo,
}, comment.Content)
if err != nil {
ctx.ServerError("RenderString", err)
comment.RenderedContent, err = markdown.RenderString(&markup.RenderContext{
URLPrefix: ctx.Repo.RepoLink,
Metas: ctx.Repo.Repository.ComposeMetas(),
+ GitRepo: ctx.Repo.GitRepo,
}, comment.Content)
if err != nil {
ctx.ServerError("RenderString", err)
content, err := markdown.RenderString(&markup.RenderContext{
URLPrefix: ctx.Query("context"),
Metas: ctx.Repo.Repository.ComposeMetas(),
+ GitRepo: ctx.Repo.GitRepo,
}, issue.Content)
if err != nil {
ctx.ServerError("RenderString", err)
content, err := markdown.RenderString(&markup.RenderContext{
URLPrefix: ctx.Query("context"),
Metas: ctx.Repo.Repository.ComposeMetas(),
+ GitRepo: ctx.Repo.GitRepo,
}, comment.Content)
if err != nil {
ctx.ServerError("RenderString", err)
m.RenderedContent, err = markdown.RenderString(&markup.RenderContext{
URLPrefix: ctx.Repo.RepoLink,
Metas: ctx.Repo.Repository.ComposeMetas(),
+ GitRepo: ctx.Repo.GitRepo,
}, m.Content)
if err != nil {
ctx.ServerError("RenderString", err)
milestone.RenderedContent, err = markdown.RenderString(&markup.RenderContext{
URLPrefix: ctx.Repo.RepoLink,
Metas: ctx.Repo.Repository.ComposeMetas(),
+ GitRepo: ctx.Repo.GitRepo,
}, milestone.Content)
if err != nil {
ctx.ServerError("RenderString", err)
projects[i].RenderedContent, err = markdown.RenderString(&markup.RenderContext{
URLPrefix: ctx.Repo.RepoLink,
Metas: ctx.Repo.Repository.ComposeMetas(),
+ GitRepo: ctx.Repo.GitRepo,
}, projects[i].Description)
if err != nil {
ctx.ServerError("RenderString", err)
project.RenderedContent, err = markdown.RenderString(&markup.RenderContext{
URLPrefix: ctx.Repo.RepoLink,
Metas: ctx.Repo.Repository.ComposeMetas(),
+ GitRepo: ctx.Repo.GitRepo,
}, project.Description)
if err != nil {
ctx.ServerError("RenderString", err)
r.Note, err = markdown.RenderString(&markup.RenderContext{
URLPrefix: ctx.Repo.RepoLink,
Metas: ctx.Repo.Repository.ComposeMetas(),
+ GitRepo: ctx.Repo.GitRepo,
}, r.Note)
if err != nil {
ctx.ServerError("RenderString", err)
release.Note, err = markdown.RenderString(&markup.RenderContext{
URLPrefix: ctx.Repo.RepoLink,
Metas: ctx.Repo.Repository.ComposeMetas(),
+ GitRepo: ctx.Repo.GitRepo,
}, release.Note)
if err != nil {
ctx.ServerError("RenderString", err)
Filename: readmeFile.name,
URLPrefix: readmeTreelink,
Metas: ctx.Repo.Repository.ComposeDocumentMetas(),
+ GitRepo: ctx.Repo.GitRepo,
}, rd, &result)
if err != nil {
log.Error("Render failed: %v then fallback", err)
Filename: blob.Name(),
URLPrefix: path.Dir(treeLink),
Metas: ctx.Repo.Repository.ComposeDocumentMetas(),
+ GitRepo: ctx.Repo.GitRepo,
}, rd, &result)
if err != nil {
ctx.ServerError("Render", err)
Filename: blob.Name(),
URLPrefix: path.Dir(treeLink),
Metas: ctx.Repo.Repository.ComposeDocumentMetas(),
+ GitRepo: ctx.Repo.GitRepo,
}, rd, &result)
if err != nil {
ctx.ServerError("Render", err)
content, err := markdown.RenderString(&markup.RenderContext{
URLPrefix: ctx.Repo.RepoLink,
Metas: map[string]string{"mode": "document"},
+ GitRepo: ctx.Repo.GitRepo,
}, ctxUser.Description)
if err != nil {
ctx.ServerError("RenderString", err)