"gopkg.in/yaml.v3"
"go.fuhry.dev/runtime/constants"
+ "go.fuhry.dev/runtime/utils/hashset"
"go.fuhry.dev/runtime/utils/subst"
)
fmt.Fprintf(os.Stderr, fmtstr+"\n", args...)
}
+type RenameRule struct {
+ Source string `yaml:"src" json:"src" jsonschema:"title=source path"`
+ Destination string `yaml:"dst" json:"dst" jsonschema:"title=destination path"`
+}
+
type NfpmConfig struct {
*nfpm.Config
- Vars subst.KV `yaml:"vars" json:"vars" jsonschema:"title=map of context vars to inject into subst"`
+ Vars subst.KV `yaml:"vars" json:"vars" jsonschema:"title=map of context vars to inject into subst"`
+ RenameRules []*RenameRule `yaml:"rename_rules" json:"rename_rules" jsonschema:"title=dictionary of files to rename as source: target"`
files map[string]struct{} `yaml:"-" json:"-"`
}
return out, nil
}
-func (c *NfpmConfig) DiscoverBinaries(bazelBinDir string) error {
+func (c *NfpmConfig) DiscoverBinaries(bazelBinDirs []string) error {
wd, err := os.Getwd()
if err != nil {
return err
}
- cmdDir, err := os.ReadDir(path.Join(wd, bazelBinDir, "cmd"))
- if err != nil {
- return err
+ var entries []os.DirEntry
+ dedup := hashset.NewHashSet[string]()
+
+ for _, dir := range bazelBinDirs {
+ if dirEntries, err := os.ReadDir(path.Join(wd, dir, "cmd")); err == nil {
+ entries = append(entries, dirEntries...)
+ }
}
- for _, entry := range cmdDir {
+ for _, entry := range entries {
if entry.Name() == "." || entry.Name() == ".." || !entry.IsDir() {
continue
}
exe := executable(entry.Name())
+ if dedup.Contains(exe.pkgPath(c.Vars)) {
+ continue
+ }
- exePath := exe.buildPath(bazelBinDir)
+ var exePath string
+ for _, bazelBinDir := range bazelBinDirs {
+ checkPath := exe.buildPath(bazelBinDir)
- if _, ok := c.files[exePath]; !ok {
- debug("exe not allowlisted in includes: %s", exePath)
+ if _, ok := c.files[checkPath]; ok {
+ exePath = checkPath
+ break
+ }
+ }
+
+ if exePath == "" {
+ debug("exe not allowlisted in includes: %s", entry.Name())
continue
}
continue
}
+ pkgPath := exe.pkgPath(c.Vars)
+ dedup.Add(pkgPath)
+
c.Config.Contents = append(c.Config.Contents, &files.Content{
Source: exePath,
- Destination: exe.pkgPath(c.Vars),
+ Destination: pkgPath,
FileInfo: &files.ContentFileInfo{
Owner: "root",
Group: "root",
return out, nil
}
-func (c *NfpmConfig) DiscoverSystemdUnits(bazelBinDir string) error {
- unitFiles, err := recursiveDirectoryScan(
- bazelBinDir,
- func(e os.DirEntry) bool {
- if e.IsDir() {
- return false
- }
+func (c *NfpmConfig) DiscoverSystemdUnits(bazelBinDirs []string) error {
+ var unitFiles []string
- return systemdUnitFilename.MatchString(e.Name())
- },
- )
- if err != nil {
- return err
+ for _, bazelBinDir := range bazelBinDirs {
+ files, err := recursiveDirectoryScan(
+ bazelBinDir,
+ func(e os.DirEntry) bool {
+ if e.IsDir() {
+ return false
+ }
+
+ return systemdUnitFilename.MatchString(e.Name())
+ },
+ )
+ if err == nil {
+ unitFiles = append(unitFiles, files...)
+ }
}
for _, f := range unitFiles {
return nil
}
+func (c *NfpmConfig) ProcessRenameRules() error {
+ for _, r := range c.RenameRules {
+ found := false
+ src, err := subst.Eval(c.Vars, r.Source)
+ if err != nil {
+ return err
+ }
+ dst, err := subst.Eval(c.Vars, r.Destination)
+ if err != nil {
+ return err
+ }
+
+ for _, file := range c.Config.Contents {
+ if file.Destination == src {
+ found = true
+ file.Destination = dst
+ break
+ }
+
+ debug("destination: %s", file.Destination)
+ }
+
+ if !found {
+ return fmt.Errorf("src %q not found among contents", src)
+ }
+ }
+ return nil
+}
+
func (c *NfpmConfig) Generate() (string, error) {
out, err := yaml.Marshal(c.Config)
if err != nil {
"flag"
"fmt"
"os"
+ "slices"
"strings"
"go.fuhry.dev/runtime/utils/subst"
panic(err)
}
- bazelBinDir := ""
+ var bazelBinDirs []string
if outFile != nil && *outFile != "" {
// pushd to the bazel-bin dir `bazel-bin/[arch]/bin` directory
parts := strings.Split(*outFile, "/")
if len(parts) >= 3 {
- bazelBinDir = strings.Join(parts[:3], "/")
+ bazelBinDirs = append(bazelBinDirs, strings.Join(parts[:3], "/"))
}
}
+ for _, incl := range includes {
+ if strings.HasPrefix(incl, "bazel-out/") {
+ parts := strings.Split(incl, "/")
+ if len(parts) >= 3 {
+ candidate := strings.Join(parts[:3], "/")
+ if !slices.Contains(bazelBinDirs, candidate) {
+ bazelBinDirs = append(bazelBinDirs, candidate)
+ }
+ }
+ }
+ }
+
+ debug("loaded nfpm config template: %s\ncwd: %s\nout: %s\nbazelBinDirs: %+v\n",
+ *yamlFile, wd, *outFile, bazelBinDirs)
- debug("loaded nfpm config template: %s\ncwd: %s\nout: %s\n",
- *yamlFile, wd, *outFile)
+ if err := c.DiscoverBinaries(bazelBinDirs); err != nil {
+ panic(err)
+ }
- if err := c.DiscoverBinaries(bazelBinDir); err != nil {
+ if err := c.DiscoverSystemdUnits(bazelBinDirs); err != nil {
panic(err)
}
- if err := c.DiscoverSystemdUnits(bazelBinDir); err != nil {
+ if err := c.ProcessRenameRules(); err != nil {
panic(err)
}