mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-12-07 14:09:47 +00:00
To make sure that the code stays maintainable, I added the `importas` linter to ensure that the imports for models and services stay consistent. I realised that this might be needed after finding some discrepancies between singular/plural naming, and, especially in the case of the `forgejo.org/services/context` package, multiple different aliases like `gitea_ctx`, `app_context` and `forgejo_context`. I decided for `app_context`, as that seems to be the most commonly used naming. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10253 Reviewed-by: Gusted <gusted@noreply.codeberg.org> Co-authored-by: nachtjasmin <nachtjasmin@posteo.de> Co-committed-by: nachtjasmin <nachtjasmin@posteo.de>
119 lines
3.4 KiB
Go
119 lines
3.4 KiB
Go
// Copyright 2019 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package db
|
|
|
|
import (
|
|
"context"
|
|
|
|
"forgejo.org/models/db"
|
|
issues_model "forgejo.org/models/issues"
|
|
indexer_internal "forgejo.org/modules/indexer/internal"
|
|
inner_db "forgejo.org/modules/indexer/internal/db"
|
|
"forgejo.org/modules/indexer/issues/internal"
|
|
|
|
"xorm.io/builder"
|
|
)
|
|
|
|
var _ internal.Indexer = &Indexer{}
|
|
|
|
// Indexer implements Indexer interface to use database's like search
|
|
type Indexer struct {
|
|
indexer_internal.Indexer
|
|
}
|
|
|
|
func NewIndexer() *Indexer {
|
|
return &Indexer{
|
|
Indexer: &inner_db.Indexer{},
|
|
}
|
|
}
|
|
|
|
// Index dummy function
|
|
func (i *Indexer) Index(_ context.Context, _ ...*internal.IndexerData) error {
|
|
return nil
|
|
}
|
|
|
|
// Delete dummy function
|
|
func (i *Indexer) Delete(_ context.Context, _ ...int64) error {
|
|
return nil
|
|
}
|
|
|
|
// Search searches for issues
|
|
func (i *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (*internal.SearchResult, error) {
|
|
// FIXME: I tried to avoid importing models here, but it seems to be impossible.
|
|
// We can provide a function to register the search function, so models/issues can register it.
|
|
// So models/issues will import modules/indexer/issues, it's OK because it's by design.
|
|
// But modules/indexer/issues has already imported models/issues to do UpdateRepoIndexer and UpdateIssueIndexer.
|
|
// And to avoid circular import, we have to move the functions to another package.
|
|
// I believe it should be services/indexer, sounds great!
|
|
// But the two functions are used in modules/notification/indexer, that means we will import services/indexer in modules/notification/indexer.
|
|
// So that's the root problem:
|
|
// The notification is defined in modules, but it's using lots of things should be in services.
|
|
|
|
cond := builder.NewCond()
|
|
|
|
var priorityIssueIndex int64
|
|
if len(options.Tokens) != 0 {
|
|
repoCond := builder.In("repo_id", options.RepoIDs)
|
|
if len(options.RepoIDs) == 1 {
|
|
repoCond = builder.Eq{"repo_id": options.RepoIDs[0]}
|
|
}
|
|
subQuery := builder.Select("id").From("issue").Where(repoCond)
|
|
|
|
for _, token := range options.Tokens {
|
|
cond = builder.Or(
|
|
db.BuildCaseInsensitiveLike("issue.name", token.Term),
|
|
db.BuildCaseInsensitiveLike("issue.content", token.Term),
|
|
builder.In("issue.id", builder.Select("issue_id").
|
|
From("comment").
|
|
Where(builder.And(
|
|
builder.Eq{"type": issues_model.CommentTypeComment},
|
|
builder.In("issue_id", subQuery),
|
|
db.BuildCaseInsensitiveLike("content", token.Term),
|
|
)),
|
|
),
|
|
)
|
|
|
|
if ref, err := token.ParseIssueReference(); err != nil {
|
|
cond = builder.Or(
|
|
builder.Eq{"`index`": ref},
|
|
cond,
|
|
)
|
|
priorityIssueIndex = ref
|
|
}
|
|
}
|
|
}
|
|
|
|
opt, err := ToDBOptions(ctx, options)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
opt.PriorityIssueIndex = priorityIssueIndex
|
|
|
|
// If pagesize == 0, return total count only. It's a special case for search count.
|
|
if options.Paginator != nil && options.Paginator.PageSize == 0 {
|
|
total, err := issues_model.CountIssues(ctx, opt, cond)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &internal.SearchResult{
|
|
Total: total,
|
|
}, nil
|
|
}
|
|
|
|
ids, total, err := issues_model.IssueIDs(ctx, opt, cond)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
hits := make([]internal.Match, 0, len(ids))
|
|
for _, id := range ids {
|
|
hits = append(hits, internal.Match{
|
|
ID: id,
|
|
})
|
|
}
|
|
return &internal.SearchResult{
|
|
Total: total,
|
|
Hits: hits,
|
|
}, nil
|
|
}
|