155 lines
3.2 KiB
Go
155 lines
3.2 KiB
Go
package rpmpack
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
type rpmSense uint32
|
|
|
|
// SenseAny (0) specifies no specific version compare
|
|
// SenseLess (2) specifies less then the specified version
|
|
// SenseGreater (4) specifies greater then the specified version
|
|
// SenseEqual (8) specifies equal to the specified version
|
|
const (
|
|
SenseAny rpmSense = 0
|
|
SenseLess = 1 << iota
|
|
SenseGreater
|
|
SenseEqual
|
|
)
|
|
|
|
var relationMatch = regexp.MustCompile(`([^=<>\s]*)\s*((?:=|>|<)*)\s*(.*)?`)
|
|
|
|
// Relation is the structure of rpm sense relationships
|
|
type Relation struct {
|
|
Name string
|
|
Version string
|
|
Sense rpmSense
|
|
}
|
|
|
|
// String return the string representation of the Relation
|
|
func (r *Relation) String() string {
|
|
return fmt.Sprintf("%s%v%s", r.Name, r.Sense, r.Version)
|
|
}
|
|
|
|
// Equal compare the equality of two relations
|
|
func (r *Relation) Equal(o *Relation) bool {
|
|
return r.Name == o.Name && r.Version == o.Version && r.Sense == o.Sense
|
|
}
|
|
|
|
// Relations is a slice of Relation pointers
|
|
type Relations []*Relation
|
|
|
|
// String return the string representation of the Relations
|
|
func (r *Relations) String() string {
|
|
var val []string
|
|
for _, rel := range *r {
|
|
val = append(val, rel.String())
|
|
}
|
|
return strings.Join(val, ",")
|
|
}
|
|
|
|
// Set parse a string into a Relation and append it to the Relations slice if it is missing
|
|
// this is used by the flag package
|
|
func (r *Relations) Set(value string) error {
|
|
relation, err := NewRelation(value)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
r.addIfMissing(relation)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *Relations) addIfMissing(value *Relation) {
|
|
for _, relation := range *r {
|
|
if relation.Equal(value) {
|
|
return
|
|
}
|
|
}
|
|
|
|
*r = append(*r, value)
|
|
}
|
|
|
|
// AddToIndex add the relations to the specified category on the index
|
|
func (r *Relations) AddToIndex(h *index, nameTag, versionTag, flagsTag int) error {
|
|
var (
|
|
num = len(*r)
|
|
names = make([]string, num)
|
|
versions = make([]string, num)
|
|
flags = make([]uint32, num)
|
|
)
|
|
|
|
if num == 0 {
|
|
return nil
|
|
}
|
|
|
|
for idx, relation := range *r {
|
|
names[idx] = relation.Name
|
|
versions[idx] = relation.Version
|
|
flags[idx] = uint32(relation.Sense)
|
|
}
|
|
|
|
h.Add(nameTag, EntryStringSlice(names))
|
|
h.Add(versionTag, EntryStringSlice(versions))
|
|
h.Add(flagsTag, EntryUint32(flags))
|
|
|
|
return nil
|
|
}
|
|
|
|
// NewRelation parse a string into a Relation
|
|
func NewRelation(related string) (*Relation, error) {
|
|
var (
|
|
err error
|
|
sense rpmSense
|
|
)
|
|
parts := relationMatch.FindStringSubmatch(related)
|
|
if sense, err = parseSense(parts[2]); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &Relation{
|
|
Name: parts[1],
|
|
Version: parts[3],
|
|
Sense: sense,
|
|
}, nil
|
|
}
|
|
|
|
var stringToSense = map[string]rpmSense{
|
|
"": SenseAny,
|
|
"<": SenseLess,
|
|
">": SenseGreater,
|
|
"=": SenseEqual,
|
|
"<=": SenseLess | SenseEqual,
|
|
">=": SenseGreater | SenseEqual,
|
|
}
|
|
|
|
// String return the string representation of the rpmSense
|
|
func (r rpmSense) String() string {
|
|
var (
|
|
val rpmSense
|
|
ret string
|
|
)
|
|
|
|
for ret, val = range stringToSense {
|
|
if r == val {
|
|
return ret
|
|
}
|
|
}
|
|
|
|
return "unknown"
|
|
}
|
|
|
|
func parseSense(sense string) (rpmSense, error) {
|
|
var (
|
|
ret rpmSense
|
|
ok bool
|
|
)
|
|
if ret, ok = stringToSense[sense]; !ok {
|
|
return SenseAny, fmt.Errorf("unknown sense value: %s", sense)
|
|
}
|
|
|
|
return ret, nil
|
|
}
|