mirror of
				https://github.com/go-gitea/gitea
				synced 2025-11-04 13:28:25 +00:00 
			
		
		
		
	* 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
This commit is contained in:
		@@ -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)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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,21 +206,26 @@ 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())
 | 
			
		||||
 | 
			
		||||
		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())
 | 
			
		||||
 | 
			
		||||
			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,19 +243,24 @@ func mediaTest(t *testing.T, ctx *APITestContext, little, big, littleLFS, bigLFS
 | 
			
		||||
		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)
 | 
			
		||||
 | 
			
		||||
			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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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()))
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -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())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -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,7 +333,14 @@ 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" {
 | 
			
		||||
	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
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		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 {
 | 
			
		||||
@@ -348,7 +349,7 @@ func CreateOrUpdateRepoFile(repo *models.Repository, doer *models.User, opts *Up
 | 
			
		||||
			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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -74,10 +74,13 @@ func UploadRepoFiles(repo *models.Repository, doer *models.User, opts *UploadRep
 | 
			
		||||
		infos[i] = uploadInfo{upload: upload}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	filename2attribute2info, err := t.CheckAttribute("filter", names...)
 | 
			
		||||
	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.
 | 
			
		||||
	for i, uploadInfo := range infos {
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user