chore: enable forcetypeassert linter, fix issues (#38804)

Enable [`forcetypeassert`](https://github.com/gostaticanalysis/forcetypeassert)
linter to prevent unchecked type assertions. ~650 issues fixed, most
fixes were clean, some use `setting.PanicInDevOrTesting`.

The only behaviour changes are where code would previously send a 500 error
or panic, a 4xx error is now emitted.

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
silverwind
2026-08-09 10:25:06 +00:00
committed by GitHub
co-authored by wxiaoguang
parent fac8bf2eca
commit 76a81b24f9
248 changed files with 1110 additions and 995 deletions
+34 -26
View File
@@ -20,7 +20,6 @@ import (
"gitea.dev/modules/optional"
"gitea.dev/modules/setting"
api "gitea.dev/modules/structs"
"gitea.dev/modules/util"
)
type GiteaContext map[string]any
@@ -318,36 +317,45 @@ func mergeTwoOutputs(o1, o2 map[string]string) map[string]string {
return ret
}
func contextMapValueOrDefault[T any](m map[string]any, key string, defaultValue T) T {
if value, ok := m[key]; ok {
if v, ok := value.(T); ok {
return v
}
}
return defaultValue
}
func (g *GiteaContext) ToGitHubContext() *model.GithubContext {
return &model.GithubContext{
Event: util.GetMapValueOrDefault(*g, "event", map[string]any(nil)),
EventPath: util.GetMapValueOrDefault(*g, "event_path", ""),
Workflow: util.GetMapValueOrDefault(*g, "workflow", ""),
RunID: util.GetMapValueOrDefault(*g, "run_id", ""),
RunNumber: util.GetMapValueOrDefault(*g, "run_number", ""),
Actor: util.GetMapValueOrDefault(*g, "actor", ""),
Repository: util.GetMapValueOrDefault(*g, "repository", ""),
EventName: util.GetMapValueOrDefault(*g, "event_name", ""),
Sha: util.GetMapValueOrDefault(*g, "sha", ""),
Ref: util.GetMapValueOrDefault(*g, "ref", ""),
RefName: util.GetMapValueOrDefault(*g, "ref_name", ""),
RefType: util.GetMapValueOrDefault(*g, "ref_type", ""),
HeadRef: util.GetMapValueOrDefault(*g, "head_ref", ""),
BaseRef: util.GetMapValueOrDefault(*g, "base_ref", ""),
Event: contextMapValueOrDefault(*g, "event", map[string]any(nil)),
EventPath: contextMapValueOrDefault(*g, "event_path", ""),
Workflow: contextMapValueOrDefault(*g, "workflow", ""),
RunID: contextMapValueOrDefault(*g, "run_id", ""),
RunNumber: contextMapValueOrDefault(*g, "run_number", ""),
Actor: contextMapValueOrDefault(*g, "actor", ""),
Repository: contextMapValueOrDefault(*g, "repository", ""),
EventName: contextMapValueOrDefault(*g, "event_name", ""),
Sha: contextMapValueOrDefault(*g, "sha", ""),
Ref: contextMapValueOrDefault(*g, "ref", ""),
RefName: contextMapValueOrDefault(*g, "ref_name", ""),
RefType: contextMapValueOrDefault(*g, "ref_type", ""),
HeadRef: contextMapValueOrDefault(*g, "head_ref", ""),
BaseRef: contextMapValueOrDefault(*g, "base_ref", ""),
Token: "", // deliberately omitted for security
Workspace: util.GetMapValueOrDefault(*g, "workspace", ""),
Action: util.GetMapValueOrDefault(*g, "action", ""),
ActionPath: util.GetMapValueOrDefault(*g, "action_path", ""),
ActionRef: util.GetMapValueOrDefault(*g, "action_ref", ""),
ActionRepository: util.GetMapValueOrDefault(*g, "action_repository", ""),
Job: util.GetMapValueOrDefault(*g, "job", ""),
Workspace: contextMapValueOrDefault(*g, "workspace", ""),
Action: contextMapValueOrDefault(*g, "action", ""),
ActionPath: contextMapValueOrDefault(*g, "action_path", ""),
ActionRef: contextMapValueOrDefault(*g, "action_ref", ""),
ActionRepository: contextMapValueOrDefault(*g, "action_repository", ""),
Job: contextMapValueOrDefault(*g, "job", ""),
JobName: "", // not present in GiteaContext
RepositoryOwner: util.GetMapValueOrDefault(*g, "repository_owner", ""),
RetentionDays: util.GetMapValueOrDefault(*g, "retention_days", ""),
RepositoryOwner: contextMapValueOrDefault(*g, "repository_owner", ""),
RetentionDays: contextMapValueOrDefault(*g, "retention_days", ""),
RunnerPerflog: "", // not present in GiteaContext
RunnerTrackingID: "", // not present in GiteaContext
ServerURL: util.GetMapValueOrDefault(*g, "server_url", ""),
APIURL: util.GetMapValueOrDefault(*g, "api_url", ""),
GraphQLURL: util.GetMapValueOrDefault(*g, "graphql_url", ""),
ServerURL: contextMapValueOrDefault(*g, "server_url", ""),
APIURL: contextMapValueOrDefault(*g, "api_url", ""),
GraphQLURL: contextMapValueOrDefault(*g, "graphql_url", ""),
}
}
+10 -3
View File
@@ -10,6 +10,7 @@ import (
api "gitea.dev/modules/structs"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestWithScheduleInEventPayload(t *testing.T) {
@@ -49,9 +50,15 @@ func TestWithScheduleInEventPayload(t *testing.T) {
event := map[string]any{}
assert.NoError(t, json.Unmarshal([]byte(updated), &event))
assert.Equal(t, "@weekly", event["schedule"])
assert.Equal(t, "test-repo", event["repository"].(map[string]any)["name"])
assert.Equal(t, "test-user", event["sender"].(map[string]any)["login"])
assert.Equal(t, "test-org", event["organization"].(map[string]any)["name"])
repository, ok := event["repository"].(map[string]any)
require.True(t, ok)
assert.Equal(t, "test-repo", repository["name"])
sender, ok := event["sender"].(map[string]any)
require.True(t, ok)
assert.Equal(t, "test-user", sender["login"])
organization, ok := event["organization"].(map[string]any)
require.True(t, ok)
assert.Equal(t, "test-org", organization["name"])
})
t.Run("keeps payload when schedule empty", func(t *testing.T) {
@@ -18,6 +18,8 @@ import (
"gitea.dev/modules/log"
"gitea.dev/modules/setting"
"gitea.dev/modules/util"
"xorm.io/builder"
)
// This file contains functions for creating authorized_principals files
@@ -88,8 +90,8 @@ func rewriteAllPrincipalKeys(ctx context.Context) error {
}
func regeneratePrincipalKeys(ctx context.Context, t io.Writer) error {
if err := db.GetEngine(ctx).Where("type = ?", asymkey_model.KeyTypePrincipal).Iterate(new(asymkey_model.PublicKey), func(idx int, bean any) (err error) {
return asymkey_model.WriteAuthorizedStringForValidKey(bean.(*asymkey_model.PublicKey), t)
if err := db.Iterate(ctx, builder.Eq{"type": asymkey_model.KeyTypePrincipal}, func(ctx context.Context, key *asymkey_model.PublicKey) error {
return asymkey_model.WriteAuthorizedStringForValidKey(key, t)
}); err != nil {
return err
}
+2 -2
View File
@@ -187,8 +187,8 @@ func validateTOTP(req *http.Request, u *user_model.User) error {
}
func GetAccessScope(store DataStore) auth_model.AccessTokenScope {
if v, ok := store.GetData()["ApiTokenScope"]; ok {
return v.(auth_model.AccessTokenScope)
if scope, ok := store.GetData()["ApiTokenScope"].(auth_model.AccessTokenScope); ok {
return scope
}
switch store.GetData()["LoginMethod"] {
case OAuth2TokenMethodName:
+5 -1
View File
@@ -197,7 +197,11 @@ func VerifyCert(r *http.Request) (*asymkey_model.PublicKey, error) {
// doVerify iterates across the provided public keys attempting the verify the current request against each key in turn
func doVerify(verifier httpsig.Verifier, sshPublicKeys []ssh.PublicKey) error {
for _, publicKey := range sshPublicKeys {
cryptoPubkey := publicKey.(ssh.CryptoPublicKey).CryptoPublicKey()
cryptoPublicKey, ok := publicKey.(ssh.CryptoPublicKey)
if !ok {
continue
}
cryptoPubkey := cryptoPublicKey.CryptoPublicKey()
var algos []httpsig.Algorithm
+1 -1
View File
@@ -143,7 +143,7 @@ func (s *SSPI) getConfig(ctx context.Context) (*sspi.Source, error) {
if len(sources) > 1 {
return nil, errors.New("more than one active login source of type SSPI found")
}
return sources[0].Cfg.(*sspi.Source), nil
return auth.MustSourceCfg[*sspi.Source](sources[0]), nil
}
func (s *SSPI) shouldAuthenticate(req *http.Request) (shouldAuth bool) {
+3 -2
View File
@@ -122,8 +122,9 @@ func AccessLogger() func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
start := time.Now()
next.ServeHTTP(w, req)
recorder.record(start, w.(ResponseWriter), req)
respWriter := WrapResponseWriter(w)
next.ServeHTTP(respWriter, req)
recorder.record(start, respWriter, req)
})
}
}
+3 -2
View File
@@ -20,6 +20,7 @@ import (
"gitea.dev/modules/git"
"gitea.dev/modules/httpcache"
"gitea.dev/modules/log"
"gitea.dev/modules/reqctx"
"gitea.dev/modules/setting"
"gitea.dev/modules/util"
"gitea.dev/modules/web"
@@ -56,7 +57,7 @@ func (ctx *APIContext) TokenCanAccessRepo(repo *repo_model.Repository) bool {
func init() {
web.RegisterResponseStatusProvider[*APIContext](func(req *http.Request) web_types.ResponseStatusProvider {
return req.Context().Value(apiContextKey).(*APIContext)
return GetAPIContext(req)
})
}
@@ -185,7 +186,7 @@ var apiContextKey = apiContextKeyType{}
// GetAPIContext returns a context for API routes
func GetAPIContext(req *http.Request) *APIContext {
return req.Context().Value(apiContextKey).(*APIContext)
return reqctx.MustContextValue[*APIContext](req.Context(), apiContextKey)
}
func genAPILinks(curURL *url.URL, total int64, pageSize, curPage int) []string {
+2 -2
View File
@@ -65,10 +65,10 @@ type Context struct {
func init() {
web.RegisterResponseStatusProvider[*Base](func(req *http.Request) web_types.ResponseStatusProvider {
return req.Context().Value(BaseContextKey).(*Base)
return reqctx.MustContextValue[*Base](req.Context(), BaseContextKey)
})
web.RegisterResponseStatusProvider[*Context](func(req *http.Request) web_types.ResponseStatusProvider {
return req.Context().Value(WebContextKey).(*Context)
return reqctx.MustContextValue[*Context](req.Context(), WebContextKey)
})
}
+2 -2
View File
@@ -29,11 +29,11 @@ func NewTemplateContext(ctx context.Context, req *http.Request) TemplateContext
}
func (c TemplateContext) req() *http.Request {
return c["_req"].(*http.Request)
return c["_req"].(*http.Request) //nolint:forcetypeassert // must exist
}
func (c TemplateContext) parentContext() context.Context {
return c["_ctx"].(context.Context)
return c["_ctx"].(context.Context) //nolint:forcetypeassert // must exist
}
func (c TemplateContext) Deadline() (deadline time.Time, ok bool) {
+3 -2
View File
@@ -13,6 +13,7 @@ import (
"gitea.dev/modules/log"
"gitea.dev/modules/private"
"gitea.dev/modules/process"
"gitea.dev/modules/reqctx"
"gitea.dev/modules/web"
web_types "gitea.dev/modules/web/types"
)
@@ -27,7 +28,7 @@ type PrivateContext struct {
func init() {
web.RegisterResponseStatusProvider[*PrivateContext](func(req *http.Request) web_types.ResponseStatusProvider {
return req.Context().Value(privateContextKey).(*PrivateContext)
return GetPrivateContext(req)
})
}
@@ -67,7 +68,7 @@ type privateContextKeyType struct{}
var privateContextKey privateContextKeyType
func GetPrivateContext(req *http.Request) *PrivateContext {
return req.Context().Value(privateContextKey).(*PrivateContext)
return reqctx.MustContextValue[*PrivateContext](req.Context(), privateContextKey)
}
func PrivateContexter() func(http.Handler) http.Handler {
+3 -3
View File
@@ -193,8 +193,8 @@ func PrepareCommitFormOptions(ctx *Context, doer *user_model.User, targetRepo *r
willSign, signKey, _, err := asymkey_service.SignCRUDAction(ctx, doer, targetGitRepo, refName.String())
wontSignReason := ""
if asymkey_service.IsErrWontSign(err) {
wontSignReason = string(err.(*asymkey_service.ErrWontSign).Reason)
if errWontSign, ok := err.(*asymkey_service.ErrWontSign); ok {
wontSignReason = string(errWontSign.Reason)
} else if err != nil {
return nil, err
}
@@ -964,7 +964,7 @@ func RepoRefByType(detectRefType git.RefType) func(*Context) {
ctx.Repo.RefFullName = repoRefFullName(refType, refShortName)
isRenamedBranch, has := ctx.Data["IsRenamedBranch"].(bool)
if isRenamedBranch && has {
renamedBranchName := ctx.Data["RenamedBranchName"].(string)
renamedBranchName := ctx.Data["RenamedBranchName"].(string) //nolint:forcetypeassert // must exist
ctx.Flash.Info(ctx.Tr("repo.branch.renamed", refShortName, renamedBranchName))
link := setting.AppSubURL + strings.Replace(ctx.Req.URL.EscapedPath(), util.PathEscapeSegments(refShortName), util.PathEscapeSegments(renamedBranchName), 1)
ctx.Redirect(link)
+9 -9
View File
@@ -58,11 +58,9 @@ func (t *Task) IsEnabled() bool {
// GetConfig will return a copy of the task's config
func (t *Task) GetConfig() Config {
if reflect.TypeOf(t.config).Kind() == reflect.Pointer {
// Pointer:
return reflect.New(reflect.ValueOf(t.config).Elem().Type()).Interface().(Config)
return reflect.New(reflect.ValueOf(t.config).Elem().Type()).Interface().(Config) //nolint:forcetypeassert // pointer
}
// Not pointer:
return reflect.New(reflect.TypeOf(t.config)).Elem().Interface().(Config)
return reflect.New(reflect.TypeOf(t.config)).Elem().Interface().(Config) //nolint:forcetypeassert // not pointer
}
// Run will run the task incrementing the cron counter with no user defined
@@ -124,9 +122,9 @@ func (t *Task) RunWithUser(doer *user_model.User, config Config) {
if err := t.fun(ctx, doer, config); err != nil {
var message string
var status string
if db.IsErrCancelled(err) {
if errCancelled, ok := err.(db.ErrCancelled); ok {
status = "cancelled"
message = err.(db.ErrCancelled).Message
message = errCancelled.Message
} else {
status = "error"
message = err.Error()
@@ -168,7 +166,7 @@ func GetTask(name string) *Task {
}
// RegisterTask allows a task to be registered with the cron service
func RegisterTask(name string, config Config, fun func(context.Context, *user_model.User, Config) error) error {
func RegisterTask[T Config](name string, config T, fun func(context.Context, *user_model.User, T) error) error {
log.Debug("Registering task: %s", name)
i18nKey := "admin.dashboard." + name
@@ -185,7 +183,9 @@ func RegisterTask(name string, config Config, fun func(context.Context, *user_mo
task := &Task{
Name: name,
config: config,
fun: fun,
fun: func(ctx context.Context, doer *user_model.User, runConfig Config) error {
return fun(ctx, doer, runConfig.(T)) //nolint:forcetypeassert // must be valid
},
}
lock.Lock()
locked := true
@@ -218,7 +218,7 @@ func RegisterTask(name string, config Config, fun func(context.Context, *user_mo
}
// RegisterTaskFatal will register a task but if there is an error log.Fatal
func RegisterTaskFatal(name string, config Config, fun func(context.Context, *user_model.User, Config) error) {
func RegisterTaskFatal[T Config](name string, config T, fun func(context.Context, *user_model.User, T) error) {
if err := RegisterTask(name, config, fun); err != nil {
log.Fatal("Unable to register cron task %s Error: %v", name, err)
}
+5 -5
View File
@@ -27,7 +27,7 @@ func registerStopZombieTasks() {
Enabled: true,
RunAtStart: true,
Schedule: "@every 5m",
}, func(ctx context.Context, _ *user_model.User, cfg Config) error {
}, func(ctx context.Context, _ *user_model.User, _ *BaseConfig) error {
return actions_service.StopZombieTasks(ctx)
})
}
@@ -37,7 +37,7 @@ func registerStopEndlessTasks() {
Enabled: true,
RunAtStart: true,
Schedule: "@every 30m",
}, func(ctx context.Context, _ *user_model.User, cfg Config) error {
}, func(ctx context.Context, _ *user_model.User, _ *BaseConfig) error {
return actions_service.StopEndlessTasks(ctx)
})
}
@@ -47,7 +47,7 @@ func registerCancelAbandonedJobs() {
Enabled: true,
RunAtStart: true,
Schedule: "@every 6h",
}, func(ctx context.Context, _ *user_model.User, cfg Config) error {
}, func(ctx context.Context, _ *user_model.User, _ *BaseConfig) error {
return actions_service.CancelAbandonedJobs(ctx)
})
}
@@ -59,7 +59,7 @@ func registerScheduleTasks() {
Enabled: true,
RunAtStart: false,
Schedule: "@every 1m",
}, func(ctx context.Context, _ *user_model.User, cfg Config) error {
}, func(ctx context.Context, _ *user_model.User, _ *BaseConfig) error {
// Call the function to start schedule tasks and pass the context.
return actions_service.StartScheduleTasks(ctx)
})
@@ -70,7 +70,7 @@ func registerActionsCleanup() {
Enabled: true,
RunAtStart: false,
Schedule: "@midnight",
}, func(ctx context.Context, _ *user_model.User, _ Config) error {
}, func(ctx context.Context, _ *user_model.User, _ *BaseConfig) error {
return actions_service.Cleanup(ctx)
})
}
+17 -24
View File
@@ -36,9 +36,8 @@ func registerUpdateMirrorTask() {
},
PullLimit: 50,
PushLimit: 50,
}, func(ctx context.Context, _ *user_model.User, cfg Config) error {
umtc := cfg.(*UpdateMirrorTaskConfig)
return mirror_service.Update(ctx, umtc.PullLimit, umtc.PushLimit)
}, func(ctx context.Context, _ *user_model.User, cfg *UpdateMirrorTaskConfig) error {
return mirror_service.Update(ctx, cfg.PullLimit, cfg.PushLimit)
})
}
@@ -56,10 +55,9 @@ func registerRepoHealthCheck() {
},
Timeout: time.Duration(setting.Git.Timeout.GC) * time.Second,
Args: []string{},
}, func(ctx context.Context, _ *user_model.User, config Config) error {
rhcConfig := config.(*RepoHealthCheckConfig)
}, func(ctx context.Context, _ *user_model.User, config *RepoHealthCheckConfig) error {
// the git args are set by config, they can be safe to be trusted
return repo_service.GitFsckRepos(ctx, rhcConfig.Timeout, gitcmd.ToTrustedCmdArgs(rhcConfig.Args))
return repo_service.GitFsckRepos(ctx, config.Timeout, gitcmd.ToTrustedCmdArgs(config.Args))
})
}
@@ -68,7 +66,7 @@ func registerCheckRepoStats() {
Enabled: true,
RunAtStart: true,
Schedule: "@midnight",
}, func(ctx context.Context, _ *user_model.User, _ Config) error {
}, func(ctx context.Context, _ *user_model.User, _ *BaseConfig) error {
return repostats.CheckRepoStats(ctx)
})
}
@@ -81,9 +79,8 @@ func registerArchiveCleanup() {
Schedule: "@midnight",
},
OlderThan: 24 * time.Hour,
}, func(ctx context.Context, _ *user_model.User, config Config) error {
acConfig := config.(*OlderThanConfig)
return archiver_service.DeleteOldRepositoryArchives(ctx, acConfig.OlderThan)
}, func(ctx context.Context, _ *user_model.User, config *OlderThanConfig) error {
return archiver_service.DeleteOldRepositoryArchives(ctx, config.OlderThan)
})
}
@@ -95,9 +92,8 @@ func registerSyncExternalUsers() {
Schedule: "@midnight",
},
UpdateExisting: true,
}, func(ctx context.Context, _ *user_model.User, config Config) error {
realConfig := config.(*UpdateExistingConfig)
return auth.SyncExternalUsers(ctx, realConfig.UpdateExisting)
}, func(ctx context.Context, _ *user_model.User, config *UpdateExistingConfig) error {
return auth.SyncExternalUsers(ctx, config.UpdateExisting)
})
}
@@ -109,9 +105,8 @@ func registerDeletedBranchesCleanup() {
Schedule: "@midnight",
},
OlderThan: 24 * time.Hour,
}, func(ctx context.Context, _ *user_model.User, config Config) error {
realConfig := config.(*OlderThanConfig)
git_model.RemoveOldDeletedBranches(ctx, realConfig.OlderThan)
}, func(ctx context.Context, _ *user_model.User, config *OlderThanConfig) error {
git_model.RemoveOldDeletedBranches(ctx, config.OlderThan)
return nil
})
}
@@ -121,7 +116,7 @@ func registerUpdateMigrationPosterID() {
Enabled: true,
RunAtStart: true,
Schedule: "@midnight",
}, func(ctx context.Context, _ *user_model.User, _ Config) error {
}, func(ctx context.Context, _ *user_model.User, _ *BaseConfig) error {
return migrations.UpdateMigrationPosterID(ctx)
})
}
@@ -136,9 +131,8 @@ func registerCleanupHookTaskTable() {
CleanupType: "OlderThan",
OlderThan: 168 * time.Hour,
NumberToKeep: 10,
}, func(ctx context.Context, _ *user_model.User, config Config) error {
realConfig := config.(*CleanupHookTaskConfig)
return webhook.CleanupHookTaskTable(ctx, webhook.ToHookTaskCleanupType(realConfig.CleanupType), realConfig.OlderThan, realConfig.NumberToKeep)
}, func(ctx context.Context, _ *user_model.User, config *CleanupHookTaskConfig) error {
return webhook.CleanupHookTaskTable(ctx, webhook.ToHookTaskCleanupType(config.CleanupType), config.OlderThan, config.NumberToKeep)
})
}
@@ -150,9 +144,8 @@ func registerCleanupPackages() {
Schedule: "@midnight",
},
OlderThan: 24 * time.Hour,
}, func(ctx context.Context, _ *user_model.User, config Config) error {
realConfig := config.(*OlderThanConfig)
return packages_cleanup_service.CleanupTask(ctx, realConfig.OlderThan)
}, func(ctx context.Context, _ *user_model.User, config *OlderThanConfig) error {
return packages_cleanup_service.CleanupTask(ctx, config.OlderThan)
})
}
@@ -161,7 +154,7 @@ func registerSyncRepoLicenses() {
Enabled: false,
RunAtStart: false,
Schedule: "@annually",
}, func(ctx context.Context, _ *user_model.User, config Config) error {
}, func(ctx context.Context, _ *user_model.User, _ *BaseConfig) error {
return repo_service.SyncRepoLicenses(ctx)
})
}
+21 -27
View File
@@ -28,9 +28,8 @@ func registerDeleteInactiveUsers() {
Schedule: "@annually",
},
OlderThan: time.Minute * time.Duration(setting.Service.ActiveCodeLives),
}, func(ctx context.Context, _ *user_model.User, config Config) error {
olderThanConfig := config.(*OlderThanConfig)
return user_service.DeleteInactiveUsers(ctx, olderThanConfig.OlderThan)
}, func(ctx context.Context, _ *user_model.User, config *OlderThanConfig) error {
return user_service.DeleteInactiveUsers(ctx, config.OlderThan)
})
}
@@ -39,7 +38,7 @@ func registerDeleteRepositoryArchives() {
Enabled: false,
RunAtStart: false,
Schedule: "@annually",
}, func(ctx context.Context, _ *user_model.User, _ Config) error {
}, func(ctx context.Context, _ *user_model.User, _ *BaseConfig) error {
return archiver_service.DeleteRepositoryArchives(ctx)
})
}
@@ -58,10 +57,9 @@ func registerGarbageCollectRepositories() {
},
Timeout: time.Duration(setting.Git.Timeout.GC) * time.Second,
Args: setting.Git.GCArgs,
}, func(ctx context.Context, _ *user_model.User, config Config) error {
rhcConfig := config.(*RepoHealthCheckConfig)
}, func(ctx context.Context, _ *user_model.User, config *RepoHealthCheckConfig) error {
// the git args are set by config, they can be safe to be trusted
return repo_service.GitGcRepos(ctx, rhcConfig.Timeout, gitcmd.ToTrustedCmdArgs(rhcConfig.Args))
return repo_service.GitGcRepos(ctx, config.Timeout, gitcmd.ToTrustedCmdArgs(config.Args))
})
}
@@ -70,7 +68,7 @@ func registerRewriteAllPublicKeys() {
Enabled: false,
RunAtStart: false,
Schedule: "@every 72h",
}, func(ctx context.Context, _ *user_model.User, _ Config) error {
}, func(ctx context.Context, _ *user_model.User, _ *BaseConfig) error {
return asymkey_service.RewriteAllPublicKeys(ctx)
})
}
@@ -80,7 +78,7 @@ func registerRewriteAllPrincipalKeys() {
Enabled: false,
RunAtStart: false,
Schedule: "@every 72h",
}, func(ctx context.Context, _ *user_model.User, _ Config) error {
}, func(ctx context.Context, _ *user_model.User, _ *BaseConfig) error {
return asymkey_service.RewriteAllPrincipalKeys(ctx)
})
}
@@ -90,7 +88,7 @@ func registerRepositoryUpdateHook() {
Enabled: false,
RunAtStart: false,
Schedule: "@every 72h",
}, func(ctx context.Context, _ *user_model.User, _ Config) error {
}, func(ctx context.Context, _ *user_model.User, _ *BaseConfig) error {
return repo_service.SyncRepositoryHooks(ctx)
})
}
@@ -100,7 +98,7 @@ func registerReinitMissingRepositories() {
Enabled: false,
RunAtStart: false,
Schedule: "@every 72h",
}, func(ctx context.Context, _ *user_model.User, _ Config) error {
}, func(ctx context.Context, _ *user_model.User, _ *BaseConfig) error {
return repo_service.ReinitMissingRepositories(ctx)
})
}
@@ -110,7 +108,7 @@ func registerDeleteMissingRepositories() {
Enabled: false,
RunAtStart: false,
Schedule: "@every 72h",
}, func(ctx context.Context, user *user_model.User, _ Config) error {
}, func(ctx context.Context, user *user_model.User, _ *BaseConfig) error {
return repo_service.DeleteMissingRepositories(ctx, user)
})
}
@@ -120,7 +118,7 @@ func registerRemoveRandomAvatars() {
Enabled: false,
RunAtStart: false,
Schedule: "@every 72h",
}, func(ctx context.Context, _ *user_model.User, _ Config) error {
}, func(ctx context.Context, _ *user_model.User, _ *BaseConfig) error {
return repo_service.RemoveRandomAvatars(ctx)
})
}
@@ -133,9 +131,8 @@ func registerDeleteOldActions() {
Schedule: "@every 168h",
},
OlderThan: 365 * 24 * time.Hour,
}, func(ctx context.Context, _ *user_model.User, config Config) error {
olderThanConfig := config.(*OlderThanConfig)
return activities_model.DeleteOldActions(ctx, olderThanConfig.OlderThan)
}, func(ctx context.Context, _ *user_model.User, config *OlderThanConfig) error {
return activities_model.DeleteOldActions(ctx, config.OlderThan)
})
}
@@ -151,9 +148,8 @@ func registerUpdateGiteaChecker() {
Schedule: "@every 168h",
},
HTTPEndpoint: "https://dl.gitea.com/gitea/version.json",
}, func(ctx context.Context, _ *user_model.User, config Config) error {
updateCheckerConfig := config.(*UpdateCheckerConfig)
return updatechecker.GiteaUpdateChecker(updateCheckerConfig.HTTPEndpoint)
}, func(ctx context.Context, _ *user_model.User, config *UpdateCheckerConfig) error {
return updatechecker.GiteaUpdateChecker(config.HTTPEndpoint)
})
}
@@ -165,9 +161,8 @@ func registerDeleteOldSystemNotices() {
Schedule: "@every 168h",
},
OlderThan: 365 * 24 * time.Hour,
}, func(ctx context.Context, _ *user_model.User, config Config) error {
olderThanConfig := config.(*OlderThanConfig)
return system.DeleteOldSystemNotices(ctx, olderThanConfig.OlderThan)
}, func(ctx context.Context, _ *user_model.User, config *OlderThanConfig) error {
return system.DeleteOldSystemNotices(ctx, config.OlderThan)
})
}
@@ -204,12 +199,11 @@ func registerGCLFS() {
LastUpdatedMoreThanAgo: 24 * time.Hour * 3,
NumberToCheckPerRepo: 100,
ProportionToCheckPerRepo: 0.6,
}, func(ctx context.Context, _ *user_model.User, config Config) error {
gcLFSConfig := config.(*GCLFSConfig)
}, func(ctx context.Context, _ *user_model.User, config *GCLFSConfig) error {
return repo_service.GarbageCollectLFSMetaObjects(ctx, repo_service.GarbageCollectLFSMetaObjectsOptions{
AutoFix: true,
OlderThan: time.Now().Add(-gcLFSConfig.OlderThan),
UpdatedLessRecentlyThan: time.Now().Add(-gcLFSConfig.LastUpdatedMoreThanAgo),
OlderThan: time.Now().Add(-config.OlderThan),
UpdatedLessRecentlyThan: time.Now().Add(-config.LastUpdatedMoreThanAgo),
})
})
}
@@ -219,7 +213,7 @@ func registerRebuildIssueIndexer() {
Enabled: false,
RunAtStart: false,
Schedule: "@annually",
}, func(ctx context.Context, _ *user_model.User, config Config) error {
}, func(ctx context.Context, _ *user_model.User, _ *BaseConfig) error {
return issue_indexer.PopulateIssueIndexer(ctx)
})
}
+2 -2
View File
@@ -71,7 +71,7 @@ func checkUserStarNum(ctx context.Context, logger log.Logger, autofix bool) erro
func checkDaemonExport(ctx context.Context, logger log.Logger, autofix bool) error {
numRepos := 0
numNeedUpdate := 0
cache, err := lru.New[int64, any](512)
cache, err := lru.New[int64, *user_model.User](512)
if err != nil {
logger.Critical("Unable to create cache: %v", err)
return err
@@ -80,7 +80,7 @@ func checkDaemonExport(ctx context.Context, logger log.Logger, autofix bool) err
numRepos++
if owner, has := cache.Get(repo.OwnerID); has {
repo.Owner = owner.(*user_model.User)
repo.Owner = owner
} else {
if err := repo.LoadOwner(ctx); err != nil {
return err
+6 -6
View File
@@ -81,7 +81,7 @@ type rsaSingingKey struct {
}
func newRSASingingKey(signingMethod jwt.SigningMethod, key *rsa.PrivateKey) (rsaSingingKey, error) {
kid, err := util.CreatePublicKeyFingerprint(key.Public().(*rsa.PublicKey))
kid, err := util.CreatePublicKeyFingerprint(&key.PublicKey)
if err != nil {
return rsaSingingKey{}, err
}
@@ -110,7 +110,7 @@ func (key rsaSingingKey) VerifyKey() any {
}
func (key rsaSingingKey) ToJWK() (map[string]string, error) {
pubKey := key.key.Public().(*rsa.PublicKey)
pubKey := &key.key.PublicKey
return map[string]string{
"kty": "RSA",
@@ -132,7 +132,7 @@ type eddsaSigningKey struct {
}
func newEdDSASingingKey(signingMethod jwt.SigningMethod, key ed25519.PrivateKey) (eddsaSigningKey, error) {
kid, err := util.CreatePublicKeyFingerprint(key.Public().(ed25519.PublicKey))
kid, err := util.CreatePublicKeyFingerprint(key.Public().(ed25519.PublicKey)) //nolint:forcetypeassert // ed25519.PrivateKey.Public always returns ed25519.PublicKey
if err != nil {
return eddsaSigningKey{}, err
}
@@ -161,7 +161,7 @@ func (key eddsaSigningKey) VerifyKey() any {
}
func (key eddsaSigningKey) ToJWK() (map[string]string, error) {
pubKey := key.key.Public().(ed25519.PublicKey)
pubKey := key.key.Public().(ed25519.PublicKey) //nolint:forcetypeassert // ed25519.PrivateKey.Public always returns ed25519.PublicKey
return map[string]string{
"alg": key.SigningMethod().Alg(),
@@ -183,7 +183,7 @@ type ecdsaSingingKey struct {
}
func newECDSASingingKey(signingMethod jwt.SigningMethod, key *ecdsa.PrivateKey) (ecdsaSingingKey, error) {
kid, err := util.CreatePublicKeyFingerprint(key.Public().(*ecdsa.PublicKey))
kid, err := util.CreatePublicKeyFingerprint(&key.PublicKey)
if err != nil {
return ecdsaSingingKey{}, err
}
@@ -212,7 +212,7 @@ func (key ecdsaSingingKey) VerifyKey() any {
}
func (key ecdsaSingingKey) ToJWK() (map[string]string, error) {
pubKey := key.key.Public().(*ecdsa.PublicKey)
pubKey := &key.key.PublicKey
// PublicKey.Bytes returns the uncompressed SEC 1 format: 0x04 || X || Y
pubKeyBytes, err := pubKey.Bytes()
@@ -53,7 +53,8 @@ func TestECDSASigningKeyToJWK(t *testing.T) {
assert.Len(t, yBytes, tc.coordLen)
// Verify the decoded coordinates reconstruct the original public key point
pubKey := privKey.Public().(*ecdsa.PublicKey)
pubKey, ok := privKey.Public().(*ecdsa.PublicKey)
require.True(t, ok)
assert.Equal(t, 0, new(big.Int).SetBytes(xBytes).Cmp(pubKey.X))
assert.Equal(t, 0, new(big.Int).SetBytes(yBytes).Cmp(pubKey.Y))
})
+1 -1
View File
@@ -162,7 +162,7 @@ func BuildPackageIndex(ctx context.Context, p *packages_model.Package) (*bytes.B
var b bytes.Buffer
for _, pd := range pds {
metadata := pd.Metadata.(*cargo_module.Metadata)
metadata := packages_model.DescriptorMetadata[*cargo_module.Metadata](pd)
dependencies := metadata.Dependencies
if dependencies == nil {
+2 -1
View File
@@ -38,7 +38,8 @@ func TestRedisBroker(t *testing.T) {
// RedisBroker tears down its per-topic Redis subscription and internal
// state once the last local subscriber cancels.
t.Run("CancelCleansTopicState", func(t *testing.T) {
b := newBroker(t).(*RedisBroker)
b, isRedisBroker := newBroker(t).(*RedisBroker)
require.True(t, isRedisBroker)
ch, cancel := b.Subscribe(t.Name())
cancel()
+1 -2
View File
@@ -595,8 +595,7 @@ func pushToBaseRepoHelper(ctx context.Context, pr *issues_model.PullRequest, pre
// This should not happen as we're using force!
log.Error("Unable to push PR head for %s#%d (%-v:%s) due to ErrPushOfDate: %v", pr.BaseRepo.FullName(), pr.Index, pr.BaseRepo, gitRefName, err)
return err
} else if git.IsErrPushRejected(err) {
rejectErr := err.(*git.ErrPushRejected)
} else if rejectErr, ok := err.(*git.ErrPushRejected); ok {
log.Info("Unable to push PR head for %s#%d (%-v:%s) due to rejection:\nStdout: %s\nStderr: %s\nError: %v", pr.BaseRepo.FullName(), pr.Index, pr.BaseRepo, gitRefName, rejectErr.StdOut, rejectErr.StdErr, rejectErr.Err)
return err
} else if git.IsErrMoreThanOne(err) {
+8 -4
View File
@@ -27,15 +27,19 @@ import (
)
func handleCreateError(owner *user_model.User, err error) error {
var (
errNameReserved db.ErrNameReserved
errNamePatternNotAllowed db.ErrNamePatternNotAllowed
)
switch {
case repo_model.IsErrReachLimitOfRepo(err):
return fmt.Errorf("you have already reached your limit of %d repositories", owner.MaxCreationLimit())
case repo_model.IsErrRepoAlreadyExist(err):
return errors.New("the repository name is already used")
case db.IsErrNameReserved(err):
return fmt.Errorf("the repository name '%s' is reserved", err.(db.ErrNameReserved).Name)
case db.IsErrNamePatternNotAllowed(err):
return fmt.Errorf("the pattern '%s' is not allowed in a repository name", err.(db.ErrNamePatternNotAllowed).Pattern)
case errors.As(err, &errNameReserved):
return fmt.Errorf("the repository name '%s' is reserved", errNameReserved.Name)
case errors.As(err, &errNamePatternNotAllowed):
return fmt.Errorf("the pattern '%s' is not allowed in a repository name", errNamePatternNotAllowed.Pattern)
default:
return err
}
+4 -4
View File
@@ -149,8 +149,8 @@ func parseThemeMetaInfo(fileName, cssContent string) *ThemeMetaInfo {
return themeInfo
}
func collectThemeFiles(dirFS fs.ReadDirFS, fsPath string) (themes []*ThemeMetaInfo, _ error) {
files, err := dirFS.ReadDir(fsPath)
func collectThemeFiles(dirFS fs.FS, fsPath string) (themes []*ThemeMetaInfo, _ error) {
files, err := fs.ReadDir(dirFS, fsPath)
if err != nil {
return nil, err
}
@@ -170,12 +170,12 @@ func collectThemeFiles(dirFS fs.ReadDirFS, fsPath string) (themes []*ThemeMetaIn
}
func loadThemesFromAssets(isViteDevMode bool) (themeList []*ThemeMetaInfo, themeMap map[string]*ThemeMetaInfo) {
var themeDir fs.ReadDirFS
var themeDir fs.FS
var themePath string
if isViteDevMode {
// In vite dev mode, Vite serves themes directly from source files.
themeDir, themePath = os.DirFS(setting.StaticRootPath).(fs.ReadDirFS), "web_src/css/themes"
themeDir, themePath = os.DirFS(setting.StaticRootPath), "web_src/css/themes"
} else {
// Without vite dev server, use built assets from AssetFS.
themeDir, themePath = public.AssetFS(), "assets/css"