* clean git support for ver < 2.0 * fine tune tests for markup (which requires git module) * remove unnecessary comments * try to fix tests * try test again * use const for GitVersionRequired instead of var * try to fix integration test * Refactor CheckAttributeReader to make a *git.Repository version * update document for commit signing with Gitea's internal gitconfig * update document for commit signing with Gitea's internal gitconfig Co-authored-by: Andrew Thornton <art27@cantab.net> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>tags/v1.18.0-dev
@@ -308,6 +308,8 @@ func runHookPostReceive(c *cli.Context) error { | |||
ctx, cancel := installSignals() | |||
defer cancel() | |||
setup("hooks/post-receive.log", c.Bool("debug")) | |||
// First of all run update-server-info no matter what | |||
if _, _, err := git.NewCommand(ctx, "update-server-info").RunStdString(nil); err != nil { | |||
return fmt.Errorf("Failed to call 'git update-server-info': %v", err) | |||
@@ -318,8 +320,6 @@ func runHookPostReceive(c *cli.Context) error { | |||
return nil | |||
} | |||
setup("hooks/post-receive.log", c.Bool("debug")) | |||
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 { | |||
if setting.OnlyAllowPushIfGiteaEnvironmentSet { | |||
return fail(`Rejecting changes as Gitea environment not set. |
@@ -83,8 +83,7 @@ The first option to discuss is the `SIGNING_KEY`. There are three main | |||
options: | |||
- `none` - this prevents Gitea from signing any commits | |||
- `default` - Gitea will default to the key configured within | |||
`git config` | |||
- `default` - Gitea will default to the key configured within `git config` | |||
- `KEYID` - Gitea will sign commits with the gpg key with the ID | |||
`KEYID`. In this case you should provide a `SIGNING_NAME` and | |||
`SIGNING_EMAIL` to be displayed for this key. | |||
@@ -98,6 +97,12 @@ repositories, `SIGNING_KEY=default` could be used to provide different | |||
signing keys on a per-repository basis. However, this is clearly not an | |||
ideal UI and therefore subject to change. | |||
**Since 1.17**, Gitea runs git in its own home directory `[repository].ROOT` and uses its own config `{[repository].ROOT}/.gitconfig`. | |||
If you have your own customized git config for Gitea, you should set these configs in system git config (aka `/etc/gitconfig`) | |||
or the Gitea internal git config `{[repository].ROOT}/.gitconfig`. | |||
Related home files for git command (like `.gnupg`) should also be put in Gitea's git home directory `[repository].ROOT`. | |||
### `INITIAL_COMMIT` | |||
This option determines whether Gitea should sign the initial commit | |||
@@ -118,7 +123,7 @@ The possible values are: | |||
- `never`: Never sign | |||
- `pubkey`: Only sign if the user has a public key | |||
- `twofa`: Only sign if the user logs in with two factor authentication | |||
- `twofa`: Only sign if the user logs in with two-factor authentication | |||
- `parentsigned`: Only sign if the parent commit is signed. | |||
- `always`: Always sign | |||
@@ -132,7 +137,7 @@ editor or API CRUD actions. The possible values are: | |||
- `never`: Never sign | |||
- `pubkey`: Only sign if the user has a public key | |||
- `twofa`: Only sign if the user logs in with two factor authentication | |||
- `twofa`: Only sign if the user logs in with two-factor authentication | |||
- `parentsigned`: Only sign if the parent commit is signed. | |||
- `always`: Always sign | |||
@@ -146,7 +151,7 @@ The possible options are: | |||
- `never`: Never sign | |||
- `pubkey`: Only sign if the user has a public key | |||
- `twofa`: Only sign if the user logs in with two factor authentication | |||
- `twofa`: Only sign if the user logs in with two-factor authentication | |||
- `basesigned`: Only sign if the parent commit in the base repo is signed. | |||
- `headsigned`: Only sign if the head commit in the head branch is signed. | |||
- `commitssigned`: Only sign if all the commits in the head branch to the merge point are signed. |
@@ -174,7 +174,12 @@ func initIntegrationTest() { | |||
setting.LoadForTest() | |||
setting.Repository.DefaultBranch = "master" // many test code still assume that default branch is called "master" | |||
_ = util.RemoveAll(repo_module.LocalCopyPath()) | |||
if err := git.InitOnceWithSync(context.Background()); err != nil { | |||
log.Fatal("git.InitOnceWithSync: %v", err) | |||
} | |||
git.CheckLFSVersion() | |||
setting.InitDBConfig() | |||
if err := storage.Init(); err != nil { | |||
fmt.Printf("Init storage failed: %v", err) | |||
@@ -275,7 +280,7 @@ func prepareTestEnv(t testing.TB, skip ...int) func() { | |||
assert.NoError(t, unittest.LoadFixtures()) | |||
assert.NoError(t, util.RemoveAll(setting.RepoRootPath)) | |||
assert.NoError(t, unittest.CopyDir(path.Join(filepath.Dir(setting.AppPath), "integrations/gitea-repositories-meta"), setting.RepoRootPath)) | |||
assert.NoError(t, git.InitOnceWithSync(context.Background())) | |||
assert.NoError(t, git.InitOnceWithSync(context.Background())) // the gitconfig has been removed above, so sync the gitconfig again | |||
ownerDirs, err := os.ReadDir(setting.RepoRootPath) | |||
if err != nil { | |||
assert.NoError(t, err, "unable to read the new repo root: %v\n", err) | |||
@@ -576,7 +581,7 @@ func resetFixtures(t *testing.T) { | |||
assert.NoError(t, unittest.LoadFixtures()) | |||
assert.NoError(t, util.RemoveAll(setting.RepoRootPath)) | |||
assert.NoError(t, unittest.CopyDir(path.Join(filepath.Dir(setting.AppPath), "integrations/gitea-repositories-meta"), setting.RepoRootPath)) | |||
assert.NoError(t, git.InitOnceWithSync(context.Background())) | |||
assert.NoError(t, git.InitOnceWithSync(context.Background())) // the gitconfig has been removed above, so sync the gitconfig again | |||
ownerDirs, err := os.ReadDir(setting.RepoRootPath) | |||
if err != nil { | |||
assert.NoError(t, err, "unable to read the new repo root: %v\n", err) |
@@ -62,7 +62,6 @@ func initMigrationTest(t *testing.T) func() { | |||
assert.True(t, len(setting.RepoRootPath) != 0) | |||
assert.NoError(t, util.RemoveAll(setting.RepoRootPath)) | |||
assert.NoError(t, unittest.CopyDir(path.Join(filepath.Dir(setting.AppPath), "integrations/gitea-repositories-meta"), setting.RepoRootPath)) | |||
assert.NoError(t, git.InitOnceWithSync(context.Background())) | |||
ownerDirs, err := os.ReadDir(setting.RepoRootPath) | |||
if err != nil { | |||
assert.NoError(t, err, "unable to read the new repo root: %v\n", err) | |||
@@ -83,6 +82,7 @@ func initMigrationTest(t *testing.T) func() { | |||
} | |||
} | |||
assert.NoError(t, git.InitOnceWithSync(context.Background())) | |||
git.CheckLFSVersion() | |||
setting.InitDBConfig() | |||
setting.NewLogServices(true) |
@@ -66,6 +66,10 @@ func TestMain(m *testing.M) { | |||
setting.SetCustomPathAndConf("", "", "") | |||
setting.LoadForTest() | |||
if err = git.InitOnceWithSync(context.Background()); err != nil { | |||
fmt.Printf("Unable to InitOnceWithSync: %v\n", err) | |||
os.Exit(1) | |||
} | |||
git.CheckLFSVersion() | |||
setting.InitDBConfig() | |||
setting.NewLogServices(true) | |||
@@ -203,7 +207,7 @@ func prepareTestEnv(t *testing.T, skip int, syncModels ...interface{}) (*xorm.En | |||
deferFn := PrintCurrentTest(t, ourSkip) | |||
assert.NoError(t, os.RemoveAll(setting.RepoRootPath)) | |||
assert.NoError(t, unittest.CopyDir(path.Join(filepath.Dir(setting.AppPath), "integrations/gitea-repositories-meta"), setting.RepoRootPath)) | |||
assert.NoError(t, git.InitOnceWithSync(context.Background())) | |||
assert.NoError(t, git.InitOnceWithSync(context.Background())) // the gitconfig has been removed above, so sync the gitconfig again | |||
ownerDirs, err := os.ReadDir(setting.RepoRootPath) | |||
if err != nil { | |||
assert.NoError(t, err, "unable to read the new repo root: %v\n", err) |
@@ -117,9 +117,11 @@ func MainTest(m *testing.M, testOpts *TestOptions) { | |||
if err = CopyDir(filepath.Join(testOpts.GiteaRootPath, "integrations", "gitea-repositories-meta"), setting.RepoRootPath); err != nil { | |||
fatalTestError("util.CopyDir: %v\n", err) | |||
} | |||
if err = git.InitOnceWithSync(context.Background()); err != nil { | |||
fatalTestError("git.Init: %v\n", err) | |||
} | |||
git.CheckLFSVersion() | |||
ownerDirs, err := os.ReadDir(setting.RepoRootPath) | |||
if err != nil { | |||
@@ -202,7 +204,7 @@ func PrepareTestEnv(t testing.TB) { | |||
assert.NoError(t, util.RemoveAll(setting.RepoRootPath)) | |||
metaPath := filepath.Join(giteaRoot, "integrations", "gitea-repositories-meta") | |||
assert.NoError(t, CopyDir(metaPath, setting.RepoRootPath)) | |||
assert.NoError(t, git.InitOnceWithSync(context.Background())) | |||
assert.NoError(t, git.InitOnceWithSync(context.Background())) // the gitconfig has been removed above, so sync the gitconfig again | |||
ownerDirs, err := os.ReadDir(setting.RepoRootPath) | |||
assert.NoError(t, err) |
@@ -206,26 +206,17 @@ func (c *Commit) HasPreviousCommit(commitHash SHA1) (bool, error) { | |||
return false, nil | |||
} | |||
if err := CheckGitVersionAtLeast("1.8"); err == nil { | |||
_, _, err := NewCommand(c.repo.Ctx, "merge-base", "--is-ancestor", that, this).RunStdString(&RunOpts{Dir: c.repo.Path}) | |||
if err == nil { | |||
return true, nil | |||
_, _, err := NewCommand(c.repo.Ctx, "merge-base", "--is-ancestor", that, this).RunStdString(&RunOpts{Dir: c.repo.Path}) | |||
if err == nil { | |||
return true, nil | |||
} | |||
var exitError *exec.ExitError | |||
if errors.As(err, &exitError) { | |||
if exitError.ProcessState.ExitCode() == 1 && len(exitError.Stderr) == 0 { | |||
return false, nil | |||
} | |||
var exitError *exec.ExitError | |||
if errors.As(err, &exitError) { | |||
if exitError.ProcessState.ExitCode() == 1 && len(exitError.Stderr) == 0 { | |||
return false, nil | |||
} | |||
} | |||
return false, err | |||
} | |||
result, _, err := NewCommand(c.repo.Ctx, "rev-list", "--ancestry-path", "-n1", that+".."+this, "--").RunStdString(&RunOpts{Dir: c.repo.Path}) | |||
if err != nil { | |||
return false, err | |||
} | |||
return len(strings.TrimSpace(result)) > 0, nil | |||
return false, err | |||
} | |||
// CommitsBeforeLimit returns num commits before current revision |
@@ -7,10 +7,10 @@ package git | |||
import ( | |||
"context" | |||
"errors" | |||
"fmt" | |||
"os" | |||
"os/exec" | |||
"path/filepath" | |||
"runtime" | |||
"strings" | |||
"sync" | |||
@@ -22,20 +22,16 @@ import ( | |||
"github.com/hashicorp/go-version" | |||
) | |||
var ( | |||
// GitVersionRequired is the minimum Git version required | |||
// At the moment, all code for git 1.x are not changed, if some users want to test with old git client | |||
// or bypass the check, they still have a chance to edit this variable manually. | |||
// If everything works fine, the code for git 1.x could be removed in a separate PR before 1.17 frozen. | |||
GitVersionRequired = "2.0.0" | |||
// GitVersionRequired is the minimum Git version required | |||
const GitVersionRequired = "2.0.0" | |||
var ( | |||
// GitExecutable is the command name of git | |||
// Could be updated to an absolute path while initialization | |||
GitExecutable = "git" | |||
// DefaultContext is the default context to run git commands in | |||
// will be overwritten by InitXxx with HammerContext | |||
DefaultContext = context.Background() | |||
// DefaultContext is the default context to run git commands in, must be initialized by git.InitXxx | |||
DefaultContext context.Context | |||
// SupportProcReceive version >= 2.29.0 | |||
SupportProcReceive bool | |||
@@ -128,36 +124,43 @@ func VersionInfo() string { | |||
return fmt.Sprintf(format, args...) | |||
} | |||
func checkInit() error { | |||
if setting.RepoRootPath == "" { | |||
return errors.New("can not init Git's HomeDir (RepoRootPath is empty), the setting and git modules are not initialized correctly") | |||
} | |||
if DefaultContext != nil { | |||
log.Warn("git module has been initialized already, duplicate init should be fixed") | |||
} | |||
return nil | |||
} | |||
// HomeDir is the home dir for git to store the global config file used by Gitea internally | |||
func HomeDir() string { | |||
if setting.RepoRootPath == "" { | |||
// TODO: now, some unit test code call the git module directly without initialization, which is incorrect. | |||
// at the moment, we just use a temp HomeDir to prevent from conflicting with user's git config | |||
// in the future, the git module should be initialized first before use. | |||
tmpHomeDir := filepath.Join(os.TempDir(), "gitea-temp-home") | |||
log.Error("Git's HomeDir is empty (RepoRootPath is empty), the git module is not initialized correctly, using a temp HomeDir (%s) temporarily", tmpHomeDir) | |||
return tmpHomeDir | |||
// strict check, make sure the git module is initialized correctly. | |||
// attention: when the git module is called in gitea sub-command (serv/hook), the log module is not able to show messages to users. | |||
// for example: if there is gitea git hook code calling git.NewCommand before git.InitXxx, the integration test won't show the real failure reasons. | |||
log.Fatal("can not get Git's HomeDir (RepoRootPath is empty), the setting and git modules are not initialized correctly") | |||
return "" | |||
} | |||
return setting.RepoRootPath | |||
} | |||
// InitSimple initializes git module with a very simple step, no config changes, no global command arguments. | |||
// This method doesn't change anything to filesystem. At the moment, it is only used by "git serv" sub-command, no data-race | |||
// However, in integration test, the sub-command function may be called in the current process, so the InitSimple would be called multiple times, too | |||
func InitSimple(ctx context.Context) error { | |||
if err := checkInit(); err != nil { | |||
return err | |||
} | |||
DefaultContext = ctx | |||
if setting.Git.Timeout.Default > 0 { | |||
defaultCommandExecutionTimeout = time.Duration(setting.Git.Timeout.Default) * time.Second | |||
} | |||
if err := SetExecutablePath(setting.Git.Path); err != nil { | |||
return err | |||
} | |||
// force cleanup args | |||
globalCommandArgs = []string{} | |||
return nil | |||
return SetExecutablePath(setting.Git.Path) | |||
} | |||
var initOnce sync.Once | |||
@@ -166,6 +169,10 @@ var initOnce sync.Once | |||
// This method will update the global variables ONLY ONCE (just like git.CheckLFSVersion -- which is not ideal too), | |||
// otherwise there will be data-race problem at the moment. | |||
func InitOnceWithSync(ctx context.Context) (err error) { | |||
if err = checkInit(); err != nil { | |||
return err | |||
} | |||
initOnce.Do(func() { | |||
err = InitSimple(ctx) | |||
if err != nil { |
@@ -30,10 +30,10 @@ type CheckAttributeOpts struct { | |||
func (repo *Repository) CheckAttribute(opts CheckAttributeOpts) (map[string]map[string]string, error) { | |||
env := []string{} | |||
if len(opts.IndexFile) > 0 && CheckGitVersionAtLeast("1.7.8") == nil { | |||
if len(opts.IndexFile) > 0 { | |||
env = append(env, "GIT_INDEX_FILE="+opts.IndexFile) | |||
} | |||
if len(opts.WorkTree) > 0 && CheckGitVersionAtLeast("1.7.8") == nil { | |||
if len(opts.WorkTree) > 0 { | |||
env = append(env, "GIT_WORK_TREE="+opts.WorkTree) | |||
} | |||
@@ -56,8 +56,7 @@ func (repo *Repository) CheckAttribute(opts CheckAttributeOpts) (map[string]map[ | |||
} | |||
} | |||
// git check-attr --cached first appears in git 1.7.8 | |||
if opts.CachedOnly && CheckGitVersionAtLeast("1.7.8") == nil { | |||
if opts.CachedOnly { | |||
cmdArgs = append(cmdArgs, "--cached") | |||
} | |||
@@ -125,12 +124,12 @@ type CheckAttributeReader struct { | |||
func (c *CheckAttributeReader) Init(ctx context.Context) error { | |||
cmdArgs := []string{"check-attr", "--stdin", "-z"} | |||
if len(c.IndexFile) > 0 && CheckGitVersionAtLeast("1.7.8") == nil { | |||
if len(c.IndexFile) > 0 { | |||
cmdArgs = append(cmdArgs, "--cached") | |||
c.env = append(c.env, "GIT_INDEX_FILE="+c.IndexFile) | |||
} | |||
if len(c.WorkTree) > 0 && CheckGitVersionAtLeast("1.7.8") == nil { | |||
if len(c.WorkTree) > 0 { | |||
c.env = append(c.env, "GIT_WORK_TREE="+c.WorkTree) | |||
} | |||
@@ -160,17 +159,10 @@ func (c *CheckAttributeReader) Init(ctx context.Context) error { | |||
return err | |||
} | |||
if CheckGitVersionAtLeast("1.8.5") == nil { | |||
lw := new(nulSeparatedAttributeWriter) | |||
lw.attributes = make(chan attributeTriple, 5) | |||
lw.closed = make(chan struct{}) | |||
c.stdOut = lw | |||
} else { | |||
lw := new(lineSeparatedAttributeWriter) | |||
lw.attributes = make(chan attributeTriple, 5) | |||
lw.closed = make(chan struct{}) | |||
c.stdOut = lw | |||
} | |||
lw := new(nulSeparatedAttributeWriter) | |||
lw.attributes = make(chan attributeTriple, 5) | |||
lw.closed = make(chan struct{}) | |||
c.stdOut = lw | |||
return nil | |||
} | |||
@@ -400,3 +392,37 @@ func (wr *lineSeparatedAttributeWriter) Close() error { | |||
close(wr.closed) | |||
return nil | |||
} | |||
// Create a check attribute reader for the current repository and provided commit ID | |||
func (repo *Repository) CheckAttributeReader(commitID string) (*CheckAttributeReader, context.CancelFunc) { | |||
indexFilename, worktree, deleteTemporaryFile, err := repo.ReadTreeToTemporaryIndex(commitID) | |||
if err != nil { | |||
return nil, func() {} | |||
} | |||
checker := &CheckAttributeReader{ | |||
Attributes: []string{"linguist-vendored", "linguist-generated", "linguist-language", "gitlab-language"}, | |||
Repo: repo, | |||
IndexFile: indexFilename, | |||
WorkTree: worktree, | |||
} | |||
ctx, cancel := context.WithCancel(repo.Ctx) | |||
if err := checker.Init(ctx); err != nil { | |||
log.Error("Unable to open checker for %s. Error: %v", commitID, err) | |||
} else { | |||
go func() { | |||
err := checker.Run() | |||
if err != nil && err != ctx.Err() { | |||
log.Error("Unable to open checker for %s. Error: %v", commitID, err) | |||
} | |||
cancel() | |||
}() | |||
} | |||
deferable := func() { | |||
_ = checker.Close() | |||
cancel() | |||
deleteTemporaryFile() | |||
} | |||
return checker, deferable | |||
} |
@@ -255,13 +255,7 @@ func (repo *Repository) GetDiff(base, head string, w io.Writer) error { | |||
// GetDiffBinary generates and returns patch data between given revisions, including binary diffs. | |||
func (repo *Repository) GetDiffBinary(base, head string, w io.Writer) error { | |||
if CheckGitVersionAtLeast("1.7.7") == nil { | |||
return NewCommand(repo.Ctx, "diff", "-p", "--binary", "--histogram", base, head).Run(&RunOpts{ | |||
Dir: repo.Path, | |||
Stdout: w, | |||
}) | |||
} | |||
return NewCommand(repo.Ctx, "diff", "-p", "--binary", "--patience", base, head).Run(&RunOpts{ | |||
return NewCommand(repo.Ctx, "diff", "-p", "--binary", "--histogram", base, head).Run(&RunOpts{ | |||
Dir: repo.Path, | |||
Stdout: w, | |||
}) |
@@ -8,12 +8,10 @@ package git | |||
import ( | |||
"bytes" | |||
"context" | |||
"io" | |||
"strings" | |||
"code.gitea.io/gitea/modules/analyze" | |||
"code.gitea.io/gitea/modules/log" | |||
"github.com/go-enry/go-enry/v2" | |||
"github.com/go-git/go-git/v5" | |||
@@ -43,33 +41,8 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err | |||
return nil, err | |||
} | |||
var checker *CheckAttributeReader | |||
if CheckGitVersionAtLeast("1.7.8") == nil { | |||
indexFilename, workTree, deleteTemporaryFile, err := repo.ReadTreeToTemporaryIndex(commitID) | |||
if err == nil { | |||
defer deleteTemporaryFile() | |||
checker = &CheckAttributeReader{ | |||
Attributes: []string{"linguist-vendored", "linguist-generated", "linguist-language", "gitlab-language"}, | |||
Repo: repo, | |||
IndexFile: indexFilename, | |||
WorkTree: workTree, | |||
} | |||
ctx, cancel := context.WithCancel(DefaultContext) | |||
if err := checker.Init(ctx); err != nil { | |||
log.Error("Unable to open checker for %s. Error: %v", commitID, err) | |||
} else { | |||
go func() { | |||
err = checker.Run() | |||
if err != nil { | |||
log.Error("Unable to open checker for %s. Error: %v", commitID, err) | |||
cancel() | |||
} | |||
}() | |||
} | |||
defer cancel() | |||
} | |||
} | |||
checker, deferable := repo.CheckAttributeReader(commitID) | |||
defer deferable() | |||
sizes := make(map[string]int64) | |||
err = tree.Files().ForEach(func(f *object.File) error { |
@@ -9,7 +9,6 @@ package git | |||
import ( | |||
"bufio" | |||
"bytes" | |||
"context" | |||
"io" | |||
"math" | |||
"strings" | |||
@@ -63,36 +62,8 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err | |||
return nil, err | |||
} | |||
var checker *CheckAttributeReader | |||
if CheckGitVersionAtLeast("1.7.8") == nil { | |||
indexFilename, worktree, deleteTemporaryFile, err := repo.ReadTreeToTemporaryIndex(commitID) | |||
if err == nil { | |||
defer deleteTemporaryFile() | |||
checker = &CheckAttributeReader{ | |||
Attributes: []string{"linguist-vendored", "linguist-generated", "linguist-language", "gitlab-language"}, | |||
Repo: repo, | |||
IndexFile: indexFilename, | |||
WorkTree: worktree, | |||
} | |||
ctx, cancel := context.WithCancel(repo.Ctx) | |||
if err := checker.Init(ctx); err != nil { | |||
log.Error("Unable to open checker for %s. Error: %v", commitID, err) | |||
} else { | |||
go func() { | |||
err = checker.Run() | |||
if err != nil { | |||
log.Error("Unable to open checker for %s. Error: %v", commitID, err) | |||
cancel() | |||
} | |||
}() | |||
} | |||
defer func() { | |||
_ = checker.Close() | |||
cancel() | |||
}() | |||
} | |||
} | |||
checker, deferable := repo.CheckAttributeReader(commitID) | |||
defer deferable() | |||
contentBuf := bytes.Buffer{} | |||
var content []byte |
@@ -45,11 +45,11 @@ func (repo *Repository) CommitTree(author, committer *Signature, tree *Tree, opt | |||
_, _ = messageBytes.WriteString(opts.Message) | |||
_, _ = messageBytes.WriteString("\n") | |||
if CheckGitVersionAtLeast("1.7.9") == nil && (opts.KeyID != "" || opts.AlwaysSign) { | |||
if opts.KeyID != "" || opts.AlwaysSign { | |||
cmd.AddArguments(fmt.Sprintf("-S%s", opts.KeyID)) | |||
} | |||
if CheckGitVersionAtLeast("2.0.0") == nil && opts.NoGPGSign { | |||
if opts.NoGPGSign { | |||
cmd.AddArguments("--no-gpg-sign") | |||
} | |||
@@ -5,12 +5,14 @@ | |||
package markup_test | |||
import ( | |||
"context" | |||
"io" | |||
"strings" | |||
"testing" | |||
"code.gitea.io/gitea/modules/emoji" | |||
"code.gitea.io/gitea/modules/git" | |||
"code.gitea.io/gitea/modules/log" | |||
. "code.gitea.io/gitea/modules/markup" | |||
"code.gitea.io/gitea/modules/markup/markdown" | |||
"code.gitea.io/gitea/modules/setting" | |||
@@ -25,6 +27,13 @@ var localMetas = map[string]string{ | |||
"repoPath": "../../integrations/gitea-repositories-meta/user13/repo11.git/", | |||
} | |||
func TestMain(m *testing.M) { | |||
setting.LoadAllowEmpty() | |||
if err := git.InitSimple(context.Background()); err != nil { | |||
log.Fatal("git init failed, err: %v", err) | |||
} | |||
} | |||
func TestRender_Commits(t *testing.T) { | |||
setting.AppURL = TestAppURL | |||
test := func(input, expected string) { |
@@ -5,6 +5,7 @@ | |||
package markdown_test | |||
import ( | |||
"context" | |||
"strings" | |||
"testing" | |||
@@ -31,6 +32,13 @@ var localMetas = map[string]string{ | |||
"repoPath": "../../../integrations/gitea-repositories-meta/user13/repo11.git/", | |||
} | |||
func TestMain(m *testing.M) { | |||
setting.LoadAllowEmpty() | |||
if err := git.InitSimple(context.Background()); err != nil { | |||
log.Fatal("git init failed, err: %v", err) | |||
} | |||
} | |||
func TestRender_StandardLinks(t *testing.T) { | |||
setting.AppURL = AppURL | |||
setting.AppSubURL = AppSubURL |
@@ -323,19 +323,17 @@ func initRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Reposi | |||
"-m", "Initial commit", | |||
} | |||
if git.CheckGitVersionAtLeast("1.7.9") == nil { | |||
sign, keyID, signer, _ := asymkey_service.SignInitialCommit(ctx, tmpPath, u) | |||
if sign { | |||
args = append(args, "-S"+keyID) | |||
if repo.GetTrustModel() == repo_model.CommitterTrustModel || repo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel { | |||
// need to set the committer to the KeyID owner | |||
committerName = signer.Name | |||
committerEmail = signer.Email | |||
} | |||
} else if git.CheckGitVersionAtLeast("2.0.0") == nil { | |||
args = append(args, "--no-gpg-sign") | |||
sign, keyID, signer, _ := asymkey_service.SignInitialCommit(ctx, tmpPath, u) | |||
if sign { | |||
args = append(args, "-S"+keyID) | |||
if repo.GetTrustModel() == repo_model.CommitterTrustModel || repo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel { | |||
// need to set the committer to the KeyID owner | |||
committerName = signer.Name | |||
committerEmail = signer.Email | |||
} | |||
} else { | |||
args = append(args, "--no-gpg-sign") | |||
} | |||
env = append(env, |
@@ -1417,37 +1417,8 @@ func GetDiff(gitRepo *git.Repository, opts *DiffOptions, files ...string) (*Diff | |||
} | |||
diff.Start = opts.SkipTo | |||
var checker *git.CheckAttributeReader | |||
if git.CheckGitVersionAtLeast("1.7.8") == nil { | |||
indexFilename, worktree, deleteTemporaryFile, err := gitRepo.ReadTreeToTemporaryIndex(opts.AfterCommitID) | |||
if err == nil { | |||
defer deleteTemporaryFile() | |||
checker = &git.CheckAttributeReader{ | |||
Attributes: []string{"linguist-vendored", "linguist-generated", "linguist-language", "gitlab-language"}, | |||
Repo: gitRepo, | |||
IndexFile: indexFilename, | |||
WorkTree: worktree, | |||
} | |||
ctx, cancel := context.WithCancel(gitRepo.Ctx) | |||
if err := checker.Init(ctx); err != nil { | |||
log.Error("Unable to open checker for %s. Error: %v", opts.AfterCommitID, err) | |||
} else { | |||
go func() { | |||
err := checker.Run() | |||
if err != nil && err != ctx.Err() { | |||
log.Error("Unable to open checker for %s. Error: %v", opts.AfterCommitID, err) | |||
} | |||
cancel() | |||
}() | |||
} | |||
defer func() { | |||
_ = checker.Close() | |||
cancel() | |||
}() | |||
} | |||
} | |||
checker, deferable := gitRepo.CheckAttributeReader(opts.AfterCommitID) | |||
defer deferable() | |||
for _, diffFile := range diff.Files { | |||
@@ -276,15 +276,8 @@ func rawMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_mode | |||
return "", fmt.Errorf("Unable to write .git/info/sparse-checkout file in tmpBasePath: %v", err) | |||
} | |||
var gitConfigCommand func() *git.Command | |||
if git.CheckGitVersionAtLeast("1.8.0") == nil { | |||
gitConfigCommand = func() *git.Command { | |||
return git.NewCommand(ctx, "config", "--local") | |||
} | |||
} else { | |||
gitConfigCommand = func() *git.Command { | |||
return git.NewCommand(ctx, "config") | |||
} | |||
gitConfigCommand := func() *git.Command { | |||
return git.NewCommand(ctx, "config", "--local") | |||
} | |||
// Switch off LFS process (set required, clean and smudge here also) | |||
@@ -366,16 +359,14 @@ func rawMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_mode | |||
// Determine if we should sign | |||
signArg := "" | |||
if git.CheckGitVersionAtLeast("1.7.9") == nil { | |||
sign, keyID, signer, _ := asymkey_service.SignMerge(ctx, pr, doer, tmpBasePath, "HEAD", trackingBranch) | |||
if sign { | |||
signArg = "-S" + keyID | |||
if pr.BaseRepo.GetTrustModel() == repo_model.CommitterTrustModel || pr.BaseRepo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel { | |||
committer = signer | |||
} | |||
} else if git.CheckGitVersionAtLeast("2.0.0") == nil { | |||
signArg = "--no-gpg-sign" | |||
sign, keyID, signer, _ := asymkey_service.SignMerge(ctx, pr, doer, tmpBasePath, "HEAD", trackingBranch) | |||
if sign { | |||
signArg = "-S" + keyID | |||
if pr.BaseRepo.GetTrustModel() == repo_model.CommitterTrustModel || pr.BaseRepo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel { | |||
committer = signer | |||
} | |||
} else { | |||
signArg = "--no-gpg-sign" | |||
} | |||
commitTimeStr := time.Now().Format(time.RFC3339) |
@@ -248,34 +248,31 @@ func (t *TemporaryUploadRepository) CommitTreeWithDate(parent string, author, co | |||
args = []string{"commit-tree", treeHash} | |||
} | |||
// Determine if we should sign | |||
if git.CheckGitVersionAtLeast("1.7.9") == nil { | |||
var sign bool | |||
var keyID string | |||
var signer *git.Signature | |||
if parent != "" { | |||
sign, keyID, signer, _ = asymkey_service.SignCRUDAction(t.ctx, t.repo.RepoPath(), author, t.basePath, parent) | |||
} else { | |||
sign, keyID, signer, _ = asymkey_service.SignInitialCommit(t.ctx, t.repo.RepoPath(), author) | |||
} | |||
if sign { | |||
args = append(args, "-S"+keyID) | |||
if t.repo.GetTrustModel() == repo_model.CommitterTrustModel || t.repo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel { | |||
if committerSig.Name != authorSig.Name || committerSig.Email != authorSig.Email { | |||
// Add trailers | |||
_, _ = messageBytes.WriteString("\n") | |||
_, _ = messageBytes.WriteString("Co-authored-by: ") | |||
_, _ = messageBytes.WriteString(committerSig.String()) | |||
_, _ = messageBytes.WriteString("\n") | |||
_, _ = messageBytes.WriteString("Co-committed-by: ") | |||
_, _ = messageBytes.WriteString(committerSig.String()) | |||
_, _ = messageBytes.WriteString("\n") | |||
} | |||
committerSig = signer | |||
var sign bool | |||
var keyID string | |||
var signer *git.Signature | |||
if parent != "" { | |||
sign, keyID, signer, _ = asymkey_service.SignCRUDAction(t.ctx, t.repo.RepoPath(), author, t.basePath, parent) | |||
} else { | |||
sign, keyID, signer, _ = asymkey_service.SignInitialCommit(t.ctx, t.repo.RepoPath(), author) | |||
} | |||
if sign { | |||
args = append(args, "-S"+keyID) | |||
if t.repo.GetTrustModel() == repo_model.CommitterTrustModel || t.repo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel { | |||
if committerSig.Name != authorSig.Name || committerSig.Email != authorSig.Email { | |||
// Add trailers | |||
_, _ = messageBytes.WriteString("\n") | |||
_, _ = messageBytes.WriteString("Co-authored-by: ") | |||
_, _ = messageBytes.WriteString(committerSig.String()) | |||
_, _ = messageBytes.WriteString("\n") | |||
_, _ = messageBytes.WriteString("Co-committed-by: ") | |||
_, _ = messageBytes.WriteString(committerSig.String()) | |||
_, _ = messageBytes.WriteString("\n") | |||
} | |||
} else if git.CheckGitVersionAtLeast("2.0.0") == nil { | |||
args = append(args, "--no-gpg-sign") | |||
committerSig = signer | |||
} | |||
} else { | |||
args = append(args, "--no-gpg-sign") | |||
} | |||
if signoff { |