Skip to content

Commit

Permalink
feat: remote package installations can skip scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
femnad committed Dec 24, 2023
1 parent ab5ee03 commit c5f8456
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 38 deletions.
1 change: 1 addition & 0 deletions entity/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
}

Expand Down
64 changes: 36 additions & 28 deletions packages/apt.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
}

Expand Down Expand Up @@ -46,56 +49,61 @@ 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)
if err != nil {
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)
Expand Down
37 changes: 29 additions & 8 deletions packages/dnf.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down
7 changes: 5 additions & 2 deletions packages/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type PkgManager interface {
PkgNameSeparator() string
PreserveEnv() bool
RemoveCmd() string
RemoteInstall(urls []string) error
RemoteInstall(pkgs []entity.RemotePackage) error
UpdateCmd() string
}

Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit c5f8456

Please sign in to comment.