diff --git a/config_dist.yaml b/config_dist.yaml index 3189049..3fca74f 100644 --- a/config_dist.yaml +++ b/config_dist.yaml @@ -8,6 +8,18 @@ svn2git: upstream-core-extra: "https://github.com/archlinux/svntogit-packages.git" upstream-community: "https://github.com/archlinux/svntogit-community.git" +kernel_to_patch: + - linux + - linux-lts + - linux-zen + - linux-hardened + +kernel_patches: + 4.19: "https://raw.githubusercontent.com/graysky2/kernel_compiler_patch/master/more-uarches-for-kernel-4.19-5.4.patch" + 5.5: "none" + 5.8: "https://raw.githubusercontent.com/graysky2/kernel_compiler_patch/master/more-uarches-for-kernel-5.8-5.14.patch" + 5.15: "https://raw.githubusercontent.com/graysky2/kernel_compiler_patch/master/more-uarches-for-kernel-5.15%2B.patch" + db: driver: pgx connect_to: "postgres://username:password@localhost:5432/database_name" diff --git a/main.go b/main.go index 70bb51b..8bde6e8 100644 --- a/main.go +++ b/main.go @@ -72,6 +72,17 @@ func (b *BuildManager) buildWorker(id int) { b.buildWG.Done() continue } + + if contains(conf.KernelToPatch, pkg.Pkgbase) { + err = pkg.prepareKernelPatches() + if err != nil { + log.Warningf("[%s/%s] Failed to modify PKGBUILD for kernel patch: %v", pkg.FullRepo, pkg.Pkgbase, err) + pkg.DbPackage.Update().SetStatus(dbpackage.StatusFailed).SetSkipReason("failed to apply patch").SetHash(pkg.Hash).ExecX(context.Background()) + b.buildWG.Done() + continue + } + } + pkg.PkgFiles = []string{} ltoDisabled := false @@ -113,7 +124,7 @@ func (b *BuildManager) buildWorker(id int) { continue } - log.Warningf("[%s/%s] Build failed, exit code %d", pkg.FullRepo, pkg.Pkgbase, cmd.ProcessState.ExitCode()) + log.Warningf("[%s/%s] Build failed (%d)", pkg.FullRepo, pkg.Pkgbase, cmd.ProcessState.ExitCode()) check(os.MkdirAll(filepath.Join(conf.Basedir.Repo, "logs"), 0755)) check(os.WriteFile(filepath.Join(conf.Basedir.Repo, "logs", pkg.Pkgbase+".log"), out.Bytes(), 0644)) @@ -452,7 +463,7 @@ func (b *BuildManager) repoWorker(repo string) { res, err := cmd.CombinedOutput() log.Debug(string(res)) if err != nil && cmd.ProcessState.ExitCode() == 1 { - log.Debugf("Deleting package %s failed: Package not found in repo-database", pkg.Pkgbase) + log.Warningf("Error while deleting package %s: %s", pkg.Pkgbase, string(res)) } if pkg.DbPackage != nil { diff --git a/utils.go b/utils.go index 0fde319..c360644 100644 --- a/utils.go +++ b/utils.go @@ -4,6 +4,7 @@ import ( "ALHP.go/ent" "ALHP.go/ent/dbpackage" "context" + "crypto/sha256" "encoding/hex" "fmt" "github.com/Jguer/go-alpm/v2" @@ -13,6 +14,7 @@ import ( "io" "io/fs" "lukechampine.com/blake3" + "net/http" "os" "os/exec" "path/filepath" @@ -32,9 +34,11 @@ const ( ) var ( - reMarch = regexp.MustCompile(`(-march=)(.+?) `) - rePkgRel = regexp.MustCompile(`(?m)^pkgrel\s*=\s*(.+)$`) - rePkgFile = regexp.MustCompile(`^(.+)(?:-.+){2}-(?:x86_64|any)\.pkg\.tar\.zst(?:\.sig)*$`) + 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)*$`) ) type BuildPackage struct { @@ -96,6 +100,8 @@ type Conf struct { Skipped, Queued, Latest, Failed, Signing, Building, Unknown string } } + KernelPatches map[string]string `yaml:"kernel_patches"` + KernelToPatch []string `yaml:"kernel_to_patch"` } type Globs []string @@ -223,6 +229,104 @@ func (p *BuildPackage) increasePkgRel() error { return nil } +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 + for k, _ := range conf.KernelPatches { + if alpm.VerCmp(p.Srcinfo.Pkgver, k) >= 0 && alpm.VerCmp(k, curVer) >= 0 { + curVer = k + } + } + log.Debugf("[KP] choose patch %s for kernel %s", curVer, p.Srcinfo.Pkgver) + + if curVer == "none" { + return nil + } + + // add patch to source-array + orgSource := rePkgSource.FindStringSubmatch(string(fStr)) + if orgSource == nil || len(orgSource) < 1 { + return fmt.Errorf("no source=() found") + } + + sources := strings.Split(orgSource[1], "\n") + sources = append(sources, fmt.Sprintf("\"%s\"", conf.KernelPatches[curVer])) + + newPKGBUILD := rePkgSource.ReplaceAllLiteralString(string(fStr), fmt.Sprintf("source=(%s)", strings.Join(sources, "\n"))) + + // 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 { + 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 + } + + orgSums := rePkgSum.FindStringSubmatch(newPKGBUILD) + if orgSums == nil || len(orgSums) < 1 { + return fmt.Errorf("no sha256sums=() found") + } + + sums := strings.Split(orgSums[1], "\n") + sums = append(sums, fmt.Sprintf("'%s'", hex.EncodeToString(h.Sum(nil)))) + + newPKGBUILD = rePkgSum.ReplaceAllLiteralString(newPKGBUILD, fmt.Sprintf("sha256sums=(\n%s\n)", strings.Join(sums, "\n"))) + + // enable config option + switch { + case strings.Contains(p.March, "v4"): + newPKGBUILD = strings.Replace(newPKGBUILD, "make olddefconfig\n", "echo GENERIC_CPU4=y >> .config\nmake olddefconfig\n", 1) + case strings.Contains(p.March, "v3"): + newPKGBUILD = strings.Replace(newPKGBUILD, "make olddefconfig\n", "echo GENERIC_CPU3=y >> .config\nmake olddefconfig\n", 1) + case strings.Contains(p.March, "v2"): + newPKGBUILD = strings.Replace(newPKGBUILD, "make olddefconfig\n", "echo GENERIC_CPU2=y >> .config\nmake olddefconfig\n", 1) + } + + // 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 + } + + log.Debug(newPKGBUILD) + + return nil +} + func packages2slice(pkgs interface{}) []string { switch v := pkgs.(type) { case []srcinfo.Package: @@ -562,7 +666,7 @@ func housekeeping(repo string, wg *sync.WaitGroup) error { if err != nil { log.Infof("[HK/%s/%s] package not present on disk", pkg.FullRepo, pkg.Pkgbase) // error means package was not found -> delete version & hash from db so rebuild can happen - err := pkg.DbPackage.Update().ClearHash().ClearRepoVersion().Exec(context.Background()) + err := pkg.DbPackage.Update().ClearStatus().ClearHash().ClearRepoVersion().Exec(context.Background()) if err != nil { return err }