diff --git a/Dockerfile b/Dockerfile
index 2a6b1dd6b7..b95ba83289 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,5 +1,5 @@
# Build stage
-FROM docker.io/library/golang:1.23-alpine3.20 AS build-env
+FROM docker.io/library/golang:1.23-alpine3.21 AS build-env
ARG GOPROXY
ENV GOPROXY=${GOPROXY:-direct}
@@ -41,7 +41,7 @@ RUN chmod 755 /tmp/local/usr/bin/entrypoint \
/go/src/code.gitea.io/gitea/environment-to-ini
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
-FROM docker.io/library/alpine:3.20
+FROM docker.io/library/alpine:3.21
LABEL maintainer="maintainers@gitea.io"
EXPOSE 22 3000
@@ -78,7 +78,7 @@ ENV GITEA_CUSTOM=/data/gitea
VOLUME ["/data"]
ENTRYPOINT ["/usr/bin/entrypoint"]
-CMD ["/bin/s6-svscan", "/etc/s6"]
+CMD ["/usr/bin/s6-svscan", "/etc/s6"]
COPY --from=build-env /tmp/local /
COPY --from=build-env /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
diff --git a/Dockerfile.rootless b/Dockerfile.rootless
index 26f02205a7..be6f125104 100644
--- a/Dockerfile.rootless
+++ b/Dockerfile.rootless
@@ -1,5 +1,5 @@
# Build stage
-FROM docker.io/library/golang:1.23-alpine3.20 AS build-env
+FROM docker.io/library/golang:1.23-alpine3.21 AS build-env
ARG GOPROXY
ENV GOPROXY=${GOPROXY:-direct}
@@ -39,7 +39,7 @@ RUN chmod 755 /tmp/local/usr/local/bin/docker-entrypoint.sh \
/go/src/code.gitea.io/gitea/environment-to-ini
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
-FROM docker.io/library/alpine:3.20
+FROM docker.io/library/alpine:3.21
LABEL maintainer="maintainers@gitea.io"
EXPOSE 2222 3000
diff --git a/Makefile b/Makefile
index 4889958c3b..32ea823e1e 100644
--- a/Makefile
+++ b/Makefile
@@ -26,17 +26,17 @@ COMMA := ,
XGO_VERSION := go-1.23.x
AIR_PACKAGE ?= github.com/air-verse/air@v1
-EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.7.0
+EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3.0.3
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.7.0
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.62.2
-GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11
-MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.5.1
+GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.12
+MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.6.0
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.31.0
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1
ACTIONLINT_PACKAGE ?= github.com/rhysd/actionlint/cmd/actionlint@v1
-GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.15.3
+GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.17.0
DOCKER_IMAGE ?= gitea/gitea
DOCKER_TAG ?= latest
diff --git a/models/actions/runner_token.go b/models/actions/runner_token.go
index fd6ba7ecad..1eab5efcce 100644
--- a/models/actions/runner_token.go
+++ b/models/actions/runner_token.go
@@ -10,6 +10,7 @@ import (
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
)
@@ -51,7 +52,7 @@ func GetRunnerToken(ctx context.Context, token string) (*ActionRunnerToken, erro
if err != nil {
return nil, err
} else if !has {
- return nil, fmt.Errorf("runner token %q: %w", token, util.ErrNotExist)
+ return nil, fmt.Errorf(`runner token "%s...": %w`, base.TruncateString(token, 3), util.ErrNotExist)
}
return &runnerToken, nil
}
@@ -68,19 +69,15 @@ func UpdateRunnerToken(ctx context.Context, r *ActionRunnerToken, cols ...string
return err
}
-// NewRunnerToken creates a new active runner token and invalidate all old tokens
+// NewRunnerTokenWithValue creates a new active runner token and invalidate all old tokens
// ownerID will be ignored and treated as 0 if repoID is non-zero.
-func NewRunnerToken(ctx context.Context, ownerID, repoID int64) (*ActionRunnerToken, error) {
+func NewRunnerTokenWithValue(ctx context.Context, ownerID, repoID int64, token string) (*ActionRunnerToken, error) {
if ownerID != 0 && repoID != 0 {
// It's trying to create a runner token that belongs to a repository, but OwnerID has been set accidentally.
// Remove OwnerID to avoid confusion; it's not worth returning an error here.
ownerID = 0
}
- token, err := util.CryptoRandomString(40)
- if err != nil {
- return nil, err
- }
runnerToken := &ActionRunnerToken{
OwnerID: ownerID,
RepoID: repoID,
@@ -95,11 +92,19 @@ func NewRunnerToken(ctx context.Context, ownerID, repoID int64) (*ActionRunnerTo
return err
}
- _, err = db.GetEngine(ctx).Insert(runnerToken)
+ _, err := db.GetEngine(ctx).Insert(runnerToken)
return err
})
}
+func NewRunnerToken(ctx context.Context, ownerID, repoID int64) (*ActionRunnerToken, error) {
+ token, err := util.CryptoRandomString(40)
+ if err != nil {
+ return nil, err
+ }
+ return NewRunnerTokenWithValue(ctx, ownerID, repoID, token)
+}
+
// GetLatestRunnerToken returns the latest runner token
func GetLatestRunnerToken(ctx context.Context, ownerID, repoID int64) (*ActionRunnerToken, error) {
if ownerID != 0 && repoID != 0 {
diff --git a/models/auth/source_test.go b/models/auth/source_test.go
index 36e76d5e28..84aede0a6b 100644
--- a/models/auth/source_test.go
+++ b/models/auth/source_test.go
@@ -13,6 +13,8 @@ import (
"code.gitea.io/gitea/modules/json"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ "xorm.io/xorm"
"xorm.io/xorm/schemas"
)
@@ -54,7 +56,8 @@ func TestDumpAuthSource(t *testing.T) {
sb := new(strings.Builder)
- db.DumpTables([]*schemas.Table{authSourceSchema}, sb)
-
+ // TODO: this test is quite hacky, it should use a low-level "select" (without model processors) but not a database dump
+ engine := db.GetEngine(db.DefaultContext).(*xorm.Engine)
+ require.NoError(t, engine.DumpTables([]*schemas.Table{authSourceSchema}, sb))
assert.Contains(t, sb.String(), `"Provider":"ConvertibleSourceName"`)
}
diff --git a/models/db/collation.go b/models/db/collation.go
index a7db9f5442..79ade87380 100644
--- a/models/db/collation.go
+++ b/models/db/collation.go
@@ -140,7 +140,7 @@ func CheckCollations(x *xorm.Engine) (*CheckCollationsResult, error) {
}
func CheckCollationsDefaultEngine() (*CheckCollationsResult, error) {
- return CheckCollations(x)
+ return CheckCollations(xormEngine)
}
func alterDatabaseCollation(x *xorm.Engine, collation string) error {
diff --git a/models/db/context.go b/models/db/context.go
index 171e26b933..51627712b1 100644
--- a/models/db/context.go
+++ b/models/db/context.go
@@ -94,7 +94,7 @@ func GetEngine(ctx context.Context) Engine {
if e := getExistingEngine(ctx); e != nil {
return e
}
- return x.Context(ctx)
+ return xormEngine.Context(ctx)
}
// getExistingEngine gets an existing db Engine/Statement from this context or returns nil
@@ -155,7 +155,7 @@ func TxContext(parentCtx context.Context) (*Context, Committer, error) {
return newContext(parentCtx, sess), &halfCommitter{committer: sess}, nil
}
- sess := x.NewSession()
+ sess := xormEngine.NewSession()
if err := sess.Begin(); err != nil {
_ = sess.Close()
return nil, nil, err
@@ -179,7 +179,7 @@ func WithTx(parentCtx context.Context, f func(ctx context.Context) error) error
}
func txWithNoCheck(parentCtx context.Context, f func(ctx context.Context) error) error {
- sess := x.NewSession()
+ sess := xormEngine.NewSession()
defer sess.Close()
if err := sess.Begin(); err != nil {
return err
@@ -322,7 +322,7 @@ func CountByBean(ctx context.Context, bean any) (int64, error) {
// TableName returns the table name according a bean object
func TableName(bean any) string {
- return x.TableName(bean)
+ return xormEngine.TableName(bean)
}
// InTransaction returns true if the engine is in a transaction otherwise return false
diff --git a/models/db/convert.go b/models/db/convert.go
index 8c124471ab..80b0f7b04b 100644
--- a/models/db/convert.go
+++ b/models/db/convert.go
@@ -16,30 +16,30 @@ import (
// ConvertDatabaseTable converts database and tables from utf8 to utf8mb4 if it's mysql and set ROW_FORMAT=dynamic
func ConvertDatabaseTable() error {
- if x.Dialect().URI().DBType != schemas.MYSQL {
+ if xormEngine.Dialect().URI().DBType != schemas.MYSQL {
return nil
}
- r, err := CheckCollations(x)
+ r, err := CheckCollations(xormEngine)
if err != nil {
return err
}
- _, err = x.Exec(fmt.Sprintf("ALTER DATABASE `%s` CHARACTER SET utf8mb4 COLLATE %s", setting.Database.Name, r.ExpectedCollation))
+ _, err = xormEngine.Exec(fmt.Sprintf("ALTER DATABASE `%s` CHARACTER SET utf8mb4 COLLATE %s", setting.Database.Name, r.ExpectedCollation))
if err != nil {
return err
}
- tables, err := x.DBMetas()
+ tables, err := xormEngine.DBMetas()
if err != nil {
return err
}
for _, table := range tables {
- if _, err := x.Exec(fmt.Sprintf("ALTER TABLE `%s` ROW_FORMAT=dynamic", table.Name)); err != nil {
+ if _, err := xormEngine.Exec(fmt.Sprintf("ALTER TABLE `%s` ROW_FORMAT=dynamic", table.Name)); err != nil {
return err
}
- if _, err := x.Exec(fmt.Sprintf("ALTER TABLE `%s` CONVERT TO CHARACTER SET utf8mb4 COLLATE %s", table.Name, r.ExpectedCollation)); err != nil {
+ if _, err := xormEngine.Exec(fmt.Sprintf("ALTER TABLE `%s` CONVERT TO CHARACTER SET utf8mb4 COLLATE %s", table.Name, r.ExpectedCollation)); err != nil {
return err
}
}
@@ -49,11 +49,11 @@ func ConvertDatabaseTable() error {
// ConvertVarcharToNVarchar converts database and tables from varchar to nvarchar if it's mssql
func ConvertVarcharToNVarchar() error {
- if x.Dialect().URI().DBType != schemas.MSSQL {
+ if xormEngine.Dialect().URI().DBType != schemas.MSSQL {
return nil
}
- sess := x.NewSession()
+ sess := xormEngine.NewSession()
defer sess.Close()
res, err := sess.QuerySliceString(`SELECT 'ALTER TABLE ' + OBJECT_NAME(SC.object_id) + ' MODIFY SC.name NVARCHAR(' + CONVERT(VARCHAR(5),SC.max_length) + ')'
FROM SYS.columns SC
diff --git a/models/db/engine.go b/models/db/engine.go
index b17188945a..91015f7038 100755
--- a/models/db/engine.go
+++ b/models/db/engine.go
@@ -8,17 +8,10 @@ import (
"context"
"database/sql"
"fmt"
- "io"
"reflect"
"strings"
- "time"
-
- "code.gitea.io/gitea/modules/log"
- "code.gitea.io/gitea/modules/setting"
"xorm.io/xorm"
- "xorm.io/xorm/contexts"
- "xorm.io/xorm/names"
"xorm.io/xorm/schemas"
_ "github.com/go-sql-driver/mysql" // Needed for the MySQL driver
@@ -27,9 +20,9 @@ import (
)
var (
- x *xorm.Engine
- tables []any
- initFuncs []func() error
+ xormEngine *xorm.Engine
+ registeredModels []any
+ registeredInitFuncs []func() error
)
// Engine represents a xorm engine or session.
@@ -70,167 +63,38 @@ type Engine interface {
// TableInfo returns table's information via an object
func TableInfo(v any) (*schemas.Table, error) {
- return x.TableInfo(v)
+ return xormEngine.TableInfo(v)
}
-// DumpTables dump tables information
-func DumpTables(tables []*schemas.Table, w io.Writer, tp ...schemas.DBType) error {
- return x.DumpTables(tables, w, tp...)
-}
-
-// RegisterModel registers model, if initfunc provided, it will be invoked after data model sync
+// RegisterModel registers model, if initFuncs provided, it will be invoked after data model sync
func RegisterModel(bean any, initFunc ...func() error) {
- tables = append(tables, bean)
- if len(initFuncs) > 0 && initFunc[0] != nil {
- initFuncs = append(initFuncs, initFunc[0])
+ registeredModels = append(registeredModels, bean)
+ if len(registeredInitFuncs) > 0 && initFunc[0] != nil {
+ registeredInitFuncs = append(registeredInitFuncs, initFunc[0])
}
}
-func init() {
- gonicNames := []string{"SSL", "UID"}
- for _, name := range gonicNames {
- names.LintGonicMapper[name] = true
- }
-}
-
-// newXORMEngine returns a new XORM engine from the configuration
-func newXORMEngine() (*xorm.Engine, error) {
- connStr, err := setting.DBConnStr()
- if err != nil {
- return nil, err
- }
-
- var engine *xorm.Engine
-
- if setting.Database.Type.IsPostgreSQL() && len(setting.Database.Schema) > 0 {
- // OK whilst we sort out our schema issues - create a schema aware postgres
- registerPostgresSchemaDriver()
- engine, err = xorm.NewEngine("postgresschema", connStr)
- } else {
- engine, err = xorm.NewEngine(setting.Database.Type.String(), connStr)
- }
-
- if err != nil {
- return nil, err
- }
- if setting.Database.Type == "mysql" {
- engine.Dialect().SetParams(map[string]string{"rowFormat": "DYNAMIC"})
- } else if setting.Database.Type == "mssql" {
- engine.Dialect().SetParams(map[string]string{"DEFAULT_VARCHAR": "nvarchar"})
- }
- engine.SetSchema(setting.Database.Schema)
- return engine, nil
-}
-
// SyncAllTables sync the schemas of all tables, is required by unit test code
func SyncAllTables() error {
- _, err := x.StoreEngine("InnoDB").SyncWithOptions(xorm.SyncOptions{
+ _, err := xormEngine.StoreEngine("InnoDB").SyncWithOptions(xorm.SyncOptions{
WarnIfDatabaseColumnMissed: true,
- }, tables...)
+ }, registeredModels...)
return err
}
-// InitEngine initializes the xorm.Engine and sets it as db.DefaultContext
-func InitEngine(ctx context.Context) error {
- xormEngine, err := newXORMEngine()
- if err != nil {
- if strings.Contains(err.Error(), "SQLite3 support") {
- return fmt.Errorf(`sqlite3 requires: -tags sqlite,sqlite_unlock_notify%s%w`, "\n", err)
- }
- return fmt.Errorf("failed to connect to database: %w", err)
- }
-
- xormEngine.SetMapper(names.GonicMapper{})
- // WARNING: for serv command, MUST remove the output to os.stdout,
- // so use log file to instead print to stdout.
- xormEngine.SetLogger(NewXORMLogger(setting.Database.LogSQL))
- xormEngine.ShowSQL(setting.Database.LogSQL)
- xormEngine.SetMaxOpenConns(setting.Database.MaxOpenConns)
- xormEngine.SetMaxIdleConns(setting.Database.MaxIdleConns)
- xormEngine.SetConnMaxLifetime(setting.Database.ConnMaxLifetime)
- xormEngine.SetDefaultContext(ctx)
-
- if setting.Database.SlowQueryThreshold > 0 {
- xormEngine.AddHook(&SlowQueryHook{
- Threshold: setting.Database.SlowQueryThreshold,
- Logger: log.GetLogger("xorm"),
- })
- }
-
- SetDefaultEngine(ctx, xormEngine)
- return nil
-}
-
-// SetDefaultEngine sets the default engine for db
-func SetDefaultEngine(ctx context.Context, eng *xorm.Engine) {
- x = eng
- DefaultContext = &Context{Context: ctx, engine: x}
-}
-
-// UnsetDefaultEngine closes and unsets the default engine
-// We hope the SetDefaultEngine and UnsetDefaultEngine can be paired, but it's impossible now,
-// there are many calls to InitEngine -> SetDefaultEngine directly to overwrite the `x` and DefaultContext without close
-// Global database engine related functions are all racy and there is no graceful close right now.
-func UnsetDefaultEngine() {
- if x != nil {
- _ = x.Close()
- x = nil
- }
- DefaultContext = nil
-}
-
-// InitEngineWithMigration initializes a new xorm.Engine and sets it as the db.DefaultContext
-// This function must never call .Sync() if the provided migration function fails.
-// When called from the "doctor" command, the migration function is a version check
-// that prevents the doctor from fixing anything in the database if the migration level
-// is different from the expected value.
-func InitEngineWithMigration(ctx context.Context, migrateFunc func(*xorm.Engine) error) (err error) {
- if err = InitEngine(ctx); err != nil {
- return err
- }
-
- if err = x.Ping(); err != nil {
- return err
- }
-
- preprocessDatabaseCollation(x)
-
- // We have to run migrateFunc here in case the user is re-running installation on a previously created DB.
- // If we do not then table schemas will be changed and there will be conflicts when the migrations run properly.
- //
- // Installation should only be being re-run if users want to recover an old database.
- // However, we should think carefully about should we support re-install on an installed instance,
- // as there may be other problems due to secret reinitialization.
- if err = migrateFunc(x); err != nil {
- return fmt.Errorf("migrate: %w", err)
- }
-
- if err = SyncAllTables(); err != nil {
- return fmt.Errorf("sync database struct error: %w", err)
- }
-
- for _, initFunc := range initFuncs {
- if err := initFunc(); err != nil {
- return fmt.Errorf("initFunc failed: %w", err)
- }
- }
-
- return nil
-}
-
// NamesToBean return a list of beans or an error
func NamesToBean(names ...string) ([]any, error) {
beans := []any{}
if len(names) == 0 {
- beans = append(beans, tables...)
+ beans = append(beans, registeredModels...)
return beans, nil
}
// Need to map provided names to beans...
beanMap := make(map[string]any)
- for _, bean := range tables {
+ for _, bean := range registeredModels {
beanMap[strings.ToLower(reflect.Indirect(reflect.ValueOf(bean)).Type().Name())] = bean
- beanMap[strings.ToLower(x.TableName(bean))] = bean
- beanMap[strings.ToLower(x.TableName(bean, true))] = bean
+ beanMap[strings.ToLower(xormEngine.TableName(bean))] = bean
+ beanMap[strings.ToLower(xormEngine.TableName(bean, true))] = bean
}
gotBean := make(map[any]bool)
@@ -247,36 +111,9 @@ func NamesToBean(names ...string) ([]any, error) {
return beans, nil
}
-// DumpDatabase dumps all data from database according the special database SQL syntax to file system.
-func DumpDatabase(filePath, dbType string) error {
- var tbs []*schemas.Table
- for _, t := range tables {
- t, err := x.TableInfo(t)
- if err != nil {
- return err
- }
- tbs = append(tbs, t)
- }
-
- type Version struct {
- ID int64 `xorm:"pk autoincr"`
- Version int64
- }
- t, err := x.TableInfo(&Version{})
- if err != nil {
- return err
- }
- tbs = append(tbs, t)
-
- if len(dbType) > 0 {
- return x.DumpTablesToFile(tbs, filePath, schemas.DBType(dbType))
- }
- return x.DumpTablesToFile(tbs, filePath)
-}
-
// MaxBatchInsertSize returns the table's max batch insert size
func MaxBatchInsertSize(bean any) int {
- t, err := x.TableInfo(bean)
+ t, err := xormEngine.TableInfo(bean)
if err != nil {
return 50
}
@@ -285,18 +122,18 @@ func MaxBatchInsertSize(bean any) int {
// IsTableNotEmpty returns true if table has at least one record
func IsTableNotEmpty(beanOrTableName any) (bool, error) {
- return x.Table(beanOrTableName).Exist()
+ return xormEngine.Table(beanOrTableName).Exist()
}
// DeleteAllRecords will delete all the records of this table
func DeleteAllRecords(tableName string) error {
- _, err := x.Exec(fmt.Sprintf("DELETE FROM %s", tableName))
+ _, err := xormEngine.Exec(fmt.Sprintf("DELETE FROM %s", tableName))
return err
}
// GetMaxID will return max id of the table
func GetMaxID(beanOrTableName any) (maxID int64, err error) {
- _, err = x.Select("MAX(id)").Table(beanOrTableName).Get(&maxID)
+ _, err = xormEngine.Select("MAX(id)").Table(beanOrTableName).Get(&maxID)
return maxID, err
}
@@ -308,24 +145,3 @@ func SetLogSQL(ctx context.Context, on bool) {
sess.Engine().ShowSQL(on)
}
}
-
-type SlowQueryHook struct {
- Threshold time.Duration
- Logger log.Logger
-}
-
-var _ contexts.Hook = &SlowQueryHook{}
-
-func (SlowQueryHook) BeforeProcess(c *contexts.ContextHook) (context.Context, error) {
- return c.Ctx, nil
-}
-
-func (h *SlowQueryHook) AfterProcess(c *contexts.ContextHook) error {
- if c.ExecuteTime >= h.Threshold {
- // 8 is the amount of skips passed to runtime.Caller, so that in the log the correct function
- // is being displayed (the function that ultimately wants to execute the query in the code)
- // instead of the function of the slow query hook being called.
- h.Logger.Log(8, log.WARN, "[Slow SQL Query] %s %v - %v", c.SQL, c.Args, c.ExecuteTime)
- }
- return nil
-}
diff --git a/models/db/engine_dump.go b/models/db/engine_dump.go
new file mode 100644
index 0000000000..63f2d4e093
--- /dev/null
+++ b/models/db/engine_dump.go
@@ -0,0 +1,33 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package db
+
+import "xorm.io/xorm/schemas"
+
+// DumpDatabase dumps all data from database according the special database SQL syntax to file system.
+func DumpDatabase(filePath, dbType string) error {
+ var tbs []*schemas.Table
+ for _, t := range registeredModels {
+ t, err := xormEngine.TableInfo(t)
+ if err != nil {
+ return err
+ }
+ tbs = append(tbs, t)
+ }
+
+ type Version struct {
+ ID int64 `xorm:"pk autoincr"`
+ Version int64
+ }
+ t, err := xormEngine.TableInfo(&Version{})
+ if err != nil {
+ return err
+ }
+ tbs = append(tbs, t)
+
+ if dbType != "" {
+ return xormEngine.DumpTablesToFile(tbs, filePath, schemas.DBType(dbType))
+ }
+ return xormEngine.DumpTablesToFile(tbs, filePath)
+}
diff --git a/models/db/engine_hook.go b/models/db/engine_hook.go
new file mode 100644
index 0000000000..b4c543c3dd
--- /dev/null
+++ b/models/db/engine_hook.go
@@ -0,0 +1,34 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package db
+
+import (
+ "context"
+ "time"
+
+ "code.gitea.io/gitea/modules/log"
+
+ "xorm.io/xorm/contexts"
+)
+
+type SlowQueryHook struct {
+ Threshold time.Duration
+ Logger log.Logger
+}
+
+var _ contexts.Hook = (*SlowQueryHook)(nil)
+
+func (*SlowQueryHook) BeforeProcess(c *contexts.ContextHook) (context.Context, error) {
+ return c.Ctx, nil
+}
+
+func (h *SlowQueryHook) AfterProcess(c *contexts.ContextHook) error {
+ if c.ExecuteTime >= h.Threshold {
+ // 8 is the amount of skips passed to runtime.Caller, so that in the log the correct function
+ // is being displayed (the function that ultimately wants to execute the query in the code)
+ // instead of the function of the slow query hook being called.
+ h.Logger.Log(8, log.WARN, "[Slow SQL Query] %s %v - %v", c.SQL, c.Args, c.ExecuteTime)
+ }
+ return nil
+}
diff --git a/models/db/engine_init.go b/models/db/engine_init.go
new file mode 100644
index 0000000000..da85018957
--- /dev/null
+++ b/models/db/engine_init.go
@@ -0,0 +1,140 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package db
+
+import (
+ "context"
+ "fmt"
+ "strings"
+
+ "code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/setting"
+
+ "xorm.io/xorm"
+ "xorm.io/xorm/names"
+)
+
+func init() {
+ gonicNames := []string{"SSL", "UID"}
+ for _, name := range gonicNames {
+ names.LintGonicMapper[name] = true
+ }
+}
+
+// newXORMEngine returns a new XORM engine from the configuration
+func newXORMEngine() (*xorm.Engine, error) {
+ connStr, err := setting.DBConnStr()
+ if err != nil {
+ return nil, err
+ }
+
+ var engine *xorm.Engine
+
+ if setting.Database.Type.IsPostgreSQL() && len(setting.Database.Schema) > 0 {
+ // OK whilst we sort out our schema issues - create a schema aware postgres
+ registerPostgresSchemaDriver()
+ engine, err = xorm.NewEngine("postgresschema", connStr)
+ } else {
+ engine, err = xorm.NewEngine(setting.Database.Type.String(), connStr)
+ }
+
+ if err != nil {
+ return nil, err
+ }
+ if setting.Database.Type == "mysql" {
+ engine.Dialect().SetParams(map[string]string{"rowFormat": "DYNAMIC"})
+ } else if setting.Database.Type == "mssql" {
+ engine.Dialect().SetParams(map[string]string{"DEFAULT_VARCHAR": "nvarchar"})
+ }
+ engine.SetSchema(setting.Database.Schema)
+ return engine, nil
+}
+
+// InitEngine initializes the xorm.Engine and sets it as db.DefaultContext
+func InitEngine(ctx context.Context) error {
+ xe, err := newXORMEngine()
+ if err != nil {
+ if strings.Contains(err.Error(), "SQLite3 support") {
+ return fmt.Errorf(`sqlite3 requires: -tags sqlite,sqlite_unlock_notify%s%w`, "\n", err)
+ }
+ return fmt.Errorf("failed to connect to database: %w", err)
+ }
+
+ xe.SetMapper(names.GonicMapper{})
+ // WARNING: for serv command, MUST remove the output to os.stdout,
+ // so use log file to instead print to stdout.
+ xe.SetLogger(NewXORMLogger(setting.Database.LogSQL))
+ xe.ShowSQL(setting.Database.LogSQL)
+ xe.SetMaxOpenConns(setting.Database.MaxOpenConns)
+ xe.SetMaxIdleConns(setting.Database.MaxIdleConns)
+ xe.SetConnMaxLifetime(setting.Database.ConnMaxLifetime)
+ xe.SetDefaultContext(ctx)
+
+ if setting.Database.SlowQueryThreshold > 0 {
+ xe.AddHook(&SlowQueryHook{
+ Threshold: setting.Database.SlowQueryThreshold,
+ Logger: log.GetLogger("xorm"),
+ })
+ }
+
+ SetDefaultEngine(ctx, xe)
+ return nil
+}
+
+// SetDefaultEngine sets the default engine for db
+func SetDefaultEngine(ctx context.Context, eng *xorm.Engine) {
+ xormEngine = eng
+ DefaultContext = &Context{Context: ctx, engine: xormEngine}
+}
+
+// UnsetDefaultEngine closes and unsets the default engine
+// We hope the SetDefaultEngine and UnsetDefaultEngine can be paired, but it's impossible now,
+// there are many calls to InitEngine -> SetDefaultEngine directly to overwrite the `xormEngine` and DefaultContext without close
+// Global database engine related functions are all racy and there is no graceful close right now.
+func UnsetDefaultEngine() {
+ if xormEngine != nil {
+ _ = xormEngine.Close()
+ xormEngine = nil
+ }
+ DefaultContext = nil
+}
+
+// InitEngineWithMigration initializes a new xorm.Engine and sets it as the db.DefaultContext
+// This function must never call .Sync() if the provided migration function fails.
+// When called from the "doctor" command, the migration function is a version check
+// that prevents the doctor from fixing anything in the database if the migration level
+// is different from the expected value.
+func InitEngineWithMigration(ctx context.Context, migrateFunc func(*xorm.Engine) error) (err error) {
+ if err = InitEngine(ctx); err != nil {
+ return err
+ }
+
+ if err = xormEngine.Ping(); err != nil {
+ return err
+ }
+
+ preprocessDatabaseCollation(xormEngine)
+
+ // We have to run migrateFunc here in case the user is re-running installation on a previously created DB.
+ // If we do not then table schemas will be changed and there will be conflicts when the migrations run properly.
+ //
+ // Installation should only be being re-run if users want to recover an old database.
+ // However, we should think carefully about should we support re-install on an installed instance,
+ // as there may be other problems due to secret reinitialization.
+ if err = migrateFunc(xormEngine); err != nil {
+ return fmt.Errorf("migrate: %w", err)
+ }
+
+ if err = SyncAllTables(); err != nil {
+ return fmt.Errorf("sync database struct error: %w", err)
+ }
+
+ for _, initFunc := range registeredInitFuncs {
+ if err := initFunc(); err != nil {
+ return fmt.Errorf("initFunc failed: %w", err)
+ }
+ }
+
+ return nil
+}
diff --git a/models/db/name.go b/models/db/name.go
index 51be33a8bc..55c9dffb6a 100644
--- a/models/db/name.go
+++ b/models/db/name.go
@@ -16,7 +16,7 @@ var (
// ErrNameEmpty name is empty error
ErrNameEmpty = util.SilentWrap{Message: "name is empty", Err: util.ErrInvalidArgument}
- // AlphaDashDotPattern characters prohibited in a user name (anything except A-Za-z0-9_.-)
+ // AlphaDashDotPattern characters prohibited in a username (anything except A-Za-z0-9_.-)
AlphaDashDotPattern = regexp.MustCompile(`[^\w-\.]`)
)
diff --git a/models/db/sequence.go b/models/db/sequence.go
index f49ad935de..9adc5113ac 100644
--- a/models/db/sequence.go
+++ b/models/db/sequence.go
@@ -17,11 +17,11 @@ func CountBadSequences(_ context.Context) (int64, error) {
return 0, nil
}
- sess := x.NewSession()
+ sess := xormEngine.NewSession()
defer sess.Close()
var sequences []string
- schema := x.Dialect().URI().Schema
+ schema := xormEngine.Dialect().URI().Schema
sess.Engine().SetSchema("")
if err := sess.Table("information_schema.sequences").Cols("sequence_name").Where("sequence_name LIKE 'tmp_recreate__%_id_seq%' AND sequence_catalog = ?", setting.Database.Name).Find(&sequences); err != nil {
@@ -38,7 +38,7 @@ func FixBadSequences(_ context.Context) error {
return nil
}
- sess := x.NewSession()
+ sess := xormEngine.NewSession()
defer sess.Close()
if err := sess.Begin(); err != nil {
return err
diff --git a/models/error.go b/models/error.go
deleted file mode 100644
index 865d5a442f..0000000000
--- a/models/error.go
+++ /dev/null
@@ -1,510 +0,0 @@
-// Copyright 2015 The Gogs Authors. All rights reserved.
-// Copyright 2019 The Gitea Authors. All rights reserved.
-// SPDX-License-Identifier: MIT
-
-package models
-
-import (
- "fmt"
-
- repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/git"
- "code.gitea.io/gitea/modules/util"
-)
-
-// ErrUserOwnRepos represents a "UserOwnRepos" kind of error.
-type ErrUserOwnRepos struct {
- UID int64
-}
-
-// IsErrUserOwnRepos checks if an error is a ErrUserOwnRepos.
-func IsErrUserOwnRepos(err error) bool {
- _, ok := err.(ErrUserOwnRepos)
- return ok
-}
-
-func (err ErrUserOwnRepos) Error() string {
- return fmt.Sprintf("user still has ownership of repositories [uid: %d]", err.UID)
-}
-
-// ErrUserHasOrgs represents a "UserHasOrgs" kind of error.
-type ErrUserHasOrgs struct {
- UID int64
-}
-
-// IsErrUserHasOrgs checks if an error is a ErrUserHasOrgs.
-func IsErrUserHasOrgs(err error) bool {
- _, ok := err.(ErrUserHasOrgs)
- return ok
-}
-
-func (err ErrUserHasOrgs) Error() string {
- return fmt.Sprintf("user still has membership of organizations [uid: %d]", err.UID)
-}
-
-// ErrUserOwnPackages notifies that the user (still) owns the packages.
-type ErrUserOwnPackages struct {
- UID int64
-}
-
-// IsErrUserOwnPackages checks if an error is an ErrUserOwnPackages.
-func IsErrUserOwnPackages(err error) bool {
- _, ok := err.(ErrUserOwnPackages)
- return ok
-}
-
-func (err ErrUserOwnPackages) Error() string {
- return fmt.Sprintf("user still has ownership of packages [uid: %d]", err.UID)
-}
-
-// ErrDeleteLastAdminUser represents a "DeleteLastAdminUser" kind of error.
-type ErrDeleteLastAdminUser struct {
- UID int64
-}
-
-// IsErrDeleteLastAdminUser checks if an error is a ErrDeleteLastAdminUser.
-func IsErrDeleteLastAdminUser(err error) bool {
- _, ok := err.(ErrDeleteLastAdminUser)
- return ok
-}
-
-func (err ErrDeleteLastAdminUser) Error() string {
- return fmt.Sprintf("can not delete the last admin user [uid: %d]", err.UID)
-}
-
-// ErrInvalidCloneAddr represents a "InvalidCloneAddr" kind of error.
-type ErrInvalidCloneAddr struct {
- Host string
- IsURLError bool
- IsInvalidPath bool
- IsProtocolInvalid bool
- IsPermissionDenied bool
- LocalPath bool
-}
-
-// IsErrInvalidCloneAddr checks if an error is a ErrInvalidCloneAddr.
-func IsErrInvalidCloneAddr(err error) bool {
- _, ok := err.(*ErrInvalidCloneAddr)
- return ok
-}
-
-func (err *ErrInvalidCloneAddr) Error() string {
- if err.IsInvalidPath {
- return fmt.Sprintf("migration/cloning from '%s' is not allowed: the provided path is invalid", err.Host)
- }
- if err.IsProtocolInvalid {
- return fmt.Sprintf("migration/cloning from '%s' is not allowed: the provided url protocol is not allowed", err.Host)
- }
- if err.IsPermissionDenied {
- return fmt.Sprintf("migration/cloning from '%s' is not allowed.", err.Host)
- }
- if err.IsURLError {
- return fmt.Sprintf("migration/cloning from '%s' is not allowed: the provided url is invalid", err.Host)
- }
-
- return fmt.Sprintf("migration/cloning from '%s' is not allowed", err.Host)
-}
-
-func (err *ErrInvalidCloneAddr) Unwrap() error {
- return util.ErrInvalidArgument
-}
-
-// ErrUpdateTaskNotExist represents a "UpdateTaskNotExist" kind of error.
-type ErrUpdateTaskNotExist struct {
- UUID string
-}
-
-// IsErrUpdateTaskNotExist checks if an error is a ErrUpdateTaskNotExist.
-func IsErrUpdateTaskNotExist(err error) bool {
- _, ok := err.(ErrUpdateTaskNotExist)
- return ok
-}
-
-func (err ErrUpdateTaskNotExist) Error() string {
- return fmt.Sprintf("update task does not exist [uuid: %s]", err.UUID)
-}
-
-func (err ErrUpdateTaskNotExist) Unwrap() error {
- return util.ErrNotExist
-}
-
-// ErrInvalidTagName represents a "InvalidTagName" kind of error.
-type ErrInvalidTagName struct {
- TagName string
-}
-
-// IsErrInvalidTagName checks if an error is a ErrInvalidTagName.
-func IsErrInvalidTagName(err error) bool {
- _, ok := err.(ErrInvalidTagName)
- return ok
-}
-
-func (err ErrInvalidTagName) Error() string {
- return fmt.Sprintf("release tag name is not valid [tag_name: %s]", err.TagName)
-}
-
-func (err ErrInvalidTagName) Unwrap() error {
- return util.ErrInvalidArgument
-}
-
-// ErrProtectedTagName represents a "ProtectedTagName" kind of error.
-type ErrProtectedTagName struct {
- TagName string
-}
-
-// IsErrProtectedTagName checks if an error is a ErrProtectedTagName.
-func IsErrProtectedTagName(err error) bool {
- _, ok := err.(ErrProtectedTagName)
- return ok
-}
-
-func (err ErrProtectedTagName) Error() string {
- return fmt.Sprintf("release tag name is protected [tag_name: %s]", err.TagName)
-}
-
-func (err ErrProtectedTagName) Unwrap() error {
- return util.ErrPermissionDenied
-}
-
-// ErrRepoFileAlreadyExists represents a "RepoFileAlreadyExist" kind of error.
-type ErrRepoFileAlreadyExists struct {
- Path string
-}
-
-// IsErrRepoFileAlreadyExists checks if an error is a ErrRepoFileAlreadyExists.
-func IsErrRepoFileAlreadyExists(err error) bool {
- _, ok := err.(ErrRepoFileAlreadyExists)
- return ok
-}
-
-func (err ErrRepoFileAlreadyExists) Error() string {
- return fmt.Sprintf("repository file already exists [path: %s]", err.Path)
-}
-
-func (err ErrRepoFileAlreadyExists) Unwrap() error {
- return util.ErrAlreadyExist
-}
-
-// ErrRepoFileDoesNotExist represents a "RepoFileDoesNotExist" kind of error.
-type ErrRepoFileDoesNotExist struct {
- Path string
- Name string
-}
-
-// IsErrRepoFileDoesNotExist checks if an error is a ErrRepoDoesNotExist.
-func IsErrRepoFileDoesNotExist(err error) bool {
- _, ok := err.(ErrRepoFileDoesNotExist)
- return ok
-}
-
-func (err ErrRepoFileDoesNotExist) Error() string {
- return fmt.Sprintf("repository file does not exist [path: %s]", err.Path)
-}
-
-func (err ErrRepoFileDoesNotExist) Unwrap() error {
- return util.ErrNotExist
-}
-
-// ErrFilenameInvalid represents a "FilenameInvalid" kind of error.
-type ErrFilenameInvalid struct {
- Path string
-}
-
-// IsErrFilenameInvalid checks if an error is an ErrFilenameInvalid.
-func IsErrFilenameInvalid(err error) bool {
- _, ok := err.(ErrFilenameInvalid)
- return ok
-}
-
-func (err ErrFilenameInvalid) Error() string {
- return fmt.Sprintf("path contains a malformed path component [path: %s]", err.Path)
-}
-
-func (err ErrFilenameInvalid) Unwrap() error {
- return util.ErrInvalidArgument
-}
-
-// ErrUserCannotCommit represents "UserCannotCommit" kind of error.
-type ErrUserCannotCommit struct {
- UserName string
-}
-
-// IsErrUserCannotCommit checks if an error is an ErrUserCannotCommit.
-func IsErrUserCannotCommit(err error) bool {
- _, ok := err.(ErrUserCannotCommit)
- return ok
-}
-
-func (err ErrUserCannotCommit) Error() string {
- return fmt.Sprintf("user cannot commit to repo [user: %s]", err.UserName)
-}
-
-func (err ErrUserCannotCommit) Unwrap() error {
- return util.ErrPermissionDenied
-}
-
-// ErrFilePathInvalid represents a "FilePathInvalid" kind of error.
-type ErrFilePathInvalid struct {
- Message string
- Path string
- Name string
- Type git.EntryMode
-}
-
-// IsErrFilePathInvalid checks if an error is an ErrFilePathInvalid.
-func IsErrFilePathInvalid(err error) bool {
- _, ok := err.(ErrFilePathInvalid)
- return ok
-}
-
-func (err ErrFilePathInvalid) Error() string {
- if err.Message != "" {
- return err.Message
- }
- return fmt.Sprintf("path is invalid [path: %s]", err.Path)
-}
-
-func (err ErrFilePathInvalid) Unwrap() error {
- return util.ErrInvalidArgument
-}
-
-// ErrFilePathProtected represents a "FilePathProtected" kind of error.
-type ErrFilePathProtected struct {
- Message string
- Path string
-}
-
-// IsErrFilePathProtected checks if an error is an ErrFilePathProtected.
-func IsErrFilePathProtected(err error) bool {
- _, ok := err.(ErrFilePathProtected)
- return ok
-}
-
-func (err ErrFilePathProtected) Error() string {
- if err.Message != "" {
- return err.Message
- }
- return fmt.Sprintf("path is protected and can not be changed [path: %s]", err.Path)
-}
-
-func (err ErrFilePathProtected) Unwrap() error {
- return util.ErrPermissionDenied
-}
-
-// ErrDisallowedToMerge represents an error that a branch is protected and the current user is not allowed to modify it.
-type ErrDisallowedToMerge struct {
- Reason string
-}
-
-// IsErrDisallowedToMerge checks if an error is an ErrDisallowedToMerge.
-func IsErrDisallowedToMerge(err error) bool {
- _, ok := err.(ErrDisallowedToMerge)
- return ok
-}
-
-func (err ErrDisallowedToMerge) Error() string {
- return fmt.Sprintf("not allowed to merge [reason: %s]", err.Reason)
-}
-
-func (err ErrDisallowedToMerge) Unwrap() error {
- return util.ErrPermissionDenied
-}
-
-// ErrTagAlreadyExists represents an error that tag with such name already exists.
-type ErrTagAlreadyExists struct {
- TagName string
-}
-
-// IsErrTagAlreadyExists checks if an error is an ErrTagAlreadyExists.
-func IsErrTagAlreadyExists(err error) bool {
- _, ok := err.(ErrTagAlreadyExists)
- return ok
-}
-
-func (err ErrTagAlreadyExists) Error() string {
- return fmt.Sprintf("tag already exists [name: %s]", err.TagName)
-}
-
-func (err ErrTagAlreadyExists) Unwrap() error {
- return util.ErrAlreadyExist
-}
-
-// ErrSHADoesNotMatch represents a "SHADoesNotMatch" kind of error.
-type ErrSHADoesNotMatch struct {
- Path string
- GivenSHA string
- CurrentSHA string
-}
-
-// IsErrSHADoesNotMatch checks if an error is a ErrSHADoesNotMatch.
-func IsErrSHADoesNotMatch(err error) bool {
- _, ok := err.(ErrSHADoesNotMatch)
- return ok
-}
-
-func (err ErrSHADoesNotMatch) Error() string {
- return fmt.Sprintf("sha does not match [given: %s, expected: %s]", err.GivenSHA, err.CurrentSHA)
-}
-
-// ErrSHANotFound represents a "SHADoesNotMatch" kind of error.
-type ErrSHANotFound struct {
- SHA string
-}
-
-// IsErrSHANotFound checks if an error is a ErrSHANotFound.
-func IsErrSHANotFound(err error) bool {
- _, ok := err.(ErrSHANotFound)
- return ok
-}
-
-func (err ErrSHANotFound) Error() string {
- return fmt.Sprintf("sha not found [%s]", err.SHA)
-}
-
-func (err ErrSHANotFound) Unwrap() error {
- return util.ErrNotExist
-}
-
-// ErrCommitIDDoesNotMatch represents a "CommitIDDoesNotMatch" kind of error.
-type ErrCommitIDDoesNotMatch struct {
- GivenCommitID string
- CurrentCommitID string
-}
-
-// IsErrCommitIDDoesNotMatch checks if an error is a ErrCommitIDDoesNotMatch.
-func IsErrCommitIDDoesNotMatch(err error) bool {
- _, ok := err.(ErrCommitIDDoesNotMatch)
- return ok
-}
-
-func (err ErrCommitIDDoesNotMatch) Error() string {
- return fmt.Sprintf("file CommitID does not match [given: %s, expected: %s]", err.GivenCommitID, err.CurrentCommitID)
-}
-
-// ErrSHAOrCommitIDNotProvided represents a "SHAOrCommitIDNotProvided" kind of error.
-type ErrSHAOrCommitIDNotProvided struct{}
-
-// IsErrSHAOrCommitIDNotProvided checks if an error is a ErrSHAOrCommitIDNotProvided.
-func IsErrSHAOrCommitIDNotProvided(err error) bool {
- _, ok := err.(ErrSHAOrCommitIDNotProvided)
- return ok
-}
-
-func (err ErrSHAOrCommitIDNotProvided) Error() string {
- return "a SHA or commit ID must be proved when updating a file"
-}
-
-// ErrInvalidMergeStyle represents an error if merging with disabled merge strategy
-type ErrInvalidMergeStyle struct {
- ID int64
- Style repo_model.MergeStyle
-}
-
-// IsErrInvalidMergeStyle checks if an error is a ErrInvalidMergeStyle.
-func IsErrInvalidMergeStyle(err error) bool {
- _, ok := err.(ErrInvalidMergeStyle)
- return ok
-}
-
-func (err ErrInvalidMergeStyle) Error() string {
- return fmt.Sprintf("merge strategy is not allowed or is invalid [repo_id: %d, strategy: %s]",
- err.ID, err.Style)
-}
-
-func (err ErrInvalidMergeStyle) Unwrap() error {
- return util.ErrInvalidArgument
-}
-
-// ErrMergeConflicts represents an error if merging fails with a conflict
-type ErrMergeConflicts struct {
- Style repo_model.MergeStyle
- StdOut string
- StdErr string
- Err error
-}
-
-// IsErrMergeConflicts checks if an error is a ErrMergeConflicts.
-func IsErrMergeConflicts(err error) bool {
- _, ok := err.(ErrMergeConflicts)
- return ok
-}
-
-func (err ErrMergeConflicts) Error() string {
- return fmt.Sprintf("Merge Conflict Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut)
-}
-
-// ErrMergeUnrelatedHistories represents an error if merging fails due to unrelated histories
-type ErrMergeUnrelatedHistories struct {
- Style repo_model.MergeStyle
- StdOut string
- StdErr string
- Err error
-}
-
-// IsErrMergeUnrelatedHistories checks if an error is a ErrMergeUnrelatedHistories.
-func IsErrMergeUnrelatedHistories(err error) bool {
- _, ok := err.(ErrMergeUnrelatedHistories)
- return ok
-}
-
-func (err ErrMergeUnrelatedHistories) Error() string {
- return fmt.Sprintf("Merge UnrelatedHistories Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut)
-}
-
-// ErrMergeDivergingFastForwardOnly represents an error if a fast-forward-only merge fails because the branches diverge
-type ErrMergeDivergingFastForwardOnly struct {
- StdOut string
- StdErr string
- Err error
-}
-
-// IsErrMergeDivergingFastForwardOnly checks if an error is a ErrMergeDivergingFastForwardOnly.
-func IsErrMergeDivergingFastForwardOnly(err error) bool {
- _, ok := err.(ErrMergeDivergingFastForwardOnly)
- return ok
-}
-
-func (err ErrMergeDivergingFastForwardOnly) Error() string {
- return fmt.Sprintf("Merge DivergingFastForwardOnly Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut)
-}
-
-// ErrRebaseConflicts represents an error if rebase fails with a conflict
-type ErrRebaseConflicts struct {
- Style repo_model.MergeStyle
- CommitSHA string
- StdOut string
- StdErr string
- Err error
-}
-
-// IsErrRebaseConflicts checks if an error is a ErrRebaseConflicts.
-func IsErrRebaseConflicts(err error) bool {
- _, ok := err.(ErrRebaseConflicts)
- return ok
-}
-
-func (err ErrRebaseConflicts) Error() string {
- return fmt.Sprintf("Rebase Error: %v: Whilst Rebasing: %s\n%s\n%s", err.Err, err.CommitSHA, err.StdErr, err.StdOut)
-}
-
-// ErrPullRequestHasMerged represents a "PullRequestHasMerged"-error
-type ErrPullRequestHasMerged struct {
- ID int64
- IssueID int64
- HeadRepoID int64
- BaseRepoID int64
- HeadBranch string
- BaseBranch string
-}
-
-// IsErrPullRequestHasMerged checks if an error is a ErrPullRequestHasMerged.
-func IsErrPullRequestHasMerged(err error) bool {
- _, ok := err.(ErrPullRequestHasMerged)
- return ok
-}
-
-// Error does pretty-printing :D
-func (err ErrPullRequestHasMerged) Error() string {
- return fmt.Sprintf("pull request has merged [id: %d, issue_id: %d, head_repo_id: %d, base_repo_id: %d, head_branch: %s, base_branch: %s]",
- err.ID, err.IssueID, err.HeadRepoID, err.BaseRepoID, err.HeadBranch, err.BaseBranch)
-}
diff --git a/models/migrations/base/tests.go b/models/migrations/base/tests.go
index c2134f702a..2eb85cd8a7 100644
--- a/models/migrations/base/tests.go
+++ b/models/migrations/base/tests.go
@@ -13,9 +13,9 @@ import (
"testing"
"code.gitea.io/gitea/models/unittest"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/modules/testlogger"
"github.com/stretchr/testify/require"
@@ -92,10 +92,7 @@ func PrepareTestEnv(t *testing.T, skip int, syncModels ...any) (*xorm.Engine, fu
func MainTest(m *testing.M) {
testlogger.Init()
- giteaRoot := base.SetupGiteaRoot()
- if giteaRoot == "" {
- testlogger.Fatalf("Environment variable $GITEA_ROOT not set\n")
- }
+ giteaRoot := test.SetupGiteaRoot()
giteaBinary := "gitea"
if runtime.GOOS == "windows" {
giteaBinary += ".exe"
diff --git a/models/organization/org_user.go b/models/organization/org_user.go
index 1d3b2fab44..08d936d922 100644
--- a/models/organization/org_user.go
+++ b/models/organization/org_user.go
@@ -36,6 +36,21 @@ func init() {
db.RegisterModel(new(OrgUser))
}
+// ErrUserHasOrgs represents a "UserHasOrgs" kind of error.
+type ErrUserHasOrgs struct {
+ UID int64
+}
+
+// IsErrUserHasOrgs checks if an error is a ErrUserHasOrgs.
+func IsErrUserHasOrgs(err error) bool {
+ _, ok := err.(ErrUserHasOrgs)
+ return ok
+}
+
+func (err ErrUserHasOrgs) Error() string {
+ return fmt.Sprintf("user still has membership of organizations [uid: %d]", err.UID)
+}
+
// GetOrganizationCount returns count of membership of organization of the user.
func GetOrganizationCount(ctx context.Context, u *user_model.User) (int64, error) {
return db.GetEngine(ctx).
diff --git a/models/packages/package.go b/models/packages/package.go
index 417d62d199..c12f345f0e 100644
--- a/models/packages/package.go
+++ b/models/packages/package.go
@@ -301,6 +301,21 @@ func FindUnreferencedPackages(ctx context.Context) ([]*Package, error) {
Find(&ps)
}
+// ErrUserOwnPackages notifies that the user (still) owns the packages.
+type ErrUserOwnPackages struct {
+ UID int64
+}
+
+// IsErrUserOwnPackages checks if an error is an ErrUserOwnPackages.
+func IsErrUserOwnPackages(err error) bool {
+ _, ok := err.(ErrUserOwnPackages)
+ return ok
+}
+
+func (err ErrUserOwnPackages) Error() string {
+ return fmt.Sprintf("user still has ownership of packages [uid: %d]", err.UID)
+}
+
// HasOwnerPackages tests if a user/org has accessible packages
func HasOwnerPackages(ctx context.Context, ownerID int64) (bool, error) {
return db.GetEngine(ctx).
diff --git a/models/repo/repo.go b/models/repo/repo.go
index 8d211caf40..2d9b9de88d 100644
--- a/models/repo/repo.go
+++ b/models/repo/repo.go
@@ -37,7 +37,7 @@ type ErrUserDoesNotHaveAccessToRepo struct {
RepoName string
}
-// IsErrUserDoesNotHaveAccessToRepo checks if an error is a ErrRepoFileAlreadyExists.
+// IsErrUserDoesNotHaveAccessToRepo checks if an error is a ErrUserDoesNotHaveAccessToRepo.
func IsErrUserDoesNotHaveAccessToRepo(err error) bool {
_, ok := err.(ErrUserDoesNotHaveAccessToRepo)
return ok
@@ -866,6 +866,21 @@ func (repo *Repository) TemplateRepo(ctx context.Context) *Repository {
return repo
}
+// ErrUserOwnRepos represents a "UserOwnRepos" kind of error.
+type ErrUserOwnRepos struct {
+ UID int64
+}
+
+// IsErrUserOwnRepos checks if an error is a ErrUserOwnRepos.
+func IsErrUserOwnRepos(err error) bool {
+ _, ok := err.(ErrUserOwnRepos)
+ return ok
+}
+
+func (err ErrUserOwnRepos) Error() string {
+ return fmt.Sprintf("user still has ownership of repositories [uid: %d]", err.UID)
+}
+
type CountRepositoryOptions struct {
OwnerID int64
Private optional.Option[bool]
diff --git a/models/unittest/testdb.go b/models/unittest/testdb.go
index 5a1c27dbea..12f3c25676 100644
--- a/models/unittest/testdb.go
+++ b/models/unittest/testdb.go
@@ -14,13 +14,13 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/system"
"code.gitea.io/gitea/modules/auth/password/hash"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/cache"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/setting/config"
"code.gitea.io/gitea/modules/storage"
+ "code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/modules/util"
"github.com/stretchr/testify/assert"
@@ -206,7 +206,7 @@ func CreateTestEngine(opts FixturesOptions) error {
x, err := xorm.NewEngine("sqlite3", "file::memory:?cache=shared&_txlock=immediate")
if err != nil {
if strings.Contains(err.Error(), "unknown driver") {
- return fmt.Errorf(`sqlite3 requires: import _ "github.com/mattn/go-sqlite3" or -tags sqlite,sqlite_unlock_notify%s%w`, "\n", err)
+ return fmt.Errorf(`sqlite3 requires: -tags sqlite,sqlite_unlock_notify%s%w`, "\n", err)
}
return err
}
@@ -235,5 +235,5 @@ func PrepareTestEnv(t testing.TB) {
assert.NoError(t, PrepareTestDatabase())
metaPath := filepath.Join(giteaRoot, "tests", "gitea-repositories-meta")
assert.NoError(t, SyncDirs(metaPath, setting.RepoRootPath))
- base.SetupGiteaRoot() // Makes sure GITEA_ROOT is set
+ test.SetupGiteaRoot() // Makes sure GITEA_ROOT is set
}
diff --git a/models/user/user.go b/models/user/user.go
index bd92693b6e..72caafc3ba 100644
--- a/models/user/user.go
+++ b/models/user/user.go
@@ -788,6 +788,21 @@ func createUser(ctx context.Context, u *User, meta *Meta, createdByAdmin bool, o
return committer.Commit()
}
+// ErrDeleteLastAdminUser represents a "DeleteLastAdminUser" kind of error.
+type ErrDeleteLastAdminUser struct {
+ UID int64
+}
+
+// IsErrDeleteLastAdminUser checks if an error is a ErrDeleteLastAdminUser.
+func IsErrDeleteLastAdminUser(err error) bool {
+ _, ok := err.(ErrDeleteLastAdminUser)
+ return ok
+}
+
+func (err ErrDeleteLastAdminUser) Error() string {
+ return fmt.Sprintf("can not delete the last admin user [uid: %d]", err.UID)
+}
+
// IsLastAdminUser check whether user is the last admin
func IsLastAdminUser(ctx context.Context, user *User) bool {
if user.IsAdmin && CountUsers(ctx, &CountUserFilter{IsAdmin: optional.Some(true)}) <= 1 {
diff --git a/modules/base/base.go b/modules/base/base.go
deleted file mode 100644
index dddce202da..0000000000
--- a/modules/base/base.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2014 The Gogs Authors. All rights reserved.
-// SPDX-License-Identifier: MIT
-
-package base
-
-type (
- // TplName template relative path type
- TplName string
-)
diff --git a/modules/base/tool.go b/modules/base/tool.go
index 928c80700b..2303e64a68 100644
--- a/modules/base/tool.go
+++ b/modules/base/tool.go
@@ -13,9 +13,6 @@ import (
"errors"
"fmt"
"hash"
- "os"
- "path/filepath"
- "runtime"
"strconv"
"strings"
"time"
@@ -189,49 +186,3 @@ func EntryIcon(entry *git.TreeEntry) string {
return "file"
}
-
-// SetupGiteaRoot Sets GITEA_ROOT if it is not already set and returns the value
-func SetupGiteaRoot() string {
- giteaRoot := os.Getenv("GITEA_ROOT")
- if giteaRoot == "" {
- _, filename, _, _ := runtime.Caller(0)
- giteaRoot = strings.TrimSuffix(filename, "modules/base/tool.go")
- wd, err := os.Getwd()
- if err != nil {
- rel, err := filepath.Rel(giteaRoot, wd)
- if err != nil && strings.HasPrefix(filepath.ToSlash(rel), "../") {
- giteaRoot = wd
- }
- }
- if _, err := os.Stat(filepath.Join(giteaRoot, "gitea")); os.IsNotExist(err) {
- giteaRoot = ""
- } else if err := os.Setenv("GITEA_ROOT", giteaRoot); err != nil {
- giteaRoot = ""
- }
- }
- return giteaRoot
-}
-
-// FormatNumberSI format a number
-func FormatNumberSI(data any) string {
- var num int64
- if num1, ok := data.(int64); ok {
- num = num1
- } else if num1, ok := data.(int); ok {
- num = int64(num1)
- } else {
- return ""
- }
-
- if num < 1000 {
- return fmt.Sprintf("%d", num)
- } else if num < 1000000 {
- num2 := float32(num) / float32(1000.0)
- return fmt.Sprintf("%.1fk", num2)
- } else if num < 1000000000 {
- num2 := float32(num) / float32(1000000.0)
- return fmt.Sprintf("%.1fM", num2)
- }
- num2 := float32(num) / float32(1000000000.0)
- return fmt.Sprintf("%.1fG", num2)
-}
diff --git a/modules/base/tool_test.go b/modules/base/tool_test.go
index f63679048e..de6c311856 100644
--- a/modules/base/tool_test.go
+++ b/modules/base/tool_test.go
@@ -169,18 +169,3 @@ func TestInt64sToStrings(t *testing.T) {
}
// TODO: Test EntryIcon
-
-func TestSetupGiteaRoot(t *testing.T) {
- t.Setenv("GITEA_ROOT", "test")
- assert.Equal(t, "test", SetupGiteaRoot())
- t.Setenv("GITEA_ROOT", "")
- assert.NotEqual(t, "test", SetupGiteaRoot())
-}
-
-func TestFormatNumberSI(t *testing.T) {
- assert.Equal(t, "125", FormatNumberSI(int(125)))
- assert.Equal(t, "1.3k", FormatNumberSI(int64(1317)))
- assert.Equal(t, "21.3M", FormatNumberSI(21317675))
- assert.Equal(t, "45.7G", FormatNumberSI(45721317675))
- assert.Equal(t, "", FormatNumberSI("test"))
-}
diff --git a/modules/git/batch_reader.go b/modules/git/batch_reader.go
index 7dfda72155..532dbad989 100644
--- a/modules/git/batch_reader.go
+++ b/modules/git/batch_reader.go
@@ -7,10 +7,8 @@ import (
"bufio"
"bytes"
"context"
- "fmt"
"io"
"math"
- "runtime"
"strconv"
"strings"
@@ -32,7 +30,6 @@ type WriteCloserError interface {
func ensureValidGitRepository(ctx context.Context, repoPath string) error {
stderr := strings.Builder{}
err := NewCommand(ctx, "rev-parse").
- SetDescription(fmt.Sprintf("%s rev-parse [repo_path: %s]", GitExecutable, repoPath)).
Run(&RunOpts{
Dir: repoPath,
Stderr: &stderr,
@@ -62,13 +59,9 @@ func catFileBatchCheck(ctx context.Context, repoPath string) (WriteCloserError,
cancel()
}()
- _, filename, line, _ := runtime.Caller(2)
- filename = strings.TrimPrefix(filename, callerPrefix)
-
go func() {
stderr := strings.Builder{}
err := NewCommand(ctx, "cat-file", "--batch-check").
- SetDescription(fmt.Sprintf("%s cat-file --batch-check [repo_path: %s] (%s:%d)", GitExecutable, repoPath, filename, line)).
Run(&RunOpts{
Dir: repoPath,
Stdin: batchStdinReader,
@@ -114,13 +107,9 @@ func catFileBatch(ctx context.Context, repoPath string) (WriteCloserError, *bufi
cancel()
}()
- _, filename, line, _ := runtime.Caller(2)
- filename = strings.TrimPrefix(filename, callerPrefix)
-
go func() {
stderr := strings.Builder{}
err := NewCommand(ctx, "cat-file", "--batch").
- SetDescription(fmt.Sprintf("%s cat-file --batch [repo_path: %s] (%s:%d)", GitExecutable, repoPath, filename, line)).
Run(&RunOpts{
Dir: repoPath,
Stdin: batchStdinReader,
@@ -320,13 +309,6 @@ func ParseTreeLine(objectFormat ObjectFormat, rd *bufio.Reader, modeBuf, fnameBu
return mode, fname, sha, n, err
}
-var callerPrefix string
-
-func init() {
- _, filename, _, _ := runtime.Caller(0)
- callerPrefix = strings.TrimSuffix(filename, "modules/git/batch_reader.go")
-}
-
func DiscardFull(rd *bufio.Reader, discard int64) error {
if discard > math.MaxInt32 {
n, err := rd.Discard(math.MaxInt32)
diff --git a/modules/git/blame.go b/modules/git/blame.go
index a9b2706f21..cad720edf4 100644
--- a/modules/git/blame.go
+++ b/modules/git/blame.go
@@ -7,7 +7,6 @@ import (
"bufio"
"bytes"
"context"
- "fmt"
"io"
"os"
@@ -142,9 +141,7 @@ func CreateBlameReader(ctx context.Context, objectFormat ObjectFormat, repoPath
// There is no equivalent on Windows. May be implemented if Gitea uses an external git backend.
cmd.AddOptionValues("--ignore-revs-file", *ignoreRevsFile)
}
- cmd.AddDynamicArguments(commit.ID.String()).
- AddDashesAndList(file).
- SetDescription(fmt.Sprintf("GetBlame [repo_path: %s]", repoPath))
+ cmd.AddDynamicArguments(commit.ID.String()).AddDashesAndList(file)
reader, stdout, err := os.Pipe()
if err != nil {
if ignoreRevsFile != nil {
diff --git a/modules/git/command.go b/modules/git/command.go
index 22cb275ab2..b231c3beea 100644
--- a/modules/git/command.go
+++ b/modules/git/command.go
@@ -12,6 +12,7 @@ import (
"io"
"os"
"os/exec"
+ "path/filepath"
"runtime"
"strings"
"time"
@@ -43,18 +44,24 @@ type Command struct {
prog string
args []string
parentContext context.Context
- desc string
globalArgsLength int
brokenArgs []string
}
-func (c *Command) String() string {
- return c.toString(false)
+func logArgSanitize(arg string) string {
+ if strings.Contains(arg, "://") && strings.Contains(arg, "@") {
+ return util.SanitizeCredentialURLs(arg)
+ } else if filepath.IsAbs(arg) {
+ base := filepath.Base(arg)
+ dir := filepath.Dir(arg)
+ return filepath.Join(filepath.Base(dir), base)
+ }
+ return arg
}
-func (c *Command) toString(sanitizing bool) string {
+func (c *Command) LogString() string {
// WARNING: this function is for debugging purposes only. It's much better than old code (which only joins args with space),
- // It's impossible to make a simple and 100% correct implementation of argument quoting for different platforms.
+ // It's impossible to make a simple and 100% correct implementation of argument quoting for different platforms here.
debugQuote := func(s string) string {
if strings.ContainsAny(s, " `'\"\t\r\n") {
return fmt.Sprintf("%q", s)
@@ -63,12 +70,11 @@ func (c *Command) toString(sanitizing bool) string {
}
a := make([]string, 0, len(c.args)+1)
a = append(a, debugQuote(c.prog))
- for _, arg := range c.args {
- if sanitizing && (strings.Contains(arg, "://") && strings.Contains(arg, "@")) {
- a = append(a, debugQuote(util.SanitizeCredentialURLs(arg)))
- } else {
- a = append(a, debugQuote(arg))
- }
+ if c.globalArgsLength > 0 {
+ a = append(a, "...global...")
+ }
+ for i := c.globalArgsLength; i < len(c.args); i++ {
+ a = append(a, debugQuote(logArgSanitize(c.args[i])))
}
return strings.Join(a, " ")
}
@@ -112,12 +118,6 @@ func (c *Command) SetParentContext(ctx context.Context) *Command {
return c
}
-// SetDescription sets the description for this command which be returned on c.String()
-func (c *Command) SetDescription(desc string) *Command {
- c.desc = desc
- return c
-}
-
// isSafeArgumentValue checks if the argument is safe to be used as a value (not an option)
func isSafeArgumentValue(s string) bool {
return s == "" || s[0] != '-'
@@ -271,8 +271,12 @@ var ErrBrokenCommand = errors.New("git command is broken")
// Run runs the command with the RunOpts
func (c *Command) Run(opts *RunOpts) error {
+ return c.run(1, opts)
+}
+
+func (c *Command) run(skip int, opts *RunOpts) error {
if len(c.brokenArgs) != 0 {
- log.Error("git command is broken: %s, broken args: %s", c.String(), strings.Join(c.brokenArgs, " "))
+ log.Error("git command is broken: %s, broken args: %s", c.LogString(), strings.Join(c.brokenArgs, " "))
return ErrBrokenCommand
}
if opts == nil {
@@ -285,20 +289,14 @@ func (c *Command) Run(opts *RunOpts) error {
timeout = defaultCommandExecutionTimeout
}
- if len(opts.Dir) == 0 {
- log.Debug("git.Command.Run: %s", c)
- } else {
- log.Debug("git.Command.RunDir(%s): %s", opts.Dir, c)
- }
-
- desc := c.desc
- if desc == "" {
- if opts.Dir == "" {
- desc = fmt.Sprintf("git: %s", c.toString(true))
- } else {
- desc = fmt.Sprintf("git(dir:%s): %s", opts.Dir, c.toString(true))
- }
+ var desc string
+ callerInfo := util.CallerFuncName(1 /* util */ + 1 /* this */ + skip /* parent */)
+ if pos := strings.LastIndex(callerInfo, "/"); pos >= 0 {
+ callerInfo = callerInfo[pos+1:]
}
+ // these logs are for debugging purposes only, so no guarantee of correctness or stability
+ desc = fmt.Sprintf("git.Run(by:%s, repo:%s): %s", callerInfo, logArgSanitize(opts.Dir), c.LogString())
+ log.Debug("git.Command: %s", desc)
var ctx context.Context
var cancel context.CancelFunc
@@ -401,7 +399,7 @@ func IsErrorExitCode(err error, code int) bool {
// 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)
+ stdoutBytes, stderrBytes, err := c.runStdBytes(opts)
stdout = util.UnsafeBytesToString(stdoutBytes)
stderr = util.UnsafeBytesToString(stderrBytes)
if err != nil {
@@ -413,6 +411,10 @@ func (c *Command) RunStdString(opts *RunOpts) (stdout, stderr string, runErr Run
// RunStdBytes runs the command with options and returns stdout/stderr as bytes. and store stderr to returned error (err combined with stderr).
func (c *Command) RunStdBytes(opts *RunOpts) (stdout, stderr []byte, runErr RunStdError) {
+ return c.runStdBytes(opts)
+}
+
+func (c *Command) runStdBytes(opts *RunOpts) (stdout, stderr []byte, runErr RunStdError) {
if opts == nil {
opts = &RunOpts{}
}
@@ -435,7 +437,7 @@ func (c *Command) RunStdBytes(opts *RunOpts) (stdout, stderr []byte, runErr RunS
PipelineFunc: opts.PipelineFunc,
}
- err := c.Run(newOpts)
+ err := c.run(2, newOpts)
stderr = stderrBuf.Bytes()
if err != nil {
return nil, stderr, &runStdError{err: err, stderr: util.UnsafeBytesToString(stderr)}
diff --git a/modules/git/command_test.go b/modules/git/command_test.go
index 9a6228c9ad..0823afd7f7 100644
--- a/modules/git/command_test.go
+++ b/modules/git/command_test.go
@@ -55,8 +55,8 @@ func TestGitArgument(t *testing.T) {
func TestCommandString(t *testing.T) {
cmd := NewCommandContextNoGlobals(context.Background(), "a", "-m msg", "it's a test", `say "hello"`)
- assert.EqualValues(t, cmd.prog+` a "-m msg" "it's a test" "say \"hello\""`, cmd.String())
+ assert.EqualValues(t, cmd.prog+` a "-m msg" "it's a test" "say \"hello\""`, cmd.LogString())
- cmd = NewCommandContextNoGlobals(context.Background(), "url: https://a:b@c/")
- assert.EqualValues(t, cmd.prog+` "url: https://sanitized-credential@c/"`, cmd.toString(true))
+ cmd = NewCommandContextNoGlobals(context.Background(), "url: https://a:b@c/", "/root/dir-a/dir-b")
+ assert.EqualValues(t, cmd.prog+` "url: https://sanitized-credential@c/" dir-a/dir-b`, cmd.LogString())
}
diff --git a/modules/git/remote.go b/modules/git/remote.go
index 7b10e6b663..de8d74eded 100644
--- a/modules/git/remote.go
+++ b/modules/git/remote.go
@@ -5,8 +5,12 @@ package git
import (
"context"
+ "fmt"
+ "net/url"
+ "strings"
giturl "code.gitea.io/gitea/modules/git/url"
+ "code.gitea.io/gitea/modules/util"
)
// GetRemoteAddress returns remote url of git repository in the repoPath with special remote name
@@ -37,3 +41,61 @@ func GetRemoteURL(ctx context.Context, repoPath, remoteName string) (*giturl.Git
}
return giturl.Parse(addr)
}
+
+// ErrInvalidCloneAddr represents a "InvalidCloneAddr" kind of error.
+type ErrInvalidCloneAddr struct {
+ Host string
+ IsURLError bool
+ IsInvalidPath bool
+ IsProtocolInvalid bool
+ IsPermissionDenied bool
+ LocalPath bool
+}
+
+// IsErrInvalidCloneAddr checks if an error is a ErrInvalidCloneAddr.
+func IsErrInvalidCloneAddr(err error) bool {
+ _, ok := err.(*ErrInvalidCloneAddr)
+ return ok
+}
+
+func (err *ErrInvalidCloneAddr) Error() string {
+ if err.IsInvalidPath {
+ return fmt.Sprintf("migration/cloning from '%s' is not allowed: the provided path is invalid", err.Host)
+ }
+ if err.IsProtocolInvalid {
+ return fmt.Sprintf("migration/cloning from '%s' is not allowed: the provided url protocol is not allowed", err.Host)
+ }
+ if err.IsPermissionDenied {
+ return fmt.Sprintf("migration/cloning from '%s' is not allowed.", err.Host)
+ }
+ if err.IsURLError {
+ return fmt.Sprintf("migration/cloning from '%s' is not allowed: the provided url is invalid", err.Host)
+ }
+
+ return fmt.Sprintf("migration/cloning from '%s' is not allowed", err.Host)
+}
+
+func (err *ErrInvalidCloneAddr) Unwrap() error {
+ return util.ErrInvalidArgument
+}
+
+// ParseRemoteAddr checks if given remote address is valid,
+// and returns composed URL with needed username and password.
+func ParseRemoteAddr(remoteAddr, authUsername, authPassword string) (string, error) {
+ remoteAddr = strings.TrimSpace(remoteAddr)
+ // Remote address can be HTTP/HTTPS/Git URL or local path.
+ if strings.HasPrefix(remoteAddr, "http://") ||
+ strings.HasPrefix(remoteAddr, "https://") ||
+ strings.HasPrefix(remoteAddr, "git://") {
+ u, err := url.Parse(remoteAddr)
+ if err != nil {
+ return "", &ErrInvalidCloneAddr{IsURLError: true, Host: remoteAddr}
+ }
+ if len(authUsername)+len(authPassword) > 0 {
+ u.User = url.UserPassword(authUsername, authPassword)
+ }
+ remoteAddr = u.String()
+ }
+
+ return remoteAddr, nil
+}
diff --git a/modules/git/repo.go b/modules/git/repo.go
index fc6e6e7acc..0993a4ac37 100644
--- a/modules/git/repo.go
+++ b/modules/git/repo.go
@@ -18,7 +18,6 @@ import (
"time"
"code.gitea.io/gitea/modules/proxy"
- "code.gitea.io/gitea/modules/util"
)
// GPGSettings represents the default GPG settings for this repository
@@ -160,12 +159,6 @@ func CloneWithArgs(ctx context.Context, args TrustedCmdArgs, from, to string, op
}
cmd.AddDashesAndList(from, to)
- if strings.Contains(from, "://") && strings.Contains(from, "@") {
- cmd.SetDescription(fmt.Sprintf("clone branch %s from %s to %s (shared: %t, mirror: %t, depth: %d)", opts.Branch, util.SanitizeCredentialURLs(from), to, opts.Shared, opts.Mirror, opts.Depth))
- } else {
- cmd.SetDescription(fmt.Sprintf("clone branch %s from %s to %s (shared: %t, mirror: %t, depth: %d)", opts.Branch, from, to, opts.Shared, opts.Mirror, opts.Depth))
- }
-
if opts.Timeout <= 0 {
opts.Timeout = -1
}
@@ -213,12 +206,6 @@ func Push(ctx context.Context, repoPath string, opts PushOptions) error {
}
cmd.AddDashesAndList(remoteBranchArgs...)
- if strings.Contains(opts.Remote, "://") && strings.Contains(opts.Remote, "@") {
- cmd.SetDescription(fmt.Sprintf("push branch %s to %s (force: %t, mirror: %t)", opts.Branch, util.SanitizeCredentialURLs(opts.Remote), opts.Force, opts.Mirror))
- } else {
- cmd.SetDescription(fmt.Sprintf("push branch %s to %s (force: %t, mirror: %t)", opts.Branch, opts.Remote, opts.Force, opts.Mirror))
- }
-
stdout, stderr, err := cmd.RunStdString(&RunOpts{Env: opts.Env, Timeout: opts.Timeout, Dir: repoPath})
if err != nil {
if strings.Contains(stderr, "non-fast-forward") {
diff --git a/modules/git/repo_commit.go b/modules/git/repo_commit.go
index 9ffadb833d..647894bb21 100644
--- a/modules/git/repo_commit.go
+++ b/modules/git/repo_commit.go
@@ -216,8 +216,6 @@ type CommitsByFileAndRangeOptions struct {
// CommitsByFileAndRange return the commits according revision file and the page
func (repo *Repository) CommitsByFileAndRange(opts CommitsByFileAndRangeOptions) ([]*Commit, error) {
- skip := (opts.Page - 1) * setting.Git.CommitsRangeSize
-
stdoutReader, stdoutWriter := io.Pipe()
defer func() {
_ = stdoutReader.Close()
@@ -226,8 +224,8 @@ func (repo *Repository) CommitsByFileAndRange(opts CommitsByFileAndRangeOptions)
go func() {
stderr := strings.Builder{}
gitCmd := NewCommand(repo.Ctx, "rev-list").
- AddOptionFormat("--max-count=%d", setting.Git.CommitsRangeSize*opts.Page).
- AddOptionFormat("--skip=%d", skip)
+ AddOptionFormat("--max-count=%d", setting.Git.CommitsRangeSize).
+ AddOptionFormat("--skip=%d", (opts.Page-1)*setting.Git.CommitsRangeSize)
gitCmd.AddDynamicArguments(opts.Revision)
if opts.Not != "" {
diff --git a/modules/git/repo_commit_test.go b/modules/git/repo_commit_test.go
index 4c26fa2a48..e9f469accd 100644
--- a/modules/git/repo_commit_test.go
+++ b/modules/git/repo_commit_test.go
@@ -8,7 +8,11 @@ import (
"path/filepath"
"testing"
+ "code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/test"
+
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
)
func TestRepository_GetCommitBranches(t *testing.T) {
@@ -126,3 +130,21 @@ func TestGetRefCommitID(t *testing.T) {
}
}
}
+
+func TestCommitsByFileAndRange(t *testing.T) {
+ defer test.MockVariableValue(&setting.Git.CommitsRangeSize, 2)()
+
+ bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
+ bareRepo1, err := openRepositoryWithDefaultContext(bareRepo1Path)
+ require.NoError(t, err)
+ defer bareRepo1.Close()
+
+ // "foo" has 3 commits in "master" branch
+ commits, err := bareRepo1.CommitsByFileAndRange(CommitsByFileAndRangeOptions{Revision: "master", File: "foo", Page: 1})
+ require.NoError(t, err)
+ assert.Len(t, commits, 2)
+
+ commits, err = bareRepo1.CommitsByFileAndRange(CommitsByFileAndRangeOptions{Revision: "master", File: "foo", Page: 2})
+ require.NoError(t, err)
+ assert.Len(t, commits, 1)
+}
diff --git a/modules/git/repo_compare.go b/modules/git/repo_compare.go
index 16fcdcf4c8..877a7ff3b8 100644
--- a/modules/git/repo_compare.go
+++ b/modules/git/repo_compare.go
@@ -233,72 +233,34 @@ func parseDiffStat(stdout string) (numFiles, totalAdditions, totalDeletions int,
return numFiles, totalAdditions, totalDeletions, err
}
-// GetDiffOrPatch generates either diff or formatted patch data between given revisions
-func (repo *Repository) GetDiffOrPatch(base, head string, w io.Writer, patch, binary bool) error {
- if patch {
- return repo.GetPatch(base, head, w)
- }
- if binary {
- return repo.GetDiffBinary(base, head, w)
- }
- return repo.GetDiff(base, head, w)
-}
-
// GetDiff generates and returns patch data between given revisions, optimized for human readability
-func (repo *Repository) GetDiff(base, head string, w io.Writer) error {
+func (repo *Repository) GetDiff(compareArg string, w io.Writer) error {
stderr := new(bytes.Buffer)
- err := NewCommand(repo.Ctx, "diff", "-p").AddDynamicArguments(base + "..." + head).
+ return NewCommand(repo.Ctx, "diff", "-p").AddDynamicArguments(compareArg).
Run(&RunOpts{
Dir: repo.Path,
Stdout: w,
Stderr: stderr,
})
- if err != nil && bytes.Contains(stderr.Bytes(), []byte("no merge base")) {
- return NewCommand(repo.Ctx, "diff", "-p").AddDynamicArguments(base, head).
- Run(&RunOpts{
- Dir: repo.Path,
- Stdout: w,
- })
- }
- return err
}
// GetDiffBinary generates and returns patch data between given revisions, including binary diffs.
-func (repo *Repository) GetDiffBinary(base, head string, w io.Writer) error {
- stderr := new(bytes.Buffer)
- err := NewCommand(repo.Ctx, "diff", "-p", "--binary", "--histogram").AddDynamicArguments(base + "..." + head).
- Run(&RunOpts{
- Dir: repo.Path,
- Stdout: w,
- Stderr: stderr,
- })
- if err != nil && bytes.Contains(stderr.Bytes(), []byte("no merge base")) {
- return NewCommand(repo.Ctx, "diff", "-p", "--binary", "--histogram").AddDynamicArguments(base, head).
- Run(&RunOpts{
- Dir: repo.Path,
- Stdout: w,
- })
- }
- return err
+func (repo *Repository) GetDiffBinary(compareArg string, w io.Writer) error {
+ return NewCommand(repo.Ctx, "diff", "-p", "--binary", "--histogram").AddDynamicArguments(compareArg).Run(&RunOpts{
+ Dir: repo.Path,
+ Stdout: w,
+ })
}
// GetPatch generates and returns format-patch data between given revisions, able to be used with `git apply`
-func (repo *Repository) GetPatch(base, head string, w io.Writer) error {
+func (repo *Repository) GetPatch(compareArg string, w io.Writer) error {
stderr := new(bytes.Buffer)
- err := NewCommand(repo.Ctx, "format-patch", "--binary", "--stdout").AddDynamicArguments(base + "..." + head).
+ return NewCommand(repo.Ctx, "format-patch", "--binary", "--stdout").AddDynamicArguments(compareArg).
Run(&RunOpts{
Dir: repo.Path,
Stdout: w,
Stderr: stderr,
})
- if err != nil && bytes.Contains(stderr.Bytes(), []byte("no merge base")) {
- return NewCommand(repo.Ctx, "format-patch", "--binary", "--stdout").AddDynamicArguments(base, head).
- Run(&RunOpts{
- Dir: repo.Path,
- Stdout: w,
- })
- }
- return err
}
// GetFilesChangedBetween returns a list of all files that have been changed between the given commits
@@ -329,21 +291,6 @@ func (repo *Repository) GetFilesChangedBetween(base, head string) ([]string, err
return split, err
}
-// GetDiffFromMergeBase generates and return patch data from merge base to head
-func (repo *Repository) GetDiffFromMergeBase(base, head string, w io.Writer) error {
- stderr := new(bytes.Buffer)
- err := NewCommand(repo.Ctx, "diff", "-p", "--binary").AddDynamicArguments(base + "..." + head).
- Run(&RunOpts{
- Dir: repo.Path,
- Stdout: w,
- Stderr: stderr,
- })
- if err != nil && bytes.Contains(stderr.Bytes(), []byte("no merge base")) {
- return repo.GetDiffBinary(base, head, w)
- }
- return err
-}
-
// ReadPatchCommit will check if a diff patch exists and return stats
func (repo *Repository) ReadPatchCommit(prID int64) (commitSHA string, err error) {
// Migrated repositories download patches to "pulls" location
diff --git a/modules/git/repo_compare_test.go b/modules/git/repo_compare_test.go
index 454ed6b9f8..25ee4c5198 100644
--- a/modules/git/repo_compare_test.go
+++ b/modules/git/repo_compare_test.go
@@ -28,7 +28,7 @@ func TestGetFormatPatch(t *testing.T) {
defer repo.Close()
rd := &bytes.Buffer{}
- err = repo.GetPatch("8d92fc95^", "8d92fc95", rd)
+ err = repo.GetPatch("8d92fc95^...8d92fc95", rd)
if err != nil {
assert.NoError(t, err)
return
diff --git a/modules/gitrepo/gitrepo.go b/modules/gitrepo/gitrepo.go
index 14d809aedb..831b9d7bb7 100644
--- a/modules/gitrepo/gitrepo.go
+++ b/modules/gitrepo/gitrepo.go
@@ -10,6 +10,7 @@ import (
"strings"
"code.gitea.io/gitea/modules/git"
+ "code.gitea.io/gitea/modules/reqctx"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
)
@@ -38,63 +39,32 @@ func OpenWikiRepository(ctx context.Context, repo Repository) (*git.Repository,
// contextKey is a value for use with context.WithValue.
type contextKey struct {
- name string
-}
-
-// RepositoryContextKey is a context key. It is used with context.Value() to get the current Repository for the context
-var RepositoryContextKey = &contextKey{"repository"}
-
-// RepositoryFromContext attempts to get the repository from the context
-func repositoryFromContext(ctx context.Context, repo Repository) *git.Repository {
- value := ctx.Value(RepositoryContextKey)
- if value == nil {
- return nil
- }
-
- if gitRepo, ok := value.(*git.Repository); ok && gitRepo != nil {
- if gitRepo.Path == repoPath(repo) {
- return gitRepo
- }
- }
-
- return nil
+ repoPath string
}
// RepositoryFromContextOrOpen attempts to get the repository from the context or just opens it
func RepositoryFromContextOrOpen(ctx context.Context, repo Repository) (*git.Repository, io.Closer, error) {
- gitRepo := repositoryFromContext(ctx, repo)
- if gitRepo != nil {
- return gitRepo, util.NopCloser{}, nil
+ ds := reqctx.GetRequestDataStore(ctx)
+ if ds != nil {
+ gitRepo, err := RepositoryFromRequestContextOrOpen(ctx, ds, repo)
+ return gitRepo, util.NopCloser{}, err
}
-
gitRepo, err := OpenRepository(ctx, repo)
return gitRepo, gitRepo, err
}
-// repositoryFromContextPath attempts to get the repository from the context
-func repositoryFromContextPath(ctx context.Context, path string) *git.Repository {
- value := ctx.Value(RepositoryContextKey)
- if value == nil {
- return nil
+// RepositoryFromRequestContextOrOpen opens the repository at the given relative path in the provided request context
+// The repo will be automatically closed when the request context is done
+func RepositoryFromRequestContextOrOpen(ctx context.Context, ds reqctx.RequestDataStore, repo Repository) (*git.Repository, error) {
+ ck := contextKey{repoPath: repoPath(repo)}
+ if gitRepo, ok := ctx.Value(ck).(*git.Repository); ok {
+ return gitRepo, nil
}
-
- if repo, ok := value.(*git.Repository); ok && repo != nil {
- if repo.Path == path {
- return repo
- }
+ gitRepo, err := git.OpenRepository(ctx, ck.repoPath)
+ if err != nil {
+ return nil, err
}
-
- return nil
-}
-
-// RepositoryFromContextOrOpenPath attempts to get the repository from the context or just opens it
-// Deprecated: Use RepositoryFromContextOrOpen instead
-func RepositoryFromContextOrOpenPath(ctx context.Context, path string) (*git.Repository, io.Closer, error) {
- gitRepo := repositoryFromContextPath(ctx, path)
- if gitRepo != nil {
- return gitRepo, util.NopCloser{}, nil
- }
-
- gitRepo, err := git.OpenRepository(ctx, path)
- return gitRepo, gitRepo, err
+ ds.AddCloser(gitRepo)
+ ds.SetContextValue(ck, gitRepo)
+ return gitRepo, nil
}
diff --git a/modules/gitrepo/walk_gogit.go b/modules/gitrepo/walk_gogit.go
index 6370faf08e..709897ba0c 100644
--- a/modules/gitrepo/walk_gogit.go
+++ b/modules/gitrepo/walk_gogit.go
@@ -14,15 +14,11 @@ import (
// WalkReferences walks all the references from the repository
// refname is empty, ObjectTag or ObjectBranch. All other values should be treated as equivalent to empty.
func WalkReferences(ctx context.Context, repo Repository, walkfn func(sha1, refname string) error) (int, error) {
- gitRepo := repositoryFromContext(ctx, repo)
- if gitRepo == nil {
- var err error
- gitRepo, err = OpenRepository(ctx, repo)
- if err != nil {
- return 0, err
- }
- defer gitRepo.Close()
+ gitRepo, closer, err := RepositoryFromContextOrOpen(ctx, repo)
+ if err != nil {
+ return 0, err
}
+ defer closer.Close()
i := 0
iter, err := gitRepo.GoGitRepo().References()
diff --git a/modules/graceful/manager.go b/modules/graceful/manager.go
index cac6ce62d6..433e8c4c27 100644
--- a/modules/graceful/manager.go
+++ b/modules/graceful/manager.go
@@ -9,6 +9,7 @@ import (
"sync"
"time"
+ "code.gitea.io/gitea/modules/gtprof"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/process"
"code.gitea.io/gitea/modules/setting"
@@ -136,7 +137,7 @@ func (g *Manager) doShutdown() {
}
g.lock.Lock()
g.shutdownCtxCancel()
- atShutdownCtx := pprof.WithLabels(g.hammerCtx, pprof.Labels(LifecyclePProfLabel, "post-shutdown"))
+ atShutdownCtx := pprof.WithLabels(g.hammerCtx, pprof.Labels(gtprof.LabelGracefulLifecycle, "post-shutdown"))
pprof.SetGoroutineLabels(atShutdownCtx)
for _, fn := range g.toRunAtShutdown {
go fn()
@@ -167,7 +168,7 @@ func (g *Manager) doHammerTime(d time.Duration) {
default:
log.Warn("Setting Hammer condition")
g.hammerCtxCancel()
- atHammerCtx := pprof.WithLabels(g.terminateCtx, pprof.Labels(LifecyclePProfLabel, "post-hammer"))
+ atHammerCtx := pprof.WithLabels(g.terminateCtx, pprof.Labels(gtprof.LabelGracefulLifecycle, "post-hammer"))
pprof.SetGoroutineLabels(atHammerCtx)
}
g.lock.Unlock()
@@ -183,7 +184,7 @@ func (g *Manager) doTerminate() {
default:
log.Warn("Terminating")
g.terminateCtxCancel()
- atTerminateCtx := pprof.WithLabels(g.managerCtx, pprof.Labels(LifecyclePProfLabel, "post-terminate"))
+ atTerminateCtx := pprof.WithLabels(g.managerCtx, pprof.Labels(gtprof.LabelGracefulLifecycle, "post-terminate"))
pprof.SetGoroutineLabels(atTerminateCtx)
for _, fn := range g.toRunAtTerminate {
diff --git a/modules/graceful/manager_common.go b/modules/graceful/manager_common.go
index 15dd4406d5..7cfbdfbeb0 100644
--- a/modules/graceful/manager_common.go
+++ b/modules/graceful/manager_common.go
@@ -8,6 +8,8 @@ import (
"runtime/pprof"
"sync"
"time"
+
+ "code.gitea.io/gitea/modules/gtprof"
)
// FIXME: it seems that there is a bug when using systemd Type=notify: the "Install Page" (INSTALL_LOCK=false) doesn't notify properly.
@@ -22,12 +24,6 @@ const (
watchdogMsg systemdNotifyMsg = "WATCHDOG=1"
)
-// LifecyclePProfLabel is a label marking manager lifecycle phase
-// Making it compliant with prometheus key regex https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels
-// would enable someone interested to be able to to continuously gather profiles into pyroscope.
-// Other labels for pprof (in "modules/process" package) should also follow this rule.
-const LifecyclePProfLabel = "graceful_lifecycle"
-
func statusMsg(msg string) systemdNotifyMsg {
return systemdNotifyMsg("STATUS=" + msg)
}
@@ -71,10 +67,10 @@ func (g *Manager) prepare(ctx context.Context) {
g.hammerCtx, g.hammerCtxCancel = context.WithCancel(ctx)
g.managerCtx, g.managerCtxCancel = context.WithCancel(ctx)
- g.terminateCtx = pprof.WithLabels(g.terminateCtx, pprof.Labels(LifecyclePProfLabel, "with-terminate"))
- g.shutdownCtx = pprof.WithLabels(g.shutdownCtx, pprof.Labels(LifecyclePProfLabel, "with-shutdown"))
- g.hammerCtx = pprof.WithLabels(g.hammerCtx, pprof.Labels(LifecyclePProfLabel, "with-hammer"))
- g.managerCtx = pprof.WithLabels(g.managerCtx, pprof.Labels(LifecyclePProfLabel, "with-manager"))
+ g.terminateCtx = pprof.WithLabels(g.terminateCtx, pprof.Labels(gtprof.LabelGracefulLifecycle, "with-terminate"))
+ g.shutdownCtx = pprof.WithLabels(g.shutdownCtx, pprof.Labels(gtprof.LabelGracefulLifecycle, "with-shutdown"))
+ g.hammerCtx = pprof.WithLabels(g.hammerCtx, pprof.Labels(gtprof.LabelGracefulLifecycle, "with-hammer"))
+ g.managerCtx = pprof.WithLabels(g.managerCtx, pprof.Labels(gtprof.LabelGracefulLifecycle, "with-manager"))
if !g.setStateTransition(stateInit, stateRunning) {
panic("invalid graceful manager state: transition from init to running failed")
diff --git a/modules/gtprof/gtprof.go b/modules/gtprof/gtprof.go
new file mode 100644
index 0000000000..974b2c9757
--- /dev/null
+++ b/modules/gtprof/gtprof.go
@@ -0,0 +1,25 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package gtprof
+
+// This is a Gitea-specific profiling package,
+// the name is chosen to distinguish it from the standard pprof tool and "GNU gprof"
+
+// LabelGracefulLifecycle is a label marking manager lifecycle phase
+// Making it compliant with prometheus key regex https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels
+// would enable someone interested to be able to continuously gather profiles into pyroscope.
+// Other labels for pprof should also follow this rule.
+const LabelGracefulLifecycle = "graceful_lifecycle"
+
+// LabelPid is a label set on goroutines that have a process attached
+const LabelPid = "pid"
+
+// LabelPpid is a label set on goroutines that have a process attached
+const LabelPpid = "ppid"
+
+// LabelProcessType is a label set on goroutines that have a process attached
+const LabelProcessType = "process_type"
+
+// LabelProcessDescription is a label set on goroutines that have a process attached
+const LabelProcessDescription = "process_description"
diff --git a/modules/log/event_format.go b/modules/log/event_format.go
index 0b8d1cec79..8fda0a4980 100644
--- a/modules/log/event_format.go
+++ b/modules/log/event_format.go
@@ -13,10 +13,9 @@ import (
type Event struct {
Time time.Time
- GoroutinePid string
- Caller string
- Filename string
- Line int
+ Caller string
+ Filename string
+ Line int
Level Level
@@ -218,17 +217,16 @@ func EventFormatTextMessage(mode *WriterMode, event *Event, msgFormat string, ms
}
if flags&Lgopid == Lgopid {
- if event.GoroutinePid != "" {
- buf = append(buf, '[')
- if mode.Colorize {
- buf = append(buf, ColorBytes(FgHiYellow)...)
- }
- buf = append(buf, event.GoroutinePid...)
- if mode.Colorize {
- buf = append(buf, resetBytes...)
- }
- buf = append(buf, ']', ' ')
+ deprecatedGoroutinePid := "no-gopid" // use a dummy value to avoid breaking the log format
+ buf = append(buf, '[')
+ if mode.Colorize {
+ buf = append(buf, ColorBytes(FgHiYellow)...)
}
+ buf = append(buf, deprecatedGoroutinePid...)
+ if mode.Colorize {
+ buf = append(buf, resetBytes...)
+ }
+ buf = append(buf, ']', ' ')
}
buf = append(buf, msg...)
diff --git a/modules/log/event_format_test.go b/modules/log/event_format_test.go
index 7c299a607d..6fd0f36d48 100644
--- a/modules/log/event_format_test.go
+++ b/modules/log/event_format_test.go
@@ -24,34 +24,32 @@ func TestItoa(t *testing.T) {
func TestEventFormatTextMessage(t *testing.T) {
res := EventFormatTextMessage(&WriterMode{Prefix: "[PREFIX] ", Colorize: false, Flags: Flags{defined: true, flags: 0xffffffff}},
&Event{
- Time: time.Date(2020, 1, 2, 3, 4, 5, 6, time.UTC),
- Caller: "caller",
- Filename: "filename",
- Line: 123,
- GoroutinePid: "pid",
- Level: ERROR,
- Stacktrace: "stacktrace",
+ Time: time.Date(2020, 1, 2, 3, 4, 5, 6, time.UTC),
+ Caller: "caller",
+ Filename: "filename",
+ Line: 123,
+ Level: ERROR,
+ Stacktrace: "stacktrace",
},
"msg format: %v %v", "arg0", NewColoredValue("arg1", FgBlue),
)
- assert.Equal(t, `[PREFIX] 2020/01/02 03:04:05.000000 filename:123:caller [E] [pid] msg format: arg0 arg1
+ assert.Equal(t, `[PREFIX] 2020/01/02 03:04:05.000000 filename:123:caller [E] [no-gopid] msg format: arg0 arg1
stacktrace
`, string(res))
res = EventFormatTextMessage(&WriterMode{Prefix: "[PREFIX] ", Colorize: true, Flags: Flags{defined: true, flags: 0xffffffff}},
&Event{
- Time: time.Date(2020, 1, 2, 3, 4, 5, 6, time.UTC),
- Caller: "caller",
- Filename: "filename",
- Line: 123,
- GoroutinePid: "pid",
- Level: ERROR,
- Stacktrace: "stacktrace",
+ Time: time.Date(2020, 1, 2, 3, 4, 5, 6, time.UTC),
+ Caller: "caller",
+ Filename: "filename",
+ Line: 123,
+ Level: ERROR,
+ Stacktrace: "stacktrace",
},
"msg format: %v %v", "arg0", NewColoredValue("arg1", FgBlue),
)
- assert.Equal(t, "[PREFIX] \x1b[36m2020/01/02 03:04:05.000000 \x1b[0m\x1b[32mfilename:123:\x1b[32mcaller\x1b[0m \x1b[1;31m[E]\x1b[0m [\x1b[93mpid\x1b[0m] msg format: arg0 \x1b[34marg1\x1b[0m\n\tstacktrace\n\n", string(res))
+ assert.Equal(t, "[PREFIX] \x1b[36m2020/01/02 03:04:05.000000 \x1b[0m\x1b[32mfilename:123:\x1b[32mcaller\x1b[0m \x1b[1;31m[E]\x1b[0m [\x1b[93mno-gopid\x1b[0m] msg format: arg0 \x1b[34marg1\x1b[0m\n\tstacktrace\n\n", string(res))
}
diff --git a/modules/log/flags.go b/modules/log/flags.go
index f025159d53..8064c91745 100644
--- a/modules/log/flags.go
+++ b/modules/log/flags.go
@@ -30,7 +30,7 @@ const (
LUTC // if Ldate or Ltime is set, use UTC rather than the local time zone
Llevelinitial // Initial character of the provided level in brackets, eg. [I] for info
Llevel // Provided level in brackets [INFO]
- Lgopid // the Goroutine-PID of the context
+ Lgopid // the Goroutine-PID of the context, deprecated and it is always a const value
Lmedfile = Lshortfile | Llongfile // last 20 characters of the filename
LstdFlags = Ldate | Ltime | Lmedfile | Lshortfuncname | Llevelinitial // default
diff --git a/modules/log/groutinelabel.go b/modules/log/groutinelabel.go
deleted file mode 100644
index 56d7af42da..0000000000
--- a/modules/log/groutinelabel.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2022 The Gitea Authors. All rights reserved.
-// SPDX-License-Identifier: MIT
-
-package log
-
-import "unsafe"
-
-//go:linkname runtime_getProfLabel runtime/pprof.runtime_getProfLabel
-func runtime_getProfLabel() unsafe.Pointer //nolint
-
-type labelMap map[string]string
-
-func getGoroutineLabels() map[string]string {
- l := (*labelMap)(runtime_getProfLabel())
- if l == nil {
- return nil
- }
- return *l
-}
diff --git a/modules/log/groutinelabel_test.go b/modules/log/groutinelabel_test.go
deleted file mode 100644
index 34e99653d6..0000000000
--- a/modules/log/groutinelabel_test.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2022 The Gitea Authors. All rights reserved.
-// SPDX-License-Identifier: MIT
-
-package log
-
-import (
- "context"
- "runtime/pprof"
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func Test_getGoroutineLabels(t *testing.T) {
- pprof.Do(context.Background(), pprof.Labels(), func(ctx context.Context) {
- currentLabels := getGoroutineLabels()
- pprof.ForLabels(ctx, func(key, value string) bool {
- assert.EqualValues(t, value, currentLabels[key])
- return true
- })
-
- pprof.Do(ctx, pprof.Labels("Test_getGoroutineLabels", "Test_getGoroutineLabels_child1"), func(ctx context.Context) {
- currentLabels := getGoroutineLabels()
- pprof.ForLabels(ctx, func(key, value string) bool {
- assert.EqualValues(t, value, currentLabels[key])
- return true
- })
- if assert.NotNil(t, currentLabels) {
- assert.EqualValues(t, "Test_getGoroutineLabels_child1", currentLabels["Test_getGoroutineLabels"])
- }
- })
- })
-}
diff --git a/modules/log/logger_impl.go b/modules/log/logger_impl.go
index d38c6516ed..76dd5f43fb 100644
--- a/modules/log/logger_impl.go
+++ b/modules/log/logger_impl.go
@@ -200,11 +200,6 @@ func (l *LoggerImpl) Log(skip int, level Level, format string, logArgs ...any) {
event.Stacktrace = Stack(skip + 1)
}
- labels := getGoroutineLabels()
- if labels != nil {
- event.GoroutinePid = labels["pid"]
- }
-
// get a simple text message without color
msgArgs := make([]any, len(logArgs))
copy(msgArgs, logArgs)
diff --git a/modules/markup/common/linkify.go b/modules/markup/common/linkify.go
index be6ab22b55..52888958fa 100644
--- a/modules/markup/common/linkify.go
+++ b/modules/markup/common/linkify.go
@@ -24,7 +24,7 @@ type GlobalVarsType struct {
LinkRegex *regexp.Regexp // fast matching a URL link, no any extra validation.
}
-var GlobalVars = sync.OnceValue[*GlobalVarsType](func() *GlobalVarsType {
+var GlobalVars = sync.OnceValue(func() *GlobalVarsType {
v := &GlobalVarsType{}
v.wwwURLRegxp = regexp.MustCompile(`^www\.[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}((?:/|[#?])[-a-zA-Z0-9@:%_\+.~#!?&//=\(\);,'">\^{}\[\]` + "`" + `]*)?`)
v.LinkRegex, _ = xurls.StrictMatchingScheme("https?://")
diff --git a/modules/markup/html.go b/modules/markup/html.go
index 25628db39e..bb12febf27 100644
--- a/modules/markup/html.go
+++ b/modules/markup/html.go
@@ -42,7 +42,7 @@ type globalVarsType struct {
nulCleaner *strings.Replacer
}
-var globalVars = sync.OnceValue[*globalVarsType](func() *globalVarsType {
+var globalVars = sync.OnceValue(func() *globalVarsType {
v := &globalVarsType{}
// NOTE: All below regex matching do not perform any extra validation.
// Thus a link is produced even if the linked entity does not exist.
diff --git a/modules/markup/html_commit.go b/modules/markup/html_commit.go
index 358e7b06ba..aa1b7d034a 100644
--- a/modules/markup/html_commit.go
+++ b/modules/markup/html_commit.go
@@ -8,6 +8,7 @@ import (
"strings"
"code.gitea.io/gitea/modules/base"
+ "code.gitea.io/gitea/modules/references"
"code.gitea.io/gitea/modules/util"
"golang.org/x/net/html"
@@ -194,3 +195,21 @@ func hashCurrentPatternProcessor(ctx *RenderContext, node *html.Node) {
node = node.NextSibling.NextSibling
}
}
+
+func commitCrossReferencePatternProcessor(ctx *RenderContext, node *html.Node) {
+ next := node.NextSibling
+
+ for node != nil && node != next {
+ found, ref := references.FindRenderizableCommitCrossReference(node.Data)
+ if !found {
+ return
+ }
+
+ reftext := ref.Owner + "/" + ref.Name + "@" + base.ShortSha(ref.CommitSha)
+ linkHref := ctx.RenderHelper.ResolveLink(util.URLJoin(ref.Owner, ref.Name, "commit", ref.CommitSha), LinkTypeApp)
+ link := createLink(ctx, linkHref, reftext, "commit")
+
+ replaceContent(node, ref.RefLocation.Start, ref.RefLocation.End, link)
+ node = node.NextSibling.NextSibling
+ }
+}
diff --git a/modules/markup/html_issue.go b/modules/markup/html_issue.go
index e64ec76c3d..7a6f33011a 100644
--- a/modules/markup/html_issue.go
+++ b/modules/markup/html_issue.go
@@ -4,9 +4,9 @@
package markup
import (
+ "strconv"
"strings"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/httplib"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/references"
@@ -16,8 +16,16 @@ import (
"code.gitea.io/gitea/modules/util"
"golang.org/x/net/html"
+ "golang.org/x/net/html/atom"
)
+type RenderIssueIconTitleOptions struct {
+ OwnerName string
+ RepoName string
+ LinkHref string
+ IssueIndex int64
+}
+
func fullIssuePatternProcessor(ctx *RenderContext, node *html.Node) {
if ctx.RenderOptions.Metas == nil {
return
@@ -66,6 +74,27 @@ func fullIssuePatternProcessor(ctx *RenderContext, node *html.Node) {
}
}
+func createIssueLinkContentWithSummary(ctx *RenderContext, linkHref string, ref *references.RenderizableReference) *html.Node {
+ if DefaultRenderHelperFuncs.RenderRepoIssueIconTitle == nil {
+ return nil
+ }
+ issueIndex, _ := strconv.ParseInt(ref.Issue, 10, 64)
+ h, err := DefaultRenderHelperFuncs.RenderRepoIssueIconTitle(ctx, RenderIssueIconTitleOptions{
+ OwnerName: ref.Owner,
+ RepoName: ref.Name,
+ LinkHref: linkHref,
+ IssueIndex: issueIndex,
+ })
+ if err != nil {
+ log.Error("RenderRepoIssueIconTitle failed: %v", err)
+ return nil
+ }
+ if h == "" {
+ return nil
+ }
+ return &html.Node{Type: html.RawNode, Data: string(ctx.RenderInternal.ProtectSafeAttrs(h))}
+}
+
func issueIndexPatternProcessor(ctx *RenderContext, node *html.Node) {
if ctx.RenderOptions.Metas == nil {
return
@@ -76,32 +105,28 @@ func issueIndexPatternProcessor(ctx *RenderContext, node *html.Node) {
// old logic: crossLinkOnly := ctx.RenderOptions.Metas["mode"] == "document" && !ctx.IsWiki
crossLinkOnly := ctx.RenderOptions.Metas["markupAllowShortIssuePattern"] != "true"
- var (
- found bool
- ref *references.RenderizableReference
- )
+ var ref *references.RenderizableReference
next := node.NextSibling
-
for node != nil && node != next {
_, hasExtTrackFormat := ctx.RenderOptions.Metas["format"]
// Repos with external issue trackers might still need to reference local PRs
// We need to concern with the first one that shows up in the text, whichever it is
isNumericStyle := ctx.RenderOptions.Metas["style"] == "" || ctx.RenderOptions.Metas["style"] == IssueNameStyleNumeric
- foundNumeric, refNumeric := references.FindRenderizableReferenceNumeric(node.Data, hasExtTrackFormat && !isNumericStyle, crossLinkOnly)
+ refNumeric := references.FindRenderizableReferenceNumeric(node.Data, hasExtTrackFormat && !isNumericStyle, crossLinkOnly)
switch ctx.RenderOptions.Metas["style"] {
case "", IssueNameStyleNumeric:
- found, ref = foundNumeric, refNumeric
+ ref = refNumeric
case IssueNameStyleAlphanumeric:
- found, ref = references.FindRenderizableReferenceAlphanumeric(node.Data)
+ ref = references.FindRenderizableReferenceAlphanumeric(node.Data)
case IssueNameStyleRegexp:
pattern, err := regexplru.GetCompiled(ctx.RenderOptions.Metas["regexp"])
if err != nil {
return
}
- found, ref = references.FindRenderizableReferenceRegexp(node.Data, pattern)
+ ref = references.FindRenderizableReferenceRegexp(node.Data, pattern)
}
// Repos with external issue trackers might still need to reference local PRs
@@ -109,17 +134,17 @@ func issueIndexPatternProcessor(ctx *RenderContext, node *html.Node) {
if hasExtTrackFormat && !isNumericStyle && refNumeric != nil {
// If numeric (PR) was found, and it was BEFORE the non-numeric pattern, use that
// Allow a free-pass when non-numeric pattern wasn't found.
- if found && (ref == nil || refNumeric.RefLocation.Start < ref.RefLocation.Start) {
- found = foundNumeric
+ if ref == nil || refNumeric.RefLocation.Start < ref.RefLocation.Start {
ref = refNumeric
}
}
- if !found {
+
+ if ref == nil {
return
}
var link *html.Node
- reftext := node.Data[ref.RefLocation.Start:ref.RefLocation.End]
+ refText := node.Data[ref.RefLocation.Start:ref.RefLocation.End]
if hasExtTrackFormat && !ref.IsPull {
ctx.RenderOptions.Metas["index"] = ref.Issue
@@ -129,18 +154,23 @@ func issueIndexPatternProcessor(ctx *RenderContext, node *html.Node) {
log.Error("unable to expand template vars for ref %s, err: %v", ref.Issue, err)
}
- link = createLink(ctx, res, reftext, "ref-issue ref-external-issue")
+ link = createLink(ctx, res, refText, "ref-issue ref-external-issue")
} else {
// Path determines the type of link that will be rendered. It's unknown at this point whether
// the linked item is actually a PR or an issue. Luckily it's of no real consequence because
// Gitea will redirect on click as appropriate.
+ issueOwner := util.Iif(ref.Owner == "", ctx.RenderOptions.Metas["user"], ref.Owner)
+ issueRepo := util.Iif(ref.Owner == "", ctx.RenderOptions.Metas["repo"], ref.Name)
issuePath := util.Iif(ref.IsPull, "pulls", "issues")
- if ref.Owner == "" {
- linkHref := ctx.RenderHelper.ResolveLink(util.URLJoin(ctx.RenderOptions.Metas["user"], ctx.RenderOptions.Metas["repo"], issuePath, ref.Issue), LinkTypeApp)
- link = createLink(ctx, linkHref, reftext, "ref-issue")
- } else {
- linkHref := ctx.RenderHelper.ResolveLink(util.URLJoin(ref.Owner, ref.Name, issuePath, ref.Issue), LinkTypeApp)
- link = createLink(ctx, linkHref, reftext, "ref-issue")
+ linkHref := ctx.RenderHelper.ResolveLink(util.URLJoin(issueOwner, issueRepo, issuePath, ref.Issue), LinkTypeApp)
+
+ // at the moment, only render the issue index in a full line (or simple line) as icon+title
+ // otherwise it would be too noisy for "take #1 as an example" in a sentence
+ if node.Parent.DataAtom == atom.Li && ref.RefLocation.Start < 20 && ref.RefLocation.End == len(node.Data) {
+ link = createIssueLinkContentWithSummary(ctx, linkHref, ref)
+ }
+ if link == nil {
+ link = createLink(ctx, linkHref, refText, "ref-issue")
}
}
@@ -168,21 +198,3 @@ func issueIndexPatternProcessor(ctx *RenderContext, node *html.Node) {
node = node.NextSibling.NextSibling.NextSibling.NextSibling
}
}
-
-func commitCrossReferencePatternProcessor(ctx *RenderContext, node *html.Node) {
- next := node.NextSibling
-
- for node != nil && node != next {
- found, ref := references.FindRenderizableCommitCrossReference(node.Data)
- if !found {
- return
- }
-
- reftext := ref.Owner + "/" + ref.Name + "@" + base.ShortSha(ref.CommitSha)
- linkHref := ctx.RenderHelper.ResolveLink(util.URLJoin(ref.Owner, ref.Name, "commit", ref.CommitSha), LinkTypeApp)
- link := createLink(ctx, linkHref, reftext, "commit")
-
- replaceContent(node, ref.RefLocation.Start, ref.RefLocation.End, link)
- node = node.NextSibling.NextSibling
- }
-}
diff --git a/modules/markup/html_issue_test.go b/modules/markup/html_issue_test.go
new file mode 100644
index 0000000000..8d189fbdf6
--- /dev/null
+++ b/modules/markup/html_issue_test.go
@@ -0,0 +1,72 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package markup_test
+
+import (
+ "context"
+ "html/template"
+ "strings"
+ "testing"
+
+ "code.gitea.io/gitea/modules/htmlutil"
+ "code.gitea.io/gitea/modules/markup"
+ "code.gitea.io/gitea/modules/markup/markdown"
+ testModule "code.gitea.io/gitea/modules/test"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestRender_IssueList(t *testing.T) {
+ defer testModule.MockVariableValue(&markup.RenderBehaviorForTesting.DisableAdditionalAttributes, true)()
+ markup.Init(&markup.RenderHelperFuncs{
+ RenderRepoIssueIconTitle: func(ctx context.Context, opts markup.RenderIssueIconTitleOptions) (template.HTML, error) {
+ return htmlutil.HTMLFormat("
issue #%d
", opts.IssueIndex), nil
+ },
+ })
+
+ test := func(input, expected string) {
+ rctx := markup.NewTestRenderContext(markup.TestAppURL, map[string]string{
+ "user": "test-user", "repo": "test-repo",
+ "markupAllowShortIssuePattern": "true",
+ })
+ out, err := markdown.RenderString(rctx, input)
+ require.NoError(t, err)
+ assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(out)))
+ }
+
+ t.Run("NormalIssueRef", func(t *testing.T) {
+ test(
+ "#12345",
+ `#12345
`,
+ )
+ })
+
+ t.Run("ListIssueRef", func(t *testing.T) {
+ test(
+ "* #12345",
+ ``,
+ )
+ })
+
+ t.Run("ListIssueRefNormal", func(t *testing.T) {
+ test(
+ "* foo #12345 bar",
+ ``,
+ )
+ })
+
+ t.Run("ListTodoIssueRef", func(t *testing.T) {
+ test(
+ "* [ ] #12345",
+ ``,
+ )
+ })
+}
diff --git a/modules/markup/internal/renderinternal.go b/modules/markup/internal/renderinternal.go
index 4775fecfc7..4d58f160a9 100644
--- a/modules/markup/internal/renderinternal.go
+++ b/modules/markup/internal/renderinternal.go
@@ -17,7 +17,7 @@ import (
"golang.org/x/net/html"
)
-var reAttrClass = sync.OnceValue[*regexp.Regexp](func() *regexp.Regexp {
+var reAttrClass = sync.OnceValue(func() *regexp.Regexp {
// TODO: it isn't a problem at the moment because our HTML contents are always well constructed
return regexp.MustCompile(`(<[^>]+)\s+class="([^"]+)"([^>]*>)`)
})
diff --git a/modules/markup/markdown/goldmark.go b/modules/markup/markdown/goldmark.go
index 620a39ebfd..69c2a96ff1 100644
--- a/modules/markup/markdown/goldmark.go
+++ b/modules/markup/markdown/goldmark.go
@@ -112,7 +112,7 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa
}
// it is copied from old code, which is quite doubtful whether it is correct
-var reValidIconName = sync.OnceValue[*regexp.Regexp](func() *regexp.Regexp {
+var reValidIconName = sync.OnceValue(func() *regexp.Regexp {
return regexp.MustCompile(`^[-\w]+$`) // old: regexp.MustCompile("^[a-z ]+$")
})
diff --git a/modules/markup/render_helper.go b/modules/markup/render_helper.go
index 82796ef274..8ff0e7d6fb 100644
--- a/modules/markup/render_helper.go
+++ b/modules/markup/render_helper.go
@@ -38,6 +38,7 @@ type RenderHelper interface {
type RenderHelperFuncs struct {
IsUsernameMentionable func(ctx context.Context, username string) bool
RenderRepoFileCodePreview func(ctx context.Context, options RenderCodePreviewOptions) (template.HTML, error)
+ RenderRepoIssueIconTitle func(ctx context.Context, options RenderIssueIconTitleOptions) (template.HTML, error)
}
var DefaultRenderHelperFuncs *RenderHelperFuncs
diff --git a/modules/packages/arch/metadata.go b/modules/packages/arch/metadata.go
index 06a2206a36..3d7bdf3997 100644
--- a/modules/packages/arch/metadata.go
+++ b/modules/packages/arch/metadata.go
@@ -43,8 +43,9 @@ var (
ErrInvalidArchitecture = util.NewInvalidArgumentErrorf("package architecture is invalid")
// https://man.archlinux.org/man/PKGBUILD.5
- namePattern = regexp.MustCompile(`\A[a-zA-Z0-9@._+-]+\z`)
- versionPattern = regexp.MustCompile(`\A(?:[0-9]:)?[a-zA-Z0-9.+~]+(?:-[a-zA-Z0-9.+-~]+)?\z`)
+ namePattern = regexp.MustCompile(`\A[a-zA-Z0-9@._+-]+\z`)
+ // (epoch:pkgver-pkgrel)
+ versionPattern = regexp.MustCompile(`\A(?:\d:)?[\w.+~]+(?:-[-\w.+~]+)?\z`)
)
type Package struct {
diff --git a/modules/packages/arch/metadata_test.go b/modules/packages/arch/metadata_test.go
index 37c0a553b8..5bdf63a3ee 100644
--- a/modules/packages/arch/metadata_test.go
+++ b/modules/packages/arch/metadata_test.go
@@ -122,6 +122,14 @@ func TestParsePackageInfo(t *testing.T) {
assert.ErrorIs(t, err, ErrInvalidName)
})
+ t.Run("Regexp", func(t *testing.T) {
+ assert.Regexp(t, versionPattern, "1.2_3~4+5")
+ assert.Regexp(t, versionPattern, "1:2_3~4+5")
+ assert.NotRegexp(t, versionPattern, "a:1.0.0-1")
+ assert.NotRegexp(t, versionPattern, "0.0.1/1-1")
+ assert.NotRegexp(t, versionPattern, "1.0.0 -1")
+ })
+
t.Run("InvalidVersion", func(t *testing.T) {
data := createPKGINFOContent(packageName, "")
diff --git a/modules/process/manager.go b/modules/process/manager.go
index 7b8ada786e..661511ce8d 100644
--- a/modules/process/manager.go
+++ b/modules/process/manager.go
@@ -11,6 +11,8 @@ import (
"sync"
"sync/atomic"
"time"
+
+ "code.gitea.io/gitea/modules/gtprof"
)
// TODO: This packages still uses a singleton for the Manager.
@@ -25,18 +27,6 @@ var (
DefaultContext = context.Background()
)
-// DescriptionPProfLabel is a label set on goroutines that have a process attached
-const DescriptionPProfLabel = "process_description"
-
-// PIDPProfLabel is a label set on goroutines that have a process attached
-const PIDPProfLabel = "pid"
-
-// PPIDPProfLabel is a label set on goroutines that have a process attached
-const PPIDPProfLabel = "ppid"
-
-// ProcessTypePProfLabel is a label set on goroutines that have a process attached
-const ProcessTypePProfLabel = "process_type"
-
// IDType is a pid type
type IDType string
@@ -187,7 +177,12 @@ func (pm *Manager) Add(ctx context.Context, description string, cancel context.C
Trace(true, pid, description, parentPID, processType)
- pprofCtx := pprof.WithLabels(ctx, pprof.Labels(DescriptionPProfLabel, description, PPIDPProfLabel, string(parentPID), PIDPProfLabel, string(pid), ProcessTypePProfLabel, processType))
+ pprofCtx := pprof.WithLabels(ctx, pprof.Labels(
+ gtprof.LabelProcessDescription, description,
+ gtprof.LabelPpid, string(parentPID),
+ gtprof.LabelPid, string(pid),
+ gtprof.LabelProcessType, processType,
+ ))
if currentlyRunning {
pprof.SetGoroutineLabels(pprofCtx)
}
diff --git a/modules/process/manager_stacktraces.go b/modules/process/manager_stacktraces.go
index e260893113..d83060f6ee 100644
--- a/modules/process/manager_stacktraces.go
+++ b/modules/process/manager_stacktraces.go
@@ -10,6 +10,8 @@ import (
"sort"
"time"
+ "code.gitea.io/gitea/modules/gtprof"
+
"github.com/google/pprof/profile"
)
@@ -202,7 +204,7 @@ func (pm *Manager) ProcessStacktraces(flat, noSystem bool) ([]*Process, int, int
// Add the non-process associated labels from the goroutine sample to the Stack
for name, value := range sample.Label {
- if name == DescriptionPProfLabel || name == PIDPProfLabel || (!flat && name == PPIDPProfLabel) || name == ProcessTypePProfLabel {
+ if name == gtprof.LabelProcessDescription || name == gtprof.LabelPid || (!flat && name == gtprof.LabelPpid) || name == gtprof.LabelProcessType {
continue
}
@@ -224,7 +226,7 @@ func (pm *Manager) ProcessStacktraces(flat, noSystem bool) ([]*Process, int, int
var process *Process
// Try to get the PID from the goroutine labels
- if pidvalue, ok := sample.Label[PIDPProfLabel]; ok && len(pidvalue) == 1 {
+ if pidvalue, ok := sample.Label[gtprof.LabelPid]; ok && len(pidvalue) == 1 {
pid := IDType(pidvalue[0])
// Now try to get the process from our map
@@ -238,20 +240,20 @@ func (pm *Manager) ProcessStacktraces(flat, noSystem bool) ([]*Process, int, int
// get the parent PID
ppid := IDType("")
- if value, ok := sample.Label[PPIDPProfLabel]; ok && len(value) == 1 {
+ if value, ok := sample.Label[gtprof.LabelPpid]; ok && len(value) == 1 {
ppid = IDType(value[0])
}
// format the description
description := "(dead process)"
- if value, ok := sample.Label[DescriptionPProfLabel]; ok && len(value) == 1 {
+ if value, ok := sample.Label[gtprof.LabelProcessDescription]; ok && len(value) == 1 {
description = value[0] + " " + description
}
// override the type of the process to "code" but add the old type as a label on the first stack
ptype := NoneProcessType
- if value, ok := sample.Label[ProcessTypePProfLabel]; ok && len(value) == 1 {
- stack.Labels = append(stack.Labels, &Label{Name: ProcessTypePProfLabel, Value: value[0]})
+ if value, ok := sample.Label[gtprof.LabelProcessType]; ok && len(value) == 1 {
+ stack.Labels = append(stack.Labels, &Label{Name: gtprof.LabelProcessType, Value: value[0]})
}
process = &Process{
PID: pid,
diff --git a/modules/queue/workerqueue.go b/modules/queue/workerqueue.go
index 672e9a4114..0f5b105551 100644
--- a/modules/queue/workerqueue.go
+++ b/modules/queue/workerqueue.go
@@ -6,6 +6,7 @@ package queue
import (
"context"
"fmt"
+ "runtime/pprof"
"sync"
"sync/atomic"
"time"
@@ -241,6 +242,9 @@ func NewWorkerPoolQueueWithContext[T any](ctx context.Context, name string, queu
w.origHandler = handler
w.safeHandler = func(t ...T) (unhandled []T) {
defer func() {
+ // FIXME: there is no ctx support in the handler, so process manager is unable to restore the labels
+ // so here we explicitly set the "queue ctx" labels again after the handler is done
+ pprof.SetGoroutineLabels(w.ctxRun)
err := recover()
if err != nil {
log.Error("Recovered from panic in queue %q handler: %v\n%s", name, err, log.Stack(2))
diff --git a/modules/references/references.go b/modules/references/references.go
index 6e549cb875..a5b102b7f2 100644
--- a/modules/references/references.go
+++ b/modules/references/references.go
@@ -32,7 +32,7 @@ var (
// issueNumericPattern matches string that references to a numeric issue, e.g. #1287
issueNumericPattern = regexp.MustCompile(`(?:\s|^|\(|\[|\'|\")([#!][0-9]+)(?:\s|$|\)|\]|\'|\"|[:;,.?!]\s|[:;,.?!]$)`)
// issueAlphanumericPattern matches string that references to an alphanumeric issue, e.g. ABC-1234
- issueAlphanumericPattern = regexp.MustCompile(`(?:\s|^|\(|\[|\"|\')([A-Z]{1,10}-[1-9][0-9]*)(?:\s|$|\)|\]|:|\.(\s|$)|\"|\')`)
+ issueAlphanumericPattern = regexp.MustCompile(`(?:\s|^|\(|\[|\"|\')([A-Z]{1,10}-[1-9][0-9]*)(?:\s|$|\)|\]|:|\.(\s|$)|\"|\'|,)`)
// crossReferenceIssueNumericPattern matches string that references a numeric issue in a different repository
// e.g. org/repo#12345
crossReferenceIssueNumericPattern = regexp.MustCompile(`(?:\s|^|\(|\[)([0-9a-zA-Z-_\.]+/[0-9a-zA-Z-_\.]+[#!][0-9]+)(?:\s|$|\)|\]|[:;,.?!]\s|[:;,.?!]$)`)
@@ -330,22 +330,22 @@ func FindAllIssueReferences(content string) []IssueReference {
}
// FindRenderizableReferenceNumeric returns the first unvalidated reference found in a string.
-func FindRenderizableReferenceNumeric(content string, prOnly, crossLinkOnly bool) (bool, *RenderizableReference) {
+func FindRenderizableReferenceNumeric(content string, prOnly, crossLinkOnly bool) *RenderizableReference {
var match []int
if !crossLinkOnly {
match = issueNumericPattern.FindStringSubmatchIndex(content)
}
if match == nil {
if match = crossReferenceIssueNumericPattern.FindStringSubmatchIndex(content); match == nil {
- return false, nil
+ return nil
}
}
r := getCrossReference(util.UnsafeStringToBytes(content), match[2], match[3], false, prOnly)
if r == nil {
- return false, nil
+ return nil
}
- return true, &RenderizableReference{
+ return &RenderizableReference{
Issue: r.issue,
Owner: r.owner,
Name: r.name,
@@ -372,15 +372,14 @@ func FindRenderizableCommitCrossReference(content string) (bool, *RenderizableRe
}
// FindRenderizableReferenceRegexp returns the first regexp unvalidated references found in a string.
-func FindRenderizableReferenceRegexp(content string, pattern *regexp.Regexp) (bool, *RenderizableReference) {
+func FindRenderizableReferenceRegexp(content string, pattern *regexp.Regexp) *RenderizableReference {
match := pattern.FindStringSubmatchIndex(content)
if len(match) < 4 {
- return false, nil
+ return nil
}
action, location := findActionKeywords([]byte(content), match[2])
-
- return true, &RenderizableReference{
+ return &RenderizableReference{
Issue: content[match[2]:match[3]],
RefLocation: &RefSpan{Start: match[0], End: match[1]},
Action: action,
@@ -390,15 +389,14 @@ func FindRenderizableReferenceRegexp(content string, pattern *regexp.Regexp) (bo
}
// FindRenderizableReferenceAlphanumeric returns the first alphanumeric unvalidated references found in a string.
-func FindRenderizableReferenceAlphanumeric(content string) (bool, *RenderizableReference) {
+func FindRenderizableReferenceAlphanumeric(content string) *RenderizableReference {
match := issueAlphanumericPattern.FindStringSubmatchIndex(content)
if match == nil {
- return false, nil
+ return nil
}
action, location := findActionKeywords([]byte(content), match[2])
-
- return true, &RenderizableReference{
+ return &RenderizableReference{
Issue: content[match[2]:match[3]],
RefLocation: &RefSpan{Start: match[2], End: match[3]},
Action: action,
diff --git a/modules/references/references_test.go b/modules/references/references_test.go
index e224c919e9..1b6a968d6a 100644
--- a/modules/references/references_test.go
+++ b/modules/references/references_test.go
@@ -249,11 +249,10 @@ func TestFindAllIssueReferences(t *testing.T) {
}
for _, fixture := range alnumFixtures {
- found, ref := FindRenderizableReferenceAlphanumeric(fixture.input)
+ ref := FindRenderizableReferenceAlphanumeric(fixture.input)
if fixture.issue == "" {
- assert.False(t, found, "Failed to parse: {%s}", fixture.input)
+ assert.Nil(t, ref, "Failed to parse: {%s}", fixture.input)
} else {
- assert.True(t, found, "Failed to parse: {%s}", fixture.input)
assert.Equal(t, fixture.issue, ref.Issue, "Failed to parse: {%s}", fixture.input)
assert.Equal(t, fixture.refLocation, ref.RefLocation, "Failed to parse: {%s}", fixture.input)
assert.Equal(t, fixture.action, ref.Action, "Failed to parse: {%s}", fixture.input)
@@ -463,6 +462,7 @@ func TestRegExp_issueAlphanumericPattern(t *testing.T) {
"ABC-123:",
"\"ABC-123\"",
"'ABC-123'",
+ "ABC-123, unknown PR",
}
falseTestCases := []string{
"RC-08",
diff --git a/modules/repository/license_test.go b/modules/repository/license_test.go
index 3b0cfa1eed..d00156a496 100644
--- a/modules/repository/license_test.go
+++ b/modules/repository/license_test.go
@@ -31,12 +31,7 @@ func Test_getLicense(t *testing.T) {
Copyright (c) 2023 Gitea
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-`,
+Permission is hereby granted`,
wantErr: assert.NoError,
},
{
@@ -53,7 +48,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
if !tt.wantErr(t, err, fmt.Sprintf("GetLicense(%v, %v)", tt.args.name, tt.args.values)) {
return
}
- assert.Equalf(t, tt.want, string(got), "GetLicense(%v, %v)", tt.args.name, tt.args.values)
+ assert.Contains(t, string(got), tt.want, "GetLicense(%v, %v)", tt.args.name, tt.args.values)
})
}
}
diff --git a/modules/reqctx/datastore.go b/modules/reqctx/datastore.go
new file mode 100644
index 0000000000..66361a4587
--- /dev/null
+++ b/modules/reqctx/datastore.go
@@ -0,0 +1,123 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package reqctx
+
+import (
+ "context"
+ "io"
+ "sync"
+
+ "code.gitea.io/gitea/modules/process"
+)
+
+type ContextDataProvider interface {
+ GetData() ContextData
+}
+
+type ContextData map[string]any
+
+func (ds ContextData) GetData() ContextData {
+ return ds
+}
+
+func (ds ContextData) MergeFrom(other ContextData) ContextData {
+ for k, v := range other {
+ ds[k] = v
+ }
+ return ds
+}
+
+// RequestDataStore is a short-lived context-related object that is used to store request-specific data.
+type RequestDataStore interface {
+ GetData() ContextData
+ SetContextValue(k, v any)
+ GetContextValue(key any) any
+ AddCleanUp(f func())
+ AddCloser(c io.Closer)
+}
+
+type requestDataStoreKeyType struct{}
+
+var RequestDataStoreKey requestDataStoreKeyType
+
+type requestDataStore struct {
+ data ContextData
+
+ mu sync.RWMutex
+ values map[any]any
+ cleanUpFuncs []func()
+}
+
+func (r *requestDataStore) GetContextValue(key any) any {
+ if key == RequestDataStoreKey {
+ return r
+ }
+ r.mu.RLock()
+ defer r.mu.RUnlock()
+ return r.values[key]
+}
+
+func (r *requestDataStore) SetContextValue(k, v any) {
+ r.mu.Lock()
+ r.values[k] = v
+ r.mu.Unlock()
+}
+
+// GetData and the underlying ContextData are not thread-safe, callers should ensure thread-safety.
+func (r *requestDataStore) GetData() ContextData {
+ if r.data == nil {
+ r.data = make(ContextData)
+ }
+ return r.data
+}
+
+func (r *requestDataStore) AddCleanUp(f func()) {
+ r.mu.Lock()
+ r.cleanUpFuncs = append(r.cleanUpFuncs, f)
+ r.mu.Unlock()
+}
+
+func (r *requestDataStore) AddCloser(c io.Closer) {
+ r.AddCleanUp(func() { _ = c.Close() })
+}
+
+func (r *requestDataStore) cleanUp() {
+ for _, f := range r.cleanUpFuncs {
+ f()
+ }
+}
+
+func GetRequestDataStore(ctx context.Context) RequestDataStore {
+ if req, ok := ctx.Value(RequestDataStoreKey).(*requestDataStore); ok {
+ return req
+ }
+ return nil
+}
+
+type requestContext struct {
+ context.Context
+ dataStore *requestDataStore
+}
+
+func (c *requestContext) Value(key any) any {
+ if v := c.dataStore.GetContextValue(key); v != nil {
+ return v
+ }
+ return c.Context.Value(key)
+}
+
+func NewRequestContext(parentCtx context.Context, profDesc string) (_ context.Context, finished func()) {
+ ctx, _, processFinished := process.GetManager().AddTypedContext(parentCtx, profDesc, process.RequestProcessType, true)
+ reqCtx := &requestContext{Context: ctx, dataStore: &requestDataStore{values: make(map[any]any)}}
+ return reqCtx, func() {
+ reqCtx.dataStore.cleanUp()
+ processFinished()
+ }
+}
+
+// NewRequestContextForTest creates a new RequestContext for testing purposes
+// It doesn't add the context to the process manager, nor do cleanup
+func NewRequestContextForTest(parentCtx context.Context) context.Context {
+ return &requestContext{Context: parentCtx, dataStore: &requestDataStore{values: make(map[any]any)}}
+}
diff --git a/modules/setting/i18n.go b/modules/setting/i18n.go
index c3076c0ab7..6e0767320f 100644
--- a/modules/setting/i18n.go
+++ b/modules/setting/i18n.go
@@ -11,6 +11,7 @@ var defaultI18nLangNames = []string{
"zh-TW", "繁體中文(台灣)",
"de-DE", "Deutsch",
"fr-FR", "Français",
+ "ga-IE", "Gaeilge",
"nl-NL", "Nederlands",
"lv-LV", "Latviešu",
"ru-RU", "Русский",
diff --git a/modules/svg/processor.go b/modules/svg/processor.go
index 82248fb0c1..4fcb11a57d 100644
--- a/modules/svg/processor.go
+++ b/modules/svg/processor.go
@@ -10,7 +10,7 @@ import (
"sync"
)
-type normalizeVarsStruct struct {
+type globalVarsStruct struct {
reXMLDoc,
reComment,
reAttrXMLNs,
@@ -18,26 +18,23 @@ type normalizeVarsStruct struct {
reAttrClassPrefix *regexp.Regexp
}
-var (
- normalizeVars *normalizeVarsStruct
- normalizeVarsOnce sync.Once
-)
+var globalVars = sync.OnceValue(func() *globalVarsStruct {
+ return &globalVarsStruct{
+ reXMLDoc: regexp.MustCompile(`(?s)<\?xml.*?>`),
+ reComment: regexp.MustCompile(`(?s)`),
+
+ reAttrXMLNs: regexp.MustCompile(`(?s)\s+xmlns\s*=\s*"[^"]*"`),
+ reAttrSize: regexp.MustCompile(`(?s)\s+(width|height)\s*=\s*"[^"]+"`),
+ reAttrClassPrefix: regexp.MustCompile(`(?s)\s+class\s*=\s*"`),
+ }
+})
// Normalize normalizes the SVG content: set default width/height, remove unnecessary tags/attributes
// It's designed to work with valid SVG content. For invalid SVG content, the returned content is not guaranteed.
func Normalize(data []byte, size int) []byte {
- normalizeVarsOnce.Do(func() {
- normalizeVars = &normalizeVarsStruct{
- reXMLDoc: regexp.MustCompile(`(?s)<\?xml.*?>`),
- reComment: regexp.MustCompile(`(?s)`),
-
- reAttrXMLNs: regexp.MustCompile(`(?s)\s+xmlns\s*=\s*"[^"]*"`),
- reAttrSize: regexp.MustCompile(`(?s)\s+(width|height)\s*=\s*"[^"]+"`),
- reAttrClassPrefix: regexp.MustCompile(`(?s)\s+class\s*=\s*"`),
- }
- })
- data = normalizeVars.reXMLDoc.ReplaceAll(data, nil)
- data = normalizeVars.reComment.ReplaceAll(data, nil)
+ vars := globalVars()
+ data = vars.reXMLDoc.ReplaceAll(data, nil)
+ data = vars.reComment.ReplaceAll(data, nil)
data = bytes.TrimSpace(data)
svgTag, svgRemaining, ok := bytes.Cut(data, []byte(">"))
@@ -45,9 +42,9 @@ func Normalize(data []byte, size int) []byte {
return data
}
normalized := bytes.Clone(svgTag)
- normalized = normalizeVars.reAttrXMLNs.ReplaceAll(normalized, nil)
- normalized = normalizeVars.reAttrSize.ReplaceAll(normalized, nil)
- normalized = normalizeVars.reAttrClassPrefix.ReplaceAll(normalized, []byte(` class="`))
+ normalized = vars.reAttrXMLNs.ReplaceAll(normalized, nil)
+ normalized = vars.reAttrSize.ReplaceAll(normalized, nil)
+ normalized = vars.reAttrClassPrefix.ReplaceAll(normalized, []byte(` class="`))
normalized = bytes.TrimSpace(normalized)
normalized = fmt.Appendf(normalized, ` width="%d" height="%d"`, size, size)
if !bytes.Contains(normalized, []byte(` class="`)) {
diff --git a/modules/templates/helper.go b/modules/templates/helper.go
index ff9673ccef..880769dc65 100644
--- a/modules/templates/helper.go
+++ b/modules/templates/helper.go
@@ -9,7 +9,6 @@ import (
"html"
"html/template"
"net/url"
- "reflect"
"strings"
"time"
@@ -69,7 +68,7 @@ func NewFuncMap() template.FuncMap {
// -----------------------------------------------------------------
// time / number / format
"FileSize": base.FileSize,
- "CountFmt": base.FormatNumberSI,
+ "CountFmt": countFmt,
"Sec2Time": util.SecToTime,
"TimeEstimateString": timeEstimateString,
@@ -239,29 +238,8 @@ func iif(condition any, vals ...any) any {
}
func isTemplateTruthy(v any) bool {
- if v == nil {
- return false
- }
-
- rv := reflect.ValueOf(v)
- switch rv.Kind() {
- case reflect.Bool:
- return rv.Bool()
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- return rv.Int() != 0
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- return rv.Uint() != 0
- case reflect.Float32, reflect.Float64:
- return rv.Float() != 0
- case reflect.Complex64, reflect.Complex128:
- return rv.Complex() != 0
- case reflect.String, reflect.Slice, reflect.Array, reflect.Map:
- return rv.Len() > 0
- case reflect.Struct:
- return true
- default:
- return !rv.IsNil()
- }
+ truth, _ := template.IsTrue(v)
+ return truth
}
// evalTokens evaluates the expression by tokens and returns the result, see the comment of eval.Expr for details.
@@ -286,14 +264,6 @@ func userThemeName(user *user_model.User) string {
return setting.UI.DefaultTheme
}
-func timeEstimateString(timeSec any) string {
- v, _ := util.ToInt64(timeSec)
- if v == 0 {
- return ""
- }
- return util.TimeEstimateString(v)
-}
-
// QueryBuild builds a query string from a list of key-value pairs.
// It omits the nil and empty strings, but it doesn't omit other zero values,
// because the zero value of number types may have a meaning.
diff --git a/modules/templates/helper_test.go b/modules/templates/helper_test.go
index 3e17e86c66..a530d484bc 100644
--- a/modules/templates/helper_test.go
+++ b/modules/templates/helper_test.go
@@ -8,6 +8,7 @@ import (
"strings"
"testing"
+ "code.gitea.io/gitea/modules/htmlutil"
"code.gitea.io/gitea/modules/util"
"github.com/stretchr/testify/assert"
@@ -65,31 +66,12 @@ func TestSanitizeHTML(t *testing.T) {
assert.Equal(t, template.HTML(`link xss inline
`), SanitizeHTML(`link xss inline
`))
}
-func TestTemplateTruthy(t *testing.T) {
+func TestTemplateIif(t *testing.T) {
tmpl := template.New("test")
tmpl.Funcs(template.FuncMap{"Iif": iif})
template.Must(tmpl.Parse(`{{if .Value}}true{{else}}false{{end}}:{{Iif .Value "true" "false"}}`))
- cases := []any{
- nil, false, true, "", "string", 0, 1,
- byte(0), byte(1), int64(0), int64(1), float64(0), float64(1),
- complex(0, 0), complex(1, 0),
- (chan int)(nil), make(chan int),
- (func())(nil), func() {},
- util.ToPointer(0), util.ToPointer(util.ToPointer(0)),
- util.ToPointer(1), util.ToPointer(util.ToPointer(1)),
- [0]int{},
- [1]int{0},
- []int(nil),
- []int{},
- []int{0},
- map[any]any(nil),
- map[any]any{},
- map[any]any{"k": "v"},
- (*struct{})(nil),
- struct{}{},
- util.ToPointer(struct{}{}),
- }
+ cases := []any{nil, false, true, "", "string", 0, 1}
w := &strings.Builder{}
truthyCount := 0
for i, v := range cases {
@@ -102,3 +84,37 @@ func TestTemplateTruthy(t *testing.T) {
}
assert.True(t, truthyCount != 0 && truthyCount != len(cases))
}
+
+func TestTemplateEscape(t *testing.T) {
+ execTmpl := func(code string) string {
+ tmpl := template.New("test")
+ tmpl.Funcs(template.FuncMap{"QueryBuild": QueryBuild, "HTMLFormat": htmlutil.HTMLFormat})
+ template.Must(tmpl.Parse(code))
+ w := &strings.Builder{}
+ assert.NoError(t, tmpl.Execute(w, nil))
+ return w.String()
+ }
+
+ t.Run("Golang URL Escape", func(t *testing.T) {
+ // Golang template considers "href", "*src*", "*uri*", "*url*" (and more) ... attributes as contentTypeURL and does auto-escaping
+ actual := execTmpl(``)
+ assert.Equal(t, ``, actual)
+ actual = execTmpl(``)
+ assert.Equal(t, ``, actual)
+ })
+ t.Run("Golang URL No-escape", func(t *testing.T) {
+ // non-URL content isn't auto-escaped
+ actual := execTmpl(``)
+ assert.Equal(t, ``, actual)
+ })
+ t.Run("QueryBuild", func(t *testing.T) {
+ actual := execTmpl(``)
+ assert.Equal(t, ``, actual)
+ actual = execTmpl(``)
+ assert.Equal(t, ``, actual)
+ })
+ t.Run("HTMLFormat", func(t *testing.T) {
+ actual := execTmpl("{{HTMLFormat `%s` `\"` `<>`}}")
+ assert.Equal(t, `<>`, actual)
+ })
+}
diff --git a/modules/templates/htmlrenderer.go b/modules/templates/htmlrenderer.go
index e7e805ed30..529284f7e8 100644
--- a/modules/templates/htmlrenderer.go
+++ b/modules/templates/htmlrenderer.go
@@ -29,6 +29,8 @@ import (
type TemplateExecutor scopedtmpl.TemplateExecutor
+type TplName string
+
type HTMLRender struct {
templates atomic.Pointer[scopedtmpl.ScopedTemplate]
}
@@ -40,7 +42,8 @@ var (
var ErrTemplateNotInitialized = errors.New("template system is not initialized, check your log for errors")
-func (h *HTMLRender) HTML(w io.Writer, status int, name string, data any, ctx context.Context) error { //nolint:revive
+func (h *HTMLRender) HTML(w io.Writer, status int, tplName TplName, data any, ctx context.Context) error { //nolint:revive
+ name := string(tplName)
if respWriter, ok := w.(http.ResponseWriter); ok {
if respWriter.Header().Get("Content-Type") == "" {
respWriter.Header().Set("Content-Type", "text/html; charset=utf-8")
diff --git a/modules/templates/util_format.go b/modules/templates/util_format.go
new file mode 100644
index 0000000000..bee6fb7b75
--- /dev/null
+++ b/modules/templates/util_format.go
@@ -0,0 +1,37 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package templates
+
+import (
+ "fmt"
+
+ "code.gitea.io/gitea/modules/util"
+)
+
+func timeEstimateString(timeSec any) string {
+ v, _ := util.ToInt64(timeSec)
+ if v == 0 {
+ return ""
+ }
+ return util.TimeEstimateString(v)
+}
+
+func countFmt(data any) string {
+ // legacy code, not ideal, still used in some places
+ num, err := util.ToInt64(data)
+ if err != nil {
+ return ""
+ }
+ if num < 1000 {
+ return fmt.Sprintf("%d", num)
+ } else if num < 1_000_000 {
+ num2 := float32(num) / 1000.0
+ return fmt.Sprintf("%.1fk", num2)
+ } else if num < 1_000_000_000 {
+ num2 := float32(num) / 1_000_000.0
+ return fmt.Sprintf("%.1fM", num2)
+ }
+ num2 := float32(num) / 1_000_000_000.0
+ return fmt.Sprintf("%.1fG", num2)
+}
diff --git a/modules/templates/util_format_test.go b/modules/templates/util_format_test.go
new file mode 100644
index 0000000000..8d466faff0
--- /dev/null
+++ b/modules/templates/util_format_test.go
@@ -0,0 +1,18 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package templates
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestCountFmt(t *testing.T) {
+ assert.Equal(t, "125", countFmt(125))
+ assert.Equal(t, "1.3k", countFmt(int64(1317)))
+ assert.Equal(t, "21.3M", countFmt(21317675))
+ assert.Equal(t, "45.7G", countFmt(45721317675))
+ assert.Equal(t, "", countFmt("test"))
+}
diff --git a/modules/test/utils.go b/modules/test/utils.go
index 8dee92fbce..ec4c976388 100644
--- a/modules/test/utils.go
+++ b/modules/test/utils.go
@@ -4,11 +4,16 @@
package test
import (
+ "fmt"
"net/http"
"net/http/httptest"
+ "os"
+ "path/filepath"
+ "runtime"
"strings"
"code.gitea.io/gitea/modules/json"
+ "code.gitea.io/gitea/modules/util"
)
// RedirectURL returns the redirect URL of a http response.
@@ -41,3 +46,19 @@ func MockVariableValue[T any](p *T, v ...T) (reset func()) {
}
return func() { *p = old }
}
+
+// SetupGiteaRoot Sets GITEA_ROOT if it is not already set and returns the value
+func SetupGiteaRoot() string {
+ giteaRoot := os.Getenv("GITEA_ROOT")
+ if giteaRoot != "" {
+ return giteaRoot
+ }
+ _, filename, _, _ := runtime.Caller(0)
+ giteaRoot = filepath.Dir(filepath.Dir(filepath.Dir(filename)))
+ fixturesDir := filepath.Join(giteaRoot, "models", "fixtures")
+ if exist, _ := util.IsDir(fixturesDir); !exist {
+ panic(fmt.Sprintf("fixtures directory not found: %s", fixturesDir))
+ }
+ _ = os.Setenv("GITEA_ROOT", giteaRoot)
+ return giteaRoot
+}
diff --git a/modules/test/utils_test.go b/modules/test/utils_test.go
new file mode 100644
index 0000000000..0469ce97f2
--- /dev/null
+++ b/modules/test/utils_test.go
@@ -0,0 +1,17 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package test
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestSetupGiteaRoot(t *testing.T) {
+ t.Setenv("GITEA_ROOT", "test")
+ assert.Equal(t, "test", SetupGiteaRoot())
+ t.Setenv("GITEA_ROOT", "")
+ assert.NotEqual(t, "test", SetupGiteaRoot())
+}
diff --git a/modules/util/runtime.go b/modules/util/runtime.go
new file mode 100644
index 0000000000..91ec3c869c
--- /dev/null
+++ b/modules/util/runtime.go
@@ -0,0 +1,13 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package util
+
+import "runtime"
+
+func CallerFuncName(skip int) string {
+ pc := make([]uintptr, 1)
+ runtime.Callers(skip+1, pc)
+ funcName := runtime.FuncForPC(pc[0]).Name()
+ return funcName
+}
diff --git a/modules/util/runtime_test.go b/modules/util/runtime_test.go
new file mode 100644
index 0000000000..20f9063b0b
--- /dev/null
+++ b/modules/util/runtime_test.go
@@ -0,0 +1,32 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package util
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestCallerFuncName(t *testing.T) {
+ s := CallerFuncName(1)
+ assert.Equal(t, "code.gitea.io/gitea/modules/util.TestCallerFuncName", s)
+}
+
+func BenchmarkCallerFuncName(b *testing.B) {
+ // BenchmarkCaller/sprintf-12 12744829 95.49 ns/op
+ b.Run("sprintf", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ _ = fmt.Sprintf("aaaaaaaaaaaaaaaa %s %s %s", "bbbbbbbbbbbbbbbbbbb", b.Name(), "ccccccccccccccccccccc")
+ }
+ })
+ // BenchmarkCaller/caller-12 10625133 113.6 ns/op
+ // It is almost as fast as fmt.Sprintf
+ b.Run("caller", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ CallerFuncName(1)
+ }
+ })
+}
diff --git a/modules/util/time_str.go b/modules/util/time_str.go
index b56f4740af..0fccfe82cc 100644
--- a/modules/util/time_str.go
+++ b/modules/util/time_str.go
@@ -25,7 +25,7 @@ type timeStrGlobalVarsType struct {
// In the future, it could be some configurable options to help users
// to convert the working time to different units.
-var timeStrGlobalVars = sync.OnceValue[*timeStrGlobalVarsType](func() *timeStrGlobalVarsType {
+var timeStrGlobalVars = sync.OnceValue(func() *timeStrGlobalVarsType {
v := &timeStrGlobalVarsType{}
v.re = regexp.MustCompile(`(?i)(\d+)\s*([hms])`)
v.units = []struct {
diff --git a/modules/util/util_test.go b/modules/util/util_test.go
index 5abce08b41..52b05acc5b 100644
--- a/modules/util/util_test.go
+++ b/modules/util/util_test.go
@@ -242,10 +242,10 @@ func TestReserveLineBreakForTextarea(t *testing.T) {
}
func TestOptionalArg(t *testing.T) {
- foo := func(other any, optArg ...int) int {
+ foo := func(_ any, optArg ...int) int {
return OptionalArg(optArg)
}
- bar := func(other any, optArg ...int) int {
+ bar := func(_ any, optArg ...int) int {
return OptionalArg(optArg, 42)
}
assert.Equal(t, 0, foo(nil))
diff --git a/modules/web/handler.go b/modules/web/handler.go
index 1812c664b3..9a3e4a7f17 100644
--- a/modules/web/handler.go
+++ b/modules/web/handler.go
@@ -4,7 +4,6 @@
package web
import (
- goctx "context"
"fmt"
"net/http"
"reflect"
@@ -51,7 +50,6 @@ func (r *responseWriter) WriteHeader(statusCode int) {
var (
httpReqType = reflect.TypeOf((*http.Request)(nil))
respWriterType = reflect.TypeOf((*http.ResponseWriter)(nil)).Elem()
- cancelFuncType = reflect.TypeOf((*goctx.CancelFunc)(nil)).Elem()
)
// preCheckHandler checks whether the handler is valid, developers could get first-time feedback, all mistakes could be found at startup
@@ -65,11 +63,8 @@ func preCheckHandler(fn reflect.Value, argsIn []reflect.Value) {
if !hasStatusProvider {
panic(fmt.Sprintf("handler should have at least one ResponseStatusProvider argument, but got %s", fn.Type()))
}
- if fn.Type().NumOut() != 0 && fn.Type().NumIn() != 1 {
- panic(fmt.Sprintf("handler should have no return value or only one argument, but got %s", fn.Type()))
- }
- if fn.Type().NumOut() == 1 && fn.Type().Out(0) != cancelFuncType {
- panic(fmt.Sprintf("handler should return a cancel function, but got %s", fn.Type()))
+ if fn.Type().NumOut() != 0 {
+ panic(fmt.Sprintf("handler should have no return value other than registered ones, but got %s", fn.Type()))
}
}
@@ -105,16 +100,10 @@ func prepareHandleArgsIn(resp http.ResponseWriter, req *http.Request, fn reflect
return argsIn
}
-func handleResponse(fn reflect.Value, ret []reflect.Value) goctx.CancelFunc {
- if len(ret) == 1 {
- if cancelFunc, ok := ret[0].Interface().(goctx.CancelFunc); ok {
- return cancelFunc
- }
- panic(fmt.Sprintf("unsupported return type: %s", ret[0].Type()))
- } else if len(ret) > 1 {
+func handleResponse(fn reflect.Value, ret []reflect.Value) {
+ if len(ret) != 0 {
panic(fmt.Sprintf("unsupported return values: %s", fn.Type()))
}
- return nil
}
func hasResponseBeenWritten(argsIn []reflect.Value) bool {
@@ -171,11 +160,8 @@ func toHandlerProvider(handler any) func(next http.Handler) http.Handler {
routing.UpdateFuncInfo(req.Context(), funcInfo)
ret := fn.Call(argsIn)
- // handle the return value, and defer the cancel function if there is one
- cancelFunc := handleResponse(fn, ret)
- if cancelFunc != nil {
- defer cancelFunc()
- }
+ // handle the return value (no-op at the moment)
+ handleResponse(fn, ret)
// if the response has not been written, call the next handler
if next != nil && !hasResponseBeenWritten(argsIn) {
diff --git a/modules/web/middleware/data.go b/modules/web/middleware/data.go
index 08d83f94be..a47da0f836 100644
--- a/modules/web/middleware/data.go
+++ b/modules/web/middleware/data.go
@@ -7,46 +7,21 @@ import (
"context"
"time"
+ "code.gitea.io/gitea/modules/reqctx"
"code.gitea.io/gitea/modules/setting"
)
-// ContextDataStore represents a data store
-type ContextDataStore interface {
- GetData() ContextData
-}
-
-type ContextData map[string]any
-
-func (ds ContextData) GetData() ContextData {
- return ds
-}
-
-func (ds ContextData) MergeFrom(other ContextData) ContextData {
- for k, v := range other {
- ds[k] = v
- }
- return ds
-}
-
const ContextDataKeySignedUser = "SignedUser"
-type contextDataKeyType struct{}
-
-var contextDataKey contextDataKeyType
-
-func WithContextData(c context.Context) context.Context {
- return context.WithValue(c, contextDataKey, make(ContextData, 10))
-}
-
-func GetContextData(c context.Context) ContextData {
- if ds, ok := c.Value(contextDataKey).(ContextData); ok {
- return ds
+func GetContextData(c context.Context) reqctx.ContextData {
+ if rc := reqctx.GetRequestDataStore(c); rc != nil {
+ return rc.GetData()
}
return nil
}
-func CommonTemplateContextData() ContextData {
- return ContextData{
+func CommonTemplateContextData() reqctx.ContextData {
+ return reqctx.ContextData{
"IsLandingPageOrganizations": setting.LandingPageURL == setting.LandingPageOrganizations,
"ShowRegistrationButton": setting.Service.ShowRegistrationButton,
diff --git a/modules/web/middleware/flash.go b/modules/web/middleware/flash.go
index 88da2049a4..0caaa8c036 100644
--- a/modules/web/middleware/flash.go
+++ b/modules/web/middleware/flash.go
@@ -7,11 +7,13 @@ import (
"fmt"
"html/template"
"net/url"
+
+ "code.gitea.io/gitea/modules/reqctx"
)
// Flash represents a one time data transfer between two requests.
type Flash struct {
- DataStore ContextDataStore
+ DataStore reqctx.RequestDataStore
url.Values
ErrorMsg, WarningMsg, InfoMsg, SuccessMsg string
}
diff --git a/modules/web/route.go b/modules/web/route.go
index 787521dfb0..533ac3eaf1 100644
--- a/modules/web/route.go
+++ b/modules/web/route.go
@@ -10,6 +10,7 @@ import (
"strings"
"code.gitea.io/gitea/modules/htmlutil"
+ "code.gitea.io/gitea/modules/reqctx"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web/middleware"
@@ -29,12 +30,12 @@ func Bind[T any](_ T) http.HandlerFunc {
}
// SetForm set the form object
-func SetForm(dataStore middleware.ContextDataStore, obj any) {
+func SetForm(dataStore reqctx.ContextDataProvider, obj any) {
dataStore.GetData()["__form"] = obj
}
// GetForm returns the validate form information
-func GetForm(dataStore middleware.ContextDataStore) any {
+func GetForm(dataStore reqctx.RequestDataStore) any {
return dataStore.GetData()["__form"]
}
diff --git a/options/gitignore/AutomationStudio b/options/gitignore/AutomationStudio
new file mode 100644
index 0000000000..b5552b17a0
--- /dev/null
+++ b/options/gitignore/AutomationStudio
@@ -0,0 +1,31 @@
+# gitignore template for B&R Automation Studio (AS) 4
+# website: https://www.br-automation.com/en-us/products/software/automation-software/automation-studio/
+
+# AS temporary directories
+Binaries/
+Diagnosis/
+Temp/
+TempObjects/
+
+# AS transfer files
+*artransfer.br
+*arTrsfmode.nv
+
+# 'ignored' directory
+ignored/
+
+# ARNC0ext
+*arnc0ext.br
+
+# AS File types
+*.bak
+*.isopen
+*.orig
+*.log
+*.asar
+*.csvlog*
+*.set
+!**/Physical/**/*.set
+
+# RevInfo variables
+*RevInfo.var
diff --git a/options/gitignore/Firebase b/options/gitignore/Firebase
new file mode 100644
index 0000000000..55b8b0ea7f
--- /dev/null
+++ b/options/gitignore/Firebase
@@ -0,0 +1,28 @@
+# Firebase build and deployment files
+/firebase-debug.log
+/firebase-debug.*.log
+.firebaserc
+
+# Firebase Hosting
+/firebase.json
+*.cache
+hosting/.cache
+
+# Firebase Functions
+/functions/node_modules/
+/functions/.env
+/functions/package-lock.json
+
+# Firebase Emulators
+/firebase-*.zip
+/.firebase/
+/emulator-ui/
+
+# Logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Environment files (local configs)
+/.env.*
diff --git a/options/gitignore/Modelica b/options/gitignore/Modelica
new file mode 100644
index 0000000000..aa2cc996da
--- /dev/null
+++ b/options/gitignore/Modelica
@@ -0,0 +1,42 @@
+# Modelica - an object-oriented language for modeling of cyber-physical systems
+# https://modelica.org/
+# Ignore temporary files, build results, simulation files
+
+## Modelica-specific files
+*~
+*.bak
+*.bak-mo
+*.mof
+\#*\#
+*.moe
+*.mol
+
+## Build artefacts
+*.exe
+*.exp
+*.o
+*.pyc
+
+## Simulation files
+*.mat
+
+## Package files
+*.gz
+*.rar
+*.tar
+*.zip
+
+## Dymola-specific files
+buildlog.txt
+dsfinal.txt
+dsin.txt
+dslog.txt
+dsmodel*
+dsres.txt
+dymosim*
+request
+stat
+status
+stop
+success
+*.
diff --git a/options/gitignore/Python b/options/gitignore/Python
index c2fb773388..15201acc11 100644
--- a/options/gitignore/Python
+++ b/options/gitignore/Python
@@ -166,3 +166,6 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
+
+# PyPI configuration file
+.pypirc
diff --git a/options/gitignore/TeX b/options/gitignore/TeX
index a1f5212090..45e1706c28 100644
--- a/options/gitignore/TeX
+++ b/options/gitignore/TeX
@@ -26,6 +26,7 @@
## Bibliography auxiliary files (bibtex/biblatex/biber):
*.bbl
+*.bbl-SAVE-ERROR
*.bcf
*.blg
*-blx.aux
diff --git a/options/license/Elastic-2.0 b/options/license/Elastic-2.0
index 809108b857..9496955678 100644
--- a/options/license/Elastic-2.0
+++ b/options/license/Elastic-2.0
@@ -2,18 +2,18 @@ Elastic License 2.0
URL: https://www.elastic.co/licensing/elastic-license
-## Acceptance
+Acceptance
By using the software, you agree to all of the terms and conditions below.
-## Copyright License
+Copyright License
The licensor grants you a non-exclusive, royalty-free, worldwide,
non-sublicensable, non-transferable license to use, copy, distribute, make
available, and prepare derivative works of the software, in each case subject to
the limitations and conditions below.
-## Limitations
+Limitations
You may not provide the software to third parties as a hosted or managed
service, where the service provides users with access to any substantial set of
@@ -27,7 +27,7 @@ You may not alter, remove, or obscure any licensing, copyright, or other notices
of the licensor in the software. Any use of the licensor’s trademarks is subject
to applicable law.
-## Patents
+Patents
The licensor grants you a license, under any patent claims the licensor can
license, or becomes able to license, to make, have made, use, sell, offer for
@@ -40,7 +40,7 @@ the software granted under these terms ends immediately. If your company makes
such a claim, your patent license ends immediately for work on behalf of your
company.
-## Notices
+Notices
You must ensure that anyone who gets a copy of any part of the software from you
also gets a copy of these terms.
@@ -53,7 +53,7 @@ software prominent notices stating that you have modified the software.
These terms do not imply any licenses other than those expressly granted in
these terms.
-## Termination
+Termination
If you use the software in violation of these terms, such use is not licensed,
and your licenses will automatically terminate. If the licensor provides you
@@ -63,31 +63,31 @@ reinstated retroactively. However, if you violate these terms after such
reinstatement, any additional violation of these terms will cause your licenses
to terminate automatically and permanently.
-## No Liability
+No Liability
-*As far as the law allows, the software comes as is, without any warranty or
+As far as the law allows, the software comes as is, without any warranty or
condition, and the licensor will not be liable to you for any damages arising
out of these terms or the use or nature of the software, under any kind of
-legal claim.*
+legal claim.
-## Definitions
+Definitions
-The **licensor** is the entity offering these terms, and the **software** is the
+The licensor is the entity offering these terms, and the software is the
software the licensor makes available under these terms, including any portion
of it.
-**you** refers to the individual or entity agreeing to these terms.
+you refers to the individual or entity agreeing to these terms.
-**your company** is any legal entity, sole proprietorship, or other kind of
+your company is any legal entity, sole proprietorship, or other kind of
organization that you work for, plus all organizations that have control over,
are under the control of, or are under common control with that
-organization. **control** means ownership of substantially all the assets of an
+organization. control means ownership of substantially all the assets of an
entity, or the power to direct its management and policies by vote, contract, or
otherwise. Control can be direct or indirect.
-**your licenses** are all the licenses granted to you for the software under
+your licenses are all the licenses granted to you for the software under
these terms.
-**use** means anything you do with the software requiring one of your licenses.
+use means anything you do with the software requiring one of your licenses.
-**trademark** means trademarks, service marks, and similar rights.
+trademark means trademarks, service marks, and similar rights.
diff --git a/options/license/MIT b/options/license/MIT
index 2071b23b0e..fc2cf8e6b6 100644
--- a/options/license/MIT
+++ b/options/license/MIT
@@ -2,8 +2,17 @@ MIT License
Copyright (c)
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
+following conditions:
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+The above copyright notice and this permission notice shall be included in all copies or substantial
+portions of the Software.
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
+EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/options/locale/locale_cs-CZ.ini b/options/locale/locale_cs-CZ.ini
index 2abe3672cd..3c7e247d13 100644
--- a/options/locale/locale_cs-CZ.ini
+++ b/options/locale/locale_cs-CZ.ini
@@ -3742,6 +3742,7 @@ variables.creation.success=Proměnná „%s“ byla přidána.
variables.update.failed=Úprava proměnné se nezdařila.
variables.update.success=Proměnná byla upravena.
+
[projects]
deleted.display_name=Odstraněný projekt
type-1.display_name=Samostatný projekt
diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini
index c8dd3f71a2..78bfb26d73 100644
--- a/options/locale/locale_de-DE.ini
+++ b/options/locale/locale_de-DE.ini
@@ -3556,6 +3556,7 @@ variables.creation.success=Die Variable „%s“ wurde hinzugefügt.
variables.update.failed=Fehler beim Bearbeiten der Variable.
variables.update.success=Die Variable wurde bearbeitet.
+
[projects]
type-1.display_name=Individuelles Projekt
type-2.display_name=Repository-Projekt
diff --git a/options/locale/locale_el-GR.ini b/options/locale/locale_el-GR.ini
index 193441828a..db7b3ffae3 100644
--- a/options/locale/locale_el-GR.ini
+++ b/options/locale/locale_el-GR.ini
@@ -3439,6 +3439,7 @@ variables.creation.success=Η μεταβλητή "%s" έχει προστεθε
variables.update.failed=Αποτυχία επεξεργασίας μεταβλητής.
variables.update.success=Η μεταβλητή έχει τροποποιηθεί.
+
[projects]
type-1.display_name=Ατομικό Έργο
type-2.display_name=Έργο Αποθετηρίου
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index 92ce4f2db9..ea4d36fb1c 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -1946,8 +1946,8 @@ pulls.delete.title = Delete this pull request?
pulls.delete.text = Do you really want to delete this pull request? (This will permanently remove all content. Consider closing it instead, if you intend to keep it archived)
pulls.recently_pushed_new_branches = You pushed on branch %[1]s %[2]s
-pulls.upstream_diverging_prompt_behind_1 = This branch is %d commit behind %s
-pulls.upstream_diverging_prompt_behind_n = This branch is %d commits behind %s
+pulls.upstream_diverging_prompt_behind_1 = This branch is %[1]d commit behind %[2]s
+pulls.upstream_diverging_prompt_behind_n = This branch is %[1]d commits behind %[2]s
pulls.upstream_diverging_prompt_base_newer = The base branch %s has new changes
pulls.upstream_diverging_merge = Sync fork
@@ -3722,6 +3722,7 @@ runners.status.active = Active
runners.status.offline = Offline
runners.version = Version
runners.reset_registration_token = Reset registration token
+runners.reset_registration_token_confirm = Would you like to invalidate the current token and generate a new one?
runners.reset_registration_token_success = Runner registration token reset successfully
runs.all_workflows = All Workflows
@@ -3773,6 +3774,9 @@ variables.creation.success = The variable "%s" has been added.
variables.update.failed = Failed to edit variable.
variables.update.success = The variable has been edited.
+logs.always_auto_scroll = Always auto scroll logs
+logs.always_expand_running = Always expand running logs
+
[projects]
deleted.display_name = Deleted Project
type-1.display_name = Individual Project
diff --git a/options/locale/locale_es-ES.ini b/options/locale/locale_es-ES.ini
index e95513766b..010bee186d 100644
--- a/options/locale/locale_es-ES.ini
+++ b/options/locale/locale_es-ES.ini
@@ -3415,6 +3415,7 @@ variables.creation.success=La variable "%s" ha sido añadida.
variables.update.failed=Error al editar la variable.
variables.update.success=La variable ha sido editada.
+
[projects]
type-1.display_name=Proyecto individual
type-2.display_name=Proyecto repositorio
diff --git a/options/locale/locale_fa-IR.ini b/options/locale/locale_fa-IR.ini
index 640592f2bf..b92361db34 100644
--- a/options/locale/locale_fa-IR.ini
+++ b/options/locale/locale_fa-IR.ini
@@ -2529,6 +2529,7 @@ runs.commit=کامیت
+
[projects]
[git.filemode]
diff --git a/options/locale/locale_fi-FI.ini b/options/locale/locale_fi-FI.ini
index 375c7b11bf..b4f3869db4 100644
--- a/options/locale/locale_fi-FI.ini
+++ b/options/locale/locale_fi-FI.ini
@@ -1707,6 +1707,7 @@ runs.commit=Commit
+
[projects]
[git.filemode]
diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini
index 08a40a2494..0898d0fd29 100644
--- a/options/locale/locale_fr-FR.ini
+++ b/options/locale/locale_fr-FR.ini
@@ -3772,6 +3772,7 @@ variables.creation.success=La variable « %s » a été ajoutée.
variables.update.failed=Impossible d’éditer la variable.
variables.update.success=La variable a bien été modifiée.
+
[projects]
deleted.display_name=Projet supprimé
type-1.display_name=Projet personnel
diff --git a/options/locale/locale_ga-IE.ini b/options/locale/locale_ga-IE.ini
index c37c8e0157..20672569ac 100644
--- a/options/locale/locale_ga-IE.ini
+++ b/options/locale/locale_ga-IE.ini
@@ -1945,8 +1945,6 @@ pulls.delete.title=Scrios an t-iarratas tarraingthe seo?
pulls.delete.text=An bhfuil tú cinnte gur mhaith leat an t-iarratas tarraingthe seo a scriosadh? (Bainfidh sé seo an t-inneachar go léir go buan. Smaoinigh ar é a dhúnadh ina ionad sin, má tá sé i gceist agat é a choinneáil i gcartlann)
pulls.recently_pushed_new_branches=Bhrúigh tú ar bhrainse %[1]s %[2]s
-pulls.upstream_diverging_prompt_behind_1=Tá an brainse seo %d tiomantas taobh thiar de %s
-pulls.upstream_diverging_prompt_behind_n=Tá an brainse seo %d geallta taobh thiar de %s
pulls.upstream_diverging_prompt_base_newer=Tá athruithe nua ar an mbunbhrainse %s
pulls.upstream_diverging_merge=Forc sionc
@@ -3772,6 +3770,7 @@ variables.creation.success=Tá an athróg "%s" curtha leis.
variables.update.failed=Theip ar athróg a chur in eagar.
variables.update.success=Tá an t-athróg curtha in eagar.
+
[projects]
deleted.display_name=Tionscadal scriosta
type-1.display_name=Tionscadal Aonair
diff --git a/options/locale/locale_hu-HU.ini b/options/locale/locale_hu-HU.ini
index 88ccc9fac2..8e11f07d33 100644
--- a/options/locale/locale_hu-HU.ini
+++ b/options/locale/locale_hu-HU.ini
@@ -1615,6 +1615,7 @@ runs.commit=Commit
+
[projects]
[git.filemode]
diff --git a/options/locale/locale_id-ID.ini b/options/locale/locale_id-ID.ini
index 00a406aae4..7c8271b98b 100644
--- a/options/locale/locale_id-ID.ini
+++ b/options/locale/locale_id-ID.ini
@@ -1444,6 +1444,7 @@ variables.creation.success=Variabel "%s" telah ditambahkan.
variables.update.failed=Gagal mengedit variabel.
variables.update.success=Variabel telah diedit.
+
[projects]
type-1.display_name=Proyek Individu
type-2.display_name=Proyek Repositori
diff --git a/options/locale/locale_is-IS.ini b/options/locale/locale_is-IS.ini
index 0564d49b1c..d3824f83a2 100644
--- a/options/locale/locale_is-IS.ini
+++ b/options/locale/locale_is-IS.ini
@@ -1342,6 +1342,7 @@ runs.commit=Framlag
+
[projects]
[git.filemode]
diff --git a/options/locale/locale_it-IT.ini b/options/locale/locale_it-IT.ini
index 567e6acdce..26b4f9e27b 100644
--- a/options/locale/locale_it-IT.ini
+++ b/options/locale/locale_it-IT.ini
@@ -2807,6 +2807,7 @@ runs.commit=Commit
+
[projects]
[git.filemode]
diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini
index 2c84302f83..da07d77825 100644
--- a/options/locale/locale_ja-JP.ini
+++ b/options/locale/locale_ja-JP.ini
@@ -1669,12 +1669,25 @@ issues.delete.title=このイシューを削除しますか?
issues.delete.text=本当にこのイシューを削除しますか? (これはすべてのコンテンツを完全に削除します。 保存しておきたい場合は、代わりにクローズすることを検討してください)
issues.tracker=タイムトラッカー
+issues.timetracker_timer_start=タイマー開始
+issues.timetracker_timer_stop=タイマー終了
+issues.timetracker_timer_discard=タイマー破棄
+issues.timetracker_timer_manually_add=時間を追加
+issues.time_estimate_set=見積時間を設定
+issues.time_estimate_display=見積時間: %s
+issues.change_time_estimate_at=が見積時間を %s に変更 %s
+issues.remove_time_estimate_at=が見積時間を削除 %s
+issues.time_estimate_invalid=見積時間のフォーマットが不正です
+issues.start_tracking_history=が作業を開始 %s
issues.tracker_auto_close=タイマーは、このイシューがクローズされると自動的に終了します
issues.tracking_already_started=`別のイシューで既にタイムトラッキングを開始しています!`
+issues.stop_tracking_history=が %s の作業を終了 %s
issues.cancel_tracking_history=`がタイムトラッキングを中止 %s`
issues.del_time=このタイムログを削除
+issues.add_time_history=が作業時間 %s を追加 %s
issues.del_time_history=`が作業時間を削除 %s`
+issues.add_time_manually=時間の手入力
issues.add_time_hours=時間
issues.add_time_minutes=分
issues.add_time_sum_to_small=時間が入力されていません。
@@ -1694,15 +1707,15 @@ issues.due_date_form_add=期日の追加
issues.due_date_form_edit=変更
issues.due_date_form_remove=削除
issues.due_date_not_writer=イシューの期日を変更するには、リポジトリへの書き込み権限が必要です。
-issues.due_date_not_set=期日は未設定です。
+issues.due_date_not_set=期日は設定されていません。
issues.due_date_added=が期日 %s を追加 %s
issues.due_date_modified=が期日を %[2]s から %[1]s に変更 %[3]s
issues.due_date_remove=が期日 %s を削除 %s
issues.due_date_overdue=期日は過ぎています
issues.due_date_invalid=期日が正しくないか範囲を超えています。 'yyyy-mm-dd' の形式で入力してください。
issues.dependency.title=依存関係
-issues.dependency.issue_no_dependencies=依存関係が設定されていません。
-issues.dependency.pr_no_dependencies=依存関係が設定されていません。
+issues.dependency.issue_no_dependencies=依存関係は設定されていません。
+issues.dependency.pr_no_dependencies=依存関係は設定されていません。
issues.dependency.no_permission_1=%d 個の依存関係への読み取り権限がありません
issues.dependency.no_permission_n=%d 個の依存関係への読み取り権限がありません
issues.dependency.no_permission.can_remove=この依存関係への読み取り権限はありませんが、この依存関係は削除できます
@@ -1927,8 +1940,6 @@ pulls.delete.title=このプルリクエストを削除しますか?
pulls.delete.text=本当にこのプルリクエストを削除しますか? (これはすべてのコンテンツを完全に削除します。 保存しておきたい場合は、代わりにクローズすることを検討してください)
pulls.recently_pushed_new_branches=%[2]s 、あなたはブランチ %[1]s にプッシュしました
-pulls.upstream_diverging_prompt_behind_1=このブランチは %[2]s よりも %[1]d コミット遅れています
-pulls.upstream_diverging_prompt_behind_n=このブランチは %[2]s よりも %[1]d コミット遅れています
pulls.upstream_diverging_prompt_base_newer=ベースブランチ %s に新しい変更があります
pulls.upstream_diverging_merge=フォークを同期
@@ -3751,6 +3762,7 @@ variables.creation.success=変数 "%s" を追加しました。
variables.update.failed=変数を更新できませんでした。
variables.update.success=変数を更新しました。
+
[projects]
deleted.display_name=削除されたプロジェクト
type-1.display_name=個人プロジェクト
diff --git a/options/locale/locale_ko-KR.ini b/options/locale/locale_ko-KR.ini
index 48220d5c99..361ab23e4c 100644
--- a/options/locale/locale_ko-KR.ini
+++ b/options/locale/locale_ko-KR.ini
@@ -1563,6 +1563,7 @@ runs.commit=커밋
+
[projects]
[git.filemode]
diff --git a/options/locale/locale_lv-LV.ini b/options/locale/locale_lv-LV.ini
index fd412b95b4..27a061d722 100644
--- a/options/locale/locale_lv-LV.ini
+++ b/options/locale/locale_lv-LV.ini
@@ -3443,6 +3443,7 @@ variables.creation.success=Mainīgais "%s" tika pievienots.
variables.update.failed=Neizdevās labot mainīgo.
variables.update.success=Mainīgais tika labots.
+
[projects]
type-1.display_name=Individuālais projekts
type-2.display_name=Repozitorija projekts
diff --git a/options/locale/locale_nl-NL.ini b/options/locale/locale_nl-NL.ini
index a4da8177bc..5c07b521e9 100644
--- a/options/locale/locale_nl-NL.ini
+++ b/options/locale/locale_nl-NL.ini
@@ -2537,6 +2537,7 @@ runs.commit=Commit
+
[projects]
[git.filemode]
diff --git a/options/locale/locale_pl-PL.ini b/options/locale/locale_pl-PL.ini
index 22f701219d..13c05eebe0 100644
--- a/options/locale/locale_pl-PL.ini
+++ b/options/locale/locale_pl-PL.ini
@@ -2430,6 +2430,7 @@ runs.commit=Commit
+
[projects]
[git.filemode]
diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini
index 8fb869898b..c053b33210 100644
--- a/options/locale/locale_pt-BR.ini
+++ b/options/locale/locale_pt-BR.ini
@@ -3353,6 +3353,7 @@ runs.empty_commit_message=(mensagem de commit vazia)
need_approval_desc=Precisa de aprovação para executar workflows para pull request do fork.
+
[projects]
type-1.display_name=Projeto individual
type-2.display_name=Projeto do repositório
diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini
index b959e7fdba..13e7318c6f 100644
--- a/options/locale/locale_pt-PT.ini
+++ b/options/locale/locale_pt-PT.ini
@@ -1945,8 +1945,6 @@ pulls.delete.title=Eliminar este pedido de integração?
pulls.delete.text=Tem a certeza que quer eliminar este pedido de integração? Isso irá remover todo o conteúdo permanentemente. Como alternativa considere fechá-lo, se pretender mantê-lo em arquivo.
pulls.recently_pushed_new_branches=Enviou para o ramo %[1]s %[2]s
-pulls.upstream_diverging_prompt_behind_1=Este ramo está %d cometimento atrás de %s
-pulls.upstream_diverging_prompt_behind_n=Este ramo está %d cometimentos atrás de %s
pulls.upstream_diverging_prompt_base_newer=O ramo base %s tem novas modificações
pulls.upstream_diverging_merge=Sincronizar derivação
@@ -3772,6 +3770,9 @@ variables.creation.success=A variável "%s" foi adicionada.
variables.update.failed=Falha ao editar a variável.
variables.update.success=A variável foi editada.
+logs.always_auto_scroll=Rolar registos de forma automática e permanente
+logs.always_expand_running=Expandir sempre os registos que vão rolando
+
[projects]
deleted.display_name=Planeamento eliminado
type-1.display_name=Planeamento individual
diff --git a/options/locale/locale_ru-RU.ini b/options/locale/locale_ru-RU.ini
index 735077bd41..0662c1f5f9 100644
--- a/options/locale/locale_ru-RU.ini
+++ b/options/locale/locale_ru-RU.ini
@@ -3373,6 +3373,7 @@ variables.creation.success=Переменная «%s» добавлена.
variables.update.failed=Не удалось изменить переменную.
variables.update.success=Переменная изменена.
+
[projects]
type-1.display_name=Индивидуальный проект
type-2.display_name=Проект репозитория
diff --git a/options/locale/locale_si-LK.ini b/options/locale/locale_si-LK.ini
index 506fa5b492..debcf8e3e9 100644
--- a/options/locale/locale_si-LK.ini
+++ b/options/locale/locale_si-LK.ini
@@ -2470,6 +2470,7 @@ runs.commit=කැප
+
[projects]
[git.filemode]
diff --git a/options/locale/locale_sk-SK.ini b/options/locale/locale_sk-SK.ini
index b4bf6fb552..39c13c358e 100644
--- a/options/locale/locale_sk-SK.ini
+++ b/options/locale/locale_sk-SK.ini
@@ -1328,6 +1328,7 @@ runners.labels=Štítky
+
[projects]
[git.filemode]
diff --git a/options/locale/locale_sv-SE.ini b/options/locale/locale_sv-SE.ini
index fc138381db..2fd8277b76 100644
--- a/options/locale/locale_sv-SE.ini
+++ b/options/locale/locale_sv-SE.ini
@@ -2005,6 +2005,7 @@ runs.commit=Commit
+
[projects]
[git.filemode]
diff --git a/options/locale/locale_tr-TR.ini b/options/locale/locale_tr-TR.ini
index 9b7f2cb5c6..d17985dba5 100644
--- a/options/locale/locale_tr-TR.ini
+++ b/options/locale/locale_tr-TR.ini
@@ -3633,6 +3633,7 @@ variables.creation.success=`"%s" değişkeni eklendi.`
variables.update.failed=Değişken düzenlenemedi.
variables.update.success=Değişken düzenlendi.
+
[projects]
deleted.display_name=Silinmiş Proje
type-1.display_name=Kişisel Proje
diff --git a/options/locale/locale_uk-UA.ini b/options/locale/locale_uk-UA.ini
index efefeeb436..541a5bd0b5 100644
--- a/options/locale/locale_uk-UA.ini
+++ b/options/locale/locale_uk-UA.ini
@@ -2538,6 +2538,7 @@ runs.commit=Коміт
+
[projects]
[git.filemode]
diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini
index 8c6392a4dc..a1fc26528e 100644
--- a/options/locale/locale_zh-CN.ini
+++ b/options/locale/locale_zh-CN.ini
@@ -1945,8 +1945,8 @@ pulls.delete.title=删除此合并请求?
pulls.delete.text=你真的要删除这个合并请求吗? (这将永久删除所有内容。如果你打算将内容存档,请考虑关闭它)
pulls.recently_pushed_new_branches=您已经于%[2]s推送了分支 %[1]s
-pulls.upstream_diverging_prompt_behind_1=该分支落后于 %s %d 个提交
-pulls.upstream_diverging_prompt_behind_n=该分支落后于 %s %d 个提交
+pulls.upstream_diverging_prompt_behind_1=该分支落后于 %[2]s %[1]d 个提交
+pulls.upstream_diverging_prompt_behind_n=该分支落后于 %[2]s %[1]d 个提交
pulls.upstream_diverging_prompt_base_newer=基础分支 %s 有新的更改
pulls.upstream_diverging_merge=同步派生
@@ -3772,6 +3772,7 @@ variables.creation.success=变量 “%s” 添加成功。
variables.update.failed=编辑变量失败。
variables.update.success=该变量已被编辑。
+
[projects]
deleted.display_name=已删除项目
type-1.display_name=个人项目
diff --git a/options/locale/locale_zh-HK.ini b/options/locale/locale_zh-HK.ini
index 6f37d30efc..e1ca6ebfc8 100644
--- a/options/locale/locale_zh-HK.ini
+++ b/options/locale/locale_zh-HK.ini
@@ -975,6 +975,7 @@ runners.task_list.repository=儲存庫
+
[projects]
[git.filemode]
diff --git a/options/locale/locale_zh-TW.ini b/options/locale/locale_zh-TW.ini
index fb93a2ff07..267f8b4947 100644
--- a/options/locale/locale_zh-TW.ini
+++ b/options/locale/locale_zh-TW.ini
@@ -1938,8 +1938,6 @@ pulls.delete.title=刪除此合併請求?
pulls.delete.text=您真的要刪除此合併請求嗎?(這將會永久移除所有內容。若您還想保留,請考慮改為關閉它。)
pulls.recently_pushed_new_branches=您在分支 %[1]s 上推送了 %[2]s
-pulls.upstream_diverging_prompt_behind_1=此分支落後 %s %d 次提交
-pulls.upstream_diverging_prompt_behind_n=此分支落後 %s %d 次提交
pulls.upstream_diverging_prompt_base_newer=基底分支 %s 有新變更
pulls.upstream_diverging_merge=同步 fork
@@ -3765,6 +3763,7 @@ variables.creation.success=已新增變數「%s」。
variables.update.failed=編輯變數失敗。
variables.update.success=已編輯變數。
+
[projects]
deleted.display_name=已刪除的專案
type-1.display_name=個人專案
diff --git a/package-lock.json b/package-lock.json
index 8755cfe06f..60edfa95d0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,7 +13,7 @@
"@github/relative-time-element": "4.4.4",
"@github/text-expander-element": "2.8.0",
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
- "@primer/octicons": "19.13.0",
+ "@primer/octicons": "19.14.0",
"@silverwind/vue3-calendar-heatmap": "2.0.6",
"add-asset-webpack-plugin": "3.0.0",
"ansi_up": "6.0.2",
@@ -33,12 +33,12 @@
"htmx.org": "2.0.4",
"idiomorph": "0.3.0",
"jquery": "3.7.1",
- "katex": "0.16.11",
+ "katex": "0.16.18",
"license-checker-webpack-plugin": "0.2.1",
"mermaid": "11.4.1",
"mini-css-extract-plugin": "2.9.2",
"minimatch": "10.0.1",
- "monaco-editor": "0.52.0",
+ "monaco-editor": "0.52.2",
"monaco-editor-webpack-plugin": "7.1.0",
"pdfobject": "2.3.0",
"perfect-debounce": "1.0.0",
@@ -47,7 +47,7 @@
"postcss-nesting": "13.0.1",
"sortablejs": "1.15.6",
"swagger-ui-dist": "5.18.2",
- "tailwindcss": "3.4.16",
+ "tailwindcss": "3.4.17",
"throttle-debounce": "5.0.2",
"tinycolor2": "1.6.0",
"tippy.js": "6.3.7",
@@ -60,16 +60,16 @@
"vue-bar-graph": "2.2.0",
"vue-chartjs": "5.3.2",
"vue-loader": "17.4.2",
- "webpack": "5.97.0",
+ "webpack": "5.97.1",
"webpack-cli": "5.1.4",
"wrap-ansi": "9.0.0"
},
"devDependencies": {
"@eslint-community/eslint-plugin-eslint-comments": "4.4.1",
- "@playwright/test": "1.49.0",
+ "@playwright/test": "1.49.1",
"@silverwind/vue-tsc": "2.1.13",
"@stoplight/spectral-cli": "6.14.2",
- "@stylistic/eslint-plugin-js": "2.11.0",
+ "@stylistic/eslint-plugin-js": "2.12.1",
"@stylistic/stylelint-plugin": "3.1.1",
"@types/dropzone": "5.7.9",
"@types/jquery": "3.5.32",
@@ -81,19 +81,19 @@
"@types/throttle-debounce": "5.0.2",
"@types/tinycolor2": "1.4.6",
"@types/toastify-js": "1.12.3",
- "@typescript-eslint/eslint-plugin": "8.17.0",
- "@typescript-eslint/parser": "8.17.0",
+ "@typescript-eslint/eslint-plugin": "8.18.1",
+ "@typescript-eslint/parser": "8.18.1",
"@vitejs/plugin-vue": "5.2.1",
"eslint": "8.57.0",
"eslint-import-resolver-typescript": "3.7.0",
"eslint-plugin-array-func": "4.0.0",
- "eslint-plugin-github": "5.1.3",
- "eslint-plugin-import-x": "4.5.0",
+ "eslint-plugin-github": "5.1.4",
+ "eslint-plugin-import-x": "4.6.1",
"eslint-plugin-no-jquery": "3.1.0",
"eslint-plugin-no-use-extend-native": "0.5.0",
"eslint-plugin-playwright": "2.1.0",
"eslint-plugin-regexp": "2.7.0",
- "eslint-plugin-sonarjs": "2.0.4",
+ "eslint-plugin-sonarjs": "3.0.1",
"eslint-plugin-unicorn": "56.0.1",
"eslint-plugin-vitest": "0.4.1",
"eslint-plugin-vitest-globals": "1.5.0",
@@ -102,15 +102,15 @@
"eslint-plugin-wc": "2.2.0",
"happy-dom": "15.11.7",
"markdownlint-cli": "0.43.0",
- "nolyfill": "1.0.42",
+ "nolyfill": "1.0.43",
"postcss-html": "1.7.0",
- "stylelint": "16.11.0",
+ "stylelint": "16.12.0",
"stylelint-declaration-block-no-ignored-properties": "2.8.0",
"stylelint-declaration-strict-value": "1.10.6",
"stylelint-value-no-unknown-custom-properties": "6.0.1",
"svgo": "3.3.2",
- "type-fest": "4.30.0",
- "updates": "16.4.0",
+ "type-fest": "4.30.2",
+ "updates": "16.4.1",
"vite-string-plugin": "1.3.4",
"vitest": "2.1.8"
},
@@ -190,12 +190,6 @@
"node": ">=6.9.0"
}
},
- "node_modules/@babel/code-frame/node_modules/js-tokens": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
- "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
- "license": "MIT"
- },
"node_modules/@babel/compat-data": {
"version": "7.26.3",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.3.tgz",
@@ -207,22 +201,22 @@
}
},
"node_modules/@babel/core": {
- "version": "7.25.2",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz",
- "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==",
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz",
+ "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@ampproject/remapping": "^2.2.0",
- "@babel/code-frame": "^7.24.7",
- "@babel/generator": "^7.25.0",
- "@babel/helper-compilation-targets": "^7.25.2",
- "@babel/helper-module-transforms": "^7.25.2",
- "@babel/helpers": "^7.25.0",
- "@babel/parser": "^7.25.0",
- "@babel/template": "^7.25.0",
- "@babel/traverse": "^7.25.2",
- "@babel/types": "^7.25.2",
+ "@babel/code-frame": "^7.26.0",
+ "@babel/generator": "^7.26.0",
+ "@babel/helper-compilation-targets": "^7.25.9",
+ "@babel/helper-module-transforms": "^7.26.0",
+ "@babel/helpers": "^7.26.0",
+ "@babel/parser": "^7.26.0",
+ "@babel/template": "^7.25.9",
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.26.0",
"convert-source-map": "^2.0.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
@@ -248,9 +242,9 @@
}
},
"node_modules/@babel/eslint-parser": {
- "version": "7.25.1",
- "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.25.1.tgz",
- "integrity": "sha512-Y956ghgTT4j7rKesabkh5WeqgSFZVFwaPR0IWFm7KFHFmmJ4afbG49SmfW4S+GyRPx0Dy5jxEWA5t0rpxfElWg==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.25.9.tgz",
+ "integrity": "sha512-5UXfgpK0j0Xr/xIdgdLEhOFxaDZ0bRPWJJchRpqOSur/3rZoPbqqki5mm0p4NE2cs28krBEiSM2MB7//afRSQQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -333,16 +327,6 @@
"node": ">=6.9.0"
}
},
- "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
- "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "yallist": "^3.0.2"
- }
- },
"node_modules/@babel/helper-compilation-targets/node_modules/semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
@@ -706,15 +690,15 @@
}
},
"node_modules/@babel/plugin-proposal-decorators": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.24.7.tgz",
- "integrity": "sha512-RL9GR0pUG5Kc8BUWLNDm2T5OpYwSX15r98I0IkgmRQTXuELq/OynH8xtMTMvTJFjXbMWFVTKtYkTaYQsuAwQlQ==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.25.9.tgz",
+ "integrity": "sha512-smkNLL/O1ezy9Nhy4CNosc4Va+1wo5w4gzSZeLe6y6dM4mmHfYOCPolXQPHQxonZCF+ZyebxN9vqOolkYrSn5g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.24.7",
- "@babel/helper-plugin-utils": "^7.24.7",
- "@babel/plugin-syntax-decorators": "^7.24.7"
+ "@babel/helper-create-class-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/plugin-syntax-decorators": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -736,48 +720,6 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-syntax-async-generators": {
- "version": "7.8.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
- "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-class-properties": {
- "version": "7.12.13",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
- "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.12.13"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-class-static-block": {
- "version": "7.14.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
- "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
"node_modules/@babel/plugin-syntax-decorators": {
"version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.25.9.tgz",
@@ -794,32 +736,6 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-syntax-dynamic-import": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
- "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-export-namespace-from": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz",
- "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.3"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
"node_modules/@babel/plugin-syntax-flow": {
"version": "7.26.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.26.0.tgz",
@@ -868,32 +784,6 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-syntax-import-meta": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
- "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.10.4"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-json-strings": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
- "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
"node_modules/@babel/plugin-syntax-jsx": {
"version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz",
@@ -910,116 +800,6 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
- "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.10.4"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
- "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-numeric-separator": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
- "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.10.4"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-object-rest-spread": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
- "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-optional-catch-binding": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
- "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-optional-chaining": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
- "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-private-property-in-object": {
- "version": "7.14.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
- "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-top-level-await": {
- "version": "7.14.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
- "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
"node_modules/@babel/plugin-syntax-unicode-sets-regex": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz",
@@ -1789,6 +1569,23 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/plugin-transform-regexp-modifiers": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz",
+ "integrity": "sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
"node_modules/@babel/plugin-transform-reserved-words": {
"version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz",
@@ -1954,94 +1751,80 @@
}
},
"node_modules/@babel/preset-env": {
- "version": "7.25.4",
- "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.4.tgz",
- "integrity": "sha512-W9Gyo+KmcxjGahtt3t9fb14vFRWvPpu5pT6GBlovAK6BTBcxgjfVMSQCfJl4oi35ODrxP6xx2Wr8LNST57Mraw==",
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.0.tgz",
+ "integrity": "sha512-H84Fxq0CQJNdPFT2DrfnylZ3cf5K43rGfWK4LJGPpjKHiZlk0/RzwEus3PDDZZg+/Er7lCA03MVacueUuXdzfw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/compat-data": "^7.25.4",
- "@babel/helper-compilation-targets": "^7.25.2",
- "@babel/helper-plugin-utils": "^7.24.8",
- "@babel/helper-validator-option": "^7.24.8",
- "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.3",
- "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.0",
- "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.0",
- "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7",
- "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.0",
+ "@babel/compat-data": "^7.26.0",
+ "@babel/helper-compilation-targets": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-validator-option": "^7.25.9",
+ "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9",
+ "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9",
+ "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9",
+ "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9",
+ "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9",
"@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2",
- "@babel/plugin-syntax-async-generators": "^7.8.4",
- "@babel/plugin-syntax-class-properties": "^7.12.13",
- "@babel/plugin-syntax-class-static-block": "^7.14.5",
- "@babel/plugin-syntax-dynamic-import": "^7.8.3",
- "@babel/plugin-syntax-export-namespace-from": "^7.8.3",
- "@babel/plugin-syntax-import-assertions": "^7.24.7",
- "@babel/plugin-syntax-import-attributes": "^7.24.7",
- "@babel/plugin-syntax-import-meta": "^7.10.4",
- "@babel/plugin-syntax-json-strings": "^7.8.3",
- "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
- "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
- "@babel/plugin-syntax-numeric-separator": "^7.10.4",
- "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
- "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
- "@babel/plugin-syntax-optional-chaining": "^7.8.3",
- "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
- "@babel/plugin-syntax-top-level-await": "^7.14.5",
+ "@babel/plugin-syntax-import-assertions": "^7.26.0",
+ "@babel/plugin-syntax-import-attributes": "^7.26.0",
"@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
- "@babel/plugin-transform-arrow-functions": "^7.24.7",
- "@babel/plugin-transform-async-generator-functions": "^7.25.4",
- "@babel/plugin-transform-async-to-generator": "^7.24.7",
- "@babel/plugin-transform-block-scoped-functions": "^7.24.7",
- "@babel/plugin-transform-block-scoping": "^7.25.0",
- "@babel/plugin-transform-class-properties": "^7.25.4",
- "@babel/plugin-transform-class-static-block": "^7.24.7",
- "@babel/plugin-transform-classes": "^7.25.4",
- "@babel/plugin-transform-computed-properties": "^7.24.7",
- "@babel/plugin-transform-destructuring": "^7.24.8",
- "@babel/plugin-transform-dotall-regex": "^7.24.7",
- "@babel/plugin-transform-duplicate-keys": "^7.24.7",
- "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.0",
- "@babel/plugin-transform-dynamic-import": "^7.24.7",
- "@babel/plugin-transform-exponentiation-operator": "^7.24.7",
- "@babel/plugin-transform-export-namespace-from": "^7.24.7",
- "@babel/plugin-transform-for-of": "^7.24.7",
- "@babel/plugin-transform-function-name": "^7.25.1",
- "@babel/plugin-transform-json-strings": "^7.24.7",
- "@babel/plugin-transform-literals": "^7.25.2",
- "@babel/plugin-transform-logical-assignment-operators": "^7.24.7",
- "@babel/plugin-transform-member-expression-literals": "^7.24.7",
- "@babel/plugin-transform-modules-amd": "^7.24.7",
- "@babel/plugin-transform-modules-commonjs": "^7.24.8",
- "@babel/plugin-transform-modules-systemjs": "^7.25.0",
- "@babel/plugin-transform-modules-umd": "^7.24.7",
- "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7",
- "@babel/plugin-transform-new-target": "^7.24.7",
- "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7",
- "@babel/plugin-transform-numeric-separator": "^7.24.7",
- "@babel/plugin-transform-object-rest-spread": "^7.24.7",
- "@babel/plugin-transform-object-super": "^7.24.7",
- "@babel/plugin-transform-optional-catch-binding": "^7.24.7",
- "@babel/plugin-transform-optional-chaining": "^7.24.8",
- "@babel/plugin-transform-parameters": "^7.24.7",
- "@babel/plugin-transform-private-methods": "^7.25.4",
- "@babel/plugin-transform-private-property-in-object": "^7.24.7",
- "@babel/plugin-transform-property-literals": "^7.24.7",
- "@babel/plugin-transform-regenerator": "^7.24.7",
- "@babel/plugin-transform-reserved-words": "^7.24.7",
- "@babel/plugin-transform-shorthand-properties": "^7.24.7",
- "@babel/plugin-transform-spread": "^7.24.7",
- "@babel/plugin-transform-sticky-regex": "^7.24.7",
- "@babel/plugin-transform-template-literals": "^7.24.7",
- "@babel/plugin-transform-typeof-symbol": "^7.24.8",
- "@babel/plugin-transform-unicode-escapes": "^7.24.7",
- "@babel/plugin-transform-unicode-property-regex": "^7.24.7",
- "@babel/plugin-transform-unicode-regex": "^7.24.7",
- "@babel/plugin-transform-unicode-sets-regex": "^7.25.4",
+ "@babel/plugin-transform-arrow-functions": "^7.25.9",
+ "@babel/plugin-transform-async-generator-functions": "^7.25.9",
+ "@babel/plugin-transform-async-to-generator": "^7.25.9",
+ "@babel/plugin-transform-block-scoped-functions": "^7.25.9",
+ "@babel/plugin-transform-block-scoping": "^7.25.9",
+ "@babel/plugin-transform-class-properties": "^7.25.9",
+ "@babel/plugin-transform-class-static-block": "^7.26.0",
+ "@babel/plugin-transform-classes": "^7.25.9",
+ "@babel/plugin-transform-computed-properties": "^7.25.9",
+ "@babel/plugin-transform-destructuring": "^7.25.9",
+ "@babel/plugin-transform-dotall-regex": "^7.25.9",
+ "@babel/plugin-transform-duplicate-keys": "^7.25.9",
+ "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9",
+ "@babel/plugin-transform-dynamic-import": "^7.25.9",
+ "@babel/plugin-transform-exponentiation-operator": "^7.25.9",
+ "@babel/plugin-transform-export-namespace-from": "^7.25.9",
+ "@babel/plugin-transform-for-of": "^7.25.9",
+ "@babel/plugin-transform-function-name": "^7.25.9",
+ "@babel/plugin-transform-json-strings": "^7.25.9",
+ "@babel/plugin-transform-literals": "^7.25.9",
+ "@babel/plugin-transform-logical-assignment-operators": "^7.25.9",
+ "@babel/plugin-transform-member-expression-literals": "^7.25.9",
+ "@babel/plugin-transform-modules-amd": "^7.25.9",
+ "@babel/plugin-transform-modules-commonjs": "^7.25.9",
+ "@babel/plugin-transform-modules-systemjs": "^7.25.9",
+ "@babel/plugin-transform-modules-umd": "^7.25.9",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9",
+ "@babel/plugin-transform-new-target": "^7.25.9",
+ "@babel/plugin-transform-nullish-coalescing-operator": "^7.25.9",
+ "@babel/plugin-transform-numeric-separator": "^7.25.9",
+ "@babel/plugin-transform-object-rest-spread": "^7.25.9",
+ "@babel/plugin-transform-object-super": "^7.25.9",
+ "@babel/plugin-transform-optional-catch-binding": "^7.25.9",
+ "@babel/plugin-transform-optional-chaining": "^7.25.9",
+ "@babel/plugin-transform-parameters": "^7.25.9",
+ "@babel/plugin-transform-private-methods": "^7.25.9",
+ "@babel/plugin-transform-private-property-in-object": "^7.25.9",
+ "@babel/plugin-transform-property-literals": "^7.25.9",
+ "@babel/plugin-transform-regenerator": "^7.25.9",
+ "@babel/plugin-transform-regexp-modifiers": "^7.26.0",
+ "@babel/plugin-transform-reserved-words": "^7.25.9",
+ "@babel/plugin-transform-shorthand-properties": "^7.25.9",
+ "@babel/plugin-transform-spread": "^7.25.9",
+ "@babel/plugin-transform-sticky-regex": "^7.25.9",
+ "@babel/plugin-transform-template-literals": "^7.25.9",
+ "@babel/plugin-transform-typeof-symbol": "^7.25.9",
+ "@babel/plugin-transform-unicode-escapes": "^7.25.9",
+ "@babel/plugin-transform-unicode-property-regex": "^7.25.9",
+ "@babel/plugin-transform-unicode-regex": "^7.25.9",
+ "@babel/plugin-transform-unicode-sets-regex": "^7.25.9",
"@babel/preset-modules": "0.1.6-no-external-plugins",
"babel-plugin-polyfill-corejs2": "^0.4.10",
"babel-plugin-polyfill-corejs3": "^0.10.6",
"babel-plugin-polyfill-regenerator": "^0.6.1",
- "core-js-compat": "^3.37.1",
+ "core-js-compat": "^3.38.1",
"semver": "^6.3.1"
},
"engines": {
@@ -2062,15 +1845,15 @@
}
},
"node_modules/@babel/preset-flow": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.24.7.tgz",
- "integrity": "sha512-NL3Lo0NorCU607zU3NwRyJbpaB6E3t0xtd3LfAQKDfkeX4/ggcDXvkmkW42QWT5owUeW/jAe4hn+2qvkV1IbfQ==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.25.9.tgz",
+ "integrity": "sha512-EASHsAhE+SSlEzJ4bzfusnXSHiU+JfAYzj+jbw2vgQKgq5HrUr8qs+vgtiEL5dOH6sEweI+PNt2D7AqrDSHyqQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7",
- "@babel/helper-validator-option": "^7.24.7",
- "@babel/plugin-transform-flow-strip-types": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-validator-option": "^7.25.9",
+ "@babel/plugin-transform-flow-strip-types": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -2095,18 +1878,18 @@
}
},
"node_modules/@babel/preset-react": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.7.tgz",
- "integrity": "sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==",
+ "version": "7.26.3",
+ "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.26.3.tgz",
+ "integrity": "sha512-Nl03d6T9ky516DGK2YMxrTqvnpUW63TnJMOMonj+Zae0JiPC5BC9xPMSL6L8fiSpA5vP88qfygavVQvnLp+6Cw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7",
- "@babel/helper-validator-option": "^7.24.7",
- "@babel/plugin-transform-react-display-name": "^7.24.7",
- "@babel/plugin-transform-react-jsx": "^7.24.7",
- "@babel/plugin-transform-react-jsx-development": "^7.24.7",
- "@babel/plugin-transform-react-pure-annotations": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-validator-option": "^7.25.9",
+ "@babel/plugin-transform-react-display-name": "^7.25.9",
+ "@babel/plugin-transform-react-jsx": "^7.25.9",
+ "@babel/plugin-transform-react-jsx-development": "^7.25.9",
+ "@babel/plugin-transform-react-pure-annotations": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -2143,9 +1926,9 @@
}
},
"node_modules/@babel/traverse": {
- "version": "7.26.3",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.3.tgz",
- "integrity": "sha512-yTmc8J+Sj8yLzwr4PD5Xb/WF3bOYu2C2OoSZPzbuqRm4n98XirsbzaX+GloeO376UnSYIYJ4NCanwV5/ugZkwA==",
+ "version": "7.26.4",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.4.tgz",
+ "integrity": "sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3109,18 +2892,31 @@
"license": "MIT"
},
"node_modules/@iconify/utils": {
- "version": "2.1.33",
- "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-2.1.33.tgz",
- "integrity": "sha512-jP9h6v/g0BIZx0p7XGJJVtkVnydtbgTgt9mVNcGDYwaa7UhdHdI9dvoq+gKj9sijMSJKxUPEG2JyjsgXjxL7Kw==",
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-2.2.1.tgz",
+ "integrity": "sha512-0/7J7hk4PqXmxo5PDBDxmnecw5PxklZJfNjIVG9FM0mEfVrvfudS22rYWsqVk6gR3UJ/mSYS90X4R3znXnqfNA==",
"license": "MIT",
"dependencies": {
- "@antfu/install-pkg": "^0.4.0",
+ "@antfu/install-pkg": "^0.4.1",
"@antfu/utils": "^0.7.10",
"@iconify/types": "^2.0.0",
- "debug": "^4.3.6",
+ "debug": "^4.4.0",
+ "globals": "^15.13.0",
"kolorist": "^1.8.0",
- "local-pkg": "^0.5.0",
- "mlly": "^1.7.1"
+ "local-pkg": "^0.5.1",
+ "mlly": "^1.7.3"
+ }
+ },
+ "node_modules/@iconify/utils/node_modules/globals": {
+ "version": "15.14.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz",
+ "integrity": "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@isaacs/cliui": {
@@ -3214,9 +3010,9 @@
}
},
"node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.5",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
- "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
+ "version": "0.3.8",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
+ "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
"license": "MIT",
"dependencies": {
"@jridgewell/set-array": "^1.2.1",
@@ -3486,13 +3282,13 @@
}
},
"node_modules/@playwright/test": {
- "version": "1.49.0",
- "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.49.0.tgz",
- "integrity": "sha512-DMulbwQURa8rNIQrf94+jPJQ4FmOVdpE5ZppRNvWVjvhC+6sOeo28r8MgIpQRYouXRtt/FCCXU7zn20jnHR4Qw==",
+ "version": "1.49.1",
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.49.1.tgz",
+ "integrity": "sha512-Ky+BVzPz8pL6PQxHqNRW1k3mIyv933LML7HktS8uik0bUXNCdPhoS/kLihiO1tMf/egaJb4IutXd7UywvXEW+g==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "playwright": "1.49.0"
+ "playwright": "1.49.1"
},
"bin": {
"playwright": "cli.js"
@@ -3512,9 +3308,9 @@
}
},
"node_modules/@primer/octicons": {
- "version": "19.13.0",
- "resolved": "https://registry.npmjs.org/@primer/octicons/-/octicons-19.13.0.tgz",
- "integrity": "sha512-U5g7Bv89At8qFXUy9MQlOUs4iPXR5XR4QPnSZWhmOn2oCgwf4LjdvfC+8OzhUFx2wC8k9TbRRAMVuCkqFLPlfQ==",
+ "version": "19.14.0",
+ "resolved": "https://registry.npmjs.org/@primer/octicons/-/octicons-19.14.0.tgz",
+ "integrity": "sha512-9Ovw/xcUFHC/zbsNhr/Hkp1+m9XnNeQvnGHDHrI5vhlf6PRZVzSsdMnesV2xCzQh7jXP3EVRcaeXsUGlsZrfcA==",
"license": "MIT",
"dependencies": {
"object-assign": "^4.1.1"
@@ -3568,9 +3364,9 @@
"license": "MIT"
},
"node_modules/@rollup/rollup-android-arm-eabi": {
- "version": "4.28.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.28.0.tgz",
- "integrity": "sha512-wLJuPLT6grGZsy34g4N1yRfYeouklTgPhH1gWXCYspenKYD0s3cR99ZevOGw5BexMNywkbV3UkjADisozBmpPQ==",
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.28.1.tgz",
+ "integrity": "sha512-2aZp8AES04KI2dy3Ss6/MDjXbwBzj+i0GqKtWXgw2/Ma6E4jJvujryO6gJAghIRVz7Vwr9Gtl/8na3nDUKpraQ==",
"cpu": [
"arm"
],
@@ -3582,9 +3378,9 @@
]
},
"node_modules/@rollup/rollup-android-arm64": {
- "version": "4.28.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.28.0.tgz",
- "integrity": "sha512-eiNkznlo0dLmVG/6wf+Ifi/v78G4d4QxRhuUl+s8EWZpDewgk7PX3ZyECUXU0Zq/Ca+8nU8cQpNC4Xgn2gFNDA==",
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.28.1.tgz",
+ "integrity": "sha512-EbkK285O+1YMrg57xVA+Dp0tDBRB93/BZKph9XhMjezf6F4TpYjaUSuPt5J0fZXlSag0LmZAsTmdGGqPp4pQFA==",
"cpu": [
"arm64"
],
@@ -3596,9 +3392,9 @@
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
- "version": "4.28.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.28.0.tgz",
- "integrity": "sha512-lmKx9yHsppblnLQZOGxdO66gT77bvdBtr/0P+TPOseowE7D9AJoBw8ZDULRasXRWf1Z86/gcOdpBrV6VDUY36Q==",
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.28.1.tgz",
+ "integrity": "sha512-prduvrMKU6NzMq6nxzQw445zXgaDBbMQvmKSJaxpaZ5R1QDM8w+eGxo6Y/jhT/cLoCvnZI42oEqf9KQNYz1fqQ==",
"cpu": [
"arm64"
],
@@ -3610,9 +3406,9 @@
]
},
"node_modules/@rollup/rollup-darwin-x64": {
- "version": "4.28.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.28.0.tgz",
- "integrity": "sha512-8hxgfReVs7k9Js1uAIhS6zq3I+wKQETInnWQtgzt8JfGx51R1N6DRVy3F4o0lQwumbErRz52YqwjfvuwRxGv1w==",
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.28.1.tgz",
+ "integrity": "sha512-WsvbOunsUk0wccO/TV4o7IKgloJ942hVFK1CLatwv6TJspcCZb9umQkPdvB7FihmdxgaKR5JyxDjWpCOp4uZlQ==",
"cpu": [
"x64"
],
@@ -3624,9 +3420,9 @@
]
},
"node_modules/@rollup/rollup-freebsd-arm64": {
- "version": "4.28.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.28.0.tgz",
- "integrity": "sha512-lA1zZB3bFx5oxu9fYud4+g1mt+lYXCoch0M0V/xhqLoGatbzVse0wlSQ1UYOWKpuSu3gyN4qEc0Dxf/DII1bhQ==",
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.28.1.tgz",
+ "integrity": "sha512-HTDPdY1caUcU4qK23FeeGxCdJF64cKkqajU0iBnTVxS8F7H/7BewvYoG+va1KPSL63kQ1PGNyiwKOfReavzvNA==",
"cpu": [
"arm64"
],
@@ -3638,9 +3434,9 @@
]
},
"node_modules/@rollup/rollup-freebsd-x64": {
- "version": "4.28.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.28.0.tgz",
- "integrity": "sha512-aI2plavbUDjCQB/sRbeUZWX9qp12GfYkYSJOrdYTL/C5D53bsE2/nBPuoiJKoWp5SN78v2Vr8ZPnB+/VbQ2pFA==",
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.28.1.tgz",
+ "integrity": "sha512-m/uYasxkUevcFTeRSM9TeLyPe2QDuqtjkeoTpP9SW0XxUWfcYrGDMkO/m2tTw+4NMAF9P2fU3Mw4ahNvo7QmsQ==",
"cpu": [
"x64"
],
@@ -3652,9 +3448,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
- "version": "4.28.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.28.0.tgz",
- "integrity": "sha512-WXveUPKtfqtaNvpf0iOb0M6xC64GzUX/OowbqfiCSXTdi/jLlOmH0Ba94/OkiY2yTGTwteo4/dsHRfh5bDCZ+w==",
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.28.1.tgz",
+ "integrity": "sha512-QAg11ZIt6mcmzpNE6JZBpKfJaKkqTm1A9+y9O+frdZJEuhQxiugM05gnCWiANHj4RmbgeVJpTdmKRmH/a+0QbA==",
"cpu": [
"arm"
],
@@ -3666,9 +3462,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
- "version": "4.28.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.28.0.tgz",
- "integrity": "sha512-yLc3O2NtOQR67lI79zsSc7lk31xjwcaocvdD1twL64PK1yNaIqCeWI9L5B4MFPAVGEVjH5k1oWSGuYX1Wutxpg==",
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.28.1.tgz",
+ "integrity": "sha512-dRP9PEBfolq1dmMcFqbEPSd9VlRuVWEGSmbxVEfiq2cs2jlZAl0YNxFzAQS2OrQmsLBLAATDMb3Z6MFv5vOcXg==",
"cpu": [
"arm"
],
@@ -3680,9 +3476,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
- "version": "4.28.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.28.0.tgz",
- "integrity": "sha512-+P9G9hjEpHucHRXqesY+3X9hD2wh0iNnJXX/QhS/J5vTdG6VhNYMxJ2rJkQOxRUd17u5mbMLHM7yWGZdAASfcg==",
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.28.1.tgz",
+ "integrity": "sha512-uGr8khxO+CKT4XU8ZUH1TTEUtlktK6Kgtv0+6bIFSeiSlnGJHG1tSFSjm41uQ9sAO/5ULx9mWOz70jYLyv1QkA==",
"cpu": [
"arm64"
],
@@ -3694,9 +3490,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
- "version": "4.28.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.28.0.tgz",
- "integrity": "sha512-1xsm2rCKSTpKzi5/ypT5wfc+4bOGa/9yI/eaOLW0oMs7qpC542APWhl4A37AENGZ6St6GBMWhCCMM6tXgTIplw==",
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.28.1.tgz",
+ "integrity": "sha512-QF54q8MYGAqMLrX2t7tNpi01nvq5RI59UBNx+3+37zoKX5KViPo/gk2QLhsuqok05sSCRluj0D00LzCwBikb0A==",
"cpu": [
"arm64"
],
@@ -3707,10 +3503,24 @@
"linux"
]
},
+ "node_modules/@rollup/rollup-linux-loongarch64-gnu": {
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.28.1.tgz",
+ "integrity": "sha512-vPul4uodvWvLhRco2w0GcyZcdyBfpfDRgNKU+p35AWEbJ/HPs1tOUrkSueVbBS0RQHAf/A+nNtDpvw95PeVKOA==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
- "version": "4.28.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.28.0.tgz",
- "integrity": "sha512-zgWxMq8neVQeXL+ouSf6S7DoNeo6EPgi1eeqHXVKQxqPy1B2NvTbaOUWPn/7CfMKL7xvhV0/+fq/Z/J69g1WAQ==",
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.28.1.tgz",
+ "integrity": "sha512-pTnTdBuC2+pt1Rmm2SV7JWRqzhYpEILML4PKODqLz+C7Ou2apEV52h19CR7es+u04KlqplggmN9sqZlekg3R1A==",
"cpu": [
"ppc64"
],
@@ -3722,9 +3532,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
- "version": "4.28.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.28.0.tgz",
- "integrity": "sha512-VEdVYacLniRxbRJLNtzwGt5vwS0ycYshofI7cWAfj7Vg5asqj+pt+Q6x4n+AONSZW/kVm+5nklde0qs2EUwU2g==",
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.28.1.tgz",
+ "integrity": "sha512-vWXy1Nfg7TPBSuAncfInmAI/WZDd5vOklyLJDdIRKABcZWojNDY0NJwruY2AcnCLnRJKSaBgf/GiJfauu8cQZA==",
"cpu": [
"riscv64"
],
@@ -3736,9 +3546,9 @@
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
- "version": "4.28.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.28.0.tgz",
- "integrity": "sha512-LQlP5t2hcDJh8HV8RELD9/xlYtEzJkm/aWGsauvdO2ulfl3QYRjqrKW+mGAIWP5kdNCBheqqqYIGElSRCaXfpw==",
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.28.1.tgz",
+ "integrity": "sha512-/yqC2Y53oZjb0yz8PVuGOQQNOTwxcizudunl/tFs1aLvObTclTwZ0JhXF2XcPT/zuaymemCDSuuUPXJJyqeDOg==",
"cpu": [
"s390x"
],
@@ -3750,9 +3560,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
- "version": "4.28.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.28.0.tgz",
- "integrity": "sha512-Nl4KIzteVEKE9BdAvYoTkW19pa7LR/RBrT6F1dJCV/3pbjwDcaOq+edkP0LXuJ9kflW/xOK414X78r+K84+msw==",
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.28.1.tgz",
+ "integrity": "sha512-fzgeABz7rrAlKYB0y2kSEiURrI0691CSL0+KXwKwhxvj92VULEDQLpBYLHpF49MSiPG4sq5CK3qHMnb9tlCjBw==",
"cpu": [
"x64"
],
@@ -3764,9 +3574,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
- "version": "4.28.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.28.0.tgz",
- "integrity": "sha512-eKpJr4vBDOi4goT75MvW+0dXcNUqisK4jvibY9vDdlgLx+yekxSm55StsHbxUsRxSTt3JEQvlr3cGDkzcSP8bw==",
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.28.1.tgz",
+ "integrity": "sha512-xQTDVzSGiMlSshpJCtudbWyRfLaNiVPXt1WgdWTwWz9n0U12cI2ZVtWe/Jgwyv/6wjL7b66uu61Vg0POWVfz4g==",
"cpu": [
"x64"
],
@@ -3778,9 +3588,9 @@
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
- "version": "4.28.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.28.0.tgz",
- "integrity": "sha512-Vi+WR62xWGsE/Oj+mD0FNAPY2MEox3cfyG0zLpotZdehPFXwz6lypkGs5y38Jd/NVSbOD02aVad6q6QYF7i8Bg==",
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.28.1.tgz",
+ "integrity": "sha512-wSXmDRVupJstFP7elGMgv+2HqXelQhuNf+IS4V+nUpNVi/GUiBgDmfwD0UGN3pcAnWsgKG3I52wMOBnk1VHr/A==",
"cpu": [
"arm64"
],
@@ -3792,9 +3602,9 @@
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
- "version": "4.28.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.28.0.tgz",
- "integrity": "sha512-kN/Vpip8emMLn/eOza+4JwqDZBL6MPNpkdaEsgUtW1NYN3DZvZqSQrbKzJcTL6hd8YNmFTn7XGWMwccOcJBL0A==",
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.28.1.tgz",
+ "integrity": "sha512-ZkyTJ/9vkgrE/Rk9vhMXhf8l9D+eAhbAVbsGsXKy2ohmJaWg0LPQLnIxRdRp/bKyr8tXuPlXhIoGlEB5XpJnGA==",
"cpu": [
"ia32"
],
@@ -3806,9 +3616,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
- "version": "4.28.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.28.0.tgz",
- "integrity": "sha512-Bvno2/aZT6usSa7lRDL2+hMjVAGjuqaymF1ApZm31JXzniR/hvr14jpU+/z4X6Gt5BPlzosscyJZGUvguXIqeQ==",
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.28.1.tgz",
+ "integrity": "sha512-ZvK2jBafvttJjoIdKm/Q/Bh7IJ1Ose9IBOwpOXcOvW3ikGTQGmKDgxTC6oCAzW6PynbkKP8+um1du81XJHZ0JA==",
"cpu": [
"x64"
],
@@ -4383,9 +4193,9 @@
}
},
"node_modules/@stylistic/eslint-plugin-js": {
- "version": "2.11.0",
- "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-2.11.0.tgz",
- "integrity": "sha512-btchD0P3iij6cIk5RR5QMdEhtCCV0+L6cNheGhGCd//jaHILZMTi/EOqgEDAf1s4ZoViyExoToM+S2Iwa3U9DA==",
+ "version": "2.12.1",
+ "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-2.12.1.tgz",
+ "integrity": "sha512-5ybogtEgWIGCR6dMnaabztbWyVdAPDsf/5XOk6jBonWug875Q9/a6gm9QxnU3rhdyDEnckWKX7dduwYJMOWrVA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4700,6 +4510,13 @@
"@types/d3-selection": "*"
}
},
+ "node_modules/@types/doctrine": {
+ "version": "0.0.9",
+ "resolved": "https://registry.npmjs.org/@types/doctrine/-/doctrine-0.0.9.tgz",
+ "integrity": "sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/dropzone": {
"version": "5.7.9",
"resolved": "https://registry.npmjs.org/@types/dropzone/-/dropzone-5.7.9.tgz",
@@ -4747,9 +4564,9 @@
"license": "MIT"
},
"node_modules/@types/geojson": {
- "version": "7946.0.14",
- "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz",
- "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==",
+ "version": "7946.0.15",
+ "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.15.tgz",
+ "integrity": "sha512-9oSxFzDCT2Rj6DfcHF8G++jxBKS7mBqXl5xrRW+Kbvjry6Uduya2iiwqHPhVXpasAVMBYKkEPGgKhd3+/HZ6xA==",
"license": "MIT"
},
"node_modules/@types/hammerjs": {
@@ -4812,9 +4629,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
- "version": "22.10.1",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.1.tgz",
- "integrity": "sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==",
+ "version": "22.10.2",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz",
+ "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==",
"license": "MIT",
"dependencies": {
"undici-types": "~6.20.0"
@@ -4968,17 +4785,17 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "8.17.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.17.0.tgz",
- "integrity": "sha512-HU1KAdW3Tt8zQkdvNoIijfWDMvdSweFYm4hWh+KwhPstv+sCmWb89hCIP8msFm9N1R/ooh9honpSuvqKWlYy3w==",
+ "version": "8.18.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.18.1.tgz",
+ "integrity": "sha512-Ncvsq5CT3Gvh+uJG0Lwlho6suwDfUXH0HztslDf5I+F2wAFAZMRwYLEorumpKLzmO2suAXZ/td1tBg4NZIi9CQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
- "@typescript-eslint/scope-manager": "8.17.0",
- "@typescript-eslint/type-utils": "8.17.0",
- "@typescript-eslint/utils": "8.17.0",
- "@typescript-eslint/visitor-keys": "8.17.0",
+ "@typescript-eslint/scope-manager": "8.18.1",
+ "@typescript-eslint/type-utils": "8.18.1",
+ "@typescript-eslint/utils": "8.18.1",
+ "@typescript-eslint/visitor-keys": "8.18.1",
"graphemer": "^1.4.0",
"ignore": "^5.3.1",
"natural-compare": "^1.4.0",
@@ -4993,25 +4810,21 @@
},
"peerDependencies": {
"@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0",
- "eslint": "^8.57.0 || ^9.0.0"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <5.8.0"
}
},
"node_modules/@typescript-eslint/parser": {
- "version": "8.17.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.17.0.tgz",
- "integrity": "sha512-Drp39TXuUlD49F7ilHHCG7TTg8IkA+hxCuULdmzWYICxGXvDXmDmWEjJYZQYgf6l/TFfYNE167m7isnc3xlIEg==",
+ "version": "8.18.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.18.1.tgz",
+ "integrity": "sha512-rBnTWHCdbYM2lh7hjyXqxk70wvon3p2FyaniZuey5TrcGBpfhVp0OxOa6gxr9Q9YhZFKyfbEnxc24ZnVbbUkCA==",
"dev": true,
- "license": "BSD-2-Clause",
+ "license": "MIT",
"dependencies": {
- "@typescript-eslint/scope-manager": "8.17.0",
- "@typescript-eslint/types": "8.17.0",
- "@typescript-eslint/typescript-estree": "8.17.0",
- "@typescript-eslint/visitor-keys": "8.17.0",
+ "@typescript-eslint/scope-manager": "8.18.1",
+ "@typescript-eslint/types": "8.18.1",
+ "@typescript-eslint/typescript-estree": "8.18.1",
+ "@typescript-eslint/visitor-keys": "8.18.1",
"debug": "^4.3.4"
},
"engines": {
@@ -5022,23 +4835,19 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <5.8.0"
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "8.17.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.17.0.tgz",
- "integrity": "sha512-/ewp4XjvnxaREtqsZjF4Mfn078RD/9GmiEAtTeLQ7yFdKnqwTOgRMSvFz4et9U5RiJQ15WTGXPLj89zGusvxBg==",
+ "version": "8.18.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.18.1.tgz",
+ "integrity": "sha512-HxfHo2b090M5s2+/9Z3gkBhI6xBH8OJCFjH9MhQ+nnoZqxU3wNxkLT+VWXWSFWc3UF3Z+CfPAyqdCTdoXtDPCQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.17.0",
- "@typescript-eslint/visitor-keys": "8.17.0"
+ "@typescript-eslint/types": "8.18.1",
+ "@typescript-eslint/visitor-keys": "8.18.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -5049,14 +4858,14 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
- "version": "8.17.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.17.0.tgz",
- "integrity": "sha512-q38llWJYPd63rRnJ6wY/ZQqIzPrBCkPdpIsaCfkR3Q4t3p6sb422zougfad4TFW9+ElIFLVDzWGiGAfbb/v2qw==",
+ "version": "8.18.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.18.1.tgz",
+ "integrity": "sha512-jAhTdK/Qx2NJPNOTxXpMwlOiSymtR2j283TtPqXkKBdH8OAMmhiUfP0kJjc/qSE51Xrq02Gj9NY7MwK+UxVwHQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/typescript-estree": "8.17.0",
- "@typescript-eslint/utils": "8.17.0",
+ "@typescript-eslint/typescript-estree": "8.18.1",
+ "@typescript-eslint/utils": "8.18.1",
"debug": "^4.3.4",
"ts-api-utils": "^1.3.0"
},
@@ -5068,18 +4877,14 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <5.8.0"
}
},
"node_modules/@typescript-eslint/types": {
- "version": "8.17.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.17.0.tgz",
- "integrity": "sha512-gY2TVzeve3z6crqh2Ic7Cr+CAv6pfb0Egee7J5UAVWCpVvDI/F71wNfolIim4FE6hT15EbpZFVUj9j5i38jYXA==",
+ "version": "8.18.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.18.1.tgz",
+ "integrity": "sha512-7uoAUsCj66qdNQNpH2G8MyTFlgerum8ubf21s3TSM3XmKXuIn+H2Sifh/ES2nPOPiYSRJWAk0fDkW0APBWcpfw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -5091,14 +4896,14 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.17.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.17.0.tgz",
- "integrity": "sha512-JqkOopc1nRKZpX+opvKqnM3XUlM7LpFMD0lYxTqOTKQfCWAmxw45e3qlOCsEqEB2yuacujivudOFpCnqkBDNMw==",
+ "version": "8.18.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.1.tgz",
+ "integrity": "sha512-z8U21WI5txzl2XYOW7i9hJhxoKKNG1kcU4RzyNvKrdZDmbjkmLBo8bgeiOJmA06kizLI76/CCBAAGlTlEeUfyg==",
"dev": true,
- "license": "BSD-2-Clause",
+ "license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.17.0",
- "@typescript-eslint/visitor-keys": "8.17.0",
+ "@typescript-eslint/types": "8.18.1",
+ "@typescript-eslint/visitor-keys": "8.18.1",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
@@ -5113,10 +4918,8 @@
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <5.8.0"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
@@ -5136,16 +4939,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
- "version": "8.17.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.17.0.tgz",
- "integrity": "sha512-bQC8BnEkxqG8HBGKwG9wXlZqg37RKSMY7v/X8VEWD8JG2JuTHuNK0VFvMPMUKQcbk6B+tf05k+4AShAEtCtJ/w==",
+ "version": "8.18.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.18.1.tgz",
+ "integrity": "sha512-8vikiIj2ebrC4WRdcAdDcmnu9Q/MXXwg+STf40BVfT8exDqBCUPdypvzcUPxEqRGKg9ALagZ0UWcYCtn+4W2iQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
- "@typescript-eslint/scope-manager": "8.17.0",
- "@typescript-eslint/types": "8.17.0",
- "@typescript-eslint/typescript-estree": "8.17.0"
+ "@typescript-eslint/scope-manager": "8.18.1",
+ "@typescript-eslint/types": "8.18.1",
+ "@typescript-eslint/typescript-estree": "8.18.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -5155,22 +4958,18 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <5.8.0"
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.17.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.17.0.tgz",
- "integrity": "sha512-1Hm7THLpO6ww5QU6H/Qp+AusUUl+z/CAm3cNZZ0jQvon9yicgO7Rwd+/WWRpMKLYV6p2UvdbR27c86rzCPpreg==",
+ "version": "8.18.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.1.tgz",
+ "integrity": "sha512-Vj0WLm5/ZsD013YeUKn+K0y8p1M0jPpxOkKdbD1wB0ns53a5piVY02zjf072TblEweAbcYiFiPoSMF3kp+VhhQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.17.0",
+ "@typescript-eslint/types": "8.18.1",
"eslint-visitor-keys": "^4.2.0"
},
"engines": {
@@ -5182,9 +4981,9 @@
}
},
"node_modules/@ungap/structured-clone": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
- "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.1.tgz",
+ "integrity": "sha512-fEzPV3hSkSMltkw152tJKNARhOupqbH96MZWyRjNaYZOMIzbrTeQDG+MTc6Mr2pgzFQzFxAfmhGDNP5QK++2ZA==",
"dev": true,
"license": "ISC"
},
@@ -5263,9 +5062,9 @@
}
},
"node_modules/@vitest/mocker/node_modules/magic-string": {
- "version": "0.30.14",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.14.tgz",
- "integrity": "sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw==",
+ "version": "0.30.17",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
+ "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5315,9 +5114,9 @@
}
},
"node_modules/@vitest/snapshot/node_modules/magic-string": {
- "version": "0.30.14",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.14.tgz",
- "integrity": "sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw==",
+ "version": "0.30.17",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
+ "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5422,9 +5221,9 @@
}
},
"node_modules/@vue/compiler-sfc/node_modules/magic-string": {
- "version": "0.30.14",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.14.tgz",
- "integrity": "sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw==",
+ "version": "0.30.17",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
+ "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0"
@@ -5978,27 +5777,6 @@
"node": ">=8"
}
},
- "node_modules/array.prototype.findlast": {
- "name": "@nolyfill/array.prototype.findlast",
- "version": "1.0.24",
- "resolved": "https://registry.npmjs.org/@nolyfill/array.prototype.findlast/-/array.prototype.findlast-1.0.24.tgz",
- "integrity": "sha512-yFCyZLs0iNNubzYnBINcOCJAiGtusxiR2F1DnwkOB1HQbWXl/zltkDIWIXO3cJxhQdngDlmM4ysTfyAfoB297g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@nolyfill/shared": "1.0.24"
- },
- "engines": {
- "node": ">=12.4.0"
- }
- },
- "node_modules/array.prototype.findlast/node_modules/@nolyfill/shared": {
- "version": "1.0.24",
- "resolved": "https://registry.npmjs.org/@nolyfill/shared/-/shared-1.0.24.tgz",
- "integrity": "sha512-TGCpg3k5N7jj9AgU/1xFw9K1g4AC1vEE5ZFkW77oPNNLzprxT17PvFaNr/lr3BkkT5fJ5LNMntaTIq+pyWaeEA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/array.prototype.findlastindex": {
"name": "@nolyfill/array.prototype.findlastindex",
"version": "1.0.24",
@@ -6048,27 +5826,6 @@
"node": ">=12.4.0"
}
},
- "node_modules/array.prototype.tosorted": {
- "name": "@nolyfill/array.prototype.tosorted",
- "version": "1.0.24",
- "resolved": "https://registry.npmjs.org/@nolyfill/array.prototype.tosorted/-/array.prototype.tosorted-1.0.24.tgz",
- "integrity": "sha512-lVo8TVDqaslOaOvEH7iL7glu/WdlX7ZrB+7FZY4BL25hg8TLHvg3e9pxafCp8vAQ96IOL+tdgBdfeoC7qLeQYg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@nolyfill/shared": "1.0.24"
- },
- "engines": {
- "node": ">=12.4.0"
- }
- },
- "node_modules/array.prototype.tosorted/node_modules/@nolyfill/shared": {
- "version": "1.0.24",
- "resolved": "https://registry.npmjs.org/@nolyfill/shared/-/shared-1.0.24.tgz",
- "integrity": "sha512-TGCpg3k5N7jj9AgU/1xFw9K1g4AC1vEE5ZFkW77oPNNLzprxT17PvFaNr/lr3BkkT5fJ5LNMntaTIq+pyWaeEA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/as-table": {
"version": "1.0.55",
"resolved": "https://registry.npmjs.org/as-table/-/as-table-1.0.55.tgz",
@@ -6300,9 +6057,9 @@
}
},
"node_modules/browserslist": {
- "version": "4.24.2",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz",
- "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==",
+ "version": "4.24.3",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.3.tgz",
+ "integrity": "sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==",
"funding": [
{
"type": "opencollective",
@@ -6319,9 +6076,9 @@
],
"license": "MIT",
"dependencies": {
- "caniuse-lite": "^1.0.30001669",
- "electron-to-chromium": "^1.5.41",
- "node-releases": "^2.0.18",
+ "caniuse-lite": "^1.0.30001688",
+ "electron-to-chromium": "^1.5.73",
+ "node-releases": "^2.0.19",
"update-browserslist-db": "^1.1.1"
},
"bin": {
@@ -6420,9 +6177,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001686",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001686.tgz",
- "integrity": "sha512-Y7deg0Aergpa24M3qLC5xjNklnKnhsmSyR/V89dLZ1n0ucJIFNs7PgR2Yfa/Zf6W79SbBicgtGxZr2juHkEUIA==",
+ "version": "1.0.30001690",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz",
+ "integrity": "sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==",
"funding": [
{
"type": "opencollective",
@@ -6933,13 +6690,13 @@
}
},
"node_modules/css-tree": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.0.1.tgz",
- "integrity": "sha512-8Fxxv+tGhORlshCdCwnNJytvlvq46sOLSYEx2ZIGurahWvMucSRnyjPA3AmrMq4VPRYbHVpWj5VkiVasrM2H4Q==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz",
+ "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "mdn-data": "2.12.1",
+ "mdn-data": "2.12.2",
"source-map-js": "^1.0.1"
},
"engines": {
@@ -7549,9 +7306,9 @@
"license": "MIT"
},
"node_modules/debug": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
- "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
+ "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
@@ -7585,20 +7342,6 @@
"node": ">=6"
}
},
- "node_modules/deep-equal": {
- "name": "@nolyfill/deep-equal",
- "version": "1.0.29",
- "resolved": "https://registry.npmjs.org/@nolyfill/deep-equal/-/deep-equal-1.0.29.tgz",
- "integrity": "sha512-EtrJBbOXHhVz8Y1gMYolKgPqh2u96UPqkZMHR0lcjn3y4TC4R7GuN3E4kEhDIpyK3q1+y7HHPHHkt5fGvW1crQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "dequal": "2.0.3"
- },
- "engines": {
- "node": ">=12.4.0"
- }
- },
"node_modules/deep-extend": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
@@ -7635,16 +7378,6 @@
"node": ">= 0.6.0"
}
},
- "node_modules/dequal": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
- "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/didyoumean": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
@@ -7737,9 +7470,9 @@
}
},
"node_modules/dompurify": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.2.tgz",
- "integrity": "sha512-YMM+erhdZ2nkZ4fTNRTSI94mb7VG7uVF5vj5Zde7tImgnhZE3R6YW/IACGIHb2ux+QkEXMhe591N+5jWOmL4Zw==",
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.3.tgz",
+ "integrity": "sha512-U1U5Hzc2MO0oW3DF+G9qYN0aT7atAou4AgI0XjWz061nyBPbdxkfdhfy5uMgGn6+oLFCfn44ZGbdDqCzVmlOWA==",
"license": "(MPL-2.0 OR Apache-2.0)",
"optionalDependencies": {
"@types/trusted-types": "^2.0.7"
@@ -7790,9 +7523,9 @@
}
},
"node_modules/electron-to-chromium": {
- "version": "1.5.68",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.68.tgz",
- "integrity": "sha512-FgMdJlma0OzUYlbrtZ4AeXjKxKPk6KT8WOP8BjcqxWtlg8qyJQjRzPJzUtUn5GBg1oQ26hFs7HOOHJMYiJRnvQ==",
+ "version": "1.5.74",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.74.tgz",
+ "integrity": "sha512-ck3//9RC+6oss/1Bh9tiAVFy5vfSKbRHAFh7Z3/eTRkEqJeWgymloShB17Vg3Z4nmDNp35vAd1BZ6CMW4Wt6Iw==",
"license": "ISC"
},
"node_modules/emoji-regex": {
@@ -7879,27 +7612,6 @@
"node": ">=12.4.0"
}
},
- "node_modules/es-iterator-helpers": {
- "name": "@nolyfill/es-iterator-helpers",
- "version": "1.0.21",
- "resolved": "https://registry.npmjs.org/@nolyfill/es-iterator-helpers/-/es-iterator-helpers-1.0.21.tgz",
- "integrity": "sha512-i326KeE0nhW4STobcUhkxpXzZUddedCmfh7b/IyXR9kW0CFHiNNT80C3JSEy33mUlhZtk/ezX47nymcFxyBigg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@nolyfill/shared": "1.0.21"
- },
- "engines": {
- "node": ">=12.4.0"
- }
- },
- "node_modules/es-iterator-helpers/node_modules/@nolyfill/shared": {
- "version": "1.0.21",
- "resolved": "https://registry.npmjs.org/@nolyfill/shared/-/shared-1.0.21.tgz",
- "integrity": "sha512-qDc/NoaFU23E0hhiDPeUrvWzTXIPE+RbvRQtRWSeHHNmCIgYI9HS1jKzNYNJxv4jvZ/1VmM3L6rNVxbj+LBMNA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/es-module-lexer": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz",
@@ -8241,9 +7953,9 @@
}
},
"node_modules/eslint-plugin-github": {
- "version": "5.1.3",
- "resolved": "https://registry.npmjs.org/eslint-plugin-github/-/eslint-plugin-github-5.1.3.tgz",
- "integrity": "sha512-/0lyEqLLodXW3p+D9eYtmEp6e9DcJmV5FhnE9wNWV1bcqyShuZFXn5kOeJIvxSbFbdbrKiNO8zFiV/VXeSpRSw==",
+ "version": "5.1.4",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-github/-/eslint-plugin-github-5.1.4.tgz",
+ "integrity": "sha512-j5IgIxsDoch06zJzeqPvenfzRXDKI9Z8YwfUg1pm2ay1q44tMSFwvEu6l0uEIrTpA3v8QdPyLr98LqDl1TIhSA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -8333,9 +8045,9 @@
}
},
"node_modules/eslint-plugin-github/node_modules/@eslint/js": {
- "version": "9.16.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.16.0.tgz",
- "integrity": "sha512-tw2HxzQkrbeuvyj1tG2Yqq+0H9wGoI2IMk4EOsQeX+vmd75FtJAzf+gTA69WF+baUKRYQ3x2kbLE08js5OsTVg==",
+ "version": "9.17.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.17.0.tgz",
+ "integrity": "sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==",
"dev": true,
"license": "MIT",
"engines": {
@@ -8371,9 +8083,9 @@
}
},
"node_modules/eslint-plugin-github/node_modules/globals": {
- "version": "15.13.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-15.13.0.tgz",
- "integrity": "sha512-49TewVEz0UxZjr1WYYsWpPrhyC/B/pA8Bq0fUmet2n+eR7yn0IvNzNaoBwnK6mdkzcN+se7Ez9zUgULTz2QH4g==",
+ "version": "15.14.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz",
+ "integrity": "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==",
"dev": true,
"license": "MIT",
"engines": {
@@ -8448,16 +8160,18 @@
}
},
"node_modules/eslint-plugin-import-x": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.5.0.tgz",
- "integrity": "sha512-l0OTfnPF8RwmSXfjT75N8d6ZYLVrVYWpaGlgvVkVqFERCI5SyBfDP7QEMr3kt0zWi2sOa9EQ47clbdFsHkF83Q==",
+ "version": "4.6.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.6.1.tgz",
+ "integrity": "sha512-wluSUifMIb7UfwWXqx7Yx0lE/SGCcGXECLx/9bCmbY2nneLwvAZ4vkd1IXDjPKFvdcdUgr1BaRnaRpx3k2+Pfw==",
"dev": true,
"license": "MIT",
"dependencies": {
+ "@types/doctrine": "^0.0.9",
"@typescript-eslint/scope-manager": "^8.1.0",
"@typescript-eslint/utils": "^8.1.0",
"debug": "^4.3.4",
"doctrine": "^3.0.0",
+ "enhanced-resolve": "^5.17.1",
"eslint-import-resolver-node": "^0.3.9",
"get-tsconfig": "^4.7.3",
"is-glob": "^4.0.3",
@@ -8686,117 +8400,6 @@
}
}
},
- "node_modules/eslint-plugin-react": {
- "version": "7.36.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.36.1.tgz",
- "integrity": "sha512-/qwbqNXZoq+VP30s1d4Nc1C5GTxjJQjk4Jzs4Wq2qzxFM7dSmuG2UkIjg2USMLh3A/aVcUNrK7v0J5U1XEGGwA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "array-includes": "^3.1.8",
- "array.prototype.findlast": "^1.2.5",
- "array.prototype.flatmap": "^1.3.2",
- "array.prototype.tosorted": "^1.1.4",
- "doctrine": "^2.1.0",
- "es-iterator-helpers": "^1.0.19",
- "estraverse": "^5.3.0",
- "hasown": "^2.0.2",
- "jsx-ast-utils": "^2.4.1 || ^3.0.0",
- "minimatch": "^3.1.2",
- "object.entries": "^1.1.8",
- "object.fromentries": "^2.0.8",
- "object.values": "^1.2.0",
- "prop-types": "^15.8.1",
- "resolve": "^2.0.0-next.5",
- "semver": "^6.3.1",
- "string.prototype.matchall": "^4.0.11",
- "string.prototype.repeat": "^1.0.0"
- },
- "engines": {
- "node": ">=4"
- },
- "peerDependencies": {
- "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7"
- }
- },
- "node_modules/eslint-plugin-react-hooks": {
- "version": "4.6.2",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz",
- "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "peerDependencies": {
- "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0"
- }
- },
- "node_modules/eslint-plugin-react/node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/eslint-plugin-react/node_modules/doctrine": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
- "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "esutils": "^2.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/eslint-plugin-react/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/eslint-plugin-react/node_modules/resolve": {
- "version": "2.0.0-next.5",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",
- "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-core-module": "^2.13.0",
- "path-parse": "^1.0.7",
- "supports-preserve-symlinks-flag": "^1.0.0"
- },
- "bin": {
- "resolve": "bin/resolve"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/eslint-plugin-react/node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- }
- },
"node_modules/eslint-plugin-regexp": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-2.7.0.tgz",
@@ -8820,256 +8423,33 @@
}
},
"node_modules/eslint-plugin-sonarjs": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-2.0.4.tgz",
- "integrity": "sha512-XVVAB/t0WSgHitHNajIcIDmviCO8kB9VSsrjy+4WUEVM3eieY9SDHEtCDaOMTjj6XMtcAr8BFDXCFaP005s+tg==",
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-3.0.1.tgz",
+ "integrity": "sha512-RT6VgdPqizbMLmTryIc3fB169hRjvDFlqieSZEEswGtApPb4Dn9BndmN9qyfBV/By0hbseIX8zQWKBz5E7lyiQ==",
"dev": true,
"license": "LGPL-3.0-only",
"dependencies": {
- "@babel/core": "7.25.2",
- "@babel/eslint-parser": "7.25.1",
- "@babel/plugin-proposal-decorators": "7.24.7",
- "@babel/preset-env": "7.25.4",
- "@babel/preset-flow": "7.24.7",
- "@babel/preset-react": "7.24.7",
- "@eslint-community/regexpp": "4.11.1",
- "@typescript-eslint/eslint-plugin": "7.16.1",
- "@typescript-eslint/utils": "7.16.1",
+ "@babel/core": "7.26.0",
+ "@babel/eslint-parser": "7.25.9",
+ "@babel/plugin-proposal-decorators": "7.25.9",
+ "@babel/preset-env": "7.26.0",
+ "@babel/preset-flow": "7.25.9",
+ "@babel/preset-react": "7.26.3",
+ "@eslint-community/regexpp": "4.12.1",
"builtin-modules": "3.3.0",
"bytes": "3.1.2",
- "eslint-plugin-import": "2.30.0",
- "eslint-plugin-jsx-a11y": "6.10.0",
- "eslint-plugin-react": "7.36.1",
- "eslint-plugin-react-hooks": "4.6.2",
- "eslint-scope": "8.1.0",
"functional-red-black-tree": "1.0.1",
"jsx-ast-utils": "3.3.5",
- "minimatch": "10.0.1",
+ "minimatch": "9.0.5",
"scslre": "0.3.0",
"semver": "7.6.3",
- "typescript": "5.6.2",
- "vue-eslint-parser": "9.4.3"
+ "typescript": "^5"
},
"peerDependencies": {
"eslint": "^8.0.0 || ^9.0.0"
}
},
- "node_modules/eslint-plugin-sonarjs/node_modules/@eslint-community/regexpp": {
- "version": "4.11.1",
- "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz",
- "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/eslint-plugin": {
- "version": "7.16.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.1.tgz",
- "integrity": "sha512-SxdPak/5bO0EnGktV05+Hq8oatjAYVY3Zh2bye9pGZy6+jwyR3LG3YKkV4YatlsgqXP28BTeVm9pqwJM96vf2A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@eslint-community/regexpp": "^4.10.0",
- "@typescript-eslint/scope-manager": "7.16.1",
- "@typescript-eslint/type-utils": "7.16.1",
- "@typescript-eslint/utils": "7.16.1",
- "@typescript-eslint/visitor-keys": "7.16.1",
- "graphemer": "^1.4.0",
- "ignore": "^5.3.1",
- "natural-compare": "^1.4.0",
- "ts-api-utils": "^1.3.0"
- },
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "@typescript-eslint/parser": "^7.0.0",
- "eslint": "^8.56.0"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/parser": {
- "version": "7.18.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz",
- "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==",
- "dev": true,
- "license": "BSD-2-Clause",
- "peer": true,
- "dependencies": {
- "@typescript-eslint/scope-manager": "7.18.0",
- "@typescript-eslint/types": "7.18.0",
- "@typescript-eslint/typescript-estree": "7.18.0",
- "@typescript-eslint/visitor-keys": "7.18.0",
- "debug": "^4.3.4"
- },
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.56.0"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": {
- "version": "7.18.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz",
- "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@typescript-eslint/types": "7.18.0",
- "@typescript-eslint/visitor-keys": "7.18.0"
- },
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": {
- "version": "7.18.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz",
- "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@typescript-eslint/types": "7.18.0",
- "eslint-visitor-keys": "^3.4.3"
- },
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/scope-manager": {
- "version": "7.16.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.1.tgz",
- "integrity": "sha512-nYpyv6ALte18gbMz323RM+vpFpTjfNdyakbf3nsLvF43uF9KeNC289SUEW3QLZ1xPtyINJ1dIsZOuWuSRIWygw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/types": "7.16.1",
- "@typescript-eslint/visitor-keys": "7.16.1"
- },
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/scope-manager/node_modules/@typescript-eslint/types": {
- "version": "7.16.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.1.tgz",
- "integrity": "sha512-AQn9XqCzUXd4bAVEsAXM/Izk11Wx2u4H3BAfQVhSfzfDOm/wAON9nP7J5rpkCxts7E5TELmN845xTUCQrD1xIQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/type-utils": {
- "version": "7.16.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.1.tgz",
- "integrity": "sha512-rbu/H2MWXN4SkjIIyWcmYBjlp55VT+1G3duFOIukTNFxr9PI35pLc2ydwAfejCEitCv4uztA07q0QWanOHC7dA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/typescript-estree": "7.16.1",
- "@typescript-eslint/utils": "7.16.1",
- "debug": "^4.3.4",
- "ts-api-utils": "^1.3.0"
- },
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.56.0"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": {
- "version": "7.16.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.1.tgz",
- "integrity": "sha512-AQn9XqCzUXd4bAVEsAXM/Izk11Wx2u4H3BAfQVhSfzfDOm/wAON9nP7J5rpkCxts7E5TELmN845xTUCQrD1xIQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": {
- "version": "7.16.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.1.tgz",
- "integrity": "sha512-0vFPk8tMjj6apaAZ1HlwM8w7jbghC8jc1aRNJG5vN8Ym5miyhTQGMqU++kuBFDNKe9NcPeZ6x0zfSzV8xC1UlQ==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "@typescript-eslint/types": "7.16.1",
- "@typescript-eslint/visitor-keys": "7.16.1",
- "debug": "^4.3.4",
- "globby": "^11.1.0",
- "is-glob": "^4.0.3",
- "minimatch": "^9.0.4",
- "semver": "^7.6.0",
- "ts-api-utils": "^1.3.0"
- },
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/type-utils/node_modules/minimatch": {
+ "node_modules/eslint-plugin-sonarjs/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
@@ -9085,400 +8465,6 @@
"url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/types": {
- "version": "7.18.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz",
- "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/typescript-estree": {
- "version": "7.18.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz",
- "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==",
- "dev": true,
- "license": "BSD-2-Clause",
- "peer": true,
- "dependencies": {
- "@typescript-eslint/types": "7.18.0",
- "@typescript-eslint/visitor-keys": "7.18.0",
- "debug": "^4.3.4",
- "globby": "^11.1.0",
- "is-glob": "^4.0.3",
- "minimatch": "^9.0.4",
- "semver": "^7.6.0",
- "ts-api-utils": "^1.3.0"
- },
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/visitor-keys": {
- "version": "7.18.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz",
- "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@typescript-eslint/types": "7.18.0",
- "eslint-visitor-keys": "^3.4.3"
- },
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
- "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
- "dev": true,
- "license": "ISC",
- "peer": true,
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=16 || 14 >=14.17"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/utils": {
- "version": "7.16.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.1.tgz",
- "integrity": "sha512-WrFM8nzCowV0he0RlkotGDujx78xudsxnGMBHI88l5J8wEhED6yBwaSLP99ygfrzAjsQvcYQ94quDwI0d7E1fA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@eslint-community/eslint-utils": "^4.4.0",
- "@typescript-eslint/scope-manager": "7.16.1",
- "@typescript-eslint/types": "7.16.1",
- "@typescript-eslint/typescript-estree": "7.16.1"
- },
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.56.0"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": {
- "version": "7.16.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.1.tgz",
- "integrity": "sha512-AQn9XqCzUXd4bAVEsAXM/Izk11Wx2u4H3BAfQVhSfzfDOm/wAON9nP7J5rpkCxts7E5TELmN845xTUCQrD1xIQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": {
- "version": "7.16.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.1.tgz",
- "integrity": "sha512-0vFPk8tMjj6apaAZ1HlwM8w7jbghC8jc1aRNJG5vN8Ym5miyhTQGMqU++kuBFDNKe9NcPeZ6x0zfSzV8xC1UlQ==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "@typescript-eslint/types": "7.16.1",
- "@typescript-eslint/visitor-keys": "7.16.1",
- "debug": "^4.3.4",
- "globby": "^11.1.0",
- "is-glob": "^4.0.3",
- "minimatch": "^9.0.4",
- "semver": "^7.6.0",
- "ts-api-utils": "^1.3.0"
- },
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/utils/node_modules/minimatch": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
- "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=16 || 14 >=14.17"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/visitor-keys": {
- "version": "7.16.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.1.tgz",
- "integrity": "sha512-Qlzzx4sE4u3FsHTPQAAQFJFNOuqtuY0LFrZHwQ8IHK705XxBiWOFkfKRWu6niB7hwfgnwIpO4jTC75ozW1PHWg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/types": "7.16.1",
- "eslint-visitor-keys": "^3.4.3"
- },
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/visitor-keys/node_modules/@typescript-eslint/types": {
- "version": "7.16.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.1.tgz",
- "integrity": "sha512-AQn9XqCzUXd4bAVEsAXM/Izk11Wx2u4H3BAfQVhSfzfDOm/wAON9nP7J5rpkCxts7E5TELmN845xTUCQrD1xIQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/aria-query": {
- "version": "5.1.3",
- "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz",
- "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "deep-equal": "^2.0.5"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/doctrine": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
- "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "esutils": "^2.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/eslint-plugin-import": {
- "version": "2.30.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.30.0.tgz",
- "integrity": "sha512-/mHNE9jINJfiD2EKkg1BKyPyUk4zdnT54YgbOgfjSakWT5oyX/qQLVNTkehyfpcMxZXMy1zyonZ2v7hZTX43Yw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@rtsao/scc": "^1.1.0",
- "array-includes": "^3.1.8",
- "array.prototype.findlastindex": "^1.2.5",
- "array.prototype.flat": "^1.3.2",
- "array.prototype.flatmap": "^1.3.2",
- "debug": "^3.2.7",
- "doctrine": "^2.1.0",
- "eslint-import-resolver-node": "^0.3.9",
- "eslint-module-utils": "^2.9.0",
- "hasown": "^2.0.2",
- "is-core-module": "^2.15.1",
- "is-glob": "^4.0.3",
- "minimatch": "^3.1.2",
- "object.fromentries": "^2.0.8",
- "object.groupby": "^1.0.3",
- "object.values": "^1.2.0",
- "semver": "^6.3.1",
- "tsconfig-paths": "^3.15.0"
- },
- "engines": {
- "node": ">=4"
- },
- "peerDependencies": {
- "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/eslint-plugin-import/node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/eslint-plugin-import/node_modules/debug": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
- "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.1"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/eslint-plugin-import/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/eslint-plugin-import/node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/eslint-plugin-jsx-a11y": {
- "version": "6.10.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.0.tgz",
- "integrity": "sha512-ySOHvXX8eSN6zz8Bywacm7CvGNhUtdjvqfQDVe6020TUK34Cywkw7m0KsCCk1Qtm9G1FayfTN1/7mMYnYO2Bhg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "aria-query": "~5.1.3",
- "array-includes": "^3.1.8",
- "array.prototype.flatmap": "^1.3.2",
- "ast-types-flow": "^0.0.8",
- "axe-core": "^4.10.0",
- "axobject-query": "^4.1.0",
- "damerau-levenshtein": "^1.0.8",
- "emoji-regex": "^9.2.2",
- "es-iterator-helpers": "^1.0.19",
- "hasown": "^2.0.2",
- "jsx-ast-utils": "^3.3.5",
- "language-tags": "^1.0.9",
- "minimatch": "^3.1.2",
- "object.fromentries": "^2.0.8",
- "safe-regex-test": "^1.0.3",
- "string.prototype.includes": "^2.0.0"
- },
- "engines": {
- "node": ">=4.0"
- },
- "peerDependencies": {
- "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/eslint-scope": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz",
- "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "esrecurse": "^4.3.0",
- "estraverse": "^5.2.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/eslint-visitor-keys": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
- "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/typescript": {
- "version": "5.6.2",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz",
- "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==",
- "dev": true,
- "license": "Apache-2.0",
- "bin": {
- "tsc": "bin/tsc",
- "tsserver": "bin/tsserver"
- },
- "engines": {
- "node": ">=14.17"
- }
- },
"node_modules/eslint-plugin-unicorn": {
"version": "56.0.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-56.0.1.tgz",
@@ -9514,9 +8500,9 @@
}
},
"node_modules/eslint-plugin-unicorn/node_modules/globals": {
- "version": "15.13.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-15.13.0.tgz",
- "integrity": "sha512-49TewVEz0UxZjr1WYYsWpPrhyC/B/pA8Bq0fUmet2n+eR7yn0IvNzNaoBwnK6mdkzcN+se7Ez9zUgULTz2QH4g==",
+ "version": "15.14.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz",
+ "integrity": "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==",
"dev": true,
"license": "MIT",
"engines": {
@@ -10995,9 +9981,9 @@
}
},
"node_modules/jiti": {
- "version": "1.21.6",
- "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz",
- "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==",
+ "version": "1.21.7",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
+ "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
"license": "MIT",
"bin": {
"jiti": "bin/jiti.js"
@@ -11017,10 +10003,9 @@
"license": "MIT"
},
"node_modules/js-tokens": {
- "version": "9.0.1",
- "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz",
- "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==",
- "dev": true,
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"license": "MIT"
},
"node_modules/js-types": {
@@ -11066,9 +10051,9 @@
}
},
"node_modules/jsesc": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz",
- "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
"dev": true,
"license": "MIT",
"bin": {
@@ -11188,9 +10173,9 @@
"license": "MIT"
},
"node_modules/katex": {
- "version": "0.16.11",
- "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.11.tgz",
- "integrity": "sha512-RQrI8rlHY92OLf3rho/Ts8i/XvjgguEjOkO1BEXcU3N8BqPpSzBNwV/G0Ukr+P/l3ivvJUE/Fa/CwbS6HesGNQ==",
+ "version": "0.16.18",
+ "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.18.tgz",
+ "integrity": "sha512-LRuk0rPdXrecAFwQucYjMiIs0JFefk6N1q/04mlw14aVIVgxq1FO0MA9RiIIGVaKOB5GIP5GH4aBBNraZERmaQ==",
"funding": [
"https://opencollective.com/katex",
"https://github.com/sponsors/katex"
@@ -11555,26 +10540,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/loose-envify": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
- "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "js-tokens": "^3.0.0 || ^4.0.0"
- },
- "bin": {
- "loose-envify": "cli.js"
- }
- },
- "node_modules/loose-envify/node_modules/js-tokens": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
- "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/loupe": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz",
@@ -11593,13 +10558,13 @@
}
},
"node_modules/lru-cache": {
- "version": "11.0.2",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz",
- "integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==",
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
"dev": true,
"license": "ISC",
- "engines": {
- "node": "20 || >=22"
+ "dependencies": {
+ "yallist": "^3.0.2"
}
},
"node_modules/magic-string": {
@@ -11767,9 +10732,9 @@
}
},
"node_modules/mdn-data": {
- "version": "2.12.1",
- "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.1.tgz",
- "integrity": "sha512-rsfnCbOHjqrhWxwt5/wtSLzpoKTzW7OXdT5lLOIH1OTYhWu9rRJveGq0sKvDZODABH7RX+uoR+DYcpFnq4Tf6Q==",
+ "version": "2.12.2",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz",
+ "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==",
"dev": true,
"license": "CC0-1.0"
},
@@ -11959,9 +10924,9 @@
}
},
"node_modules/monaco-editor": {
- "version": "0.52.0",
- "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.0.tgz",
- "integrity": "sha512-OeWhNpABLCeTqubfqLMXGsqf6OmPU6pHM85kF3dhy6kq5hnhuVS1p3VrEW/XhWHc71P2tHyS5JFySD8mgs1crw==",
+ "version": "0.52.2",
+ "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.2.tgz",
+ "integrity": "sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==",
"license": "MIT"
},
"node_modules/monaco-editor-webpack-plugin": {
@@ -12079,9 +11044,9 @@
}
},
"node_modules/node-releases": {
- "version": "2.0.18",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz",
- "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==",
+ "version": "2.0.19",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
+ "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
"license": "MIT"
},
"node_modules/node-sarif-builder": {
@@ -12099,9 +11064,9 @@
}
},
"node_modules/nolyfill": {
- "version": "1.0.42",
- "resolved": "https://registry.npmjs.org/nolyfill/-/nolyfill-1.0.42.tgz",
- "integrity": "sha512-OG++zEsBoEbEmsuF/yjh91dLCTxt8tSJdV7ZzufpszpvG69opWsK9MfAnfjntVVQhreEeBNvwnftI/mCZVBh6w==",
+ "version": "1.0.43",
+ "resolved": "https://registry.npmjs.org/nolyfill/-/nolyfill-1.0.43.tgz",
+ "integrity": "sha512-wi8cCDStYl2cmKOWoF5Jv/0PZXkFcRgKpk9rtxWk+7/VDlI6WDBdPM5nUOsphZjibudajsyAh1+QQvxCyLnbMA==",
"dev": true,
"license": "MIT",
"bin": {
@@ -12198,20 +11163,6 @@
"node": ">=12.4.0"
}
},
- "node_modules/object.entries": {
- "name": "@nolyfill/object.entries",
- "version": "1.0.28",
- "resolved": "https://registry.npmjs.org/@nolyfill/object.entries/-/object.entries-1.0.28.tgz",
- "integrity": "sha512-2t4PayP6Sx7Z20HJjcf8XhhPBO8/H31bwMdP0yEdDcxSXeEhl90Ibb9E3XKzSlcsGf43nXyfabHNrnfvdWE4Ng==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@nolyfill/shared": "1.0.28"
- },
- "engines": {
- "node": ">=12.4.0"
- }
- },
"node_modules/object.fromentries": {
"name": "@nolyfill/object.fromentries",
"version": "1.0.28",
@@ -12434,6 +11385,16 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/path-scurry/node_modules/lru-cache": {
+ "version": "11.0.2",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz",
+ "integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
"node_modules/path-type": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
@@ -12584,13 +11545,13 @@
}
},
"node_modules/playwright": {
- "version": "1.49.0",
- "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.0.tgz",
- "integrity": "sha512-eKpmys0UFDnfNb3vfsf8Vx2LEOtflgRebl0Im2eQQnYMA4Aqd+Zw8bEOB+7ZKvN76901mRnqdsiOGKxzVTbi7A==",
+ "version": "1.49.1",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.1.tgz",
+ "integrity": "sha512-VYL8zLoNTBxVOrJBbDuRgDWa3i+mfQgDTrL8Ah9QXZ7ax4Dsj0MSq5bYgytRnDVVe+njoKnfsYkH3HzqVj5UZA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "playwright-core": "1.49.0"
+ "playwright-core": "1.49.1"
},
"bin": {
"playwright": "cli.js"
@@ -12603,9 +11564,9 @@
}
},
"node_modules/playwright-core": {
- "version": "1.49.0",
- "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.0.tgz",
- "integrity": "sha512-R+3KKTQF3npy5GTiKH/T+kdhoJfJojjHESR1YEWhYuEKRVfVaxH3+4+GvXE5xyCngCxhxnykk0Vlah9v8fs3jA==",
+ "version": "1.49.1",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.1.tgz",
+ "integrity": "sha512-BzmpVcs4kE2CH15rWfzpjzVGhWERJfmnXmniSyKeRZUs9Ws65m+RGIi7mjJK/euCegfn3i7jvqWeWyHe9y3Vgg==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -12695,6 +11656,13 @@
"node": "^12 || >=14"
}
},
+ "node_modules/postcss-html/node_modules/js-tokens": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz",
+ "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/postcss-import": {
"version": "15.1.0",
"resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
@@ -12810,9 +11778,9 @@
}
},
"node_modules/postcss-modules-local-by-default": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.1.0.tgz",
- "integrity": "sha512-rm0bdSv4jC3BDma3s9H19ZddW0aHX6EoqwDYU2IfZhRN+53QrufTRo2IdkAbRqLx4R2IYbZnbjKKxg4VN5oU9Q==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz",
+ "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==",
"license": "MIT",
"dependencies": {
"icss-utils": "^5.0.0",
@@ -13127,18 +12095,6 @@
"dev": true,
"license": "Unlicense"
},
- "node_modules/prop-types": {
- "version": "15.8.1",
- "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
- "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "loose-envify": "^1.4.0",
- "object-assign": "^4.1.1",
- "react-is": "^16.13.1"
- }
- },
"node_modules/proto-props": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/proto-props/-/proto-props-2.0.0.tgz",
@@ -13197,13 +12153,6 @@
"safe-buffer": "^5.1.0"
}
},
- "node_modules/react-is": {
- "version": "16.13.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
- "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
@@ -13438,6 +12387,19 @@
"node": ">=4"
}
},
+ "node_modules/regexpu-core/node_modules/jsesc": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz",
+ "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/regexpu-core/node_modules/regjsparser": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz",
@@ -13509,12 +12471,12 @@
}
},
"node_modules/resolve": {
- "version": "1.22.8",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
- "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
+ "version": "1.22.9",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.9.tgz",
+ "integrity": "sha512-QxrmX1DzraFIi9PxdG5VkRfRwIgjwyud+z/iBwfRRrVmHc+P9Q7u2lSSpQ6bjr2gy5lrqIiU9vb6iAeGf2400A==",
"license": "MIT",
"dependencies": {
- "is-core-module": "^2.13.0",
+ "is-core-module": "^2.16.0",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
},
@@ -13716,9 +12678,9 @@
"license": "ISC"
},
"node_modules/schema-utils": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz",
- "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==",
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz",
+ "integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==",
"license": "MIT",
"dependencies": {
"@types/json-schema": "^7.0.9",
@@ -13727,7 +12689,7 @@
"ajv-keywords": "^5.1.0"
},
"engines": {
- "node": ">= 12.13.0"
+ "node": ">= 10.13.0"
},
"funding": {
"type": "opencollective",
@@ -14125,34 +13087,6 @@
"node": ">=12.4.0"
}
},
- "node_modules/string.prototype.matchall": {
- "name": "@nolyfill/string.prototype.matchall",
- "version": "1.0.28",
- "resolved": "https://registry.npmjs.org/@nolyfill/string.prototype.matchall/-/string.prototype.matchall-1.0.28.tgz",
- "integrity": "sha512-k74WKi7WmtRV847QWlY1ndg6XU1loeAyO9+NVoXrd7RL5lEjBtovp4CPZkifipBMBrZrZu2WwrQqkGrvLNZYpw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@nolyfill/shared": "1.0.28"
- },
- "engines": {
- "node": ">=12.4.0"
- }
- },
- "node_modules/string.prototype.repeat": {
- "name": "@nolyfill/string.prototype.repeat",
- "version": "1.0.28",
- "resolved": "https://registry.npmjs.org/@nolyfill/string.prototype.repeat/-/string.prototype.repeat-1.0.28.tgz",
- "integrity": "sha512-8ww39xe0r4qki8HwAaXTRamO0KpkHHyYoG+PCOFGaBZ8rrlAKcGQcJhu5aB2axauggqsnUfU25j5snEC0aJvYg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@nolyfill/shared": "1.0.28"
- },
- "engines": {
- "node": ">=12.4.0"
- }
- },
"node_modules/string.prototype.trimend": {
"name": "@nolyfill/string.prototype.trimend",
"version": "1.0.28",
@@ -14236,9 +13170,9 @@
"license": "ISC"
},
"node_modules/stylelint": {
- "version": "16.11.0",
- "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.11.0.tgz",
- "integrity": "sha512-zrl4IrKmjJQ+h9FoMp69UMCq5SxeHk0URhxUBj4d3ISzo/DplOFBJZc7t7Dr6otB+1bfbbKNLOmCDpzKSlW+Nw==",
+ "version": "16.12.0",
+ "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.12.0.tgz",
+ "integrity": "sha512-F8zZ3L/rBpuoBZRvI4JVT20ZanPLXfQLzMOZg1tzPflRVh9mKpOZ8qcSIhh1my3FjAjZWG4T2POwGnmn6a6hbg==",
"dev": true,
"funding": [
{
@@ -14288,7 +13222,7 @@
"string-width": "^4.2.3",
"supports-hyperlinks": "^3.1.0",
"svg-tags": "^1.0.0",
- "table": "^6.8.2",
+ "table": "^6.9.0",
"write-file-atomic": "^5.0.1"
},
"bin": {
@@ -14801,9 +13735,9 @@
}
},
"node_modules/tailwindcss": {
- "version": "3.4.16",
- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.16.tgz",
- "integrity": "sha512-TI4Cyx7gDiZ6r44ewaJmt0o6BrMCT5aK5e0rmJ/G9Xq3w7CX/5VXl/zIPEJZFUK5VEqwByyhqNPycPlvcK4ZNw==",
+ "version": "3.4.17",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz",
+ "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==",
"license": "MIT",
"dependencies": {
"@alloc/quick-lru": "^5.2.0",
@@ -14847,9 +13781,9 @@
}
},
"node_modules/terser": {
- "version": "5.36.0",
- "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz",
- "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==",
+ "version": "5.37.0",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz",
+ "integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==",
"license": "BSD-2-Clause",
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
@@ -14865,16 +13799,16 @@
}
},
"node_modules/terser-webpack-plugin": {
- "version": "5.3.10",
- "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz",
- "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==",
+ "version": "5.3.11",
+ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.11.tgz",
+ "integrity": "sha512-RVCsMfuD0+cTt3EwX8hSl2Ks56EbFHWmhluwcqoPKtBnfjiT6olaq7PRIRfhyU8nnC2MrnDrBLfrD/RGE+cVXQ==",
"license": "MIT",
"dependencies": {
- "@jridgewell/trace-mapping": "^0.3.20",
+ "@jridgewell/trace-mapping": "^0.3.25",
"jest-worker": "^27.4.5",
- "schema-utils": "^3.1.1",
- "serialize-javascript": "^6.0.1",
- "terser": "^5.26.0"
+ "schema-utils": "^4.3.0",
+ "serialize-javascript": "^6.0.2",
+ "terser": "^5.31.1"
},
"engines": {
"node": ">= 10.13.0"
@@ -14898,55 +13832,6 @@
}
}
},
- "node_modules/terser-webpack-plugin/node_modules/ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
- "license": "MIT",
- "dependencies": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
- }
- },
- "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": {
- "version": "3.5.2",
- "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
- "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
- "license": "MIT",
- "peerDependencies": {
- "ajv": "^6.9.1"
- }
- },
- "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "license": "MIT"
- },
- "node_modules/terser-webpack-plugin/node_modules/schema-utils": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
- "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
- "license": "MIT",
- "dependencies": {
- "@types/json-schema": "^7.0.8",
- "ajv": "^6.12.5",
- "ajv-keywords": "^3.5.2"
- },
- "engines": {
- "node": ">= 10.13.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/webpack"
- }
- },
"node_modules/terser/node_modules/commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
@@ -15153,9 +14038,9 @@
}
},
"node_modules/type-fest": {
- "version": "4.30.0",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.30.0.tgz",
- "integrity": "sha512-G6zXWS1dLj6eagy6sVhOMQiLtJdxQBHIA9Z6HFUNLOlr6MFOgzV8wvmidtPONfPtEUv0uZsy77XJNzTAfwPDaA==",
+ "version": "4.30.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.30.2.tgz",
+ "integrity": "sha512-UJShLPYi1aWqCdq9HycOL/gwsuqda1OISdBO3t8RlXQC4QvtuIz4b5FCfe2dQIWEpmlRExKmcTBfP1r9bhY7ig==",
"dev": true,
"license": "(MIT OR CC0-1.0)",
"engines": {
@@ -15179,15 +14064,15 @@
}
},
"node_modules/typescript-eslint": {
- "version": "8.17.0",
- "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.17.0.tgz",
- "integrity": "sha512-409VXvFd/f1br1DCbuKNFqQpXICoTB+V51afcwG1pn1a3Cp92MqAUges3YjwEdQ0cMUoCIodjVDAYzyD8h3SYA==",
+ "version": "8.18.1",
+ "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.18.1.tgz",
+ "integrity": "sha512-Mlaw6yxuaDEPQvb/2Qwu3/TfgeBHy9iTJ3mTwe7OvpPmF6KPQjVOfGyEJpPv6Ez2C34OODChhXrzYw/9phI0MQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/eslint-plugin": "8.17.0",
- "@typescript-eslint/parser": "8.17.0",
- "@typescript-eslint/utils": "8.17.0"
+ "@typescript-eslint/eslint-plugin": "8.18.1",
+ "@typescript-eslint/parser": "8.18.1",
+ "@typescript-eslint/utils": "8.18.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -15197,18 +14082,14 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <5.8.0"
}
},
"node_modules/typo-js": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/typo-js/-/typo-js-1.2.4.tgz",
- "integrity": "sha512-Oy/k+tFle5NAA3J/yrrYGfvEnPVrDZ8s8/WCwjUE75k331QyKIsFss7byQ/PzBmXLY6h1moRnZbnaxWBe3I3CA==",
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/typo-js/-/typo-js-1.2.5.tgz",
+ "integrity": "sha512-F45vFWdGX8xahIk/sOp79z2NJs8ETMYsmMChm9D5Hlx3+9j7VnCyQyvij5MOCrNY3NNe8noSyokRjQRfq+Bc7A==",
"license": "BSD-3-Clause"
},
"node_modules/uc.micro": {
@@ -15321,9 +14202,9 @@
}
},
"node_modules/updates": {
- "version": "16.4.0",
- "resolved": "https://registry.npmjs.org/updates/-/updates-16.4.0.tgz",
- "integrity": "sha512-HtkG1MgXbQ5gpqu5eX4qVOwclMHbygiTYjSkFMVDEXuwb5clwkDh75xRb11PzRX9ozVOfcVUHl7lpBNDPquXrw==",
+ "version": "16.4.1",
+ "resolved": "https://registry.npmjs.org/updates/-/updates-16.4.1.tgz",
+ "integrity": "sha512-dYsXzAISSiTFk6mg2ZB7IOlhIN5CO4qINxpbN7rrE9ffpuycq82SZ8rvLSc2QpBEO98BBY7wKm3d8SdA94o5TQ==",
"dev": true,
"license": "BSD-2-Clause",
"bin": {
@@ -15518,9 +14399,9 @@
}
},
"node_modules/vite/node_modules/rollup": {
- "version": "4.28.0",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.28.0.tgz",
- "integrity": "sha512-G9GOrmgWHBma4YfCcX8PjH0qhXSdH8B4HDE2o4/jaxj93S4DPCIDoLcXz99eWMji4hB29UFCEd7B2gwGJDR9cQ==",
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.28.1.tgz",
+ "integrity": "sha512-61fXYl/qNVinKmGSTHAZ6Yy8I3YIJC/r2m9feHo6SwVAVcLT5MPwOUFe7EuURA/4m0NR8lXG4BBXuo/IZEsjMg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -15534,24 +14415,25 @@
"npm": ">=8.0.0"
},
"optionalDependencies": {
- "@rollup/rollup-android-arm-eabi": "4.28.0",
- "@rollup/rollup-android-arm64": "4.28.0",
- "@rollup/rollup-darwin-arm64": "4.28.0",
- "@rollup/rollup-darwin-x64": "4.28.0",
- "@rollup/rollup-freebsd-arm64": "4.28.0",
- "@rollup/rollup-freebsd-x64": "4.28.0",
- "@rollup/rollup-linux-arm-gnueabihf": "4.28.0",
- "@rollup/rollup-linux-arm-musleabihf": "4.28.0",
- "@rollup/rollup-linux-arm64-gnu": "4.28.0",
- "@rollup/rollup-linux-arm64-musl": "4.28.0",
- "@rollup/rollup-linux-powerpc64le-gnu": "4.28.0",
- "@rollup/rollup-linux-riscv64-gnu": "4.28.0",
- "@rollup/rollup-linux-s390x-gnu": "4.28.0",
- "@rollup/rollup-linux-x64-gnu": "4.28.0",
- "@rollup/rollup-linux-x64-musl": "4.28.0",
- "@rollup/rollup-win32-arm64-msvc": "4.28.0",
- "@rollup/rollup-win32-ia32-msvc": "4.28.0",
- "@rollup/rollup-win32-x64-msvc": "4.28.0",
+ "@rollup/rollup-android-arm-eabi": "4.28.1",
+ "@rollup/rollup-android-arm64": "4.28.1",
+ "@rollup/rollup-darwin-arm64": "4.28.1",
+ "@rollup/rollup-darwin-x64": "4.28.1",
+ "@rollup/rollup-freebsd-arm64": "4.28.1",
+ "@rollup/rollup-freebsd-x64": "4.28.1",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.28.1",
+ "@rollup/rollup-linux-arm-musleabihf": "4.28.1",
+ "@rollup/rollup-linux-arm64-gnu": "4.28.1",
+ "@rollup/rollup-linux-arm64-musl": "4.28.1",
+ "@rollup/rollup-linux-loongarch64-gnu": "4.28.1",
+ "@rollup/rollup-linux-powerpc64le-gnu": "4.28.1",
+ "@rollup/rollup-linux-riscv64-gnu": "4.28.1",
+ "@rollup/rollup-linux-s390x-gnu": "4.28.1",
+ "@rollup/rollup-linux-x64-gnu": "4.28.1",
+ "@rollup/rollup-linux-x64-musl": "4.28.1",
+ "@rollup/rollup-win32-arm64-msvc": "4.28.1",
+ "@rollup/rollup-win32-ia32-msvc": "4.28.1",
+ "@rollup/rollup-win32-x64-msvc": "4.28.1",
"fsevents": "~2.3.2"
}
},
@@ -15622,9 +14504,9 @@
}
},
"node_modules/vitest/node_modules/magic-string": {
- "version": "0.30.14",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.14.tgz",
- "integrity": "sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw==",
+ "version": "0.30.17",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
+ "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -15822,9 +14704,9 @@
}
},
"node_modules/webpack": {
- "version": "5.97.0",
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.0.tgz",
- "integrity": "sha512-CWT8v7ShSfj7tGs4TLRtaOLmOCPWhoKEvp+eA7FVx8Xrjb3XfT0aXdxDItnRZmE8sHcH+a8ayDrJCOjXKxVFfQ==",
+ "version": "5.97.1",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz",
+ "integrity": "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==",
"license": "MIT",
"dependencies": {
"@types/eslint-scope": "^3.7.7",
diff --git a/package.json b/package.json
index 61e65c1f43..9f5fbe3fdd 100644
--- a/package.json
+++ b/package.json
@@ -12,7 +12,7 @@
"@github/relative-time-element": "4.4.4",
"@github/text-expander-element": "2.8.0",
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
- "@primer/octicons": "19.13.0",
+ "@primer/octicons": "19.14.0",
"@silverwind/vue3-calendar-heatmap": "2.0.6",
"add-asset-webpack-plugin": "3.0.0",
"ansi_up": "6.0.2",
@@ -32,12 +32,12 @@
"htmx.org": "2.0.4",
"idiomorph": "0.3.0",
"jquery": "3.7.1",
- "katex": "0.16.11",
+ "katex": "0.16.18",
"license-checker-webpack-plugin": "0.2.1",
"mermaid": "11.4.1",
"mini-css-extract-plugin": "2.9.2",
"minimatch": "10.0.1",
- "monaco-editor": "0.52.0",
+ "monaco-editor": "0.52.2",
"monaco-editor-webpack-plugin": "7.1.0",
"pdfobject": "2.3.0",
"perfect-debounce": "1.0.0",
@@ -46,7 +46,7 @@
"postcss-nesting": "13.0.1",
"sortablejs": "1.15.6",
"swagger-ui-dist": "5.18.2",
- "tailwindcss": "3.4.16",
+ "tailwindcss": "3.4.17",
"throttle-debounce": "5.0.2",
"tinycolor2": "1.6.0",
"tippy.js": "6.3.7",
@@ -59,16 +59,16 @@
"vue-bar-graph": "2.2.0",
"vue-chartjs": "5.3.2",
"vue-loader": "17.4.2",
- "webpack": "5.97.0",
+ "webpack": "5.97.1",
"webpack-cli": "5.1.4",
"wrap-ansi": "9.0.0"
},
"devDependencies": {
"@eslint-community/eslint-plugin-eslint-comments": "4.4.1",
- "@playwright/test": "1.49.0",
+ "@playwright/test": "1.49.1",
"@silverwind/vue-tsc": "2.1.13",
"@stoplight/spectral-cli": "6.14.2",
- "@stylistic/eslint-plugin-js": "2.11.0",
+ "@stylistic/eslint-plugin-js": "2.12.1",
"@stylistic/stylelint-plugin": "3.1.1",
"@types/dropzone": "5.7.9",
"@types/jquery": "3.5.32",
@@ -80,19 +80,19 @@
"@types/throttle-debounce": "5.0.2",
"@types/tinycolor2": "1.4.6",
"@types/toastify-js": "1.12.3",
- "@typescript-eslint/eslint-plugin": "8.17.0",
- "@typescript-eslint/parser": "8.17.0",
+ "@typescript-eslint/eslint-plugin": "8.18.1",
+ "@typescript-eslint/parser": "8.18.1",
"@vitejs/plugin-vue": "5.2.1",
"eslint": "8.57.0",
"eslint-import-resolver-typescript": "3.7.0",
"eslint-plugin-array-func": "4.0.0",
- "eslint-plugin-github": "5.1.3",
- "eslint-plugin-import-x": "4.5.0",
+ "eslint-plugin-github": "5.1.4",
+ "eslint-plugin-import-x": "4.6.1",
"eslint-plugin-no-jquery": "3.1.0",
"eslint-plugin-no-use-extend-native": "0.5.0",
"eslint-plugin-playwright": "2.1.0",
"eslint-plugin-regexp": "2.7.0",
- "eslint-plugin-sonarjs": "2.0.4",
+ "eslint-plugin-sonarjs": "3.0.1",
"eslint-plugin-unicorn": "56.0.1",
"eslint-plugin-vitest": "0.4.1",
"eslint-plugin-vitest-globals": "1.5.0",
@@ -101,15 +101,15 @@
"eslint-plugin-wc": "2.2.0",
"happy-dom": "15.11.7",
"markdownlint-cli": "0.43.0",
- "nolyfill": "1.0.42",
+ "nolyfill": "1.0.43",
"postcss-html": "1.7.0",
- "stylelint": "16.11.0",
+ "stylelint": "16.12.0",
"stylelint-declaration-block-no-ignored-properties": "2.8.0",
"stylelint-declaration-strict-value": "1.10.6",
"stylelint-value-no-unknown-custom-properties": "6.0.1",
"svgo": "3.3.2",
- "type-fest": "4.30.0",
- "updates": "16.4.0",
+ "type-fest": "4.30.2",
+ "updates": "16.4.1",
"vite-string-plugin": "1.3.4",
"vitest": "2.1.8"
},
diff --git a/routers/api/actions/artifacts.go b/routers/api/actions/artifacts.go
index 0a7f92ac40..910edd6d58 100644
--- a/routers/api/actions/artifacts.go
+++ b/routers/api/actions/artifacts.go
@@ -126,11 +126,10 @@ func ArtifactsRoutes(prefix string) *web.Router {
func ArtifactContexter() func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
- base, baseCleanUp := context.NewBaseContext(resp, req)
- defer baseCleanUp()
+ base := context.NewBaseContext(resp, req)
ctx := &ArtifactContext{Base: base}
- ctx.AppendContextValue(artifactContextKey, ctx)
+ ctx.SetContextValue(artifactContextKey, ctx)
// action task call server api with Bearer ACTIONS_RUNTIME_TOKEN
// we should verify the ACTIONS_RUNTIME_TOKEN
diff --git a/routers/api/actions/artifactsv4.go b/routers/api/actions/artifactsv4.go
index 6dd36888d2..8917a7a8a2 100644
--- a/routers/api/actions/artifactsv4.go
+++ b/routers/api/actions/artifactsv4.go
@@ -126,12 +126,9 @@ type artifactV4Routes struct {
func ArtifactV4Contexter() func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
- base, baseCleanUp := context.NewBaseContext(resp, req)
- defer baseCleanUp()
-
+ base := context.NewBaseContext(resp, req)
ctx := &ArtifactContext{Base: base}
- ctx.AppendContextValue(artifactContextKey, ctx)
-
+ ctx.SetContextValue(artifactContextKey, ctx)
next.ServeHTTP(ctx.Resp, ctx.Req)
})
}
diff --git a/routers/api/v1/admin/user.go b/routers/api/v1/admin/user.go
index b0f40084da..3f4a73dcad 100644
--- a/routers/api/v1/admin/user.go
+++ b/routers/api/v1/admin/user.go
@@ -9,10 +9,12 @@ import (
"fmt"
"net/http"
- "code.gitea.io/gitea/models"
asymkey_model "code.gitea.io/gitea/models/asymkey"
"code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
+ org_model "code.gitea.io/gitea/models/organization"
+ packages_model "code.gitea.io/gitea/models/packages"
+ repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/auth/password"
"code.gitea.io/gitea/modules/log"
@@ -247,7 +249,7 @@ func EditUser(ctx *context.APIContext) {
}
if err := user_service.UpdateUser(ctx, ctx.ContextUser, opts); err != nil {
- if models.IsErrDeleteLastAdminUser(err) {
+ if user_model.IsErrDeleteLastAdminUser(err) {
ctx.Error(http.StatusBadRequest, "LastAdmin", err)
} else {
ctx.Error(http.StatusInternalServerError, "UpdateUser", err)
@@ -299,10 +301,10 @@ func DeleteUser(ctx *context.APIContext) {
}
if err := user_service.DeleteUser(ctx, ctx.ContextUser, ctx.FormBool("purge")); err != nil {
- if models.IsErrUserOwnRepos(err) ||
- models.IsErrUserHasOrgs(err) ||
- models.IsErrUserOwnPackages(err) ||
- models.IsErrDeleteLastAdminUser(err) {
+ if repo_model.IsErrUserOwnRepos(err) ||
+ org_model.IsErrUserHasOrgs(err) ||
+ packages_model.IsErrUserOwnPackages(err) ||
+ user_model.IsErrDeleteLastAdminUser(err) {
ctx.Error(http.StatusUnprocessableEntity, "", err)
} else {
ctx.Error(http.StatusInternalServerError, "DeleteUser", err)
diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go
index 946203e97e..f6df866efc 100644
--- a/routers/api/v1/repo/branch.go
+++ b/routers/api/v1/repo/branch.go
@@ -9,7 +9,6 @@ import (
"fmt"
"net/http"
- "code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
"code.gitea.io/gitea/models/organization"
@@ -24,6 +23,7 @@ import (
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
pull_service "code.gitea.io/gitea/services/pull"
+ release_service "code.gitea.io/gitea/services/release"
repo_service "code.gitea.io/gitea/services/repository"
)
@@ -247,7 +247,7 @@ func CreateBranch(ctx *context.APIContext) {
if err != nil {
if git_model.IsErrBranchNotExist(err) {
ctx.Error(http.StatusNotFound, "", "The old branch does not exist")
- } else if models.IsErrTagAlreadyExists(err) {
+ } else if release_service.IsErrTagAlreadyExists(err) {
ctx.Error(http.StatusConflict, "", "The branch with the same tag already exists.")
} else if git_model.IsErrBranchAlreadyExists(err) || git.IsErrPushOutOfDate(err) {
ctx.Error(http.StatusConflict, "", "The branch already exists.")
@@ -729,15 +729,11 @@ func CreateBranchProtection(ctx *context.APIContext) {
} else {
if !isPlainRule {
if ctx.Repo.GitRepo == nil {
- ctx.Repo.GitRepo, err = gitrepo.OpenRepository(ctx, ctx.Repo.Repository)
+ ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx, ctx.Repo.Repository)
if err != nil {
ctx.Error(http.StatusInternalServerError, "OpenRepository", err)
return
}
- defer func() {
- ctx.Repo.GitRepo.Close()
- ctx.Repo.GitRepo = nil
- }()
}
// FIXME: since we only need to recheck files protected rules, we could improve this
matchedBranches, err := git_model.FindAllMatchedBranches(ctx, ctx.Repo.Repository.ID, ruleName)
@@ -1061,15 +1057,11 @@ func EditBranchProtection(ctx *context.APIContext) {
} else {
if !isPlainRule {
if ctx.Repo.GitRepo == nil {
- ctx.Repo.GitRepo, err = gitrepo.OpenRepository(ctx, ctx.Repo.Repository)
+ ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx, ctx.Repo.Repository)
if err != nil {
ctx.Error(http.StatusInternalServerError, "OpenRepository", err)
return
}
- defer func() {
- ctx.Repo.GitRepo.Close()
- ctx.Repo.GitRepo = nil
- }()
}
// FIXME: since we only need to recheck files protected rules, we could improve this
diff --git a/routers/api/v1/repo/compare.go b/routers/api/v1/repo/compare.go
index 1678bc033c..87b890cb62 100644
--- a/routers/api/v1/repo/compare.go
+++ b/routers/api/v1/repo/compare.go
@@ -44,13 +44,12 @@ func CompareDiff(ctx *context.APIContext) {
// "$ref": "#/responses/notFound"
if ctx.Repo.GitRepo == nil {
- gitRepo, err := gitrepo.OpenRepository(ctx, ctx.Repo.Repository)
+ var err error
+ ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx, ctx.Repo.Repository)
if err != nil {
ctx.Error(http.StatusInternalServerError, "OpenRepository", err)
return
}
- ctx.Repo.GitRepo = gitRepo
- defer gitRepo.Close()
}
infoPath := ctx.PathParam("*")
diff --git a/routers/api/v1/repo/download.go b/routers/api/v1/repo/download.go
index 3620c1465f..eb967772ed 100644
--- a/routers/api/v1/repo/download.go
+++ b/routers/api/v1/repo/download.go
@@ -28,13 +28,12 @@ func DownloadArchive(ctx *context.APIContext) {
}
if ctx.Repo.GitRepo == nil {
- gitRepo, err := gitrepo.OpenRepository(ctx, ctx.Repo.Repository)
+ var err error
+ ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx, ctx.Repo.Repository)
if err != nil {
ctx.Error(http.StatusInternalServerError, "OpenRepository", err)
return
}
- ctx.Repo.GitRepo = gitRepo
- defer gitRepo.Close()
}
r, err := archiver_service.NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, ctx.PathParam("*"), tp)
diff --git a/routers/api/v1/repo/file.go b/routers/api/v1/repo/file.go
index 959a4b952a..6591b9a752 100644
--- a/routers/api/v1/repo/file.go
+++ b/routers/api/v1/repo/file.go
@@ -15,7 +15,6 @@ import (
"strings"
"time"
- "code.gitea.io/gitea/models"
git_model "code.gitea.io/gitea/models/git"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
@@ -30,6 +29,7 @@ import (
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/common"
"code.gitea.io/gitea/services/context"
+ pull_service "code.gitea.io/gitea/services/pull"
archiver_service "code.gitea.io/gitea/services/repository/archiver"
files_service "code.gitea.io/gitea/services/repository/files"
)
@@ -287,13 +287,12 @@ func GetArchive(ctx *context.APIContext) {
// "$ref": "#/responses/notFound"
if ctx.Repo.GitRepo == nil {
- gitRepo, err := gitrepo.OpenRepository(ctx, ctx.Repo.Repository)
+ var err error
+ ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx, ctx.Repo.Repository)
if err != nil {
ctx.Error(http.StatusInternalServerError, "OpenRepository", err)
return
}
- ctx.Repo.GitRepo = gitRepo
- defer gitRepo.Close()
}
archiveDownload(ctx)
@@ -736,12 +735,12 @@ func UpdateFile(ctx *context.APIContext) {
}
func handleCreateOrUpdateFileError(ctx *context.APIContext, err error) {
- if models.IsErrUserCannotCommit(err) || models.IsErrFilePathProtected(err) {
+ if files_service.IsErrUserCannotCommit(err) || pull_service.IsErrFilePathProtected(err) {
ctx.Error(http.StatusForbidden, "Access", err)
return
}
- if git_model.IsErrBranchAlreadyExists(err) || models.IsErrFilenameInvalid(err) || models.IsErrSHADoesNotMatch(err) ||
- models.IsErrFilePathInvalid(err) || models.IsErrRepoFileAlreadyExists(err) {
+ if git_model.IsErrBranchAlreadyExists(err) || files_service.IsErrFilenameInvalid(err) || pull_service.IsErrSHADoesNotMatch(err) ||
+ files_service.IsErrFilePathInvalid(err) || files_service.IsErrRepoFileAlreadyExists(err) {
ctx.Error(http.StatusUnprocessableEntity, "Invalid", err)
return
}
@@ -887,17 +886,17 @@ func DeleteFile(ctx *context.APIContext) {
}
if filesResponse, err := files_service.ChangeRepoFiles(ctx, ctx.Repo.Repository, ctx.Doer, opts); err != nil {
- if git.IsErrBranchNotExist(err) || models.IsErrRepoFileDoesNotExist(err) || git.IsErrNotExist(err) {
+ if git.IsErrBranchNotExist(err) || files_service.IsErrRepoFileDoesNotExist(err) || git.IsErrNotExist(err) {
ctx.Error(http.StatusNotFound, "DeleteFile", err)
return
} else if git_model.IsErrBranchAlreadyExists(err) ||
- models.IsErrFilenameInvalid(err) ||
- models.IsErrSHADoesNotMatch(err) ||
- models.IsErrCommitIDDoesNotMatch(err) ||
- models.IsErrSHAOrCommitIDNotProvided(err) {
+ files_service.IsErrFilenameInvalid(err) ||
+ pull_service.IsErrSHADoesNotMatch(err) ||
+ files_service.IsErrCommitIDDoesNotMatch(err) ||
+ files_service.IsErrSHAOrCommitIDNotProvided(err) {
ctx.Error(http.StatusBadRequest, "DeleteFile", err)
return
- } else if models.IsErrUserCannotCommit(err) {
+ } else if files_service.IsErrUserCannotCommit(err) {
ctx.Error(http.StatusForbidden, "DeleteFile", err)
return
}
diff --git a/routers/api/v1/repo/migrate.go b/routers/api/v1/repo/migrate.go
index dcbd8f3dd5..452825c0a3 100644
--- a/routers/api/v1/repo/migrate.go
+++ b/routers/api/v1/repo/migrate.go
@@ -10,13 +10,13 @@ import (
"net/http"
"strings"
- "code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/organization"
"code.gitea.io/gitea/models/perm"
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/lfs"
"code.gitea.io/gitea/modules/log"
@@ -27,7 +27,6 @@ import (
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
- "code.gitea.io/gitea/services/forms"
"code.gitea.io/gitea/services/migrations"
notify_service "code.gitea.io/gitea/services/notify"
repo_service "code.gitea.io/gitea/services/repository"
@@ -104,7 +103,7 @@ func Migrate(ctx *context.APIContext) {
}
}
- remoteAddr, err := forms.ParseRemoteAddr(form.CloneAddr, form.AuthUsername, form.AuthPassword)
+ remoteAddr, err := git.ParseRemoteAddr(form.CloneAddr, form.AuthUsername, form.AuthPassword)
if err == nil {
err = migrations.IsMigrateURLAllowed(remoteAddr, ctx.Doer)
}
@@ -237,7 +236,7 @@ func handleMigrateError(ctx *context.APIContext, repoOwner *user_model.User, err
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("The username '%s' contains invalid characters.", err.(db.ErrNameCharsNotAllowed).Name))
case db.IsErrNamePatternNotAllowed(err):
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("The pattern '%s' is not allowed in a username.", err.(db.ErrNamePatternNotAllowed).Pattern))
- case models.IsErrInvalidCloneAddr(err):
+ case git.IsErrInvalidCloneAddr(err):
ctx.Error(http.StatusUnprocessableEntity, "", err)
case base.IsErrNotSupported(err):
ctx.Error(http.StatusUnprocessableEntity, "", err)
@@ -256,8 +255,8 @@ func handleMigrateError(ctx *context.APIContext, repoOwner *user_model.User, err
}
func handleRemoteAddrError(ctx *context.APIContext, err error) {
- if models.IsErrInvalidCloneAddr(err) {
- addrErr := err.(*models.ErrInvalidCloneAddr)
+ if git.IsErrInvalidCloneAddr(err) {
+ addrErr := err.(*git.ErrInvalidCloneAddr)
switch {
case addrErr.IsURLError:
ctx.Error(http.StatusUnprocessableEntity, "", err)
diff --git a/routers/api/v1/repo/mirror.go b/routers/api/v1/repo/mirror.go
index 310b82881e..047203501e 100644
--- a/routers/api/v1/repo/mirror.go
+++ b/routers/api/v1/repo/mirror.go
@@ -9,10 +9,10 @@ import (
"net/http"
"time"
- "code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
+ "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
@@ -20,7 +20,6 @@ import (
"code.gitea.io/gitea/routers/api/v1/utils"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
- "code.gitea.io/gitea/services/forms"
"code.gitea.io/gitea/services/migrations"
mirror_service "code.gitea.io/gitea/services/mirror"
)
@@ -344,7 +343,7 @@ func CreatePushMirror(ctx *context.APIContext, mirrorOption *api.CreatePushMirro
return
}
- address, err := forms.ParseRemoteAddr(mirrorOption.RemoteAddress, mirrorOption.RemoteUsername, mirrorOption.RemotePassword)
+ address, err := git.ParseRemoteAddr(mirrorOption.RemoteAddress, mirrorOption.RemoteUsername, mirrorOption.RemotePassword)
if err == nil {
err = migrations.IsMigrateURLAllowed(address, ctx.ContextUser)
}
@@ -397,8 +396,8 @@ func CreatePushMirror(ctx *context.APIContext, mirrorOption *api.CreatePushMirro
}
func HandleRemoteAddressError(ctx *context.APIContext, err error) {
- if models.IsErrInvalidCloneAddr(err) {
- addrErr := err.(*models.ErrInvalidCloneAddr)
+ if git.IsErrInvalidCloneAddr(err) {
+ addrErr := err.(*git.ErrInvalidCloneAddr)
switch {
case addrErr.IsProtocolInvalid:
ctx.Error(http.StatusBadRequest, "CreatePushMirror", "Invalid mirror protocol")
diff --git a/routers/api/v1/repo/patch.go b/routers/api/v1/repo/patch.go
index 0e0601b7d9..5e24dcf891 100644
--- a/routers/api/v1/repo/patch.go
+++ b/routers/api/v1/repo/patch.go
@@ -7,13 +7,13 @@ import (
"net/http"
"time"
- "code.gitea.io/gitea/models"
git_model "code.gitea.io/gitea/models/git"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/modules/git"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/context"
+ pull_service "code.gitea.io/gitea/services/pull"
"code.gitea.io/gitea/services/repository/files"
)
@@ -92,12 +92,12 @@ func ApplyDiffPatch(ctx *context.APIContext) {
fileResponse, err := files.ApplyDiffPatch(ctx, ctx.Repo.Repository, ctx.Doer, opts)
if err != nil {
- if models.IsErrUserCannotCommit(err) || models.IsErrFilePathProtected(err) {
+ if files.IsErrUserCannotCommit(err) || pull_service.IsErrFilePathProtected(err) {
ctx.Error(http.StatusForbidden, "Access", err)
return
}
- if git_model.IsErrBranchAlreadyExists(err) || models.IsErrFilenameInvalid(err) || models.IsErrSHADoesNotMatch(err) ||
- models.IsErrFilePathInvalid(err) || models.IsErrRepoFileAlreadyExists(err) {
+ if git_model.IsErrBranchAlreadyExists(err) || files.IsErrFilenameInvalid(err) || pull_service.IsErrSHADoesNotMatch(err) ||
+ files.IsErrFilePathInvalid(err) || files.IsErrRepoFileAlreadyExists(err) {
ctx.Error(http.StatusUnprocessableEntity, "Invalid", err)
return
}
diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go
index 6f4f3efaa1..71c4c81b67 100644
--- a/routers/api/v1/repo/pull.go
+++ b/routers/api/v1/repo/pull.go
@@ -12,7 +12,6 @@ import (
"strings"
"time"
- "code.gitea.io/gitea/models"
activities_model "code.gitea.io/gitea/models/activities"
git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues"
@@ -765,7 +764,7 @@ func EditPullRequest(ctx *context.APIContext) {
} else if issues_model.IsErrIssueIsClosed(err) {
ctx.Error(http.StatusUnprocessableEntity, "IsErrIssueIsClosed", err)
return
- } else if models.IsErrPullRequestHasMerged(err) {
+ } else if pull_service.IsErrPullRequestHasMerged(err) {
ctx.Error(http.StatusConflict, "IsErrPullRequestHasMerged", err)
return
}
@@ -941,7 +940,7 @@ func MergePullRequest(ctx *context.APIContext) {
ctx.Error(http.StatusMethodNotAllowed, "PR is a work in progress", "Work in progress PRs cannot be merged")
} else if errors.Is(err, pull_service.ErrNotMergeableState) {
ctx.Error(http.StatusMethodNotAllowed, "PR not in mergeable state", "Please try again later")
- } else if models.IsErrDisallowedToMerge(err) {
+ } else if pull_service.IsErrDisallowedToMerge(err) {
ctx.Error(http.StatusMethodNotAllowed, "PR is not ready to be merged", err)
} else if asymkey_service.IsErrWontSign(err) {
ctx.Error(http.StatusMethodNotAllowed, fmt.Sprintf("Protected branch %s requires signed commits but this merge would not be signed", pr.BaseBranch), err)
@@ -954,7 +953,7 @@ func MergePullRequest(ctx *context.APIContext) {
// handle manually-merged mark
if manuallyMerged {
if err := pull_service.MergedManually(ctx, pr, ctx.Doer, ctx.Repo.GitRepo, form.MergeCommitID); err != nil {
- if models.IsErrInvalidMergeStyle(err) {
+ if pull_service.IsErrInvalidMergeStyle(err) {
ctx.Error(http.StatusMethodNotAllowed, "Invalid merge style", fmt.Errorf("%s is not allowed an allowed merge style for this repository", repo_model.MergeStyle(form.Do)))
return
}
@@ -1004,20 +1003,20 @@ func MergePullRequest(ctx *context.APIContext) {
}
if err := pull_service.Merge(ctx, pr, ctx.Doer, ctx.Repo.GitRepo, repo_model.MergeStyle(form.Do), form.HeadCommitID, message, false); err != nil {
- if models.IsErrInvalidMergeStyle(err) {
+ if pull_service.IsErrInvalidMergeStyle(err) {
ctx.Error(http.StatusMethodNotAllowed, "Invalid merge style", fmt.Errorf("%s is not allowed an allowed merge style for this repository", repo_model.MergeStyle(form.Do)))
- } else if models.IsErrMergeConflicts(err) {
- conflictError := err.(models.ErrMergeConflicts)
+ } else if pull_service.IsErrMergeConflicts(err) {
+ conflictError := err.(pull_service.ErrMergeConflicts)
ctx.JSON(http.StatusConflict, conflictError)
- } else if models.IsErrRebaseConflicts(err) {
- conflictError := err.(models.ErrRebaseConflicts)
+ } else if pull_service.IsErrRebaseConflicts(err) {
+ conflictError := err.(pull_service.ErrRebaseConflicts)
ctx.JSON(http.StatusConflict, conflictError)
- } else if models.IsErrMergeUnrelatedHistories(err) {
- conflictError := err.(models.ErrMergeUnrelatedHistories)
+ } else if pull_service.IsErrMergeUnrelatedHistories(err) {
+ conflictError := err.(pull_service.ErrMergeUnrelatedHistories)
ctx.JSON(http.StatusConflict, conflictError)
} else if git.IsErrPushOutOfDate(err) {
ctx.Error(http.StatusConflict, "Merge", "merge push out of date")
- } else if models.IsErrSHADoesNotMatch(err) {
+ } else if pull_service.IsErrSHADoesNotMatch(err) {
ctx.Error(http.StatusConflict, "Merge", "head out of date")
} else if git.IsErrPushRejected(err) {
errPushRej := err.(*git.ErrPushRejected)
@@ -1308,10 +1307,10 @@ func UpdatePullRequest(ctx *context.APIContext) {
message := fmt.Sprintf("Merge branch '%s' into %s", pr.BaseBranch, pr.HeadBranch)
if err = pull_service.Update(ctx, pr, ctx.Doer, message, rebase); err != nil {
- if models.IsErrMergeConflicts(err) {
+ if pull_service.IsErrMergeConflicts(err) {
ctx.Error(http.StatusConflict, "Update", "merge failed because of conflict")
return
- } else if models.IsErrRebaseConflicts(err) {
+ } else if pull_service.IsErrRebaseConflicts(err) {
ctx.Error(http.StatusConflict, "Update", "rebase failed because of conflict")
return
}
diff --git a/routers/api/v1/repo/release.go b/routers/api/v1/repo/release.go
index 478bdbd797..141f812172 100644
--- a/routers/api/v1/repo/release.go
+++ b/routers/api/v1/repo/release.go
@@ -7,7 +7,6 @@ import (
"fmt"
"net/http"
- "code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/perm"
repo_model "code.gitea.io/gitea/models/repo"
@@ -250,7 +249,7 @@ func CreateRelease(ctx *context.APIContext) {
if err := release_service.CreateRelease(ctx.Repo.GitRepo, rel, nil, ""); err != nil {
if repo_model.IsErrReleaseAlreadyExist(err) {
ctx.Error(http.StatusConflict, "ReleaseAlreadyExist", err)
- } else if models.IsErrProtectedTagName(err) {
+ } else if release_service.IsErrProtectedTagName(err) {
ctx.Error(http.StatusUnprocessableEntity, "ProtectedTagName", err)
} else if git.IsErrNotExist(err) {
ctx.Error(http.StatusNotFound, "ErrNotExist", fmt.Errorf("target \"%v\" not found: %w", rel.Target, err))
@@ -408,7 +407,7 @@ func DeleteRelease(ctx *context.APIContext) {
return
}
if err := release_service.DeleteReleaseByID(ctx, ctx.Repo.Repository, rel, ctx.Doer, false); err != nil {
- if models.IsErrProtectedTagName(err) {
+ if release_service.IsErrProtectedTagName(err) {
ctx.Error(http.StatusUnprocessableEntity, "delTag", "user not allowed to delete protected tag")
return
}
diff --git a/routers/api/v1/repo/release_tags.go b/routers/api/v1/repo/release_tags.go
index 6df47af8d9..99f7a8cbf2 100644
--- a/routers/api/v1/repo/release_tags.go
+++ b/routers/api/v1/repo/release_tags.go
@@ -6,11 +6,10 @@ package repo
import (
"net/http"
- "code.gitea.io/gitea/models"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
- releaseservice "code.gitea.io/gitea/services/release"
+ release_service "code.gitea.io/gitea/services/release"
)
// GetReleaseByTag get a single release of a repository by tag name
@@ -112,8 +111,8 @@ func DeleteReleaseByTag(ctx *context.APIContext) {
return
}
- if err = releaseservice.DeleteReleaseByID(ctx, ctx.Repo.Repository, release, ctx.Doer, false); err != nil {
- if models.IsErrProtectedTagName(err) {
+ if err = release_service.DeleteReleaseByID(ctx, ctx.Repo.Repository, release, ctx.Doer, false); err != nil {
+ if release_service.IsErrProtectedTagName(err) {
ctx.Error(http.StatusUnprocessableEntity, "delTag", "user not allowed to delete protected tag")
return
}
diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go
index 40990a28cb..f0f5db0536 100644
--- a/routers/api/v1/repo/repo.go
+++ b/routers/api/v1/repo/repo.go
@@ -726,12 +726,11 @@ func updateBasicProperties(ctx *context.APIContext, opts api.EditRepoOption) err
if ctx.Repo.GitRepo == nil && !repo.IsEmpty {
var err error
- ctx.Repo.GitRepo, err = gitrepo.OpenRepository(ctx, repo)
+ ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx, repo)
if err != nil {
ctx.Error(http.StatusInternalServerError, "Unable to OpenRepository", err)
return err
}
- defer ctx.Repo.GitRepo.Close()
}
// Default branch only updated if changed and exist or the repository is empty
diff --git a/routers/api/v1/repo/tag.go b/routers/api/v1/repo/tag.go
index a72df78666..fe0910c735 100644
--- a/routers/api/v1/repo/tag.go
+++ b/routers/api/v1/repo/tag.go
@@ -9,7 +9,6 @@ import (
"net/http"
"strings"
- "code.gitea.io/gitea/models"
git_model "code.gitea.io/gitea/models/git"
"code.gitea.io/gitea/models/organization"
repo_model "code.gitea.io/gitea/models/repo"
@@ -19,7 +18,7 @@ import (
"code.gitea.io/gitea/routers/api/v1/utils"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
- releaseservice "code.gitea.io/gitea/services/release"
+ release_service "code.gitea.io/gitea/services/release"
)
// ListTags list all the tags of a repository
@@ -205,12 +204,12 @@ func CreateTag(ctx *context.APIContext) {
return
}
- if err := releaseservice.CreateNewTag(ctx, ctx.Doer, ctx.Repo.Repository, commit.ID.String(), form.TagName, form.Message); err != nil {
- if models.IsErrTagAlreadyExists(err) {
+ if err := release_service.CreateNewTag(ctx, ctx.Doer, ctx.Repo.Repository, commit.ID.String(), form.TagName, form.Message); err != nil {
+ if release_service.IsErrTagAlreadyExists(err) {
ctx.Error(http.StatusConflict, "tag exist", err)
return
}
- if models.IsErrProtectedTagName(err) {
+ if release_service.IsErrProtectedTagName(err) {
ctx.Error(http.StatusUnprocessableEntity, "CreateNewTag", "user not allowed to create protected tag")
return
}
@@ -280,8 +279,8 @@ func DeleteTag(ctx *context.APIContext) {
return
}
- if err = releaseservice.DeleteReleaseByID(ctx, ctx.Repo.Repository, tag, ctx.Doer, true); err != nil {
- if models.IsErrProtectedTagName(err) {
+ if err = release_service.DeleteReleaseByID(ctx, ctx.Repo.Repository, tag, ctx.Doer, true); err != nil {
+ if release_service.IsErrProtectedTagName(err) {
ctx.Error(http.StatusUnprocessableEntity, "delTag", "user not allowed to delete protected tag")
return
}
diff --git a/routers/api/v1/repo/transfer.go b/routers/api/v1/repo/transfer.go
index 787ec34404..b2090cac41 100644
--- a/routers/api/v1/repo/transfer.go
+++ b/routers/api/v1/repo/transfer.go
@@ -100,7 +100,7 @@ func Transfer(ctx *context.APIContext) {
}
if ctx.Repo.GitRepo != nil {
- ctx.Repo.GitRepo.Close()
+ _ = ctx.Repo.GitRepo.Close()
ctx.Repo.GitRepo = nil
}
diff --git a/routers/common/errpage.go b/routers/common/errpage.go
index 402ca44c12..c0b16dbdde 100644
--- a/routers/common/errpage.go
+++ b/routers/common/errpage.go
@@ -8,7 +8,6 @@ import (
"net/http"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/httpcache"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
@@ -18,7 +17,7 @@ import (
"code.gitea.io/gitea/services/context"
)
-const tplStatus500 base.TplName = "status/500"
+const tplStatus500 templates.TplName = "status/500"
// RenderPanicErrorPage renders a 500 page, and it never panics
func RenderPanicErrorPage(w http.ResponseWriter, req *http.Request, err any) {
@@ -47,7 +46,7 @@ func RenderPanicErrorPage(w http.ResponseWriter, req *http.Request, err any) {
ctxData["ErrorMsg"] = "PANIC: " + combinedErr
}
- err = templates.HTMLRenderer().HTML(w, http.StatusInternalServerError, string(tplStatus500), ctxData, tmplCtx)
+ err = templates.HTMLRenderer().HTML(w, http.StatusInternalServerError, tplStatus500, ctxData, tmplCtx)
if err != nil {
log.Error("Error occurs again when rendering error page: %v", err)
w.WriteHeader(http.StatusInternalServerError)
diff --git a/routers/common/errpage_test.go b/routers/common/errpage_test.go
index 4fd63ba49e..dfea55f510 100644
--- a/routers/common/errpage_test.go
+++ b/routers/common/errpage_test.go
@@ -12,8 +12,8 @@ import (
"testing"
"code.gitea.io/gitea/models/unittest"
+ "code.gitea.io/gitea/modules/reqctx"
"code.gitea.io/gitea/modules/test"
- "code.gitea.io/gitea/modules/web/middleware"
"github.com/stretchr/testify/assert"
)
@@ -21,7 +21,7 @@ import (
func TestRenderPanicErrorPage(t *testing.T) {
w := httptest.NewRecorder()
req := &http.Request{URL: &url.URL{}}
- req = req.WithContext(middleware.WithContextData(context.Background()))
+ req = req.WithContext(reqctx.NewRequestContextForTest(context.Background()))
RenderPanicErrorPage(w, req, errors.New("fake panic error (for test only)"))
respContent := w.Body.String()
assert.Contains(t, respContent, `class="page-content status-page-500"`)
diff --git a/routers/common/middleware.go b/routers/common/middleware.go
index 51e42d87a0..047d327ce8 100644
--- a/routers/common/middleware.go
+++ b/routers/common/middleware.go
@@ -4,16 +4,14 @@
package common
import (
- go_context "context"
"fmt"
"net/http"
"strings"
"code.gitea.io/gitea/modules/cache"
"code.gitea.io/gitea/modules/httplib"
- "code.gitea.io/gitea/modules/process"
+ "code.gitea.io/gitea/modules/reqctx"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/web/middleware"
"code.gitea.io/gitea/modules/web/routing"
"code.gitea.io/gitea/services/context"
@@ -24,54 +22,12 @@ import (
// ProtocolMiddlewares returns HTTP protocol related middlewares, and it provides a global panic recovery
func ProtocolMiddlewares() (handlers []any) {
- // make sure chi uses EscapedPath(RawPath) as RoutePath, then "%2f" could be handled correctly
- handlers = append(handlers, func(next http.Handler) http.Handler {
- return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
- ctx := chi.RouteContext(req.Context())
- if req.URL.RawPath == "" {
- ctx.RoutePath = req.URL.EscapedPath()
- } else {
- ctx.RoutePath = req.URL.RawPath
- }
- next.ServeHTTP(resp, req)
- })
- })
+ // the order is important
+ handlers = append(handlers, ChiRoutePathHandler()) // make sure chi has correct paths
+ handlers = append(handlers, RequestContextHandler()) // // prepare the context and panic recovery
- // prepare the ContextData and panic recovery
- handlers = append(handlers, func(next http.Handler) http.Handler {
- return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
- defer func() {
- if err := recover(); err != nil {
- RenderPanicErrorPage(resp, req, err) // it should never panic
- }
- }()
- req = req.WithContext(middleware.WithContextData(req.Context()))
- req = req.WithContext(go_context.WithValue(req.Context(), httplib.RequestContextKey, req))
- next.ServeHTTP(resp, req)
- })
- })
-
- // wrap the request and response, use the process context and add it to the process manager
- handlers = append(handlers, func(next http.Handler) http.Handler {
- return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
- ctx, _, finished := process.GetManager().AddTypedContext(req.Context(), fmt.Sprintf("%s: %s", req.Method, req.RequestURI), process.RequestProcessType, true)
- defer finished()
- next.ServeHTTP(context.WrapResponseWriter(resp), req.WithContext(cache.WithCacheContext(ctx)))
- })
- })
-
- if setting.ReverseProxyLimit > 0 {
- opt := proxy.NewForwardedHeadersOptions().
- WithForwardLimit(setting.ReverseProxyLimit).
- ClearTrustedProxies()
- for _, n := range setting.ReverseProxyTrustedProxies {
- if !strings.Contains(n, "/") {
- opt.AddTrustedProxy(n)
- } else {
- opt.AddTrustedNetwork(n)
- }
- }
- handlers = append(handlers, proxy.ForwardedHeaders(opt))
+ if setting.ReverseProxyLimit > 0 && len(setting.ReverseProxyTrustedProxies) > 0 {
+ handlers = append(handlers, ForwardedHeadersHandler(setting.ReverseProxyLimit, setting.ReverseProxyTrustedProxies))
}
if setting.IsRouteLogEnabled() {
@@ -85,6 +41,59 @@ func ProtocolMiddlewares() (handlers []any) {
return handlers
}
+func RequestContextHandler() func(h http.Handler) http.Handler {
+ return func(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
+ profDesc := fmt.Sprintf("%s: %s", req.Method, req.RequestURI)
+ ctx, finished := reqctx.NewRequestContext(req.Context(), profDesc)
+ defer finished()
+
+ defer func() {
+ if err := recover(); err != nil {
+ RenderPanicErrorPage(resp, req, err) // it should never panic
+ }
+ }()
+
+ ds := reqctx.GetRequestDataStore(ctx)
+ req = req.WithContext(cache.WithCacheContext(ctx))
+ ds.SetContextValue(httplib.RequestContextKey, req)
+ ds.AddCleanUp(func() {
+ if req.MultipartForm != nil {
+ _ = req.MultipartForm.RemoveAll() // remove the temp files buffered to tmp directory
+ }
+ })
+ next.ServeHTTP(context.WrapResponseWriter(resp), req)
+ })
+ }
+}
+
+func ChiRoutePathHandler() func(h http.Handler) http.Handler {
+ // make sure chi uses EscapedPath(RawPath) as RoutePath, then "%2f" could be handled correctly
+ return func(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
+ ctx := chi.RouteContext(req.Context())
+ if req.URL.RawPath == "" {
+ ctx.RoutePath = req.URL.EscapedPath()
+ } else {
+ ctx.RoutePath = req.URL.RawPath
+ }
+ next.ServeHTTP(resp, req)
+ })
+ }
+}
+
+func ForwardedHeadersHandler(limit int, trustedProxies []string) func(h http.Handler) http.Handler {
+ opt := proxy.NewForwardedHeadersOptions().WithForwardLimit(limit).ClearTrustedProxies()
+ for _, n := range trustedProxies {
+ if !strings.Contains(n, "/") {
+ opt.AddTrustedProxy(n)
+ } else {
+ opt.AddTrustedNetwork(n)
+ }
+ }
+ return proxy.ForwardedHeaders(opt)
+}
+
func Sessioner() func(next http.Handler) http.Handler {
return session.Sessioner(session.Options{
Provider: setting.SessionConfig.Provider,
diff --git a/routers/init.go b/routers/init.go
index 2091f5967a..e7aa765bf0 100644
--- a/routers/init.go
+++ b/routers/init.go
@@ -133,7 +133,7 @@ func InitWebInstalled(ctx context.Context) {
highlight.NewContext()
external.RegisterRenderers()
- markup.Init(markup_service.ProcessorHelper())
+ markup.Init(markup_service.FormalRenderHelperFuncs())
if setting.EnableSQLite3 {
log.Info("SQLite3 support is enabled")
@@ -171,7 +171,7 @@ func InitWebInstalled(ctx context.Context) {
auth.Init()
mustInit(svg.Init)
- actions_service.Init()
+ mustInitCtx(ctx, actions_service.Init)
mustInit(repo_service.InitLicenseClassifier)
diff --git a/routers/install/install.go b/routers/install/install.go
index e420d36da5..8a1d57aa0b 100644
--- a/routers/install/install.go
+++ b/routers/install/install.go
@@ -21,11 +21,11 @@ import (
system_model "code.gitea.io/gitea/models/system"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/auth/password/hash"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/generate"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
+ "code.gitea.io/gitea/modules/reqctx"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/timeutil"
@@ -43,8 +43,8 @@ import (
const (
// tplInstall template for installation page
- tplInstall base.TplName = "install"
- tplPostInstall base.TplName = "post-install"
+ tplInstall templates.TplName = "install"
+ tplPostInstall templates.TplName = "post-install"
)
// getSupportedDbTypeNames returns a slice for supported database types and names. The slice is used to keep the order
@@ -62,15 +62,11 @@ func Contexter() func(next http.Handler) http.Handler {
envConfigKeys := setting.CollectEnvConfigKeys()
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
- base, baseCleanUp := context.NewBaseContext(resp, req)
- defer baseCleanUp()
-
+ base := context.NewBaseContext(resp, req)
ctx := context.NewWebContext(base, rnd, session.GetSession(req))
- ctx.AppendContextValue(context.WebContextKey, ctx)
+ ctx.SetContextValue(context.WebContextKey, ctx)
ctx.Data.MergeFrom(middleware.CommonTemplateContextData())
- ctx.Data.MergeFrom(middleware.ContextData{
- "Context": ctx, // TODO: use "ctx" in template and remove this
- "locale": ctx.Locale,
+ ctx.Data.MergeFrom(reqctx.ContextData{
"Title": ctx.Locale.Tr("install.install"),
"PageIsInstall": true,
"DbTypeNames": dbTypeNames,
diff --git a/routers/private/hook_pre_receive.go b/routers/private/hook_pre_receive.go
index 73fe9b886c..eb7bb2b480 100644
--- a/routers/private/hook_pre_receive.go
+++ b/routers/private/hook_pre_receive.go
@@ -8,7 +8,6 @@ import (
"net/http"
"os"
- "code.gitea.io/gitea/models"
asymkey_model "code.gitea.io/gitea/models/asymkey"
git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues"
@@ -237,7 +236,7 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r
if len(globs) > 0 {
_, err := pull_service.CheckFileProtection(gitRepo, branchName, oldCommitID, newCommitID, globs, 1, ctx.env)
if err != nil {
- if !models.IsErrFilePathProtected(err) {
+ if !pull_service.IsErrFilePathProtected(err) {
log.Error("Unable to check file protection for commits from %s to %s in %-v: %v", oldCommitID, newCommitID, repo, err)
ctx.JSON(http.StatusInternalServerError, private.Response{
Err: fmt.Sprintf("Unable to check file protection for commits from %s to %s: %v", oldCommitID, newCommitID, err),
@@ -246,7 +245,7 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r
}
changedProtectedfiles = true
- protectedFilePath = err.(models.ErrFilePathProtected).Path
+ protectedFilePath = err.(pull_service.ErrFilePathProtected).Path
}
}
@@ -374,7 +373,7 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r
// Check all status checks and reviews are ok
if err := pull_service.CheckPullBranchProtections(ctx, pr, true); err != nil {
- if models.IsErrDisallowedToMerge(err) {
+ if pull_service.IsErrDisallowedToMerge(err) {
log.Warn("Forbidden: User %d is not allowed push to protected branch %s in %-v and pr #%d is not ready to be merged: %s", ctx.opts.UserID, branchName, repo, pr.Index, err.Error())
ctx.JSON(http.StatusForbidden, private.Response{
UserMsg: fmt.Sprintf("Not allowed to push to protected branch %s and pr #%d is not ready to be merged: %s", branchName, ctx.opts.PullRequestID, err.Error()),
diff --git a/routers/private/internal.go b/routers/private/internal.go
index 1fb72f13d9..a78c76f897 100644
--- a/routers/private/internal.go
+++ b/routers/private/internal.go
@@ -63,8 +63,8 @@ func Routes() *web.Router {
r.Post("/ssh/{id}/update/{repoid}", UpdatePublicKeyInRepo)
r.Post("/ssh/log", bind(private.SSHLogOption{}), SSHLog)
r.Post("/hook/pre-receive/{owner}/{repo}", RepoAssignment, bind(private.HookOptions{}), HookPreReceive)
- r.Post("/hook/post-receive/{owner}/{repo}", context.OverrideContext, bind(private.HookOptions{}), HookPostReceive)
- r.Post("/hook/proc-receive/{owner}/{repo}", context.OverrideContext, RepoAssignment, bind(private.HookOptions{}), HookProcReceive)
+ r.Post("/hook/post-receive/{owner}/{repo}", context.OverrideContext(), bind(private.HookOptions{}), HookPostReceive)
+ r.Post("/hook/proc-receive/{owner}/{repo}", context.OverrideContext(), RepoAssignment, bind(private.HookOptions{}), HookProcReceive)
r.Post("/hook/set-default-branch/{owner}/{repo}/{branch}", RepoAssignment, SetDefaultBranch)
r.Get("/serv/none/{keyid}", ServNoCommand)
r.Get("/serv/command/{keyid}/{owner}/{repo}", ServCommand)
@@ -88,7 +88,7 @@ func Routes() *web.Router {
// Fortunately, the LFS handlers are able to handle requests without a complete web context
common.AddOwnerRepoGitLFSRoutes(r, func(ctx *context.PrivateContext) {
webContext := &context.Context{Base: ctx.Base}
- ctx.AppendContextValue(context.WebContextKey, webContext)
+ ctx.SetContextValue(context.WebContextKey, webContext)
})
})
diff --git a/routers/private/internal_repo.go b/routers/private/internal_repo.go
index aad0a3fb1a..4255be7e52 100644
--- a/routers/private/internal_repo.go
+++ b/routers/private/internal_repo.go
@@ -4,7 +4,6 @@
package private
import (
- "context"
"fmt"
"net/http"
@@ -17,40 +16,29 @@ import (
// This file contains common functions relating to setting the Repository for the internal routes
-// RepoAssignment assigns the repository and gitrepository to the private context
-func RepoAssignment(ctx *gitea_context.PrivateContext) context.CancelFunc {
+// RepoAssignment assigns the repository and git repository to the private context
+func RepoAssignment(ctx *gitea_context.PrivateContext) {
ownerName := ctx.PathParam(":owner")
repoName := ctx.PathParam(":repo")
repo := loadRepository(ctx, ownerName, repoName)
if ctx.Written() {
// Error handled in loadRepository
- return nil
+ return
}
- gitRepo, err := gitrepo.OpenRepository(ctx, repo)
+ gitRepo, err := gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx, repo)
if err != nil {
log.Error("Failed to open repository: %s/%s Error: %v", ownerName, repoName, err)
ctx.JSON(http.StatusInternalServerError, private.Response{
Err: fmt.Sprintf("Failed to open repository: %s/%s Error: %v", ownerName, repoName, err),
})
- return nil
+ return
}
-
ctx.Repo = &gitea_context.Repository{
Repository: repo,
GitRepo: gitRepo,
}
-
- // We opened it, we should close it
- cancel := func() {
- // If it's been set to nil then assume someone else has closed it.
- if ctx.Repo.GitRepo != nil {
- ctx.Repo.GitRepo.Close()
- }
- }
-
- return cancel
}
func loadRepository(ctx *gitea_context.PrivateContext, ownerName, repoName string) *repo_model.Repository {
diff --git a/routers/web/admin/admin.go b/routers/web/admin/admin.go
index 37c54b5362..3902a1efb1 100644
--- a/routers/web/admin/admin.go
+++ b/routers/web/admin/admin.go
@@ -21,6 +21,7 @@ import (
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/updatechecker"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/context"
@@ -31,14 +32,14 @@ import (
)
const (
- tplDashboard base.TplName = "admin/dashboard"
- tplSystemStatus base.TplName = "admin/system_status"
- tplSelfCheck base.TplName = "admin/self_check"
- tplCron base.TplName = "admin/cron"
- tplQueue base.TplName = "admin/queue"
- tplStacktrace base.TplName = "admin/stacktrace"
- tplQueueManage base.TplName = "admin/queue_manage"
- tplStats base.TplName = "admin/stats"
+ tplDashboard templates.TplName = "admin/dashboard"
+ tplSystemStatus templates.TplName = "admin/system_status"
+ tplSelfCheck templates.TplName = "admin/self_check"
+ tplCron templates.TplName = "admin/cron"
+ tplQueue templates.TplName = "admin/queue"
+ tplStacktrace templates.TplName = "admin/stacktrace"
+ tplQueueManage templates.TplName = "admin/queue_manage"
+ tplStats templates.TplName = "admin/stats"
)
var sysStatus struct {
diff --git a/routers/web/admin/applications.go b/routers/web/admin/applications.go
index 9b48f21eca..aec6349f21 100644
--- a/routers/web/admin/applications.go
+++ b/routers/web/admin/applications.go
@@ -9,15 +9,15 @@ import (
"code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
user_setting "code.gitea.io/gitea/routers/web/user/setting"
"code.gitea.io/gitea/services/context"
)
var (
- tplSettingsApplications base.TplName = "admin/applications/list"
- tplSettingsOauth2ApplicationEdit base.TplName = "admin/applications/oauth2_edit"
+ tplSettingsApplications templates.TplName = "admin/applications/list"
+ tplSettingsOauth2ApplicationEdit templates.TplName = "admin/applications/oauth2_edit"
)
func newOAuth2CommonHandlers() *user_setting.OAuth2CommonHandlers {
diff --git a/routers/web/admin/auths.go b/routers/web/admin/auths.go
index 60e2b7c86f..6a65cfa697 100644
--- a/routers/web/admin/auths.go
+++ b/routers/web/admin/auths.go
@@ -15,9 +15,9 @@ import (
"code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/auth/pam"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
auth_service "code.gitea.io/gitea/services/auth"
@@ -33,9 +33,9 @@ import (
)
const (
- tplAuths base.TplName = "admin/auth/list"
- tplAuthNew base.TplName = "admin/auth/new"
- tplAuthEdit base.TplName = "admin/auth/edit"
+ tplAuths templates.TplName = "admin/auth/list"
+ tplAuthNew templates.TplName = "admin/auth/new"
+ tplAuthEdit templates.TplName = "admin/auth/edit"
)
var (
diff --git a/routers/web/admin/config.go b/routers/web/admin/config.go
index d067250a5b..520f14e89f 100644
--- a/routers/web/admin/config.go
+++ b/routers/web/admin/config.go
@@ -11,13 +11,13 @@ import (
"strings"
system_model "code.gitea.io/gitea/models/system"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/cache"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/setting/config"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/mailer"
@@ -26,8 +26,8 @@ import (
)
const (
- tplConfig base.TplName = "admin/config"
- tplConfigSettings base.TplName = "admin/config_settings"
+ tplConfig templates.TplName = "admin/config"
+ tplConfigSettings templates.TplName = "admin/config_settings"
)
// SendTestMail send test mail to confirm mail service is OK
diff --git a/routers/web/admin/emails.go b/routers/web/admin/emails.go
index e9c97d8b8f..e925de8937 100644
--- a/routers/web/admin/emails.go
+++ b/routers/web/admin/emails.go
@@ -10,16 +10,16 @@ import (
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/user"
)
const (
- tplEmails base.TplName = "admin/emails/list"
+ tplEmails templates.TplName = "admin/emails/list"
)
// Emails show all emails
diff --git a/routers/web/admin/hooks.go b/routers/web/admin/hooks.go
index 91ca6e3fa7..34dc0fc9b0 100644
--- a/routers/web/admin/hooks.go
+++ b/routers/web/admin/hooks.go
@@ -7,15 +7,15 @@ import (
"net/http"
"code.gitea.io/gitea/models/webhook"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/services/context"
)
const (
// tplAdminHooks template path to render hook settings
- tplAdminHooks base.TplName = "admin/hooks"
+ tplAdminHooks templates.TplName = "admin/hooks"
)
// DefaultOrSystemWebhooks renders both admin default and system webhook list pages
diff --git a/routers/web/admin/notice.go b/routers/web/admin/notice.go
index 5f7432e629..21a8ab0d17 100644
--- a/routers/web/admin/notice.go
+++ b/routers/web/admin/notice.go
@@ -10,14 +10,14 @@ import (
"code.gitea.io/gitea/models/db"
system_model "code.gitea.io/gitea/models/system"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/services/context"
)
const (
- tplNotices base.TplName = "admin/notice"
+ tplNotices templates.TplName = "admin/notice"
)
// Notices show notices for admin
diff --git a/routers/web/admin/orgs.go b/routers/web/admin/orgs.go
index cea28f8220..35e61efa17 100644
--- a/routers/web/admin/orgs.go
+++ b/routers/web/admin/orgs.go
@@ -7,15 +7,15 @@ package admin
import (
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/routers/web/explore"
"code.gitea.io/gitea/services/context"
)
const (
- tplOrgs base.TplName = "admin/org/list"
+ tplOrgs templates.TplName = "admin/org/list"
)
// Organizations show all the organizations
diff --git a/routers/web/admin/packages.go b/routers/web/admin/packages.go
index 2b9edc622d..da345f2f89 100644
--- a/routers/web/admin/packages.go
+++ b/routers/web/admin/packages.go
@@ -10,16 +10,16 @@ import (
"code.gitea.io/gitea/models/db"
packages_model "code.gitea.io/gitea/models/packages"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/services/context"
packages_service "code.gitea.io/gitea/services/packages"
packages_cleanup_service "code.gitea.io/gitea/services/packages/cleanup"
)
const (
- tplPackagesList base.TplName = "admin/packages/list"
+ tplPackagesList templates.TplName = "admin/packages/list"
)
// Packages shows all packages
diff --git a/routers/web/admin/repos.go b/routers/web/admin/repos.go
index 75e5ee5d86..27d39dcf4b 100644
--- a/routers/web/admin/repos.go
+++ b/routers/web/admin/repos.go
@@ -12,9 +12,9 @@ import (
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/web/explore"
"code.gitea.io/gitea/services/context"
@@ -22,8 +22,8 @@ import (
)
const (
- tplRepos base.TplName = "admin/repo/list"
- tplUnadoptedRepos base.TplName = "admin/repo/unadopted"
+ tplRepos templates.TplName = "admin/repo/list"
+ tplUnadoptedRepos templates.TplName = "admin/repo/unadopted"
)
// Repos show all the repositories
diff --git a/routers/web/admin/users.go b/routers/web/admin/users.go
index a6b0b5c78b..cf158f7aa9 100644
--- a/routers/web/admin/users.go
+++ b/routers/web/admin/users.go
@@ -11,17 +11,17 @@ import (
"strconv"
"strings"
- "code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
org_model "code.gitea.io/gitea/models/organization"
+ packages_model "code.gitea.io/gitea/models/packages"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/auth/password"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/web/explore"
@@ -33,10 +33,10 @@ import (
)
const (
- tplUsers base.TplName = "admin/user/list"
- tplUserNew base.TplName = "admin/user/new"
- tplUserView base.TplName = "admin/user/view"
- tplUserEdit base.TplName = "admin/user/edit"
+ tplUsers templates.TplName = "admin/user/list"
+ tplUserNew templates.TplName = "admin/user/new"
+ tplUserView templates.TplName = "admin/user/view"
+ tplUserEdit templates.TplName = "admin/user/edit"
)
// UserSearchDefaultAdminSort is the default sort type for admin view
@@ -446,7 +446,7 @@ func EditUserPost(ctx *context.Context) {
}
if err := user_service.UpdateUser(ctx, u, opts); err != nil {
- if models.IsErrDeleteLastAdminUser(err) {
+ if user_model.IsErrDeleteLastAdminUser(err) {
ctx.RenderWithErr(ctx.Tr("auth.last_admin"), tplUserEdit, &form)
} else {
ctx.ServerError("UpdateUser", err)
@@ -501,16 +501,16 @@ func DeleteUser(ctx *context.Context) {
if err = user_service.DeleteUser(ctx, u, ctx.FormBool("purge")); err != nil {
switch {
- case models.IsErrUserOwnRepos(err):
+ case repo_model.IsErrUserOwnRepos(err):
ctx.Flash.Error(ctx.Tr("admin.users.still_own_repo"))
ctx.Redirect(setting.AppSubURL + "/-/admin/users/" + url.PathEscape(ctx.PathParam(":userid")))
- case models.IsErrUserHasOrgs(err):
+ case org_model.IsErrUserHasOrgs(err):
ctx.Flash.Error(ctx.Tr("admin.users.still_has_org"))
ctx.Redirect(setting.AppSubURL + "/-/admin/users/" + url.PathEscape(ctx.PathParam(":userid")))
- case models.IsErrUserOwnPackages(err):
+ case packages_model.IsErrUserOwnPackages(err):
ctx.Flash.Error(ctx.Tr("admin.users.still_own_packages"))
ctx.Redirect(setting.AppSubURL + "/-/admin/users/" + url.PathEscape(ctx.PathParam(":userid")))
- case models.IsErrDeleteLastAdminUser(err):
+ case user_model.IsErrDeleteLastAdminUser(err):
ctx.Flash.Error(ctx.Tr("auth.last_admin"))
ctx.Redirect(setting.AppSubURL + "/-/admin/users/" + url.PathEscape(ctx.PathParam(":userid")))
default:
diff --git a/routers/web/auth/2fa.go b/routers/web/auth/2fa.go
index f93177bf96..fe363fe90a 100644
--- a/routers/web/auth/2fa.go
+++ b/routers/web/auth/2fa.go
@@ -9,8 +9,8 @@ import (
"code.gitea.io/gitea/models/auth"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/externalaccount"
@@ -18,8 +18,8 @@ import (
)
var (
- tplTwofa base.TplName = "user/auth/twofa"
- tplTwofaScratch base.TplName = "user/auth/twofa_scratch"
+ tplTwofa templates.TplName = "user/auth/twofa"
+ tplTwofaScratch templates.TplName = "user/auth/twofa_scratch"
)
// TwoFactor shows the user a two-factor authentication page.
diff --git a/routers/web/auth/auth.go b/routers/web/auth/auth.go
index 3f16da3cdd..42736a423f 100644
--- a/routers/web/auth/auth.go
+++ b/routers/web/auth/auth.go
@@ -15,13 +15,13 @@ import (
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/auth/password"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/eventsource"
"code.gitea.io/gitea/modules/httplib"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/session"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
@@ -38,10 +38,10 @@ import (
)
const (
- tplSignIn base.TplName = "user/auth/signin" // for sign in page
- tplSignUp base.TplName = "user/auth/signup" // for sign up page
- TplActivate base.TplName = "user/auth/activate" // for activate user
- TplActivatePrompt base.TplName = "user/auth/activate_prompt" // for showing a message for user activation
+ tplSignIn templates.TplName = "user/auth/signin" // for sign in page
+ tplSignUp templates.TplName = "user/auth/signup" // for sign up page
+ TplActivate templates.TplName = "user/auth/activate" // for activate user
+ TplActivatePrompt templates.TplName = "user/auth/activate_prompt" // for showing a message for user activation
)
// autoSignIn reads cookie and try to auto-login.
@@ -517,7 +517,7 @@ func SignUpPost(ctx *context.Context) {
// createAndHandleCreatedUser calls createUserInContext and
// then handleUserCreated.
-func createAndHandleCreatedUser(ctx *context.Context, tpl base.TplName, form any, u *user_model.User, overwrites *user_model.CreateUserOverwriteOptions, gothUser *goth.User, allowLink bool) bool {
+func createAndHandleCreatedUser(ctx *context.Context, tpl templates.TplName, form any, u *user_model.User, overwrites *user_model.CreateUserOverwriteOptions, gothUser *goth.User, allowLink bool) bool {
if !createUserInContext(ctx, tpl, form, u, overwrites, gothUser, allowLink) {
return false
}
@@ -526,7 +526,7 @@ func createAndHandleCreatedUser(ctx *context.Context, tpl base.TplName, form any
// createUserInContext creates a user and handles errors within a given context.
// Optionally a template can be specified.
-func createUserInContext(ctx *context.Context, tpl base.TplName, form any, u *user_model.User, overwrites *user_model.CreateUserOverwriteOptions, gothUser *goth.User, allowLink bool) (ok bool) {
+func createUserInContext(ctx *context.Context, tpl templates.TplName, form any, u *user_model.User, overwrites *user_model.CreateUserOverwriteOptions, gothUser *goth.User, allowLink bool) (ok bool) {
meta := &user_model.Meta{
InitialIP: ctx.RemoteAddr(),
InitialUserAgent: ctx.Req.UserAgent(),
diff --git a/routers/web/auth/linkaccount.go b/routers/web/auth/linkaccount.go
index 519431d92b..147d8d3802 100644
--- a/routers/web/auth/linkaccount.go
+++ b/routers/web/auth/linkaccount.go
@@ -11,9 +11,9 @@ import (
"code.gitea.io/gitea/models/auth"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
auth_service "code.gitea.io/gitea/services/auth"
@@ -25,7 +25,7 @@ import (
"github.com/markbates/goth"
)
-var tplLinkAccount base.TplName = "user/auth/link_account"
+var tplLinkAccount templates.TplName = "user/auth/link_account"
// LinkAccount shows the page where the user can decide to login or create a new account
func LinkAccount(ctx *context.Context) {
@@ -92,7 +92,7 @@ func LinkAccount(ctx *context.Context) {
ctx.HTML(http.StatusOK, tplLinkAccount)
}
-func handleSignInError(ctx *context.Context, userName string, ptrForm any, tmpl base.TplName, invoker string, err error) {
+func handleSignInError(ctx *context.Context, userName string, ptrForm any, tmpl templates.TplName, invoker string, err error) {
if errors.Is(err, util.ErrNotExist) {
ctx.RenderWithErr(ctx.Tr("form.username_password_incorrect"), tmpl, ptrForm)
} else if errors.Is(err, util.ErrInvalidArgument) {
diff --git a/routers/web/auth/oauth.go b/routers/web/auth/oauth.go
index 75f94de0ed..32c30c71e8 100644
--- a/routers/web/auth/oauth.go
+++ b/routers/web/auth/oauth.go
@@ -15,11 +15,11 @@ import (
"code.gitea.io/gitea/models/auth"
user_model "code.gitea.io/gitea/models/user"
auth_module "code.gitea.io/gitea/modules/auth"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/web/middleware"
source_service "code.gitea.io/gitea/services/auth/source"
"code.gitea.io/gitea/services/auth/source/oauth2"
@@ -194,7 +194,7 @@ func SignInOAuthCallback(ctx *context.Context) {
u.IsAdmin = isAdmin.ValueOrDefault(false)
u.IsRestricted = isRestricted.ValueOrDefault(false)
- if !createAndHandleCreatedUser(ctx, base.TplName(""), nil, u, overwriteDefault, &gothUser, setting.OAuth2Client.AccountLinking != setting.OAuth2AccountLinkingDisabled) {
+ if !createAndHandleCreatedUser(ctx, templates.TplName(""), nil, u, overwriteDefault, &gothUser, setting.OAuth2Client.AccountLinking != setting.OAuth2AccountLinkingDisabled) {
// error already handled
return
}
diff --git a/routers/web/auth/oauth2_provider.go b/routers/web/auth/oauth2_provider.go
index 1aebc047bd..6262ad8a6d 100644
--- a/routers/web/auth/oauth2_provider.go
+++ b/routers/web/auth/oauth2_provider.go
@@ -18,6 +18,7 @@ import (
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/web"
auth_service "code.gitea.io/gitea/services/auth"
"code.gitea.io/gitea/services/context"
@@ -29,8 +30,8 @@ import (
)
const (
- tplGrantAccess base.TplName = "user/auth/grant"
- tplGrantError base.TplName = "user/auth/grant_error"
+ tplGrantAccess templates.TplName = "user/auth/grant"
+ tplGrantError templates.TplName = "user/auth/grant_error"
)
// TODO move error and responses to SDK or models
diff --git a/routers/web/auth/openid.go b/routers/web/auth/openid.go
index 83268faacb..41d37ecb8b 100644
--- a/routers/web/auth/openid.go
+++ b/routers/web/auth/openid.go
@@ -10,9 +10,9 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/auth/openid"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/auth"
@@ -21,9 +21,9 @@ import (
)
const (
- tplSignInOpenID base.TplName = "user/auth/signin_openid"
- tplConnectOID base.TplName = "user/auth/signup_openid_connect"
- tplSignUpOID base.TplName = "user/auth/signup_openid_register"
+ tplSignInOpenID templates.TplName = "user/auth/signin_openid"
+ tplConnectOID templates.TplName = "user/auth/signup_openid_connect"
+ tplSignUpOID templates.TplName = "user/auth/signup_openid_register"
)
// SignInOpenID render sign in page
diff --git a/routers/web/auth/password.go b/routers/web/auth/password.go
index 334d864c6a..3812d582e5 100644
--- a/routers/web/auth/password.go
+++ b/routers/web/auth/password.go
@@ -11,10 +11,10 @@ import (
"code.gitea.io/gitea/models/auth"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/auth/password"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/modules/web/middleware"
@@ -26,9 +26,9 @@ import (
var (
// tplMustChangePassword template for updating a user's password
- tplMustChangePassword base.TplName = "user/auth/change_passwd"
- tplForgotPassword base.TplName = "user/auth/forgot_passwd"
- tplResetPassword base.TplName = "user/auth/reset_passwd"
+ tplMustChangePassword templates.TplName = "user/auth/change_passwd"
+ tplForgotPassword templates.TplName = "user/auth/forgot_passwd"
+ tplResetPassword templates.TplName = "user/auth/reset_passwd"
)
// ForgotPasswd render the forget password page
diff --git a/routers/web/auth/webauthn.go b/routers/web/auth/webauthn.go
index ba25d45070..69031adeaa 100644
--- a/routers/web/auth/webauthn.go
+++ b/routers/web/auth/webauthn.go
@@ -11,9 +11,9 @@ import (
"code.gitea.io/gitea/models/auth"
user_model "code.gitea.io/gitea/models/user"
wa "code.gitea.io/gitea/modules/auth/webauthn"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/externalaccount"
@@ -21,7 +21,7 @@ import (
"github.com/go-webauthn/webauthn/webauthn"
)
-var tplWebAuthn base.TplName = "user/auth/webauthn"
+var tplWebAuthn templates.TplName = "user/auth/webauthn"
// WebAuthn shows the WebAuthn login page
func WebAuthn(ctx *context.Context) {
diff --git a/routers/web/devtest/devtest.go b/routers/web/devtest/devtest.go
index 0068c9fe88..0bc84d2d1e 100644
--- a/routers/web/devtest/devtest.go
+++ b/routers/web/devtest/devtest.go
@@ -9,7 +9,6 @@ import (
"strings"
"time"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/services/context"
)
@@ -62,5 +61,5 @@ func Tmpl(ctx *context.Context) {
time.Sleep(2 * time.Second)
}
- ctx.HTML(http.StatusOK, base.TplName("devtest"+path.Clean("/"+ctx.PathParam("sub"))))
+ ctx.HTML(http.StatusOK, templates.TplName("devtest"+path.Clean("/"+ctx.PathParam("sub"))))
}
diff --git a/routers/web/devtest/mock_actions.go b/routers/web/devtest/mock_actions.go
index 46e302d634..f29b8e4046 100644
--- a/routers/web/devtest/mock_actions.go
+++ b/routers/web/devtest/mock_actions.go
@@ -31,7 +31,11 @@ func generateMockStepsLog(logCur actions.LogCursor) (stepsLog []*actions.ViewSte
"##[endgroup]",
}
cur := logCur.Cursor // usually the cursor is the "file offset", but here we abuse it as "line number" to make the mock easier, intentionally
- for i := 0; i < util.Iif(logCur.Step == 0, 3, 1); i++ {
+ mockCount := util.Iif(logCur.Step == 0, 3, 1)
+ if logCur.Step == 1 && logCur.Cursor == 0 {
+ mockCount = 30 // for the first batch, return as many as possible to test the auto-expand and auto-scroll
+ }
+ for i := 0; i < mockCount; i++ {
logStr := mockedLogs[int(cur)%len(mockedLogs)]
cur++
logStr = strings.ReplaceAll(logStr, "{step}", fmt.Sprintf("%d", logCur.Step))
@@ -56,6 +60,21 @@ func MockActionsRunsJobs(ctx *context.Context) {
resp.State.Run.Status = actions_model.StatusRunning.String()
resp.State.Run.CanCancel = true
resp.State.Run.CanDeleteArtifact = true
+ resp.State.Run.WorkflowID = "workflow-id"
+ resp.State.Run.WorkflowLink = "./workflow-link"
+ resp.State.Run.Commit = actions.ViewCommit{
+ ShortSha: "ccccdddd",
+ Link: "./commit-link",
+ Pusher: actions.ViewUser{
+ DisplayName: "pusher user",
+ Link: "./pusher-link",
+ },
+ Branch: actions.ViewBranch{
+ Name: "commit-branch",
+ Link: "./branch-link",
+ IsDeleted: false,
+ },
+ }
resp.Artifacts = append(resp.Artifacts, &actions.ArtifactsViewItem{
Name: "artifact-a",
Size: 100 * 1024,
diff --git a/routers/web/explore/code.go b/routers/web/explore/code.go
index 48f890332b..4df89253b4 100644
--- a/routers/web/explore/code.go
+++ b/routers/web/explore/code.go
@@ -8,15 +8,15 @@ import (
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/base"
code_indexer "code.gitea.io/gitea/modules/indexer/code"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/services/context"
)
const (
// tplExploreCode explore code page template
- tplExploreCode base.TplName = "explore/code"
+ tplExploreCode templates.TplName = "explore/code"
)
// Code render explore code page
diff --git a/routers/web/explore/repo.go b/routers/web/explore/repo.go
index 5b6f612e72..c421aea715 100644
--- a/routers/web/explore/repo.go
+++ b/routers/web/explore/repo.go
@@ -9,17 +9,17 @@ import (
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/sitemap"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/services/context"
)
const (
// tplExploreRepos explore repositories page template
- tplExploreRepos base.TplName = "explore/repos"
- relevantReposOnlyParam string = "only_show_relevant"
+ tplExploreRepos templates.TplName = "explore/repos"
+ relevantReposOnlyParam string = "only_show_relevant"
)
// RepoSearchOptions when calling search repositories
@@ -29,7 +29,7 @@ type RepoSearchOptions struct {
Restricted bool
PageSize int
OnlyShowRelevant bool
- TplName base.TplName
+ TplName templates.TplName
}
// RenderRepoSearch render repositories search page
diff --git a/routers/web/explore/user.go b/routers/web/explore/user.go
index c009982d42..ef103af8cf 100644
--- a/routers/web/explore/user.go
+++ b/routers/web/explore/user.go
@@ -9,20 +9,20 @@ import (
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/sitemap"
"code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/services/context"
)
const (
// tplExploreUsers explore users page template
- tplExploreUsers base.TplName = "explore/users"
+ tplExploreUsers templates.TplName = "explore/users"
)
var nullByte = []byte{0x00}
@@ -32,7 +32,7 @@ func isKeywordValid(keyword string) bool {
}
// RenderUserSearch render user search page
-func RenderUserSearch(ctx *context.Context, opts *user_model.SearchUserOptions, tplName base.TplName) {
+func RenderUserSearch(ctx *context.Context, opts *user_model.SearchUserOptions, tplName templates.TplName) {
// Sitemap index for sitemap paths
opts.Page = int(ctx.PathParamInt64("idx"))
isSitemap := ctx.PathParam("idx") != ""
diff --git a/routers/web/home.go b/routers/web/home.go
index d4be0931e8..9ad495d54f 100644
--- a/routers/web/home.go
+++ b/routers/web/home.go
@@ -11,12 +11,12 @@ import (
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/sitemap"
"code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/web/middleware"
"code.gitea.io/gitea/routers/web/auth"
"code.gitea.io/gitea/routers/web/user"
@@ -25,7 +25,7 @@ import (
const (
// tplHome home page template
- tplHome base.TplName = "home"
+ tplHome templates.TplName = "home"
)
// Home render home page
diff --git a/routers/web/misc/swagger.go b/routers/web/misc/swagger.go
index 5fddfa8885..1ca347551c 100644
--- a/routers/web/misc/swagger.go
+++ b/routers/web/misc/swagger.go
@@ -6,12 +6,12 @@ package misc
import (
"net/http"
- "code.gitea.io/gitea/modules/base"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/services/context"
)
// tplSwagger swagger page template
-const tplSwagger base.TplName = "swagger/ui"
+const tplSwagger templates.TplName = "swagger/ui"
// Swagger render swagger-ui page with v1 json
func Swagger(ctx *context.Context) {
diff --git a/routers/web/org/block.go b/routers/web/org/block.go
index d40458e250..aeb4bd51a8 100644
--- a/routers/web/org/block.go
+++ b/routers/web/org/block.go
@@ -6,13 +6,13 @@ package org
import (
"net/http"
- "code.gitea.io/gitea/modules/base"
+ "code.gitea.io/gitea/modules/templates"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
"code.gitea.io/gitea/services/context"
)
const (
- tplSettingsBlockedUsers base.TplName = "org/settings/blocked_users"
+ tplSettingsBlockedUsers templates.TplName = "org/settings/blocked_users"
)
func BlockedUsers(ctx *context.Context) {
diff --git a/routers/web/org/home.go b/routers/web/org/home.go
index f02c08ae76..7122aff6bd 100644
--- a/routers/web/org/home.go
+++ b/routers/web/org/home.go
@@ -13,17 +13,17 @@ import (
"code.gitea.io/gitea/models/organization"
"code.gitea.io/gitea/models/renderhelper"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
"code.gitea.io/gitea/services/context"
)
const (
- tplOrgHome base.TplName = "org/home"
+ tplOrgHome templates.TplName = "org/home"
)
// Home show organization home page
diff --git a/routers/web/org/members.go b/routers/web/org/members.go
index 7af087c4df..f91062957e 100644
--- a/routers/web/org/members.go
+++ b/routers/web/org/members.go
@@ -9,9 +9,9 @@ import (
"code.gitea.io/gitea/models/organization"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
"code.gitea.io/gitea/services/context"
org_service "code.gitea.io/gitea/services/org"
@@ -19,7 +19,7 @@ import (
const (
// tplMembers template for organization members page
- tplMembers base.TplName = "org/member/members"
+ tplMembers templates.TplName = "org/member/members"
)
// Members render organization users page
diff --git a/routers/web/org/org.go b/routers/web/org/org.go
index f94dd16eae..856a605764 100644
--- a/routers/web/org/org.go
+++ b/routers/web/org/org.go
@@ -11,9 +11,9 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/organization"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
@@ -21,7 +21,7 @@ import (
const (
// tplCreateOrg template path for create organization
- tplCreateOrg base.TplName = "org/create"
+ tplCreateOrg templates.TplName = "org/create"
)
// Create render the page for create organization
diff --git a/routers/web/org/projects.go b/routers/web/org/projects.go
index 3b9ec2a7b8..08201e5eaa 100644
--- a/routers/web/org/projects.go
+++ b/routers/web/org/projects.go
@@ -15,7 +15,6 @@ import (
project_model "code.gitea.io/gitea/models/project"
attachment_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
@@ -29,9 +28,9 @@ import (
)
const (
- tplProjects base.TplName = "org/projects/list"
- tplProjectsNew base.TplName = "org/projects/new"
- tplProjectsView base.TplName = "org/projects/view"
+ tplProjects templates.TplName = "org/projects/list"
+ tplProjectsNew templates.TplName = "org/projects/new"
+ tplProjectsView templates.TplName = "org/projects/view"
)
// MustEnableProjects check if projects are enabled in settings
diff --git a/routers/web/org/setting.go b/routers/web/org/setting.go
index 494ada4323..cb1c4213c9 100644
--- a/routers/web/org/setting.go
+++ b/routers/web/org/setting.go
@@ -8,16 +8,16 @@ import (
"net/http"
"net/url"
- "code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
+ packages_model "code.gitea.io/gitea/models/packages"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/models/webhook"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/web"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
user_setting "code.gitea.io/gitea/routers/web/user/setting"
@@ -30,13 +30,13 @@ import (
const (
// tplSettingsOptions template path for render settings
- tplSettingsOptions base.TplName = "org/settings/options"
+ tplSettingsOptions templates.TplName = "org/settings/options"
// tplSettingsDelete template path for render delete repository
- tplSettingsDelete base.TplName = "org/settings/delete"
+ tplSettingsDelete templates.TplName = "org/settings/delete"
// tplSettingsHooks template path for render hook settings
- tplSettingsHooks base.TplName = "org/settings/hooks"
+ tplSettingsHooks templates.TplName = "org/settings/hooks"
// tplSettingsLabels template path for render labels settings
- tplSettingsLabels base.TplName = "org/settings/labels"
+ tplSettingsLabels templates.TplName = "org/settings/labels"
)
// Settings render the main settings page
@@ -178,10 +178,10 @@ func SettingsDelete(ctx *context.Context) {
}
if err := org_service.DeleteOrganization(ctx, ctx.Org.Organization, false); err != nil {
- if models.IsErrUserOwnRepos(err) {
+ if repo_model.IsErrUserOwnRepos(err) {
ctx.Flash.Error(ctx.Tr("form.org_still_own_repo"))
ctx.Redirect(ctx.Org.OrgLink + "/settings/delete")
- } else if models.IsErrUserOwnPackages(err) {
+ } else if packages_model.IsErrUserOwnPackages(err) {
ctx.Flash.Error(ctx.Tr("form.org_still_own_packages"))
ctx.Redirect(ctx.Org.OrgLink + "/settings/delete")
} else {
diff --git a/routers/web/org/setting_oauth2.go b/routers/web/org/setting_oauth2.go
index 7f855795d3..c93058477e 100644
--- a/routers/web/org/setting_oauth2.go
+++ b/routers/web/org/setting_oauth2.go
@@ -9,16 +9,16 @@ import (
"code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
user_setting "code.gitea.io/gitea/routers/web/user/setting"
"code.gitea.io/gitea/services/context"
)
const (
- tplSettingsApplications base.TplName = "org/settings/applications"
- tplSettingsOAuthApplicationEdit base.TplName = "org/settings/applications_oauth2_edit"
+ tplSettingsApplications templates.TplName = "org/settings/applications"
+ tplSettingsOAuthApplicationEdit templates.TplName = "org/settings/applications_oauth2_edit"
)
func newOAuth2CommonHandlers(org *context.Organization) *user_setting.OAuth2CommonHandlers {
diff --git a/routers/web/org/setting_packages.go b/routers/web/org/setting_packages.go
index af9836e42c..0912a9e0fd 100644
--- a/routers/web/org/setting_packages.go
+++ b/routers/web/org/setting_packages.go
@@ -7,17 +7,17 @@ import (
"fmt"
"net/http"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
shared "code.gitea.io/gitea/routers/web/shared/packages"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
"code.gitea.io/gitea/services/context"
)
const (
- tplSettingsPackages base.TplName = "org/settings/packages"
- tplSettingsPackagesRuleEdit base.TplName = "org/settings/packages_cleanup_rules_edit"
- tplSettingsPackagesRulePreview base.TplName = "org/settings/packages_cleanup_rules_preview"
+ tplSettingsPackages templates.TplName = "org/settings/packages"
+ tplSettingsPackagesRuleEdit templates.TplName = "org/settings/packages_cleanup_rules_edit"
+ tplSettingsPackagesRulePreview templates.TplName = "org/settings/packages_cleanup_rules_preview"
)
func Packages(ctx *context.Context) {
diff --git a/routers/web/org/teams.go b/routers/web/org/teams.go
index b03b18bd9c..7414a11308 100644
--- a/routers/web/org/teams.go
+++ b/routers/web/org/teams.go
@@ -19,9 +19,9 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
unit_model "code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/web"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
"code.gitea.io/gitea/services/context"
@@ -33,15 +33,15 @@ import (
const (
// tplTeams template path for teams list page
- tplTeams base.TplName = "org/team/teams"
+ tplTeams templates.TplName = "org/team/teams"
// tplTeamNew template path for create new team page
- tplTeamNew base.TplName = "org/team/new"
+ tplTeamNew templates.TplName = "org/team/new"
// tplTeamMembers template path for showing team members page
- tplTeamMembers base.TplName = "org/team/members"
+ tplTeamMembers templates.TplName = "org/team/members"
// tplTeamRepositories template path for showing team repositories page
- tplTeamRepositories base.TplName = "org/team/repositories"
+ tplTeamRepositories templates.TplName = "org/team/repositories"
// tplTeamInvite template path for team invites page
- tplTeamInvite base.TplName = "org/team/invite"
+ tplTeamInvite templates.TplName = "org/team/invite"
)
// Teams render teams list page
diff --git a/routers/web/repo/actions/actions.go b/routers/web/repo/actions/actions.go
index 1de1835936..099593bff0 100644
--- a/routers/web/repo/actions/actions.go
+++ b/routers/web/repo/actions/actions.go
@@ -17,12 +17,12 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/modules/actions"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
"code.gitea.io/gitea/services/context"
@@ -33,8 +33,8 @@ import (
)
const (
- tplListActions base.TplName = "repo/actions/list"
- tplViewActions base.TplName = "repo/actions/view"
+ tplListActions templates.TplName = "repo/actions/list"
+ tplViewActions templates.TplName = "repo/actions/view"
)
type Workflow struct {
diff --git a/routers/web/repo/activity.go b/routers/web/repo/activity.go
index 65dd9e392f..1d809ad8e9 100644
--- a/routers/web/repo/activity.go
+++ b/routers/web/repo/activity.go
@@ -9,12 +9,12 @@ import (
activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/models/unit"
- "code.gitea.io/gitea/modules/base"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/services/context"
)
const (
- tplActivity base.TplName = "repo/activity"
+ tplActivity templates.TplName = "repo/activity"
)
// Activity render the page to show repository latest changes
diff --git a/routers/web/repo/branch.go b/routers/web/repo/branch.go
index c918cd7a72..72fd958e28 100644
--- a/routers/web/repo/branch.go
+++ b/routers/web/repo/branch.go
@@ -11,27 +11,27 @@ import (
"net/url"
"strings"
- "code.gitea.io/gitea/models"
git_model "code.gitea.io/gitea/models/git"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/utils"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
+ pull_service "code.gitea.io/gitea/services/pull"
release_service "code.gitea.io/gitea/services/release"
repo_service "code.gitea.io/gitea/services/repository"
)
const (
- tplBranch base.TplName = "repo/branch/list"
+ tplBranch templates.TplName = "repo/branch/list"
)
// Branches render repository branch page
@@ -203,14 +203,14 @@ func CreateBranch(ctx *context.Context) {
err = repo_service.CreateNewBranchFromCommit(ctx, ctx.Doer, ctx.Repo.Repository, ctx.Repo.GitRepo, ctx.Repo.CommitID, form.NewBranchName)
}
if err != nil {
- if models.IsErrProtectedTagName(err) {
+ if release_service.IsErrProtectedTagName(err) {
ctx.Flash.Error(ctx.Tr("repo.release.tag_name_protected"))
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL())
return
}
- if models.IsErrTagAlreadyExists(err) {
- e := err.(models.ErrTagAlreadyExists)
+ if release_service.IsErrTagAlreadyExists(err) {
+ e := err.(release_service.ErrTagAlreadyExists)
ctx.Flash.Error(ctx.Tr("repo.branch.tag_collision", e.TagName))
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL())
return
@@ -267,7 +267,7 @@ func MergeUpstream(ctx *context.Context) {
if errors.Is(err, util.ErrNotExist) {
ctx.JSONError(ctx.Tr("error.not_found"))
return
- } else if models.IsErrMergeConflicts(err) {
+ } else if pull_service.IsErrMergeConflicts(err) {
ctx.JSONError(ctx.Tr("repo.pulls.merge_conflict"))
return
}
diff --git a/routers/web/repo/cherry_pick.go b/routers/web/repo/cherry_pick.go
index 61aff78d49..30f4c8a90e 100644
--- a/routers/web/repo/cherry_pick.go
+++ b/routers/web/repo/cherry_pick.go
@@ -8,12 +8,11 @@ import (
"errors"
"strings"
- "code.gitea.io/gitea/models"
git_model "code.gitea.io/gitea/models/git"
"code.gitea.io/gitea/models/unit"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/context"
@@ -21,7 +20,7 @@ import (
"code.gitea.io/gitea/services/repository/files"
)
-var tplCherryPick base.TplName = "repo/editor/cherry_pick"
+var tplCherryPick templates.TplName = "repo/editor/cherry_pick"
// CherryPick handles cherrypick GETs
func CherryPick(ctx *context.Context) {
@@ -131,7 +130,7 @@ func CherryPickPost(ctx *context.Context) {
ctx.Data["Err_NewBranchName"] = true
ctx.RenderWithErr(ctx.Tr("repo.editor.branch_already_exists", branchErr.BranchName), tplCherryPick, &form)
return
- } else if models.IsErrCommitIDDoesNotMatch(err) {
+ } else if files.IsErrCommitIDDoesNotMatch(err) {
ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+form.LastCommit+"..."+ctx.Repo.CommitID), tplPatchFile, &form)
return
}
@@ -168,7 +167,7 @@ func CherryPickPost(ctx *context.Context) {
ctx.Data["Err_NewBranchName"] = true
ctx.RenderWithErr(ctx.Tr("repo.editor.branch_already_exists", branchErr.BranchName), tplCherryPick, &form)
return
- } else if models.IsErrCommitIDDoesNotMatch(err) {
+ } else if files.IsErrCommitIDDoesNotMatch(err) {
ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+form.LastCommit+"..."+ctx.Repo.CommitID), tplPatchFile, &form)
return
}
diff --git a/routers/web/repo/code_frequency.go b/routers/web/repo/code_frequency.go
index c76f492da0..6572adce74 100644
--- a/routers/web/repo/code_frequency.go
+++ b/routers/web/repo/code_frequency.go
@@ -7,13 +7,13 @@ import (
"errors"
"net/http"
- "code.gitea.io/gitea/modules/base"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/services/context"
contributors_service "code.gitea.io/gitea/services/repository"
)
const (
- tplCodeFrequency base.TplName = "repo/activity"
+ tplCodeFrequency templates.TplName = "repo/activity"
)
// CodeFrequency renders the page to show repository code frequency
diff --git a/routers/web/repo/commit.go b/routers/web/repo/commit.go
index 6d53df7c10..1447b17a36 100644
--- a/routers/web/repo/commit.go
+++ b/routers/web/repo/commit.go
@@ -27,6 +27,7 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/gitdiff"
@@ -34,10 +35,10 @@ import (
)
const (
- tplCommits base.TplName = "repo/commits"
- tplGraph base.TplName = "repo/graph"
- tplGraphDiv base.TplName = "repo/graph/div"
- tplCommitPage base.TplName = "repo/commit_page"
+ tplCommits templates.TplName = "repo/commits"
+ tplGraph templates.TplName = "repo/graph"
+ tplGraphDiv templates.TplName = "repo/graph/div"
+ tplCommitPage templates.TplName = "repo/commit_page"
)
// RefCommits render commits page
diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go
index 278974bec3..6c59421bda 100644
--- a/routers/web/repo/compare.go
+++ b/routers/web/repo/compare.go
@@ -33,6 +33,7 @@ import (
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/typesniffer"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/common"
@@ -42,9 +43,9 @@ import (
)
const (
- tplCompare base.TplName = "repo/diff/compare"
- tplBlobExcerpt base.TplName = "repo/diff/blob_excerpt"
- tplDiffBox base.TplName = "repo/diff/box"
+ tplCompare templates.TplName = "repo/diff/compare"
+ tplBlobExcerpt templates.TplName = "repo/diff/blob_excerpt"
+ tplDiffBox templates.TplName = "repo/diff/box"
)
// setCompareContext sets context data.
diff --git a/routers/web/repo/contributors.go b/routers/web/repo/contributors.go
index 762fbf9379..e9c0919955 100644
--- a/routers/web/repo/contributors.go
+++ b/routers/web/repo/contributors.go
@@ -7,13 +7,13 @@ import (
"errors"
"net/http"
- "code.gitea.io/gitea/modules/base"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/services/context"
contributors_service "code.gitea.io/gitea/services/repository"
)
const (
- tplContributors base.TplName = "repo/activity"
+ tplContributors templates.TplName = "repo/activity"
)
// Contributors render the page to show repository contributors graph
diff --git a/routers/web/repo/editor.go b/routers/web/repo/editor.go
index 9396115b0d..5fbdeee27e 100644
--- a/routers/web/repo/editor.go
+++ b/routers/web/repo/editor.go
@@ -10,17 +10,16 @@ import (
"path"
"strings"
- "code.gitea.io/gitea/models"
git_model "code.gitea.io/gitea/models/git"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/charset"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/typesniffer"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
@@ -32,10 +31,10 @@ import (
)
const (
- tplEditFile base.TplName = "repo/editor/edit"
- tplEditDiffPreview base.TplName = "repo/editor/diff_preview"
- tplDeleteFile base.TplName = "repo/editor/delete"
- tplUploadFile base.TplName = "repo/editor/upload"
+ tplEditFile templates.TplName = "repo/editor/edit"
+ tplEditDiffPreview templates.TplName = "repo/editor/diff_preview"
+ tplDeleteFile templates.TplName = "repo/editor/delete"
+ tplUploadFile templates.TplName = "repo/editor/upload"
frmCommitChoiceDirect string = "direct"
frmCommitChoiceNewBranch string = "commit-to-new-branch"
@@ -303,12 +302,12 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b
} else if git_model.IsErrLFSFileLocked(err) {
ctx.Data["Err_TreePath"] = true
ctx.RenderWithErr(ctx.Tr("repo.editor.upload_file_is_locked", err.(git_model.ErrLFSFileLocked).Path, err.(git_model.ErrLFSFileLocked).UserName), tplEditFile, &form)
- } else if models.IsErrFilenameInvalid(err) {
+ } else if files_service.IsErrFilenameInvalid(err) {
ctx.Data["Err_TreePath"] = true
ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_invalid", form.TreePath), tplEditFile, &form)
- } else if models.IsErrFilePathInvalid(err) {
+ } else if files_service.IsErrFilePathInvalid(err) {
ctx.Data["Err_TreePath"] = true
- if fileErr, ok := err.(models.ErrFilePathInvalid); ok {
+ if fileErr, ok := err.(files_service.ErrFilePathInvalid); ok {
switch fileErr.Type {
case git.EntryModeSymlink:
ctx.RenderWithErr(ctx.Tr("repo.editor.file_is_a_symlink", fileErr.Path), tplEditFile, &form)
@@ -322,7 +321,7 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b
} else {
ctx.Error(http.StatusInternalServerError, err.Error())
}
- } else if models.IsErrRepoFileAlreadyExists(err) {
+ } else if files_service.IsErrRepoFileAlreadyExists(err) {
ctx.Data["Err_TreePath"] = true
ctx.RenderWithErr(ctx.Tr("repo.editor.file_already_exists", form.TreePath), tplEditFile, &form)
} else if git.IsErrBranchNotExist(err) {
@@ -340,7 +339,7 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b
} else {
ctx.Error(http.StatusInternalServerError, err.Error())
}
- } else if models.IsErrCommitIDDoesNotMatch(err) {
+ } else if files_service.IsErrCommitIDDoesNotMatch(err) {
ctx.RenderWithErr(ctx.Tr("repo.editor.commit_id_not_matching"), tplEditFile, &form)
} else if git.IsErrPushOutOfDate(err) {
ctx.RenderWithErr(ctx.Tr("repo.editor.push_out_of_date"), tplEditFile, &form)
@@ -506,14 +505,14 @@ func DeleteFilePost(ctx *context.Context) {
Signoff: form.Signoff,
}); err != nil {
// This is where we handle all the errors thrown by repofiles.DeleteRepoFile
- if git.IsErrNotExist(err) || models.IsErrRepoFileDoesNotExist(err) {
+ if git.IsErrNotExist(err) || files_service.IsErrRepoFileDoesNotExist(err) {
ctx.RenderWithErr(ctx.Tr("repo.editor.file_deleting_no_longer_exists", ctx.Repo.TreePath), tplDeleteFile, &form)
- } else if models.IsErrFilenameInvalid(err) {
+ } else if files_service.IsErrFilenameInvalid(err) {
ctx.Data["Err_TreePath"] = true
ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_invalid", ctx.Repo.TreePath), tplDeleteFile, &form)
- } else if models.IsErrFilePathInvalid(err) {
+ } else if files_service.IsErrFilePathInvalid(err) {
ctx.Data["Err_TreePath"] = true
- if fileErr, ok := err.(models.ErrFilePathInvalid); ok {
+ if fileErr, ok := err.(files_service.ErrFilePathInvalid); ok {
switch fileErr.Type {
case git.EntryModeSymlink:
ctx.RenderWithErr(ctx.Tr("repo.editor.file_is_a_symlink", fileErr.Path), tplDeleteFile, &form)
@@ -541,7 +540,7 @@ func DeleteFilePost(ctx *context.Context) {
} else {
ctx.Error(http.StatusInternalServerError, err.Error())
}
- } else if models.IsErrCommitIDDoesNotMatch(err) || git.IsErrPushOutOfDate(err) {
+ } else if files_service.IsErrCommitIDDoesNotMatch(err) || git.IsErrPushOutOfDate(err) {
ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_deleting", ctx.Repo.RepoLink+"/compare/"+util.PathEscapeSegments(form.LastCommit)+"..."+util.PathEscapeSegments(ctx.Repo.CommitID)), tplDeleteFile, &form)
} else if git.IsErrPushRejected(err) {
errPushRej := err.(*git.ErrPushRejected)
@@ -715,12 +714,12 @@ func UploadFilePost(ctx *context.Context) {
if git_model.IsErrLFSFileLocked(err) {
ctx.Data["Err_TreePath"] = true
ctx.RenderWithErr(ctx.Tr("repo.editor.upload_file_is_locked", err.(git_model.ErrLFSFileLocked).Path, err.(git_model.ErrLFSFileLocked).UserName), tplUploadFile, &form)
- } else if models.IsErrFilenameInvalid(err) {
+ } else if files_service.IsErrFilenameInvalid(err) {
ctx.Data["Err_TreePath"] = true
ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_invalid", form.TreePath), tplUploadFile, &form)
- } else if models.IsErrFilePathInvalid(err) {
+ } else if files_service.IsErrFilePathInvalid(err) {
ctx.Data["Err_TreePath"] = true
- fileErr := err.(models.ErrFilePathInvalid)
+ fileErr := err.(files_service.ErrFilePathInvalid)
switch fileErr.Type {
case git.EntryModeSymlink:
ctx.RenderWithErr(ctx.Tr("repo.editor.file_is_a_symlink", fileErr.Path), tplUploadFile, &form)
@@ -731,7 +730,7 @@ func UploadFilePost(ctx *context.Context) {
default:
ctx.Error(http.StatusInternalServerError, err.Error())
}
- } else if models.IsErrRepoFileAlreadyExists(err) {
+ } else if files_service.IsErrRepoFileAlreadyExists(err) {
ctx.Data["Err_TreePath"] = true
ctx.RenderWithErr(ctx.Tr("repo.editor.file_already_exists", form.TreePath), tplUploadFile, &form)
} else if git.IsErrBranchNotExist(err) {
diff --git a/routers/web/repo/find.go b/routers/web/repo/find.go
index 2c44552f9c..3a3a7610e7 100644
--- a/routers/web/repo/find.go
+++ b/routers/web/repo/find.go
@@ -6,13 +6,13 @@ package repo
import (
"net/http"
- "code.gitea.io/gitea/modules/base"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/services/context"
)
const (
- tplFindFiles base.TplName = "repo/find/files"
+ tplFindFiles templates.TplName = "repo/find/files"
)
// FindFiles render the page to find repository files
diff --git a/routers/web/repo/fork.go b/routers/web/repo/fork.go
index 86af705617..786b5d7e43 100644
--- a/routers/web/repo/fork.go
+++ b/routers/web/repo/fork.go
@@ -13,12 +13,12 @@ import (
"code.gitea.io/gitea/models/organization"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
@@ -26,7 +26,7 @@ import (
)
const (
- tplFork base.TplName = "repo/pulls/fork"
+ tplFork templates.TplName = "repo/pulls/fork"
)
func getForkRepository(ctx *context.Context) *repo_model.Repository {
diff --git a/routers/web/repo/githttp.go b/routers/web/repo/githttp.go
index 58a2bdbab1..a8a7a4bd79 100644
--- a/routers/web/repo/githttp.go
+++ b/routers/web/repo/githttp.go
@@ -458,7 +458,6 @@ func serviceRPC(ctx *context.Context, h *serviceHandler, service string) {
var stderr bytes.Buffer
cmd.AddArguments("--stateless-rpc").AddDynamicArguments(h.getRepoDir())
- cmd.SetDescription(fmt.Sprintf("%s %s %s [repo_path: %s]", git.GitExecutable, service, "--stateless-rpc", h.getRepoDir()))
if err := cmd.Run(&git.RunOpts{
Dir: h.getRepoDir(),
Env: append(os.Environ(), h.environ...),
diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go
index 5397411b59..23012dda3d 100644
--- a/routers/web/repo/issue.go
+++ b/routers/web/repo/issue.go
@@ -21,7 +21,6 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/optional"
@@ -37,14 +36,14 @@ import (
)
const (
- tplAttachment base.TplName = "repo/issue/view_content/attachments"
+ tplAttachment templates.TplName = "repo/issue/view_content/attachments"
- tplIssues base.TplName = "repo/issue/list"
- tplIssueNew base.TplName = "repo/issue/new"
- tplIssueChoose base.TplName = "repo/issue/choose"
- tplIssueView base.TplName = "repo/issue/view"
+ tplIssues templates.TplName = "repo/issue/list"
+ tplIssueNew templates.TplName = "repo/issue/new"
+ tplIssueChoose templates.TplName = "repo/issue/choose"
+ tplIssueView templates.TplName = "repo/issue/view"
- tplReactions base.TplName = "repo/issue/view_content/reactions"
+ tplReactions templates.TplName = "repo/issue/view_content/reactions"
issueTemplateKey = "IssueTemplate"
issueTemplateTitleKey = "IssueTemplateTitle"
diff --git a/routers/web/repo/issue_label.go b/routers/web/repo/issue_label.go
index 4874baaa54..5ef6b09faa 100644
--- a/routers/web/repo/issue_label.go
+++ b/routers/web/repo/issue_label.go
@@ -9,10 +9,10 @@ import (
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/organization"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/label"
"code.gitea.io/gitea/modules/log"
repo_module "code.gitea.io/gitea/modules/repository"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
@@ -20,7 +20,7 @@ import (
)
const (
- tplLabels base.TplName = "repo/issue/labels"
+ tplLabels templates.TplName = "repo/issue/labels"
)
// Labels render issue's labels page
diff --git a/routers/web/repo/issue_watch.go b/routers/web/repo/issue_watch.go
index 8b033f3b17..a2a4be1758 100644
--- a/routers/web/repo/issue_watch.go
+++ b/routers/web/repo/issue_watch.go
@@ -8,13 +8,13 @@ import (
"strconv"
issues_model "code.gitea.io/gitea/models/issues"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/services/context"
)
const (
- tplWatching base.TplName = "repo/issue/view_content/watching"
+ tplWatching templates.TplName = "repo/issue/view_content/watching"
)
// IssueWatch sets issue watching
diff --git a/routers/web/repo/migrate.go b/routers/web/repo/migrate.go
index 3eaf05f383..3a7dc29466 100644
--- a/routers/web/repo/migrate.go
+++ b/routers/web/repo/migrate.go
@@ -9,17 +9,17 @@ import (
"net/url"
"strings"
- "code.gitea.io/gitea/models"
admin_model "code.gitea.io/gitea/models/admin"
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
+ "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/lfs"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/context"
@@ -29,7 +29,7 @@ import (
)
const (
- tplMigrate base.TplName = "repo/migrate/migrate"
+ tplMigrate templates.TplName = "repo/migrate/migrate"
)
// Migrate render migration of repository page
@@ -67,10 +67,10 @@ func Migrate(ctx *context.Context) {
}
ctx.Data["ContextUser"] = ctxUser
- ctx.HTML(http.StatusOK, base.TplName("repo/migrate/"+serviceType.Name()))
+ ctx.HTML(http.StatusOK, templates.TplName("repo/migrate/"+serviceType.Name()))
}
-func handleMigrateError(ctx *context.Context, owner *user_model.User, err error, name string, tpl base.TplName, form *forms.MigrateRepoForm) {
+func handleMigrateError(ctx *context.Context, owner *user_model.User, err error, name string, tpl templates.TplName, form *forms.MigrateRepoForm) {
if setting.Repository.DisableMigrations {
ctx.Error(http.StatusForbidden, "MigrateError: the site administrator has disabled migrations")
return
@@ -122,9 +122,9 @@ func handleMigrateError(ctx *context.Context, owner *user_model.User, err error,
}
}
-func handleMigrateRemoteAddrError(ctx *context.Context, err error, tpl base.TplName, form *forms.MigrateRepoForm) {
- if models.IsErrInvalidCloneAddr(err) {
- addrErr := err.(*models.ErrInvalidCloneAddr)
+func handleMigrateRemoteAddrError(ctx *context.Context, err error, tpl templates.TplName, form *forms.MigrateRepoForm) {
+ if git.IsErrInvalidCloneAddr(err) {
+ addrErr := err.(*git.ErrInvalidCloneAddr)
switch {
case addrErr.IsProtocolInvalid:
ctx.RenderWithErr(ctx.Tr("repo.mirror_address_protocol_invalid"), tpl, form)
@@ -169,14 +169,14 @@ func MigratePost(ctx *context.Context) {
}
ctx.Data["ContextUser"] = ctxUser
- tpl := base.TplName("repo/migrate/" + form.Service.Name())
+ tpl := templates.TplName("repo/migrate/" + form.Service.Name())
if ctx.HasError() {
ctx.HTML(http.StatusOK, tpl)
return
}
- remoteAddr, err := forms.ParseRemoteAddr(form.CloneAddr, form.AuthUsername, form.AuthPassword)
+ remoteAddr, err := git.ParseRemoteAddr(form.CloneAddr, form.AuthUsername, form.AuthPassword)
if err == nil {
err = migrations.IsMigrateURLAllowed(remoteAddr, ctx.Doer)
}
diff --git a/routers/web/repo/milestone.go b/routers/web/repo/milestone.go
index 33c15e7767..d6e41a89b2 100644
--- a/routers/web/repo/milestone.go
+++ b/routers/web/repo/milestone.go
@@ -11,10 +11,10 @@ import (
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/renderhelper"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/common"
"code.gitea.io/gitea/services/context"
@@ -25,9 +25,9 @@ import (
)
const (
- tplMilestone base.TplName = "repo/issue/milestones"
- tplMilestoneNew base.TplName = "repo/issue/milestone_new"
- tplMilestoneIssues base.TplName = "repo/issue/milestone_issues"
+ tplMilestone templates.TplName = "repo/issue/milestones"
+ tplMilestoneNew templates.TplName = "repo/issue/milestone_new"
+ tplMilestoneIssues templates.TplName = "repo/issue/milestone_issues"
)
// Milestones render milestones page
diff --git a/routers/web/repo/packages.go b/routers/web/repo/packages.go
index 57e578da37..c8d3719bc0 100644
--- a/routers/web/repo/packages.go
+++ b/routers/web/repo/packages.go
@@ -9,14 +9,14 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/packages"
"code.gitea.io/gitea/models/unit"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/services/context"
)
const (
- tplPackagesList base.TplName = "repo/packages"
+ tplPackagesList templates.TplName = "repo/packages"
)
// Packages displays a list of all packages in the repository
diff --git a/routers/web/repo/patch.go b/routers/web/repo/patch.go
index 0dee02dd9c..1807cf31a1 100644
--- a/routers/web/repo/patch.go
+++ b/routers/web/repo/patch.go
@@ -6,11 +6,10 @@ package repo
import (
"strings"
- "code.gitea.io/gitea/models"
git_model "code.gitea.io/gitea/models/git"
"code.gitea.io/gitea/models/unit"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/context"
@@ -19,7 +18,7 @@ import (
)
const (
- tplPatchFile base.TplName = "repo/editor/patch"
+ tplPatchFile templates.TplName = "repo/editor/patch"
)
// NewDiffPatch render create patch page
@@ -101,7 +100,7 @@ func NewDiffPatchPost(ctx *context.Context) {
ctx.Data["Err_NewBranchName"] = true
ctx.RenderWithErr(ctx.Tr("repo.editor.branch_already_exists", branchErr.BranchName), tplEditFile, &form)
return
- } else if models.IsErrCommitIDDoesNotMatch(err) {
+ } else if files.IsErrCommitIDDoesNotMatch(err) {
ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+form.LastCommit+"..."+ctx.Repo.CommitID), tplPatchFile, &form)
return
}
diff --git a/routers/web/repo/projects.go b/routers/web/repo/projects.go
index 3be9578670..92227e3f3e 100644
--- a/routers/web/repo/projects.go
+++ b/routers/web/repo/projects.go
@@ -16,11 +16,11 @@ import (
"code.gitea.io/gitea/models/renderhelper"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/web/shared/issue"
@@ -31,9 +31,9 @@ import (
)
const (
- tplProjects base.TplName = "repo/projects/list"
- tplProjectsNew base.TplName = "repo/projects/new"
- tplProjectsView base.TplName = "repo/projects/view"
+ tplProjects templates.TplName = "repo/projects/list"
+ tplProjectsNew templates.TplName = "repo/projects/new"
+ tplProjectsView templates.TplName = "repo/projects/view"
)
// MustEnableRepoProjects check if repo projects are enabled in settings
diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go
index 9694ae845b..0948282ca2 100644
--- a/routers/web/repo/pull.go
+++ b/routers/web/repo/pull.go
@@ -14,7 +14,6 @@ import (
"strings"
"time"
- "code.gitea.io/gitea/models"
activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
@@ -24,13 +23,13 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/emoji"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
issue_template "code.gitea.io/gitea/modules/issue/template"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/utils"
@@ -50,9 +49,9 @@ import (
)
const (
- tplCompareDiff base.TplName = "repo/diff/compare"
- tplPullCommits base.TplName = "repo/pulls/commits"
- tplPullFiles base.TplName = "repo/pulls/files"
+ tplCompareDiff templates.TplName = "repo/diff/compare"
+ tplPullCommits templates.TplName = "repo/pulls/commits"
+ tplPullFiles templates.TplName = "repo/pulls/files"
pullRequestTemplateKey = "PullRequestTemplate"
)
@@ -701,9 +700,6 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi
if ctx.Written() {
return
- } else if prInfo == nil {
- ctx.NotFound("ViewPullFiles", nil)
- return
}
headCommitID, err := gitRepo.GetRefCommitID(pull.GetGitRefName())
@@ -971,8 +967,8 @@ func UpdatePullRequest(ctx *context.Context) {
message := fmt.Sprintf("Merge branch '%s' into %s", issue.PullRequest.BaseBranch, issue.PullRequest.HeadBranch)
if err = pull_service.Update(ctx, issue.PullRequest, ctx.Doer, message, rebase); err != nil {
- if models.IsErrMergeConflicts(err) {
- conflictError := err.(models.ErrMergeConflicts)
+ if pull_service.IsErrMergeConflicts(err) {
+ conflictError := err.(pull_service.ErrMergeConflicts)
flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
"Message": ctx.Tr("repo.pulls.merge_conflict"),
"Summary": ctx.Tr("repo.pulls.merge_conflict_summary"),
@@ -985,8 +981,8 @@ func UpdatePullRequest(ctx *context.Context) {
ctx.Flash.Error(flashError)
ctx.Redirect(issue.Link())
return
- } else if models.IsErrRebaseConflicts(err) {
- conflictError := err.(models.ErrRebaseConflicts)
+ } else if pull_service.IsErrRebaseConflicts(err) {
+ conflictError := err.(pull_service.ErrRebaseConflicts)
flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
"Message": ctx.Tr("repo.pulls.rebase_conflict", utils.SanitizeFlashErrorString(conflictError.CommitSHA)),
"Summary": ctx.Tr("repo.pulls.rebase_conflict_summary"),
@@ -1050,7 +1046,7 @@ func MergePullRequest(ctx *context.Context) {
ctx.JSONError(ctx.Tr("repo.pulls.no_merge_wip"))
case errors.Is(err, pull_service.ErrNotMergeableState):
ctx.JSONError(ctx.Tr("repo.pulls.no_merge_not_ready"))
- case models.IsErrDisallowedToMerge(err):
+ case pull_service.IsErrDisallowedToMerge(err):
ctx.JSONError(ctx.Tr("repo.pulls.no_merge_not_ready"))
case asymkey_service.IsErrWontSign(err):
ctx.JSONError(err.Error()) // has no translation ...
@@ -1067,7 +1063,7 @@ func MergePullRequest(ctx *context.Context) {
if manuallyMerged {
if err := pull_service.MergedManually(ctx, pr, ctx.Doer, ctx.Repo.GitRepo, form.MergeCommitID); err != nil {
switch {
- case models.IsErrInvalidMergeStyle(err):
+ case pull_service.IsErrInvalidMergeStyle(err):
ctx.JSONError(ctx.Tr("repo.pulls.invalid_merge_option"))
case strings.Contains(err.Error(), "Wrong commit ID"):
ctx.JSONError(ctx.Tr("repo.pulls.wrong_commit_id"))
@@ -1114,10 +1110,10 @@ func MergePullRequest(ctx *context.Context) {
}
if err := pull_service.Merge(ctx, pr, ctx.Doer, ctx.Repo.GitRepo, repo_model.MergeStyle(form.Do), form.HeadCommitID, message, false); err != nil {
- if models.IsErrInvalidMergeStyle(err) {
+ if pull_service.IsErrInvalidMergeStyle(err) {
ctx.JSONError(ctx.Tr("repo.pulls.invalid_merge_option"))
- } else if models.IsErrMergeConflicts(err) {
- conflictError := err.(models.ErrMergeConflicts)
+ } else if pull_service.IsErrMergeConflicts(err) {
+ conflictError := err.(pull_service.ErrMergeConflicts)
flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
"Message": ctx.Tr("repo.editor.merge_conflict"),
"Summary": ctx.Tr("repo.editor.merge_conflict_summary"),
@@ -1129,8 +1125,8 @@ func MergePullRequest(ctx *context.Context) {
}
ctx.Flash.Error(flashError)
ctx.JSONRedirect(issue.Link())
- } else if models.IsErrRebaseConflicts(err) {
- conflictError := err.(models.ErrRebaseConflicts)
+ } else if pull_service.IsErrRebaseConflicts(err) {
+ conflictError := err.(pull_service.ErrRebaseConflicts)
flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
"Message": ctx.Tr("repo.pulls.rebase_conflict", utils.SanitizeFlashErrorString(conflictError.CommitSHA)),
"Summary": ctx.Tr("repo.pulls.rebase_conflict_summary"),
@@ -1142,7 +1138,7 @@ func MergePullRequest(ctx *context.Context) {
}
ctx.Flash.Error(flashError)
ctx.JSONRedirect(issue.Link())
- } else if models.IsErrMergeUnrelatedHistories(err) {
+ } else if pull_service.IsErrMergeUnrelatedHistories(err) {
log.Debug("MergeUnrelatedHistories error: %v", err)
ctx.Flash.Error(ctx.Tr("repo.pulls.unrelated_histories"))
ctx.JSONRedirect(issue.Link())
@@ -1150,7 +1146,7 @@ func MergePullRequest(ctx *context.Context) {
log.Debug("MergePushOutOfDate error: %v", err)
ctx.Flash.Error(ctx.Tr("repo.pulls.merge_out_of_date"))
ctx.JSONRedirect(issue.Link())
- } else if models.IsErrSHADoesNotMatch(err) {
+ } else if pull_service.IsErrSHADoesNotMatch(err) {
log.Debug("MergeHeadOutOfDate error: %v", err)
ctx.Flash.Error(ctx.Tr("repo.pulls.head_out_of_date"))
ctx.JSONRedirect(issue.Link())
@@ -1609,7 +1605,7 @@ func UpdatePullRequestTarget(ctx *context.Context) {
"error": err.Error(),
"user_error": errorMessage,
})
- } else if models.IsErrPullRequestHasMerged(err) {
+ } else if pull_service.IsErrPullRequestHasMerged(err) {
errorMessage := ctx.Tr("repo.pulls.has_merged")
ctx.Flash.Error(errorMessage)
diff --git a/routers/web/repo/pull_review.go b/routers/web/repo/pull_review.go
index aa2e689e42..3e9e615b15 100644
--- a/routers/web/repo/pull_review.go
+++ b/routers/web/repo/pull_review.go
@@ -12,10 +12,10 @@ import (
"code.gitea.io/gitea/models/organization"
pull_model "code.gitea.io/gitea/models/pull"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/context/upload"
@@ -26,10 +26,10 @@ import (
)
const (
- tplDiffConversation base.TplName = "repo/diff/conversation"
- tplConversationOutdated base.TplName = "repo/diff/conversation_outdated"
- tplTimelineConversation base.TplName = "repo/issue/view_content/conversation"
- tplNewComment base.TplName = "repo/diff/new_comment"
+ tplDiffConversation templates.TplName = "repo/diff/conversation"
+ tplConversationOutdated templates.TplName = "repo/diff/conversation_outdated"
+ tplTimelineConversation templates.TplName = "repo/issue/view_content/conversation"
+ tplNewComment templates.TplName = "repo/diff/new_comment"
)
// RenderNewCodeCommentForm will render the form for creating a new review comment
diff --git a/routers/web/repo/recent_commits.go b/routers/web/repo/recent_commits.go
index c158fb30b6..dc72081900 100644
--- a/routers/web/repo/recent_commits.go
+++ b/routers/web/repo/recent_commits.go
@@ -7,13 +7,13 @@ import (
"errors"
"net/http"
- "code.gitea.io/gitea/modules/base"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/services/context"
contributors_service "code.gitea.io/gitea/services/repository"
)
const (
- tplRecentCommits base.TplName = "repo/activity"
+ tplRecentCommits templates.TplName = "repo/activity"
)
// RecentCommits renders the page to show recent commit frequency on repository
diff --git a/routers/web/repo/release.go b/routers/web/repo/release.go
index b3a91a6070..b8176cb70b 100644
--- a/routers/web/repo/release.go
+++ b/routers/web/repo/release.go
@@ -10,19 +10,18 @@ import (
"net/http"
"strings"
- "code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
"code.gitea.io/gitea/models/renderhelper"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/web/feed"
@@ -30,13 +29,13 @@ import (
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/context/upload"
"code.gitea.io/gitea/services/forms"
- releaseservice "code.gitea.io/gitea/services/release"
+ release_service "code.gitea.io/gitea/services/release"
)
const (
- tplReleasesList base.TplName = "repo/release/list"
- tplReleaseNew base.TplName = "repo/release/new"
- tplTagsList base.TplName = "repo/tag/list"
+ tplReleasesList templates.TplName = "repo/release/list"
+ tplReleaseNew templates.TplName = "repo/release/new"
+ tplTagsList templates.TplName = "repo/tag/list"
)
// calReleaseNumCommitsBehind calculates given release has how many commits behind release target.
@@ -432,27 +431,27 @@ func NewReleasePost(ctx *context.Context) {
}
if len(form.TagOnly) > 0 {
- if err = releaseservice.CreateNewTag(ctx, ctx.Doer, ctx.Repo.Repository, form.Target, form.TagName, msg); err != nil {
- if models.IsErrTagAlreadyExists(err) {
- e := err.(models.ErrTagAlreadyExists)
+ if err = release_service.CreateNewTag(ctx, ctx.Doer, ctx.Repo.Repository, form.Target, form.TagName, msg); err != nil {
+ if release_service.IsErrTagAlreadyExists(err) {
+ e := err.(release_service.ErrTagAlreadyExists)
ctx.Flash.Error(ctx.Tr("repo.branch.tag_collision", e.TagName))
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL())
return
}
- if models.IsErrInvalidTagName(err) {
+ if release_service.IsErrInvalidTagName(err) {
ctx.Flash.Error(ctx.Tr("repo.release.tag_name_invalid"))
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL())
return
}
- if models.IsErrProtectedTagName(err) {
+ if release_service.IsErrProtectedTagName(err) {
ctx.Flash.Error(ctx.Tr("repo.release.tag_name_protected"))
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL())
return
}
- ctx.ServerError("releaseservice.CreateNewTag", err)
+ ctx.ServerError("release_service.CreateNewTag", err)
return
}
@@ -475,14 +474,14 @@ func NewReleasePost(ctx *context.Context) {
IsTag: false,
}
- if err = releaseservice.CreateRelease(ctx.Repo.GitRepo, rel, attachmentUUIDs, msg); err != nil {
+ if err = release_service.CreateRelease(ctx.Repo.GitRepo, rel, attachmentUUIDs, msg); err != nil {
ctx.Data["Err_TagName"] = true
switch {
case repo_model.IsErrReleaseAlreadyExist(err):
ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_already_exist"), tplReleaseNew, &form)
- case models.IsErrInvalidTagName(err):
+ case release_service.IsErrInvalidTagName(err):
ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_invalid"), tplReleaseNew, &form)
- case models.IsErrProtectedTagName(err):
+ case release_service.IsErrProtectedTagName(err):
ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_protected"), tplReleaseNew, &form)
default:
ctx.ServerError("CreateRelease", err)
@@ -504,7 +503,7 @@ func NewReleasePost(ctx *context.Context) {
rel.PublisherID = ctx.Doer.ID
rel.IsTag = false
- if err = releaseservice.UpdateRelease(ctx, ctx.Doer, ctx.Repo.GitRepo, rel, attachmentUUIDs, nil, nil); err != nil {
+ if err = release_service.UpdateRelease(ctx, ctx.Doer, ctx.Repo.GitRepo, rel, attachmentUUIDs, nil, nil); err != nil {
ctx.Data["Err_TagName"] = true
ctx.ServerError("UpdateRelease", err)
return
@@ -610,7 +609,7 @@ func EditReleasePost(ctx *context.Context) {
rel.Note = form.Content
rel.IsDraft = len(form.Draft) > 0
rel.IsPrerelease = form.Prerelease
- if err = releaseservice.UpdateRelease(ctx, ctx.Doer, ctx.Repo.GitRepo,
+ if err = release_service.UpdateRelease(ctx, ctx.Doer, ctx.Repo.GitRepo,
rel, addAttachmentUUIDs, delAttachmentUUIDs, editAttachments); err != nil {
ctx.ServerError("UpdateRelease", err)
return
@@ -649,8 +648,8 @@ func deleteReleaseOrTag(ctx *context.Context, isDelTag bool) {
return
}
- if err := releaseservice.DeleteReleaseByID(ctx, ctx.Repo.Repository, rel, ctx.Doer, isDelTag); err != nil {
- if models.IsErrProtectedTagName(err) {
+ if err := release_service.DeleteReleaseByID(ctx, ctx.Repo.Repository, rel, ctx.Doer, isDelTag); err != nil {
+ if release_service.IsErrProtectedTagName(err) {
ctx.Flash.Error(ctx.Tr("repo.release.tag_name_protected"))
} else {
ctx.Flash.Error("DeleteReleaseByID: " + err.Error())
diff --git a/routers/web/repo/repo.go b/routers/web/repo/repo.go
index 4b017f61c4..6df7d78f7a 100644
--- a/routers/web/repo/repo.go
+++ b/routers/web/repo/repo.go
@@ -18,7 +18,6 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/cache"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
@@ -27,6 +26,7 @@ import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/context"
@@ -38,8 +38,8 @@ import (
)
const (
- tplCreate base.TplName = "repo/create"
- tplAlertDetails base.TplName = "base/alert_details"
+ tplCreate templates.TplName = "repo/create"
+ tplAlertDetails templates.TplName = "base/alert_details"
)
// MustBeNotEmpty render when a repo is a empty git dir
@@ -185,7 +185,7 @@ func Create(ctx *context.Context) {
ctx.HTML(http.StatusOK, tplCreate)
}
-func handleCreateError(ctx *context.Context, owner *user_model.User, err error, name string, tpl base.TplName, form any) {
+func handleCreateError(ctx *context.Context, owner *user_model.User, err error, name string, tpl templates.TplName, form any) {
switch {
case repo_model.IsErrReachLimitOfRepo(err):
maxCreationLimit := owner.MaxCreationLimit()
@@ -304,8 +304,8 @@ func CreatePost(ctx *context.Context) {
}
const (
- tplWatchUnwatch base.TplName = "repo/watch_unwatch"
- tplStarUnstar base.TplName = "repo/star_unstar"
+ tplWatchUnwatch templates.TplName = "repo/watch_unwatch"
+ tplStarUnstar templates.TplName = "repo/star_unstar"
)
// Action response for actions to a repository
diff --git a/routers/web/repo/search.go b/routers/web/repo/search.go
index 920a865555..a037a34833 100644
--- a/routers/web/repo/search.go
+++ b/routers/web/repo/search.go
@@ -8,14 +8,14 @@ import (
"strings"
"code.gitea.io/gitea/models/db"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/git"
code_indexer "code.gitea.io/gitea/modules/indexer/code"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/services/context"
)
-const tplSearch base.TplName = "repo/search"
+const tplSearch templates.TplName = "repo/search"
func indexSettingToGitGrepPathspecList() (list []string) {
for _, expr := range setting.Indexer.IncludePatterns {
diff --git a/routers/web/repo/setting/lfs.go b/routers/web/repo/setting/lfs.go
index fad6359668..2df483fa34 100644
--- a/routers/web/repo/setting/lfs.go
+++ b/routers/web/repo/setting/lfs.go
@@ -15,7 +15,6 @@ import (
"strings"
git_model "code.gitea.io/gitea/models/git"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/charset"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/git"
@@ -25,17 +24,18 @@ import (
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/typesniffer"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/services/context"
)
const (
- tplSettingsLFS base.TplName = "repo/settings/lfs"
- tplSettingsLFSLocks base.TplName = "repo/settings/lfs_locks"
- tplSettingsLFSFile base.TplName = "repo/settings/lfs_file"
- tplSettingsLFSFileFind base.TplName = "repo/settings/lfs_file_find"
- tplSettingsLFSPointers base.TplName = "repo/settings/lfs_pointers"
+ tplSettingsLFS templates.TplName = "repo/settings/lfs"
+ tplSettingsLFSLocks templates.TplName = "repo/settings/lfs_locks"
+ tplSettingsLFSFile templates.TplName = "repo/settings/lfs_file"
+ tplSettingsLFSFileFind templates.TplName = "repo/settings/lfs_file_find"
+ tplSettingsLFSPointers templates.TplName = "repo/settings/lfs_pointers"
)
// LFSFiles shows a repository's LFS files
diff --git a/routers/web/repo/setting/protected_branch.go b/routers/web/repo/setting/protected_branch.go
index f651d8f318..022a24a9ad 100644
--- a/routers/web/repo/setting/protected_branch.go
+++ b/routers/web/repo/setting/protected_branch.go
@@ -15,6 +15,7 @@ import (
"code.gitea.io/gitea/models/perm"
access_model "code.gitea.io/gitea/models/perm/access"
"code.gitea.io/gitea/modules/base"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/web/repo"
"code.gitea.io/gitea/services/context"
@@ -26,7 +27,7 @@ import (
)
const (
- tplProtectedBranch base.TplName = "repo/settings/protected_branch"
+ tplProtectedBranch templates.TplName = "repo/settings/protected_branch"
)
// ProtectedBranchRules render the page to protect the repository
diff --git a/routers/web/repo/setting/protected_tag.go b/routers/web/repo/setting/protected_tag.go
index fcfa77aa8c..1c24c8a7ba 100644
--- a/routers/web/repo/setting/protected_tag.go
+++ b/routers/web/repo/setting/protected_tag.go
@@ -14,13 +14,14 @@ import (
access_model "code.gitea.io/gitea/models/perm/access"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
)
const (
- tplTags base.TplName = "repo/settings/tags"
+ tplTags templates.TplName = "repo/settings/tags"
)
// Tags render the page to protect tags
diff --git a/routers/web/repo/setting/runners.go b/routers/web/repo/setting/runners.go
index 3141d8f42a..ec037baec1 100644
--- a/routers/web/repo/setting/runners.go
+++ b/routers/web/repo/setting/runners.go
@@ -10,8 +10,8 @@ import (
actions_model "code.gitea.io/gitea/models/actions"
"code.gitea.io/gitea/models/db"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
actions_shared "code.gitea.io/gitea/routers/web/shared/actions"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
"code.gitea.io/gitea/services/context"
@@ -19,14 +19,14 @@ import (
const (
// TODO: Separate secrets from runners when layout is ready
- tplRepoRunners base.TplName = "repo/settings/actions"
- tplOrgRunners base.TplName = "org/settings/actions"
- tplAdminRunners base.TplName = "admin/actions"
- tplUserRunners base.TplName = "user/settings/actions"
- tplRepoRunnerEdit base.TplName = "repo/settings/runner_edit"
- tplOrgRunnerEdit base.TplName = "org/settings/runners_edit"
- tplAdminRunnerEdit base.TplName = "admin/runners/edit"
- tplUserRunnerEdit base.TplName = "user/settings/runner_edit"
+ tplRepoRunners templates.TplName = "repo/settings/actions"
+ tplOrgRunners templates.TplName = "org/settings/actions"
+ tplAdminRunners templates.TplName = "admin/actions"
+ tplUserRunners templates.TplName = "user/settings/actions"
+ tplRepoRunnerEdit templates.TplName = "repo/settings/runner_edit"
+ tplOrgRunnerEdit templates.TplName = "org/settings/runners_edit"
+ tplAdminRunnerEdit templates.TplName = "admin/runners/edit"
+ tplUserRunnerEdit templates.TplName = "user/settings/runner_edit"
)
type runnersCtx struct {
@@ -36,8 +36,8 @@ type runnersCtx struct {
IsOrg bool
IsAdmin bool
IsUser bool
- RunnersTemplate base.TplName
- RunnerEditTemplate base.TplName
+ RunnersTemplate templates.TplName
+ RunnerEditTemplate templates.TplName
RedirectLink string
}
diff --git a/routers/web/repo/setting/secrets.go b/routers/web/repo/setting/secrets.go
index df11729344..46cb875f9b 100644
--- a/routers/web/repo/setting/secrets.go
+++ b/routers/web/repo/setting/secrets.go
@@ -8,8 +8,8 @@ import (
"net/http"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
shared "code.gitea.io/gitea/routers/web/shared/secrets"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
"code.gitea.io/gitea/services/context"
@@ -17,9 +17,9 @@ import (
const (
// TODO: Separate secrets from runners when layout is ready
- tplRepoSecrets base.TplName = "repo/settings/actions"
- tplOrgSecrets base.TplName = "org/settings/actions"
- tplUserSecrets base.TplName = "user/settings/actions"
+ tplRepoSecrets templates.TplName = "repo/settings/actions"
+ tplOrgSecrets templates.TplName = "org/settings/actions"
+ tplUserSecrets templates.TplName = "user/settings/actions"
)
type secretsCtx struct {
@@ -28,7 +28,7 @@ type secretsCtx struct {
IsRepo bool
IsOrg bool
IsUser bool
- SecretsTemplate base.TplName
+ SecretsTemplate templates.TplName
RedirectLink string
}
diff --git a/routers/web/repo/setting/setting.go b/routers/web/repo/setting/setting.go
index f2169d8a79..7399c681e2 100644
--- a/routers/web/repo/setting/setting.go
+++ b/routers/web/repo/setting/setting.go
@@ -11,7 +11,6 @@ import (
"strings"
"time"
- "code.gitea.io/gitea/models"
actions_model "code.gitea.io/gitea/models/actions"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/organization"
@@ -19,7 +18,6 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
unit_model "code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/indexer/code"
issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
@@ -28,6 +26,7 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/validation"
"code.gitea.io/gitea/modules/web"
@@ -42,12 +41,12 @@ import (
)
const (
- tplSettingsOptions base.TplName = "repo/settings/options"
- tplCollaboration base.TplName = "repo/settings/collaboration"
- tplBranches base.TplName = "repo/settings/branches"
- tplGithooks base.TplName = "repo/settings/githooks"
- tplGithookEdit base.TplName = "repo/settings/githook_edit"
- tplDeployKeys base.TplName = "repo/settings/deploy_keys"
+ tplSettingsOptions templates.TplName = "repo/settings/options"
+ tplCollaboration templates.TplName = "repo/settings/collaboration"
+ tplBranches templates.TplName = "repo/settings/branches"
+ tplGithooks templates.TplName = "repo/settings/githooks"
+ tplGithookEdit templates.TplName = "repo/settings/githook_edit"
+ tplDeployKeys templates.TplName = "repo/settings/deploy_keys"
)
// SettingsCtxData is a middleware that sets all the general context data for the
@@ -223,7 +222,7 @@ func SettingsPost(ctx *context.Context) {
form.MirrorPassword, _ = u.User.Password()
}
- address, err := forms.ParseRemoteAddr(form.MirrorAddress, form.MirrorUsername, form.MirrorPassword)
+ address, err := git.ParseRemoteAddr(form.MirrorAddress, form.MirrorUsername, form.MirrorPassword)
if err == nil {
err = migrations.IsMigrateURLAllowed(address, ctx.Doer)
}
@@ -385,7 +384,7 @@ func SettingsPost(ctx *context.Context) {
return
}
- address, err := forms.ParseRemoteAddr(form.PushMirrorAddress, form.PushMirrorUsername, form.PushMirrorPassword)
+ address, err := git.ParseRemoteAddr(form.PushMirrorAddress, form.PushMirrorUsername, form.PushMirrorPassword)
if err == nil {
err = migrations.IsMigrateURLAllowed(address, ctx.Doer)
}
@@ -980,8 +979,8 @@ func SettingsPost(ctx *context.Context) {
}
func handleSettingRemoteAddrError(ctx *context.Context, err error, form *forms.RepoSettingForm) {
- if models.IsErrInvalidCloneAddr(err) {
- addrErr := err.(*models.ErrInvalidCloneAddr)
+ if git.IsErrInvalidCloneAddr(err) {
+ addrErr := err.(*git.ErrInvalidCloneAddr)
switch {
case addrErr.IsProtocolInvalid:
ctx.RenderWithErr(ctx.Tr("repo.mirror_address_protocol_invalid"), tplSettingsOptions, form)
diff --git a/routers/web/repo/setting/variables.go b/routers/web/repo/setting/variables.go
index cc2e619f66..9b5453f043 100644
--- a/routers/web/repo/setting/variables.go
+++ b/routers/web/repo/setting/variables.go
@@ -7,18 +7,18 @@ import (
"errors"
"net/http"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
shared "code.gitea.io/gitea/routers/web/shared/actions"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
"code.gitea.io/gitea/services/context"
)
const (
- tplRepoVariables base.TplName = "repo/settings/actions"
- tplOrgVariables base.TplName = "org/settings/actions"
- tplUserVariables base.TplName = "user/settings/actions"
- tplAdminVariables base.TplName = "admin/actions"
+ tplRepoVariables templates.TplName = "repo/settings/actions"
+ tplOrgVariables templates.TplName = "org/settings/actions"
+ tplUserVariables templates.TplName = "user/settings/actions"
+ tplAdminVariables templates.TplName = "admin/actions"
)
type variablesCtx struct {
@@ -28,7 +28,7 @@ type variablesCtx struct {
IsOrg bool
IsUser bool
IsGlobal bool
- VariablesTemplate base.TplName
+ VariablesTemplate templates.TplName
RedirectLink string
}
diff --git a/routers/web/repo/setting/webhook.go b/routers/web/repo/setting/webhook.go
index 8d548c4e3d..bcf8a7eac0 100644
--- a/routers/web/repo/setting/webhook.go
+++ b/routers/web/repo/setting/webhook.go
@@ -17,11 +17,11 @@ import (
access_model "code.gitea.io/gitea/models/perm/access"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/models/webhook"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
webhook_module "code.gitea.io/gitea/modules/webhook"
@@ -32,11 +32,11 @@ import (
)
const (
- tplHooks base.TplName = "repo/settings/webhook/base"
- tplHookNew base.TplName = "repo/settings/webhook/new"
- tplOrgHookNew base.TplName = "org/settings/hook_new"
- tplUserHookNew base.TplName = "user/settings/hook_new"
- tplAdminHookNew base.TplName = "admin/hook_new"
+ tplHooks templates.TplName = "repo/settings/webhook/base"
+ tplHookNew templates.TplName = "repo/settings/webhook/new"
+ tplOrgHookNew templates.TplName = "org/settings/hook_new"
+ tplUserHookNew templates.TplName = "user/settings/hook_new"
+ tplAdminHookNew templates.TplName = "admin/hook_new"
)
// Webhooks render web hooks list page
@@ -64,7 +64,7 @@ type ownerRepoCtx struct {
IsSystemWebhook bool
Link string
LinkNew string
- NewTemplate base.TplName
+ NewTemplate templates.TplName
}
// getOwnerRepoCtx determines whether this is a repo, owner, or admin (both default and system) context.
diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go
index e43841acd3..14fc9038f3 100644
--- a/routers/web/repo/view.go
+++ b/routers/web/repo/view.go
@@ -35,6 +35,7 @@ import (
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/typesniffer"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/services/context"
@@ -45,12 +46,12 @@ import (
)
const (
- tplRepoEMPTY base.TplName = "repo/empty"
- tplRepoHome base.TplName = "repo/home"
- tplRepoViewList base.TplName = "repo/view_list"
- tplWatchers base.TplName = "repo/watchers"
- tplForks base.TplName = "repo/forks"
- tplMigrating base.TplName = "repo/migrate/migrating"
+ tplRepoEMPTY templates.TplName = "repo/empty"
+ tplRepoHome templates.TplName = "repo/home"
+ tplRepoViewList templates.TplName = "repo/view_list"
+ tplWatchers templates.TplName = "repo/watchers"
+ tplForks templates.TplName = "repo/forks"
+ tplMigrating templates.TplName = "repo/migrate/migrating"
)
type fileInfo struct {
@@ -314,7 +315,7 @@ func renderDirectoryFiles(ctx *context.Context, timeout time.Duration) git.Entri
}
// RenderUserCards render a page show users according the input template
-func RenderUserCards(ctx *context.Context, total int, getter func(opts db.ListOptions) ([]*user_model.User, error), tpl base.TplName) {
+func RenderUserCards(ctx *context.Context, total int, getter func(opts db.ListOptions) ([]*user_model.User, error), tpl templates.TplName) {
page := ctx.FormInt("page")
if page <= 0 {
page = 1
diff --git a/routers/web/repo/wiki.go b/routers/web/repo/wiki.go
index fec72c9253..3fca7cebea 100644
--- a/routers/web/repo/wiki.go
+++ b/routers/web/repo/wiki.go
@@ -26,6 +26,7 @@ import (
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
@@ -37,11 +38,11 @@ import (
)
const (
- tplWikiStart base.TplName = "repo/wiki/start"
- tplWikiView base.TplName = "repo/wiki/view"
- tplWikiRevision base.TplName = "repo/wiki/revision"
- tplWikiNew base.TplName = "repo/wiki/new"
- tplWikiPages base.TplName = "repo/wiki/pages"
+ tplWikiStart templates.TplName = "repo/wiki/start"
+ tplWikiView templates.TplName = "repo/wiki/view"
+ tplWikiRevision templates.TplName = "repo/wiki/revision"
+ tplWikiNew templates.TplName = "repo/wiki/new"
+ tplWikiPages templates.TplName = "repo/wiki/pages"
)
// MustEnableWiki check if wiki is enabled, if external then redirect
diff --git a/routers/web/shared/actions/runners.go b/routers/web/shared/actions/runners.go
index f38933226b..6d77bdd2fa 100644
--- a/routers/web/shared/actions/runners.go
+++ b/routers/web/shared/actions/runners.go
@@ -136,9 +136,8 @@ func RunnerResetRegistrationToken(ctx *context.Context, ownerID, repoID int64, r
ctx.ServerError("ResetRunnerRegistrationToken", err)
return
}
-
ctx.Flash.Success(ctx.Tr("actions.runners.reset_registration_token_success"))
- ctx.Redirect(redirectTo)
+ ctx.JSONRedirect(redirectTo)
}
// RunnerDeletePost response for deleting a runner
diff --git a/routers/web/shared/packages/packages.go b/routers/web/shared/packages/packages.go
index 1d3cabf71b..a1bcb09850 100644
--- a/routers/web/shared/packages/packages.go
+++ b/routers/web/shared/packages/packages.go
@@ -11,9 +11,9 @@ import (
"code.gitea.io/gitea/models/db"
packages_model "code.gitea.io/gitea/models/packages"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
@@ -54,11 +54,11 @@ func setRuleEditContext(ctx *context.Context, pcr *packages_model.PackageCleanup
ctx.Data["AvailableTypes"] = packages_model.TypeList
}
-func PerformRuleAddPost(ctx *context.Context, owner *user_model.User, redirectURL string, template base.TplName) {
+func PerformRuleAddPost(ctx *context.Context, owner *user_model.User, redirectURL string, template templates.TplName) {
performRuleEditPost(ctx, owner, nil, redirectURL, template)
}
-func PerformRuleEditPost(ctx *context.Context, owner *user_model.User, redirectURL string, template base.TplName) {
+func PerformRuleEditPost(ctx *context.Context, owner *user_model.User, redirectURL string, template templates.TplName) {
pcr := getCleanupRuleByContext(ctx, owner)
if pcr == nil {
return
@@ -79,7 +79,7 @@ func PerformRuleEditPost(ctx *context.Context, owner *user_model.User, redirectU
}
}
-func performRuleEditPost(ctx *context.Context, owner *user_model.User, pcr *packages_model.PackageCleanupRule, redirectURL string, template base.TplName) {
+func performRuleEditPost(ctx *context.Context, owner *user_model.User, pcr *packages_model.PackageCleanupRule, redirectURL string, template templates.TplName) {
isEditRule := pcr != nil
if pcr == nil {
diff --git a/routers/web/user/code.go b/routers/web/user/code.go
index 785c37b124..f805f2b028 100644
--- a/routers/web/user/code.go
+++ b/routers/web/user/code.go
@@ -8,15 +8,15 @@ import (
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/base"
code_indexer "code.gitea.io/gitea/modules/indexer/code"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
"code.gitea.io/gitea/services/context"
)
const (
- tplUserCode base.TplName = "user/code"
+ tplUserCode templates.TplName = "user/code"
)
// CodeSearch render user/organization code search page
diff --git a/routers/web/user/home.go b/routers/web/user/home.go
index befa33b0c0..e118aa051e 100644
--- a/routers/web/user/home.go
+++ b/routers/web/user/home.go
@@ -31,6 +31,7 @@ import (
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/web/feed"
"code.gitea.io/gitea/routers/web/shared/issue"
@@ -46,10 +47,10 @@ import (
)
const (
- tplDashboard base.TplName = "user/dashboard/dashboard"
- tplIssues base.TplName = "user/dashboard/issues"
- tplMilestones base.TplName = "user/dashboard/milestones"
- tplProfile base.TplName = "user/profile"
+ tplDashboard templates.TplName = "user/dashboard/dashboard"
+ tplIssues templates.TplName = "user/dashboard/issues"
+ tplMilestones templates.TplName = "user/dashboard/milestones"
+ tplProfile templates.TplName = "user/profile"
)
// getDashboardContextUser finds out which context user dashboard is being viewed as .
diff --git a/routers/web/user/notification.go b/routers/web/user/notification.go
index 414cb0be49..732fac2595 100644
--- a/routers/web/user/notification.go
+++ b/routers/web/user/notification.go
@@ -22,6 +22,7 @@ import (
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/services/context"
issue_service "code.gitea.io/gitea/services/issue"
@@ -29,9 +30,9 @@ import (
)
const (
- tplNotification base.TplName = "user/notification/notification"
- tplNotificationDiv base.TplName = "user/notification/notification_div"
- tplNotificationSubscriptions base.TplName = "user/notification/notification_subscriptions"
+ tplNotification templates.TplName = "user/notification/notification"
+ tplNotificationDiv templates.TplName = "user/notification/notification_div"
+ tplNotificationSubscriptions templates.TplName = "user/notification/notification_subscriptions"
)
// GetNotificationCount is the middleware that sets the notification count in the context
diff --git a/routers/web/user/package.go b/routers/web/user/package.go
index c6f85ac734..d5aac513b6 100644
--- a/routers/web/user/package.go
+++ b/routers/web/user/package.go
@@ -14,7 +14,6 @@ import (
"code.gitea.io/gitea/models/perm"
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/httplib"
"code.gitea.io/gitea/modules/log"
@@ -24,6 +23,7 @@ import (
debian_module "code.gitea.io/gitea/modules/packages/debian"
rpm_module "code.gitea.io/gitea/modules/packages/rpm"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
packages_helper "code.gitea.io/gitea/routers/api/packages/helper"
@@ -34,10 +34,10 @@ import (
)
const (
- tplPackagesList base.TplName = "user/overview/packages"
- tplPackagesView base.TplName = "package/view"
- tplPackageVersionList base.TplName = "user/overview/package_versions"
- tplPackagesSettings base.TplName = "package/settings"
+ tplPackagesList templates.TplName = "user/overview/packages"
+ tplPackagesView templates.TplName = "package/view"
+ tplPackageVersionList templates.TplName = "user/overview/package_versions"
+ tplPackagesSettings templates.TplName = "package/settings"
)
// ListPackages displays a list of all packages of the context user
diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go
index c41030a5e2..44824de752 100644
--- a/routers/web/user/profile.go
+++ b/routers/web/user/profile.go
@@ -15,12 +15,12 @@ import (
"code.gitea.io/gitea/models/renderhelper"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/web/feed"
"code.gitea.io/gitea/routers/web/org"
@@ -30,8 +30,8 @@ import (
)
const (
- tplProfileBigAvatar base.TplName = "shared/user/profile_big_avatar"
- tplFollowUnfollow base.TplName = "org/follow_unfollow"
+ tplProfileBigAvatar templates.TplName = "shared/user/profile_big_avatar"
+ tplFollowUnfollow templates.TplName = "org/follow_unfollow"
)
// OwnerProfile render profile page for a user or a organization (aka, repo owner)
diff --git a/routers/web/user/setting/account.go b/routers/web/user/setting/account.go
index 7f2dece416..3acc3c7a54 100644
--- a/routers/web/user/setting/account.go
+++ b/routers/web/user/setting/account.go
@@ -10,13 +10,15 @@ import (
"net/http"
"time"
- "code.gitea.io/gitea/models"
+ org_model "code.gitea.io/gitea/models/organization"
+ packages_model "code.gitea.io/gitea/models/packages"
+ repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/auth/password"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/auth"
@@ -29,7 +31,7 @@ import (
)
const (
- tplSettingsAccount base.TplName = "user/settings/account"
+ tplSettingsAccount templates.TplName = "user/settings/account"
)
// Account renders change user's password, user's email and user suicide page
@@ -301,16 +303,16 @@ func DeleteAccount(ctx *context.Context) {
if err := user.DeleteUser(ctx, ctx.Doer, false); err != nil {
switch {
- case models.IsErrUserOwnRepos(err):
+ case repo_model.IsErrUserOwnRepos(err):
ctx.Flash.Error(ctx.Tr("form.still_own_repo"))
ctx.Redirect(setting.AppSubURL + "/user/settings/account")
- case models.IsErrUserHasOrgs(err):
+ case org_model.IsErrUserHasOrgs(err):
ctx.Flash.Error(ctx.Tr("form.still_has_org"))
ctx.Redirect(setting.AppSubURL + "/user/settings/account")
- case models.IsErrUserOwnPackages(err):
+ case packages_model.IsErrUserOwnPackages(err):
ctx.Flash.Error(ctx.Tr("form.still_own_packages"))
ctx.Redirect(setting.AppSubURL + "/user/settings/account")
- case models.IsErrDeleteLastAdminUser(err):
+ case user_model.IsErrDeleteLastAdminUser(err):
ctx.Flash.Error(ctx.Tr("auth.last_admin"))
ctx.Redirect(setting.AppSubURL + "/user/settings/account")
default:
diff --git a/routers/web/user/setting/applications.go b/routers/web/user/setting/applications.go
index 356c2ea5de..cf71d01dc1 100644
--- a/routers/web/user/setting/applications.go
+++ b/routers/web/user/setting/applications.go
@@ -10,15 +10,15 @@ import (
auth_model "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
)
const (
- tplSettingsApplications base.TplName = "user/settings/applications"
+ tplSettingsApplications templates.TplName = "user/settings/applications"
)
// Applications render manage access token page
diff --git a/routers/web/user/setting/block.go b/routers/web/user/setting/block.go
index d419fb321b..3756495fd2 100644
--- a/routers/web/user/setting/block.go
+++ b/routers/web/user/setting/block.go
@@ -7,14 +7,14 @@ import (
"net/http"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
"code.gitea.io/gitea/services/context"
)
const (
- tplSettingsBlockedUsers base.TplName = "user/settings/blocked_users"
+ tplSettingsBlockedUsers templates.TplName = "user/settings/blocked_users"
)
func BlockedUsers(ctx *context.Context) {
diff --git a/routers/web/user/setting/keys.go b/routers/web/user/setting/keys.go
index c492715fb5..127aed9845 100644
--- a/routers/web/user/setting/keys.go
+++ b/routers/web/user/setting/keys.go
@@ -11,8 +11,8 @@ import (
asymkey_model "code.gitea.io/gitea/models/asymkey"
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/web"
asymkey_service "code.gitea.io/gitea/services/asymkey"
"code.gitea.io/gitea/services/context"
@@ -20,7 +20,7 @@ import (
)
const (
- tplSettingsKeys base.TplName = "user/settings/keys"
+ tplSettingsKeys templates.TplName = "user/settings/keys"
)
// Keys render user's SSH/GPG public keys page
diff --git a/routers/web/user/setting/oauth2.go b/routers/web/user/setting/oauth2.go
index 1f485e06c8..d50728c24e 100644
--- a/routers/web/user/setting/oauth2.go
+++ b/routers/web/user/setting/oauth2.go
@@ -4,13 +4,13 @@
package setting
import (
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/services/context"
)
const (
- tplSettingsOAuthApplicationEdit base.TplName = "user/settings/applications_oauth2_edit"
+ tplSettingsOAuthApplicationEdit templates.TplName = "user/settings/applications_oauth2_edit"
)
func newOAuth2CommonHandlers(userID int64) *OAuth2CommonHandlers {
diff --git a/routers/web/user/setting/oauth2_common.go b/routers/web/user/setting/oauth2_common.go
index e93e9e1954..783deca710 100644
--- a/routers/web/user/setting/oauth2_common.go
+++ b/routers/web/user/setting/oauth2_common.go
@@ -8,7 +8,7 @@ import (
"net/http"
"code.gitea.io/gitea/models/auth"
- "code.gitea.io/gitea/modules/base"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
@@ -17,10 +17,10 @@ import (
)
type OAuth2CommonHandlers struct {
- OwnerID int64 // 0 for instance-wide, otherwise OrgID or UserID
- BasePathList string // the base URL for the application list page, eg: "/user/setting/applications"
- BasePathEditPrefix string // the base URL for the application edit page, will be appended with app id, eg: "/user/setting/applications/oauth2"
- TplAppEdit base.TplName // the template for the application edit page
+ OwnerID int64 // 0 for instance-wide, otherwise OrgID or UserID
+ BasePathList string // the base URL for the application list page, eg: "/user/setting/applications"
+ BasePathEditPrefix string // the base URL for the application edit page, will be appended with app id, eg: "/user/setting/applications/oauth2"
+ TplAppEdit templates.TplName // the template for the application edit page
}
func (oa *OAuth2CommonHandlers) renderEditPage(ctx *context.Context) {
diff --git a/routers/web/user/setting/packages.go b/routers/web/user/setting/packages.go
index 50521c11c0..9692cd9db0 100644
--- a/routers/web/user/setting/packages.go
+++ b/routers/web/user/setting/packages.go
@@ -8,18 +8,18 @@ import (
"strings"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
chef_module "code.gitea.io/gitea/modules/packages/chef"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
shared "code.gitea.io/gitea/routers/web/shared/packages"
"code.gitea.io/gitea/services/context"
)
const (
- tplSettingsPackages base.TplName = "user/settings/packages"
- tplSettingsPackagesRuleEdit base.TplName = "user/settings/packages_cleanup_rules_edit"
- tplSettingsPackagesRulePreview base.TplName = "user/settings/packages_cleanup_rules_preview"
+ tplSettingsPackages templates.TplName = "user/settings/packages"
+ tplSettingsPackagesRuleEdit templates.TplName = "user/settings/packages_cleanup_rules_edit"
+ tplSettingsPackagesRulePreview templates.TplName = "user/settings/packages_cleanup_rules_preview"
)
func Packages(ctx *context.Context) {
diff --git a/routers/web/user/setting/profile.go b/routers/web/user/setting/profile.go
index 3b051c9b5f..4b3c214096 100644
--- a/routers/web/user/setting/profile.go
+++ b/routers/web/user/setting/profile.go
@@ -19,10 +19,10 @@ import (
"code.gitea.io/gitea/models/organization"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/translation"
"code.gitea.io/gitea/modules/typesniffer"
"code.gitea.io/gitea/modules/util"
@@ -35,10 +35,10 @@ import (
)
const (
- tplSettingsProfile base.TplName = "user/settings/profile"
- tplSettingsAppearance base.TplName = "user/settings/appearance"
- tplSettingsOrganization base.TplName = "user/settings/organization"
- tplSettingsRepositories base.TplName = "user/settings/repos"
+ tplSettingsProfile templates.TplName = "user/settings/profile"
+ tplSettingsAppearance templates.TplName = "user/settings/appearance"
+ tplSettingsOrganization templates.TplName = "user/settings/organization"
+ tplSettingsRepositories templates.TplName = "user/settings/repos"
)
// Profile render user's profile page
diff --git a/routers/web/user/setting/security/security.go b/routers/web/user/setting/security/security.go
index b44cb4dd49..38d1910e2d 100644
--- a/routers/web/user/setting/security/security.go
+++ b/routers/web/user/setting/security/security.go
@@ -11,16 +11,16 @@ import (
auth_model "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/services/auth/source/oauth2"
"code.gitea.io/gitea/services/context"
)
const (
- tplSettingsSecurity base.TplName = "user/settings/security/security"
- tplSettingsTwofaEnroll base.TplName = "user/settings/security/twofa_enroll"
+ tplSettingsSecurity templates.TplName = "user/settings/security/security"
+ tplSettingsTwofaEnroll templates.TplName = "user/settings/security/twofa_enroll"
)
// Security render change user's password page and 2FA
diff --git a/routers/web/user/setting/webhooks.go b/routers/web/user/setting/webhooks.go
index 3732ca27c0..ca7c7ec1ac 100644
--- a/routers/web/user/setting/webhooks.go
+++ b/routers/web/user/setting/webhooks.go
@@ -9,13 +9,13 @@ import (
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/models/webhook"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/services/context"
)
const (
- tplSettingsHooks base.TplName = "user/settings/hooks"
+ tplSettingsHooks templates.TplName = "user/settings/hooks"
)
// Webhooks render webhook list page
diff --git a/routers/web/web.go b/routers/web/web.go
index 72ee47bb4c..4f2a8b72c0 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -4,7 +4,6 @@
package web
import (
- gocontext "context"
"net/http"
"strings"
@@ -463,7 +462,7 @@ func registerRoutes(m *web.Router) {
m.Combo("/{runnerid}").Get(repo_setting.RunnersEdit).
Post(web.Bind(forms.EditRunnerForm{}), repo_setting.RunnersEditPost)
m.Post("/{runnerid}/delete", repo_setting.RunnerDeletePost)
- m.Get("/reset_registration_token", repo_setting.ResetRunnerRegistrationToken)
+ m.Post("/reset_registration_token", repo_setting.ResetRunnerRegistrationToken)
})
}
@@ -1020,14 +1019,15 @@ func registerRoutes(m *web.Router) {
m.Get("/new", org.RenderNewProject)
m.Post("/new", web.Bind(forms.CreateProjectForm{}), org.NewProjectPost)
m.Group("/{id}", func() {
- m.Post("", web.Bind(forms.EditProjectColumnForm{}), org.AddColumnToProjectPost)
- m.Post("/move", project.MoveColumns)
m.Post("/delete", org.DeleteProject)
m.Get("/edit", org.RenderEditProject)
m.Post("/edit", web.Bind(forms.CreateProjectForm{}), org.EditProjectPost)
m.Post("/{action:open|close}", org.ChangeProjectStatus)
+ // TODO: improper name. Others are "delete project", "edit project", but this one is "move columns"
+ m.Post("/move", project.MoveColumns)
+ m.Post("/columns/new", web.Bind(forms.EditProjectColumnForm{}), org.AddColumnToProjectPost)
m.Group("/{columnID}", func() {
m.Put("", web.Bind(forms.EditProjectColumnForm{}), org.EditProjectColumn)
m.Delete("", org.DeleteProjectColumn)
@@ -1387,14 +1387,15 @@ func registerRoutes(m *web.Router) {
m.Get("/new", repo.RenderNewProject)
m.Post("/new", web.Bind(forms.CreateProjectForm{}), repo.NewProjectPost)
m.Group("/{id}", func() {
- m.Post("", web.Bind(forms.EditProjectColumnForm{}), repo.AddColumnToProjectPost)
- m.Post("/move", project.MoveColumns)
m.Post("/delete", repo.DeleteProject)
m.Get("/edit", repo.RenderEditProject)
m.Post("/edit", web.Bind(forms.CreateProjectForm{}), repo.EditProjectPost)
m.Post("/{action:open|close}", repo.ChangeProjectStatus)
+ // TODO: improper name. Others are "delete project", "edit project", but this one is "move columns"
+ m.Post("/move", project.MoveColumns)
+ m.Post("/columns/new", web.Bind(forms.EditProjectColumnForm{}), repo.AddColumnToProjectPost)
m.Group("/{columnID}", func() {
m.Put("", web.Bind(forms.EditProjectColumnForm{}), repo.EditProjectColumn)
m.Delete("", repo.DeleteProjectColumn)
@@ -1519,24 +1520,23 @@ func registerRoutes(m *web.Router) {
m.Group("/blob_excerpt", func() {
m.Get("/{sha}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.ExcerptBlob)
- }, func(ctx *context.Context) gocontext.CancelFunc {
+ }, func(ctx *context.Context) {
// FIXME: refactor this function, use separate routes for wiki/code
if ctx.FormBool("wiki") {
ctx.Data["PageIsWiki"] = true
repo.MustEnableWiki(ctx)
- return nil
+ return
}
if ctx.Written() {
- return nil
+ return
}
- cancel := context.RepoRef()(ctx)
+ context.RepoRef()(ctx)
if ctx.Written() {
- return cancel
+ return
}
repo.MustBeNotEmpty(ctx)
- return cancel
})
m.Group("/media", func() {
diff --git a/services/actions/init.go b/services/actions/init.go
index 0f49cb6297..7136da05ed 100644
--- a/services/actions/init.go
+++ b/services/actions/init.go
@@ -4,23 +4,68 @@
package actions
import (
+ "context"
+ "errors"
+ "fmt"
+ "os"
+ "strings"
+
+ actions_model "code.gitea.io/gitea/models/actions"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/queue"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/util"
notify_service "code.gitea.io/gitea/services/notify"
)
-func Init() {
+func initGlobalRunnerToken(ctx context.Context) error {
+ // use the same env name as the runner, for consistency
+ token := os.Getenv("GITEA_RUNNER_REGISTRATION_TOKEN")
+ tokenFile := os.Getenv("GITEA_RUNNER_REGISTRATION_TOKEN_FILE")
+ if token != "" && tokenFile != "" {
+ return errors.New("both GITEA_RUNNER_REGISTRATION_TOKEN and GITEA_RUNNER_REGISTRATION_TOKEN_FILE are set, only one can be used")
+ }
+ if tokenFile != "" {
+ file, err := os.ReadFile(tokenFile)
+ if err != nil {
+ return fmt.Errorf("unable to read GITEA_RUNNER_REGISTRATION_TOKEN_FILE: %w", err)
+ }
+ token = strings.TrimSpace(string(file))
+ }
+ if token == "" {
+ return nil
+ }
+
+ if len(token) < 32 {
+ return errors.New("GITEA_RUNNER_REGISTRATION_TOKEN must be at least 32 random characters")
+ }
+
+ existing, err := actions_model.GetRunnerToken(ctx, token)
+ if err != nil && !errors.Is(err, util.ErrNotExist) {
+ return fmt.Errorf("unable to check existing token: %w", err)
+ }
+ if existing != nil {
+ if !existing.IsActive {
+ log.Warn("The token defined by GITEA_RUNNER_REGISTRATION_TOKEN is already invalidated, please use the latest one from web UI")
+ }
+ return nil
+ }
+ _, err = actions_model.NewRunnerTokenWithValue(ctx, 0, 0, token)
+ return err
+}
+
+func Init(ctx context.Context) error {
if !setting.Actions.Enabled {
- return
+ return nil
}
jobEmitterQueue = queue.CreateUniqueQueue(graceful.GetManager().ShutdownContext(), "actions_ready_job", jobEmitterQueueHandler)
if jobEmitterQueue == nil {
- log.Fatal("Unable to create actions_ready_job queue")
+ return errors.New("unable to create actions_ready_job queue")
}
go graceful.GetManager().RunWithCancel(jobEmitterQueue)
notify_service.RegisterNotifier(NewNotifier())
+ return initGlobalRunnerToken(ctx)
}
diff --git a/services/actions/init_test.go b/services/actions/init_test.go
new file mode 100644
index 0000000000..59c321ccd7
--- /dev/null
+++ b/services/actions/init_test.go
@@ -0,0 +1,80 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package actions
+
+import (
+ "os"
+ "testing"
+
+ actions_model "code.gitea.io/gitea/models/actions"
+ "code.gitea.io/gitea/models/db"
+ "code.gitea.io/gitea/models/unittest"
+ "code.gitea.io/gitea/modules/util"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestMain(m *testing.M) {
+ unittest.MainTest(m, &unittest.TestOptions{
+ FixtureFiles: []string{"action_runner_token.yml"},
+ })
+ os.Exit(m.Run())
+}
+
+func TestInitToken(t *testing.T) {
+ assert.NoError(t, unittest.PrepareTestDatabase())
+
+ t.Run("NoToken", func(t *testing.T) {
+ _, _ = db.Exec(db.DefaultContext, "DELETE FROM action_runner_token")
+ t.Setenv("GITEA_RUNNER_REGISTRATION_TOKEN", "")
+ t.Setenv("GITEA_RUNNER_REGISTRATION_TOKEN_FILE", "")
+ err := initGlobalRunnerToken(db.DefaultContext)
+ require.NoError(t, err)
+ notEmpty, err := db.IsTableNotEmpty(&actions_model.ActionRunnerToken{})
+ require.NoError(t, err)
+ assert.False(t, notEmpty)
+ })
+
+ t.Run("EnvToken", func(t *testing.T) {
+ tokenValue, _ := util.CryptoRandomString(32)
+ t.Setenv("GITEA_RUNNER_REGISTRATION_TOKEN", tokenValue)
+ t.Setenv("GITEA_RUNNER_REGISTRATION_TOKEN_FILE", "")
+ err := initGlobalRunnerToken(db.DefaultContext)
+ require.NoError(t, err)
+ token := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunnerToken{Token: tokenValue})
+ assert.True(t, token.IsActive)
+
+ // init with the same token again, should not create a new token
+ err = initGlobalRunnerToken(db.DefaultContext)
+ require.NoError(t, err)
+ token2 := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunnerToken{Token: tokenValue})
+ assert.Equal(t, token.ID, token2.ID)
+ assert.True(t, token.IsActive)
+ })
+
+ t.Run("EnvFileToken", func(t *testing.T) {
+ tokenValue, _ := util.CryptoRandomString(32)
+ f := t.TempDir() + "/token"
+ _ = os.WriteFile(f, []byte(tokenValue), 0o644)
+ t.Setenv("GITEA_RUNNER_REGISTRATION_TOKEN", "")
+ t.Setenv("GITEA_RUNNER_REGISTRATION_TOKEN_FILE", f)
+ err := initGlobalRunnerToken(db.DefaultContext)
+ require.NoError(t, err)
+ token := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunnerToken{Token: tokenValue})
+ assert.True(t, token.IsActive)
+
+ // if the env token is invalidated by another new token, then it shouldn't be active anymore
+ _, err = actions_model.NewRunnerToken(db.DefaultContext, 0, 0)
+ require.NoError(t, err)
+ token = unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunnerToken{Token: tokenValue})
+ assert.False(t, token.IsActive)
+ })
+
+ t.Run("InvalidToken", func(t *testing.T) {
+ t.Setenv("GITEA_RUNNER_REGISTRATION_TOKEN", "abc")
+ err := initGlobalRunnerToken(db.DefaultContext)
+ assert.ErrorContains(t, err, "must be at least")
+ })
+}
diff --git a/services/auth/interface.go b/services/auth/interface.go
index ece28af12d..275b4dd56c 100644
--- a/services/auth/interface.go
+++ b/services/auth/interface.go
@@ -8,12 +8,11 @@ import (
"net/http"
user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/reqctx"
"code.gitea.io/gitea/modules/session"
- "code.gitea.io/gitea/modules/web/middleware"
)
-// DataStore represents a data store
-type DataStore middleware.ContextDataStore
+type DataStore = reqctx.ContextDataProvider
// SessionStore represents a session store
type SessionStore session.Store
diff --git a/services/auth/oauth2_test.go b/services/auth/oauth2_test.go
index b706847e8e..0d9e793cf3 100644
--- a/services/auth/oauth2_test.go
+++ b/services/auth/oauth2_test.go
@@ -9,7 +9,7 @@ import (
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/web/middleware"
+ "code.gitea.io/gitea/modules/reqctx"
"code.gitea.io/gitea/services/actions"
"github.com/stretchr/testify/assert"
@@ -23,7 +23,7 @@ func TestUserIDFromToken(t *testing.T) {
token, err := actions.CreateAuthorizationToken(RunningTaskID, 1, 2)
assert.NoError(t, err)
- ds := make(middleware.ContextData)
+ ds := make(reqctx.ContextData)
o := OAuth2{}
uid := o.userIDFromToken(context.Background(), token, ds)
diff --git a/services/auth/sspi.go b/services/auth/sspi.go
index 7f8a03a4c6..8ac83dcb04 100644
--- a/services/auth/sspi.go
+++ b/services/auth/sspi.go
@@ -13,10 +13,10 @@ import (
"code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/web/middleware"
"code.gitea.io/gitea/services/auth/source/sspi"
gitea_context "code.gitea.io/gitea/services/context"
@@ -25,7 +25,7 @@ import (
)
const (
- tplSignIn base.TplName = "user/auth/signin"
+ tplSignIn templates.TplName = "user/auth/signin"
)
type SSPIAuth interface {
diff --git a/services/context/api.go b/services/context/api.go
index b45e80a329..7b604c5ea1 100644
--- a/services/context/api.go
+++ b/services/context/api.go
@@ -5,7 +5,6 @@
package context
import (
- "context"
"fmt"
"net/http"
"net/url"
@@ -212,17 +211,15 @@ func (ctx *APIContext) SetLinkHeader(total, pageSize int) {
func APIContexter() func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
- base, baseCleanUp := NewBaseContext(w, req)
+ base := NewBaseContext(w, req)
ctx := &APIContext{
Base: base,
Cache: cache.GetCache(),
Repo: &Repository{PullRequest: &PullRequest{}},
Org: &APIOrganization{},
}
- defer baseCleanUp()
- ctx.Base.AppendContextValue(apiContextKey, ctx)
- ctx.Base.AppendContextValueFunc(gitrepo.RepositoryContextKey, func() any { return ctx.Repo.GitRepo })
+ ctx.SetContextValue(apiContextKey, ctx)
// If request sends files, parse them here otherwise the Query() can't be parsed and the CsrfToken will be invalid.
if ctx.Req.Method == "POST" && strings.Contains(ctx.Req.Header.Get("Content-Type"), "multipart/form-data") {
@@ -267,31 +264,22 @@ func (ctx *APIContext) NotFound(objs ...any) {
// ReferencesGitRepo injects the GitRepo into the Context
// you can optional skip the IsEmpty check
-func ReferencesGitRepo(allowEmpty ...bool) func(ctx *APIContext) (cancel context.CancelFunc) {
- return func(ctx *APIContext) (cancel context.CancelFunc) {
+func ReferencesGitRepo(allowEmpty ...bool) func(ctx *APIContext) {
+ return func(ctx *APIContext) {
// Empty repository does not have reference information.
if ctx.Repo.Repository.IsEmpty && !(len(allowEmpty) != 0 && allowEmpty[0]) {
- return nil
+ return
}
// For API calls.
if ctx.Repo.GitRepo == nil {
- gitRepo, err := gitrepo.OpenRepository(ctx, ctx.Repo.Repository)
+ var err error
+ ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx, ctx.Repo.Repository)
if err != nil {
ctx.Error(http.StatusInternalServerError, fmt.Sprintf("Open Repository %v failed", ctx.Repo.Repository.FullName()), err)
- return cancel
- }
- ctx.Repo.GitRepo = gitRepo
- // We opened it, we should close it
- return func() {
- // If it's been set to nil then assume someone else has closed it.
- if ctx.Repo.GitRepo != nil {
- _ = ctx.Repo.GitRepo.Close()
- }
+ return
}
}
-
- return cancel
}
}
diff --git a/services/context/base.go b/services/context/base.go
index d627095584..cb89cdea02 100644
--- a/services/context/base.go
+++ b/services/context/base.go
@@ -12,12 +12,12 @@ import (
"net/url"
"strconv"
"strings"
- "time"
"code.gitea.io/gitea/modules/httplib"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
+ "code.gitea.io/gitea/modules/reqctx"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/translation"
"code.gitea.io/gitea/modules/web/middleware"
@@ -25,65 +25,25 @@ import (
"github.com/go-chi/chi/v5"
)
-type contextValuePair struct {
- key any
- valueFn func() any
-}
-
type BaseContextKeyType struct{}
var BaseContextKey BaseContextKeyType
type Base struct {
- originCtx context.Context
- contextValues []contextValuePair
+ context.Context
+ reqctx.RequestDataStore
Resp ResponseWriter
Req *http.Request
// Data is prepared by ContextDataStore middleware, this field only refers to the pre-created/prepared ContextData.
// Although it's mainly used for MVC templates, sometimes it's also used to pass data between middlewares/handler
- Data middleware.ContextData
+ Data reqctx.ContextData
// Locale is mainly for Web context, although the API context also uses it in some cases: message response, form validation
Locale translation.Locale
}
-func (b *Base) Deadline() (deadline time.Time, ok bool) {
- return b.originCtx.Deadline()
-}
-
-func (b *Base) Done() <-chan struct{} {
- return b.originCtx.Done()
-}
-
-func (b *Base) Err() error {
- return b.originCtx.Err()
-}
-
-func (b *Base) Value(key any) any {
- for _, pair := range b.contextValues {
- if pair.key == key {
- return pair.valueFn()
- }
- }
- return b.originCtx.Value(key)
-}
-
-func (b *Base) AppendContextValueFunc(key any, valueFn func() any) any {
- b.contextValues = append(b.contextValues, contextValuePair{key, valueFn})
- return b
-}
-
-func (b *Base) AppendContextValue(key, value any) any {
- b.contextValues = append(b.contextValues, contextValuePair{key, func() any { return value }})
- return b
-}
-
-func (b *Base) GetData() middleware.ContextData {
- return b.Data
-}
-
// AppendAccessControlExposeHeaders append headers by name to "Access-Control-Expose-Headers" header
func (b *Base) AppendAccessControlExposeHeaders(names ...string) {
val := b.RespHeader().Get("Access-Control-Expose-Headers")
@@ -295,13 +255,6 @@ func (b *Base) ServeContent(r io.ReadSeeker, opts *ServeHeaderOptions) {
http.ServeContent(b.Resp, b.Req, opts.Filename, opts.LastModified, r)
}
-// Close frees all resources hold by Context
-func (b *Base) cleanUp() {
- if b.Req != nil && b.Req.MultipartForm != nil {
- _ = b.Req.MultipartForm.RemoveAll() // remove the temp files buffered to tmp directory
- }
-}
-
func (b *Base) Tr(msg string, args ...any) template.HTML {
return b.Locale.Tr(msg, args...)
}
@@ -310,17 +263,28 @@ func (b *Base) TrN(cnt any, key1, keyN string, args ...any) template.HTML {
return b.Locale.TrN(cnt, key1, keyN, args...)
}
-func NewBaseContext(resp http.ResponseWriter, req *http.Request) (b *Base, closeFunc func()) {
- b = &Base{
- originCtx: req.Context(),
- Req: req,
- Resp: WrapResponseWriter(resp),
- Locale: middleware.Locale(resp, req),
- Data: middleware.GetContextData(req.Context()),
+func NewBaseContext(resp http.ResponseWriter, req *http.Request) *Base {
+ ds := reqctx.GetRequestDataStore(req.Context())
+ b := &Base{
+ Context: req.Context(),
+ RequestDataStore: ds,
+ Req: req,
+ Resp: WrapResponseWriter(resp),
+ Locale: middleware.Locale(resp, req),
+ Data: ds.GetData(),
}
b.Req = b.Req.WithContext(b)
- b.AppendContextValue(BaseContextKey, b)
- b.AppendContextValue(translation.ContextKey, b.Locale)
- b.AppendContextValue(httplib.RequestContextKey, b.Req)
- return b, b.cleanUp
+ ds.SetContextValue(BaseContextKey, b)
+ ds.SetContextValue(translation.ContextKey, b.Locale)
+ ds.SetContextValue(httplib.RequestContextKey, b.Req)
+ return b
+}
+
+func NewBaseContextForTest(resp http.ResponseWriter, req *http.Request) *Base {
+ if !setting.IsInTesting {
+ panic("This function is only for testing")
+ }
+ ctx := reqctx.NewRequestContextForTest(req.Context())
+ *req = *req.WithContext(ctx)
+ return NewBaseContext(resp, req)
}
diff --git a/services/context/base_test.go b/services/context/base_test.go
index 823f20e00b..b936b76f58 100644
--- a/services/context/base_test.go
+++ b/services/context/base_test.go
@@ -14,6 +14,7 @@ import (
)
func TestRedirect(t *testing.T) {
+ setting.IsInTesting = true
req, _ := http.NewRequest("GET", "/", nil)
cases := []struct {
@@ -28,10 +29,9 @@ func TestRedirect(t *testing.T) {
}
for _, c := range cases {
resp := httptest.NewRecorder()
- b, cleanup := NewBaseContext(resp, req)
+ b := NewBaseContextForTest(resp, req)
resp.Header().Add("Set-Cookie", (&http.Cookie{Name: setting.SessionConfig.CookieName, Value: "dummy"}).String())
b.Redirect(c.url)
- cleanup()
has := resp.Header().Get("Set-Cookie") == "i_like_gitea=dummy"
assert.Equal(t, c.keep, has, "url = %q", c.url)
}
@@ -39,9 +39,8 @@ func TestRedirect(t *testing.T) {
req, _ = http.NewRequest("GET", "/", nil)
resp := httptest.NewRecorder()
req.Header.Add("HX-Request", "true")
- b, cleanup := NewBaseContext(resp, req)
+ b := NewBaseContextForTest(resp, req)
b.Redirect("/other")
- cleanup()
assert.Equal(t, "/other", resp.Header().Get("HX-Redirect"))
assert.Equal(t, http.StatusNoContent, resp.Code)
}
diff --git a/services/context/captcha.go b/services/context/captcha.go
index 41afe0e7d2..9272e7a65a 100644
--- a/services/context/captcha.go
+++ b/services/context/captcha.go
@@ -7,13 +7,13 @@ import (
"fmt"
"sync"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/cache"
"code.gitea.io/gitea/modules/hcaptcha"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/mcaptcha"
"code.gitea.io/gitea/modules/recaptcha"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/turnstile"
"gitea.com/go-chi/captcha"
@@ -60,7 +60,7 @@ const (
// VerifyCaptcha verifies Captcha data
// No-op if captchas are not enabled
-func VerifyCaptcha(ctx *Context, tpl base.TplName, form any) {
+func VerifyCaptcha(ctx *Context, tpl templates.TplName, form any) {
if !setting.Service.EnableCaptcha {
return
}
diff --git a/services/context/context.go b/services/context/context.go
index 812a8c27ee..6715c5663d 100644
--- a/services/context/context.go
+++ b/services/context/context.go
@@ -18,7 +18,6 @@ import (
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/cache"
- "code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/httpcache"
"code.gitea.io/gitea/modules/session"
"code.gitea.io/gitea/modules/setting"
@@ -32,7 +31,7 @@ import (
// Render represents a template render
type Render interface {
TemplateLookup(tmpl string, templateCtx context.Context) (templates.TemplateExecutor, error)
- HTML(w io.Writer, status int, name string, data any, templateCtx context.Context) error
+ HTML(w io.Writer, status int, name templates.TplName, data any, templateCtx context.Context) error
}
// Context represents context of a request.
@@ -153,14 +152,9 @@ func Contexter() func(next http.Handler) http.Handler {
}
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
- base, baseCleanUp := NewBaseContext(resp, req)
- defer baseCleanUp()
+ base := NewBaseContext(resp, req)
ctx := NewWebContext(base, rnd, session.GetContextSession(req))
-
ctx.Data.MergeFrom(middleware.CommonTemplateContextData())
- if setting.IsProd && !setting.IsInTesting {
- ctx.Data["Context"] = ctx // TODO: use "ctx" in template and remove this
- }
ctx.Data["CurrentURL"] = setting.AppSubURL + req.URL.RequestURI()
ctx.Data["Link"] = ctx.Link
@@ -168,9 +162,7 @@ func Contexter() func(next http.Handler) http.Handler {
ctx.PageData = map[string]any{}
ctx.Data["PageData"] = ctx.PageData
- ctx.Base.AppendContextValue(WebContextKey, ctx)
- ctx.Base.AppendContextValueFunc(gitrepo.RepositoryContextKey, func() any { return ctx.Repo.GitRepo })
-
+ ctx.Base.SetContextValue(WebContextKey, ctx)
ctx.Csrf = NewCSRFProtector(csrfOpts)
// Get the last flash message from cookie
diff --git a/services/context/context_response.go b/services/context/context_response.go
index c43a649b49..c7044791eb 100644
--- a/services/context/context_response.go
+++ b/services/context/context_response.go
@@ -17,7 +17,6 @@ import (
"time"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/httplib"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
@@ -63,10 +62,10 @@ func (ctx *Context) RedirectToCurrentSite(location ...string) {
ctx.Redirect(setting.AppSubURL + "/")
}
-const tplStatus500 base.TplName = "status/500"
+const tplStatus500 templates.TplName = "status/500"
// HTML calls Context.HTML and renders the template to HTTP response
-func (ctx *Context) HTML(status int, name base.TplName) {
+func (ctx *Context) HTML(status int, name templates.TplName) {
log.Debug("Template: %s", name)
tmplStartTime := time.Now()
@@ -77,7 +76,7 @@ func (ctx *Context) HTML(status int, name base.TplName) {
return strconv.FormatInt(time.Since(tmplStartTime).Nanoseconds()/1e6, 10) + "ms"
}
- err := ctx.Render.HTML(ctx.Resp, status, string(name), ctx.Data, ctx.TemplateContext)
+ err := ctx.Render.HTML(ctx.Resp, status, name, ctx.Data, ctx.TemplateContext)
if err == nil || errors.Is(err, syscall.EPIPE) {
return
}
@@ -94,7 +93,7 @@ func (ctx *Context) HTML(status int, name base.TplName) {
// JSONTemplate renders the template as JSON response
// keep in mind that the template is processed in HTML context, so JSON-things should be handled carefully, eg: by JSEscape
-func (ctx *Context) JSONTemplate(tmpl base.TplName) {
+func (ctx *Context) JSONTemplate(tmpl templates.TplName) {
t, err := ctx.Render.TemplateLookup(string(tmpl), nil)
if err != nil {
ctx.ServerError("unable to find template", err)
@@ -107,14 +106,14 @@ func (ctx *Context) JSONTemplate(tmpl base.TplName) {
}
// RenderToHTML renders the template content to a HTML string
-func (ctx *Context) RenderToHTML(name base.TplName, data map[string]any) (template.HTML, error) {
+func (ctx *Context) RenderToHTML(name templates.TplName, data any) (template.HTML, error) {
var buf strings.Builder
- err := ctx.Render.HTML(&buf, 0, string(name), data, ctx.TemplateContext)
+ err := ctx.Render.HTML(&buf, 0, name, data, ctx.TemplateContext)
return template.HTML(buf.String()), err
}
// RenderWithErr used for page has form validation but need to prompt error to users.
-func (ctx *Context) RenderWithErr(msg any, tpl base.TplName, form any) {
+func (ctx *Context) RenderWithErr(msg any, tpl templates.TplName, form any) {
if form != nil {
middleware.AssignForm(form, ctx.Data)
}
@@ -151,7 +150,7 @@ func (ctx *Context) notFoundInternal(logMsg string, logErr error) {
ctx.Data["IsRepo"] = ctx.Repo.Repository != nil
ctx.Data["Title"] = "Page Not Found"
- ctx.HTML(http.StatusNotFound, base.TplName("status/404"))
+ ctx.HTML(http.StatusNotFound, templates.TplName("status/404"))
}
// ServerError displays a 500 (Internal Server Error) page and prints the given error, if any.
diff --git a/services/context/context_test.go b/services/context/context_test.go
index 984593398d..54044644f0 100644
--- a/services/context/context_test.go
+++ b/services/context/context_test.go
@@ -26,6 +26,7 @@ func TestRemoveSessionCookieHeader(t *testing.T) {
}
func TestRedirectToCurrentSite(t *testing.T) {
+ setting.IsInTesting = true
defer test.MockVariableValue(&setting.AppURL, "http://localhost:3000/sub/")()
defer test.MockVariableValue(&setting.AppSubURL, "/sub")()
cases := []struct {
@@ -40,8 +41,7 @@ func TestRedirectToCurrentSite(t *testing.T) {
t.Run(c.location, func(t *testing.T) {
req := &http.Request{URL: &url.URL{Path: "/"}}
resp := httptest.NewRecorder()
- base, baseCleanUp := NewBaseContext(resp, req)
- defer baseCleanUp()
+ base := NewBaseContextForTest(resp, req)
ctx := NewWebContext(base, nil, nil)
ctx.RedirectToCurrentSite(c.location)
redirect := test.RedirectURL(resp)
diff --git a/services/context/package.go b/services/context/package.go
index 271b61e99c..e98e01acbb 100644
--- a/services/context/package.go
+++ b/services/context/package.go
@@ -153,12 +153,10 @@ func PackageContexter() func(next http.Handler) http.Handler {
renderer := templates.HTMLRenderer()
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
- base, baseCleanUp := NewBaseContext(resp, req)
- defer baseCleanUp()
-
+ base := NewBaseContext(resp, req)
// it is still needed when rendering 500 page in a package handler
ctx := NewWebContext(base, renderer, nil)
- ctx.Base.AppendContextValue(WebContextKey, ctx)
+ ctx.SetContextValue(WebContextKey, ctx)
next.ServeHTTP(ctx.Resp, ctx.Req)
})
}
diff --git a/services/context/private.go b/services/context/private.go
index 8b41949f60..51857da8fe 100644
--- a/services/context/private.go
+++ b/services/context/private.go
@@ -64,11 +64,9 @@ func GetPrivateContext(req *http.Request) *PrivateContext {
func PrivateContexter() func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
- base, baseCleanUp := NewBaseContext(w, req)
+ base := NewBaseContext(w, req)
ctx := &PrivateContext{Base: base}
- defer baseCleanUp()
- ctx.Base.AppendContextValue(privateContextKey, ctx)
-
+ ctx.SetContextValue(privateContextKey, ctx)
next.ServeHTTP(ctx.Resp, ctx.Req)
})
}
@@ -78,8 +76,15 @@ func PrivateContexter() func(http.Handler) http.Handler {
// This function should be used when there is a need for work to continue even if the request has been cancelled.
// Primarily this affects hook/post-receive and hook/proc-receive both of which need to continue working even if
// the underlying request has timed out from the ssh/http push
-func OverrideContext(ctx *PrivateContext) (cancel context.CancelFunc) {
- // We now need to override the request context as the base for our work because even if the request is cancelled we have to continue this work
- ctx.Override, _, cancel = process.GetManager().AddTypedContext(graceful.GetManager().HammerContext(), fmt.Sprintf("PrivateContext: %s", ctx.Req.RequestURI), process.RequestProcessType, true)
- return cancel
+func OverrideContext() func(http.Handler) http.Handler {
+ return func(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
+ // We now need to override the request context as the base for our work because even if the request is cancelled we have to continue this work
+ ctx := GetPrivateContext(req)
+ var finished func()
+ ctx.Override, _, finished = process.GetManager().AddTypedContext(graceful.GetManager().HammerContext(), fmt.Sprintf("PrivateContext: %s", ctx.Req.RequestURI), process.RequestProcessType, true)
+ defer finished()
+ next.ServeHTTP(ctx.Resp, ctx.Req)
+ })
+ }
}
diff --git a/services/context/repo.go b/services/context/repo.go
index e96916ca42..db5308415e 100644
--- a/services/context/repo.go
+++ b/services/context/repo.go
@@ -397,11 +397,13 @@ func repoAssignment(ctx *Context, repo *repo_model.Repository) {
}
// RepoAssignment returns a middleware to handle repository assignment
-func RepoAssignment(ctx *Context) context.CancelFunc {
+func RepoAssignment(ctx *Context) {
if _, repoAssignmentOnce := ctx.Data["repoAssignmentExecuted"]; repoAssignmentOnce {
// FIXME: it should panic in dev/test modes to have a clear behavior
- log.Trace("RepoAssignment was exec already, skipping second call ...")
- return nil
+ if !setting.IsProd || setting.IsInTesting {
+ panic("RepoAssignment should not be executed twice")
+ }
+ return
}
ctx.Data["repoAssignmentExecuted"] = true
@@ -429,7 +431,7 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
// https://github.com/golang/go/issues/19760
if ctx.FormString("go-get") == "1" {
EarlyResponseForGoGetMeta(ctx)
- return nil
+ return
}
if redirectUserID, err := user_model.LookupUserRedirect(ctx, userName); err == nil {
@@ -442,7 +444,7 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
} else {
ctx.ServerError("GetUserByName", err)
}
- return nil
+ return
}
}
ctx.Repo.Owner = owner
@@ -467,7 +469,7 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
redirectPath += "?" + ctx.Req.URL.RawQuery
}
ctx.Redirect(path.Join(setting.AppSubURL, redirectPath))
- return nil
+ return
}
// Get repository.
@@ -480,7 +482,7 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
} else if repo_model.IsErrRedirectNotExist(err) {
if ctx.FormString("go-get") == "1" {
EarlyResponseForGoGetMeta(ctx)
- return nil
+ return
}
ctx.NotFound("GetRepositoryByName", nil)
} else {
@@ -489,13 +491,13 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
} else {
ctx.ServerError("GetRepositoryByName", err)
}
- return nil
+ return
}
repo.Owner = owner
repoAssignment(ctx, repo)
if ctx.Written() {
- return nil
+ return
}
ctx.Repo.RepoLink = repo.Link()
@@ -520,7 +522,7 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
})
if err != nil {
ctx.ServerError("GetReleaseCountByRepoID", err)
- return nil
+ return
}
ctx.Data["NumReleases"], err = db.Count[repo_model.Release](ctx, repo_model.FindReleasesOptions{
// only show draft releases for users who can write, read-only users shouldn't see draft releases.
@@ -529,7 +531,7 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
})
if err != nil {
ctx.ServerError("GetReleaseCountByRepoID", err)
- return nil
+ return
}
ctx.Data["Title"] = owner.Name + "/" + repo.Name
@@ -546,14 +548,14 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
canSignedUserFork, err := repo_module.CanUserForkRepo(ctx, ctx.Doer, ctx.Repo.Repository)
if err != nil {
ctx.ServerError("CanUserForkRepo", err)
- return nil
+ return
}
ctx.Data["CanSignedUserFork"] = canSignedUserFork
userAndOrgForks, err := repo_model.GetForksByUserAndOrgs(ctx, ctx.Doer, ctx.Repo.Repository)
if err != nil {
ctx.ServerError("GetForksByUserAndOrgs", err)
- return nil
+ return
}
ctx.Data["UserAndOrgForks"] = userAndOrgForks
@@ -587,14 +589,14 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
if repo.IsFork {
RetrieveBaseRepo(ctx, repo)
if ctx.Written() {
- return nil
+ return
}
}
if repo.IsGenerated() {
RetrieveTemplateRepo(ctx, repo)
if ctx.Written() {
- return nil
+ return
}
}
@@ -609,10 +611,18 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
if !isHomeOrSettings {
ctx.Redirect(ctx.Repo.RepoLink)
}
- return nil
+ return
}
- gitRepo, err := gitrepo.OpenRepository(ctx, repo)
+ if ctx.Repo.GitRepo != nil {
+ if !setting.IsProd || setting.IsInTesting {
+ panic("RepoAssignment: GitRepo should be nil")
+ }
+ _ = ctx.Repo.GitRepo.Close()
+ ctx.Repo.GitRepo = nil
+ }
+
+ ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx, repo)
if err != nil {
if strings.Contains(err.Error(), "repository does not exist") || strings.Contains(err.Error(), "no such file or directory") {
log.Error("Repository %-v has a broken repository on the file system: %s Error: %v", ctx.Repo.Repository, ctx.Repo.Repository.RepoPath(), err)
@@ -622,28 +632,16 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
if !isHomeOrSettings {
ctx.Redirect(ctx.Repo.RepoLink)
}
- return nil
+ return
}
ctx.ServerError("RepoAssignment Invalid repo "+repo.FullName(), err)
- return nil
- }
- if ctx.Repo.GitRepo != nil {
- ctx.Repo.GitRepo.Close()
- }
- ctx.Repo.GitRepo = gitRepo
-
- // We opened it, we should close it
- cancel := func() {
- // If it's been set to nil then assume someone else has closed it.
- if ctx.Repo.GitRepo != nil {
- ctx.Repo.GitRepo.Close()
- }
+ return
}
// Stop at this point when the repo is empty.
if ctx.Repo.Repository.IsEmpty {
ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch
- return cancel
+ return
}
branchOpts := git_model.FindBranchOptions{
@@ -654,7 +652,7 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
branchesTotal, err := db.Count[git_model.Branch](ctx, branchOpts)
if err != nil {
ctx.ServerError("CountBranches", err)
- return cancel
+ return
}
// non-empty repo should have at least 1 branch, so this repository's branches haven't been synced yet
@@ -662,7 +660,7 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
branchesTotal, err = repo_module.SyncRepoBranches(ctx, ctx.Repo.Repository.ID, 0)
if err != nil {
ctx.ServerError("SyncRepoBranches", err)
- return cancel
+ return
}
}
@@ -670,7 +668,7 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
// If no branch is set in the request URL, try to guess a default one.
if len(ctx.Repo.BranchName) == 0 {
- if len(ctx.Repo.Repository.DefaultBranch) > 0 && gitRepo.IsBranchExist(ctx.Repo.Repository.DefaultBranch) {
+ if len(ctx.Repo.Repository.DefaultBranch) > 0 && ctx.Repo.GitRepo.IsBranchExist(ctx.Repo.Repository.DefaultBranch) {
ctx.Repo.BranchName = ctx.Repo.Repository.DefaultBranch
} else {
ctx.Repo.BranchName, _ = gitrepo.GetDefaultBranch(ctx, ctx.Repo.Repository)
@@ -711,12 +709,12 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
repoTransfer, err := repo_model.GetPendingRepositoryTransfer(ctx, ctx.Repo.Repository)
if err != nil {
ctx.ServerError("GetPendingRepositoryTransfer", err)
- return cancel
+ return
}
if err := repoTransfer.LoadAttributes(ctx); err != nil {
ctx.ServerError("LoadRecipient", err)
- return cancel
+ return
}
ctx.Data["RepoTransfer"] = repoTransfer
@@ -731,7 +729,6 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
ctx.Data["GoDocDirectory"] = fullURLPrefix + "{/dir}"
ctx.Data["GoDocFile"] = fullURLPrefix + "{/dir}/{file}#L{line}"
}
- return cancel
}
// RepoRefType type of repo reference
@@ -750,7 +747,7 @@ const headRefName = "HEAD"
// RepoRef handles repository reference names when the ref name is not
// explicitly given
-func RepoRef() func(*Context) context.CancelFunc {
+func RepoRef() func(*Context) {
// since no ref name is explicitly specified, ok to just use branch
return RepoRefByType(RepoRefBranch)
}
@@ -865,9 +862,9 @@ type RepoRefByTypeOptions struct {
// RepoRefByType handles repository reference name for a specific type
// of repository reference
-func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func(*Context) context.CancelFunc {
+func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func(*Context) {
opt := util.OptionalArg(opts)
- return func(ctx *Context) (cancel context.CancelFunc) {
+ return func(ctx *Context) {
refType := detectRefType
// Empty repository does not have reference information.
if ctx.Repo.Repository.IsEmpty {
@@ -875,7 +872,7 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
ctx.Repo.IsViewBranch = true
ctx.Repo.BranchName = ctx.Repo.Repository.DefaultBranch
ctx.Data["TreePath"] = ""
- return nil
+ return
}
var (
@@ -884,17 +881,10 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
)
if ctx.Repo.GitRepo == nil {
- ctx.Repo.GitRepo, err = gitrepo.OpenRepository(ctx, ctx.Repo.Repository)
+ ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx, ctx.Repo.Repository)
if err != nil {
ctx.ServerError(fmt.Sprintf("Open Repository %v failed", ctx.Repo.Repository.FullName()), err)
- return nil
- }
- // We opened it, we should close it
- cancel = func() {
- // If it's been set to nil then assume someone else has closed it.
- if ctx.Repo.GitRepo != nil {
- ctx.Repo.GitRepo.Close()
- }
+ return
}
}
@@ -924,7 +914,7 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
ctx.Repo.Repository.MarkAsBrokenEmpty()
} else {
ctx.ServerError("GetBranchCommit", err)
- return cancel
+ return
}
ctx.Repo.IsViewBranch = true
} else {
@@ -941,7 +931,7 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
ctx.Flash.Info(ctx.Tr("repo.branch.renamed", refName, renamedBranchName))
link := setting.AppSubURL + strings.Replace(ctx.Req.URL.EscapedPath(), util.PathEscapeSegments(refName), util.PathEscapeSegments(renamedBranchName), 1)
ctx.Redirect(link)
- return cancel
+ return
}
if refType == RepoRefBranch && ctx.Repo.GitRepo.IsBranchExist(refName) {
@@ -951,7 +941,7 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refName)
if err != nil {
ctx.ServerError("GetBranchCommit", err)
- return cancel
+ return
}
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
} else if refType == RepoRefTag && ctx.Repo.GitRepo.IsTagExist(refName) {
@@ -962,10 +952,10 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
if err != nil {
if git.IsErrNotExist(err) {
ctx.NotFound("GetTagCommit", err)
- return cancel
+ return
}
ctx.ServerError("GetTagCommit", err)
- return cancel
+ return
}
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
} else if git.IsStringLikelyCommitID(ctx.Repo.GetObjectFormat(), refName, 7) {
@@ -975,7 +965,7 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommit(refName)
if err != nil {
ctx.NotFound("GetCommit", err)
- return cancel
+ return
}
// If short commit ID add canonical link header
if len(refName) < ctx.Repo.GetObjectFormat().FullLength() {
@@ -984,10 +974,10 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
}
} else {
if opt.IgnoreNotExistErr {
- return cancel
+ return
}
ctx.NotFound("RepoRef invalid repo", fmt.Errorf("branch or tag not exist: %s", refName))
- return cancel
+ return
}
if guessLegacyPath {
@@ -999,7 +989,7 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
ctx.Repo.BranchNameSubURL(),
util.PathEscapeSegments(ctx.Repo.TreePath))
ctx.Redirect(redirect)
- return cancel
+ return
}
}
@@ -1017,12 +1007,10 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
ctx.Repo.CommitsCount, err = ctx.Repo.GetCommitsCount()
if err != nil {
ctx.ServerError("GetCommitsCount", err)
- return cancel
+ return
}
ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount
ctx.Repo.GitRepo.LastCommitCache = git.NewLastCommitCache(ctx.Repo.CommitsCount, ctx.Repo.Repository.FullName(), ctx.Repo.GitRepo, cache.GetCache())
-
- return cancel
}
}
diff --git a/services/contexttest/context_tests.go b/services/contexttest/context_tests.go
index 3c3fa76e3c..b0f71cad20 100644
--- a/services/contexttest/context_tests.go
+++ b/services/contexttest/context_tests.go
@@ -21,6 +21,7 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/cache"
"code.gitea.io/gitea/modules/gitrepo"
+ "code.gitea.io/gitea/modules/reqctx"
"code.gitea.io/gitea/modules/session"
"code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/translation"
@@ -40,7 +41,7 @@ func mockRequest(t *testing.T, reqPath string) *http.Request {
requestURL, err := url.Parse(path)
assert.NoError(t, err)
req := &http.Request{Method: method, Host: requestURL.Host, URL: requestURL, Form: maps.Clone(requestURL.Query()), Header: http.Header{}}
- req = req.WithContext(middleware.WithContextData(req.Context()))
+ req = req.WithContext(reqctx.NewRequestContextForTest(req.Context()))
return req
}
@@ -60,17 +61,16 @@ func MockContext(t *testing.T, reqPath string, opts ...MockContextOption) (*cont
}
resp := httptest.NewRecorder()
req := mockRequest(t, reqPath)
- base, baseCleanUp := context.NewBaseContext(resp, req)
- _ = baseCleanUp // during test, it doesn't need to do clean up. TODO: this can be improved later
+ base := context.NewBaseContext(resp, req)
base.Data = middleware.GetContextData(req.Context())
base.Locale = &translation.MockLocale{}
chiCtx := chi.NewRouteContext()
ctx := context.NewWebContext(base, opt.Render, nil)
- ctx.AppendContextValue(context.WebContextKey, ctx)
- ctx.AppendContextValue(chi.RouteCtxKey, chiCtx)
+ ctx.SetContextValue(context.WebContextKey, ctx)
+ ctx.SetContextValue(chi.RouteCtxKey, chiCtx)
if opt.SessionStore != nil {
- ctx.AppendContextValue(session.MockStoreContextKey, opt.SessionStore)
+ ctx.SetContextValue(session.MockStoreContextKey, opt.SessionStore)
ctx.Session = opt.SessionStore
}
ctx.Cache = cache.GetCache()
@@ -83,27 +83,24 @@ func MockContext(t *testing.T, reqPath string, opts ...MockContextOption) (*cont
func MockAPIContext(t *testing.T, reqPath string) (*context.APIContext, *httptest.ResponseRecorder) {
resp := httptest.NewRecorder()
req := mockRequest(t, reqPath)
- base, baseCleanUp := context.NewBaseContext(resp, req)
+ base := context.NewBaseContext(resp, req)
base.Data = middleware.GetContextData(req.Context())
base.Locale = &translation.MockLocale{}
ctx := &context.APIContext{Base: base}
- _ = baseCleanUp // during test, it doesn't need to do clean up. TODO: this can be improved later
-
chiCtx := chi.NewRouteContext()
- ctx.Base.AppendContextValue(chi.RouteCtxKey, chiCtx)
+ ctx.SetContextValue(chi.RouteCtxKey, chiCtx)
return ctx, resp
}
func MockPrivateContext(t *testing.T, reqPath string) (*context.PrivateContext, *httptest.ResponseRecorder) {
resp := httptest.NewRecorder()
req := mockRequest(t, reqPath)
- base, baseCleanUp := context.NewBaseContext(resp, req)
+ base := context.NewBaseContext(resp, req)
base.Data = middleware.GetContextData(req.Context())
base.Locale = &translation.MockLocale{}
ctx := &context.PrivateContext{Base: base}
- _ = baseCleanUp // during test, it doesn't need to do clean up. TODO: this can be improved later
chiCtx := chi.NewRouteContext()
- ctx.Base.AppendContextValue(chi.RouteCtxKey, chiCtx)
+ ctx.SetContextValue(chi.RouteCtxKey, chiCtx)
return ctx, resp
}
@@ -183,7 +180,7 @@ func (tr *MockRender) TemplateLookup(tmpl string, _ gocontext.Context) (template
return nil, nil
}
-func (tr *MockRender) HTML(w io.Writer, status int, _ string, _ any, _ gocontext.Context) error {
+func (tr *MockRender) HTML(w io.Writer, status int, _ templates.TplName, _ any, _ gocontext.Context) error {
if resp, ok := w.(http.ResponseWriter); ok {
resp.WriteHeader(status)
}
diff --git a/services/convert/pull.go b/services/convert/pull.go
index ddaaa300a4..a1ab7eeb8e 100644
--- a/services/convert/pull.go
+++ b/services/convert/pull.go
@@ -31,6 +31,11 @@ func ToAPIPullRequest(ctx context.Context, pr *issues_model.PullRequest, doer *u
err error
)
+ if err = pr.LoadIssue(ctx); err != nil {
+ log.Error("pr.LoadIssue[%d]: %v", pr.ID, err)
+ return nil
+ }
+
if err = pr.Issue.LoadRepo(ctx); err != nil {
log.Error("pr.Issue.LoadRepo[%d]: %v", pr.ID, err)
return nil
diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go
index 7647c74e46..b14171787e 100644
--- a/services/forms/repo_form.go
+++ b/services/forms/repo_form.go
@@ -6,10 +6,8 @@ package forms
import (
"net/http"
- "net/url"
"strings"
- "code.gitea.io/gitea/models"
issues_model "code.gitea.io/gitea/models/issues"
project_model "code.gitea.io/gitea/models/project"
"code.gitea.io/gitea/modules/setting"
@@ -90,27 +88,6 @@ func (f *MigrateRepoForm) Validate(req *http.Request, errs binding.Errors) bindi
return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
}
-// ParseRemoteAddr checks if given remote address is valid,
-// and returns composed URL with needed username and password.
-func ParseRemoteAddr(remoteAddr, authUsername, authPassword string) (string, error) {
- remoteAddr = strings.TrimSpace(remoteAddr)
- // Remote address can be HTTP/HTTPS/Git URL or local path.
- if strings.HasPrefix(remoteAddr, "http://") ||
- strings.HasPrefix(remoteAddr, "https://") ||
- strings.HasPrefix(remoteAddr, "git://") {
- u, err := url.Parse(remoteAddr)
- if err != nil {
- return "", &models.ErrInvalidCloneAddr{IsURLError: true, Host: remoteAddr}
- }
- if len(authUsername)+len(authPassword) > 0 {
- u.User = url.UserPassword(authUsername, authPassword)
- }
- remoteAddr = u.String()
- }
-
- return remoteAddr, nil
-}
-
// RepoSettingForm form for changing repository settings
type RepoSettingForm struct {
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"`
diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go
index bb1722039e..0b5a855d42 100644
--- a/services/gitdiff/gitdiff.go
+++ b/services/gitdiff/gitdiff.go
@@ -1156,7 +1156,6 @@ func GetDiff(ctx context.Context, gitRepo *git.Repository, opts *DiffOptions, fi
go func() {
stderr := &bytes.Buffer{}
- cmdDiff.SetDescription(fmt.Sprintf("GetDiffRange [repo_path: %s]", repoPath))
if err := cmdDiff.Run(&git.RunOpts{
Timeout: time.Duration(setting.Git.Timeout.Default) * time.Second,
Dir: repoPath,
diff --git a/services/mailer/mail.go b/services/mailer/mail.go
index ee2c8c0963..a6763e4f03 100644
--- a/services/mailer/mail.go
+++ b/services/mailer/mail.go
@@ -21,11 +21,11 @@ import (
"code.gitea.io/gitea/models/renderhelper"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/emoji"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/translation"
incoming_payload "code.gitea.io/gitea/services/mailer/incoming/payload"
@@ -34,14 +34,14 @@ import (
)
const (
- mailAuthActivate base.TplName = "auth/activate"
- mailAuthActivateEmail base.TplName = "auth/activate_email"
- mailAuthResetPassword base.TplName = "auth/reset_passwd"
- mailAuthRegisterNotify base.TplName = "auth/register_notify"
+ mailAuthActivate templates.TplName = "auth/activate"
+ mailAuthActivateEmail templates.TplName = "auth/activate_email"
+ mailAuthResetPassword templates.TplName = "auth/reset_passwd"
+ mailAuthRegisterNotify templates.TplName = "auth/register_notify"
- mailNotifyCollaborator base.TplName = "notify/collaborator"
+ mailNotifyCollaborator templates.TplName = "notify/collaborator"
- mailRepoTransferNotify base.TplName = "notify/repo_transfer"
+ mailRepoTransferNotify templates.TplName = "notify/repo_transfer"
// There's no actual limit for subject in RFC 5322
mailMaxSubjectRunes = 256
@@ -63,7 +63,7 @@ func SendTestMail(email string) error {
}
// sendUserMail sends a mail to the user
-func sendUserMail(language string, u *user_model.User, tpl base.TplName, code, subject, info string) {
+func sendUserMail(language string, u *user_model.User, tpl templates.TplName, code, subject, info string) {
locale := translation.NewLocale(language)
data := map[string]any{
"locale": locale,
diff --git a/services/mailer/mail_release.go b/services/mailer/mail_release.go
index 1d73d77612..796d63d27a 100644
--- a/services/mailer/mail_release.go
+++ b/services/mailer/mail_release.go
@@ -10,16 +10,16 @@ import (
"code.gitea.io/gitea/models/renderhelper"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/translation"
sender_service "code.gitea.io/gitea/services/mailer/sender"
)
const (
- tplNewReleaseMail base.TplName = "release"
+ tplNewReleaseMail templates.TplName = "release"
)
// MailNewRelease send new release notify to all repo watchers.
diff --git a/services/mailer/mail_team_invite.go b/services/mailer/mail_team_invite.go
index 4f2d5e4ca7..5ca44442f3 100644
--- a/services/mailer/mail_team_invite.go
+++ b/services/mailer/mail_team_invite.go
@@ -11,15 +11,15 @@ import (
org_model "code.gitea.io/gitea/models/organization"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/translation"
sender_service "code.gitea.io/gitea/services/mailer/sender"
)
const (
- tplTeamInviteMail base.TplName = "team_invite"
+ tplTeamInviteMail templates.TplName = "team_invite"
)
// MailTeamInvite sends team invites
diff --git a/services/markup/main_test.go b/services/markup/main_test.go
index 5553ebc058..d04a18bfa1 100644
--- a/services/markup/main_test.go
+++ b/services/markup/main_test.go
@@ -11,6 +11,6 @@ import (
func TestMain(m *testing.M) {
unittest.MainTest(m, &unittest.TestOptions{
- FixtureFiles: []string{"user.yml", "repository.yml", "access.yml", "repo_unit.yml"},
+ FixtureFiles: []string{"user.yml", "repository.yml", "access.yml", "repo_unit.yml", "issue.yml"},
})
}
diff --git a/services/markup/processorhelper.go b/services/markup/renderhelper.go
similarity index 88%
rename from services/markup/processorhelper.go
rename to services/markup/renderhelper.go
index 1f1abf496a..4b9852b48b 100644
--- a/services/markup/processorhelper.go
+++ b/services/markup/renderhelper.go
@@ -11,9 +11,10 @@ import (
gitea_context "code.gitea.io/gitea/services/context"
)
-func ProcessorHelper() *markup.RenderHelperFuncs {
+func FormalRenderHelperFuncs() *markup.RenderHelperFuncs {
return &markup.RenderHelperFuncs{
RenderRepoFileCodePreview: renderRepoFileCodePreview,
+ RenderRepoIssueIconTitle: renderRepoIssueIconTitle,
IsUsernameMentionable: func(ctx context.Context, username string) bool {
mentionedUser, err := user.GetUserByName(ctx, username)
if err != nil {
diff --git a/services/markup/processorhelper_codepreview.go b/services/markup/renderhelper_codepreview.go
similarity index 97%
rename from services/markup/processorhelper_codepreview.go
rename to services/markup/renderhelper_codepreview.go
index 0500e57e46..170c70c409 100644
--- a/services/markup/processorhelper_codepreview.go
+++ b/services/markup/renderhelper_codepreview.go
@@ -18,6 +18,7 @@ import (
"code.gitea.io/gitea/modules/indexer/code"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/util"
gitea_context "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/repository/files"
)
@@ -46,7 +47,7 @@ func renderRepoFileCodePreview(ctx context.Context, opts markup.RenderCodePrevie
return "", err
}
if !perms.CanRead(unit.TypeCode) {
- return "", fmt.Errorf("no permission")
+ return "", util.ErrPermissionDenied
}
gitRepo, err := gitrepo.OpenRepository(ctx, dbRepo)
diff --git a/services/markup/processorhelper_codepreview_test.go b/services/markup/renderhelper_codepreview_test.go
similarity index 95%
rename from services/markup/processorhelper_codepreview_test.go
rename to services/markup/renderhelper_codepreview_test.go
index 154e4e8e44..ea945584b4 100644
--- a/services/markup/processorhelper_codepreview_test.go
+++ b/services/markup/renderhelper_codepreview_test.go
@@ -9,12 +9,13 @@ import (
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/templates"
+ "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/services/contexttest"
"github.com/stretchr/testify/assert"
)
-func TestProcessorHelperCodePreview(t *testing.T) {
+func TestRenderHelperCodePreview(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
ctx, _ := contexttest.MockContext(t, "/", contexttest.MockContextOption{Render: templates.HTMLRenderer()})
@@ -79,5 +80,5 @@ func TestProcessorHelperCodePreview(t *testing.T) {
LineStart: 1,
LineStop: 10,
})
- assert.ErrorContains(t, err, "no permission")
+ assert.ErrorIs(t, err, util.ErrPermissionDenied)
}
diff --git a/services/markup/renderhelper_issueicontitle.go b/services/markup/renderhelper_issueicontitle.go
new file mode 100644
index 0000000000..53a508e908
--- /dev/null
+++ b/services/markup/renderhelper_issueicontitle.go
@@ -0,0 +1,66 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package markup
+
+import (
+ "context"
+ "fmt"
+ "html/template"
+
+ "code.gitea.io/gitea/models/issues"
+ "code.gitea.io/gitea/models/perm/access"
+ "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/modules/htmlutil"
+ "code.gitea.io/gitea/modules/markup"
+ "code.gitea.io/gitea/modules/util"
+ gitea_context "code.gitea.io/gitea/services/context"
+)
+
+func renderRepoIssueIconTitle(ctx context.Context, opts markup.RenderIssueIconTitleOptions) (_ template.HTML, err error) {
+ webCtx, ok := ctx.Value(gitea_context.WebContextKey).(*gitea_context.Context)
+ if !ok {
+ return "", fmt.Errorf("context is not a web context")
+ }
+
+ textIssueIndex := fmt.Sprintf("(#%d)", opts.IssueIndex)
+ dbRepo := webCtx.Repo.Repository
+ if opts.OwnerName != "" {
+ dbRepo, err = repo.GetRepositoryByOwnerAndName(ctx, opts.OwnerName, opts.RepoName)
+ if err != nil {
+ return "", err
+ }
+ textIssueIndex = fmt.Sprintf("(%s/%s#%d)", dbRepo.OwnerName, dbRepo.Name, opts.IssueIndex)
+ }
+ if dbRepo == nil {
+ return "", nil
+ }
+
+ issue, err := issues.GetIssueByIndex(ctx, dbRepo.ID, opts.IssueIndex)
+ if err != nil {
+ return "", err
+ }
+
+ if webCtx.Repo.Repository == nil || dbRepo.ID != webCtx.Repo.Repository.ID {
+ perms, err := access.GetUserRepoPermission(ctx, dbRepo, webCtx.Doer)
+ if err != nil {
+ return "", err
+ }
+ if !perms.CanReadIssuesOrPulls(issue.IsPull) {
+ return "", util.ErrPermissionDenied
+ }
+ }
+
+ if issue.IsPull {
+ if err = issue.LoadPullRequest(ctx); err != nil {
+ return "", err
+ }
+ }
+
+ htmlIcon, err := webCtx.RenderToHTML("shared/issueicon", issue)
+ if err != nil {
+ return "", err
+ }
+
+ return htmlutil.HTMLFormat(`%s %s %s`, opts.LinkHref, htmlIcon, issue.Title, textIssueIndex), nil
+}
diff --git a/services/markup/renderhelper_issueicontitle_test.go b/services/markup/renderhelper_issueicontitle_test.go
new file mode 100644
index 0000000000..adce8401e0
--- /dev/null
+++ b/services/markup/renderhelper_issueicontitle_test.go
@@ -0,0 +1,49 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package markup
+
+import (
+ "testing"
+
+ "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/models/unittest"
+ "code.gitea.io/gitea/modules/markup"
+ "code.gitea.io/gitea/modules/templates"
+ "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/services/contexttest"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestRenderHelperIssueIconTitle(t *testing.T) {
+ assert.NoError(t, unittest.PrepareTestDatabase())
+
+ ctx, _ := contexttest.MockContext(t, "/", contexttest.MockContextOption{Render: templates.HTMLRenderer()})
+ ctx.Repo.Repository = unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 1})
+ htm, err := renderRepoIssueIconTitle(ctx, markup.RenderIssueIconTitleOptions{
+ LinkHref: "/link",
+ IssueIndex: 1,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, `octicon-issue-opened(16/text green) issue1 (#1)`, string(htm))
+
+ ctx, _ = contexttest.MockContext(t, "/", contexttest.MockContextOption{Render: templates.HTMLRenderer()})
+ htm, err = renderRepoIssueIconTitle(ctx, markup.RenderIssueIconTitleOptions{
+ OwnerName: "user2",
+ RepoName: "repo1",
+ LinkHref: "/link",
+ IssueIndex: 1,
+ })
+ assert.NoError(t, err)
+ assert.Equal(t, `octicon-issue-opened(16/text green) issue1 (user2/repo1#1)`, string(htm))
+
+ ctx, _ = contexttest.MockContext(t, "/", contexttest.MockContextOption{Render: templates.HTMLRenderer()})
+ _, err = renderRepoIssueIconTitle(ctx, markup.RenderIssueIconTitleOptions{
+ OwnerName: "user2",
+ RepoName: "repo2",
+ LinkHref: "/link",
+ IssueIndex: 2,
+ })
+ assert.ErrorIs(t, err, util.ErrPermissionDenied)
+}
diff --git a/services/markup/processorhelper_test.go b/services/markup/renderhelper_mention_test.go
similarity index 57%
rename from services/markup/processorhelper_test.go
rename to services/markup/renderhelper_mention_test.go
index 170edae0e0..c244fa3d21 100644
--- a/services/markup/processorhelper_test.go
+++ b/services/markup/renderhelper_mention_test.go
@@ -18,7 +18,7 @@ import (
"github.com/stretchr/testify/assert"
)
-func TestProcessorHelper(t *testing.T) {
+func TestRenderHelperMention(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
userPublic := "user1"
@@ -32,23 +32,22 @@ func TestProcessorHelper(t *testing.T) {
unittest.AssertCount(t, &user.User{Name: userNoSuch}, 0)
// when using general context, use user's visibility to check
- assert.True(t, ProcessorHelper().IsUsernameMentionable(context.Background(), userPublic))
- assert.False(t, ProcessorHelper().IsUsernameMentionable(context.Background(), userLimited))
- assert.False(t, ProcessorHelper().IsUsernameMentionable(context.Background(), userPrivate))
- assert.False(t, ProcessorHelper().IsUsernameMentionable(context.Background(), userNoSuch))
+ assert.True(t, FormalRenderHelperFuncs().IsUsernameMentionable(context.Background(), userPublic))
+ assert.False(t, FormalRenderHelperFuncs().IsUsernameMentionable(context.Background(), userLimited))
+ assert.False(t, FormalRenderHelperFuncs().IsUsernameMentionable(context.Background(), userPrivate))
+ assert.False(t, FormalRenderHelperFuncs().IsUsernameMentionable(context.Background(), userNoSuch))
// when using web context, use user.IsUserVisibleToViewer to check
req, err := http.NewRequest("GET", "/", nil)
assert.NoError(t, err)
- base, baseCleanUp := gitea_context.NewBaseContext(httptest.NewRecorder(), req)
- defer baseCleanUp()
+ base := gitea_context.NewBaseContextForTest(httptest.NewRecorder(), req)
giteaCtx := gitea_context.NewWebContext(base, &contexttest.MockRender{}, nil)
- assert.True(t, ProcessorHelper().IsUsernameMentionable(giteaCtx, userPublic))
- assert.False(t, ProcessorHelper().IsUsernameMentionable(giteaCtx, userPrivate))
+ assert.True(t, FormalRenderHelperFuncs().IsUsernameMentionable(giteaCtx, userPublic))
+ assert.False(t, FormalRenderHelperFuncs().IsUsernameMentionable(giteaCtx, userPrivate))
giteaCtx.Doer, err = user.GetUserByName(db.DefaultContext, userPrivate)
assert.NoError(t, err)
- assert.True(t, ProcessorHelper().IsUsernameMentionable(giteaCtx, userPublic))
- assert.True(t, ProcessorHelper().IsUsernameMentionable(giteaCtx, userPrivate))
+ assert.True(t, FormalRenderHelperFuncs().IsUsernameMentionable(giteaCtx, userPublic))
+ assert.True(t, FormalRenderHelperFuncs().IsUsernameMentionable(giteaCtx, userPrivate))
}
diff --git a/services/migrations/migrate.go b/services/migrations/migrate.go
index d0ad6d0139..51b22d6111 100644
--- a/services/migrations/migrate.go
+++ b/services/migrations/migrate.go
@@ -12,10 +12,10 @@ import (
"path/filepath"
"strings"
- "code.gitea.io/gitea/models"
repo_model "code.gitea.io/gitea/models/repo"
system_model "code.gitea.io/gitea/models/system"
user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/hostmatcher"
"code.gitea.io/gitea/modules/log"
base "code.gitea.io/gitea/modules/migration"
@@ -43,16 +43,16 @@ func IsMigrateURLAllowed(remoteURL string, doer *user_model.User) error {
// Remote address can be HTTP/HTTPS/Git URL or local path.
u, err := url.Parse(remoteURL)
if err != nil {
- return &models.ErrInvalidCloneAddr{IsURLError: true, Host: remoteURL}
+ return &git.ErrInvalidCloneAddr{IsURLError: true, Host: remoteURL}
}
if u.Scheme == "file" || u.Scheme == "" {
if !doer.CanImportLocal() {
- return &models.ErrInvalidCloneAddr{Host: "", IsPermissionDenied: true, LocalPath: true}
+ return &git.ErrInvalidCloneAddr{Host: "", IsPermissionDenied: true, LocalPath: true}
}
isAbs := filepath.IsAbs(u.Host + u.Path)
if !isAbs {
- return &models.ErrInvalidCloneAddr{Host: "", IsInvalidPath: true, LocalPath: true}
+ return &git.ErrInvalidCloneAddr{Host: "", IsInvalidPath: true, LocalPath: true}
}
isDir, err := util.IsDir(u.Host + u.Path)
if err != nil {
@@ -60,18 +60,18 @@ func IsMigrateURLAllowed(remoteURL string, doer *user_model.User) error {
return err
}
if !isDir {
- return &models.ErrInvalidCloneAddr{Host: "", IsInvalidPath: true, LocalPath: true}
+ return &git.ErrInvalidCloneAddr{Host: "", IsInvalidPath: true, LocalPath: true}
}
return nil
}
if u.Scheme == "git" && u.Port() != "" && (strings.Contains(remoteURL, "%0d") || strings.Contains(remoteURL, "%0a")) {
- return &models.ErrInvalidCloneAddr{Host: u.Host, IsURLError: true}
+ return &git.ErrInvalidCloneAddr{Host: u.Host, IsURLError: true}
}
if u.Opaque != "" || u.Scheme != "" && u.Scheme != "http" && u.Scheme != "https" && u.Scheme != "git" {
- return &models.ErrInvalidCloneAddr{Host: u.Host, IsProtocolInvalid: true, IsPermissionDenied: true, IsURLError: true}
+ return &git.ErrInvalidCloneAddr{Host: u.Host, IsProtocolInvalid: true, IsPermissionDenied: true, IsURLError: true}
}
hostName, _, err := net.SplitHostPort(u.Host)
@@ -95,12 +95,12 @@ func checkByAllowBlockList(hostName string, addrList []net.IP) error {
}
var blockedError error
if blockList.MatchHostName(hostName) || ipBlocked {
- blockedError = &models.ErrInvalidCloneAddr{Host: hostName, IsPermissionDenied: true}
+ blockedError = &git.ErrInvalidCloneAddr{Host: hostName, IsPermissionDenied: true}
}
// if we have an allow-list, check the allow-list before return to get the more accurate error
if !allowList.IsEmpty() {
if !allowList.MatchHostName(hostName) && !ipAllowed {
- return &models.ErrInvalidCloneAddr{Host: hostName, IsPermissionDenied: true}
+ return &git.ErrInvalidCloneAddr{Host: hostName, IsPermissionDenied: true}
}
}
// otherwise, we always follow the blocked list
diff --git a/services/mirror/mirror_pull.go b/services/mirror/mirror_pull.go
index a81fe6e9bd..22d380e8e6 100644
--- a/services/mirror/mirror_pull.go
+++ b/services/mirror/mirror_pull.go
@@ -46,11 +46,6 @@ func UpdateAddress(ctx context.Context, m *repo_model.Mirror, addr string) error
}
cmd := git.NewCommand(ctx, "remote", "add").AddDynamicArguments(remoteName).AddArguments("--mirror=fetch").AddDynamicArguments(addr)
- if strings.Contains(addr, "://") && strings.Contains(addr, "@") {
- cmd.SetDescription(fmt.Sprintf("remote add %s --mirror=fetch %s [repo_path: %s]", remoteName, util.SanitizeCredentialURLs(addr), repoPath))
- } else {
- cmd.SetDescription(fmt.Sprintf("remote add %s --mirror=fetch %s [repo_path: %s]", remoteName, addr, repoPath))
- }
_, _, err = cmd.RunStdString(&git.RunOpts{Dir: repoPath})
if err != nil && !strings.HasPrefix(err.Error(), "exit status 128 - fatal: No such remote ") {
return err
@@ -66,11 +61,6 @@ func UpdateAddress(ctx context.Context, m *repo_model.Mirror, addr string) error
}
cmd = git.NewCommand(ctx, "remote", "add").AddDynamicArguments(remoteName).AddArguments("--mirror=fetch").AddDynamicArguments(wikiRemotePath)
- if strings.Contains(wikiRemotePath, "://") && strings.Contains(wikiRemotePath, "@") {
- cmd.SetDescription(fmt.Sprintf("remote add %s --mirror=fetch %s [repo_path: %s]", remoteName, util.SanitizeCredentialURLs(wikiRemotePath), wikiPath))
- } else {
- cmd.SetDescription(fmt.Sprintf("remote add %s --mirror=fetch %s [repo_path: %s]", remoteName, wikiRemotePath, wikiPath))
- }
_, _, err = cmd.RunStdString(&git.RunOpts{Dir: wikiPath})
if err != nil && !strings.HasPrefix(err.Error(), "exit status 128 - fatal: No such remote ") {
return err
@@ -197,7 +187,6 @@ func pruneBrokenReferences(ctx context.Context,
stderrBuilder.Reset()
stdoutBuilder.Reset()
pruneErr := git.NewCommand(ctx, "remote", "prune").AddDynamicArguments(m.GetRemoteName()).
- SetDescription(fmt.Sprintf("Mirror.runSync %ssPrune references: %s ", wiki, m.Repo.FullName())).
Run(&git.RunOpts{
Timeout: timeout,
Dir: repoPath,
@@ -248,15 +237,13 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo
stdoutBuilder := strings.Builder{}
stderrBuilder := strings.Builder{}
- if err := cmd.
- SetDescription(fmt.Sprintf("Mirror.runSync: %s", m.Repo.FullName())).
- Run(&git.RunOpts{
- Timeout: timeout,
- Dir: repoPath,
- Env: envs,
- Stdout: &stdoutBuilder,
- Stderr: &stderrBuilder,
- }); err != nil {
+ if err := cmd.Run(&git.RunOpts{
+ Timeout: timeout,
+ Dir: repoPath,
+ Env: envs,
+ Stdout: &stdoutBuilder,
+ Stderr: &stderrBuilder,
+ }); err != nil {
stdout := stdoutBuilder.String()
stderr := stderrBuilder.String()
@@ -275,14 +262,12 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo
// Successful prune - reattempt mirror
stderrBuilder.Reset()
stdoutBuilder.Reset()
- if err = cmd.
- SetDescription(fmt.Sprintf("Mirror.runSync: %s", m.Repo.FullName())).
- Run(&git.RunOpts{
- Timeout: timeout,
- Dir: repoPath,
- Stdout: &stdoutBuilder,
- Stderr: &stderrBuilder,
- }); err != nil {
+ if err = cmd.Run(&git.RunOpts{
+ Timeout: timeout,
+ Dir: repoPath,
+ Stdout: &stdoutBuilder,
+ Stderr: &stderrBuilder,
+ }); err != nil {
stdout := stdoutBuilder.String()
stderr := stderrBuilder.String()
@@ -346,7 +331,6 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo
stderrBuilder.Reset()
stdoutBuilder.Reset()
if err := git.NewCommand(ctx, "remote", "update", "--prune").AddDynamicArguments(m.GetRemoteName()).
- SetDescription(fmt.Sprintf("Mirror.runSync Wiki: %s ", m.Repo.FullName())).
Run(&git.RunOpts{
Timeout: timeout,
Dir: wikiPath,
@@ -373,7 +357,6 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo
stdoutBuilder.Reset()
if err = git.NewCommand(ctx, "remote", "update", "--prune").AddDynamicArguments(m.GetRemoteName()).
- SetDescription(fmt.Sprintf("Mirror.runSync Wiki: %s ", m.Repo.FullName())).
Run(&git.RunOpts{
Timeout: timeout,
Dir: wikiPath,
diff --git a/services/mirror/mirror_push.go b/services/mirror/mirror_push.go
index 21ba0afeff..02ff97b1f0 100644
--- a/services/mirror/mirror_push.go
+++ b/services/mirror/mirror_push.go
@@ -9,7 +9,6 @@ import (
"fmt"
"io"
"regexp"
- "strings"
"time"
"code.gitea.io/gitea/models/db"
@@ -31,11 +30,6 @@ var stripExitStatus = regexp.MustCompile(`exit status \d+ - `)
func AddPushMirrorRemote(ctx context.Context, m *repo_model.PushMirror, addr string) error {
addRemoteAndConfig := func(addr, path string) error {
cmd := git.NewCommand(ctx, "remote", "add", "--mirror=push").AddDynamicArguments(m.RemoteName, addr)
- if strings.Contains(addr, "://") && strings.Contains(addr, "@") {
- cmd.SetDescription(fmt.Sprintf("remote add %s --mirror=push %s [repo_path: %s]", m.RemoteName, util.SanitizeCredentialURLs(addr), path))
- } else {
- cmd.SetDescription(fmt.Sprintf("remote add %s --mirror=push %s [repo_path: %s]", m.RemoteName, addr, path))
- }
if _, _, err := cmd.RunStdString(&git.RunOpts{Dir: path}); err != nil {
return err
}
diff --git a/services/org/org.go b/services/org/org.go
index 471e6fcaf1..3d30ae21a3 100644
--- a/services/org/org.go
+++ b/services/org/org.go
@@ -7,7 +7,6 @@ import (
"context"
"fmt"
- "code.gitea.io/gitea/models"
actions_model "code.gitea.io/gitea/models/actions"
"code.gitea.io/gitea/models/db"
org_model "code.gitea.io/gitea/models/organization"
@@ -67,14 +66,14 @@ func DeleteOrganization(ctx context.Context, org *org_model.Organization, purge
if err != nil {
return fmt.Errorf("GetRepositoryCount: %w", err)
} else if count > 0 {
- return models.ErrUserOwnRepos{UID: org.ID}
+ return repo_model.ErrUserOwnRepos{UID: org.ID}
}
// Check ownership of packages.
if ownsPackages, err := packages_model.HasOwnerPackages(ctx, org.ID); err != nil {
return fmt.Errorf("HasOwnerPackages: %w", err)
} else if ownsPackages {
- return models.ErrUserOwnPackages{UID: org.ID}
+ return packages_model.ErrUserOwnPackages{UID: org.ID}
}
if err := deleteOrganization(ctx, org); err != nil {
diff --git a/services/org/org_test.go b/services/org/org_test.go
index e7d2a18ea9..791404c5c8 100644
--- a/services/org/org_test.go
+++ b/services/org/org_test.go
@@ -6,9 +6,9 @@ package org
import (
"testing"
- "code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/organization"
+ repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
@@ -30,7 +30,7 @@ func TestDeleteOrganization(t *testing.T) {
org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
err := DeleteOrganization(db.DefaultContext, org, false)
assert.Error(t, err)
- assert.True(t, models.IsErrUserOwnRepos(err))
+ assert.True(t, repo_model.IsErrUserOwnRepos(err))
user := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 5})
assert.Error(t, DeleteOrganization(db.DefaultContext, user, false))
diff --git a/services/pull/check.go b/services/pull/check.go
index 736be4611b..bffca394a8 100644
--- a/services/pull/check.go
+++ b/services/pull/check.go
@@ -11,7 +11,6 @@ import (
"strconv"
"strings"
- "code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues"
@@ -36,7 +35,7 @@ var prPatchCheckerQueue *queue.WorkerPoolQueue[string]
var (
ErrIsClosed = errors.New("pull is closed")
- ErrUserNotAllowedToMerge = models.ErrDisallowedToMerge{}
+ ErrUserNotAllowedToMerge = ErrDisallowedToMerge{}
ErrHasMerged = errors.New("has already been merged")
ErrIsWorkInProgress = errors.New("work in progress PRs cannot be merged")
ErrIsChecking = errors.New("cannot merge while conflict checking is in progress")
@@ -106,7 +105,7 @@ func CheckPullMergeable(stdCtx context.Context, doer *user_model.User, perm *acc
}
if err := CheckPullBranchProtections(ctx, pr, false); err != nil {
- if !models.IsErrDisallowedToMerge(err) {
+ if !IsErrDisallowedToMerge(err) {
log.Error("Error whilst checking pull branch protection for %-v: %v", pr, err)
return err
}
diff --git a/services/pull/merge.go b/services/pull/merge.go
index a3fbe4f627..fba85f1e51 100644
--- a/services/pull/merge.go
+++ b/services/pull/merge.go
@@ -13,7 +13,6 @@ import (
"strconv"
"strings"
- "code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues"
@@ -30,6 +29,7 @@ import (
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
+ "code.gitea.io/gitea/modules/util"
issue_service "code.gitea.io/gitea/services/issue"
notify_service "code.gitea.io/gitea/services/notify"
)
@@ -159,6 +159,27 @@ func GetDefaultMergeMessage(ctx context.Context, baseGitRepo *git.Repository, pr
return getMergeMessage(ctx, baseGitRepo, pr, mergeStyle, nil)
}
+// ErrInvalidMergeStyle represents an error if merging with disabled merge strategy
+type ErrInvalidMergeStyle struct {
+ ID int64
+ Style repo_model.MergeStyle
+}
+
+// IsErrInvalidMergeStyle checks if an error is a ErrInvalidMergeStyle.
+func IsErrInvalidMergeStyle(err error) bool {
+ _, ok := err.(ErrInvalidMergeStyle)
+ return ok
+}
+
+func (err ErrInvalidMergeStyle) Error() string {
+ return fmt.Sprintf("merge strategy is not allowed or is invalid [repo_id: %d, strategy: %s]",
+ err.ID, err.Style)
+}
+
+func (err ErrInvalidMergeStyle) Unwrap() error {
+ return util.ErrInvalidArgument
+}
+
// Merge merges pull request to base repository.
// Caller should check PR is ready to be merged (review and status checks)
func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User, baseGitRepo *git.Repository, mergeStyle repo_model.MergeStyle, expectedHeadCommitID, message string, wasAutoMerged bool) error {
@@ -179,7 +200,7 @@ func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.U
// Check if merge style is correct and allowed
if !prConfig.IsMergeStyleAllowed(mergeStyle) {
- return models.ErrInvalidMergeStyle{ID: pr.BaseRepo.ID, Style: mergeStyle}
+ return ErrInvalidMergeStyle{ID: pr.BaseRepo.ID, Style: mergeStyle}
}
releaser, err := globallock.Lock(ctx, getPullWorkingLockKey(pr.ID))
@@ -283,7 +304,7 @@ func doMergeAndPush(ctx context.Context, pr *issues_model.PullRequest, doer *use
return "", err
}
default:
- return "", models.ErrInvalidMergeStyle{ID: pr.BaseRepo.ID, Style: mergeStyle}
+ return "", ErrInvalidMergeStyle{ID: pr.BaseRepo.ID, Style: mergeStyle}
}
// OK we should cache our current head and origin/headbranch
@@ -374,13 +395,66 @@ func commitAndSignNoAuthor(ctx *mergeContext, message string) error {
return nil
}
+// ErrMergeConflicts represents an error if merging fails with a conflict
+type ErrMergeConflicts struct {
+ Style repo_model.MergeStyle
+ StdOut string
+ StdErr string
+ Err error
+}
+
+// IsErrMergeConflicts checks if an error is a ErrMergeConflicts.
+func IsErrMergeConflicts(err error) bool {
+ _, ok := err.(ErrMergeConflicts)
+ return ok
+}
+
+func (err ErrMergeConflicts) Error() string {
+ return fmt.Sprintf("Merge Conflict Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut)
+}
+
+// ErrMergeUnrelatedHistories represents an error if merging fails due to unrelated histories
+type ErrMergeUnrelatedHistories struct {
+ Style repo_model.MergeStyle
+ StdOut string
+ StdErr string
+ Err error
+}
+
+// IsErrMergeUnrelatedHistories checks if an error is a ErrMergeUnrelatedHistories.
+func IsErrMergeUnrelatedHistories(err error) bool {
+ _, ok := err.(ErrMergeUnrelatedHistories)
+ return ok
+}
+
+func (err ErrMergeUnrelatedHistories) Error() string {
+ return fmt.Sprintf("Merge UnrelatedHistories Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut)
+}
+
+// ErrMergeDivergingFastForwardOnly represents an error if a fast-forward-only merge fails because the branches diverge
+type ErrMergeDivergingFastForwardOnly struct {
+ StdOut string
+ StdErr string
+ Err error
+}
+
+// IsErrMergeDivergingFastForwardOnly checks if an error is a ErrMergeDivergingFastForwardOnly.
+func IsErrMergeDivergingFastForwardOnly(err error) bool {
+ _, ok := err.(ErrMergeDivergingFastForwardOnly)
+ return ok
+}
+
+func (err ErrMergeDivergingFastForwardOnly) Error() string {
+ return fmt.Sprintf("Merge DivergingFastForwardOnly Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut)
+}
+
func runMergeCommand(ctx *mergeContext, mergeStyle repo_model.MergeStyle, cmd *git.Command) error {
if err := cmd.Run(ctx.RunOpts()); err != nil {
// Merge will leave a MERGE_HEAD file in the .git folder if there is a conflict
if _, statErr := os.Stat(filepath.Join(ctx.tmpBasePath, ".git", "MERGE_HEAD")); statErr == nil {
// We have a merge conflict error
log.Debug("MergeConflict %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
- return models.ErrMergeConflicts{
+ return ErrMergeConflicts{
Style: mergeStyle,
StdOut: ctx.outbuf.String(),
StdErr: ctx.errbuf.String(),
@@ -388,7 +462,7 @@ func runMergeCommand(ctx *mergeContext, mergeStyle repo_model.MergeStyle, cmd *g
}
} else if strings.Contains(ctx.errbuf.String(), "refusing to merge unrelated histories") {
log.Debug("MergeUnrelatedHistories %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
- return models.ErrMergeUnrelatedHistories{
+ return ErrMergeUnrelatedHistories{
Style: mergeStyle,
StdOut: ctx.outbuf.String(),
StdErr: ctx.errbuf.String(),
@@ -396,7 +470,7 @@ func runMergeCommand(ctx *mergeContext, mergeStyle repo_model.MergeStyle, cmd *g
}
} else if mergeStyle == repo_model.MergeStyleFastForwardOnly && strings.Contains(ctx.errbuf.String(), "Not possible to fast-forward, aborting") {
log.Debug("MergeDivergingFastForwardOnly %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
- return models.ErrMergeDivergingFastForwardOnly{
+ return ErrMergeDivergingFastForwardOnly{
StdOut: ctx.outbuf.String(),
StdErr: ctx.errbuf.String(),
Err: err,
@@ -431,6 +505,25 @@ func IsUserAllowedToMerge(ctx context.Context, pr *issues_model.PullRequest, p a
return false, nil
}
+// ErrDisallowedToMerge represents an error that a branch is protected and the current user is not allowed to modify it.
+type ErrDisallowedToMerge struct {
+ Reason string
+}
+
+// IsErrDisallowedToMerge checks if an error is an ErrDisallowedToMerge.
+func IsErrDisallowedToMerge(err error) bool {
+ _, ok := err.(ErrDisallowedToMerge)
+ return ok
+}
+
+func (err ErrDisallowedToMerge) Error() string {
+ return fmt.Sprintf("not allowed to merge [reason: %s]", err.Reason)
+}
+
+func (err ErrDisallowedToMerge) Unwrap() error {
+ return util.ErrPermissionDenied
+}
+
// CheckPullBranchProtections checks whether the PR is ready to be merged (reviews and status checks)
func CheckPullBranchProtections(ctx context.Context, pr *issues_model.PullRequest, skipProtectedFilesCheck bool) (err error) {
if err = pr.LoadBaseRepo(ctx); err != nil {
@@ -450,29 +543,29 @@ func CheckPullBranchProtections(ctx context.Context, pr *issues_model.PullReques
return err
}
if !isPass {
- return models.ErrDisallowedToMerge{
+ return ErrDisallowedToMerge{
Reason: "Not all required status checks successful",
}
}
if !issues_model.HasEnoughApprovals(ctx, pb, pr) {
- return models.ErrDisallowedToMerge{
+ return ErrDisallowedToMerge{
Reason: "Does not have enough approvals",
}
}
if issues_model.MergeBlockedByRejectedReview(ctx, pb, pr) {
- return models.ErrDisallowedToMerge{
+ return ErrDisallowedToMerge{
Reason: "There are requested changes",
}
}
if issues_model.MergeBlockedByOfficialReviewRequests(ctx, pb, pr) {
- return models.ErrDisallowedToMerge{
+ return ErrDisallowedToMerge{
Reason: "There are official review requests",
}
}
if issues_model.MergeBlockedByOutdatedBranch(pb, pr) {
- return models.ErrDisallowedToMerge{
+ return ErrDisallowedToMerge{
Reason: "The head branch is behind the base branch",
}
}
@@ -482,7 +575,7 @@ func CheckPullBranchProtections(ctx context.Context, pr *issues_model.PullReques
}
if pb.MergeBlockedByProtectedFiles(pr.ChangedProtectedFiles) {
- return models.ErrDisallowedToMerge{
+ return ErrDisallowedToMerge{
Reason: "Changed protected files",
}
}
@@ -511,7 +604,7 @@ func MergedManually(ctx context.Context, pr *issues_model.PullRequest, doer *use
// Check if merge style is correct and allowed
if !prConfig.IsMergeStyleAllowed(repo_model.MergeStyleManuallyMerged) {
- return models.ErrInvalidMergeStyle{ID: pr.BaseRepo.ID, Style: repo_model.MergeStyleManuallyMerged}
+ return ErrInvalidMergeStyle{ID: pr.BaseRepo.ID, Style: repo_model.MergeStyleManuallyMerged}
}
objectFormat := git.ObjectFormatFromName(pr.BaseRepo.ObjectFormatName)
diff --git a/services/pull/merge_prepare.go b/services/pull/merge_prepare.go
index 88f6c037eb..2e1cc8cf85 100644
--- a/services/pull/merge_prepare.go
+++ b/services/pull/merge_prepare.go
@@ -14,7 +14,6 @@ import (
"strings"
"time"
- "code.gitea.io/gitea/models"
issues_model "code.gitea.io/gitea/models/issues"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
@@ -43,6 +42,23 @@ func (ctx *mergeContext) RunOpts() *git.RunOpts {
}
}
+// ErrSHADoesNotMatch represents a "SHADoesNotMatch" kind of error.
+type ErrSHADoesNotMatch struct {
+ Path string
+ GivenSHA string
+ CurrentSHA string
+}
+
+// IsErrSHADoesNotMatch checks if an error is a ErrSHADoesNotMatch.
+func IsErrSHADoesNotMatch(err error) bool {
+ _, ok := err.(ErrSHADoesNotMatch)
+ return ok
+}
+
+func (err ErrSHADoesNotMatch) Error() string {
+ return fmt.Sprintf("sha does not match [given: %s, expected: %s]", err.GivenSHA, err.CurrentSHA)
+}
+
func createTemporaryRepoForMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User, expectedHeadCommitID string) (mergeCtx *mergeContext, cancel context.CancelFunc, err error) {
// Clone base repo.
prCtx, cancel, err := createTemporaryRepoForPR(ctx, pr)
@@ -65,7 +81,7 @@ func createTemporaryRepoForMerge(ctx context.Context, pr *issues_model.PullReque
}
if strings.TrimSpace(trackingCommitID) != expectedHeadCommitID {
defer cancel()
- return nil, nil, models.ErrSHADoesNotMatch{
+ return nil, nil, ErrSHADoesNotMatch{
GivenSHA: expectedHeadCommitID,
CurrentSHA: trackingCommitID,
}
@@ -233,8 +249,27 @@ func getDiffTree(ctx context.Context, repoPath, baseBranch, headBranch string, o
return err
}
+// ErrRebaseConflicts represents an error if rebase fails with a conflict
+type ErrRebaseConflicts struct {
+ Style repo_model.MergeStyle
+ CommitSHA string
+ StdOut string
+ StdErr string
+ Err error
+}
+
+// IsErrRebaseConflicts checks if an error is a ErrRebaseConflicts.
+func IsErrRebaseConflicts(err error) bool {
+ _, ok := err.(ErrRebaseConflicts)
+ return ok
+}
+
+func (err ErrRebaseConflicts) Error() string {
+ return fmt.Sprintf("Rebase Error: %v: Whilst Rebasing: %s\n%s\n%s", err.Err, err.CommitSHA, err.StdErr, err.StdOut)
+}
+
// rebaseTrackingOnToBase checks out the tracking branch as staging and rebases it on to the base branch
-// if there is a conflict it will return a models.ErrRebaseConflicts
+// if there is a conflict it will return an ErrRebaseConflicts
func rebaseTrackingOnToBase(ctx *mergeContext, mergeStyle repo_model.MergeStyle) error {
// Checkout head branch
if err := git.NewCommand(ctx, "checkout", "-b").AddDynamicArguments(stagingBranch, trackingBranch).
@@ -268,11 +303,11 @@ func rebaseTrackingOnToBase(ctx *mergeContext, mergeStyle repo_model.MergeStyle)
}
}
if !ok {
- log.Error("Unable to determine failing commit sha for failing rebase in temp repo for %-v. Cannot cast as models.ErrRebaseConflicts.", ctx.pr)
+ log.Error("Unable to determine failing commit sha for failing rebase in temp repo for %-v. Cannot cast as ErrRebaseConflicts.", ctx.pr)
return fmt.Errorf("unable to git rebase staging on to base in temp repo for %v: %w\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
}
log.Debug("Conflict when rebasing staging on to base in %-v at %s: %v\n%s\n%s", ctx.pr, commitSha, err, ctx.outbuf.String(), ctx.errbuf.String())
- return models.ErrRebaseConflicts{
+ return ErrRebaseConflicts{
CommitSHA: commitSha,
Style: mergeStyle,
StdOut: ctx.outbuf.String(),
diff --git a/services/pull/merge_squash.go b/services/pull/merge_squash.go
index 197d8102dd..8f8a5d82e7 100644
--- a/services/pull/merge_squash.go
+++ b/services/pull/merge_squash.go
@@ -10,7 +10,6 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/git"
- "code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
)
@@ -25,12 +24,12 @@ func getAuthorSignatureSquash(ctx *mergeContext) (*git.Signature, error) {
// Try to get an signature from the same user in one of the commits, as the
// poster email might be private or commits might have a different signature
// than the primary email address of the poster.
- gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpenPath(ctx, ctx.tmpBasePath)
+ gitRepo, err := git.OpenRepository(ctx, ctx.tmpBasePath)
if err != nil {
log.Error("%-v Unable to open base repository: %v", ctx.pr, err)
return nil, err
}
- defer closer.Close()
+ defer gitRepo.Close()
commits, err := gitRepo.CommitsBetweenIDs(trackingBranch, "HEAD")
if err != nil {
diff --git a/services/pull/patch.go b/services/pull/patch.go
index 0934a86c89..13623d73c6 100644
--- a/services/pull/patch.go
+++ b/services/pull/patch.go
@@ -13,7 +13,6 @@ import (
"path/filepath"
"strings"
- "code.gitea.io/gitea/models"
git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/unit"
@@ -42,9 +41,19 @@ func DownloadDiffOrPatch(ctx context.Context, pr *issues_model.PullRequest, w io
}
defer closer.Close()
- if err := gitRepo.GetDiffOrPatch(pr.MergeBase, pr.GetGitRefName(), w, patch, binary); err != nil {
- log.Error("Unable to get patch file from %s to %s in %s Error: %v", pr.MergeBase, pr.HeadBranch, pr.BaseRepo.FullName(), err)
- return fmt.Errorf("Unable to get patch file from %s to %s in %s Error: %w", pr.MergeBase, pr.HeadBranch, pr.BaseRepo.FullName(), err)
+ compareArg := pr.MergeBase + "..." + pr.GetGitRefName()
+ switch {
+ case patch:
+ err = gitRepo.GetPatch(compareArg, w)
+ case binary:
+ err = gitRepo.GetDiffBinary(compareArg, w)
+ default:
+ err = gitRepo.GetDiff(compareArg, w)
+ }
+
+ if err != nil {
+ log.Error("unable to get patch file from %s to %s in %s Error: %v", pr.MergeBase, pr.HeadBranch, pr.BaseRepo.FullName(), err)
+ return fmt.Errorf("unable to get patch file from %s to %s in %s Error: %w", pr.MergeBase, pr.HeadBranch, pr.BaseRepo.FullName(), err)
}
return nil
}
@@ -355,7 +364,7 @@ func checkConflicts(ctx context.Context, pr *issues_model.PullRequest, gitRepo *
_ = util.Remove(tmpPatchFile.Name())
}()
- if err := gitRepo.GetDiffBinary(pr.MergeBase, "tracking", tmpPatchFile); err != nil {
+ if err := gitRepo.GetDiffBinary(pr.MergeBase+"...tracking", tmpPatchFile); err != nil {
tmpPatchFile.Close()
log.Error("Unable to get patch file from %s to %s in %s Error: %v", pr.MergeBase, pr.HeadBranch, pr.BaseRepo.FullName(), err)
return false, fmt.Errorf("unable to get patch file from %s to %s in %s Error: %w", pr.MergeBase, pr.HeadBranch, pr.BaseRepo.FullName(), err)
@@ -502,6 +511,29 @@ func checkConflicts(ctx context.Context, pr *issues_model.PullRequest, gitRepo *
return false, nil
}
+// ErrFilePathProtected represents a "FilePathProtected" kind of error.
+type ErrFilePathProtected struct {
+ Message string
+ Path string
+}
+
+// IsErrFilePathProtected checks if an error is an ErrFilePathProtected.
+func IsErrFilePathProtected(err error) bool {
+ _, ok := err.(ErrFilePathProtected)
+ return ok
+}
+
+func (err ErrFilePathProtected) Error() string {
+ if err.Message != "" {
+ return err.Message
+ }
+ return fmt.Sprintf("path is protected and can not be changed [path: %s]", err.Path)
+}
+
+func (err ErrFilePathProtected) Unwrap() error {
+ return util.ErrPermissionDenied
+}
+
// CheckFileProtection check file Protection
func CheckFileProtection(repo *git.Repository, branchName, oldCommitID, newCommitID string, patterns []glob.Glob, limit int, env []string) ([]string, error) {
if len(patterns) == 0 {
@@ -525,7 +557,7 @@ func CheckFileProtection(repo *git.Repository, branchName, oldCommitID, newCommi
}
}
if len(changedProtectedFiles) > 0 {
- err = models.ErrFilePathProtected{
+ err = ErrFilePathProtected{
Path: changedProtectedFiles[0],
}
}
@@ -575,7 +607,7 @@ func checkPullFilesProtection(ctx context.Context, pr *issues_model.PullRequest,
}
pr.ChangedProtectedFiles, err = CheckFileProtection(gitRepo, pr.HeadBranch, pr.MergeBase, "tracking", pb.GetProtectedFilePatterns(), 10, os.Environ())
- if err != nil && !models.IsErrFilePathProtected(err) {
+ if err != nil && !IsErrFilePathProtected(err) {
return err
}
return nil
diff --git a/services/pull/pull.go b/services/pull/pull.go
index 3362cb97ff..0256c2c3f6 100644
--- a/services/pull/pull.go
+++ b/services/pull/pull.go
@@ -13,7 +13,6 @@ import (
"strings"
"time"
- "code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues"
@@ -224,6 +223,28 @@ func NewPullRequest(ctx context.Context, opts *NewPullRequestOptions) error {
return nil
}
+// ErrPullRequestHasMerged represents a "PullRequestHasMerged"-error
+type ErrPullRequestHasMerged struct {
+ ID int64
+ IssueID int64
+ HeadRepoID int64
+ BaseRepoID int64
+ HeadBranch string
+ BaseBranch string
+}
+
+// IsErrPullRequestHasMerged checks if an error is a ErrPullRequestHasMerged.
+func IsErrPullRequestHasMerged(err error) bool {
+ _, ok := err.(ErrPullRequestHasMerged)
+ return ok
+}
+
+// Error does pretty-printing :D
+func (err ErrPullRequestHasMerged) Error() string {
+ return fmt.Sprintf("pull request has merged [id: %d, issue_id: %d, head_repo_id: %d, base_repo_id: %d, head_branch: %s, base_branch: %s]",
+ err.ID, err.IssueID, err.HeadRepoID, err.BaseRepoID, err.HeadBranch, err.BaseBranch)
+}
+
// ChangeTargetBranch changes the target branch of this pull request, as the given user.
func ChangeTargetBranch(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User, targetBranch string) (err error) {
releaser, err := globallock.Lock(ctx, getPullWorkingLockKey(pr.ID))
@@ -247,7 +268,7 @@ func ChangeTargetBranch(ctx context.Context, pr *issues_model.PullRequest, doer
}
if pr.HasMerged {
- return models.ErrPullRequestHasMerged{
+ return ErrPullRequestHasMerged{
ID: pr.ID,
IssueID: pr.Index,
HeadRepoID: pr.HeadRepoID,
@@ -654,7 +675,7 @@ func RetargetBranchPulls(ctx context.Context, doer *user_model.User, repoID int6
if err = pr.Issue.LoadRepo(ctx); err != nil {
errs = append(errs, err)
} else if err = ChangeTargetBranch(ctx, pr, doer, targetBranch); err != nil &&
- !issues_model.IsErrIssueIsClosed(err) && !models.IsErrPullRequestHasMerged(err) &&
+ !issues_model.IsErrIssueIsClosed(err) && !IsErrPullRequestHasMerged(err) &&
!issues_model.IsErrPullRequestAlreadyExists(err) {
errs = append(errs, err)
}
diff --git a/services/release/release.go b/services/release/release.go
index 980a5e98e7..84c60a105a 100644
--- a/services/release/release.go
+++ b/services/release/release.go
@@ -9,7 +9,6 @@ import (
"fmt"
"strings"
- "code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
repo_model "code.gitea.io/gitea/models/repo"
@@ -26,6 +25,44 @@ import (
notify_service "code.gitea.io/gitea/services/notify"
)
+// ErrInvalidTagName represents a "InvalidTagName" kind of error.
+type ErrInvalidTagName struct {
+ TagName string
+}
+
+// IsErrInvalidTagName checks if an error is a ErrInvalidTagName.
+func IsErrInvalidTagName(err error) bool {
+ _, ok := err.(ErrInvalidTagName)
+ return ok
+}
+
+func (err ErrInvalidTagName) Error() string {
+ return fmt.Sprintf("release tag name is not valid [tag_name: %s]", err.TagName)
+}
+
+func (err ErrInvalidTagName) Unwrap() error {
+ return util.ErrInvalidArgument
+}
+
+// ErrProtectedTagName represents a "ProtectedTagName" kind of error.
+type ErrProtectedTagName struct {
+ TagName string
+}
+
+// IsErrProtectedTagName checks if an error is a ErrProtectedTagName.
+func IsErrProtectedTagName(err error) bool {
+ _, ok := err.(ErrProtectedTagName)
+ return ok
+}
+
+func (err ErrProtectedTagName) Error() string {
+ return fmt.Sprintf("release tag name is protected [tag_name: %s]", err.TagName)
+}
+
+func (err ErrProtectedTagName) Unwrap() error {
+ return util.ErrPermissionDenied
+}
+
func createTag(ctx context.Context, gitRepo *git.Repository, rel *repo_model.Release, msg string) (bool, error) {
err := rel.LoadAttributes(ctx)
if err != nil {
@@ -58,7 +95,7 @@ func createTag(ctx context.Context, gitRepo *git.Repository, rel *repo_model.Rel
return false, err
}
if !isAllowed {
- return false, models.ErrProtectedTagName{
+ return false, ErrProtectedTagName{
TagName: rel.TagName,
}
}
@@ -71,7 +108,7 @@ func createTag(ctx context.Context, gitRepo *git.Repository, rel *repo_model.Rel
if len(msg) > 0 {
if err = gitRepo.CreateAnnotatedTag(rel.TagName, msg, commit.ID.String()); err != nil {
if strings.Contains(err.Error(), "is not a valid tag name") {
- return false, models.ErrInvalidTagName{
+ return false, ErrInvalidTagName{
TagName: rel.TagName,
}
}
@@ -79,7 +116,7 @@ func createTag(ctx context.Context, gitRepo *git.Repository, rel *repo_model.Rel
}
} else if err = gitRepo.CreateTag(rel.TagName, commit.ID.String()); err != nil {
if strings.Contains(err.Error(), "is not a valid tag name") {
- return false, models.ErrInvalidTagName{
+ return false, ErrInvalidTagName{
TagName: rel.TagName,
}
}
@@ -159,13 +196,32 @@ func CreateRelease(gitRepo *git.Repository, rel *repo_model.Release, attachmentU
return nil
}
+// ErrTagAlreadyExists represents an error that tag with such name already exists.
+type ErrTagAlreadyExists struct {
+ TagName string
+}
+
+// IsErrTagAlreadyExists checks if an error is an ErrTagAlreadyExists.
+func IsErrTagAlreadyExists(err error) bool {
+ _, ok := err.(ErrTagAlreadyExists)
+ return ok
+}
+
+func (err ErrTagAlreadyExists) Error() string {
+ return fmt.Sprintf("tag already exists [name: %s]", err.TagName)
+}
+
+func (err ErrTagAlreadyExists) Unwrap() error {
+ return util.ErrAlreadyExist
+}
+
// CreateNewTag creates a new repository tag
func CreateNewTag(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, commit, tagName, msg string) error {
has, err := repo_model.IsReleaseExist(ctx, repo.ID, tagName)
if err != nil {
return err
} else if has {
- return models.ErrTagAlreadyExists{
+ return ErrTagAlreadyExists{
TagName: tagName,
}
}
@@ -320,13 +376,12 @@ func DeleteReleaseByID(ctx context.Context, repo *repo_model.Repository, rel *re
return err
}
if !isAllowed {
- return models.ErrProtectedTagName{
+ return ErrProtectedTagName{
TagName: rel.TagName,
}
}
if stdout, _, err := git.NewCommand(ctx, "tag", "-d").AddDashesAndList(rel.TagName).
- SetDescription(fmt.Sprintf("DeleteReleaseByID (git tag -d): %d", rel.ID)).
RunStdString(&git.RunOpts{Dir: repo.RepoPath()}); err != nil && !strings.Contains(err.Error(), "not found") {
log.Error("DeleteReleaseByID (git tag -d): %d in %v Failed:\nStdout: %s\nError: %v", rel.ID, repo, stdout, err)
return fmt.Errorf("git tag -d: %w", err)
diff --git a/services/repository/adopt.go b/services/repository/adopt.go
index 615f4d482c..e37909e7ab 100644
--- a/services/repository/adopt.go
+++ b/services/repository/adopt.go
@@ -92,7 +92,6 @@ func AdoptRepository(ctx context.Context, doer, u *user_model.User, opts CreateR
}
if stdout, _, err := git.NewCommand(ctx, "update-server-info").
- SetDescription(fmt.Sprintf("CreateRepository(git update-server-info): %s", repoPath)).
RunStdString(&git.RunOpts{Dir: repoPath}); err != nil {
log.Error("CreateRepository(git update-server-info) in %v: Stdout: %s\nError: %v", repo, stdout, err)
return fmt.Errorf("CreateRepository(git update-server-info): %w", err)
diff --git a/services/repository/avatar.go b/services/repository/avatar.go
index 38c2621bc4..15e51d4a25 100644
--- a/services/repository/avatar.go
+++ b/services/repository/avatar.go
@@ -8,7 +8,6 @@ import (
"fmt"
"io"
"strconv"
- "strings"
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
@@ -107,7 +106,8 @@ func RemoveRandomAvatars(ctx context.Context) error {
// generateAvatar generates the avatar from a template repository
func generateAvatar(ctx context.Context, templateRepo, generateRepo *repo_model.Repository) error {
- generateRepo.Avatar = strings.Replace(templateRepo.Avatar, strconv.FormatInt(templateRepo.ID, 10), strconv.FormatInt(generateRepo.ID, 10), 1)
+ // generate a new different hash, whatever the "hash data" is, it doesn't matter
+ generateRepo.Avatar = avatar.HashAvatar(generateRepo.ID, []byte("new-avatar"))
if _, err := storage.Copy(storage.RepoAvatars, generateRepo.CustomAvatarRelativePath(), storage.RepoAvatars, templateRepo.CustomAvatarRelativePath()); err != nil {
return err
}
diff --git a/services/repository/avatar_test.go b/services/repository/avatar_test.go
index 4a0ba61853..bea820e85f 100644
--- a/services/repository/avatar_test.go
+++ b/services/repository/avatar_test.go
@@ -61,3 +61,11 @@ func TestDeleteAvatar(t *testing.T) {
assert.Equal(t, "", repo.Avatar)
}
+
+func TestGenerateAvatar(t *testing.T) {
+ templateRepo := &repo_model.Repository{ID: 10, Avatar: "a"}
+ generateRepo := &repo_model.Repository{ID: 11}
+ _ = generateAvatar(db.DefaultContext, templateRepo, generateRepo)
+ assert.NotEmpty(t, generateRepo.Avatar)
+ assert.NotEqual(t, templateRepo.Avatar, generateRepo.Avatar)
+}
diff --git a/services/repository/branch.go b/services/repository/branch.go
index 3a95aab264..fc476298ca 100644
--- a/services/repository/branch.go
+++ b/services/repository/branch.go
@@ -9,7 +9,6 @@ import (
"fmt"
"strings"
- "code.gitea.io/gitea/models"
actions_model "code.gitea.io/gitea/models/actions"
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
@@ -31,6 +30,7 @@ import (
"code.gitea.io/gitea/modules/util"
webhook_module "code.gitea.io/gitea/modules/webhook"
notify_service "code.gitea.io/gitea/services/notify"
+ release_service "code.gitea.io/gitea/services/release"
files_service "code.gitea.io/gitea/services/repository/files"
"xorm.io/builder"
@@ -274,7 +274,7 @@ func checkBranchName(ctx context.Context, repo *repo_model.Repository, name stri
BranchName: branchRefName,
}
case refName == git.TagPrefix+name:
- return models.ErrTagAlreadyExists{
+ return release_service.ErrTagAlreadyExists{
TagName: name,
}
}
diff --git a/services/repository/check.go b/services/repository/check.go
index 5cdcc14679..acca15daf2 100644
--- a/services/repository/check.go
+++ b/services/repository/check.go
@@ -86,8 +86,7 @@ func GitGcRepos(ctx context.Context, timeout time.Duration, args git.TrustedCmdA
// GitGcRepo calls 'git gc' to remove unnecessary files and optimize the local repository
func GitGcRepo(ctx context.Context, repo *repo_model.Repository, timeout time.Duration, args git.TrustedCmdArgs) error {
log.Trace("Running git gc on %-v", repo)
- command := git.NewCommand(ctx, "gc").AddArguments(args...).
- SetDescription(fmt.Sprintf("Repository Garbage Collection: %s", repo.FullName()))
+ command := git.NewCommand(ctx, "gc").AddArguments(args...)
var stdout string
var err error
stdout, _, err = command.RunStdString(&git.RunOpts{Timeout: timeout, Dir: repo.RepoPath()})
diff --git a/services/repository/create.go b/services/repository/create.go
index 14e625d962..a3199f2a40 100644
--- a/services/repository/create.go
+++ b/services/repository/create.go
@@ -68,7 +68,6 @@ func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir,
// Clone to temporary path and do the init commit.
if stdout, _, err := git.NewCommand(ctx, "clone").AddDynamicArguments(repoPath, tmpDir).
- SetDescription(fmt.Sprintf("prepareRepoCommit (git clone): %s to %s", repoPath, tmpDir)).
RunStdString(&git.RunOpts{Dir: "", Env: env}); err != nil {
log.Error("Failed to clone from %v into %s: stdout: %s\nError: %v", repo, tmpDir, stdout, err)
return fmt.Errorf("git clone: %w", err)
@@ -301,7 +300,6 @@ func CreateRepositoryDirectly(ctx context.Context, doer, u *user_model.User, opt
}
if stdout, _, err := git.NewCommand(ctx, "update-server-info").
- SetDescription(fmt.Sprintf("CreateRepository(git update-server-info): %s", repoPath)).
RunStdString(&git.RunOpts{Dir: repoPath}); err != nil {
log.Error("CreateRepository(git update-server-info) in %v: Stdout: %s\nError: %v", repo, stdout, err)
rollbackRepo = repo
@@ -314,9 +312,7 @@ func CreateRepositoryDirectly(ctx context.Context, doer, u *user_model.User, opt
if len(opts.License) > 0 {
licenses = append(licenses, ConvertLicenseName(opts.License))
- stdout, _, err := git.NewCommand(ctx, "rev-parse", "HEAD").
- SetDescription(fmt.Sprintf("CreateRepository(git rev-parse HEAD): %s", repoPath)).
- RunStdString(&git.RunOpts{Dir: repoPath})
+ stdout, _, err := git.NewCommand(ctx, "rev-parse", "HEAD").RunStdString(&git.RunOpts{Dir: repoPath})
if err != nil {
log.Error("CreateRepository(git rev-parse HEAD) in %v: Stdout: %s\nError: %v", repo, stdout, err)
rollbackRepo = repo
diff --git a/services/repository/delete.go b/services/repository/delete.go
index 61e39fe105..2166b4dd5c 100644
--- a/services/repository/delete.go
+++ b/services/repository/delete.go
@@ -317,7 +317,8 @@ func DeleteRepositoryDirectly(ctx context.Context, doer *user_model.User, repoID
if len(repo.Avatar) > 0 {
if err := storage.RepoAvatars.Delete(repo.CustomAvatarRelativePath()); err != nil {
- return fmt.Errorf("Failed to remove %s: %w", repo.Avatar, err)
+ log.Error("remove avatar file %q: %v", repo.CustomAvatarRelativePath(), err)
+ // go on
}
}
diff --git a/services/repository/files/cherry_pick.go b/services/repository/files/cherry_pick.go
index 451a182155..10545e9e03 100644
--- a/services/repository/files/cherry_pick.go
+++ b/services/repository/files/cherry_pick.go
@@ -8,7 +8,6 @@ import (
"fmt"
"strings"
- "code.gitea.io/gitea/models"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git"
@@ -17,6 +16,22 @@ import (
"code.gitea.io/gitea/services/pull"
)
+// ErrCommitIDDoesNotMatch represents a "CommitIDDoesNotMatch" kind of error.
+type ErrCommitIDDoesNotMatch struct {
+ GivenCommitID string
+ CurrentCommitID string
+}
+
+// IsErrCommitIDDoesNotMatch checks if an error is a ErrCommitIDDoesNotMatch.
+func IsErrCommitIDDoesNotMatch(err error) bool {
+ _, ok := err.(ErrCommitIDDoesNotMatch)
+ return ok
+}
+
+func (err ErrCommitIDDoesNotMatch) Error() string {
+ return fmt.Sprintf("file CommitID does not match [given: %s, expected: %s]", err.GivenCommitID, err.CurrentCommitID)
+}
+
// CherryPick cherrypicks or reverts a commit to the given repository
func CherryPick(ctx context.Context, repo *repo_model.Repository, doer *user_model.User, revert bool, opts *ApplyDiffPatchOptions) (*structs.FileResponse, error) {
if err := opts.Validate(ctx, repo, doer); err != nil {
@@ -57,7 +72,7 @@ func CherryPick(ctx context.Context, repo *repo_model.Repository, doer *user_mod
}
opts.LastCommitID = lastCommitID.String()
if commit.ID.String() != opts.LastCommitID {
- return nil, models.ErrCommitIDDoesNotMatch{
+ return nil, ErrCommitIDDoesNotMatch{
GivenCommitID: opts.LastCommitID,
CurrentCommitID: opts.LastCommitID,
}
diff --git a/services/repository/files/content.go b/services/repository/files/content.go
index fa639a25b6..cb39e2b771 100644
--- a/services/repository/files/content.go
+++ b/services/repository/files/content.go
@@ -10,7 +10,6 @@ import (
"path"
"strings"
- "code.gitea.io/gitea/models"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
@@ -53,7 +52,7 @@ func GetContentsOrList(ctx context.Context, repo *repo_model.Repository, treePat
// Check that the path given in opts.treePath is valid (not a git path)
cleanTreePath := CleanUploadFileName(treePath)
if cleanTreePath == "" && treePath != "" {
- return nil, models.ErrFilenameInvalid{
+ return nil, ErrFilenameInvalid{
Path: treePath,
}
}
@@ -128,7 +127,7 @@ func GetContents(ctx context.Context, repo *repo_model.Repository, treePath, ref
// Check that the path given in opts.treePath is valid (not a git path)
cleanTreePath := CleanUploadFileName(treePath)
if cleanTreePath == "" && treePath != "" {
- return nil, models.ErrFilenameInvalid{
+ return nil, ErrFilenameInvalid{
Path: treePath,
}
}
diff --git a/services/repository/files/file.go b/services/repository/files/file.go
index 16783f5b5f..d7ca8e79e5 100644
--- a/services/repository/files/file.go
+++ b/services/repository/files/file.go
@@ -156,6 +156,25 @@ func GetAuthorAndCommitterUsers(author, committer *IdentityOptions, doer *user_m
return authorUser, committerUser
}
+// ErrFilenameInvalid represents a "FilenameInvalid" kind of error.
+type ErrFilenameInvalid struct {
+ Path string
+}
+
+// IsErrFilenameInvalid checks if an error is an ErrFilenameInvalid.
+func IsErrFilenameInvalid(err error) bool {
+ _, ok := err.(ErrFilenameInvalid)
+ return ok
+}
+
+func (err ErrFilenameInvalid) Error() string {
+ return fmt.Sprintf("path contains a malformed path component [path: %s]", err.Path)
+}
+
+func (err ErrFilenameInvalid) Unwrap() error {
+ return util.ErrInvalidArgument
+}
+
// CleanUploadFileName Trims a filename and returns empty string if it is a .git directory
func CleanUploadFileName(name string) string {
// Rebase the filename
diff --git a/services/repository/files/patch.go b/services/repository/files/patch.go
index ab0e7ffd36..38c17b4073 100644
--- a/services/repository/files/patch.go
+++ b/services/repository/files/patch.go
@@ -8,7 +8,6 @@ import (
"fmt"
"strings"
- "code.gitea.io/gitea/models"
git_model "code.gitea.io/gitea/models/git"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
@@ -16,9 +15,29 @@ import (
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/util"
asymkey_service "code.gitea.io/gitea/services/asymkey"
)
+// ErrUserCannotCommit represents "UserCannotCommit" kind of error.
+type ErrUserCannotCommit struct {
+ UserName string
+}
+
+// IsErrUserCannotCommit checks if an error is an ErrUserCannotCommit.
+func IsErrUserCannotCommit(err error) bool {
+ _, ok := err.(ErrUserCannotCommit)
+ return ok
+}
+
+func (err ErrUserCannotCommit) Error() string {
+ return fmt.Sprintf("user cannot commit to repo [user: %s]", err.UserName)
+}
+
+func (err ErrUserCannotCommit) Unwrap() error {
+ return util.ErrPermissionDenied
+}
+
// ApplyDiffPatchOptions holds the repository diff patch update options
type ApplyDiffPatchOptions struct {
LastCommitID string
@@ -74,7 +93,7 @@ func (opts *ApplyDiffPatchOptions) Validate(ctx context.Context, repo *repo_mode
if protectedBranch != nil {
protectedBranch.Repo = repo
if !protectedBranch.CanUserPush(ctx, doer) {
- return models.ErrUserCannotCommit{
+ return ErrUserCannotCommit{
UserName: doer.LowerName,
}
}
@@ -85,7 +104,7 @@ func (opts *ApplyDiffPatchOptions) Validate(ctx context.Context, repo *repo_mode
if !asymkey_service.IsErrWontSign(err) {
return err
}
- return models.ErrUserCannotCommit{
+ return ErrUserCannotCommit{
UserName: doer.LowerName,
}
}
@@ -137,7 +156,7 @@ func ApplyDiffPatch(ctx context.Context, repo *repo_model.Repository, doer *user
}
opts.LastCommitID = lastCommitID.String()
if commit.ID.String() != opts.LastCommitID {
- return nil, models.ErrCommitIDDoesNotMatch{
+ return nil, ErrCommitIDDoesNotMatch{
GivenCommitID: opts.LastCommitID,
CurrentCommitID: opts.LastCommitID,
}
diff --git a/services/repository/files/temp_repo.go b/services/repository/files/temp_repo.go
index 30ab22db1e..138af991f9 100644
--- a/services/repository/files/temp_repo.go
+++ b/services/repository/files/temp_repo.go
@@ -13,7 +13,6 @@ import (
"strings"
"time"
- "code.gitea.io/gitea/models"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git"
@@ -187,7 +186,7 @@ func (t *TemporaryUploadRepository) AddObjectToIndex(mode, objectHash, objectPat
if _, _, err := git.NewCommand(t.ctx, "update-index", "--add", "--replace", "--cacheinfo").AddDynamicArguments(mode, objectHash, objectPath).RunStdString(&git.RunOpts{Dir: t.basePath}); err != nil {
stderr := err.Error()
if matched, _ := regexp.MatchString(".*Invalid path '.*", stderr); matched {
- return models.ErrFilePathInvalid{
+ return ErrFilePathInvalid{
Message: objectPath,
Path: objectPath,
}
diff --git a/services/repository/files/tree.go b/services/repository/files/tree.go
index e3a7f3b8b0..6775186afd 100644
--- a/services/repository/files/tree.go
+++ b/services/repository/files/tree.go
@@ -8,18 +8,37 @@ import (
"fmt"
"net/url"
- "code.gitea.io/gitea/models"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/util"
)
+// ErrSHANotFound represents a "SHADoesNotMatch" kind of error.
+type ErrSHANotFound struct {
+ SHA string
+}
+
+// IsErrSHANotFound checks if an error is a ErrSHANotFound.
+func IsErrSHANotFound(err error) bool {
+ _, ok := err.(ErrSHANotFound)
+ return ok
+}
+
+func (err ErrSHANotFound) Error() string {
+ return fmt.Sprintf("sha not found [%s]", err.SHA)
+}
+
+func (err ErrSHANotFound) Unwrap() error {
+ return util.ErrNotExist
+}
+
// GetTreeBySHA get the GitTreeResponse of a repository using a sha hash.
func GetTreeBySHA(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, sha string, page, perPage int, recursive bool) (*api.GitTreeResponse, error) {
gitTree, err := gitRepo.GetTree(sha)
if err != nil || gitTree == nil {
- return nil, models.ErrSHANotFound{
+ return nil, ErrSHANotFound{ // TODO: this error has never been catch outside of this function
SHA: sha,
}
}
diff --git a/services/repository/files/update.go b/services/repository/files/update.go
index b1b64bacd9..a2763105b0 100644
--- a/services/repository/files/update.go
+++ b/services/repository/files/update.go
@@ -11,7 +11,6 @@ import (
"strings"
"time"
- "code.gitea.io/gitea/models"
git_model "code.gitea.io/gitea/models/git"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
@@ -21,7 +20,9 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/util"
asymkey_service "code.gitea.io/gitea/services/asymkey"
+ pull_service "code.gitea.io/gitea/services/pull"
)
// IdentityOptions for a person's identity like an author or committer
@@ -64,6 +65,26 @@ type RepoFileOptions struct {
executable bool
}
+// ErrRepoFileDoesNotExist represents a "RepoFileDoesNotExist" kind of error.
+type ErrRepoFileDoesNotExist struct {
+ Path string
+ Name string
+}
+
+// IsErrRepoFileDoesNotExist checks if an error is a ErrRepoDoesNotExist.
+func IsErrRepoFileDoesNotExist(err error) bool {
+ _, ok := err.(ErrRepoFileDoesNotExist)
+ return ok
+}
+
+func (err ErrRepoFileDoesNotExist) Error() string {
+ return fmt.Sprintf("repository file does not exist [path: %s]", err.Path)
+}
+
+func (err ErrRepoFileDoesNotExist) Unwrap() error {
+ return util.ErrNotExist
+}
+
// ChangeRepoFiles adds, updates or removes multiple files in the given repository
func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *user_model.User, opts *ChangeRepoFilesOptions) (*structs.FilesResponse, error) {
err := repo.MustNotBeArchived()
@@ -100,14 +121,14 @@ func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use
// Check that the path given in opts.treePath is valid (not a git path)
treePath := CleanUploadFileName(file.TreePath)
if treePath == "" {
- return nil, models.ErrFilenameInvalid{
+ return nil, ErrFilenameInvalid{
Path: file.TreePath,
}
}
// If there is a fromTreePath (we are copying it), also clean it up
fromTreePath := CleanUploadFileName(file.FromTreePath)
if fromTreePath == "" && file.FromTreePath != "" {
- return nil, models.ErrFilenameInvalid{
+ return nil, ErrFilenameInvalid{
Path: file.FromTreePath,
}
}
@@ -185,7 +206,7 @@ func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use
}
}
if !inFilelist {
- return nil, models.ErrRepoFileDoesNotExist{
+ return nil, ErrRepoFileDoesNotExist{
Path: file.TreePath,
}
}
@@ -276,6 +297,63 @@ func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use
return filesResponse, nil
}
+// ErrRepoFileAlreadyExists represents a "RepoFileAlreadyExist" kind of error.
+type ErrRepoFileAlreadyExists struct {
+ Path string
+}
+
+// IsErrRepoFileAlreadyExists checks if an error is a ErrRepoFileAlreadyExists.
+func IsErrRepoFileAlreadyExists(err error) bool {
+ _, ok := err.(ErrRepoFileAlreadyExists)
+ return ok
+}
+
+func (err ErrRepoFileAlreadyExists) Error() string {
+ return fmt.Sprintf("repository file already exists [path: %s]", err.Path)
+}
+
+func (err ErrRepoFileAlreadyExists) Unwrap() error {
+ return util.ErrAlreadyExist
+}
+
+// ErrFilePathInvalid represents a "FilePathInvalid" kind of error.
+type ErrFilePathInvalid struct {
+ Message string
+ Path string
+ Name string
+ Type git.EntryMode
+}
+
+// IsErrFilePathInvalid checks if an error is an ErrFilePathInvalid.
+func IsErrFilePathInvalid(err error) bool {
+ _, ok := err.(ErrFilePathInvalid)
+ return ok
+}
+
+func (err ErrFilePathInvalid) Error() string {
+ if err.Message != "" {
+ return err.Message
+ }
+ return fmt.Sprintf("path is invalid [path: %s]", err.Path)
+}
+
+func (err ErrFilePathInvalid) Unwrap() error {
+ return util.ErrInvalidArgument
+}
+
+// ErrSHAOrCommitIDNotProvided represents a "SHAOrCommitIDNotProvided" kind of error.
+type ErrSHAOrCommitIDNotProvided struct{}
+
+// IsErrSHAOrCommitIDNotProvided checks if an error is a ErrSHAOrCommitIDNotProvided.
+func IsErrSHAOrCommitIDNotProvided(err error) bool {
+ _, ok := err.(ErrSHAOrCommitIDNotProvided)
+ return ok
+}
+
+func (err ErrSHAOrCommitIDNotProvided) Error() string {
+ return "a SHA or commit ID must be proved when updating a file"
+}
+
// handles the check for various issues for ChangeRepoFiles
func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRepoFilesOptions) error {
if file.Operation == "update" || file.Operation == "delete" {
@@ -286,7 +364,7 @@ func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRep
if file.SHA != "" {
// If a SHA was given and the SHA given doesn't match the SHA of the fromTreePath, throw error
if file.SHA != fromEntry.ID.String() {
- return models.ErrSHADoesNotMatch{
+ return pull_service.ErrSHADoesNotMatch{
Path: file.Options.treePath,
GivenSHA: file.SHA,
CurrentSHA: fromEntry.ID.String(),
@@ -299,7 +377,7 @@ func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRep
if changed, err := commit.FileChangedSinceCommit(file.Options.treePath, opts.LastCommitID); err != nil {
return err
} else if changed {
- return models.ErrCommitIDDoesNotMatch{
+ return ErrCommitIDDoesNotMatch{
GivenCommitID: opts.LastCommitID,
CurrentCommitID: opts.LastCommitID,
}
@@ -309,7 +387,7 @@ func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRep
} else {
// When updating a file, a lastCommitID or SHA needs to be given to make sure other commits
// haven't been made. We throw an error if one wasn't provided.
- return models.ErrSHAOrCommitIDNotProvided{}
+ return ErrSHAOrCommitIDNotProvided{}
}
file.Options.executable = fromEntry.IsExecutable()
}
@@ -332,7 +410,7 @@ func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRep
}
if index < len(treePathParts)-1 {
if !entry.IsDir() {
- return models.ErrFilePathInvalid{
+ return ErrFilePathInvalid{
Message: fmt.Sprintf("a file exists where you’re trying to create a subdirectory [path: %s]", subTreePath),
Path: subTreePath,
Name: part,
@@ -340,14 +418,14 @@ func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRep
}
}
} else if entry.IsLink() {
- return models.ErrFilePathInvalid{
+ return ErrFilePathInvalid{
Message: fmt.Sprintf("a symbolic link exists where you’re trying to create a subdirectory [path: %s]", subTreePath),
Path: subTreePath,
Name: part,
Type: git.EntryModeSymlink,
}
} else if entry.IsDir() {
- return models.ErrFilePathInvalid{
+ return ErrFilePathInvalid{
Message: fmt.Sprintf("a directory exists where you’re trying to create a file [path: %s]", subTreePath),
Path: subTreePath,
Name: part,
@@ -355,7 +433,7 @@ func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRep
}
} else if file.Options.fromTreePath != file.Options.treePath || file.Operation == "create" {
// The entry shouldn't exist if we are creating new file or moving to a new path
- return models.ErrRepoFileAlreadyExists{
+ return ErrRepoFileAlreadyExists{
Path: file.Options.treePath,
}
}
@@ -376,7 +454,7 @@ func CreateOrUpdateFile(ctx context.Context, t *TemporaryUploadRepository, file
if file.Operation == "create" {
for _, indexFile := range filesInIndex {
if indexFile == file.TreePath {
- return models.ErrRepoFileAlreadyExists{
+ return ErrRepoFileAlreadyExists{
Path: file.TreePath,
}
}
@@ -479,12 +557,12 @@ func VerifyBranchProtection(ctx context.Context, repo *repo_model.Repository, do
isUnprotectedFile = protectedBranch.IsUnprotectedFile(globUnprotected, treePath)
}
if !canUserPush && !isUnprotectedFile {
- return models.ErrUserCannotCommit{
+ return ErrUserCannotCommit{
UserName: doer.LowerName,
}
}
if protectedBranch.IsProtectedFile(globProtected, treePath) {
- return models.ErrFilePathProtected{
+ return pull_service.ErrFilePathProtected{
Path: treePath,
}
}
@@ -495,7 +573,7 @@ func VerifyBranchProtection(ctx context.Context, repo *repo_model.Repository, do
if !asymkey_service.IsErrWontSign(err) {
return err
}
- return models.ErrUserCannotCommit{
+ return ErrUserCannotCommit{
UserName: doer.LowerName,
}
}
diff --git a/services/repository/fork.go b/services/repository/fork.go
index bc4fdf8562..cff0b1a403 100644
--- a/services/repository/fork.go
+++ b/services/repository/fork.go
@@ -158,7 +158,6 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork
}
repoPath := repo_model.RepoPath(owner.Name, repo.Name)
if stdout, _, err := cloneCmd.AddDynamicArguments(oldRepoPath, repoPath).
- SetDescription(fmt.Sprintf("ForkRepository(git clone): %s to %s", opts.BaseRepo.FullName(), repo.FullName())).
RunStdBytes(&git.RunOpts{Timeout: 10 * time.Minute}); err != nil {
log.Error("Fork Repository (git clone) Failed for %v (from %v):\nStdout: %s\nError: %v", repo, opts.BaseRepo, stdout, err)
return fmt.Errorf("git clone: %w", err)
@@ -169,7 +168,6 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork
}
if stdout, _, err := git.NewCommand(txCtx, "update-server-info").
- SetDescription(fmt.Sprintf("ForkRepository(git update-server-info): %s", repo.FullName())).
RunStdString(&git.RunOpts{Dir: repoPath}); err != nil {
log.Error("Fork Repository (git update-server-info) failed for %v:\nStdout: %s\nError: %v", repo, stdout, err)
return fmt.Errorf("git update-server-info: %w", err)
diff --git a/services/repository/generate.go b/services/repository/generate.go
index f2280de8b2..24cf9d1b9b 100644
--- a/services/repository/generate.go
+++ b/services/repository/generate.go
@@ -237,7 +237,6 @@ func generateRepoCommit(ctx context.Context, repo, templateRepo, generateRepo *r
repoPath := repo.RepoPath()
if stdout, _, err := git.NewCommand(ctx, "remote", "add", "origin").AddDynamicArguments(repoPath).
- SetDescription(fmt.Sprintf("generateRepoCommit (git remote add): %s to %s", templateRepoPath, tmpDir)).
RunStdString(&git.RunOpts{Dir: tmpDir, Env: env}); err != nil {
log.Error("Unable to add %v as remote origin to temporary repo to %s: stdout %s\nError: %v", repo, tmpDir, stdout, err)
return fmt.Errorf("git remote add: %w", err)
@@ -369,7 +368,6 @@ func generateRepository(ctx context.Context, doer, owner *user_model.User, templ
}
if stdout, _, err := git.NewCommand(ctx, "update-server-info").
- SetDescription(fmt.Sprintf("GenerateRepository(git update-server-info): %s", repoPath)).
RunStdString(&git.RunOpts{Dir: repoPath}); err != nil {
log.Error("GenerateRepository(git update-server-info) in %v: Stdout: %s\nError: %v", generateRepo, stdout, err)
return generateRepo, fmt.Errorf("error in GenerateRepository(git update-server-info): %w", err)
diff --git a/services/repository/init.go b/services/repository/init.go
index 817fa4abd7..c719e11786 100644
--- a/services/repository/init.go
+++ b/services/repository/init.go
@@ -34,7 +34,6 @@ func initRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Reposi
committerEmail := sig.Email
if stdout, _, err := git.NewCommand(ctx, "add", "--all").
- SetDescription(fmt.Sprintf("initRepoCommit (git add): %s", tmpPath)).
RunStdString(&git.RunOpts{Dir: tmpPath}); err != nil {
log.Error("git add --all failed: Stdout: %s\nError: %v", stdout, err)
return fmt.Errorf("git add --all: %w", err)
@@ -62,9 +61,8 @@ func initRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Reposi
)
if stdout, _, err := cmd.
- SetDescription(fmt.Sprintf("initRepoCommit (git commit): %s", tmpPath)).
RunStdString(&git.RunOpts{Dir: tmpPath, Env: env}); err != nil {
- log.Error("Failed to commit: %v: Stdout: %s\nError: %v", cmd.String(), stdout, err)
+ log.Error("Failed to commit: %v: Stdout: %s\nError: %v", cmd.LogString(), stdout, err)
return fmt.Errorf("git commit: %w", err)
}
@@ -73,7 +71,6 @@ func initRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Reposi
}
if stdout, _, err := git.NewCommand(ctx, "push", "origin").AddDynamicArguments("HEAD:" + defaultBranch).
- SetDescription(fmt.Sprintf("initRepoCommit (git push): %s", tmpPath)).
RunStdString(&git.RunOpts{Dir: tmpPath, Env: repo_module.InternalPushingEnvironment(u, repo)}); err != nil {
log.Error("Failed to push back to HEAD: Stdout: %s\nError: %v", stdout, err)
return fmt.Errorf("git push: %w", err)
diff --git a/services/repository/migrate.go b/services/repository/migrate.go
index c627b46fab..7fe63eb5ca 100644
--- a/services/repository/migrate.go
+++ b/services/repository/migrate.go
@@ -122,7 +122,6 @@ func MigrateRepositoryGitData(ctx context.Context, u *user_model.User,
}
if stdout, _, err := git.NewCommand(ctx, "update-server-info").
- SetDescription(fmt.Sprintf("MigrateRepositoryGitData(git update-server-info): %s", repoPath)).
RunStdString(&git.RunOpts{Dir: repoPath}); err != nil {
log.Error("MigrateRepositoryGitData(git update-server-info) in %v: Stdout: %s\nError: %v", repo, stdout, err)
return repo, fmt.Errorf("error in MigrateRepositoryGitData(git update-server-info): %w", err)
diff --git a/services/user/update.go b/services/user/update.go
index cbaf90053a..4a39f4f783 100644
--- a/services/user/update.go
+++ b/services/user/update.go
@@ -7,7 +7,6 @@ import (
"context"
"fmt"
- "code.gitea.io/gitea/models"
auth_model "code.gitea.io/gitea/models/auth"
user_model "code.gitea.io/gitea/models/user"
password_module "code.gitea.io/gitea/modules/auth/password"
@@ -113,7 +112,7 @@ func UpdateUser(ctx context.Context, u *user_model.User, opts *UpdateOptions) er
}
if opts.IsAdmin.Has() {
if !opts.IsAdmin.Value() && user_model.IsLastAdminUser(ctx, u) {
- return models.ErrDeleteLastAdminUser{UID: u.ID}
+ return user_model.ErrDeleteLastAdminUser{UID: u.ID}
}
u.IsAdmin = opts.IsAdmin.Value()
diff --git a/services/user/user.go b/services/user/user.go
index 7bde642412..1aeebff142 100644
--- a/services/user/user.go
+++ b/services/user/user.go
@@ -10,7 +10,6 @@ import (
"strings"
"time"
- "code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/organization"
packages_model "code.gitea.io/gitea/models/packages"
@@ -127,7 +126,7 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) error {
}
if u.IsActive && user_model.IsLastAdminUser(ctx, u) {
- return models.ErrDeleteLastAdminUser{UID: u.ID}
+ return user_model.ErrDeleteLastAdminUser{UID: u.ID}
}
if purge {
@@ -225,7 +224,7 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) error {
if err != nil {
return fmt.Errorf("GetRepositoryCount: %w", err)
} else if count > 0 {
- return models.ErrUserOwnRepos{UID: u.ID}
+ return repo_model.ErrUserOwnRepos{UID: u.ID}
}
// Check membership of organization.
@@ -233,14 +232,14 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) error {
if err != nil {
return fmt.Errorf("GetOrganizationCount: %w", err)
} else if count > 0 {
- return models.ErrUserHasOrgs{UID: u.ID}
+ return organization.ErrUserHasOrgs{UID: u.ID}
}
// Check ownership of packages.
if ownsPackages, err := packages_model.HasOwnerPackages(ctx, u.ID); err != nil {
return fmt.Errorf("HasOwnerPackages: %w", err)
} else if ownsPackages {
- return models.ErrUserOwnPackages{UID: u.ID}
+ return packages_model.ErrUserOwnPackages{UID: u.ID}
}
if err := deleteUser(ctx, u, purge); err != nil {
@@ -288,7 +287,7 @@ func DeleteInactiveUsers(ctx context.Context, olderThan time.Duration) error {
for _, u := range inactiveUsers {
if err = DeleteUser(ctx, u, false); err != nil {
// Ignore inactive users that were ever active but then were set inactive by admin
- if models.IsErrUserOwnRepos(err) || models.IsErrUserHasOrgs(err) || models.IsErrUserOwnPackages(err) {
+ if repo_model.IsErrUserOwnRepos(err) || organization.IsErrUserHasOrgs(err) || packages_model.IsErrUserOwnPackages(err) {
log.Warn("Inactive user %q has repositories, organizations or packages, skipping deletion: %v", u.Name, err)
continue
}
diff --git a/services/user/user_test.go b/services/user/user_test.go
index c668b005c5..162a735cd4 100644
--- a/services/user/user_test.go
+++ b/services/user/user_test.go
@@ -9,7 +9,6 @@ import (
"testing"
"time"
- "code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/organization"
@@ -37,7 +36,7 @@ func TestDeleteUser(t *testing.T) {
if len(ownedRepos) > 0 {
err := DeleteUser(db.DefaultContext, user, false)
assert.Error(t, err)
- assert.True(t, models.IsErrUserOwnRepos(err))
+ assert.True(t, repo_model.IsErrUserOwnRepos(err))
return
}
diff --git a/services/webhook/notifier.go b/services/webhook/notifier.go
index cc263947e9..a3d5cb34b1 100644
--- a/services/webhook/notifier.go
+++ b/services/webhook/notifier.go
@@ -410,6 +410,10 @@ func (m *webhookNotifier) CreateIssueComment(ctx context.Context, doer *user_mod
var pullRequest *api.PullRequest
if issue.IsPull {
eventType = webhook_module.HookEventPullRequestComment
+ if err := issue.LoadPullRequest(ctx); err != nil {
+ log.Error("LoadPullRequest: %v", err)
+ return
+ }
pullRequest = convert.ToAPIPullRequest(ctx, issue.PullRequest, doer)
} else {
eventType = webhook_module.HookEventIssueComment
diff --git a/templates/base/head_navbar.tmpl b/templates/base/head_navbar.tmpl
index 951ee590d1..ed7a8d6f24 100644
--- a/templates/base/head_navbar.tmpl
+++ b/templates/base/head_navbar.tmpl
@@ -11,9 +11,9 @@
-