ALR

Форк
1
/
search.go 
167 строк · 3.9 Кб
1
package search
2

3
import (
4
	"context"
5
	"errors"
6
	"io"
7
	"io/fs"
8
	"os"
9
	"path/filepath"
10
	"strconv"
11
	"strings"
12

13
	"plemya-x.ru/alr/internal/config"
14
	"plemya-x.ru/alr/internal/db"
15
)
16

17
// Filter represents search filters.
18
type Filter int
19

20
// Filters
21
const (
22
	FilterNone Filter = iota
23
	FilterInRepo
24
	FilterSupportsArch
25
)
26

27
// SoryBy represents a value that packages can be sorted by.
28
type SortBy int
29

30
// Sort values
31
const (
32
	SortByNone = iota
33
	SortByName
34
	SortByRepo
35
	SortByVersion
36
)
37

38
// Package represents a package from ALR's database
39
type Package struct {
40
	Name          string
41
	Version       string
42
	Release       int
43
	Epoch         uint
44
	Description   map[string]string
45
	Homepage      map[string]string
46
	Maintainer    map[string]string
47
	Architectures []string
48
	Licenses      []string
49
	Provides      []string
50
	Conflicts     []string
51
	Replaces      []string
52
	Depends       map[string][]string
53
	BuildDepends  map[string][]string
54
	OptDepends    map[string][]string
55
	Repository    string
56
}
57

58
func convertPkg(p db.Package) Package {
59
	return Package{
60
		Name:          p.Name,
61
		Version:       p.Version,
62
		Release:       p.Release,
63
		Epoch:         p.Epoch,
64
		Description:   p.Description.Val,
65
		Homepage:      p.Homepage.Val,
66
		Maintainer:    p.Maintainer.Val,
67
		Architectures: p.Architectures.Val,
68
		Licenses:      p.Licenses.Val,
69
		Provides:      p.Provides.Val,
70
		Conflicts:     p.Conflicts.Val,
71
		Replaces:      p.Replaces.Val,
72
		Depends:       p.Depends.Val,
73
		BuildDepends:  p.BuildDepends.Val,
74
		OptDepends:    p.OptDepends.Val,
75
		Repository:    p.Repository,
76
	}
77
}
78

79
// Options contains the options for a search.
80
type Options struct {
81
	Filter      Filter
82
	FilterValue string
83
	SortBy      SortBy
84
	Limit       int64
85
	Query       string
86
}
87

88
// Search searches for packages in the database based on the given options.
89
func Search(ctx context.Context, opts Options) ([]Package, error) {
90
	query := "(name LIKE ? OR description LIKE ? OR json_array_contains(provides, ?))"
91
	args := []any{"%" + opts.Query + "%", "%" + opts.Query + "%", opts.Query}
92

93
	if opts.Filter != FilterNone {
94
		switch opts.Filter {
95
		case FilterInRepo:
96
			query += " AND repository = ?"
97
		case FilterSupportsArch:
98
			query += " AND json_array_contains(architectures, ?)"
99
		}
100
		args = append(args, opts.FilterValue)
101
	}
102

103
	if opts.SortBy != SortByNone {
104
		switch opts.SortBy {
105
		case SortByName:
106
			query += " ORDER BY name"
107
		case SortByRepo:
108
			query += " ORDER BY repository"
109
		case SortByVersion:
110
			query += " ORDER BY version"
111
		}
112
	}
113

114
	if opts.Limit != 0 {
115
		query += " LIMIT " + strconv.FormatInt(opts.Limit, 10)
116
	}
117

118
	result, err := db.GetPkgs(ctx, query, args...)
119
	if err != nil {
120
		return nil, err
121
	}
122

123
	var out []Package
124
	for result.Next() {
125
		pkg := db.Package{}
126
		err = result.StructScan(&pkg)
127
		if err != nil {
128
			return nil, err
129
		}
130
		out = append(out, convertPkg(pkg))
131
	}
132

133
	return out, err
134
}
135

136
// GetPkg gets a single package from the database and returns it.
137
func GetPkg(ctx context.Context, repo, name string) (Package, error) {
138
	pkg, err := db.GetPkg(ctx, "name = ? AND repository = ?", name, repo)
139
	return convertPkg(*pkg), err
140
}
141

142
var (
143
	// ErrInvalidArgument is an error returned by GetScript when one of its arguments
144
	// contain invalid characters
145
	ErrInvalidArgument = errors.New("name and repository must not contain . or /")
146

147
	// ErrScriptNotFound is returned by GetScript if it can't find the script requested
148
	// by the user.
149
	ErrScriptNotFound = errors.New("requested script not found")
150
)
151

152
// GetScript returns a reader containing the build script for a given package.
153
func GetScript(ctx context.Context, repo, name string) (io.ReadCloser, error) {
154
	if strings.Contains(name, "./") || strings.ContainsAny(repo, "./") {
155
		return nil, ErrInvalidArgument
156
	}
157

158
	scriptPath := filepath.Join(config.GetPaths(ctx).RepoDir, repo, name, "alr.sh")
159
	fl, err := os.Open(scriptPath)
160
	if errors.Is(err, fs.ErrNotExist) {
161
		return nil, ErrScriptNotFound
162
	} else if err != nil {
163
		return nil, err
164
	}
165

166
	return fl, nil
167
}
168

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.