mirror of
https://github.com/rocky-linux/srpmproc.git
synced 2024-12-04 18:36:26 +00:00
add directive support
This commit is contained in:
parent
1dcceac63a
commit
e4902bda71
2
gen.go
Normal file
2
gen.go
Normal file
@ -0,0 +1,2 @@
|
||||
//go:generate protoc -Iproto --go_opt=paths=source_relative --go_out=pb proto/cfg.proto
|
||||
package srpmproc
|
2
go.mod
2
go.mod
@ -10,5 +10,7 @@ require (
|
||||
github.com/cavaliercoder/go-rpm v0.0.0-20200122174316-8cb9fd9c31a8
|
||||
github.com/go-git/go-billy/v5 v5.0.0
|
||||
github.com/go-git/go-git/v5 v5.2.0
|
||||
github.com/golang/protobuf v1.4.2
|
||||
github.com/spf13/cobra v1.1.1
|
||||
google.golang.org/protobuf v1.25.0
|
||||
)
|
||||
|
21
internal/directives/directives.go
Normal file
21
internal/directives/directives.go
Normal file
@ -0,0 +1,21 @@
|
||||
package directives
|
||||
|
||||
import (
|
||||
"github.com/go-git/go-git/v5"
|
||||
srpmprocpb "github.com/mstg/srpmproc/pb"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func checkAddPrefix(file string) string {
|
||||
if strings.HasPrefix(file, "SOURCES/") ||
|
||||
strings.HasPrefix(file, "SPECS/") {
|
||||
return file
|
||||
}
|
||||
|
||||
return filepath.Join("SOURCES", file)
|
||||
}
|
||||
|
||||
func Apply(cfg *srpmprocpb.Cfg, patchTree *git.Worktree, pushTree *git.Worktree) {
|
||||
replace(cfg, patchTree, pushTree)
|
||||
}
|
54
internal/directives/replace.go
Normal file
54
internal/directives/replace.go
Normal file
@ -0,0 +1,54 @@
|
||||
package directives
|
||||
|
||||
import (
|
||||
"github.com/go-git/go-git/v5"
|
||||
srpmprocpb "github.com/mstg/srpmproc/pb"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
func replace(cfg *srpmprocpb.Cfg, patchTree *git.Worktree, pushTree *git.Worktree) {
|
||||
for _, replace := range cfg.Replace {
|
||||
filePath := checkAddPrefix(replace.File)
|
||||
stat, err := pushTree.Filesystem.Stat(filePath)
|
||||
if replace.File == "" || err != nil {
|
||||
log.Fatalf("file to replace is invalid")
|
||||
}
|
||||
|
||||
err = pushTree.Filesystem.Remove(filePath)
|
||||
if err != nil {
|
||||
log.Fatalf("could not remove old file: %v", err)
|
||||
}
|
||||
|
||||
f, err := pushTree.Filesystem.OpenFile(filePath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, stat.Mode())
|
||||
if err != nil {
|
||||
log.Fatalf("could not open replacement file: %v", err)
|
||||
}
|
||||
|
||||
switch replacing := replace.Replacing.(type) {
|
||||
case *srpmprocpb.Replace_WithFile:
|
||||
fPatch, err := patchTree.Filesystem.OpenFile(replacing.WithFile, os.O_RDONLY, 0644)
|
||||
if err != nil {
|
||||
log.Fatalf("could not open replacing file: %v", err)
|
||||
}
|
||||
|
||||
replacingBytes, err := ioutil.ReadAll(fPatch)
|
||||
if err != nil {
|
||||
log.Fatalf("could not read replacing file: %v", err)
|
||||
}
|
||||
|
||||
_, err = f.Write(replacingBytes)
|
||||
if err != nil {
|
||||
log.Fatalf("could not write replacing file: %v", err)
|
||||
}
|
||||
break
|
||||
case *srpmprocpb.Replace_WithInline:
|
||||
_, err := f.Write([]byte(replacing.WithInline))
|
||||
if err != nil {
|
||||
log.Fatalf("could not write inline replacement: %v", err)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
@ -2,19 +2,28 @@ package internal
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/bluekeyes/go-gitdiff/gitdiff"
|
||||
"github.com/go-git/go-billy/v5/memfs"
|
||||
"github.com/go-git/go-git/v5"
|
||||
"github.com/go-git/go-git/v5/config"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/storage/memory"
|
||||
"github.com/mstg/srpmproc/internal/directives"
|
||||
srpmprocpb "github.com/mstg/srpmproc/pb"
|
||||
"google.golang.org/protobuf/encoding/prototext"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func srpmPatches(w *git.Worktree) {
|
||||
func srpmPatches(patchTree *git.Worktree, pushTree *git.Worktree) {
|
||||
// check SRPM patches
|
||||
_, err := w.Filesystem.Stat("ROCKY/SRPM")
|
||||
_, err := patchTree.Filesystem.Stat("ROCKY/SRPM")
|
||||
if err == nil {
|
||||
// iterate through patches
|
||||
infos, err := w.Filesystem.ReadDir("ROCKY/SRPM")
|
||||
infos, err := patchTree.Filesystem.ReadDir("ROCKY/SRPM")
|
||||
if err != nil {
|
||||
log.Fatalf("could not walk patches: %v", err)
|
||||
}
|
||||
@ -28,7 +37,7 @@ func srpmPatches(w *git.Worktree) {
|
||||
log.Printf("applying %s", info.Name())
|
||||
filePath := filepath.Join("ROCKY/SRPM", info.Name())
|
||||
|
||||
patch, err := w.Filesystem.Open(filePath)
|
||||
patch, err := patchTree.Filesystem.Open(filePath)
|
||||
if err != nil {
|
||||
log.Fatalf("could not open patch file %s: %v", info.Name(), err)
|
||||
}
|
||||
@ -44,7 +53,7 @@ func srpmPatches(w *git.Worktree) {
|
||||
}
|
||||
var output bytes.Buffer
|
||||
if !patchedFile.IsDelete && !patchedFile.IsNew {
|
||||
patchSubjectFile, err := w.Filesystem.Open(srcPath)
|
||||
patchSubjectFile, err := pushTree.Filesystem.Open(srcPath)
|
||||
if err != nil {
|
||||
log.Fatalf("could not open patch subject: %v", err)
|
||||
}
|
||||
@ -56,11 +65,11 @@ func srpmPatches(w *git.Worktree) {
|
||||
}
|
||||
|
||||
oldName := filepath.Join("SOURCES", patchedFile.OldName)
|
||||
_ = w.Filesystem.Remove(oldName)
|
||||
_ = w.Filesystem.Remove(srcPath)
|
||||
_ = pushTree.Filesystem.Remove(oldName)
|
||||
_ = pushTree.Filesystem.Remove(srcPath)
|
||||
|
||||
if patchedFile.IsNew {
|
||||
newFile, err := w.Filesystem.Create(srcPath)
|
||||
newFile, err := pushTree.Filesystem.Create(srcPath)
|
||||
if err != nil {
|
||||
log.Fatalf("could not create new file: %v", err)
|
||||
}
|
||||
@ -72,13 +81,13 @@ func srpmPatches(w *git.Worktree) {
|
||||
if err != nil {
|
||||
log.Fatalf("could not write post-patch file: %v", err)
|
||||
}
|
||||
_, err = w.Add(srcPath)
|
||||
_, err = pushTree.Add(srcPath)
|
||||
if err != nil {
|
||||
log.Fatalf("could not add file %s to git: %v", srcPath, err)
|
||||
}
|
||||
log.Printf("git add %s", srcPath)
|
||||
} else if !patchedFile.IsDelete {
|
||||
newFile, err := w.Filesystem.Create(srcPath)
|
||||
newFile, err := pushTree.Filesystem.Create(srcPath)
|
||||
if err != nil {
|
||||
log.Fatalf("could not create post-patch file: %v", err)
|
||||
}
|
||||
@ -86,13 +95,13 @@ func srpmPatches(w *git.Worktree) {
|
||||
if err != nil {
|
||||
log.Fatalf("could not write post-patch file: %v", err)
|
||||
}
|
||||
_, err = w.Add(srcPath)
|
||||
_, err = pushTree.Add(srcPath)
|
||||
if err != nil {
|
||||
log.Fatalf("could not add file %s to git: %v", srcPath, err)
|
||||
}
|
||||
log.Printf("git add %s", srcPath)
|
||||
} else {
|
||||
_, err = w.Remove(oldName)
|
||||
_, err = pushTree.Remove(oldName)
|
||||
if err != nil {
|
||||
log.Fatalf("could not remove file %s to git: %v", oldName, err)
|
||||
}
|
||||
@ -100,7 +109,7 @@ func srpmPatches(w *git.Worktree) {
|
||||
}
|
||||
}
|
||||
|
||||
_, err = w.Add(filePath)
|
||||
_, err = pushTree.Add(filePath)
|
||||
if err != nil {
|
||||
log.Fatalf("could not add file %s to git: %v", filePath, err)
|
||||
}
|
||||
@ -109,10 +118,110 @@ func srpmPatches(w *git.Worktree) {
|
||||
}
|
||||
}
|
||||
|
||||
func executePatches(w *git.Worktree) {
|
||||
// check if patches exist
|
||||
_, err := w.Filesystem.Stat("ROCKY")
|
||||
func cfgPatches(patchTree *git.Worktree, pushTree *git.Worktree) {
|
||||
// check CFG patches
|
||||
_, err := patchTree.Filesystem.Stat("ROCKY/CFG")
|
||||
if err == nil {
|
||||
srpmPatches(w)
|
||||
// iterate through patches
|
||||
infos, err := patchTree.Filesystem.ReadDir("ROCKY/CFG")
|
||||
if err != nil {
|
||||
log.Fatalf("could not walk patches: %v", err)
|
||||
}
|
||||
|
||||
for _, info := range infos {
|
||||
// can only process .cfg files
|
||||
if !strings.HasSuffix(info.Name(), ".cfg") {
|
||||
continue
|
||||
}
|
||||
|
||||
log.Printf("applying directive %s", info.Name())
|
||||
filePath := filepath.Join("ROCKY/CFG", info.Name())
|
||||
directive, err := patchTree.Filesystem.Open(filePath)
|
||||
if err != nil {
|
||||
log.Fatalf("could not open directive file %s: %v", info.Name(), err)
|
||||
}
|
||||
directiveBytes, err := ioutil.ReadAll(directive)
|
||||
if err != nil {
|
||||
log.Fatalf("could not read directive file: %v", err)
|
||||
}
|
||||
|
||||
var cfg srpmprocpb.Cfg
|
||||
err = prototext.Unmarshal(directiveBytes, &cfg)
|
||||
if err != nil {
|
||||
log.Fatalf("could not unmarshal cfg file: %v", err)
|
||||
}
|
||||
|
||||
directives.Apply(&cfg, patchTree, pushTree)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func applyPatches(patchTree *git.Worktree, pushTree *git.Worktree) {
|
||||
// check if patches exist
|
||||
_, err := patchTree.Filesystem.Stat("ROCKY")
|
||||
if err == nil {
|
||||
srpmPatches(patchTree, pushTree)
|
||||
cfgPatches(patchTree, pushTree)
|
||||
}
|
||||
}
|
||||
|
||||
func executePatches(pd *ProcessData, md *modeData) {
|
||||
// fetch patch repository
|
||||
repo, err := git.Init(memory.NewStorage(), memfs.New())
|
||||
if err != nil {
|
||||
log.Fatalf("could not create new dist repo: %v", err)
|
||||
}
|
||||
w, err := repo.Worktree()
|
||||
if err != nil {
|
||||
log.Fatalf("could not get dist worktree: %v", err)
|
||||
}
|
||||
|
||||
remoteUrl := fmt.Sprintf("%s/patch/%s.git", pd.UpstreamPrefix, md.rpmFile.Name())
|
||||
refspec := config.RefSpec(fmt.Sprintf("+refs/heads/*:refs/remotes/origin/*"))
|
||||
|
||||
_, err = repo.CreateRemote(&config.RemoteConfig{
|
||||
Name: "origin",
|
||||
URLs: []string{remoteUrl},
|
||||
Fetch: []config.RefSpec{refspec},
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("could not create remote: %v", err)
|
||||
}
|
||||
|
||||
err = repo.Fetch(&git.FetchOptions{
|
||||
RemoteName: "origin",
|
||||
RefSpecs: []config.RefSpec{refspec},
|
||||
Auth: pd.Authenticator,
|
||||
})
|
||||
|
||||
refName := plumbing.NewBranchReferenceName(md.pushBranch)
|
||||
log.Printf("set reference to ref: %s", refName)
|
||||
|
||||
if err != nil {
|
||||
// no patches active
|
||||
log.Println("info: patch repo not found")
|
||||
return
|
||||
} else {
|
||||
err = w.Checkout(&git.CheckoutOptions{
|
||||
Branch: plumbing.NewRemoteReferenceName("origin", "master"),
|
||||
Force: true,
|
||||
})
|
||||
// common patches found, apply them
|
||||
if err == nil {
|
||||
applyPatches(w, md.worktree)
|
||||
} else {
|
||||
log.Println("info: no common patches found")
|
||||
}
|
||||
|
||||
err = w.Checkout(&git.CheckoutOptions{
|
||||
Branch: plumbing.NewRemoteReferenceName("origin", md.pushBranch),
|
||||
Force: true,
|
||||
})
|
||||
// branch specific patches found, apply them
|
||||
if err == nil {
|
||||
applyPatches(w, md.worktree)
|
||||
} else {
|
||||
log.Println("info: no branch specific patches found")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ func ProcessRPM(pd *ProcessData) {
|
||||
md.repo = repo
|
||||
md.worktree = w
|
||||
|
||||
executePatches(w)
|
||||
executePatches(pd, md)
|
||||
|
||||
// get ignored files hash and add to .{name}.metadata
|
||||
metadataFile := fmt.Sprintf(".%s.metadata", rpmFile.Name())
|
||||
|
24
proto/cfg.proto
Normal file
24
proto/cfg.proto
Normal file
@ -0,0 +1,24 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option go_package = "github.com/mstg/srpmproc/pb;srpmprocpb";
|
||||
|
||||
package srpmproc;
|
||||
|
||||
// Replace directive replaces literal files with other files.
|
||||
// Replacing content can either be inline or in the same patch-tree.
|
||||
message Replace {
|
||||
// required - replaced file
|
||||
string file = 1;
|
||||
|
||||
oneof replacing {
|
||||
// replace with in-tree file
|
||||
string with_file = 2;
|
||||
|
||||
// replace with inline content
|
||||
string with_inline = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message Cfg {
|
||||
repeated Replace replace = 1;
|
||||
}
|
Loading…
Reference in New Issue
Block a user