2021-07-27 02:43:30 +02:00
package main
import (
"ALHP.go/ent"
"ALHP.go/ent/dbpackage"
"context"
2021-11-21 23:46:21 +01:00
"crypto/sha256"
2021-08-30 11:02:06 +02:00
"encoding/hex"
2021-12-05 12:51:22 +01:00
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqljson"
2021-07-27 02:43:30 +02:00
"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"
2021-08-30 11:02:06 +02:00
"lukechampine.com/blake3"
2021-11-21 23:46:21 +01:00
"net/http"
2021-07-27 02:43:30 +02:00
"os"
"os/exec"
"path/filepath"
2021-11-21 15:24:27 +01:00
"regexp"
2021-07-27 02:43:30 +02:00
"strconv"
"strings"
"sync"
2021-11-13 22:29:46 +01:00
"time"
2021-07-27 02:43:30 +02:00
)
const (
2021-07-28 02:31:53 +02:00
pacmanConf = "/usr/share/devtools/pacman-extra.conf"
makepkgConf = "/usr/share/devtools/makepkg-x86_64.conf"
logDir = "logs"
pristineChroot = "root"
2021-12-19 16:37:10 +01:00
buildDir = "build"
2021-11-13 22:29:46 +01:00
lastUpdate = "lastupdate"
2021-12-19 16:37:10 +01:00
upstreamDir = "upstream"
chrootDir = "chroot"
makepkgDir = "makepkg"
2021-12-20 17:20:06 +01:00
waitingDir = "to_be_moved"
2021-07-27 02:43:30 +02:00
)
2021-11-21 15:24:27 +01:00
var (
2021-12-20 00:44:32 +01:00
reMarch = regexp . MustCompile ( ` (-march=)(.+?) ` )
rePkgRel = regexp . MustCompile ( ` (?m)^pkgrel\s*=\s*(.+)$ ` )
rePkgSource = regexp . MustCompile ( ` (?msU)^source.*=.*\((.+)\)$ ` )
rePkgSum = regexp . MustCompile ( ` (?msU)^sha256sums.*=.*\((.+)\)$ ` )
rePkgFile = regexp . MustCompile ( ` ^(.+)(?:-.+) { 2}-(?:x86_64|any)\.pkg\.tar\.zst(?:\.sig)*$ ` )
reLdError = regexp . MustCompile ( ` (?mi).*collect2: error: ld returned (\d+) exit status.* ` )
reDownloadError = regexp . MustCompile ( ` (?m)^error: could not rename .+$ ` )
rePortError = regexp . MustCompile ( ` (?m)^OSError: \[Errno 98] Address already in use$ ` )
reSigError = regexp . MustCompile ( ` (?m)^error: .*: signature from .* is invalid$ ` )
2021-11-21 15:24:27 +01:00
)
2021-07-27 02:43:30 +02:00
type BuildPackage struct {
2021-11-20 00:02:53 +01:00
Pkgbase string
Pkgbuild string
Srcinfo * srcinfo . Srcinfo
PkgFiles [ ] string
Repo dbpackage . Repository
March string
FullRepo string
Version string
Hash string
DbPackage * ent . DbPackage
2021-07-27 02:43:30 +02:00
}
type BuildManager struct {
2021-11-29 10:48:29 +01:00
build map [ string ] chan * BuildPackage
2021-07-27 02:43:30 +02:00
parse chan * BuildPackage
2021-12-20 16:04:13 +01:00
repoPurge map [ string ] chan [ ] * BuildPackage
repoAdd map [ string ] chan [ ] * BuildPackage
2021-07-27 02:43:30 +02:00
exit bool
buildWG sync . WaitGroup
parseWG sync . WaitGroup
repoWG sync . WaitGroup
buildProcesses [ ] * os . Process
buildProcMutex sync . RWMutex
2021-08-31 21:13:22 +02:00
alpmMutex sync . RWMutex
2021-07-27 02:43:30 +02:00
}
type Conf struct {
Arch string
Repos , March [ ] string
Svn2git map [ string ] string
Basedir struct {
2021-12-19 16:37:10 +01:00
Repo , Work string
2021-10-25 06:20:03 +02:00
}
Db struct {
Driver string
ConnectTo string ` yaml:"connect_to" `
2021-07-27 02:43:30 +02:00
}
Build struct {
Worker int
Makej int
2021-11-21 19:35:29 +01:00
Checks bool
2021-07-27 02:43:30 +02:00
}
Logging struct {
Level string
}
Blacklist struct {
Packages [ ] string
Repo [ ] string
2021-11-13 20:45:47 +01:00
LTO [ ] string ` yaml:"lto" `
2021-07-27 02:43:30 +02:00
}
2021-11-19 23:27:51 +01:00
Housekeeping struct {
Interval string
}
2021-11-21 18:27:03 +01:00
Status struct {
Class struct {
Skipped , Queued , Latest , Failed , Signing , Building , Unknown string
}
}
2021-11-21 23:46:21 +01:00
KernelPatches map [ string ] string ` yaml:"kernel_patches" `
KernelToPatch [ ] string ` yaml:"kernel_to_patch" `
2021-07-27 02:43:30 +02:00
}
type Globs [ ] string
2021-12-10 09:26:51 +01:00
type Package string
type PKGBUILD string
2021-07-27 02:43:30 +02:00
2021-08-26 12:21:20 +02:00
type MultiplePKGBUILDError struct {
error
}
2021-08-26 12:59:23 +02:00
type UnableToSatisfyError struct {
error
}
2021-08-26 12:21:20 +02:00
2021-07-27 02:43:30 +02:00
func check ( e error ) {
if e != nil {
panic ( e )
}
}
2021-12-10 09:26:51 +01:00
func ( p PKGBUILD ) FullRepo ( ) string {
sPkgbuild := strings . Split ( string ( p ) , string ( filepath . Separator ) )
return sPkgbuild [ len ( sPkgbuild ) - 2 ]
}
func ( p PKGBUILD ) Repo ( ) string {
return strings . Split ( p . FullRepo ( ) , "-" ) [ 0 ]
}
func ( p PKGBUILD ) PkgBase ( ) string {
sPkgbuild := strings . Split ( string ( p ) , string ( filepath . Separator ) )
return sPkgbuild [ len ( sPkgbuild ) - 4 ]
}
2021-11-13 22:29:46 +01:00
func updateLastUpdated ( ) {
check ( os . WriteFile ( filepath . Join ( conf . Basedir . Repo , lastUpdate ) , [ ] byte ( strconv . FormatInt ( time . Now ( ) . Unix ( ) , 10 ) ) , 0644 ) )
}
2021-12-10 09:26:51 +01:00
func ( path Package ) Name ( ) string {
fNameSplit := strings . Split ( filepath . Base ( string ( path ) ) , "-" )
return strings . Join ( fNameSplit [ : len ( fNameSplit ) - 3 ] , "-" )
}
func ( path Package ) MArch ( ) string {
splitPath := strings . Split ( string ( path ) , string ( filepath . Separator ) )
return strings . Join ( strings . Split ( splitPath [ len ( splitPath ) - 4 ] , "-" ) [ 1 : ] , "-" )
}
func ( path Package ) Repo ( ) dbpackage . Repository {
splitPath := strings . Split ( string ( path ) , string ( filepath . Separator ) )
return dbpackage . Repository ( strings . Split ( splitPath [ len ( splitPath ) - 4 ] , "-" ) [ 0 ] )
}
func ( path Package ) FullRepo ( ) string {
splitPath := strings . Split ( string ( path ) , string ( filepath . Separator ) )
return splitPath [ len ( splitPath ) - 4 ]
}
2021-12-20 17:20:06 +01:00
func ( path Package ) Version ( ) string {
fNameSplit := strings . Split ( filepath . Base ( string ( path ) ) , "-" )
2021-12-21 03:28:50 +01:00
return strings . Join ( fNameSplit [ len ( fNameSplit ) - 3 : len ( fNameSplit ) - 1 ] , "-" )
2021-12-20 17:20:06 +01:00
}
2021-11-21 18:27:03 +01:00
func statusId2string ( s dbpackage . Status ) string {
switch s {
case dbpackage . StatusSkipped :
return conf . Status . Class . Skipped
case dbpackage . StatusQueued :
return conf . Status . Class . Queued
case dbpackage . StatusLatest :
return conf . Status . Class . Latest
case dbpackage . StatusFailed :
return conf . Status . Class . Failed
case dbpackage . StatusSigning :
return conf . Status . Class . Signing
case dbpackage . StatusBuilding :
return conf . Status . Class . Building
default :
return conf . Status . Class . Unknown
}
}
2021-08-30 11:02:06 +02:00
func b3sum ( filePath string ) ( string , error ) {
file , err := os . Open ( filePath )
if err != nil {
return "" , err
}
defer func ( file * os . File ) {
check ( file . Close ( ) )
} ( file )
hash := blake3 . New ( 32 , nil )
if _ , err := io . Copy ( hash , file ) ; err != nil {
return "" , err
}
return hex . EncodeToString ( hash . Sum ( nil ) ) , nil
}
2021-07-27 02:43:30 +02:00
func containsSubStr ( str string , subList [ ] string ) bool {
for _ , checkStr := range subList {
if strings . Contains ( str , checkStr ) {
return true
}
}
return false
}
2021-11-29 15:02:14 +01:00
func cleanBuildDir ( dir string ) error {
if _ , err := os . Stat ( dir ) ; err == nil {
err = os . RemoveAll ( dir )
if err != nil {
return err
}
}
return nil
}
func ( p * BuildPackage ) setupBuildDir ( ) ( string , error ) {
2021-12-19 16:37:10 +01:00
buildDir := filepath . Join ( conf . Basedir . Work , buildDir , p . March , p . Pkgbase + "-" + p . Version )
2021-11-29 15:02:14 +01:00
err := cleanBuildDir ( buildDir )
if err != nil {
return "" , fmt . Errorf ( "removing old builddir failed: %v" , err )
}
err = os . MkdirAll ( buildDir , 0755 )
if err != nil {
return "" , err
}
files , err := filepath . Glob ( filepath . Join ( filepath . Dir ( p . Pkgbuild ) , "*" ) )
if err != nil {
return "" , err
}
for _ , file := range files {
_ , err = copyFile ( file , filepath . Join ( buildDir , filepath . Base ( file ) ) )
if err != nil {
return "" , err
}
}
p . Pkgbuild = filepath . Join ( buildDir , "PKGBUILD" )
return buildDir , nil
}
2021-11-19 22:32:11 +01:00
func ( p * BuildPackage ) repoVersion ( ) ( string , error ) {
err := p . findPkgFiles ( )
if err != nil {
return "" , err
}
2021-07-27 02:43:30 +02:00
2021-11-19 22:32:11 +01:00
if len ( p . PkgFiles ) == 0 {
2021-11-18 13:22:10 +01:00
return "" , fmt . Errorf ( "not found" )
2021-07-27 02:43:30 +02:00
}
2021-11-19 22:32:11 +01:00
fNameSplit := strings . Split ( p . PkgFiles [ 0 ] , "-" )
2021-11-18 13:22:10 +01:00
return fNameSplit [ len ( fNameSplit ) - 3 ] + "-" + fNameSplit [ len ( fNameSplit ) - 2 ] , nil
2021-07-27 02:43:30 +02:00
}
2021-11-27 01:28:42 +01:00
func ( p * BuildPackage ) increasePkgRel ( buildNo int ) error {
2021-11-19 22:32:11 +01:00
f , err := os . OpenFile ( p . Pkgbuild , os . O_RDWR , 0644 )
2021-07-27 02:43:30 +02:00
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
}
2021-11-27 01:28:42 +01:00
nStr := rePkgRel . ReplaceAllLiteralString ( string ( fStr ) , "pkgrel=" + p . Srcinfo . Pkgrel + "." + strconv . Itoa ( buildNo ) )
2021-07-27 02:43:30 +02:00
_ , 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
}
2021-11-27 01:28:42 +01:00
p . Version += "." + strconv . Itoa ( buildNo )
2021-07-27 02:43:30 +02:00
return nil
}
2021-11-21 23:46:21 +01:00
func ( p * BuildPackage ) prepareKernelPatches ( ) error {
f , err := os . OpenFile ( p . Pkgbuild , os . O_RDWR , 0644 )
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
}
// choose best suited patch based on kernel version
var curVer string
2021-11-21 23:49:01 +01:00
for k := range conf . KernelPatches {
2021-11-24 17:53:22 +01:00
if k == p . Pkgbase {
curVer = k
break
}
2021-11-21 23:46:21 +01:00
if alpm . VerCmp ( p . Srcinfo . Pkgver , k ) >= 0 && alpm . VerCmp ( k , curVer ) >= 0 {
curVer = k
}
}
2021-11-24 17:53:22 +01:00
newPKGBUILD := string ( fStr )
if conf . KernelPatches [ curVer ] == "none" {
2021-11-21 23:49:01 +01:00
return fmt . Errorf ( "no patch available" )
2021-11-24 17:53:22 +01:00
} else if conf . KernelPatches [ curVer ] == "skip" {
log . Debugf ( "[KP] skipped patching for %s" , p . Pkgbase )
} else {
log . Debugf ( "[KP] choose patch %s for kernel %s" , curVer , p . Srcinfo . Pkgver )
2021-11-21 23:46:21 +01:00
2021-11-24 17:53:22 +01:00
// add patch to source-array
orgSource := rePkgSource . FindStringSubmatch ( newPKGBUILD )
if orgSource == nil || len ( orgSource ) < 1 {
return fmt . Errorf ( "no source=() found" )
}
2021-11-21 23:46:21 +01:00
2021-11-24 17:53:22 +01:00
sources := strings . Split ( orgSource [ 1 ] , "\n" )
sources = append ( sources , fmt . Sprintf ( "\"%s\"" , conf . KernelPatches [ curVer ] ) )
2021-11-21 23:46:21 +01:00
2021-11-24 17:53:22 +01:00
newPKGBUILD = rePkgSource . ReplaceAllLiteralString ( newPKGBUILD , fmt . Sprintf ( "source=(%s)" , strings . Join ( sources , "\n" ) ) )
2021-11-21 23:46:21 +01:00
2021-11-24 17:53:22 +01:00
// add patch sha256 to sha256sums-array (yes, hardcoded to sha256)
// TODO: support all sums that makepkg also supports
// get sum
resp , err := http . Get ( conf . KernelPatches [ curVer ] )
if err != nil || resp . StatusCode != 200 {
return err
}
h := sha256 . New ( )
_ , err = io . Copy ( h , resp . Body )
defer func ( Body io . ReadCloser ) {
_ = Body . Close ( )
} ( resp . Body )
if err != nil {
return err
}
2021-11-21 23:46:21 +01:00
2021-11-24 17:53:22 +01:00
orgSums := rePkgSum . FindStringSubmatch ( newPKGBUILD )
if orgSums == nil || len ( orgSums ) < 1 {
return fmt . Errorf ( "no sha256sums=() found" )
}
2021-11-21 23:46:21 +01:00
2021-11-24 17:53:22 +01:00
sums := strings . Split ( orgSums [ 1 ] , "\n" )
sums = append ( sums , fmt . Sprintf ( "'%s'" , hex . EncodeToString ( h . Sum ( nil ) ) ) )
2021-11-21 23:46:21 +01:00
2021-11-24 17:53:22 +01:00
newPKGBUILD = rePkgSum . ReplaceAllLiteralString ( newPKGBUILD , fmt . Sprintf ( "sha256sums=(\n%s\n)" , strings . Join ( sums , "\n" ) ) )
}
2021-11-21 23:46:21 +01:00
// enable config option
switch {
case strings . Contains ( p . March , "v4" ) :
2021-11-22 23:19:43 +01:00
newPKGBUILD = strings . Replace ( newPKGBUILD , "make olddefconfig\n" , "echo CONFIG_GENERIC_CPU4=y >> .config\nmake olddefconfig\n" , 1 )
2021-11-21 23:46:21 +01:00
case strings . Contains ( p . March , "v3" ) :
2021-11-22 23:19:43 +01:00
newPKGBUILD = strings . Replace ( newPKGBUILD , "make olddefconfig\n" , "echo CONFIG_GENERIC_CPU3=y >> .config\nmake olddefconfig\n" , 1 )
2021-11-21 23:46:21 +01:00
case strings . Contains ( p . March , "v2" ) :
2021-11-22 23:19:43 +01:00
newPKGBUILD = strings . Replace ( newPKGBUILD , "make olddefconfig\n" , "echo CONFIG_GENERIC_CPU2=y >> .config\nmake olddefconfig\n" , 1 )
2021-11-21 23:46:21 +01:00
}
// empty file before writing
_ , err = f . Seek ( 0 , 0 )
if err != nil {
return err
}
err = f . Truncate ( 0 )
if err != nil {
return err
}
_ , err = f . WriteString ( newPKGBUILD )
if err != nil {
return err
}
return nil
}
2021-12-20 17:20:06 +01:00
func movePackagesLive ( fullRepo string ) error {
2021-12-20 22:59:53 +01:00
if _ , err := os . Stat ( filepath . Join ( conf . Basedir . Work , waitingDir , fullRepo ) ) ; os . IsNotExist ( err ) {
return nil
} else if err != nil {
return err
}
2021-12-20 18:40:20 +01:00
march := strings . Join ( strings . Split ( fullRepo , "-" ) [ 1 : ] , "-" )
repo := strings . Split ( fullRepo , "-" ) [ 0 ]
2021-12-20 17:20:06 +01:00
pkgFiles , err := filepath . Glob ( filepath . Join ( conf . Basedir . Work , waitingDir , fullRepo , "*.pkg.tar.zst" ) )
if err != nil {
return err
}
toAdd := make ( [ ] * BuildPackage , 0 )
for _ , file := range pkgFiles {
pkg := Package ( file )
2021-12-20 18:40:20 +01:00
dbpkg , err := pkg . DBPackageIsolated ( march , dbpackage . Repository ( repo ) )
2021-12-20 17:20:06 +01:00
if err != nil {
return err
}
err = os . Rename ( file , filepath . Join ( conf . Basedir . Repo , fullRepo , "os" , conf . Arch , filepath . Base ( file ) ) )
if err != nil {
return err
}
err = os . Rename ( file + ".sig" , filepath . Join ( conf . Basedir . Repo , fullRepo , "os" , conf . Arch , filepath . Base ( file ) + ".sig" ) )
if err != nil {
return err
}
toAdd = append ( toAdd , & BuildPackage {
DbPackage : dbpkg ,
Pkgbase : dbpkg . Pkgbase ,
PkgFiles : [ ] string { filepath . Join ( conf . Basedir . Repo , fullRepo , "os" , conf . Arch , filepath . Base ( file ) ) } ,
Version : pkg . Version ( ) ,
} )
}
2021-12-21 03:21:20 +01:00
log . Infof ( "[%s] Adding %d packages" , fullRepo , len ( toAdd ) )
2021-12-20 17:20:06 +01:00
buildManager . repoAdd [ fullRepo ] <- toAdd
return nil
}
2021-07-27 02:43:30 +02:00
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 { }
}
}
2021-11-25 01:50:49 +01:00
func ( p * BuildPackage ) importKeys ( ) error {
if p . Srcinfo . ValidPGPKeys != nil {
2021-07-27 02:43:30 +02:00
args := [ ] string { "--keyserver" , "keyserver.ubuntu.com" , "--recv-keys" }
2021-11-25 01:50:49 +01:00
args = append ( args , p . Srcinfo . ValidPGPKeys ... )
2021-07-27 02:43:30 +02:00
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
}
2021-11-20 01:02:37 +01:00
func ( p * BuildPackage ) isAvailable ( h * alpm . Handle ) bool {
dbs , err := h . SyncDBs ( )
if err != nil {
return false
}
buildManager . alpmMutex . Lock ( )
2021-12-14 12:58:18 +01:00
var pkg alpm . IPackage
if p . Srcinfo != nil {
pkg , err = dbs . FindSatisfier ( p . Srcinfo . Packages [ 0 ] . Pkgname )
} else {
pkg , err = dbs . FindSatisfier ( p . DbPackage . Packages [ 0 ] )
}
2021-11-20 01:02:37 +01:00
buildManager . alpmMutex . Unlock ( )
if err != nil {
return false
}
if pkg . DB ( ) . Name ( ) != p . Repo . String ( ) {
return false
}
return true
}
2021-11-19 22:32:11 +01:00
func ( p * BuildPackage ) SVN2GITVersion ( h * alpm . Handle ) ( string , error ) {
if p . Pkgbuild == "" && p . Pkgbase == "" {
2021-07-27 02:43:30 +02:00
return "" , fmt . Errorf ( "invalid arguments" )
}
// upstream/upstream-core-extra/extra-cmake-modules/repos/extra-any/PKGBUILD
2021-12-19 16:37:10 +01:00
pkgBuilds , _ := Glob ( filepath . Join ( conf . Basedir . Work , upstreamDir , "**/" + p . Pkgbase + "/repos/*/PKGBUILD" ) )
2021-07-27 02:43:30 +02:00
var fPkgbuilds [ ] string
for _ , pkgbuild := range pkgBuilds {
2021-12-10 09:26:51 +01:00
mPkgbuild := PKGBUILD ( pkgbuild )
if mPkgbuild . FullRepo ( ) == "trunk" || containsSubStr ( mPkgbuild . FullRepo ( ) , conf . Blacklist . Repo ) {
2021-07-27 02:43:30 +02:00
continue
}
if ! contains ( fPkgbuilds , pkgbuild ) {
fPkgbuilds = append ( fPkgbuilds , pkgbuild )
}
}
if len ( fPkgbuilds ) > 1 {
2021-11-19 22:32:11 +01:00
log . Infof ( "%s: multiple PKGBUILD found, try resolving from mirror" , p . Pkgbase )
2021-10-29 08:52:08 +02:00
dbs , err := h . SyncDBs ( )
if err != nil {
return "" , err
}
2021-11-20 01:02:37 +01:00
buildManager . alpmMutex . Lock ( )
2021-11-19 22:32:11 +01:00
iPackage , err := dbs . FindSatisfier ( p . Pkgbase )
2021-11-20 01:02:37 +01:00
buildManager . alpmMutex . Unlock ( )
2021-10-29 08:52:08 +02:00
if err != nil {
return "" , err
}
pkgloop :
for _ , pkgbuild := range fPkgbuilds {
repo := strings . Split ( filepath . Base ( filepath . Dir ( pkgbuild ) ) , "-" ) [ 0 ]
upstreamA := strings . Split ( filepath . Dir ( pkgbuild ) , "/" )
upstream := upstreamA [ len ( upstreamA ) - 4 ]
switch upstream {
case "upstream-core-extra" :
if iPackage . DB ( ) . Name ( ) == repo && ( repo == "extra" || repo == "core" ) {
fPkgbuilds = [ ] string { pkgbuild }
break pkgloop
}
case "upstream-community" :
if iPackage . DB ( ) . Name ( ) == repo && repo == "community" {
fPkgbuilds = [ ] string { pkgbuild }
break pkgloop
}
}
}
if len ( fPkgbuilds ) > 1 {
2021-11-19 22:32:11 +01:00
return "" , MultiplePKGBUILDError { fmt . Errorf ( "%s: multiple PKGBUILD found: %s" , p . Pkgbase , fPkgbuilds ) }
2021-10-29 08:52:08 +02:00
}
2021-11-19 22:32:11 +01:00
log . Infof ( "%s: resolving successful: MirrorRepo=%s; PKGBUILD chosen: %s" , p . Pkgbase , iPackage . DB ( ) . Name ( ) , fPkgbuilds [ 0 ] )
2021-07-27 02:43:30 +02:00
} else if len ( fPkgbuilds ) == 0 {
2021-12-19 16:37:10 +01:00
return "" , fmt . Errorf ( "%s: no matching PKGBUILD found (searched: %s, canidates: %s)" , p . Pkgbase , filepath . Join ( conf . Basedir . Work , upstreamDir , "**/" + p . Pkgbase + "/repos/*/PKGBUILD" ) , pkgBuilds )
2021-07-27 02:43:30 +02:00
}
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
}
2021-11-20 00:02:53 +01:00
func isPkgFailed ( pkg * BuildPackage ) bool {
if pkg . DbPackage . Version == "" {
2021-11-18 13:22:10 +01:00
return false
2021-07-27 02:43:30 +02:00
}
2021-08-26 13:56:02 +02:00
2021-11-19 22:32:11 +01:00
if err := pkg . genSrcinfo ( ) ; err != nil {
return false
}
2021-11-18 13:22:10 +01:00
if pkg . Version == "" {
pkg . Version = constructVersion ( pkg . Srcinfo . Pkgver , pkg . Srcinfo . Pkgrel , pkg . Srcinfo . Epoch )
2021-08-26 13:56:02 +02:00
}
2021-07-27 02:43:30 +02:00
2021-11-20 00:02:53 +01:00
if alpm . VerCmp ( pkg . DbPackage . Version , pkg . Version ) < 0 {
2021-11-18 13:22:10 +01:00
return false
} else {
2021-11-20 00:02:53 +01:00
return pkg . DbPackage . Status == dbpackage . StatusFailed
2021-11-18 13:22:10 +01:00
}
2021-07-27 02:43:30 +02:00
}
2021-11-19 22:32:11 +01:00
func ( p * BuildPackage ) genSrcinfo ( ) error {
if p . Srcinfo != nil {
return nil
}
cmd := exec . Command ( "sh" , "-c" , "cd " + filepath . Dir ( p . Pkgbuild ) + "&&" + "makepkg --printsrcinfo" )
2021-10-24 06:10:55 +02:00
res , err := cmd . Output ( )
if err != nil {
2021-11-19 22:32:11 +01:00
return err
2021-10-24 06:10:55 +02:00
}
info , err := srcinfo . Parse ( string ( res ) )
if err != nil {
2021-11-19 22:32:11 +01:00
return err
2021-10-24 06:10:55 +02:00
}
2021-11-19 22:32:11 +01:00
p . Srcinfo = info
return nil
2021-10-24 06:10:55 +02:00
}
2021-11-02 08:43:50 +01:00
func setupChroot ( ) error {
2021-12-19 16:37:10 +01:00
if _ , err := os . Stat ( filepath . Join ( conf . Basedir . Work , chrootDir , pristineChroot ) ) ; err == nil {
2021-07-27 02:43:30 +02:00
//goland:noinspection SpellCheckingInspection
2021-12-19 16:37:10 +01:00
cmd := exec . Command ( "arch-nspawn" , filepath . Join ( conf . Basedir . Work , chrootDir , pristineChroot ) , "pacman" , "-Syuu" , "--noconfirm" )
2021-07-27 02:43:30 +02:00
res , err := cmd . CombinedOutput ( )
log . Debug ( string ( res ) )
2021-09-09 00:27:43 +02:00
if err != nil {
2021-11-02 08:43:50 +01:00
return fmt . Errorf ( "Unable to update chroot: %v\n%s" , err , string ( res ) )
2021-09-09 00:27:43 +02:00
}
2021-07-27 02:43:30 +02:00
} else if os . IsNotExist ( err ) {
2021-12-19 16:37:10 +01:00
err := os . MkdirAll ( filepath . Join ( conf . Basedir . Work , chrootDir ) , 0755 )
2021-07-27 02:43:30 +02:00
check ( err )
2021-12-19 16:37:10 +01:00
cmd := exec . Command ( "mkarchroot" , "-C" , pacmanConf , filepath . Join ( conf . Basedir . Work , chrootDir , pristineChroot ) , "base-devel" )
2021-07-27 02:43:30 +02:00
res , err := cmd . CombinedOutput ( )
log . Debug ( string ( res ) )
2021-09-09 00:04:24 +02:00
if err != nil {
2021-11-02 08:43:50 +01:00
return fmt . Errorf ( "Unable to create chroot: %v\n%s" , err , string ( res ) )
2021-09-09 00:04:24 +02:00
}
2021-07-27 02:43:30 +02:00
} else {
2021-11-02 08:43:50 +01:00
return err
2021-07-27 02:43:30 +02:00
}
2021-11-02 08:43:50 +01:00
return nil
2021-07-27 02:43:30 +02:00
}
2021-12-10 09:26:51 +01:00
func ( path * Package ) DBPackage ( ) ( * ent . DbPackage , error ) {
2021-12-20 18:40:20 +01:00
return path . DBPackageIsolated ( path . MArch ( ) , path . Repo ( ) )
}
func ( path * Package ) DBPackageIsolated ( march string , repo dbpackage . Repository ) ( * ent . DbPackage , error ) {
2021-12-05 12:51:22 +01:00
dbPkg , err := db . DbPackage . Query ( ) . Where ( func ( s * sql . Selector ) {
s . Where (
sql . And (
2021-12-10 09:26:51 +01:00
sqljson . ValueContains ( dbpackage . FieldPackages , path . Name ( ) ) ,
2021-12-20 18:40:20 +01:00
sql . EQ ( dbpackage . FieldMarch , march ) ,
sql . EQ ( dbpackage . FieldRepository , repo ) ) ,
2021-12-05 12:51:22 +01:00
)
} ) . Only ( context . Background ( ) )
2021-10-24 05:49:57 +02:00
if err != nil {
switch err . ( type ) {
2021-09-15 17:33:22 +02:00
case * ent . NotFoundError :
2021-12-10 09:26:51 +01:00
log . Debugf ( "Not found in database: %s" , path . Name ( ) )
return nil , fmt . Errorf ( "package not found in DB: %s" , path . Name ( ) )
2021-09-15 17:33:22 +02:00
default :
2021-11-19 22:32:11 +01:00
return nil , err
2021-09-15 17:33:22 +02:00
}
}
2021-12-05 12:51:22 +01:00
return dbPkg , nil
2021-09-15 17:33:22 +02:00
}
2021-12-10 09:26:51 +01:00
func ( path Package ) hasValidSignature ( ) ( bool , error ) {
2021-11-19 22:32:11 +01:00
cmd := exec . Command ( "gpg" , "--verify" , string ( path ) + ".sig" )
2021-09-15 17:33:22 +02:00
res , err := cmd . CombinedOutput ( )
log . Debug ( string ( res ) )
2021-11-19 22:32:11 +01:00
if cmd . ProcessState . ExitCode ( ) == 2 || cmd . ProcessState . ExitCode ( ) == 1 {
2021-09-15 17:33:22 +02:00
return false , nil
} else if cmd . ProcessState . ExitCode ( ) == 0 {
return true , nil
} else if err != nil {
return false , err
}
return false , nil
}
2021-11-19 23:01:19 +01:00
func housekeeping ( repo string , wg * sync . WaitGroup ) error {
defer wg . Done ( )
log . Debugf ( "[%s] Start housekeeping" , repo )
packages , err := Glob ( filepath . Join ( conf . Basedir . Repo , repo , "/**/*.pkg.tar.zst" ) )
if err != nil {
return err
}
for _ , path := range packages {
2021-12-10 09:26:51 +01:00
mPackage := Package ( path )
2021-11-28 18:41:53 +01:00
2021-12-10 09:26:51 +01:00
dbPkg , err := mPackage . DBPackage ( )
2021-11-19 22:32:11 +01:00
if err != nil {
2021-11-20 01:02:37 +01:00
log . Infof ( "[HK/%s] removing orphan %s" , repo , filepath . Base ( path ) )
pkg := & BuildPackage {
2021-12-10 09:26:51 +01:00
FullRepo : mPackage . FullRepo ( ) ,
2021-11-20 01:02:37 +01:00
PkgFiles : [ ] string { path } ,
2021-12-10 09:26:51 +01:00
March : mPackage . MArch ( ) ,
2021-11-20 01:02:37 +01:00
}
2021-12-20 16:04:13 +01:00
buildManager . repoPurge [ pkg . FullRepo ] <- [ ] * BuildPackage { pkg }
2021-11-19 23:01:19 +01:00
continue
2021-11-19 22:32:11 +01:00
}
2021-11-19 23:01:19 +01:00
pkg := & BuildPackage {
2021-11-20 00:02:53 +01:00
Pkgbase : dbPkg . Pkgbase ,
2021-12-10 09:26:51 +01:00
Repo : mPackage . Repo ( ) ,
FullRepo : mPackage . FullRepo ( ) ,
2021-11-20 00:02:53 +01:00
DbPackage : dbPkg ,
2021-12-10 09:26:51 +01:00
March : mPackage . MArch ( ) ,
2021-11-19 23:01:19 +01:00
}
2021-09-15 17:33:22 +02:00
2021-11-19 23:01:19 +01:00
var upstream string
2021-11-20 00:02:53 +01:00
switch pkg . DbPackage . Repository {
2021-11-19 23:01:19 +01:00
case dbpackage . RepositoryCore , dbpackage . RepositoryExtra :
upstream = "upstream-core-extra"
case dbpackage . RepositoryCommunity :
upstream = "upstream-community"
}
2021-12-19 16:37:10 +01:00
pkg . Pkgbuild = filepath . Join ( conf . Basedir . Work , upstreamDir , upstream , dbPkg . Pkgbase , "repos" , pkg . DbPackage . Repository . String ( ) + "-" + conf . Arch , "PKGBUILD" )
2021-11-19 22:32:11 +01:00
2021-11-28 18:41:53 +01:00
// check if package is still part of repo
dbs , err := alpmHandle . SyncDBs ( )
if err != nil {
return err
}
buildManager . alpmMutex . Lock ( )
pkgResolved , err := dbs . FindSatisfier ( dbPkg . Packages [ 0 ] )
buildManager . alpmMutex . Unlock ( )
if err != nil || pkgResolved . DB ( ) . Name ( ) != pkg . DbPackage . Repository . String ( ) || pkgResolved . DB ( ) . Name ( ) != pkg . Repo . String ( ) {
// package not found on mirror/db -> not part of any repo anymore
log . Infof ( "[HK/%s/%s] not included in repo" , pkg . FullRepo , pkg . Pkgbase )
2021-12-20 16:04:13 +01:00
buildManager . repoPurge [ pkg . FullRepo ] <- [ ] * BuildPackage { pkg }
2021-11-28 18:41:53 +01:00
err = db . DbPackage . DeleteOne ( pkg . DbPackage ) . Exec ( context . Background ( ) )
if err != nil {
return err
}
continue
}
2021-11-19 23:01:19 +01:00
// check if pkg signature is valid
2021-12-10 09:26:51 +01:00
valid , err := mPackage . hasValidSignature ( )
2021-11-19 23:01:19 +01:00
if err != nil {
return err
}
if ! valid {
log . Infof ( "[HK/%s/%s] invalid package signature" , pkg . FullRepo , pkg . Pkgbase )
2021-12-20 16:04:13 +01:00
buildManager . repoPurge [ pkg . FullRepo ] <- [ ] * BuildPackage { pkg }
2021-11-19 23:01:19 +01:00
continue
}
2021-11-19 22:32:11 +01:00
2021-11-19 23:01:19 +01:00
// compare db-version with repo version
repoVer , err := pkg . repoVersion ( )
2021-12-21 03:39:10 +01:00
if err == nil && repoVer != dbPkg . RepoVersion {
2021-11-19 23:01:19 +01:00
log . Infof ( "[HK/%s/%s] update %s->%s in db" , pkg . FullRepo , pkg . Pkgbase , dbPkg . RepoVersion , repoVer )
2021-12-20 18:40:20 +01:00
pkg . DbPackage , err = pkg . DbPackage . Update ( ) . SetRepoVersion ( repoVer ) . ClearHash ( ) . Save ( context . Background ( ) )
2021-11-19 22:32:11 +01:00
if err != nil {
2021-11-19 23:01:19 +01:00
return err
2021-09-15 17:33:22 +02:00
}
2021-11-19 23:01:19 +01:00
}
2021-10-24 05:49:57 +02:00
2021-11-19 23:01:19 +01:00
// TODO: check split packages
2021-09-15 17:33:22 +02:00
}
2021-12-10 09:26:51 +01:00
// check all dbpackages for existence
dbpackages , err := db . DbPackage . Query ( ) . All ( context . Background ( ) )
if err != nil {
return err
}
for _ , dbpkg := range dbpackages {
pkg := & BuildPackage {
Pkgbase : dbpkg . Pkgbase ,
Repo : dbpkg . Repository ,
March : dbpkg . March ,
FullRepo : dbpkg . Repository . String ( ) + "-" + dbpkg . March ,
DbPackage : dbpkg ,
}
if ! pkg . isAvailable ( alpmHandle ) {
log . Infof ( "[HK/%s/%s] not found on mirror, removing" , pkg . FullRepo , pkg . Pkgbase )
err = db . DbPackage . DeleteOne ( dbpkg ) . Exec ( context . Background ( ) )
if err != nil {
return err
}
}
}
2021-09-15 17:33:22 +02:00
return nil
}
2021-11-19 22:32:11 +01:00
func ( p * BuildPackage ) findPkgFiles ( ) error {
pkgs , err := os . ReadDir ( filepath . Join ( conf . Basedir . Repo , p . FullRepo , "os" , conf . Arch ) )
if err != nil {
return err
}
var realPkgs [ ] string
2021-11-20 00:02:53 +01:00
for _ , realPkg := range p . DbPackage . Packages {
realPkgs = append ( realPkgs , realPkg )
2021-11-19 22:32:11 +01:00
}
2021-07-27 02:43:30 +02:00
var fPkg [ ] string
for _ , file := range pkgs {
if ! file . IsDir ( ) && ! strings . HasSuffix ( file . Name ( ) , ".sig" ) {
matches := rePkgFile . FindStringSubmatch ( file . Name ( ) )
if len ( matches ) > 1 && contains ( realPkgs , matches [ 1 ] ) {
2021-11-19 22:32:11 +01:00
fPkg = append ( fPkg , filepath . Join ( conf . Basedir . Repo , p . FullRepo , "os" , conf . Arch , file . Name ( ) ) )
2021-07-27 02:43:30 +02:00
}
}
}
2021-11-19 22:32:11 +01:00
p . PkgFiles = fPkg
return nil
2021-07-27 02:43:30 +02:00
}
2021-11-20 00:02:53 +01:00
func ( p * BuildPackage ) toDbPackage ( create bool ) {
2021-12-20 17:20:06 +01:00
if p . DbPackage != nil {
return
}
2021-12-07 09:07:29 +01:00
dbPkg , err := db . DbPackage . Query ( ) . Where ( dbpackage . And ( dbpackage . Pkgbase ( p . Pkgbase ) , dbpackage . March ( p . March ) , dbpackage . RepositoryEQ ( p . Repo ) ) ) . Only ( context . Background ( ) )
2021-11-19 22:32:11 +01:00
if err != nil && create {
dbPkg = db . DbPackage . Create ( ) . SetPkgbase ( p . Pkgbase ) . SetMarch ( p . March ) . SetPackages ( packages2slice ( p . Srcinfo . Packages ) ) . SetRepository ( p . Repo ) . SaveX ( context . Background ( ) )
2021-07-27 02:43:30 +02:00
}
2021-11-20 00:02:53 +01:00
p . DbPackage = dbPkg
2021-07-27 02:43:30 +02:00
}
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 {
2021-11-13 20:45:47 +01:00
err := setupMakepkg ( march )
if err != nil {
2021-11-29 10:48:29 +01:00
log . Fatalf ( "Can't generate makepkg for %s: %v" , march , err )
2021-11-13 20:45:47 +01:00
}
2021-11-29 10:48:29 +01:00
buildManager . build [ march ] = make ( chan * BuildPackage , 10000 )
for i := 0 ; i < conf . Build . Worker ; i ++ {
go buildManager . buildWorker ( i , march )
}
2021-07-27 02:43:30 +02:00
for _ , repo := range conf . Repos {
2021-10-25 05:57:43 +02:00
fRepo := fmt . Sprintf ( "%s-%s" , repo , march )
repos = append ( repos , fRepo )
2021-12-20 16:04:13 +01:00
buildManager . repoAdd [ fRepo ] = make ( chan [ ] * BuildPackage , conf . Build . Worker )
buildManager . repoPurge [ fRepo ] = make ( chan [ ] * BuildPackage , 10000 )
2021-10-25 05:57:43 +02:00
go buildManager . repoWorker ( fRepo )
if _ , err := os . Stat ( filepath . Join ( filepath . Join ( conf . Basedir . Repo , fRepo , "os" , conf . Arch ) ) ) ; os . IsNotExist ( err ) {
log . Debugf ( "Creating path %s" , filepath . Join ( conf . Basedir . Repo , fRepo , "os" , conf . Arch ) )
2021-11-04 11:59:57 +01:00
check ( os . MkdirAll ( filepath . Join ( conf . Basedir . Repo , fRepo , "os" , conf . Arch ) , 0755 ) )
2021-07-27 02:43:30 +02:00
}
2021-10-25 05:57:43 +02:00
if i := find ( eRepos , fRepo ) ; i != - 1 {
2021-07-27 02:43:30 +02:00
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
2021-11-13 20:45:47 +01:00
func setupMakepkg ( march string ) error {
2021-12-19 16:37:10 +01:00
lMakepkg := filepath . Join ( conf . Basedir . Work , makepkgDir , fmt . Sprintf ( "makepkg-%s.conf" , march ) )
lMakepkgLTO := filepath . Join ( conf . Basedir . Work , makepkgDir , fmt . Sprintf ( "makepkg-%s-lto.conf" , march ) )
2021-07-27 02:43:30 +02:00
2021-12-19 16:37:10 +01:00
err := os . MkdirAll ( filepath . Join ( conf . Basedir . Work , makepkgDir ) , 0755 )
2021-11-13 20:45:47 +01:00
if err != nil {
return err
}
2021-07-27 02:43:30 +02:00
t , err := os . ReadFile ( makepkgConf )
2021-11-13 20:45:47 +01:00
if err != nil {
return err
}
2021-07-27 02:43:30 +02:00
makepkgStr := string ( t )
makepkgStr = strings . ReplaceAll ( makepkgStr , "-mtune=generic" , "" )
2021-11-21 19:35:58 +01:00
if ! conf . Build . Checks {
2021-11-21 19:30:48 +01:00
makepkgStr = strings . ReplaceAll ( makepkgStr , " check " , " !check " )
}
2021-07-27 02:43:30 +02:00
makepkgStr = strings . ReplaceAll ( makepkgStr , " color " , " !color " )
2021-11-13 20:45:47 +01:00
makepkgStr = strings . ReplaceAll ( makepkgStr , "-O2" , "-O3" )
makepkgStr = strings . ReplaceAll ( makepkgStr , "#MAKEFLAGS=\"-j2\"" , "MAKEFLAGS=\"-j" + strconv . Itoa ( conf . Build . Makej ) + "\"" )
makepkgStr = reMarch . ReplaceAllString ( makepkgStr , "${1}" + march )
2021-11-25 18:10:49 +01:00
makepkgStr = strings . ReplaceAll ( makepkgStr , "#PACKAGER=\"John Doe <john@doe.com>\"" , "PACKAGER=\"ALHP " + march + " <alhp@harting.dev>\"" )
2021-11-13 20:45:47 +01:00
// write non-lto makepkg
err = os . WriteFile ( lMakepkg , [ ] byte ( makepkgStr ) , 0644 )
if err != nil {
return err
}
// Add LTO. Since (lto) not in devtools yet, add it instead.
2021-11-04 11:59:57 +01:00
// See https://git.harting.dev/anonfunc/ALHP.GO/issues/52 for more
2021-11-13 20:45:47 +01:00
makepkgStr = strings . ReplaceAll ( makepkgStr , "!lto" , "" )
2021-11-04 11:59:57 +01:00
makepkgStr = strings . ReplaceAll ( makepkgStr , "!debug" , "!debug lto" )
2021-11-13 20:45:47 +01:00
// Add align-functions=32, see https://github.com/InBetweenNames/gentooLTO/issues/164 for more
makepkgStr = strings . ReplaceAll ( makepkgStr , "-O3" , "-O3 -falign-functions=32" )
2021-11-04 11:59:57 +01:00
2021-11-13 20:45:47 +01:00
// write lto makepkg
err = os . WriteFile ( lMakepkgLTO , [ ] byte ( makepkgStr ) , 0644 )
if err != nil {
return err
}
2021-07-27 02:43:30 +02:00
2021-11-13 20:45:47 +01:00
return nil
2021-07-27 02:43:30 +02:00
}
2021-11-19 22:32:11 +01:00
func ( p * BuildPackage ) isMirrorLatest ( h * alpm . Handle ) ( bool , alpm . IPackage , string , error ) {
2021-07-27 02:43:30 +02:00
dbs , err := h . SyncDBs ( )
if err != nil {
2021-07-29 16:53:15 +02:00
return false , nil , "" , err
2021-07-27 02:43:30 +02:00
}
2021-11-19 22:32:11 +01:00
allDepends := p . Srcinfo . Depends
allDepends = append ( allDepends , p . Srcinfo . MakeDepends ... )
2021-07-27 02:43:30 +02:00
for _ , dep := range allDepends {
2021-08-31 21:13:22 +02:00
buildManager . alpmMutex . Lock ( )
2021-07-27 02:43:30 +02:00
pkg , err := dbs . FindSatisfier ( dep . Value )
2021-08-31 21:13:22 +02:00
buildManager . alpmMutex . Unlock ( )
2021-07-27 02:43:30 +02:00
if err != nil {
2021-08-26 12:59:23 +02:00
return false , nil , "" , UnableToSatisfyError { err }
2021-07-27 02:43:30 +02:00
}
2021-11-19 22:32:11 +01:00
svn2gitVer , err := ( & BuildPackage {
2021-07-27 02:43:30 +02:00
Pkgbase : pkg . Base ( ) ,
2021-11-19 22:32:11 +01:00
} ) . SVN2GITVersion ( h )
2021-07-27 02:43:30 +02:00
if err != nil {
2021-07-29 16:53:15 +02:00
return false , nil , "" , err
2021-07-27 02:43:30 +02:00
}
2021-07-31 01:00:47 +02:00
if svn2gitVer != "" && alpm . VerCmp ( svn2gitVer , pkg . Version ( ) ) > 0 {
2021-07-29 16:53:15 +02:00
return false , pkg , svn2gitVer , nil
2021-07-27 02:43:30 +02:00
}
}
2021-07-29 16:53:15 +02:00
return true , nil , "" , nil
2021-07-27 02:43:30 +02:00
}
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
}