Files
ALR/pkg/depver/depver.go
Евгений Храмов 3d9f4a0985 Улучшения обработки зависимостей и фильтрации установленных пакетов
- Добавлена поддержка версионных ограничений при установке пакетов
- Улучшена логика фильтрации уже установленных пакетов
- Добавлен метод GetInstalledVersion для всех менеджеров пакетов
- Активированы тесты для систем archlinux, alpine, opensuse-leap
- Улучшена обработка переменных в скриптах

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-01-16 01:01:01 +03:00

138 lines
3.9 KiB
Go

// ALR - Any Linux Repository
// Copyright (C) 2025 The ALR Authors
//
// 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 depver provides parsing and comparison of versioned dependencies
// in PKGBUILD-style format (e.g., "gcc>=5.0", "openssl>=1.1.0").
package depver
import (
"strings"
"gitea.plemya-x.ru/xpamych/vercmp"
)
// Operator represents a version comparison operator.
type Operator string
const (
OpNone Operator = "" // No version constraint
OpEq Operator = "=" // Equal to
OpGt Operator = ">" // Greater than
OpGe Operator = ">=" // Greater than or equal to
OpLt Operator = "<" // Less than
OpLe Operator = "<=" // Less than or equal to
)
// Dependency represents a package dependency with optional version constraint.
type Dependency struct {
Name string // Package name (e.g., "gcc")
Operator Operator // Comparison operator (e.g., OpGe for ">=")
Version string // Version string (e.g., "5.0")
}
// operators lists all supported operators in order of decreasing length
// (to ensure ">=" is matched before ">").
var operators = []Operator{OpGe, OpLe, OpGt, OpLt, OpEq}
// Parse parses a dependency string in PKGBUILD format.
// Examples:
// - "gcc>=5.0" -> Dependency{Name: "gcc", Operator: OpGe, Version: "5.0"}
// - "openssl" -> Dependency{Name: "openssl", Operator: OpNone, Version: ""}
// - "cmake>=3.10" -> Dependency{Name: "cmake", Operator: OpGe, Version: "3.10"}
func Parse(dep string) Dependency {
dep = strings.TrimSpace(dep)
if dep == "" {
return Dependency{}
}
// Try each operator (longer ones first)
for _, op := range operators {
if idx := strings.Index(dep, string(op)); idx > 0 {
return Dependency{
Name: strings.TrimSpace(dep[:idx]),
Operator: op,
Version: strings.TrimSpace(dep[idx+len(op):]),
}
}
}
// No operator found - just a package name
return Dependency{
Name: dep,
Operator: OpNone,
Version: "",
}
}
// ParseMultiple parses multiple dependency strings.
func ParseMultiple(deps []string) []Dependency {
result := make([]Dependency, 0, len(deps))
for _, dep := range deps {
if dep != "" {
result = append(result, Parse(dep))
}
}
return result
}
// String returns the dependency in PKGBUILD format.
func (d Dependency) String() string {
if d.Operator == OpNone || d.Version == "" {
return d.Name
}
return d.Name + string(d.Operator) + d.Version
}
// Satisfies checks if the given version satisfies the dependency constraint.
// Returns true if:
// - The dependency has no version constraint (OpNone)
// - The installed version satisfies the operator/version requirement
func (d Dependency) Satisfies(installedVersion string) bool {
if d.Operator == OpNone || d.Version == "" {
return true
}
if installedVersion == "" {
return false
}
// vercmp.Compare returns:
// -1 if installedVersion < d.Version
// 0 if installedVersion == d.Version
// 1 if installedVersion > d.Version
cmp := vercmp.Compare(installedVersion, d.Version)
switch d.Operator {
case OpEq:
return cmp == 0
case OpGt:
return cmp > 0
case OpGe:
return cmp >= 0
case OpLt:
return cmp < 0
case OpLe:
return cmp <= 0
default:
return true
}
}
// HasVersionConstraint returns true if the dependency has a version constraint.
func (d Dependency) HasVersionConstraint() bool {
return d.Operator != OpNone && d.Version != ""
}