Merge branch 'main' into access-token-scope
This commit is contained in:
commit
b6f6ad4cf0
40 changed files with 136 additions and 248 deletions
|
@ -83,35 +83,35 @@ var CmdMigrateStorage = cli.Command{
|
||||||
}
|
}
|
||||||
|
|
||||||
func migrateAttachments(ctx context.Context, dstStorage storage.ObjectStorage) error {
|
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())
|
_, err := storage.Copy(dstStorage, attach.RelativePath(), storage.Attachments, attach.RelativePath())
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func migrateLFS(ctx context.Context, dstStorage storage.ObjectStorage) error {
|
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())
|
_, err := storage.Copy(dstStorage, mo.RelativePath(), storage.LFS, mo.RelativePath())
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func migrateAvatars(ctx context.Context, dstStorage storage.ObjectStorage) error {
|
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())
|
_, err := storage.Copy(dstStorage, user.CustomAvatarRelativePath(), storage.Avatars, user.CustomAvatarRelativePath())
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func migrateRepoAvatars(ctx context.Context, dstStorage storage.ObjectStorage) error {
|
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())
|
_, err := storage.Copy(dstStorage, repo.CustomAvatarRelativePath(), storage.RepoAvatars, repo.CustomAvatarRelativePath())
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func migrateRepoArchivers(ctx context.Context, dstStorage storage.ObjectStorage) error {
|
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()
|
p := archiver.RelativePath()
|
||||||
_, err := storage.Copy(dstStorage, p, storage.RepoArchives, p)
|
_, err := storage.Copy(dstStorage, p, storage.RepoArchives, p)
|
||||||
return err
|
return err
|
||||||
|
@ -119,7 +119,7 @@ func migrateRepoArchivers(ctx context.Context, dstStorage storage.ObjectStorage)
|
||||||
}
|
}
|
||||||
|
|
||||||
func migratePackages(ctx context.Context, dstStorage storage.ObjectStorage) error {
|
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))
|
p := packages_module.KeyToRelativePath(packages_module.BlobHash256Key(pb.HashSHA256))
|
||||||
_, err := storage.Copy(dstStorage, p, storage.Packages, p)
|
_, err := storage.Copy(dstStorage, p, storage.Packages, p)
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -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:<USERNAME>/gitea.git
|
|
||||||
git fetch --all --prune
|
|
||||||
```
|
|
||||||
|
|
||||||
然后你就可以开始开发了。你可以看一下 `Makefile` 的内容。`make test` 可以运行测试程序, `make build` 将生成一个 `gitea` 可运行文件在根目录。如果你的提交比较复杂,尽量多写一些单元测试代码。
|
|
||||||
|
|
||||||
好了,到这里你已经设置好了所有的开发 Gitea 所需的环境。欢迎成为 Gitea 的 Contributor。
|
|
|
@ -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`.
|
|
|
@ -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` 命令即可。
|
|
|
@ -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) 下载
|
|
|
@ -8,6 +8,6 @@ draft: false
|
||||||
menu:
|
menu:
|
||||||
sidebar:
|
sidebar:
|
||||||
name: "开发者"
|
name: "开发者"
|
||||||
weight: 50
|
weight: 55
|
||||||
identifier: "developers"
|
identifier: "developers"
|
||||||
---
|
---
|
||||||
|
|
|
@ -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/)
|
- `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/)
|
- `node` {{< min-node-version >}} or higher with `npm`, see [here](https://nodejs.org/en/download/)
|
||||||
- `make`, see <a href='{{< relref "doc/developers/hacking-on-gitea.en-us.md" >}}#installing-make'>here</a>
|
- `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)
|
Various [make tasks](https://github.com/go-gitea/gitea/blob/main/Makefile)
|
||||||
are provided to keep the build process as simple as possible.
|
are provided to keep the build process as simple as possible.
|
||||||
|
|
|
@ -53,7 +53,7 @@ git checkout pr-xyz
|
||||||
|
|
||||||
## Compilation
|
## 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. <a href='{{< relref "doc/advanced/make.fr-fr.md" >}}'>Voyez ici comment obtenir Make</a>. 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.
|
* `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.
|
* `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.
|
||||||
|
|
|
@ -54,7 +54,7 @@ git checkout v{{< version >}}
|
||||||
|
|
||||||
- `go` {{< min-go-version >}} 或以上版本, 详见[这里](https://golang.google.cn/doc/install)
|
- `go` {{< min-go-version >}} 或以上版本, 详见[这里](https://golang.google.cn/doc/install)
|
||||||
- `node` {{< min-node-version >}} 或以上版本,并且安装 `npm`, 详见[这里](https://nodejs.org/zh-cn/download/)
|
- `node` {{< min-node-version >}} 或以上版本,并且安装 `npm`, 详见[这里](https://nodejs.org/zh-cn/download/)
|
||||||
- `make`, 详见[这里]({{< relref "make.zh-cn.md" >}})</a>
|
- `make`, 详见[这里]({{< relref "doc/developers/hacking-on-gitea.zh-cn.md" >}})</a>
|
||||||
|
|
||||||
各种可用的 [make 任务](https://github.com/go-gitea/gitea/blob/main/Makefile)
|
各种可用的 [make 任务](https://github.com/go-gitea/gitea/blob/main/Makefile)
|
||||||
可以用来使编译过程更方便。
|
可以用来使编译过程更方便。
|
||||||
|
|
|
@ -47,7 +47,8 @@ Directly use SMTP server as relay. This option is useful if you don't want to se
|
||||||
ENABLED = true
|
ENABLED = true
|
||||||
FROM = gitea@mydomain.com
|
FROM = gitea@mydomain.com
|
||||||
MAILER_TYPE = smtp
|
MAILER_TYPE = smtp
|
||||||
HOST = mail.mydomain.com:587
|
SMTP_ADDR = mail.mydomain.com
|
||||||
|
SMTP_PORT = 587
|
||||||
IS_TLS_ENABLED = true
|
IS_TLS_ENABLED = true
|
||||||
USER = gitea@mydomain.com
|
USER = gitea@mydomain.com
|
||||||
PASSWD = `password`
|
PASSWD = `password`
|
||||||
|
@ -75,7 +76,8 @@ The following configuration should work with GMail's SMTP server:
|
||||||
```ini
|
```ini
|
||||||
[mailer]
|
[mailer]
|
||||||
ENABLED = true
|
ENABLED = true
|
||||||
HOST = smtp.gmail.com:465
|
SMTP_ADDR = smtp.gmail.com
|
||||||
|
SMTP_PORT = 465
|
||||||
FROM = example@gmail.com
|
FROM = example@gmail.com
|
||||||
USER = example@gmail.com
|
USER = example@gmail.com
|
||||||
PASSWD = ***
|
PASSWD = ***
|
||||||
|
|
3
docs/static/_redirects
vendored
3
docs/static/_redirects
vendored
|
@ -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/ci-cd/ /en-us/integrations/ 302!
|
||||||
/en-us/third-party-tools/ /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!
|
/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!
|
/en-us/upgrade/ /en-us/upgrade-from-gitea/ 302!
|
||||||
/fr-fr/upgrade/ /fr-fr/upgrade-from-gitea/ 302!
|
/fr-fr/upgrade/ /fr-fr/upgrade-from-gitea/ 302!
|
||||||
/zh-cn/upgrade/ /zh-cn/upgrade-from-gitea/ 302!
|
/zh-cn/upgrade/ /zh-cn/upgrade-from-gitea/ 302!
|
||||||
|
|
|
@ -8,9 +8,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
|
|
||||||
"xorm.io/builder"
|
|
||||||
"xorm.io/xorm/schemas"
|
"xorm.io/xorm/schemas"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -121,13 +118,6 @@ func WithTx(f func(ctx context.Context) error, stdCtx ...context.Context) error
|
||||||
return sess.Commit()
|
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
|
// Insert inserts records into database
|
||||||
func Insert(ctx context.Context, beans ...interface{}) error {
|
func Insert(ctx context.Context, beans ...interface{}) error {
|
||||||
_, err := GetEngine(ctx).Insert(beans...)
|
_, err := GetEngine(ctx).Insert(beans...)
|
||||||
|
|
|
@ -8,25 +8,30 @@ import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IterateObjects iterate all the Bean object
|
// Iterate iterate all the Bean object
|
||||||
func IterateObjects[Object any](ctx context.Context, f func(repo *Object) error) error {
|
func Iterate[Bean any](ctx context.Context, cond builder.Cond, f func(ctx context.Context, bean *Bean) error) error {
|
||||||
var start int
|
var start int
|
||||||
batchSize := setting.Database.IterateBufferSize
|
batchSize := setting.Database.IterateBufferSize
|
||||||
sess := GetEngine(ctx)
|
sess := GetEngine(ctx)
|
||||||
for {
|
for {
|
||||||
repos := make([]*Object, 0, batchSize)
|
beans := make([]*Bean, 0, batchSize)
|
||||||
if err := sess.Limit(batchSize, start).Find(&repos); err != nil {
|
if cond != nil {
|
||||||
|
sess = sess.Where(cond)
|
||||||
|
}
|
||||||
|
if err := sess.Limit(batchSize, start).Find(&beans); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(repos) == 0 {
|
if len(beans) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
start += len(repos)
|
start += len(beans)
|
||||||
|
|
||||||
for _, repo := range repos {
|
for _, bean := range beans {
|
||||||
if err := f(repo); err != nil {
|
if err := f(ctx, bean); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
44
models/db/iterate_test.go
Normal file
44
models/db/iterate_test.go
Normal file
|
@ -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)
|
||||||
|
}
|
|
@ -18,10 +18,9 @@ import (
|
||||||
func iterateUserAccounts(ctx context.Context, each func(*user.User) error) error {
|
func iterateUserAccounts(ctx context.Context, each func(*user.User) error) error {
|
||||||
err := db.Iterate(
|
err := db.Iterate(
|
||||||
ctx,
|
ctx,
|
||||||
new(user.User),
|
|
||||||
builder.Gt{"id": 0},
|
builder.Gt{"id": 0},
|
||||||
func(idx int, bean interface{}) error {
|
func(ctx context.Context, bean *user.User) error {
|
||||||
return each(bean.(*user.User))
|
return each(bean)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -269,13 +269,10 @@ func fixBrokenRepoUnits16961(ctx context.Context, logger log.Logger, autofix boo
|
||||||
|
|
||||||
err := db.Iterate(
|
err := db.Iterate(
|
||||||
ctx,
|
ctx,
|
||||||
new(RepoUnit),
|
|
||||||
builder.Gt{
|
builder.Gt{
|
||||||
"id": 0,
|
"id": 0,
|
||||||
},
|
},
|
||||||
func(idx int, bean interface{}) error {
|
func(ctx context.Context, unit *RepoUnit) error {
|
||||||
unit := bean.(*RepoUnit)
|
|
||||||
|
|
||||||
bs := unit.Config
|
bs := unit.Config
|
||||||
repoUnit := &repo_model.RepoUnit{
|
repoUnit := &repo_model.RepoUnit{
|
||||||
ID: unit.ID,
|
ID: unit.ID,
|
||||||
|
|
|
@ -21,10 +21,9 @@ import (
|
||||||
func iteratePRs(ctx context.Context, repo *repo_model.Repository, each func(*repo_model.Repository, *issues_model.PullRequest) error) error {
|
func iteratePRs(ctx context.Context, repo *repo_model.Repository, each func(*repo_model.Repository, *issues_model.PullRequest) error) error {
|
||||||
return db.Iterate(
|
return db.Iterate(
|
||||||
ctx,
|
ctx,
|
||||||
new(issues_model.PullRequest),
|
|
||||||
builder.Eq{"base_repo_id": repo.ID},
|
builder.Eq{"base_repo_id": repo.ID},
|
||||||
func(idx int, bean interface{}) error {
|
func(ctx context.Context, bean *issues_model.PullRequest) error {
|
||||||
return each(repo, bean.(*issues_model.PullRequest))
|
return each(repo, bean)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,10 +30,9 @@ import (
|
||||||
func iterateRepositories(ctx context.Context, each func(*repo_model.Repository) error) error {
|
func iterateRepositories(ctx context.Context, each func(*repo_model.Repository) error) error {
|
||||||
err := db.Iterate(
|
err := db.Iterate(
|
||||||
ctx,
|
ctx,
|
||||||
new(repo_model.Repository),
|
|
||||||
builder.Gt{"id": 0},
|
builder.Gt{"id": 0},
|
||||||
func(idx int, bean interface{}) error {
|
func(ctx context.Context, bean *repo_model.Repository) error {
|
||||||
return each(bean.(*repo_model.Repository))
|
return each(bean)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/markup/markdown"
|
"code.gitea.io/gitea/modules/markup/markdown"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
@ -95,14 +96,27 @@ func unmarshal(filename string, content []byte) (*api.IssueTemplate, error) {
|
||||||
}{}
|
}{}
|
||||||
|
|
||||||
if typ := it.Type(); typ == api.IssueTemplateTypeMarkdown {
|
if typ := it.Type(); typ == api.IssueTemplateTypeMarkdown {
|
||||||
templateBody, err := markdown.ExtractMetadata(string(content), it)
|
if templateBody, err := markdown.ExtractMetadata(string(content), it); err != nil {
|
||||||
if err != nil {
|
// The only thing we know here is that we can't extract metadata from the content,
|
||||||
return nil, err
|
// it's hard to tell if metadata doesn't exist or metadata isn't valid.
|
||||||
}
|
// There's an example template:
|
||||||
it.Content = templateBody
|
//
|
||||||
if it.About == "" {
|
// ---
|
||||||
if _, err := markdown.ExtractMetadata(string(content), compatibleTemplate); err == nil && compatibleTemplate.About != "" {
|
// # Title
|
||||||
it.About = compatibleTemplate.About
|
// ---
|
||||||
|
// 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 {
|
} else if typ == api.IssueTemplateTypeYaml {
|
||||||
|
|
|
@ -170,7 +170,7 @@ func (it IssueTemplate) Type() IssueTemplateType {
|
||||||
if ext := filepath.Ext(it.FileName); ext == ".md" {
|
if ext := filepath.Ext(it.FileName); ext == ".md" {
|
||||||
return IssueTemplateTypeMarkdown
|
return IssueTemplateTypeMarkdown
|
||||||
} else if ext == ".yaml" || ext == ".yml" {
|
} else if ext == ".yaml" || ext == ".yml" {
|
||||||
return "yaml"
|
return IssueTemplateTypeYaml
|
||||||
}
|
}
|
||||||
return IssueTemplateTypeYaml
|
return ""
|
||||||
}
|
}
|
||||||
|
|
|
@ -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'.
|
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 = 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.
|
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]
|
[home]
|
||||||
uname_holder = Username or Email Address
|
uname_holder = Username or Email Address
|
||||||
|
|
|
@ -451,7 +451,7 @@ SSPIDefaultLanguage=默认语言
|
||||||
|
|
||||||
require_error=不能为空。
|
require_error=不能为空。
|
||||||
alpha_dash_error=应该只包含字母数字、破折号 ('-') 和下划线 ('_') 字符。
|
alpha_dash_error=应该只包含字母数字、破折号 ('-') 和下划线 ('_') 字符。
|
||||||
alpha_dash_dot_error=' 应该只包含字母数字, 破折号 ('-'), 下划线 ('_') 和点 ('. ') 。
|
alpha_dash_dot_error=` 应该只包含字母数字, 破折号 ('-'), 下划线 ('_') 和点 ('. ') 。`
|
||||||
git_ref_name_error=` 必须是格式良好的 git 引用名称。`
|
git_ref_name_error=` 必须是格式良好的 git 引用名称。`
|
||||||
size_error=长度必须为 %s。
|
size_error=长度必须为 %s。
|
||||||
min_size_error=长度最小为 %s 个字符。
|
min_size_error=长度最小为 %s 个字符。
|
||||||
|
|
|
@ -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_ALLOW_CREATE_ORGANIZATION").SetValue(fmt.Sprint(form.DefaultAllowCreateOrganization))
|
||||||
cfg.Section("service").Key("DEFAULT_ENABLE_TIMETRACKING").SetValue(fmt.Sprint(form.DefaultEnableTimetracking))
|
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("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")
|
cfg.Section("").Key("RUN_MODE").SetValue("prod")
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
package private
|
package private
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
stdCtx "context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -60,7 +61,7 @@ func SendEmail(ctx *context.PrivateContext) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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 {
|
if len(user.Email) > 0 && user.IsActive {
|
||||||
emails = append(emails, user.Email)
|
emails = append(emails, user.Email)
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,7 @@ type InstallForm struct {
|
||||||
DefaultKeepEmailPrivate bool
|
DefaultKeepEmailPrivate bool
|
||||||
DefaultAllowCreateOrganization bool
|
DefaultAllowCreateOrganization bool
|
||||||
DefaultEnableTimetracking bool
|
DefaultEnableTimetracking bool
|
||||||
|
EnableUpdateChecker bool
|
||||||
NoReplyAddress string
|
NoReplyAddress string
|
||||||
|
|
||||||
PasswordAlgorithm string
|
PasswordAlgorithm string
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -218,21 +219,21 @@ func DeleteUnadoptedRepository(doer, u *user_model.User, repoName string) error
|
||||||
return util.RemoveAll(repoPath)
|
return util.RemoveAll(repoPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
type unadoptedRrepositories struct {
|
type unadoptedRepositories struct {
|
||||||
repositories []string
|
repositories []string
|
||||||
index int
|
index int
|
||||||
start int
|
start int
|
||||||
end int
|
end int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (unadopted *unadoptedRrepositories) add(repository string) {
|
func (unadopted *unadoptedRepositories) add(repository string) {
|
||||||
if unadopted.index >= unadopted.start && unadopted.index < unadopted.end {
|
if unadopted.index >= unadopted.start && unadopted.index < unadopted.end {
|
||||||
unadopted.repositories = append(unadopted.repositories, repository)
|
unadopted.repositories = append(unadopted.repositories, repository)
|
||||||
}
|
}
|
||||||
unadopted.index++
|
unadopted.index++
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkUnadoptedRepositories(userName string, repoNamesToCheck []string, unadopted *unadoptedRrepositories) error {
|
func checkUnadoptedRepositories(userName string, repoNamesToCheck []string, unadopted *unadoptedRepositories) error {
|
||||||
if len(repoNamesToCheck) == 0 {
|
if len(repoNamesToCheck) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -264,7 +265,7 @@ func checkUnadoptedRepositories(userName string, repoNamesToCheck []string, unad
|
||||||
}
|
}
|
||||||
for _, repoName := range repoNamesToCheck {
|
for _, repoName := range repoNamesToCheck {
|
||||||
if !repoNames.Contains(repoName) {
|
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
|
return nil
|
||||||
|
@ -292,7 +293,7 @@ func ListUnadoptedRepositories(query string, opts *db.ListOptions) ([]string, in
|
||||||
var repoNamesToCheck []string
|
var repoNamesToCheck []string
|
||||||
|
|
||||||
start := (opts.Page - 1) * opts.PageSize
|
start := (opts.Page - 1) * opts.PageSize
|
||||||
unadopted := &unadoptedRrepositories{
|
unadopted := &unadoptedRepositories{
|
||||||
repositories: make([]string, 0, opts.PageSize),
|
repositories: make([]string, 0, opts.PageSize),
|
||||||
start: start,
|
start: start,
|
||||||
end: start + opts.PageSize,
|
end: start + opts.PageSize,
|
||||||
|
|
|
@ -19,7 +19,7 @@ import (
|
||||||
func TestCheckUnadoptedRepositories_Add(t *testing.T) {
|
func TestCheckUnadoptedRepositories_Add(t *testing.T) {
|
||||||
start := 10
|
start := 10
|
||||||
end := 20
|
end := 20
|
||||||
unadopted := &unadoptedRrepositories{
|
unadopted := &unadoptedRepositories{
|
||||||
start: start,
|
start: start,
|
||||||
end: end,
|
end: end,
|
||||||
index: 0,
|
index: 0,
|
||||||
|
@ -39,7 +39,7 @@ func TestCheckUnadoptedRepositories(t *testing.T) {
|
||||||
//
|
//
|
||||||
// Non existent user
|
// Non existent user
|
||||||
//
|
//
|
||||||
unadopted := &unadoptedRrepositories{start: 0, end: 100}
|
unadopted := &unadoptedRepositories{start: 0, end: 100}
|
||||||
err := checkUnadoptedRepositories("notauser", []string{"repo"}, unadopted)
|
err := checkUnadoptedRepositories("notauser", []string{"repo"}, unadopted)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, 0, len(unadopted.repositories))
|
assert.Equal(t, 0, len(unadopted.repositories))
|
||||||
|
@ -50,14 +50,14 @@ func TestCheckUnadoptedRepositories(t *testing.T) {
|
||||||
userName := "user2"
|
userName := "user2"
|
||||||
repoName := "repo2"
|
repoName := "repo2"
|
||||||
unadoptedRepoName := "unadopted"
|
unadoptedRepoName := "unadopted"
|
||||||
unadopted = &unadoptedRrepositories{start: 0, end: 100}
|
unadopted = &unadoptedRepositories{start: 0, end: 100}
|
||||||
err = checkUnadoptedRepositories(userName, []string{repoName, unadoptedRepoName}, unadopted)
|
err = checkUnadoptedRepositories(userName, []string{repoName, unadoptedRepoName}, unadopted)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, []string{path.Join(userName, unadoptedRepoName)}, unadopted.repositories)
|
assert.Equal(t, []string{path.Join(userName, unadoptedRepoName)}, unadopted.repositories)
|
||||||
//
|
//
|
||||||
// Existing (adopted) repository is not returned
|
// Existing (adopted) repository is not returned
|
||||||
//
|
//
|
||||||
unadopted = &unadoptedRrepositories{start: 0, end: 100}
|
unadopted = &unadoptedRepositories{start: 0, end: 100}
|
||||||
err = checkUnadoptedRepositories(userName, []string{repoName}, unadopted)
|
err = checkUnadoptedRepositories(userName, []string{repoName}, unadopted)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, 0, len(unadopted.repositories))
|
assert.Equal(t, 0, len(unadopted.repositories))
|
||||||
|
|
|
@ -96,7 +96,7 @@ func DeleteAvatar(repo *repo_model.Repository) error {
|
||||||
|
|
||||||
// RemoveRandomAvatars removes the randomly generated avatars that were created for repositories
|
// RemoveRandomAvatars removes the randomly generated avatars that were created for repositories
|
||||||
func RemoveRandomAvatars(ctx context.Context) error {
|
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 {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return db.ErrCancelledf("before random avatars removed for %s", repository.FullName())
|
return db.ErrCancelledf("before random avatars removed for %s", repository.FullName())
|
||||||
|
|
|
@ -29,10 +29,8 @@ func GitFsck(ctx context.Context, timeout time.Duration, args []git.CmdArg) erro
|
||||||
|
|
||||||
if err := db.Iterate(
|
if err := db.Iterate(
|
||||||
ctx,
|
ctx,
|
||||||
new(repo_model.Repository),
|
|
||||||
builder.Expr("id>0 AND is_fsck_enabled=?", true),
|
builder.Expr("id>0 AND is_fsck_enabled=?", true),
|
||||||
func(idx int, bean interface{}) error {
|
func(ctx context.Context, repo *repo_model.Repository) error {
|
||||||
repo := bean.(*repo_model.Repository)
|
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return db.ErrCancelledf("before fsck of %s", repo.FullName())
|
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(
|
if err := db.Iterate(
|
||||||
ctx,
|
ctx,
|
||||||
new(repo_model.Repository),
|
|
||||||
builder.Gt{"id": 0},
|
builder.Gt{"id": 0},
|
||||||
func(idx int, bean interface{}) error {
|
func(ctx context.Context, repo *repo_model.Repository) error {
|
||||||
repo := bean.(*repo_model.Repository)
|
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return db.ErrCancelledf("before GC of %s", repo.FullName())
|
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)
|
repos := make([]*repo_model.Repository, 0, 10)
|
||||||
if err := db.Iterate(
|
if err := db.Iterate(
|
||||||
ctx,
|
ctx,
|
||||||
new(repo_model.Repository),
|
|
||||||
builder.Gt{"id": 0},
|
builder.Gt{"id": 0},
|
||||||
func(idx int, bean interface{}) error {
|
func(ctx context.Context, repo *repo_model.Repository) error {
|
||||||
repo := bean.(*repo_model.Repository)
|
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return db.ErrCancelledf("during gathering missing repo records before checking %s", repo.FullName())
|
return db.ErrCancelledf("during gathering missing repo records before checking %s", repo.FullName())
|
||||||
|
|
|
@ -25,10 +25,8 @@ func SyncRepositoryHooks(ctx context.Context) error {
|
||||||
|
|
||||||
if err := db.Iterate(
|
if err := db.Iterate(
|
||||||
ctx,
|
ctx,
|
||||||
new(repo_model.Repository),
|
|
||||||
builder.Gt{"id": 0},
|
builder.Gt{"id": 0},
|
||||||
func(idx int, bean interface{}) error {
|
func(ctx context.Context, repo *repo_model.Repository) error {
|
||||||
repo := bean.(*repo_model.Repository)
|
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return db.ErrCancelledf("before sync repository hooks for %s", repo.FullName())
|
return db.ErrCancelledf("before sync repository hooks for %s", repo.FullName())
|
||||||
|
|
|
@ -162,6 +162,13 @@
|
||||||
<input id="log_root_path" name="log_root_path" value="{{.log_root_path}}" placeholder="log" required>
|
<input id="log_root_path" name="log_root_path" value="{{.log_root_path}}" placeholder="log" required>
|
||||||
<span class="help">{{.locale.Tr "install.log_root_path_helper"}}</span>
|
<span class="help">{{.locale.Tr "install.log_root_path_helper"}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="inline field">
|
||||||
|
<label for="enable_update_checker">{{.locale.Tr "install.enable_update_checker"}}</label>
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<input name="enable_update_checker" type="checkbox">
|
||||||
|
</div>
|
||||||
|
<span class="help">{{.locale.Tr "install.enable_update_checker_helper"}}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<!-- Optional Settings -->
|
<!-- Optional Settings -->
|
||||||
|
|
|
@ -2,6 +2,7 @@ import {isDarkTheme} from '../utils.js';
|
||||||
const {mermaidMaxSourceCharacters} = window.config;
|
const {mermaidMaxSourceCharacters} = window.config;
|
||||||
|
|
||||||
const iframeCss = `
|
const iframeCss = `
|
||||||
|
:root {color-scheme: normal}
|
||||||
body {margin: 0; padding: 0}
|
body {margin: 0; padding: 0}
|
||||||
#mermaid {display: block; margin: 0 auto}
|
#mermaid {display: block; margin: 0 auto}
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -537,6 +537,7 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: var(--height-loading); // actual height is set in JS after loading
|
height: var(--height-loading); // actual height is set in JS after loading
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
color-scheme: normal; // match the value inside the iframe to allow it to become transparent
|
||||||
}
|
}
|
||||||
|
|
||||||
.markup-block-error {
|
.markup-block-error {
|
||||||
|
|
Loading…
Add table
Reference in a new issue