]> source.dussan.org Git - gitea.git/commitdiff
Restore functionality for early gits (#7775) (#8476)
authorzeripath <art27@cantab.net>
Sun, 13 Oct 2019 04:40:13 +0000 (05:40 +0100)
committerLunny Xiao <xiaolunwen@gmail.com>
Sun, 13 Oct 2019 04:40:13 +0000 (12:40 +0800)
* Change tests to make it possible to run TestGit with 1.7.2

* Make merge run on 1.7.2

* Fix tracking and staging branch name problem

* Ensure that git 1.7.2 works on tests

* ensure that there is no chance for conflicts

* Fix-up missing merge issues

* Final rm

* Ensure LFS filters run on the tests

* Do not sign commits from temp repo

* Apply suggestions from code review

* Update modules/repofiles/temp_repo.go

12 files changed:
integrations/git_helper_for_declarative_test.go
integrations/git_test.go
integrations/lfs_getobject_test.go
models/repo.go
models/repo_mirror.go
modules/git/repo_branch.go
modules/git/repo_tree.go
modules/process/manager.go
modules/pull/merge.go
modules/repofiles/temp_repo.go
modules/repofiles/update.go
modules/repofiles/upload.go

index 9190d4bb4e53100021de5abdd5ec254522febb43..d3f934d54c1a6909d6863ffcf946b6a0e11247dd 100644 (file)
@@ -12,7 +12,9 @@ import (
        "net/http"
        "net/url"
        "os"
+       "path"
        "path/filepath"
+       "strings"
        "testing"
        "time"
 
@@ -36,7 +38,12 @@ func withKeyFile(t *testing.T, keyname string, callback func(string)) {
        err = ssh.GenKeyPair(keyFile)
        assert.NoError(t, err)
 
+       err = ioutil.WriteFile(path.Join(tmpDir, "ssh"), []byte("#!/bin/bash\n"+
+               "ssh -o \"UserKnownHostsFile=/dev/null\" -o \"StrictHostKeyChecking=no\" -o \"IdentitiesOnly=yes\" -i \""+keyFile+"\" \"$@\""), 0700)
+       assert.NoError(t, err)
+
        //Setup ssh wrapper
+       os.Setenv("GIT_SSH", path.Join(tmpDir, "ssh"))
        os.Setenv("GIT_SSH_COMMAND",
                "ssh -o \"UserKnownHostsFile=/dev/null\" -o \"StrictHostKeyChecking=no\" -o \"IdentitiesOnly=yes\" -i \""+keyFile+"\"")
        os.Setenv("GIT_SSH_VARIANT", "ssh")
@@ -53,6 +60,24 @@ func createSSHUrl(gitPath string, u *url.URL) *url.URL {
        return &u2
 }
 
+func allowLFSFilters() []string {
+       // Now here we should explicitly allow lfs filters to run
+       globalArgs := git.GlobalCommandArgs
+       filteredLFSGlobalArgs := make([]string, len(git.GlobalCommandArgs))
+       j := 0
+       for _, arg := range git.GlobalCommandArgs {
+               if strings.Contains(arg, "lfs") {
+                       j--
+               } else {
+                       filteredLFSGlobalArgs[j] = arg
+                       j++
+               }
+       }
+       filteredLFSGlobalArgs = filteredLFSGlobalArgs[:j]
+       git.GlobalCommandArgs = filteredLFSGlobalArgs
+       return globalArgs
+}
+
 func onGiteaRun(t *testing.T, callback func(*testing.T, *url.URL)) {
        prepareTestEnv(t, 1)
        s := http.Server{
@@ -78,7 +103,9 @@ func onGiteaRun(t *testing.T, callback func(*testing.T, *url.URL)) {
 
 func doGitClone(dstLocalPath string, u *url.URL) func(*testing.T) {
        return func(t *testing.T) {
+               oldGlobals := allowLFSFilters()
                assert.NoError(t, git.Clone(u.String(), dstLocalPath, git.CloneRepoOptions{}))
+               git.GlobalCommandArgs = oldGlobals
                assert.True(t, com.IsExist(filepath.Join(dstLocalPath, "README.md")))
        }
 }
@@ -139,7 +166,9 @@ func doGitCreateBranch(dstPath, branch string) func(*testing.T) {
 
 func doGitCheckoutBranch(dstPath string, args ...string) func(*testing.T) {
        return func(t *testing.T) {
+               oldGlobals := allowLFSFilters()
                _, err := git.NewCommand(append([]string{"checkout"}, args...)...).RunInDir(dstPath)
+               git.GlobalCommandArgs = oldGlobals
                assert.NoError(t, err)
        }
 }
@@ -153,7 +182,9 @@ func doGitMerge(dstPath string, args ...string) func(*testing.T) {
 
 func doGitPull(dstPath string, args ...string) func(*testing.T) {
        return func(t *testing.T) {
+               oldGlobals := allowLFSFilters()
                _, err := git.NewCommand(append([]string{"pull"}, args...)...).RunInDir(dstPath)
+               git.GlobalCommandArgs = oldGlobals
                assert.NoError(t, err)
        }
 }
index 8578fb86d5d7624b3c9a14fb688fe1b6aac94c07..dbcc26522765f50e5c6b4ed11709c59903e954fe 100644 (file)
@@ -19,6 +19,7 @@ import (
 
        "code.gitea.io/gitea/models"
        "code.gitea.io/gitea/modules/git"
+       "code.gitea.io/gitea/modules/setting"
        api "code.gitea.io/gitea/modules/structs"
 
        "github.com/stretchr/testify/assert"
@@ -135,6 +136,11 @@ func standardCommitAndPushTest(t *testing.T, dstPath string) (little, big string
 func lfsCommitAndPushTest(t *testing.T, dstPath string) (littleLFS, bigLFS string) {
        t.Run("LFS", func(t *testing.T) {
                PrintCurrentTest(t)
+               setting.CheckLFSVersion()
+               if !setting.LFS.StartServer {
+                       t.Skip()
+                       return
+               }
                prefix := "lfs-data-file-"
                _, err := git.NewCommand("lfs").AddArguments("install").RunInDir(dstPath)
                assert.NoError(t, err)
@@ -142,6 +148,21 @@ func lfsCommitAndPushTest(t *testing.T, dstPath string) (littleLFS, bigLFS strin
                assert.NoError(t, err)
                err = git.AddChanges(dstPath, false, ".gitattributes")
                assert.NoError(t, err)
+               oldGlobals := allowLFSFilters()
+               err = git.CommitChanges(dstPath, git.CommitChangesOptions{
+                       Committer: &git.Signature{
+                               Email: "user2@example.com",
+                               Name:  "User Two",
+                               When:  time.Now(),
+                       },
+                       Author: &git.Signature{
+                               Email: "user2@example.com",
+                               Name:  "User Two",
+                               When:  time.Now(),
+                       },
+                       Message: fmt.Sprintf("Testing commit @ %v", time.Now()),
+               })
+               git.GlobalCommandArgs = oldGlobals
 
                littleLFS, bigLFS = commitAndPushTest(t, dstPath, prefix)
 
@@ -185,20 +206,25 @@ func rawTest(t *testing.T, ctx *APITestContext, little, big, littleLFS, bigLFS s
                resp := session.MakeRequest(t, req, http.StatusOK)
                assert.Equal(t, littleSize, resp.Body.Len())
 
-               req = NewRequest(t, "GET", path.Join("/", username, reponame, "/raw/branch/master/", littleLFS))
-               resp = session.MakeRequest(t, req, http.StatusOK)
-               assert.NotEqual(t, littleSize, resp.Body.Len())
-               assert.Contains(t, resp.Body.String(), models.LFSMetaFileIdentifier)
+               setting.CheckLFSVersion()
+               if setting.LFS.StartServer {
+                       req = NewRequest(t, "GET", path.Join("/", username, reponame, "/raw/branch/master/", littleLFS))
+                       resp = session.MakeRequest(t, req, http.StatusOK)
+                       assert.NotEqual(t, littleSize, resp.Body.Len())
+                       assert.Contains(t, resp.Body.String(), models.LFSMetaFileIdentifier)
+               }
 
                if !testing.Short() {
                        req = NewRequest(t, "GET", path.Join("/", username, reponame, "/raw/branch/master/", big))
                        resp = session.MakeRequest(t, req, http.StatusOK)
                        assert.Equal(t, bigSize, resp.Body.Len())
 
-                       req = NewRequest(t, "GET", path.Join("/", username, reponame, "/raw/branch/master/", bigLFS))
-                       resp = session.MakeRequest(t, req, http.StatusOK)
-                       assert.NotEqual(t, bigSize, resp.Body.Len())
-                       assert.Contains(t, resp.Body.String(), models.LFSMetaFileIdentifier)
+                       if setting.LFS.StartServer {
+                               req = NewRequest(t, "GET", path.Join("/", username, reponame, "/raw/branch/master/", bigLFS))
+                               resp = session.MakeRequest(t, req, http.StatusOK)
+                               assert.NotEqual(t, bigSize, resp.Body.Len())
+                               assert.Contains(t, resp.Body.String(), models.LFSMetaFileIdentifier)
+                       }
                }
        })
 }
@@ -217,18 +243,23 @@ func mediaTest(t *testing.T, ctx *APITestContext, little, big, littleLFS, bigLFS
                resp := session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
                assert.Equal(t, littleSize, resp.Length)
 
-               req = NewRequest(t, "GET", path.Join("/", username, reponame, "/media/branch/master/", littleLFS))
-               resp = session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
-               assert.Equal(t, littleSize, resp.Length)
+               setting.CheckLFSVersion()
+               if setting.LFS.StartServer {
+                       req = NewRequest(t, "GET", path.Join("/", username, reponame, "/media/branch/master/", littleLFS))
+                       resp = session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
+                       assert.Equal(t, littleSize, resp.Length)
+               }
 
                if !testing.Short() {
                        req = NewRequest(t, "GET", path.Join("/", username, reponame, "/media/branch/master/", big))
                        resp = session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
                        assert.Equal(t, bigSize, resp.Length)
 
-                       req = NewRequest(t, "GET", path.Join("/", username, reponame, "/media/branch/master/", bigLFS))
-                       resp = session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
-                       assert.Equal(t, bigSize, resp.Length)
+                       if setting.LFS.StartServer {
+                               req = NewRequest(t, "GET", path.Join("/", username, reponame, "/media/branch/master/", bigLFS))
+                               resp = session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
+                               assert.Equal(t, bigSize, resp.Length)
+                       }
                }
        })
 }
@@ -274,6 +305,8 @@ func generateCommitWithNewData(size int, repoPath, email, fullName, prefix strin
        }
 
        //Commit
+       // Now here we should explicitly allow lfs filters to run
+       oldGlobals := allowLFSFilters()
        err = git.AddChanges(repoPath, false, filepath.Base(tmpFile.Name()))
        if err != nil {
                return "", err
@@ -291,6 +324,7 @@ func generateCommitWithNewData(size int, repoPath, email, fullName, prefix strin
                },
                Message: fmt.Sprintf("Testing commit @ %v", time.Now()),
        })
+       git.GlobalCommandArgs = oldGlobals
        return filepath.Base(tmpFile.Name()), err
 }
 
index 567cf13b45b6daed22f0faa1d411c6006125ff98..da3ddcec706d14ee05217a4832d74240d4c9359e 100644 (file)
@@ -58,6 +58,11 @@ func storeObjectInRepo(t *testing.T, repositoryID int64, content *[]byte) string
 
 func doLfs(t *testing.T, content *[]byte, expectGzip bool) {
        prepareTestEnv(t)
+       setting.CheckLFSVersion()
+       if !setting.LFS.StartServer {
+               t.Skip()
+               return
+       }
        repo, err := models.GetRepositoryByOwnerAndName("user2", "repo1")
        assert.NoError(t, err)
        oid := storeObjectInRepo(t, repo.ID, content)
index 976e8532325efaffeb24165117ba23fb35d2b1d3..36f27fef53a62afed93fdf44eb1d2ce508b91086 100644 (file)
@@ -1063,7 +1063,7 @@ func CleanUpMigrateInfo(repo *Repository) (*Repository, error) {
                }
        }
 
-       _, err := git.NewCommand("remote", "remove", "origin").RunInDir(repoPath)
+       _, err := git.NewCommand("remote", "rm", "origin").RunInDir(repoPath)
        if err != nil && !strings.HasPrefix(err.Error(), "exit status 128 - fatal: No such remote ") {
                return repo, fmt.Errorf("CleanUpMigrateInfo: %v", err)
        }
index c62834f6fb69e95ce4a28ccdd77e33e2c043e7d9..982672ea2b83e4db2f4c3ffd260e088718519a08 100644 (file)
@@ -134,7 +134,7 @@ func (m *Mirror) FullAddress() string {
 func (m *Mirror) SaveAddress(addr string) error {
        repoPath := m.Repo.RepoPath()
        // Remove old origin
-       _, err := git.NewCommand("remote", "remove", "origin").RunInDir(repoPath)
+       _, err := git.NewCommand("remote", "rm", "origin").RunInDir(repoPath)
        if err != nil && !strings.HasPrefix(err.Error(), "exit status 128 - fatal: No such remote ") {
                return err
        }
index 9209f4a764f4af013ef352961fd35f03202fabe6..3e1261d294cf80590a92c3730bd70f9726bcaae8 100644 (file)
@@ -165,7 +165,7 @@ func (repo *Repository) AddRemote(name, url string, fetch bool) error {
 
 // RemoveRemote removes a remote from repository.
 func (repo *Repository) RemoveRemote(name string) error {
-       _, err := NewCommand("remote", "remove", name).RunInDir(repo.Path)
+       _, err := NewCommand("remote", "rm", name).RunInDir(repo.Path)
        return err
 }
 
index f7c9dff923cabe4bf86e116914f8c58127bf7a80..f6b393d8d86f3a17f2859751dda4870e45c57721 100644 (file)
@@ -6,11 +6,13 @@
 package git
 
 import (
+       "bytes"
        "fmt"
        "os"
        "strings"
        "time"
 
+       "github.com/mcuadros/go-version"
        "gopkg.in/src-d/go-git.v4/plumbing"
 )
 
@@ -63,6 +65,11 @@ type CommitTreeOpts struct {
 
 // CommitTree creates a commit from a given tree id for the user with provided message
 func (repo *Repository) CommitTree(sig *Signature, tree *Tree, opts CommitTreeOpts) (SHA1, error) {
+       binVersion, err := BinVersion()
+       if err != nil {
+               return SHA1{}, err
+       }
+
        commitTimeStr := time.Now().Format(time.RFC3339)
 
        // Because this may call hooks we should pass in the environment
@@ -80,20 +87,24 @@ func (repo *Repository) CommitTree(sig *Signature, tree *Tree, opts CommitTreeOp
                cmd.AddArguments("-p", parent)
        }
 
-       cmd.AddArguments("-m", opts.Message)
+       messageBytes := new(bytes.Buffer)
+       _, _ = messageBytes.WriteString(opts.Message)
+       _, _ = messageBytes.WriteString("\n")
 
        if opts.KeyID != "" {
                cmd.AddArguments(fmt.Sprintf("-S%s", opts.KeyID))
        }
 
-       if opts.NoGPGSign {
+       if version.Compare(binVersion, "2.0.0", ">=") && opts.NoGPGSign {
                cmd.AddArguments("--no-gpg-sign")
        }
 
-       res, err := cmd.RunInDirWithEnv(repo.Path, env)
+       stdout := new(bytes.Buffer)
+       stderr := new(bytes.Buffer)
+       err = cmd.RunInDirTimeoutEnvFullPipeline(env, -1, repo.Path, stdout, stderr, messageBytes)
 
        if err != nil {
-               return SHA1{}, err
+               return SHA1{}, concatenateError(err, stderr.String())
        }
-       return NewIDFromString(strings.TrimSpace(res))
+       return NewIDFromString(strings.TrimSpace(stdout.String()))
 }
index 9ac3af86f106e76d459ef724e51854f319ca8695..3e77c0a6a90f15a8280909b018297bffed8f9f3b 100644 (file)
@@ -1,4 +1,5 @@
 // Copyright 2014 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.
 
@@ -9,6 +10,7 @@ import (
        "context"
        "errors"
        "fmt"
+       "io"
        "os/exec"
        "sync"
        "time"
@@ -93,6 +95,14 @@ func (pm *Manager) ExecDir(timeout time.Duration, dir, desc, cmdName string, arg
 // Returns its complete stdout and stderr
 // outputs and an error, if any (including timeout)
 func (pm *Manager) ExecDirEnv(timeout time.Duration, dir, desc string, env []string, cmdName string, args ...string) (string, string, error) {
+       return pm.ExecDirEnvStdIn(timeout, dir, desc, env, nil, cmdName, args...)
+}
+
+// ExecDirEnvStdIn runs a command in given path and environment variables with provided stdIN, and waits for its completion
+// up to the given timeout (or DefaultTimeout if -1 is given).
+// Returns its complete stdout and stderr
+// outputs and an error, if any (including timeout)
+func (pm *Manager) ExecDirEnvStdIn(timeout time.Duration, dir, desc string, env []string, stdIn io.Reader, cmdName string, args ...string) (string, string, error) {
        if timeout == -1 {
                timeout = 60 * time.Second
        }
@@ -108,6 +118,10 @@ func (pm *Manager) ExecDirEnv(timeout time.Duration, dir, desc string, env []str
        cmd.Env = env
        cmd.Stdout = stdOut
        cmd.Stderr = stdErr
+       if stdIn != nil {
+               cmd.Stdin = stdIn
+       }
+
        if err := cmd.Start(); err != nil {
                return "", "", err
        }
index 0e9e3b8b1457b3b56be1e05d91d6fad278e08957..e9c77ff9d9317f576e2575f8ac23de41609f09a0 100644 (file)
@@ -11,7 +11,6 @@ import (
        "fmt"
        "io/ioutil"
        "os"
-       "path"
        "path/filepath"
        "strings"
 
@@ -22,6 +21,7 @@ import (
        "code.gitea.io/gitea/modules/setting"
        api "code.gitea.io/gitea/modules/structs"
        "code.gitea.io/gitea/modules/util"
+       "github.com/mcuadros/go-version"
 )
 
 // Merge merges pull request to base repository.
@@ -66,20 +66,17 @@ func Merge(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repositor
 
        headRepoPath := models.RepoPath(pr.HeadUserName, pr.HeadRepo.Name)
 
-       if err := git.Clone(baseGitRepo.Path, tmpBasePath, git.CloneRepoOptions{
-               Shared:     true,
-               NoCheckout: true,
-               Branch:     pr.BaseBranch,
-       }); err != nil {
-               return fmt.Errorf("git clone: %v", err)
+       if err := git.InitRepository(tmpBasePath, false); err != nil {
+               return fmt.Errorf("git init: %v", err)
        }
 
        remoteRepoName := "head_repo"
+       baseBranch := "base"
 
        // Add head repo remote.
        addCacheRepo := func(staging, cache string) error {
                p := filepath.Join(staging, ".git", "objects", "info", "alternates")
-               f, err := os.OpenFile(p, os.O_APPEND|os.O_WRONLY, 0600)
+               f, err := os.OpenFile(p, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
                if err != nil {
                        return err
                }
@@ -91,25 +88,41 @@ func Merge(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repositor
                return nil
        }
 
-       if err := addCacheRepo(tmpBasePath, headRepoPath); err != nil {
+       if err := addCacheRepo(tmpBasePath, baseGitRepo.Path); err != nil {
                return fmt.Errorf("addCacheRepo [%s -> %s]: %v", headRepoPath, tmpBasePath, err)
        }
 
        var errbuf strings.Builder
+       if err := git.NewCommand("remote", "add", "-t", pr.BaseBranch, "-m", pr.BaseBranch, "origin", baseGitRepo.Path).RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
+               return fmt.Errorf("git remote add [%s -> %s]: %s", baseGitRepo.Path, tmpBasePath, errbuf.String())
+       }
+
+       if err := git.NewCommand("fetch", "origin", "--no-tags", pr.BaseBranch+":"+baseBranch, pr.BaseBranch+":original_"+baseBranch).RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
+               return fmt.Errorf("git fetch [%s -> %s]: %s", headRepoPath, tmpBasePath, errbuf.String())
+       }
+
+       if err := git.NewCommand("symbolic-ref", "HEAD", git.BranchPrefix+baseBranch).RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
+               return fmt.Errorf("git symbolic-ref HEAD base [%s]: %s", tmpBasePath, errbuf.String())
+       }
+
+       if err := addCacheRepo(tmpBasePath, headRepoPath); err != nil {
+               return fmt.Errorf("addCacheRepo [%s -> %s]: %v", headRepoPath, tmpBasePath, err)
+       }
+
        if err := git.NewCommand("remote", "add", remoteRepoName, headRepoPath).RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
                return fmt.Errorf("git remote add [%s -> %s]: %s", headRepoPath, tmpBasePath, errbuf.String())
        }
 
+       trackingBranch := "tracking"
        // Fetch head branch
-       if err := git.NewCommand("fetch", remoteRepoName, fmt.Sprintf("%s:refs/remotes/%s/%s", pr.HeadBranch, remoteRepoName, pr.HeadBranch)).RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
+       if err := git.NewCommand("fetch", "--no-tags", remoteRepoName, pr.HeadBranch+":"+trackingBranch).RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
                return fmt.Errorf("git fetch [%s -> %s]: %s", headRepoPath, tmpBasePath, errbuf.String())
        }
 
-       trackingBranch := path.Join(remoteRepoName, pr.HeadBranch)
-       stagingBranch := fmt.Sprintf("%s_%s", remoteRepoName, pr.HeadBranch)
+       stagingBranch := "staging"
 
        // Enable sparse-checkout
-       sparseCheckoutList, err := getDiffTree(tmpBasePath, pr.BaseBranch, trackingBranch)
+       sparseCheckoutList, err := getDiffTree(tmpBasePath, baseBranch, trackingBranch)
        if err != nil {
                return fmt.Errorf("getDiffTree: %v", err)
        }
@@ -123,21 +136,37 @@ func Merge(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repositor
                return fmt.Errorf("Writing sparse-checkout file to %s: %v", sparseCheckoutListPath, err)
        }
 
+       gitConfigCommand := func() func() *git.Command {
+               binVersion, err := git.BinVersion()
+               if err != nil {
+                       log.Fatal("Error retrieving git version: %v", err)
+               }
+
+               if version.Compare(binVersion, "1.8.0", ">=") {
+                       return func() *git.Command {
+                               return git.NewCommand("config", "--local")
+                       }
+               }
+               return func() *git.Command {
+                       return git.NewCommand("config")
+               }
+       }()
+
        // Switch off LFS process (set required, clean and smudge here also)
-       if err := git.NewCommand("config", "--local", "filter.lfs.process", "").RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
+       if err := gitConfigCommand().AddArguments("filter.lfs.process", "").RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
                return fmt.Errorf("git config [filter.lfs.process -> <> ]: %v", errbuf.String())
        }
-       if err := git.NewCommand("config", "--local", "filter.lfs.required", "false").RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
+       if err := gitConfigCommand().AddArguments("filter.lfs.required", "false").RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
                return fmt.Errorf("git config [filter.lfs.required -> <false> ]: %v", errbuf.String())
        }
-       if err := git.NewCommand("config", "--local", "filter.lfs.clean", "").RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
+       if err := gitConfigCommand().AddArguments("filter.lfs.clean", "").RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
                return fmt.Errorf("git config [filter.lfs.clean -> <> ]: %v", errbuf.String())
        }
-       if err := git.NewCommand("config", "--local", "filter.lfs.smudge", "").RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
+       if err := gitConfigCommand().AddArguments("filter.lfs.smudge", "").RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
                return fmt.Errorf("git config [filter.lfs.smudge -> <> ]: %v", errbuf.String())
        }
 
-       if err := git.NewCommand("config", "--local", "core.sparseCheckout", "true").RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
+       if err := gitConfigCommand().AddArguments("core.sparseCheckout", "true").RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
                return fmt.Errorf("git config [core.sparsecheckout -> true]: %v", errbuf.String())
        }
 
@@ -163,11 +192,11 @@ func Merge(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repositor
                        return fmt.Errorf("git checkout: %s", errbuf.String())
                }
                // Rebase before merging
-               if err := git.NewCommand("rebase", "-q", pr.BaseBranch).RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
+               if err := git.NewCommand("rebase", "-q", baseBranch).RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
                        return fmt.Errorf("git rebase [%s -> %s]: %s", headRepoPath, tmpBasePath, errbuf.String())
                }
                // Checkout base branch again
-               if err := git.NewCommand("checkout", pr.BaseBranch).RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
+               if err := git.NewCommand("checkout", baseBranch).RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
                        return fmt.Errorf("git checkout: %s", errbuf.String())
                }
                // Merge fast forward
@@ -180,11 +209,11 @@ func Merge(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repositor
                        return fmt.Errorf("git checkout: %s", errbuf.String())
                }
                // Rebase before merging
-               if err := git.NewCommand("rebase", "-q", pr.BaseBranch).RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
+               if err := git.NewCommand("rebase", "-q", baseBranch).RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
                        return fmt.Errorf("git rebase [%s -> %s]: %s", headRepoPath, tmpBasePath, errbuf.String())
                }
                // Checkout base branch again
-               if err := git.NewCommand("checkout", pr.BaseBranch).RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
+               if err := git.NewCommand("checkout", baseBranch).RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
                        return fmt.Errorf("git checkout: %s", errbuf.String())
                }
                // Prepare merge with commit
@@ -216,7 +245,7 @@ func Merge(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repositor
        if err != nil {
                return fmt.Errorf("Failed to get full commit id for HEAD: %v", err)
        }
-       mergeBaseSHA, err := git.GetFullCommitID(tmpBasePath, "origin/"+pr.BaseBranch)
+       mergeBaseSHA, err := git.GetFullCommitID(tmpBasePath, "original_"+baseBranch)
        if err != nil {
                return fmt.Errorf("Failed to get full commit id for origin/%s: %v", pr.BaseBranch, err)
        }
@@ -249,7 +278,7 @@ func Merge(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repositor
        )
 
        // Push back to upstream.
-       if err := git.NewCommand("push", "origin", pr.BaseBranch).RunInDirTimeoutEnvPipeline(env, -1, tmpBasePath, nil, &errbuf); err != nil {
+       if err := git.NewCommand("push", "origin", baseBranch+":"+pr.BaseBranch).RunInDirTimeoutEnvPipeline(env, -1, tmpBasePath, nil, &errbuf); err != nil {
                return fmt.Errorf("git push: %s", errbuf.String())
        }
 
index d640ba80b02bc5cd311e00494e78df3545262ef2..28f3836d0e119fcbd6148d475323310b21d0bd2a 100644 (file)
@@ -20,6 +20,7 @@ import (
        "code.gitea.io/gitea/modules/log"
        "code.gitea.io/gitea/modules/process"
        "code.gitea.io/gitea/modules/setting"
+       "github.com/mcuadros/go-version"
 )
 
 // TemporaryUploadRepository is a type to wrap our upload repositories as a shallow clone
@@ -253,6 +254,11 @@ func (t *TemporaryUploadRepository) CommitTree(author, committer *models.User, t
        authorSig := author.NewGitSig()
        committerSig := committer.NewGitSig()
 
+       binVersion, err := git.BinVersion()
+       if err != nil {
+               return "", fmt.Errorf("Unable to get git version: %v", err)
+       }
+
        // FIXME: Should we add SSH_ORIGINAL_COMMAND to this
        // Because this may call hooks we should pass in the environment
        env := append(os.Environ(),
@@ -263,11 +269,21 @@ func (t *TemporaryUploadRepository) CommitTree(author, committer *models.User, t
                "GIT_COMMITTER_EMAIL="+committerSig.Email,
                "GIT_COMMITTER_DATE="+commitTimeStr,
        )
-       commitHash, stderr, err := process.GetManager().ExecDirEnv(5*time.Minute,
+       messageBytes := new(bytes.Buffer)
+       _, _ = messageBytes.WriteString(message)
+       _, _ = messageBytes.WriteString("\n")
+
+       args := []string{"commit-tree", treeHash, "-p", "HEAD"}
+       if version.Compare(binVersion, "2.0.0", ">=") {
+               args = append(args, "--no-gpg-sign")
+       }
+
+       commitHash, stderr, err := process.GetManager().ExecDirEnvStdIn(5*time.Minute,
                t.basePath,
                fmt.Sprintf("commitTree (git commit-tree): %s", t.basePath),
                env,
-               git.GitExecutable, "commit-tree", treeHash, "-p", "HEAD", "-m", message)
+               messageBytes,
+               git.GitExecutable, args...)
        if err != nil {
                return "", fmt.Errorf("git commit-tree: %s", stderr)
        }
@@ -327,6 +343,12 @@ func (t *TemporaryUploadRepository) DiffIndex() (diff *models.Diff, err error) {
 
 // CheckAttribute checks the given attribute of the provided files
 func (t *TemporaryUploadRepository) CheckAttribute(attribute string, args ...string) (map[string]map[string]string, error) {
+       binVersion, err := git.BinVersion()
+       if err != nil {
+               log.Error("Error retrieving git version: %v", err)
+               return nil, err
+       }
+
        stdOut := new(bytes.Buffer)
        stdErr := new(bytes.Buffer)
 
@@ -334,7 +356,14 @@ func (t *TemporaryUploadRepository) CheckAttribute(attribute string, args ...str
        ctx, cancel := context.WithTimeout(context.Background(), timeout)
        defer cancel()
 
-       cmdArgs := []string{"check-attr", "-z", attribute, "--cached", "--"}
+       cmdArgs := []string{"check-attr", "-z", attribute}
+
+       // git check-attr --cached first appears in git 1.7.8
+       if version.Compare(binVersion, "1.7.8", ">=") {
+               cmdArgs = append(cmdArgs, "--cached")
+       }
+       cmdArgs = append(cmdArgs, "--")
+
        for _, arg := range args {
                if arg != "" {
                        cmdArgs = append(cmdArgs, arg)
@@ -352,7 +381,7 @@ func (t *TemporaryUploadRepository) CheckAttribute(attribute string, args ...str
        }
 
        pid := process.GetManager().Add(desc, cmd)
-       err := cmd.Wait()
+       err = cmd.Wait()
        process.GetManager().Remove(pid)
 
        if err != nil {
index 47fe89cf6309637d011be65c1fdbf261b49117b0..4a8aeec638a06e2d42d4387b2c38d72580be5ae5 100644 (file)
@@ -311,12 +311,6 @@ func CreateOrUpdateRepoFile(repo *models.Repository, doer *models.User, opts *Up
                }
        }
 
-       // Check there is no way this can return multiple infos
-       filename2attribute2info, err := t.CheckAttribute("filter", treePath)
-       if err != nil {
-               return nil, err
-       }
-
        content := opts.Content
        if bom {
                content = string(base.UTF8BOM) + content
@@ -339,16 +333,23 @@ func CreateOrUpdateRepoFile(repo *models.Repository, doer *models.User, opts *Up
        opts.Content = content
        var lfsMetaObject *models.LFSMetaObject
 
-       if setting.LFS.StartServer && filename2attribute2info[treePath] != nil && filename2attribute2info[treePath]["filter"] == "lfs" {
-               // OK so we are supposed to LFS this data!
-               oid, err := models.GenerateLFSOid(strings.NewReader(opts.Content))
+       if setting.LFS.StartServer {
+               // Check there is no way this can return multiple infos
+               filename2attribute2info, err := t.CheckAttribute("filter", treePath)
                if err != nil {
                        return nil, err
                }
-               lfsMetaObject = &models.LFSMetaObject{Oid: oid, Size: int64(len(opts.Content)), RepositoryID: repo.ID}
-               content = lfsMetaObject.Pointer()
-       }
 
+               if filename2attribute2info[treePath] != nil && filename2attribute2info[treePath]["filter"] == "lfs" {
+                       // OK so we are supposed to LFS this data!
+                       oid, err := models.GenerateLFSOid(strings.NewReader(opts.Content))
+                       if err != nil {
+                               return nil, err
+                       }
+                       lfsMetaObject = &models.LFSMetaObject{Oid: oid, Size: int64(len(opts.Content)), RepositoryID: repo.ID}
+                       content = lfsMetaObject.Pointer()
+               }
+       }
        // Add the object to the database
        objectHash, err := t.HashObject(strings.NewReader(content))
        if err != nil {
index f2ffec7ebcddb0f7f9292894f7b68e0883465b3c..202e66b89a1cab85661b4a7aa2f9cd42489fb423 100644 (file)
@@ -74,9 +74,12 @@ func UploadRepoFiles(repo *models.Repository, doer *models.User, opts *UploadRep
                infos[i] = uploadInfo{upload: upload}
        }
 
-       filename2attribute2info, err := t.CheckAttribute("filter", names...)
-       if err != nil {
-               return err
+       var filename2attribute2info map[string]map[string]string
+       if setting.LFS.StartServer {
+               filename2attribute2info, err = t.CheckAttribute("filter", names...)
+               if err != nil {
+                       return err
+               }
        }
 
        // Copy uploaded files into repository.
@@ -88,7 +91,7 @@ func UploadRepoFiles(repo *models.Repository, doer *models.User, opts *UploadRep
                defer file.Close()
 
                var objectHash string
-               if filename2attribute2info[uploadInfo.upload.Name] != nil && filename2attribute2info[uploadInfo.upload.Name]["filter"] == "lfs" {
+               if setting.LFS.StartServer && filename2attribute2info[uploadInfo.upload.Name] != nil && filename2attribute2info[uploadInfo.upload.Name]["filter"] == "lfs" {
                        // Handle LFS
                        // FIXME: Inefficient! this should probably happen in models.Upload
                        oid, err := models.GenerateLFSOid(file)