Added pre-build dependency version check (#32)

Fixes #15.

Uses ALPM's `satisfies` to resolve dependencies and then compares resolved dependency from local sync database with svn2git's version.

Reviewed-on: https://git.harting.dev/anonfunc/ALHP.GO/pulls/32
Co-authored-by: Giovanni Harting <539@idlegandalf.com>
Co-committed-by: Giovanni Harting <539@idlegandalf.com>
This commit is contained in:
Giovanni Harting 2021-07-27 02:43:30 +02:00
parent 17b415f8f3
commit e28d85b10d
5 changed files with 639 additions and 412 deletions

View File

@ -19,10 +19,16 @@ march:
- x86-64-v3
blacklist:
- pacman
- tensorflow
- tensorflow-cuda
- gcc
packages:
- pacman
- tensorflow
- tensorflow-cuda
- gcc
repo:
- testing
- i686
- staging
- unstable
build:
worker: 4
@ -39,4 +45,4 @@ status:
unknown: "dark"
logging:
level: DEBUG
level: INFO

2
go.mod
View File

@ -5,11 +5,11 @@ go 1.16
require (
entgo.io/ent v0.8.0
github.com/Jguer/go-alpm/v2 v2.0.5
github.com/Morganamilo/go-pacmanconf v0.0.0-20210502114700-cff030e927a5
github.com/Morganamilo/go-srcinfo v1.0.0
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect
github.com/mattn/go-sqlite3 v1.14.6
github.com/sirupsen/logrus v1.8.1
github.com/wercker/journalhook v0.0.0-20180428041537-5d0a5ae867b3
github.com/yargevad/filepathx v1.0.0
gopkg.in/yaml.v2 v2.4.0
)

19
go.sum
View File

@ -19,6 +19,8 @@ github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20O
github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/Jguer/go-alpm/v2 v2.0.5 h1:1TZxkvCIfTOhjhxGy/Z1FNSeuY9DXBKF5qxUoj0IZ0A=
github.com/Jguer/go-alpm/v2 v2.0.5/go.mod h1:zU4iKCtNkDARfj5BrKJXYAQ5nIjtZbySfa0paboSmTQ=
github.com/Morganamilo/go-pacmanconf v0.0.0-20210502114700-cff030e927a5 h1:TMscPjkb1ThXN32LuFY5bEYIcXZx3YlwzhS1GxNpn/c=
github.com/Morganamilo/go-pacmanconf v0.0.0-20210502114700-cff030e927a5/go.mod h1:Hk55m330jNiwxRodIlMCvw5iEyoRUCIY64W1p9D+tHc=
github.com/Morganamilo/go-srcinfo v1.0.0 h1:Wh4nEF+HJWo+29hnxM18Q2hi+DUf0GejS13+Wg+dzmI=
github.com/Morganamilo/go-srcinfo v1.0.0/go.mod h1:MP6VGY1NNpVUmYIEgoM9acix95KQqIRyqQ0hCLsyYUY=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
@ -60,7 +62,6 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-openapi/inflect v0.19.0 h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4=
github.com/go-openapi/inflect v0.19.0/go.mod h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4=
github.com/go-sql-driver/mysql v1.5.1-0.20200311113236-681ffa848bae/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
@ -127,10 +128,6 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.1 h1:g39TucaRWyV3dwDO++eEc6qf8TVIQ/Da48WmqjZ3i7E=
github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@ -151,9 +148,7 @@ github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
@ -173,7 +168,6 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
@ -208,11 +202,9 @@ github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4k
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M=
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@ -263,7 +255,6 @@ golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -334,12 +325,10 @@ golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
@ -390,10 +379,6 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/sqlite v1.1.4 h1:PDzwYE+sI6De2+mxAneV9Xs11+ZyKV6oxD3wDGkaNvM=
gorm.io/driver/sqlite v1.1.4/go.mod h1:mJCeTFr7+crvS+TRnWc5Z3UvwxUN1BGBLMrf5LA9DYw=
gorm.io/gorm v1.20.7 h1:rMS4CL3pNmYq1V5/X+nHHjh1Dx6dnf27+Cai5zabo+M=
gorm.io/gorm v1.20.7/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

423
main.go
View File

@ -4,7 +4,6 @@ import (
"ALHP.go/ent"
"ALHP.go/ent/dbpackage"
"ALHP.go/ent/migrate"
"bufio"
"bytes"
"context"
"fmt"
@ -13,10 +12,8 @@ import (
_ "github.com/mattn/go-sqlite3"
log "github.com/sirupsen/logrus"
"github.com/wercker/journalhook"
"github.com/yargevad/filepathx"
"gopkg.in/yaml.v2"
"html/template"
"io"
"math/rand"
"os"
"os/exec"
@ -24,7 +21,6 @@ import (
"path/filepath"
"regexp"
"runtime"
"sort"
"strconv"
"strings"
"sync"
@ -39,19 +35,11 @@ const (
orgChrootName = "root"
)
const (
SKIPPED = iota
FAILED = iota
BUILD = iota
QUEUED = iota
BUILDING = iota
LATEST = iota
UNKNOWN = iota
)
var (
conf = Conf{}
repos []string
alpmHandle *alpm.Handle
alpmLock sync.RWMutex
reMarch = regexp.MustCompile(`(-march=)(.+?) `)
rePkgRel = regexp.MustCompile(`(?m)^pkgrel\s*=\s*(.+)$`)
rePkgFile = regexp.MustCompile(`^(.*)-.*-.*-(?:x86_64|any)\.pkg\.tar\.zst(?:\.sig)*$`)
@ -60,231 +48,6 @@ var (
dbLock sync.RWMutex
)
type BuildPackage struct {
Pkgbase string
Pkgbuild string
Srcinfo *srcinfo.Srcinfo
PkgFiles []string
Repo string
March string
FullRepo string
Version string
}
type BuildManager struct {
build chan *BuildPackage
parse chan *BuildPackage
repoPurge map[string]chan *BuildPackage
repoAdd map[string]chan *BuildPackage
exit bool
buildWG sync.WaitGroup
parseWG sync.WaitGroup
repoWG sync.WaitGroup
failedMutex sync.RWMutex
buildProcesses []*os.Process
buildProcMutex sync.RWMutex
}
type Conf struct {
Arch string
Repos, March, Blacklist []string
Svn2git map[string]string
Basedir struct {
Repo, Chroot, Makepkg, Upstream, Db string
}
Build struct {
Worker int
Makej int
}
Logging struct {
Level string
}
Status struct {
Class struct {
Skipped, Queued, Latest, Failed, Signing, Building, Unknown string
}
}
}
func check(e error) {
if e != nil {
panic(e)
}
}
func contains(s interface{}, str string) bool {
switch v := s.(type) {
case []string:
if i := find(v, str); i != -1 {
return true
}
case []srcinfo.ArchString:
var n []string
for _, as := range v {
n = append(n, as.Value)
}
if i := find(n, str); i != -1 {
return true
}
default:
return false
}
return false
}
func find(s []string, str string) int {
for i, v := range s {
if v == str {
return i
}
}
return -1
}
func copyFile(src, dst string) (int64, error) {
sourceFileStat, err := os.Stat(src)
if err != nil {
return 0, err
}
if !sourceFileStat.Mode().IsRegular() {
return 0, fmt.Errorf("%s is not a regular file", src)
}
source, err := os.Open(src)
if err != nil {
return 0, err
}
defer func(source *os.File) {
check(source.Close())
}(source)
destination, err := os.Create(dst)
if err != nil {
return 0, err
}
defer func(destination *os.File) {
check(destination.Close())
}(destination)
nBytes, err := io.Copy(destination, source)
return nBytes, err
}
//goland:noinspection SpellCheckingInspection
func setupMakepkg(march string) {
lMakepkg := filepath.Join(conf.Basedir.Makepkg, fmt.Sprintf("makepkg-%s.conf", march))
check(os.MkdirAll(conf.Basedir.Makepkg, os.ModePerm))
t, err := os.ReadFile(makepkgConf)
check(err)
makepkgStr := string(t)
makepkgStr = strings.ReplaceAll(makepkgStr, "-mtune=generic", "")
makepkgStr = strings.ReplaceAll(makepkgStr, "-O2", "-O3")
makepkgStr = strings.ReplaceAll(makepkgStr, " check ", " !check ")
makepkgStr = strings.ReplaceAll(makepkgStr, " color ", " !color ")
makepkgStr = strings.ReplaceAll(makepkgStr, "#MAKEFLAGS=\"-j2\"", "MAKEFLAGS=\"-j"+strconv.Itoa(conf.Build.Makej)+"\"")
makepkgStr = reMarch.ReplaceAllString(makepkgStr, "${1}"+march)
check(os.WriteFile(lMakepkg, []byte(makepkgStr), os.ModePerm))
}
func syncMarchs() {
files, err := os.ReadDir(conf.Basedir.Repo)
check(err)
var eRepos []string
for _, file := range files {
if file.Name() != "." && file.Name() != logDir && file.IsDir() {
eRepos = append(eRepos, file.Name())
}
}
for _, march := range conf.March {
setupMakepkg(march)
for _, repo := range conf.Repos {
tRepo := fmt.Sprintf("%s-%s", repo, march)
repos = append(repos, tRepo)
buildManager.repoAdd[tRepo] = make(chan *BuildPackage, conf.Build.Worker)
buildManager.repoPurge[tRepo] = make(chan *BuildPackage, 10000)
go buildManager.repoWorker(tRepo)
if _, err := os.Stat(filepath.Join(filepath.Join(conf.Basedir.Repo, tRepo, "os", conf.Arch))); os.IsNotExist(err) {
log.Debugf("Creating path %s", filepath.Join(conf.Basedir.Repo, tRepo, "os", conf.Arch))
check(os.MkdirAll(filepath.Join(conf.Basedir.Repo, tRepo, "os", conf.Arch), os.ModePerm))
}
if i := find(eRepos, tRepo); i != -1 {
eRepos = append(eRepos[:i], eRepos[i+1:]...)
}
}
}
log.Infof("Repos: %s", repos)
for _, repo := range eRepos {
log.Infof("Removing old repo %s", repo)
check(os.RemoveAll(filepath.Join(conf.Basedir.Repo, repo)))
}
}
func importKeys(pkg *BuildPackage) {
if pkg.Srcinfo.ValidPGPKeys != nil {
args := []string{"--keyserver", "keyserver.ubuntu.com", "--recv-keys"}
args = append(args, pkg.Srcinfo.ValidPGPKeys...)
cmd := exec.Command("gpg", args...)
res, err := cmd.CombinedOutput()
log.Debug(string(res))
if err != nil {
log.Warningf("Unable to import keys: %s", string(res))
}
}
}
func packages2string(pkgs []srcinfo.Package) []string {
var sPkgs []string
for _, p := range pkgs {
sPkgs = append(sPkgs, p.Pkgname)
}
return sPkgs
}
func increasePkgRel(pkg *BuildPackage) {
f, err := os.OpenFile(pkg.Pkgbuild, os.O_RDWR, os.ModePerm)
check(err)
defer func(f *os.File) {
check(f.Close())
}(f)
fStr, err := io.ReadAll(f)
check(err)
nStr := rePkgRel.ReplaceAllLiteralString(string(fStr), "pkgrel="+pkg.Srcinfo.Pkgrel+".1")
_, err = f.Seek(0, 0)
check(err)
check(f.Truncate(0))
_, err = f.WriteString(nStr)
check(err)
pkg.Version = pkg.Version + ".1"
}
func gitClean(pkg *BuildPackage) {
cmd := exec.Command("sudo", "git_clean.sh", filepath.Dir(pkg.Pkgbuild))
res, err := cmd.CombinedOutput()
if err != nil {
log.Warningf("git clean failed with %v:\n%s", err, res)
} else {
log.Debug(string(res))
}
}
func (b *BuildManager) buildWorker(id int) {
err := syscall.Setpriority(syscall.PRIO_PROCESS, 0, 18)
if err != nil {
@ -310,8 +73,17 @@ func (b *BuildManager) buildWorker(id int) {
dbPkg.Update().SetStatus(BUILDING).SaveX(context.Background())
dbLock.Unlock()
importKeys(pkg)
increasePkgRel(pkg)
err := importKeys(pkg)
if err != nil {
log.Warningf("[%s/%s] Failed to import pgp keys: %v", pkg.FullRepo, pkg.Pkgbase, err)
}
err = increasePkgRel(pkg)
if err != nil {
log.Errorf("[%s/%s] Failed to increase pkgrel: %v", pkg.FullRepo, pkg.Pkgbase, err)
b.buildWG.Done()
continue
}
pkg.PkgFiles = []string{}
cmd := exec.Command("sh", "-c",
@ -351,13 +123,8 @@ func (b *BuildManager) buildWorker(id int) {
f, err := os.OpenFile(filepath.Join(conf.Basedir.Repo, pkg.FullRepo+"_failed.txt"), os.O_WRONLY|os.O_APPEND|os.O_CREATE|os.O_SYNC, os.ModePerm)
check(err)
if pkg.Srcinfo.Epoch != "" {
_, err := f.WriteString(fmt.Sprintf("%s==%s:%s-%s\n", pkg.Pkgbase, pkg.Srcinfo.Epoch, pkg.Srcinfo.Pkgver, pkg.Srcinfo.Pkgrel))
check(err)
} else {
_, err := f.WriteString(fmt.Sprintf("%s==%s-%s\n", pkg.Pkgbase, pkg.Srcinfo.Pkgver, pkg.Srcinfo.Pkgrel))
check(err)
}
_, err = f.WriteString(fmt.Sprintf("%s==%s\n", pkg.Pkgbase, constructVersion(pkg.Srcinfo.Pkgver, pkg.Srcinfo.Pkgrel, pkg.Srcinfo.Epoch)))
check(err)
check(f.Close())
b.failedMutex.Unlock()
@ -430,17 +197,6 @@ func (b *BuildManager) buildWorker(id int) {
}
}
func getDbPackage(pkg *BuildPackage) *ent.DbPackage {
dbLock.Lock()
dbPkg, err := db.DbPackage.Query().Where(dbpackage.Pkgbase(pkg.Pkgbase)).Only(context.Background())
if err != nil {
dbPkg = db.DbPackage.Create().SetPkgbase(pkg.Pkgbase).SetMarch(pkg.March).SetPackages(packages2string(pkg.Srcinfo.Packages)).SetRepository(pkg.Repo).SaveX(context.Background())
}
dbLock.Unlock()
return dbPkg
}
func (b *BuildManager) parseWorker() {
for {
if b.exit {
@ -463,11 +219,7 @@ func (b *BuildManager) parseWorker() {
continue
}
pkg.Srcinfo = info
if pkg.Srcinfo.Epoch == "" {
pkg.Version = pkg.Srcinfo.Pkgver + "-" + pkg.Srcinfo.Pkgrel
} else {
pkg.Version = pkg.Srcinfo.Epoch + ":" + pkg.Srcinfo.Pkgver + "-" + pkg.Srcinfo.Pkgrel
}
pkg.Version = constructVersion(pkg.Srcinfo.Pkgver, pkg.Srcinfo.Pkgrel, pkg.Srcinfo.Epoch)
dbPkg := getDbPackage(pkg)
dbLock.Lock()
@ -481,7 +233,7 @@ func (b *BuildManager) parseWorker() {
dbPkg = dbPkg.Update().SetStatus(SKIPPED).SetSkipReason("arch = any").SaveX(context.Background())
dbLock.Unlock()
skipping = true
} else if contains(conf.Blacklist, info.Pkgbase) {
} else if contains(conf.Blacklist.Packages, info.Pkgbase) {
log.Debugf("Skipped %s: blacklisted package", info.Pkgbase)
dbLock.Lock()
dbPkg = dbPkg.Update().SetStatus(SKIPPED).SetSkipReason("blacklisted").SaveX(context.Background())
@ -527,114 +279,21 @@ func (b *BuildManager) parseWorker() {
dbPkg = dbPkg.Update().SetStatus(QUEUED).SaveX(context.Background())
dbLock.Unlock()
isLatest, err := isMirrorLatest(alpmHandle, pkg)
check(err)
if !isLatest {
log.Infof("Delayed %s: not all dependencies are up to date", info.Pkgbase)
b.parseWG.Done()
continue
}
b.parseWG.Done()
b.build <- pkg
}
}
}
func findPkgFiles(pkg *BuildPackage) {
pkgs, err := os.ReadDir(filepath.Join(conf.Basedir.Repo, pkg.FullRepo, "os", conf.Arch))
check(err)
var fPkg []string
for _, file := range pkgs {
if !file.IsDir() && !strings.HasSuffix(file.Name(), ".sig") {
matches := rePkgFile.FindStringSubmatch(file.Name())
var realPkgs []string
for _, realPkg := range pkg.Srcinfo.Packages {
realPkgs = append(realPkgs, realPkg.Pkgname)
}
if len(matches) > 1 && contains(realPkgs, matches[1]) {
fPkg = append(fPkg, filepath.Join(conf.Basedir.Repo, pkg.FullRepo, "os", conf.Arch, file.Name()))
}
}
}
pkg.PkgFiles = fPkg
}
func getVersionFromRepo(pkg *BuildPackage) string {
findPkgFiles(pkg)
if len(pkg.PkgFiles) == 0 {
return ""
}
fNameSplit := strings.Split(pkg.PkgFiles[0], "-")
return fNameSplit[len(fNameSplit)-3] + "-" + fNameSplit[len(fNameSplit)-2]
}
func isPkgFailed(pkg *BuildPackage) bool {
buildManager.failedMutex.Lock()
defer buildManager.failedMutex.Unlock()
file, err := os.OpenFile(filepath.Join(conf.Basedir.Repo, pkg.FullRepo+"_failed.txt"), os.O_RDWR|os.O_CREATE|os.O_SYNC, os.ModePerm)
check(err)
defer func(file *os.File) {
check(file.Close())
}(file)
failed := false
var newContent []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
splitPkg := strings.Split(line, "==")
if splitPkg[0] == pkg.Pkgbase {
var pkgVer string
if pkg.Srcinfo.Epoch == "" {
pkgVer = pkg.Srcinfo.Pkgver + "-" + pkg.Srcinfo.Pkgrel
} else {
pkgVer = pkg.Srcinfo.Epoch + ":" + pkg.Srcinfo.Pkgver + "-" + pkg.Srcinfo.Pkgrel
}
// try to build new versions of previously failed packages
if alpm.VerCmp(splitPkg[1], pkgVer) < 0 {
failed = false
} else {
failed = true
newContent = append(newContent, line+"\n")
}
} else {
newContent = append(newContent, line+"\n")
}
}
check(scanner.Err())
sort.Strings(newContent)
_, err = file.Seek(0, 0)
check(err)
check(file.Truncate(0))
_, err = file.WriteString(strings.Join(newContent, ""))
check(err)
return failed
}
func statusId2string(status int) (string, string) {
switch status {
case SKIPPED:
return "SKIPPED", "table-" + conf.Status.Class.Skipped
case QUEUED:
return "QUEUED", "table-" + conf.Status.Class.Queued
case LATEST:
return "LATEST", "table-" + conf.Status.Class.Latest
case FAILED:
return "FAILED", "table-" + conf.Status.Class.Failed
case BUILD:
return "SIGNING", "table-" + conf.Status.Class.Signing
case BUILDING:
return "BUILDING", "table-" + conf.Status.Class.Building
default:
return "UNKNOWN", "table-" + conf.Status.Class.Unknown
}
}
func (b *BuildManager) htmlWorker() {
type Pkg struct {
Pkgbase string
@ -731,26 +390,6 @@ func (b *BuildManager) htmlWorker() {
}
}
func setupChroot() {
if _, err := os.Stat(filepath.Join(conf.Basedir.Chroot, orgChrootName)); err == nil {
//goland:noinspection SpellCheckingInspection
cmd := exec.Command("arch-nspawn", filepath.Join(conf.Basedir.Chroot, orgChrootName), "pacman", "-Syuu", "--noconfirm")
res, err := cmd.CombinedOutput()
log.Debug(string(res))
check(err)
} else if os.IsNotExist(err) {
err := os.MkdirAll(conf.Basedir.Chroot, os.ModePerm)
check(err)
cmd := exec.Command("mkarchroot", "-C", pacmanConf, filepath.Join(conf.Basedir.Chroot, orgChrootName), "base-devel")
res, err := cmd.CombinedOutput()
log.Debug(string(res))
check(err)
} else {
check(err)
}
}
func (b *BuildManager) repoWorker(repo string) {
for {
select {
@ -874,7 +513,7 @@ func (b *BuildManager) syncWorker() {
// fetch updates between sync runs
setupChroot()
pkgBuilds, err := filepathx.Glob(filepath.Join(conf.Basedir.Upstream, "/**/PKGBUILD"))
pkgBuilds, err := Glob(filepath.Join(conf.Basedir.Upstream, "/**/PKGBUILD"))
check(err)
// Shuffle pkgbuilds to spread out long-running builds, otherwise pkgBuilds is alphabetically-sorted
@ -889,7 +528,7 @@ func (b *BuildManager) syncWorker() {
sPkgbuild := strings.Split(pkgbuild, "/")
repo := sPkgbuild[len(sPkgbuild)-2]
if repo == "trunk" || !contains(conf.Repos, strings.Split(repo, "-")[0]) || strings.Contains(repo, "i686") || strings.Contains(repo, "testing") || strings.Contains(repo, "staging") {
if repo == "trunk" || !contains(conf.Repos, strings.Split(repo, "-")[0]) || containsSubStr(repo, conf.Blacklist.Repo) {
continue
}
@ -956,6 +595,11 @@ func main() {
setupChroot()
syncMarchs()
alpmLock.Lock()
alpmHandle, err = initALPM(filepath.Join(conf.Basedir.Chroot, "root"), filepath.Join(conf.Basedir.Chroot, "/root/var/lib/pacman"))
check(err)
alpmLock.Unlock()
go buildManager.syncWorker()
go buildManager.htmlWorker()
@ -972,4 +616,5 @@ func main() {
buildManager.buildProcMutex.RUnlock()
buildManager.buildWG.Wait()
buildManager.repoWG.Wait()
check(alpmHandle.Release())
}

591
utils.go Normal file
View File

@ -0,0 +1,591 @@
package main
import (
"ALHP.go/ent"
"ALHP.go/ent/dbpackage"
"bufio"
"context"
"fmt"
"github.com/Jguer/go-alpm/v2"
paconf "github.com/Morganamilo/go-pacmanconf"
"github.com/Morganamilo/go-srcinfo"
log "github.com/sirupsen/logrus"
"io"
"io/fs"
"os"
"os/exec"
"path/filepath"
"sort"
"strconv"
"strings"
"sync"
)
const (
SKIPPED = iota
FAILED = iota
BUILD = iota
QUEUED = iota
BUILDING = iota
LATEST = iota
UNKNOWN = iota
)
type BuildPackage struct {
Pkgbase string
Pkgbuild string
Srcinfo *srcinfo.Srcinfo
PkgFiles []string
Repo string
March string
FullRepo string
Version string
}
type BuildManager struct {
build chan *BuildPackage
parse chan *BuildPackage
repoPurge map[string]chan *BuildPackage
repoAdd map[string]chan *BuildPackage
exit bool
buildWG sync.WaitGroup
parseWG sync.WaitGroup
repoWG sync.WaitGroup
failedMutex sync.RWMutex
buildProcesses []*os.Process
buildProcMutex sync.RWMutex
}
type Conf struct {
Arch string
Repos, March []string
Svn2git map[string]string
Basedir struct {
Repo, Chroot, Makepkg, Upstream, Db string
}
Build struct {
Worker int
Makej int
}
Logging struct {
Level string
}
Status struct {
Class struct {
Skipped, Queued, Latest, Failed, Signing, Building, Unknown string
}
}
Blacklist struct {
Packages []string
Repo []string
}
}
type Globs []string
func check(e error) {
if e != nil {
panic(e)
}
}
func containsSubStr(str string, subList []string) bool {
for _, checkStr := range subList {
if strings.Contains(str, checkStr) {
return true
}
}
return false
}
func statusId2string(status int) (string, string) {
switch status {
case SKIPPED:
return "SKIPPED", "table-" + conf.Status.Class.Skipped
case QUEUED:
return "QUEUED", "table-" + conf.Status.Class.Queued
case LATEST:
return "LATEST", "table-" + conf.Status.Class.Latest
case FAILED:
return "FAILED", "table-" + conf.Status.Class.Failed
case BUILD:
return "SIGNING", "table-" + conf.Status.Class.Signing
case BUILDING:
return "BUILDING", "table-" + conf.Status.Class.Building
default:
return "UNKNOWN", "table-" + conf.Status.Class.Unknown
}
}
func getVersionFromRepo(pkg *BuildPackage) string {
findPkgFiles(pkg)
if len(pkg.PkgFiles) == 0 {
return ""
}
fNameSplit := strings.Split(pkg.PkgFiles[0], "-")
return fNameSplit[len(fNameSplit)-3] + "-" + fNameSplit[len(fNameSplit)-2]
}
func gitClean(pkg *BuildPackage) {
cmd := exec.Command("sudo", "git_clean.sh", filepath.Dir(pkg.Pkgbuild))
res, err := cmd.CombinedOutput()
if err != nil {
log.Warningf("git clean failed with %v:\n%s", err, res)
} else {
log.Debug(string(res))
}
}
func increasePkgRel(pkg *BuildPackage) error {
f, err := os.OpenFile(pkg.Pkgbuild, os.O_RDWR, os.ModePerm)
if err != nil {
return err
}
defer func(f *os.File) {
err := f.Close()
if err != nil {
panic(err)
}
}(f)
fStr, err := io.ReadAll(f)
if err != nil {
return err
}
nStr := rePkgRel.ReplaceAllLiteralString(string(fStr), "pkgrel="+pkg.Srcinfo.Pkgrel+".1")
_, err = f.Seek(0, 0)
if err != nil {
return err
}
err = f.Truncate(0)
if err != nil {
return err
}
_, err = f.WriteString(nStr)
if err != nil {
return err
}
pkg.Version = pkg.Version + ".1"
return nil
}
func packages2slice(pkgs interface{}) []string {
switch v := pkgs.(type) {
case []srcinfo.Package:
var sPkgs []string
for _, p := range v {
sPkgs = append(sPkgs, p.Pkgname)
}
return sPkgs
case []srcinfo.ArchString:
var sPkgs []string
for _, p := range v {
sPkgs = append(sPkgs, p.Value)
}
return sPkgs
default:
return []string{}
}
}
func importKeys(pkg *BuildPackage) error {
if pkg.Srcinfo.ValidPGPKeys != nil {
args := []string{"--keyserver", "keyserver.ubuntu.com", "--recv-keys"}
args = append(args, pkg.Srcinfo.ValidPGPKeys...)
cmd := exec.Command("gpg", args...)
_, err := cmd.CombinedOutput()
return err
}
return nil
}
func constructVersion(pkgver string, pkgrel string, epoch string) string {
if epoch == "" {
return pkgver + "-" + pkgrel
} else {
return epoch + ":" + pkgver + "-" + pkgrel
}
}
func initALPM(root string, dbpath string) (*alpm.Handle, error) {
h, err := alpm.Initialize(root, dbpath)
if err != nil {
return nil, err
}
PacmanConfig, _, err := paconf.ParseFile(filepath.Join(root, "/etc/pacman.conf"))
if err != nil {
return nil, err
}
for _, repo := range PacmanConfig.Repos {
db, err := h.RegisterSyncDB(repo.Name, 0)
if err != nil {
return nil, err
}
db.SetServers(repo.Servers)
if len(repo.Usage) == 0 {
db.SetUsage(alpm.UsageAll)
}
for _, usage := range repo.Usage {
switch usage {
case "Sync":
db.SetUsage(alpm.UsageSync)
case "Search":
db.SetUsage(alpm.UsageSearch)
case "Install":
db.SetUsage(alpm.UsageInstall)
case "Upgrade":
db.SetUsage(alpm.UsageUpgrade)
case "All":
db.SetUsage(alpm.UsageAll)
}
}
}
return h, nil
}
func getSVN2GITVersion(pkg *BuildPackage) (string, error) {
if pkg.Pkgbuild == "" && pkg.Pkgbase == "" {
return "", fmt.Errorf("invalid arguments")
}
// upstream/upstream-core-extra/extra-cmake-modules/repos/extra-any/PKGBUILD
pkgBuilds, _ := Glob(filepath.Join(conf.Basedir.Upstream, "**/"+pkg.Pkgbase+"/repos/*/PKGBUILD"))
var fPkgbuilds []string
for _, pkgbuild := range pkgBuilds {
sPkgbuild := strings.Split(pkgbuild, "/")
repo := sPkgbuild[len(sPkgbuild)-2]
if repo == "trunk" || containsSubStr(repo, conf.Blacklist.Repo) {
continue
}
if !contains(fPkgbuilds, pkgbuild) {
fPkgbuilds = append(fPkgbuilds, pkgbuild)
}
}
if len(fPkgbuilds) > 1 {
return "", fmt.Errorf("%s: multiple PKGBUILD found: %s", pkg.Pkgbase, fPkgbuilds)
} else if len(fPkgbuilds) == 0 {
return "", fmt.Errorf("%s: no matching PKGBUILD found (searched: %s, canidates: %s)", pkg.Pkgbase, filepath.Join(conf.Basedir.Upstream, "**/"+pkg.Pkgbase+"/repos/*/PKGBUILD"), pkgBuilds)
}
cmd := exec.Command("sh", "-c", "cd "+filepath.Dir(fPkgbuilds[0])+"&&"+"makepkg --printsrcinfo")
res, err := cmd.Output()
if err != nil {
return "", err
}
info, err := srcinfo.Parse(string(res))
if err != nil {
return "", err
}
return constructVersion(info.Pkgver, info.Pkgrel, info.Epoch), nil
}
func isPkgFailed(pkg *BuildPackage) bool {
buildManager.failedMutex.Lock()
defer buildManager.failedMutex.Unlock()
file, err := os.OpenFile(filepath.Join(conf.Basedir.Repo, pkg.FullRepo+"_failed.txt"), os.O_RDWR|os.O_CREATE|os.O_SYNC, os.ModePerm)
check(err)
defer func(file *os.File) {
check(file.Close())
}(file)
failed := false
var newContent []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
splitPkg := strings.Split(line, "==")
if splitPkg[0] == pkg.Pkgbase {
pkgVer := constructVersion(pkg.Srcinfo.Pkgver, pkg.Srcinfo.Pkgrel, pkg.Srcinfo.Epoch)
// try to build new versions of previously failed packages
if alpm.VerCmp(splitPkg[1], pkgVer) < 0 {
failed = false
} else {
failed = true
newContent = append(newContent, line+"\n")
}
} else {
newContent = append(newContent, line+"\n")
}
}
check(scanner.Err())
sort.Strings(newContent)
_, err = file.Seek(0, 0)
check(err)
check(file.Truncate(0))
_, err = file.WriteString(strings.Join(newContent, ""))
check(err)
return failed
}
func setupChroot() {
if _, err := os.Stat(filepath.Join(conf.Basedir.Chroot, orgChrootName)); err == nil {
//goland:noinspection SpellCheckingInspection
cmd := exec.Command("arch-nspawn", filepath.Join(conf.Basedir.Chroot, orgChrootName), "pacman", "-Syuu", "--noconfirm")
res, err := cmd.CombinedOutput()
log.Debug(string(res))
check(err)
} else if os.IsNotExist(err) {
err := os.MkdirAll(conf.Basedir.Chroot, os.ModePerm)
check(err)
cmd := exec.Command("mkarchroot", "-C", pacmanConf, filepath.Join(conf.Basedir.Chroot, orgChrootName), "base-devel")
res, err := cmd.CombinedOutput()
log.Debug(string(res))
check(err)
} else {
check(err)
}
}
func findPkgFiles(pkg *BuildPackage) {
pkgs, err := os.ReadDir(filepath.Join(conf.Basedir.Repo, pkg.FullRepo, "os", conf.Arch))
check(err)
var fPkg []string
for _, file := range pkgs {
if !file.IsDir() && !strings.HasSuffix(file.Name(), ".sig") {
matches := rePkgFile.FindStringSubmatch(file.Name())
var realPkgs []string
for _, realPkg := range pkg.Srcinfo.Packages {
realPkgs = append(realPkgs, realPkg.Pkgname)
}
if len(matches) > 1 && contains(realPkgs, matches[1]) {
fPkg = append(fPkg, filepath.Join(conf.Basedir.Repo, pkg.FullRepo, "os", conf.Arch, file.Name()))
}
}
}
pkg.PkgFiles = fPkg
}
func getDbPackage(pkg *BuildPackage) *ent.DbPackage {
dbLock.Lock()
dbPkg, err := db.DbPackage.Query().Where(dbpackage.Pkgbase(pkg.Pkgbase)).Only(context.Background())
if err != nil {
dbPkg = db.DbPackage.Create().SetPkgbase(pkg.Pkgbase).SetMarch(pkg.March).SetPackages(packages2slice(pkg.Srcinfo.Packages)).SetRepository(pkg.Repo).SaveX(context.Background())
}
dbLock.Unlock()
return dbPkg
}
func syncMarchs() {
files, err := os.ReadDir(conf.Basedir.Repo)
check(err)
var eRepos []string
for _, file := range files {
if file.Name() != "." && file.Name() != logDir && file.IsDir() {
eRepos = append(eRepos, file.Name())
}
}
for _, march := range conf.March {
setupMakepkg(march)
for _, repo := range conf.Repos {
tRepo := fmt.Sprintf("%s-%s", repo, march)
repos = append(repos, tRepo)
buildManager.repoAdd[tRepo] = make(chan *BuildPackage, conf.Build.Worker)
buildManager.repoPurge[tRepo] = make(chan *BuildPackage, 10000)
go buildManager.repoWorker(tRepo)
if _, err := os.Stat(filepath.Join(filepath.Join(conf.Basedir.Repo, tRepo, "os", conf.Arch))); os.IsNotExist(err) {
log.Debugf("Creating path %s", filepath.Join(conf.Basedir.Repo, tRepo, "os", conf.Arch))
check(os.MkdirAll(filepath.Join(conf.Basedir.Repo, tRepo, "os", conf.Arch), os.ModePerm))
}
if i := find(eRepos, tRepo); i != -1 {
eRepos = append(eRepos[:i], eRepos[i+1:]...)
}
}
}
log.Infof("Repos: %s", repos)
for _, repo := range eRepos {
log.Infof("Removing old repo %s", repo)
check(os.RemoveAll(filepath.Join(conf.Basedir.Repo, repo)))
}
}
//goland:noinspection SpellCheckingInspection
func setupMakepkg(march string) {
lMakepkg := filepath.Join(conf.Basedir.Makepkg, fmt.Sprintf("makepkg-%s.conf", march))
check(os.MkdirAll(conf.Basedir.Makepkg, os.ModePerm))
t, err := os.ReadFile(makepkgConf)
check(err)
makepkgStr := string(t)
makepkgStr = strings.ReplaceAll(makepkgStr, "-mtune=generic", "")
makepkgStr = strings.ReplaceAll(makepkgStr, "-O2", "-O3")
makepkgStr = strings.ReplaceAll(makepkgStr, " check ", " !check ")
makepkgStr = strings.ReplaceAll(makepkgStr, " color ", " !color ")
makepkgStr = strings.ReplaceAll(makepkgStr, "#MAKEFLAGS=\"-j2\"", "MAKEFLAGS=\"-j"+strconv.Itoa(conf.Build.Makej)+"\"")
makepkgStr = reMarch.ReplaceAllString(makepkgStr, "${1}"+march)
check(os.WriteFile(lMakepkg, []byte(makepkgStr), os.ModePerm))
}
func isMirrorLatest(h *alpm.Handle, buildPkg *BuildPackage) (bool, error) {
alpmLock.Lock()
dbs, err := h.SyncDBs()
if err != nil {
return false, err
}
allDepends := buildPkg.Srcinfo.Depends
allDepends = append(allDepends, buildPkg.Srcinfo.MakeDepends...)
for _, dep := range allDepends {
pkg, err := dbs.FindSatisfier(dep.Value)
if err != nil {
return false, err
}
svn2gitVer, err := getSVN2GITVersion(&BuildPackage{
Pkgbase: pkg.Base(),
})
if err != nil {
return false, err
}
if svn2gitVer != "" && alpm.VerCmp(svn2gitVer, pkg.Version()) != 0 {
return false, nil
}
}
alpmLock.Unlock()
return true, nil
}
func contains(s interface{}, str string) bool {
switch v := s.(type) {
case []string:
if i := find(v, str); i != -1 {
return true
}
case []srcinfo.ArchString:
var n []string
for _, as := range v {
n = append(n, as.Value)
}
if i := find(n, str); i != -1 {
return true
}
default:
return false
}
return false
}
func find(s []string, str string) int {
for i, v := range s {
if v == str {
return i
}
}
return -1
}
func copyFile(src, dst string) (int64, error) {
sourceFileStat, err := os.Stat(src)
if err != nil {
return 0, err
}
if !sourceFileStat.Mode().IsRegular() {
return 0, fmt.Errorf("%s is not a regular file", src)
}
source, err := os.Open(src)
if err != nil {
return 0, err
}
defer func(source *os.File) {
check(source.Close())
}(source)
destination, err := os.Create(dst)
if err != nil {
return 0, err
}
defer func(destination *os.File) {
check(destination.Close())
}(destination)
nBytes, err := io.Copy(destination, source)
return nBytes, err
}
func Glob(pattern string) ([]string, error) {
if !strings.Contains(pattern, "**") {
return filepath.Glob(pattern)
}
return Globs(strings.Split(pattern, "**")).Expand()
}
func (globs Globs) Expand() ([]string, error) {
var matches = []string{""}
for _, glob := range globs {
var hits []string
var hitMap = map[string]bool{}
for _, match := range matches {
paths, err := filepath.Glob(match + glob)
if err != nil {
return nil, err
}
for _, path := range paths {
err = filepath.WalkDir(path, func(path string, d os.DirEntry, err error) error {
if err != nil {
return fs.SkipDir
}
if _, ok := hitMap[path]; !ok {
hits = append(hits, path)
hitMap[path] = true
}
return nil
})
if err != nil {
return nil, err
}
}
}
matches = hits
}
if globs == nil && len(matches) > 0 && matches[0] == "" {
matches = matches[1:]
}
return matches, nil
}