Merge pull request '[gitea] week 13 cherry-pick' (#2769) from earl-warren/forgejo:wip-gitea-cherry-pick into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/2769 Reviewed-by: oliverpool <oliverpool@noreply.codeberg.org>
This commit is contained in:
commit
8339b24d61
302 changed files with 2569 additions and 5061 deletions
|
@ -100,7 +100,7 @@ func ReadLogs(ctx context.Context, inStorage bool, filename string, offset, limi
|
|||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, fmt.Errorf("scan: %w", err)
|
||||
return nil, fmt.Errorf("ReadLogs scan: %w", err)
|
||||
}
|
||||
|
||||
return rows, nil
|
||||
|
|
|
@ -41,6 +41,12 @@ func FullSteps(task *actions_model.ActionTask) []*actions_model.ActionTaskStep {
|
|||
}
|
||||
logIndex += preStep.LogLength
|
||||
|
||||
// lastHasRunStep is the last step that has run.
|
||||
// For example,
|
||||
// 1. preStep(Success) -> step1(Success) -> step2(Running) -> step3(Waiting) -> postStep(Waiting): lastHasRunStep is step1.
|
||||
// 2. preStep(Success) -> step1(Success) -> step2(Success) -> step3(Success) -> postStep(Success): lastHasRunStep is step3.
|
||||
// 3. preStep(Success) -> step1(Success) -> step2(Failure) -> step3 -> postStep(Waiting): lastHasRunStep is step2.
|
||||
// So its Stopped is the Started of postStep when there are no more steps to run.
|
||||
var lastHasRunStep *actions_model.ActionTaskStep
|
||||
for _, step := range task.Steps {
|
||||
if step.Status.HasRun() {
|
||||
|
@ -56,11 +62,15 @@ func FullSteps(task *actions_model.ActionTask) []*actions_model.ActionTaskStep {
|
|||
Name: postStepName,
|
||||
Status: actions_model.StatusWaiting,
|
||||
}
|
||||
if task.Status.IsDone() {
|
||||
// If the lastHasRunStep is the last step, or it has failed, postStep has started.
|
||||
if lastHasRunStep.Status.IsFailure() || lastHasRunStep == task.Steps[len(task.Steps)-1] {
|
||||
postStep.LogIndex = logIndex
|
||||
postStep.LogLength = task.LogLength - postStep.LogIndex
|
||||
postStep.Status = task.Status
|
||||
postStep.Started = lastHasRunStep.Stopped
|
||||
postStep.Status = actions_model.StatusRunning
|
||||
}
|
||||
if task.Status.IsDone() {
|
||||
postStep.Status = task.Status
|
||||
postStep.Stopped = task.Stopped
|
||||
}
|
||||
ret := make([]*actions_model.ActionTaskStep, 0, len(task.Steps)+2)
|
||||
|
|
|
@ -103,6 +103,40 @@ func TestFullSteps(t *testing.T) {
|
|||
{Name: postStepName, Status: actions_model.StatusSuccess, LogIndex: 100, LogLength: 0, Started: 10100, Stopped: 10100},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "all steps finished but task is running",
|
||||
task: &actions_model.ActionTask{
|
||||
Steps: []*actions_model.ActionTaskStep{
|
||||
{Status: actions_model.StatusSuccess, LogIndex: 10, LogLength: 80, Started: 10010, Stopped: 10090},
|
||||
},
|
||||
Status: actions_model.StatusRunning,
|
||||
Started: 10000,
|
||||
Stopped: 0,
|
||||
LogLength: 100,
|
||||
},
|
||||
want: []*actions_model.ActionTaskStep{
|
||||
{Name: preStepName, Status: actions_model.StatusSuccess, LogIndex: 0, LogLength: 10, Started: 10000, Stopped: 10010},
|
||||
{Status: actions_model.StatusSuccess, LogIndex: 10, LogLength: 80, Started: 10010, Stopped: 10090},
|
||||
{Name: postStepName, Status: actions_model.StatusRunning, LogIndex: 90, LogLength: 10, Started: 10090, Stopped: 0},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "skipped task",
|
||||
task: &actions_model.ActionTask{
|
||||
Steps: []*actions_model.ActionTaskStep{
|
||||
{Status: actions_model.StatusSkipped, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0},
|
||||
},
|
||||
Status: actions_model.StatusSkipped,
|
||||
Started: 0,
|
||||
Stopped: 0,
|
||||
LogLength: 0,
|
||||
},
|
||||
want: []*actions_model.ActionTaskStep{
|
||||
{Name: preStepName, Status: actions_model.StatusSkipped, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0},
|
||||
{Status: actions_model.StatusSkipped, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0},
|
||||
{Name: postStepName, Status: actions_model.StatusSkipped, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
|
|
@ -150,13 +150,16 @@ func TruncateString(str string, limit int) string {
|
|||
|
||||
// StringsToInt64s converts a slice of string to a slice of int64.
|
||||
func StringsToInt64s(strs []string) ([]int64, error) {
|
||||
ints := make([]int64, len(strs))
|
||||
for i := range strs {
|
||||
n, err := strconv.ParseInt(strs[i], 10, 64)
|
||||
if strs == nil {
|
||||
return nil, nil
|
||||
}
|
||||
ints := make([]int64, 0, len(strs))
|
||||
for _, s := range strs {
|
||||
n, err := strconv.ParseInt(s, 10, 64)
|
||||
if err != nil {
|
||||
return ints, err
|
||||
return nil, err
|
||||
}
|
||||
ints[i] = n
|
||||
ints = append(ints, n)
|
||||
}
|
||||
return ints, nil
|
||||
}
|
||||
|
|
|
@ -138,12 +138,13 @@ func TestStringsToInt64s(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.Equal(t, expected, result)
|
||||
}
|
||||
testSuccess(nil, nil)
|
||||
testSuccess([]string{}, []int64{})
|
||||
testSuccess([]string{"-1234"}, []int64{-1234})
|
||||
testSuccess([]string{"1", "4", "16", "64", "256"},
|
||||
[]int64{1, 4, 16, 64, 256})
|
||||
testSuccess([]string{"1", "4", "16", "64", "256"}, []int64{1, 4, 16, 64, 256})
|
||||
|
||||
_, err := StringsToInt64s([]string{"-1", "a", "$"})
|
||||
ints, err := StringsToInt64s([]string{"-1", "a"})
|
||||
assert.Len(t, ints, 0)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
|
@ -390,6 +391,9 @@ func (c *Commit) GetSubModules() (*ObjectCache, error) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if err = scanner.Err(); err != nil {
|
||||
return nil, fmt.Errorf("GetSubModules scan: %w", err)
|
||||
}
|
||||
|
||||
return c.submoduleCache, nil
|
||||
}
|
||||
|
|
|
@ -283,7 +283,7 @@ type DivergeObject struct {
|
|||
// GetDivergingCommits returns the number of commits a targetBranch is ahead or behind a baseBranch
|
||||
func GetDivergingCommits(ctx context.Context, repoPath, baseBranch, targetBranch string) (do DivergeObject, err error) {
|
||||
cmd := NewCommand(ctx, "rev-list", "--count", "--left-right").
|
||||
AddDynamicArguments(baseBranch + "..." + targetBranch)
|
||||
AddDynamicArguments(baseBranch + "..." + targetBranch).AddArguments("--")
|
||||
stdout, _, err := cmd.RunStdString(&RunOpts{Dir: repoPath})
|
||||
if err != nil {
|
||||
return do, err
|
||||
|
|
|
@ -124,6 +124,10 @@ func (repo *Repository) GetCodeActivityStats(fromTime time.Time, branch string)
|
|||
}
|
||||
}
|
||||
}
|
||||
if err = scanner.Err(); err != nil {
|
||||
_ = stdoutReader.Close()
|
||||
return fmt.Errorf("GetCodeActivityStats scan: %w", err)
|
||||
}
|
||||
a := make([]*CodeActivityAuthor, 0, len(authors))
|
||||
for _, v := range authors {
|
||||
a = append(a, v)
|
||||
|
|
|
@ -59,8 +59,8 @@ func (g *Manager) start() {
|
|||
go func() {
|
||||
defer func() {
|
||||
close(startupDone)
|
||||
// Close the unused listeners and ignore the error here there's not much we can do with it, they're logged in the CloseProvidedListeners function
|
||||
_ = CloseProvidedListeners()
|
||||
// Close the unused listeners
|
||||
closeProvidedListeners()
|
||||
}()
|
||||
// Wait for all servers to be created
|
||||
g.createServerCond.L.Lock()
|
||||
|
|
|
@ -129,25 +129,17 @@ func getProvidedFDs() (savedErr error) {
|
|||
return savedErr
|
||||
}
|
||||
|
||||
// CloseProvidedListeners closes all unused provided listeners.
|
||||
func CloseProvidedListeners() error {
|
||||
// closeProvidedListeners closes all unused provided listeners.
|
||||
func closeProvidedListeners() {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
var returnableError error
|
||||
for _, l := range providedListeners {
|
||||
err := l.Close()
|
||||
if err != nil {
|
||||
log.Error("Error in closing unused provided listener: %v", err)
|
||||
if returnableError != nil {
|
||||
returnableError = fmt.Errorf("%v & %w", returnableError, err)
|
||||
} else {
|
||||
returnableError = err
|
||||
}
|
||||
}
|
||||
}
|
||||
providedListeners = []net.Listener{}
|
||||
|
||||
return returnableError
|
||||
}
|
||||
|
||||
// DefaultGetListener obtains a listener for the stream-oriented local network address:
|
||||
|
|
|
@ -39,6 +39,8 @@ import (
|
|||
const (
|
||||
unicodeNormalizeName = "unicodeNormalize"
|
||||
maxBatchSize = 16
|
||||
// fuzzyDenominator determines the levenshtein distance per each character of a keyword
|
||||
fuzzyDenominator = 4
|
||||
)
|
||||
|
||||
func addUnicodeNormalizeTokenFilter(m *mapping.IndexMappingImpl) error {
|
||||
|
@ -239,15 +241,12 @@ 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 := bleve.NewMatchPhraseQuery(opts.Keyword)
|
||||
phraseQuery.FieldVal = "Content"
|
||||
phraseQuery.Analyzer = repoIndexerAnalyzer
|
||||
keywordQuery = phraseQuery
|
||||
} else {
|
||||
prefixQuery := bleve.NewPrefixQuery(opts.Keyword)
|
||||
prefixQuery.FieldVal = "Content"
|
||||
keywordQuery = prefixQuery
|
||||
phraseQuery.Fuzziness = len(opts.Keyword) / fuzzyDenominator
|
||||
}
|
||||
|
||||
if len(opts.RepoIDs) > 0 {
|
||||
|
|
|
@ -20,17 +20,11 @@ func NumericEqualityQuery(value int64, field string) *query.NumericRangeQuery {
|
|||
}
|
||||
|
||||
// MatchPhraseQuery generates a match phrase query for the given phrase, field and analyzer
|
||||
func MatchPhraseQuery(matchPhrase, field, analyzer string) *query.MatchPhraseQuery {
|
||||
func MatchPhraseQuery(matchPhrase, field, analyzer string, fuzziness int) *query.MatchPhraseQuery {
|
||||
q := bleve.NewMatchPhraseQuery(matchPhrase)
|
||||
q.FieldVal = field
|
||||
q.Analyzer = analyzer
|
||||
return q
|
||||
}
|
||||
|
||||
// PrefixQuery generates a match prefix query for the given prefix and field
|
||||
func PrefixQuery(matchPrefix, field string) *query.PrefixQuery {
|
||||
q := bleve.NewPrefixQuery(matchPrefix)
|
||||
q.FieldVal = field
|
||||
q.Fuzziness = fuzziness
|
||||
return q
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,11 @@ func addUnicodeNormalizeTokenFilter(m *mapping.IndexMappingImpl) error {
|
|||
})
|
||||
}
|
||||
|
||||
const maxBatchSize = 16
|
||||
const (
|
||||
maxBatchSize = 16
|
||||
// fuzzyDenominator determines the levenshtein distance per each character of a keyword
|
||||
fuzzyDenominator = 4
|
||||
)
|
||||
|
||||
// IndexerData an update to the issue indexer
|
||||
type IndexerData internal.IndexerData
|
||||
|
@ -156,19 +160,16 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
|
|||
var queries []query.Query
|
||||
|
||||
if options.Keyword != "" {
|
||||
fuzziness := 0
|
||||
if options.IsFuzzyKeyword {
|
||||
queries = append(queries, bleve.NewDisjunctionQuery([]query.Query{
|
||||
inner_bleve.MatchPhraseQuery(options.Keyword, "title", issueIndexerAnalyzer),
|
||||
inner_bleve.MatchPhraseQuery(options.Keyword, "content", issueIndexerAnalyzer),
|
||||
inner_bleve.MatchPhraseQuery(options.Keyword, "comments", issueIndexerAnalyzer),
|
||||
}...))
|
||||
} else {
|
||||
queries = append(queries, bleve.NewDisjunctionQuery([]query.Query{
|
||||
inner_bleve.PrefixQuery(options.Keyword, "title"),
|
||||
inner_bleve.PrefixQuery(options.Keyword, "content"),
|
||||
inner_bleve.PrefixQuery(options.Keyword, "comments"),
|
||||
}...))
|
||||
fuzziness = len(options.Keyword) / fuzzyDenominator
|
||||
}
|
||||
|
||||
queries = append(queries, bleve.NewDisjunctionQuery([]query.Query{
|
||||
inner_bleve.MatchPhraseQuery(options.Keyword, "title", issueIndexerAnalyzer, fuzziness),
|
||||
inner_bleve.MatchPhraseQuery(options.Keyword, "content", issueIndexerAnalyzer, fuzziness),
|
||||
inner_bleve.MatchPhraseQuery(options.Keyword, "comments", issueIndexerAnalyzer, fuzziness),
|
||||
}...))
|
||||
}
|
||||
|
||||
if len(options.RepoIDs) > 0 || options.AllPublic {
|
||||
|
|
|
@ -515,10 +515,8 @@ var cases = []*testIndexerCase{
|
|||
{
|
||||
Name: "SortByCreatedDesc",
|
||||
SearchOptions: &internal.SearchOptions{
|
||||
Paginator: &db.ListOptions{
|
||||
ListAll: true,
|
||||
},
|
||||
SortBy: internal.SortByCreatedDesc,
|
||||
Paginator: &db.ListOptionsAll,
|
||||
SortBy: internal.SortByCreatedDesc,
|
||||
},
|
||||
Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
|
||||
assert.Equal(t, len(data), len(result.Hits))
|
||||
|
@ -533,10 +531,8 @@ var cases = []*testIndexerCase{
|
|||
{
|
||||
Name: "SortByUpdatedDesc",
|
||||
SearchOptions: &internal.SearchOptions{
|
||||
Paginator: &db.ListOptions{
|
||||
ListAll: true,
|
||||
},
|
||||
SortBy: internal.SortByUpdatedDesc,
|
||||
Paginator: &db.ListOptionsAll,
|
||||
SortBy: internal.SortByUpdatedDesc,
|
||||
},
|
||||
Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
|
||||
assert.Equal(t, len(data), len(result.Hits))
|
||||
|
@ -551,10 +547,8 @@ var cases = []*testIndexerCase{
|
|||
{
|
||||
Name: "SortByCommentsDesc",
|
||||
SearchOptions: &internal.SearchOptions{
|
||||
Paginator: &db.ListOptions{
|
||||
ListAll: true,
|
||||
},
|
||||
SortBy: internal.SortByCommentsDesc,
|
||||
Paginator: &db.ListOptionsAll,
|
||||
SortBy: internal.SortByCommentsDesc,
|
||||
},
|
||||
Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
|
||||
assert.Equal(t, len(data), len(result.Hits))
|
||||
|
@ -569,10 +563,8 @@ var cases = []*testIndexerCase{
|
|||
{
|
||||
Name: "SortByDeadlineDesc",
|
||||
SearchOptions: &internal.SearchOptions{
|
||||
Paginator: &db.ListOptions{
|
||||
ListAll: true,
|
||||
},
|
||||
SortBy: internal.SortByDeadlineDesc,
|
||||
Paginator: &db.ListOptionsAll,
|
||||
SortBy: internal.SortByDeadlineDesc,
|
||||
},
|
||||
Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
|
||||
assert.Equal(t, len(data), len(result.Hits))
|
||||
|
@ -587,10 +579,8 @@ var cases = []*testIndexerCase{
|
|||
{
|
||||
Name: "SortByCreatedAsc",
|
||||
SearchOptions: &internal.SearchOptions{
|
||||
Paginator: &db.ListOptions{
|
||||
ListAll: true,
|
||||
},
|
||||
SortBy: internal.SortByCreatedAsc,
|
||||
Paginator: &db.ListOptionsAll,
|
||||
SortBy: internal.SortByCreatedAsc,
|
||||
},
|
||||
Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
|
||||
assert.Equal(t, len(data), len(result.Hits))
|
||||
|
@ -605,10 +595,8 @@ var cases = []*testIndexerCase{
|
|||
{
|
||||
Name: "SortByUpdatedAsc",
|
||||
SearchOptions: &internal.SearchOptions{
|
||||
Paginator: &db.ListOptions{
|
||||
ListAll: true,
|
||||
},
|
||||
SortBy: internal.SortByUpdatedAsc,
|
||||
Paginator: &db.ListOptionsAll,
|
||||
SortBy: internal.SortByUpdatedAsc,
|
||||
},
|
||||
Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
|
||||
assert.Equal(t, len(data), len(result.Hits))
|
||||
|
@ -623,10 +611,8 @@ var cases = []*testIndexerCase{
|
|||
{
|
||||
Name: "SortByCommentsAsc",
|
||||
SearchOptions: &internal.SearchOptions{
|
||||
Paginator: &db.ListOptions{
|
||||
ListAll: true,
|
||||
},
|
||||
SortBy: internal.SortByCommentsAsc,
|
||||
Paginator: &db.ListOptionsAll,
|
||||
SortBy: internal.SortByCommentsAsc,
|
||||
},
|
||||
Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
|
||||
assert.Equal(t, len(data), len(result.Hits))
|
||||
|
@ -641,10 +627,8 @@ var cases = []*testIndexerCase{
|
|||
{
|
||||
Name: "SortByDeadlineAsc",
|
||||
SearchOptions: &internal.SearchOptions{
|
||||
Paginator: &db.ListOptions{
|
||||
ListAll: true,
|
||||
},
|
||||
SortBy: internal.SortByDeadlineAsc,
|
||||
Paginator: &db.ListOptionsAll,
|
||||
SortBy: internal.SortByDeadlineAsc,
|
||||
},
|
||||
Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
|
||||
assert.Equal(t, len(data), len(result.Hits))
|
||||
|
|
|
@ -61,9 +61,7 @@ func getIssueIndexerData(ctx context.Context, issueID int64) (*internal.IndexerD
|
|||
)
|
||||
{
|
||||
reviews, err := issue_model.FindReviews(ctx, issue_model.FindReviewOptions{
|
||||
ListOptions: db.ListOptions{
|
||||
ListAll: true,
|
||||
},
|
||||
ListOptions: db.ListOptionsAll,
|
||||
IssueID: issueID,
|
||||
OfficialOnly: false,
|
||||
})
|
||||
|
|
|
@ -6,6 +6,7 @@ package markup
|
|||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"html"
|
||||
"io"
|
||||
"regexp"
|
||||
|
@ -123,6 +124,9 @@ func (Renderer) fallbackRender(input io.Reader, tmpBlock *bufio.Writer) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
if err = scan.Err(); err != nil {
|
||||
return fmt.Errorf("fallbackRender scan: %w", err)
|
||||
}
|
||||
|
||||
_, err = tmpBlock.WriteString("</pre>")
|
||||
if err != nil {
|
||||
|
|
|
@ -54,7 +54,7 @@ func Sorted[S ~[]E, E cmp.Ordered](values S) S {
|
|||
return values
|
||||
}
|
||||
|
||||
// TODO: Replace with "maps.Values" once available
|
||||
// TODO: Replace with "maps.Values" once available, current it only in golang.org/x/exp/maps but not in standard library
|
||||
func ValuesOfMap[K comparable, V any](m map[K]V) []V {
|
||||
values := make([]V, 0, len(m))
|
||||
for _, v := range m {
|
||||
|
@ -62,3 +62,12 @@ func ValuesOfMap[K comparable, V any](m map[K]V) []V {
|
|||
}
|
||||
return values
|
||||
}
|
||||
|
||||
// TODO: Replace with "maps.Keys" once available, current it only in golang.org/x/exp/maps but not in standard library
|
||||
func KeysOfMap[K comparable, V any](m map[K]V) []K {
|
||||
keys := make([]K, 0, len(m))
|
||||
for k := range m {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue