Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove legacy git code (ver < 2.0), fine tune markup tests #19930

Merged
merged 21 commits into from
Jun 16, 2022
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
db0d7a1
clean git support for ver < 2.0
wxiaoguang Jun 10, 2022
d01ca3a
fine tune tests for markup (which requires git module)
wxiaoguang Jun 10, 2022
5e8c6b4
remove unnecessary comments
wxiaoguang Jun 10, 2022
e8fad37
try to fix tests
wxiaoguang Jun 10, 2022
9f89b2f
Merge branch 'main' into fix-git-legacy
wxiaoguang Jun 11, 2022
b32101f
try test again
wxiaoguang Jun 11, 2022
187a27f
use const for GitVersionRequired instead of var
wxiaoguang Jun 11, 2022
09e29f4
try to fix integration test
wxiaoguang Jun 11, 2022
94b2386
Merge branch 'main' into fix-git-legacy
wxiaoguang Jun 11, 2022
6d87ea8
Merge branch 'main' into fix-git-legacy
wxiaoguang Jun 13, 2022
334e5d2
Merge branch 'main' into fix-git-legacy
wxiaoguang Jun 13, 2022
038929e
Refactor CheckAttributeReader to make a *git.Repository version
zeripath Jun 13, 2022
a8f2999
Merge pull request #6 from zeripath/fix-git-legacy
wxiaoguang Jun 14, 2022
64959f0
update document for commit signing with Gitea's internal gitconfig
wxiaoguang Jun 14, 2022
8a2b4a8
Merge branch 'main' into fix-git-legacy
wxiaoguang Jun 14, 2022
e4dcba6
update document for commit signing with Gitea's internal gitconfig
wxiaoguang Jun 14, 2022
c551d8d
Merge branch 'main' into fix-git-legacy
wxiaoguang Jun 15, 2022
30ae9f3
Merge branch 'main' into fix-git-legacy
wxiaoguang Jun 15, 2022
4a3aa85
Merge branch 'main' into fix-git-legacy
lunny Jun 16, 2022
faed560
Merge branch 'main' into fix-git-legacy
lunny Jun 16, 2022
375eaba
Merge branch 'main' into fix-git-legacy
lunny Jun 16, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cmd/hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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.
Expand Down
15 changes: 10 additions & 5 deletions docs/content/doc/advanced/signing.en-us.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand All @@ -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

Expand All @@ -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

Expand All @@ -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.
Expand Down
9 changes: 7 additions & 2 deletions integrations/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion integrations/migration-test/migration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -83,6 +82,7 @@ func initMigrationTest(t *testing.T) func() {
}
}

assert.NoError(t, git.InitOnceWithSync(context.Background()))
git.CheckLFSVersion()
setting.InitDBConfig()
setting.NewLogServices(true)
Expand Down
6 changes: 5 additions & 1 deletion models/migrations/migrations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
4 changes: 3 additions & 1 deletion models/unittest/testdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
Expand Down
27 changes: 9 additions & 18 deletions modules/git/commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
55 changes: 31 additions & 24 deletions modules/git/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ package git

import (
"context"
"errors"
"fmt"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"sync"
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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 {
Expand Down
60 changes: 43 additions & 17 deletions modules/git/repo_attribute.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand All @@ -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")
}

Expand Down Expand Up @@ -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)
}

Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -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
}
Loading