diff options
author | Mario Lubenka <mario.lubenka@googlemail.com> | 2019-06-07 22:29:29 +0200 |
---|---|---|
committer | techknowlogick <hello@techknowlogick.com> | 2019-06-07 16:29:29 -0400 |
commit | 311ce2d1d06c26d0d5a3b745493995813e2ea6f2 (patch) | |
tree | 128b7cf4a9772373ea25bfea523de4298e5e78a2 /routers | |
parent | bd55f6ff36d40503bfa3407225780d0ab7d37930 (diff) | |
download | gitea-311ce2d1d06c26d0d5a3b745493995813e2ea6f2.tar.gz gitea-311ce2d1d06c26d0d5a3b745493995813e2ea6f2.zip |
Compare branches, commits and tags with each other (#6991)
* Supports tags when comparing commits or branches
Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com>
* Hide headline when only comparing and don't load unused data
Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com>
* Merges compare logics to allow comparing branches, commits and tags with eachother
Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com>
* Display branch or tag instead of commit when used for comparing
Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com>
* Show pull request form after click on button
Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com>
* Transfers relevant pull.go changes from master to compare.go
Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com>
* Fixes error when comparing forks against a commit or tag
Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com>
* Removes console.log from JavaScript file
Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com>
* Show icon next to commit reference when comparing branch or tag
Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com>
* Updates css file
Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com>
* Fixes import order
* Renames template variable
* Update routers/repo/compare.go
Co-Authored-By: zeripath <art27@cantab.net>
* Update from master
Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com>
* Allow short-shas in compare
* Renames prInfo to compareInfo
Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com>
* Check PR permissions only if compare is pull request
Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com>
* Adjusts comment
Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com>
* Use compareInfo instead of prInfo
Diffstat (limited to 'routers')
-rw-r--r-- | routers/api/v1/repo/pull.go | 14 | ||||
-rw-r--r-- | routers/repo/commit.go | 59 | ||||
-rw-r--r-- | routers/repo/compare.go | 337 | ||||
-rw-r--r-- | routers/repo/pull.go | 278 | ||||
-rw-r--r-- | routers/routes/routes.go | 9 |
5 files changed, 360 insertions, 337 deletions
diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index f53ab4b8f3..0e1db144b1 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -188,7 +188,7 @@ func CreatePullRequest(ctx *context.APIContext, form api.CreatePullRequestOption ) // Get repo/branch information - headUser, headRepo, headGitRepo, prInfo, baseBranch, headBranch := parseCompareInfo(ctx, form) + headUser, headRepo, headGitRepo, compareInfo, baseBranch, headBranch := parseCompareInfo(ctx, form) if ctx.Written() { return } @@ -240,7 +240,7 @@ func CreatePullRequest(ctx *context.APIContext, form api.CreatePullRequestOption milestoneID = milestone.ID } - patch, err := headGitRepo.GetPatch(prInfo.MergeBase, headBranch) + patch, err := headGitRepo.GetPatch(compareInfo.MergeBase, headBranch) if err != nil { ctx.Error(500, "GetPatch", err) return @@ -277,7 +277,7 @@ func CreatePullRequest(ctx *context.APIContext, form api.CreatePullRequestOption BaseBranch: baseBranch, HeadRepo: headRepo, BaseRepo: repo, - MergeBase: prInfo.MergeBase, + MergeBase: compareInfo.MergeBase, Type: models.PullRequestGitea, } @@ -600,7 +600,7 @@ func MergePullRequest(ctx *context.APIContext, form auth.MergePullRequestForm) { ctx.Status(200) } -func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption) (*models.User, *models.Repository, *git.Repository, *git.PullRequestInfo, string, string) { +func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption) (*models.User, *models.Repository, *git.Repository, *git.CompareInfo, string, string) { baseRepo := ctx.Repo.Repository // Get compared branches information @@ -712,11 +712,11 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption) return nil, nil, nil, nil, "", "" } - prInfo, err := headGitRepo.GetPullRequestInfo(models.RepoPath(baseRepo.Owner.Name, baseRepo.Name), baseBranch, headBranch) + compareInfo, err := headGitRepo.GetCompareInfo(models.RepoPath(baseRepo.Owner.Name, baseRepo.Name), baseBranch, headBranch) if err != nil { - ctx.Error(500, "GetPullRequestInfo", err) + ctx.Error(500, "GetCompareInfo", err) return nil, nil, nil, nil, "", "" } - return headUser, headRepo, headGitRepo, prInfo, baseBranch, headBranch + return headUser, headRepo, headGitRepo, compareInfo, baseBranch, headBranch } diff --git a/routers/repo/commit.go b/routers/repo/commit.go index 870ff568f3..dde6d8f321 100644 --- a/routers/repo/commit.go +++ b/routers/repo/commit.go @@ -19,9 +19,9 @@ import ( ) const ( - tplCommits base.TplName = "repo/commits" - tplGraph base.TplName = "repo/graph" - tplDiff base.TplName = "repo/diff/page" + tplCommits base.TplName = "repo/commits" + tplGraph base.TplName = "repo/graph" + tplCommitPage base.TplName = "repo/commit_page" ) // RefCommits render commits page @@ -261,7 +261,7 @@ func Diff(ctx *context.Context) { } ctx.Data["RawPath"] = setting.AppSubURL + "/" + path.Join(userName, repoName, "raw", "commit", commitID) ctx.Data["BranchName"], err = commit.GetBranchName() - ctx.HTML(200, tplDiff) + ctx.HTML(200, tplCommitPage) } // RawDiff dumps diff results of repository in given commit ID to io.Writer @@ -276,54 +276,3 @@ func RawDiff(ctx *context.Context) { return } } - -// CompareDiff show different from one commit to another commit -func CompareDiff(ctx *context.Context) { - ctx.Data["IsRepoToolbarCommits"] = true - ctx.Data["IsDiffCompare"] = true - userName := ctx.Repo.Owner.Name - repoName := ctx.Repo.Repository.Name - beforeCommitID := ctx.Params(":before") - afterCommitID := ctx.Params(":after") - - commit, err := ctx.Repo.GitRepo.GetCommit(afterCommitID) - if err != nil { - ctx.NotFound("GetCommit", err) - return - } - - diff, err := models.GetDiffRange(models.RepoPath(userName, repoName), beforeCommitID, - afterCommitID, setting.Git.MaxGitDiffLines, - setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles) - if err != nil { - ctx.NotFound("GetDiffRange", err) - return - } - - commits, err := commit.CommitsBeforeUntil(beforeCommitID) - if err != nil { - ctx.ServerError("CommitsBeforeUntil", err) - return - } - commits = models.ValidateCommitsWithEmails(commits) - commits = models.ParseCommitsWithSignature(commits) - commits = models.ParseCommitsWithStatus(commits, ctx.Repo.Repository) - - ctx.Data["CommitRepoLink"] = ctx.Repo.RepoLink - ctx.Data["Commits"] = commits - ctx.Data["CommitCount"] = commits.Len() - ctx.Data["BeforeCommitID"] = beforeCommitID - ctx.Data["AfterCommitID"] = afterCommitID - ctx.Data["Username"] = userName - ctx.Data["Reponame"] = repoName - ctx.Data["IsImageFile"] = commit.IsImageFile - ctx.Data["Title"] = "Comparing " + base.ShortSha(beforeCommitID) + "..." + base.ShortSha(afterCommitID) + " ยท " + userName + "/" + repoName - ctx.Data["Commit"] = commit - ctx.Data["Diff"] = diff - ctx.Data["DiffNotAvailable"] = diff.NumFiles() == 0 - ctx.Data["SourcePath"] = setting.AppSubURL + "/" + path.Join(userName, repoName, "src", "commit", afterCommitID) - ctx.Data["BeforeSourcePath"] = setting.AppSubURL + "/" + path.Join(userName, repoName, "src", "commit", beforeCommitID) - ctx.Data["RawPath"] = setting.AppSubURL + "/" + path.Join(userName, repoName, "raw", "commit", afterCommitID) - ctx.Data["RequireHighlightJS"] = true - ctx.HTML(200, tplDiff) -} diff --git a/routers/repo/compare.go b/routers/repo/compare.go new file mode 100644 index 0000000000..a85084791d --- /dev/null +++ b/routers/repo/compare.go @@ -0,0 +1,337 @@ +// 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 repo + +import ( + "path" + "strings" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting" +) + +const ( + tplCompare base.TplName = "repo/diff/compare" +) + +// ParseCompareInfo parse compare info between two commit for preparing comparing references +func ParseCompareInfo(ctx *context.Context) (*models.User, *models.Repository, *git.Repository, *git.CompareInfo, string, string) { + baseRepo := ctx.Repo.Repository + + // Get compared branches information + // format: <base branch>...[<head repo>:]<head branch> + // base<-head: master...head:feature + // same repo: master...feature + + var ( + headUser *models.User + headBranch string + isSameRepo bool + infoPath string + err error + ) + infoPath = ctx.Params("*") + infos := strings.Split(infoPath, "...") + if len(infos) != 2 { + log.Trace("ParseCompareInfo[%d]: not enough compared branches information %s", baseRepo.ID, infos) + ctx.NotFound("CompareAndPullRequest", nil) + return nil, nil, nil, nil, "", "" + } + + baseBranch := infos[0] + ctx.Data["BaseBranch"] = baseBranch + + // If there is no head repository, it means compare between same repository. + headInfos := strings.Split(infos[1], ":") + if len(headInfos) == 1 { + isSameRepo = true + headUser = ctx.Repo.Owner + headBranch = headInfos[0] + + } else if len(headInfos) == 2 { + headUser, err = models.GetUserByName(headInfos[0]) + if err != nil { + if models.IsErrUserNotExist(err) { + ctx.NotFound("GetUserByName", nil) + } else { + ctx.ServerError("GetUserByName", err) + } + return nil, nil, nil, nil, "", "" + } + headBranch = headInfos[1] + isSameRepo = headUser.ID == ctx.Repo.Owner.ID + } else { + ctx.NotFound("CompareAndPullRequest", nil) + return nil, nil, nil, nil, "", "" + } + ctx.Data["HeadUser"] = headUser + ctx.Data["HeadBranch"] = headBranch + ctx.Repo.PullRequest.SameRepo = isSameRepo + + // Check if base branch is valid. + baseIsCommit := ctx.Repo.GitRepo.IsCommitExist(baseBranch) + baseIsBranch := ctx.Repo.GitRepo.IsBranchExist(baseBranch) + baseIsTag := ctx.Repo.GitRepo.IsTagExist(baseBranch) + if !baseIsCommit && !baseIsBranch && !baseIsTag { + // Check if baseBranch is short sha commit hash + if baseCommit, _ := ctx.Repo.GitRepo.GetCommit(baseBranch); baseCommit != nil { + baseBranch = baseCommit.ID.String() + ctx.Data["BaseBranch"] = baseBranch + baseIsCommit = true + } else { + ctx.NotFound("IsRefExist", nil) + return nil, nil, nil, nil, "", "" + } + } + ctx.Data["BaseIsCommit"] = baseIsCommit + ctx.Data["BaseIsBranch"] = baseIsBranch + ctx.Data["BaseIsTag"] = baseIsTag + + // Check if current user has fork of repository or in the same repository. + headRepo, has := models.HasForkedRepo(headUser.ID, baseRepo.ID) + if !has && !isSameRepo { + ctx.Data["PageIsComparePull"] = false + } + + var headGitRepo *git.Repository + if isSameRepo { + headRepo = ctx.Repo.Repository + headGitRepo = ctx.Repo.GitRepo + ctx.Data["BaseName"] = headUser.Name + } else { + headGitRepo, err = git.OpenRepository(models.RepoPath(headUser.Name, headRepo.Name)) + ctx.Data["BaseName"] = baseRepo.OwnerName + if err != nil { + ctx.ServerError("OpenRepository", err) + return nil, nil, nil, nil, "", "" + } + } + + // user should have permission to read baseRepo's codes and pulls, NOT headRepo's + permBase, err := models.GetUserRepoPermission(baseRepo, ctx.User) + if err != nil { + ctx.ServerError("GetUserRepoPermission", err) + return nil, nil, nil, nil, "", "" + } + if !permBase.CanRead(models.UnitTypeCode) { + if log.IsTrace() { + log.Trace("Permission Denied: User: %-v cannot read code in Repo: %-v\nUser in baseRepo has Permissions: %-+v", + ctx.User, + baseRepo, + permBase) + } + ctx.NotFound("ParseCompareInfo", nil) + return nil, nil, nil, nil, "", "" + } + + // user should have permission to read headrepo's codes + permHead, err := models.GetUserRepoPermission(headRepo, ctx.User) + if err != nil { + ctx.ServerError("GetUserRepoPermission", err) + return nil, nil, nil, nil, "", "" + } + if !permHead.CanRead(models.UnitTypeCode) { + if log.IsTrace() { + log.Trace("Permission Denied: User: %-v cannot read code in Repo: %-v\nUser in headRepo has Permissions: %-+v", + ctx.User, + headRepo, + permHead) + } + ctx.NotFound("ParseCompareInfo", nil) + return nil, nil, nil, nil, "", "" + } + + // Check if head branch is valid. + headIsCommit := ctx.Repo.GitRepo.IsCommitExist(headBranch) + headIsBranch := headGitRepo.IsBranchExist(headBranch) + headIsTag := headGitRepo.IsTagExist(headBranch) + if !headIsCommit && !headIsBranch && !headIsTag { + // Check if headBranch is short sha commit hash + if headCommit, _ := ctx.Repo.GitRepo.GetCommit(headBranch); headCommit != nil { + headBranch = headCommit.ID.String() + ctx.Data["HeadBranch"] = headBranch + headIsCommit = true + } else { + ctx.NotFound("IsRefExist", nil) + return nil, nil, nil, nil, "", "" + } + } + ctx.Data["HeadIsCommit"] = headIsCommit + ctx.Data["HeadIsBranch"] = headIsBranch + ctx.Data["HeadIsTag"] = headIsTag + + // Treat as pull request if both references are branches + if ctx.Data["PageIsComparePull"] == nil { + ctx.Data["PageIsComparePull"] = headIsBranch && baseIsBranch + } + + if ctx.Data["PageIsComparePull"] == true && !permBase.CanReadIssuesOrPulls(true) { + if log.IsTrace() { + log.Trace("Permission Denied: User: %-v cannot create/read pull requests in Repo: %-v\nUser in baseRepo has Permissions: %-+v", + ctx.User, + baseRepo, + permBase) + } + ctx.NotFound("ParseCompareInfo", nil) + return nil, nil, nil, nil, "", "" + } + + compareInfo, err := headGitRepo.GetCompareInfo(models.RepoPath(baseRepo.Owner.Name, baseRepo.Name), baseBranch, headBranch) + if err != nil { + ctx.ServerError("GetCompareInfo", err) + return nil, nil, nil, nil, "", "" + } + ctx.Data["BeforeCommitID"] = compareInfo.MergeBase + + return headUser, headRepo, headGitRepo, compareInfo, baseBranch, headBranch +} + +// PrepareCompareDiff renders compare diff page +func PrepareCompareDiff( + ctx *context.Context, + headUser *models.User, + headRepo *models.Repository, + headGitRepo *git.Repository, + compareInfo *git.CompareInfo, + baseBranch, headBranch string) bool { + + var ( + repo = ctx.Repo.Repository + err error + title string + ) + + // Get diff information. + ctx.Data["CommitRepoLink"] = headRepo.Link() + + headCommitID := headBranch + if ctx.Data["HeadIsCommit"] == false { + if ctx.Data["HeadIsTag"] == true { + headCommitID, err = headGitRepo.GetTagCommitID(headBranch) + } else { + headCommitID, err = headGitRepo.GetBranchCommitID(headBranch) + } + if err != nil { + ctx.ServerError("GetRefCommitID", err) + return false + } + } + + ctx.Data["AfterCommitID"] = headCommitID + + if headCommitID == compareInfo.MergeBase { + ctx.Data["IsNothingToCompare"] = true + return true + } + + diff, err := models.GetDiffRange(models.RepoPath(headUser.Name, headRepo.Name), + compareInfo.MergeBase, headCommitID, setting.Git.MaxGitDiffLines, + setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles) + if err != nil { + ctx.ServerError("GetDiffRange", err) + return false + } + ctx.Data["Diff"] = diff + ctx.Data["DiffNotAvailable"] = diff.NumFiles() == 0 + + headCommit, err := headGitRepo.GetCommit(headCommitID) + if err != nil { + ctx.ServerError("GetCommit", err) + return false + } + + compareInfo.Commits = models.ValidateCommitsWithEmails(compareInfo.Commits) + compareInfo.Commits = models.ParseCommitsWithSignature(compareInfo.Commits) + compareInfo.Commits = models.ParseCommitsWithStatus(compareInfo.Commits, headRepo) + ctx.Data["Commits"] = compareInfo.Commits + ctx.Data["CommitCount"] = compareInfo.Commits.Len() + if ctx.Data["CommitCount"] == 0 { + ctx.Data["PageIsComparePull"] = false + } + + if compareInfo.Commits.Len() == 1 { + c := compareInfo.Commits.Front().Value.(models.SignCommitWithStatuses) + title = strings.TrimSpace(c.UserCommit.Summary()) + + body := strings.Split(strings.TrimSpace(c.UserCommit.Message()), "\n") + if len(body) > 1 { + ctx.Data["content"] = strings.Join(body[1:], "\n") + } + } else { + title = headBranch + } + + ctx.Data["title"] = title + ctx.Data["Username"] = headUser.Name + ctx.Data["Reponame"] = headRepo.Name + ctx.Data["IsImageFile"] = headCommit.IsImageFile + + headTarget := path.Join(headUser.Name, repo.Name) + ctx.Data["SourcePath"] = setting.AppSubURL + "/" + path.Join(headTarget, "src", "commit", headCommitID) + ctx.Data["BeforeSourcePath"] = setting.AppSubURL + "/" + path.Join(headTarget, "src", "commit", compareInfo.MergeBase) + ctx.Data["RawPath"] = setting.AppSubURL + "/" + path.Join(headTarget, "raw", "commit", headCommitID) + return false +} + +// CompareDiff show different from one commit to another commit +func CompareDiff(ctx *context.Context) { + headUser, headRepo, headGitRepo, compareInfo, baseBranch, headBranch := ParseCompareInfo(ctx) + if ctx.Written() { + return + } + + nothingToCompare := PrepareCompareDiff(ctx, headUser, headRepo, headGitRepo, compareInfo, baseBranch, headBranch) + if ctx.Written() { + return + } + + if ctx.Data["PageIsComparePull"] == true { + pr, err := models.GetUnmergedPullRequest(headRepo.ID, ctx.Repo.Repository.ID, headBranch, baseBranch) + if err != nil { + if !models.IsErrPullRequestNotExist(err) { + ctx.ServerError("GetUnmergedPullRequest", err) + return + } + } else { + ctx.Data["HasPullRequest"] = true + ctx.Data["PullRequest"] = pr + ctx.HTML(200, tplCompareDiff) + return + } + + if !nothingToCompare { + // Setup information for new form. + RetrieveRepoMetas(ctx, ctx.Repo.Repository) + if ctx.Written() { + return + } + } + + headBranches, err := headGitRepo.GetBranches() + if err != nil { + ctx.ServerError("GetBranches", err) + return + } + ctx.Data["HeadBranches"] = headBranches + } + beforeCommitID := ctx.Data["BeforeCommitID"].(string) + afterCommitID := ctx.Data["AfterCommitID"].(string) + + ctx.Data["Title"] = "Comparing " + base.ShortSha(beforeCommitID) + "..." + base.ShortSha(afterCommitID) + + ctx.Data["IsRepoToolbarCommits"] = true + ctx.Data["IsDiffCompare"] = true + ctx.Data["RequireHighlightJS"] = true + ctx.Data["RequireTribute"] = true + ctx.Data["PullRequestWorkInProgressPrefixes"] = setting.Repository.PullRequest.WorkInProgressPrefixes + setTemplateIfExists(ctx, pullRequestTemplateKey, pullRequestTemplateCandidates) + renderAttachmentSettings(ctx) + + ctx.HTML(200, tplCompare) +} diff --git a/routers/repo/pull.go b/routers/repo/pull.go index 412750dd55..182f715545 100644 --- a/routers/repo/pull.go +++ b/routers/repo/pull.go @@ -28,7 +28,7 @@ import ( const ( tplFork base.TplName = "repo/pulls/fork" - tplComparePull base.TplName = "repo/pulls/compare" + tplCompareDiff base.TplName = "repo/diff/compare" tplPullCommits base.TplName = "repo/pulls/commits" tplPullFiles base.TplName = "repo/pulls/files" @@ -280,13 +280,13 @@ func setMergeTarget(ctx *context.Context, pull *models.PullRequest) { } // PrepareMergedViewPullInfo show meta information for a merged pull request view page -func PrepareMergedViewPullInfo(ctx *context.Context, issue *models.Issue) *git.PullRequestInfo { +func PrepareMergedViewPullInfo(ctx *context.Context, issue *models.Issue) *git.CompareInfo { pull := issue.PullRequest setMergeTarget(ctx, pull) ctx.Data["HasMerged"] = true - prInfo, err := ctx.Repo.GitRepo.GetPullRequestInfo(ctx.Repo.Repository.RepoPath(), + prInfo, err := ctx.Repo.GitRepo.GetCompareInfo(ctx.Repo.Repository.RepoPath(), pull.MergeBase, pull.GetGitRefName()) if err != nil { @@ -298,7 +298,7 @@ func PrepareMergedViewPullInfo(ctx *context.Context, issue *models.Issue) *git.P return nil } - ctx.ServerError("GetPullRequestInfo", err) + ctx.ServerError("GetCompareInfo", err) return nil } ctx.Data["NumCommits"] = prInfo.Commits.Len() @@ -307,7 +307,7 @@ func PrepareMergedViewPullInfo(ctx *context.Context, issue *models.Issue) *git.P } // PrepareViewPullInfo show meta information for a pull request preview page -func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.PullRequestInfo { +func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.CompareInfo { repo := ctx.Repo.Repository pull := issue.PullRequest @@ -336,7 +336,7 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.PullReq return nil } - prInfo, err := headGitRepo.GetPullRequestInfo(models.RepoPath(repo.Owner.Name, repo.Name), + prInfo, err := headGitRepo.GetCompareInfo(models.RepoPath(repo.Owner.Name, repo.Name), pull.BaseBranch, pull.HeadBranch) if err != nil { if strings.Contains(err.Error(), "fatal: Not a valid object name") { @@ -347,7 +347,7 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.PullReq return nil } - ctx.ServerError("GetPullRequestInfo", err) + ctx.ServerError("GetCompareInfo", err) return nil } @@ -628,266 +628,6 @@ func stopTimerIfAvailable(user *models.User, issue *models.Issue) error { return nil } -// ParseCompareInfo parse compare info between two commit for preparing pull request -func ParseCompareInfo(ctx *context.Context) (*models.User, *models.Repository, *git.Repository, *git.PullRequestInfo, string, string) { - baseRepo := ctx.Repo.Repository - - // Get compared branches information - // format: <base branch>...[<head repo>:]<head branch> - // base<-head: master...head:feature - // same repo: master...feature - - var ( - headUser *models.User - headBranch string - isSameRepo bool - infoPath string - err error - ) - infoPath = ctx.Params("*") - infos := strings.Split(infoPath, "...") - if len(infos) != 2 { - log.Trace("ParseCompareInfo[%d]: not enough compared branches information %s", baseRepo.ID, infos) - ctx.NotFound("CompareAndPullRequest", nil) - return nil, nil, nil, nil, "", "" - } - - baseBranch := infos[0] - ctx.Data["BaseBranch"] = baseBranch - - // If there is no head repository, it means pull request between same repository. - headInfos := strings.Split(infos[1], ":") - if len(headInfos) == 1 { - isSameRepo = true - headUser = ctx.Repo.Owner - headBranch = headInfos[0] - - } else if len(headInfos) == 2 { - headUser, err = models.GetUserByName(headInfos[0]) - if err != nil { - if models.IsErrUserNotExist(err) { - ctx.NotFound("GetUserByName", nil) - } else { - ctx.ServerError("GetUserByName", err) - } - return nil, nil, nil, nil, "", "" - } - headBranch = headInfos[1] - isSameRepo = headUser.ID == ctx.Repo.Owner.ID - } else { - ctx.NotFound("CompareAndPullRequest", nil) - return nil, nil, nil, nil, "", "" - } - ctx.Data["HeadUser"] = headUser - ctx.Data["HeadBranch"] = headBranch - ctx.Repo.PullRequest.SameRepo = isSameRepo - - // Check if base branch is valid. - if !ctx.Repo.GitRepo.IsBranchExist(baseBranch) { - ctx.NotFound("IsBranchExist", nil) - return nil, nil, nil, nil, "", "" - } - - // Check if current user has fork of repository or in the same repository. - headRepo, has := models.HasForkedRepo(headUser.ID, baseRepo.ID) - if !has && !isSameRepo { - log.Trace("ParseCompareInfo[%d]: does not have fork or in same repository", baseRepo.ID) - ctx.NotFound("ParseCompareInfo", nil) - return nil, nil, nil, nil, "", "" - } - - var headGitRepo *git.Repository - if isSameRepo { - headRepo = ctx.Repo.Repository - headGitRepo = ctx.Repo.GitRepo - ctx.Data["BaseName"] = headUser.Name - } else { - headGitRepo, err = git.OpenRepository(models.RepoPath(headUser.Name, headRepo.Name)) - ctx.Data["BaseName"] = baseRepo.OwnerName - if err != nil { - ctx.ServerError("OpenRepository", err) - return nil, nil, nil, nil, "", "" - } - } - - // user should have permission to read baseRepo's codes and pulls, NOT headRepo's - permBase, err := models.GetUserRepoPermission(baseRepo, ctx.User) - if err != nil { - ctx.ServerError("GetUserRepoPermission", err) - return nil, nil, nil, nil, "", "" - } - if !permBase.CanReadIssuesOrPulls(true) || !permBase.CanRead(models.UnitTypeCode) { - if log.IsTrace() { - log.Trace("Permission Denied: User: %-v cannot create/read pull requests or cannot read code in Repo: %-v\nUser in baseRepo has Permissions: %-+v", - ctx.User, - baseRepo, - permBase) - } - ctx.NotFound("ParseCompareInfo", nil) - return nil, nil, nil, nil, "", "" - } - - // user should have permission to read headrepo's codes - permHead, err := models.GetUserRepoPermission(headRepo, ctx.User) - if err != nil { - ctx.ServerError("GetUserRepoPermission", err) - return nil, nil, nil, nil, "", "" - } - if !permHead.CanRead(models.UnitTypeCode) { - if log.IsTrace() { - log.Trace("Permission Denied: User: %-v cannot read code requests in Repo: %-v\nUser in headRepo has Permissions: %-+v", - ctx.User, - headRepo, - permHead) - } - ctx.NotFound("ParseCompareInfo", nil) - return nil, nil, nil, nil, "", "" - } - - // Check if head branch is valid. - if !headGitRepo.IsBranchExist(headBranch) { - ctx.NotFound("IsBranchExist", nil) - return nil, nil, nil, nil, "", "" - } - - headBranches, err := headGitRepo.GetBranches() - if err != nil { - ctx.ServerError("GetBranches", err) - return nil, nil, nil, nil, "", "" - } - ctx.Data["HeadBranches"] = headBranches - - prInfo, err := headGitRepo.GetPullRequestInfo(models.RepoPath(baseRepo.Owner.Name, baseRepo.Name), baseBranch, headBranch) - if err != nil { - ctx.ServerError("GetPullRequestInfo", err) - return nil, nil, nil, nil, "", "" - } - ctx.Data["BeforeCommitID"] = prInfo.MergeBase - - return headUser, headRepo, headGitRepo, prInfo, baseBranch, headBranch -} - -// PrepareCompareDiff render pull request preview diff page -func PrepareCompareDiff( - ctx *context.Context, - headUser *models.User, - headRepo *models.Repository, - headGitRepo *git.Repository, - prInfo *git.PullRequestInfo, - baseBranch, headBranch string) bool { - - var ( - repo = ctx.Repo.Repository - err error - title string - ) - - // Get diff information. - ctx.Data["CommitRepoLink"] = headRepo.Link() - - headCommitID, err := headGitRepo.GetBranchCommitID(headBranch) - if err != nil { - ctx.ServerError("GetBranchCommitID", err) - return false - } - ctx.Data["AfterCommitID"] = headCommitID - - if headCommitID == prInfo.MergeBase { - ctx.Data["IsNothingToCompare"] = true - return true - } - - diff, err := models.GetDiffRange(models.RepoPath(headUser.Name, headRepo.Name), - prInfo.MergeBase, headCommitID, setting.Git.MaxGitDiffLines, - setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles) - if err != nil { - ctx.ServerError("GetDiffRange", err) - return false - } - ctx.Data["Diff"] = diff - ctx.Data["DiffNotAvailable"] = diff.NumFiles() == 0 - - headCommit, err := headGitRepo.GetCommit(headCommitID) - if err != nil { - ctx.ServerError("GetCommit", err) - return false - } - - prInfo.Commits = models.ValidateCommitsWithEmails(prInfo.Commits) - prInfo.Commits = models.ParseCommitsWithSignature(prInfo.Commits) - prInfo.Commits = models.ParseCommitsWithStatus(prInfo.Commits, headRepo) - ctx.Data["Commits"] = prInfo.Commits - ctx.Data["CommitCount"] = prInfo.Commits.Len() - - if prInfo.Commits.Len() == 1 { - c := prInfo.Commits.Front().Value.(models.SignCommitWithStatuses) - title = strings.TrimSpace(c.UserCommit.Summary()) - - body := strings.Split(strings.TrimSpace(c.UserCommit.Message()), "\n") - if len(body) > 1 { - ctx.Data["content"] = strings.Join(body[1:], "\n") - } - } else { - title = headBranch - } - - ctx.Data["title"] = title - ctx.Data["Username"] = headUser.Name - ctx.Data["Reponame"] = headRepo.Name - ctx.Data["IsImageFile"] = headCommit.IsImageFile - - headTarget := path.Join(headUser.Name, repo.Name) - ctx.Data["SourcePath"] = setting.AppSubURL + "/" + path.Join(headTarget, "src", "commit", headCommitID) - ctx.Data["BeforeSourcePath"] = setting.AppSubURL + "/" + path.Join(headTarget, "src", "commit", prInfo.MergeBase) - ctx.Data["RawPath"] = setting.AppSubURL + "/" + path.Join(headTarget, "raw", "commit", headCommitID) - return false -} - -// CompareAndPullRequest render pull request preview page -func CompareAndPullRequest(ctx *context.Context) { - ctx.Data["Title"] = ctx.Tr("repo.pulls.compare_changes") - ctx.Data["PageIsComparePull"] = true - ctx.Data["IsDiffCompare"] = true - ctx.Data["RequireHighlightJS"] = true - ctx.Data["RequireTribute"] = true - ctx.Data["PullRequestWorkInProgressPrefixes"] = setting.Repository.PullRequest.WorkInProgressPrefixes - setTemplateIfExists(ctx, pullRequestTemplateKey, pullRequestTemplateCandidates) - renderAttachmentSettings(ctx) - - headUser, headRepo, headGitRepo, prInfo, baseBranch, headBranch := ParseCompareInfo(ctx) - if ctx.Written() { - return - } - - pr, err := models.GetUnmergedPullRequest(headRepo.ID, ctx.Repo.Repository.ID, headBranch, baseBranch) - if err != nil { - if !models.IsErrPullRequestNotExist(err) { - ctx.ServerError("GetUnmergedPullRequest", err) - return - } - } else { - ctx.Data["HasPullRequest"] = true - ctx.Data["PullRequest"] = pr - ctx.HTML(200, tplComparePull) - return - } - - nothingToCompare := PrepareCompareDiff(ctx, headUser, headRepo, headGitRepo, prInfo, baseBranch, headBranch) - if ctx.Written() { - return - } - - if !nothingToCompare { - // Setup information for new form. - RetrieveRepoMetas(ctx, ctx.Repo.Repository) - if ctx.Written() { - return - } - } - - ctx.HTML(200, tplComparePull) -} - // CompareAndPullRequestPost response for creating pull request func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm) { ctx.Data["Title"] = ctx.Tr("repo.pulls.compare_changes") @@ -926,7 +666,7 @@ func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm) return } - ctx.HTML(200, tplComparePull) + ctx.HTML(200, tplCompareDiff) return } @@ -936,7 +676,7 @@ func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm) return } - ctx.RenderWithErr(ctx.Tr("repo.issues.new.title_empty"), tplComparePull, form) + ctx.RenderWithErr(ctx.Tr("repo.issues.new.title_empty"), tplCompareDiff, form) return } diff --git a/routers/routes/routes.go b/routers/routes/routes.go index eb5f73768e..4c736f63ed 100644 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -732,9 +732,9 @@ func RegisterRoutes(m *macaron.Macaron) { m.Group("/milestone", func() { m.Get("/:id", repo.MilestoneIssuesAndPulls) }, reqRepoIssuesOrPullsReader, context.RepoRef()) - m.Combo("/compare/*", context.RepoMustNotBeArchived(), reqRepoCodeReader, reqRepoPullsReader, repo.MustAllowPulls, repo.SetEditorconfigIfExists). - Get(repo.SetDiffViewStyle, repo.CompareAndPullRequest). - Post(bindIgnErr(auth.CreateIssueForm{}), repo.CompareAndPullRequestPost) + m.Combo("/compare/*", repo.MustBeNotEmpty, reqRepoCodeReader, repo.SetEditorconfigIfExists). + Get(repo.SetDiffViewStyle, repo.CompareDiff). + Post(context.RepoMustNotBeArchived(), reqRepoPullsReader, repo.MustAllowPulls, bindIgnErr(auth.CreateIssueForm{}), repo.CompareAndPullRequestPost) m.Group("", func() { m.Group("", func() { @@ -906,9 +906,6 @@ func RegisterRoutes(m *macaron.Macaron) { }, context.RepoRef(), reqRepoCodeReader) m.Get("/commit/:sha([a-f0-9]{7,40})\\.:ext(patch|diff)", repo.MustBeNotEmpty, reqRepoCodeReader, repo.RawDiff) - - m.Get("/compare/:before([a-z0-9]{40})\\.\\.\\.:after([a-z0-9]{40})", repo.SetEditorconfigIfExists, - repo.SetDiffViewStyle, repo.MustBeNotEmpty, reqRepoCodeReader, repo.CompareDiff) }, ignSignIn, context.RepoAssignment(), context.UnitTypes()) m.Group("/:username/:reponame", func() { m.Get("/stars", repo.Stars) |