diff --git a/cmd/hook.go b/cmd/hook.go index 2a9c25add5..9c1cb66f2a 100644 --- a/cmd/hook.go +++ b/cmd/hook.go @@ -220,10 +220,7 @@ Gitea or set your environment appropriately.`, "") } } - supportProcReceive := false - if git.CheckGitVersionAtLeast("2.29") == nil { - supportProcReceive = true - } + supportProcReceive := git.DefaultFeatures().SupportProcReceive for scanner.Scan() { // TODO: support news feeds for wiki @@ -497,7 +494,7 @@ Gitea or set your environment appropriately.`, "") 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.") } diff --git a/cmd/serv.go b/cmd/serv.go index 90190a19db..2bfd111061 100644 --- a/cmd/serv.go +++ b/cmd/serv.go @@ -178,7 +178,7 @@ func runServ(c *cli.Context) error { } if len(words) < 2 { - if git.CheckGitVersionAtLeast("2.29") == nil { + if git.DefaultFeatures().SupportProcReceive { // for AGit Flow if cmd == "ssh_info" { fmt.Print(`{"type":"gitea","version":1}`) diff --git a/models/repo/search.go b/models/repo/search.go index 4d64acf8cf..54d6dcfb44 100644 --- a/models/repo/search.go +++ b/models/repo/search.go @@ -8,14 +8,14 @@ import "code.gitea.io/gitea/models/db" // SearchOrderByMap represents all possible search order var SearchOrderByMap = map[string]map[string]db.SearchOrderBy{ "asc": { - "alpha": db.SearchOrderByAlphabetically, + "alpha": "owner_name ASC, name ASC", "created": db.SearchOrderByOldest, "updated": db.SearchOrderByLeastUpdated, "size": db.SearchOrderBySize, "id": db.SearchOrderByID, }, "desc": { - "alpha": db.SearchOrderByAlphabeticallyReverse, + "alpha": "owner_name DESC, name DESC", "created": db.SearchOrderByNewest, "updated": db.SearchOrderByRecentUpdated, "size": db.SearchOrderBySizeReverse, diff --git a/modules/git/blame.go b/modules/git/blame.go index 69e1b08f93..a9b2706f21 100644 --- a/modules/git/blame.go +++ b/modules/git/blame.go @@ -132,7 +132,7 @@ func (r *BlameReader) Close() error { // 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) { var ignoreRevsFile *string - if CheckGitVersionAtLeast("2.23") == nil && !bypassBlameIgnore { + if DefaultFeatures().CheckVersionAtLeast("2.23") && !bypassBlameIgnore { ignoreRevsFile = tryCreateBlameIgnoreRevsFile(commit) } diff --git a/modules/git/commit.go b/modules/git/commit.go index d96cef37c8..86adaa79a6 100644 --- a/modules/git/commit.go +++ b/modules/git/commit.go @@ -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') func (c *Commit) GetBranchName() (string, error) { 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("--name-only", "--no-undefined").AddDynamicArguments(c.ID.String()) diff --git a/modules/git/git.go b/modules/git/git.go index e411269f7c..05ca260855 100644 --- a/modules/git/git.go +++ b/modules/git/git.go @@ -22,42 +22,63 @@ import ( "github.com/hashicorp/go-version" ) -// RequiredVersion is the minimum Git version required -const RequiredVersion = "2.0.0" +const RequiredVersion = "2.0.0" // the minimum Git version required + +type Features struct { + gitVersion *version.Version + + UsingGogit bool + SupportProcReceive bool // >= 2.29 + SupportHashSha256 bool // >= 2.42, SHA-256 repositories no longer an ‘experimental curiosity’ + SupportedObjectFormats []ObjectFormat // sha1, sha256 +} 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, must be initialized by git.InitXxx - DefaultContext context.Context - - DefaultFeatures struct { - GitVersion *version.Version - - SupportProcReceive bool // >= 2.29 - SupportHashSha256 bool // >= 2.42, SHA-256 repositories no longer an ‘experimental curiosity’ - } + 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 loadGitVersion() error { - // doesn't need RWMutex because it's executed by Init() - if DefaultFeatures.GitVersion != nil { - return nil - } +func (f *Features) CheckVersionAtLeast(atLeast string) bool { + return f.gitVersion.Compare(version.Must(version.NewVersion(atLeast))) >= 0 +} +// 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) if runErr != nil { - return runErr + return nil, runErr } ver, err := parseGitVersionLine(strings.TrimSpace(stdout)) - if err == nil { - DefaultFeatures.GitVersion = ver + if err != nil { + 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) { @@ -85,56 +106,24 @@ func SetExecutablePath(path string) error { return fmt.Errorf("git not found: %w", err) } GitExecutable = absPath + return nil +} - if err = loadGitVersion(); err != nil { - return fmt.Errorf("unable to load git version: %w", err) - } - - versionRequired, err := version.NewVersion(RequiredVersion) - if err != nil { - return err - } - - if DefaultFeatures.GitVersion.LessThan(versionRequired) { +func ensureGitVersion() error { + if !DefaultFeatures().CheckVersionAtLeast(RequiredVersion) { moreHint := "get git: https://git-scm.com/download/" if runtime.GOOS == "linux" { // 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 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 { - 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") + 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 nil } @@ -154,8 +143,12 @@ func HomeDir() string { // 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. func InitSimple(ctx context.Context) error { - if err := checkInit(); err != nil { - return err + if setting.Git.HomePath == "" { + 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 @@ -165,7 +158,24 @@ func InitSimple(ctx context.Context) error { 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. @@ -175,30 +185,18 @@ func InitFull(ctx context.Context) (err error) { 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 - if setting.Git.EnableAutoGitWireProtocol && CheckGitVersionAtLeast("2.18") == nil { + if setting.Git.EnableAutoGitWireProtocol && DefaultFeatures().CheckVersionAtLeast("2.18") { globalCommandArgs = append(globalCommandArgs, "-c", "protocol.version=2") } // 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=") } - 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 CheckGitVersionAtLeast("2.1.2") != nil { + if !DefaultFeatures().CheckVersionAtLeast("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=") @@ -238,13 +236,13 @@ func syncGitConfig() (err error) { return err } - if CheckGitVersionAtLeast("2.10") == nil { + if DefaultFeatures().CheckVersionAtLeast("2.10") { if err := configSet("receive.advertisePushOptions", "true"); err != nil { return err } } - if CheckGitVersionAtLeast("2.18") == nil { + if DefaultFeatures().CheckVersionAtLeast("2.18") { if err := configSet("core.commitGraph", "true"); err != nil { return err } @@ -256,7 +254,7 @@ func syncGitConfig() (err error) { } } - if DefaultFeatures.SupportProcReceive { + if DefaultFeatures().SupportProcReceive { // set support for AGit flow if err := configAddNonExist("receive.procReceiveRefs", "refs/for"); err != nil { return err @@ -294,7 +292,7 @@ func syncGitConfig() (err error) { } // 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 { return err } @@ -309,21 +307,6 @@ func syncGitConfig() (err error) { 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 { badVersions := []struct { Version *version.Version diff --git a/modules/git/object_format.go b/modules/git/object_format.go index 3de9ff8cf4..242d782e17 100644 --- a/modules/git/object_format.go +++ b/modules/git/object_format.go @@ -120,12 +120,8 @@ var ( Sha256ObjectFormat ObjectFormat = Sha256ObjectFormatImpl{} ) -var SupportedObjectFormats = []ObjectFormat{ - Sha1ObjectFormat, -} - func ObjectFormatFromName(name string) ObjectFormat { - for _, objectFormat := range SupportedObjectFormats { + for _, objectFormat := range DefaultFeatures().SupportedObjectFormats { if name == objectFormat.Name() { return objectFormat } diff --git a/modules/git/object_id.go b/modules/git/object_id.go index 33e5085005..82d30184df 100644 --- a/modules/git/object_id.go +++ b/modules/git/object_id.go @@ -54,7 +54,7 @@ func (*Sha256Hash) Type() ObjectFormat { return Sha256ObjectFormat } func NewIDFromString(hexHash string) (ObjectID, error) { var theObjectFormat ObjectFormat - for _, objectFormat := range SupportedObjectFormats { + for _, objectFormat := range DefaultFeatures().SupportedObjectFormats { if len(hexHash) == objectFormat.FullLength() { theObjectFormat = objectFormat break diff --git a/modules/git/remote.go b/modules/git/remote.go index 3585313f6a..7b10e6b663 100644 --- a/modules/git/remote.go +++ b/modules/git/remote.go @@ -12,7 +12,7 @@ import ( // GetRemoteAddress returns remote url of git repository in the repoPath with special remote name func GetRemoteAddress(ctx context.Context, repoPath, remoteName string) (string, error) { var cmd *Command - if CheckGitVersionAtLeast("2.7") == nil { + if DefaultFeatures().CheckVersionAtLeast("2.7") { cmd = NewCommand(ctx, "remote", "get-url").AddDynamicArguments(remoteName) } else { cmd = NewCommand(ctx, "config", "--get").AddDynamicArguments("remote." + remoteName + ".url") diff --git a/modules/git/repo.go b/modules/git/repo.go index 4511e900e0..1c223018ad 100644 --- a/modules/git/repo.go +++ b/modules/git/repo.go @@ -7,7 +7,6 @@ package git import ( "bytes" "context" - "errors" "fmt" "io" "net/url" @@ -63,32 +62,6 @@ func IsRepoURLAccessible(ctx context.Context, url string) bool { return err == nil } -// GetObjectFormatOfRepo returns the hash type of repository at a given path -func GetObjectFormatOfRepo(ctx context.Context, repoPath string) (ObjectFormat, error) { - var stdout, stderr strings.Builder - - err := NewCommand(ctx, "hash-object", "--stdin").Run(&RunOpts{ - Dir: repoPath, - Stdout: &stdout, - Stderr: &stderr, - Stdin: &strings.Reader{}, - }) - if err != nil { - return nil, err - } - - if stderr.Len() > 0 { - return nil, errors.New(stderr.String()) - } - - h, err := NewIDFromString(strings.TrimRight(stdout.String(), "\n")) - if err != nil { - return nil, err - } - - return h.Type(), nil -} - // InitRepository initializes a new Git repository. func InitRepository(ctx context.Context, repoPath string, bare bool, objectFormatName string) error { err := os.MkdirAll(repoPath, os.ModePerm) @@ -101,7 +74,7 @@ func InitRepository(ctx context.Context, repoPath string, bare bool, objectForma if !IsValidObjectFormat(objectFormatName) { return fmt.Errorf("invalid object format: %s", objectFormatName) } - if DefaultFeatures.SupportHashSha256 { + if DefaultFeatures().SupportHashSha256 { cmd.AddOptionValues("--object-format", objectFormatName) } diff --git a/modules/git/repo_base.go b/modules/git/repo_base.go deleted file mode 100644 index 6c148d9af5..0000000000 --- a/modules/git/repo_base.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2021 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package git - -var isGogit bool diff --git a/modules/git/repo_base_gogit.go b/modules/git/repo_base_gogit.go index 0cd07dcdc8..a1127f4e6c 100644 --- a/modules/git/repo_base_gogit.go +++ b/modules/git/repo_base_gogit.go @@ -22,9 +22,7 @@ import ( "github.com/go-git/go-git/v5/storage/filesystem" ) -func init() { - isGogit = true -} +const isGogit = true // Repository represents a Git repository. type Repository struct { diff --git a/modules/git/repo_base_nogogit.go b/modules/git/repo_base_nogogit.go index 5511526e78..bc241cdd79 100644 --- a/modules/git/repo_base_nogogit.go +++ b/modules/git/repo_base_nogogit.go @@ -15,9 +15,7 @@ import ( "code.gitea.io/gitea/modules/util" ) -func init() { - isGogit = false -} +const isGogit = false // Repository represents a Git repository. type Repository struct { diff --git a/modules/git/repo_commit.go b/modules/git/repo_commit.go index f9168bef7e..8c3285769e 100644 --- a/modules/git/repo_commit.go +++ b/modules/git/repo_commit.go @@ -438,7 +438,7 @@ func (repo *Repository) getCommitsBeforeLimit(id ObjectID, num int) ([]*Commit, } 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)"). AddOptionFormat("--count=%d", limit). AddOptionValues("--contains", commit.ID.String(), BranchPrefix). diff --git a/modules/git/repo_commitgraph.go b/modules/git/repo_commitgraph.go index 492438be37..087d5bcec4 100644 --- a/modules/git/repo_commitgraph.go +++ b/modules/git/repo_commitgraph.go @@ -11,7 +11,7 @@ import ( // WriteCommitGraph write commit graph to speed up repo access // this requires git v2.18 to be installed 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 { return fmt.Errorf("unable to write commit-graph for '%s' : %w", repoPath, err) } diff --git a/modules/lfs/pointer_scanner_nogogit.go b/modules/lfs/pointer_scanner_nogogit.go index 658b98feab..c37a93e73b 100644 --- a/modules/lfs/pointer_scanner_nogogit.go +++ b/modules/lfs/pointer_scanner_nogogit.go @@ -41,7 +41,7 @@ func SearchPointerBlobs(ctx context.Context, repo *git.Repository, pointerChan c go pipeline.BlobsLessThan1024FromCatFileBatchCheck(catFileCheckReader, shasToBatchWriter, &wg) // 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() shasToCheckReader, shasToCheckWriter := io.Pipe() wg.Add(2) diff --git a/modules/repository/branch.go b/modules/repository/branch.go index e448490f4a..a3fca7c7ce 100644 --- a/modules/repository/branch.go +++ b/modules/repository/branch.go @@ -5,6 +5,7 @@ package repository import ( "context" + "fmt" "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" @@ -36,6 +37,15 @@ func SyncRepoBranches(ctx context.Context, repoID, doerID int64) (int64, error) } func SyncRepoBranchesWithRepo(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, doerID int64) (int64, error) { + objFmt, err := gitRepo.GetObjectFormat() + if err != nil { + return 0, fmt.Errorf("GetObjectFormat: %w", err) + } + _, err = db.GetEngine(ctx).ID(repo.ID).Update(&repo_model.Repository{ObjectFormatName: objFmt.Name()}) + if err != nil { + return 0, fmt.Errorf("UpdateRepository: %w", err) + } + allBranches := container.Set[string]{} { branches, _, err := gitRepo.GetBranchNames(0, 0) diff --git a/modules/repository/branch_test.go b/modules/repository/branch_test.go new file mode 100644 index 0000000000..acf75a1ac0 --- /dev/null +++ b/modules/repository/branch_test.go @@ -0,0 +1,31 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package repository + +import ( + "testing" + + "code.gitea.io/gitea/models/db" + git_model "code.gitea.io/gitea/models/git" + repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/unittest" + + "github.com/stretchr/testify/assert" +) + +func TestSyncRepoBranches(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + _, err := db.GetEngine(db.DefaultContext).ID(1).Update(&repo_model.Repository{ObjectFormatName: "bad-fmt"}) + assert.NoError(t, db.TruncateBeans(db.DefaultContext, &git_model.Branch{})) + assert.NoError(t, err) + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + assert.Equal(t, "bad-fmt", repo.ObjectFormatName) + _, err = SyncRepoBranches(db.DefaultContext, 1, 0) + assert.NoError(t, err) + repo = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + assert.Equal(t, "sha1", repo.ObjectFormatName) + branch, err := git_model.GetBranch(db.DefaultContext, 1, "master") + assert.NoError(t, err) + assert.EqualValues(t, "master", branch.Name) +} diff --git a/routers/init.go b/routers/init.go index 030ef3c740..56c95cd1ca 100644 --- a/routers/init.go +++ b/routers/init.go @@ -25,6 +25,7 @@ import ( "code.gitea.io/gitea/modules/system" "code.gitea.io/gitea/modules/templates" "code.gitea.io/gitea/modules/translation" + "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/modules/web/routing" actions_router "code.gitea.io/gitea/routers/api/actions" @@ -112,7 +113,10 @@ func InitWebInstallPage(ctx context.Context) { // InitWebInstalled is for global installed configuration. func InitWebInstalled(ctx context.Context) { 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 translation.InitLocales(ctx) diff --git a/routers/private/hook_pre_receive.go b/routers/private/hook_pre_receive.go index 7189fd715c..0a3c8e2559 100644 --- a/routers/private/hook_pre_receive.go +++ b/routers/private/hook_pre_receive.go @@ -122,7 +122,7 @@ func HookPreReceive(ctx *gitea_context.PrivateContext) { preReceiveBranch(ourCtx, oldCommitID, newCommitID, refFullName) case refFullName.IsTag(): preReceiveTag(ourCtx, refFullName) - case git.DefaultFeatures.SupportProcReceive && refFullName.IsFor(): + case git.DefaultFeatures().SupportProcReceive && refFullName.IsFor(): preReceiveFor(ourCtx, refFullName) default: ourCtx.AssertCanWriteCode() diff --git a/routers/private/hook_proc_receive.go b/routers/private/hook_proc_receive.go index cee3bbdd12..efb3f5831e 100644 --- a/routers/private/hook_proc_receive.go +++ b/routers/private/hook_proc_receive.go @@ -18,7 +18,7 @@ import ( // HookProcReceive proc-receive hook - only handles agit Proc-Receive requests at present func HookProcReceive(ctx *gitea_context.PrivateContext) { opts := web.GetForm(ctx).(*private.HookOptions) - if !git.DefaultFeatures.SupportProcReceive { + if !git.DefaultFeatures().SupportProcReceive { ctx.Status(http.StatusNotFound) return } diff --git a/routers/private/serv.go b/routers/private/serv.go index 85368a0aed..1c309865d7 100644 --- a/routers/private/serv.go +++ b/routers/private/serv.go @@ -297,7 +297,7 @@ func ServCommand(ctx *context.PrivateContext) { } } else { // 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 } diff --git a/routers/web/admin/config.go b/routers/web/admin/config.go index 48f80dbbf1..fd8c73b62d 100644 --- a/routers/web/admin/config.go +++ b/routers/web/admin/config.go @@ -112,7 +112,7 @@ func Config(ctx *context.Context) { ctx.Data["OfflineMode"] = setting.OfflineMode ctx.Data["RunUser"] = setting.RunUser 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["RepoRootPath"] = setting.RepoRootPath diff --git a/routers/web/misc/misc.go b/routers/web/misc/misc.go index ac5496ce91..caaca7f521 100644 --- a/routers/web/misc/misc.go +++ b/routers/web/misc/misc.go @@ -15,7 +15,7 @@ import ( ) func SSHInfo(rw http.ResponseWriter, req *http.Request) { - if !git.DefaultFeatures.SupportProcReceive { + if !git.DefaultFeatures().SupportProcReceive { rw.WriteHeader(http.StatusNotFound) return } diff --git a/routers/web/repo/githttp.go b/routers/web/repo/githttp.go index 8fb6d93068..f0579b56ea 100644 --- a/routers/web/repo/githttp.go +++ b/routers/web/repo/githttp.go @@ -183,7 +183,7 @@ func httpBase(ctx *context.Context) *serviceHandler { if repoExist { // Because of special ref "refs/for" .. , need delay write permission check - if git.DefaultFeatures.SupportProcReceive { + if git.DefaultFeatures().SupportProcReceive { accessMode = perm.AccessModeRead } diff --git a/routers/web/repo/repo.go b/routers/web/repo/repo.go index 4e448933c7..48be1c2296 100644 --- a/routers/web/repo/repo.go +++ b/routers/web/repo/repo.go @@ -180,7 +180,7 @@ func Create(ctx *context.Context) { ctx.Data["CanCreateRepo"] = ctx.Doer.CanCreateRepo() ctx.Data["MaxCreationLimit"] = ctx.Doer.MaxCreationLimit() - ctx.Data["SupportedObjectFormats"] = git.SupportedObjectFormats + ctx.Data["SupportedObjectFormats"] = git.DefaultFeatures().SupportedObjectFormats ctx.Data["DefaultObjectFormat"] = git.Sha1ObjectFormat ctx.HTML(http.StatusOK, tplCreate) diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go index d115686491..3a35d24dff 100644 --- a/services/gitdiff/gitdiff.go +++ b/services/gitdiff/gitdiff.go @@ -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 // the skipping for us 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) parsePatchSkipToFile = "" } diff --git a/services/pull/patch.go b/services/pull/patch.go index 12b79a0625..981bc989fc 100644 --- a/services/pull/patch.go +++ b/services/pull/patch.go @@ -383,7 +383,7 @@ func checkConflicts(ctx context.Context, pr *issues_model.PullRequest, gitRepo * cmdApply.AddArguments("--ignore-whitespace") } is3way := false - if git.CheckGitVersionAtLeast("2.32.0") == nil { + if git.DefaultFeatures().CheckVersionAtLeast("2.32.0") { cmdApply.AddArguments("--3way") is3way = true } diff --git a/services/pull/temp_repo.go b/services/pull/temp_repo.go index 36bdbde55c..e5753178b8 100644 --- a/services/pull/temp_repo.go +++ b/services/pull/temp_repo.go @@ -104,7 +104,7 @@ func createTemporaryRepoForPR(ctx context.Context, pr *issues_model.PullRequest) baseBranch := "base" 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 fetchArgs = append(fetchArgs, "--no-write-commit-graph") } diff --git a/services/repository/adopt.go b/services/repository/adopt.go index 914cd9047b..f4d0da67a5 100644 --- a/services/repository/adopt.go +++ b/services/repository/adopt.go @@ -195,6 +195,10 @@ func adoptRepository(ctx context.Context, repoPath string, repo *repo_model.Repo } defer gitRepo.Close() + if _, err = repo_module.SyncRepoBranchesWithRepo(ctx, repo, gitRepo, 0); err != nil { + return fmt.Errorf("SyncRepoBranches: %w", err) + } + if err = repo_module.SyncReleasesWithTags(ctx, repo, gitRepo); err != nil { return fmt.Errorf("SyncReleasesWithTags: %w", err) } diff --git a/services/repository/files/patch.go b/services/repository/files/patch.go index e5f7e2af96..ab0e7ffd36 100644 --- a/services/repository/files/patch.go +++ b/services/repository/files/patch.go @@ -148,7 +148,7 @@ func ApplyDiffPatch(ctx context.Context, repo *repo_model.Repository, doer *user stderr := &strings.Builder{} 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") } diff --git a/templates/devtest/fomantic-dropdown.tmpl b/templates/devtest/fomantic-dropdown.tmpl new file mode 100644 index 0000000000..57a7c1313e --- /dev/null +++ b/templates/devtest/fomantic-dropdown.tmpl @@ -0,0 +1,109 @@ +{{template "base/head" .}} + +
+
+

Dropdown

+
+ + + + +
+ + +
+
+ +

Selection

+
+ {{/* the "selection" class is optional, it will be added by JS automatically */}} + + +
+

Dropdown Button (demo only without menu)

+
+ + + +
+ +
+ + + +
+ +
+
+
Other button align with ...
+ +
+
+
+{{template "base/footer" .}} diff --git a/templates/devtest/gitea-ui.tmpl b/templates/devtest/gitea-ui.tmpl index 3b13c13be8..ea293fd3b4 100644 --- a/templates/devtest/gitea-ui.tmpl +++ b/templates/devtest/gitea-ui.tmpl @@ -180,94 +180,6 @@ - -

Dropdown with SVG

-
- - - - -
- - -
-
- -
- - - -
- -
- - - -
- -
-
-
Button align with ...
- -
diff --git a/templates/install.tmpl b/templates/install.tmpl index f3117af547..965e57f213 100644 --- a/templates/install.tmpl +++ b/templates/install.tmpl @@ -157,168 +157,171 @@

{{ctx.Locale.Tr "install.optional_title"}}

- - -
- - {{ctx.Locale.Tr "install.email_title"}} - -
- - -
-
- - -
-
- - - {{ctx.Locale.TrString "install.smtp_from_helper"}}{{/* it contains lt/gt chars*/}} -
-
- - -
-
- - -
-
-
- - +
+ +
+ + {{ctx.Locale.Tr "install.email_title"}} + +
+ +
-
-
-
- - +
+ +
-
-
- - -
- - {{ctx.Locale.Tr "install.server_service_title"}} - -
-
- - +
+ + + {{ctx.Locale.TrString "install.smtp_from_helper"}}{{/* it contains lt/gt chars*/}}
-
-
-
- - +
+ +
-
-
-
- - +
+ +
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
- - - {{ctx.Locale.Tr "install.no_reply_address_helper"}} -
-
- -
+
+
+ + +
+
+ - -
- - {{ctx.Locale.Tr "install.admin_title"}} - -

{{ctx.Locale.Tr "install.admin_setting_desc"}}

-
- - -
-
- - -
-
- - -
-
- - -
-
+ +
+ + {{ctx.Locale.Tr "install.server_service_title"}} + +
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+ + + {{ctx.Locale.Tr "install.no_reply_address_helper"}} +
+
+ + + {{ctx.Locale.Tr "install.password_algorithm_helper"}} +
+
+ + +
+ + {{ctx.Locale.Tr "install.admin_title"}} + +

{{ctx.Locale.Tr "install.admin_setting_desc"}}

+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ +
{{if .EnvConfigKeys}} @@ -333,12 +336,11 @@ {{end}} -
These configuration options will be written into: {{.CustomConfFile}}
-
+
diff --git a/templates/repo/branch_dropdown.tmpl b/templates/repo/branch_dropdown.tmpl index 8f58826c6a..c4f73875f2 100644 --- a/templates/repo/branch_dropdown.tmpl +++ b/templates/repo/branch_dropdown.tmpl @@ -69,7 +69,7 @@
{{/* show dummy elements before Vue componment is mounted, this code must match the code in BranchTagSelector.vue */}} -