1
1
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:
Henry Goodman 2023-12-19 20:36:12 +11:00 committed by GitHub
commit be622e5db9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
146 changed files with 907 additions and 1091 deletions

File diff suppressed because one or more lines are too long

View File

@ -15,9 +15,8 @@ import (
var (
// CmdActions represents the available actions sub-commands.
CmdActions = &cli.Command{
Name: "actions",
Usage: "",
Description: "Commands for managing Gitea Actions",
Name: "actions",
Usage: "Manage Gitea Actions",
Subcommands: []*cli.Command{
subcmdActionsGenRunnerToken,
},

View File

@ -21,7 +21,7 @@ var (
// CmdAdmin represents the available admin sub-command.
CmdAdmin = &cli.Command{
Name: "admin",
Usage: "Command line interface to perform common administrative operations",
Usage: "Perform common administrative operations",
Subcommands: []*cli.Command{
subcmdUser,
subcmdRepoSyncReleases,

View File

@ -26,7 +26,7 @@ import (
// CmdDoctor represents the available doctor sub-command.
var CmdDoctor = &cli.Command{
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.",
Subcommands: []*cli.Command{

View File

@ -18,7 +18,7 @@ var (
// CmdGenerate represents the available generate sub-command.
CmdGenerate = &cli.Command{
Name: "generate",
Usage: "Command line interface for running generators",
Usage: "Generate Gitea's secrets/keys/tokens",
Subcommands: []*cli.Command{
subcmdSecret,
},

View File

@ -31,8 +31,8 @@ var (
// CmdHook represents the available hooks sub-command.
CmdHook = &cli.Command{
Name: "hook",
Usage: "Delegate commands to corresponding Git hooks",
Description: "This should only be called by Git",
Usage: "(internal) Should only be called by Git",
Description: "Delegate commands to corresponding Git hooks",
Before: PrepareConsoleLoggerLevel(log.FATAL),
Subcommands: []*cli.Command{
subcmdHookPreReceive,
@ -377,7 +377,7 @@ Gitea or set your environment appropriately.`, "")
newCommitIDs[count] = string(fields[1])
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 {
masterPushed = true
}
@ -671,7 +671,7 @@ Gitea or set your environment appropriately.`, "")
if err != nil {
return err
}
commitID, _ := git.IDFromString(rs.OldOID)
commitID, _ := git.NewIDFromString(rs.OldOID)
if !commitID.IsZero() {
err = writeDataPktLine(ctx, os.Stdout, []byte("option old-oid "+rs.OldOID))
if err != nil {

View File

@ -16,10 +16,11 @@ import (
// CmdKeys represents the available keys sub-command
var CmdKeys = &cli.Command{
Name: "keys",
Usage: "This command queries the Gitea database to get the authorized command for a given ssh key fingerprint",
Before: PrepareConsoleLoggerLevel(log.FATAL),
Action: runKeys,
Name: "keys",
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),
Action: runKeys,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "expected",

View File

@ -10,12 +10,12 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"github.com/urfave/cli/v2"
)
// 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 {
c := &cli.Command{
Name: "help",
@ -47,16 +47,10 @@ DEFAULT CONFIGURATION:
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 {
return []cli.Flag{
// 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
// 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 {
app := cli.NewApp()
app.Name = "Gitea"
app.HelpName = "gitea"
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.EnableBashCompletion = true
// these sub-commands need to use config file
subCmdWithConfig := []*cli.Command{
cmdHelp(), // the "help" sub-command was used to show the more information for "work path" and "custom config"
CmdWeb,
CmdServ,
CmdHook,
CmdKeys,
CmdDump,
CmdAdmin,
CmdMigrate,
CmdKeys,
CmdDoctor,
CmdManager,
CmdEmbedded,
@ -142,13 +138,8 @@ func NewMainApp(version, versionExtra string) *cli.App {
CmdDumpRepository,
CmdRestoreRepository,
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.
subCmdStandalone := []*cli.Command{
CmdCert,

View File

@ -42,7 +42,7 @@ const (
// CmdServ represents the available serv sub-command.
var CmdServ = &cli.Command{
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",
Before: PrepareConsoleLoggerLevel(log.FATAL),
Action: runServ,

View File

@ -17,7 +17,7 @@ import (
"strings"
"syscall"
"github.com/google/go-github/v53/github"
"github.com/google/go-github/v57/github"
"github.com/urfave/cli/v2"
"gopkg.in/yaml.v3"
)

View File

@ -1212,6 +1212,9 @@ LEVEL = Info
;; Max size of files to be displayed (default is 8MiB)
;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
;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"
;ADAPTER = memory
;;
@ -1729,8 +1729,6 @@ LEVEL = Info
;[cache.last_commit]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; if the cache enabled
;ENABLED = true
;;
;; Time to keep items in cache if not used, default is 8760 hours.
;; Setting it to -1 disables caching

View File

@ -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.
regardless of the value of `DEFAULT_THEME`.
- `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
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
@ -572,6 +573,7 @@ And the following unique queues:
- off - do not check password complexity
- `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.
- `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`)
@ -761,7 +763,6 @@ and
## 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.)
- `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.
@ -773,7 +774,6 @@ and
## 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.
- `COMMITS_COUNT`: **1000**: Only enable the cache when repository's commits count great than.

View File

@ -721,7 +721,6 @@ Gitea 创建以下非唯一队列:
## 缓存 (`cache`)
- `ENABLED`: **true**: 是否启用缓存。
- `ADAPTER`: **memory**: 缓存引擎,可以为 `memory`, `redis`, `redis-cluster`, `twoqueue``memcache`. (`twoqueue` 代表缓冲区固定的LRU缓存)
- `INTERVAL`: **60**: 垃圾回收间隔(秒),只对`memory`和`towqueue`有效。
- `HOST`: **_empty_**: 缓存配置。`redis`, `redis-cluster``memcache`配置连接字符串;`twoqueue` 设置队列参数
@ -733,7 +732,6 @@ Gitea 创建以下非唯一队列:
### 缓存 - 最后提交缓存设置 (`cache.last_commit`)
- `ENABLED`: **true**:是否启用缓存。
- `ITEM_TTL`: **8760h**:如果未使用,保持缓存中的项目的时间,将其设置为 -1 会禁用缓存。
- `COMMITS_COUNT`: **1000**:仅在存储库的提交计数大于时启用缓存。
@ -1039,10 +1037,11 @@ Gitea 创建以下非唯一队列:
## API (`api`)
- `ENABLE_SWAGGER`: **true**: 是否启用swagger路由 (`/api/swagger`, `/api/v1/swagger`, …)。
- `MAX_RESPONSE_ITEMS`: **50**: 单个页面的最大 Feed.
- `ENABLE_OPENID_SIGNIN`: **false**: 允许使用OpenID登录当设置为`true`时可以通过 `/user/login` 页面进行OpenID登录。
- `DISABLE_REGISTRATION`: **false**: 关闭用户注册。
- `ENABLE_SWAGGER`: **true**: 启用API文档接口 (`/api/swagger`, `/api/v1/swagger`, …). True or false。
- `MAX_RESPONSE_ITEMS`: **50**: API分页的最大单页项目数。
- `DEFAULT_PAGING_NUM`: **30**: API分页的默认分页数。
- `DEFAULT_GIT_TREES_PER_PAGE`: **1000**: Git trees API的默认单页项目数。
- `DEFAULT_MAX_BLOB_SIZE`: **10485760** (10MiB): blobs API的默认最大文件大小。
## OAuth2 (`oauth2`)

View File

@ -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...`
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
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
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 each table in the database.

View File

@ -366,7 +366,7 @@ Gitea 提供了一个子命令`gitea migrate`来初始化数据库,然后您
> `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`。
@ -389,9 +389,8 @@ SET GLOBAL innodb_large_prefix=1;
他们创建了一个名为 `utf8mb4`的字符集和校对规则,允许存储 Emoji但使用
utf8 字符集的表和连接将不会使用它。
请运行 `gitea 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;`
请运行 `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;`
您还需要将`app.ini`文件中的数据库字符集设置为`CHARSET=utf8mb4`。

168
go.mod
View File

@ -5,7 +5,7 @@ go 1.21
require (
code.gitea.io/actions-proto-go v0.3.1
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
gitea.com/go-chi/binding v0.0.0-20230415142243-04b515c6d669
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/NYTimes/gziphandler v1.1.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/blevesearch/bleve/v2 v2.3.10
github.com/bufbuild/connect-go v1.10.0
github.com/buildkite/terminal-to-html/v3 v3.9.1
github.com/caddyserver/certmagic v0.19.2
github.com/buildkite/terminal-to-html/v3 v3.10.0
github.com/caddyserver/certmagic v0.20.0
github.com/chi-middleware/proxy v1.1.1
github.com/denisenkom/go-mssqldb v0.12.3
github.com/dimiro1/reply v0.0.0-20200315094148-d0136a4c9e21
@ -35,13 +35,13 @@ require (
github.com/emirpasic/gods v1.18.1
github.com/ethantkoenig/rupture v1.0.1
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/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-chi/chi/v5 v5.0.10
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-fed/httpsig v1.1.1-0.20201223112313-55836744818e
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-swagger/go-swagger v0.30.5
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/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
github.com/golang-jwt/jwt/v5 v5.0.0
github.com/google/go-github/v53 v53.2.0
github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98
github.com/google/uuid v1.3.1
github.com/gorilla/feeds v1.1.1
github.com/gorilla/sessions v1.2.1
github.com/golang-jwt/jwt/v5 v5.2.0
github.com/google/go-github/v57 v57.0.0
github.com/google/pprof v0.0.0-20231212022811-ec68065c825e
github.com/google/uuid v1.5.0
github.com/gorilla/feeds v1.1.2
github.com/gorilla/sessions v1.2.2
github.com/hashicorp/go-version v1.6.0
github.com/hashicorp/golang-lru/v2 v2.0.7
github.com/huandu/xstrings v1.4.0
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/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4
github.com/klauspost/compress v1.17.0
github.com/klauspost/cpuid/v2 v2.2.5
github.com/klauspost/compress v1.17.4
github.com/klauspost/cpuid/v2 v2.2.6
github.com/lib/pq v1.10.9
github.com/markbates/goth v1.78.0
github.com/mattn/go-isatty v0.0.19
github.com/mattn/go-sqlite3 v1.14.17
github.com/meilisearch/meilisearch-go v0.25.1
github.com/mattn/go-isatty v0.0.20
github.com/mattn/go-sqlite3 v1.14.19
github.com/meilisearch/meilisearch-go v0.26.0
github.com/mholt/archiver/v3 v3.5.1
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/msteinert/pam v1.2.0
github.com/nektos/act v0.2.52
@ -89,7 +89,7 @@ require (
github.com/pquerna/otp v1.4.0
github.com/prometheus/client_golang v1.17.0
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/santhosh-tekuri/jsonschema/v5 v5.3.1
github.com/sassoftware/go-rpmutils v0.2.0
@ -99,21 +99,21 @@ require (
github.com/syndtr/goleveldb v1.0.0
github.com/tstranex/u2f v1.0.0
github.com/ulikunitz/xz v0.5.11
github.com/urfave/cli/v2 v2.25.7
github.com/xanzy/go-gitlab v0.93.1
github.com/urfave/cli/v2 v2.26.0
github.com/xanzy/go-gitlab v0.95.2
github.com/xeipuuv/gojsonschema v1.2.0
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-meta v1.1.0
golang.org/x/crypto v0.14.0
golang.org/x/image v0.13.0
golang.org/x/net v0.17.0
golang.org/x/oauth2 v0.13.0
golang.org/x/sys v0.13.0
golang.org/x/text v0.13.0
golang.org/x/tools v0.14.0
google.golang.org/grpc v1.58.3
golang.org/x/crypto v0.17.0
golang.org/x/image v0.14.0
golang.org/x/net v0.19.0
golang.org/x/oauth2 v0.15.0
golang.org/x/sys v0.15.0
golang.org/x/text v0.14.0
golang.org/x/tools v0.16.1
google.golang.org/grpc v1.60.0
google.golang.org/protobuf v1.31.0
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
gopkg.in/ini.v1 v1.67.0
@ -125,33 +125,33 @@ 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
dario.cat/mergo v1.0.0 // 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/clickhouse-go/v2 v2.14.3 // indirect
github.com/ClickHouse/ch-go v0.61.0 // indirect
github.com/ClickHouse/clickhouse-go/v2 v2.16.0 // indirect
github.com/DataDog/zstd v1.5.5 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.2.1 // indirect
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
github.com/Microsoft/go-winio v0.6.1 // 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/andybalholm/brotli v1.0.5 // indirect
github.com/andybalholm/brotli v1.0.6 // indirect
github.com/andybalholm/cascadia v1.3.2 // indirect
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bits-and-blooms/bitset v1.9.0 // indirect
github.com/blevesearch/bleve_index_api v1.0.6 // indirect
github.com/bits-and-blooms/bitset v1.12.0 // indirect
github.com/blevesearch/bleve_index_api v1.1.4 // indirect
github.com/blevesearch/geo v0.1.18 // indirect
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
github.com/blevesearch/gtreap v0.1.1 // 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/snowballstem v0.9.0 // 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/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // 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/gomemcached v0.2.1 // indirect
github.com/couchbase/gomemcached v0.3.0 // indirect
github.com/couchbase/goutils v0.1.2 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.3 // 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/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dlclark/regexp2 v1.10.0 // indirect
github.com/emersion/go-sasl v0.0.0-20220912192320-0145f2c60ead // indirect
github.com/fatih/color v1.15.0 // indirect
github.com/felixge/httpsnoop v1.0.3 // indirect
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fxamacker/cbor/v2 v2.5.0 // 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-enry/go-oniguruma v1.2.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-openapi/analysis v0.21.4 // indirect
github.com/go-openapi/errors v0.20.4 // indirect
github.com/go-openapi/analysis v0.21.5 // indirect
github.com/go-openapi/errors v0.21.0 // indirect
github.com/go-openapi/inflect v0.19.0 // indirect
github.com/go-openapi/jsonpointer v0.20.0 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/loads v0.21.2 // indirect
github.com/go-openapi/runtime v0.26.0 // indirect
github.com/go-openapi/spec v0.20.9 // indirect
github.com/go-openapi/strfmt v0.21.7 // indirect
github.com/go-openapi/swag v0.22.4 // indirect
github.com/go-openapi/validate v0.22.1 // indirect
github.com/go-webauthn/x v0.1.4 // indirect
github.com/go-openapi/jsonpointer v0.20.1 // indirect
github.com/go-openapi/jsonreference v0.20.3 // indirect
github.com/go-openapi/loads v0.21.3 // indirect
github.com/go-openapi/runtime v0.26.2 // indirect
github.com/go-openapi/spec v0.20.12 // indirect
github.com/go-openapi/strfmt v0.21.10 // indirect
github.com/go-openapi/swag v0.22.5 // indirect
github.com/go-openapi/validate v0.22.4 // indirect
github.com/go-webauthn/x v0.1.5 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // 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/google/go-querystring v1.1.0 // indirect
github.com/google/go-tpm v0.9.0 // indirect
github.com/gorilla/css v1.0.0 // indirect
github.com/gorilla/handlers v1.5.1 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/gorilla/securecookie v1.1.1 // indirect
github.com/gorilla/css v1.0.1 // indirect
github.com/gorilla/handlers v1.5.2 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/gorilla/securecookie v1.1.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/imdario/mergo v0.3.16 // 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/mattn/go-colorable v0.1.13 // 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/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/mitchellh/copystructure v1.2.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/onsi/ginkgo v1.16.5 // indirect
github.com/paulmach/orb v0.10.0 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/pierrec/lz4/v4 v4.1.18 // indirect
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
github.com/pierrec/lz4/v4 v4.1.19 // indirect
github.com/pjbgf/sha1cd v0.3.0 // 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/common v0.44.0 // indirect
github.com/prometheus/common v0.45.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/rhysd/actionlint v1.6.26 // 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/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/segmentio/asm v1.2.0 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
@ -264,37 +264,37 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/skeema/knownhosts v1.2.1 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.10.0 // indirect
github.com/spf13/cast v1.5.1 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // 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/subosito/gotenv v1.6.0 // indirect
github.com/toqueteos/webbrowser v1.2.0 // indirect
github.com/unknwon/com v1.0.1 // 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/x448/float16 v0.8.4 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // 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
go.etcd.io/bbolt v1.3.7 // indirect
go.mongodb.org/mongo-driver v1.12.1 // indirect
go.opentelemetry.io/otel v1.19.0 // indirect
go.opentelemetry.io/otel/trace v1.19.0 // indirect
go.etcd.io/bbolt v1.3.8 // indirect
go.mongodb.org/mongo-driver v1.13.1 // indirect
go.opentelemetry.io/otel v1.21.0 // indirect
go.opentelemetry.io/otel/trace v1.21.0 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.26.0 // indirect
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
golang.org/x/mod v0.13.0 // indirect
golang.org/x/sync v0.4.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/sync v0.5.0 // indirect
golang.org/x/time v0.5.0 // 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/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect

488
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -51,6 +51,11 @@ type ActionRunner struct {
Deleted timeutil.TimeStamp `xorm:"deleted"`
}
const (
RunnerOfflineTime = time.Minute
RunnerIdleTime = 10 * time.Second
)
// BelongsToOwnerName before calling, should guarantee that all attributes are loaded
func (r *ActionRunner) BelongsToOwnerName() string {
if r.RepoID != 0 {
@ -76,11 +81,12 @@ func (r *ActionRunner) BelongsToOwnerType() types.OwnerType {
return types.OwnerTypeSystemGlobal
}
// if the logic here changed, you should also modify FindRunnerOptions.ToCond
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
}
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_ACTIVE
@ -153,6 +159,7 @@ type FindRunnerOptions struct {
OwnerID int64
Sort string
Filter string
IsOnline util.OptionalBool
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 != "" {
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
}

View File

@ -20,6 +20,7 @@ import (
func TestAddDeletedBranch(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
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})
assert.True(t, firstBranch.IsDeleted)
@ -30,7 +31,7 @@ func TestAddDeletedBranch(t *testing.T) {
assert.True(t, secondBranch.IsDeleted)
commit := &git.Commit{
ID: repo.ObjectFormat.MustIDFromString(secondBranch.CommitID),
ID: git.MustIDFromString(secondBranch.CommitID),
CommitMessage: secondBranch.CommitMessage,
Committer: &git.Signature{
When: secondBranch.CommitTime.AsLocalTime(),

View File

@ -114,7 +114,7 @@ WHEN NOT MATCHED
// GetNextCommitStatusIndex retried 3 times to generate a resource index
func GetNextCommitStatusIndex(ctx context.Context, repoID int64, sha string) (int64, error) {
_, err := git.IDFromString(sha)
_, err := git.NewIDFromString(sha)
if err != nil {
return 0, git.ErrInvalidSHA{SHA: sha}
}

View File

@ -180,7 +180,7 @@ type Repository struct {
IsFsckEnabled bool `xorm:"NOT NULL DEFAULT true"`
CloseIssuesViaCommitInAnyBranch bool `xorm:"NOT NULL DEFAULT false"`
Topics []string `xorm:"TEXT JSON"`
ObjectFormat git.ObjectFormat `xorm:"-"`
ObjectFormatName string `xorm:"-"`
TrustModel TrustModelType
@ -277,7 +277,9 @@ func (repo *Repository) AfterLoad() {
repo.NumOpenProjects = repo.NumProjects - repo.NumClosedProjects
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.
@ -606,25 +608,23 @@ func ComposeHTTPSCloneURL(owner, repo string) string {
func ComposeSSHCloneURL(ownerName, repoName string) string {
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
ip := net.ParseIP(setting.SSH.Domain)
if ip != nil && ip.To4() == nil {
sshDomain = "[" + setting.SSH.Domain + "]"
// non-standard port, it must use full URI
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 {
return fmt.Sprintf("ssh://%s@%s/%s/%s.git", sshUser,
net.JoinHostPort(setting.SSH.Domain, strconv.Itoa(setting.SSH.Port)),
url.PathEscape(ownerName),
url.PathEscape(repoName))
// for standard port, it can use a shorter URI (without the port)
sshHost := sshDomain
if ip := net.ParseIP(sshHost); ip != nil && ip.To4() == nil {
sshHost = "[" + sshHost + "]" // for IPv6 address, wrap it with brackets
}
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 {

View File

@ -12,6 +12,8 @@ import (
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/modules/util"
"github.com/stretchr/testify/assert"
@ -186,3 +188,32 @@ func TestGetRepositoryByURL(t *testing.T) {
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"))
}

View File

@ -377,3 +377,13 @@ func syncTopicsInRepository(sess db.Engine, repoID int64) error {
}
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))
}

View File

@ -24,11 +24,11 @@ func newCache(cacheConfig setting.Cache) (mc.Cache, error) {
})
}
// NewContext start cache service
func NewContext() error {
// Init start cache service
func Init() error {
var err error
if conn == nil && setting.CacheService.Enabled {
if conn == nil {
if conn, err = newCache(setting.CacheService.Cache); err != nil {
return err
}

View File

@ -22,9 +22,9 @@ func createTestCache() {
}
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{
Adapter: "rand",
Conn: "false conf",

View File

@ -8,11 +8,12 @@
package charset
import (
"bufio"
"html/template"
"io"
"strings"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/translation"
)
@ -20,20 +21,18 @@ import (
const RuneNBSP = 0xa0
// 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{}
outputStream := &HTMLStreamerWriter{Writer: sb}
streamer := NewEscapeStreamer(locale, outputStream, allowed...).(*escapeStreamer)
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()
escaped, _ = EscapeControlReader(strings.NewReader(string(html)), sb, locale, allowed...) // err has been handled in EscapeControlReader
return escaped, template.HTML(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) {
if !setting.UI.AmbiguousUnicodeDetection {
_, err = io.Copy(writer, reader)
return &EscapeStatus{}, err
}
outputStream := &HTMLStreamerWriter{Writer: writer}
streamer := NewEscapeStreamer(locale, outputStream, allowed...).(*escapeStreamer)
@ -43,41 +42,3 @@ func EscapeControlReader(reader io.Reader, writer io.Writer, locale translation.
}
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()
}

View File

@ -64,7 +64,7 @@ func (e *escapeStreamer) Text(data string) error {
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)
positions := make([]int, 0, next-until+1)

View File

@ -4,11 +4,14 @@
package charset
import (
"reflect"
"strings"
"testing"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/modules/translation"
"github.com/stretchr/testify/assert"
)
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) {
// lets add some control characters to the tests
// add some control characters to the tests
tests := make([]escapeControlTest, 0, len(escapeControlTests)*3)
copy(tests, escapeControlTests)
@ -169,29 +158,20 @@ func TestEscapeControlReader(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
input := strings.NewReader(tt.text)
output := &strings.Builder{}
status, err := EscapeControlReader(input, output, &translation.MockLocale{})
result := output.String()
if err != nil {
t.Errorf("EscapeControlReader(): err = %v", err)
}
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)
}
status, err := EscapeControlReader(strings.NewReader(tt.text), output, &translation.MockLocale{})
assert.NoError(t, err)
assert.Equal(t, tt.status, *status)
assert.Equal(t, tt.result, output.String())
})
}
}
func TestEscapeControlReader_panic(t *testing.T) {
bs := make([]byte, 0, 20479)
bs = append(bs, 'A')
for i := 0; i < 6826; i++ {
bs = append(bs, []byte("—")...)
}
_, _ = EscapeControlString(string(bs), &translation.MockLocale{})
func TestSettingAmbiguousUnicodeDetection(t *testing.T) {
defer test.MockVariableValue(&setting.UI.AmbiguousUnicodeDetection, true)()
_, out := EscapeControlHTML("a test", &translation.MockLocale{})
assert.EqualValues(t, `a<span class="escaped-code-point" data-escaped="[U+00A0]"><span class="char"> </span></span>test`, out)
setting.UI.AmbiguousUnicodeDetection = false
_, out = EscapeControlHTML("a test", &translation.MockLocale{})
assert.EqualValues(t, `a test`, out)
}

View File

@ -158,6 +158,12 @@ func checkDBConsistency(ctx context.Context, logger log.Logger, autofix bool) er
Fixer: actions_model.FixRunnersWithoutBelongingOwner,
FixedMessage: "Removed",
},
{
Name: "Topics with empty repository count",
Counter: repo_model.CountOrphanedTopics,
Fixer: repo_model.DeleteOrphanedTopics,
FixedMessage: "Removed",
},
}
// TODO: function to recalc all counters

View File

@ -9,6 +9,7 @@ import (
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/storage"
repo_service "code.gitea.io/gitea/services/repository"
"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
func deleteOrphanedRepos(ctx context.Context) (int64, error) {
if err := storage.Init(); err != nil {
return 0, err
}
batchSize := db.MaxBatchInsertSize("repository")
e := db.GetEngine(ctx)
var deleted int64

View File

@ -39,7 +39,7 @@ func TestReadingBlameOutput(t *testing.T) {
}
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.NotNil(t, blameReader)
defer blameReader.Close()

View File

@ -14,7 +14,6 @@ import (
"os/exec"
"strings"
"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/log"
@ -389,15 +388,11 @@ func (r *runStdError) IsExitCode(code int) bool {
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).
func (c *Command) RunStdString(opts *RunOpts) (stdout, stderr string, runErr RunStdError) {
stdoutBytes, stderrBytes, err := c.RunStdBytes(opts)
stdout = bytesToString(stdoutBytes)
stderr = bytesToString(stderrBytes)
stdout = util.UnsafeBytesToString(stdoutBytes)
stderr = util.UnsafeBytesToString(stderrBytes)
if err != nil {
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)
stderr = stderrBuf.Bytes()
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
return stdoutBuf.Bytes(), stderr, nil

View File

@ -236,7 +236,7 @@ func (c *Commit) IsForcePush(oldCommitID string) (bool, error) {
if err != nil {
return false, err
}
if oldCommitID == objectFormat.Empty().String() {
if oldCommitID == objectFormat.EmptyObjectID().String() {
return false, nil
}

View File

@ -153,7 +153,7 @@ func GetLastCommitForPaths(ctx context.Context, commit *Commit, treePath string,
if typ != "commit" {
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 {
return nil, err
}

View File

@ -71,10 +71,10 @@ readLoop:
switch string(split[0]) {
case "tree":
commit.Tree = *NewTree(gitRepo, objectID.Type().MustIDFromString(string(data)))
commit.Tree = *NewTree(gitRepo, MustIDFromString(string(data)))
_, _ = payloadSB.Write(line)
case "parent":
commit.Parents = append(commit.Parents, objectID.Type().MustIDFromString(string(data)))
commit.Parents = append(commit.Parents, MustIDFromString(string(data)))
_, _ = payloadSB.Write(line)
case "author":
commit.Author = &Signature{}

View File

@ -135,8 +135,8 @@ func TestHasPreviousCommit(t *testing.T) {
commit, err := repo.GetCommit("8006ff9adbf0cb94da7dad9e537e53817f9fa5c0")
assert.NoError(t, err)
parentSHA := repo.objectFormat.MustIDFromString("8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2")
notParentSHA := repo.objectFormat.MustIDFromString("2839944139e0de9737a044f78b0e4b40d989a9e3")
parentSHA := MustIDFromString("8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2")
notParentSHA := MustIDFromString("2839944139e0de9737a044f78b0e4b40d989a9e3")
haz, err := commit.HasPreviousCommit(parentSHA)
assert.NoError(t, err)

View File

@ -39,7 +39,7 @@ func NewLastCommitCache(count int64, repoPath string, gitRepo *Repository, cache
if cache == nil {
return nil
}
if !setting.CacheService.LastCommit.Enabled || count < setting.CacheService.LastCommit.CommitsCount {
if count < setting.CacheService.LastCommit.CommitsCount {
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
func (c *LastCommitCache) GetCommitByPath(commitID, entryPath string) (*Commit, error) {
objectFormat, err := c.repo.GetObjectFormat()
if err != nil {
return nil, err
}
sha, err := objectFormat.NewIDFromString(commitID)
sha, err := NewIDFromString(commitID)
if err != nil {
return nil, err
}

View File

@ -5,97 +5,89 @@ package git
import (
"crypto/sha1"
"fmt"
"regexp"
"strings"
)
type ObjectFormatID int
const (
Sha1 ObjectFormatID = iota
"strconv"
)
// sha1Pattern can be used to determine if a string is an valid sha
var sha1Pattern = regexp.MustCompile(`^[0-9a-f]{4,40}$`)
type ObjectFormat interface {
ID() ObjectFormatID
String() string
// Empty is the hash of empty git
Empty() ObjectID
// Name returns the name of the object format
Name() string
// EmptyObjectID creates a new empty ObjectID from an object format hash name
EmptyObjectID() ObjectID
// EmptyTree is the hash of an empty tree
EmptyTree() ObjectID
// FullLength is the length of the hash's hex string
FullLength() int
// IsValid returns true if the input is a valid hash
IsValid(input string) bool
// MustID creates a new ObjectID from a byte slice
MustID(b []byte) ObjectID
MustIDFromString(s string) ObjectID
NewID(b []byte) (ObjectID, error)
NewIDFromString(s string) (ObjectID, error)
NewEmptyID() ObjectID
NewHasher() HasherInterface
// ComputeHash compute the hash for a given ObjectType and content
ComputeHash(t ObjectType, content []byte) ObjectID
}
type Sha1ObjectFormat struct{}
type Sha1ObjectFormatImpl struct{}
func (*Sha1ObjectFormat) ID() ObjectFormatID { return Sha1 }
func (*Sha1ObjectFormat) String() string { return "sha1" }
func (*Sha1ObjectFormat) Empty() ObjectID { return &Sha1Hash{} }
func (*Sha1ObjectFormat) EmptyTree() ObjectID {
return &Sha1Hash{
var (
emptyObjectID = &Sha1Hash{}
emptyTree = &Sha1Hash{
0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,
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)
}
func (*Sha1ObjectFormat) MustID(b []byte) ObjectID {
func (Sha1ObjectFormatImpl) MustID(b []byte) ObjectID {
var id Sha1Hash
copy(id[0:20], b)
return &id
}
func (h *Sha1ObjectFormat) MustIDFromString(s string) ObjectID {
return MustIDFromString(h, s)
// ComputeHash compute the hash for a given ObjectType and content
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) {
return IDFromRaw(h, b)
var Sha1ObjectFormat ObjectFormat = Sha1ObjectFormatImpl{}
var SupportedObjectFormats = []ObjectFormat{
Sha1ObjectFormat,
// TODO: add sha256
}
func (h *Sha1ObjectFormat) NewIDFromString(s string) (ObjectID, error) {
return genericIDFromString(h, s)
}
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{}
func ObjectFormatFromName(name string) ObjectFormat {
for _, objectFormat := range SupportedObjectFormats {
if name == objectFormat.Name() {
return objectFormat
}
}
return nil
}
func ObjectFormatFromString(hash string) (ObjectFormat, error) {
switch strings.ToLower(hash) {
case "sha1":
return &Sha1ObjectFormat{}, nil
}
return nil, fmt.Errorf("unknown hash type: %s", hash)
func IsValidObjectFormat(name string) bool {
return ObjectFormatFromName(name) != nil
}

View File

@ -6,11 +6,7 @@ package git
import (
"bytes"
"encoding/hex"
"errors"
"fmt"
"hash"
"strconv"
"strings"
)
type ObjectID interface {
@ -31,59 +27,40 @@ func (h *Sha1Hash) IsZero() bool {
return bytes.Equal(empty[:], h[:])
}
func (h *Sha1Hash) RawValue() []byte { return h[:] }
func (*Sha1Hash) Type() ObjectFormat { return &Sha1ObjectFormat{} }
func (*Sha1Hash) Type() ObjectFormat { return Sha1ObjectFormat }
func NewSha1() *Sha1Hash {
return &Sha1Hash{}
}
var _ ObjectID = &Sha1Hash{}
// NewHash is for generic implementations
func NewHash(hash string) (ObjectID, error) {
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)
func MustIDFromString(hexHash string) ObjectID {
id, err := NewIDFromString(hexHash)
if err != nil {
return h.Empty(), err
panic(err)
}
return h.NewID(b)
return id
}
func IDFromString(hexHash string) (ObjectID, error) {
switch len(hexHash) {
case 40:
hashType := Sha1ObjectFormat{}
h, err := hashType.NewIDFromString(hexHash)
if err != nil {
return nil, err
func NewIDFromString(hexHash string) (ObjectID, error) {
var theObjectFormat ObjectFormat
for _, objectFormat := range SupportedObjectFormats {
if len(hexHash) == objectFormat.FullLength() {
theObjectFormat = objectFormat
break
}
return h, nil
}
return nil, fmt.Errorf("invalid hash hex string: '%s' len: %d", hexHash, len(hexHash))
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 {
return nil, err
}
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 {
@ -91,7 +68,7 @@ func IsEmptyCommitID(commitID string) bool {
return true
}
id, err := IDFromString(commitID)
id, err := NewIDFromString(commitID)
if err != nil {
return false
}
@ -99,37 +76,9 @@ func IsEmptyCommitID(commitID string) bool {
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
func ComputeBlobHash(hashType ObjectFormat, content []byte) ObjectID {
return ComputeHash(hashType, 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
return hashType.ComputeHash(ObjectBlob, content)
}
type ErrInvalidSHA struct {

View File

@ -12,7 +12,7 @@ import (
func ParseGogitHash(h plumbing.Hash) ObjectID {
switch hash.Size {
case 20:
return ObjectFormatFromID(Sha1).MustID(h[:])
return Sha1ObjectFormat.MustID(h[:])
}
return nil

View File

@ -10,7 +10,7 @@ import (
)
func TestIsValidSHAPattern(t *testing.T) {
h := NewSha1().Type()
h := Sha1ObjectFormat
assert.True(t, h.IsValid("fee1"))
assert.True(t, h.IsValid("abc000"))
assert.True(t, h.IsValid("9023902390239023902390239023902390239023"))

View File

@ -57,7 +57,7 @@ func parseTreeEntries(data []byte, ptree *Tree) ([]*TreeEntry, error) {
return nil, fmt.Errorf("Invalid ls-tree output: %s", string(data))
}
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 {
return nil, fmt.Errorf("invalid ls-tree output: %w", err)
}

View File

@ -28,9 +28,9 @@ func TestParseTreeEntries(t *testing.T) {
Input: "100644 blob 61ab7345a1a3bbc590068ccae37b8515cfc5843c 1022\texample/file2.txt\n",
Expected: []*TreeEntry{
{
ID: ObjectFormatFromID(Sha1).MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c"),
ID: MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c"),
gogitTreeEntry: &object.TreeEntry{
Hash: plumbing.Hash(ObjectFormatFromID(Sha1).MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c").RawValue()),
Hash: plumbing.Hash(MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c").RawValue()),
Name: "example/file2.txt",
Mode: filemode.Regular,
},
@ -44,9 +44,9 @@ func TestParseTreeEntries(t *testing.T) {
"040000 tree 1d01fb729fb0db5881daaa6030f9f2d3cd3d5ae8 -\texample\n",
Expected: []*TreeEntry{
{
ID: ObjectFormatFromID(Sha1).MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c"),
ID: MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c"),
gogitTreeEntry: &object.TreeEntry{
Hash: plumbing.Hash(ObjectFormatFromID(Sha1).MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c").RawValue()),
Hash: plumbing.Hash(MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c").RawValue()),
Name: "example/\n.txt",
Mode: filemode.Symlink,
},
@ -54,10 +54,10 @@ func TestParseTreeEntries(t *testing.T) {
sized: true,
},
{
ID: ObjectFormatFromID(Sha1).MustIDFromString("1d01fb729fb0db5881daaa6030f9f2d3cd3d5ae8"),
ID: MustIDFromString("1d01fb729fb0db5881daaa6030f9f2d3cd3d5ae8"),
sized: true,
gogitTreeEntry: &object.TreeEntry{
Hash: plumbing.Hash(ObjectFormatFromID(Sha1).MustIDFromString("1d01fb729fb0db5881daaa6030f9f2d3cd3d5ae8").RawValue()),
Hash: plumbing.Hash(MustIDFromString("1d01fb729fb0db5881daaa6030f9f2d3cd3d5ae8").RawValue()),
Name: "example",
Mode: filemode.Dir,
},
@ -67,7 +67,7 @@ func TestParseTreeEntries(t *testing.T) {
}
for _, testCase := range testCases {
entries, err := ParseTreeEntries(ObjectFormatFromID(Sha1), []byte(testCase.Input))
entries, err := ParseTreeEntries(Sha1ObjectFormat, []byte(testCase.Input))
assert.NoError(t, err)
if len(entries) > 1 {
fmt.Println(testCase.Expected[0].ID)

View File

@ -72,7 +72,7 @@ func parseTreeEntries(objectFormat ObjectFormat, data []byte, ptree *Tree) ([]*T
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 {
return nil, fmt.Errorf("invalid ls-tree output (invalid object id): %q, err: %w", line, err)
}

View File

@ -12,7 +12,7 @@ import (
)
func TestParseTreeEntriesLong(t *testing.T) {
objectFormat := ObjectFormatFromID(Sha1)
objectFormat := Sha1ObjectFormat
testCases := []struct {
Input string
@ -26,28 +26,28 @@ func TestParseTreeEntriesLong(t *testing.T) {
`,
Expected: []*TreeEntry{
{
ID: objectFormat.MustIDFromString("ea0d83c9081af9500ac9f804101b3fd0a5c293af"),
ID: MustIDFromString("ea0d83c9081af9500ac9f804101b3fd0a5c293af"),
name: "README.md",
entryMode: EntryModeBlob,
size: 8218,
sized: true,
},
{
ID: objectFormat.MustIDFromString("037f27dc9d353ae4fd50f0474b2194c593914e35"),
ID: MustIDFromString("037f27dc9d353ae4fd50f0474b2194c593914e35"),
name: "README_ZH.md",
entryMode: EntryModeBlob,
size: 4681,
sized: true,
},
{
ID: objectFormat.MustIDFromString("9846a94f7e8350a916632929d0fda38c90dd2ca8"),
ID: MustIDFromString("9846a94f7e8350a916632929d0fda38c90dd2ca8"),
name: "SECURITY.md",
entryMode: EntryModeBlob,
size: 429,
sized: true,
},
{
ID: objectFormat.MustIDFromString("84b90550547016f73c5dd3f50dea662389e67b6d"),
ID: MustIDFromString("84b90550547016f73c5dd3f50dea662389e67b6d"),
name: "assets",
entryMode: EntryModeTree,
sized: true,
@ -66,7 +66,7 @@ func TestParseTreeEntriesLong(t *testing.T) {
}
func TestParseTreeEntriesShort(t *testing.T) {
objectFormat := ObjectFormatFromID(Sha1)
objectFormat := Sha1ObjectFormat
testCases := []struct {
Input string
@ -78,12 +78,12 @@ func TestParseTreeEntriesShort(t *testing.T) {
`,
Expected: []*TreeEntry{
{
ID: objectFormat.MustIDFromString("ea0d83c9081af9500ac9f804101b3fd0a5c293af"),
ID: MustIDFromString("ea0d83c9081af9500ac9f804101b3fd0a5c293af"),
name: "README.md",
entryMode: EntryModeBlob,
},
{
ID: objectFormat.MustIDFromString("84b90550547016f73c5dd3f50dea662389e67b6d"),
ID: MustIDFromString("84b90550547016f73c5dd3f50dea662389e67b6d"),
name: "assets",
entryMode: EntryModeTree,
},
@ -102,7 +102,7 @@ func TestParseTreeEntriesShort(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
entries, err := ParseTreeEntries(ObjectFormatFromID(Sha1), []byte("100644 blob ea0d83c9081af9500ac9f804101b3fd0a5c293af"))
entries, err := ParseTreeEntries(Sha1ObjectFormat, []byte("100644 blob ea0d83c9081af9500ac9f804101b3fd0a5c293af"))
assert.Error(t, err)
assert.Len(t, entries, 0)
}

View File

@ -115,11 +115,7 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
continue
case "commit":
// Read in the commit to get its tree and in case this is one of the last used commits
objectFormat, err := repo.GetObjectFormat()
if err != nil {
return nil, err
}
curCommit, err = git.CommitFromReader(repo, objectFormat.MustIDFromString(string(commitID)), io.LimitReader(batchReader, size))
curCommit, err = git.CommitFromReader(repo, git.MustIDFromString(string(commitID)), io.LimitReader(batchReader, size))
if err != nil {
return nil, err
}

View File

@ -205,7 +205,7 @@ func RefURL(repoURL, ref string) string {
return repoURL + "/src/branch/" + refName
case refFullName.IsTag():
return repoURL + "/src/tag/" + refName
case !ObjectFormatFromID(Sha1).IsValid(ref):
case !Sha1ObjectFormat.IsValid(ref):
// assume they mean a branch
return repoURL + "/src/branch/" + refName
default:

View File

@ -81,7 +81,7 @@ func GetObjectFormatOfRepo(ctx context.Context, repoPath string) (ObjectFormat,
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 {
return nil, err
}
@ -90,7 +90,7 @@ func GetObjectFormatOfRepo(ctx context.Context, repoPath string) (ObjectFormat,
}
// 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)
if err != nil {
return err
@ -98,7 +98,13 @@ func InitRepository(ctx context.Context, repoPath string, bare bool, objectForma
cmd := NewCommand(ctx, "init")
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 {
cmd.AddArguments("--bare")

View File

@ -5,7 +5,7 @@ package git
// GetBlob finds the blob object in the repository.
func (repo *Repository) GetBlob(idStr string) (*Blob, error) {
id, err := repo.objectFormat.NewIDFromString(idStr)
id, err := NewIDFromString(idStr)
if err != nil {
return nil, err
}

View File

@ -61,7 +61,7 @@ func TestRepository_GetBlob_NoId(t *testing.T) {
defer r.Close()
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)
assert.Nil(t, blob)

View File

@ -63,7 +63,7 @@ func (repo *Repository) getCommitByPathWithID(id ObjectID, relpath string) (*Com
return nil, runErr
}
id, err := repo.objectFormat.NewIDFromString(stdout)
id, err := NewIDFromString(stdout)
if err != nil {
return nil, err
}
@ -254,7 +254,7 @@ func (repo *Repository) CommitsByFileAndRange(opts CommitsByFileAndRangeOptions)
}
return commits, err
}
objectID, err := repo.objectFormat.NewIDFromString(string(shaline[0:len]))
objectID, err := NewIDFromString(string(shaline[0:len]))
if err != nil {
return nil, err
}

View File

@ -43,7 +43,7 @@ func (repo *Repository) RemoveReference(name string) error {
func (repo *Repository) ConvertToGitID(commitID string) (ObjectID, error) {
objectFormat := repo.objectFormat
if len(commitID) == hash.HexSize && objectFormat.IsValid(commitID) {
ID, err := objectFormat.NewIDFromString(commitID)
ID, err := NewIDFromString(commitID)
if err == nil {
return ID, nil
}
@ -54,12 +54,12 @@ func (repo *Repository) ConvertToGitID(commitID string) (ObjectID, error) {
if err != nil {
if strings.Contains(err.Error(), "unknown revision or path") ||
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.

View File

@ -135,7 +135,7 @@ func (repo *Repository) getCommitFromBatchReader(rd *bufio.Reader, id ObjectID)
func (repo *Repository) ConvertToGitID(commitID string) (ObjectID, error) {
IDType := repo.objectFormat
if len(commitID) == IDType.FullLength() && IDType.IsValid(commitID) {
ID, err := repo.objectFormat.NewIDFromString(commitID)
ID, err := NewIDFromString(commitID)
if err == nil {
return ID, nil
}
@ -155,5 +155,5 @@ func (repo *Repository) ConvertToGitID(commitID string) (ObjectID, error) {
return nil, err
}
return repo.objectFormat.MustIDFromString(string(sha)), nil
return MustIDFromString(string(sha)), nil
}

View File

@ -22,7 +22,7 @@ func (r *Repository) CommitNodeIndex() (cgobject.CommitNodeIndex, *os.File) {
file, err := os.Open(indexPath)
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)
if err == nil {
return cgobject.NewGraphCommitNodeIndex(index, r.gogitRepo.Storer), file

View 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
func (repo *Repository) GetFilesChangedBetween(base, head string) ([]string, error) {
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)
} else {
cmd.AddDynamicArguments(base, head)

View File

@ -131,12 +131,12 @@ func TestGetCommitFilesChanged(t *testing.T) {
files []string
}{
{
repo.objectFormat.Empty().String(),
repo.objectFormat.EmptyObjectID().String(),
"95bb4d39648ee7e325106df01a621c530863a653",
[]string{"file1.txt"},
},
{
repo.objectFormat.Empty().String(),
repo.objectFormat.EmptyObjectID().String(),
"8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2",
[]string{"file2.txt"},
},

View File

@ -30,7 +30,7 @@ func (repo *Repository) ReadTreeToIndex(treeish string, indexFilename ...string)
treeish = res[:len(res)-1]
}
}
id, err := objectFormat.NewIDFromString(treeish)
id, err := NewIDFromString(treeish)
if err != nil {
return err
}
@ -101,7 +101,7 @@ func (repo *Repository) RemoveFilesFromIndex(filenames ...string) error {
for _, file := range filenames {
if file != "" {
buffer.WriteString("0 ")
buffer.WriteString(repo.objectFormat.Empty().String())
buffer.WriteString(repo.objectFormat.EmptyObjectID().String())
buffer.WriteByte('\t')
buffer.WriteString(file)
buffer.WriteByte('\000')
@ -128,7 +128,7 @@ func (repo *Repository) WriteTree() (*Tree, error) {
if runErr != nil {
return nil, runErr
}
id, err := repo.objectFormat.NewIDFromString(strings.TrimSpace(stdout))
id, err := NewIDFromString(strings.TrimSpace(stdout))
if err != nil {
return nil, err
}

View File

@ -39,7 +39,7 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err
return nil, ErrNotExist{commitID, ""}
}
sha, err := repo.objectFormat.NewIDFromString(string(shaBytes))
sha, err := NewIDFromString(string(shaBytes))
if err != nil {
log.Debug("Unable to get commit for: %s. Err: %v", commitID, err)
return nil, ErrNotExist{commitID, ""}

View File

@ -46,7 +46,7 @@ func (repo *Repository) GetObjectFormat() (ObjectFormat, error) {
if err != nil {
return nil, err
}
hash, err := IDFromString(str)
hash, err := NewIDFromString(str)
if err != nil {
return nil, err
}
@ -62,7 +62,7 @@ func (repo *Repository) HashObject(reader io.Reader) (ObjectID, error) {
if err != nil {
return nil, err
}
return repo.objectFormat.NewIDFromString(idStr)
return NewIDFromString(idStr)
}
func (repo *Repository) hashObject(reader io.Reader, save bool) (string, error) {

View File

@ -75,7 +75,7 @@ func (repo *Repository) GetRefsFiltered(pattern string) ([]*Reference, error) {
if pattern == "" || strings.HasPrefix(refName, pattern) {
r := &Reference{
Name: refName,
Object: repo.objectFormat.MustIDFromString(sha),
Object: MustIDFromString(sha),
Type: typ,
repo: repo,
}

View File

@ -84,7 +84,7 @@ func (repo *Repository) GetTag(name string) (*Tag, error) {
return nil, err
}
id, err := repo.objectFormat.NewIDFromString(idStr)
id, err := NewIDFromString(idStr)
if err != nil {
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
func (repo *Repository) GetTagWithID(idStr, name string) (*Tag, error) {
id, err := repo.objectFormat.NewIDFromString(idStr)
id, err := NewIDFromString(idStr)
if err != nil {
return nil, err
}
@ -165,7 +165,7 @@ func parseTagRef(objectFormat ObjectFormat, ref map[string]string) (tag *Tag, er
Name: ref["refname:short"],
}
tag.ID, err = objectFormat.NewIDFromString(ref["objectname"])
tag.ID, err = NewIDFromString(ref["objectname"])
if err != nil {
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
} else {
// annotated tag
tag.Object, err = objectFormat.NewIDFromString(ref["object"])
tag.Object, err = NewIDFromString(ref["object"])
if err != nil {
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
func (repo *Repository) GetAnnotatedTag(sha string) (*Tag, error) {
id, err := repo.objectFormat.NewIDFromString(sha)
id, err := NewIDFromString(sha)
if err != nil {
return nil, err
}

View File

@ -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
return nil, err
}
commitID, err := IDFromString(commitIDStr)
commitID, err := NewIDFromString(commitIDStr)
if err != nil {
return nil, err
}

View File

@ -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
return nil, err
}
commitID, err := repo.objectFormat.NewIDFromString(commitIDStr)
commitID, err := NewIDFromString(commitIDStr)
if err != nil {
return nil, err
}

View File

@ -194,7 +194,7 @@ func TestRepository_GetAnnotatedTag(t *testing.T) {
}
func TestRepository_parseTagRef(t *testing.T) {
sha1 := ObjectFormatFromID(Sha1)
sha1 := Sha1ObjectFormat
tests := []struct {
name string
@ -224,8 +224,8 @@ func TestRepository_parseTagRef(t *testing.T) {
want: &Tag{
Name: "v1.9.1",
ID: sha1.MustIDFromString("ab23e4b7f4cd0caafe0174c0e7ef6d651ba72889"),
Object: sha1.MustIDFromString("ab23e4b7f4cd0caafe0174c0e7ef6d651ba72889"),
ID: MustIDFromString("ab23e4b7f4cd0caafe0174c0e7ef6d651ba72889"),
Object: MustIDFromString("ab23e4b7f4cd0caafe0174c0e7ef6d651ba72889"),
Type: "commit",
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",
@ -253,8 +253,8 @@ func TestRepository_parseTagRef(t *testing.T) {
want: &Tag{
Name: "v0.0.1",
ID: sha1.MustIDFromString("8c68a1f06fc59c655b7e3905b159d761e91c53c9"),
Object: sha1.MustIDFromString("3325fd8a973321fd59455492976c042dde3fd1ca"),
ID: MustIDFromString("8c68a1f06fc59c655b7e3905b159d761e91c53c9"),
Object: MustIDFromString("3325fd8a973321fd59455492976c042dde3fd1ca"),
Type: "tag",
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",
@ -311,8 +311,8 @@ qbHDASXl
want: &Tag{
Name: "v0.0.1",
ID: sha1.MustIDFromString("8c68a1f06fc59c655b7e3905b159d761e91c53c9"),
Object: sha1.MustIDFromString("3325fd8a973321fd59455492976c042dde3fd1ca"),
ID: MustIDFromString("8c68a1f06fc59c655b7e3905b159d761e91c53c9"),
Object: MustIDFromString("3325fd8a973321fd59455492976c042dde3fd1ca"),
Type: "tag",
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",

View File

@ -63,5 +63,5 @@ func (repo *Repository) CommitTree(author, committer *Signature, tree *Tree, opt
if err != nil {
return nil, ConcatenateError(err, stderr.String())
}
return repo.objectFormat.NewIDFromString(strings.TrimSpace(stdout.String()))
return NewIDFromString(strings.TrimSpace(stdout.String()))
}

View File

@ -30,7 +30,7 @@ func (repo *Repository) GetTree(idStr string) (*Tree, error) {
idStr = res[:len(res)-1]
}
}
id, err := repo.objectFormat.NewIDFromString(idStr)
id, err := NewIDFromString(idStr)
if err != nil {
return nil, err
}

View File

@ -75,7 +75,7 @@ func (repo *Repository) GetTree(idStr string) (*Tree, error) {
idStr = res
}
}
id, err := repo.objectFormat.NewIDFromString(idStr)
id, err := NewIDFromString(idStr)
if err != nil {
return nil, err
}

View File

@ -35,8 +35,8 @@ func (tag *Tag) Commit(gitRepo *Repository) (*Commit, error) {
// \n\n separate headers from message
func parseTagData(objectFormat ObjectFormat, data []byte) (*Tag, error) {
tag := new(Tag)
tag.ID = objectFormat.NewEmptyID()
tag.Object = objectFormat.NewEmptyID()
tag.ID = objectFormat.EmptyObjectID()
tag.Object = objectFormat.EmptyObjectID()
tag.Tagger = &Signature{}
// we now have the contents of the commit object. Let's investigate...
nextline := 0
@ -50,7 +50,7 @@ l:
reftype := line[:spacepos]
switch string(reftype) {
case "object":
id, err := objectFormat.NewIDFromString(string(line[spacepos+1:]))
id, err := NewIDFromString(string(line[spacepos+1:]))
if err != nil {
return nil, err
}

View File

@ -22,7 +22,7 @@ tagger Lucas Michot <lucas@semalead.com> 1484491741 +0100
`), tag: Tag{
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},
Type: "commit",
Tagger: &Signature{Name: "Lucas Michot", Email: "lucas@semalead.com", When: time.Unix(1484491741, 0)},
@ -39,7 +39,7 @@ o
ono`), tag: Tag{
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},
Type: "commit",
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 {
tag, err := parseTagData(ObjectFormatFromID(Sha1), test.data)
tag, err := parseTagData(Sha1ObjectFormat, test.data)
assert.NoError(t, err)
assert.EqualValues(t, test.tag.ID, tag.ID)
assert.EqualValues(t, test.tag.Object, tag.Object)

View File

@ -9,6 +9,7 @@ import (
"bytes"
"fmt"
gohtml "html"
"html/template"
"io"
"path/filepath"
"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
func Code(fileName, language, code string) (string, string) {
func Code(fileName, language, code string) (output template.HTML, lexerName string) {
NewContext()
// 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 {
return code, ""
return template.HTML(template.HTMLEscapeString(code)), ""
}
var lexer chroma.Lexer
@ -102,13 +103,11 @@ func Code(fileName, language, code string) (string, string) {
cache.Add(fileName, lexer)
}
lexerName := formatLexerName(lexer.Config().Name)
return CodeFromLexer(lexer, code), lexerName
return CodeFromLexer(lexer, code), formatLexerName(lexer.Config().Name)
}
// 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),
html.WithLineNumbers(false),
html.PreventSurroundingPre(true),
@ -120,23 +119,23 @@ func CodeFromLexer(lexer chroma.Lexer, code string) string {
iterator, err := lexer.Tokenise(nil, code)
if err != nil {
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
err = formatter.Format(htmlw, githubStyles, iterator)
if err != nil {
log.Error("Can't format code: %v", err)
return code
return template.HTML(template.HTMLEscapeString(code))
}
_ = htmlw.Flush()
// 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
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
func File(fileName, language string, code []byte) ([]string, string, error) {
func File(fileName, language string, code []byte) ([]template.HTML, string, error) {
NewContext()
if len(code) > sizeLimit {
@ -183,14 +182,14 @@ func File(fileName, language string, code []byte) ([]string, string, error) {
tokensLines := chroma.SplitTokensIntoLines(iterator.Tokens())
htmlBuf := &bytes.Buffer{}
lines := make([]string, 0, len(tokensLines))
lines := make([]template.HTML, 0, len(tokensLines))
for _, tokens := range tokensLines {
iterator = chroma.Literator(tokens...)
err = formatter.Format(htmlBuf, githubStyles, iterator)
if err != nil {
return nil, "", fmt.Errorf("can't format code: %w", err)
}
lines = append(lines, htmlBuf.String())
lines = append(lines, template.HTML(htmlBuf.String()))
htmlBuf.Reset()
}
@ -198,9 +197,9 @@ func File(fileName, language string, code []byte) ([]string, string, error) {
}
// PlainText returns non-highlighted HTML for code
func PlainText(code []byte) []string {
func PlainText(code []byte) []template.HTML {
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 {
content, err := r.ReadString('\n')
if err != nil && err != io.EOF {
@ -210,7 +209,7 @@ func PlainText(code []byte) []string {
if content == "" && err == io.EOF {
break
}
s := gohtml.EscapeString(content)
s := template.HTML(gohtml.EscapeString(content))
m = append(m, s)
}
return m

View File

@ -4,21 +4,36 @@
package highlight
import (
"html/template"
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
func lines(s string) []string {
return strings.Split(strings.ReplaceAll(strings.TrimSpace(s), `\n`, "\n"), "\n")
func lines(s string) (out []template.HTML) {
// "" => [], "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) {
tests := []struct {
name string
code string
want []string
want []template.HTML
lexerName string
}{
{
@ -99,10 +114,7 @@ c=2
t.Run(tt.name, func(t *testing.T) {
out, lexerName, err := File(tt.name, "", []byte(tt.code))
assert.NoError(t, err)
expected := strings.Join(tt.want, "\n")
actual := strings.Join(out, "\n")
assert.Equal(t, strings.Count(actual, "<span"), strings.Count(actual, "</span>"))
assert.EqualValues(t, expected, actual)
assert.EqualValues(t, tt.want, out)
assert.Equal(t, tt.lexerName, lexerName)
})
}
@ -112,7 +124,7 @@ func TestPlainText(t *testing.T) {
tests := []struct {
name string
code string
want []string
want []template.HTML
}{
{
name: "empty.py",
@ -165,9 +177,7 @@ c=2`),
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
out := PlainText([]byte(tt.code))
expected := strings.Join(tt.want, "\n")
actual := strings.Join(out, "\n")
assert.EqualValues(t, expected, actual)
assert.EqualValues(t, tt.want, out)
})
}
}

View File

@ -6,6 +6,7 @@ package code
import (
"bytes"
"context"
"html/template"
"strings"
"code.gitea.io/gitea/modules/highlight"
@ -22,7 +23,7 @@ type Result struct {
Language string
Color string
LineNumbers []int
FormattedLines string
FormattedLines template.HTML
}
type SearchResultLanguages = internal.SearchResultLanguages

View File

@ -87,7 +87,7 @@ func Render(ctx *markup.RenderContext, input io.Reader, output io.Writer) error
}
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 ""
}
}

View File

@ -144,7 +144,7 @@ func TestCommitToPushCommit(t *testing.T) {
When: now,
}
const hexString = "0123456789abcdef0123456789abcdef01234567"
sha1, err := git.IDFromString(hexString)
sha1, err := git.NewIDFromString(hexString)
assert.NoError(t, err)
pushCommit := CommitToPushCommit(&git.Commit{
ID: sha1,
@ -169,12 +169,11 @@ func TestListToPushCommits(t *testing.T) {
When: now,
}
hashType := git.ObjectFormatFromID(git.Sha1)
const hexString1 = "0123456789abcdef0123456789abcdef01234567"
hash1, err := hashType.NewIDFromString(hexString1)
hash1, err := git.NewIDFromString(hexString1)
assert.NoError(t, err)
const hexString2 = "fedcba9876543210fedcba9876543210fedcba98"
hash2, err := hashType.NewIDFromString(hexString2)
hash2, err := git.NewIDFromString(hexString2)
assert.NoError(t, err)
l := []*git.Commit{

View File

@ -224,7 +224,7 @@ func generateRepoCommit(ctx context.Context, repo, templateRepo, generateRepo *r
}
// 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
}
@ -358,7 +358,7 @@ func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templ
}
// 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
}

View File

@ -188,7 +188,7 @@ func InitRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Reposi
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.
repoPath := repo_model.RepoPath(owner, name)
isExist, err := util.IsExist(repoPath)
@ -204,7 +204,7 @@ func CheckInitRepository(ctx context.Context, owner, name string, objectFormat g
}
// 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)
} else if err = CreateDelegateHooks(repoPath); err != nil {
return fmt.Errorf("createDelegateHooks: %w", err)

View File

@ -20,13 +20,13 @@ type PushUpdateOptions struct {
// IsNewRef return true if it's a first-time push to a branch, tag or etc.
func (opts *PushUpdateOptions) IsNewRef() bool {
commitID, err := git.IDFromString(opts.OldCommitID)
commitID, err := git.NewIDFromString(opts.OldCommitID)
return err == nil && commitID.IsZero()
}
// IsDelRef return true if it's a deletion to a branch or tag
func (opts *PushUpdateOptions) IsDelRef() bool {
commitID, err := git.IDFromString(opts.NewCommitID)
commitID, err := git.NewIDFromString(opts.NewCommitID)
return err == nil && commitID.IsZero()
}

View File

@ -12,7 +12,6 @@ import (
// Cache represents cache settings
type Cache struct {
Enabled bool
Adapter string
Interval int
Conn string
@ -24,23 +23,19 @@ var CacheService = struct {
Cache `ini:"cache"`
LastCommit struct {
Enabled bool
TTL time.Duration `ini:"ITEM_TTL"`
CommitsCount int64
} `ini:"cache.last_commit"`
}{
Cache: Cache{
Enabled: true,
Adapter: "memory",
Interval: 60,
TTL: 16 * time.Hour,
},
LastCommit: struct {
Enabled bool
TTL time.Duration `ini:"ITEM_TTL"`
CommitsCount int64
}{
Enabled: true,
TTL: 8760 * time.Hour,
CommitsCount: 1000,
},
@ -65,30 +60,12 @@ func loadCacheFrom(rootCfg ConfigProvider) {
if CacheService.Conn == "" {
CacheService.Conn = "50000"
}
case "": // disable cache
CacheService.Enabled = false
default:
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")
if !CacheService.Enabled {
CacheService.LastCommit.Enabled = false
}
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

View File

@ -35,6 +35,8 @@ var UI = struct {
OnlyShowRelevantRepos bool
ExploreDefaultSort string `ini:"EXPLORE_PAGING_DEFAULT_SORT"`
AmbiguousUnicodeDetection bool
Notification struct {
MinTimeout time.Duration
TimeoutStep time.Duration
@ -82,6 +84,9 @@ var UI = struct {
Reactions: []string{`+1`, `-1`, `laugh`, `hooray`, `confused`, `heart`, `rocket`, `eyes`},
CustomEmojis: []string{`git`, `gitea`, `codeberg`, `gitlab`, `github`, `gogs`},
CustomEmojisMap: map[string]string{"git": ":git:", "gitea": ":gitea:", "codeberg": ":codeberg:", "gitlab": ":gitlab:", "github": ":github:", "gogs": ":gogs:"},
AmbiguousUnicodeDetection: true,
Notification: struct {
MinTimeout time.Duration
TimeoutStep time.Duration

View File

@ -15,9 +15,8 @@ type CreateUserOption struct {
FullName string `json:"full_name" binding:"MaxSize(100)"`
// required: true
// swagger:strfmt email
Email string `json:"email" binding:"Required;Email;MaxSize(254)"`
// required: true
Password string `json:"password" binding:"Required;MaxSize(255)"`
Email string `json:"email" binding:"Required;Email;MaxSize(254)"`
Password string `json:"password" binding:"MaxSize(255)"`
MustChangePassword *bool `json:"must_change_password"`
SendNotify bool `json:"send_notify"`
Restricted *bool `json:"restricted"`

View File

@ -3,7 +3,7 @@
package util
import "github.com/yuin/goldmark/util"
import "unsafe"
func isSnakeCaseUpper(c byte) bool {
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))
}

View File

@ -3090,7 +3090,6 @@ config.enable_openid_signin = Enable OpenID Sign-In
config.show_registration_button = Show Register Button
config.require_sign_in_view = Require Sign-In to View Pages
config.mail_notify = Enable Email Notifications
config.disable_key_size_check = Disable Minimum Key Size Check
config.enable_captcha = Enable CAPTCHA
config.active_code_lives = Active Code Lives
config.reset_password_code_lives = Recover Account Code Expiry Time
@ -3536,7 +3535,7 @@ runs.commit = Commit
runs.scheduled = Scheduled
runs.pushed_by = pushed by
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.status = Status
runs.actors_no_select = All actors

View File

@ -17,6 +17,7 @@ template=テンプレート
language=言語
notifications=通知
active_stopwatch=進行中のタイムトラッカー
tracked_time_summary=イシューリストのフィルタに基づき集計したトラッキング時間
create_new=作成…
user_profile_and_more=プロフィールと設定…
signed_in_as=サインイン済み
@ -359,6 +360,7 @@ disable_register_prompt=登録は無効になっています。 サイト管理
disable_register_mail=登録でのメール確認は無効になっています。
manual_activation_only=アクティベーションを完了するにはサイト管理者に連絡してください。
remember_me=このデバイスで自動サインイン
remember_me.compromised=ログイントークンはもう有効ではなく、アカウントが侵害されたことを示している可能性があります。 異常なアクティビティがないかアカウントを確認してください。
forgot_password_title=パスワードを忘れた
forgot_password=パスワードをお忘れですか?
sign_up_now=アカウントが必要ですか? 今すぐ登録しましょう。
@ -623,11 +625,11 @@ applications=アプリケーション
orgs=組織の管理
repos=リポジトリ
delete=アカウントを削除
twofa=2要素認証
twofa=2要素認証 (TOTP)
account_link=連携アカウント
organization=組織
uid=UID
webauthn=セキュリティキー
webauthn=2要素認証 (セキュリティキー)
public_profile=公開プロフィール
biography_placeholder=自己紹介してください!(Markdownを使うことができます)
@ -861,22 +863,23 @@ revoke_oauth2_grant=アクセス権の取り消し
revoke_oauth2_grant_description=このサードパーティ アプリケーションのアクセス権を取り消し、アプリケーションがあなたのデータへアクセスすることを防ぎます。 続行しますか?
revoke_oauth2_grant_success=アクセス権を取り消しました。
twofa_desc=2要素認証はアカウントのセキュリティを強化します。
twofa_desc=パスワードの盗難からアカウントを守るために、スマートフォンや他のデバイスを使用して、時間ベースのワンタイムパスワード("TOTP")を受け取ることができます。
twofa_recovery_tip=デバイスを紛失した場合は、一回限りのリカバリキーを使用してアカウントへのアクセスを回復することができます。
twofa_is_enrolled=このアカウントは2要素認証が<strong>有効</strong>になっています。
twofa_not_enrolled=このアカウントは2要素認証が設定されていません。
twofa_disable=2要素認証を無効にする
twofa_scratch_token_regenerate=スクラッチトークンを再生成
twofa_scratch_token_regenerated=あなたのスクラッチトークンは %s になりました。 安全な場所に保管してください。 二度と表示されません。
twofa_scratch_token_regenerate=一回限りのリカバリキーを再生成
twofa_scratch_token_regenerated=あなたの一回限りのリカバリキーは %s になりました。 安全な場所に保管してください。 これは二度と表示されません。
twofa_enroll=2要素認証の開始
twofa_disable_note=2要素認証は必要に応じて無効にできます。
twofa_disable_desc=2要素認証を無効にするとアカウントのセキュリティが低下します。 続行しますか?
regenerate_scratch_token_desc=スクラッチトークンを紛失した場合やサインインで使用済みとなった場合は、ここでリセットできます。
regenerate_scratch_token_desc=リカバリキーを紛失した場合や、すでにサインインに使用済みの場合は、ここでリセットできます。
twofa_disabled=2要素認証を無効にしました。
scan_this_image=この画像を認証アプリケーションで読み取ってください。
or_enter_secret=またはシークレット文字列を入力: %s
then_enter_passcode=次に、アプリケーションに表示されているパスコードを入力します。
passcode_invalid=パスコードが間違っています。 再度お試しください。
twofa_enrolled=あなたのアカウントに2要素認証が設定されました。 スクラッチトークン (%s) は一度しか表示しませんので安全な場所に保存してください!
twofa_enrolled=あなたのアカウントは正常に登録されました。 一回限りのリカバリキー (%s) は安全な場所に保存してください。 これは二度と表示されません。
twofa_failed_get_secret=シークレットが取得できません。
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_delete_key=セキュリティキーの登録解除
webauthn_delete_key_desc=セキュリティキーの登録を解除すると、今後そのセキュリティキーでサインインすることはできなくなります。 続行しますか?
webauthn_key_loss_warning=セキュリティキーを紛失すると、アカウントへのアクセスを失います。
webauthn_alternative_tip=もうひとつ別の認証方法も設定しておくと良いでしょう。
manage_account_links=連携アカウントの管理
manage_account_links_desc=これらの外部アカウントがGiteaアカウントと連携されています。
@ -920,6 +925,7 @@ visibility.private=プライベート
visibility.private_tooltip=あなたが参加した組織のメンバーのみに表示されます
[repo]
new_repo_helper=リポジトリには、プロジェクトのすべてのファイルとリビジョン履歴が入ります。 すでにほかの場所でホストしていますか? <a href="%s">リポジトリを移行</a> もどうぞ。
owner=オーナー
owner_helper=リポジトリ数の上限により、一部の組織はドロップダウンに表示されない場合があります。
repo_name=リポジトリ名
@ -1782,6 +1788,8 @@ pulls.status_checks_failure=失敗したステータスチェックがありま
pulls.status_checks_error=ステータスチェックによりエラーが出ています
pulls.status_checks_requested=必須
pulls.status_checks_details=詳細
pulls.status_checks_hide_all=すべてのチェックを隠す
pulls.status_checks_show_all=すべてのチェックを表示
pulls.update_branch=マージでブランチを更新
pulls.update_branch_rebase=リベースでブランチを更新
pulls.update_branch_success=ブランチの更新が成功しました
@ -1790,6 +1798,11 @@ pulls.outdated_with_base_branch=このブランチはベースブランチに対
pulls.close=プルリクエストをクローズ
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.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_hint=マージメッセージのクリアは、コミットメッセージの除去だけを行います。 生成されたGitトレーラー("Co-Authored-By …" 等)はそのまま残ります。
@ -2301,6 +2314,7 @@ settings.dismiss_stale_approvals_desc=プルリクエストの内容を変える
settings.require_signed_commits=コミット署名必須
settings.require_signed_commits_desc=署名されていない場合、または署名が検証できなかった場合は、このブランチへのプッシュを拒否します。
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_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>
@ -2846,6 +2860,7 @@ emails.updated=メール設定を更新しました
emails.not_updated=メール設定の更新に失敗しました: %v
emails.duplicate_active=メールアドレスは別のユーザーが既に使用中です。
emails.change_email_header=メール設定の更新
emails.change_email_text=このメールアドレスで更新してもよろしいですか?
orgs.org_manage_panel=組織の管理
orgs.name=名称
@ -2870,6 +2885,7 @@ packages.package_manage_panel=パッケージ管理
packages.total_size=合計サイズ: %s
packages.unreferenced_size=非参照サイズ: %s
packages.cleanup=期限切れデータを掃除する
packages.cleanup.success=期限切れのデータを正常にクリーンアップしました
packages.owner=オーナー
packages.creator=作成者
packages.name=名前
@ -3441,7 +3457,7 @@ owner.settings.chef.keypair.description=Chefレジストリの認証にはキー
[secrets]
secrets=シークレット
description=シークレットは特定のActionsに渡されます。 それ以外で読み出されることはありません。
none=まだシークレットはありません。
none=シークレットはまだありません。
creation=シークレットを追加
creation.name_placeholder=大文字小文字の区別なし、英数字とアンダースコアのみ、GITEA_ や GITHUB_ で始まるものは不可
creation.value_placeholder=内容を入力してください。前後の空白は除去されます。
@ -3516,6 +3532,7 @@ runs.actors_no_select=すべてのアクター
runs.status_no_select=すべてのステータス
runs.no_results=一致する結果はありません。
runs.no_runs=ワークフローはまだ実行されていません。
runs.empty_commit_message=(空のコミットメッセージ)
workflow.disable=ワークフローを無効にする
workflow.disable_success=ワークフロー '%s' が無効になりました。

View File

@ -93,18 +93,28 @@ func CreateUser(ctx *context.APIContext) {
if ctx.Written() {
return
}
if !password.IsComplexEnough(form.Password) {
err := errors.New("PasswordComplexity")
ctx.Error(http.StatusBadRequest, "PasswordComplexity", err)
return
}
pwned, err := password.IsPwned(ctx, form.Password)
if pwned {
if err != nil {
log.Error(err.Error())
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) {
err := errors.New("PasswordComplexity")
ctx.Error(http.StatusBadRequest, "PasswordComplexity", err)
return
}
pwned, err := password.IsPwned(ctx, form.Password)
if pwned {
if err != nil {
log.Error(err.Error())
}
ctx.Error(http.StatusBadRequest, "PasswordPwned", errors.New("PasswordPwned"))
return
}
ctx.Error(http.StatusBadRequest, "PasswordPwned", errors.New("PasswordPwned"))
return
}
overwriteDefault := &user_model.CreateUserOverwriteOptions{

View File

@ -29,10 +29,9 @@ func NodeInfo(ctx *context.APIContext) {
nodeInfoUsage := structs.NodeInfoUsage{}
if setting.Federation.ShareUserStatistics {
cached := false
if setting.CacheService.Enabled {
nodeInfoUsage, cached = ctx.Cache.Get(cacheKeyNodeInfoUsage).(structs.NodeInfoUsage)
}
var cached bool
nodeInfoUsage, cached = ctx.Cache.Get(cacheKeyNodeInfoUsage).(structs.NodeInfoUsage)
if !cached {
usersTotal := int(user_model.CountUsers(ctx, nil))
now := time.Now()
@ -53,11 +52,10 @@ func NodeInfo(ctx *context.APIContext) {
LocalPosts: int(allIssues),
LocalComments: int(allComments),
}
if setting.CacheService.Enabled {
if err := ctx.Cache.Put(cacheKeyNodeInfoUsage, nodeInfoUsage, 180); err != nil {
ctx.InternalServerError(err)
return
}
if err := ctx.Cache.Put(cacheKeyNodeInfoUsage, nodeInfoUsage, 180); err != nil {
ctx.InternalServerError(err)
return
}
}
}

View File

@ -242,18 +242,18 @@ func CreateUserRepo(ctx *context.APIContext, owner *user_model.User, opt api.Cre
}
repo, err := repo_service.CreateRepository(ctx, ctx.Doer, owner, repo_service.CreateRepoOptions{
Name: opt.Name,
Description: opt.Description,
IssueLabels: opt.IssueLabels,
Gitignores: opt.Gitignores,
License: opt.License,
Readme: opt.Readme,
IsPrivate: opt.Private,
AutoInit: opt.AutoInit,
DefaultBranch: opt.DefaultBranch,
TrustModel: repo_model.ToTrustModel(opt.TrustModel),
IsTemplate: opt.Template,
ObjectFormat: git.ObjectFormatFromID(git.Sha1),
Name: opt.Name,
Description: opt.Description,
IssueLabels: opt.IssueLabels,
Gitignores: opt.Gitignores,
License: opt.License,
Readme: opt.Readme,
IsPrivate: opt.Private,
AutoInit: opt.AutoInit,
DefaultBranch: opt.DefaultBranch,
TrustModel: repo_model.ToTrustModel(opt.TrustModel),
IsTemplate: opt.Template,
ObjectFormatName: git.Sha1ObjectFormat.Name(),
})
if err != nil {
if repo_model.IsErrRepoAlreadyExist(err) {

View File

@ -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) {
objectFormat, _ := repo.GitRepo.GetObjectFormat()
if len(commitID) == objectFormat.FullLength() && objectFormat.IsValid(commitID) {
sha, err := objectFormat.NewIDFromString(commitID)
sha, err := git.NewIDFromString(commitID)
if err == 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())
if err != nil {
return objectFormat.Empty(), fmt.Errorf("RepositoryFromContextOrOpen: %w", err)
return objectFormat.EmptyObjectID(), fmt.Errorf("RepositoryFromContextOrOpen: %w", err)
}
defer closer.Close()

View File

@ -118,7 +118,7 @@ func InitWebInstalled(ctx context.Context) {
mustInit(storage.Init)
mailer.NewContext(ctx)
mustInit(cache.NewContext)
mustInit(cache.Init)
mustInit(feed_service.Init)
mustInit(uinotification.Init)
mustInitCtx(ctx, archiver.Init)

View File

@ -147,7 +147,7 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r
gitRepo := ctx.Repo.GitRepo
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)
ctx.JSON(http.StatusForbidden, private.Response{
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:
//
// 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)
ctx.JSON(http.StatusForbidden, private.Response{
UserMsg: fmt.Sprintf("branch %s is protected from deletion", branchName),
@ -186,7 +186,7 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r
isForcePush := false
// 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})
if err != nil {
log.Error("Unable to detect force push between: %s and %s in %-v Error: %v", oldCommitID, newCommitID, repo, err)

View File

@ -30,7 +30,7 @@ func verifyCommits(oldCommitID, newCommitID string, repo *git.Repository, env []
var command *git.Command
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":
// 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
@ -83,8 +83,8 @@ func readAndVerifyCommit(sha string, repo *git.Repository, env []string) error {
_ = stdoutReader.Close()
_ = stdoutWriter.Close()
}()
objectFormat, _ := repo.GetObjectFormat()
commitID := objectFormat.MustIDFromString(sha)
commitID := git.MustIDFromString(sha)
return git.NewCommand(repo.Ctx, "cat-file", "commit").AddDynamicArguments(sha).
Run(&git.RunOpts{

View File

@ -30,9 +30,9 @@ func TestVerifyCommits(t *testing.T) {
verified bool
}{
{"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},
{objectFormat.Empty().String(), "9ce3f779ae33f31fce17fac3c512047b75d7498b", false}, // New branch with unverified commit
{objectFormat.EmptyObjectID().String(), "9ce3f779ae33f31fce17fac3c512047b75d7498b", false}, // New branch with unverified commit
}
for _, tc := range testCases {

View File

@ -622,10 +622,8 @@ func handleUserCreated(ctx *context.Context, u *user_model.User, gothUser *goth.
ctx.Data["ActiveCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale)
ctx.HTML(http.StatusOK, TplActivate)
if setting.CacheService.Enabled {
if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil {
log.Error("Set cache(MailResendLimit) fail: %v", err)
}
if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil {
log.Error("Set cache(MailResendLimit) fail: %v", err)
}
return false
}
@ -645,16 +643,14 @@ func Activate(ctx *context.Context) {
}
// Resend confirmation email.
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
} else {
ctx.Data["ActiveCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale)
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 {
log.Error("Set cache(MailResendLimit) fail: %v", err)
}
if err := ctx.Cache.Put("MailResendLimit_"+ctx.Doer.LowerName, ctx.Doer.LowerName, 180); err != nil {
log.Error("Set cache(MailResendLimit) fail: %v", err)
}
}
} else {
@ -789,7 +785,7 @@ func ActivateEmail(ctx *context.Context) {
if u, err := user_model.GetUserByID(ctx, email.UID); err != nil {
log.Warn("GetUserByID: %d", email.UID)
} else if setting.CacheService.Enabled {
} else {
// Allow user to validate more emails
_ = ctx.Cache.Delete("MailResendLimit_" + u.LowerName)
}

View File

@ -79,7 +79,7 @@ func ForgotPasswdPost(ctx *context.Context) {
return
}
if setting.CacheService.Enabled && ctx.Cache.IsExist("MailResendLimit_"+u.LowerName) {
if ctx.Cache.IsExist("MailResendLimit_" + u.LowerName) {
ctx.Data["ResendLimited"] = true
ctx.HTML(http.StatusOK, tplForgotPassword)
return
@ -87,10 +87,8 @@ func ForgotPasswdPost(ctx *context.Context) {
mailer.SendResetPasswordMail(u)
if setting.CacheService.Enabled {
if err = ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil {
log.Error("Set cache(MailResendLimit) fail: %v", err)
}
if err = ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil {
log.Error("Set cache(MailResendLimit) fail: %v", err)
}
ctx.Data["ResetPwdCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ResetPwdCodeLives, ctx.Locale)

View File

@ -121,10 +121,6 @@ func checkDatabase(ctx context.Context, checks checks) status {
// cache checks gitea cache status
func checkCache(checks checks) status {
if !setting.CacheService.Enabled {
return pass
}
st := componentStatus{}
if err := cache.GetCache().Ping(); err != nil {
st.Status = fail

View File

@ -18,6 +18,7 @@ import (
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/web/repo"
"code.gitea.io/gitea/services/convert"
@ -77,6 +78,7 @@ func List(ctx *context.Context) {
// Get all runner labels
runners, err := db.Find[actions_model.ActionRunner](ctx, actions_model.FindRunnerOptions{
RepoID: ctx.Repo.Repository.ID,
IsOnline: util.OptionalBoolTrue,
WithAvailable: true,
})
if err != nil {
@ -113,7 +115,7 @@ func List(ctx *context.Context) {
continue
}
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
}
}

View File

@ -315,8 +315,7 @@ func renderBlame(ctx *context.Context, blameParts []git.BlamePart, commitNames m
lexerName = lexerNameForLine
}
br.EscapeStatus, line = charset.EscapeControlHTML(line, ctx.Locale)
br.Code = gotemplate.HTML(line)
br.EscapeStatus, br.Code = charset.EscapeControlHTML(line, ctx.Locale)
rows = append(rows, br)
escapeStatus = escapeStatus.Or(br.EscapeStatus)
}

View File

@ -158,7 +158,7 @@ func RestoreBranchPost(ctx *context.Context) {
if err := repo_service.PushUpdate(
&repo_module.PushUpdateOptions{
RefFullName: git.RefNameFromBranch(deletedBranch.Name),
OldCommitID: objectFormat.Empty().String(),
OldCommitID: objectFormat.EmptyObjectID().String(),
NewCommitID: deletedBranch.CommitID,
PusherID: ctx.Doer.ID,
PusherName: ctx.Doer.Name,

View File

@ -317,7 +317,7 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo {
ci.BaseBranch = baseCommit.ID.String()
ctx.Data["BaseBranch"] = ci.BaseBranch
baseIsCommit = true
} else if ci.BaseBranch == objectFormat.Empty().String() {
} else if ci.BaseBranch == objectFormat.EmptyObjectID().String() {
if isSameRepo {
ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ci.HeadBranch))
} else {

View File

@ -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)
return
}

View File

@ -278,18 +278,18 @@ func CreatePost(ctx *context.Context) {
}
} else {
repo, err = repo_service.CreateRepository(ctx, ctx.Doer, ctxUser, repo_service.CreateRepoOptions{
Name: form.RepoName,
Description: form.Description,
Gitignores: form.Gitignores,
IssueLabels: form.IssueLabels,
License: form.License,
Readme: form.Readme,
IsPrivate: form.Private || setting.Repository.ForcePrivate,
DefaultBranch: form.DefaultBranch,
AutoInit: form.AutoInit,
IsTemplate: form.Template,
TrustModel: repo_model.ToTrustModel(form.TrustModel),
ObjectFormat: form.ObjectFormat,
Name: form.RepoName,
Description: form.Description,
Gitignores: form.Gitignores,
IssueLabels: form.IssueLabels,
License: form.License,
Readme: form.Readme,
IsPrivate: form.Private || setting.Repository.ForcePrivate,
DefaultBranch: form.DefaultBranch,
AutoInit: form.AutoInit,
IsTemplate: form.Template,
TrustModel: repo_model.ToTrustModel(form.TrustModel),
ObjectFormatName: form.ObjectFormatName,
})
if err == nil {
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