From c5f845613b5e8d7922e9d7f143cd9b74cbf0c826 Mon Sep 17 00:00:00 2001 From: fcd <1352288+femnad@users.noreply.github.com> Date: Mon, 25 Dec 2023 01:00:09 +0300 Subject: [PATCH] feat: remote package installations can skip scripts --- entity/package.go | 1 + packages/apt.go | 64 +++++++++++++++++++++++++-------------------- packages/dnf.go | 37 ++++++++++++++++++++------ packages/install.go | 7 +++-- 4 files changed, 71 insertions(+), 38 deletions(-) diff --git a/entity/package.go b/entity/package.go index ed18c79..caa507e 100644 --- a/entity/package.go +++ b/entity/package.go @@ -5,6 +5,7 @@ type RemotePackage struct { InstallOnce bool `yaml:"install_once"` Name string `yaml:"name"` Version string `yaml:"version"` + SkipScripts bool `yaml:"skip_scripts"` Url string `yaml:"url"` } diff --git a/packages/apt.go b/packages/apt.go index a0b2090..cd545b2 100644 --- a/packages/apt.go +++ b/packages/apt.go @@ -6,12 +6,15 @@ import ( "path" "strings" - marecmd "github.com/femnad/mare/cmd" - + "github.com/femnad/fup/entity" "github.com/femnad/fup/internal" "github.com/femnad/fup/remote" ) +const pkgScriptsDir = "/var/lib/dpkg/info" + +var pkgScripts = []string{"postinst", "preinst"} + type Apt struct { } @@ -46,36 +49,34 @@ func (Apt) UpdateCmd() string { return "update" } -func (Apt) remoteInstall(url string) error { - _, file := path.Split(url) - tmpDir, err := os.MkdirTemp("/tmp", "fup-remote-pkg") +func installPkgSkipScripts(pkgName, filename string) error { + err := internal.MaybeRunWithSudo(fmt.Sprintf("dpkg --unpack %s", filename)) if err != nil { return err } - target := path.Join(tmpDir, file) - err = remote.Download(url, target) - if err != nil { - return err - } - - isRoot, err := internal.IsUserRoot() - if err != nil { - return err + for _, script := range pkgScripts { + scriptFile := path.Join(pkgScriptsDir, fmt.Sprintf("%s.%s", pkgName, script)) + err = internal.MaybeRunWithSudo(fmt.Sprintf("rm %s", scriptFile)) + if err != nil { + return err + } } - input := marecmd.Input{Command: fmt.Sprintf("apt install -y %s", target), Sudo: !isRoot} - return marecmd.RunNoOutput(input) + return internal.MaybeRunWithSudo(fmt.Sprintf("dkpg --configure %s", pkgName)) } -func (Apt) RemoteInstall(urls []string) error { - var targets []string +func (Apt) RemoteInstall(pkgs []entity.RemotePackage) error { tmpDir, err := os.MkdirTemp("/tmp", "fup-remote-pkg") if err != nil { return err } - for _, url := range urls { + skipScriptTargets := make(map[string]string) + var regularTargets []string + + for _, pkg := range pkgs { + url := pkg.Url _, file := path.Split(url) target := path.Join(tmpDir, file) err = remote.Download(url, target) @@ -83,19 +84,26 @@ func (Apt) RemoteInstall(urls []string) error { return err } - targets = append(targets, target) + if pkg.SkipScripts { + skipScriptTargets[pkg.Name] = target + } else { + regularTargets = append(regularTargets, target) + } } - isRoot, err := internal.IsUserRoot() - if err != nil { - return err + targetArgs := strings.Join(regularTargets, " ") + if targetArgs != "" { + err = internal.MaybeRunWithSudo(fmt.Sprintf("apt install -y %s", targetArgs)) + if err != nil { + return err + } } - targetArgs := strings.Join(targets, " ") - input := marecmd.Input{Command: fmt.Sprintf("apt install -y %s", targetArgs), Sudo: !isRoot} - _, err = marecmd.RunFormatError(input) - if err != nil { - return err + for pkg, filename := range skipScriptTargets { + err = installPkgSkipScripts(pkg, filename) + if err != nil { + return err + } } return os.RemoveAll(tmpDir) diff --git a/packages/dnf.go b/packages/dnf.go index fae4123..017ffce 100644 --- a/packages/dnf.go +++ b/packages/dnf.go @@ -4,8 +4,8 @@ import ( "fmt" "strings" + "github.com/femnad/fup/entity" "github.com/femnad/fup/internal" - marecmd "github.com/femnad/mare/cmd" ) type Dnf struct { @@ -35,15 +35,36 @@ func (Dnf) RemoveCmd() string { return "remove" } -func (Dnf) RemoteInstall(urls []string) error { - isRoot, err := internal.IsUserRoot() - if err != nil { - return err +func (Dnf) RemoteInstall(pkgs []entity.RemotePackage) error { + var regularUrls []string + var skipScriptUrls []string + + for _, pkg := range pkgs { + url := pkg.Url + if pkg.SkipScripts { + skipScriptUrls = append(skipScriptUrls, url) + } else { + regularUrls = append(regularUrls, url) + } + } + + if len(regularUrls) > 0 { + cmd := fmt.Sprintf("dnf install -y %s", strings.Join(regularUrls, " ")) + err := internal.MaybeRunWithSudo(cmd) + if err != nil { + return err + } } - input := marecmd.Input{Command: fmt.Sprintf("dnf install -y %s", strings.Join(urls, " ")), Sudo: !isRoot} - _, err = marecmd.RunFormatError(input) - return err + if len(skipScriptUrls) > 0 { + cmd := fmt.Sprintf("dnf install -y --setopt=tsflags=noscripts %s", strings.Join(skipScriptUrls, " ")) + err := internal.MaybeRunWithSudo(cmd) + if err != nil { + return err + } + } + + return nil } func (Dnf) UpdateCmd() string { diff --git a/packages/install.go b/packages/install.go index 0124e47..9ce0367 100644 --- a/packages/install.go +++ b/packages/install.go @@ -21,7 +21,7 @@ type PkgManager interface { PkgNameSeparator() string PreserveEnv() bool RemoveCmd() string - RemoteInstall(urls []string) error + RemoteInstall(pkgs []entity.RemotePackage) error UpdateCmd() string } @@ -140,17 +140,20 @@ func (i Installer) RemoteInstall(desired mapset.Set[entity.RemotePackage], s set } var urls []string + var pkgs []entity.RemotePackage missing.Each(func(pkg entity.RemotePackage) bool { version := desiredPkgVersion(pkg, s) url := settings.ExpandStringWithLookup(s, pkg.Url, map[string]string{"version": version}) + pkg.Url = url urls = append(urls, url) + pkgs = append(pkgs, pkg) return false }) sort.Strings(urls) internal.Log.Infof("Remote packages to install: %s", strings.Join(urls, " ")) - return true, i.Pkg.RemoteInstall(urls) + return true, i.Pkg.RemoteInstall(pkgs) } func (i Installer) InstalledPackages(pkg PkgManager) (mapset.Set[string], error) {