diff --git a/cmd/migrate_storage.go b/cmd/migrate_storage.go index a283f91401..b6af5b96e8 100644 --- a/cmd/migrate_storage.go +++ b/cmd/migrate_storage.go @@ -83,35 +83,35 @@ var CmdMigrateStorage = cli.Command{ } func migrateAttachments(ctx context.Context, dstStorage storage.ObjectStorage) error { - return db.IterateObjects(ctx, func(attach *repo_model.Attachment) error { + return db.Iterate(ctx, nil, func(ctx context.Context, attach *repo_model.Attachment) error { _, err := storage.Copy(dstStorage, attach.RelativePath(), storage.Attachments, attach.RelativePath()) return err }) } func migrateLFS(ctx context.Context, dstStorage storage.ObjectStorage) error { - return db.IterateObjects(ctx, func(mo *git_model.LFSMetaObject) error { + return db.Iterate(ctx, nil, func(ctx context.Context, mo *git_model.LFSMetaObject) error { _, err := storage.Copy(dstStorage, mo.RelativePath(), storage.LFS, mo.RelativePath()) return err }) } func migrateAvatars(ctx context.Context, dstStorage storage.ObjectStorage) error { - return db.IterateObjects(ctx, func(user *user_model.User) error { + return db.Iterate(ctx, nil, func(ctx context.Context, user *user_model.User) error { _, err := storage.Copy(dstStorage, user.CustomAvatarRelativePath(), storage.Avatars, user.CustomAvatarRelativePath()) return err }) } func migrateRepoAvatars(ctx context.Context, dstStorage storage.ObjectStorage) error { - return db.IterateObjects(ctx, func(repo *repo_model.Repository) error { + return db.Iterate(ctx, nil, func(ctx context.Context, repo *repo_model.Repository) error { _, err := storage.Copy(dstStorage, repo.CustomAvatarRelativePath(), storage.RepoAvatars, repo.CustomAvatarRelativePath()) return err }) } func migrateRepoArchivers(ctx context.Context, dstStorage storage.ObjectStorage) error { - return db.IterateObjects(ctx, func(archiver *repo_model.RepoArchiver) error { + return db.Iterate(ctx, nil, func(ctx context.Context, archiver *repo_model.RepoArchiver) error { p := archiver.RelativePath() _, err := storage.Copy(dstStorage, p, storage.RepoArchives, p) return err @@ -119,7 +119,7 @@ func migrateRepoArchivers(ctx context.Context, dstStorage storage.ObjectStorage) } func migratePackages(ctx context.Context, dstStorage storage.ObjectStorage) error { - return db.IterateObjects(ctx, func(pb *packages_model.PackageBlob) error { + return db.Iterate(ctx, nil, func(ctx context.Context, pb *packages_model.PackageBlob) error { p := packages_module.KeyToRelativePath(packages_module.BlobHash256Key(pb.HashSHA256)) _, err := storage.Copy(dstStorage, p, storage.Packages, p) return err diff --git a/docs/content/doc/advanced/hacking-on-gitea.zh-cn.md b/docs/content/doc/advanced/hacking-on-gitea.zh-cn.md deleted file mode 100644 index 7ad8019c5e..0000000000 --- a/docs/content/doc/advanced/hacking-on-gitea.zh-cn.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -date: "2016-12-01T16:00:00+02:00" -title: "加入 Gitea 开源" -slug: "hacking-on-gitea" -weight: 10 -toc: false -draft: false -menu: - sidebar: - parent: "advanced" - name: "加入 Gitea 开源" - weight: 10 - identifier: "hacking-on-gitea" ---- - -# Hacking on Gitea - -首先你需要一些运行环境,这和 [从源代码安装]({{< relref "from-source.zh-cn.md" >}}) 相同,如果你还没有设置好,可以先阅读那个章节。 - -如果你想为 Gitea 贡献代码,你需要 Fork 这个项目并且以 `master` 为开发分支。Gitea 使用 Govendor -来管理依赖,因此所有依赖项都被工具自动 copy 在 vendor 子目录下。用下面的命令来下载源码: - -``` -go get -d code.gitea.io/gitea -``` - -然后你可以在 Github 上 fork [Gitea 项目](https://github.com/go-gitea/gitea),之后可以通过下面的命令进入源码目录: - -``` -cd $GOPATH/src/code.gitea.io/gitea -``` - -要创建 pull requests 你还需要在源码中新增一个 remote 指向你 Fork 的地址,直接推送到 origin 的话会告诉你没有写权限: - -``` -git remote rename origin upstream -git remote add origin git@github.com:/gitea.git -git fetch --all --prune -``` - -然后你就可以开始开发了。你可以看一下 `Makefile` 的内容。`make test` 可以运行测试程序, `make build` 将生成一个 `gitea` 可运行文件在根目录。如果你的提交比较复杂,尽量多写一些单元测试代码。 - -好了,到这里你已经设置好了所有的开发 Gitea 所需的环境。欢迎成为 Gitea 的 Contributor。 diff --git a/docs/content/doc/advanced/mail-templates-us.md b/docs/content/doc/advanced/mail-templates.en-us.md similarity index 100% rename from docs/content/doc/advanced/mail-templates-us.md rename to docs/content/doc/advanced/mail-templates.en-us.md diff --git a/docs/content/doc/advanced/make.fr-fr.md b/docs/content/doc/advanced/make.fr-fr.md deleted file mode 100644 index f30b709f0e..0000000000 --- a/docs/content/doc/advanced/make.fr-fr.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -date: "2017-08-23T09:00:00+02:00" -title: "Make" -slug: "make" -weight: 10 -toc: false -draft: false -menu: - sidebar: - parent: "advanced" - name: "Make" - weight: 30 - identifier: "make" ---- - -# Make - -Gitea fait largement usage de Make pour automatiser les tâches et avoir un développement plus rapide. Ce guide explique comment installer Make. - -### Linux - -Vous pouvez installer Make avec votre gestionnaire de paquetages - -Depuis Ubuntu/Debian: - -```bash -sudo apt-get install build-essential -``` - -Depuis Fedora/RHEL/CentOS: - -```bash -sudo yum install make -``` - -### Windows - -Si vous utilisez Windows, vous pouvez télécharger une des versions suivantes de Make: - -- [Simple binaire](http://www.equation.com/servlet/equation.cmd?fa=make). Copiez-le quelque part et mettez à jour `PATH`. - - [32-bits version](ftp://ftp.equation.com/make/32/make.exe) - - [64-bits version](ftp://ftp.equation.com/make/64/make.exe) -- [MinGW](http://www.mingw.org/) inclut un _build_. Le fichier binaire est nommé `mingw32-make.exe` plutôt que `make.exe`. Ajoutez le dossier `bin` à votre `PATH`. -- [Chocolatey package](https://chocolatey.org/packages/make). Exécutez `choco install make`. diff --git a/docs/content/doc/advanced/make.zh-cn.md b/docs/content/doc/advanced/make.zh-cn.md deleted file mode 100644 index 2491dbe231..0000000000 --- a/docs/content/doc/advanced/make.zh-cn.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -date: "2017-01-14T11:00:00-02:00" -title: "Make 安装" -slug: "make" -weight: 10 -toc: false -draft: false -menu: - sidebar: - parent: "advanced" - name: "Make 安装" - weight: 30 - identifier: "make" ---- - -# 安装 Make - -Gitea 大量使用了 Make 工具来自动执行任务并改进开发,本文将介绍如何安装 Make。 - -### 在 Linux 环境下 - -可以使用包管理工具来安装 Make。 - -Ubuntu/Debian 环境,执行以下命令: - -```bash -sudo apt-get install make -``` - -Fedora/RHEL/CentOS,执行以下命令: - -```bash -sudo yum install make -``` - -### 在 Windows 环境下 - -您可以参照以下三种方案在 Windows 环境安装 Make: - -- 直接使用 [exe文件](http://www.equation.com/servlet/equation.cmd?fa=make):将适合您系统的exe文件拷贝到某处并添加至环境变量 `PATH` 中。 - - [32 位版本](ftp://ftp.equation.com/make/32/make.exe) - - [64 位版本](ftp://ftp.equation.com/make/64/make.exe) -- 使用 [MinGW](http://www.mingw.org/) 工具: - - 此处使用二进制文件 `mingw32-make.exe` 替代前面提到的 `make.exe`文件。同样您需要将包含此exe文件的 `bin` 目录添加至环境变量 `PATH`中。 -- 通过 [Chocolatey](https://chocolatey.org/packages/make) 安装: 执行 `choco install make` 命令即可。 diff --git a/docs/content/doc/advanced/third-party-tools.zh-cn.md b/docs/content/doc/advanced/third-party-tools.zh-cn.md deleted file mode 100644 index e961e9ec1f..0000000000 --- a/docs/content/doc/advanced/third-party-tools.zh-cn.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -date: "2019-03-11T21:45:00+00:00" -title: "高级: 第三方工具" -slug: "third-party-tools" -weight: 50 -toc: false -draft: false -menu: - sidebar: - parent: "advanced" - name: "第三方工具" - weight: 50 - identifier: "third-party-tools" ---- - -# 第三方工具列表 - -**注意:** 这些工具并没有经过Gitea的检验,在这里列出它们只是为了便捷. - -*此列表并不是完整的列表,可以随时咨询如何添加!* - -### 持续集成 - -[BuildKite 连接器](https://github.com/techknowlogick/gitea-buildkite-connector) -[Jenkins 插件](https://github.com/jenkinsci/gitea-plugin) -[Gitea搭配Drone](https://docs.drone.io/installation/gitea) - -### 迁移 - -[Gitea安装脚本](https://git.coolaj86.com/coolaj86/gitea-installer.sh) -[GitHub迁移](https://gitea.com/gitea/migrator) - -### 移动端 - -[安卓客户端GitNex](https://gitlab.com/mmarif4u/gitnex) - -### 编辑器扩展 - -- [Gitea的Visual Studio扩展](https://github.com/maikebing/Gitea.VisualStudio) 从 [Visual Studio 扩展市场](https://marketplace.visualstudio.com/items?itemName=MysticBoy.GiteaExtensionforVisualStudio) 下载 diff --git a/docs/content/doc/developers.zh-cn.md b/docs/content/doc/developers.zh-cn.md index 0a873102bc..97fb3a9782 100644 --- a/docs/content/doc/developers.zh-cn.md +++ b/docs/content/doc/developers.zh-cn.md @@ -8,6 +8,6 @@ draft: false menu: sidebar: name: "开发者" - weight: 50 + weight: 55 identifier: "developers" --- diff --git a/docs/content/doc/developers/guidelines-backend.md b/docs/content/doc/developers/guidelines-backend.en-us.md similarity index 100% rename from docs/content/doc/developers/guidelines-backend.md rename to docs/content/doc/developers/guidelines-backend.en-us.md diff --git a/docs/content/doc/developers/oauth2-provider.md b/docs/content/doc/developers/oauth2-provider.en-us.md similarity index 100% rename from docs/content/doc/developers/oauth2-provider.md rename to docs/content/doc/developers/oauth2-provider.en-us.md diff --git a/docs/content/doc/installation/from-source.en-us.md b/docs/content/doc/installation/from-source.en-us.md index 660f996b1e..0be5673be4 100644 --- a/docs/content/doc/installation/from-source.en-us.md +++ b/docs/content/doc/installation/from-source.en-us.md @@ -87,7 +87,7 @@ To build from source, the following programs must be present on the system: - `go` {{< min-go-version >}} or higher, see [here](https://golang.org/dl/) - `node` {{< min-node-version >}} or higher with `npm`, see [here](https://nodejs.org/en/download/) -- `make`, see here +- `make`, see [here]({{< relref "doc/developers/hacking-on-gitea.en-us.md" >}}#installing-make) Various [make tasks](https://github.com/go-gitea/gitea/blob/main/Makefile) are provided to keep the build process as simple as possible. diff --git a/docs/content/doc/installation/from-source.fr-fr.md b/docs/content/doc/installation/from-source.fr-fr.md index 00f67eab55..6ff4853a22 100644 --- a/docs/content/doc/installation/from-source.fr-fr.md +++ b/docs/content/doc/installation/from-source.fr-fr.md @@ -53,7 +53,7 @@ git checkout pr-xyz ## Compilation -Comme nous regroupons déjà toutes les bibliothèques requises pour compiler Gitea, vous pouvez continuer avec le processus de compilation lui-même. Nous fournissons diverses [tâches Make](https://github.com/go-gitea/gitea/blob/master/Makefile) pour rendre le processus de construction aussi simple que possible. Voyez ici comment obtenir Make. Selon vos besoins, vous pourrez éventuellement ajouter diverses options de compilation, vous pouvez choisir entre ces options : +Comme nous regroupons déjà toutes les bibliothèques requises pour compiler Gitea, vous pouvez continuer avec le processus de compilation lui-même. Nous fournissons diverses [tâches Make](https://github.com/go-gitea/gitea/blob/master/Makefile) pour rendre le processus de construction aussi simple que possible. [Voyez ici comment obtenir Make]({{< relref "doc/developers/hacking-on-gitea.fr-fr.md" >}}#installing-make). Selon vos besoins, vous pourrez éventuellement ajouter diverses options de compilation, vous pouvez choisir entre ces options : * `bindata`: Intègre toutes les ressources nécessaires à l'exécution d'une instance de Gitea, ce qui rend un déploiement facile car il n'est pas nécessaire de se préoccuper des fichiers supplémentaires. * `sqlite sqlite_unlock_notify`: Active la prise en charge d'une base de données [SQLite3](https://sqlite.org/), ceci n'est recommandé que pour les petites installations de Gitea. diff --git a/docs/content/doc/installation/from-source.zh-cn.md b/docs/content/doc/installation/from-source.zh-cn.md index 008566e57d..659c992346 100644 --- a/docs/content/doc/installation/from-source.zh-cn.md +++ b/docs/content/doc/installation/from-source.zh-cn.md @@ -54,7 +54,7 @@ git checkout v{{< version >}} - `go` {{< min-go-version >}} 或以上版本, 详见[这里](https://golang.google.cn/doc/install) - `node` {{< min-node-version >}} 或以上版本,并且安装 `npm`, 详见[这里](https://nodejs.org/zh-cn/download/) -- `make`, 详见[这里]({{< relref "make.zh-cn.md" >}}) +- `make`, 详见[这里]({{< relref "doc/developers/hacking-on-gitea.zh-cn.md" >}}) 各种可用的 [make 任务](https://github.com/go-gitea/gitea/blob/main/Makefile) 可以用来使编译过程更方便。 diff --git a/docs/content/doc/installation/on-cloud-provider.md b/docs/content/doc/installation/on-cloud-provider.en-us.md similarity index 100% rename from docs/content/doc/installation/on-cloud-provider.md rename to docs/content/doc/installation/on-cloud-provider.en-us.md diff --git a/docs/content/doc/usage/email-setup.en-us.md b/docs/content/doc/usage/email-setup.en-us.md index 533e0fe1a8..05cc19c134 100644 --- a/docs/content/doc/usage/email-setup.en-us.md +++ b/docs/content/doc/usage/email-setup.en-us.md @@ -47,7 +47,8 @@ Directly use SMTP server as relay. This option is useful if you don't want to se ENABLED = true FROM = gitea@mydomain.com MAILER_TYPE = smtp -HOST = mail.mydomain.com:587 +SMTP_ADDR = mail.mydomain.com +SMTP_PORT = 587 IS_TLS_ENABLED = true USER = gitea@mydomain.com PASSWD = `password` @@ -75,7 +76,8 @@ The following configuration should work with GMail's SMTP server: ```ini [mailer] ENABLED = true -HOST = smtp.gmail.com:465 +SMTP_ADDR = smtp.gmail.com +SMTP_PORT = 465 FROM = example@gmail.com USER = example@gmail.com PASSWD = *** diff --git a/docs/content/doc/usage/git-lfs-support.md b/docs/content/doc/usage/git-lfs-support.en-us.md similarity index 100% rename from docs/content/doc/usage/git-lfs-support.md rename to docs/content/doc/usage/git-lfs-support.en-us.md diff --git a/docs/content/doc/usage/https-support.md b/docs/content/doc/usage/https-support.en-us.md similarity index 100% rename from docs/content/doc/usage/https-support.md rename to docs/content/doc/usage/https-support.en-us.md diff --git a/docs/content/doc/usage/template-repositories.md b/docs/content/doc/usage/template-repositories.en-us.md similarity index 100% rename from docs/content/doc/usage/template-repositories.md rename to docs/content/doc/usage/template-repositories.en-us.md diff --git a/docs/static/_redirects b/docs/static/_redirects index 676181b61f..39bd09f9ba 100644 --- a/docs/static/_redirects +++ b/docs/static/_redirects @@ -9,7 +9,10 @@ https://gitea-docs.netlify.com/* https://docs.gitea.io/:splat 302! /en-us/ci-cd/ /en-us/integrations/ 302! /en-us/third-party-tools/ /en-us/integrations/ 302! +/zh-cn/third-party-tools/ /zh-cn/integrations/ 302! /en-us/make/ /en-us/hacking-on-gitea/ 302! +/zh-cn/make/ /zh-cn/hacking-on-gitea/ 302! +/fr-fr/make/ /fr-fr/hacking-on-gitea/ 302! /en-us/upgrade/ /en-us/upgrade-from-gitea/ 302! /fr-fr/upgrade/ /fr-fr/upgrade-from-gitea/ 302! /zh-cn/upgrade/ /zh-cn/upgrade-from-gitea/ 302! diff --git a/models/db/context.go b/models/db/context.go index 4fd35200cf..e90780e4e9 100644 --- a/models/db/context.go +++ b/models/db/context.go @@ -8,9 +8,6 @@ import ( "context" "database/sql" - "code.gitea.io/gitea/modules/setting" - - "xorm.io/builder" "xorm.io/xorm/schemas" ) @@ -121,13 +118,6 @@ func WithTx(f func(ctx context.Context) error, stdCtx ...context.Context) error return sess.Commit() } -// Iterate iterates the databases and doing something -func Iterate(ctx context.Context, tableBean interface{}, cond builder.Cond, fun func(idx int, bean interface{}) error) error { - return GetEngine(ctx).Where(cond). - BufferSize(setting.Database.IterateBufferSize). - Iterate(tableBean, fun) -} - // Insert inserts records into database func Insert(ctx context.Context, beans ...interface{}) error { _, err := GetEngine(ctx).Insert(beans...) diff --git a/models/db/iterate.go b/models/db/iterate.go index 3d4fa06eeb..cbd2feed28 100644 --- a/models/db/iterate.go +++ b/models/db/iterate.go @@ -8,25 +8,30 @@ import ( "context" "code.gitea.io/gitea/modules/setting" + + "xorm.io/builder" ) -// IterateObjects iterate all the Bean object -func IterateObjects[Object any](ctx context.Context, f func(repo *Object) error) error { +// Iterate iterate all the Bean object +func Iterate[Bean any](ctx context.Context, cond builder.Cond, f func(ctx context.Context, bean *Bean) error) error { var start int batchSize := setting.Database.IterateBufferSize sess := GetEngine(ctx) for { - repos := make([]*Object, 0, batchSize) - if err := sess.Limit(batchSize, start).Find(&repos); err != nil { + beans := make([]*Bean, 0, batchSize) + if cond != nil { + sess = sess.Where(cond) + } + if err := sess.Limit(batchSize, start).Find(&beans); err != nil { return err } - if len(repos) == 0 { + if len(beans) == 0 { return nil } - start += len(repos) + start += len(beans) - for _, repo := range repos { - if err := f(repo); err != nil { + for _, bean := range beans { + if err := f(ctx, bean); err != nil { return err } } diff --git a/models/db/iterate_test.go b/models/db/iterate_test.go new file mode 100644 index 0000000000..5d03a6e9ce --- /dev/null +++ b/models/db/iterate_test.go @@ -0,0 +1,44 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package db_test + +import ( + "context" + "testing" + + "code.gitea.io/gitea/models/db" + repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/unittest" + + "github.com/stretchr/testify/assert" +) + +func TestIterate(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + xe := unittest.GetXORMEngine() + assert.NoError(t, xe.Sync(&repo_model.RepoUnit{})) + + var repoCnt int + err := db.Iterate(db.DefaultContext, nil, func(ctx context.Context, repo *repo_model.RepoUnit) error { + repoCnt++ + return nil + }) + assert.NoError(t, err) + assert.EqualValues(t, 79, repoCnt) + + err = db.Iterate(db.DefaultContext, nil, func(ctx context.Context, repoUnit *repo_model.RepoUnit) error { + reopUnit2 := repo_model.RepoUnit{ID: repoUnit.ID} + has, err := db.GetByBean(ctx, &reopUnit2) + if err != nil { + return err + } else if !has { + return db.ErrNotExist{Resource: "repo_unit", ID: repoUnit.ID} + } + assert.EqualValues(t, repoUnit.RepoID, repoUnit.RepoID) + assert.EqualValues(t, repoUnit.CreatedUnix, repoUnit.CreatedUnix) + return nil + }) + assert.NoError(t, err) +} diff --git a/modules/doctor/breaking.go b/modules/doctor/breaking.go index 51122d9a61..474997acd8 100644 --- a/modules/doctor/breaking.go +++ b/modules/doctor/breaking.go @@ -18,10 +18,9 @@ import ( func iterateUserAccounts(ctx context.Context, each func(*user.User) error) error { err := db.Iterate( ctx, - new(user.User), builder.Gt{"id": 0}, - func(idx int, bean interface{}) error { - return each(bean.(*user.User)) + func(ctx context.Context, bean *user.User) error { + return each(bean) }, ) return err diff --git a/modules/doctor/fix16961.go b/modules/doctor/fix16961.go index 307cfcd9ff..d9f895739f 100644 --- a/modules/doctor/fix16961.go +++ b/modules/doctor/fix16961.go @@ -269,13 +269,10 @@ func fixBrokenRepoUnits16961(ctx context.Context, logger log.Logger, autofix boo err := db.Iterate( ctx, - new(RepoUnit), builder.Gt{ "id": 0, }, - func(idx int, bean interface{}) error { - unit := bean.(*RepoUnit) - + func(ctx context.Context, unit *RepoUnit) error { bs := unit.Config repoUnit := &repo_model.RepoUnit{ ID: unit.ID, diff --git a/modules/doctor/mergebase.go b/modules/doctor/mergebase.go index b279c453f7..9f5e336461 100644 --- a/modules/doctor/mergebase.go +++ b/modules/doctor/mergebase.go @@ -21,10 +21,9 @@ import ( func iteratePRs(ctx context.Context, repo *repo_model.Repository, each func(*repo_model.Repository, *issues_model.PullRequest) error) error { return db.Iterate( ctx, - new(issues_model.PullRequest), builder.Eq{"base_repo_id": repo.ID}, - func(idx int, bean interface{}) error { - return each(repo, bean.(*issues_model.PullRequest)) + func(ctx context.Context, bean *issues_model.PullRequest) error { + return each(repo, bean) }, ) } diff --git a/modules/doctor/misc.go b/modules/doctor/misc.go index 277d66a177..6f0e066f54 100644 --- a/modules/doctor/misc.go +++ b/modules/doctor/misc.go @@ -30,10 +30,9 @@ import ( func iterateRepositories(ctx context.Context, each func(*repo_model.Repository) error) error { err := db.Iterate( ctx, - new(repo_model.Repository), builder.Gt{"id": 0}, - func(idx int, bean interface{}) error { - return each(bean.(*repo_model.Repository)) + func(ctx context.Context, bean *repo_model.Repository) error { + return each(bean) }, ) return err diff --git a/modules/issue/template/unmarshal.go b/modules/issue/template/unmarshal.go index e695d1e1cc..24587b0fed 100644 --- a/modules/issue/template/unmarshal.go +++ b/modules/issue/template/unmarshal.go @@ -14,6 +14,7 @@ import ( "code.gitea.io/gitea/modules/markup/markdown" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/util" "gopkg.in/yaml.v2" ) @@ -95,14 +96,27 @@ func unmarshal(filename string, content []byte) (*api.IssueTemplate, error) { }{} if typ := it.Type(); typ == api.IssueTemplateTypeMarkdown { - templateBody, err := markdown.ExtractMetadata(string(content), it) - if err != nil { - return nil, err - } - it.Content = templateBody - if it.About == "" { - if _, err := markdown.ExtractMetadata(string(content), compatibleTemplate); err == nil && compatibleTemplate.About != "" { - it.About = compatibleTemplate.About + if templateBody, err := markdown.ExtractMetadata(string(content), it); err != nil { + // The only thing we know here is that we can't extract metadata from the content, + // it's hard to tell if metadata doesn't exist or metadata isn't valid. + // There's an example template: + // + // --- + // # Title + // --- + // Content + // + // It could be a valid markdown with two horizontal lines, or an invalid markdown with wrong metadata. + + it.Content = string(content) + it.Name = filepath.Base(it.FileName) + it.About, _ = util.SplitStringAtByteN(it.Content, 80) + } else { + it.Content = templateBody + if it.About == "" { + if _, err := markdown.ExtractMetadata(string(content), compatibleTemplate); err == nil && compatibleTemplate.About != "" { + it.About = compatibleTemplate.About + } } } } else if typ == api.IssueTemplateTypeYaml { diff --git a/modules/structs/issue.go b/modules/structs/issue.go index 27ec81f728..70f5e1ba8e 100644 --- a/modules/structs/issue.go +++ b/modules/structs/issue.go @@ -170,7 +170,7 @@ func (it IssueTemplate) Type() IssueTemplateType { if ext := filepath.Ext(it.FileName); ext == ".md" { return IssueTemplateTypeMarkdown } else if ext == ".yaml" || ext == ".yml" { - return "yaml" + return IssueTemplateTypeYaml } - return IssueTemplateTypeYaml + return "" } diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 392a14db6e..e3afef14a6 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -238,6 +238,8 @@ no_reply_address = Hidden Email Domain no_reply_address_helper = Domain name for users with a hidden email address. For example, the username 'joe' will be logged in Git as 'joe@noreply.example.org' if the hidden email domain is set to 'noreply.example.org'. password_algorithm = Password Hash Algorithm password_algorithm_helper = Set the password hashing algorithm. Algorithms have differing requirements and strength. `argon2` whilst having good characteristics uses a lot of memory and may be inappropriate for small systems. +enable_update_checker = Enable Update Checker +enable_update_checker_helper = Checks for new version releases periodically by connecting to gitea.io. [home] uname_holder = Username or Email Address diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 3d164f005e..b00400477e 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -451,7 +451,7 @@ SSPIDefaultLanguage=默认语言 require_error=不能为空。 alpha_dash_error=应该只包含字母数字、破折号 ('-') 和下划线 ('_') 字符。 -alpha_dash_dot_error=' 应该只包含字母数字, 破折号 ('-'), 下划线 ('_') 和点 ('. ') 。 +alpha_dash_dot_error=` 应该只包含字母数字, 破折号 ('-'), 下划线 ('_') 和点 ('. ') 。` git_ref_name_error=` 必须是格式良好的 git 引用名称。` size_error=长度必须为 %s。 min_size_error=长度最小为 %s 个字符。 diff --git a/routers/install/install.go b/routers/install/install.go index 962dee8c86..6bac5b5ff7 100644 --- a/routers/install/install.go +++ b/routers/install/install.go @@ -457,6 +457,7 @@ func SubmitInstall(ctx *context.Context) { cfg.Section("service").Key("DEFAULT_ALLOW_CREATE_ORGANIZATION").SetValue(fmt.Sprint(form.DefaultAllowCreateOrganization)) cfg.Section("service").Key("DEFAULT_ENABLE_TIMETRACKING").SetValue(fmt.Sprint(form.DefaultEnableTimetracking)) cfg.Section("service").Key("NO_REPLY_ADDRESS").SetValue(fmt.Sprint(form.NoReplyAddress)) + cfg.Section("cron.update_checker").Key("ENABLED").SetValue(fmt.Sprint(form.EnableUpdateChecker)) cfg.Section("").Key("RUN_MODE").SetValue("prod") diff --git a/routers/private/mail.go b/routers/private/mail.go index e858992aee..255e1d901d 100644 --- a/routers/private/mail.go +++ b/routers/private/mail.go @@ -5,6 +5,7 @@ package private import ( + stdCtx "context" "fmt" "net/http" "strconv" @@ -60,7 +61,7 @@ func SendEmail(ctx *context.PrivateContext) { } } } else { - err := db.IterateObjects(ctx, func(user *user_model.User) error { + err := db.Iterate(ctx, nil, func(ctx stdCtx.Context, user *user_model.User) error { if len(user.Email) > 0 && user.IsActive { emails = append(emails, user.Email) } diff --git a/services/forms/user_form.go b/services/forms/user_form.go index 07fe5928ea..64b8caff79 100644 --- a/services/forms/user_form.go +++ b/services/forms/user_form.go @@ -62,6 +62,7 @@ type InstallForm struct { DefaultKeepEmailPrivate bool DefaultAllowCreateOrganization bool DefaultEnableTimetracking bool + EnableUpdateChecker bool NoReplyAddress string PasswordAlgorithm string diff --git a/services/repository/adopt.go b/services/repository/adopt.go index 3b986c66c6..a9a0639548 100644 --- a/services/repository/adopt.go +++ b/services/repository/adopt.go @@ -8,6 +8,7 @@ import ( "context" "fmt" "os" + "path" "path/filepath" "strings" @@ -218,21 +219,21 @@ func DeleteUnadoptedRepository(doer, u *user_model.User, repoName string) error return util.RemoveAll(repoPath) } -type unadoptedRrepositories struct { +type unadoptedRepositories struct { repositories []string index int start int end int } -func (unadopted *unadoptedRrepositories) add(repository string) { +func (unadopted *unadoptedRepositories) add(repository string) { if unadopted.index >= unadopted.start && unadopted.index < unadopted.end { unadopted.repositories = append(unadopted.repositories, repository) } unadopted.index++ } -func checkUnadoptedRepositories(userName string, repoNamesToCheck []string, unadopted *unadoptedRrepositories) error { +func checkUnadoptedRepositories(userName string, repoNamesToCheck []string, unadopted *unadoptedRepositories) error { if len(repoNamesToCheck) == 0 { return nil } @@ -264,7 +265,7 @@ func checkUnadoptedRepositories(userName string, repoNamesToCheck []string, unad } for _, repoName := range repoNamesToCheck { if !repoNames.Contains(repoName) { - unadopted.add(filepath.Join(userName, repoName)) + unadopted.add(path.Join(userName, repoName)) // These are not used as filepaths - but as reponames - therefore use path.Join not filepath.Join } } return nil @@ -292,7 +293,7 @@ func ListUnadoptedRepositories(query string, opts *db.ListOptions) ([]string, in var repoNamesToCheck []string start := (opts.Page - 1) * opts.PageSize - unadopted := &unadoptedRrepositories{ + unadopted := &unadoptedRepositories{ repositories: make([]string, 0, opts.PageSize), start: start, end: start + opts.PageSize, diff --git a/services/repository/adopt_test.go b/services/repository/adopt_test.go index 685bfe9bc4..b450005f34 100644 --- a/services/repository/adopt_test.go +++ b/services/repository/adopt_test.go @@ -19,7 +19,7 @@ import ( func TestCheckUnadoptedRepositories_Add(t *testing.T) { start := 10 end := 20 - unadopted := &unadoptedRrepositories{ + unadopted := &unadoptedRepositories{ start: start, end: end, index: 0, @@ -39,7 +39,7 @@ func TestCheckUnadoptedRepositories(t *testing.T) { // // Non existent user // - unadopted := &unadoptedRrepositories{start: 0, end: 100} + unadopted := &unadoptedRepositories{start: 0, end: 100} err := checkUnadoptedRepositories("notauser", []string{"repo"}, unadopted) assert.NoError(t, err) assert.Equal(t, 0, len(unadopted.repositories)) @@ -50,14 +50,14 @@ func TestCheckUnadoptedRepositories(t *testing.T) { userName := "user2" repoName := "repo2" unadoptedRepoName := "unadopted" - unadopted = &unadoptedRrepositories{start: 0, end: 100} + unadopted = &unadoptedRepositories{start: 0, end: 100} err = checkUnadoptedRepositories(userName, []string{repoName, unadoptedRepoName}, unadopted) assert.NoError(t, err) assert.Equal(t, []string{path.Join(userName, unadoptedRepoName)}, unadopted.repositories) // // Existing (adopted) repository is not returned // - unadopted = &unadoptedRrepositories{start: 0, end: 100} + unadopted = &unadoptedRepositories{start: 0, end: 100} err = checkUnadoptedRepositories(userName, []string{repoName}, unadopted) assert.NoError(t, err) assert.Equal(t, 0, len(unadopted.repositories)) diff --git a/services/repository/avatar.go b/services/repository/avatar.go index b80a8fb775..1cf9e869c0 100644 --- a/services/repository/avatar.go +++ b/services/repository/avatar.go @@ -96,7 +96,7 @@ func DeleteAvatar(repo *repo_model.Repository) error { // RemoveRandomAvatars removes the randomly generated avatars that were created for repositories func RemoveRandomAvatars(ctx context.Context) error { - return db.IterateObjects(ctx, func(repository *repo_model.Repository) error { + return db.Iterate(ctx, nil, func(ctx context.Context, repository *repo_model.Repository) error { select { case <-ctx.Done(): return db.ErrCancelledf("before random avatars removed for %s", repository.FullName()) diff --git a/services/repository/check.go b/services/repository/check.go index 5529a61b39..5725f540b0 100644 --- a/services/repository/check.go +++ b/services/repository/check.go @@ -29,10 +29,8 @@ func GitFsck(ctx context.Context, timeout time.Duration, args []git.CmdArg) erro if err := db.Iterate( ctx, - new(repo_model.Repository), builder.Expr("id>0 AND is_fsck_enabled=?", true), - func(idx int, bean interface{}) error { - repo := bean.(*repo_model.Repository) + func(ctx context.Context, repo *repo_model.Repository) error { select { case <-ctx.Done(): return db.ErrCancelledf("before fsck of %s", repo.FullName()) @@ -64,10 +62,8 @@ func GitGcRepos(ctx context.Context, timeout time.Duration, args ...git.CmdArg) if err := db.Iterate( ctx, - new(repo_model.Repository), builder.Gt{"id": 0}, - func(idx int, bean interface{}) error { - repo := bean.(*repo_model.Repository) + func(ctx context.Context, repo *repo_model.Repository) error { select { case <-ctx.Done(): return db.ErrCancelledf("before GC of %s", repo.FullName()) @@ -113,10 +109,8 @@ func gatherMissingRepoRecords(ctx context.Context) ([]*repo_model.Repository, er repos := make([]*repo_model.Repository, 0, 10) if err := db.Iterate( ctx, - new(repo_model.Repository), builder.Gt{"id": 0}, - func(idx int, bean interface{}) error { - repo := bean.(*repo_model.Repository) + func(ctx context.Context, repo *repo_model.Repository) error { select { case <-ctx.Done(): return db.ErrCancelledf("during gathering missing repo records before checking %s", repo.FullName()) diff --git a/services/repository/hooks.go b/services/repository/hooks.go index d326cd26b1..d29384e012 100644 --- a/services/repository/hooks.go +++ b/services/repository/hooks.go @@ -25,10 +25,8 @@ func SyncRepositoryHooks(ctx context.Context) error { if err := db.Iterate( ctx, - new(repo_model.Repository), builder.Gt{"id": 0}, - func(idx int, bean interface{}) error { - repo := bean.(*repo_model.Repository) + func(ctx context.Context, repo *repo_model.Repository) error { select { case <-ctx.Done(): return db.ErrCancelledf("before sync repository hooks for %s", repo.FullName()) diff --git a/templates/install.tmpl b/templates/install.tmpl index 36f58218d4..8d6918e6a2 100644 --- a/templates/install.tmpl +++ b/templates/install.tmpl @@ -162,6 +162,13 @@ {{.locale.Tr "install.log_root_path_helper"}} +
+ +
+ +
+ {{.locale.Tr "install.enable_update_checker_helper"}} +
diff --git a/web_src/js/markup/mermaid.js b/web_src/js/markup/mermaid.js index 62de9a3aae..984946045d 100644 --- a/web_src/js/markup/mermaid.js +++ b/web_src/js/markup/mermaid.js @@ -2,6 +2,7 @@ import {isDarkTheme} from '../utils.js'; const {mermaidMaxSourceCharacters} = window.config; const iframeCss = ` + :root {color-scheme: normal} body {margin: 0; padding: 0} #mermaid {display: block; margin: 0 auto} `; diff --git a/web_src/less/markup/content.less b/web_src/less/markup/content.less index 7ee55ea7f8..80c6267af8 100644 --- a/web_src/less/markup/content.less +++ b/web_src/less/markup/content.less @@ -537,6 +537,7 @@ width: 100%; height: var(--height-loading); // actual height is set in JS after loading overflow: hidden; + color-scheme: normal; // match the value inside the iframe to allow it to become transparent } .markup-block-error {