mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-03-13 23:32:41 +00:00
Merge branch 'forgejo' into forgejo
This commit is contained in:
commit
44b238e0da
28 changed files with 191 additions and 143 deletions
|
@ -26,3 +26,8 @@ insert_final_newline = false
|
|||
|
||||
[options/locale/locale_*.ini]
|
||||
insert_final_newline = false
|
||||
|
||||
# Weblate JSON output defaults to four spaces
|
||||
[options/locale_next/locale_*.json]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
|
|
@ -28,7 +28,7 @@ jobs:
|
|||
|
||||
runs-on: docker
|
||||
container:
|
||||
image: data.forgejo.org/renovate/renovate:39.185.0
|
||||
image: data.forgejo.org/renovate/renovate:39.195.1
|
||||
|
||||
steps:
|
||||
- name: Load renovate repo cache
|
||||
|
|
2
Makefile
2
Makefile
|
@ -49,7 +49,7 @@ GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1 # renovate: datasour
|
|||
DEADCODE_PACKAGE ?= golang.org/x/tools/cmd/deadcode@v0.31.0 # renovate: datasource=go
|
||||
GOMOCK_PACKAGE ?= go.uber.org/mock/mockgen@v0.4.0 # renovate: datasource=go
|
||||
GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.18.1 # renovate: datasource=go
|
||||
RENOVATE_NPM_PACKAGE ?= renovate@39.185.0 # renovate: datasource=docker packageName=data.forgejo.org/renovate/renovate
|
||||
RENOVATE_NPM_PACKAGE ?= renovate@39.195.1 # renovate: datasource=docker packageName=data.forgejo.org/renovate/renovate
|
||||
|
||||
# https://github.com/disposable-email-domains/disposable-email-domains/commits/main/
|
||||
DISPOSABLE_EMAILS_SHA ?= 0c27e671231d27cf66370034d7f6818037416989 # renovate: ...
|
||||
|
|
5
assets/go-licenses.json
generated
5
assets/go-licenses.json
generated
File diff suppressed because one or more lines are too long
11
go.mod
11
go.mod
|
@ -49,7 +49,7 @@ require (
|
|||
github.com/go-openapi/spec v0.20.14
|
||||
github.com/go-sql-driver/mysql v1.8.1
|
||||
github.com/go-testfixtures/testfixtures/v3 v3.14.0
|
||||
github.com/go-webauthn/webauthn v0.11.2
|
||||
github.com/go-webauthn/webauthn v0.12.2
|
||||
github.com/gobwas/glob v0.2.3
|
||||
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
|
||||
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
|
||||
|
@ -76,7 +76,7 @@ require (
|
|||
github.com/meilisearch/meilisearch-go v0.31.0
|
||||
github.com/mholt/archiver/v3 v3.5.1
|
||||
github.com/microcosm-cc/bluemonday v1.0.27
|
||||
github.com/minio/minio-go/v7 v7.0.85
|
||||
github.com/minio/minio-go/v7 v7.0.88
|
||||
github.com/msteinert/pam/v2 v2.0.0
|
||||
github.com/nektos/act v0.2.52
|
||||
github.com/niklasfasching/go-org v1.7.0
|
||||
|
@ -191,8 +191,8 @@ require (
|
|||
github.com/go-openapi/jsonpointer v0.20.2 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.4 // indirect
|
||||
github.com/go-openapi/swag v0.22.7 // indirect
|
||||
github.com/go-webauthn/x v0.1.14 // indirect
|
||||
github.com/goccy/go-json v0.10.4 // indirect
|
||||
github.com/go-webauthn/x v0.1.19 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
|
||||
github.com/golang/geo v0.0.0-20230421003525-6adc56603217 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
|
@ -201,7 +201,7 @@ require (
|
|||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/go-tpm v0.9.1 // indirect
|
||||
github.com/google/go-tpm v0.9.3 // indirect
|
||||
github.com/google/s2a-go v0.1.8 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.13.0 // indirect
|
||||
|
@ -222,6 +222,7 @@ require (
|
|||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/mholt/acmez/v3 v3.1.0 // indirect
|
||||
github.com/miekg/dns v1.1.63 // indirect
|
||||
github.com/minio/crc64nvme v1.0.1 // indirect
|
||||
github.com/minio/md5-simd v1.1.2 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
|
|
22
go.sum
22
go.sum
|
@ -967,18 +967,18 @@ github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
|
|||
github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||
github.com/go-testfixtures/testfixtures/v3 v3.14.0 h1:aRt5qyH2XjzFgCC5NizNs6QrzjO7rC4pQZ1oJpPIdo8=
|
||||
github.com/go-testfixtures/testfixtures/v3 v3.14.0/go.mod h1:HHb6Yd8spzm6aFZU6jwBj9qFvVUNNkx5nGbjG4UHeOE=
|
||||
github.com/go-webauthn/webauthn v0.11.2 h1:Fgx0/wlmkClTKlnOsdOQ+K5HcHDsDcYIvtYmfhEOSUc=
|
||||
github.com/go-webauthn/webauthn v0.11.2/go.mod h1:aOtudaF94pM71g3jRwTYYwQTG1KyTILTcZqN1srkmD0=
|
||||
github.com/go-webauthn/x v0.1.14 h1:1wrB8jzXAofojJPAaRxnZhRgagvLGnLjhCAwg3kTpT0=
|
||||
github.com/go-webauthn/x v0.1.14/go.mod h1:UuVvFZ8/NbOnkDz3y1NaxtUN87pmtpC1PQ+/5BBQRdc=
|
||||
github.com/go-webauthn/webauthn v0.12.2 h1:yLaNPgBUEXDQtWnOjhsGhMMCEWbXwjg/aNkC8riJQI8=
|
||||
github.com/go-webauthn/webauthn v0.12.2/go.mod h1:Q8SZPPj4sZ469fNTcQXxRpzJOdb30jQrn/36FX8jilA=
|
||||
github.com/go-webauthn/x v0.1.19 h1:IUfdHiBRoTdujpBA/14qbrMXQ3LGzYe/PRGWdZcmudg=
|
||||
github.com/go-webauthn/x v0.1.19/go.mod h1:C5arLuTQ3pVHKPw89v7CDGnqAZSZJj+4Jnr40dsn7tk=
|
||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||
github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
|
||||
github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM=
|
||||
github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f h1:3BSP1Tbs2djlpprl7wCLuiqMaUh5SJkkzI2gDs+FgLs=
|
||||
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14=
|
||||
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85 h1:UjoPNDAQ5JPCjlxoJd6K8ALZqSDDhk2ymieAZOVaDg0=
|
||||
|
@ -1065,8 +1065,8 @@ github.com/google/go-github/v64 v64.0.0 h1:4G61sozmY3eiPAjjoOHponXDBONm+utovTKby
|
|||
github.com/google/go-github/v64 v64.0.0/go.mod h1:xB3vqMQNdHzilXBiO2I+M7iEFtHf+DP/omBOv6tQzVo=
|
||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||
github.com/google/go-tpm v0.9.1 h1:0pGc4X//bAlmZzMKf8iz6IsDo1nYTbYJ6FZN/rg4zdM=
|
||||
github.com/google/go-tpm v0.9.1/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
|
||||
github.com/google/go-tpm v0.9.3 h1:+yx0/anQuGzi+ssRqeD6WpXjW2L/V0dItUayO0i9sRc=
|
||||
github.com/google/go-tpm v0.9.3/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
|
@ -1264,10 +1264,12 @@ github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY=
|
|||
github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs=
|
||||
github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY=
|
||||
github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE=
|
||||
github.com/minio/crc64nvme v1.0.1 h1:DHQPrYPdqK7jQG/Ls5CTBZWeex/2FMS3G5XGkycuFrY=
|
||||
github.com/minio/crc64nvme v1.0.1/go.mod h1:eVfm2fAzLlxMdUGc0EEBGSMmPwmXD5XiNRpnu9J3bvg=
|
||||
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
|
||||
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
|
||||
github.com/minio/minio-go/v7 v7.0.85 h1:9psTLS/NTvC3MWoyjhjXpwcKoNbkongaCSF3PNpSuXo=
|
||||
github.com/minio/minio-go/v7 v7.0.85/go.mod h1:57YXpvc5l3rjPdhqNrDsvVlY0qPI6UTk1bflAe+9doY=
|
||||
github.com/minio/minio-go/v7 v7.0.88 h1:v8MoIJjwYxOkehp+eiLIuvXk87P2raUtoU5klrAAshs=
|
||||
github.com/minio/minio-go/v7 v7.0.88/go.mod h1:33+O8h0tO7pCeCWwBVa07RhVVfB/3vS4kEX7rwYKmIg=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
|
|
|
@ -45,15 +45,12 @@ func init() {
|
|||
// GetSchedulesMapByIDs returns the schedules by given id slice.
|
||||
func GetSchedulesMapByIDs(ctx context.Context, ids []int64) (map[int64]*ActionSchedule, error) {
|
||||
schedules := make(map[int64]*ActionSchedule, len(ids))
|
||||
if len(ids) == 0 {
|
||||
return schedules, nil
|
||||
}
|
||||
return schedules, db.GetEngine(ctx).In("id", ids).Find(&schedules)
|
||||
}
|
||||
|
||||
// GetReposMapByIDs returns the repos by given id slice.
|
||||
func GetReposMapByIDs(ctx context.Context, ids []int64) (map[int64]*repo_model.Repository, error) {
|
||||
repos := make(map[int64]*repo_model.Repository, len(ids))
|
||||
return repos, db.GetEngine(ctx).In("id", ids).Find(&repos)
|
||||
}
|
||||
|
||||
// CreateScheduleTask creates new schedule task.
|
||||
func CreateScheduleTask(ctx context.Context, rows []*ActionSchedule) error {
|
||||
// Return early if there are no rows to insert
|
||||
|
|
|
@ -36,7 +36,7 @@ func (specs SpecList) LoadSchedules(ctx context.Context) error {
|
|||
}
|
||||
|
||||
repoIDs := specs.GetRepoIDs()
|
||||
repos, err := GetReposMapByIDs(ctx, repoIDs)
|
||||
repos, err := repo_model.GetRepositoriesMapByIDs(ctx, repoIDs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -269,6 +269,9 @@ func FindIDs(ctx context.Context, tableName, idCol string, cond builder.Cond) ([
|
|||
// DecrByIDs decreases the given column for entities of the "bean" type with one of the given ids by one
|
||||
// Timestamps of the entities won't be updated
|
||||
func DecrByIDs(ctx context.Context, ids []int64, decrCol string, bean any) error {
|
||||
if len(ids) == 0 {
|
||||
return nil
|
||||
}
|
||||
_, err := GetEngine(ctx).Decr(decrCol).In("id", ids).NoAutoCondition().NoAutoTime().Update(bean)
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -546,6 +546,9 @@ func GetIssueByID(ctx context.Context, id int64) (*Issue, error) {
|
|||
// If keepOrder is true, the order of the returned issues will be the same as the given IDs.
|
||||
func GetIssuesByIDs(ctx context.Context, issueIDs []int64, keepOrder ...bool) (IssueList, error) {
|
||||
issues := make([]*Issue, 0, len(issueIDs))
|
||||
if len(issueIDs) == 0 {
|
||||
return issues, nil
|
||||
}
|
||||
|
||||
if err := db.GetEngine(ctx).In("id", issueIDs).Find(&issues); err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -303,6 +303,9 @@ func GetLabelByID(ctx context.Context, labelID int64) (*Label, error) {
|
|||
// GetLabelsByIDs returns a list of labels by IDs
|
||||
func GetLabelsByIDs(ctx context.Context, labelIDs []int64, cols ...string) ([]*Label, error) {
|
||||
labels := make([]*Label, 0, len(labelIDs))
|
||||
if len(labelIDs) == 0 {
|
||||
return labels, nil
|
||||
}
|
||||
return labels, db.GetEngine(ctx).Table("label").
|
||||
In("id", labelIDs).
|
||||
Asc("name").
|
||||
|
@ -379,6 +382,9 @@ func BuildLabelNamesIssueIDsCondition(labelNames []string) *builder.Builder {
|
|||
// it silently ignores label IDs that do not belong to the repository.
|
||||
func GetLabelsInRepoByIDs(ctx context.Context, repoID int64, labelIDs []int64) ([]*Label, error) {
|
||||
labels := make([]*Label, 0, len(labelIDs))
|
||||
if len(labelIDs) == 0 {
|
||||
return labels, nil
|
||||
}
|
||||
return labels, db.GetEngine(ctx).
|
||||
Where("repo_id = ?", repoID).
|
||||
In("id", labelIDs).
|
||||
|
@ -451,6 +457,9 @@ func GetLabelInOrgByID(ctx context.Context, orgID, labelID int64) (*Label, error
|
|||
// it silently ignores label IDs that do not belong to the organization.
|
||||
func GetLabelsInOrgByIDs(ctx context.Context, orgID int64, labelIDs []int64) ([]*Label, error) {
|
||||
labels := make([]*Label, 0, len(labelIDs))
|
||||
if len(labelIDs) == 0 {
|
||||
return labels, nil
|
||||
}
|
||||
return labels, db.GetEngine(ctx).
|
||||
Where("org_id = ?", orgID).
|
||||
In("id", labelIDs).
|
||||
|
|
|
@ -293,6 +293,9 @@ func SetDefaultColumn(ctx context.Context, projectID, columnID int64) error {
|
|||
|
||||
func GetColumnsByIDs(ctx context.Context, projectID int64, columnsIDs []int64) (ColumnList, error) {
|
||||
columns := make([]*Column, 0, 5)
|
||||
if len(columnsIDs) == 0 {
|
||||
return columns, nil
|
||||
}
|
||||
if err := db.GetEngine(ctx).
|
||||
Where("project_id =?", projectID).
|
||||
In("id", columnsIDs).
|
||||
|
|
|
@ -28,10 +28,10 @@ type GrepResult struct {
|
|||
HighlightedRanges [][3]int
|
||||
}
|
||||
|
||||
type grepMode int
|
||||
type GrepMode int
|
||||
|
||||
const (
|
||||
FixedGrepMode grepMode = iota
|
||||
FixedGrepMode GrepMode = iota
|
||||
FixedAnyGrepMode
|
||||
RegExpGrepMode
|
||||
)
|
||||
|
@ -43,7 +43,7 @@ type GrepOptions struct {
|
|||
MaxResultLimit int
|
||||
MatchesPerFile int // >= git 2.38
|
||||
ContextLineNumber int
|
||||
Mode grepMode
|
||||
Mode GrepMode
|
||||
Filename string
|
||||
}
|
||||
|
||||
|
|
|
@ -40,10 +40,6 @@ import (
|
|||
const (
|
||||
unicodeNormalizeName = "unicodeNormalize"
|
||||
maxBatchSize = 16
|
||||
// fuzzyDenominator determines the levenshtein distance per each character of a keyword
|
||||
fuzzyDenominator = 4
|
||||
// see https://github.com/blevesearch/bleve/issues/1563#issuecomment-786822311
|
||||
maxFuzziness = 2
|
||||
)
|
||||
|
||||
func addUnicodeNormalizeTokenFilter(m *mapping.IndexMappingImpl) error {
|
||||
|
@ -260,12 +256,14 @@ func (b *Indexer) Search(ctx context.Context, opts *internal.SearchOptions) (int
|
|||
keywordQuery query.Query
|
||||
)
|
||||
|
||||
phraseQuery := bleve.NewMatchPhraseQuery(opts.Keyword)
|
||||
phraseQuery.FieldVal = "Content"
|
||||
phraseQuery.Analyzer = repoIndexerAnalyzer
|
||||
keywordQuery = phraseQuery
|
||||
if opts.IsKeywordFuzzy {
|
||||
phraseQuery.Fuzziness = min(maxFuzziness, len(opts.Keyword)/fuzzyDenominator)
|
||||
if opts.Mode == internal.CodeSearchModeUnion {
|
||||
query := bleve.NewDisjunctionQuery()
|
||||
for _, field := range strings.Fields(opts.Keyword) {
|
||||
query.AddQuery(inner_bleve.MatchPhraseQuery(field, "Content", repoIndexerAnalyzer, 0))
|
||||
}
|
||||
keywordQuery = query
|
||||
} else {
|
||||
keywordQuery = inner_bleve.MatchPhraseQuery(opts.Keyword, "Content", repoIndexerAnalyzer, 0)
|
||||
}
|
||||
|
||||
if len(opts.RepoIDs) > 0 {
|
||||
|
@ -325,13 +323,16 @@ func (b *Indexer) Search(ctx context.Context, opts *internal.SearchOptions) (int
|
|||
for i, hit := range result.Hits {
|
||||
startIndex, endIndex := -1, -1
|
||||
for _, locations := range hit.Locations["Content"] {
|
||||
if startIndex != -1 && endIndex != -1 {
|
||||
break
|
||||
}
|
||||
location := locations[0]
|
||||
locationStart := int(location.Start)
|
||||
locationEnd := int(location.End)
|
||||
if startIndex < 0 || locationStart < startIndex {
|
||||
startIndex = locationStart
|
||||
}
|
||||
if endIndex < 0 || locationEnd > endIndex {
|
||||
if endIndex < 0 && locationEnd > endIndex {
|
||||
endIndex = locationEnd
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,8 +33,8 @@ const (
|
|||
esRepoIndexerLatestVersion = 2
|
||||
// multi-match-types, currently only 2 types are used
|
||||
// Reference: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-multi-match-query.html#multi-match-types
|
||||
esMultiMatchTypeBestFields = "best_fields"
|
||||
esMultiMatchTypePhrasePrefix = "phrase_prefix"
|
||||
esMultiMatchTypeBestFields = "best_fields"
|
||||
esMultiMatchTypePhrase = "phrase"
|
||||
)
|
||||
|
||||
var _ internal.Indexer = &Indexer{}
|
||||
|
@ -334,8 +334,8 @@ func extractAggs(searchResult *elastic.SearchResult) []*internal.SearchResultLan
|
|||
|
||||
// Search searches for codes and language stats by given conditions.
|
||||
func (b *Indexer) Search(ctx context.Context, opts *internal.SearchOptions) (int64, []*internal.SearchResult, []*internal.SearchResultLanguages, error) {
|
||||
searchType := esMultiMatchTypePhrasePrefix
|
||||
if opts.IsKeywordFuzzy {
|
||||
searchType := esMultiMatchTypePhrase
|
||||
if opts.Mode == internal.CodeSearchModeUnion {
|
||||
searchType = esMultiMatchTypeBestFields
|
||||
}
|
||||
|
||||
|
|
|
@ -100,8 +100,8 @@ func testIndexer(name string, t *testing.T, indexer internal.Indexer) {
|
|||
Page: 1,
|
||||
PageSize: 10,
|
||||
},
|
||||
Filename: kw.Filename,
|
||||
IsKeywordFuzzy: true,
|
||||
Filename: kw.Filename,
|
||||
Mode: SearchModeUnion,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, kw.IDs, int(total))
|
||||
|
|
|
@ -20,13 +20,27 @@ type Indexer interface {
|
|||
Search(ctx context.Context, opts *SearchOptions) (int64, []*SearchResult, []*SearchResultLanguages, error)
|
||||
}
|
||||
|
||||
type CodeSearchMode int
|
||||
|
||||
const (
|
||||
CodeSearchModeExact CodeSearchMode = iota
|
||||
CodeSearchModeUnion
|
||||
)
|
||||
|
||||
func (mode CodeSearchMode) String() string {
|
||||
if mode == CodeSearchModeUnion {
|
||||
return "union"
|
||||
}
|
||||
return "exact"
|
||||
}
|
||||
|
||||
type SearchOptions struct {
|
||||
RepoIDs []int64
|
||||
Keyword string
|
||||
Language string
|
||||
Filename string
|
||||
|
||||
IsKeywordFuzzy bool
|
||||
Mode CodeSearchMode
|
||||
|
||||
db.Paginator
|
||||
}
|
||||
|
|
|
@ -35,7 +35,14 @@ type SearchResultLanguages = internal.SearchResultLanguages
|
|||
|
||||
type SearchOptions = internal.SearchOptions
|
||||
|
||||
var CodeSearchOptions = [2]string{"exact", "fuzzy"}
|
||||
var CodeSearchOptions = [2]string{"exact", "union"}
|
||||
|
||||
type SearchMode = internal.CodeSearchMode
|
||||
|
||||
const (
|
||||
SearchModeExact = internal.CodeSearchModeExact
|
||||
SearchModeUnion = internal.CodeSearchModeUnion
|
||||
)
|
||||
|
||||
func indices(content string, selectionStartIndex, selectionEndIndex int) (int, int) {
|
||||
startIndex := selectionStartIndex
|
||||
|
@ -206,7 +213,6 @@ func searchResult(result *internal.SearchResult, startIndex, endIndex int) (*Res
|
|||
}
|
||||
|
||||
// PerformSearch perform a search on a repository
|
||||
// if isFuzzy is true set the Damerau-Levenshtein distance from 0 to 2
|
||||
func PerformSearch(ctx context.Context, opts *SearchOptions) (int, []*Result, []*SearchResultLanguages, error) {
|
||||
if opts == nil || len(opts.Keyword) == 0 {
|
||||
return 0, nil, nil, nil
|
||||
|
|
|
@ -16,12 +16,12 @@
|
|||
package keying
|
||||
|
||||
import (
|
||||
"crypto/hkdf"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
|
||||
"golang.org/x/crypto/chacha20poly1305"
|
||||
"golang.org/x/crypto/hkdf"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -41,7 +41,11 @@ const (
|
|||
// Set the main IKM for this module.
|
||||
func Init(ikm []byte) {
|
||||
// Salt is intentionally left empty, it's not useful to Forgejo's use case.
|
||||
prk = hkdf.Extract(hash, ikm, nil)
|
||||
var err error
|
||||
prk, err = hkdf.Extract(hash, ikm, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Specifies the context for which a subkey should be derived for.
|
||||
|
@ -62,11 +66,8 @@ func DeriveKey(context Context) *Key {
|
|||
panic("keying: not initialized")
|
||||
}
|
||||
|
||||
r := hkdf.Expand(hash, prk, []byte(context))
|
||||
|
||||
key := make([]byte, aeadKeySize)
|
||||
// This should never return an error, but if it does, panic.
|
||||
if n, err := r.Read(key); err != nil || n != aeadKeySize {
|
||||
key, err := hkdf.Expand(hash, prk, string(context), aeadKeySize)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
{
|
||||
"home.welcome.no_activity": "No activity",
|
||||
"home.welcome.activity_hint": "There is nothing in your feed yet. Your actions and activity from repositories that you watch will show up here.",
|
||||
"home.explore_repos": "Explore repositories",
|
||||
"home.explore_users": "Explore users",
|
||||
"home.explore_orgs": "Explore organizations",
|
||||
"repo.pulls.merged_title_desc": {
|
||||
"one": "merged %[1]d commit from <code>%[2]s</code> into <code>%[3]s</code> %[4]s",
|
||||
"other": "merged %[1]d commits from <code>%[2]s</code> into <code>%[3]s</code> %[4]s"
|
||||
},
|
||||
"repo.pulls.title_desc": {
|
||||
"one": "wants to merge %[1]d commit from <code>%[2]s</code> into <code id=\"%[4]s\">%[3]s</code>",
|
||||
"other": "wants to merge %[1]d commits from <code>%[2]s</code> into <code id=\"%[4]s\">%[3]s</code>"
|
||||
},
|
||||
"search.milestone_kind": "Search milestones…",
|
||||
"incorrect_root_url": "This Forgejo instance is configured to be served on \"%s\". You are currently viewing Forgejo through a different URL, which may cause parts of the application to break. The canonical URL is controlled by Forgejo admins via the ROOT_URL setting in the app.ini.",
|
||||
"themes.names.forgejo-auto": "Forgejo (follow system theme)",
|
||||
"themes.names.forgejo-light": "Forgejo light",
|
||||
"themes.names.forgejo-dark": "Forgejo dark"
|
||||
"home.welcome.no_activity": "No activity",
|
||||
"home.welcome.activity_hint": "There is nothing in your feed yet. Your actions and activity from repositories that you watch will show up here.",
|
||||
"home.explore_repos": "Explore repositories",
|
||||
"home.explore_users": "Explore users",
|
||||
"home.explore_orgs": "Explore organizations",
|
||||
"repo.pulls.merged_title_desc": {
|
||||
"one": "merged %[1]d commit from <code>%[2]s</code> into <code>%[3]s</code> %[4]s",
|
||||
"other": "merged %[1]d commits from <code>%[2]s</code> into <code>%[3]s</code> %[4]s"
|
||||
},
|
||||
"repo.pulls.title_desc": {
|
||||
"one": "wants to merge %[1]d commit from <code>%[2]s</code> into <code id=\"%[4]s\">%[3]s</code>",
|
||||
"other": "wants to merge %[1]d commits from <code>%[2]s</code> into <code id=\"%[4]s\">%[3]s</code>"
|
||||
},
|
||||
"search.milestone_kind": "Search milestones…",
|
||||
"incorrect_root_url": "This Forgejo instance is configured to be served on \"%s\". You are currently viewing Forgejo through a different URL, which may cause parts of the application to break. The canonical URL is controlled by Forgejo admins via the ROOT_URL setting in the app.ini.",
|
||||
"themes.names.forgejo-auto": "Forgejo (follow system theme)",
|
||||
"themes.names.forgejo-light": "Forgejo light",
|
||||
"themes.names.forgejo-dark": "Forgejo dark"
|
||||
}
|
||||
|
|
10
poetry.lock
generated
10
poetry.lock
generated
|
@ -404,13 +404,13 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "yamllint"
|
||||
version = "1.35.1"
|
||||
version = "1.36.0"
|
||||
description = "A linter for YAML files."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "yamllint-1.35.1-py3-none-any.whl", hash = "sha256:2e16e504bb129ff515b37823b472750b36b6de07963bd74b307341ef5ad8bdc3"},
|
||||
{file = "yamllint-1.35.1.tar.gz", hash = "sha256:7a003809f88324fd2c877734f2d575ee7881dd9043360657cc8049c809eba6cd"},
|
||||
{file = "yamllint-1.36.0-py3-none-any.whl", hash = "sha256:22ab6a7db9d5f0954bd7a50ef70a41c1465c61f955893070b0767c0ec6693b7b"},
|
||||
{file = "yamllint-1.36.0.tar.gz", hash = "sha256:3835a65994858679ea06fd998dd968c3f71935cd93742990405999d888e21130"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -423,4 +423,4 @@ dev = ["doc8", "flake8", "flake8-import-order", "rstcheck[sphinx]", "sphinx"]
|
|||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.10"
|
||||
content-hash = "f0f2f5f83d2277f5c289c62b96a2526fc89a7d54a88ac5fd044a022486c1cbb7"
|
||||
content-hash = "c8ff4ba89b1588b4222e79f9832b3596b5c5d5a2fce8c5659b90bd31bd0f61b0"
|
||||
|
|
|
@ -6,7 +6,7 @@ python = "^3.10"
|
|||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
djlint = "1.36.4"
|
||||
yamllint = "1.35.1"
|
||||
yamllint = "1.36.0"
|
||||
codespell = "2.4.1"
|
||||
|
||||
[tool.djlint]
|
||||
|
|
|
@ -85,7 +85,7 @@ func Search(ctx *context.APIContext) {
|
|||
// type: boolean
|
||||
// - name: is_private
|
||||
// in: query
|
||||
// description: show only pubic, private or all repositories (defaults to all)
|
||||
// description: show only public, private or all repositories (defaults to all)
|
||||
// type: boolean
|
||||
// - name: template
|
||||
// in: query
|
||||
|
|
|
@ -37,19 +37,17 @@ func Code(ctx *context.Context) {
|
|||
keyword := ctx.FormTrim("q")
|
||||
path := ctx.FormTrim("path")
|
||||
|
||||
isFuzzy := ctx.FormOptionalBool("fuzzy").ValueOrDefault(true)
|
||||
if mode := ctx.FormTrim("mode"); len(mode) > 0 {
|
||||
isFuzzy = mode == "fuzzy"
|
||||
mode := code_indexer.SearchModeExact
|
||||
if m := ctx.FormTrim("mode"); m == "union" ||
|
||||
m == "fuzzy" ||
|
||||
ctx.FormBool("fuzzy") {
|
||||
mode = code_indexer.SearchModeUnion
|
||||
}
|
||||
|
||||
ctx.Data["Keyword"] = keyword
|
||||
ctx.Data["Language"] = language
|
||||
ctx.Data["CodeSearchOptions"] = []string{"exact", "fuzzy"}
|
||||
if isFuzzy {
|
||||
ctx.Data["CodeSearchMode"] = "fuzzy"
|
||||
} else {
|
||||
ctx.Data["CodeSearchMode"] = "exact"
|
||||
}
|
||||
ctx.Data["CodeSearchOptions"] = code_indexer.CodeSearchOptions
|
||||
ctx.Data["CodeSearchMode"] = mode.String()
|
||||
ctx.Data["PageIsViewCode"] = true
|
||||
|
||||
if keyword == "" {
|
||||
|
@ -88,11 +86,11 @@ func Code(ctx *context.Context) {
|
|||
|
||||
if (len(repoIDs) > 0) || isAdmin {
|
||||
total, searchResults, searchResultLanguages, err = code_indexer.PerformSearch(ctx, &code_indexer.SearchOptions{
|
||||
RepoIDs: repoIDs,
|
||||
Keyword: keyword,
|
||||
IsKeywordFuzzy: isFuzzy,
|
||||
Language: language,
|
||||
Filename: path,
|
||||
RepoIDs: repoIDs,
|
||||
Keyword: keyword,
|
||||
Mode: mode,
|
||||
Language: language,
|
||||
Filename: path,
|
||||
Paginator: &db.ListOptions{
|
||||
Page: page,
|
||||
PageSize: setting.UI.RepoSearchPagingNum,
|
||||
|
|
|
@ -21,14 +21,14 @@ type searchMode int
|
|||
|
||||
const (
|
||||
ExactSearchMode searchMode = iota
|
||||
FuzzySearchMode
|
||||
UnionSearchMode
|
||||
RegExpSearchMode
|
||||
)
|
||||
|
||||
func searchModeFromString(s string) searchMode {
|
||||
switch s {
|
||||
case "fuzzy", "union":
|
||||
return FuzzySearchMode
|
||||
return UnionSearchMode
|
||||
case "regexp":
|
||||
return RegExpSearchMode
|
||||
default:
|
||||
|
@ -40,8 +40,8 @@ func (m searchMode) String() string {
|
|||
switch m {
|
||||
case ExactSearchMode:
|
||||
return "exact"
|
||||
case FuzzySearchMode:
|
||||
return "fuzzy"
|
||||
case UnionSearchMode:
|
||||
return "union"
|
||||
case RegExpSearchMode:
|
||||
return "regexp"
|
||||
default:
|
||||
|
@ -49,6 +49,24 @@ func (m searchMode) String() string {
|
|||
}
|
||||
}
|
||||
|
||||
func (m searchMode) ToIndexer() code_indexer.SearchMode {
|
||||
if m == ExactSearchMode {
|
||||
return code_indexer.SearchModeExact
|
||||
}
|
||||
return code_indexer.SearchModeUnion
|
||||
}
|
||||
|
||||
func (m searchMode) ToGitGrep() git.GrepMode {
|
||||
switch m {
|
||||
case RegExpSearchMode:
|
||||
return git.RegExpGrepMode
|
||||
case UnionSearchMode:
|
||||
return git.FixedAnyGrepMode
|
||||
default:
|
||||
return git.FixedGrepMode
|
||||
}
|
||||
}
|
||||
|
||||
// Search render repository search page
|
||||
func Search(ctx *context.Context) {
|
||||
language := ctx.FormTrim("l")
|
||||
|
@ -59,7 +77,7 @@ func Search(ctx *context.Context) {
|
|||
if modeStr := ctx.FormString("mode"); len(modeStr) > 0 {
|
||||
mode = searchModeFromString(modeStr)
|
||||
} else if ctx.FormOptionalBool("fuzzy").ValueOrDefault(true) { // for backward compatibility in links
|
||||
mode = FuzzySearchMode
|
||||
mode = UnionSearchMode
|
||||
}
|
||||
|
||||
ctx.Data["Keyword"] = keyword
|
||||
|
@ -90,11 +108,11 @@ func Search(ctx *context.Context) {
|
|||
if setting.Indexer.RepoIndexerEnabled {
|
||||
var err error
|
||||
total, searchResults, searchResultLanguages, err = code_indexer.PerformSearch(ctx, &code_indexer.SearchOptions{
|
||||
RepoIDs: []int64{ctx.Repo.Repository.ID},
|
||||
Keyword: keyword,
|
||||
IsKeywordFuzzy: mode == FuzzySearchMode,
|
||||
Language: language,
|
||||
Filename: path,
|
||||
RepoIDs: []int64{ctx.Repo.Repository.ID},
|
||||
Keyword: keyword,
|
||||
Mode: mode.ToIndexer(),
|
||||
Language: language,
|
||||
Filename: path,
|
||||
Paginator: &db.ListOptions{
|
||||
Page: page,
|
||||
PageSize: setting.UI.RepoSearchPagingNum,
|
||||
|
@ -110,19 +128,12 @@ func Search(ctx *context.Context) {
|
|||
ctx.Data["CodeIndexerUnavailable"] = !code_indexer.IsAvailable(ctx)
|
||||
}
|
||||
} else {
|
||||
grepOpt := git.GrepOptions{
|
||||
res, err := git.GrepSearch(ctx, ctx.Repo.GitRepo, keyword, git.GrepOptions{
|
||||
ContextLineNumber: 1,
|
||||
RefName: ctx.Repo.RefName,
|
||||
Filename: path,
|
||||
}
|
||||
switch mode {
|
||||
case FuzzySearchMode:
|
||||
grepOpt.Mode = git.FixedAnyGrepMode
|
||||
ctx.Data["CodeSearchMode"] = "union"
|
||||
case RegExpSearchMode:
|
||||
grepOpt.Mode = git.RegExpGrepMode
|
||||
}
|
||||
res, err := git.GrepSearch(ctx, ctx.Repo.GitRepo, keyword, grepOpt)
|
||||
Mode: mode.ToGitGrep(),
|
||||
})
|
||||
if err != nil {
|
||||
ctx.ServerError("GrepSearch", err)
|
||||
return
|
||||
|
|
|
@ -41,19 +41,17 @@ func CodeSearch(ctx *context.Context) {
|
|||
keyword := ctx.FormTrim("q")
|
||||
path := ctx.FormTrim("path")
|
||||
|
||||
isFuzzy := ctx.FormOptionalBool("fuzzy").ValueOrDefault(true)
|
||||
if mode := ctx.FormTrim("mode"); len(mode) > 0 {
|
||||
isFuzzy = mode == "fuzzy"
|
||||
mode := code_indexer.SearchModeExact
|
||||
if m := ctx.FormTrim("mode"); m == "union" ||
|
||||
m == "fuzzy" ||
|
||||
ctx.FormBool("fuzzy") {
|
||||
mode = code_indexer.SearchModeUnion
|
||||
}
|
||||
|
||||
ctx.Data["Keyword"] = keyword
|
||||
ctx.Data["Language"] = language
|
||||
ctx.Data["CodeSearchOptions"] = []string{"exact", "fuzzy"}
|
||||
if isFuzzy {
|
||||
ctx.Data["CodeSearchMode"] = "fuzzy"
|
||||
} else {
|
||||
ctx.Data["CodeSearchMode"] = "exact"
|
||||
}
|
||||
ctx.Data["CodeSearchOptions"] = code_indexer.CodeSearchOptions
|
||||
ctx.Data["CodeSearchMode"] = mode.String()
|
||||
ctx.Data["IsCodePage"] = true
|
||||
|
||||
if keyword == "" {
|
||||
|
@ -85,11 +83,11 @@ func CodeSearch(ctx *context.Context) {
|
|||
|
||||
if len(repoIDs) > 0 {
|
||||
total, searchResults, searchResultLanguages, err = code_indexer.PerformSearch(ctx, &code_indexer.SearchOptions{
|
||||
RepoIDs: repoIDs,
|
||||
Keyword: keyword,
|
||||
IsKeywordFuzzy: isFuzzy,
|
||||
Language: language,
|
||||
Filename: path,
|
||||
RepoIDs: repoIDs,
|
||||
Keyword: keyword,
|
||||
Mode: mode,
|
||||
Language: language,
|
||||
Filename: path,
|
||||
Paginator: &db.ListOptions{
|
||||
Page: page,
|
||||
PageSize: setting.UI.RepoSearchPagingNum,
|
||||
|
|
2
templates/swagger/v1_json.tmpl
generated
2
templates/swagger/v1_json.tmpl
generated
|
@ -4645,7 +4645,7 @@
|
|||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"description": "show only pubic, private or all repositories (defaults to all)",
|
||||
"description": "show only public, private or all repositories (defaults to all)",
|
||||
"name": "is_private",
|
||||
"in": "query"
|
||||
},
|
||||
|
|
|
@ -82,19 +82,10 @@ func testSearchRepo(t *testing.T, indexer bool) {
|
|||
testSearch(t, "/user2/glob/search?q=loren&page=1", []string{"a.txt"}, indexer)
|
||||
testSearch(t, "/user2/glob/search?q=loren&page=1&mode=exact", []string{"a.txt"}, indexer)
|
||||
|
||||
if indexer {
|
||||
// fuzzy search: matches both file3 (x/b.txt) and file1 (a.txt)
|
||||
// when indexer is enabled
|
||||
testSearch(t, "/user2/glob/search?q=file3&mode=fuzzy&page=1", []string{"x/b.txt", "a.txt"}, indexer)
|
||||
testSearch(t, "/user2/glob/search?q=file4&mode=fuzzy&page=1", []string{"x/b.txt", "a.txt"}, indexer)
|
||||
testSearch(t, "/user2/glob/search?q=file5&mode=fuzzy&page=1", []string{"x/b.txt", "a.txt"}, indexer)
|
||||
} else {
|
||||
// fuzzy search: Union/OR of all the keywords
|
||||
// when indexer is disabled
|
||||
testSearch(t, "/user2/glob/search?q=file3+file1&mode=union&page=1", []string{"a.txt", "x/b.txt"}, indexer)
|
||||
testSearch(t, "/user2/glob/search?q=file4&mode=union&page=1", []string{}, indexer)
|
||||
testSearch(t, "/user2/glob/search?q=file5&mode=union&page=1", []string{}, indexer)
|
||||
}
|
||||
// union search: Union/OR of all the keywords
|
||||
testSearch(t, "/user2/glob/search?q=file3+file1&mode=union&page=1", []string{"a.txt", "x/b.txt"}, indexer)
|
||||
testSearch(t, "/user2/glob/search?q=file4&mode=union&page=1", []string{}, indexer)
|
||||
testSearch(t, "/user2/glob/search?q=file5&mode=union&page=1", []string{}, indexer)
|
||||
|
||||
testSearch(t, "/user2/glob/search?q=file3&page=1&mode=exact", []string{"x/b.txt"}, indexer)
|
||||
testSearch(t, "/user2/glob/search?q=file4&page=1&mode=exact", []string{}, indexer)
|
||||
|
@ -121,11 +112,11 @@ func testSearch(t *testing.T, url string, expected []string, indexer bool) {
|
|||
})
|
||||
|
||||
if indexer {
|
||||
assert.EqualValues(t, []string{"exact", "fuzzy"}, dropdownOptions)
|
||||
assert.EqualValues(t, []string{"exact", "union"}, dropdownOptions)
|
||||
} else {
|
||||
assert.EqualValues(t, []string{"exact", "union", "regexp"}, dropdownOptions)
|
||||
}
|
||||
|
||||
filenames := resultFilenames(t, doc)
|
||||
assert.EqualValues(t, expected, filenames)
|
||||
assert.ElementsMatch(t, expected, filenames)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue