mirror of
https://github.com/go-gitea/gitea
synced 2024-11-11 04:34:25 +00:00
Merge branch 'main' into allow-force-push-protected-branches
This commit is contained in:
commit
be622e5db9
18
assets/go-licenses.json
generated
18
assets/go-licenses.json
generated
File diff suppressed because one or more lines are too long
@ -16,8 +16,7 @@ var (
|
|||||||
// CmdActions represents the available actions sub-commands.
|
// CmdActions represents the available actions sub-commands.
|
||||||
CmdActions = &cli.Command{
|
CmdActions = &cli.Command{
|
||||||
Name: "actions",
|
Name: "actions",
|
||||||
Usage: "",
|
Usage: "Manage Gitea Actions",
|
||||||
Description: "Commands for managing Gitea Actions",
|
|
||||||
Subcommands: []*cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
subcmdActionsGenRunnerToken,
|
subcmdActionsGenRunnerToken,
|
||||||
},
|
},
|
||||||
|
@ -21,7 +21,7 @@ var (
|
|||||||
// CmdAdmin represents the available admin sub-command.
|
// CmdAdmin represents the available admin sub-command.
|
||||||
CmdAdmin = &cli.Command{
|
CmdAdmin = &cli.Command{
|
||||||
Name: "admin",
|
Name: "admin",
|
||||||
Usage: "Command line interface to perform common administrative operations",
|
Usage: "Perform common administrative operations",
|
||||||
Subcommands: []*cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
subcmdUser,
|
subcmdUser,
|
||||||
subcmdRepoSyncReleases,
|
subcmdRepoSyncReleases,
|
||||||
|
@ -26,7 +26,7 @@ import (
|
|||||||
// CmdDoctor represents the available doctor sub-command.
|
// CmdDoctor represents the available doctor sub-command.
|
||||||
var CmdDoctor = &cli.Command{
|
var CmdDoctor = &cli.Command{
|
||||||
Name: "doctor",
|
Name: "doctor",
|
||||||
Usage: "Diagnose and optionally fix problems",
|
Usage: "Diagnose and optionally fix problems, convert or re-create database tables",
|
||||||
Description: "A command to diagnose problems with the current Gitea instance according to the given configuration. Some problems can optionally be fixed by modifying the database or data storage.",
|
Description: "A command to diagnose problems with the current Gitea instance according to the given configuration. Some problems can optionally be fixed by modifying the database or data storage.",
|
||||||
|
|
||||||
Subcommands: []*cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
|
@ -18,7 +18,7 @@ var (
|
|||||||
// CmdGenerate represents the available generate sub-command.
|
// CmdGenerate represents the available generate sub-command.
|
||||||
CmdGenerate = &cli.Command{
|
CmdGenerate = &cli.Command{
|
||||||
Name: "generate",
|
Name: "generate",
|
||||||
Usage: "Command line interface for running generators",
|
Usage: "Generate Gitea's secrets/keys/tokens",
|
||||||
Subcommands: []*cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
subcmdSecret,
|
subcmdSecret,
|
||||||
},
|
},
|
||||||
|
@ -31,8 +31,8 @@ var (
|
|||||||
// CmdHook represents the available hooks sub-command.
|
// CmdHook represents the available hooks sub-command.
|
||||||
CmdHook = &cli.Command{
|
CmdHook = &cli.Command{
|
||||||
Name: "hook",
|
Name: "hook",
|
||||||
Usage: "Delegate commands to corresponding Git hooks",
|
Usage: "(internal) Should only be called by Git",
|
||||||
Description: "This should only be called by Git",
|
Description: "Delegate commands to corresponding Git hooks",
|
||||||
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
||||||
Subcommands: []*cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
subcmdHookPreReceive,
|
subcmdHookPreReceive,
|
||||||
@ -377,7 +377,7 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
newCommitIDs[count] = string(fields[1])
|
newCommitIDs[count] = string(fields[1])
|
||||||
refFullNames[count] = git.RefName(fields[2])
|
refFullNames[count] = git.RefName(fields[2])
|
||||||
|
|
||||||
commitID, _ := git.IDFromString(newCommitIDs[count])
|
commitID, _ := git.NewIDFromString(newCommitIDs[count])
|
||||||
if refFullNames[count] == git.BranchPrefix+"master" && !commitID.IsZero() && count == total {
|
if refFullNames[count] == git.BranchPrefix+"master" && !commitID.IsZero() && count == total {
|
||||||
masterPushed = true
|
masterPushed = true
|
||||||
}
|
}
|
||||||
@ -671,7 +671,7 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
commitID, _ := git.IDFromString(rs.OldOID)
|
commitID, _ := git.NewIDFromString(rs.OldOID)
|
||||||
if !commitID.IsZero() {
|
if !commitID.IsZero() {
|
||||||
err = writeDataPktLine(ctx, os.Stdout, []byte("option old-oid "+rs.OldOID))
|
err = writeDataPktLine(ctx, os.Stdout, []byte("option old-oid "+rs.OldOID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -17,7 +17,8 @@ import (
|
|||||||
// CmdKeys represents the available keys sub-command
|
// CmdKeys represents the available keys sub-command
|
||||||
var CmdKeys = &cli.Command{
|
var CmdKeys = &cli.Command{
|
||||||
Name: "keys",
|
Name: "keys",
|
||||||
Usage: "This command queries the Gitea database to get the authorized command for a given ssh key fingerprint",
|
Usage: "(internal) Should only be called by SSH server",
|
||||||
|
Description: "Queries the Gitea database to get the authorized command for a given ssh key fingerprint",
|
||||||
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
||||||
Action: runKeys,
|
Action: runKeys,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
|
21
cmd/main.go
21
cmd/main.go
@ -10,12 +10,12 @@ import (
|
|||||||
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/util"
|
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// cmdHelp is our own help subcommand with more information
|
// cmdHelp is our own help subcommand with more information
|
||||||
|
// Keep in mind that the "./gitea help"(subcommand) is different from "./gitea --help"(flag), the flag doesn't parse the config or output "DEFAULT CONFIGURATION:" information
|
||||||
func cmdHelp() *cli.Command {
|
func cmdHelp() *cli.Command {
|
||||||
c := &cli.Command{
|
c := &cli.Command{
|
||||||
Name: "help",
|
Name: "help",
|
||||||
@ -47,16 +47,10 @@ DEFAULT CONFIGURATION:
|
|||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
var helpFlag = cli.HelpFlag
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// cli.HelpFlag = nil TODO: after https://github.com/urfave/cli/issues/1794 we can use this
|
|
||||||
}
|
|
||||||
|
|
||||||
func appGlobalFlags() []cli.Flag {
|
func appGlobalFlags() []cli.Flag {
|
||||||
return []cli.Flag{
|
return []cli.Flag{
|
||||||
// make the builtin flags at the top
|
// make the builtin flags at the top
|
||||||
helpFlag,
|
cli.HelpFlag,
|
||||||
|
|
||||||
// shared configuration flags, they are for global and for each sub-command at the same time
|
// shared configuration flags, they are for global and for each sub-command at the same time
|
||||||
// eg: such command is valid: "./gitea --config /tmp/app.ini web --config /tmp/app.ini", while it's discouraged indeed
|
// eg: such command is valid: "./gitea --config /tmp/app.ini web --config /tmp/app.ini", while it's discouraged indeed
|
||||||
@ -121,20 +115,22 @@ func prepareWorkPathAndCustomConf(action cli.ActionFunc) func(ctx *cli.Context)
|
|||||||
func NewMainApp(version, versionExtra string) *cli.App {
|
func NewMainApp(version, versionExtra string) *cli.App {
|
||||||
app := cli.NewApp()
|
app := cli.NewApp()
|
||||||
app.Name = "Gitea"
|
app.Name = "Gitea"
|
||||||
|
app.HelpName = "gitea"
|
||||||
app.Usage = "A painless self-hosted Git service"
|
app.Usage = "A painless self-hosted Git service"
|
||||||
app.Description = `By default, Gitea will start serving using the web-server with no argument, which can alternatively be run by running the subcommand "web".`
|
app.Description = `Gitea program contains "web" and other subcommands. If no subcommand is given, it starts the web server by default. Use "web" subcommand for more web server arguments, use other subcommands for other purposes.`
|
||||||
app.Version = version + versionExtra
|
app.Version = version + versionExtra
|
||||||
app.EnableBashCompletion = true
|
app.EnableBashCompletion = true
|
||||||
|
|
||||||
// these sub-commands need to use config file
|
// these sub-commands need to use config file
|
||||||
subCmdWithConfig := []*cli.Command{
|
subCmdWithConfig := []*cli.Command{
|
||||||
|
cmdHelp(), // the "help" sub-command was used to show the more information for "work path" and "custom config"
|
||||||
CmdWeb,
|
CmdWeb,
|
||||||
CmdServ,
|
CmdServ,
|
||||||
CmdHook,
|
CmdHook,
|
||||||
|
CmdKeys,
|
||||||
CmdDump,
|
CmdDump,
|
||||||
CmdAdmin,
|
CmdAdmin,
|
||||||
CmdMigrate,
|
CmdMigrate,
|
||||||
CmdKeys,
|
|
||||||
CmdDoctor,
|
CmdDoctor,
|
||||||
CmdManager,
|
CmdManager,
|
||||||
CmdEmbedded,
|
CmdEmbedded,
|
||||||
@ -142,13 +138,8 @@ func NewMainApp(version, versionExtra string) *cli.App {
|
|||||||
CmdDumpRepository,
|
CmdDumpRepository,
|
||||||
CmdRestoreRepository,
|
CmdRestoreRepository,
|
||||||
CmdActions,
|
CmdActions,
|
||||||
cmdHelp(), // the "help" sub-command was used to show the more information for "work path" and "custom config"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdConvert := util.ToPointer(*cmdDoctorConvert)
|
|
||||||
cmdConvert.Hidden = true // still support the legacy "./gitea doctor" by the hidden sub-command, remove it in next release
|
|
||||||
subCmdWithConfig = append(subCmdWithConfig, cmdConvert)
|
|
||||||
|
|
||||||
// these sub-commands do not need the config file, and they do not depend on any path or environment variable.
|
// these sub-commands do not need the config file, and they do not depend on any path or environment variable.
|
||||||
subCmdStandalone := []*cli.Command{
|
subCmdStandalone := []*cli.Command{
|
||||||
CmdCert,
|
CmdCert,
|
||||||
|
@ -42,7 +42,7 @@ const (
|
|||||||
// CmdServ represents the available serv sub-command.
|
// CmdServ represents the available serv sub-command.
|
||||||
var CmdServ = &cli.Command{
|
var CmdServ = &cli.Command{
|
||||||
Name: "serv",
|
Name: "serv",
|
||||||
Usage: "This command should only be called by SSH shell",
|
Usage: "(internal) Should only be called by SSH shell",
|
||||||
Description: "Serv provides access auth for repositories",
|
Description: "Serv provides access auth for repositories",
|
||||||
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
||||||
Action: runServ,
|
Action: runServ,
|
||||||
|
@ -17,7 +17,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/google/go-github/v53/github"
|
"github.com/google/go-github/v57/github"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
@ -1212,6 +1212,9 @@ LEVEL = Info
|
|||||||
;; Max size of files to be displayed (default is 8MiB)
|
;; Max size of files to be displayed (default is 8MiB)
|
||||||
;MAX_DISPLAY_FILE_SIZE = 8388608
|
;MAX_DISPLAY_FILE_SIZE = 8388608
|
||||||
;;
|
;;
|
||||||
|
;; Detect ambiguous unicode characters in file contents and show warnings on the UI
|
||||||
|
;AMBIGUOUS_UNICODE_DETECTION = true
|
||||||
|
;;
|
||||||
;; Whether the email of the user should be shown in the Explore Users page
|
;; Whether the email of the user should be shown in the Explore Users page
|
||||||
;SHOW_USER_EMAIL = true
|
;SHOW_USER_EMAIL = true
|
||||||
;;
|
;;
|
||||||
@ -1702,9 +1705,6 @@ LEVEL = Info
|
|||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;
|
;;
|
||||||
;; if the cache enabled
|
|
||||||
;ENABLED = true
|
|
||||||
;;
|
|
||||||
;; Either "memory", "redis", "memcache", or "twoqueue". default is "memory"
|
;; Either "memory", "redis", "memcache", or "twoqueue". default is "memory"
|
||||||
;ADAPTER = memory
|
;ADAPTER = memory
|
||||||
;;
|
;;
|
||||||
@ -1729,8 +1729,6 @@ LEVEL = Info
|
|||||||
;[cache.last_commit]
|
;[cache.last_commit]
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; if the cache enabled
|
|
||||||
;ENABLED = true
|
|
||||||
;;
|
;;
|
||||||
;; Time to keep items in cache if not used, default is 8760 hours.
|
;; Time to keep items in cache if not used, default is 8760 hours.
|
||||||
;; Setting it to -1 disables caching
|
;; Setting it to -1 disables caching
|
||||||
|
@ -220,6 +220,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
|||||||
- `THEMES`: **gitea-auto,gitea-light,gitea-dark**: All available themes. Allow users select personalized themes.
|
- `THEMES`: **gitea-auto,gitea-light,gitea-dark**: All available themes. Allow users select personalized themes.
|
||||||
regardless of the value of `DEFAULT_THEME`.
|
regardless of the value of `DEFAULT_THEME`.
|
||||||
- `MAX_DISPLAY_FILE_SIZE`: **8388608**: Max size of files to be displayed (default is 8MiB)
|
- `MAX_DISPLAY_FILE_SIZE`: **8388608**: Max size of files to be displayed (default is 8MiB)
|
||||||
|
- `AMBIGUOUS_UNICODE_DETECTION`: **true**: Detect ambiguous unicode characters in file contents and show warnings on the UI
|
||||||
- `REACTIONS`: All available reactions users can choose on issues/prs and comments
|
- `REACTIONS`: All available reactions users can choose on issues/prs and comments
|
||||||
Values can be emoji alias (:smile:) or a unicode emoji.
|
Values can be emoji alias (:smile:) or a unicode emoji.
|
||||||
For custom reactions, add a tightly cropped square image to public/assets/img/emoji/reaction_name.png
|
For custom reactions, add a tightly cropped square image to public/assets/img/emoji/reaction_name.png
|
||||||
@ -572,6 +573,7 @@ And the following unique queues:
|
|||||||
- off - do not check password complexity
|
- off - do not check password complexity
|
||||||
- `PASSWORD_CHECK_PWN`: **false**: Check [HaveIBeenPwned](https://haveibeenpwned.com/Passwords) to see if a password has been exposed.
|
- `PASSWORD_CHECK_PWN`: **false**: Check [HaveIBeenPwned](https://haveibeenpwned.com/Passwords) to see if a password has been exposed.
|
||||||
- `SUCCESSFUL_TOKENS_CACHE_SIZE`: **20**: Cache successful token hashes. API tokens are stored in the DB as pbkdf2 hashes however, this means that there is a potentially significant hashing load when there are multiple API operations. This cache will store the successfully hashed tokens in a LRU cache as a balance between performance and security.
|
- `SUCCESSFUL_TOKENS_CACHE_SIZE`: **20**: Cache successful token hashes. API tokens are stored in the DB as pbkdf2 hashes however, this means that there is a potentially significant hashing load when there are multiple API operations. This cache will store the successfully hashed tokens in a LRU cache as a balance between performance and security.
|
||||||
|
- `DISABLE_QUERY_AUTH_TOKEN`: **false**: Reject API tokens sent in URL query string (Accept Header-based API tokens only). This setting will default to `true` in Gitea 1.23 and be deprecated in Gitea 1.24.
|
||||||
|
|
||||||
## Camo (`camo`)
|
## Camo (`camo`)
|
||||||
|
|
||||||
@ -761,7 +763,6 @@ and
|
|||||||
|
|
||||||
## Cache (`cache`)
|
## Cache (`cache`)
|
||||||
|
|
||||||
- `ENABLED`: **true**: Enable the cache.
|
|
||||||
- `ADAPTER`: **memory**: Cache engine adapter, either `memory`, `redis`, `redis-cluster`, `twoqueue` or `memcache`. (`twoqueue` represents a size limited LRU cache.)
|
- `ADAPTER`: **memory**: Cache engine adapter, either `memory`, `redis`, `redis-cluster`, `twoqueue` or `memcache`. (`twoqueue` represents a size limited LRU cache.)
|
||||||
- `INTERVAL`: **60**: Garbage Collection interval (sec), for memory and twoqueue cache only.
|
- `INTERVAL`: **60**: Garbage Collection interval (sec), for memory and twoqueue cache only.
|
||||||
- `HOST`: **_empty_**: Connection string for `redis`, `redis-cluster` and `memcache`. For `twoqueue` sets configuration for the queue.
|
- `HOST`: **_empty_**: Connection string for `redis`, `redis-cluster` and `memcache`. For `twoqueue` sets configuration for the queue.
|
||||||
@ -773,7 +774,6 @@ and
|
|||||||
|
|
||||||
## Cache - LastCommitCache settings (`cache.last_commit`)
|
## Cache - LastCommitCache settings (`cache.last_commit`)
|
||||||
|
|
||||||
- `ENABLED`: **true**: Enable the cache.
|
|
||||||
- `ITEM_TTL`: **8760h**: Time to keep items in cache if not used, Setting it to -1 disables caching.
|
- `ITEM_TTL`: **8760h**: Time to keep items in cache if not used, Setting it to -1 disables caching.
|
||||||
- `COMMITS_COUNT`: **1000**: Only enable the cache when repository's commits count great than.
|
- `COMMITS_COUNT`: **1000**: Only enable the cache when repository's commits count great than.
|
||||||
|
|
||||||
|
@ -721,7 +721,6 @@ Gitea 创建以下非唯一队列:
|
|||||||
|
|
||||||
## 缓存 (`cache`)
|
## 缓存 (`cache`)
|
||||||
|
|
||||||
- `ENABLED`: **true**: 是否启用缓存。
|
|
||||||
- `ADAPTER`: **memory**: 缓存引擎,可以为 `memory`, `redis`, `redis-cluster`, `twoqueue` 和 `memcache`. (`twoqueue` 代表缓冲区固定的LRU缓存)
|
- `ADAPTER`: **memory**: 缓存引擎,可以为 `memory`, `redis`, `redis-cluster`, `twoqueue` 和 `memcache`. (`twoqueue` 代表缓冲区固定的LRU缓存)
|
||||||
- `INTERVAL`: **60**: 垃圾回收间隔(秒),只对`memory`和`towqueue`有效。
|
- `INTERVAL`: **60**: 垃圾回收间隔(秒),只对`memory`和`towqueue`有效。
|
||||||
- `HOST`: **_empty_**: 缓存配置。`redis`, `redis-cluster`,`memcache`配置连接字符串;`twoqueue` 设置队列参数
|
- `HOST`: **_empty_**: 缓存配置。`redis`, `redis-cluster`,`memcache`配置连接字符串;`twoqueue` 设置队列参数
|
||||||
@ -733,7 +732,6 @@ Gitea 创建以下非唯一队列:
|
|||||||
|
|
||||||
### 缓存 - 最后提交缓存设置 (`cache.last_commit`)
|
### 缓存 - 最后提交缓存设置 (`cache.last_commit`)
|
||||||
|
|
||||||
- `ENABLED`: **true**:是否启用缓存。
|
|
||||||
- `ITEM_TTL`: **8760h**:如果未使用,保持缓存中的项目的时间,将其设置为 -1 会禁用缓存。
|
- `ITEM_TTL`: **8760h**:如果未使用,保持缓存中的项目的时间,将其设置为 -1 会禁用缓存。
|
||||||
- `COMMITS_COUNT`: **1000**:仅在存储库的提交计数大于时启用缓存。
|
- `COMMITS_COUNT`: **1000**:仅在存储库的提交计数大于时启用缓存。
|
||||||
|
|
||||||
@ -1039,10 +1037,11 @@ Gitea 创建以下非唯一队列:
|
|||||||
|
|
||||||
## API (`api`)
|
## API (`api`)
|
||||||
|
|
||||||
- `ENABLE_SWAGGER`: **true**: 是否启用swagger路由 (`/api/swagger`, `/api/v1/swagger`, …)。
|
- `ENABLE_SWAGGER`: **true**: 启用API文档接口 (`/api/swagger`, `/api/v1/swagger`, …). True or false。
|
||||||
- `MAX_RESPONSE_ITEMS`: **50**: 单个页面的最大 Feed.
|
- `MAX_RESPONSE_ITEMS`: **50**: API分页的最大单页项目数。
|
||||||
- `ENABLE_OPENID_SIGNIN`: **false**: 允许使用OpenID登录,当设置为`true`时可以通过 `/user/login` 页面进行OpenID登录。
|
- `DEFAULT_PAGING_NUM`: **30**: API分页的默认分页数。
|
||||||
- `DISABLE_REGISTRATION`: **false**: 关闭用户注册。
|
- `DEFAULT_GIT_TREES_PER_PAGE`: **1000**: Git trees API的默认单页项目数。
|
||||||
|
- `DEFAULT_MAX_BLOB_SIZE`: **10485760** (10MiB): blobs API的默认最大文件大小。
|
||||||
|
|
||||||
## OAuth2 (`oauth2`)
|
## OAuth2 (`oauth2`)
|
||||||
|
|
||||||
|
@ -362,7 +362,7 @@ If you are receiving errors on upgrade of Gitea using MySQL that read:
|
|||||||
|
|
||||||
> `ORM engine initialization failed: migrate: do migrate: Error: 1118: Row size too large...`
|
> `ORM engine initialization failed: migrate: do migrate: Error: 1118: Row size too large...`
|
||||||
|
|
||||||
Please run `gitea convert` or run `ALTER TABLE table_name ROW_FORMAT=dynamic;` for each table in the database.
|
Please run `gitea doctor convert` or run `ALTER TABLE table_name ROW_FORMAT=dynamic;` for each table in the database.
|
||||||
|
|
||||||
The underlying problem is that the space allocated for indices by the default row format
|
The underlying problem is that the space allocated for indices by the default row format
|
||||||
is too small. Gitea requires that the `ROWFORMAT` for its tables is `DYNAMIC`.
|
is too small. Gitea requires that the `ROWFORMAT` for its tables is `DYNAMIC`.
|
||||||
@ -385,7 +385,7 @@ Unfortunately MySQL's `utf8` charset does not completely allow all possible UTF-
|
|||||||
They created a new charset and collation called `utf8mb4` that allows for emoji to be stored but tables which use
|
They created a new charset and collation called `utf8mb4` that allows for emoji to be stored but tables which use
|
||||||
the `utf8` charset, and connections which use the `utf8` charset will not use this.
|
the `utf8` charset, and connections which use the `utf8` charset will not use this.
|
||||||
|
|
||||||
Please run `gitea convert`, or run `ALTER DATABASE database_name CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;`
|
Please run `gitea doctor convert`, or run `ALTER DATABASE database_name CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;`
|
||||||
for the database_name and run `ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;`
|
for the database_name and run `ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;`
|
||||||
for each table in the database.
|
for each table in the database.
|
||||||
|
|
||||||
|
@ -366,7 +366,7 @@ Gitea 提供了一个子命令`gitea migrate`来初始化数据库,然后您
|
|||||||
|
|
||||||
> `ORM engine initialization failed: migrate: do migrate: Error: 1118: Row size too large...`
|
> `ORM engine initialization failed: migrate: do migrate: Error: 1118: Row size too large...`
|
||||||
|
|
||||||
请运行`gitea convert`或对数据库中的每个表运行`ALTER TABLE table_name ROW_FORMAT=dynamic;`。
|
请运行 `gitea doctor convert` 或对数据库中的每个表运行 `ALTER TABLE table_name ROW_FORMAT=dynamic;`。
|
||||||
|
|
||||||
潜在问题是默认行格式分配给每个表的索引空间
|
潜在问题是默认行格式分配给每个表的索引空间
|
||||||
太小。Gitea 要求其表的`ROWFORMAT`为`DYNAMIC`。
|
太小。Gitea 要求其表的`ROWFORMAT`为`DYNAMIC`。
|
||||||
@ -389,9 +389,8 @@ SET GLOBAL innodb_large_prefix=1;
|
|||||||
他们创建了一个名为 `utf8mb4`的字符集和校对规则,允许存储 Emoji,但使用
|
他们创建了一个名为 `utf8mb4`的字符集和校对规则,允许存储 Emoji,但使用
|
||||||
utf8 字符集的表和连接将不会使用它。
|
utf8 字符集的表和连接将不会使用它。
|
||||||
|
|
||||||
请运行 `gitea convert` 或对数据库运行`ALTER DATABASE database_name CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;`
|
请运行 `gitea doctor convert` 或对数据库运行 `ALTER DATABASE database_name CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;`
|
||||||
并对每个表运行
|
并对每个表运行 `ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;`。
|
||||||
`ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;`。
|
|
||||||
|
|
||||||
您还需要将`app.ini`文件中的数据库字符集设置为`CHARSET=utf8mb4`。
|
您还需要将`app.ini`文件中的数据库字符集设置为`CHARSET=utf8mb4`。
|
||||||
|
|
||||||
|
168
go.mod
168
go.mod
@ -5,7 +5,7 @@ go 1.21
|
|||||||
require (
|
require (
|
||||||
code.gitea.io/actions-proto-go v0.3.1
|
code.gitea.io/actions-proto-go v0.3.1
|
||||||
code.gitea.io/gitea-vet v0.2.3
|
code.gitea.io/gitea-vet v0.2.3
|
||||||
code.gitea.io/sdk/gitea v0.16.0
|
code.gitea.io/sdk/gitea v0.17.0
|
||||||
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570
|
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570
|
||||||
gitea.com/go-chi/binding v0.0.0-20230415142243-04b515c6d669
|
gitea.com/go-chi/binding v0.0.0-20230415142243-04b515c6d669
|
||||||
gitea.com/go-chi/cache v0.2.0
|
gitea.com/go-chi/cache v0.2.0
|
||||||
@ -17,12 +17,12 @@ require (
|
|||||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
|
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
|
||||||
github.com/NYTimes/gziphandler v1.1.1
|
github.com/NYTimes/gziphandler v1.1.1
|
||||||
github.com/PuerkitoBio/goquery v1.8.1
|
github.com/PuerkitoBio/goquery v1.8.1
|
||||||
github.com/alecthomas/chroma/v2 v2.10.0
|
github.com/alecthomas/chroma/v2 v2.12.0
|
||||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
|
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
|
||||||
github.com/blevesearch/bleve/v2 v2.3.10
|
github.com/blevesearch/bleve/v2 v2.3.10
|
||||||
github.com/bufbuild/connect-go v1.10.0
|
github.com/bufbuild/connect-go v1.10.0
|
||||||
github.com/buildkite/terminal-to-html/v3 v3.9.1
|
github.com/buildkite/terminal-to-html/v3 v3.10.0
|
||||||
github.com/caddyserver/certmagic v0.19.2
|
github.com/caddyserver/certmagic v0.20.0
|
||||||
github.com/chi-middleware/proxy v1.1.1
|
github.com/chi-middleware/proxy v1.1.1
|
||||||
github.com/denisenkom/go-mssqldb v0.12.3
|
github.com/denisenkom/go-mssqldb v0.12.3
|
||||||
github.com/dimiro1/reply v0.0.0-20200315094148-d0136a4c9e21
|
github.com/dimiro1/reply v0.0.0-20200315094148-d0136a4c9e21
|
||||||
@ -35,13 +35,13 @@ require (
|
|||||||
github.com/emirpasic/gods v1.18.1
|
github.com/emirpasic/gods v1.18.1
|
||||||
github.com/ethantkoenig/rupture v1.0.1
|
github.com/ethantkoenig/rupture v1.0.1
|
||||||
github.com/felixge/fgprof v0.9.3
|
github.com/felixge/fgprof v0.9.3
|
||||||
github.com/fsnotify/fsnotify v1.6.0
|
github.com/fsnotify/fsnotify v1.7.0
|
||||||
github.com/gliderlabs/ssh v0.3.6-0.20230927171611-ece6c7995e46
|
github.com/gliderlabs/ssh v0.3.6-0.20230927171611-ece6c7995e46
|
||||||
github.com/go-ap/activitypub v0.0.0-20231003111253-1fba3772399b
|
github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9
|
||||||
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73
|
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73
|
||||||
github.com/go-chi/chi/v5 v5.0.10
|
github.com/go-chi/chi/v5 v5.0.10
|
||||||
github.com/go-chi/cors v1.2.1
|
github.com/go-chi/cors v1.2.1
|
||||||
github.com/go-co-op/gocron v1.31.1
|
github.com/go-co-op/gocron v1.37.0
|
||||||
github.com/go-enry/go-enry/v2 v2.8.6
|
github.com/go-enry/go-enry/v2 v2.8.6
|
||||||
github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e
|
github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e
|
||||||
github.com/go-git/go-billy/v5 v5.5.0
|
github.com/go-git/go-billy/v5 v5.5.0
|
||||||
@ -50,34 +50,34 @@ require (
|
|||||||
github.com/go-sql-driver/mysql v1.7.1
|
github.com/go-sql-driver/mysql v1.7.1
|
||||||
github.com/go-swagger/go-swagger v0.30.5
|
github.com/go-swagger/go-swagger v0.30.5
|
||||||
github.com/go-testfixtures/testfixtures/v3 v3.9.0
|
github.com/go-testfixtures/testfixtures/v3 v3.9.0
|
||||||
github.com/go-webauthn/webauthn v0.8.6
|
github.com/go-webauthn/webauthn v0.9.4
|
||||||
github.com/gobwas/glob v0.2.3
|
github.com/gobwas/glob v0.2.3
|
||||||
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
|
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
|
||||||
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
|
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
|
||||||
github.com/golang-jwt/jwt/v5 v5.0.0
|
github.com/golang-jwt/jwt/v5 v5.2.0
|
||||||
github.com/google/go-github/v53 v53.2.0
|
github.com/google/go-github/v57 v57.0.0
|
||||||
github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98
|
github.com/google/pprof v0.0.0-20231212022811-ec68065c825e
|
||||||
github.com/google/uuid v1.3.1
|
github.com/google/uuid v1.5.0
|
||||||
github.com/gorilla/feeds v1.1.1
|
github.com/gorilla/feeds v1.1.2
|
||||||
github.com/gorilla/sessions v1.2.1
|
github.com/gorilla/sessions v1.2.2
|
||||||
github.com/hashicorp/go-version v1.6.0
|
github.com/hashicorp/go-version v1.6.0
|
||||||
github.com/hashicorp/golang-lru/v2 v2.0.7
|
github.com/hashicorp/golang-lru/v2 v2.0.7
|
||||||
github.com/huandu/xstrings v1.4.0
|
github.com/huandu/xstrings v1.4.0
|
||||||
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056
|
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056
|
||||||
github.com/jhillyerd/enmime v1.0.1
|
github.com/jhillyerd/enmime v1.1.0
|
||||||
github.com/json-iterator/go v1.1.12
|
github.com/json-iterator/go v1.1.12
|
||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
||||||
github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4
|
github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4
|
||||||
github.com/klauspost/compress v1.17.0
|
github.com/klauspost/compress v1.17.4
|
||||||
github.com/klauspost/cpuid/v2 v2.2.5
|
github.com/klauspost/cpuid/v2 v2.2.6
|
||||||
github.com/lib/pq v1.10.9
|
github.com/lib/pq v1.10.9
|
||||||
github.com/markbates/goth v1.78.0
|
github.com/markbates/goth v1.78.0
|
||||||
github.com/mattn/go-isatty v0.0.19
|
github.com/mattn/go-isatty v0.0.20
|
||||||
github.com/mattn/go-sqlite3 v1.14.17
|
github.com/mattn/go-sqlite3 v1.14.19
|
||||||
github.com/meilisearch/meilisearch-go v0.25.1
|
github.com/meilisearch/meilisearch-go v0.26.0
|
||||||
github.com/mholt/archiver/v3 v3.5.1
|
github.com/mholt/archiver/v3 v3.5.1
|
||||||
github.com/microcosm-cc/bluemonday v1.0.26
|
github.com/microcosm-cc/bluemonday v1.0.26
|
||||||
github.com/minio/minio-go/v7 v7.0.63
|
github.com/minio/minio-go/v7 v7.0.66
|
||||||
github.com/minio/sha256-simd v1.0.1
|
github.com/minio/sha256-simd v1.0.1
|
||||||
github.com/msteinert/pam v1.2.0
|
github.com/msteinert/pam v1.2.0
|
||||||
github.com/nektos/act v0.2.52
|
github.com/nektos/act v0.2.52
|
||||||
@ -89,7 +89,7 @@ require (
|
|||||||
github.com/pquerna/otp v1.4.0
|
github.com/pquerna/otp v1.4.0
|
||||||
github.com/prometheus/client_golang v1.17.0
|
github.com/prometheus/client_golang v1.17.0
|
||||||
github.com/quasoft/websspi v1.1.2
|
github.com/quasoft/websspi v1.1.2
|
||||||
github.com/redis/go-redis/v9 v9.2.1
|
github.com/redis/go-redis/v9 v9.3.0
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
|
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
|
||||||
github.com/sassoftware/go-rpmutils v0.2.0
|
github.com/sassoftware/go-rpmutils v0.2.0
|
||||||
@ -99,21 +99,21 @@ require (
|
|||||||
github.com/syndtr/goleveldb v1.0.0
|
github.com/syndtr/goleveldb v1.0.0
|
||||||
github.com/tstranex/u2f v1.0.0
|
github.com/tstranex/u2f v1.0.0
|
||||||
github.com/ulikunitz/xz v0.5.11
|
github.com/ulikunitz/xz v0.5.11
|
||||||
github.com/urfave/cli/v2 v2.25.7
|
github.com/urfave/cli/v2 v2.26.0
|
||||||
github.com/xanzy/go-gitlab v0.93.1
|
github.com/xanzy/go-gitlab v0.95.2
|
||||||
github.com/xeipuuv/gojsonschema v1.2.0
|
github.com/xeipuuv/gojsonschema v1.2.0
|
||||||
github.com/yohcop/openid-go v1.0.1
|
github.com/yohcop/openid-go v1.0.1
|
||||||
github.com/yuin/goldmark v1.5.6
|
github.com/yuin/goldmark v1.6.0
|
||||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
||||||
github.com/yuin/goldmark-meta v1.1.0
|
github.com/yuin/goldmark-meta v1.1.0
|
||||||
golang.org/x/crypto v0.14.0
|
golang.org/x/crypto v0.17.0
|
||||||
golang.org/x/image v0.13.0
|
golang.org/x/image v0.14.0
|
||||||
golang.org/x/net v0.17.0
|
golang.org/x/net v0.19.0
|
||||||
golang.org/x/oauth2 v0.13.0
|
golang.org/x/oauth2 v0.15.0
|
||||||
golang.org/x/sys v0.13.0
|
golang.org/x/sys v0.15.0
|
||||||
golang.org/x/text v0.13.0
|
golang.org/x/text v0.14.0
|
||||||
golang.org/x/tools v0.14.0
|
golang.org/x/tools v0.16.1
|
||||||
google.golang.org/grpc v1.58.3
|
google.golang.org/grpc v1.60.0
|
||||||
google.golang.org/protobuf v1.31.0
|
google.golang.org/protobuf v1.31.0
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||||
gopkg.in/ini.v1 v1.67.0
|
gopkg.in/ini.v1 v1.67.0
|
||||||
@ -125,33 +125,33 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go/compute v1.23.1 // indirect
|
cloud.google.com/go/compute v1.23.3 // indirect
|
||||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||||
dario.cat/mergo v1.0.0 // indirect
|
dario.cat/mergo v1.0.0 // indirect
|
||||||
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 // indirect
|
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 // indirect
|
||||||
github.com/ClickHouse/ch-go v0.58.2 // indirect
|
github.com/ClickHouse/ch-go v0.61.0 // indirect
|
||||||
github.com/ClickHouse/clickhouse-go/v2 v2.14.3 // indirect
|
github.com/ClickHouse/clickhouse-go/v2 v2.16.0 // indirect
|
||||||
github.com/DataDog/zstd v1.5.5 // indirect
|
github.com/DataDog/zstd v1.5.5 // indirect
|
||||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||||
github.com/Masterminds/semver/v3 v3.2.1 // indirect
|
github.com/Masterminds/semver/v3 v3.2.1 // indirect
|
||||||
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
|
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
|
||||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||||
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c // indirect
|
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c // indirect
|
||||||
github.com/RoaringBitmap/roaring v1.6.0 // indirect
|
github.com/RoaringBitmap/roaring v1.7.0 // indirect
|
||||||
github.com/acomagu/bufpipe v1.0.4 // indirect
|
github.com/acomagu/bufpipe v1.0.4 // indirect
|
||||||
github.com/andybalholm/brotli v1.0.5 // indirect
|
github.com/andybalholm/brotli v1.0.6 // indirect
|
||||||
github.com/andybalholm/cascadia v1.3.2 // indirect
|
github.com/andybalholm/cascadia v1.3.2 // indirect
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
|
||||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||||
github.com/aymerick/douceur v0.2.0 // indirect
|
github.com/aymerick/douceur v0.2.0 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bits-and-blooms/bitset v1.9.0 // indirect
|
github.com/bits-and-blooms/bitset v1.12.0 // indirect
|
||||||
github.com/blevesearch/bleve_index_api v1.0.6 // indirect
|
github.com/blevesearch/bleve_index_api v1.1.4 // indirect
|
||||||
github.com/blevesearch/geo v0.1.18 // indirect
|
github.com/blevesearch/geo v0.1.18 // indirect
|
||||||
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
|
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
|
||||||
github.com/blevesearch/gtreap v0.1.1 // indirect
|
github.com/blevesearch/gtreap v0.1.1 // indirect
|
||||||
github.com/blevesearch/mmap-go v1.0.4 // indirect
|
github.com/blevesearch/mmap-go v1.0.4 // indirect
|
||||||
github.com/blevesearch/scorch_segment_api/v2 v2.1.6 // indirect
|
github.com/blevesearch/scorch_segment_api/v2 v2.2.5 // indirect
|
||||||
github.com/blevesearch/segment v0.9.1 // indirect
|
github.com/blevesearch/segment v0.9.1 // indirect
|
||||||
github.com/blevesearch/snowballstem v0.9.0 // indirect
|
github.com/blevesearch/snowballstem v0.9.0 // indirect
|
||||||
github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect
|
github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect
|
||||||
@ -165,9 +165,9 @@ require (
|
|||||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 // indirect
|
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 // indirect
|
||||||
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect
|
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||||
github.com/cloudflare/circl v1.3.3 // indirect
|
github.com/cloudflare/circl v1.3.6 // indirect
|
||||||
github.com/couchbase/go-couchbase v0.1.1 // indirect
|
github.com/couchbase/go-couchbase v0.1.1 // indirect
|
||||||
github.com/couchbase/gomemcached v0.2.1 // indirect
|
github.com/couchbase/gomemcached v0.3.0 // indirect
|
||||||
github.com/couchbase/goutils v0.1.2 // indirect
|
github.com/couchbase/goutils v0.1.2 // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
|
||||||
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
|
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
|
||||||
@ -175,28 +175,28 @@ require (
|
|||||||
github.com/davidmz/go-pageant v1.0.2 // indirect
|
github.com/davidmz/go-pageant v1.0.2 // indirect
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||||
github.com/dlclark/regexp2 v1.10.0 // indirect
|
github.com/dlclark/regexp2 v1.10.0 // indirect
|
||||||
github.com/emersion/go-sasl v0.0.0-20220912192320-0145f2c60ead // indirect
|
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 // indirect
|
||||||
github.com/fatih/color v1.15.0 // indirect
|
github.com/fatih/color v1.16.0 // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.3 // indirect
|
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||||
github.com/fxamacker/cbor/v2 v2.5.0 // indirect
|
github.com/fxamacker/cbor/v2 v2.5.0 // indirect
|
||||||
github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7 // indirect
|
github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7 // indirect
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
|
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
|
||||||
github.com/go-enry/go-oniguruma v1.2.1 // indirect
|
github.com/go-enry/go-oniguruma v1.2.1 // indirect
|
||||||
github.com/go-faster/city v1.0.1 // indirect
|
github.com/go-faster/city v1.0.1 // indirect
|
||||||
github.com/go-faster/errors v0.6.1 // indirect
|
github.com/go-faster/errors v0.7.1 // indirect
|
||||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||||
github.com/go-openapi/analysis v0.21.4 // indirect
|
github.com/go-openapi/analysis v0.21.5 // indirect
|
||||||
github.com/go-openapi/errors v0.20.4 // indirect
|
github.com/go-openapi/errors v0.21.0 // indirect
|
||||||
github.com/go-openapi/inflect v0.19.0 // indirect
|
github.com/go-openapi/inflect v0.19.0 // indirect
|
||||||
github.com/go-openapi/jsonpointer v0.20.0 // indirect
|
github.com/go-openapi/jsonpointer v0.20.1 // indirect
|
||||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
github.com/go-openapi/jsonreference v0.20.3 // indirect
|
||||||
github.com/go-openapi/loads v0.21.2 // indirect
|
github.com/go-openapi/loads v0.21.3 // indirect
|
||||||
github.com/go-openapi/runtime v0.26.0 // indirect
|
github.com/go-openapi/runtime v0.26.2 // indirect
|
||||||
github.com/go-openapi/spec v0.20.9 // indirect
|
github.com/go-openapi/spec v0.20.12 // indirect
|
||||||
github.com/go-openapi/strfmt v0.21.7 // indirect
|
github.com/go-openapi/strfmt v0.21.10 // indirect
|
||||||
github.com/go-openapi/swag v0.22.4 // indirect
|
github.com/go-openapi/swag v0.22.5 // indirect
|
||||||
github.com/go-openapi/validate v0.22.1 // indirect
|
github.com/go-openapi/validate v0.22.4 // indirect
|
||||||
github.com/go-webauthn/x v0.1.4 // indirect
|
github.com/go-webauthn/x v0.1.5 // indirect
|
||||||
github.com/goccy/go-json v0.10.2 // indirect
|
github.com/goccy/go-json v0.10.2 // indirect
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
||||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
||||||
@ -207,12 +207,12 @@ require (
|
|||||||
github.com/golang/snappy v0.0.4 // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/google/go-querystring v1.1.0 // indirect
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
github.com/google/go-tpm v0.9.0 // indirect
|
github.com/google/go-tpm v0.9.0 // indirect
|
||||||
github.com/gorilla/css v1.0.0 // indirect
|
github.com/gorilla/css v1.0.1 // indirect
|
||||||
github.com/gorilla/handlers v1.5.1 // indirect
|
github.com/gorilla/handlers v1.5.2 // indirect
|
||||||
github.com/gorilla/mux v1.8.0 // indirect
|
github.com/gorilla/mux v1.8.1 // indirect
|
||||||
github.com/gorilla/securecookie v1.1.1 // indirect
|
github.com/gorilla/securecookie v1.1.2 // indirect
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.4 // indirect
|
github.com/hashicorp/go-retryablehttp v0.7.5 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
github.com/imdario/mergo v0.3.16 // indirect
|
github.com/imdario/mergo v0.3.16 // indirect
|
||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||||
@ -228,9 +228,9 @@ require (
|
|||||||
github.com/markbates/going v1.0.3 // indirect
|
github.com/markbates/going v1.0.3 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
|
||||||
github.com/mholt/acmez v1.2.0 // indirect
|
github.com/mholt/acmez v1.2.0 // indirect
|
||||||
github.com/miekg/dns v1.1.56 // indirect
|
github.com/miekg/dns v1.1.57 // indirect
|
||||||
github.com/minio/md5-simd v1.1.2 // indirect
|
github.com/minio/md5-simd v1.1.2 // indirect
|
||||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
@ -244,19 +244,19 @@ require (
|
|||||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||||
github.com/paulmach/orb v0.10.0 // indirect
|
github.com/paulmach/orb v0.10.0 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
|
||||||
github.com/pierrec/lz4/v4 v4.1.18 // indirect
|
github.com/pierrec/lz4/v4 v4.1.19 // indirect
|
||||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||||
github.com/prometheus/client_model v0.5.0 // indirect
|
github.com/prometheus/client_model v0.5.0 // indirect
|
||||||
github.com/prometheus/common v0.44.0 // indirect
|
github.com/prometheus/common v0.45.0 // indirect
|
||||||
github.com/prometheus/procfs v0.12.0 // indirect
|
github.com/prometheus/procfs v0.12.0 // indirect
|
||||||
github.com/rhysd/actionlint v1.6.26 // indirect
|
github.com/rhysd/actionlint v1.6.26 // indirect
|
||||||
github.com/rivo/uniseg v0.4.4 // indirect
|
github.com/rivo/uniseg v0.4.4 // indirect
|
||||||
github.com/rogpeppe/go-internal v1.11.0 // indirect
|
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||||
github.com/rs/xid v1.5.0 // indirect
|
github.com/rs/xid v1.5.0 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/sagikazarmark/locafero v0.3.0 // indirect
|
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||||
github.com/segmentio/asm v1.2.0 // indirect
|
github.com/segmentio/asm v1.2.0 // indirect
|
||||||
github.com/shopspring/decimal v1.3.1 // indirect
|
github.com/shopspring/decimal v1.3.1 // indirect
|
||||||
@ -264,37 +264,37 @@ require (
|
|||||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
github.com/skeema/knownhosts v1.2.1 // indirect
|
github.com/skeema/knownhosts v1.2.1 // indirect
|
||||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||||
github.com/spf13/afero v1.10.0 // indirect
|
github.com/spf13/afero v1.11.0 // indirect
|
||||||
github.com/spf13/cast v1.5.1 // indirect
|
github.com/spf13/cast v1.6.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/spf13/viper v1.17.0 // indirect
|
github.com/spf13/viper v1.18.2 // indirect
|
||||||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
|
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
|
||||||
github.com/subosito/gotenv v1.6.0 // indirect
|
github.com/subosito/gotenv v1.6.0 // indirect
|
||||||
github.com/toqueteos/webbrowser v1.2.0 // indirect
|
github.com/toqueteos/webbrowser v1.2.0 // indirect
|
||||||
github.com/unknwon/com v1.0.1 // indirect
|
github.com/unknwon/com v1.0.1 // indirect
|
||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
github.com/valyala/fasthttp v1.50.0 // indirect
|
github.com/valyala/fasthttp v1.51.0 // indirect
|
||||||
github.com/valyala/fastjson v1.6.4 // indirect
|
github.com/valyala/fastjson v1.6.4 // indirect
|
||||||
github.com/x448/float16 v0.8.4 // indirect
|
github.com/x448/float16 v0.8.4 // indirect
|
||||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
||||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e // indirect
|
||||||
github.com/zeebo/blake3 v0.2.3 // indirect
|
github.com/zeebo/blake3 v0.2.3 // indirect
|
||||||
go.etcd.io/bbolt v1.3.7 // indirect
|
go.etcd.io/bbolt v1.3.8 // indirect
|
||||||
go.mongodb.org/mongo-driver v1.12.1 // indirect
|
go.mongodb.org/mongo-driver v1.13.1 // indirect
|
||||||
go.opentelemetry.io/otel v1.19.0 // indirect
|
go.opentelemetry.io/otel v1.21.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.19.0 // indirect
|
go.opentelemetry.io/otel/trace v1.21.0 // indirect
|
||||||
go.uber.org/atomic v1.11.0 // indirect
|
go.uber.org/atomic v1.11.0 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.uber.org/zap v1.26.0 // indirect
|
go.uber.org/zap v1.26.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
|
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 // indirect
|
||||||
golang.org/x/mod v0.13.0 // indirect
|
golang.org/x/mod v0.14.0 // indirect
|
||||||
golang.org/x/sync v0.4.0 // indirect
|
golang.org/x/sync v0.5.0 // indirect
|
||||||
golang.org/x/time v0.3.0 // indirect
|
golang.org/x/time v0.5.0 // indirect
|
||||||
google.golang.org/appengine v1.6.8 // indirect
|
google.golang.org/appengine v1.6.8 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 // indirect
|
||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
|
@ -51,6 +51,11 @@ type ActionRunner struct {
|
|||||||
Deleted timeutil.TimeStamp `xorm:"deleted"`
|
Deleted timeutil.TimeStamp `xorm:"deleted"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
RunnerOfflineTime = time.Minute
|
||||||
|
RunnerIdleTime = 10 * time.Second
|
||||||
|
)
|
||||||
|
|
||||||
// BelongsToOwnerName before calling, should guarantee that all attributes are loaded
|
// BelongsToOwnerName before calling, should guarantee that all attributes are loaded
|
||||||
func (r *ActionRunner) BelongsToOwnerName() string {
|
func (r *ActionRunner) BelongsToOwnerName() string {
|
||||||
if r.RepoID != 0 {
|
if r.RepoID != 0 {
|
||||||
@ -76,11 +81,12 @@ func (r *ActionRunner) BelongsToOwnerType() types.OwnerType {
|
|||||||
return types.OwnerTypeSystemGlobal
|
return types.OwnerTypeSystemGlobal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if the logic here changed, you should also modify FindRunnerOptions.ToCond
|
||||||
func (r *ActionRunner) Status() runnerv1.RunnerStatus {
|
func (r *ActionRunner) Status() runnerv1.RunnerStatus {
|
||||||
if time.Since(r.LastOnline.AsTime()) > time.Minute {
|
if time.Since(r.LastOnline.AsTime()) > RunnerOfflineTime {
|
||||||
return runnerv1.RunnerStatus_RUNNER_STATUS_OFFLINE
|
return runnerv1.RunnerStatus_RUNNER_STATUS_OFFLINE
|
||||||
}
|
}
|
||||||
if time.Since(r.LastActive.AsTime()) > 10*time.Second {
|
if time.Since(r.LastActive.AsTime()) > RunnerIdleTime {
|
||||||
return runnerv1.RunnerStatus_RUNNER_STATUS_IDLE
|
return runnerv1.RunnerStatus_RUNNER_STATUS_IDLE
|
||||||
}
|
}
|
||||||
return runnerv1.RunnerStatus_RUNNER_STATUS_ACTIVE
|
return runnerv1.RunnerStatus_RUNNER_STATUS_ACTIVE
|
||||||
@ -153,6 +159,7 @@ type FindRunnerOptions struct {
|
|||||||
OwnerID int64
|
OwnerID int64
|
||||||
Sort string
|
Sort string
|
||||||
Filter string
|
Filter string
|
||||||
|
IsOnline util.OptionalBool
|
||||||
WithAvailable bool // not only runners belong to, but also runners can be used
|
WithAvailable bool // not only runners belong to, but also runners can be used
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,6 +185,12 @@ func (opts FindRunnerOptions) ToConds() builder.Cond {
|
|||||||
if opts.Filter != "" {
|
if opts.Filter != "" {
|
||||||
cond = cond.And(builder.Like{"name", opts.Filter})
|
cond = cond.And(builder.Like{"name", opts.Filter})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if opts.IsOnline.IsTrue() {
|
||||||
|
cond = cond.And(builder.Gt{"last_online": time.Now().Add(-RunnerOfflineTime).Unix()})
|
||||||
|
} else if opts.IsOnline.IsFalse() {
|
||||||
|
cond = cond.And(builder.Lte{"last_online": time.Now().Add(-RunnerOfflineTime).Unix()})
|
||||||
|
}
|
||||||
return cond
|
return cond
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
func TestAddDeletedBranch(t *testing.T) {
|
func TestAddDeletedBranch(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||||
|
assert.EqualValues(t, git.Sha1ObjectFormat.Name(), repo.ObjectFormatName)
|
||||||
firstBranch := unittest.AssertExistsAndLoadBean(t, &git_model.Branch{ID: 1})
|
firstBranch := unittest.AssertExistsAndLoadBean(t, &git_model.Branch{ID: 1})
|
||||||
|
|
||||||
assert.True(t, firstBranch.IsDeleted)
|
assert.True(t, firstBranch.IsDeleted)
|
||||||
@ -30,7 +31,7 @@ func TestAddDeletedBranch(t *testing.T) {
|
|||||||
assert.True(t, secondBranch.IsDeleted)
|
assert.True(t, secondBranch.IsDeleted)
|
||||||
|
|
||||||
commit := &git.Commit{
|
commit := &git.Commit{
|
||||||
ID: repo.ObjectFormat.MustIDFromString(secondBranch.CommitID),
|
ID: git.MustIDFromString(secondBranch.CommitID),
|
||||||
CommitMessage: secondBranch.CommitMessage,
|
CommitMessage: secondBranch.CommitMessage,
|
||||||
Committer: &git.Signature{
|
Committer: &git.Signature{
|
||||||
When: secondBranch.CommitTime.AsLocalTime(),
|
When: secondBranch.CommitTime.AsLocalTime(),
|
||||||
|
@ -114,7 +114,7 @@ WHEN NOT MATCHED
|
|||||||
|
|
||||||
// GetNextCommitStatusIndex retried 3 times to generate a resource index
|
// GetNextCommitStatusIndex retried 3 times to generate a resource index
|
||||||
func GetNextCommitStatusIndex(ctx context.Context, repoID int64, sha string) (int64, error) {
|
func GetNextCommitStatusIndex(ctx context.Context, repoID int64, sha string) (int64, error) {
|
||||||
_, err := git.IDFromString(sha)
|
_, err := git.NewIDFromString(sha)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, git.ErrInvalidSHA{SHA: sha}
|
return 0, git.ErrInvalidSHA{SHA: sha}
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,7 @@ type Repository struct {
|
|||||||
IsFsckEnabled bool `xorm:"NOT NULL DEFAULT true"`
|
IsFsckEnabled bool `xorm:"NOT NULL DEFAULT true"`
|
||||||
CloseIssuesViaCommitInAnyBranch bool `xorm:"NOT NULL DEFAULT false"`
|
CloseIssuesViaCommitInAnyBranch bool `xorm:"NOT NULL DEFAULT false"`
|
||||||
Topics []string `xorm:"TEXT JSON"`
|
Topics []string `xorm:"TEXT JSON"`
|
||||||
ObjectFormat git.ObjectFormat `xorm:"-"`
|
ObjectFormatName string `xorm:"-"`
|
||||||
|
|
||||||
TrustModel TrustModelType
|
TrustModel TrustModelType
|
||||||
|
|
||||||
@ -277,7 +277,9 @@ func (repo *Repository) AfterLoad() {
|
|||||||
repo.NumOpenProjects = repo.NumProjects - repo.NumClosedProjects
|
repo.NumOpenProjects = repo.NumProjects - repo.NumClosedProjects
|
||||||
repo.NumOpenActionRuns = repo.NumActionRuns - repo.NumClosedActionRuns
|
repo.NumOpenActionRuns = repo.NumActionRuns - repo.NumClosedActionRuns
|
||||||
|
|
||||||
repo.ObjectFormat = git.ObjectFormatFromID(git.Sha1)
|
// this is a temporary behaviour to support old repos, next step is to store the object format in the database
|
||||||
|
// and read from database so this line could be removed. To not depend on git module, we use a constant variable here
|
||||||
|
repo.ObjectFormatName = "sha1"
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadAttributes loads attributes of the repository.
|
// LoadAttributes loads attributes of the repository.
|
||||||
@ -606,25 +608,23 @@ func ComposeHTTPSCloneURL(owner, repo string) string {
|
|||||||
|
|
||||||
func ComposeSSHCloneURL(ownerName, repoName string) string {
|
func ComposeSSHCloneURL(ownerName, repoName string) string {
|
||||||
sshUser := setting.SSH.User
|
sshUser := setting.SSH.User
|
||||||
|
|
||||||
// if we have a ipv6 literal we need to put brackets around it
|
|
||||||
// for the git cloning to work.
|
|
||||||
sshDomain := setting.SSH.Domain
|
sshDomain := setting.SSH.Domain
|
||||||
ip := net.ParseIP(setting.SSH.Domain)
|
|
||||||
if ip != nil && ip.To4() == nil {
|
// non-standard port, it must use full URI
|
||||||
sshDomain = "[" + setting.SSH.Domain + "]"
|
if setting.SSH.Port != 22 {
|
||||||
|
sshHost := net.JoinHostPort(sshDomain, strconv.Itoa(setting.SSH.Port))
|
||||||
|
return fmt.Sprintf("ssh://%s@%s/%s/%s.git", sshUser, sshHost, url.PathEscape(ownerName), url.PathEscape(repoName))
|
||||||
}
|
}
|
||||||
|
|
||||||
if setting.SSH.Port != 22 {
|
// for standard port, it can use a shorter URI (without the port)
|
||||||
return fmt.Sprintf("ssh://%s@%s/%s/%s.git", sshUser,
|
sshHost := sshDomain
|
||||||
net.JoinHostPort(setting.SSH.Domain, strconv.Itoa(setting.SSH.Port)),
|
if ip := net.ParseIP(sshHost); ip != nil && ip.To4() == nil {
|
||||||
url.PathEscape(ownerName),
|
sshHost = "[" + sshHost + "]" // for IPv6 address, wrap it with brackets
|
||||||
url.PathEscape(repoName))
|
|
||||||
}
|
}
|
||||||
if setting.Repository.UseCompatSSHURI {
|
if setting.Repository.UseCompatSSHURI {
|
||||||
return fmt.Sprintf("ssh://%s@%s/%s/%s.git", sshUser, sshDomain, url.PathEscape(ownerName), url.PathEscape(repoName))
|
return fmt.Sprintf("ssh://%s@%s/%s/%s.git", sshUser, sshHost, url.PathEscape(ownerName), url.PathEscape(repoName))
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s@%s:%s/%s.git", sshUser, sshDomain, url.PathEscape(ownerName), url.PathEscape(repoName))
|
return fmt.Sprintf("%s@%s:%s/%s.git", sshUser, sshHost, url.PathEscape(ownerName), url.PathEscape(repoName))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *Repository) cloneLink(isWiki bool) *CloneLink {
|
func (repo *Repository) cloneLink(isWiki bool) *CloneLink {
|
||||||
|
@ -12,6 +12,8 @@ import (
|
|||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/markup"
|
"code.gitea.io/gitea/modules/markup"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/modules/test"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@ -186,3 +188,32 @@ func TestGetRepositoryByURL(t *testing.T) {
|
|||||||
test(t, "try.gitea.io:user2/repo2.git")
|
test(t, "try.gitea.io:user2/repo2.git")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestComposeSSHCloneURL(t *testing.T) {
|
||||||
|
defer test.MockVariableValue(&setting.SSH, setting.SSH)()
|
||||||
|
defer test.MockVariableValue(&setting.Repository, setting.Repository)()
|
||||||
|
|
||||||
|
setting.SSH.User = "git"
|
||||||
|
|
||||||
|
// test SSH_DOMAIN
|
||||||
|
setting.SSH.Domain = "domain"
|
||||||
|
setting.SSH.Port = 22
|
||||||
|
setting.Repository.UseCompatSSHURI = false
|
||||||
|
assert.Equal(t, "git@domain:user/repo.git", repo_model.ComposeSSHCloneURL("user", "repo"))
|
||||||
|
setting.Repository.UseCompatSSHURI = true
|
||||||
|
assert.Equal(t, "ssh://git@domain/user/repo.git", repo_model.ComposeSSHCloneURL("user", "repo"))
|
||||||
|
// test SSH_DOMAIN while use non-standard SSH port
|
||||||
|
setting.SSH.Port = 123
|
||||||
|
setting.Repository.UseCompatSSHURI = false
|
||||||
|
assert.Equal(t, "ssh://git@domain:123/user/repo.git", repo_model.ComposeSSHCloneURL("user", "repo"))
|
||||||
|
setting.Repository.UseCompatSSHURI = true
|
||||||
|
assert.Equal(t, "ssh://git@domain:123/user/repo.git", repo_model.ComposeSSHCloneURL("user", "repo"))
|
||||||
|
|
||||||
|
// test IPv6 SSH_DOMAIN
|
||||||
|
setting.Repository.UseCompatSSHURI = false
|
||||||
|
setting.SSH.Domain = "::1"
|
||||||
|
setting.SSH.Port = 22
|
||||||
|
assert.Equal(t, "git@[::1]:user/repo.git", repo_model.ComposeSSHCloneURL("user", "repo"))
|
||||||
|
setting.SSH.Port = 123
|
||||||
|
assert.Equal(t, "ssh://git@[::1]:123/user/repo.git", repo_model.ComposeSSHCloneURL("user", "repo"))
|
||||||
|
}
|
||||||
|
@ -377,3 +377,13 @@ func syncTopicsInRepository(sess db.Engine, repoID int64) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CountOrphanedAttachments returns the number of topics that don't belong to any repository.
|
||||||
|
func CountOrphanedTopics(ctx context.Context) (int64, error) {
|
||||||
|
return db.GetEngine(ctx).Where("repo_count = 0").Count(new(Topic))
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteOrphanedAttachments delete all topics that don't belong to any repository.
|
||||||
|
func DeleteOrphanedTopics(ctx context.Context) (int64, error) {
|
||||||
|
return db.GetEngine(ctx).Where("repo_count = 0").Delete(new(Topic))
|
||||||
|
}
|
||||||
|
6
modules/cache/cache.go
vendored
6
modules/cache/cache.go
vendored
@ -24,11 +24,11 @@ func newCache(cacheConfig setting.Cache) (mc.Cache, error) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewContext start cache service
|
// Init start cache service
|
||||||
func NewContext() error {
|
func Init() error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if conn == nil && setting.CacheService.Enabled {
|
if conn == nil {
|
||||||
if conn, err = newCache(setting.CacheService.Cache); err != nil {
|
if conn, err = newCache(setting.CacheService.Cache); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
4
modules/cache/cache_test.go
vendored
4
modules/cache/cache_test.go
vendored
@ -22,9 +22,9 @@ func createTestCache() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestNewContext(t *testing.T) {
|
func TestNewContext(t *testing.T) {
|
||||||
assert.NoError(t, NewContext())
|
assert.NoError(t, Init())
|
||||||
|
|
||||||
setting.CacheService.Cache = setting.Cache{Enabled: true, Adapter: "redis", Conn: "some random string"}
|
setting.CacheService.Cache = setting.Cache{Adapter: "redis", Conn: "some random string"}
|
||||||
con, err := newCache(setting.Cache{
|
con, err := newCache(setting.Cache{
|
||||||
Adapter: "rand",
|
Adapter: "rand",
|
||||||
Conn: "false conf",
|
Conn: "false conf",
|
||||||
|
@ -8,11 +8,12 @@
|
|||||||
package charset
|
package charset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/translation"
|
"code.gitea.io/gitea/modules/translation"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -20,20 +21,18 @@ import (
|
|||||||
const RuneNBSP = 0xa0
|
const RuneNBSP = 0xa0
|
||||||
|
|
||||||
// EscapeControlHTML escapes the unicode control sequences in a provided html document
|
// EscapeControlHTML escapes the unicode control sequences in a provided html document
|
||||||
func EscapeControlHTML(text string, locale translation.Locale, allowed ...rune) (escaped *EscapeStatus, output string) {
|
func EscapeControlHTML(html template.HTML, locale translation.Locale, allowed ...rune) (escaped *EscapeStatus, output template.HTML) {
|
||||||
sb := &strings.Builder{}
|
sb := &strings.Builder{}
|
||||||
outputStream := &HTMLStreamerWriter{Writer: sb}
|
escaped, _ = EscapeControlReader(strings.NewReader(string(html)), sb, locale, allowed...) // err has been handled in EscapeControlReader
|
||||||
streamer := NewEscapeStreamer(locale, outputStream, allowed...).(*escapeStreamer)
|
return escaped, template.HTML(sb.String())
|
||||||
|
|
||||||
if err := StreamHTML(strings.NewReader(text), streamer); err != nil {
|
|
||||||
streamer.escaped.HasError = true
|
|
||||||
log.Error("Error whilst escaping: %v", err)
|
|
||||||
}
|
|
||||||
return streamer.escaped, sb.String()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// EscapeControlReaders escapes the unicode control sequences in a provided reader of HTML content and writer in a locale and returns the findings as an EscapeStatus and the escaped []byte
|
// EscapeControlReader escapes the unicode control sequences in a provided reader of HTML content and writer in a locale and returns the findings as an EscapeStatus
|
||||||
func EscapeControlReader(reader io.Reader, writer io.Writer, locale translation.Locale, allowed ...rune) (escaped *EscapeStatus, err error) {
|
func EscapeControlReader(reader io.Reader, writer io.Writer, locale translation.Locale, allowed ...rune) (escaped *EscapeStatus, err error) {
|
||||||
|
if !setting.UI.AmbiguousUnicodeDetection {
|
||||||
|
_, err = io.Copy(writer, reader)
|
||||||
|
return &EscapeStatus{}, err
|
||||||
|
}
|
||||||
outputStream := &HTMLStreamerWriter{Writer: writer}
|
outputStream := &HTMLStreamerWriter{Writer: writer}
|
||||||
streamer := NewEscapeStreamer(locale, outputStream, allowed...).(*escapeStreamer)
|
streamer := NewEscapeStreamer(locale, outputStream, allowed...).(*escapeStreamer)
|
||||||
|
|
||||||
@ -43,41 +42,3 @@ func EscapeControlReader(reader io.Reader, writer io.Writer, locale translation.
|
|||||||
}
|
}
|
||||||
return streamer.escaped, err
|
return streamer.escaped, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// EscapeControlStringReader escapes the unicode control sequences in a provided reader of string content and writer in a locale and returns the findings as an EscapeStatus and the escaped []byte. HTML line breaks are not inserted after every newline by this method.
|
|
||||||
func EscapeControlStringReader(reader io.Reader, writer io.Writer, locale translation.Locale, allowed ...rune) (escaped *EscapeStatus, err error) {
|
|
||||||
bufRd := bufio.NewReader(reader)
|
|
||||||
outputStream := &HTMLStreamerWriter{Writer: writer}
|
|
||||||
streamer := NewEscapeStreamer(locale, outputStream, allowed...).(*escapeStreamer)
|
|
||||||
|
|
||||||
for {
|
|
||||||
line, rdErr := bufRd.ReadString('\n')
|
|
||||||
if len(line) > 0 {
|
|
||||||
if err := streamer.Text(line); err != nil {
|
|
||||||
streamer.escaped.HasError = true
|
|
||||||
log.Error("Error whilst escaping: %v", err)
|
|
||||||
return streamer.escaped, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if rdErr != nil {
|
|
||||||
if rdErr != io.EOF {
|
|
||||||
err = rdErr
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return streamer.escaped, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// EscapeControlString escapes the unicode control sequences in a provided string and returns the findings as an EscapeStatus and the escaped string
|
|
||||||
func EscapeControlString(text string, locale translation.Locale, allowed ...rune) (escaped *EscapeStatus, output string) {
|
|
||||||
sb := &strings.Builder{}
|
|
||||||
outputStream := &HTMLStreamerWriter{Writer: sb}
|
|
||||||
streamer := NewEscapeStreamer(locale, outputStream, allowed...).(*escapeStreamer)
|
|
||||||
|
|
||||||
if err := streamer.Text(text); err != nil {
|
|
||||||
streamer.escaped.HasError = true
|
|
||||||
log.Error("Error whilst escaping: %v", err)
|
|
||||||
}
|
|
||||||
return streamer.escaped, sb.String()
|
|
||||||
}
|
|
||||||
|
@ -64,7 +64,7 @@ func (e *escapeStreamer) Text(data string) error {
|
|||||||
until, next = nextIdxs[0]+pos, nextIdxs[1]+pos
|
until, next = nextIdxs[0]+pos, nextIdxs[1]+pos
|
||||||
}
|
}
|
||||||
|
|
||||||
// from pos until until we know that the runes are not \r\t\n or even ' '
|
// from pos until we know that the runes are not \r\t\n or even ' '
|
||||||
runes := make([]rune, 0, next-until)
|
runes := make([]rune, 0, next-until)
|
||||||
positions := make([]int, 0, next-until+1)
|
positions := make([]int, 0, next-until+1)
|
||||||
|
|
||||||
|
@ -4,11 +4,14 @@
|
|||||||
package charset
|
package charset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/modules/test"
|
||||||
"code.gitea.io/gitea/modules/translation"
|
"code.gitea.io/gitea/modules/translation"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
type escapeControlTest struct {
|
type escapeControlTest struct {
|
||||||
@ -132,22 +135,8 @@ then resh (ר), and finally heh (ה) (which should appear leftmost).`,
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEscapeControlString(t *testing.T) {
|
|
||||||
for _, tt := range escapeControlTests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
status, result := EscapeControlString(tt.text, &translation.MockLocale{})
|
|
||||||
if !reflect.DeepEqual(*status, tt.status) {
|
|
||||||
t.Errorf("EscapeControlString() status = %v, wanted= %v", status, tt.status)
|
|
||||||
}
|
|
||||||
if result != tt.result {
|
|
||||||
t.Errorf("EscapeControlString()\nresult= %v,\nwanted= %v", result, tt.result)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEscapeControlReader(t *testing.T) {
|
func TestEscapeControlReader(t *testing.T) {
|
||||||
// lets add some control characters to the tests
|
// add some control characters to the tests
|
||||||
tests := make([]escapeControlTest, 0, len(escapeControlTests)*3)
|
tests := make([]escapeControlTest, 0, len(escapeControlTests)*3)
|
||||||
copy(tests, escapeControlTests)
|
copy(tests, escapeControlTests)
|
||||||
|
|
||||||
@ -169,29 +158,20 @@ func TestEscapeControlReader(t *testing.T) {
|
|||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
input := strings.NewReader(tt.text)
|
|
||||||
output := &strings.Builder{}
|
output := &strings.Builder{}
|
||||||
status, err := EscapeControlReader(input, output, &translation.MockLocale{})
|
status, err := EscapeControlReader(strings.NewReader(tt.text), output, &translation.MockLocale{})
|
||||||
result := output.String()
|
assert.NoError(t, err)
|
||||||
if err != nil {
|
assert.Equal(t, tt.status, *status)
|
||||||
t.Errorf("EscapeControlReader(): err = %v", err)
|
assert.Equal(t, tt.result, output.String())
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(*status, tt.status) {
|
|
||||||
t.Errorf("EscapeControlReader() status = %v, wanted= %v", status, tt.status)
|
|
||||||
}
|
|
||||||
if result != tt.result {
|
|
||||||
t.Errorf("EscapeControlReader()\nresult= %v,\nwanted= %v", result, tt.result)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEscapeControlReader_panic(t *testing.T) {
|
func TestSettingAmbiguousUnicodeDetection(t *testing.T) {
|
||||||
bs := make([]byte, 0, 20479)
|
defer test.MockVariableValue(&setting.UI.AmbiguousUnicodeDetection, true)()
|
||||||
bs = append(bs, 'A')
|
_, out := EscapeControlHTML("a test", &translation.MockLocale{})
|
||||||
for i := 0; i < 6826; i++ {
|
assert.EqualValues(t, `a<span class="escaped-code-point" data-escaped="[U+00A0]"><span class="char"> </span></span>test`, out)
|
||||||
bs = append(bs, []byte("—")...)
|
setting.UI.AmbiguousUnicodeDetection = false
|
||||||
}
|
_, out = EscapeControlHTML("a test", &translation.MockLocale{})
|
||||||
_, _ = EscapeControlString(string(bs), &translation.MockLocale{})
|
assert.EqualValues(t, `a test`, out)
|
||||||
}
|
}
|
||||||
|
@ -158,6 +158,12 @@ func checkDBConsistency(ctx context.Context, logger log.Logger, autofix bool) er
|
|||||||
Fixer: actions_model.FixRunnersWithoutBelongingOwner,
|
Fixer: actions_model.FixRunnersWithoutBelongingOwner,
|
||||||
FixedMessage: "Removed",
|
FixedMessage: "Removed",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "Topics with empty repository count",
|
||||||
|
Counter: repo_model.CountOrphanedTopics,
|
||||||
|
Fixer: repo_model.DeleteOrphanedTopics,
|
||||||
|
FixedMessage: "Removed",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: function to recalc all counters
|
// TODO: function to recalc all counters
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/storage"
|
||||||
repo_service "code.gitea.io/gitea/services/repository"
|
repo_service "code.gitea.io/gitea/services/repository"
|
||||||
|
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
@ -31,6 +32,10 @@ func countOrphanedRepos(ctx context.Context) (int64, error) {
|
|||||||
|
|
||||||
// deleteOrphanedRepos delete repository where user of owner_id do not exist
|
// deleteOrphanedRepos delete repository where user of owner_id do not exist
|
||||||
func deleteOrphanedRepos(ctx context.Context) (int64, error) {
|
func deleteOrphanedRepos(ctx context.Context) (int64, error) {
|
||||||
|
if err := storage.Init(); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
batchSize := db.MaxBatchInsertSize("repository")
|
batchSize := db.MaxBatchInsertSize("repository")
|
||||||
e := db.GetEngine(ctx)
|
e := db.GetEngine(ctx)
|
||||||
var deleted int64
|
var deleted int64
|
||||||
|
@ -39,7 +39,7 @@ func TestReadingBlameOutput(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, bypass := range []bool{false, true} {
|
for _, bypass := range []bool{false, true} {
|
||||||
blameReader, err := CreateBlameReader(ctx, &Sha1ObjectFormat{}, "./tests/repos/repo5_pulls", commit, "README.md", bypass)
|
blameReader, err := CreateBlameReader(ctx, Sha1ObjectFormat, "./tests/repos/repo5_pulls", commit, "README.md", bypass)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, blameReader)
|
assert.NotNil(t, blameReader)
|
||||||
defer blameReader.Close()
|
defer blameReader.Close()
|
||||||
|
@ -14,7 +14,6 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/git/internal" //nolint:depguard // only this file can use the internal type CmdArg, other files and packages should use AddXxx functions
|
"code.gitea.io/gitea/modules/git/internal" //nolint:depguard // only this file can use the internal type CmdArg, other files and packages should use AddXxx functions
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
@ -389,15 +388,11 @@ func (r *runStdError) IsExitCode(code int) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func bytesToString(b []byte) string {
|
|
||||||
return *(*string)(unsafe.Pointer(&b)) // that's what Golang's strings.Builder.String() does (go/src/strings/builder.go)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RunStdString runs the command with options and returns stdout/stderr as string. and store stderr to returned error (err combined with stderr).
|
// RunStdString runs the command with options and returns stdout/stderr as string. and store stderr to returned error (err combined with stderr).
|
||||||
func (c *Command) RunStdString(opts *RunOpts) (stdout, stderr string, runErr RunStdError) {
|
func (c *Command) RunStdString(opts *RunOpts) (stdout, stderr string, runErr RunStdError) {
|
||||||
stdoutBytes, stderrBytes, err := c.RunStdBytes(opts)
|
stdoutBytes, stderrBytes, err := c.RunStdBytes(opts)
|
||||||
stdout = bytesToString(stdoutBytes)
|
stdout = util.UnsafeBytesToString(stdoutBytes)
|
||||||
stderr = bytesToString(stderrBytes)
|
stderr = util.UnsafeBytesToString(stderrBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return stdout, stderr, &runStdError{err: err, stderr: stderr}
|
return stdout, stderr, &runStdError{err: err, stderr: stderr}
|
||||||
}
|
}
|
||||||
@ -432,7 +427,7 @@ func (c *Command) RunStdBytes(opts *RunOpts) (stdout, stderr []byte, runErr RunS
|
|||||||
err := c.Run(newOpts)
|
err := c.Run(newOpts)
|
||||||
stderr = stderrBuf.Bytes()
|
stderr = stderrBuf.Bytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, stderr, &runStdError{err: err, stderr: bytesToString(stderr)}
|
return nil, stderr, &runStdError{err: err, stderr: util.UnsafeBytesToString(stderr)}
|
||||||
}
|
}
|
||||||
// even if there is no err, there could still be some stderr output
|
// even if there is no err, there could still be some stderr output
|
||||||
return stdoutBuf.Bytes(), stderr, nil
|
return stdoutBuf.Bytes(), stderr, nil
|
||||||
|
@ -236,7 +236,7 @@ func (c *Commit) IsForcePush(oldCommitID string) (bool, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
if oldCommitID == objectFormat.Empty().String() {
|
if oldCommitID == objectFormat.EmptyObjectID().String() {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ func GetLastCommitForPaths(ctx context.Context, commit *Commit, treePath string,
|
|||||||
if typ != "commit" {
|
if typ != "commit" {
|
||||||
return nil, fmt.Errorf("unexpected type: %s for commit id: %s", typ, commitID)
|
return nil, fmt.Errorf("unexpected type: %s for commit id: %s", typ, commitID)
|
||||||
}
|
}
|
||||||
c, err = CommitFromReader(commit.repo, commit.ID.Type().MustIDFromString(commitID), io.LimitReader(batchReader, size))
|
c, err = CommitFromReader(commit.repo, MustIDFromString(commitID), io.LimitReader(batchReader, size))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -71,10 +71,10 @@ readLoop:
|
|||||||
|
|
||||||
switch string(split[0]) {
|
switch string(split[0]) {
|
||||||
case "tree":
|
case "tree":
|
||||||
commit.Tree = *NewTree(gitRepo, objectID.Type().MustIDFromString(string(data)))
|
commit.Tree = *NewTree(gitRepo, MustIDFromString(string(data)))
|
||||||
_, _ = payloadSB.Write(line)
|
_, _ = payloadSB.Write(line)
|
||||||
case "parent":
|
case "parent":
|
||||||
commit.Parents = append(commit.Parents, objectID.Type().MustIDFromString(string(data)))
|
commit.Parents = append(commit.Parents, MustIDFromString(string(data)))
|
||||||
_, _ = payloadSB.Write(line)
|
_, _ = payloadSB.Write(line)
|
||||||
case "author":
|
case "author":
|
||||||
commit.Author = &Signature{}
|
commit.Author = &Signature{}
|
||||||
|
@ -135,8 +135,8 @@ func TestHasPreviousCommit(t *testing.T) {
|
|||||||
commit, err := repo.GetCommit("8006ff9adbf0cb94da7dad9e537e53817f9fa5c0")
|
commit, err := repo.GetCommit("8006ff9adbf0cb94da7dad9e537e53817f9fa5c0")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
parentSHA := repo.objectFormat.MustIDFromString("8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2")
|
parentSHA := MustIDFromString("8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2")
|
||||||
notParentSHA := repo.objectFormat.MustIDFromString("2839944139e0de9737a044f78b0e4b40d989a9e3")
|
notParentSHA := MustIDFromString("2839944139e0de9737a044f78b0e4b40d989a9e3")
|
||||||
|
|
||||||
haz, err := commit.HasPreviousCommit(parentSHA)
|
haz, err := commit.HasPreviousCommit(parentSHA)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -39,7 +39,7 @@ func NewLastCommitCache(count int64, repoPath string, gitRepo *Repository, cache
|
|||||||
if cache == nil {
|
if cache == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if !setting.CacheService.LastCommit.Enabled || count < setting.CacheService.LastCommit.CommitsCount {
|
if count < setting.CacheService.LastCommit.CommitsCount {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,11 +92,7 @@ func (c *LastCommitCache) Get(ref, entryPath string) (*Commit, error) {
|
|||||||
|
|
||||||
// GetCommitByPath gets the last commit for the entry in the provided commit
|
// GetCommitByPath gets the last commit for the entry in the provided commit
|
||||||
func (c *LastCommitCache) GetCommitByPath(commitID, entryPath string) (*Commit, error) {
|
func (c *LastCommitCache) GetCommitByPath(commitID, entryPath string) (*Commit, error) {
|
||||||
objectFormat, err := c.repo.GetObjectFormat()
|
sha, err := NewIDFromString(commitID)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
sha, err := objectFormat.NewIDFromString(commitID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -5,97 +5,89 @@ package git
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"fmt"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strconv"
|
||||||
)
|
|
||||||
|
|
||||||
type ObjectFormatID int
|
|
||||||
|
|
||||||
const (
|
|
||||||
Sha1 ObjectFormatID = iota
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// sha1Pattern can be used to determine if a string is an valid sha
|
// sha1Pattern can be used to determine if a string is an valid sha
|
||||||
var sha1Pattern = regexp.MustCompile(`^[0-9a-f]{4,40}$`)
|
var sha1Pattern = regexp.MustCompile(`^[0-9a-f]{4,40}$`)
|
||||||
|
|
||||||
type ObjectFormat interface {
|
type ObjectFormat interface {
|
||||||
ID() ObjectFormatID
|
// Name returns the name of the object format
|
||||||
String() string
|
Name() string
|
||||||
|
// EmptyObjectID creates a new empty ObjectID from an object format hash name
|
||||||
// Empty is the hash of empty git
|
EmptyObjectID() ObjectID
|
||||||
Empty() ObjectID
|
|
||||||
// EmptyTree is the hash of an empty tree
|
// EmptyTree is the hash of an empty tree
|
||||||
EmptyTree() ObjectID
|
EmptyTree() ObjectID
|
||||||
// FullLength is the length of the hash's hex string
|
// FullLength is the length of the hash's hex string
|
||||||
FullLength() int
|
FullLength() int
|
||||||
|
// IsValid returns true if the input is a valid hash
|
||||||
IsValid(input string) bool
|
IsValid(input string) bool
|
||||||
|
// MustID creates a new ObjectID from a byte slice
|
||||||
MustID(b []byte) ObjectID
|
MustID(b []byte) ObjectID
|
||||||
MustIDFromString(s string) ObjectID
|
// ComputeHash compute the hash for a given ObjectType and content
|
||||||
NewID(b []byte) (ObjectID, error)
|
ComputeHash(t ObjectType, content []byte) ObjectID
|
||||||
NewIDFromString(s string) (ObjectID, error)
|
|
||||||
NewEmptyID() ObjectID
|
|
||||||
|
|
||||||
NewHasher() HasherInterface
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Sha1ObjectFormat struct{}
|
type Sha1ObjectFormatImpl struct{}
|
||||||
|
|
||||||
func (*Sha1ObjectFormat) ID() ObjectFormatID { return Sha1 }
|
var (
|
||||||
func (*Sha1ObjectFormat) String() string { return "sha1" }
|
emptyObjectID = &Sha1Hash{}
|
||||||
func (*Sha1ObjectFormat) Empty() ObjectID { return &Sha1Hash{} }
|
emptyTree = &Sha1Hash{
|
||||||
func (*Sha1ObjectFormat) EmptyTree() ObjectID {
|
|
||||||
return &Sha1Hash{
|
|
||||||
0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,
|
0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,
|
||||||
0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04,
|
0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04,
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (Sha1ObjectFormatImpl) Name() string { return "sha1" }
|
||||||
|
func (Sha1ObjectFormatImpl) EmptyObjectID() ObjectID {
|
||||||
|
return emptyObjectID
|
||||||
}
|
}
|
||||||
func (*Sha1ObjectFormat) FullLength() int { return 40 }
|
|
||||||
func (*Sha1ObjectFormat) IsValid(input string) bool {
|
func (Sha1ObjectFormatImpl) EmptyTree() ObjectID {
|
||||||
|
return emptyTree
|
||||||
|
}
|
||||||
|
func (Sha1ObjectFormatImpl) FullLength() int { return 40 }
|
||||||
|
func (Sha1ObjectFormatImpl) IsValid(input string) bool {
|
||||||
return sha1Pattern.MatchString(input)
|
return sha1Pattern.MatchString(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*Sha1ObjectFormat) MustID(b []byte) ObjectID {
|
func (Sha1ObjectFormatImpl) MustID(b []byte) ObjectID {
|
||||||
var id Sha1Hash
|
var id Sha1Hash
|
||||||
copy(id[0:20], b)
|
copy(id[0:20], b)
|
||||||
return &id
|
return &id
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Sha1ObjectFormat) MustIDFromString(s string) ObjectID {
|
// ComputeHash compute the hash for a given ObjectType and content
|
||||||
return MustIDFromString(h, s)
|
func (h Sha1ObjectFormatImpl) ComputeHash(t ObjectType, content []byte) ObjectID {
|
||||||
|
hasher := sha1.New()
|
||||||
|
_, _ = hasher.Write(t.Bytes())
|
||||||
|
_, _ = hasher.Write([]byte(" "))
|
||||||
|
_, _ = hasher.Write([]byte(strconv.FormatInt(int64(len(content)), 10)))
|
||||||
|
_, _ = hasher.Write([]byte{0})
|
||||||
|
|
||||||
|
// HashSum generates a SHA1 for the provided hash
|
||||||
|
var sha1 Sha1Hash
|
||||||
|
copy(sha1[:], hasher.Sum(nil))
|
||||||
|
return &sha1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Sha1ObjectFormat) NewID(b []byte) (ObjectID, error) {
|
var Sha1ObjectFormat ObjectFormat = Sha1ObjectFormatImpl{}
|
||||||
return IDFromRaw(h, b)
|
|
||||||
|
var SupportedObjectFormats = []ObjectFormat{
|
||||||
|
Sha1ObjectFormat,
|
||||||
|
// TODO: add sha256
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Sha1ObjectFormat) NewIDFromString(s string) (ObjectID, error) {
|
func ObjectFormatFromName(name string) ObjectFormat {
|
||||||
return genericIDFromString(h, s)
|
for _, objectFormat := range SupportedObjectFormats {
|
||||||
|
if name == objectFormat.Name() {
|
||||||
|
return objectFormat
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*Sha1ObjectFormat) NewEmptyID() ObjectID {
|
|
||||||
return NewSha1()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Sha1ObjectFormat) NewHasher() HasherInterface {
|
|
||||||
return &Sha1Hasher{sha1.New()}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ObjectFormatFromID(id ObjectFormatID) ObjectFormat {
|
|
||||||
switch id {
|
|
||||||
case Sha1:
|
|
||||||
return &Sha1ObjectFormat{}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ObjectFormatFromString(hash string) (ObjectFormat, error) {
|
func IsValidObjectFormat(name string) bool {
|
||||||
switch strings.ToLower(hash) {
|
return ObjectFormatFromName(name) != nil
|
||||||
case "sha1":
|
|
||||||
return &Sha1ObjectFormat{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("unknown hash type: %s", hash)
|
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,7 @@ package git
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ObjectID interface {
|
type ObjectID interface {
|
||||||
@ -31,59 +27,40 @@ func (h *Sha1Hash) IsZero() bool {
|
|||||||
return bytes.Equal(empty[:], h[:])
|
return bytes.Equal(empty[:], h[:])
|
||||||
}
|
}
|
||||||
func (h *Sha1Hash) RawValue() []byte { return h[:] }
|
func (h *Sha1Hash) RawValue() []byte { return h[:] }
|
||||||
func (*Sha1Hash) Type() ObjectFormat { return &Sha1ObjectFormat{} }
|
func (*Sha1Hash) Type() ObjectFormat { return Sha1ObjectFormat }
|
||||||
|
|
||||||
func NewSha1() *Sha1Hash {
|
var _ ObjectID = &Sha1Hash{}
|
||||||
return &Sha1Hash{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewHash is for generic implementations
|
func MustIDFromString(hexHash string) ObjectID {
|
||||||
func NewHash(hash string) (ObjectID, error) {
|
id, err := NewIDFromString(hexHash)
|
||||||
hash = strings.ToLower(hash)
|
|
||||||
switch hash {
|
|
||||||
case "sha1":
|
|
||||||
return &Sha1Hash{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, errors.New("unsupported hash type")
|
|
||||||
}
|
|
||||||
|
|
||||||
func IDFromRaw(h ObjectFormat, b []byte) (ObjectID, error) {
|
|
||||||
if len(b) != h.FullLength()/2 {
|
|
||||||
return h.Empty(), fmt.Errorf("length must be %d: %v", h.FullLength(), b)
|
|
||||||
}
|
|
||||||
return h.MustID(b), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func MustIDFromString(h ObjectFormat, s string) ObjectID {
|
|
||||||
b, _ := hex.DecodeString(s)
|
|
||||||
return h.MustID(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func genericIDFromString(h ObjectFormat, s string) (ObjectID, error) {
|
|
||||||
s = strings.TrimSpace(s)
|
|
||||||
if len(s) != h.FullLength() {
|
|
||||||
return h.Empty(), fmt.Errorf("length must be %d: %s", h.FullLength(), s)
|
|
||||||
}
|
|
||||||
b, err := hex.DecodeString(s)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return h.Empty(), err
|
panic(err)
|
||||||
}
|
}
|
||||||
return h.NewID(b)
|
return id
|
||||||
}
|
}
|
||||||
|
|
||||||
func IDFromString(hexHash string) (ObjectID, error) {
|
func NewIDFromString(hexHash string) (ObjectID, error) {
|
||||||
switch len(hexHash) {
|
var theObjectFormat ObjectFormat
|
||||||
case 40:
|
for _, objectFormat := range SupportedObjectFormats {
|
||||||
hashType := Sha1ObjectFormat{}
|
if len(hexHash) == objectFormat.FullLength() {
|
||||||
h, err := hashType.NewIDFromString(hexHash)
|
theObjectFormat = objectFormat
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if theObjectFormat == nil {
|
||||||
|
return nil, fmt.Errorf("length %d has no matched object format: %s", len(hexHash), hexHash)
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := hex.DecodeString(hexHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return h, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("invalid hash hex string: '%s' len: %d", hexHash, len(hexHash))
|
if len(b) != theObjectFormat.FullLength()/2 {
|
||||||
|
return theObjectFormat.EmptyObjectID(), fmt.Errorf("length must be %d: %v", theObjectFormat.FullLength(), b)
|
||||||
|
}
|
||||||
|
return theObjectFormat.MustID(b), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsEmptyCommitID(commitID string) bool {
|
func IsEmptyCommitID(commitID string) bool {
|
||||||
@ -91,7 +68,7 @@ func IsEmptyCommitID(commitID string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := IDFromString(commitID)
|
id, err := NewIDFromString(commitID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -99,37 +76,9 @@ func IsEmptyCommitID(commitID string) bool {
|
|||||||
return id.IsZero()
|
return id.IsZero()
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasherInterface is a struct that will generate a Hash
|
|
||||||
type HasherInterface interface {
|
|
||||||
hash.Hash
|
|
||||||
|
|
||||||
HashSum() ObjectID
|
|
||||||
}
|
|
||||||
|
|
||||||
type Sha1Hasher struct {
|
|
||||||
hash.Hash
|
|
||||||
}
|
|
||||||
|
|
||||||
// ComputeBlobHash compute the hash for a given blob content
|
// ComputeBlobHash compute the hash for a given blob content
|
||||||
func ComputeBlobHash(hashType ObjectFormat, content []byte) ObjectID {
|
func ComputeBlobHash(hashType ObjectFormat, content []byte) ObjectID {
|
||||||
return ComputeHash(hashType, ObjectBlob, content)
|
return hashType.ComputeHash(ObjectBlob, content)
|
||||||
}
|
|
||||||
|
|
||||||
// ComputeHash compute the hash for a given ObjectType and content
|
|
||||||
func ComputeHash(hashType ObjectFormat, t ObjectType, content []byte) ObjectID {
|
|
||||||
h := hashType.NewHasher()
|
|
||||||
_, _ = h.Write(t.Bytes())
|
|
||||||
_, _ = h.Write([]byte(" "))
|
|
||||||
_, _ = h.Write([]byte(strconv.FormatInt(int64(len(content)), 10)))
|
|
||||||
_, _ = h.Write([]byte{0})
|
|
||||||
return h.HashSum()
|
|
||||||
}
|
|
||||||
|
|
||||||
// HashSum generates a SHA1 for the provided hash
|
|
||||||
func (h *Sha1Hasher) HashSum() ObjectID {
|
|
||||||
var sha1 Sha1Hash
|
|
||||||
copy(sha1[:], h.Hash.Sum(nil))
|
|
||||||
return &sha1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ErrInvalidSHA struct {
|
type ErrInvalidSHA struct {
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
func ParseGogitHash(h plumbing.Hash) ObjectID {
|
func ParseGogitHash(h plumbing.Hash) ObjectID {
|
||||||
switch hash.Size {
|
switch hash.Size {
|
||||||
case 20:
|
case 20:
|
||||||
return ObjectFormatFromID(Sha1).MustID(h[:])
|
return Sha1ObjectFormat.MustID(h[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestIsValidSHAPattern(t *testing.T) {
|
func TestIsValidSHAPattern(t *testing.T) {
|
||||||
h := NewSha1().Type()
|
h := Sha1ObjectFormat
|
||||||
assert.True(t, h.IsValid("fee1"))
|
assert.True(t, h.IsValid("fee1"))
|
||||||
assert.True(t, h.IsValid("abc000"))
|
assert.True(t, h.IsValid("abc000"))
|
||||||
assert.True(t, h.IsValid("9023902390239023902390239023902390239023"))
|
assert.True(t, h.IsValid("9023902390239023902390239023902390239023"))
|
||||||
|
@ -57,7 +57,7 @@ func parseTreeEntries(data []byte, ptree *Tree) ([]*TreeEntry, error) {
|
|||||||
return nil, fmt.Errorf("Invalid ls-tree output: %s", string(data))
|
return nil, fmt.Errorf("Invalid ls-tree output: %s", string(data))
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
entry.ID, err = IDFromString(string(data[pos : pos+hash.Size*2]))
|
entry.ID, err = NewIDFromString(string(data[pos : pos+hash.Size*2]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("invalid ls-tree output: %w", err)
|
return nil, fmt.Errorf("invalid ls-tree output: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -28,9 +28,9 @@ func TestParseTreeEntries(t *testing.T) {
|
|||||||
Input: "100644 blob 61ab7345a1a3bbc590068ccae37b8515cfc5843c 1022\texample/file2.txt\n",
|
Input: "100644 blob 61ab7345a1a3bbc590068ccae37b8515cfc5843c 1022\texample/file2.txt\n",
|
||||||
Expected: []*TreeEntry{
|
Expected: []*TreeEntry{
|
||||||
{
|
{
|
||||||
ID: ObjectFormatFromID(Sha1).MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c"),
|
ID: MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c"),
|
||||||
gogitTreeEntry: &object.TreeEntry{
|
gogitTreeEntry: &object.TreeEntry{
|
||||||
Hash: plumbing.Hash(ObjectFormatFromID(Sha1).MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c").RawValue()),
|
Hash: plumbing.Hash(MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c").RawValue()),
|
||||||
Name: "example/file2.txt",
|
Name: "example/file2.txt",
|
||||||
Mode: filemode.Regular,
|
Mode: filemode.Regular,
|
||||||
},
|
},
|
||||||
@ -44,9 +44,9 @@ func TestParseTreeEntries(t *testing.T) {
|
|||||||
"040000 tree 1d01fb729fb0db5881daaa6030f9f2d3cd3d5ae8 -\texample\n",
|
"040000 tree 1d01fb729fb0db5881daaa6030f9f2d3cd3d5ae8 -\texample\n",
|
||||||
Expected: []*TreeEntry{
|
Expected: []*TreeEntry{
|
||||||
{
|
{
|
||||||
ID: ObjectFormatFromID(Sha1).MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c"),
|
ID: MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c"),
|
||||||
gogitTreeEntry: &object.TreeEntry{
|
gogitTreeEntry: &object.TreeEntry{
|
||||||
Hash: plumbing.Hash(ObjectFormatFromID(Sha1).MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c").RawValue()),
|
Hash: plumbing.Hash(MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c").RawValue()),
|
||||||
Name: "example/\n.txt",
|
Name: "example/\n.txt",
|
||||||
Mode: filemode.Symlink,
|
Mode: filemode.Symlink,
|
||||||
},
|
},
|
||||||
@ -54,10 +54,10 @@ func TestParseTreeEntries(t *testing.T) {
|
|||||||
sized: true,
|
sized: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ID: ObjectFormatFromID(Sha1).MustIDFromString("1d01fb729fb0db5881daaa6030f9f2d3cd3d5ae8"),
|
ID: MustIDFromString("1d01fb729fb0db5881daaa6030f9f2d3cd3d5ae8"),
|
||||||
sized: true,
|
sized: true,
|
||||||
gogitTreeEntry: &object.TreeEntry{
|
gogitTreeEntry: &object.TreeEntry{
|
||||||
Hash: plumbing.Hash(ObjectFormatFromID(Sha1).MustIDFromString("1d01fb729fb0db5881daaa6030f9f2d3cd3d5ae8").RawValue()),
|
Hash: plumbing.Hash(MustIDFromString("1d01fb729fb0db5881daaa6030f9f2d3cd3d5ae8").RawValue()),
|
||||||
Name: "example",
|
Name: "example",
|
||||||
Mode: filemode.Dir,
|
Mode: filemode.Dir,
|
||||||
},
|
},
|
||||||
@ -67,7 +67,7 @@ func TestParseTreeEntries(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
entries, err := ParseTreeEntries(ObjectFormatFromID(Sha1), []byte(testCase.Input))
|
entries, err := ParseTreeEntries(Sha1ObjectFormat, []byte(testCase.Input))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
if len(entries) > 1 {
|
if len(entries) > 1 {
|
||||||
fmt.Println(testCase.Expected[0].ID)
|
fmt.Println(testCase.Expected[0].ID)
|
||||||
|
@ -72,7 +72,7 @@ func parseTreeEntries(objectFormat ObjectFormat, data []byte, ptree *Tree) ([]*T
|
|||||||
return nil, fmt.Errorf("unknown type: %v", string(entryMode))
|
return nil, fmt.Errorf("unknown type: %v", string(entryMode))
|
||||||
}
|
}
|
||||||
|
|
||||||
entry.ID, err = objectFormat.NewIDFromString(string(entryObjectID))
|
entry.ID, err = NewIDFromString(string(entryObjectID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("invalid ls-tree output (invalid object id): %q, err: %w", line, err)
|
return nil, fmt.Errorf("invalid ls-tree output (invalid object id): %q, err: %w", line, err)
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestParseTreeEntriesLong(t *testing.T) {
|
func TestParseTreeEntriesLong(t *testing.T) {
|
||||||
objectFormat := ObjectFormatFromID(Sha1)
|
objectFormat := Sha1ObjectFormat
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
Input string
|
Input string
|
||||||
@ -26,28 +26,28 @@ func TestParseTreeEntriesLong(t *testing.T) {
|
|||||||
`,
|
`,
|
||||||
Expected: []*TreeEntry{
|
Expected: []*TreeEntry{
|
||||||
{
|
{
|
||||||
ID: objectFormat.MustIDFromString("ea0d83c9081af9500ac9f804101b3fd0a5c293af"),
|
ID: MustIDFromString("ea0d83c9081af9500ac9f804101b3fd0a5c293af"),
|
||||||
name: "README.md",
|
name: "README.md",
|
||||||
entryMode: EntryModeBlob,
|
entryMode: EntryModeBlob,
|
||||||
size: 8218,
|
size: 8218,
|
||||||
sized: true,
|
sized: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ID: objectFormat.MustIDFromString("037f27dc9d353ae4fd50f0474b2194c593914e35"),
|
ID: MustIDFromString("037f27dc9d353ae4fd50f0474b2194c593914e35"),
|
||||||
name: "README_ZH.md",
|
name: "README_ZH.md",
|
||||||
entryMode: EntryModeBlob,
|
entryMode: EntryModeBlob,
|
||||||
size: 4681,
|
size: 4681,
|
||||||
sized: true,
|
sized: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ID: objectFormat.MustIDFromString("9846a94f7e8350a916632929d0fda38c90dd2ca8"),
|
ID: MustIDFromString("9846a94f7e8350a916632929d0fda38c90dd2ca8"),
|
||||||
name: "SECURITY.md",
|
name: "SECURITY.md",
|
||||||
entryMode: EntryModeBlob,
|
entryMode: EntryModeBlob,
|
||||||
size: 429,
|
size: 429,
|
||||||
sized: true,
|
sized: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ID: objectFormat.MustIDFromString("84b90550547016f73c5dd3f50dea662389e67b6d"),
|
ID: MustIDFromString("84b90550547016f73c5dd3f50dea662389e67b6d"),
|
||||||
name: "assets",
|
name: "assets",
|
||||||
entryMode: EntryModeTree,
|
entryMode: EntryModeTree,
|
||||||
sized: true,
|
sized: true,
|
||||||
@ -66,7 +66,7 @@ func TestParseTreeEntriesLong(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestParseTreeEntriesShort(t *testing.T) {
|
func TestParseTreeEntriesShort(t *testing.T) {
|
||||||
objectFormat := ObjectFormatFromID(Sha1)
|
objectFormat := Sha1ObjectFormat
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
Input string
|
Input string
|
||||||
@ -78,12 +78,12 @@ func TestParseTreeEntriesShort(t *testing.T) {
|
|||||||
`,
|
`,
|
||||||
Expected: []*TreeEntry{
|
Expected: []*TreeEntry{
|
||||||
{
|
{
|
||||||
ID: objectFormat.MustIDFromString("ea0d83c9081af9500ac9f804101b3fd0a5c293af"),
|
ID: MustIDFromString("ea0d83c9081af9500ac9f804101b3fd0a5c293af"),
|
||||||
name: "README.md",
|
name: "README.md",
|
||||||
entryMode: EntryModeBlob,
|
entryMode: EntryModeBlob,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ID: objectFormat.MustIDFromString("84b90550547016f73c5dd3f50dea662389e67b6d"),
|
ID: MustIDFromString("84b90550547016f73c5dd3f50dea662389e67b6d"),
|
||||||
name: "assets",
|
name: "assets",
|
||||||
entryMode: EntryModeTree,
|
entryMode: EntryModeTree,
|
||||||
},
|
},
|
||||||
@ -102,7 +102,7 @@ func TestParseTreeEntriesShort(t *testing.T) {
|
|||||||
|
|
||||||
func TestParseTreeEntriesInvalid(t *testing.T) {
|
func TestParseTreeEntriesInvalid(t *testing.T) {
|
||||||
// there was a panic: "runtime error: slice bounds out of range" when the input was invalid: #20315
|
// there was a panic: "runtime error: slice bounds out of range" when the input was invalid: #20315
|
||||||
entries, err := ParseTreeEntries(ObjectFormatFromID(Sha1), []byte("100644 blob ea0d83c9081af9500ac9f804101b3fd0a5c293af"))
|
entries, err := ParseTreeEntries(Sha1ObjectFormat, []byte("100644 blob ea0d83c9081af9500ac9f804101b3fd0a5c293af"))
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Len(t, entries, 0)
|
assert.Len(t, entries, 0)
|
||||||
}
|
}
|
||||||
|
@ -115,11 +115,7 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
|
|||||||
continue
|
continue
|
||||||
case "commit":
|
case "commit":
|
||||||
// Read in the commit to get its tree and in case this is one of the last used commits
|
// Read in the commit to get its tree and in case this is one of the last used commits
|
||||||
objectFormat, err := repo.GetObjectFormat()
|
curCommit, err = git.CommitFromReader(repo, git.MustIDFromString(string(commitID)), io.LimitReader(batchReader, size))
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
curCommit, err = git.CommitFromReader(repo, objectFormat.MustIDFromString(string(commitID)), io.LimitReader(batchReader, size))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -205,7 +205,7 @@ func RefURL(repoURL, ref string) string {
|
|||||||
return repoURL + "/src/branch/" + refName
|
return repoURL + "/src/branch/" + refName
|
||||||
case refFullName.IsTag():
|
case refFullName.IsTag():
|
||||||
return repoURL + "/src/tag/" + refName
|
return repoURL + "/src/tag/" + refName
|
||||||
case !ObjectFormatFromID(Sha1).IsValid(ref):
|
case !Sha1ObjectFormat.IsValid(ref):
|
||||||
// assume they mean a branch
|
// assume they mean a branch
|
||||||
return repoURL + "/src/branch/" + refName
|
return repoURL + "/src/branch/" + refName
|
||||||
default:
|
default:
|
||||||
|
@ -81,7 +81,7 @@ func GetObjectFormatOfRepo(ctx context.Context, repoPath string) (ObjectFormat,
|
|||||||
return nil, errors.New(stderr.String())
|
return nil, errors.New(stderr.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
h, err := IDFromString(strings.TrimRight(stdout.String(), "\n"))
|
h, err := NewIDFromString(strings.TrimRight(stdout.String(), "\n"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -90,7 +90,7 @@ func GetObjectFormatOfRepo(ctx context.Context, repoPath string) (ObjectFormat,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// InitRepository initializes a new Git repository.
|
// InitRepository initializes a new Git repository.
|
||||||
func InitRepository(ctx context.Context, repoPath string, bare bool, objectFormat ObjectFormat) error {
|
func InitRepository(ctx context.Context, repoPath string, bare bool, objectFormatName string) error {
|
||||||
err := os.MkdirAll(repoPath, os.ModePerm)
|
err := os.MkdirAll(repoPath, os.ModePerm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -98,7 +98,13 @@ func InitRepository(ctx context.Context, repoPath string, bare bool, objectForma
|
|||||||
|
|
||||||
cmd := NewCommand(ctx, "init")
|
cmd := NewCommand(ctx, "init")
|
||||||
if SupportHashSha256 {
|
if SupportHashSha256 {
|
||||||
cmd.AddOptionValues("--object-format", objectFormat.String())
|
if objectFormatName == "" {
|
||||||
|
objectFormatName = Sha1ObjectFormat.Name()
|
||||||
|
}
|
||||||
|
if !IsValidObjectFormat(objectFormatName) {
|
||||||
|
return fmt.Errorf("invalid object format: %s", objectFormatName)
|
||||||
|
}
|
||||||
|
cmd.AddOptionValues("--object-format", objectFormatName)
|
||||||
}
|
}
|
||||||
if bare {
|
if bare {
|
||||||
cmd.AddArguments("--bare")
|
cmd.AddArguments("--bare")
|
||||||
|
@ -5,7 +5,7 @@ package git
|
|||||||
|
|
||||||
// GetBlob finds the blob object in the repository.
|
// GetBlob finds the blob object in the repository.
|
||||||
func (repo *Repository) GetBlob(idStr string) (*Blob, error) {
|
func (repo *Repository) GetBlob(idStr string) (*Blob, error) {
|
||||||
id, err := repo.objectFormat.NewIDFromString(idStr)
|
id, err := NewIDFromString(idStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ func TestRepository_GetBlob_NoId(t *testing.T) {
|
|||||||
defer r.Close()
|
defer r.Close()
|
||||||
|
|
||||||
testCase := ""
|
testCase := ""
|
||||||
testError := fmt.Errorf("length must be 40: %s", testCase)
|
testError := fmt.Errorf("length %d has no matched object format: %s", len(testCase), testCase)
|
||||||
|
|
||||||
blob, err := r.GetBlob(testCase)
|
blob, err := r.GetBlob(testCase)
|
||||||
assert.Nil(t, blob)
|
assert.Nil(t, blob)
|
||||||
|
@ -63,7 +63,7 @@ func (repo *Repository) getCommitByPathWithID(id ObjectID, relpath string) (*Com
|
|||||||
return nil, runErr
|
return nil, runErr
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := repo.objectFormat.NewIDFromString(stdout)
|
id, err := NewIDFromString(stdout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -254,7 +254,7 @@ func (repo *Repository) CommitsByFileAndRange(opts CommitsByFileAndRangeOptions)
|
|||||||
}
|
}
|
||||||
return commits, err
|
return commits, err
|
||||||
}
|
}
|
||||||
objectID, err := repo.objectFormat.NewIDFromString(string(shaline[0:len]))
|
objectID, err := NewIDFromString(string(shaline[0:len]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ func (repo *Repository) RemoveReference(name string) error {
|
|||||||
func (repo *Repository) ConvertToGitID(commitID string) (ObjectID, error) {
|
func (repo *Repository) ConvertToGitID(commitID string) (ObjectID, error) {
|
||||||
objectFormat := repo.objectFormat
|
objectFormat := repo.objectFormat
|
||||||
if len(commitID) == hash.HexSize && objectFormat.IsValid(commitID) {
|
if len(commitID) == hash.HexSize && objectFormat.IsValid(commitID) {
|
||||||
ID, err := objectFormat.NewIDFromString(commitID)
|
ID, err := NewIDFromString(commitID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return ID, nil
|
return ID, nil
|
||||||
}
|
}
|
||||||
@ -54,12 +54,12 @@ func (repo *Repository) ConvertToGitID(commitID string) (ObjectID, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
if strings.Contains(err.Error(), "unknown revision or path") ||
|
if strings.Contains(err.Error(), "unknown revision or path") ||
|
||||||
strings.Contains(err.Error(), "fatal: Needed a single revision") {
|
strings.Contains(err.Error(), "fatal: Needed a single revision") {
|
||||||
return objectFormat.Empty(), ErrNotExist{commitID, ""}
|
return objectFormat.EmptyObjectID(), ErrNotExist{commitID, ""}
|
||||||
}
|
}
|
||||||
return objectFormat.Empty(), err
|
return objectFormat.EmptyObjectID(), err
|
||||||
}
|
}
|
||||||
|
|
||||||
return objectFormat.NewIDFromString(actualCommitID)
|
return NewIDFromString(actualCommitID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsCommitExist returns true if given commit exists in current repository.
|
// IsCommitExist returns true if given commit exists in current repository.
|
||||||
|
@ -135,7 +135,7 @@ func (repo *Repository) getCommitFromBatchReader(rd *bufio.Reader, id ObjectID)
|
|||||||
func (repo *Repository) ConvertToGitID(commitID string) (ObjectID, error) {
|
func (repo *Repository) ConvertToGitID(commitID string) (ObjectID, error) {
|
||||||
IDType := repo.objectFormat
|
IDType := repo.objectFormat
|
||||||
if len(commitID) == IDType.FullLength() && IDType.IsValid(commitID) {
|
if len(commitID) == IDType.FullLength() && IDType.IsValid(commitID) {
|
||||||
ID, err := repo.objectFormat.NewIDFromString(commitID)
|
ID, err := NewIDFromString(commitID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return ID, nil
|
return ID, nil
|
||||||
}
|
}
|
||||||
@ -155,5 +155,5 @@ func (repo *Repository) ConvertToGitID(commitID string) (ObjectID, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return repo.objectFormat.MustIDFromString(string(sha)), nil
|
return MustIDFromString(string(sha)), nil
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ func (r *Repository) CommitNodeIndex() (cgobject.CommitNodeIndex, *os.File) {
|
|||||||
|
|
||||||
file, err := os.Open(indexPath)
|
file, err := os.Open(indexPath)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
var index commitgraph.Index
|
var index commitgraph.Index // TODO: in newer go-git, it might need to use "github.com/go-git/go-git/v5/plumbing/format/commitgraph/v2" package to compile
|
||||||
index, err = commitgraph.OpenFileIndex(file)
|
index, err = commitgraph.OpenFileIndex(file)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return cgobject.NewGraphCommitNodeIndex(index, r.gogitRepo.Storer), file
|
return cgobject.NewGraphCommitNodeIndex(index, r.gogitRepo.Storer), file
|
||||||
|
@ -284,7 +284,7 @@ func (repo *Repository) GetPatch(base, head string, w io.Writer) error {
|
|||||||
// If base is the SHA of an empty tree (EmptyTreeSHA), it returns the files changes from the initial commit to the head commit
|
// If base is the SHA of an empty tree (EmptyTreeSHA), it returns the files changes from the initial commit to the head commit
|
||||||
func (repo *Repository) GetFilesChangedBetween(base, head string) ([]string, error) {
|
func (repo *Repository) GetFilesChangedBetween(base, head string) ([]string, error) {
|
||||||
cmd := NewCommand(repo.Ctx, "diff-tree", "--name-only", "--root", "--no-commit-id", "-r", "-z")
|
cmd := NewCommand(repo.Ctx, "diff-tree", "--name-only", "--root", "--no-commit-id", "-r", "-z")
|
||||||
if base == repo.objectFormat.Empty().String() {
|
if base == repo.objectFormat.EmptyObjectID().String() {
|
||||||
cmd.AddDynamicArguments(head)
|
cmd.AddDynamicArguments(head)
|
||||||
} else {
|
} else {
|
||||||
cmd.AddDynamicArguments(base, head)
|
cmd.AddDynamicArguments(base, head)
|
||||||
|
@ -131,12 +131,12 @@ func TestGetCommitFilesChanged(t *testing.T) {
|
|||||||
files []string
|
files []string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
repo.objectFormat.Empty().String(),
|
repo.objectFormat.EmptyObjectID().String(),
|
||||||
"95bb4d39648ee7e325106df01a621c530863a653",
|
"95bb4d39648ee7e325106df01a621c530863a653",
|
||||||
[]string{"file1.txt"},
|
[]string{"file1.txt"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
repo.objectFormat.Empty().String(),
|
repo.objectFormat.EmptyObjectID().String(),
|
||||||
"8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2",
|
"8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2",
|
||||||
[]string{"file2.txt"},
|
[]string{"file2.txt"},
|
||||||
},
|
},
|
||||||
|
@ -30,7 +30,7 @@ func (repo *Repository) ReadTreeToIndex(treeish string, indexFilename ...string)
|
|||||||
treeish = res[:len(res)-1]
|
treeish = res[:len(res)-1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
id, err := objectFormat.NewIDFromString(treeish)
|
id, err := NewIDFromString(treeish)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -101,7 +101,7 @@ func (repo *Repository) RemoveFilesFromIndex(filenames ...string) error {
|
|||||||
for _, file := range filenames {
|
for _, file := range filenames {
|
||||||
if file != "" {
|
if file != "" {
|
||||||
buffer.WriteString("0 ")
|
buffer.WriteString("0 ")
|
||||||
buffer.WriteString(repo.objectFormat.Empty().String())
|
buffer.WriteString(repo.objectFormat.EmptyObjectID().String())
|
||||||
buffer.WriteByte('\t')
|
buffer.WriteByte('\t')
|
||||||
buffer.WriteString(file)
|
buffer.WriteString(file)
|
||||||
buffer.WriteByte('\000')
|
buffer.WriteByte('\000')
|
||||||
@ -128,7 +128,7 @@ func (repo *Repository) WriteTree() (*Tree, error) {
|
|||||||
if runErr != nil {
|
if runErr != nil {
|
||||||
return nil, runErr
|
return nil, runErr
|
||||||
}
|
}
|
||||||
id, err := repo.objectFormat.NewIDFromString(strings.TrimSpace(stdout))
|
id, err := NewIDFromString(strings.TrimSpace(stdout))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err
|
|||||||
return nil, ErrNotExist{commitID, ""}
|
return nil, ErrNotExist{commitID, ""}
|
||||||
}
|
}
|
||||||
|
|
||||||
sha, err := repo.objectFormat.NewIDFromString(string(shaBytes))
|
sha, err := NewIDFromString(string(shaBytes))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("Unable to get commit for: %s. Err: %v", commitID, err)
|
log.Debug("Unable to get commit for: %s. Err: %v", commitID, err)
|
||||||
return nil, ErrNotExist{commitID, ""}
|
return nil, ErrNotExist{commitID, ""}
|
||||||
|
@ -46,7 +46,7 @@ func (repo *Repository) GetObjectFormat() (ObjectFormat, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
hash, err := IDFromString(str)
|
hash, err := NewIDFromString(str)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -62,7 +62,7 @@ func (repo *Repository) HashObject(reader io.Reader) (ObjectID, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return repo.objectFormat.NewIDFromString(idStr)
|
return NewIDFromString(idStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *Repository) hashObject(reader io.Reader, save bool) (string, error) {
|
func (repo *Repository) hashObject(reader io.Reader, save bool) (string, error) {
|
||||||
|
@ -75,7 +75,7 @@ func (repo *Repository) GetRefsFiltered(pattern string) ([]*Reference, error) {
|
|||||||
if pattern == "" || strings.HasPrefix(refName, pattern) {
|
if pattern == "" || strings.HasPrefix(refName, pattern) {
|
||||||
r := &Reference{
|
r := &Reference{
|
||||||
Name: refName,
|
Name: refName,
|
||||||
Object: repo.objectFormat.MustIDFromString(sha),
|
Object: MustIDFromString(sha),
|
||||||
Type: typ,
|
Type: typ,
|
||||||
repo: repo,
|
repo: repo,
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ func (repo *Repository) GetTag(name string) (*Tag, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := repo.objectFormat.NewIDFromString(idStr)
|
id, err := NewIDFromString(idStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -98,7 +98,7 @@ func (repo *Repository) GetTag(name string) (*Tag, error) {
|
|||||||
|
|
||||||
// GetTagWithID returns a Git tag by given name and ID
|
// GetTagWithID returns a Git tag by given name and ID
|
||||||
func (repo *Repository) GetTagWithID(idStr, name string) (*Tag, error) {
|
func (repo *Repository) GetTagWithID(idStr, name string) (*Tag, error) {
|
||||||
id, err := repo.objectFormat.NewIDFromString(idStr)
|
id, err := NewIDFromString(idStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -165,7 +165,7 @@ func parseTagRef(objectFormat ObjectFormat, ref map[string]string) (tag *Tag, er
|
|||||||
Name: ref["refname:short"],
|
Name: ref["refname:short"],
|
||||||
}
|
}
|
||||||
|
|
||||||
tag.ID, err = objectFormat.NewIDFromString(ref["objectname"])
|
tag.ID, err = NewIDFromString(ref["objectname"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("parse objectname '%s': %w", ref["objectname"], err)
|
return nil, fmt.Errorf("parse objectname '%s': %w", ref["objectname"], err)
|
||||||
}
|
}
|
||||||
@ -175,7 +175,7 @@ func parseTagRef(objectFormat ObjectFormat, ref map[string]string) (tag *Tag, er
|
|||||||
tag.Object = tag.ID
|
tag.Object = tag.ID
|
||||||
} else {
|
} else {
|
||||||
// annotated tag
|
// annotated tag
|
||||||
tag.Object, err = objectFormat.NewIDFromString(ref["object"])
|
tag.Object, err = NewIDFromString(ref["object"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("parse object '%s': %w", ref["object"], err)
|
return nil, fmt.Errorf("parse object '%s': %w", ref["object"], err)
|
||||||
}
|
}
|
||||||
@ -208,7 +208,7 @@ func parseTagRef(objectFormat ObjectFormat, ref map[string]string) (tag *Tag, er
|
|||||||
|
|
||||||
// GetAnnotatedTag returns a Git tag by its SHA, must be an annotated tag
|
// GetAnnotatedTag returns a Git tag by its SHA, must be an annotated tag
|
||||||
func (repo *Repository) GetAnnotatedTag(sha string) (*Tag, error) {
|
func (repo *Repository) GetAnnotatedTag(sha string) (*Tag, error) {
|
||||||
id, err := repo.objectFormat.NewIDFromString(sha)
|
id, err := NewIDFromString(sha)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ func (repo *Repository) getTag(tagID ObjectID, name string) (*Tag, error) {
|
|||||||
// every tag should have a commit ID so return all errors
|
// every tag should have a commit ID so return all errors
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
commitID, err := IDFromString(commitIDStr)
|
commitID, err := NewIDFromString(commitIDStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ func (repo *Repository) getTag(tagID ObjectID, name string) (*Tag, error) {
|
|||||||
// every tag should have a commit ID so return all errors
|
// every tag should have a commit ID so return all errors
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
commitID, err := repo.objectFormat.NewIDFromString(commitIDStr)
|
commitID, err := NewIDFromString(commitIDStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -194,7 +194,7 @@ func TestRepository_GetAnnotatedTag(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRepository_parseTagRef(t *testing.T) {
|
func TestRepository_parseTagRef(t *testing.T) {
|
||||||
sha1 := ObjectFormatFromID(Sha1)
|
sha1 := Sha1ObjectFormat
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
|
||||||
@ -224,8 +224,8 @@ func TestRepository_parseTagRef(t *testing.T) {
|
|||||||
|
|
||||||
want: &Tag{
|
want: &Tag{
|
||||||
Name: "v1.9.1",
|
Name: "v1.9.1",
|
||||||
ID: sha1.MustIDFromString("ab23e4b7f4cd0caafe0174c0e7ef6d651ba72889"),
|
ID: MustIDFromString("ab23e4b7f4cd0caafe0174c0e7ef6d651ba72889"),
|
||||||
Object: sha1.MustIDFromString("ab23e4b7f4cd0caafe0174c0e7ef6d651ba72889"),
|
Object: MustIDFromString("ab23e4b7f4cd0caafe0174c0e7ef6d651ba72889"),
|
||||||
Type: "commit",
|
Type: "commit",
|
||||||
Tagger: parseAuthorLine(t, "Foo Bar <foo@bar.com> 1565789218 +0300"),
|
Tagger: parseAuthorLine(t, "Foo Bar <foo@bar.com> 1565789218 +0300"),
|
||||||
Message: "Add changelog of v1.9.1 (#7859)\n\n* add changelog of v1.9.1\n* Update CHANGELOG.md\n",
|
Message: "Add changelog of v1.9.1 (#7859)\n\n* add changelog of v1.9.1\n* Update CHANGELOG.md\n",
|
||||||
@ -253,8 +253,8 @@ func TestRepository_parseTagRef(t *testing.T) {
|
|||||||
|
|
||||||
want: &Tag{
|
want: &Tag{
|
||||||
Name: "v0.0.1",
|
Name: "v0.0.1",
|
||||||
ID: sha1.MustIDFromString("8c68a1f06fc59c655b7e3905b159d761e91c53c9"),
|
ID: MustIDFromString("8c68a1f06fc59c655b7e3905b159d761e91c53c9"),
|
||||||
Object: sha1.MustIDFromString("3325fd8a973321fd59455492976c042dde3fd1ca"),
|
Object: MustIDFromString("3325fd8a973321fd59455492976c042dde3fd1ca"),
|
||||||
Type: "tag",
|
Type: "tag",
|
||||||
Tagger: parseAuthorLine(t, "Foo Bar <foo@bar.com> 1565789218 +0300"),
|
Tagger: parseAuthorLine(t, "Foo Bar <foo@bar.com> 1565789218 +0300"),
|
||||||
Message: "Add changelog of v1.9.1 (#7859)\n\n* add changelog of v1.9.1\n* Update CHANGELOG.md\n",
|
Message: "Add changelog of v1.9.1 (#7859)\n\n* add changelog of v1.9.1\n* Update CHANGELOG.md\n",
|
||||||
@ -311,8 +311,8 @@ qbHDASXl
|
|||||||
|
|
||||||
want: &Tag{
|
want: &Tag{
|
||||||
Name: "v0.0.1",
|
Name: "v0.0.1",
|
||||||
ID: sha1.MustIDFromString("8c68a1f06fc59c655b7e3905b159d761e91c53c9"),
|
ID: MustIDFromString("8c68a1f06fc59c655b7e3905b159d761e91c53c9"),
|
||||||
Object: sha1.MustIDFromString("3325fd8a973321fd59455492976c042dde3fd1ca"),
|
Object: MustIDFromString("3325fd8a973321fd59455492976c042dde3fd1ca"),
|
||||||
Type: "tag",
|
Type: "tag",
|
||||||
Tagger: parseAuthorLine(t, "Foo Bar <foo@bar.com> 1565789218 +0300"),
|
Tagger: parseAuthorLine(t, "Foo Bar <foo@bar.com> 1565789218 +0300"),
|
||||||
Message: "Add changelog of v1.9.1 (#7859)\n\n* add changelog of v1.9.1\n* Update CHANGELOG.md",
|
Message: "Add changelog of v1.9.1 (#7859)\n\n* add changelog of v1.9.1\n* Update CHANGELOG.md",
|
||||||
|
@ -63,5 +63,5 @@ func (repo *Repository) CommitTree(author, committer *Signature, tree *Tree, opt
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ConcatenateError(err, stderr.String())
|
return nil, ConcatenateError(err, stderr.String())
|
||||||
}
|
}
|
||||||
return repo.objectFormat.NewIDFromString(strings.TrimSpace(stdout.String()))
|
return NewIDFromString(strings.TrimSpace(stdout.String()))
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ func (repo *Repository) GetTree(idStr string) (*Tree, error) {
|
|||||||
idStr = res[:len(res)-1]
|
idStr = res[:len(res)-1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
id, err := repo.objectFormat.NewIDFromString(idStr)
|
id, err := NewIDFromString(idStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ func (repo *Repository) GetTree(idStr string) (*Tree, error) {
|
|||||||
idStr = res
|
idStr = res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
id, err := repo.objectFormat.NewIDFromString(idStr)
|
id, err := NewIDFromString(idStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -35,8 +35,8 @@ func (tag *Tag) Commit(gitRepo *Repository) (*Commit, error) {
|
|||||||
// \n\n separate headers from message
|
// \n\n separate headers from message
|
||||||
func parseTagData(objectFormat ObjectFormat, data []byte) (*Tag, error) {
|
func parseTagData(objectFormat ObjectFormat, data []byte) (*Tag, error) {
|
||||||
tag := new(Tag)
|
tag := new(Tag)
|
||||||
tag.ID = objectFormat.NewEmptyID()
|
tag.ID = objectFormat.EmptyObjectID()
|
||||||
tag.Object = objectFormat.NewEmptyID()
|
tag.Object = objectFormat.EmptyObjectID()
|
||||||
tag.Tagger = &Signature{}
|
tag.Tagger = &Signature{}
|
||||||
// we now have the contents of the commit object. Let's investigate...
|
// we now have the contents of the commit object. Let's investigate...
|
||||||
nextline := 0
|
nextline := 0
|
||||||
@ -50,7 +50,7 @@ l:
|
|||||||
reftype := line[:spacepos]
|
reftype := line[:spacepos]
|
||||||
switch string(reftype) {
|
switch string(reftype) {
|
||||||
case "object":
|
case "object":
|
||||||
id, err := objectFormat.NewIDFromString(string(line[spacepos+1:]))
|
id, err := NewIDFromString(string(line[spacepos+1:]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ tagger Lucas Michot <lucas@semalead.com> 1484491741 +0100
|
|||||||
|
|
||||||
`), tag: Tag{
|
`), tag: Tag{
|
||||||
Name: "",
|
Name: "",
|
||||||
ID: NewSha1(),
|
ID: Sha1ObjectFormat.EmptyObjectID(),
|
||||||
Object: &Sha1Hash{0x3b, 0x11, 0x4a, 0xb8, 0x0, 0xc6, 0x43, 0x2a, 0xd4, 0x23, 0x87, 0xcc, 0xf6, 0xbc, 0x8d, 0x43, 0x88, 0xa2, 0x88, 0x5a},
|
Object: &Sha1Hash{0x3b, 0x11, 0x4a, 0xb8, 0x0, 0xc6, 0x43, 0x2a, 0xd4, 0x23, 0x87, 0xcc, 0xf6, 0xbc, 0x8d, 0x43, 0x88, 0xa2, 0x88, 0x5a},
|
||||||
Type: "commit",
|
Type: "commit",
|
||||||
Tagger: &Signature{Name: "Lucas Michot", Email: "lucas@semalead.com", When: time.Unix(1484491741, 0)},
|
Tagger: &Signature{Name: "Lucas Michot", Email: "lucas@semalead.com", When: time.Unix(1484491741, 0)},
|
||||||
@ -39,7 +39,7 @@ o
|
|||||||
|
|
||||||
ono`), tag: Tag{
|
ono`), tag: Tag{
|
||||||
Name: "",
|
Name: "",
|
||||||
ID: NewSha1(),
|
ID: Sha1ObjectFormat.EmptyObjectID(),
|
||||||
Object: &Sha1Hash{0x7c, 0xdf, 0x42, 0xc0, 0xb1, 0xcc, 0x76, 0x3a, 0xb7, 0xe4, 0xc3, 0x3c, 0x47, 0xa2, 0x4e, 0x27, 0xc6, 0x6b, 0xfc, 0xcc},
|
Object: &Sha1Hash{0x7c, 0xdf, 0x42, 0xc0, 0xb1, 0xcc, 0x76, 0x3a, 0xb7, 0xe4, 0xc3, 0x3c, 0x47, 0xa2, 0x4e, 0x27, 0xc6, 0x6b, 0xfc, 0xcc},
|
||||||
Type: "commit",
|
Type: "commit",
|
||||||
Tagger: &Signature{Name: "Lucas Michot", Email: "lucas@semalead.com", When: time.Unix(1484553735, 0)},
|
Tagger: &Signature{Name: "Lucas Michot", Email: "lucas@semalead.com", When: time.Unix(1484553735, 0)},
|
||||||
@ -49,7 +49,7 @@ ono`), tag: Tag{
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range testData {
|
for _, test := range testData {
|
||||||
tag, err := parseTagData(ObjectFormatFromID(Sha1), test.data)
|
tag, err := parseTagData(Sha1ObjectFormat, test.data)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.EqualValues(t, test.tag.ID, tag.ID)
|
assert.EqualValues(t, test.tag.ID, tag.ID)
|
||||||
assert.EqualValues(t, test.tag.Object, tag.Object)
|
assert.EqualValues(t, test.tag.Object, tag.Object)
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
gohtml "html"
|
gohtml "html"
|
||||||
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
@ -55,7 +56,7 @@ func NewContext() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Code returns a HTML version of code string with chroma syntax highlighting classes and the matched lexer name
|
// Code returns a HTML version of code string with chroma syntax highlighting classes and the matched lexer name
|
||||||
func Code(fileName, language, code string) (string, string) {
|
func Code(fileName, language, code string) (output template.HTML, lexerName string) {
|
||||||
NewContext()
|
NewContext()
|
||||||
|
|
||||||
// diff view newline will be passed as empty, change to literal '\n' so it can be copied
|
// diff view newline will be passed as empty, change to literal '\n' so it can be copied
|
||||||
@ -65,7 +66,7 @@ func Code(fileName, language, code string) (string, string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(code) > sizeLimit {
|
if len(code) > sizeLimit {
|
||||||
return code, ""
|
return template.HTML(template.HTMLEscapeString(code)), ""
|
||||||
}
|
}
|
||||||
|
|
||||||
var lexer chroma.Lexer
|
var lexer chroma.Lexer
|
||||||
@ -102,13 +103,11 @@ func Code(fileName, language, code string) (string, string) {
|
|||||||
cache.Add(fileName, lexer)
|
cache.Add(fileName, lexer)
|
||||||
}
|
}
|
||||||
|
|
||||||
lexerName := formatLexerName(lexer.Config().Name)
|
return CodeFromLexer(lexer, code), formatLexerName(lexer.Config().Name)
|
||||||
|
|
||||||
return CodeFromLexer(lexer, code), lexerName
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CodeFromLexer returns a HTML version of code string with chroma syntax highlighting classes
|
// CodeFromLexer returns a HTML version of code string with chroma syntax highlighting classes
|
||||||
func CodeFromLexer(lexer chroma.Lexer, code string) string {
|
func CodeFromLexer(lexer chroma.Lexer, code string) template.HTML {
|
||||||
formatter := html.New(html.WithClasses(true),
|
formatter := html.New(html.WithClasses(true),
|
||||||
html.WithLineNumbers(false),
|
html.WithLineNumbers(false),
|
||||||
html.PreventSurroundingPre(true),
|
html.PreventSurroundingPre(true),
|
||||||
@ -120,23 +119,23 @@ func CodeFromLexer(lexer chroma.Lexer, code string) string {
|
|||||||
iterator, err := lexer.Tokenise(nil, code)
|
iterator, err := lexer.Tokenise(nil, code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Can't tokenize code: %v", err)
|
log.Error("Can't tokenize code: %v", err)
|
||||||
return code
|
return template.HTML(template.HTMLEscapeString(code))
|
||||||
}
|
}
|
||||||
// style not used for live site but need to pass something
|
// style not used for live site but need to pass something
|
||||||
err = formatter.Format(htmlw, githubStyles, iterator)
|
err = formatter.Format(htmlw, githubStyles, iterator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Can't format code: %v", err)
|
log.Error("Can't format code: %v", err)
|
||||||
return code
|
return template.HTML(template.HTMLEscapeString(code))
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = htmlw.Flush()
|
_ = htmlw.Flush()
|
||||||
// Chroma will add newlines for certain lexers in order to highlight them properly
|
// Chroma will add newlines for certain lexers in order to highlight them properly
|
||||||
// Once highlighted, strip them here, so they don't cause copy/paste trouble in HTML output
|
// Once highlighted, strip them here, so they don't cause copy/paste trouble in HTML output
|
||||||
return strings.TrimSuffix(htmlbuf.String(), "\n")
|
return template.HTML(strings.TrimSuffix(htmlbuf.String(), "\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// File returns a slice of chroma syntax highlighted HTML lines of code and the matched lexer name
|
// File returns a slice of chroma syntax highlighted HTML lines of code and the matched lexer name
|
||||||
func File(fileName, language string, code []byte) ([]string, string, error) {
|
func File(fileName, language string, code []byte) ([]template.HTML, string, error) {
|
||||||
NewContext()
|
NewContext()
|
||||||
|
|
||||||
if len(code) > sizeLimit {
|
if len(code) > sizeLimit {
|
||||||
@ -183,14 +182,14 @@ func File(fileName, language string, code []byte) ([]string, string, error) {
|
|||||||
tokensLines := chroma.SplitTokensIntoLines(iterator.Tokens())
|
tokensLines := chroma.SplitTokensIntoLines(iterator.Tokens())
|
||||||
htmlBuf := &bytes.Buffer{}
|
htmlBuf := &bytes.Buffer{}
|
||||||
|
|
||||||
lines := make([]string, 0, len(tokensLines))
|
lines := make([]template.HTML, 0, len(tokensLines))
|
||||||
for _, tokens := range tokensLines {
|
for _, tokens := range tokensLines {
|
||||||
iterator = chroma.Literator(tokens...)
|
iterator = chroma.Literator(tokens...)
|
||||||
err = formatter.Format(htmlBuf, githubStyles, iterator)
|
err = formatter.Format(htmlBuf, githubStyles, iterator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", fmt.Errorf("can't format code: %w", err)
|
return nil, "", fmt.Errorf("can't format code: %w", err)
|
||||||
}
|
}
|
||||||
lines = append(lines, htmlBuf.String())
|
lines = append(lines, template.HTML(htmlBuf.String()))
|
||||||
htmlBuf.Reset()
|
htmlBuf.Reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,9 +197,9 @@ func File(fileName, language string, code []byte) ([]string, string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PlainText returns non-highlighted HTML for code
|
// PlainText returns non-highlighted HTML for code
|
||||||
func PlainText(code []byte) []string {
|
func PlainText(code []byte) []template.HTML {
|
||||||
r := bufio.NewReader(bytes.NewReader(code))
|
r := bufio.NewReader(bytes.NewReader(code))
|
||||||
m := make([]string, 0, bytes.Count(code, []byte{'\n'})+1)
|
m := make([]template.HTML, 0, bytes.Count(code, []byte{'\n'})+1)
|
||||||
for {
|
for {
|
||||||
content, err := r.ReadString('\n')
|
content, err := r.ReadString('\n')
|
||||||
if err != nil && err != io.EOF {
|
if err != nil && err != io.EOF {
|
||||||
@ -210,7 +209,7 @@ func PlainText(code []byte) []string {
|
|||||||
if content == "" && err == io.EOF {
|
if content == "" && err == io.EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
s := gohtml.EscapeString(content)
|
s := template.HTML(gohtml.EscapeString(content))
|
||||||
m = append(m, s)
|
m = append(m, s)
|
||||||
}
|
}
|
||||||
return m
|
return m
|
||||||
|
@ -4,21 +4,36 @@
|
|||||||
package highlight
|
package highlight
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"html/template"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func lines(s string) []string {
|
func lines(s string) (out []template.HTML) {
|
||||||
return strings.Split(strings.ReplaceAll(strings.TrimSpace(s), `\n`, "\n"), "\n")
|
// "" => [], "a" => ["a"], "a\n" => ["a\n"], "a\nb" => ["a\n", "b"] (each line always includes EOL "\n" if it exists)
|
||||||
|
out = make([]template.HTML, 0)
|
||||||
|
s = strings.ReplaceAll(strings.ReplaceAll(strings.TrimSpace(s), "\n", ""), `\n`, "\n")
|
||||||
|
for {
|
||||||
|
if p := strings.IndexByte(s, '\n'); p != -1 {
|
||||||
|
out = append(out, template.HTML(s[:p+1]))
|
||||||
|
s = s[p+1:]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if s != "" {
|
||||||
|
out = append(out, template.HTML(s))
|
||||||
|
}
|
||||||
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFile(t *testing.T) {
|
func TestFile(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
code string
|
code string
|
||||||
want []string
|
want []template.HTML
|
||||||
lexerName string
|
lexerName string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
@ -99,10 +114,7 @@ c=2
|
|||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
out, lexerName, err := File(tt.name, "", []byte(tt.code))
|
out, lexerName, err := File(tt.name, "", []byte(tt.code))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
expected := strings.Join(tt.want, "\n")
|
assert.EqualValues(t, tt.want, out)
|
||||||
actual := strings.Join(out, "\n")
|
|
||||||
assert.Equal(t, strings.Count(actual, "<span"), strings.Count(actual, "</span>"))
|
|
||||||
assert.EqualValues(t, expected, actual)
|
|
||||||
assert.Equal(t, tt.lexerName, lexerName)
|
assert.Equal(t, tt.lexerName, lexerName)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -112,7 +124,7 @@ func TestPlainText(t *testing.T) {
|
|||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
code string
|
code string
|
||||||
want []string
|
want []template.HTML
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "empty.py",
|
name: "empty.py",
|
||||||
@ -165,9 +177,7 @@ c=2`),
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
out := PlainText([]byte(tt.code))
|
out := PlainText([]byte(tt.code))
|
||||||
expected := strings.Join(tt.want, "\n")
|
assert.EqualValues(t, tt.want, out)
|
||||||
actual := strings.Join(out, "\n")
|
|
||||||
assert.EqualValues(t, expected, actual)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ package code
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"html/template"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/highlight"
|
"code.gitea.io/gitea/modules/highlight"
|
||||||
@ -22,7 +23,7 @@ type Result struct {
|
|||||||
Language string
|
Language string
|
||||||
Color string
|
Color string
|
||||||
LineNumbers []int
|
LineNumbers []int
|
||||||
FormattedLines string
|
FormattedLines template.HTML
|
||||||
}
|
}
|
||||||
|
|
||||||
type SearchResultLanguages = internal.SearchResultLanguages
|
type SearchResultLanguages = internal.SearchResultLanguages
|
||||||
|
@ -87,7 +87,7 @@ func Render(ctx *markup.RenderContext, input io.Reader, output io.Writer) error
|
|||||||
}
|
}
|
||||||
lexer = chroma.Coalesce(lexer)
|
lexer = chroma.Coalesce(lexer)
|
||||||
|
|
||||||
if _, err := w.WriteString(highlight.CodeFromLexer(lexer, source)); err != nil {
|
if _, err := w.WriteString(string(highlight.CodeFromLexer(lexer, source))); err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,7 +144,7 @@ func TestCommitToPushCommit(t *testing.T) {
|
|||||||
When: now,
|
When: now,
|
||||||
}
|
}
|
||||||
const hexString = "0123456789abcdef0123456789abcdef01234567"
|
const hexString = "0123456789abcdef0123456789abcdef01234567"
|
||||||
sha1, err := git.IDFromString(hexString)
|
sha1, err := git.NewIDFromString(hexString)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
pushCommit := CommitToPushCommit(&git.Commit{
|
pushCommit := CommitToPushCommit(&git.Commit{
|
||||||
ID: sha1,
|
ID: sha1,
|
||||||
@ -169,12 +169,11 @@ func TestListToPushCommits(t *testing.T) {
|
|||||||
When: now,
|
When: now,
|
||||||
}
|
}
|
||||||
|
|
||||||
hashType := git.ObjectFormatFromID(git.Sha1)
|
|
||||||
const hexString1 = "0123456789abcdef0123456789abcdef01234567"
|
const hexString1 = "0123456789abcdef0123456789abcdef01234567"
|
||||||
hash1, err := hashType.NewIDFromString(hexString1)
|
hash1, err := git.NewIDFromString(hexString1)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
const hexString2 = "fedcba9876543210fedcba9876543210fedcba98"
|
const hexString2 = "fedcba9876543210fedcba9876543210fedcba98"
|
||||||
hash2, err := hashType.NewIDFromString(hexString2)
|
hash2, err := git.NewIDFromString(hexString2)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
l := []*git.Commit{
|
l := []*git.Commit{
|
||||||
|
@ -224,7 +224,7 @@ func generateRepoCommit(ctx context.Context, repo, templateRepo, generateRepo *r
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: fix the hash
|
// FIXME: fix the hash
|
||||||
if err := git.InitRepository(ctx, tmpDir, false, git.ObjectFormatFromID(git.Sha1)); err != nil {
|
if err := git.InitRepository(ctx, tmpDir, false, git.Sha1ObjectFormat.Name()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,7 +358,7 @@ func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templ
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FIXME - fix the hash
|
// FIXME - fix the hash
|
||||||
if err = CheckInitRepository(ctx, owner.Name, generateRepo.Name, git.ObjectFormatFromID(git.Sha1)); err != nil {
|
if err = CheckInitRepository(ctx, owner.Name, generateRepo.Name, git.Sha1ObjectFormat.Name()); err != nil {
|
||||||
return generateRepo, err
|
return generateRepo, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,7 +188,7 @@ func InitRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Reposi
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckInitRepository(ctx context.Context, owner, name string, objectFormat git.ObjectFormat) (err error) {
|
func CheckInitRepository(ctx context.Context, owner, name, objectFormatName string) (err error) {
|
||||||
// Somehow the directory could exist.
|
// Somehow the directory could exist.
|
||||||
repoPath := repo_model.RepoPath(owner, name)
|
repoPath := repo_model.RepoPath(owner, name)
|
||||||
isExist, err := util.IsExist(repoPath)
|
isExist, err := util.IsExist(repoPath)
|
||||||
@ -204,7 +204,7 @@ func CheckInitRepository(ctx context.Context, owner, name string, objectFormat g
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Init git bare new repository.
|
// Init git bare new repository.
|
||||||
if err = git.InitRepository(ctx, repoPath, true, objectFormat); err != nil {
|
if err = git.InitRepository(ctx, repoPath, true, objectFormatName); err != nil {
|
||||||
return fmt.Errorf("git.InitRepository: %w", err)
|
return fmt.Errorf("git.InitRepository: %w", err)
|
||||||
} else if err = CreateDelegateHooks(repoPath); err != nil {
|
} else if err = CreateDelegateHooks(repoPath); err != nil {
|
||||||
return fmt.Errorf("createDelegateHooks: %w", err)
|
return fmt.Errorf("createDelegateHooks: %w", err)
|
||||||
|
@ -20,13 +20,13 @@ type PushUpdateOptions struct {
|
|||||||
|
|
||||||
// IsNewRef return true if it's a first-time push to a branch, tag or etc.
|
// IsNewRef return true if it's a first-time push to a branch, tag or etc.
|
||||||
func (opts *PushUpdateOptions) IsNewRef() bool {
|
func (opts *PushUpdateOptions) IsNewRef() bool {
|
||||||
commitID, err := git.IDFromString(opts.OldCommitID)
|
commitID, err := git.NewIDFromString(opts.OldCommitID)
|
||||||
return err == nil && commitID.IsZero()
|
return err == nil && commitID.IsZero()
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsDelRef return true if it's a deletion to a branch or tag
|
// IsDelRef return true if it's a deletion to a branch or tag
|
||||||
func (opts *PushUpdateOptions) IsDelRef() bool {
|
func (opts *PushUpdateOptions) IsDelRef() bool {
|
||||||
commitID, err := git.IDFromString(opts.NewCommitID)
|
commitID, err := git.NewIDFromString(opts.NewCommitID)
|
||||||
return err == nil && commitID.IsZero()
|
return err == nil && commitID.IsZero()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@ import (
|
|||||||
|
|
||||||
// Cache represents cache settings
|
// Cache represents cache settings
|
||||||
type Cache struct {
|
type Cache struct {
|
||||||
Enabled bool
|
|
||||||
Adapter string
|
Adapter string
|
||||||
Interval int
|
Interval int
|
||||||
Conn string
|
Conn string
|
||||||
@ -24,23 +23,19 @@ var CacheService = struct {
|
|||||||
Cache `ini:"cache"`
|
Cache `ini:"cache"`
|
||||||
|
|
||||||
LastCommit struct {
|
LastCommit struct {
|
||||||
Enabled bool
|
|
||||||
TTL time.Duration `ini:"ITEM_TTL"`
|
TTL time.Duration `ini:"ITEM_TTL"`
|
||||||
CommitsCount int64
|
CommitsCount int64
|
||||||
} `ini:"cache.last_commit"`
|
} `ini:"cache.last_commit"`
|
||||||
}{
|
}{
|
||||||
Cache: Cache{
|
Cache: Cache{
|
||||||
Enabled: true,
|
|
||||||
Adapter: "memory",
|
Adapter: "memory",
|
||||||
Interval: 60,
|
Interval: 60,
|
||||||
TTL: 16 * time.Hour,
|
TTL: 16 * time.Hour,
|
||||||
},
|
},
|
||||||
LastCommit: struct {
|
LastCommit: struct {
|
||||||
Enabled bool
|
|
||||||
TTL time.Duration `ini:"ITEM_TTL"`
|
TTL time.Duration `ini:"ITEM_TTL"`
|
||||||
CommitsCount int64
|
CommitsCount int64
|
||||||
}{
|
}{
|
||||||
Enabled: true,
|
|
||||||
TTL: 8760 * time.Hour,
|
TTL: 8760 * time.Hour,
|
||||||
CommitsCount: 1000,
|
CommitsCount: 1000,
|
||||||
},
|
},
|
||||||
@ -65,30 +60,12 @@ func loadCacheFrom(rootCfg ConfigProvider) {
|
|||||||
if CacheService.Conn == "" {
|
if CacheService.Conn == "" {
|
||||||
CacheService.Conn = "50000"
|
CacheService.Conn = "50000"
|
||||||
}
|
}
|
||||||
case "": // disable cache
|
|
||||||
CacheService.Enabled = false
|
|
||||||
default:
|
default:
|
||||||
log.Fatal("Unknown cache adapter: %s", CacheService.Adapter)
|
log.Fatal("Unknown cache adapter: %s", CacheService.Adapter)
|
||||||
}
|
}
|
||||||
|
|
||||||
if CacheService.Enabled {
|
|
||||||
log.Info("Cache Service Enabled")
|
|
||||||
} else {
|
|
||||||
log.Warn("Cache Service Disabled so that captcha disabled too")
|
|
||||||
// captcha depends on cache service
|
|
||||||
Service.EnableCaptcha = false
|
|
||||||
}
|
|
||||||
|
|
||||||
sec = rootCfg.Section("cache.last_commit")
|
sec = rootCfg.Section("cache.last_commit")
|
||||||
if !CacheService.Enabled {
|
|
||||||
CacheService.LastCommit.Enabled = false
|
|
||||||
}
|
|
||||||
|
|
||||||
CacheService.LastCommit.CommitsCount = sec.Key("COMMITS_COUNT").MustInt64(1000)
|
CacheService.LastCommit.CommitsCount = sec.Key("COMMITS_COUNT").MustInt64(1000)
|
||||||
|
|
||||||
if CacheService.LastCommit.Enabled {
|
|
||||||
log.Info("Last Commit Cache Service Enabled")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TTLSeconds returns the TTLSeconds or unix timestamp for memcache
|
// TTLSeconds returns the TTLSeconds or unix timestamp for memcache
|
||||||
|
@ -35,6 +35,8 @@ var UI = struct {
|
|||||||
OnlyShowRelevantRepos bool
|
OnlyShowRelevantRepos bool
|
||||||
ExploreDefaultSort string `ini:"EXPLORE_PAGING_DEFAULT_SORT"`
|
ExploreDefaultSort string `ini:"EXPLORE_PAGING_DEFAULT_SORT"`
|
||||||
|
|
||||||
|
AmbiguousUnicodeDetection bool
|
||||||
|
|
||||||
Notification struct {
|
Notification struct {
|
||||||
MinTimeout time.Duration
|
MinTimeout time.Duration
|
||||||
TimeoutStep time.Duration
|
TimeoutStep time.Duration
|
||||||
@ -82,6 +84,9 @@ var UI = struct {
|
|||||||
Reactions: []string{`+1`, `-1`, `laugh`, `hooray`, `confused`, `heart`, `rocket`, `eyes`},
|
Reactions: []string{`+1`, `-1`, `laugh`, `hooray`, `confused`, `heart`, `rocket`, `eyes`},
|
||||||
CustomEmojis: []string{`git`, `gitea`, `codeberg`, `gitlab`, `github`, `gogs`},
|
CustomEmojis: []string{`git`, `gitea`, `codeberg`, `gitlab`, `github`, `gogs`},
|
||||||
CustomEmojisMap: map[string]string{"git": ":git:", "gitea": ":gitea:", "codeberg": ":codeberg:", "gitlab": ":gitlab:", "github": ":github:", "gogs": ":gogs:"},
|
CustomEmojisMap: map[string]string{"git": ":git:", "gitea": ":gitea:", "codeberg": ":codeberg:", "gitlab": ":gitlab:", "github": ":github:", "gogs": ":gogs:"},
|
||||||
|
|
||||||
|
AmbiguousUnicodeDetection: true,
|
||||||
|
|
||||||
Notification: struct {
|
Notification: struct {
|
||||||
MinTimeout time.Duration
|
MinTimeout time.Duration
|
||||||
TimeoutStep time.Duration
|
TimeoutStep time.Duration
|
||||||
|
@ -16,8 +16,7 @@ type CreateUserOption struct {
|
|||||||
// required: true
|
// required: true
|
||||||
// swagger:strfmt email
|
// swagger:strfmt email
|
||||||
Email string `json:"email" binding:"Required;Email;MaxSize(254)"`
|
Email string `json:"email" binding:"Required;Email;MaxSize(254)"`
|
||||||
// required: true
|
Password string `json:"password" binding:"MaxSize(255)"`
|
||||||
Password string `json:"password" binding:"Required;MaxSize(255)"`
|
|
||||||
MustChangePassword *bool `json:"must_change_password"`
|
MustChangePassword *bool `json:"must_change_password"`
|
||||||
SendNotify bool `json:"send_notify"`
|
SendNotify bool `json:"send_notify"`
|
||||||
Restricted *bool `json:"restricted"`
|
Restricted *bool `json:"restricted"`
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
package util
|
package util
|
||||||
|
|
||||||
import "github.com/yuin/goldmark/util"
|
import "unsafe"
|
||||||
|
|
||||||
func isSnakeCaseUpper(c byte) bool {
|
func isSnakeCaseUpper(c byte) bool {
|
||||||
return 'A' <= c && c <= 'Z'
|
return 'A' <= c && c <= 'Z'
|
||||||
@ -83,5 +83,15 @@ func ToSnakeCase(input string) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return util.BytesToReadOnlyString(res)
|
return UnsafeBytesToString(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnsafeBytesToString uses Go's unsafe package to convert a byte slice to a string.
|
||||||
|
// TODO: replace all "goldmark/util.BytesToReadOnlyString" with this official approach
|
||||||
|
func UnsafeBytesToString(b []byte) string {
|
||||||
|
return unsafe.String(unsafe.SliceData(b), len(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnsafeStringToBytes(s string) []byte {
|
||||||
|
return unsafe.Slice(unsafe.StringData(s), len(s))
|
||||||
}
|
}
|
||||||
|
@ -3090,7 +3090,6 @@ config.enable_openid_signin = Enable OpenID Sign-In
|
|||||||
config.show_registration_button = Show Register Button
|
config.show_registration_button = Show Register Button
|
||||||
config.require_sign_in_view = Require Sign-In to View Pages
|
config.require_sign_in_view = Require Sign-In to View Pages
|
||||||
config.mail_notify = Enable Email Notifications
|
config.mail_notify = Enable Email Notifications
|
||||||
config.disable_key_size_check = Disable Minimum Key Size Check
|
|
||||||
config.enable_captcha = Enable CAPTCHA
|
config.enable_captcha = Enable CAPTCHA
|
||||||
config.active_code_lives = Active Code Lives
|
config.active_code_lives = Active Code Lives
|
||||||
config.reset_password_code_lives = Recover Account Code Expiry Time
|
config.reset_password_code_lives = Recover Account Code Expiry Time
|
||||||
@ -3536,7 +3535,7 @@ runs.commit = Commit
|
|||||||
runs.scheduled = Scheduled
|
runs.scheduled = Scheduled
|
||||||
runs.pushed_by = pushed by
|
runs.pushed_by = pushed by
|
||||||
runs.invalid_workflow_helper = Workflow config file is invalid. Please check your config file: %s
|
runs.invalid_workflow_helper = Workflow config file is invalid. Please check your config file: %s
|
||||||
runs.no_matching_runner_helper = No matching runner: %s
|
runs.no_matching_online_runner_helper = No matching online runner with label: %s
|
||||||
runs.actor = Actor
|
runs.actor = Actor
|
||||||
runs.status = Status
|
runs.status = Status
|
||||||
runs.actors_no_select = All actors
|
runs.actors_no_select = All actors
|
||||||
|
@ -17,6 +17,7 @@ template=テンプレート
|
|||||||
language=言語
|
language=言語
|
||||||
notifications=通知
|
notifications=通知
|
||||||
active_stopwatch=進行中のタイムトラッカー
|
active_stopwatch=進行中のタイムトラッカー
|
||||||
|
tracked_time_summary=イシューリストのフィルタに基づき集計したトラッキング時間
|
||||||
create_new=作成…
|
create_new=作成…
|
||||||
user_profile_and_more=プロフィールと設定…
|
user_profile_and_more=プロフィールと設定…
|
||||||
signed_in_as=サインイン済み
|
signed_in_as=サインイン済み
|
||||||
@ -359,6 +360,7 @@ disable_register_prompt=登録は無効になっています。 サイト管理
|
|||||||
disable_register_mail=登録でのメール確認は無効になっています。
|
disable_register_mail=登録でのメール確認は無効になっています。
|
||||||
manual_activation_only=アクティベーションを完了するにはサイト管理者に連絡してください。
|
manual_activation_only=アクティベーションを完了するにはサイト管理者に連絡してください。
|
||||||
remember_me=このデバイスで自動サインイン
|
remember_me=このデバイスで自動サインイン
|
||||||
|
remember_me.compromised=ログイントークンはもう有効ではなく、アカウントが侵害されたことを示している可能性があります。 異常なアクティビティがないかアカウントを確認してください。
|
||||||
forgot_password_title=パスワードを忘れた
|
forgot_password_title=パスワードを忘れた
|
||||||
forgot_password=パスワードをお忘れですか?
|
forgot_password=パスワードをお忘れですか?
|
||||||
sign_up_now=アカウントが必要ですか? 今すぐ登録しましょう。
|
sign_up_now=アカウントが必要ですか? 今すぐ登録しましょう。
|
||||||
@ -623,11 +625,11 @@ applications=アプリケーション
|
|||||||
orgs=組織の管理
|
orgs=組織の管理
|
||||||
repos=リポジトリ
|
repos=リポジトリ
|
||||||
delete=アカウントを削除
|
delete=アカウントを削除
|
||||||
twofa=2要素認証
|
twofa=2要素認証 (TOTP)
|
||||||
account_link=連携アカウント
|
account_link=連携アカウント
|
||||||
organization=組織
|
organization=組織
|
||||||
uid=UID
|
uid=UID
|
||||||
webauthn=セキュリティキー
|
webauthn=2要素認証 (セキュリティキー)
|
||||||
|
|
||||||
public_profile=公開プロフィール
|
public_profile=公開プロフィール
|
||||||
biography_placeholder=自己紹介してください!(Markdownを使うことができます)
|
biography_placeholder=自己紹介してください!(Markdownを使うことができます)
|
||||||
@ -861,22 +863,23 @@ revoke_oauth2_grant=アクセス権の取り消し
|
|||||||
revoke_oauth2_grant_description=このサードパーティ アプリケーションのアクセス権を取り消し、アプリケーションがあなたのデータへアクセスすることを防ぎます。 続行しますか?
|
revoke_oauth2_grant_description=このサードパーティ アプリケーションのアクセス権を取り消し、アプリケーションがあなたのデータへアクセスすることを防ぎます。 続行しますか?
|
||||||
revoke_oauth2_grant_success=アクセス権を取り消しました。
|
revoke_oauth2_grant_success=アクセス権を取り消しました。
|
||||||
|
|
||||||
twofa_desc=2要素認証はアカウントのセキュリティを強化します。
|
twofa_desc=パスワードの盗難からアカウントを守るために、スマートフォンや他のデバイスを使用して、時間ベースのワンタイムパスワード("TOTP")を受け取ることができます。
|
||||||
|
twofa_recovery_tip=デバイスを紛失した場合は、一回限りのリカバリキーを使用してアカウントへのアクセスを回復することができます。
|
||||||
twofa_is_enrolled=このアカウントは2要素認証が<strong>有効</strong>になっています。
|
twofa_is_enrolled=このアカウントは2要素認証が<strong>有効</strong>になっています。
|
||||||
twofa_not_enrolled=このアカウントは2要素認証が設定されていません。
|
twofa_not_enrolled=このアカウントは2要素認証が設定されていません。
|
||||||
twofa_disable=2要素認証を無効にする
|
twofa_disable=2要素認証を無効にする
|
||||||
twofa_scratch_token_regenerate=スクラッチトークンを再生成
|
twofa_scratch_token_regenerate=一回限りのリカバリキーを再生成
|
||||||
twofa_scratch_token_regenerated=あなたのスクラッチトークンは %s になりました。 安全な場所に保管してください。 二度と表示されません。
|
twofa_scratch_token_regenerated=あなたの一回限りのリカバリキーは %s になりました。 安全な場所に保管してください。 これは二度と表示されません。
|
||||||
twofa_enroll=2要素認証の開始
|
twofa_enroll=2要素認証の開始
|
||||||
twofa_disable_note=2要素認証は必要に応じて無効にできます。
|
twofa_disable_note=2要素認証は必要に応じて無効にできます。
|
||||||
twofa_disable_desc=2要素認証を無効にするとアカウントのセキュリティが低下します。 続行しますか?
|
twofa_disable_desc=2要素認証を無効にするとアカウントのセキュリティが低下します。 続行しますか?
|
||||||
regenerate_scratch_token_desc=スクラッチトークンを紛失した場合やサインインで使用済みとなった場合は、ここでリセットできます。
|
regenerate_scratch_token_desc=リカバリキーを紛失した場合や、すでにサインインに使用済みの場合は、ここでリセットできます。
|
||||||
twofa_disabled=2要素認証を無効にしました。
|
twofa_disabled=2要素認証を無効にしました。
|
||||||
scan_this_image=この画像を認証アプリケーションで読み取ってください。
|
scan_this_image=この画像を認証アプリケーションで読み取ってください。
|
||||||
or_enter_secret=またはシークレット文字列を入力: %s
|
or_enter_secret=またはシークレット文字列を入力: %s
|
||||||
then_enter_passcode=次に、アプリケーションに表示されているパスコードを入力します。
|
then_enter_passcode=次に、アプリケーションに表示されているパスコードを入力します。
|
||||||
passcode_invalid=パスコードが間違っています。 再度お試しください。
|
passcode_invalid=パスコードが間違っています。 再度お試しください。
|
||||||
twofa_enrolled=あなたのアカウントに2要素認証が設定されました。 スクラッチトークン (%s) は一度しか表示しませんので安全な場所に保存してください!
|
twofa_enrolled=あなたのアカウントは正常に登録されました。 一回限りのリカバリキー (%s) は安全な場所に保存してください。 これは二度と表示されません。
|
||||||
twofa_failed_get_secret=シークレットが取得できません。
|
twofa_failed_get_secret=シークレットが取得できません。
|
||||||
|
|
||||||
webauthn_desc=セキュリティキーは暗号化キーを内蔵するハードウェア ・ デバイスです。 2要素認証に使用できます。 セキュリティキーは<a rel="noreferrer" target="_blank" href="https://w3c.github.io/webauthn/#webauthn-authenticator">WebAuthn Authenticator</a>規格をサポートしている必要があります。
|
webauthn_desc=セキュリティキーは暗号化キーを内蔵するハードウェア ・ デバイスです。 2要素認証に使用できます。 セキュリティキーは<a rel="noreferrer" target="_blank" href="https://w3c.github.io/webauthn/#webauthn-authenticator">WebAuthn Authenticator</a>規格をサポートしている必要があります。
|
||||||
@ -884,6 +887,8 @@ webauthn_register_key=セキュリティキーを追加
|
|||||||
webauthn_nickname=ニックネーム
|
webauthn_nickname=ニックネーム
|
||||||
webauthn_delete_key=セキュリティキーの登録解除
|
webauthn_delete_key=セキュリティキーの登録解除
|
||||||
webauthn_delete_key_desc=セキュリティキーの登録を解除すると、今後そのセキュリティキーでサインインすることはできなくなります。 続行しますか?
|
webauthn_delete_key_desc=セキュリティキーの登録を解除すると、今後そのセキュリティキーでサインインすることはできなくなります。 続行しますか?
|
||||||
|
webauthn_key_loss_warning=セキュリティキーを紛失すると、アカウントへのアクセスを失います。
|
||||||
|
webauthn_alternative_tip=もうひとつ別の認証方法も設定しておくと良いでしょう。
|
||||||
|
|
||||||
manage_account_links=連携アカウントの管理
|
manage_account_links=連携アカウントの管理
|
||||||
manage_account_links_desc=これらの外部アカウントがGiteaアカウントと連携されています。
|
manage_account_links_desc=これらの外部アカウントがGiteaアカウントと連携されています。
|
||||||
@ -920,6 +925,7 @@ visibility.private=プライベート
|
|||||||
visibility.private_tooltip=あなたが参加した組織のメンバーのみに表示されます
|
visibility.private_tooltip=あなたが参加した組織のメンバーのみに表示されます
|
||||||
|
|
||||||
[repo]
|
[repo]
|
||||||
|
new_repo_helper=リポジトリには、プロジェクトのすべてのファイルとリビジョン履歴が入ります。 すでにほかの場所でホストしていますか? <a href="%s">リポジトリを移行</a> もどうぞ。
|
||||||
owner=オーナー
|
owner=オーナー
|
||||||
owner_helper=リポジトリ数の上限により、一部の組織はドロップダウンに表示されない場合があります。
|
owner_helper=リポジトリ数の上限により、一部の組織はドロップダウンに表示されない場合があります。
|
||||||
repo_name=リポジトリ名
|
repo_name=リポジトリ名
|
||||||
@ -1782,6 +1788,8 @@ pulls.status_checks_failure=失敗したステータスチェックがありま
|
|||||||
pulls.status_checks_error=ステータスチェックによりエラーが出ています
|
pulls.status_checks_error=ステータスチェックによりエラーが出ています
|
||||||
pulls.status_checks_requested=必須
|
pulls.status_checks_requested=必須
|
||||||
pulls.status_checks_details=詳細
|
pulls.status_checks_details=詳細
|
||||||
|
pulls.status_checks_hide_all=すべてのチェックを隠す
|
||||||
|
pulls.status_checks_show_all=すべてのチェックを表示
|
||||||
pulls.update_branch=マージでブランチを更新
|
pulls.update_branch=マージでブランチを更新
|
||||||
pulls.update_branch_rebase=リベースでブランチを更新
|
pulls.update_branch_rebase=リベースでブランチを更新
|
||||||
pulls.update_branch_success=ブランチの更新が成功しました
|
pulls.update_branch_success=ブランチの更新が成功しました
|
||||||
@ -1790,6 +1798,11 @@ pulls.outdated_with_base_branch=このブランチはベースブランチに対
|
|||||||
pulls.close=プルリクエストをクローズ
|
pulls.close=プルリクエストをクローズ
|
||||||
pulls.closed_at=`がプルリクエストをクローズ <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
pulls.closed_at=`がプルリクエストをクローズ <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||||
pulls.reopened_at=`がプルリクエストを再オープン <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
pulls.reopened_at=`がプルリクエストを再オープン <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||||
|
pulls.cmd_instruction_hint=`<a class="show-instruction">コマンドラインの手順</a>を表示します。`
|
||||||
|
pulls.cmd_instruction_checkout_title=チェックアウト
|
||||||
|
pulls.cmd_instruction_checkout_desc=プロジェクトリポジトリから新しいブランチをチェックアウトし、変更内容をテストします。
|
||||||
|
pulls.cmd_instruction_merge_title=マージ
|
||||||
|
pulls.cmd_instruction_merge_desc=変更内容をマージして、Giteaに反映します。
|
||||||
pulls.clear_merge_message=マージメッセージをクリア
|
pulls.clear_merge_message=マージメッセージをクリア
|
||||||
pulls.clear_merge_message_hint=マージメッセージのクリアは、コミットメッセージの除去だけを行います。 生成されたGitトレーラー("Co-Authored-By …" 等)はそのまま残ります。
|
pulls.clear_merge_message_hint=マージメッセージのクリアは、コミットメッセージの除去だけを行います。 生成されたGitトレーラー("Co-Authored-By …" 等)はそのまま残ります。
|
||||||
|
|
||||||
@ -2301,6 +2314,7 @@ settings.dismiss_stale_approvals_desc=プルリクエストの内容を変える
|
|||||||
settings.require_signed_commits=コミット署名必須
|
settings.require_signed_commits=コミット署名必須
|
||||||
settings.require_signed_commits_desc=署名されていない場合、または署名が検証できなかった場合は、このブランチへのプッシュを拒否します。
|
settings.require_signed_commits_desc=署名されていない場合、または署名が検証できなかった場合は、このブランチへのプッシュを拒否します。
|
||||||
settings.protect_branch_name_pattern=保護ブランチ名のパターン
|
settings.protect_branch_name_pattern=保護ブランチ名のパターン
|
||||||
|
settings.protect_branch_name_pattern_desc=保護ブランチ名のパターン。書き方については <a href="https://github.com/gobwas/glob">ドキュメント</a> を参照してください。例: main, release/**
|
||||||
settings.protect_patterns=パターン
|
settings.protect_patterns=パターン
|
||||||
settings.protect_protected_file_patterns=保護されるファイルのパターン (セミコロン';'で区切る):
|
settings.protect_protected_file_patterns=保護されるファイルのパターン (セミコロン';'で区切る):
|
||||||
settings.protect_protected_file_patterns_desc=保護されたファイルは、このブランチにファイルを追加・編集・削除する権限を持つユーザーであっても、直接変更することができなくなります。 セミコロン(';')で区切って複数のパターンを指定できます。 パターンの文法については <a href='https://pkg.go.dev/github.com/gobwas/glob#Compile'>github.com/gobwas/glob</a> を参照してください。 例: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>
|
settings.protect_protected_file_patterns_desc=保護されたファイルは、このブランチにファイルを追加・編集・削除する権限を持つユーザーであっても、直接変更することができなくなります。 セミコロン(';')で区切って複数のパターンを指定できます。 パターンの文法については <a href='https://pkg.go.dev/github.com/gobwas/glob#Compile'>github.com/gobwas/glob</a> を参照してください。 例: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>
|
||||||
@ -2846,6 +2860,7 @@ emails.updated=メール設定を更新しました
|
|||||||
emails.not_updated=メール設定の更新に失敗しました: %v
|
emails.not_updated=メール設定の更新に失敗しました: %v
|
||||||
emails.duplicate_active=メールアドレスは別のユーザーが既に使用中です。
|
emails.duplicate_active=メールアドレスは別のユーザーが既に使用中です。
|
||||||
emails.change_email_header=メール設定の更新
|
emails.change_email_header=メール設定の更新
|
||||||
|
emails.change_email_text=このメールアドレスで更新してもよろしいですか?
|
||||||
|
|
||||||
orgs.org_manage_panel=組織の管理
|
orgs.org_manage_panel=組織の管理
|
||||||
orgs.name=名称
|
orgs.name=名称
|
||||||
@ -2870,6 +2885,7 @@ packages.package_manage_panel=パッケージ管理
|
|||||||
packages.total_size=合計サイズ: %s
|
packages.total_size=合計サイズ: %s
|
||||||
packages.unreferenced_size=非参照サイズ: %s
|
packages.unreferenced_size=非参照サイズ: %s
|
||||||
packages.cleanup=期限切れデータを掃除する
|
packages.cleanup=期限切れデータを掃除する
|
||||||
|
packages.cleanup.success=期限切れのデータを正常にクリーンアップしました
|
||||||
packages.owner=オーナー
|
packages.owner=オーナー
|
||||||
packages.creator=作成者
|
packages.creator=作成者
|
||||||
packages.name=名前
|
packages.name=名前
|
||||||
@ -3441,7 +3457,7 @@ owner.settings.chef.keypair.description=Chefレジストリの認証にはキー
|
|||||||
[secrets]
|
[secrets]
|
||||||
secrets=シークレット
|
secrets=シークレット
|
||||||
description=シークレットは特定のActionsに渡されます。 それ以外で読み出されることはありません。
|
description=シークレットは特定のActionsに渡されます。 それ以外で読み出されることはありません。
|
||||||
none=まだシークレットはありません。
|
none=シークレットはまだありません。
|
||||||
creation=シークレットを追加
|
creation=シークレットを追加
|
||||||
creation.name_placeholder=大文字小文字の区別なし、英数字とアンダースコアのみ、GITEA_ や GITHUB_ で始まるものは不可
|
creation.name_placeholder=大文字小文字の区別なし、英数字とアンダースコアのみ、GITEA_ や GITHUB_ で始まるものは不可
|
||||||
creation.value_placeholder=内容を入力してください。前後の空白は除去されます。
|
creation.value_placeholder=内容を入力してください。前後の空白は除去されます。
|
||||||
@ -3516,6 +3532,7 @@ runs.actors_no_select=すべてのアクター
|
|||||||
runs.status_no_select=すべてのステータス
|
runs.status_no_select=すべてのステータス
|
||||||
runs.no_results=一致する結果はありません。
|
runs.no_results=一致する結果はありません。
|
||||||
runs.no_runs=ワークフローはまだ実行されていません。
|
runs.no_runs=ワークフローはまだ実行されていません。
|
||||||
|
runs.empty_commit_message=(空のコミットメッセージ)
|
||||||
|
|
||||||
workflow.disable=ワークフローを無効にする
|
workflow.disable=ワークフローを無効にする
|
||||||
workflow.disable_success=ワークフロー '%s' が無効になりました。
|
workflow.disable_success=ワークフロー '%s' が無効になりました。
|
||||||
|
@ -93,11 +93,20 @@ func CreateUser(ctx *context.APIContext) {
|
|||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if u.LoginType == auth.Plain {
|
||||||
|
if len(form.Password) < setting.MinPasswordLength {
|
||||||
|
err := errors.New("PasswordIsRequired")
|
||||||
|
ctx.Error(http.StatusBadRequest, "PasswordIsRequired", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if !password.IsComplexEnough(form.Password) {
|
if !password.IsComplexEnough(form.Password) {
|
||||||
err := errors.New("PasswordComplexity")
|
err := errors.New("PasswordComplexity")
|
||||||
ctx.Error(http.StatusBadRequest, "PasswordComplexity", err)
|
ctx.Error(http.StatusBadRequest, "PasswordComplexity", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
pwned, err := password.IsPwned(ctx, form.Password)
|
pwned, err := password.IsPwned(ctx, form.Password)
|
||||||
if pwned {
|
if pwned {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -106,6 +115,7 @@ func CreateUser(ctx *context.APIContext) {
|
|||||||
ctx.Error(http.StatusBadRequest, "PasswordPwned", errors.New("PasswordPwned"))
|
ctx.Error(http.StatusBadRequest, "PasswordPwned", errors.New("PasswordPwned"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
overwriteDefault := &user_model.CreateUserOverwriteOptions{
|
overwriteDefault := &user_model.CreateUserOverwriteOptions{
|
||||||
IsActive: util.OptionalBoolTrue,
|
IsActive: util.OptionalBoolTrue,
|
||||||
|
@ -29,10 +29,9 @@ func NodeInfo(ctx *context.APIContext) {
|
|||||||
|
|
||||||
nodeInfoUsage := structs.NodeInfoUsage{}
|
nodeInfoUsage := structs.NodeInfoUsage{}
|
||||||
if setting.Federation.ShareUserStatistics {
|
if setting.Federation.ShareUserStatistics {
|
||||||
cached := false
|
var cached bool
|
||||||
if setting.CacheService.Enabled {
|
|
||||||
nodeInfoUsage, cached = ctx.Cache.Get(cacheKeyNodeInfoUsage).(structs.NodeInfoUsage)
|
nodeInfoUsage, cached = ctx.Cache.Get(cacheKeyNodeInfoUsage).(structs.NodeInfoUsage)
|
||||||
}
|
|
||||||
if !cached {
|
if !cached {
|
||||||
usersTotal := int(user_model.CountUsers(ctx, nil))
|
usersTotal := int(user_model.CountUsers(ctx, nil))
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
@ -53,14 +52,13 @@ func NodeInfo(ctx *context.APIContext) {
|
|||||||
LocalPosts: int(allIssues),
|
LocalPosts: int(allIssues),
|
||||||
LocalComments: int(allComments),
|
LocalComments: int(allComments),
|
||||||
}
|
}
|
||||||
if setting.CacheService.Enabled {
|
|
||||||
if err := ctx.Cache.Put(cacheKeyNodeInfoUsage, nodeInfoUsage, 180); err != nil {
|
if err := ctx.Cache.Put(cacheKeyNodeInfoUsage, nodeInfoUsage, 180); err != nil {
|
||||||
ctx.InternalServerError(err)
|
ctx.InternalServerError(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
nodeInfo := &structs.NodeInfo{
|
nodeInfo := &structs.NodeInfo{
|
||||||
Version: "2.1",
|
Version: "2.1",
|
||||||
|
@ -253,7 +253,7 @@ func CreateUserRepo(ctx *context.APIContext, owner *user_model.User, opt api.Cre
|
|||||||
DefaultBranch: opt.DefaultBranch,
|
DefaultBranch: opt.DefaultBranch,
|
||||||
TrustModel: repo_model.ToTrustModel(opt.TrustModel),
|
TrustModel: repo_model.ToTrustModel(opt.TrustModel),
|
||||||
IsTemplate: opt.Template,
|
IsTemplate: opt.Template,
|
||||||
ObjectFormat: git.ObjectFormatFromID(git.Sha1),
|
ObjectFormatName: git.Sha1ObjectFormat.Name(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if repo_model.IsErrRepoAlreadyExist(err) {
|
if repo_model.IsErrRepoAlreadyExist(err) {
|
||||||
|
@ -73,7 +73,7 @@ func searchRefCommitByType(ctx *context.APIContext, refType, filter string) (str
|
|||||||
func ConvertToObjectID(ctx gocontext.Context, repo *context.Repository, commitID string) (git.ObjectID, error) {
|
func ConvertToObjectID(ctx gocontext.Context, repo *context.Repository, commitID string) (git.ObjectID, error) {
|
||||||
objectFormat, _ := repo.GitRepo.GetObjectFormat()
|
objectFormat, _ := repo.GitRepo.GetObjectFormat()
|
||||||
if len(commitID) == objectFormat.FullLength() && objectFormat.IsValid(commitID) {
|
if len(commitID) == objectFormat.FullLength() && objectFormat.IsValid(commitID) {
|
||||||
sha, err := objectFormat.NewIDFromString(commitID)
|
sha, err := git.NewIDFromString(commitID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return sha, nil
|
return sha, nil
|
||||||
}
|
}
|
||||||
@ -81,7 +81,7 @@ func ConvertToObjectID(ctx gocontext.Context, repo *context.Repository, commitID
|
|||||||
|
|
||||||
gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo.Repository.RepoPath())
|
gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo.Repository.RepoPath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return objectFormat.Empty(), fmt.Errorf("RepositoryFromContextOrOpen: %w", err)
|
return objectFormat.EmptyObjectID(), fmt.Errorf("RepositoryFromContextOrOpen: %w", err)
|
||||||
}
|
}
|
||||||
defer closer.Close()
|
defer closer.Close()
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ func InitWebInstalled(ctx context.Context) {
|
|||||||
mustInit(storage.Init)
|
mustInit(storage.Init)
|
||||||
|
|
||||||
mailer.NewContext(ctx)
|
mailer.NewContext(ctx)
|
||||||
mustInit(cache.NewContext)
|
mustInit(cache.Init)
|
||||||
mustInit(feed_service.Init)
|
mustInit(feed_service.Init)
|
||||||
mustInit(uinotification.Init)
|
mustInit(uinotification.Init)
|
||||||
mustInitCtx(ctx, archiver.Init)
|
mustInitCtx(ctx, archiver.Init)
|
||||||
|
@ -147,7 +147,7 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r
|
|||||||
gitRepo := ctx.Repo.GitRepo
|
gitRepo := ctx.Repo.GitRepo
|
||||||
objectFormat, _ := gitRepo.GetObjectFormat()
|
objectFormat, _ := gitRepo.GetObjectFormat()
|
||||||
|
|
||||||
if branchName == repo.DefaultBranch && newCommitID == objectFormat.Empty().String() {
|
if branchName == repo.DefaultBranch && newCommitID == objectFormat.EmptyObjectID().String() {
|
||||||
log.Warn("Forbidden: Branch: %s is the default branch in %-v and cannot be deleted", branchName, repo)
|
log.Warn("Forbidden: Branch: %s is the default branch in %-v and cannot be deleted", branchName, repo)
|
||||||
ctx.JSON(http.StatusForbidden, private.Response{
|
ctx.JSON(http.StatusForbidden, private.Response{
|
||||||
UserMsg: fmt.Sprintf("branch %s is the default branch and cannot be deleted", branchName),
|
UserMsg: fmt.Sprintf("branch %s is the default branch and cannot be deleted", branchName),
|
||||||
@ -175,7 +175,7 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r
|
|||||||
// First of all we need to enforce absolutely:
|
// First of all we need to enforce absolutely:
|
||||||
//
|
//
|
||||||
// 1. Detect and prevent deletion of the branch
|
// 1. Detect and prevent deletion of the branch
|
||||||
if newCommitID == objectFormat.Empty().String() {
|
if newCommitID == objectFormat.EmptyObjectID().String() {
|
||||||
log.Warn("Forbidden: Branch: %s in %-v is protected from deletion", branchName, repo)
|
log.Warn("Forbidden: Branch: %s in %-v is protected from deletion", branchName, repo)
|
||||||
ctx.JSON(http.StatusForbidden, private.Response{
|
ctx.JSON(http.StatusForbidden, private.Response{
|
||||||
UserMsg: fmt.Sprintf("branch %s is protected from deletion", branchName),
|
UserMsg: fmt.Sprintf("branch %s is protected from deletion", branchName),
|
||||||
@ -186,7 +186,7 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r
|
|||||||
isForcePush := false
|
isForcePush := false
|
||||||
|
|
||||||
// 2. Disallow force pushes to protected branches
|
// 2. Disallow force pushes to protected branches
|
||||||
if oldCommitID != objectFormat.Empty().String() {
|
if oldCommitID != objectFormat.EmptyObjectID().String() {
|
||||||
output, _, err := git.NewCommand(ctx, "rev-list", "--max-count=1").AddDynamicArguments(oldCommitID, "^"+newCommitID).RunStdString(&git.RunOpts{Dir: repo.RepoPath(), Env: ctx.env})
|
output, _, err := git.NewCommand(ctx, "rev-list", "--max-count=1").AddDynamicArguments(oldCommitID, "^"+newCommitID).RunStdString(&git.RunOpts{Dir: repo.RepoPath(), Env: ctx.env})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Unable to detect force push between: %s and %s in %-v Error: %v", oldCommitID, newCommitID, repo, err)
|
log.Error("Unable to detect force push between: %s and %s in %-v Error: %v", oldCommitID, newCommitID, repo, err)
|
||||||
|
@ -30,7 +30,7 @@ func verifyCommits(oldCommitID, newCommitID string, repo *git.Repository, env []
|
|||||||
|
|
||||||
var command *git.Command
|
var command *git.Command
|
||||||
objectFormat, _ := repo.GetObjectFormat()
|
objectFormat, _ := repo.GetObjectFormat()
|
||||||
if oldCommitID == objectFormat.Empty().String() {
|
if oldCommitID == objectFormat.EmptyObjectID().String() {
|
||||||
// When creating a new branch, the oldCommitID is empty, by using "newCommitID --not --all":
|
// When creating a new branch, the oldCommitID is empty, by using "newCommitID --not --all":
|
||||||
// List commits that are reachable by following the newCommitID, exclude "all" existing heads/tags commits
|
// List commits that are reachable by following the newCommitID, exclude "all" existing heads/tags commits
|
||||||
// So, it only lists the new commits received, doesn't list the commits already present in the receiving repository
|
// So, it only lists the new commits received, doesn't list the commits already present in the receiving repository
|
||||||
@ -83,8 +83,8 @@ func readAndVerifyCommit(sha string, repo *git.Repository, env []string) error {
|
|||||||
_ = stdoutReader.Close()
|
_ = stdoutReader.Close()
|
||||||
_ = stdoutWriter.Close()
|
_ = stdoutWriter.Close()
|
||||||
}()
|
}()
|
||||||
objectFormat, _ := repo.GetObjectFormat()
|
|
||||||
commitID := objectFormat.MustIDFromString(sha)
|
commitID := git.MustIDFromString(sha)
|
||||||
|
|
||||||
return git.NewCommand(repo.Ctx, "cat-file", "commit").AddDynamicArguments(sha).
|
return git.NewCommand(repo.Ctx, "cat-file", "commit").AddDynamicArguments(sha).
|
||||||
Run(&git.RunOpts{
|
Run(&git.RunOpts{
|
||||||
|
@ -30,9 +30,9 @@ func TestVerifyCommits(t *testing.T) {
|
|||||||
verified bool
|
verified bool
|
||||||
}{
|
}{
|
||||||
{"72920278f2f999e3005801e5d5b8ab8139d3641c", "d766f2917716d45be24bfa968b8409544941be32", true},
|
{"72920278f2f999e3005801e5d5b8ab8139d3641c", "d766f2917716d45be24bfa968b8409544941be32", true},
|
||||||
{objectFormat.Empty().String(), "93eac826f6188f34646cea81bf426aa5ba7d3bfe", true}, // New branch with verified commit
|
{objectFormat.EmptyObjectID().String(), "93eac826f6188f34646cea81bf426aa5ba7d3bfe", true}, // New branch with verified commit
|
||||||
{"9779d17a04f1e2640583d35703c62460b2d86e0a", "72920278f2f999e3005801e5d5b8ab8139d3641c", false},
|
{"9779d17a04f1e2640583d35703c62460b2d86e0a", "72920278f2f999e3005801e5d5b8ab8139d3641c", false},
|
||||||
{objectFormat.Empty().String(), "9ce3f779ae33f31fce17fac3c512047b75d7498b", false}, // New branch with unverified commit
|
{objectFormat.EmptyObjectID().String(), "9ce3f779ae33f31fce17fac3c512047b75d7498b", false}, // New branch with unverified commit
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
|
@ -622,11 +622,9 @@ func handleUserCreated(ctx *context.Context, u *user_model.User, gothUser *goth.
|
|||||||
ctx.Data["ActiveCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale)
|
ctx.Data["ActiveCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale)
|
||||||
ctx.HTML(http.StatusOK, TplActivate)
|
ctx.HTML(http.StatusOK, TplActivate)
|
||||||
|
|
||||||
if setting.CacheService.Enabled {
|
|
||||||
if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil {
|
if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil {
|
||||||
log.Error("Set cache(MailResendLimit) fail: %v", err)
|
log.Error("Set cache(MailResendLimit) fail: %v", err)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -645,18 +643,16 @@ func Activate(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
// Resend confirmation email.
|
// Resend confirmation email.
|
||||||
if setting.Service.RegisterEmailConfirm {
|
if setting.Service.RegisterEmailConfirm {
|
||||||
if setting.CacheService.Enabled && ctx.Cache.IsExist("MailResendLimit_"+ctx.Doer.LowerName) {
|
if ctx.Cache.IsExist("MailResendLimit_" + ctx.Doer.LowerName) {
|
||||||
ctx.Data["ResendLimited"] = true
|
ctx.Data["ResendLimited"] = true
|
||||||
} else {
|
} else {
|
||||||
ctx.Data["ActiveCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale)
|
ctx.Data["ActiveCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale)
|
||||||
mailer.SendActivateAccountMail(ctx.Locale, ctx.Doer)
|
mailer.SendActivateAccountMail(ctx.Locale, ctx.Doer)
|
||||||
|
|
||||||
if setting.CacheService.Enabled {
|
|
||||||
if err := ctx.Cache.Put("MailResendLimit_"+ctx.Doer.LowerName, ctx.Doer.LowerName, 180); err != nil {
|
if err := ctx.Cache.Put("MailResendLimit_"+ctx.Doer.LowerName, ctx.Doer.LowerName, 180); err != nil {
|
||||||
log.Error("Set cache(MailResendLimit) fail: %v", err)
|
log.Error("Set cache(MailResendLimit) fail: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
ctx.Data["ServiceNotEnabled"] = true
|
ctx.Data["ServiceNotEnabled"] = true
|
||||||
}
|
}
|
||||||
@ -789,7 +785,7 @@ func ActivateEmail(ctx *context.Context) {
|
|||||||
|
|
||||||
if u, err := user_model.GetUserByID(ctx, email.UID); err != nil {
|
if u, err := user_model.GetUserByID(ctx, email.UID); err != nil {
|
||||||
log.Warn("GetUserByID: %d", email.UID)
|
log.Warn("GetUserByID: %d", email.UID)
|
||||||
} else if setting.CacheService.Enabled {
|
} else {
|
||||||
// Allow user to validate more emails
|
// Allow user to validate more emails
|
||||||
_ = ctx.Cache.Delete("MailResendLimit_" + u.LowerName)
|
_ = ctx.Cache.Delete("MailResendLimit_" + u.LowerName)
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ func ForgotPasswdPost(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if setting.CacheService.Enabled && ctx.Cache.IsExist("MailResendLimit_"+u.LowerName) {
|
if ctx.Cache.IsExist("MailResendLimit_" + u.LowerName) {
|
||||||
ctx.Data["ResendLimited"] = true
|
ctx.Data["ResendLimited"] = true
|
||||||
ctx.HTML(http.StatusOK, tplForgotPassword)
|
ctx.HTML(http.StatusOK, tplForgotPassword)
|
||||||
return
|
return
|
||||||
@ -87,11 +87,9 @@ func ForgotPasswdPost(ctx *context.Context) {
|
|||||||
|
|
||||||
mailer.SendResetPasswordMail(u)
|
mailer.SendResetPasswordMail(u)
|
||||||
|
|
||||||
if setting.CacheService.Enabled {
|
|
||||||
if err = ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil {
|
if err = ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil {
|
||||||
log.Error("Set cache(MailResendLimit) fail: %v", err)
|
log.Error("Set cache(MailResendLimit) fail: %v", err)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ctx.Data["ResetPwdCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ResetPwdCodeLives, ctx.Locale)
|
ctx.Data["ResetPwdCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ResetPwdCodeLives, ctx.Locale)
|
||||||
ctx.Data["IsResetSent"] = true
|
ctx.Data["IsResetSent"] = true
|
||||||
|
@ -121,10 +121,6 @@ func checkDatabase(ctx context.Context, checks checks) status {
|
|||||||
|
|
||||||
// cache checks gitea cache status
|
// cache checks gitea cache status
|
||||||
func checkCache(checks checks) status {
|
func checkCache(checks checks) status {
|
||||||
if !setting.CacheService.Enabled {
|
|
||||||
return pass
|
|
||||||
}
|
|
||||||
|
|
||||||
st := componentStatus{}
|
st := componentStatus{}
|
||||||
if err := cache.GetCache().Ping(); err != nil {
|
if err := cache.GetCache().Ping(); err != nil {
|
||||||
st.Status = fail
|
st.Status = fail
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/modules/util"
|
||||||
"code.gitea.io/gitea/routers/web/repo"
|
"code.gitea.io/gitea/routers/web/repo"
|
||||||
"code.gitea.io/gitea/services/convert"
|
"code.gitea.io/gitea/services/convert"
|
||||||
|
|
||||||
@ -77,6 +78,7 @@ func List(ctx *context.Context) {
|
|||||||
// Get all runner labels
|
// Get all runner labels
|
||||||
runners, err := db.Find[actions_model.ActionRunner](ctx, actions_model.FindRunnerOptions{
|
runners, err := db.Find[actions_model.ActionRunner](ctx, actions_model.FindRunnerOptions{
|
||||||
RepoID: ctx.Repo.Repository.ID,
|
RepoID: ctx.Repo.Repository.ID,
|
||||||
|
IsOnline: util.OptionalBoolTrue,
|
||||||
WithAvailable: true,
|
WithAvailable: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -113,7 +115,7 @@ func List(ctx *context.Context) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !allRunnerLabels.Contains(ro) {
|
if !allRunnerLabels.Contains(ro) {
|
||||||
workflow.ErrMsg = ctx.Locale.Tr("actions.runs.no_matching_runner_helper", ro)
|
workflow.ErrMsg = ctx.Locale.Tr("actions.runs.no_matching_online_runner_helper", ro)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -315,8 +315,7 @@ func renderBlame(ctx *context.Context, blameParts []git.BlamePart, commitNames m
|
|||||||
lexerName = lexerNameForLine
|
lexerName = lexerNameForLine
|
||||||
}
|
}
|
||||||
|
|
||||||
br.EscapeStatus, line = charset.EscapeControlHTML(line, ctx.Locale)
|
br.EscapeStatus, br.Code = charset.EscapeControlHTML(line, ctx.Locale)
|
||||||
br.Code = gotemplate.HTML(line)
|
|
||||||
rows = append(rows, br)
|
rows = append(rows, br)
|
||||||
escapeStatus = escapeStatus.Or(br.EscapeStatus)
|
escapeStatus = escapeStatus.Or(br.EscapeStatus)
|
||||||
}
|
}
|
||||||
|
@ -158,7 +158,7 @@ func RestoreBranchPost(ctx *context.Context) {
|
|||||||
if err := repo_service.PushUpdate(
|
if err := repo_service.PushUpdate(
|
||||||
&repo_module.PushUpdateOptions{
|
&repo_module.PushUpdateOptions{
|
||||||
RefFullName: git.RefNameFromBranch(deletedBranch.Name),
|
RefFullName: git.RefNameFromBranch(deletedBranch.Name),
|
||||||
OldCommitID: objectFormat.Empty().String(),
|
OldCommitID: objectFormat.EmptyObjectID().String(),
|
||||||
NewCommitID: deletedBranch.CommitID,
|
NewCommitID: deletedBranch.CommitID,
|
||||||
PusherID: ctx.Doer.ID,
|
PusherID: ctx.Doer.ID,
|
||||||
PusherName: ctx.Doer.Name,
|
PusherName: ctx.Doer.Name,
|
||||||
|
@ -317,7 +317,7 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo {
|
|||||||
ci.BaseBranch = baseCommit.ID.String()
|
ci.BaseBranch = baseCommit.ID.String()
|
||||||
ctx.Data["BaseBranch"] = ci.BaseBranch
|
ctx.Data["BaseBranch"] = ci.BaseBranch
|
||||||
baseIsCommit = true
|
baseIsCommit = true
|
||||||
} else if ci.BaseBranch == objectFormat.Empty().String() {
|
} else if ci.BaseBranch == objectFormat.EmptyObjectID().String() {
|
||||||
if isSameRepo {
|
if isSameRepo {
|
||||||
ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ci.HeadBranch))
|
ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ci.HeadBranch))
|
||||||
} else {
|
} else {
|
||||||
|
@ -329,7 +329,7 @@ func dummyInfoRefs(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if err := git.InitRepository(ctx, tmpDir, true, git.ObjectFormatFromID(git.Sha1)); err != nil {
|
if err := git.InitRepository(ctx, tmpDir, true, git.Sha1ObjectFormat.Name()); err != nil {
|
||||||
log.Error("Failed to init bare repo for git-receive-pack cache: %v", err)
|
log.Error("Failed to init bare repo for git-receive-pack cache: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -289,7 +289,7 @@ func CreatePost(ctx *context.Context) {
|
|||||||
AutoInit: form.AutoInit,
|
AutoInit: form.AutoInit,
|
||||||
IsTemplate: form.Template,
|
IsTemplate: form.Template,
|
||||||
TrustModel: repo_model.ToTrustModel(form.TrustModel),
|
TrustModel: repo_model.ToTrustModel(form.TrustModel),
|
||||||
ObjectFormat: form.ObjectFormat,
|
ObjectFormatName: form.ObjectFormatName,
|
||||||
})
|
})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
log.Trace("Repository created [%d]: %s/%s", repo.ID, ctxUser.Name, repo.Name)
|
log.Trace("Repository created [%d]: %s/%s", repo.ID, ctxUser.Name, repo.Name)
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user