forked from Plemya-x/ALR
		
	feat: add search command
This commit is contained in:
		| @@ -11,7 +11,7 @@ | |||||||
|     <g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11"> |     <g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11"> | ||||||
|         <text x="33.5" y="15" fill="#010101" fill-opacity=".3">coverage</text> |         <text x="33.5" y="15" fill="#010101" fill-opacity=".3">coverage</text> | ||||||
|         <text x="33.5" y="14">coverage</text> |         <text x="33.5" y="14">coverage</text> | ||||||
|         <text x="86" y="15" fill="#010101" fill-opacity=".3">20.8%</text> |         <text x="86" y="15" fill="#010101" fill-opacity=".3">20.5%</text> | ||||||
|         <text x="86" y="14">20.8%</text> |         <text x="86" y="14">20.5%</text> | ||||||
|     </g> |     </g> | ||||||
| </svg> | </svg> | ||||||
|   | |||||||
| Before Width: | Height: | Size: 926 B After Width: | Height: | Size: 926 B | 
| @@ -299,13 +299,13 @@ msgstr "" | |||||||
| msgid "Enable interactive questions and prompts" | msgid "Enable interactive questions and prompts" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: main.go:90 | #: main.go:91 | ||||||
| msgid "" | msgid "" | ||||||
| "Running ALR as root is forbidden as it may cause catastrophic damage to your " | "Running ALR as root is forbidden as it may cause catastrophic damage to your " | ||||||
| "system" | "system" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: main.go:124 | #: main.go:125 | ||||||
| msgid "Error while running app" | msgid "Error while running app" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| @@ -457,6 +457,46 @@ msgstr "" | |||||||
| msgid "Pull all repositories that have changed" | msgid "Pull all repositories that have changed" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
|  | #: search.go:36 | ||||||
|  | msgid "Search packages" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: search.go:42 | ||||||
|  | msgid "Search by name" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: search.go:47 | ||||||
|  | msgid "Search by description" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: search.go:52 | ||||||
|  | msgid "Search by repository" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: search.go:57 | ||||||
|  | msgid "Search by provides" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: search.go:62 | ||||||
|  | msgid "Format output using a Go template" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: search.go:94 | ||||||
|  | msgid "At least one search parameter is required" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: search.go:100 | ||||||
|  | msgid "Error db search" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: search.go:109 | ||||||
|  | msgid "Error parsing format template" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: search.go:124 | ||||||
|  | msgid "Error executing template" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: upgrade.go:47 | #: upgrade.go:47 | ||||||
| msgid "Upgrade all installed packages" | msgid "Upgrade all installed packages" | ||||||
| msgstr "" | msgstr "" | ||||||
|   | |||||||
| @@ -312,7 +312,7 @@ msgstr "Аргументы, которые будут переданы мене | |||||||
| msgid "Enable interactive questions and prompts" | msgid "Enable interactive questions and prompts" | ||||||
| msgstr "Включение интерактивных вопросов и запросов" | msgstr "Включение интерактивных вопросов и запросов" | ||||||
|  |  | ||||||
| #: main.go:90 | #: main.go:91 | ||||||
| msgid "" | msgid "" | ||||||
| "Running ALR as root is forbidden as it may cause catastrophic damage to your " | "Running ALR as root is forbidden as it may cause catastrophic damage to your " | ||||||
| "system" | "system" | ||||||
| @@ -320,7 +320,7 @@ msgstr "" | |||||||
| "Запуск ALR от имени root запрещён, так как это может привести к " | "Запуск ALR от имени root запрещён, так как это может привести к " | ||||||
| "катастрофическому повреждению вашей системы" | "катастрофическому повреждению вашей системы" | ||||||
|  |  | ||||||
| #: main.go:124 | #: main.go:125 | ||||||
| msgid "Error while running app" | msgid "Error while running app" | ||||||
| msgstr "Ошибка при запуске приложения" | msgstr "Ошибка при запуске приложения" | ||||||
|  |  | ||||||
| @@ -479,6 +479,49 @@ msgstr "Ошибка при удалении пакетов из базы дан | |||||||
| msgid "Pull all repositories that have changed" | msgid "Pull all repositories that have changed" | ||||||
| msgstr "Скачать все изменённые репозитории" | msgstr "Скачать все изменённые репозитории" | ||||||
|  |  | ||||||
|  | #: search.go:36 | ||||||
|  | msgid "Search packages" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: search.go:42 | ||||||
|  | msgid "Search by name" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: search.go:47 | ||||||
|  | msgid "Search by description" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: search.go:52 | ||||||
|  | #, fuzzy | ||||||
|  | msgid "Search by repository" | ||||||
|  | msgstr "Добавить новый репозиторий" | ||||||
|  |  | ||||||
|  | #: search.go:57 | ||||||
|  | msgid "Search by provides" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: search.go:62 | ||||||
|  | msgid "Format output using a Go template" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: search.go:94 | ||||||
|  | msgid "At least one search parameter is required" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: search.go:100 | ||||||
|  | msgid "Error db search" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: search.go:109 | ||||||
|  | #, fuzzy | ||||||
|  | msgid "Error parsing format template" | ||||||
|  | msgstr "Ошибка при разборе файла выпуска операционной системы" | ||||||
|  |  | ||||||
|  | #: search.go:124 | ||||||
|  | #, fuzzy | ||||||
|  | msgid "Error executing template" | ||||||
|  | msgstr "Ошибка при получении пакетов" | ||||||
|  |  | ||||||
| #: upgrade.go:47 | #: upgrade.go:47 | ||||||
| msgid "Upgrade all installed packages" | msgid "Upgrade all installed packages" | ||||||
| msgstr "Обновить все установленные пакеты" | msgstr "Обновить все установленные пакеты" | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								main.go
									
									
									
									
									
								
							| @@ -81,6 +81,7 @@ func GetApp() *cli.App { | |||||||
| 			GenCmd(), | 			GenCmd(), | ||||||
| 			HelperCmd(), | 			HelperCmd(), | ||||||
| 			VersionCmd(), | 			VersionCmd(), | ||||||
|  | 			SearchCmd(), | ||||||
| 		}, | 		}, | ||||||
| 		Before: func(c *cli.Context) error { | 		Before: func(c *cli.Context) error { | ||||||
| 			ctx := c.Context | 			ctx := c.Context | ||||||
|   | |||||||
							
								
								
									
										136
									
								
								search.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								search.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,136 @@ | |||||||
|  | // ALR - Any Linux Repository | ||||||
|  | // Copyright (C) 2025 Евгений Храмов | ||||||
|  | // | ||||||
|  | // This program is free software: you can redistribute it and/or modify | ||||||
|  | // it under the terms of the GNU General Public License as published by | ||||||
|  | // the Free Software Foundation, either version 3 of the License, or | ||||||
|  | // (at your option) any later version. | ||||||
|  | // | ||||||
|  | // This program is distributed in the hope that it will be useful, | ||||||
|  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | // GNU General Public License for more details. | ||||||
|  | // | ||||||
|  | // You should have received a copy of the GNU General Public License | ||||||
|  | // along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  |  | ||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"log/slog" | ||||||
|  | 	"os" | ||||||
|  | 	"strings" | ||||||
|  | 	"text/template" | ||||||
|  |  | ||||||
|  | 	"github.com/leonelquinteros/gotext" | ||||||
|  | 	"github.com/urfave/cli/v2" | ||||||
|  |  | ||||||
|  | 	"gitea.plemya-x.ru/Plemya-x/ALR/internal/config" | ||||||
|  | 	database "gitea.plemya-x.ru/Plemya-x/ALR/internal/db" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func SearchCmd() *cli.Command { | ||||||
|  | 	return &cli.Command{ | ||||||
|  | 		Name:    "search", | ||||||
|  | 		Usage:   gotext.Get("Search packages"), | ||||||
|  | 		Aliases: []string{"s"}, | ||||||
|  | 		Flags: []cli.Flag{ | ||||||
|  | 			&cli.StringFlag{ | ||||||
|  | 				Name:    "name", | ||||||
|  | 				Aliases: []string{"n"}, | ||||||
|  | 				Usage:   gotext.Get("Search by name"), | ||||||
|  | 			}, | ||||||
|  | 			&cli.StringFlag{ | ||||||
|  | 				Name:    "description", | ||||||
|  | 				Aliases: []string{"d"}, | ||||||
|  | 				Usage:   gotext.Get("Search by description"), | ||||||
|  | 			}, | ||||||
|  | 			&cli.StringFlag{ | ||||||
|  | 				Name:    "repository", | ||||||
|  | 				Aliases: []string{"repo"}, | ||||||
|  | 				Usage:   gotext.Get("Search by repository"), | ||||||
|  | 			}, | ||||||
|  | 			&cli.StringFlag{ | ||||||
|  | 				Name:    "provides", | ||||||
|  | 				Aliases: []string{"p"}, | ||||||
|  | 				Usage:   gotext.Get("Search by provides"), | ||||||
|  | 			}, | ||||||
|  | 			&cli.StringFlag{ | ||||||
|  | 				Name:    "format", | ||||||
|  | 				Aliases: []string{"f"}, | ||||||
|  | 				Usage:   gotext.Get("Format output using a Go template"), | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		Action: func(c *cli.Context) error { | ||||||
|  | 			ctx := c.Context | ||||||
|  | 			cfg := config.New() | ||||||
|  | 			db := database.New(cfg) | ||||||
|  | 			err := db.Init(ctx) | ||||||
|  | 			defer db.Close() | ||||||
|  |  | ||||||
|  | 			if err != nil { | ||||||
|  | 				slog.Error(gotext.Get("Error db init"), "err", err) | ||||||
|  | 				os.Exit(1) | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			var conditions []string | ||||||
|  | 			if name := c.String("name"); name != "" { | ||||||
|  | 				conditions = append(conditions, fmt.Sprintf("name LIKE '%%%s%%'", name)) | ||||||
|  | 			} | ||||||
|  | 			if description := c.String("description"); description != "" { | ||||||
|  | 				conditions = append(conditions, fmt.Sprintf("description LIKE '%%%s%%'", description)) | ||||||
|  | 			} | ||||||
|  | 			if repo := c.String("repository"); repo != "" { | ||||||
|  | 				conditions = append(conditions, fmt.Sprintf("repository = '%s'", repo)) | ||||||
|  | 			} | ||||||
|  | 			if provides := c.String("provides"); provides != "" { | ||||||
|  | 				conditions = append(conditions, fmt.Sprintf("EXISTS (SELECT 1 FROM json_each(provides) WHERE value = '%s')", provides)) | ||||||
|  | 			} | ||||||
|  | 			query := "" | ||||||
|  | 			if len(conditions) > 0 { | ||||||
|  | 				query = strings.Join(conditions, " AND ") | ||||||
|  | 			} else { | ||||||
|  | 				slog.Error(gotext.Get("At least one search parameter is required")) | ||||||
|  | 				os.Exit(1) | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			result, err := db.GetPkgs(ctx, query) | ||||||
|  | 			if err != nil { | ||||||
|  | 				slog.Error(gotext.Get("Error db search"), "err", err) | ||||||
|  | 				os.Exit(1) | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			format := c.String("format") | ||||||
|  | 			var tmpl *template.Template | ||||||
|  | 			if format != "" { | ||||||
|  | 				tmpl, err = template.New("format").Parse(format) | ||||||
|  | 				if err != nil { | ||||||
|  | 					slog.Error(gotext.Get("Error parsing format template"), "err", err) | ||||||
|  | 					os.Exit(1) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			for result.Next() { | ||||||
|  | 				var dbPkg database.Package | ||||||
|  | 				err = result.StructScan(&dbPkg) | ||||||
|  | 				if err != nil { | ||||||
|  | 					os.Exit(1) | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				if tmpl != nil { | ||||||
|  | 					err = tmpl.Execute(os.Stdout, dbPkg) | ||||||
|  | 					if err != nil { | ||||||
|  | 						slog.Error(gotext.Get("Error executing template"), "err", err) | ||||||
|  | 						os.Exit(1) | ||||||
|  | 					} | ||||||
|  | 					fmt.Println() | ||||||
|  | 				} else { | ||||||
|  | 					fmt.Println(dbPkg.Name) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			return nil | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user