snapshot of https://github.com/go-gitea/gitea.git (main, 2026-09-15; blobs > 131072B omitted)
Some checks failed
cache-seeder / prune (push) Has been skipped
cache-seeder / frontend (push) Failing after 3s
cache-seeder / python (push) Failing after 3s
cache-seeder / gobuild (push) Failing after 4s
cache-seeder / lint (bindata, lint-backend) (push) Failing after 3s
giteabot backport / giteabot (push) Has been skipped
giteabot / giteabot (push) Has been skipped
cache-prune / prune (push) Has been skipped
release-nightly-snapcraft / build-and-publish (ubuntu-24.04) (push) Has been cancelled
release-nightly-snapcraft / build-and-publish (ubuntu-24.04-arm) (push) Has been cancelled
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
cron-renovate / cron-renovate (push) Has been skipped
Some checks failed
cache-seeder / prune (push) Has been skipped
cache-seeder / frontend (push) Failing after 3s
cache-seeder / python (push) Failing after 3s
cache-seeder / gobuild (push) Failing after 4s
cache-seeder / lint (bindata, lint-backend) (push) Failing after 3s
giteabot backport / giteabot (push) Has been skipped
giteabot / giteabot (push) Has been skipped
cache-prune / prune (push) Has been skipped
release-nightly-snapcraft / build-and-publish (ubuntu-24.04) (push) Has been cancelled
release-nightly-snapcraft / build-and-publish (ubuntu-24.04-arm) (push) Has been cancelled
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
cron-renovate / cron-renovate (push) Has been skipped
This commit is contained in:
469
routers/web/repo/commit.go
Normal file
469
routers/web/repo/commit.go
Normal file
@@ -0,0 +1,469 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package repo
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
asymkey_model "gitea.dev/models/asymkey"
|
||||
"gitea.dev/models/db"
|
||||
git_model "gitea.dev/models/git"
|
||||
"gitea.dev/models/gituser"
|
||||
issues_model "gitea.dev/models/issues"
|
||||
"gitea.dev/models/renderhelper"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
user_model "gitea.dev/models/user"
|
||||
"gitea.dev/modules/base"
|
||||
"gitea.dev/modules/container"
|
||||
"gitea.dev/modules/fileicon"
|
||||
"gitea.dev/modules/git"
|
||||
"gitea.dev/modules/htmlutil"
|
||||
"gitea.dev/modules/log"
|
||||
"gitea.dev/modules/markup"
|
||||
"gitea.dev/modules/setting"
|
||||
"gitea.dev/modules/templates"
|
||||
"gitea.dev/modules/util"
|
||||
asymkey_service "gitea.dev/services/asymkey"
|
||||
"gitea.dev/services/context"
|
||||
git_service "gitea.dev/services/git"
|
||||
"gitea.dev/services/gitdiff"
|
||||
repo_service "gitea.dev/services/repository"
|
||||
"gitea.dev/services/repository/gitgraph"
|
||||
)
|
||||
|
||||
const (
|
||||
tplCommits templates.TplName = "repo/commits"
|
||||
tplGraph templates.TplName = "repo/graph"
|
||||
tplGraphDiv templates.TplName = "repo/graph/div"
|
||||
tplCommitPage templates.TplName = "repo/commit_page"
|
||||
)
|
||||
|
||||
// RefCommits render commits page
|
||||
func RefCommits(ctx *context.Context) {
|
||||
switch {
|
||||
case len(ctx.Repo.TreePath) == 0:
|
||||
Commits(ctx)
|
||||
case ctx.Repo.TreePath == "search": // FIXME: legacy dirty design, it conflicts with the FileHistory
|
||||
SearchCommits(ctx)
|
||||
default:
|
||||
FileHistory(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
// Commits render branch's commits
|
||||
func Commits(ctx *context.Context) {
|
||||
ctx.Data["PageIsCommits"] = true
|
||||
if ctx.Repo.Commit == nil {
|
||||
ctx.NotFound(nil)
|
||||
return
|
||||
}
|
||||
ctx.Data["PageIsViewCode"] = true
|
||||
|
||||
commitsCount := ctx.Repo.CommitsCount
|
||||
|
||||
page := max(ctx.FormInt("page"), 1)
|
||||
|
||||
pageSize := ctx.FormInt("limit")
|
||||
if pageSize <= 0 {
|
||||
pageSize = setting.Git.CommitsRangeSize
|
||||
}
|
||||
|
||||
// Both `git log branchName` and `git log commitId` work.
|
||||
commits, err := ctx.Repo.Commit.CommitsByRange(ctx, ctx.Repo.GitRepo, page, pageSize, "", "", "")
|
||||
if err != nil {
|
||||
ctx.ServerError("CommitsByRange", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["Commits"], err = processGitCommits(ctx, commits)
|
||||
if err != nil {
|
||||
ctx.ServerError("processGitCommits", err)
|
||||
return
|
||||
}
|
||||
commitIDs := make([]string, 0, len(commits))
|
||||
for _, c := range commits {
|
||||
commitIDs = append(commitIDs, c.ID.String())
|
||||
}
|
||||
commitsTagsMap, err := repo_model.FindTagsByCommitIDs(ctx, ctx.Repo.Repository.ID, commitIDs...)
|
||||
if err != nil {
|
||||
log.Error("FindTagsByCommitIDs: %v", err)
|
||||
ctx.Flash.Error(ctx.Tr("internal_error_skipped", "FindTagsByCommitIDs"))
|
||||
} else {
|
||||
ctx.Data["CommitsTagsMap"] = commitsTagsMap
|
||||
}
|
||||
ctx.Data["CommitCount"] = commitsCount
|
||||
|
||||
pager := context.NewPagerBuilder(ctx).TotalCount(commitsCount).PerPageLimit(pageSize).CurPage(page).Build()
|
||||
ctx.Data["Page"] = pager
|
||||
ctx.HTML(http.StatusOK, tplCommits)
|
||||
}
|
||||
|
||||
// Graph render commit graph - show commits from all branches.
|
||||
func Graph(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.commit_graph")
|
||||
ctx.Data["PageIsCommits"] = true
|
||||
ctx.Data["PageIsViewCode"] = true
|
||||
mode := strings.ToLower(ctx.FormTrim("mode"))
|
||||
if mode != "monochrome" {
|
||||
mode = "color"
|
||||
}
|
||||
ctx.Data["Mode"] = mode
|
||||
hidePRRefs := ctx.FormBool("hide-pr-refs")
|
||||
ctx.Data["HidePRRefs"] = hidePRRefs
|
||||
branches := ctx.FormStrings("branch")
|
||||
ctx.Data["SelectedBranches"] = branches
|
||||
|
||||
branchRefs := make([]string, 0, len(branches))
|
||||
for _, branchName := range branches {
|
||||
branchRef := branchName
|
||||
if !strings.HasPrefix(branchRef, "refs/") {
|
||||
branchRef = git.BranchPrefix + branchRef
|
||||
}
|
||||
branchRefs = append(branchRefs, branchRef)
|
||||
}
|
||||
|
||||
files := ctx.FormStrings("file")
|
||||
graphCommitsCount, err := ctx.Repo.GetCommitGraphsCount(ctx, hidePRRefs, branchRefs, files)
|
||||
if err != nil {
|
||||
if len(branchRefs) > 0 {
|
||||
// maybe: "fatal: bad revision '.....'" if a ref doesn't exist
|
||||
// maybe it's better to show a 404 page instead of the unclear retry, anyway, a retry isn't harmful, so keep the old behavior
|
||||
branchRefs = nil
|
||||
graphCommitsCount, err = ctx.Repo.GetCommitGraphsCount(ctx, hidePRRefs, branchRefs, files)
|
||||
}
|
||||
if err != nil {
|
||||
ctx.ServerError("GetCommitGraphsCount", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
page := ctx.FormInt("page")
|
||||
graph, err := gitgraph.GetCommitGraph(ctx, ctx.Repo.GitRepo, page, 0, hidePRRefs, branchRefs, files)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetCommitGraph", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := graph.LoadAndProcessCommits(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo); err != nil {
|
||||
ctx.ServerError("LoadAndProcessCommits", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data["Graph"] = graph
|
||||
|
||||
gitRefs, err := ctx.Repo.GitRepo.GetRefs(ctx)
|
||||
if err != nil {
|
||||
ctx.ServerError("GitRepo.GetRefs", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data["AllRefs"] = gitRefs
|
||||
|
||||
divOnly := ctx.FormBool("div-only")
|
||||
paginator := context.NewPagerBuilder(ctx).TotalCount(graphCommitsCount).PerPageLimit(setting.UI.GraphMaxCommitNum).CurPage(page).Build()
|
||||
paginator.RemoveParam(container.SetOf("div-only"))
|
||||
ctx.Data["Page"] = paginator
|
||||
if divOnly {
|
||||
ctx.HTML(http.StatusOK, tplGraphDiv)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.HTML(http.StatusOK, tplGraph)
|
||||
}
|
||||
|
||||
// SearchCommits render commits filtered by keyword
|
||||
func SearchCommits(ctx *context.Context) {
|
||||
ctx.Data["PageIsCommits"] = true
|
||||
ctx.Data["PageIsViewCode"] = true
|
||||
|
||||
query := ctx.FormTrim("q")
|
||||
if len(query) == 0 {
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/commits/" + ctx.Repo.RefTypeNameSubURL())
|
||||
return
|
||||
}
|
||||
|
||||
all := ctx.FormBool("all")
|
||||
opts := git.NewSearchCommitsOptions(query, all)
|
||||
commits, err := ctx.Repo.Commit.SearchCommits(ctx, ctx.Repo.GitRepo, opts)
|
||||
if err != nil {
|
||||
ctx.ServerError("SearchCommits", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["CommitCount"] = len(commits)
|
||||
ctx.Data["Commits"], err = processGitCommits(ctx, commits)
|
||||
if err != nil {
|
||||
ctx.ServerError("processGitCommits", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data["Keyword"] = query
|
||||
if all {
|
||||
ctx.Data["All"] = true
|
||||
}
|
||||
ctx.HTML(http.StatusOK, tplCommits)
|
||||
}
|
||||
|
||||
// FileHistory show a file's reversions
|
||||
func FileHistory(ctx *context.Context) {
|
||||
if ctx.Repo.TreePath == "" {
|
||||
Commits(ctx)
|
||||
return
|
||||
}
|
||||
|
||||
followRename := ctx.FormBool("follow-rename")
|
||||
ctx.Data["ShowFollowRename"] = true
|
||||
ctx.Data["FollowRenameChecked"] = followRename
|
||||
|
||||
page := max(ctx.FormInt("page"), 1)
|
||||
commits, hasMore, err := ctx.Repo.GitRepo.CommitsByFileAndRange(ctx,
|
||||
git.CommitsByFileAndRangeOptions{
|
||||
Revision: ctx.Repo.RefFullName.ShortName(), // FIXME: legacy code used ShortName
|
||||
File: ctx.Repo.TreePath,
|
||||
Page: page,
|
||||
FollowRename: followRename,
|
||||
})
|
||||
if err != nil {
|
||||
ctx.ServerError("CommitsByFileAndRange", err)
|
||||
return
|
||||
}
|
||||
|
||||
var commitsCount int64
|
||||
if followRename {
|
||||
// there is no quick method to know the total count when "follow rename"
|
||||
commitsCount = -1
|
||||
} else {
|
||||
commitsCount, err = git.FileCommitsCount(ctx, ctx.Repo.Repository, ctx.Repo.RefFullName.ShortName(), ctx.Repo.TreePath)
|
||||
if err != nil {
|
||||
ctx.ServerError("FileCommitsCount", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if len(commits) == 0 {
|
||||
ctx.NotFound(nil)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data["FileTreePath"] = ctx.Repo.TreePath
|
||||
ctx.Data["CommitCount"] = commitsCount
|
||||
ctx.Data["Commits"], err = processGitCommits(ctx, commits)
|
||||
if err != nil {
|
||||
ctx.ServerError("processGitCommits", err)
|
||||
return
|
||||
}
|
||||
|
||||
pager := context.NewPagerBuilder(ctx).TotalCount(commitsCount).PerPageLimit(setting.Git.CommitsRangeSize).CurPage(page).Build()
|
||||
if commitsCount == -1 {
|
||||
pager.WithUnlimitedPaging(len(commits), hasMore)
|
||||
}
|
||||
ctx.Data["Page"] = pager
|
||||
ctx.HTML(http.StatusOK, tplCommits)
|
||||
}
|
||||
|
||||
func LoadBranchesAndTags(ctx *context.Context) {
|
||||
response, err := repo_service.LoadBranchesAndTags(ctx, ctx.Repo, ctx.PathParam("sha"))
|
||||
if err == nil {
|
||||
ctx.JSON(http.StatusOK, response)
|
||||
return
|
||||
}
|
||||
ctx.NotFoundOrServerError(fmt.Sprintf("could not load branches and tags the commit %s belongs to", ctx.PathParam("sha")), git.IsErrNotExist, err)
|
||||
}
|
||||
|
||||
// Diff show different from current commit to previous commit
|
||||
func Diff(ctx *context.Context) {
|
||||
ctx.Data["PageIsDiff"] = true
|
||||
|
||||
userName := ctx.Repo.Owner.Name
|
||||
repoName := ctx.Repo.Repository.Name
|
||||
commitID := ctx.PathParam("sha")
|
||||
|
||||
diffBlobExcerptData := &gitdiff.DiffBlobExcerptData{
|
||||
BaseLink: ctx.Repo.RepoLink + "/blob_excerpt",
|
||||
DiffStyle: GetDiffViewStyle(ctx),
|
||||
AfterCommitID: commitID,
|
||||
}
|
||||
gitRepo := ctx.Repo.GitRepo // don't access ctx.Repo.GitRepo anymore, because it might not be right for wiki repo
|
||||
|
||||
if ctx.Data["PageIsWiki"] != nil {
|
||||
var err error
|
||||
gitRepo, err = git.RepositoryFromRequestContextOrOpen(ctx, ctx.Repo.Repository.WikiStorageRepo())
|
||||
if err != nil {
|
||||
ctx.ServerError("Repo.GitRepo.GetCommit", err)
|
||||
return
|
||||
}
|
||||
diffBlobExcerptData.BaseLink = ctx.Repo.RepoLink + "/wiki/blob_excerpt"
|
||||
}
|
||||
|
||||
commit, err := gitRepo.GetCommit(ctx, commitID)
|
||||
if err != nil {
|
||||
if git.IsErrNotExist(err) {
|
||||
ctx.NotFound(err)
|
||||
} else {
|
||||
ctx.ServerError("Repo.GitRepo.GetCommit", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if len(commitID) != commit.ID.Type().FullLength() {
|
||||
commitID = commit.ID.String()
|
||||
}
|
||||
|
||||
fileOnly := ctx.FormBool("file-only")
|
||||
maxLines, maxFiles := setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffFiles
|
||||
files := ctx.FormStrings("files")
|
||||
if fileOnly && (len(files) == 2 || len(files) == 1) {
|
||||
maxLines, maxFiles = -1, -1
|
||||
}
|
||||
|
||||
diffCommonOptions := gitdiff.DiffCommonOptions{
|
||||
WhitespaceBehavior: gitdiff.GetWhitespaceFlag(GetWhitespaceBehavior(ctx)),
|
||||
AfterCommitID: commitID,
|
||||
}
|
||||
diff, err := gitdiff.GetDiffForRender(ctx, ctx.Repo.RepoLink, gitRepo, &gitdiff.DiffOptions{
|
||||
DiffCommonOptions: diffCommonOptions,
|
||||
SkipTo: ctx.FormString("skip-to"),
|
||||
MaxLines: maxLines,
|
||||
MaxLineCharacters: setting.Git.MaxGitDiffLineCharacters,
|
||||
MaxFiles: maxFiles,
|
||||
}, files...)
|
||||
if err != nil {
|
||||
ctx.NotFound(err)
|
||||
return
|
||||
}
|
||||
diffShortStat, err := gitdiff.GetDiffShortStat(ctx, gitRepo, &diffCommonOptions)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetDiffShortStat", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["DiffShortStat"] = diffShortStat
|
||||
|
||||
parents := make([]string, commit.ParentCount())
|
||||
for i := 0; i < commit.ParentCount(); i++ {
|
||||
sha, err := commit.ParentID(i)
|
||||
if err != nil {
|
||||
ctx.NotFound(err)
|
||||
return
|
||||
}
|
||||
parents[i] = sha.String()
|
||||
}
|
||||
|
||||
ctx.Data["CommitID"] = commitID
|
||||
ctx.Data["AfterCommitID"] = commitID
|
||||
|
||||
var parentCommit *git.Commit
|
||||
var parentCommitID string
|
||||
if commit.ParentCount() > 0 {
|
||||
parentCommit, err = gitRepo.GetCommit(ctx, parents[0])
|
||||
if err != nil {
|
||||
ctx.NotFound(err)
|
||||
return
|
||||
}
|
||||
parentCommitID = parentCommit.ID.String()
|
||||
}
|
||||
setCompareContext(ctx, parentCommit, commit, userName, repoName)
|
||||
ctx.Data["Title"] = commit.MessageTitle() + " · " + base.ShortSha(commitID)
|
||||
ctx.Data["Commit"] = commit
|
||||
ctx.Data["Diff"] = diff
|
||||
ctx.Data["DiffBlobExcerptData"] = diffBlobExcerptData
|
||||
|
||||
if !fileOnly {
|
||||
diffTree, err := gitdiff.GetDiffTree(ctx, gitRepo, false, parentCommitID, commitID)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetDiffTree", err)
|
||||
return
|
||||
}
|
||||
|
||||
renderedIconPool := fileicon.NewRenderedIconPool()
|
||||
ctx.PageData["DiffFileTree"] = transformDiffTreeForWeb(renderedIconPool, diffTree, nil)
|
||||
ctx.PageData["FolderIcon"] = fileicon.RenderEntryIconHTML(renderedIconPool, fileicon.EntryInfoFolder())
|
||||
ctx.PageData["FolderOpenIcon"] = fileicon.RenderEntryIconHTML(renderedIconPool, fileicon.EntryInfoFolderOpen())
|
||||
ctx.Data["FileIconPoolHTML"] = renderedIconPool.RenderToHTML()
|
||||
}
|
||||
|
||||
statuses, err := git_model.GetLatestCommitStatus(ctx, ctx.Repo.Repository.ID, commitID, db.ListOptionsAll)
|
||||
if err != nil {
|
||||
log.Error("GetLatestCommitStatus: %v", err)
|
||||
}
|
||||
git_model.CommitStatusesApplyDoerPermission(ctx, ctx.Doer, statuses)
|
||||
|
||||
ctx.Data["CommitStatus"] = git_model.CalcCommitStatus(statuses)
|
||||
ctx.Data["CommitStatuses"] = statuses
|
||||
|
||||
verification := asymkey_service.ParseCommitWithSignature(ctx, commit)
|
||||
ctx.Data["Verification"] = util.Iif(verification.IsCommitNotSigned(), nil, verification)
|
||||
ctx.Data["CommitAvatarStackData"] = gituser.BuildAvatarStackData(ctx, commit.AllAuthorIdentities(), nil)
|
||||
ctx.Data["Parents"] = parents
|
||||
ctx.Data["DiffNotAvailable"] = diffShortStat.NumFiles == 0
|
||||
ctx.Data["ShowDiffSummaryInToolbar"] = false
|
||||
ctx.Data["ShowDiffSummaryInCommitHeader"] = diffShortStat.NumFiles != 0
|
||||
|
||||
if err := asymkey_model.CalculateTrustStatus(verification, ctx.Repo.Repository.GetTrustModel(), func(user *user_model.User) (bool, error) {
|
||||
return repo_model.HasAccessToRepoCodeUnit(ctx, ctx.Repo.Repository, user.ID)
|
||||
}, nil); err != nil {
|
||||
ctx.ServerError("CalculateTrustStatus", err)
|
||||
return
|
||||
}
|
||||
|
||||
note, noteLastCommit, err := git.GetNoteWithLastCommit(ctx, gitRepo, commitID)
|
||||
if err == nil {
|
||||
ctx.Data["NoteCommit"] = noteLastCommit
|
||||
ctx.Data["NoteAuthor"] = user_model.GetUserByGitAuthor(ctx, noteLastCommit)
|
||||
rctx := renderhelper.NewRenderContextRepoComment(ctx, ctx.Repo.Repository, renderhelper.RepoCommentOptions{CurrentRefSubURL: "commit/" + util.PathEscapeSegments(commitID)})
|
||||
htmlMessage := htmlutil.EscapeString(note.BlobMessage.MessageUTF8())
|
||||
ctx.Data["NoteRendered"] = markup.PostProcessCommitMessage(rctx, htmlMessage)
|
||||
} else if !git.IsErrNotExist(err) {
|
||||
log.Error("GetNote: %v", err)
|
||||
}
|
||||
|
||||
pr, _ := issues_model.GetPullRequestByMergedCommit(ctx, ctx.Repo.Repository.ID, commitID)
|
||||
if pr != nil {
|
||||
ctx.Data["MergedPRIssueNumber"] = pr.Index
|
||||
}
|
||||
|
||||
ctx.HTML(http.StatusOK, tplCommitPage)
|
||||
}
|
||||
|
||||
// RawDiff dumps diff results of repository in given commit ID to io.Writer
|
||||
func RawDiff(ctx *context.Context) {
|
||||
var gitRepo *git.Repository
|
||||
if ctx.Data["PageIsWiki"] != nil {
|
||||
wikiRepo, err := git.OpenRepository(ctx, ctx.Repo.Repository.WikiStorageRepo())
|
||||
if err != nil {
|
||||
ctx.ServerError("OpenRepository", err)
|
||||
return
|
||||
}
|
||||
defer wikiRepo.Close()
|
||||
gitRepo = wikiRepo
|
||||
} else {
|
||||
gitRepo = ctx.Repo.GitRepo
|
||||
if gitRepo == nil {
|
||||
ctx.ServerError("GitRepo not open", fmt.Errorf("no open git repo for '%s'", ctx.Repo.Repository.FullName()))
|
||||
return
|
||||
}
|
||||
}
|
||||
if err := git.GetRawDiff(ctx,
|
||||
gitRepo,
|
||||
ctx.PathParam("sha"),
|
||||
git.RawDiffType(ctx.PathParam("ext")),
|
||||
ctx.Resp,
|
||||
); err != nil {
|
||||
if git.IsErrNotExist(err) {
|
||||
ctx.NotFound(errors.New("commit " + ctx.PathParam("sha") + " does not exist."))
|
||||
return
|
||||
}
|
||||
ctx.ServerError("GetRawDiff", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func processGitCommits(ctx *context.Context, gitCommits []*git.Commit) ([]*git_model.SignCommitWithStatuses, error) {
|
||||
commits, err := git_service.ConvertFromGitCommit(ctx, gitCommits, ctx.Repo.Repository, ctx.Repo.RefFullName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
git_model.SignCommitsApplyDoerPermission(ctx, ctx.Doer, commits)
|
||||
return commits, nil
|
||||
}
|
||||
Reference in New Issue
Block a user