mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-29 18:06:38 +01:00 
			
		
		
		
	Make sure git version&feature are always prepared (#30877)
Otherwise there would be more similar issues like #29287
This commit is contained in:
		| @@ -220,10 +220,7 @@ Gitea or set your environment appropriately.`, "") | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	supportProcReceive := false | 	supportProcReceive := git.DefaultFeatures().SupportProcReceive | ||||||
| 	if git.CheckGitVersionAtLeast("2.29") == nil { |  | ||||||
| 		supportProcReceive = true |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	for scanner.Scan() { | 	for scanner.Scan() { | ||||||
| 		// TODO: support news feeds for wiki | 		// TODO: support news feeds for wiki | ||||||
| @@ -497,7 +494,7 @@ Gitea or set your environment appropriately.`, "") | |||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if git.CheckGitVersionAtLeast("2.29") != nil { | 	if !git.DefaultFeatures().SupportProcReceive { | ||||||
| 		return fail(ctx, "No proc-receive support", "current git version doesn't support proc-receive.") | 		return fail(ctx, "No proc-receive support", "current git version doesn't support proc-receive.") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -178,7 +178,7 @@ func runServ(c *cli.Context) error { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(words) < 2 { | 	if len(words) < 2 { | ||||||
| 		if git.CheckGitVersionAtLeast("2.29") == nil { | 		if git.DefaultFeatures().SupportProcReceive { | ||||||
| 			// for AGit Flow | 			// for AGit Flow | ||||||
| 			if cmd == "ssh_info" { | 			if cmd == "ssh_info" { | ||||||
| 				fmt.Print(`{"type":"gitea","version":1}`) | 				fmt.Print(`{"type":"gitea","version":1}`) | ||||||
|   | |||||||
| @@ -132,7 +132,7 @@ func (r *BlameReader) Close() error { | |||||||
| // CreateBlameReader creates reader for given repository, commit and file | // CreateBlameReader creates reader for given repository, commit and file | ||||||
| func CreateBlameReader(ctx context.Context, objectFormat ObjectFormat, repoPath string, commit *Commit, file string, bypassBlameIgnore bool) (*BlameReader, error) { | func CreateBlameReader(ctx context.Context, objectFormat ObjectFormat, repoPath string, commit *Commit, file string, bypassBlameIgnore bool) (*BlameReader, error) { | ||||||
| 	var ignoreRevsFile *string | 	var ignoreRevsFile *string | ||||||
| 	if CheckGitVersionAtLeast("2.23") == nil && !bypassBlameIgnore { | 	if DefaultFeatures().CheckVersionAtLeast("2.23") && !bypassBlameIgnore { | ||||||
| 		ignoreRevsFile = tryCreateBlameIgnoreRevsFile(commit) | 		ignoreRevsFile = tryCreateBlameIgnoreRevsFile(commit) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -423,7 +423,7 @@ func (c *Commit) GetSubModule(entryname string) (*SubModule, error) { | |||||||
| // GetBranchName gets the closest branch name (as returned by 'git name-rev --name-only') | // GetBranchName gets the closest branch name (as returned by 'git name-rev --name-only') | ||||||
| func (c *Commit) GetBranchName() (string, error) { | func (c *Commit) GetBranchName() (string, error) { | ||||||
| 	cmd := NewCommand(c.repo.Ctx, "name-rev") | 	cmd := NewCommand(c.repo.Ctx, "name-rev") | ||||||
| 	if CheckGitVersionAtLeast("2.13.0") == nil { | 	if DefaultFeatures().CheckVersionAtLeast("2.13.0") { | ||||||
| 		cmd.AddArguments("--exclude", "refs/tags/*") | 		cmd.AddArguments("--exclude", "refs/tags/*") | ||||||
| 	} | 	} | ||||||
| 	cmd.AddArguments("--name-only", "--no-undefined").AddDynamicArguments(c.ID.String()) | 	cmd.AddArguments("--name-only", "--no-undefined").AddDynamicArguments(c.ID.String()) | ||||||
|   | |||||||
| @@ -22,42 +22,63 @@ import ( | |||||||
| 	"github.com/hashicorp/go-version" | 	"github.com/hashicorp/go-version" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // RequiredVersion is the minimum Git version required | const RequiredVersion = "2.0.0" // the minimum Git version required | ||||||
| const RequiredVersion = "2.0.0" |  | ||||||
|  |  | ||||||
| var ( | type Features struct { | ||||||
| 	// GitExecutable is the command name of git | 	gitVersion *version.Version | ||||||
| 	// Could be updated to an absolute path while initialization |  | ||||||
| 	GitExecutable = "git" |  | ||||||
|  |  | ||||||
| 	// DefaultContext is the default context to run git commands in, must be initialized by git.InitXxx |  | ||||||
| 	DefaultContext context.Context |  | ||||||
|  |  | ||||||
| 	DefaultFeatures struct { |  | ||||||
| 		GitVersion *version.Version |  | ||||||
|  |  | ||||||
|  | 	UsingGogit             bool | ||||||
| 	SupportProcReceive     bool           // >= 2.29 | 	SupportProcReceive     bool           // >= 2.29 | ||||||
| 	SupportHashSha256      bool           // >= 2.42, SHA-256 repositories no longer an ‘experimental curiosity’ | 	SupportHashSha256      bool           // >= 2.42, SHA-256 repositories no longer an ‘experimental curiosity’ | ||||||
| 	} | 	SupportedObjectFormats []ObjectFormat // sha1, sha256 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	GitExecutable   = "git"         // the command name of git, will be updated to an absolute path during initialization | ||||||
|  | 	DefaultContext  context.Context // the default context to run git commands in, must be initialized by git.InitXxx | ||||||
|  | 	defaultFeatures *Features | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // loadGitVersion tries to get the current git version and stores it into a global variable | func (f *Features) CheckVersionAtLeast(atLeast string) bool { | ||||||
| func loadGitVersion() error { | 	return f.gitVersion.Compare(version.Must(version.NewVersion(atLeast))) >= 0 | ||||||
| 	// doesn't need RWMutex because it's executed by Init() | } | ||||||
| 	if DefaultFeatures.GitVersion != nil { |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
|  | // VersionInfo returns git version information | ||||||
|  | func (f *Features) VersionInfo() string { | ||||||
|  | 	return f.gitVersion.Original() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func DefaultFeatures() *Features { | ||||||
|  | 	if defaultFeatures == nil { | ||||||
|  | 		if !setting.IsProd || setting.IsInTesting { | ||||||
|  | 			log.Warn("git.DefaultFeatures is called before git.InitXxx, initializing with default values") | ||||||
|  | 		} | ||||||
|  | 		if err := InitSimple(context.Background()); err != nil { | ||||||
|  | 			log.Fatal("git.InitSimple failed: %v", err) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return defaultFeatures | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func loadGitVersionFeatures() (*Features, error) { | ||||||
| 	stdout, _, runErr := NewCommand(DefaultContext, "version").RunStdString(nil) | 	stdout, _, runErr := NewCommand(DefaultContext, "version").RunStdString(nil) | ||||||
| 	if runErr != nil { | 	if runErr != nil { | ||||||
| 		return runErr | 		return nil, runErr | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	ver, err := parseGitVersionLine(strings.TrimSpace(stdout)) | 	ver, err := parseGitVersionLine(strings.TrimSpace(stdout)) | ||||||
| 	if err == nil { | 	if err != nil { | ||||||
| 		DefaultFeatures.GitVersion = ver | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	return err |  | ||||||
|  | 	features := &Features{gitVersion: ver, UsingGogit: isGogit} | ||||||
|  | 	features.SupportProcReceive = features.CheckVersionAtLeast("2.29") | ||||||
|  | 	features.SupportHashSha256 = features.CheckVersionAtLeast("2.42") && !isGogit | ||||||
|  | 	features.SupportedObjectFormats = []ObjectFormat{Sha1ObjectFormat} | ||||||
|  | 	if features.SupportHashSha256 { | ||||||
|  | 		features.SupportedObjectFormats = append(features.SupportedObjectFormats, Sha256ObjectFormat) | ||||||
|  | 	} | ||||||
|  | 	return features, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func parseGitVersionLine(s string) (*version.Version, error) { | func parseGitVersionLine(s string) (*version.Version, error) { | ||||||
| @@ -85,56 +106,24 @@ func SetExecutablePath(path string) error { | |||||||
| 		return fmt.Errorf("git not found: %w", err) | 		return fmt.Errorf("git not found: %w", err) | ||||||
| 	} | 	} | ||||||
| 	GitExecutable = absPath | 	GitExecutable = absPath | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
| 	if err = loadGitVersion(); err != nil { | func ensureGitVersion() error { | ||||||
| 		return fmt.Errorf("unable to load git version: %w", err) | 	if !DefaultFeatures().CheckVersionAtLeast(RequiredVersion) { | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	versionRequired, err := version.NewVersion(RequiredVersion) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if DefaultFeatures.GitVersion.LessThan(versionRequired) { |  | ||||||
| 		moreHint := "get git: https://git-scm.com/download/" | 		moreHint := "get git: https://git-scm.com/download/" | ||||||
| 		if runtime.GOOS == "linux" { | 		if runtime.GOOS == "linux" { | ||||||
| 			// there are a lot of CentOS/RHEL users using old git, so we add a special hint for them | 			// there are a lot of CentOS/RHEL users using old git, so we add a special hint for them | ||||||
| 			if _, err = os.Stat("/etc/redhat-release"); err == nil { | 			if _, err := os.Stat("/etc/redhat-release"); err == nil { | ||||||
| 				// ius.io is the recommended official(git-scm.com) method to install git | 				// ius.io is the recommended official(git-scm.com) method to install git | ||||||
| 				moreHint = "get git: https://git-scm.com/download/linux and https://ius.io" | 				moreHint = "get git: https://git-scm.com/download/linux and https://ius.io" | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		return fmt.Errorf("installed git version %q is not supported, Gitea requires git version >= %q, %s", DefaultFeatures.GitVersion.Original(), RequiredVersion, moreHint) | 		return fmt.Errorf("installed git version %q is not supported, Gitea requires git version >= %q, %s", DefaultFeatures().gitVersion.Original(), RequiredVersion, moreHint) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if err = checkGitVersionCompatibility(DefaultFeatures.GitVersion); err != nil { | 	if err := checkGitVersionCompatibility(DefaultFeatures().gitVersion); err != nil { | ||||||
| 		return fmt.Errorf("installed git version %s has a known compatibility issue with Gitea: %w, please upgrade (or downgrade) git", DefaultFeatures.GitVersion.String(), err) | 		return fmt.Errorf("installed git version %s has a known compatibility issue with Gitea: %w, please upgrade (or downgrade) git", DefaultFeatures().gitVersion.String(), err) | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // VersionInfo returns git version information |  | ||||||
| func VersionInfo() string { |  | ||||||
| 	if DefaultFeatures.GitVersion == nil { |  | ||||||
| 		return "(git not found)" |  | ||||||
| 	} |  | ||||||
| 	format := "%s" |  | ||||||
| 	args := []any{DefaultFeatures.GitVersion.Original()} |  | ||||||
| 	// Since git wire protocol has been released from git v2.18 |  | ||||||
| 	if setting.Git.EnableAutoGitWireProtocol && CheckGitVersionAtLeast("2.18") == nil { |  | ||||||
| 		format += ", Wire Protocol %s Enabled" |  | ||||||
| 		args = append(args, "Version 2") // for focus color |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return fmt.Sprintf(format, args...) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func checkInit() error { |  | ||||||
| 	if setting.Git.HomePath == "" { |  | ||||||
| 		return errors.New("unable to init Git's HomeDir, incorrect initialization of the setting and git modules") |  | ||||||
| 	} |  | ||||||
| 	if DefaultContext != nil { |  | ||||||
| 		log.Warn("git module has been initialized already, duplicate init may work but it's better to fix it") |  | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| @@ -154,8 +143,12 @@ func HomeDir() string { | |||||||
| // InitSimple initializes git module with a very simple step, no config changes, no global command arguments. | // 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 some Gitea sub-commands. | // This method doesn't change anything to filesystem. At the moment, it is only used by some Gitea sub-commands. | ||||||
| func InitSimple(ctx context.Context) error { | func InitSimple(ctx context.Context) error { | ||||||
| 	if err := checkInit(); err != nil { | 	if setting.Git.HomePath == "" { | ||||||
| 		return err | 		return errors.New("unable to init Git's HomeDir, incorrect initialization of the setting and git modules") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if DefaultContext != nil && (!setting.IsProd || setting.IsInTesting) { | ||||||
|  | 		log.Warn("git module has been initialized already, duplicate init may work but it's better to fix it") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	DefaultContext = ctx | 	DefaultContext = ctx | ||||||
| @@ -165,7 +158,24 @@ func InitSimple(ctx context.Context) error { | |||||||
| 		defaultCommandExecutionTimeout = time.Duration(setting.Git.Timeout.Default) * time.Second | 		defaultCommandExecutionTimeout = time.Duration(setting.Git.Timeout.Default) * time.Second | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return SetExecutablePath(setting.Git.Path) | 	if err := SetExecutablePath(setting.Git.Path); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var err error | ||||||
|  | 	defaultFeatures, err = loadGitVersionFeatures() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	if err = ensureGitVersion(); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// when git works with gnupg (commit signing), there should be a stable home for gnupg commands | ||||||
|  | 	if _, ok := os.LookupEnv("GNUPGHOME"); !ok { | ||||||
|  | 		_ = os.Setenv("GNUPGHOME", filepath.Join(HomeDir(), ".gnupg")) | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // InitFull initializes git module with version check and change global variables, sync gitconfig. | // InitFull initializes git module with version check and change global variables, sync gitconfig. | ||||||
| @@ -175,30 +185,18 @@ func InitFull(ctx context.Context) (err error) { | |||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// when git works with gnupg (commit signing), there should be a stable home for gnupg commands |  | ||||||
| 	if _, ok := os.LookupEnv("GNUPGHOME"); !ok { |  | ||||||
| 		_ = os.Setenv("GNUPGHOME", filepath.Join(HomeDir(), ".gnupg")) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// Since git wire protocol has been released from git v2.18 | 	// Since git wire protocol has been released from git v2.18 | ||||||
| 	if setting.Git.EnableAutoGitWireProtocol && CheckGitVersionAtLeast("2.18") == nil { | 	if setting.Git.EnableAutoGitWireProtocol && DefaultFeatures().CheckVersionAtLeast("2.18") { | ||||||
| 		globalCommandArgs = append(globalCommandArgs, "-c", "protocol.version=2") | 		globalCommandArgs = append(globalCommandArgs, "-c", "protocol.version=2") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Explicitly disable credential helper, otherwise Git credentials might leak | 	// Explicitly disable credential helper, otherwise Git credentials might leak | ||||||
| 	if CheckGitVersionAtLeast("2.9") == nil { | 	if DefaultFeatures().CheckVersionAtLeast("2.9") { | ||||||
| 		globalCommandArgs = append(globalCommandArgs, "-c", "credential.helper=") | 		globalCommandArgs = append(globalCommandArgs, "-c", "credential.helper=") | ||||||
| 	} | 	} | ||||||
| 	DefaultFeatures.SupportProcReceive = CheckGitVersionAtLeast("2.29") == nil |  | ||||||
| 	DefaultFeatures.SupportHashSha256 = CheckGitVersionAtLeast("2.42") == nil && !isGogit |  | ||||||
| 	if DefaultFeatures.SupportHashSha256 { |  | ||||||
| 		SupportedObjectFormats = append(SupportedObjectFormats, Sha256ObjectFormat) |  | ||||||
| 	} else { |  | ||||||
| 		log.Warn("sha256 hash support is disabled - requires Git >= 2.42. Gogit is currently unsupported") |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if setting.LFS.StartServer { | 	if setting.LFS.StartServer { | ||||||
| 		if CheckGitVersionAtLeast("2.1.2") != nil { | 		if !DefaultFeatures().CheckVersionAtLeast("2.1.2") { | ||||||
| 			return errors.New("LFS server support requires Git >= 2.1.2") | 			return errors.New("LFS server support requires Git >= 2.1.2") | ||||||
| 		} | 		} | ||||||
| 		globalCommandArgs = append(globalCommandArgs, "-c", "filter.lfs.required=", "-c", "filter.lfs.smudge=", "-c", "filter.lfs.clean=") | 		globalCommandArgs = append(globalCommandArgs, "-c", "filter.lfs.required=", "-c", "filter.lfs.smudge=", "-c", "filter.lfs.clean=") | ||||||
| @@ -238,13 +236,13 @@ func syncGitConfig() (err error) { | |||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if CheckGitVersionAtLeast("2.10") == nil { | 	if DefaultFeatures().CheckVersionAtLeast("2.10") { | ||||||
| 		if err := configSet("receive.advertisePushOptions", "true"); err != nil { | 		if err := configSet("receive.advertisePushOptions", "true"); err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if CheckGitVersionAtLeast("2.18") == nil { | 	if DefaultFeatures().CheckVersionAtLeast("2.18") { | ||||||
| 		if err := configSet("core.commitGraph", "true"); err != nil { | 		if err := configSet("core.commitGraph", "true"); err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| @@ -256,7 +254,7 @@ func syncGitConfig() (err error) { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if DefaultFeatures.SupportProcReceive { | 	if DefaultFeatures().SupportProcReceive { | ||||||
| 		// set support for AGit flow | 		// set support for AGit flow | ||||||
| 		if err := configAddNonExist("receive.procReceiveRefs", "refs/for"); err != nil { | 		if err := configAddNonExist("receive.procReceiveRefs", "refs/for"); err != nil { | ||||||
| 			return err | 			return err | ||||||
| @@ -294,7 +292,7 @@ func syncGitConfig() (err error) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// By default partial clones are disabled, enable them from git v2.22 | 	// By default partial clones are disabled, enable them from git v2.22 | ||||||
| 	if !setting.Git.DisablePartialClone && CheckGitVersionAtLeast("2.22") == nil { | 	if !setting.Git.DisablePartialClone && DefaultFeatures().CheckVersionAtLeast("2.22") { | ||||||
| 		if err = configSet("uploadpack.allowfilter", "true"); err != nil { | 		if err = configSet("uploadpack.allowfilter", "true"); err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| @@ -309,21 +307,6 @@ func syncGitConfig() (err error) { | |||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
|  |  | ||||||
| // CheckGitVersionAtLeast check git version is at least the constraint version |  | ||||||
| func CheckGitVersionAtLeast(atLeast string) error { |  | ||||||
| 	if DefaultFeatures.GitVersion == nil { |  | ||||||
| 		panic("git module is not initialized") // it shouldn't happen |  | ||||||
| 	} |  | ||||||
| 	atLeastVersion, err := version.NewVersion(atLeast) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	if DefaultFeatures.GitVersion.Compare(atLeastVersion) < 0 { |  | ||||||
| 		return fmt.Errorf("installed git binary version %s is not at least %s", DefaultFeatures.GitVersion.Original(), atLeast) |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func checkGitVersionCompatibility(gitVer *version.Version) error { | func checkGitVersionCompatibility(gitVer *version.Version) error { | ||||||
| 	badVersions := []struct { | 	badVersions := []struct { | ||||||
| 		Version *version.Version | 		Version *version.Version | ||||||
|   | |||||||
| @@ -120,12 +120,8 @@ var ( | |||||||
| 	Sha256ObjectFormat ObjectFormat = Sha256ObjectFormatImpl{} | 	Sha256ObjectFormat ObjectFormat = Sha256ObjectFormatImpl{} | ||||||
| ) | ) | ||||||
|  |  | ||||||
| var SupportedObjectFormats = []ObjectFormat{ |  | ||||||
| 	Sha1ObjectFormat, |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func ObjectFormatFromName(name string) ObjectFormat { | func ObjectFormatFromName(name string) ObjectFormat { | ||||||
| 	for _, objectFormat := range SupportedObjectFormats { | 	for _, objectFormat := range DefaultFeatures().SupportedObjectFormats { | ||||||
| 		if name == objectFormat.Name() { | 		if name == objectFormat.Name() { | ||||||
| 			return objectFormat | 			return objectFormat | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -54,7 +54,7 @@ func (*Sha256Hash) Type() ObjectFormat { return Sha256ObjectFormat } | |||||||
|  |  | ||||||
| func NewIDFromString(hexHash string) (ObjectID, error) { | func NewIDFromString(hexHash string) (ObjectID, error) { | ||||||
| 	var theObjectFormat ObjectFormat | 	var theObjectFormat ObjectFormat | ||||||
| 	for _, objectFormat := range SupportedObjectFormats { | 	for _, objectFormat := range DefaultFeatures().SupportedObjectFormats { | ||||||
| 		if len(hexHash) == objectFormat.FullLength() { | 		if len(hexHash) == objectFormat.FullLength() { | ||||||
| 			theObjectFormat = objectFormat | 			theObjectFormat = objectFormat | ||||||
| 			break | 			break | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ import ( | |||||||
| // GetRemoteAddress returns remote url of git repository in the repoPath with special remote name | // GetRemoteAddress returns remote url of git repository in the repoPath with special remote name | ||||||
| func GetRemoteAddress(ctx context.Context, repoPath, remoteName string) (string, error) { | func GetRemoteAddress(ctx context.Context, repoPath, remoteName string) (string, error) { | ||||||
| 	var cmd *Command | 	var cmd *Command | ||||||
| 	if CheckGitVersionAtLeast("2.7") == nil { | 	if DefaultFeatures().CheckVersionAtLeast("2.7") { | ||||||
| 		cmd = NewCommand(ctx, "remote", "get-url").AddDynamicArguments(remoteName) | 		cmd = NewCommand(ctx, "remote", "get-url").AddDynamicArguments(remoteName) | ||||||
| 	} else { | 	} else { | ||||||
| 		cmd = NewCommand(ctx, "config", "--get").AddDynamicArguments("remote." + remoteName + ".url") | 		cmd = NewCommand(ctx, "config", "--get").AddDynamicArguments("remote." + remoteName + ".url") | ||||||
|   | |||||||
| @@ -101,7 +101,7 @@ func InitRepository(ctx context.Context, repoPath string, bare bool, objectForma | |||||||
| 	if !IsValidObjectFormat(objectFormatName) { | 	if !IsValidObjectFormat(objectFormatName) { | ||||||
| 		return fmt.Errorf("invalid object format: %s", objectFormatName) | 		return fmt.Errorf("invalid object format: %s", objectFormatName) | ||||||
| 	} | 	} | ||||||
| 	if DefaultFeatures.SupportHashSha256 { | 	if DefaultFeatures().SupportHashSha256 { | ||||||
| 		cmd.AddOptionValues("--object-format", objectFormatName) | 		cmd.AddOptionValues("--object-format", objectFormatName) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,6 +0,0 @@ | |||||||
| // Copyright 2021 The Gitea Authors. All rights reserved. |  | ||||||
| // SPDX-License-Identifier: MIT |  | ||||||
|  |  | ||||||
| package git |  | ||||||
|  |  | ||||||
| var isGogit bool |  | ||||||
| @@ -22,9 +22,7 @@ import ( | |||||||
| 	"github.com/go-git/go-git/v5/storage/filesystem" | 	"github.com/go-git/go-git/v5/storage/filesystem" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func init() { | const isGogit = true | ||||||
| 	isGogit = true |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Repository represents a Git repository. | // Repository represents a Git repository. | ||||||
| type Repository struct { | type Repository struct { | ||||||
|   | |||||||
| @@ -15,9 +15,7 @@ import ( | |||||||
| 	"code.gitea.io/gitea/modules/util" | 	"code.gitea.io/gitea/modules/util" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func init() { | const isGogit = false | ||||||
| 	isGogit = false |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Repository represents a Git repository. | // Repository represents a Git repository. | ||||||
| type Repository struct { | type Repository struct { | ||||||
|   | |||||||
| @@ -438,7 +438,7 @@ func (repo *Repository) getCommitsBeforeLimit(id ObjectID, num int) ([]*Commit, | |||||||
| } | } | ||||||
|  |  | ||||||
| func (repo *Repository) getBranches(commit *Commit, limit int) ([]string, error) { | func (repo *Repository) getBranches(commit *Commit, limit int) ([]string, error) { | ||||||
| 	if CheckGitVersionAtLeast("2.7.0") == nil { | 	if DefaultFeatures().CheckVersionAtLeast("2.7.0") { | ||||||
| 		stdout, _, err := NewCommand(repo.Ctx, "for-each-ref", "--format=%(refname:strip=2)"). | 		stdout, _, err := NewCommand(repo.Ctx, "for-each-ref", "--format=%(refname:strip=2)"). | ||||||
| 			AddOptionFormat("--count=%d", limit). | 			AddOptionFormat("--count=%d", limit). | ||||||
| 			AddOptionValues("--contains", commit.ID.String(), BranchPrefix). | 			AddOptionValues("--contains", commit.ID.String(), BranchPrefix). | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ import ( | |||||||
| // WriteCommitGraph write commit graph to speed up repo access | // WriteCommitGraph write commit graph to speed up repo access | ||||||
| // this requires git v2.18 to be installed | // this requires git v2.18 to be installed | ||||||
| func WriteCommitGraph(ctx context.Context, repoPath string) error { | func WriteCommitGraph(ctx context.Context, repoPath string) error { | ||||||
| 	if CheckGitVersionAtLeast("2.18") == nil { | 	if DefaultFeatures().CheckVersionAtLeast("2.18") { | ||||||
| 		if _, _, err := NewCommand(ctx, "commit-graph", "write").RunStdString(&RunOpts{Dir: repoPath}); err != nil { | 		if _, _, err := NewCommand(ctx, "commit-graph", "write").RunStdString(&RunOpts{Dir: repoPath}); err != nil { | ||||||
| 			return fmt.Errorf("unable to write commit-graph for '%s' : %w", repoPath, err) | 			return fmt.Errorf("unable to write commit-graph for '%s' : %w", repoPath, err) | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -41,7 +41,7 @@ func SearchPointerBlobs(ctx context.Context, repo *git.Repository, pointerChan c | |||||||
| 	go pipeline.BlobsLessThan1024FromCatFileBatchCheck(catFileCheckReader, shasToBatchWriter, &wg) | 	go pipeline.BlobsLessThan1024FromCatFileBatchCheck(catFileCheckReader, shasToBatchWriter, &wg) | ||||||
|  |  | ||||||
| 	// 1. Run batch-check on all objects in the repository | 	// 1. Run batch-check on all objects in the repository | ||||||
| 	if git.CheckGitVersionAtLeast("2.6.0") != nil { | 	if !git.DefaultFeatures().CheckVersionAtLeast("2.6.0") { | ||||||
| 		revListReader, revListWriter := io.Pipe() | 		revListReader, revListWriter := io.Pipe() | ||||||
| 		shasToCheckReader, shasToCheckWriter := io.Pipe() | 		shasToCheckReader, shasToCheckWriter := io.Pipe() | ||||||
| 		wg.Add(2) | 		wg.Add(2) | ||||||
|   | |||||||
| @@ -25,6 +25,7 @@ import ( | |||||||
| 	"code.gitea.io/gitea/modules/system" | 	"code.gitea.io/gitea/modules/system" | ||||||
| 	"code.gitea.io/gitea/modules/templates" | 	"code.gitea.io/gitea/modules/templates" | ||||||
| 	"code.gitea.io/gitea/modules/translation" | 	"code.gitea.io/gitea/modules/translation" | ||||||
|  | 	"code.gitea.io/gitea/modules/util" | ||||||
| 	"code.gitea.io/gitea/modules/web" | 	"code.gitea.io/gitea/modules/web" | ||||||
| 	"code.gitea.io/gitea/modules/web/routing" | 	"code.gitea.io/gitea/modules/web/routing" | ||||||
| 	actions_router "code.gitea.io/gitea/routers/api/actions" | 	actions_router "code.gitea.io/gitea/routers/api/actions" | ||||||
| @@ -112,7 +113,10 @@ func InitWebInstallPage(ctx context.Context) { | |||||||
| // InitWebInstalled is for global installed configuration. | // InitWebInstalled is for global installed configuration. | ||||||
| func InitWebInstalled(ctx context.Context) { | func InitWebInstalled(ctx context.Context) { | ||||||
| 	mustInitCtx(ctx, git.InitFull) | 	mustInitCtx(ctx, git.InitFull) | ||||||
| 	log.Info("Git version: %s (home: %s)", git.VersionInfo(), git.HomeDir()) | 	log.Info("Git version: %s (home: %s)", git.DefaultFeatures().VersionInfo(), git.HomeDir()) | ||||||
|  | 	if !git.DefaultFeatures().SupportHashSha256 { | ||||||
|  | 		log.Warn("sha256 hash support is disabled - requires Git >= 2.42." + util.Iif(git.DefaultFeatures().UsingGogit, " Gogit is currently unsupported.", "")) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	// Setup i18n | 	// Setup i18n | ||||||
| 	translation.InitLocales(ctx) | 	translation.InitLocales(ctx) | ||||||
|   | |||||||
| @@ -122,7 +122,7 @@ func HookPreReceive(ctx *gitea_context.PrivateContext) { | |||||||
| 			preReceiveBranch(ourCtx, oldCommitID, newCommitID, refFullName) | 			preReceiveBranch(ourCtx, oldCommitID, newCommitID, refFullName) | ||||||
| 		case refFullName.IsTag(): | 		case refFullName.IsTag(): | ||||||
| 			preReceiveTag(ourCtx, refFullName) | 			preReceiveTag(ourCtx, refFullName) | ||||||
| 		case git.DefaultFeatures.SupportProcReceive && refFullName.IsFor(): | 		case git.DefaultFeatures().SupportProcReceive && refFullName.IsFor(): | ||||||
| 			preReceiveFor(ourCtx, refFullName) | 			preReceiveFor(ourCtx, refFullName) | ||||||
| 		default: | 		default: | ||||||
| 			ourCtx.AssertCanWriteCode() | 			ourCtx.AssertCanWriteCode() | ||||||
|   | |||||||
| @@ -18,7 +18,7 @@ import ( | |||||||
| // HookProcReceive proc-receive hook - only handles agit Proc-Receive requests at present | // HookProcReceive proc-receive hook - only handles agit Proc-Receive requests at present | ||||||
| func HookProcReceive(ctx *gitea_context.PrivateContext) { | func HookProcReceive(ctx *gitea_context.PrivateContext) { | ||||||
| 	opts := web.GetForm(ctx).(*private.HookOptions) | 	opts := web.GetForm(ctx).(*private.HookOptions) | ||||||
| 	if !git.DefaultFeatures.SupportProcReceive { | 	if !git.DefaultFeatures().SupportProcReceive { | ||||||
| 		ctx.Status(http.StatusNotFound) | 		ctx.Status(http.StatusNotFound) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -297,7 +297,7 @@ func ServCommand(ctx *context.PrivateContext) { | |||||||
| 			} | 			} | ||||||
| 		} else { | 		} else { | ||||||
| 			// Because of the special ref "refs/for" we will need to delay write permission check | 			// Because of the special ref "refs/for" we will need to delay write permission check | ||||||
| 			if git.DefaultFeatures.SupportProcReceive && unitType == unit.TypeCode { | 			if git.DefaultFeatures().SupportProcReceive && unitType == unit.TypeCode { | ||||||
| 				mode = perm.AccessModeRead | 				mode = perm.AccessModeRead | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -112,7 +112,7 @@ func Config(ctx *context.Context) { | |||||||
| 	ctx.Data["OfflineMode"] = setting.OfflineMode | 	ctx.Data["OfflineMode"] = setting.OfflineMode | ||||||
| 	ctx.Data["RunUser"] = setting.RunUser | 	ctx.Data["RunUser"] = setting.RunUser | ||||||
| 	ctx.Data["RunMode"] = util.ToTitleCase(setting.RunMode) | 	ctx.Data["RunMode"] = util.ToTitleCase(setting.RunMode) | ||||||
| 	ctx.Data["GitVersion"] = git.VersionInfo() | 	ctx.Data["GitVersion"] = git.DefaultFeatures().VersionInfo() | ||||||
|  |  | ||||||
| 	ctx.Data["AppDataPath"] = setting.AppDataPath | 	ctx.Data["AppDataPath"] = setting.AppDataPath | ||||||
| 	ctx.Data["RepoRootPath"] = setting.RepoRootPath | 	ctx.Data["RepoRootPath"] = setting.RepoRootPath | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ import ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| func SSHInfo(rw http.ResponseWriter, req *http.Request) { | func SSHInfo(rw http.ResponseWriter, req *http.Request) { | ||||||
| 	if !git.DefaultFeatures.SupportProcReceive { | 	if !git.DefaultFeatures().SupportProcReceive { | ||||||
| 		rw.WriteHeader(http.StatusNotFound) | 		rw.WriteHeader(http.StatusNotFound) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -183,7 +183,7 @@ func httpBase(ctx *context.Context) *serviceHandler { | |||||||
|  |  | ||||||
| 		if repoExist { | 		if repoExist { | ||||||
| 			// Because of special ref "refs/for" .. , need delay write permission check | 			// Because of special ref "refs/for" .. , need delay write permission check | ||||||
| 			if git.DefaultFeatures.SupportProcReceive { | 			if git.DefaultFeatures().SupportProcReceive { | ||||||
| 				accessMode = perm.AccessModeRead | 				accessMode = perm.AccessModeRead | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -180,7 +180,7 @@ func Create(ctx *context.Context) { | |||||||
|  |  | ||||||
| 	ctx.Data["CanCreateRepo"] = ctx.Doer.CanCreateRepo() | 	ctx.Data["CanCreateRepo"] = ctx.Doer.CanCreateRepo() | ||||||
| 	ctx.Data["MaxCreationLimit"] = ctx.Doer.MaxCreationLimit() | 	ctx.Data["MaxCreationLimit"] = ctx.Doer.MaxCreationLimit() | ||||||
| 	ctx.Data["SupportedObjectFormats"] = git.SupportedObjectFormats | 	ctx.Data["SupportedObjectFormats"] = git.DefaultFeatures().SupportedObjectFormats | ||||||
| 	ctx.Data["DefaultObjectFormat"] = git.Sha1ObjectFormat | 	ctx.Data["DefaultObjectFormat"] = git.Sha1ObjectFormat | ||||||
|  |  | ||||||
| 	ctx.HTML(http.StatusOK, tplCreate) | 	ctx.HTML(http.StatusOK, tplCreate) | ||||||
|   | |||||||
| @@ -1143,7 +1143,7 @@ func GetDiff(ctx context.Context, gitRepo *git.Repository, opts *DiffOptions, fi | |||||||
| 	// so if we are using at least this version of git we don't have to tell ParsePatch to do | 	// so if we are using at least this version of git we don't have to tell ParsePatch to do | ||||||
| 	// the skipping for us | 	// the skipping for us | ||||||
| 	parsePatchSkipToFile := opts.SkipTo | 	parsePatchSkipToFile := opts.SkipTo | ||||||
| 	if opts.SkipTo != "" && git.CheckGitVersionAtLeast("2.31") == nil { | 	if opts.SkipTo != "" && git.DefaultFeatures().CheckVersionAtLeast("2.31") { | ||||||
| 		cmdDiff.AddOptionFormat("--skip-to=%s", opts.SkipTo) | 		cmdDiff.AddOptionFormat("--skip-to=%s", opts.SkipTo) | ||||||
| 		parsePatchSkipToFile = "" | 		parsePatchSkipToFile = "" | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -383,7 +383,7 @@ func checkConflicts(ctx context.Context, pr *issues_model.PullRequest, gitRepo * | |||||||
| 		cmdApply.AddArguments("--ignore-whitespace") | 		cmdApply.AddArguments("--ignore-whitespace") | ||||||
| 	} | 	} | ||||||
| 	is3way := false | 	is3way := false | ||||||
| 	if git.CheckGitVersionAtLeast("2.32.0") == nil { | 	if git.DefaultFeatures().CheckVersionAtLeast("2.32.0") { | ||||||
| 		cmdApply.AddArguments("--3way") | 		cmdApply.AddArguments("--3way") | ||||||
| 		is3way = true | 		is3way = true | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -104,7 +104,7 @@ func createTemporaryRepoForPR(ctx context.Context, pr *issues_model.PullRequest) | |||||||
| 	baseBranch := "base" | 	baseBranch := "base" | ||||||
|  |  | ||||||
| 	fetchArgs := git.TrustedCmdArgs{"--no-tags"} | 	fetchArgs := git.TrustedCmdArgs{"--no-tags"} | ||||||
| 	if git.CheckGitVersionAtLeast("2.25.0") == nil { | 	if git.DefaultFeatures().CheckVersionAtLeast("2.25.0") { | ||||||
| 		// Writing the commit graph can be slow and is not needed here | 		// Writing the commit graph can be slow and is not needed here | ||||||
| 		fetchArgs = append(fetchArgs, "--no-write-commit-graph") | 		fetchArgs = append(fetchArgs, "--no-write-commit-graph") | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -148,7 +148,7 @@ func ApplyDiffPatch(ctx context.Context, repo *repo_model.Repository, doer *user | |||||||
| 	stderr := &strings.Builder{} | 	stderr := &strings.Builder{} | ||||||
|  |  | ||||||
| 	cmdApply := git.NewCommand(ctx, "apply", "--index", "--recount", "--cached", "--ignore-whitespace", "--whitespace=fix", "--binary") | 	cmdApply := git.NewCommand(ctx, "apply", "--index", "--recount", "--cached", "--ignore-whitespace", "--whitespace=fix", "--binary") | ||||||
| 	if git.CheckGitVersionAtLeast("2.32") == nil { | 	if git.DefaultFeatures().CheckVersionAtLeast("2.32") { | ||||||
| 		cmdApply.AddArguments("-3") | 		cmdApply.AddArguments("-3") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -695,7 +695,7 @@ func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, headBranch string | |||||||
| 		defer tests.PrintCurrentTest(t)() | 		defer tests.PrintCurrentTest(t)() | ||||||
|  |  | ||||||
| 		// skip this test if git version is low | 		// skip this test if git version is low | ||||||
| 		if git.CheckGitVersionAtLeast("2.29") != nil { | 		if !git.DefaultFeatures().SupportProcReceive { | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user