From 7ba201589be597a8648d6fe9ba7575195d40c077 Mon Sep 17 00:00:00 2001 From: Nicholas Dille Date: Thu, 11 Jul 2024 13:37:25 +0200 Subject: [PATCH] Add file templating #318 --- cmd/uniget/install.go | 57 ++++++++++++++++++++++++++++++++++++-- cmd/uniget/self-upgrade.go | 2 +- cmd/uniget/uninstall.go | 1 + cmd/uniget/update.go | 2 +- pkg/archive/new.go | 5 +++- pkg/tool/install.go | 8 +++--- 6 files changed, 66 insertions(+), 9 deletions(-) diff --git a/cmd/uniget/install.go b/cmd/uniget/install.go index bb9eb49d..11fd39f6 100644 --- a/cmd/uniget/install.go +++ b/cmd/uniget/install.go @@ -2,8 +2,10 @@ package main import ( "fmt" + "html/template" "os" "strings" + "syscall" "github.com/pterm/pterm" "github.com/spf13/cobra" @@ -340,10 +342,10 @@ func installTools(requestedTools tool.Tools, check bool, plan bool, reinstall bo assertDirectory(viper.GetString("prefix") + "/" + viper.GetString("target")) var err error if usePathRewrite { - err = plannedTool.InstallWithPathRewrites(registryImagePrefix, viper.GetString("prefix"), pathRewriteRules) + err = plannedTool.InstallWithPathRewrites(registryImagePrefix, viper.GetString("prefix"), pathRewriteRules, createPatchFileCallback(plannedTool)) } else { - err = plannedTool.Install(registryImagePrefix, viper.GetString("prefix"), viper.GetString("target"), libDirectory, cacheDirectory) + err = plannedTool.Install(registryImagePrefix, viper.GetString("prefix"), viper.GetString("target"), libDirectory, cacheDirectory, createPatchFileCallback(plannedTool)) } if err != nil { if installSpinner != nil { @@ -396,3 +398,54 @@ func installTools(requestedTools tool.Tools, check bool, plan bool, reinstall bo return nil } + +func createPatchFileCallback(tool tool.Tool) func(path string) { + var patchFile = func(templatePath string) { + if strings.HasSuffix(templatePath, ".go-template") { + } else { + logging.Debugf("Skipping file %s. Will not patch.", templatePath) + return + } + + values := make(map[string]interface{}) + values["Target"] = viper.GetString("target") + values["Prefix"] = viper.GetString("prefix") + values["Name"] = tool.Name + values["Version"] = tool.Version + + filePath := strings.TrimSuffix(templatePath, ".go-template") + logging.Info.Printfln("Patching file %s <- %s", filePath, templatePath) + + templathPathInfo, err := os.Stat(templatePath) + if err != nil { + logging.Error.Printfln("Unable to get file info: %s", err) + return + } + + file, err := os.Create(filePath) + if err != nil { + logging.Error.Printfln("Unable to create file: %s", err) + return + } + defer file.Close() + if stat, ok := templathPathInfo.Sys().(*syscall.Stat_t); ok { + file.Chown(int(stat.Uid), int(stat.Gid)) + } + file.Chmod(templathPathInfo.Mode()) + + tmpl, err := template.ParseFiles(templatePath) + if err != nil { + logging.Error.Printfln("Unable to parse template file: %s", err) + return + } + tmpl.Execute(file, values) + + err = os.Remove(templatePath) + if err != nil { + logging.Error.Printfln("Unable to remove template file: %s", err) + return + } + } + + return patchFile +} diff --git a/cmd/uniget/self-upgrade.go b/cmd/uniget/self-upgrade.go index 3874bfe1..c31cb553 100644 --- a/cmd/uniget/self-upgrade.go +++ b/cmd/uniget/self-upgrade.go @@ -105,7 +105,7 @@ var selfUpgradeCmd = &cobra.Command{ if err != nil { return fmt.Errorf("failed to remove %s: %s", selfExe, err) } - err = archive.ExtractTarGz(resp.Body, func(path string) string { return path }) + err = archive.ExtractTarGz(resp.Body, func(path string) string { return path }, func(path string) {}) if err != nil { return fmt.Errorf("failed to extract tar.gz: %s", err) } diff --git a/cmd/uniget/uninstall.go b/cmd/uniget/uninstall.go index 2f84bd99..d1fecf8b 100644 --- a/cmd/uniget/uninstall.go +++ b/cmd/uniget/uninstall.go @@ -92,6 +92,7 @@ func uninstallTool(toolName string) error { return fmt.Errorf("unable to read file %s: %s", filename, err) } for _, line := range strings.Split(string(data), "\n") { + line = strings.TrimSuffix(line, ".go-template") logging.Debugf("processing %s", line) strippedLine := strings.TrimPrefix(line, "./") strippedLine = strings.TrimPrefix(strippedLine, "usr/local/") diff --git a/cmd/uniget/update.go b/cmd/uniget/update.go index 00fdf1c7..7b61e4b9 100644 --- a/cmd/uniget/update.go +++ b/cmd/uniget/update.go @@ -67,7 +67,7 @@ func downloadMetadata() error { } logging.Debugf("Extracting archive to %s", viper.GetString("prefix")+"/"+cacheDirectory) - err = archive.ExtractTarGz(blob, func(path string) string { return path }) + err = archive.ExtractTarGz(blob, func(path string) string { return path }, func(path string) {}) if err != nil { return fmt.Errorf("error extracting archive: %s", err) } diff --git a/pkg/archive/new.go b/pkg/archive/new.go index f0c955f5..1a74f124 100644 --- a/pkg/archive/new.go +++ b/pkg/archive/new.go @@ -45,7 +45,7 @@ func pathIsInsideTarget(target string, candidate string) error { return nil } -func ExtractTarGz(gzipStream io.Reader, patchPath func(path string) string) error { +func ExtractTarGz(gzipStream io.Reader, patchPath func(path string) string, patchFile func(path string)) error { target := "." uncompressedStream, err := gzip.NewReader(gzipStream) @@ -123,6 +123,9 @@ func ExtractTarGz(gzipStream io.Reader, patchPath func(path string) string) erro return fmt.Errorf("ExtractTarGz: Chmod() failed: %s", err.Error()) } + // Callback for patching file + patchFile(fixedHeaderName) + // Unpack symlink case tar.TypeSymlink: logging.Tracef("Untarring symlink %s", fixedHeaderName) diff --git a/pkg/tool/install.go b/pkg/tool/install.go index baff3398..34d69aeb 100644 --- a/pkg/tool/install.go +++ b/pkg/tool/install.go @@ -51,7 +51,7 @@ func applyPathRewrites(path string, rules []PathRewrite) string { return newPath } -func (tool *Tool) InstallWithPathRewrites(registryImagePrefix string, prefix string, rules []PathRewrite) error { +func (tool *Tool) InstallWithPathRewrites(registryImagePrefix string, prefix string, rules []PathRewrite, patchFile func(path string)) error { // Fetch manifest for tool err := containers.GetManifest(fmt.Sprintf(registryImagePrefix+"%s:%s", tool.Name, strings.Replace(tool.Version, "+", "-", -1)), func(blob blob.Reader) error { logging.Debugf("Extracting with prefix=%s", prefix) @@ -75,7 +75,7 @@ func (tool *Tool) InstallWithPathRewrites(registryImagePrefix string, prefix str // Unpack tool err = archive.ExtractTarGz(blob, func(path string) string { return applyPathRewrites(path, rules) - }) + }, patchFile) if err != nil { return fmt.Errorf("failed to extract layer: %s", err) } @@ -89,7 +89,7 @@ func (tool *Tool) InstallWithPathRewrites(registryImagePrefix string, prefix str return nil } -func (tool *Tool) Install(registryImagePrefix string, prefix string, target string, libDirectory string, cacheDirectory string) error { +func (tool *Tool) Install(registryImagePrefix string, prefix string, target string, libDirectory string, cacheDirectory string, patchFile func(path string)) error { // Fetch manifest for tool err := containers.GetManifest(fmt.Sprintf(registryImagePrefix+"%s:%s", tool.Name, strings.Replace(tool.Version, "+", "-", -1)), func(blob blob.Reader) error { logging.Debugf("Extracting with prefix=%s and target=%s", prefix, target) @@ -139,7 +139,7 @@ func (tool *Tool) Install(registryImagePrefix string, prefix string, target stri } return fixedPath - }) + }, patchFile) if err != nil { return fmt.Errorf("failed to extract layer: %s", err) }