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
+1
View File
@@ -11,6 +11,7 @@ linters:
- dupl - dupl
- errcheck - errcheck
- forbidigo - forbidigo
- forcetypeassert
- gocheckcompilerdirectives - gocheckcompilerdirectives
- gocritic - gocritic
- govet - govet
+27 -17
View File
@@ -354,13 +354,10 @@ func findLdapSecurityProtocolByName(name string) (ldap.SecurityProtocol, bool) {
return 0, false return 0, false
} }
// getAuthSource gets the login source by its id defined in the command line flags. // getAuthSourceOfType gets the login source by id.
// It returns an error if the id is not set, does not match any source or if the source is not of expected type. // It returns an error if the id does not match any source or if the source is not of the expected type.
func (a *authService) getAuthSource(ctx context.Context, c *cli.Command, authType auth.Type) (*auth.Source, error) { func (a *authService) getAuthSourceOfType(ctx context.Context, id int64, authType auth.Type) (*auth.Source, error) {
if err := argsSet(c, "id"); err != nil { authSource, err := a.getAuthSourceByID(ctx, id)
return nil, err
}
authSource, err := a.getAuthSourceByID(ctx, c.Int64("id"))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -372,6 +369,15 @@ func (a *authService) getAuthSource(ctx context.Context, c *cli.Command, authTyp
return authSource, nil return authSource, nil
} }
// getAuthSource gets the login source by its id defined in the command line flags.
// It returns an error if the id is not set, does not match any source or if the source is not of expected type.
func (a *authService) getAuthSource(ctx context.Context, c *cli.Command, authType auth.Type) (*auth.Source, error) {
if err := argsSet(c, "id"); err != nil {
return nil, err
}
return a.getAuthSourceOfType(ctx, c.Int64("id"), authType)
}
// addLdapBindDn adds a new LDAP via Bind DN authentication source. // addLdapBindDn adds a new LDAP via Bind DN authentication source.
func (a *authService) addLdapBindDn(ctx context.Context, c *cli.Command) error { func (a *authService) addLdapBindDn(ctx context.Context, c *cli.Command) error {
if err := argsSet(c, "name", "security-protocol", "host", "port", "user-search-base", "user-filter", "email-attribute"); err != nil { if err := argsSet(c, "name", "security-protocol", "host", "port", "user-search-base", "user-filter", "email-attribute"); err != nil {
@@ -381,16 +387,17 @@ func (a *authService) addLdapBindDn(ctx context.Context, c *cli.Command) error {
return err return err
} }
ldapConfig := &ldap.Source{
Enabled: true, // always true
}
authSource := &auth.Source{ authSource := &auth.Source{
Type: auth.LDAP, Type: auth.LDAP,
IsActive: true, // active by default IsActive: true, // active by default
Cfg: &ldap.Source{ Cfg: ldapConfig,
Enabled: true, // always true
},
} }
parseAuthSourceLdap(c, authSource) parseAuthSourceLdap(c, authSource)
if err := parseLdapConfig(c, authSource.Cfg.(*ldap.Source)); err != nil { if err := parseLdapConfig(c, ldapConfig); err != nil {
return err return err
} }
@@ -407,9 +414,10 @@ func (a *authService) updateLdapBindDn(ctx context.Context, c *cli.Command) erro
if err != nil { if err != nil {
return err return err
} }
ldapConfig := auth.MustSourceCfg[*ldap.Source](authSource)
parseAuthSourceLdap(c, authSource) parseAuthSourceLdap(c, authSource)
if err := parseLdapConfig(c, authSource.Cfg.(*ldap.Source)); err != nil { if err := parseLdapConfig(c, ldapConfig); err != nil {
return err return err
} }
@@ -426,16 +434,17 @@ func (a *authService) addLdapSimpleAuth(ctx context.Context, c *cli.Command) err
return err return err
} }
ldapConfig := &ldap.Source{
Enabled: true, // always true
}
authSource := &auth.Source{ authSource := &auth.Source{
Type: auth.DLDAP, Type: auth.DLDAP,
IsActive: true, // active by default IsActive: true, // active by default
Cfg: &ldap.Source{ Cfg: ldapConfig,
Enabled: true, // always true
},
} }
parseAuthSourceLdap(c, authSource) parseAuthSourceLdap(c, authSource)
if err := parseLdapConfig(c, authSource.Cfg.(*ldap.Source)); err != nil { if err := parseLdapConfig(c, ldapConfig); err != nil {
return err return err
} }
@@ -452,9 +461,10 @@ func (a *authService) updateLdapSimpleAuth(ctx context.Context, c *cli.Command)
if err != nil { if err != nil {
return err return err
} }
ldapConfig := auth.MustSourceCfg[*ldap.Source](authSource)
parseAuthSourceLdap(c, authSource) parseAuthSourceLdap(c, authSource)
if err := parseLdapConfig(c, authSource.Cfg.(*ldap.Source)); err != nil { if err := parseLdapConfig(c, ldapConfig); err != nil {
return err return err
} }
+2 -3
View File
@@ -221,12 +221,11 @@ func (a *authService) runUpdateOauth(ctx context.Context, c *cli.Command) error
return err return err
} }
source, err := a.getAuthSourceByID(ctx, c.Int64("id")) source, err := a.getAuthSourceOfType(ctx, c.Int64("id"), auth_model.OAuth2)
if err != nil { if err != nil {
return err return err
} }
oAuth2Config := auth_model.MustSourceCfg[*oauth2.Source](source)
oAuth2Config := source.Cfg.(*oauth2.Source)
if c.IsSet("name") { if c.IsSet("name") {
source.Name = c.String("name") source.Name = c.String("name")
+2 -3
View File
@@ -175,12 +175,11 @@ func (a *authService) runUpdateSMTP(ctx context.Context, c *cli.Command) error {
return err return err
} }
source, err := a.getAuthSourceByID(ctx, c.Int64("id")) source, err := a.getAuthSourceOfType(ctx, c.Int64("id"), auth_model.SMTP)
if err != nil { if err != nil {
return err return err
} }
smtpConfig := auth_model.MustSourceCfg[*smtp.Source](source)
smtpConfig := source.Cfg.(*smtp.Source)
if err := parseSMTPConfig(c, smtpConfig); err != nil { if err := parseSMTPConfig(c, smtpConfig); err != nil {
return err return err
+5 -4
View File
@@ -5,6 +5,7 @@ package v1_14
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"strings" "strings"
@@ -106,8 +107,8 @@ func FixPublisherIDforTagReleases(ctx context.Context, x base.EngineMigration) e
commit, err := gitRepo.GetTagCommit(ctx, release.TagName) commit, err := gitRepo.GetTagCommit(ctx, release.TagName)
if err != nil { if err != nil {
if git.IsErrNotExist(err) { if errNotExist, ok := errors.AsType[git.ErrNotExist](err); ok {
log.Warn("Unable to find commit %s for Tag: %s in [%d]%s/%s. Cannot update publisher ID.", err.(git.ErrNotExist).ID, release.TagName, repo.ID, repo.OwnerName, repo.Name) log.Warn("Unable to find commit %s for Tag: %s in [%d]%s/%s. Cannot update publisher ID.", errNotExist.ID, release.TagName, repo.ID, repo.OwnerName, repo.Name)
continue continue
} }
log.Error("Error whilst getting commit for Tag: %s in [%d]%s/%s. Error: %v", release.TagName, repo.ID, repo.OwnerName, repo.Name, err) log.Error("Error whilst getting commit for Tag: %s in [%d]%s/%s. Error: %v", release.TagName, repo.ID, repo.OwnerName, repo.Name, err)
@@ -118,8 +119,8 @@ func FixPublisherIDforTagReleases(ctx context.Context, x base.EngineMigration) e
log.Warn("Tag: %s in Repo[%d]%s/%s does not have a tagger.", release.TagName, repo.ID, repo.OwnerName, repo.Name) log.Warn("Tag: %s in Repo[%d]%s/%s does not have a tagger.", release.TagName, repo.ID, repo.OwnerName, repo.Name)
commit, err = gitRepo.GetCommit(ctx, commit.ID.String()) commit, err = gitRepo.GetCommit(ctx, commit.ID.String())
if err != nil { if err != nil {
if git.IsErrNotExist(err) { if errNotExist, ok := errors.AsType[git.ErrNotExist](err); ok {
log.Warn("Unable to find commit %s for Tag: %s in [%d]%s/%s. Cannot update publisher ID.", err.(git.ErrNotExist).ID, release.TagName, repo.ID, repo.OwnerName, repo.Name) log.Warn("Unable to find commit %s for Tag: %s in [%d]%s/%s. Cannot update publisher ID.", errNotExist.ID, release.TagName, repo.ID, repo.OwnerName, repo.Name)
continue continue
} }
log.Error("Error whilst getting commit for Tag: %s in [%d]%s/%s. Error: %v", release.TagName, repo.ID, repo.OwnerName, repo.Name, err) log.Error("Error whilst getting commit for Tag: %s in [%d]%s/%s. Error: %v", release.TagName, repo.ID, repo.OwnerName, repo.Name, err)
+6 -6
View File
@@ -51,16 +51,16 @@ func AddPullRequestRebaseWithMerge(_ context.Context, x base.EngineMigration) er
// Allow the new merge style if all other merge styles are allowed // Allow the new merge style if all other merge styles are allowed
allowMergeRebase := true allowMergeRebase := true
if allowMerge, ok := unit.Config["AllowMerge"]; ok { if allowMerge, ok := unit.Config["AllowMerge"].(bool); ok {
allowMergeRebase = allowMergeRebase && allowMerge.(bool) allowMergeRebase = allowMergeRebase && allowMerge
} }
if allowRebase, ok := unit.Config["AllowRebase"]; ok { if allowRebase, ok := unit.Config["AllowRebase"].(bool); ok {
allowMergeRebase = allowMergeRebase && allowRebase.(bool) allowMergeRebase = allowMergeRebase && allowRebase
} }
if allowSquash, ok := unit.Config["AllowSquash"]; ok { if allowSquash, ok := unit.Config["AllowSquash"].(bool); ok {
allowMergeRebase = allowMergeRebase && allowSquash.(bool) allowMergeRebase = allowMergeRebase && allowSquash
} }
if _, ok := unit.Config["AllowRebaseMerge"]; !ok { if _, ok := unit.Config["AllowRebaseMerge"]; !ok {
+3 -2
View File
@@ -20,6 +20,7 @@ import (
"gitea.dev/modules/util" "gitea.dev/modules/util"
"golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh"
"xorm.io/builder"
) )
// AuthorizedStringCommentPrefix is a magic tag // AuthorizedStringCommentPrefix is a magic tag
@@ -162,8 +163,8 @@ func appendAuthorizedKeysToFile(keys ...*PublicKey) error {
// RegeneratePublicKeys regenerates the authorized_keys file // RegeneratePublicKeys regenerates the authorized_keys file
func RegeneratePublicKeys(ctx context.Context, t io.Writer) error { func RegeneratePublicKeys(ctx context.Context, t io.Writer) error {
if err := db.GetEngine(ctx).Where("type != ?", KeyTypePrincipal).Iterate(new(PublicKey), func(idx int, bean any) (err error) { if err := db.Iterate(ctx, builder.Neq{"type": KeyTypePrincipal}, func(ctx context.Context, key *PublicKey) error {
return WriteAuthorizedStringForValidKey(bean.(*PublicKey), t) return WriteAuthorizedStringForValidKey(key, t)
}); err != nil { }); err != nil {
return err return err
} }
+16 -20
View File
@@ -98,20 +98,12 @@ type RegisterableSource interface {
var registeredConfigs = map[Type]func() Config{} var registeredConfigs = map[Type]func() Config{}
// RegisterTypeConfig register a config for a provided type // RegisterTypeConfig register a config for a provided type, the exemplar argument only serves type inference
func RegisterTypeConfig(typ Type, exemplar Config) { func RegisterTypeConfig[T interface {
if reflect.TypeOf(exemplar).Kind() == reflect.Pointer { *E
// Pointer: Config
registeredConfigs[typ] = func() Config { }, E any](typ Type, _ T) {
return reflect.New(reflect.ValueOf(exemplar).Elem().Type()).Interface().(Config) registeredConfigs[typ] = func() Config { return T(new(E)) }
}
return
}
// Not a Pointer
registeredConfigs[typ] = func() Config {
return reflect.New(reflect.TypeOf(exemplar)).Elem().Interface().(Config)
}
} }
// Source represents an external way for authorizing users. // Source represents an external way for authorizing users.
@@ -188,6 +180,16 @@ func (source *Source) IsSSPI() bool {
return source.Type == SSPI return source.Type == SSPI
} }
// MustSourceCfg returns the source's config as T. The registry populates Cfg from the
// source type, so a mismatch is a programming error the caller can't recover from.
func MustSourceCfg[T Config](source *Source) T {
cfg, ok := source.Cfg.(T)
if !ok {
panic(fmt.Errorf("auth source %q (id=%d, type=%s) has config %T, expected %s", source.Name, source.ID, source.Type, source.Cfg, reflect.TypeFor[T]()))
}
return cfg
}
// HasTLS returns true of this source supports TLS. // HasTLS returns true of this source supports TLS.
func (source *Source) HasTLS() bool { func (source *Source) HasTLS() bool {
hasTLSer, ok := source.Cfg.(HasTLSer) hasTLSer, ok := source.Cfg.(HasTLSer)
@@ -371,12 +373,6 @@ type ErrSourceAlreadyExist struct {
Name string Name string
} }
// IsErrSourceAlreadyExist checks if an error is a ErrSourceAlreadyExist.
func IsErrSourceAlreadyExist(err error) bool {
_, ok := err.(ErrSourceAlreadyExist)
return ok
}
func (err ErrSourceAlreadyExist) Error() string { func (err ErrSourceAlreadyExist) Error() string {
return fmt.Sprintf("login source already exists [name: %s]", err.Name) return fmt.Sprintf("login source already exists [name: %s]", err.Name)
} }
+3 -1
View File
@@ -11,6 +11,7 @@ import (
"gitea.dev/models/unittest" "gitea.dev/models/unittest"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func TestInTransaction(t *testing.T) { func TestInTransaction(t *testing.T) {
@@ -107,7 +108,8 @@ func TestContextSafety(t *testing.T) {
_ = db.GetEngine(ctx).Iterate(&TestModel1{}, func(i int, bean any) error { _ = db.GetEngine(ctx).Iterate(&TestModel1{}, func(i int, bean any) error {
// here: db.GetEngine(ctx) is always the unclosed "Iterate" *Session with autoResetStatement=false, // here: db.GetEngine(ctx) is always the unclosed "Iterate" *Session with autoResetStatement=false,
// and the internal states (including "cond" and others) are always there and not be reset in this callback. // and the internal states (including "cond" and others) are always there and not be reset in this callback.
m1 := bean.(*TestModel1) m1, ok := bean.(*TestModel1)
require.True(t, ok)
assert.EqualValues(t, i+1, m1.ID) assert.EqualValues(t, i+1, m1.ID)
// here: XORM bug, it fails because the SQL becomes "WHERE id=-1", "WHERE id=-1 AND id=-2", "WHERE id=-1 AND id=-2 AND id=-3" ... // here: XORM bug, it fails because the SQL becomes "WHERE id=-1", "WHERE id=-1 AND id=-2", "WHERE id=-1 AND id=-2 AND id=-3" ...
-6
View File
@@ -14,12 +14,6 @@ type ErrCancelled struct {
Message string Message string
} }
// IsErrCancelled checks if an error is a ErrCancelled.
func IsErrCancelled(err error) bool {
_, ok := err.(ErrCancelled)
return ok
}
func (err ErrCancelled) Error() string { func (err ErrCancelled) Error() string {
return "Cancelled: " + err.Message return "Cancelled: " + err.Message
} }
+9
View File
@@ -239,6 +239,15 @@ func GetPackageDescriptorWithCache(ctx context.Context, pv *PackageVersion, c *c
}, nil }, nil
} }
// DescriptorMetadata returns the descriptor's metadata, which getPackageDescriptor has created from the package type
func DescriptorMetadata[T interface{ *E }, E any](pd *PackageDescriptor) T {
metadata, ok := pd.Metadata.(T)
if !ok {
panic(fmt.Errorf("package %s of type %s has metadata type %T instead of %T", pd.Package.Name, pd.Package.Type, pd.Metadata, metadata))
}
return metadata
}
// GetPackageFileDescriptor gets a package file descriptor for a package file // GetPackageFileDescriptor gets a package file descriptor for a package file
func GetPackageFileDescriptor(ctx context.Context, pf *PackageFile) (*PackageFileDescriptor, error) { func GetPackageFileDescriptor(ctx context.Context, pf *PackageFile) (*PackageFileDescriptor, error) {
return getPackageFileDescriptor(ctx, pf, cache.NewEphemeralCache()) return getPackageFileDescriptor(ctx, pf, cache.NewEphemeralCache())
+21 -8
View File
@@ -5,6 +5,7 @@ package repo
import ( import (
"context" "context"
"fmt"
"gitea.dev/models/db" "gitea.dev/models/db"
"gitea.dev/models/perm" "gitea.dev/models/perm"
@@ -295,44 +296,56 @@ func (r *RepoUnit) Unit() unit.Unit {
return unit.Units[r.Type] return unit.Units[r.Type]
} }
// unitConfig returns the unit's config, which BeforeSet has created from the unit type
func unitConfig[T interface {
*E
convert.Conversion
}, E any](r *RepoUnit) T {
config, ok := r.Config.(T)
if !ok {
panic(fmt.Errorf("repo unit %d of type %s has config type %T instead of %T", r.ID, r.Type.LogString(), r.Config, config))
}
return config
}
// CodeConfig returns config for unit.TypeCode // CodeConfig returns config for unit.TypeCode
func (r *RepoUnit) CodeConfig() *UnitConfig { func (r *RepoUnit) CodeConfig() *UnitConfig {
return r.Config.(*UnitConfig) return unitConfig[*UnitConfig](r)
} }
// PullRequestsConfig returns config for unit.TypePullRequests // PullRequestsConfig returns config for unit.TypePullRequests
func (r *RepoUnit) PullRequestsConfig() *PullRequestsConfig { func (r *RepoUnit) PullRequestsConfig() *PullRequestsConfig {
return r.Config.(*PullRequestsConfig) return unitConfig[*PullRequestsConfig](r)
} }
// ReleasesConfig returns config for unit.TypeReleases // ReleasesConfig returns config for unit.TypeReleases
func (r *RepoUnit) ReleasesConfig() *UnitConfig { func (r *RepoUnit) ReleasesConfig() *UnitConfig {
return r.Config.(*UnitConfig) return unitConfig[*UnitConfig](r)
} }
// ExternalWikiConfig returns config for unit.TypeExternalWiki // ExternalWikiConfig returns config for unit.TypeExternalWiki
func (r *RepoUnit) ExternalWikiConfig() *ExternalWikiConfig { func (r *RepoUnit) ExternalWikiConfig() *ExternalWikiConfig {
return r.Config.(*ExternalWikiConfig) return unitConfig[*ExternalWikiConfig](r)
} }
// IssuesConfig returns config for unit.TypeIssues // IssuesConfig returns config for unit.TypeIssues
func (r *RepoUnit) IssuesConfig() *IssuesConfig { func (r *RepoUnit) IssuesConfig() *IssuesConfig {
return r.Config.(*IssuesConfig) return unitConfig[*IssuesConfig](r)
} }
// ExternalTrackerConfig returns config for unit.TypeExternalTracker // ExternalTrackerConfig returns config for unit.TypeExternalTracker
func (r *RepoUnit) ExternalTrackerConfig() *ExternalTrackerConfig { func (r *RepoUnit) ExternalTrackerConfig() *ExternalTrackerConfig {
return r.Config.(*ExternalTrackerConfig) return unitConfig[*ExternalTrackerConfig](r)
} }
// ActionsConfig returns config for unit.ActionsConfig // ActionsConfig returns config for unit.ActionsConfig
func (r *RepoUnit) ActionsConfig() *ActionsConfig { func (r *RepoUnit) ActionsConfig() *ActionsConfig {
return r.Config.(*ActionsConfig) return unitConfig[*ActionsConfig](r)
} }
// ProjectsConfig returns config for unit.ProjectsConfig // ProjectsConfig returns config for unit.ProjectsConfig
func (r *RepoUnit) ProjectsConfig() *ProjectsConfig { func (r *RepoUnit) ProjectsConfig() *ProjectsConfig {
return r.Config.(*ProjectsConfig) return unitConfig[*ProjectsConfig](r)
} }
func getUnitsByRepoID(ctx context.Context, repoID int64) (units []*RepoUnit, err error) { func getUnitsByRepoID(ctx context.Context, repoID int64) (units []*RepoUnit, err error) {
+16 -12
View File
@@ -34,7 +34,8 @@ type FixtureItem struct {
type fixturesLoaderInternal struct { type fixturesLoaderInternal struct {
xormEngine *xorm.Engine xormEngine *xorm.Engine
tableSyncMap sync.Map tableSyncMu sync.Mutex
tableSynced map[string]bool
db *sql.DB db *sql.DB
dbType schemas.DBType dbType schemas.DBType
fixtures map[string]*FixtureItem fixtures map[string]*FixtureItem
@@ -152,32 +153,35 @@ func (f *fixturesLoaderInternal) Load() error {
ctx := context.WithValue(context.Background(), db.ContextKeyTestFixtures, true) ctx := context.WithValue(context.Background(), db.ContextKeyTestFixtures, true)
f.tableSyncMu.Lock()
defer f.tableSyncMu.Unlock()
for _, fixture := range f.fixtures { for _, fixture := range f.fixtures {
synced, existing := f.tableSyncMap.Load(fixture.tableName) synced, existing := f.tableSynced[fixture.tableName]
if synced == true || !existing { if synced || !existing {
continue continue
} }
if err := f.loadFixtures(tx, fixture); err != nil { if err := f.loadFixtures(tx, fixture); err != nil {
return fmt.Errorf("failed to load fixtures from %s: %w", fixture.fileFullPath, err) return fmt.Errorf("failed to load fixtures from %s: %w", fixture.fileFullPath, err)
} }
f.tableSyncMap.Store(fixture.tableName, true) f.tableSynced[fixture.tableName] = true
} }
if err = tx.Commit(); err != nil { if err = tx.Commit(); err != nil {
return err return err
} }
f.tableSyncMap.Range(func(k, v any) bool { for tableName, synced := range f.tableSynced {
tableName, synced := k.(string), v.(bool)
if !synced && f.fixtures[tableName] == nil { if !synced && f.fixtures[tableName] == nil {
_, _ = f.xormEngine.Context(ctx).Exec("DELETE FROM `" + tableName + "`") _, _ = f.xormEngine.Context(ctx).Exec("DELETE FROM `" + tableName + "`")
} }
f.tableSyncMap.Store(tableName, true) f.tableSynced[tableName] = true
return true }
})
return nil return nil
} }
func (f *fixturesLoaderInternal) MarkTableChanged(tableName string) { func (f *fixturesLoaderInternal) MarkTableChanged(tableName string) {
f.tableSyncMap.Store(tableName, false) f.tableSyncMu.Lock()
defer f.tableSyncMu.Unlock()
f.tableSynced[tableName] = false
} }
func FixturesFileFullPaths(dir string, files []string) (map[string]*FixtureItem, error) { func FixturesFileFullPaths(dir string, files []string) (map[string]*FixtureItem, error) {
@@ -212,7 +216,7 @@ func NewFixturesLoader(x *xorm.Engine, opts FixturesOptions) (FixturesLoader, er
return nil, fmt.Errorf("failed to get fixtures files: %w", err) return nil, fmt.Errorf("failed to get fixtures files: %w", err)
} }
f := &fixturesLoaderInternal{xormEngine: x, db: x.DB().DB, dbType: x.Dialect().URI().DBType, fixtures: fixtureItems} f := &fixturesLoaderInternal{xormEngine: x, db: x.DB().DB, dbType: x.Dialect().URI().DBType, fixtures: fixtureItems, tableSynced: map[string]bool{}}
switch f.dbType { switch f.dbType {
case schemas.SQLITE: case schemas.SQLITE:
f.quoteObject = func(s string) string { return fmt.Sprintf(`"%s"`, s) } f.quoteObject = func(s string) string { return fmt.Sprintf(`"%s"`, s) }
@@ -233,7 +237,7 @@ func NewFixturesLoader(x *xorm.Engine, opts FixturesOptions) (FixturesLoader, er
xormBeans, _ := db.NamesToBean() xormBeans, _ := db.NamesToBean()
for _, bean := range xormBeans { for _, bean := range xormBeans {
beanTableName := x.TableName(bean) beanTableName := x.TableName(bean)
f.tableSyncMap.Store(trimTableNameQuotes(beanTableName), false) f.tableSynced[trimTableNameQuotes(beanTableName)] = false
} }
return f, nil return f, nil
} }
+2 -2
View File
@@ -64,7 +64,7 @@ func MatchScopedWorkflows(
parsed []*ParsedScopedWorkflow, parsed []*ParsedScopedWorkflow,
consumerGitRepo *git.Repository, consumerGitRepo *git.Repository,
consumerCommit *git.Commit, consumerCommit *git.Commit,
triggedEvent webhook_module.HookEventType, inputEvent webhook_module.HookEventType,
payload api.Payloader, payload api.Payloader,
) (matched, filtered []*DetectedWorkflow) { ) (matched, filtered []*DetectedWorkflow) {
for _, p := range parsed { for _, p := range parsed {
@@ -78,7 +78,7 @@ func MatchScopedWorkflows(
TriggerEvent: evt, TriggerEvent: evt,
Content: p.Content, Content: p.Content,
} }
switch detectWorkflowMatch(ctx, consumerGitRepo, consumerCommit, triggedEvent, payload, evt) { switch detectWorkflowMatch(ctx, consumerGitRepo, consumerCommit, inputEvent, payload, evt) {
case detectMatched: case detectMatched:
matched = append(matched, dwf) matched = append(matched, dwf)
case detectFilteredOut: case detectFilteredOut:
+33 -14
View File
@@ -266,12 +266,22 @@ func DetectScheduledWorkflows(ctx context.Context, gitRepo *git.Repository, comm
return wfs, nil return wfs, nil
} }
func detectWorkflowMatch(ctx context.Context, gitRepo *git.Repository, commit *git.Commit, triggedEvent webhook_module.HookEventType, payload api.Payloader, evt *jobparser.Event) detectResult { // payloadAs returns the payload as the type the event is expected to carry
if !canGithubEventMatch(evt.Name, triggedEvent) { func payloadAs[T api.Payloader](payload api.Payloader, inputEvent webhook_module.HookEventType) T {
typedPayload, ok := payload.(T)
if !ok {
// the event type determines the payload type, so a mismatch can only be a programming error
panic(fmt.Errorf("event %q was triggered with payload type %T instead of %T", inputEvent, payload, typedPayload))
}
return typedPayload
}
func detectWorkflowMatch(ctx context.Context, gitRepo *git.Repository, commit *git.Commit, inputEvent webhook_module.HookEventType, payload api.Payloader, evt *jobparser.Event) detectResult {
if !canGithubEventMatch(evt.Name, inputEvent) {
return detectNotApplicable return detectNotApplicable
} }
switch triggedEvent { switch inputEvent {
case // events with no activity types case // events with no activity types
webhook_module.HookEventCreate, webhook_module.HookEventCreate,
webhook_module.HookEventDelete, webhook_module.HookEventDelete,
@@ -279,21 +289,23 @@ func detectWorkflowMatch(ctx context.Context, gitRepo *git.Repository, commit *g
webhook_module.HookEventWiki, webhook_module.HookEventWiki,
webhook_module.HookEventSchedule: webhook_module.HookEventSchedule:
if len(evt.Acts()) != 0 { if len(evt.Acts()) != 0 {
log.Warn("Ignore unsupported %s event arguments %v", triggedEvent, evt.Acts()) log.Warn("Ignore unsupported %s event arguments %v", inputEvent, evt.Acts())
} }
// no special filter parameters for these events, just return true if name matched // no special filter parameters for these events, just return true if name matched
return detectMatched return detectMatched
case // push case // push
webhook_module.HookEventPush: webhook_module.HookEventPush:
return matchPushEvent(ctx, gitRepo, commit, payload.(*api.PushPayload), evt) pushPayload := payloadAs[*api.PushPayload](payload, inputEvent)
return matchPushEvent(ctx, gitRepo, commit, pushPayload, evt)
case // issues case // issues
webhook_module.HookEventIssues, webhook_module.HookEventIssues,
webhook_module.HookEventIssueAssign, webhook_module.HookEventIssueAssign,
webhook_module.HookEventIssueLabel, webhook_module.HookEventIssueLabel,
webhook_module.HookEventIssueMilestone: webhook_module.HookEventIssueMilestone:
if matchIssuesEvent(payload.(*api.IssuePayload), evt) { issuePayload := payloadAs[*api.IssuePayload](payload, inputEvent)
if matchIssuesEvent(issuePayload, evt) {
return detectMatched return detectMatched
} }
return detectNotApplicable return detectNotApplicable
@@ -303,7 +315,8 @@ func detectWorkflowMatch(ctx context.Context, gitRepo *git.Repository, commit *g
// `pull_request_comment` is same as `issue_comment` // `pull_request_comment` is same as `issue_comment`
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_comment-use-issue_comment // See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_comment-use-issue_comment
webhook_module.HookEventPullRequestComment: webhook_module.HookEventPullRequestComment:
if matchIssueCommentEvent(payload.(*api.IssueCommentPayload), evt) { issueCommentPayload := payloadAs[*api.IssueCommentPayload](payload, inputEvent)
if matchIssueCommentEvent(issueCommentPayload, evt) {
return detectMatched return detectMatched
} }
return detectNotApplicable return detectNotApplicable
@@ -315,46 +328,52 @@ func detectWorkflowMatch(ctx context.Context, gitRepo *git.Repository, commit *g
webhook_module.HookEventPullRequestLabel, webhook_module.HookEventPullRequestLabel,
webhook_module.HookEventPullRequestReviewRequest, webhook_module.HookEventPullRequestReviewRequest,
webhook_module.HookEventPullRequestMilestone: webhook_module.HookEventPullRequestMilestone:
return matchPullRequestEvent(ctx, gitRepo, commit, payload.(*api.PullRequestPayload), evt) pullRequestPayload := payloadAs[*api.PullRequestPayload](payload, inputEvent)
return matchPullRequestEvent(ctx, gitRepo, commit, pullRequestPayload, evt)
case // pull_request_review case // pull_request_review
webhook_module.HookEventPullRequestReviewApproved, webhook_module.HookEventPullRequestReviewApproved,
webhook_module.HookEventPullRequestReviewRejected: webhook_module.HookEventPullRequestReviewRejected:
if matchPullRequestReviewEvent(payload.(*api.PullRequestPayload), evt) { reviewPayload := payloadAs[*api.PullRequestPayload](payload, inputEvent)
if matchPullRequestReviewEvent(reviewPayload, evt) {
return detectMatched return detectMatched
} }
return detectNotApplicable return detectNotApplicable
case // pull_request_review_comment case // pull_request_review_comment
webhook_module.HookEventPullRequestReviewComment: webhook_module.HookEventPullRequestReviewComment:
if matchPullRequestReviewCommentEvent(payload.(*api.PullRequestPayload), evt) { reviewCommentPayload := payloadAs[*api.PullRequestPayload](payload, inputEvent)
if matchPullRequestReviewCommentEvent(reviewCommentPayload, evt) {
return detectMatched return detectMatched
} }
return detectNotApplicable return detectNotApplicable
case // release case // release
webhook_module.HookEventRelease: webhook_module.HookEventRelease:
if matchReleaseEvent(payload.(*api.ReleasePayload), evt) { releasePayload := payloadAs[*api.ReleasePayload](payload, inputEvent)
if matchReleaseEvent(releasePayload, evt) {
return detectMatched return detectMatched
} }
return detectNotApplicable return detectNotApplicable
case // registry_package case // registry_package
webhook_module.HookEventPackage: webhook_module.HookEventPackage:
if matchPackageEvent(payload.(*api.PackagePayload), evt) { packagePayload := payloadAs[*api.PackagePayload](payload, inputEvent)
if matchPackageEvent(packagePayload, evt) {
return detectMatched return detectMatched
} }
return detectNotApplicable return detectNotApplicable
case // workflow_run case // workflow_run
webhook_module.HookEventWorkflowRun: webhook_module.HookEventWorkflowRun:
if matchWorkflowRunEvent(payload.(*api.WorkflowRunPayload), evt) { workflowRunPayload := payloadAs[*api.WorkflowRunPayload](payload, inputEvent)
if matchWorkflowRunEvent(workflowRunPayload, evt) {
return detectMatched return detectMatched
} }
return detectNotApplicable return detectNotApplicable
default: default:
log.Warn("unsupported event %q", triggedEvent) log.Warn("unsupported event %q", inputEvent)
return detectNotApplicable return detectNotApplicable
} }
} }
+7 -3
View File
@@ -37,7 +37,9 @@ func TestEmbed(t *testing.T) {
assert.Equal(t, "a", string(content)) assert.Equal(t, "a", string(content))
fi, err := fs.Stat(efs, "a.txt") fi, err := fs.Stat(efs, "a.txt")
require.NoError(t, err) require.NoError(t, err)
_, ok := fi.(EmbeddedFileInfo).GetGzipContent() fiEmbedded, ok := fi.(EmbeddedFileInfo)
require.True(t, ok)
_, ok = fiEmbedded.GetGzipContent()
assert.False(t, ok) assert.False(t, ok)
// test a compressed file // test a compressed file
@@ -48,7 +50,9 @@ func TestEmbed(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
assert.False(t, fi.Mode().IsDir()) assert.False(t, fi.Mode().IsDir())
assert.True(t, fi.Mode().IsRegular()) assert.True(t, fi.Mode().IsRegular())
gzipContent, ok := fi.(EmbeddedFileInfo).GetGzipContent() fiEmbedded, ok = fi.(EmbeddedFileInfo)
require.True(t, ok)
gzipContent, ok := fiEmbedded.GetGzipContent()
assert.True(t, ok) assert.True(t, ok)
assert.Greater(t, len(gzipContent), 1) assert.Greater(t, len(gzipContent), 1)
assert.Less(t, len(gzipContent), 1000) assert.Less(t, len(gzipContent), 1000)
@@ -82,7 +86,7 @@ func TestEmbed(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
hi, err := hf.Stat() hi, err := hf.Stat()
require.NoError(t, err) require.NoError(t, err)
fiEmbedded, ok := hi.(EmbeddedFileInfo) fiEmbedded, ok = hi.(EmbeddedFileInfo)
require.True(t, ok) require.True(t, ok)
gzipContent, ok = fiEmbedded.GetGzipContent() gzipContent, ok = fiEmbedded.GetGzipContent()
assert.True(t, ok) assert.True(t, ok)
+7 -5
View File
@@ -64,15 +64,17 @@ func CreateTimeLimitCode[T time.Time | string](data string, minutes int, startTi
const format = "200601021504" const format = "200601021504"
var start time.Time var start time.Time
var startTimeAny any = startTimeGeneric switch startTime := any(startTimeGeneric).(type) {
if t, ok := startTimeAny.(time.Time); ok { case time.Time:
start = t start = startTime
} else { case string:
var err error var err error
start, err = time.ParseInLocation(format, startTimeAny.(string), time.Local) start, err = time.ParseInLocation(format, startTime, time.Local)
if err != nil { if err != nil {
return "" // return an invalid code because the "parse" failed return "" // return an invalid code because the "parse" failed
} }
default:
panic(fmt.Sprintf("unsupported start time type %T", startTime)) // it shouldn't happen
} }
startStr := start.Format(format) startStr := start.Format(format)
end := start.Add(time.Minute * time.Duration(minutes)) end := start.Add(time.Minute * time.Duration(minutes))
+1 -1
View File
@@ -25,7 +25,7 @@ func TestWithCacheContext(t *testing.T) {
c.Put(field, "my_config1", 1) c.Put(field, "my_config1", 1)
v, _ = c.Get(field, "my_config1") v, _ = c.Get(field, "my_config1")
assert.NotNil(t, v) assert.NotNil(t, v)
assert.Equal(t, 1, v.(int)) assert.Equal(t, 1, v)
c.Delete(field, "my_config1") c.Delete(field, "my_config1")
c.Delete(field, "my_config2") // remove a non-exist key c.Delete(field, "my_config2") // remove a non-exist key
+2 -2
View File
@@ -82,7 +82,7 @@ func getLastCommitForPathsByCommitNode(ctx context.Context, gitRepo *Repository,
// We do a tree traversal with nodes sorted by commit time // We do a tree traversal with nodes sorted by commit time
heap := binaryheap.NewWith(func(a, b any) int { heap := binaryheap.NewWith(func(a, b any) int {
if a.(*commitAndPaths).commit.CommitTime().Before(b.(*commitAndPaths).commit.CommitTime()) { if a.(*commitAndPaths).commit.CommitTime().Before(b.(*commitAndPaths).commit.CommitTime()) { //nolint:forcetypeassert // this heap only ever holds *commitAndPaths
return 1 return 1
} }
return -1 return -1
@@ -110,7 +110,7 @@ heaploop:
if !ok { if !ok {
break break
} }
current := cIn.(*commitAndPaths) current := cIn.(*commitAndPaths) //nolint:forcetypeassert // this heap only ever holds *commitAndPaths
// Load the parent commits for the one we are currently examining // Load the parent commits for the one we are currently examining
numParents := current.commit.NumParents() numParents := current.commit.NumParents()
+1 -1
View File
@@ -144,7 +144,7 @@ func (repo *Repository) GetTagInfos(ctx context.Context, page, pageSize int) ([]
sortTagsByTime(tags) sortTagsByTime(tags)
tagsTotal = len(tags) tagsTotal = len(tags)
if page != 0 { if page != 0 {
tags = util.PaginateSlice(tags, page, pageSize).([]*Tag) tags = util.PaginateSlice(tags, page, pageSize)
} }
return nil return nil
}). }).
+3 -1
View File
@@ -174,8 +174,10 @@ func TestGlob(t *testing.T) {
} { } {
g, err := Compile(test.pattern, test.delimiters...) g, err := Compile(test.pattern, test.delimiters...)
require.NoError(t, err) require.NoError(t, err)
compiler, ok := g.(*globCompiler)
require.True(t, ok)
result := g.Match(test.match) result := g.Match(test.match)
assert.Equal(t, test.should, result, "pattern %q matching %q should be %v but got %v, compiled=%s", test.pattern, test.match, test.should, result, g.(*globCompiler).regexpPattern) assert.Equal(t, test.should, result, "pattern %q matching %q should be %v but got %v, compiled=%s", test.pattern, test.match, test.should, result, compiler.regexpPattern)
} }
} }
+3 -1
View File
@@ -21,7 +21,9 @@ func TestLockAndDo(t *testing.T) {
locker := newTestRedisLocker(t) locker := newTestRedisLocker(t)
defaultLocker.Store(new(locker)) defaultLocker.Store(new(locker))
testLockAndDo(t) testLockAndDo(t)
require.NoError(t, locker.(*redisLocker).Close()) rl, ok := locker.(*redisLocker)
require.True(t, ok)
require.NoError(t, rl.Close())
}) })
t.Run("memory", func(t *testing.T) { t.Run("memory", func(t *testing.T) {
defaultLocker.Store(new(NewMemoryLocker())) defaultLocker.Store(new(NewMemoryLocker()))
+9 -4
View File
@@ -26,13 +26,17 @@ func TestLocker(t *testing.T) {
defer test.MockVariableValue(&redisLockExpiry, 5*time.Second)() // make it shorter for testing defer test.MockVariableValue(&redisLockExpiry, 5*time.Second)() // make it shorter for testing
locker := newTestRedisLocker(t) locker := newTestRedisLocker(t)
testLocker(t, locker) testLocker(t, locker)
testRedisLocker(t, locker.(*redisLocker)) rl, ok := locker.(*redisLocker)
require.NoError(t, locker.(*redisLocker).Close()) require.True(t, ok)
testRedisLocker(t, rl)
require.NoError(t, rl.Close())
}) })
t.Run("memory", func(t *testing.T) { t.Run("memory", func(t *testing.T) {
locker := NewMemoryLocker() locker := NewMemoryLocker()
testLocker(t, locker) testLocker(t, locker)
testMemoryLocker(t, locker.(*memoryLocker)) ml, ok := locker.(*memoryLocker)
require.True(t, ok)
testMemoryLocker(t, ml)
}) })
} }
@@ -162,7 +166,8 @@ func testRedisLocker(t *testing.T, locker *redisLocker) {
// It simulates that there are some problems with extending like network issues or redis server down. // It simulates that there are some problems with extending like network issues or redis server down.
v, ok := locker.mutexM.Load("test") v, ok := locker.mutexM.Load("test")
require.True(t, ok) require.True(t, ok)
m := v.(*redsync.Mutex) m, ok := v.(*redsync.Mutex)
require.True(t, ok)
_, _ = m.Unlock() // release it to make it impossible to extend _, _ = m.Unlock() // release it to make it impossible to extend
// In current design, callers can't know the lock can't be extended. // In current design, callers can't know the lock can't be extended.
+5 -6
View File
@@ -52,11 +52,10 @@ func (l *redisLocker) Lock(ctx context.Context, key string) (ReleaseFunc, error)
func (l *redisLocker) TryLock(ctx context.Context, key string) (bool, ReleaseFunc, error) { func (l *redisLocker) TryLock(ctx context.Context, key string) (bool, ReleaseFunc, error) {
f, err := l.lock(ctx, key, 1) f, err := l.lock(ctx, key, 1)
var ( if _, taken := errors.AsType[*redsync.ErrTaken](err); taken {
errTaken *redsync.ErrTaken return false, f, nil
errNodeTaken *redsync.ErrNodeTaken }
) if _, nodeTaken := errors.AsType[*redsync.ErrNodeTaken](err); nodeTaken {
if errors.As(err, &errTaken) || errors.As(err, &errNodeTaken) {
return false, f, nil return false, f, nil
} }
return err == nil, f, err return err == nil, f, err
@@ -112,7 +111,7 @@ func (l *redisLocker) startExtend() {
toExtend := make([]*redsync.Mutex, 0) toExtend := make([]*redsync.Mutex, 0)
l.mutexM.Range(func(_, value any) bool { l.mutexM.Range(func(_, value any) bool {
m := value.(*redsync.Mutex) m := value.(*redsync.Mutex) //nolint:forcetypeassert // mutexM only ever holds *redsync.Mutex
// Extend the lock if it is not expired. // Extend the lock if it is not expired.
// Although the mutex will be removed from the map before it is released, // Although the mutex will be removed from the map before it is released,
+5 -2
View File
@@ -177,13 +177,15 @@ func GetListenerTCP(network string, address *net.TCPAddr) (*net.TCPListener, err
// look for a provided listener // look for a provided listener
for i, l := range providedListeners { for i, l := range providedListeners {
if isSameAddr(l.Addr(), address) { if isSameAddr(l.Addr(), address) {
tcpListener := l.(*net.TCPListener) //nolint:forcetypeassert // a listener matching a *net.TCPAddr is a *net.TCPListener
providedListeners = append(providedListeners[:i], providedListeners[i+1:]...) providedListeners = append(providedListeners[:i], providedListeners[i+1:]...)
needsUnlink := providedListenersToUnlink[i] needsUnlink := providedListenersToUnlink[i]
providedListenersToUnlink = append(providedListenersToUnlink[:i], providedListenersToUnlink[i+1:]...) providedListenersToUnlink = append(providedListenersToUnlink[:i], providedListenersToUnlink[i+1:]...)
activeListeners = append(activeListeners, l) activeListeners = append(activeListeners, l)
activeListenersToUnlink = append(activeListenersToUnlink, needsUnlink) activeListenersToUnlink = append(activeListenersToUnlink, needsUnlink)
return l.(*net.TCPListener), nil return tcpListener, nil
} }
} }
@@ -211,13 +213,14 @@ func GetListenerUnix(network string, address *net.UnixAddr) (*net.UnixListener,
// look for a provided listener // look for a provided listener
for i, l := range providedListeners { for i, l := range providedListeners {
if isSameAddr(l.Addr(), address) { if isSameAddr(l.Addr(), address) {
unixListener := l.(*net.UnixListener) //nolint:forcetypeassert // a listener matching a *net.UnixAddr is a *net.UnixListener
providedListeners = append(providedListeners[:i], providedListeners[i+1:]...) providedListeners = append(providedListeners[:i], providedListeners[i+1:]...)
needsUnlink := providedListenersToUnlink[i] needsUnlink := providedListenersToUnlink[i]
providedListenersToUnlink = append(providedListenersToUnlink[:i], providedListenersToUnlink[i+1:]...) providedListenersToUnlink = append(providedListenersToUnlink[:i], providedListenersToUnlink[i+1:]...)
activeListenersToUnlink = append(activeListenersToUnlink, needsUnlink) activeListenersToUnlink = append(activeListenersToUnlink, needsUnlink)
activeListeners = append(activeListeners, l) activeListeners = append(activeListeners, l)
unixListener := l.(*net.UnixListener)
if needsUnlink { if needsUnlink {
unixListener.SetUnlinkOnClose(true) unixListener.SetUnlinkOnClose(true)
} }
+6 -2
View File
@@ -44,10 +44,14 @@ func RestartProcess() (int, error) {
// Extract the fds from the listeners. // Extract the fds from the listeners.
files := make([]*os.File, len(listeners)) files := make([]*os.File, len(listeners))
for i, l := range listeners { for i, l := range listeners {
var err error
// Now, all our listeners actually have File() functions so instead of // Now, all our listeners actually have File() functions so instead of
// individually casting we just use a hacky interface // individually casting we just use a hacky interface
files[i], err = l.(filer).File() lf, ok := l.(filer)
if !ok {
return 0, fmt.Errorf("listener %T does not provide a File", l)
}
var err error
files[i], err = lf.File()
if err != nil { if err != nil {
return 0, err return 0, err
} }
+6 -1
View File
@@ -7,6 +7,7 @@ package graceful
import ( import (
"crypto/tls" "crypto/tls"
"fmt"
"net" "net"
"os" "os"
"strings" "strings"
@@ -260,7 +261,11 @@ func (wl *wrappedListener) Accept() (c net.Conn, err error) {
func (wl *wrappedListener) File() (*os.File, error) { func (wl *wrappedListener) File() (*os.File, error) {
// returns a dup(2) - FD_CLOEXEC flag *not* set so the listening socket can be passed to child processes // returns a dup(2) - FD_CLOEXEC flag *not* set so the listening socket can be passed to child processes
return wl.Listener.(filer).File() lf, ok := wl.Listener.(filer)
if !ok {
return nil, fmt.Errorf("listener %T does not provide a File", wl.Listener)
}
return lf.File()
} }
type wrappedConn struct { type wrappedConn struct {
+1 -1
View File
@@ -63,7 +63,7 @@ func (t *traceBuiltinSpan) toString(out *strings.Builder, indent int) {
} }
out.WriteString("\n") out.WriteString("\n")
for _, c := range t.ts.children { for _, c := range t.ts.children {
span := c.internalSpans[t.internalSpanIdx].(*traceBuiltinSpan) span := c.internalSpans[t.internalSpanIdx].(*traceBuiltinSpan) //nolint:forcetypeassert // this tracer only stores its own spans
span.toString(out, indent+2) span.toString(out, indent+2)
} }
} }
+4 -1
View File
@@ -8,6 +8,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
// "vendor span" is a simple demo for a span from a vendor library // "vendor span" is a simple demo for a span from a vendor library
@@ -82,7 +83,9 @@ func TestTraceStarter(t *testing.T) {
collectSpanNames(fullName, c) collectSpanNames(fullName, c)
} }
} }
collectSpanNames("", span.internalSpans[0].(*testTraceSpan).vendorSpan) rootSpan, ok := span.internalSpans[0].(*testTraceSpan)
require.True(t, ok)
collectSpanNames("", rootSpan.vendorSpan)
assert.Equal(t, []string{ assert.Equal(t, []string{
"/root", "/root",
"/root/span1", "/root/span1",
+17 -6
View File
@@ -21,6 +21,7 @@ import (
"gitea.dev/modules/indexer/code/internal" "gitea.dev/modules/indexer/code/internal"
indexer_internal "gitea.dev/modules/indexer/internal" indexer_internal "gitea.dev/modules/indexer/internal"
inner_bleve "gitea.dev/modules/indexer/internal/bleve" inner_bleve "gitea.dev/modules/indexer/internal/bleve"
"gitea.dev/modules/json"
"gitea.dev/modules/setting" "gitea.dev/modules/setting"
"gitea.dev/modules/timeutil" "gitea.dev/modules/timeutil"
"gitea.dev/modules/typesniffer" "gitea.dev/modules/typesniffer"
@@ -330,6 +331,17 @@ func (b *Indexer) Search(ctx context.Context, opts *internal.SearchOptions) (int
searchResults := make([]*internal.SearchResult, len(result.Hits)) searchResults := make([]*internal.SearchResult, len(result.Hits))
for i, hit := range result.Hits { for i, hit := range result.Hits {
content, okContent := hit.Fields["Content"].(string)
language, okLanguage := hit.Fields["Language"].(string)
commitID, okCommitID := hit.Fields["CommitID"].(string)
updatedAt, okUpdatedAt := hit.Fields["UpdatedAt"].(string)
repoID, okRepoID := hit.Fields["RepoID"].(float64)
if !okContent || !okLanguage || !okCommitID || !okUpdatedAt || !okRepoID {
hitFieldsJson, _ := json.Marshal(hit.Fields)
setting.PanicInDevOrTesting("unexpected field types in search hit %q: %s", hit.ID, string(hitFieldsJson))
return 0, nil, nil, fmt.Errorf("unexpected field types in search hit %q", hit.ID)
}
startIndex, endIndex := -1, -1 startIndex, endIndex := -1, -1
for _, locations := range hit.Locations["Content"] { for _, locations := range hit.Locations["Content"] {
location := locations[0] location := locations[0]
@@ -343,21 +355,20 @@ func (b *Indexer) Search(ctx context.Context, opts *internal.SearchOptions) (int
} }
} }
if len(hit.Locations["Filename"]) > 0 { if len(hit.Locations["Filename"]) > 0 {
startIndex, endIndex = internal.FilenameMatchIndexPos(hit.Fields["Content"].(string)) startIndex, endIndex = internal.FilenameMatchIndexPos(content)
} }
language := hit.Fields["Language"].(string)
var updatedUnix timeutil.TimeStamp var updatedUnix timeutil.TimeStamp
if t, err := time.Parse(time.RFC3339, hit.Fields["UpdatedAt"].(string)); err == nil { if t, err := time.Parse(time.RFC3339, updatedAt); err == nil {
updatedUnix = timeutil.TimeStamp(t.Unix()) updatedUnix = timeutil.TimeStamp(t.Unix())
} }
searchResults[i] = &internal.SearchResult{ searchResults[i] = &internal.SearchResult{
RepoID: int64(hit.Fields["RepoID"].(float64)), RepoID: int64(repoID),
StartIndex: startIndex, StartIndex: startIndex,
EndIndex: endIndex, EndIndex: endIndex,
Filename: internal.FilenameOfIndexerID(hit.ID), Filename: internal.FilenameOfIndexerID(hit.ID),
Content: hit.Fields["Content"].(string), Content: content,
CommitID: hit.Fields["CommitID"].(string), CommitID: commitID,
UpdatedUnix: updatedUnix, UpdatedUnix: updatedUnix,
Language: language, Language: language,
Color: enry.GetColor(language), Color: enry.GetColor(language),
@@ -261,12 +261,21 @@ func convertResult(searchResult *es.SearchResponse, kw string, pageSize int) (in
return 0, nil, nil, err return 0, nil, nil, err
} }
content, okContent := res["content"].(string)
language, okLanguage := res["language"].(string)
commitID, okCommitID := res["commit_id"].(string)
updatedAt, okUpdatedAt := res["updated_at"].(float64)
if !okContent || !okLanguage || !okCommitID || !okUpdatedAt {
setting.PanicInDevOrTesting("unexpected field types in search hit %q: %s", hit.ID, string(hit.Source))
return 0, nil, nil, fmt.Errorf("unexpected field types in search hit %q", hit.ID)
}
// FIXME: There is no way to get the position the keyword on the content currently on the same request. // FIXME: There is no way to get the position the keyword on the content currently on the same request.
// So we get it from content, this may made the query slower. See // So we get it from content, this may made the query slower. See
// https://discuss.elastic.co/t/fetching-position-of-keyword-in-matched-document/94291 // https://discuss.elastic.co/t/fetching-position-of-keyword-in-matched-document/94291
var startIndex, endIndex int var startIndex, endIndex int
if c, ok := hit.Highlight["filename"]; ok && len(c) > 0 { if c, ok := hit.Highlight["filename"]; ok && len(c) > 0 {
startIndex, endIndex = internal.FilenameMatchIndexPos(res["content"].(string)) startIndex, endIndex = internal.FilenameMatchIndexPos(content)
} else if c, ok := hit.Highlight["content"]; ok && len(c) > 0 { } else if c, ok := hit.Highlight["content"]; ok && len(c) > 0 {
// FIXME: Since the highlighting content will include <em> and </em> for the keywords, // FIXME: Since the highlighting content will include <em> and </em> for the keywords,
// now we should find the positions. But how to avoid html content which contains the // now we should find the positions. But how to avoid html content which contains the
@@ -279,14 +288,12 @@ func convertResult(searchResult *es.SearchResponse, kw string, pageSize int) (in
panic(fmt.Sprintf("2===%#v", hit.Highlight)) panic(fmt.Sprintf("2===%#v", hit.Highlight))
} }
language := res["language"].(string)
hits = append(hits, &internal.SearchResult{ hits = append(hits, &internal.SearchResult{
RepoID: repoID, RepoID: repoID,
Filename: fileName, Filename: fileName,
CommitID: res["commit_id"].(string), CommitID: commitID,
Content: res["content"].(string), Content: content,
UpdatedUnix: timeutil.TimeStamp(res["updated_at"].(float64)), UpdatedUnix: timeutil.TimeStamp(updatedAt),
Language: language, Language: language,
StartIndex: startIndex, StartIndex: startIndex,
EndIndex: endIndex, EndIndex: endIndex,
+1 -1
View File
@@ -24,7 +24,7 @@ var _ EventWriter = (*eventWriterConn)(nil)
func NewEventWriterConn(writerName string, writerMode WriterMode) EventWriter { func NewEventWriterConn(writerName string, writerMode WriterMode) EventWriter {
w := &eventWriterConn{EventWriterBaseImpl: NewEventWriterBase(writerName, "conn", writerMode)} w := &eventWriterConn{EventWriterBaseImpl: NewEventWriterBase(writerName, "conn", writerMode)}
opt := writerMode.WriterOption.(WriterConnOption) opt := writerMode.WriterOption.(WriterConnOption) //nolint:forcetypeassert // a conn writer is only created with WriterConnOption
w.connWriter = connWriter{ w.connWriter = connWriter{
ReconnectOnMsg: opt.ReconnectOnMsg, ReconnectOnMsg: opt.ReconnectOnMsg,
Reconnect: opt.Reconnect, Reconnect: opt.Reconnect,
+1 -1
View File
@@ -21,7 +21,7 @@ var _ EventWriter = (*eventWriterConsole)(nil)
func NewEventWriterConsole(name string, mode WriterMode) EventWriter { func NewEventWriterConsole(name string, mode WriterMode) EventWriter {
w := &eventWriterConsole{EventWriterBaseImpl: NewEventWriterBase(name, "console", mode)} w := &eventWriterConsole{EventWriterBaseImpl: NewEventWriterBase(name, "console", mode)}
opt := mode.WriterOption.(WriterConsoleOption) opt := mode.WriterOption.(WriterConsoleOption) //nolint:forcetypeassert // a console writer is only created with WriterConsoleOption
if opt.Stderr { if opt.Stderr {
w.OutputWriteCloser = util.NopCloser{Writer: os.Stderr} w.OutputWriteCloser = util.NopCloser{Writer: os.Stderr}
} else { } else {
+1 -1
View File
@@ -29,7 +29,7 @@ var _ EventWriter = (*eventWriterFile)(nil)
func NewEventWriterFile(name string, mode WriterMode) EventWriter { func NewEventWriterFile(name string, mode WriterMode) EventWriter {
w := &eventWriterFile{EventWriterBaseImpl: NewEventWriterBase(name, "file", mode)} w := &eventWriterFile{EventWriterBaseImpl: NewEventWriterBase(name, "file", mode)}
opt := mode.WriterOption.(WriterFileOption) opt := mode.WriterOption.(WriterFileOption) //nolint:forcetypeassert // a file writer is only created with WriterFileOption
var err error var err error
w.fileWriter, err = rotatingfilewriter.Open(opt.FileName, &rotatingfilewriter.Options{ w.fileWriter, err = rotatingfilewriter.Open(opt.FileName, &rotatingfilewriter.Options{
Rotate: opt.LogRotate, Rotate: opt.LogRotate,
+4 -1
View File
@@ -7,6 +7,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func TestSharedWorker(t *testing.T) { func TestSharedWorker(t *testing.T) {
@@ -37,6 +38,8 @@ func TestSharedWorker(t *testing.T) {
m.Close() m.Close()
logs := w.(*dummyWriter).FetchLogs() dw, ok := w.(*dummyWriter)
require.True(t, ok)
logs := dw.FetchLogs()
assert.Equal(t, []string{"msg-1\n", "msg-2\n", "msg-3\n"}, logs) assert.Equal(t, []string{"msg-1\n", "msg-2\n", "msg-3\n"}, logs)
} }
+13 -22
View File
@@ -237,10 +237,8 @@ func (b *footnoteBlockParser) Continue(node ast.Node, reader text.Reader, pc par
} }
func (b *footnoteBlockParser) Close(node ast.Node, reader text.Reader, pc parser.Context) { func (b *footnoteBlockParser) Close(node ast.Node, reader text.Reader, pc parser.Context) {
var list *FootnoteList list, _ := pc.Get(footnoteListKey).(*FootnoteList)
if tlist := pc.Get(footnoteListKey); tlist != nil { if list == nil {
list = tlist.(*FootnoteList)
} else {
list = NewFootnoteList() list = NewFootnoteList()
pc.Set(footnoteListKey, list) pc.Set(footnoteListKey, list)
node.Parent().InsertBefore(node.Parent(), node, list) node.Parent().InsertBefore(node.Parent(), node, list)
@@ -295,17 +293,14 @@ func (s *footnoteParser) Parse(parent ast.Node, block text.Reader, pc parser.Con
value := block.Value(text.NewSegment(segment.Start+open, segment.Start+closes)) value := block.Value(text.NewSegment(segment.Start+open, segment.Start+closes))
block.Advance(closes + 1) block.Advance(closes + 1)
var list *FootnoteList list, _ := pc.Get(footnoteListKey).(*FootnoteList)
if tlist := pc.Get(footnoteListKey); tlist != nil {
list = tlist.(*FootnoteList)
}
if list == nil { if list == nil {
return nil return nil
} }
index := 0 index := 0
name := []byte{} name := []byte{}
for def := list.FirstChild(); def != nil; def = def.NextSibling() { for def := list.FirstChild(); def != nil; def = def.NextSibling() {
d := def.(*Footnote) d := def.(*Footnote) //nolint:forcetypeassert // a FootnoteList only holds *Footnote children
if bytes.Equal(d.Ref, value) { if bytes.Equal(d.Ref, value) {
if d.Index < 0 { if d.Index < 0 {
list.Count++ list.Count++
@@ -339,10 +334,8 @@ func NewFootnoteASTTransformer() parser.ASTTransformer {
} }
func (a *footnoteASTTransformer) Transform(node *ast.Document, reader text.Reader, pc parser.Context) { func (a *footnoteASTTransformer) Transform(node *ast.Document, reader text.Reader, pc parser.Context) {
var list *FootnoteList list, _ := pc.Get(footnoteListKey).(*FootnoteList)
if tlist := pc.Get(footnoteListKey); tlist != nil { if list == nil {
list = tlist.(*FootnoteList)
} else {
return return
} }
pc.Set(footnoteListKey, nil) pc.Set(footnoteListKey, nil)
@@ -352,18 +345,16 @@ func (a *footnoteASTTransformer) Transform(node *ast.Document, reader text.Reade
if fc := container.LastChild(); fc != nil && ast.IsParagraph(fc) { if fc := container.LastChild(); fc != nil && ast.IsParagraph(fc) {
container = fc container = fc
} }
footnoteNode := footnote.(*Footnote) footnoteNode := footnote.(*Footnote) //nolint:forcetypeassert // a FootnoteList only holds *Footnote children
index := footnoteNode.Index if footnoteNode.Index < 0 {
name := footnoteNode.Name
if index < 0 {
list.RemoveChild(list, footnote) list.RemoveChild(list, footnote)
} else { } else {
container.AppendChild(container, NewFootnoteBackLink(index, name)) container.AppendChild(container, NewFootnoteBackLink(footnoteNode.Index, footnoteNode.Name))
} }
footnote = next footnote = next
} }
list.SortChildren(func(n1, n2 ast.Node) int { list.SortChildren(func(n1, n2 ast.Node) int {
if n1.(*Footnote).Index < n2.(*Footnote).Index { if n1.(*Footnote).Index < n2.(*Footnote).Index { //nolint:forcetypeassert // a FootnoteList only holds *Footnote children
return -1 return -1
} }
return 1 return 1
@@ -403,7 +394,7 @@ func (r *FootnoteHTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegist
func (r *FootnoteHTMLRenderer) renderFootnoteLink(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { func (r *FootnoteHTMLRenderer) renderFootnoteLink(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
if entering { if entering {
n := node.(*FootnoteLink) n := node.(*FootnoteLink) //nolint:forcetypeassert // registered for KindFootnoteLink only
is := strconv.Itoa(n.Index) is := strconv.Itoa(n.Index)
_, _ = w.WriteString(`<sup id="fnref:user-content-`) _, _ = w.WriteString(`<sup id="fnref:user-content-`)
_, _ = w.Write(n.Name) _, _ = w.Write(n.Name)
@@ -418,7 +409,7 @@ func (r *FootnoteHTMLRenderer) renderFootnoteLink(w util.BufWriter, source []byt
func (r *FootnoteHTMLRenderer) renderFootnoteBackLink(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { func (r *FootnoteHTMLRenderer) renderFootnoteBackLink(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
if entering { if entering {
n := node.(*FootnoteBackLink) n := node.(*FootnoteBackLink) //nolint:forcetypeassert // registered for KindFootnoteBackLink only
_, _ = w.WriteString(` <a href="#fnref:user-content-`) _, _ = w.WriteString(` <a href="#fnref:user-content-`)
_, _ = w.Write(n.Name) _, _ = w.Write(n.Name)
_, _ = w.WriteString(`" class="footnote-backref" role="doc-backlink">`) _, _ = w.WriteString(`" class="footnote-backref" role="doc-backlink">`)
@@ -429,7 +420,7 @@ func (r *FootnoteHTMLRenderer) renderFootnoteBackLink(w util.BufWriter, source [
} }
func (r *FootnoteHTMLRenderer) renderFootnote(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { func (r *FootnoteHTMLRenderer) renderFootnote(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
n := node.(*Footnote) n := node.(*Footnote) //nolint:forcetypeassert // registered for KindFootnote only
if entering { if entering {
_, _ = w.WriteString(`<li id="fn:user-content-`) _, _ = w.WriteString(`<li id="fn:user-content-`)
_, _ = w.Write(n.Name) _, _ = w.Write(n.Name)
+4 -6
View File
@@ -43,8 +43,8 @@ func (g *ASTTransformer) applyElementDir(n ast.Node) {
// Transform transforms the given AST tree. // Transform transforms the given AST tree.
func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc parser.Context) { func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc parser.Context) {
firstChild := node.FirstChild() firstChild := node.FirstChild()
ctx := pc.Get(renderContextKey).(*markup.RenderContext) ctx := pc.Get(renderContextKey).(*markup.RenderContext) //nolint:forcetypeassert // the renderer always seeds this key before parsing
rc := pc.Get(renderConfigKey).(*RenderConfig) rc := pc.Get(renderConfigKey).(*RenderConfig) //nolint:forcetypeassert // the renderer always seeds this key before parsing
tocMode := "" tocMode := ""
if rc.yamlNode != nil { if rc.yamlNode != nil {
@@ -150,9 +150,7 @@ func (r *HTMLRenderer) renderCodeBlock(w util.BufWriter, source []byte, n ast.No
} }
func (r *HTMLRenderer) renderDocument(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { func (r *HTMLRenderer) renderDocument(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
n := node.(*ast.Document) if val, has := node.AttributeString("lang"); has {
if val, has := n.AttributeString("lang"); has {
var err error var err error
if entering { if entering {
_, err = w.WriteString("<div") _, err = w.WriteString("<div")
@@ -212,7 +210,7 @@ func (r *HTMLRenderer) renderRawHTML(w util.BufWriter, source []byte, node ast.N
if !entering { if !entering {
return ast.WalkContinue, nil return ast.WalkContinue, nil
} }
n := node.(*RawHTML) n := node.(*RawHTML) //nolint:forcetypeassert // registered for KindRawHTML only
_, err := w.WriteString(string(r.renderInternal.ProtectSafeAttrs(n.rawHTML))) _, err := w.WriteString(string(r.renderInternal.ProtectSafeAttrs(n.rawHTML)))
if err != nil { if err != nil {
return ast.WalkStop, err return ast.WalkStop, err
+1 -1
View File
@@ -86,7 +86,7 @@ func (b *blockParser) Open(parent ast.Node, reader text.Reader, pc parser.Contex
// Continue parses the current line and returns a result of parsing. // Continue parses the current line and returns a result of parsing.
func (b *blockParser) Continue(node ast.Node, reader text.Reader, pc parser.Context) parser.State { func (b *blockParser) Continue(node ast.Node, reader text.Reader, pc parser.Context) parser.State {
block := node.(*Block) block := node.(*Block) //nolint:forcetypeassert // this parser only ever opens *Block nodes
if block.Closed { if block.Closed {
return parser.Close return parser.Close
} }
@@ -49,7 +49,7 @@ func (r *BlockRenderer) writeLines(w util.BufWriter, source []byte, n gast.Node)
} }
func (r *BlockRenderer) renderBlock(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) { func (r *BlockRenderer) renderBlock(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) {
n := node.(*Block) n := node.(*Block) //nolint:forcetypeassert // registered for KindBlock only
if entering { if entering {
codeHTML := giteaUtil.Iif[template.HTML](n.Inline, "", `<pre class="code-block is-loading">`) + `<code class="language-math">` codeHTML := giteaUtil.Iif[template.HTML](n.Inline, "", `<pre class="code-block is-loading">`) + `<code class="language-math">`
_, _ = w.WriteString(string(r.renderInternal.ProtectSafeAttrs(codeHTML))) _, _ = w.WriteString(string(r.renderInternal.ProtectSafeAttrs(codeHTML)))
+2 -2
View File
@@ -19,8 +19,8 @@ func (n *Inline) Inline() {}
// IsBlank returns if this inline node is empty // IsBlank returns if this inline node is empty
func (n *Inline) IsBlank(source []byte) bool { func (n *Inline) IsBlank(source []byte) bool {
for c := n.FirstChild(); c != nil; c = c.NextSibling() { for c := n.FirstChild(); c != nil; c = c.NextSibling() {
text := c.(*ast.Text).Segment text := c.(*ast.Text) //nolint:forcetypeassert // an inline math node only holds text children
if !util.IsBlank(text.Value(source)) { if !util.IsBlank(text.Segment.Value(source)) {
return false return false
} }
} }
@@ -160,12 +160,12 @@ func trimBlock(node *Inline, block text.Reader) {
} }
// trim first space and last space // trim first space and last space
first := node.FirstChild().(*ast.Text) first := node.FirstChild().(*ast.Text) //nolint:forcetypeassert // an inline math node only holds text children
if !(!first.Segment.IsEmpty() && block.Source()[first.Segment.Start] == ' ') { if !(!first.Segment.IsEmpty() && block.Source()[first.Segment.Start] == ' ') {
return return
} }
last := node.LastChild().(*ast.Text) last := node.LastChild().(*ast.Text) //nolint:forcetypeassert // an inline math node only holds text children
if !(!last.Segment.IsEmpty() && block.Source()[last.Segment.Stop-1] == ' ') { if !(!last.Segment.IsEmpty() && block.Source()[last.Segment.Stop-1] == ' ') {
return return
} }
@@ -30,7 +30,7 @@ func (r *InlineRenderer) renderInline(w util.BufWriter, source []byte, n ast.Nod
if entering { if entering {
_, _ = w.WriteString(string(r.renderInternal.ProtectSafeAttrs(`<code class="language-math">`))) _, _ = w.WriteString(string(r.renderInternal.ProtectSafeAttrs(`<code class="language-math">`)))
for c := n.FirstChild(); c != nil; c = c.NextSibling() { for c := n.FirstChild(); c != nil; c = c.NextSibling() {
segment := c.(*ast.Text).Segment segment := c.(*ast.Text).Segment //nolint:forcetypeassert // an inline math node only holds text children
value := util.EscapeHTML(segment.Value(source)) value := util.EscapeHTML(segment.Value(source))
if bytes.HasSuffix(value, []byte("\n")) { if bytes.HasSuffix(value, []byte("\n")) {
_, _ = w.Write(value[:len(value)-1]) _, _ = w.Write(value[:len(value)-1])
@@ -18,7 +18,7 @@ import (
// renderAttention renders a quote marked with i.e. "> **Note**" or "> [!Warning]" with a corresponding svg // renderAttention renders a quote marked with i.e. "> **Note**" or "> [!Warning]" with a corresponding svg
func (r *HTMLRenderer) renderAttention(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { func (r *HTMLRenderer) renderAttention(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
if entering { if entering {
n := node.(*Attention) n := node.(*Attention) //nolint:forcetypeassert // registered for KindAttention only
var octiconName string var octiconName string
switch n.AttentionType { switch n.AttentionType {
case "tip": case "tip":
+2 -2
View File
@@ -15,7 +15,7 @@ import (
) )
func (r *HTMLRenderer) renderTaskCheckBoxListItem(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { func (r *HTMLRenderer) renderTaskCheckBoxListItem(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
n := node.(*TaskCheckBoxListItem) n := node.(*TaskCheckBoxListItem) //nolint:forcetypeassert // registered for KindTaskCheckBoxListItem only
if entering { if entering {
if n.Attributes() != nil { if n.Attributes() != nil {
_, _ = w.WriteString("<li") _, _ = w.WriteString("<li")
@@ -60,7 +60,7 @@ func (g *ASTTransformer) transformList(_ *markup.RenderContext, v *ast.List, rc
v.RemoveChildren(v) v.RemoveChildren(v)
for _, child := range children { for _, child := range children {
listItem := child.(*ast.ListItem) listItem := child.(*ast.ListItem) //nolint:forcetypeassert // a list only holds list items
if !child.HasChildren() || !child.FirstChild().HasChildren() { if !child.HasChildren() || !child.FirstChild().HasChildren() {
v.AppendChild(v, child) v.AppendChild(v, child)
continue continue
+2 -2
View File
@@ -22,8 +22,8 @@ func TestMigrationJSON_IssueOK(t *testing.T) {
func TestMigrationJSON_IssueFail(t *testing.T) { func TestMigrationJSON_IssueFail(t *testing.T) {
issues := make([]*Issue, 0, 10) issues := make([]*Issue, 0, 10)
err := Load("file_format_testdata/issue_b.json", &issues, true) err := Load("file_format_testdata/issue_b.json", &issues, true)
if _, ok := err.(*jsonschema.ValidationError); ok { if validationErr, ok := err.(*jsonschema.ValidationError); ok {
errors := strings.Split(err.(*jsonschema.ValidationError).GoString(), "\n") errors := strings.Split(validationErr.GoString(), "\n")
assert.Contains(t, errors[1], "missing properties") assert.Contains(t, errors[1], "missing properties")
assert.Contains(t, errors[1], "poster_id") assert.Contains(t, errors[1], "poster_id")
} else { } else {
+17 -8
View File
@@ -56,21 +56,30 @@ func NewMultiHasher() *MultiHasher {
} }
} }
// marshalHash saves the state of a hash, every stdlib hash implements the marshaler interfaces
func marshalHash(h hash.Hash) ([]byte, error) {
return h.(encoding.BinaryMarshaler).MarshalBinary() //nolint:forcetypeassert // every hash used here is a stdlib hash
}
func unmarshalHash(h hash.Hash, state []byte) error {
return h.(encoding.BinaryUnmarshaler).UnmarshalBinary(state) //nolint:forcetypeassert // every hash used here is a stdlib hash
}
// MarshalBinary implements encoding.BinaryMarshaler // MarshalBinary implements encoding.BinaryMarshaler
func (h *MultiHasher) MarshalBinary() ([]byte, error) { func (h *MultiHasher) MarshalBinary() ([]byte, error) {
md5Bytes, err := h.md5.(encoding.BinaryMarshaler).MarshalBinary() md5Bytes, err := marshalHash(h.md5)
if err != nil { if err != nil {
return nil, err return nil, err
} }
sha1Bytes, err := h.sha1.(encoding.BinaryMarshaler).MarshalBinary() sha1Bytes, err := marshalHash(h.sha1)
if err != nil { if err != nil {
return nil, err return nil, err
} }
sha256Bytes, err := h.sha256.(encoding.BinaryMarshaler).MarshalBinary() sha256Bytes, err := marshalHash(h.sha256)
if err != nil { if err != nil {
return nil, err return nil, err
} }
sha512Bytes, err := h.sha512.(encoding.BinaryMarshaler).MarshalBinary() sha512Bytes, err := marshalHash(h.sha512)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -89,22 +98,22 @@ func (h *MultiHasher) UnmarshalBinary(b []byte) error {
return errors.New("invalid hash state size") return errors.New("invalid hash state size")
} }
if err := h.md5.(encoding.BinaryUnmarshaler).UnmarshalBinary(b[:marshaledSizeMD5]); err != nil { if err := unmarshalHash(h.md5, b[:marshaledSizeMD5]); err != nil {
return err return err
} }
b = b[marshaledSizeMD5:] b = b[marshaledSizeMD5:]
if err := h.sha1.(encoding.BinaryUnmarshaler).UnmarshalBinary(b[:marshaledSizeSHA1]); err != nil { if err := unmarshalHash(h.sha1, b[:marshaledSizeSHA1]); err != nil {
return err return err
} }
b = b[marshaledSizeSHA1:] b = b[marshaledSizeSHA1:]
if err := h.sha256.(encoding.BinaryUnmarshaler).UnmarshalBinary(b[:marshaledSizeSHA256]); err != nil { if err := unmarshalHash(h.sha256, b[:marshaledSizeSHA256]); err != nil {
return err return err
} }
b = b[marshaledSizeSHA256:] b = b[marshaledSizeSHA256:]
return h.sha512.(encoding.BinaryUnmarshaler).UnmarshalBinary(b[:marshaledSizeSHA512]) return unmarshalHash(h.sha512, b[:marshaledSizeSHA512])
} }
// Write implements io.Writer // Write implements io.Writer
+7 -7
View File
@@ -107,13 +107,13 @@ func (e *MarshalEncoder) marshal(v any) error {
return e.marshalArray(val) return e.marshalArray(val)
} }
switch typ.Name() { switch obj := val.Interface().(type) {
case "RubyUserMarshal": case RubyUserMarshal:
return e.marshalUserMarshal(val.Interface().(RubyUserMarshal)) return e.marshalUserMarshal(obj)
case "RubyUserDef": case RubyUserDef:
return e.marshalUserDef(val.Interface().(RubyUserDef)) return e.marshalUserDef(obj)
case "RubyObject": case RubyObject:
return e.marshalObject(val.Interface().(RubyObject)) return e.marshalObject(obj)
} }
return ErrUnsupportedType return ErrUnsupportedType
+12
View File
@@ -5,13 +5,25 @@ package reqctx
import ( import (
"context" "context"
"fmt"
"io" "io"
"maps" "maps"
"reflect"
"sync" "sync"
"gitea.dev/modules/process" "gitea.dev/modules/process"
) )
// MustContextValue returns the value stored under key. A missing or mistyped value can only
// be a programming error, and callers can't do anything useful with a zero value, so it panics.
func MustContextValue[T any](ctx context.Context, key any) T {
value, ok := ctx.Value(key).(T)
if !ok {
panic(fmt.Sprintf("context value %v is %T, expected %s", key, ctx.Value(key), reflect.TypeFor[T]()))
}
return value
}
type ContextDataProvider interface { type ContextDataProvider interface {
GetData() ContextData GetData() ContextData
} }
+4 -4
View File
@@ -28,8 +28,8 @@ func RegenerateSession(resp http.ResponseWriter, req *http.Request) (Store, erro
f(resp, req) f(resp, req)
} }
if setting.IsInTesting { if setting.IsInTesting {
if store := req.Context().Value(MockStoreContextKey); store != nil { if store, ok := req.Context().Value(MockStoreContextKey).(Store); ok {
return store.(Store), nil return store, nil
} }
} }
return session.RegenerateSession(resp, req) return session.RegenerateSession(resp, req)
@@ -37,8 +37,8 @@ func RegenerateSession(resp http.ResponseWriter, req *http.Request) (Store, erro
func GetContextSession(req *http.Request) Store { func GetContextSession(req *http.Request) Store {
if setting.IsInTesting { if setting.IsInTesting {
if store := req.Context().Value(MockStoreContextKey); store != nil { if store, ok := req.Context().Value(MockStoreContextKey).(Store); ok {
return store.(Store) return store
} }
} }
return session.GetSession(req) return session.GetSession(req)
+1 -1
View File
@@ -99,7 +99,7 @@ func renderHTML(icon string, others ...any) (_ template.HTML, usingCache bool) {
cacheKey := svgCacheKey{icon, size, class} cacheKey := svgCacheKey{icon, size, class}
cachedHTML, cached := svgCache.Load(cacheKey) cachedHTML, cached := svgCache.Load(cacheKey)
if cached && !svgItem.mocking { if cached && !svgItem.mocking {
return cachedHTML.(template.HTML), true return cachedHTML.(template.HTML), true //nolint:forcetypeassert // svgCache only ever holds template.HTML
} }
// the code is somewhat hacky, but it just works, because the SVG contents are all normalized // the code is somewhat hacky, but it just works, because the SVG contents are all normalized
+3 -3
View File
@@ -145,7 +145,7 @@ func applyOp2(op operator, n1, n2 Num) Num {
f2, _ := util.ToFloat64(n2.Value) f2, _ := util.ToFloat64(n2.Value)
return applyOp2Generic(op, f1, f2) return applyOp2Generic(op, f1, f2)
} }
return applyOp2Generic(op, n1.Value.(int64), n2.Value.(int64)) return applyOp2Generic(op, n1.Value.(int64), n2.Value.(int64)) //nolint:forcetypeassert // castFloat64 above already ruled out float
} }
func toOp(v any) (operator, error) { func toOp(v any) (operator, error) {
@@ -321,13 +321,13 @@ func fnSum(nums []Num) Num {
if castFloat64(nums) { if castFloat64(nums) {
var sum float64 var sum float64
for _, num := range nums { for _, num := range nums {
sum += num.Value.(float64) sum += num.Value.(float64) //nolint:forcetypeassert // castFloat64 reported every value is float64
} }
return Num{sum} return Num{sum}
} }
var sum int64 var sum int64
for _, num := range nums { for _, num := range nums {
sum += num.Value.(int64) sum += num.Value.(int64) //nolint:forcetypeassert // castFloat64 ruled out float, so every value is int64
} }
return Num{sum} return Num{sum}
} }
+4 -1
View File
@@ -9,6 +9,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func tokens(s string) (a []any) { func tokens(s string) (a []any) {
@@ -21,7 +22,9 @@ func tokens(s string) (a []any) {
func TestEval(t *testing.T) { func TestEval(t *testing.T) {
n, err := Expr(0, "/", 0.0) n, err := Expr(0, "/", 0.0)
assert.NoError(t, err) assert.NoError(t, err)
assert.True(t, math.IsNaN(n.Value.(float64))) nan, ok := n.Value.(float64)
require.True(t, ok)
assert.True(t, math.IsNaN(nan))
_, err = Expr(nil) _, err = Expr(nil)
assert.ErrorContains(t, err, "unsupported token type") assert.ErrorContains(t, err, "unsupported token type")
+17 -21
View File
@@ -166,9 +166,9 @@ func newScopedTemplateSet(all *template.Template, name string) (*scopedTemplateS
var collectErr error // only need to collect the one error var collectErr error // only need to collect the one error
collectTemplates = func(nodes []parse.Node) { collectTemplates = func(nodes []parse.Node) {
for _, node := range nodes { for _, node := range nodes {
if node.Type() == parse.NodeTemplate { switch node := node.(type) {
nodeTemplate := node.(*parse.TemplateNode) case *parse.TemplateNode:
subName := nodeTemplate.Name subName := node.Name
if ts.htmlTemplates[subName] == nil { if ts.htmlTemplates[subName] == nil {
subTmpl := all.Lookup(subName) subTmpl := all.Lookup(subName)
if subTmpl == nil { if subTmpl == nil {
@@ -185,26 +185,22 @@ func newScopedTemplateSet(all *template.Template, name string) (*scopedTemplateS
collectTemplates(subTmpl.Tree.Root.Nodes) collectTemplates(subTmpl.Tree.Root.Nodes)
} }
} }
} else if node.Type() == parse.NodeList { case *parse.ListNode:
nodeList := node.(*parse.ListNode) collectTemplates(node.Nodes)
collectTemplates(nodeList.Nodes) case *parse.IfNode:
} else if node.Type() == parse.NodeIf { collectTemplates(node.BranchNode.List.Nodes)
nodeIf := node.(*parse.IfNode) if node.BranchNode.ElseList != nil {
collectTemplates(nodeIf.BranchNode.List.Nodes) collectTemplates(node.BranchNode.ElseList.Nodes)
if nodeIf.BranchNode.ElseList != nil {
collectTemplates(nodeIf.BranchNode.ElseList.Nodes)
} }
} else if node.Type() == parse.NodeRange { case *parse.RangeNode:
nodeRange := node.(*parse.RangeNode) collectTemplates(node.BranchNode.List.Nodes)
collectTemplates(nodeRange.BranchNode.List.Nodes) if node.BranchNode.ElseList != nil {
if nodeRange.BranchNode.ElseList != nil { collectTemplates(node.BranchNode.ElseList.Nodes)
collectTemplates(nodeRange.BranchNode.ElseList.Nodes)
} }
} else if node.Type() == parse.NodeWith { case *parse.WithNode:
nodeWith := node.(*parse.WithNode) collectTemplates(node.BranchNode.List.Nodes)
collectTemplates(nodeWith.BranchNode.List.Nodes) if node.BranchNode.ElseList != nil {
if nodeWith.BranchNode.ElseList != nil { collectTemplates(node.BranchNode.ElseList.Nodes)
collectTemplates(nodeWith.BranchNode.ElseList.Nodes)
} }
} }
} }
+7 -3
View File
@@ -42,6 +42,10 @@ func NewRenderUtils(ctx reqctx.RequestContext) *RenderUtils {
return &RenderUtils{ctx: ctx, avatarUtils: NewAvatarUtils(ctx)} return &RenderUtils{ctx: ctx, avatarUtils: NewAvatarUtils(ctx)}
} }
func (ut *RenderUtils) locale() translation.Locale {
return ut.ctx.Value(translation.ContextKey).(translation.Locale) //nolint:forcetypeassert // the render context always carries a locale
}
// RenderCommitMessage renders commit message title (only title) // RenderCommitMessage renders commit message title (only title)
func (ut *RenderUtils) RenderCommitMessage(msg string, repo *repo.Repository) template.HTML { func (ut *RenderUtils) RenderCommitMessage(msg string, repo *repo.Repository) template.HTML {
msgLine := strings.TrimSpace(msg) msgLine := strings.TrimSpace(msg)
@@ -98,7 +102,7 @@ func (ut *RenderUtils) RenderIssueSimpleTitle(text string) template.HTML {
} }
func (ut *RenderUtils) RenderLabel(label *issues_model.Label) template.HTML { func (ut *RenderUtils) RenderLabel(label *issues_model.Label) template.HTML {
locale := ut.ctx.Value(translation.ContextKey).(translation.Locale) locale := ut.locale()
var extraCSSClasses string var extraCSSClasses string
textColor := util.ContrastColor(label.Color) textColor := util.ContrastColor(label.Color)
labelScope := label.ExclusiveScope() labelScope := label.ExclusiveScope()
@@ -279,7 +283,7 @@ func (ut *RenderUtils) RenderUnicodeEscapeToggleButton(escapeStatus *charset.Esc
if escapeStatus == nil || !escapeStatus.Escaped { if escapeStatus == nil || !escapeStatus.Escaped {
return "" return ""
} }
locale := ut.ctx.Value(translation.ContextKey).(translation.Locale) locale := ut.locale()
var title template.HTML var title template.HTML
if escapeStatus.HasAmbiguous { if escapeStatus.HasAmbiguous {
title += locale.Tr("repo.ambiguous_runes_line") title += locale.Tr("repo.ambiguous_runes_line")
@@ -376,7 +380,7 @@ func (ut *RenderUtils) AvatarStackPushCommit(pushCommit *repository.PushCommit)
// AvatarStackWithNames renders the avatar stack plus a label: `name` / `a and b` / `N people` (opens popup). // AvatarStackWithNames renders the avatar stack plus a label: `name` / `a and b` / `N people` (opens popup).
func (ut *RenderUtils) AvatarStackWithNames(data *user_model.AvatarStackData) template.HTML { func (ut *RenderUtils) AvatarStackWithNames(data *user_model.AvatarStackData) template.HTML {
locale := ut.ctx.Value(translation.ContextKey).(translation.Locale) locale := ut.locale()
participants := data.Participants participants := data.Participants
var b htmlutil.HTMLBuilder var b htmlutil.HTMLBuilder
+1 -2
View File
@@ -11,7 +11,6 @@ import (
"gitea.dev/modules/htmlutil" "gitea.dev/modules/htmlutil"
"gitea.dev/modules/setting" "gitea.dev/modules/setting"
"gitea.dev/modules/svg" "gitea.dev/modules/svg"
"gitea.dev/modules/translation"
"gitea.dev/modules/util" "gitea.dev/modules/util"
) )
@@ -35,7 +34,7 @@ func (ut *RenderUtils) RenderTimelineEventBadge(c *issues_model.Comment) templat
func (ut *RenderUtils) RenderTimelineEventComment(c *issues_model.Comment, createdStr template.HTML) template.HTML { func (ut *RenderUtils) RenderTimelineEventComment(c *issues_model.Comment, createdStr template.HTML) template.HTML {
if c.Type == issues_model.CommentTypeChangeTitle { if c.Type == issues_model.CommentTypeChangeTitle {
locale := ut.ctx.Value(translation.ContextKey).(translation.Locale) locale := ut.locale()
isToggle, isWip := commentTimelineEventIsWipToggle(c) isToggle, isWip := commentTimelineEventIsWipToggle(c)
if !isToggle { if !isToggle {
return locale.Tr("repo.issues.change_title_at", ut.RenderEmoji(c.OldTitle), ut.RenderEmoji(c.NewTitle), createdStr) return locale.Tr("repo.issues.change_title_at", ut.RenderEmoji(c.OldTitle), ut.RenderEmoji(c.NewTitle), createdStr)
+5 -1
View File
@@ -72,12 +72,16 @@ func (store *localeStore) AddLocaleByJSON(langName, langDesc string, source, mor
l.idxToMsgMap[idx] = v l.idxToMsgMap[idx] = v
case map[string]any: case map[string]any:
for key, val := range v { for key, val := range v {
valStr, ok := val.(string)
if !ok {
return fmt.Errorf("unsupported value type %T for key %q", val, trKey+"."+key)
}
idx, ok := store.trKeyToIdxMap[trKey+"."+key] idx, ok := store.trKeyToIdxMap[trKey+"."+key]
if !ok { if !ok {
idx = len(store.trKeyToIdxMap) idx = len(store.trKeyToIdxMap)
store.trKeyToIdxMap[trKey+"."+key] = idx store.trKeyToIdxMap[trKey+"."+key] = idx
} }
l.idxToMsgMap[idx] = val.(string) l.idxToMsgMap[idx] = valStr
} }
default: default:
return fmt.Errorf("unsupported value type %T for key %q", v, trKey) return fmt.Errorf("unsupported value type %T for key %q", v, trKey)
+1 -1
View File
@@ -20,7 +20,7 @@ import (
// httpClient returns an HTTP client that honors Gitea's proxy configuration. // httpClient returns an HTTP client that honors Gitea's proxy configuration.
var httpClient = util.OnceValue[*http.Client]{ var httpClient = util.OnceValue[*http.Client]{
Func: func() *http.Client { Func: func() *http.Client {
transport := http.DefaultTransport.(*http.Transport).Clone() transport := http.DefaultTransport.(*http.Transport).Clone() //nolint:forcetypeassert // Golang stdlib
transport.Proxy = proxy.Proxy() transport.Proxy = proxy.Proxy()
return &http.Client{Transport: transport} return &http.Client{Transport: transport}
}, },
+8 -3
View File
@@ -8,6 +8,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func TestErrorTranslatable(t *testing.T) { func TestErrorTranslatable(t *testing.T) {
@@ -16,8 +17,10 @@ func TestErrorTranslatable(t *testing.T) {
err = ErrorWrapTranslatable(io.EOF, "key", 1) err = ErrorWrapTranslatable(io.EOF, "key", 1)
assert.ErrorIs(t, err, io.EOF) assert.ErrorIs(t, err, io.EOF)
assert.Equal(t, "EOF", err.Error()) assert.Equal(t, "EOF", err.Error())
assert.Equal(t, "key", err.(*errorTranslatableWrapper).trKey) wrapped, ok := err.(*errorTranslatableWrapper)
assert.Equal(t, []any{1}, err.(*errorTranslatableWrapper).trArgs) require.True(t, ok)
assert.Equal(t, "key", wrapped.trKey)
assert.Equal(t, []any{1}, wrapped.trArgs)
err = ErrorWrap(err, "new msg %d", 100) err = ErrorWrap(err, "new msg %d", 100)
assert.ErrorIs(t, err, io.EOF) assert.ErrorIs(t, err, io.EOF)
@@ -25,5 +28,7 @@ func TestErrorTranslatable(t *testing.T) {
errTr := ErrorAsTranslatable(err) errTr := ErrorAsTranslatable(err)
assert.Equal(t, "EOF", errTr.Error()) assert.Equal(t, "EOF", errTr.Error())
assert.Equal(t, "key", errTr.(*errorTranslatableWrapper).trKey) wrapped, ok = errTr.(*errorTranslatableWrapper)
require.True(t, ok)
assert.Equal(t, "key", wrapped.trKey)
} }
+4 -1
View File
@@ -13,6 +13,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func TestKeygen(t *testing.T) { func TestKeygen(t *testing.T) {
@@ -55,6 +56,8 @@ func TestSignUsingKeys(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
// Verify // Verify
err = rsa.VerifyPKCS1v15(pubParsed.(*rsa.PublicKey), crypto.SHA256, d, sig) pubKey, ok := pubParsed.(*rsa.PublicKey)
require.True(t, ok)
err = rsa.VerifyPKCS1v15(pubKey, crypto.SHA256, d, sig)
assert.NoError(t, err) assert.NoError(t, err)
} }
-13
View File
@@ -1,13 +0,0 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package util
func GetMapValueOrDefault[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
}
-26
View File
@@ -1,26 +0,0 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package util
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestGetMapValueOrDefault(t *testing.T) {
testMap := map[string]any{
"key1": "value1",
"key2": 42,
"key3": nil,
}
assert.Equal(t, "value1", GetMapValueOrDefault(testMap, "key1", "default"))
assert.Equal(t, 42, GetMapValueOrDefault(testMap, "key2", 0))
assert.Equal(t, "default", GetMapValueOrDefault(testMap, "key4", "default"))
assert.Equal(t, 100, GetMapValueOrDefault(testMap, "key5", 100))
assert.Equal(t, "default", GetMapValueOrDefault(testMap, "key3", "default"))
}
+7 -14
View File
@@ -3,31 +3,24 @@
package util package util
import "reflect"
// PaginateSlice cut a slice as per pagination options // PaginateSlice cut a slice as per pagination options
// if page = 0 it do not paginate // if page = 0 it do not paginate
func PaginateSlice(list any, page, pageSize int) any { func PaginateSlice[S ~[]E, E any](list S, page, pageSize int) S {
if page <= 0 || pageSize <= 0 { if page <= 0 || pageSize <= 0 {
return list return list
} }
if reflect.TypeOf(list).Kind() != reflect.Slice {
return list
}
listValue := reflect.ValueOf(list)
page-- page--
if page*pageSize >= listValue.Len() { if page*pageSize >= len(list) {
return listValue.Slice(listValue.Len(), listValue.Len()).Interface() return list[len(list):]
} }
listValue = listValue.Slice(page*pageSize, listValue.Len()) list = list[page*pageSize:]
if listValue.Len() > pageSize { if len(list) > pageSize {
return listValue.Slice(0, pageSize).Interface() return list[:pageSize]
} }
return listValue.Interface() return list
} }
+7 -14
View File
@@ -11,24 +11,19 @@ import (
func TestPaginateSlice(t *testing.T) { func TestPaginateSlice(t *testing.T) {
stringSlice := []string{"a", "b", "c", "d", "e"} stringSlice := []string{"a", "b", "c", "d", "e"}
result, ok := PaginateSlice(stringSlice, 1, 2).([]string) result := PaginateSlice(stringSlice, 1, 2)
assert.True(t, ok)
assert.Equal(t, []string{"a", "b"}, result) assert.Equal(t, []string{"a", "b"}, result)
result, ok = PaginateSlice(stringSlice, 100, 2).([]string) result = PaginateSlice(stringSlice, 100, 2)
assert.True(t, ok)
assert.Equal(t, []string{}, result) assert.Equal(t, []string{}, result)
result, ok = PaginateSlice(stringSlice, 3, 2).([]string) result = PaginateSlice(stringSlice, 3, 2)
assert.True(t, ok)
assert.Equal(t, []string{"e"}, result) assert.Equal(t, []string{"e"}, result)
result, ok = PaginateSlice(stringSlice, 1, 0).([]string) result = PaginateSlice(stringSlice, 1, 0)
assert.True(t, ok)
assert.Equal(t, []string{"a", "b", "c", "d", "e"}, result) assert.Equal(t, []string{"a", "b", "c", "d", "e"}, result)
result, ok = PaginateSlice(stringSlice, 1, -1).([]string) result = PaginateSlice(stringSlice, 1, -1)
assert.True(t, ok)
assert.Equal(t, []string{"a", "b", "c", "d", "e"}, result) assert.Equal(t, []string{"a", "b", "c", "d", "e"}, result)
type Test struct { type Test struct {
@@ -36,11 +31,9 @@ func TestPaginateSlice(t *testing.T) {
} }
testVar := []*Test{{Val: 2}, {Val: 3}, {Val: 4}} testVar := []*Test{{Val: 2}, {Val: 3}, {Val: 4}}
testVar, ok = PaginateSlice(testVar, 1, 50).([]*Test) testVar = PaginateSlice(testVar, 1, 50)
assert.True(t, ok)
assert.Equal(t, []*Test{{Val: 2}, {Val: 3}, {Val: 4}}, testVar) assert.Equal(t, []*Test{{Val: 2}, {Val: 3}, {Val: 4}}, testVar)
testVar, ok = PaginateSlice(testVar, 2, 2).([]*Test) testVar = PaginateSlice(testVar, 2, 2)
assert.True(t, ok)
assert.Equal(t, []*Test{{Val: 4}}, testVar) assert.Equal(t, []*Test{{Val: 4}}, testVar)
} }
+5 -4
View File
@@ -107,7 +107,7 @@ func FastCryptoRandomBytes(length int) []byte {
// ChaCha8 is about 20x times faster than system's crypto/rand. // ChaCha8 is about 20x times faster than system's crypto/rand.
// It is suitable for UUIDs, session IDs, etc // It is suitable for UUIDs, session IDs, etc
pool := chaCha8RandPool() pool := chaCha8RandPool()
chaCha8Rand := pool.Get().(*rand2.ChaCha8) chaCha8Rand := pool.Get().(*rand2.ChaCha8) //nolint:forcetypeassert // the pool's New only ever makes *rand2.ChaCha8
defer pool.Put(chaCha8Rand) defer pool.Put(chaCha8Rand)
buf := make([]byte, length) buf := make([]byte, length)
_, _ = chaCha8Rand.Read(buf) _, _ = chaCha8Rand.Read(buf)
@@ -270,15 +270,16 @@ func OptionalArg[T any](optArg []T, defaultValue ...T) (ret T) {
} }
type EnumConst[T comparable] interface { type EnumConst[T comparable] interface {
comparable
EnumValues() []T EnumValues() []T
} }
// EnumValue returns the value if it's in the enum const's values, // EnumValue returns the value if it's in the enum const's values,
// otherwise returns the first item of enums as default value. // otherwise returns the first item of enums as default value.
func EnumValue[T comparable](val EnumConst[T]) (ret T, valid bool) { func EnumValue[T EnumConst[T]](val T) (ret T, valid bool) {
enums := val.EnumValues() enums := val.EnumValues()
if slices.Contains(enums, val.(T)) { if slices.Contains(enums, val) {
return val.(T), true return val, true
} }
return enums[0], false return enums[0], false
} }
+7 -2
View File
@@ -4,6 +4,7 @@
package web package web
import ( import (
"fmt"
"net/http" "net/http"
"net/url" "net/url"
"reflect" "reflect"
@@ -37,8 +38,12 @@ func SetForm(dataStore reqctx.ContextDataProvider, obj any) {
} }
// GetForm returns the validate form information // GetForm returns the validate form information
func GetForm(dataStore reqctx.RequestDataStore) any { func GetForm[T any](dataStore reqctx.RequestDataStore) T {
return dataStore.GetData()["__form"] form, ok := dataStore.GetData()["__form"].(T)
if !ok {
panic(fmt.Errorf("bound form %T does not match the requested type %s", dataStore.GetData()["__form"], reflect.TypeFor[T]()))
}
return form
} }
// Router defines a route based on chi's router // Router defines a route based on chi's router
+2 -2
View File
@@ -54,10 +54,10 @@ func (manager *loggerRequestManager) startSlowQueryDetector(threshold time.Durat
// print logs for slow requests // print logs for slow requests
manager.reqRecords.Range(func(key, value any) bool { manager.reqRecords.Range(func(key, value any) bool {
index, record := key.(uint64), value.(*requestRecord) record := value.(*requestRecord) //nolint:forcetypeassert // reqRecords only ever holds *requestRecord
if now.Sub(record.startTime) >= threshold { if now.Sub(record.startTime) >= threshold {
manager.logPrint(StillExecutingEvent, record) manager.logPrint(StillExecutingEvent, record)
manager.reqRecords.Delete(index) manager.reqRecords.Delete(key)
} }
return true return true
}) })
+2 -1
View File
@@ -75,6 +75,7 @@ import (
"gitea.dev/modules/json" "gitea.dev/modules/json"
"gitea.dev/modules/log" "gitea.dev/modules/log"
"gitea.dev/modules/optional" "gitea.dev/modules/optional"
"gitea.dev/modules/reqctx"
"gitea.dev/modules/setting" "gitea.dev/modules/setting"
"gitea.dev/modules/storage" "gitea.dev/modules/storage"
"gitea.dev/modules/util" "gitea.dev/modules/util"
@@ -98,7 +99,7 @@ type ArtifactContext struct {
func init() { func init() {
web.RegisterResponseStatusProvider[*ArtifactContext](func(req *http.Request) web_types.ResponseStatusProvider { web.RegisterResponseStatusProvider[*ArtifactContext](func(req *http.Request) web_types.ResponseStatusProvider {
return req.Context().Value(artifactContextKey).(*ArtifactContext) return reqctx.MustContextValue[*ArtifactContext](req.Context(), artifactContextKey)
}) })
} }
+1 -1
View File
@@ -323,7 +323,7 @@ func mergeChunksForArtifact(ctx *ArtifactContext, chunks []*chunkFileItem, st st
readers := make([]io.Reader, 0, len(allChunks)) readers := make([]io.Reader, 0, len(allChunks))
closeReaders := func() { closeReaders := func() {
for _, r := range readers { for _, r := range readers {
_ = r.(io.Closer).Close() // it guarantees to be io.Closer by the following loop's Open function _ = r.(io.Closer).Close() //nolint:forcetypeassert // it guarantees to be io.Closer by the following loop's Open function
} }
readers = nil readers = nil
} }
+1 -1
View File
@@ -127,7 +127,7 @@ func SearchPackages(ctx *context.Context) {
crates = append(crates, &SearchResultCrate{ crates = append(crates, &SearchResultCrate{
Name: pd.Package.Name, Name: pd.Package.Name,
LatestVersion: pd.Version.Version, LatestVersion: pd.Version.Version,
Description: pd.Metadata.(*cargo_module.Metadata).Description, Description: packages_model.DescriptorMetadata[*cargo_module.Metadata](pd).Description,
}) })
} }
+6 -1
View File
@@ -78,7 +78,12 @@ func (a *Auth) Verify(req *http.Request, w http.ResponseWriter, store auth.DataS
return nil, err return nil, err
} }
if err := verifySignedHeaders(req, version, pub.(*rsa.PublicKey)); err != nil { rsaPub, ok := pub.(*rsa.PublicKey)
if !ok {
return nil, errors.New("public key is not a RSA key")
}
if err := verifySignedHeaders(req, version, rsaPub); err != nil {
return nil, err return nil, err
} }
+4 -4
View File
@@ -71,7 +71,7 @@ func PackagesUniverse(ctx *context.Context) {
LocationType: "opscode", LocationType: "opscode",
LocationPath: baseURL, LocationPath: baseURL,
DownloadURL: fmt.Sprintf("%s/cookbooks/%s/versions/%s/download", baseURL, url.PathEscape(pd.Package.Name), pd.Version.Version), DownloadURL: fmt.Sprintf("%s/cookbooks/%s/versions/%s/download", baseURL, url.PathEscape(pd.Package.Name), pd.Version.Version),
Dependencies: pd.Metadata.(*chef_module.Metadata).Dependencies, Dependencies: packages_model.DescriptorMetadata[*chef_module.Metadata](pd).Dependencies,
} }
} }
@@ -128,7 +128,7 @@ func EnumeratePackages(ctx *context.Context) {
items := make([]*Item, 0, len(pds)) items := make([]*Item, 0, len(pds))
for _, pd := range pds { for _, pd := range pds {
metadata := pd.Metadata.(*chef_module.Metadata) metadata := packages_model.DescriptorMetadata[*chef_module.Metadata](pd)
items = append(items, &Item{ items = append(items, &Item{
CookbookName: pd.Package.Name, CookbookName: pd.Package.Name,
@@ -193,7 +193,7 @@ func PackageMetadata(ctx *context.Context) {
latest := pds[len(pds)-1] latest := pds[len(pds)-1]
metadata := latest.Metadata.(*chef_module.Metadata) metadata := packages_model.DescriptorMetadata[*chef_module.Metadata](latest)
ctx.JSON(http.StatusOK, &Result{ ctx.JSON(http.StatusOK, &Result{
Name: latest.Package.Name, Name: latest.Package.Name,
@@ -241,7 +241,7 @@ func PackageVersionMetadata(ctx *context.Context) {
baseURL := fmt.Sprintf("%sapi/packages/%s/chef/api/v1/cookbooks/%s", setting.AppURL, ctx.Package.Owner.Name, url.PathEscape(pd.Package.Name)) baseURL := fmt.Sprintf("%sapi/packages/%s/chef/api/v1/cookbooks/%s", setting.AppURL, ctx.Package.Owner.Name, url.PathEscape(pd.Package.Name))
metadata := pd.Metadata.(*chef_module.Metadata) metadata := packages_model.DescriptorMetadata[*chef_module.Metadata](pd)
ctx.JSON(http.StatusOK, &Result{ ctx.JSON(http.StatusOK, &Result{
Version: pd.Version.Version, Version: pd.Version.Version,
+2 -2
View File
@@ -50,7 +50,7 @@ func createSearchResultResponse(total int64, pds []*packages_model.PackageDescri
for _, pd := range pds { for _, pd := range pds {
results = append(results, &SearchResult{ results = append(results, &SearchResult{
Name: pd.Package.Name, Name: pd.Package.Name,
Description: pd.Metadata.(*composer_module.Metadata).Description, Description: packages_model.DescriptorMetadata[*composer_module.Metadata](pd).Description,
Downloads: pd.Version.DownloadCount, Downloads: pd.Version.DownloadCount,
}) })
} }
@@ -111,7 +111,7 @@ func createPackageMetadataResponse(ctx *context.Context, registryURL string, pds
Version: pd.Version.Version, Version: pd.Version.Version,
Type: packageType, Type: packageType,
Created: pd.Version.CreatedUnix.AsLocalTime(), Created: pd.Version.CreatedUnix.AsLocalTime(),
Metadata: pd.Metadata.(*composer_module.Metadata), Metadata: packages_model.DescriptorMetadata[*composer_module.Metadata](pd),
Dist: Dist{ Dist: Dist{
Type: "zip", Type: "zip",
URL: fmt.Sprintf("%s/files/%s/%s/%s", registryURL, url.PathEscape(pd.Package.LowerName), url.PathEscape(pd.Version.LowerVersion), url.PathEscape(pd.Files[0].File.LowerName)), URL: fmt.Sprintf("%s/files/%s/%s/%s", registryURL, url.PathEscape(pd.Package.LowerName), url.PathEscape(pd.Version.LowerVersion), url.PathEscape(pd.Files[0].File.LowerName)),
+35 -27
View File
@@ -103,6 +103,14 @@ func ExtractPathParameters(ctx *context.Context) {
ctx.Data[packageReferenceKey] = pref ctx.Data[packageReferenceKey] = pref
} }
func getRecipeReference(ctx *context.Context) *conan_module.RecipeReference {
return ctx.Data[recipeReferenceKey].(*conan_module.RecipeReference) //nolint:forcetypeassert // must be valid
}
func getPackageReference(ctx *context.Context) *conan_module.PackageReference {
return ctx.Data[packageReferenceKey].(*conan_module.PackageReference) //nolint:forcetypeassert // must be valid
}
// Ping reports the server capabilities // Ping reports the server capabilities
func Ping(ctx *context.Context) { func Ping(ctx *context.Context) {
ctx.RespHeader().Add("X-Conan-Server-Capabilities", "revisions") // complex_search,checksum_deploy,matrix_params ctx.RespHeader().Add("X-Conan-Server-Capabilities", "revisions") // complex_search,checksum_deploy,matrix_params
@@ -164,20 +172,20 @@ func CheckCredentials(ctx *context.Context) {
// RecipeSnapshot displays the recipe files with their md5 hash // RecipeSnapshot displays the recipe files with their md5 hash
func RecipeSnapshot(ctx *context.Context) { func RecipeSnapshot(ctx *context.Context) {
rref := ctx.Data[recipeReferenceKey].(*conan_module.RecipeReference) rref := getRecipeReference(ctx)
serveSnapshot(ctx, rref.AsKey()) serveSnapshot(ctx, rref.AsKey())
} }
// RecipeSnapshot displays the package files with their md5 hash // RecipeSnapshot displays the package files with their md5 hash
func PackageSnapshot(ctx *context.Context) { func PackageSnapshot(ctx *context.Context) {
pref := ctx.Data[packageReferenceKey].(*conan_module.PackageReference) pref := getPackageReference(ctx)
serveSnapshot(ctx, pref.AsKey()) serveSnapshot(ctx, pref.AsKey())
} }
func serveSnapshot(ctx *context.Context, fileKey string) { func serveSnapshot(ctx *context.Context, fileKey string) {
rref := ctx.Data[recipeReferenceKey].(*conan_module.RecipeReference) rref := getRecipeReference(ctx)
pv, err := packages_model.GetVersionByNameAndVersion(ctx, ctx.Package.Owner.ID, packages_model.TypeConan, rref.Name, rref.Version) pv, err := packages_model.GetVersionByNameAndVersion(ctx, ctx.Package.Owner.ID, packages_model.TypeConan, rref.Name, rref.Version)
if err != nil { if err != nil {
@@ -217,7 +225,7 @@ func serveSnapshot(ctx *context.Context, fileKey string) {
// RecipeDownloadURLs displays the recipe files with their download url // RecipeDownloadURLs displays the recipe files with their download url
func RecipeDownloadURLs(ctx *context.Context) { func RecipeDownloadURLs(ctx *context.Context) {
rref := ctx.Data[recipeReferenceKey].(*conan_module.RecipeReference) rref := getRecipeReference(ctx)
serveDownloadURLs( serveDownloadURLs(
ctx, ctx,
@@ -228,7 +236,7 @@ func RecipeDownloadURLs(ctx *context.Context) {
// PackageDownloadURLs displays the package files with their download url // PackageDownloadURLs displays the package files with their download url
func PackageDownloadURLs(ctx *context.Context) { func PackageDownloadURLs(ctx *context.Context) {
pref := ctx.Data[packageReferenceKey].(*conan_module.PackageReference) pref := getPackageReference(ctx)
serveDownloadURLs( serveDownloadURLs(
ctx, ctx,
@@ -238,7 +246,7 @@ func PackageDownloadURLs(ctx *context.Context) {
} }
func serveDownloadURLs(ctx *context.Context, fileKey, downloadURL string) { func serveDownloadURLs(ctx *context.Context, fileKey, downloadURL string) {
rref := ctx.Data[recipeReferenceKey].(*conan_module.RecipeReference) rref := getRecipeReference(ctx)
pv, err := packages_model.GetVersionByNameAndVersion(ctx, ctx.Package.Owner.ID, packages_model.TypeConan, rref.Name, rref.Version) pv, err := packages_model.GetVersionByNameAndVersion(ctx, ctx.Package.Owner.ID, packages_model.TypeConan, rref.Name, rref.Version)
if err != nil { if err != nil {
@@ -274,7 +282,7 @@ func serveDownloadURLs(ctx *context.Context, fileKey, downloadURL string) {
// RecipeUploadURLs displays the upload urls for the provided recipe files // RecipeUploadURLs displays the upload urls for the provided recipe files
func RecipeUploadURLs(ctx *context.Context) { func RecipeUploadURLs(ctx *context.Context) {
rref := ctx.Data[recipeReferenceKey].(*conan_module.RecipeReference) rref := getRecipeReference(ctx)
serveUploadURLs( serveUploadURLs(
ctx, ctx,
@@ -285,7 +293,7 @@ func RecipeUploadURLs(ctx *context.Context) {
// PackageUploadURLs displays the upload urls for the provided package files // PackageUploadURLs displays the upload urls for the provided package files
func PackageUploadURLs(ctx *context.Context) { func PackageUploadURLs(ctx *context.Context) {
pref := ctx.Data[packageReferenceKey].(*conan_module.PackageReference) pref := getPackageReference(ctx)
serveUploadURLs( serveUploadURLs(
ctx, ctx,
@@ -315,21 +323,21 @@ func serveUploadURLs(ctx *context.Context, fileFilter container.Set[string], upl
// UploadRecipeFile handles the upload of a recipe file // UploadRecipeFile handles the upload of a recipe file
func UploadRecipeFile(ctx *context.Context) { func UploadRecipeFile(ctx *context.Context) {
rref := ctx.Data[recipeReferenceKey].(*conan_module.RecipeReference) rref := getRecipeReference(ctx)
uploadFile(ctx, recipeFileList, rref.AsKey()) uploadFile(ctx, recipeFileList, rref.AsKey())
} }
// UploadPackageFile handles the upload of a package file // UploadPackageFile handles the upload of a package file
func UploadPackageFile(ctx *context.Context) { func UploadPackageFile(ctx *context.Context) {
pref := ctx.Data[packageReferenceKey].(*conan_module.PackageReference) pref := getPackageReference(ctx)
uploadFile(ctx, packageFileList, pref.AsKey()) uploadFile(ctx, packageFileList, pref.AsKey())
} }
func uploadFile(ctx *context.Context, fileFilter container.Set[string], fileKey string) { func uploadFile(ctx *context.Context, fileFilter container.Set[string], fileKey string) {
rref := ctx.Data[recipeReferenceKey].(*conan_module.RecipeReference) rref := getRecipeReference(ctx)
pref := ctx.Data[packageReferenceKey].(*conan_module.PackageReference) pref := getPackageReference(ctx)
filename := ctx.PathParam("filename") filename := ctx.PathParam("filename")
if !fileFilter.Contains(filename) { if !fileFilter.Contains(filename) {
@@ -454,20 +462,20 @@ func uploadFile(ctx *context.Context, fileFilter container.Set[string], fileKey
// DownloadRecipeFile serves the content of the requested recipe file // DownloadRecipeFile serves the content of the requested recipe file
func DownloadRecipeFile(ctx *context.Context) { func DownloadRecipeFile(ctx *context.Context) {
rref := ctx.Data[recipeReferenceKey].(*conan_module.RecipeReference) rref := getRecipeReference(ctx)
downloadFile(ctx, recipeFileList, rref.AsKey()) downloadFile(ctx, recipeFileList, rref.AsKey())
} }
// DownloadPackageFile serves the content of the requested package file // DownloadPackageFile serves the content of the requested package file
func DownloadPackageFile(ctx *context.Context) { func DownloadPackageFile(ctx *context.Context) {
pref := ctx.Data[packageReferenceKey].(*conan_module.PackageReference) pref := getPackageReference(ctx)
downloadFile(ctx, packageFileList, pref.AsKey()) downloadFile(ctx, packageFileList, pref.AsKey())
} }
func downloadFile(ctx *context.Context, fileFilter container.Set[string], fileKey string) { func downloadFile(ctx *context.Context, fileFilter container.Set[string], fileKey string) {
rref := ctx.Data[recipeReferenceKey].(*conan_module.RecipeReference) rref := getRecipeReference(ctx)
filename := ctx.PathParam("filename") filename := ctx.PathParam("filename")
if !fileFilter.Contains(filename) { if !fileFilter.Contains(filename) {
@@ -503,7 +511,7 @@ func downloadFile(ctx *context.Context, fileFilter container.Set[string], fileKe
// DeleteRecipeV1 deletes the requested recipe(s) // DeleteRecipeV1 deletes the requested recipe(s)
func DeleteRecipeV1(ctx *context.Context) { func DeleteRecipeV1(ctx *context.Context) {
rref := ctx.Data[recipeReferenceKey].(*conan_module.RecipeReference) rref := getRecipeReference(ctx)
if err := deleteRecipeOrPackage(ctx, rref, true, nil, false); err != nil { if err := deleteRecipeOrPackage(ctx, rref, true, nil, false); err != nil {
if errors.Is(err, packages_model.ErrPackageNotExist) || errors.Is(err, conan_model.ErrPackageReferenceNotExist) { if errors.Is(err, packages_model.ErrPackageNotExist) || errors.Is(err, conan_model.ErrPackageReferenceNotExist) {
@@ -518,7 +526,7 @@ func DeleteRecipeV1(ctx *context.Context) {
// DeleteRecipeV2 deletes the requested recipe(s) respecting its revisions // DeleteRecipeV2 deletes the requested recipe(s) respecting its revisions
func DeleteRecipeV2(ctx *context.Context) { func DeleteRecipeV2(ctx *context.Context) {
rref := ctx.Data[recipeReferenceKey].(*conan_module.RecipeReference) rref := getRecipeReference(ctx)
if err := deleteRecipeOrPackage(ctx, rref, rref.Revision == "", nil, false); err != nil { if err := deleteRecipeOrPackage(ctx, rref, rref.Revision == "", nil, false); err != nil {
if errors.Is(err, packages_model.ErrPackageNotExist) || errors.Is(err, conan_model.ErrPackageReferenceNotExist) { if errors.Is(err, packages_model.ErrPackageNotExist) || errors.Is(err, conan_model.ErrPackageReferenceNotExist) {
@@ -533,7 +541,7 @@ func DeleteRecipeV2(ctx *context.Context) {
// DeletePackageV1 deletes the requested package(s) // DeletePackageV1 deletes the requested package(s)
func DeletePackageV1(ctx *context.Context) { func DeletePackageV1(ctx *context.Context) {
rref := ctx.Data[recipeReferenceKey].(*conan_module.RecipeReference) rref := getRecipeReference(ctx)
type PackageReferences struct { type PackageReferences struct {
References []string `json:"package_ids"` References []string `json:"package_ids"`
@@ -582,8 +590,8 @@ func DeletePackageV1(ctx *context.Context) {
// DeletePackageV2 deletes the requested package(s) respecting its revisions // DeletePackageV2 deletes the requested package(s) respecting its revisions
func DeletePackageV2(ctx *context.Context) { func DeletePackageV2(ctx *context.Context) {
rref := ctx.Data[recipeReferenceKey].(*conan_module.RecipeReference) rref := getRecipeReference(ctx)
pref := ctx.Data[packageReferenceKey].(*conan_module.PackageReference) pref := getPackageReference(ctx)
if pref != nil { // has package reference if pref != nil { // has package reference
if err := deleteRecipeOrPackage(ctx, rref, false, pref, pref.Revision == ""); err != nil { if err := deleteRecipeOrPackage(ctx, rref, false, pref, pref.Revision == ""); err != nil {
@@ -693,7 +701,7 @@ func deleteRecipeOrPackage(apictx *context.Context, rref *conan_module.RecipeRef
// ListRecipeRevisions gets a list of all recipe revisions // ListRecipeRevisions gets a list of all recipe revisions
func ListRecipeRevisions(ctx *context.Context) { func ListRecipeRevisions(ctx *context.Context) {
rref := ctx.Data[recipeReferenceKey].(*conan_module.RecipeReference) rref := getRecipeReference(ctx)
revisions, err := conan_model.GetRecipeRevisions(ctx, ctx.Package.Owner.ID, rref) revisions, err := conan_model.GetRecipeRevisions(ctx, ctx.Package.Owner.ID, rref)
if err != nil { if err != nil {
@@ -706,7 +714,7 @@ func ListRecipeRevisions(ctx *context.Context) {
// ListPackageRevisions gets a list of all package revisions // ListPackageRevisions gets a list of all package revisions
func ListPackageRevisions(ctx *context.Context) { func ListPackageRevisions(ctx *context.Context) {
pref := ctx.Data[packageReferenceKey].(*conan_module.PackageReference) pref := getPackageReference(ctx)
revisions, err := conan_model.GetPackageRevisions(ctx, ctx.Package.Owner.ID, pref) revisions, err := conan_model.GetPackageRevisions(ctx, ctx.Package.Owner.ID, pref)
if err != nil { if err != nil {
@@ -742,7 +750,7 @@ func listRevisions(ctx *context.Context, revisions []*conan_model.PropertyValue)
// LatestRecipeRevision gets the latest recipe revision // LatestRecipeRevision gets the latest recipe revision
func LatestRecipeRevision(ctx *context.Context) { func LatestRecipeRevision(ctx *context.Context) {
rref := ctx.Data[recipeReferenceKey].(*conan_module.RecipeReference) rref := getRecipeReference(ctx)
revision, err := conan_model.GetLastRecipeRevision(ctx, ctx.Package.Owner.ID, rref) revision, err := conan_model.GetLastRecipeRevision(ctx, ctx.Package.Owner.ID, rref)
if err != nil { if err != nil {
@@ -759,7 +767,7 @@ func LatestRecipeRevision(ctx *context.Context) {
// LatestPackageRevision gets the latest package revision // LatestPackageRevision gets the latest package revision
func LatestPackageRevision(ctx *context.Context) { func LatestPackageRevision(ctx *context.Context) {
pref := ctx.Data[packageReferenceKey].(*conan_module.PackageReference) pref := getPackageReference(ctx)
revision, err := conan_model.GetLastPackageRevision(ctx, ctx.Package.Owner.ID, pref) revision, err := conan_model.GetLastPackageRevision(ctx, ctx.Package.Owner.ID, pref)
if err != nil { if err != nil {
@@ -776,20 +784,20 @@ func LatestPackageRevision(ctx *context.Context) {
// ListRecipeRevisionFiles gets a list of all recipe revision files // ListRecipeRevisionFiles gets a list of all recipe revision files
func ListRecipeRevisionFiles(ctx *context.Context) { func ListRecipeRevisionFiles(ctx *context.Context) {
rref := ctx.Data[recipeReferenceKey].(*conan_module.RecipeReference) rref := getRecipeReference(ctx)
listRevisionFiles(ctx, rref.AsKey()) listRevisionFiles(ctx, rref.AsKey())
} }
// ListPackageRevisionFiles gets a list of all package revision files // ListPackageRevisionFiles gets a list of all package revision files
func ListPackageRevisionFiles(ctx *context.Context) { func ListPackageRevisionFiles(ctx *context.Context) {
pref := ctx.Data[packageReferenceKey].(*conan_module.PackageReference) pref := getPackageReference(ctx)
listRevisionFiles(ctx, pref.AsKey()) listRevisionFiles(ctx, pref.AsKey())
} }
func listRevisionFiles(ctx *context.Context, fileKey string) { func listRevisionFiles(ctx *context.Context, fileKey string) {
rref := ctx.Data[recipeReferenceKey].(*conan_module.RecipeReference) rref := getRecipeReference(ctx)
pv, err := packages_model.GetVersionByNameAndVersion(ctx, ctx.Package.Owner.ID, packages_model.TypeConan, rref.Name, rref.Version) pv, err := packages_model.GetVersionByNameAndVersion(ctx, ctx.Package.Owner.ID, packages_model.TypeConan, rref.Name, rref.Version)
if err != nil { if err != nil {
+1 -1
View File
@@ -72,7 +72,7 @@ func SearchPackagesV2(ctx *context.Context) {
} }
func searchPackages(ctx *context.Context, searchAllRevisions bool) { func searchPackages(ctx *context.Context, searchAllRevisions bool) {
rref := ctx.Data[recipeReferenceKey].(*conan_module.RecipeReference) rref := getRecipeReference(ctx)
if !searchAllRevisions && rref.Revision == "" { if !searchAllRevisions && rref.Revision == "" {
lastRevision, err := conan_model.GetLastRecipeRevision(ctx, ctx.Package.Owner.ID, rref) lastRevision, err := conan_model.GetLastRecipeRevision(ctx, ctx.Package.Owner.ID, rref)
+1 -1
View File
@@ -138,7 +138,7 @@ func EnumeratePackages(ctx *context.Context) {
return return
} }
versionMetadata := pd.Metadata.(*conda_module.VersionMetadata) versionMetadata := packages_model.DescriptorMetadata[*conda_module.VersionMetadata](pd)
pi := &PackageInfo{ pi := &PackageInfo{
Name: pd.PackageProperties.GetByName(conda_module.PropertyName), Name: pd.PackageProperties.GetByName(conda_module.PropertyName),
+1 -1
View File
@@ -93,7 +93,7 @@ func enumeratePackages(ctx *context.Context, format string, opts *cran_model.Sea
} }
} }
metadata := pd.Metadata.(*cran_module.Metadata) metadata := packages_model.DescriptorMetadata[*cran_module.Metadata](pd)
fmt.Fprintln(w, "Package:", pd.Package.Name) fmt.Fprintln(w, "Package:", pd.Package.Name)
fmt.Fprintln(w, "Version:", pd.Version.Version) fmt.Fprintln(w, "Version:", pd.Version.Version)
+3 -3
View File
@@ -45,7 +45,7 @@ func createPackageMetadataResponse(registryURL string, pds []*packages_model.Pac
latest := pds[len(pds)-1] latest := pds[len(pds)-1]
metadata := latest.Metadata.(*npm_module.Metadata) metadata := packages_model.DescriptorMetadata[*npm_module.Metadata](latest)
return &npm_module.PackageMetadata{ return &npm_module.PackageMetadata{
ID: latest.Package.Name, ID: latest.Package.Name,
@@ -67,7 +67,7 @@ func createPackageMetadataResponse(registryURL string, pds []*packages_model.Pac
func createPackageMetadataVersion(registryURL string, pd *packages_model.PackageDescriptor) *npm_module.PackageMetadataVersion { func createPackageMetadataVersion(registryURL string, pd *packages_model.PackageDescriptor) *npm_module.PackageMetadataVersion {
hashBytes, _ := hex.DecodeString(pd.Files[0].Blob.HashSHA512) hashBytes, _ := hex.DecodeString(pd.Files[0].Blob.HashSHA512)
metadata := pd.Metadata.(*npm_module.Metadata) metadata := packages_model.DescriptorMetadata[*npm_module.Metadata](pd)
return &npm_module.PackageMetadataVersion{ return &npm_module.PackageMetadataVersion{
ID: fmt.Sprintf("%s@%s", pd.Package.Name, pd.Version.Version), ID: fmt.Sprintf("%s@%s", pd.Package.Name, pd.Version.Version),
@@ -107,7 +107,7 @@ func createPackageMetadataVersion(registryURL string, pd *packages_model.Package
func createPackageSearchResponse(pds []*packages_model.PackageDescriptor, total int64) *npm_module.PackageSearch { func createPackageSearchResponse(pds []*packages_model.PackageDescriptor, total int64) *npm_module.PackageSearch {
objects := make([]*npm_module.PackageSearchObject, 0, len(pds)) objects := make([]*npm_module.PackageSearchObject, 0, len(pds))
for _, pd := range pds { for _, pd := range pds {
metadata := pd.Metadata.(*npm_module.Metadata) metadata := packages_model.DescriptorMetadata[*npm_module.Metadata](pd)
scope := metadata.Scope scope := metadata.Scope
if scope == "" { if scope == "" {
+1 -5
View File
@@ -332,12 +332,8 @@ func createFeedResponse(l *linkBuilder, totalEntries int64, pds []*packages_mode
} }
} }
func createEntryResponse(l *linkBuilder, pd *packages_model.PackageDescriptor) *FeedEntry {
return createEntry(l, pd, true)
}
func createEntry(l *linkBuilder, pd *packages_model.PackageDescriptor, withNamespace bool) *FeedEntry { func createEntry(l *linkBuilder, pd *packages_model.PackageDescriptor, withNamespace bool) *FeedEntry {
metadata := pd.Metadata.(*nuget_module.Metadata) metadata := packages_model.DescriptorMetadata[*nuget_module.Metadata](pd)
id := l.GetPackageMetadataURL(pd.Package.Name, pd.Version.Version) id := l.GetPackageMetadataURL(pd.Package.Name, pd.Version.Version)
+7 -9
View File
@@ -111,7 +111,7 @@ func createRegistrationIndexResponse(l *linkBuilder, pds []*packages_model.Packa
} }
func createRegistrationIndexPageItem(l *linkBuilder, pd *packages_model.PackageDescriptor) *RegistrationIndexPageItem { func createRegistrationIndexPageItem(l *linkBuilder, pd *packages_model.PackageDescriptor) *RegistrationIndexPageItem {
metadata := pd.Metadata.(*nuget_module.Metadata) metadata := packages_model.DescriptorMetadata[*nuget_module.Metadata](pd)
return &RegistrationIndexPageItem{ return &RegistrationIndexPageItem{
RegistrationLeafURL: l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version), RegistrationLeafURL: l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version),
@@ -120,7 +120,7 @@ func createRegistrationIndexPageItem(l *linkBuilder, pd *packages_model.PackageD
CatalogLeafURL: l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version), CatalogLeafURL: l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version),
Authors: metadata.Authors, Authors: metadata.Authors,
Copyright: metadata.Copyright, Copyright: metadata.Copyright,
DependencyGroups: createDependencyGroups(pd), DependencyGroups: createDependencyGroups(metadata),
Description: metadata.Description, Description: metadata.Description,
IconURL: metadata.IconURL, IconURL: metadata.IconURL,
ID: pd.Package.Name, ID: pd.Package.Name,
@@ -139,9 +139,7 @@ func createRegistrationIndexPageItem(l *linkBuilder, pd *packages_model.PackageD
} }
} }
func createDependencyGroups(pd *packages_model.PackageDescriptor) []*PackageDependencyGroup { func createDependencyGroups(metadata *nuget_module.Metadata) []*PackageDependencyGroup {
metadata := pd.Metadata.(*nuget_module.Metadata)
dependencyGroups := make([]*PackageDependencyGroup, 0, len(metadata.Dependencies)) dependencyGroups := make([]*PackageDependencyGroup, 0, len(metadata.Dependencies))
for k, v := range metadata.Dependencies { for k, v := range metadata.Dependencies {
dependencies := make([]*PackageDependency, 0, len(v)) dependencies := make([]*PackageDependency, 0, len(v))
@@ -172,7 +170,7 @@ type RegistrationLeafResponse struct {
func createRegistrationLeafResponse(l *linkBuilder, pd *packages_model.PackageDescriptor) *RegistrationLeafResponse { func createRegistrationLeafResponse(l *linkBuilder, pd *packages_model.PackageDescriptor) *RegistrationLeafResponse {
registrationLeafURL := l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version) registrationLeafURL := l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version)
packageDownloadURL := l.GetPackageDownloadURL(pd.Package.Name, pd.Version.Version) packageDownloadURL := l.GetPackageDownloadURL(pd.Package.Name, pd.Version.Version)
metadata := pd.Metadata.(*nuget_module.Metadata) metadata := packages_model.DescriptorMetadata[*nuget_module.Metadata](pd)
return &RegistrationLeafResponse{ return &RegistrationLeafResponse{
RegistrationLeafURL: registrationLeafURL, RegistrationLeafURL: registrationLeafURL,
RegistrationIndexURL: l.GetRegistrationIndexURL(pd.Package.Name), RegistrationIndexURL: l.GetRegistrationIndexURL(pd.Package.Name),
@@ -182,7 +180,7 @@ func createRegistrationLeafResponse(l *linkBuilder, pd *packages_model.PackageDe
CatalogLeafURL: registrationLeafURL, CatalogLeafURL: registrationLeafURL,
Authors: metadata.Authors, Authors: metadata.Authors,
Copyright: metadata.Copyright, Copyright: metadata.Copyright,
DependencyGroups: createDependencyGroups(pd), DependencyGroups: createDependencyGroups(metadata),
Description: metadata.Description, Description: metadata.Description,
IconURL: metadata.IconURL, IconURL: metadata.IconURL,
ID: pd.Package.Name, ID: pd.Package.Name,
@@ -290,13 +288,13 @@ func createSearchResult(l *linkBuilder, pds []*packages_model.PackageDescriptor)
}) })
} }
metadata := latest.Metadata.(*nuget_module.Metadata) metadata := packages_model.DescriptorMetadata[*nuget_module.Metadata](latest)
return &SearchResult{ return &SearchResult{
Authors: metadata.Authors, Authors: metadata.Authors,
Copyright: metadata.Copyright, Copyright: metadata.Copyright,
Description: metadata.Description, Description: metadata.Description,
DependencyGroups: createDependencyGroups(latest), DependencyGroups: createDependencyGroups(metadata),
IconURL: metadata.IconURL, IconURL: metadata.IconURL,
ID: latest.Package.Name, ID: latest.Package.Name,
IsPrerelease: latest.Version.IsPrerelease(), IsPrerelease: latest.Version.IsPrerelease(),
+2 -1
View File
@@ -267,9 +267,10 @@ func RegistrationLeafV2(ctx *context.Context) {
return return
} }
resp := createEntryResponse( resp := createEntry(
&linkBuilder{Base: setting.AppURL + "api/packages/" + ctx.Package.Owner.Name + "/nuget"}, &linkBuilder{Base: setting.AppURL + "api/packages/" + ctx.Package.Owner.Name + "/nuget"},
pd, pd,
true,
) )
xmlResponse(ctx, http.StatusOK, resp) xmlResponse(ctx, http.StatusOK, resp)
+1 -1
View File
@@ -67,7 +67,7 @@ func packageDescriptorToMetadata(baseURL string, pd *packages_model.PackageDescr
Version: pd.Version.Version, Version: pd.Version.Version,
ArchiveURL: fmt.Sprintf("%s/files/%s.tar.gz", baseURL, url.PathEscape(pd.Version.Version)), ArchiveURL: fmt.Sprintf("%s/files/%s.tar.gz", baseURL, url.PathEscape(pd.Version.Version)),
Published: pd.Version.CreatedUnix.AsLocalTime(), Published: pd.Version.CreatedUnix.AsLocalTime(),
Pubspec: pd.Metadata.(*pub_module.Metadata).Pubspec, Pubspec: packages_model.DescriptorMetadata[*pub_module.Metadata](pd).Pubspec,
} }
} }
+3 -3
View File
@@ -75,7 +75,7 @@ func enumeratePackages(ctx *context.Context, filename string, pvs []*packages_mo
Name: "Gem::Version", Name: "Gem::Version",
Value: []string{p.Version.Version}, Value: []string{p.Version.Version},
}, },
p.Metadata.(*rubygems_module.Metadata).Platform, packages_model.DescriptorMetadata[*rubygems_module.Metadata](p).Platform,
}) })
} }
@@ -126,7 +126,7 @@ func ServePackageSpecification(ctx *context.Context) {
zw := zlib.NewWriter(ctx.Resp) zw := zlib.NewWriter(ctx.Resp)
defer zw.Close() defer zw.Close()
metadata := pd.Metadata.(*rubygems_module.Metadata) metadata := packages_model.DescriptorMetadata[*rubygems_module.Metadata](pd)
// create a Ruby Gem::Specification object // create a Ruby Gem::Specification object
spec := &rubygems_module.RubyUserDef{ spec := &rubygems_module.RubyUserDef{
@@ -405,7 +405,7 @@ func makePackageVersionDependency(ctx *context.Context, version *packages_model.
return "", err return "", err
} }
metadata := pd.Metadata.(*rubygems_module.Metadata) metadata := packages_model.DescriptorMetadata[*rubygems_module.Metadata](pd)
fullFilename := makeGemFullFileName(pd.Package.Name, version.Version, metadata.Platform) fullFilename := makeGemFullFileName(pd.Package.Name, version.Version, metadata.Platform)
file, err := packages_model.GetFileForVersionByName(ctx, version.ID, fullFilename, "") file, err := packages_model.GetFileForVersionByName(ctx, version.ID, fullFilename, "")
if err != nil { if err != nil {
+2 -2
View File
@@ -197,7 +197,7 @@ func PackageVersionMetadata(ctx *context.Context) {
return return
} }
metadata := pd.Metadata.(*swift_module.Metadata) metadata := packages_model.DescriptorMetadata[*swift_module.Metadata](pd)
repositoryURLs := make([]string, 0, len(pd.VersionProperties)) repositoryURLs := make([]string, 0, len(pd.VersionProperties))
for _, property := range pd.VersionProperties { for _, property := range pd.VersionProperties {
if property.Name == swift_module.PropertyRepositoryURL { if property.Name == swift_module.PropertyRepositoryURL {
@@ -278,7 +278,7 @@ func DownloadManifest(ctx *context.Context) {
swiftVersion = swift_module.TrimmedVersionString(v) swiftVersion = swift_module.TrimmedVersionString(v)
} }
} }
m, ok := pd.Metadata.(*swift_module.Metadata).Manifests[swiftVersion] m, ok := packages_model.DescriptorMetadata[*swift_module.Metadata](pd).Manifests[swiftVersion]
if !ok { if !ok {
setResponseHeaders(ctx.Resp, &headers{ setResponseHeaders(ctx.Resp, &headers{
Status: http.StatusSeeOther, Status: http.StatusSeeOther,
+1 -1
View File
@@ -130,7 +130,7 @@ func EnumeratePackageVersions(ctx *context.Context) {
ctx.JSON(http.StatusOK, &packageMetadata{ ctx.JSON(http.StatusOK, &packageMetadata{
Name: pds[0].Package.Name, Name: pds[0].Package.Name,
Description: pds[len(pds)-1].Metadata.(*vagrant_module.Metadata).Description, Description: packages_model.DescriptorMetadata[*vagrant_module.Metadata](pds[len(pds)-1]).Description,
Versions: versions, Versions: versions,
}) })
} }
+1 -1
View File
@@ -39,7 +39,7 @@ func ListCronTasks(ctx *context.APIContext) {
count := len(tasks) count := len(tasks)
listOpts := utils.GetListOptions(ctx) listOpts := utils.GetListOptions(ctx)
tasks = util.PaginateSlice(tasks, listOpts.Page, listOpts.PageSize).(cron.TaskTable) tasks = util.PaginateSlice(tasks, listOpts.Page, listOpts.PageSize)
res := make([]structs.Cron, len(tasks)) res := make([]structs.Cron, len(tasks))
for i, task := range tasks { for i, task := range tasks {
+2 -2
View File
@@ -137,7 +137,7 @@ func CreateHook(ctx *context.APIContext) {
// "201": // "201":
// "$ref": "#/responses/Hook" // "$ref": "#/responses/Hook"
form := web.GetForm(ctx).(*api.CreateHookOption) form := web.GetForm[*api.CreateHookOption](ctx)
utils.AddSystemHook(ctx, form) utils.AddSystemHook(ctx, form)
} }
@@ -166,7 +166,7 @@ func EditHook(ctx *context.APIContext) {
// "200": // "200":
// "$ref": "#/responses/Hook" // "$ref": "#/responses/Hook"
form := web.GetForm(ctx).(*api.EditHookOption) form := web.GetForm[*api.EditHookOption](ctx)
// TODO in body params // TODO in body params
hookID := ctx.PathParamInt64("id") hookID := ctx.PathParamInt64("id")
+1 -1
View File
@@ -44,7 +44,7 @@ func CreateOrg(ctx *context.APIContext) {
// "422": // "422":
// "$ref": "#/responses/validationError" // "$ref": "#/responses/validationError"
form := web.GetForm(ctx).(*api.CreateOrgOption) form := web.GetForm[*api.CreateOrgOption](ctx)
visibility := api.VisibleTypePublic visibility := api.VisibleTypePublic
if form.Visibility != "" { if form.Visibility != "" {
+1 -1
View File
@@ -43,7 +43,7 @@ func CreateRepo(ctx *context.APIContext) {
// "422": // "422":
// "$ref": "#/responses/validationError" // "$ref": "#/responses/validationError"
form := web.GetForm(ctx).(*api.CreateRepoOption) form := web.GetForm[*api.CreateRepoOption](ctx)
repo.CreateUserRepo(ctx, ctx.ContextUser, *form) repo.CreateUserRepo(ctx, ctx.ContextUser, *form)
} }
+4 -4
View File
@@ -75,7 +75,7 @@ func CreateUser(ctx *context.APIContext) {
// "422": // "422":
// "$ref": "#/responses/validationError" // "$ref": "#/responses/validationError"
form := web.GetForm(ctx).(*api.CreateUserOption) form := web.GetForm[*api.CreateUserOption](ctx)
u := &user_model.User{ u := &user_model.User{
Name: form.Username, Name: form.Username,
@@ -190,7 +190,7 @@ func EditUser(ctx *context.APIContext) {
// "422": // "422":
// "$ref": "#/responses/validationError" // "$ref": "#/responses/validationError"
form := web.GetForm(ctx).(*api.EditUserOption) form := web.GetForm[*api.EditUserOption](ctx)
authOpts := &user_service.UpdateAuthOptions{ authOpts := &user_service.UpdateAuthOptions{
LoginSource: optional.FromNonDefault(form.SourceID), LoginSource: optional.FromNonDefault(form.SourceID),
@@ -340,7 +340,7 @@ func CreatePublicKey(ctx *context.APIContext) {
// "422": // "422":
// "$ref": "#/responses/validationError" // "$ref": "#/responses/validationError"
form := web.GetForm(ctx).(*api.CreateKeyOption) form := web.GetForm[*api.CreateKeyOption](ctx)
user.CreateUserPublicKey(ctx, *form, ctx.ContextUser.ID) user.CreateUserPublicKey(ctx, *form, ctx.ContextUser.ID)
} }
@@ -551,7 +551,7 @@ func RenameUser(ctx *context.APIContext) {
return return
} }
newName := web.GetForm(ctx).(*api.RenameUserOption).NewName newName := web.GetForm[*api.RenameUserOption](ctx).NewName
// Check if username has been changed // Check if username has been changed
if err := user_service.RenameUser(ctx, ctx.ContextUser, newName, ctx.Doer); err != nil { if err := user_service.RenameUser(ctx, ctx.ContextUser, newName, ctx.Doer); err != nil {
+2 -2
View File
@@ -66,7 +66,7 @@ func AddUserBadges(ctx *context.APIContext) {
// "403": // "403":
// "$ref": "#/responses/forbidden" // "$ref": "#/responses/forbidden"
form := web.GetForm(ctx).(*api.UserBadgeOption) form := web.GetForm[*api.UserBadgeOption](ctx)
badges := prepareBadgesForReplaceOrAdd(*form) badges := prepareBadgesForReplaceOrAdd(*form)
if err := user_model.AddUserBadges(ctx, ctx.ContextUser, badges); err != nil { if err := user_model.AddUserBadges(ctx, ctx.ContextUser, badges); err != nil {
@@ -102,7 +102,7 @@ func DeleteUserBadges(ctx *context.APIContext) {
// "422": // "422":
// "$ref": "#/responses/validationError" // "$ref": "#/responses/validationError"
form := web.GetForm(ctx).(*api.UserBadgeOption) form := web.GetForm[*api.UserBadgeOption](ctx)
badges := prepareBadgesForReplaceOrAdd(*form) badges := prepareBadgesForReplaceOrAdd(*form)
if err := user_model.RemoveUserBadges(ctx, ctx.ContextUser, badges); err != nil { if err := user_model.RemoveUserBadges(ctx, ctx.ContextUser, badges); err != nil {
+1 -1
View File
@@ -396,7 +396,7 @@ func reqUsersExploreEnabled() func(ctx *context.APIContext) {
func reqBasicOrRevProxyAuth() func(ctx *context.APIContext) { func reqBasicOrRevProxyAuth() func(ctx *context.APIContext) {
return func(ctx *context.APIContext) { return func(ctx *context.APIContext) {
if ctx.IsSigned && setting.Service.EnableReverseProxyAuthAPI && ctx.Data["AuthedMethod"].(string) == auth.ReverseProxyMethodName { if ctx.IsSigned && setting.Service.EnableReverseProxyAuthAPI && ctx.Data["AuthedMethod"] == auth.ReverseProxyMethodName {
return return
} }
if !ctx.IsBasicAuth { if !ctx.IsBasicAuth {
+2 -2
View File
@@ -33,7 +33,7 @@ func Markup(ctx *context.APIContext) {
// "422": // "422":
// "$ref": "#/responses/validationError" // "$ref": "#/responses/validationError"
form := web.GetForm(ctx).(*api.MarkupOption) form := web.GetForm[*api.MarkupOption](ctx)
mode := util.Iif(form.Wiki, "wiki", form.Mode) //nolint:staticcheck // form.Wiki is deprecated mode := util.Iif(form.Wiki, "wiki", form.Mode) //nolint:staticcheck // form.Wiki is deprecated
common.RenderMarkup(ctx.Base, ctx.Repo, mode, form.Text, form.Context, form.FilePath) common.RenderMarkup(ctx.Base, ctx.Repo, mode, form.Text, form.Context, form.FilePath)
} }
@@ -58,7 +58,7 @@ func Markdown(ctx *context.APIContext) {
// "422": // "422":
// "$ref": "#/responses/validationError" // "$ref": "#/responses/validationError"
form := web.GetForm(ctx).(*api.MarkdownOption) form := web.GetForm[*api.MarkdownOption](ctx)
mode := util.Iif(form.Wiki, "wiki", form.Mode) //nolint:staticcheck // form.Wiki is deprecated mode := util.Iif(form.Wiki, "wiki", form.Mode) //nolint:staticcheck // form.Wiki is deprecated
common.RenderMarkup(ctx.Base, ctx.Repo, mode, form.Text, form.Context, "") common.RenderMarkup(ctx.Base, ctx.Repo, mode, form.Text, form.Context, "")
} }
+3 -3
View File
@@ -106,7 +106,7 @@ func (Action) CreateOrUpdateSecret(ctx *context.APIContext) {
// "404": // "404":
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
opt := web.GetForm(ctx).(*api.CreateOrUpdateSecretOption) opt := web.GetForm[*api.CreateOrUpdateSecretOption](ctx)
_, created, err := secret_service.CreateOrUpdateSecret(ctx, ctx.Org.Organization.ID, 0, ctx.PathParam("secretname"), opt.Data, opt.Description) _, created, err := secret_service.CreateOrUpdateSecret(ctx, ctx.Org.Organization.ID, 0, ctx.PathParam("secretname"), opt.Data, opt.Description)
if err != nil { if err != nil {
@@ -373,7 +373,7 @@ func (Action) CreateVariable(ctx *context.APIContext) {
// "500": // "500":
// "$ref": "#/responses/error" // "$ref": "#/responses/error"
opt := web.GetForm(ctx).(*api.CreateVariableOption) opt := web.GetForm[*api.CreateVariableOption](ctx)
ownerID := ctx.Org.Organization.ID ownerID := ctx.Org.Organization.ID
variableName := ctx.PathParam("variablename") variableName := ctx.PathParam("variablename")
@@ -437,7 +437,7 @@ func (Action) UpdateVariable(ctx *context.APIContext) {
// "404": // "404":
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
opt := web.GetForm(ctx).(*api.UpdateVariableOption) opt := web.GetForm[*api.UpdateVariableOption](ctx)
v, err := actions_service.GetVariable(ctx, actions_model.FindVariablesOpts{ v, err := actions_service.GetVariable(ctx, actions_model.FindVariablesOpts{
OwnerID: ctx.Org.Organization.ID, OwnerID: ctx.Org.Organization.ID,
+1 -1
View File
@@ -35,7 +35,7 @@ func UpdateAvatar(ctx *context.APIContext) {
// "$ref": "#/responses/empty" // "$ref": "#/responses/empty"
// "404": // "404":
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
form := web.GetForm(ctx).(*api.UpdateUserAvatarOption) form := web.GetForm[*api.UpdateUserAvatarOption](ctx)
content, err := base64.StdEncoding.DecodeString(form.Image) content, err := base64.StdEncoding.DecodeString(form.Image)
if err != nil { if err != nil {
+2 -2
View File
@@ -113,7 +113,7 @@ func CreateHook(ctx *context.APIContext) {
utils.AddOwnerHook( utils.AddOwnerHook(
ctx, ctx,
ctx.ContextUser, ctx.ContextUser,
web.GetForm(ctx).(*api.CreateHookOption), web.GetForm[*api.CreateHookOption](ctx),
) )
} }
@@ -151,7 +151,7 @@ func EditHook(ctx *context.APIContext) {
utils.EditOwnerHook( utils.EditOwnerHook(
ctx, ctx,
ctx.ContextUser, ctx.ContextUser,
web.GetForm(ctx).(*api.EditHookOption), web.GetForm[*api.EditHookOption](ctx),
ctx.PathParamInt64("id"), ctx.PathParamInt64("id"),
) )
} }
+2 -2
View File
@@ -86,7 +86,7 @@ func CreateLabel(ctx *context.APIContext) {
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
// "422": // "422":
// "$ref": "#/responses/validationError" // "$ref": "#/responses/validationError"
form := web.GetForm(ctx).(*api.CreateLabelOption) form := web.GetForm[*api.CreateLabelOption](ctx)
form.Color = strings.Trim(form.Color, " ") form.Color = strings.Trim(form.Color, " ")
color, err := label.NormalizeColor(form.Color) color, err := label.NormalizeColor(form.Color)
if err != nil { if err != nil {
@@ -189,7 +189,7 @@ func EditLabel(ctx *context.APIContext) {
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
// "422": // "422":
// "$ref": "#/responses/validationError" // "$ref": "#/responses/validationError"
form := web.GetForm(ctx).(*api.EditLabelOption) form := web.GetForm[*api.EditLabelOption](ctx)
l, err := issues_model.GetLabelInOrgByID(ctx, ctx.Org.Organization.ID, ctx.PathParamInt64("id")) l, err := issues_model.GetLabelInOrgByID(ctx, ctx.Org.Organization.ID, ctx.PathParamInt64("id"))
if err != nil { if err != nil {
if issues_model.IsErrOrgLabelNotExist(err) { if issues_model.IsErrOrgLabelNotExist(err) {
+3 -3
View File
@@ -261,7 +261,7 @@ func Create(ctx *context.APIContext) {
// "$ref": "#/responses/forbidden" // "$ref": "#/responses/forbidden"
// "422": // "422":
// "$ref": "#/responses/validationError" // "$ref": "#/responses/validationError"
form := web.GetForm(ctx).(*api.CreateOrgOption) form := web.GetForm[*api.CreateOrgOption](ctx)
if !ctx.Doer.CanCreateOrganization() { if !ctx.Doer.CanCreateOrganization() {
ctx.APIError(http.StatusForbidden, "not allowed to create org") ctx.APIError(http.StatusForbidden, "not allowed to create org")
return return
@@ -358,7 +358,7 @@ func Rename(ctx *context.APIContext) {
// "422": // "422":
// "$ref": "#/responses/validationError" // "$ref": "#/responses/validationError"
form := web.GetForm(ctx).(*api.RenameOrgOption) form := web.GetForm[*api.RenameOrgOption](ctx)
orgUser := ctx.Org.Organization.AsUser() orgUser := ctx.Org.Organization.AsUser()
if err := user_service.RenameUser(ctx, orgUser, form.NewName, ctx.Doer); err != nil { if err := user_service.RenameUser(ctx, orgUser, form.NewName, ctx.Doer); err != nil {
if user_model.IsErrUserAlreadyExist(err) || db.IsErrNameReserved(err) || db.IsErrNamePatternNotAllowed(err) || db.IsErrNameCharsNotAllowed(err) { if user_model.IsErrUserAlreadyExist(err) || db.IsErrNameReserved(err) || db.IsErrNamePatternNotAllowed(err) || db.IsErrNameCharsNotAllowed(err) {
@@ -397,7 +397,7 @@ func Edit(ctx *context.APIContext) {
// "404": // "404":
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
form := web.GetForm(ctx).(*api.EditOrgOption) form := web.GetForm[*api.EditOrgOption](ctx)
if err := org.UpdateOrgEmailAddress(ctx, ctx.Org.Organization, form.Email); err != nil { if err := org.UpdateOrgEmailAddress(ctx, ctx.Org.Organization, form.Email); err != nil {
if errors.Is(err, util.ErrInvalidArgument) { if errors.Is(err, util.ErrInvalidArgument) {
+2 -2
View File
@@ -214,7 +214,7 @@ func CreateTeam(ctx *context.APIContext) {
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
// "422": // "422":
// "$ref": "#/responses/validationError" // "$ref": "#/responses/validationError"
form := web.GetForm(ctx).(*api.CreateTeamOption) form := web.GetForm[*api.CreateTeamOption](ctx)
teamPermission := perm.ParseAccessMode(string(form.Permission), perm.AccessModeNone, perm.AccessModeAdmin) teamPermission := perm.ParseAccessMode(string(form.Permission), perm.AccessModeNone, perm.AccessModeAdmin)
team := &organization.Team{ team := &organization.Team{
OrgID: ctx.Org.Organization.ID, OrgID: ctx.Org.Organization.ID,
@@ -282,7 +282,7 @@ func EditTeam(ctx *context.APIContext) {
// "404": // "404":
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
form := web.GetForm(ctx).(*api.EditTeamOption) form := web.GetForm[*api.EditTeamOption](ctx)
team := ctx.Org.Team team := ctx.Org.Team
if err := team.LoadUnits(ctx); err != nil { if err := team.LoadUnits(ctx); err != nil {
ctx.APIErrorInternal(err) ctx.APIErrorInternal(err)
+4 -4
View File
@@ -135,7 +135,7 @@ func (Action) CreateOrUpdateSecret(ctx *context.APIContext) {
repo := ctx.Repo.Repository repo := ctx.Repo.Repository
opt := web.GetForm(ctx).(*api.CreateOrUpdateSecretOption) opt := web.GetForm[*api.CreateOrUpdateSecretOption](ctx)
_, created, err := secret_service.CreateOrUpdateSecret(ctx, 0, repo.ID, ctx.PathParam("secretname"), opt.Data, opt.Description) _, created, err := secret_service.CreateOrUpdateSecret(ctx, 0, repo.ID, ctx.PathParam("secretname"), opt.Data, opt.Description)
if err != nil { if err != nil {
@@ -346,7 +346,7 @@ func (Action) CreateVariable(ctx *context.APIContext) {
// "500": // "500":
// "$ref": "#/responses/error" // "$ref": "#/responses/error"
opt := web.GetForm(ctx).(*api.CreateVariableOption) opt := web.GetForm[*api.CreateVariableOption](ctx)
repoID := ctx.Repo.Repository.ID repoID := ctx.Repo.Repository.ID
variableName := ctx.PathParam("variablename") variableName := ctx.PathParam("variablename")
@@ -413,7 +413,7 @@ func (Action) UpdateVariable(ctx *context.APIContext) {
// "404": // "404":
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
opt := web.GetForm(ctx).(*api.UpdateVariableOption) opt := web.GetForm[*api.UpdateVariableOption](ctx)
v, err := actions_service.GetVariable(ctx, actions_model.FindVariablesOpts{ v, err := actions_service.GetVariable(ctx, actions_model.FindVariablesOpts{
RepoID: ctx.Repo.Repository.ID, RepoID: ctx.Repo.Repository.ID,
@@ -1170,7 +1170,7 @@ func ActionsDispatchWorkflow(ctx *context.APIContext) {
// "$ref": "#/responses/validationError" // "$ref": "#/responses/validationError"
workflowID := ctx.PathParam("workflow_id") workflowID := ctx.PathParam("workflow_id")
opt := web.GetForm(ctx).(*api.CreateActionWorkflowDispatch) opt := web.GetForm[*api.CreateActionWorkflowDispatch](ctx)
if opt.Ref == "" { if opt.Ref == "" {
ctx.APIError(http.StatusUnprocessableEntity, "ref is required parameter") ctx.APIError(http.StatusUnprocessableEntity, "ref is required parameter")
return return
+1 -1
View File
@@ -40,7 +40,7 @@ func UpdateAvatar(ctx *context.APIContext) {
// "$ref": "#/responses/empty" // "$ref": "#/responses/empty"
// "404": // "404":
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
form := web.GetForm(ctx).(*api.UpdateRepoAvatarOption) form := web.GetForm[*api.UpdateRepoAvatarOption](ctx)
content, err := base64.StdEncoding.DecodeString(form.Image) content, err := base64.StdEncoding.DecodeString(form.Image)
if err != nil { if err != nil {

Some files were not shown because too many files have changed in this diff Show More