232 lines
7.6 KiB
Go
232 lines
7.6 KiB
Go
package main
|
||
|
||
import (
|
||
"encoding/json"
|
||
"fmt"
|
||
"os"
|
||
"path/filepath"
|
||
"regexp"
|
||
"strings"
|
||
|
||
"github.com/pelletier/go-toml/v2"
|
||
"github.com/spf13/pflag"
|
||
"gitea.plemya-x.ru/Plemya-x/ALR-updater/internal/config"
|
||
"gitea.plemya-x.ru/Plemya-x/ALR-updater/internal/generator"
|
||
)
|
||
|
||
type AnalysisResult struct {
|
||
PackageName string `json:"package_name"`
|
||
Version string `json:"version"`
|
||
GitHubRepo string `json:"github_repo,omitempty"`
|
||
Sources []string `json:"sources,omitempty"`
|
||
Description string `json:"description,omitempty"`
|
||
Homepage string `json:"homepage,omitempty"`
|
||
PackageType string `json:"package_type"`
|
||
HasPlugin bool `json:"has_plugin"`
|
||
PluginGenerated bool `json:"can_generate_plugin"`
|
||
}
|
||
|
||
func main() {
|
||
configPath := pflag.StringP("config", "c", "/etc/alr-updater/config.toml", "Path to config file")
|
||
pluginDir := pflag.StringP("plugin-dir", "p", "/etc/alr-updater/plugins", "Path to plugin directory")
|
||
repoName := pflag.StringP("repo", "r", "alr-repo", "Repository name to analyze")
|
||
outputFormat := pflag.StringP("format", "f", "table", "Output format: table, json")
|
||
generateMissing := pflag.BoolP("generate", "g", false, "Generate missing plugins")
|
||
pflag.Parse()
|
||
|
||
// Загружаем конфигурацию
|
||
cfg := &config.Config{}
|
||
fl, err := os.Open(*configPath)
|
||
if err != nil {
|
||
fmt.Printf("Error opening config file: %v\n", err)
|
||
os.Exit(1)
|
||
}
|
||
defer fl.Close()
|
||
|
||
err = toml.NewDecoder(fl).Decode(cfg)
|
||
if err != nil {
|
||
fmt.Printf("Error decoding config file: %v\n", err)
|
||
os.Exit(1)
|
||
}
|
||
|
||
// Создаем генератор плагинов
|
||
gen, err := generator.NewPluginGenerator(cfg, *pluginDir)
|
||
if err != nil {
|
||
fmt.Printf("Error creating plugin generator: %v\n", err)
|
||
os.Exit(1)
|
||
}
|
||
|
||
// Сканируем репозиторий
|
||
packages, err := gen.ScanRepository(*repoName)
|
||
if err != nil {
|
||
fmt.Printf("Error scanning repository: %v\n", err)
|
||
os.Exit(1)
|
||
}
|
||
|
||
// Получаем список существующих плагинов
|
||
existingPlugins := make(map[string]bool)
|
||
pluginFiles, err := filepath.Glob(filepath.Join(*pluginDir, "*.star"))
|
||
if err == nil {
|
||
for _, pluginFile := range pluginFiles {
|
||
pluginName := strings.TrimSuffix(filepath.Base(pluginFile), ".star")
|
||
existingPlugins[pluginName] = true
|
||
}
|
||
}
|
||
|
||
// Подготавливаем результаты анализа
|
||
var results []AnalysisResult
|
||
var canGenerate []generator.DetectedPackage
|
||
|
||
for _, pkg := range packages {
|
||
result := AnalysisResult{
|
||
PackageName: pkg.Name,
|
||
Version: pkg.Version,
|
||
GitHubRepo: pkg.GitHubRepo,
|
||
Sources: pkg.Sources,
|
||
Description: pkg.Description,
|
||
Homepage: pkg.Homepage,
|
||
PackageType: pkg.PackageType,
|
||
HasPlugin: existingPlugins[pkg.Name],
|
||
PluginGenerated: pkg.GitHubRepo != "" && pkg.PackageType == "github_release",
|
||
}
|
||
results = append(results, result)
|
||
|
||
if !result.HasPlugin && result.PluginGenerated {
|
||
canGenerate = append(canGenerate, pkg)
|
||
}
|
||
}
|
||
|
||
// Добавляем пакеты с существующими плагинами
|
||
repoPath := filepath.Join(cfg.ReposBaseDir, *repoName)
|
||
err = filepath.Walk(repoPath, func(path string, info os.FileInfo, err error) error {
|
||
if err != nil || info.Name() != "alr.sh" {
|
||
return err
|
||
}
|
||
|
||
packageName := filepath.Base(filepath.Dir(path))
|
||
if existingPlugins[packageName] {
|
||
// Проверяем, есть ли уже в результатах
|
||
found := false
|
||
for _, r := range results {
|
||
if r.PackageName == packageName {
|
||
found = true
|
||
break
|
||
}
|
||
}
|
||
|
||
if !found {
|
||
// Добавляем пакет с существующим плагином
|
||
pkgInfo := analyzePackageFile(path)
|
||
result := AnalysisResult{
|
||
PackageName: packageName,
|
||
Version: pkgInfo.Version,
|
||
Sources: pkgInfo.Sources,
|
||
Description: pkgInfo.Description,
|
||
Homepage: pkgInfo.Homepage,
|
||
PackageType: "has_plugin",
|
||
HasPlugin: true,
|
||
}
|
||
results = append(results, result)
|
||
}
|
||
}
|
||
return nil
|
||
})
|
||
|
||
// Выводим результаты
|
||
if *outputFormat == "json" {
|
||
output, _ := json.MarshalIndent(results, "", " ")
|
||
fmt.Println(string(output))
|
||
} else {
|
||
printTable(results, canGenerate)
|
||
}
|
||
|
||
// Генерируем недостающие плагины
|
||
if *generateMissing {
|
||
fmt.Printf("\n🚀 Generating %d missing plugins...\n", len(canGenerate))
|
||
for _, pkg := range canGenerate {
|
||
err := gen.GeneratePlugin(pkg, *repoName)
|
||
if err != nil {
|
||
fmt.Printf("❌ Error generating plugin for %s: %v\n", pkg.Name, err)
|
||
}
|
||
}
|
||
fmt.Printf("✅ Plugin generation completed!\n")
|
||
}
|
||
}
|
||
|
||
func analyzePackageFile(alrFile string) generator.PackageInfo {
|
||
content, err := os.ReadFile(alrFile)
|
||
if err != nil {
|
||
return generator.PackageInfo{Name: filepath.Base(filepath.Dir(alrFile))}
|
||
}
|
||
|
||
info := generator.PackageInfo{
|
||
Name: filepath.Base(filepath.Dir(alrFile)),
|
||
}
|
||
|
||
lines := strings.Split(string(content), "\n")
|
||
for _, line := range lines {
|
||
line = strings.TrimSpace(line)
|
||
|
||
if strings.HasPrefix(line, "version=") {
|
||
versionMatch := regexp.MustCompile(`version=['"]?([^'"]+)['"]?`).FindStringSubmatch(line)
|
||
if len(versionMatch) > 1 {
|
||
info.Version = versionMatch[1]
|
||
}
|
||
}
|
||
|
||
if strings.Contains(line, "github.com") || strings.Contains(line, "https://") {
|
||
urlMatch := regexp.MustCompile(`https://[^\s"']+`).FindAllString(line, -1)
|
||
info.Sources = append(info.Sources, urlMatch...)
|
||
}
|
||
|
||
if strings.HasPrefix(line, "desc=") {
|
||
descMatch := regexp.MustCompile(`desc=['"]?([^'"]+)['"]?`).FindStringSubmatch(line)
|
||
if len(descMatch) > 1 {
|
||
info.Description = descMatch[1]
|
||
}
|
||
}
|
||
}
|
||
|
||
return info
|
||
}
|
||
|
||
func printTable(results []AnalysisResult, canGenerate []generator.DetectedPackage) {
|
||
fmt.Printf("📊 Анализ репозитория\n")
|
||
fmt.Printf("═══════════════════════════════════════════════════════════════════════════════════\n")
|
||
|
||
withPlugins := 0
|
||
withoutPlugins := 0
|
||
canGenerateCount := len(canGenerate)
|
||
|
||
for _, r := range results {
|
||
if r.HasPlugin {
|
||
withPlugins++
|
||
} else {
|
||
withoutPlugins++
|
||
}
|
||
}
|
||
|
||
fmt.Printf("📦 Всего пакетов: %d\n", len(results))
|
||
fmt.Printf("✅ С плагинами: %d\n", withPlugins)
|
||
fmt.Printf("❌ Без плагинов: %d\n", withoutPlugins)
|
||
fmt.Printf("🤖 Можно сгенерировать: %d\n", canGenerateCount)
|
||
|
||
if canGenerateCount > 0 {
|
||
fmt.Printf("\n🎯 Пакеты для автогенерации:\n")
|
||
fmt.Printf("─────────────────────────────────────────────────────────────────────────────────\n")
|
||
for _, pkg := range canGenerate {
|
||
fmt.Printf("📦 %-25s │ %s\n", pkg.Name, pkg.GitHubRepo)
|
||
}
|
||
fmt.Printf("\n💡 Запустите с флагом --generate для создания плагинов\n")
|
||
}
|
||
|
||
if withoutPlugins > canGenerateCount {
|
||
fmt.Printf("\n⚠️ Пакеты требующие ручной настройки:\n")
|
||
fmt.Printf("─────────────────────────────────────────────────────────────────────────────────\n")
|
||
for _, r := range results {
|
||
if !r.HasPlugin && !r.PluginGenerated {
|
||
fmt.Printf("📦 %-25s │ %s\n", r.PackageName, r.PackageType)
|
||
}
|
||
}
|
||
}
|
||
} |