2019-06-04 19:25:17 +00:00
|
|
|
// Copyright © 2019 Ettore Di Giacinto <mudler@gentoo.org>
|
2018-09-21 21:29:50 +00:00
|
|
|
//
|
|
|
|
// 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 2 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 pkg
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/base64"
|
|
|
|
"encoding/json"
|
2019-06-04 19:25:17 +00:00
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"hash/crc32"
|
2018-09-21 21:29:50 +00:00
|
|
|
|
|
|
|
"github.com/crillab/gophersat/bf"
|
|
|
|
|
|
|
|
"github.com/jinzhu/copier"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Package interface {
|
|
|
|
Encode() (string, error)
|
|
|
|
SetState(state State) Package
|
2019-06-03 21:06:53 +00:00
|
|
|
BuildFormula() ([]bf.Formula, error)
|
2018-09-21 21:29:50 +00:00
|
|
|
IsFlagged(bool) Package
|
2019-06-04 19:25:17 +00:00
|
|
|
Flagged() bool
|
2019-06-05 15:51:24 +00:00
|
|
|
GetFingerPrint() string
|
2019-06-04 19:25:17 +00:00
|
|
|
Requires([]*DefaultPackage) Package
|
|
|
|
Conflicts([]*DefaultPackage) Package
|
2019-06-05 15:51:24 +00:00
|
|
|
|
|
|
|
GetRequires() []*DefaultPackage
|
|
|
|
GetConflicts() []*DefaultPackage
|
2018-09-21 21:29:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type DefaultPackage struct {
|
|
|
|
Name string
|
|
|
|
Version string
|
|
|
|
UseFlags []string
|
|
|
|
State State
|
2019-06-04 19:25:17 +00:00
|
|
|
PackageRequires []*DefaultPackage
|
|
|
|
PackageConflicts []*DefaultPackage
|
2018-09-21 21:29:50 +00:00
|
|
|
IsSet bool
|
|
|
|
}
|
|
|
|
|
|
|
|
type PackageUse []string
|
|
|
|
type State string
|
|
|
|
|
2019-06-04 19:25:17 +00:00
|
|
|
func NewPackage(name, version string, requires []*DefaultPackage, conflicts []*DefaultPackage) *DefaultPackage {
|
2018-09-21 21:29:50 +00:00
|
|
|
return &DefaultPackage{Name: name, Version: version, PackageRequires: requires, PackageConflicts: conflicts}
|
|
|
|
}
|
2019-06-05 15:51:24 +00:00
|
|
|
func (p *DefaultPackage) GetFingerPrint() string {
|
|
|
|
return p.Name
|
|
|
|
}
|
2018-09-21 21:29:50 +00:00
|
|
|
|
|
|
|
func (p *DefaultPackage) AddUse(use string) {
|
|
|
|
for _, v := range p.UseFlags {
|
|
|
|
if v == use {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
p.UseFlags = append(p.UseFlags, use)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *DefaultPackage) RemoveUse(use string) {
|
|
|
|
|
|
|
|
for i := len(p.UseFlags) - 1; i >= 0; i-- {
|
|
|
|
if p.UseFlags[i] == use {
|
|
|
|
p.UseFlags = append(p.UseFlags[:i], p.UseFlags[i+1:]...)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *DefaultPackage) Encode() (string, error) {
|
|
|
|
res, err := json.Marshal(p)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
2019-06-04 19:25:17 +00:00
|
|
|
enc := base64.StdEncoding.EncodeToString(res)
|
|
|
|
crc32q := crc32.MakeTable(0xD5828281)
|
|
|
|
ID := fmt.Sprintf("%08x\n", crc32.Checksum([]byte(enc), crc32q))
|
|
|
|
Database[ID] = base64.StdEncoding.EncodeToString(res)
|
|
|
|
return ID, nil
|
2018-09-21 21:29:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (p *DefaultPackage) WithState(state State) Package {
|
|
|
|
return p.Clone().SetState(state)
|
|
|
|
}
|
|
|
|
func (p *DefaultPackage) IsFlagged(b bool) Package {
|
|
|
|
p.IsSet = b
|
|
|
|
return p
|
|
|
|
}
|
2019-06-04 19:25:17 +00:00
|
|
|
func (p *DefaultPackage) Flagged() bool {
|
|
|
|
return p.IsSet
|
|
|
|
}
|
2018-09-21 21:29:50 +00:00
|
|
|
|
|
|
|
func (p *DefaultPackage) SetState(state State) Package {
|
|
|
|
p.State = state
|
|
|
|
return p
|
|
|
|
}
|
2019-06-05 15:51:24 +00:00
|
|
|
func (p *DefaultPackage) GetRequires() []*DefaultPackage {
|
|
|
|
return p.PackageRequires
|
|
|
|
}
|
|
|
|
func (p *DefaultPackage) GetConflicts() []*DefaultPackage {
|
|
|
|
return p.PackageConflicts
|
|
|
|
}
|
2019-06-04 19:25:17 +00:00
|
|
|
func (p *DefaultPackage) Requires(req []*DefaultPackage) Package {
|
2018-09-21 21:29:50 +00:00
|
|
|
p.PackageRequires = req
|
|
|
|
return p
|
|
|
|
}
|
2019-06-04 19:25:17 +00:00
|
|
|
func (p *DefaultPackage) Conflicts(req []*DefaultPackage) Package {
|
2018-09-21 21:29:50 +00:00
|
|
|
p.PackageConflicts = req
|
|
|
|
return p
|
|
|
|
}
|
|
|
|
func (p *DefaultPackage) Clone() Package {
|
|
|
|
new := &DefaultPackage{}
|
|
|
|
copier.Copy(&new, &p)
|
|
|
|
return new
|
|
|
|
}
|
|
|
|
|
2019-06-04 19:25:17 +00:00
|
|
|
func DecodePackage(ID string) (Package, error) {
|
|
|
|
|
|
|
|
pa, ok := Database[ID]
|
|
|
|
if !ok {
|
|
|
|
return nil, errors.New("No package found with that id")
|
|
|
|
}
|
|
|
|
|
2018-09-21 21:29:50 +00:00
|
|
|
enc, err := base64.StdEncoding.DecodeString(pa)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
p := &DefaultPackage{}
|
|
|
|
|
|
|
|
if err := json.Unmarshal(enc, &p); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return p, nil
|
|
|
|
}
|
|
|
|
|
2019-06-03 21:06:53 +00:00
|
|
|
func (p *DefaultPackage) BuildFormula() ([]bf.Formula, error) {
|
2019-06-04 19:25:17 +00:00
|
|
|
encodedA, err := p.IsFlagged(true).Encode()
|
2018-09-21 21:29:50 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
A := bf.Var(encodedA)
|
|
|
|
|
2019-06-04 19:57:13 +00:00
|
|
|
var formulas []bf.Formula
|
2018-09-21 21:29:50 +00:00
|
|
|
|
|
|
|
for _, required := range p.PackageRequires {
|
2019-06-04 19:25:17 +00:00
|
|
|
encodedB, err := required.IsFlagged(true).Encode()
|
2018-09-21 21:29:50 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
B := bf.Var(encodedB)
|
2019-06-04 19:25:17 +00:00
|
|
|
formulas = append(formulas, bf.Or(bf.Not(A), B))
|
2018-09-21 21:29:50 +00:00
|
|
|
|
2019-06-03 21:23:02 +00:00
|
|
|
f, err := required.BuildFormula()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
formulas = append(formulas, f...)
|
|
|
|
|
2018-09-21 21:29:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, required := range p.PackageConflicts {
|
2019-06-04 19:25:17 +00:00
|
|
|
encodedB, err := required.IsFlagged(true).Encode()
|
2018-09-21 21:29:50 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
B := bf.Var(encodedB)
|
2019-06-04 19:25:17 +00:00
|
|
|
formulas = append(formulas, bf.Or(bf.Not(A),
|
|
|
|
bf.Not(B)))
|
2019-06-03 21:23:02 +00:00
|
|
|
|
|
|
|
f, err := required.BuildFormula()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
formulas = append(formulas, f...)
|
2018-09-21 21:29:50 +00:00
|
|
|
}
|
2019-06-04 19:25:17 +00:00
|
|
|
return formulas, nil
|
2018-09-21 21:29:50 +00:00
|
|
|
}
|