summaryrefslogtreecommitdiffstats
path: root/modules/git/repo_compare.go
diff options
context:
space:
mode:
authorMario Lubenka <mario.lubenka@googlemail.com>2019-06-07 22:29:29 +0200
committertechknowlogick <hello@techknowlogick.com>2019-06-07 16:29:29 -0400
commit311ce2d1d06c26d0d5a3b745493995813e2ea6f2 (patch)
tree128b7cf4a9772373ea25bfea523de4298e5e78a2 /modules/git/repo_compare.go
parentbd55f6ff36d40503bfa3407225780d0ab7d37930 (diff)
downloadgitea-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 'modules/git/repo_compare.go')
-rw-r--r--modules/git/repo_compare.go106
1 files changed, 106 insertions, 0 deletions
diff --git a/modules/git/repo_compare.go b/modules/git/repo_compare.go
new file mode 100644
index 0000000000..e7a1d72a85
--- /dev/null
+++ b/modules/git/repo_compare.go
@@ -0,0 +1,106 @@
+// Copyright 2015 The Gogs Authors. All rights reserved.
+// 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 (
+ "bytes"
+ "container/list"
+ "fmt"
+ "io"
+ "strconv"
+ "strings"
+ "time"
+)
+
+// CompareInfo represents needed information for comparing references.
+type CompareInfo struct {
+ MergeBase string
+ Commits *list.List
+ NumFiles int
+}
+
+// GetMergeBase checks and returns merge base of two branches.
+func (repo *Repository) GetMergeBase(tmpRemote string, base, head string) (string, error) {
+ if tmpRemote == "" {
+ tmpRemote = "origin"
+ }
+
+ if tmpRemote != "origin" {
+ tmpBaseName := "refs/remotes/" + tmpRemote + "/tmp_" + base
+ // Fetch commit into a temporary branch in order to be able to handle commits and tags
+ _, err := NewCommand("fetch", tmpRemote, base+":"+tmpBaseName).RunInDir(repo.Path)
+ if err == nil {
+ base = tmpBaseName
+ }
+ }
+
+ stdout, err := NewCommand("merge-base", base, head).RunInDir(repo.Path)
+ return strings.TrimSpace(stdout), err
+}
+
+// GetCompareInfo generates and returns compare information between base and head branches of repositories.
+func (repo *Repository) GetCompareInfo(basePath, baseBranch, headBranch string) (_ *CompareInfo, err error) {
+ var (
+ remoteBranch string
+ tmpRemote string
+ )
+
+ // We don't need a temporary remote for same repository.
+ if repo.Path != basePath {
+ // Add a temporary remote
+ tmpRemote = strconv.FormatInt(time.Now().UnixNano(), 10)
+ if err = repo.AddRemote(tmpRemote, basePath, true); err != nil {
+ return nil, fmt.Errorf("AddRemote: %v", err)
+ }
+ defer repo.RemoveRemote(tmpRemote)
+ }
+
+ compareInfo := new(CompareInfo)
+ compareInfo.MergeBase, err = repo.GetMergeBase(tmpRemote, baseBranch, headBranch)
+ if err == nil {
+ // We have a common base
+ logs, err := NewCommand("log", compareInfo.MergeBase+"..."+headBranch, prettyLogFormat).RunInDirBytes(repo.Path)
+ if err != nil {
+ return nil, err
+ }
+ compareInfo.Commits, err = repo.parsePrettyFormatLogToList(logs)
+ if err != nil {
+ return nil, fmt.Errorf("parsePrettyFormatLogToList: %v", err)
+ }
+ } else {
+ compareInfo.Commits = list.New()
+ compareInfo.MergeBase, err = GetFullCommitID(repo.Path, remoteBranch)
+ if err != nil {
+ compareInfo.MergeBase = remoteBranch
+ }
+ }
+
+ // Count number of changed files.
+ stdout, err := NewCommand("diff", "--name-only", remoteBranch+"..."+headBranch).RunInDir(repo.Path)
+ if err != nil {
+ return nil, err
+ }
+ compareInfo.NumFiles = len(strings.Split(stdout, "\n")) - 1
+
+ return compareInfo, nil
+}
+
+// GetPatch generates and returns patch data between given revisions.
+func (repo *Repository) GetPatch(base, head string) ([]byte, error) {
+ return NewCommand("diff", "-p", "--binary", base, head).RunInDirBytes(repo.Path)
+}
+
+// GetFormatPatch generates and returns format-patch data between given revisions.
+func (repo *Repository) GetFormatPatch(base, head string) (io.Reader, error) {
+ stdout := new(bytes.Buffer)
+ stderr := new(bytes.Buffer)
+
+ if err := NewCommand("format-patch", "--binary", "--stdout", base+"..."+head).
+ RunInDirPipeline(repo.Path, stdout, stderr); err != nil {
+ return nil, concatenateError(err, stderr.String())
+ }
+ return stdout, nil
+}