diff --git a/cmd/update.go b/cmd/update.go index 6de9a19..2ba1a74 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -158,7 +158,7 @@ func Update(cmd *cobra.Command, args []string) { slog.Info("Verbose run requested") for _, output := range outputs { - slog.Info("CommandOutput", slog.String("context", output.Context), slog.String("stdout", output.Stdout), slog.Any("stderr", output.Stderr)) + slog.Info(output.Context, slog.String("stdout", output.Stdout), slog.Any("stderr", output.Stderr), slog.Any("cli", output.Cli)) } return @@ -175,7 +175,7 @@ func Update(cmd *cobra.Command, args []string) { slog.Warn("Exited with failed updates.") for _, output := range failures { - slog.Info("CommandOutput", slog.String("context", output.Context), slog.String("stdout", output.Stdout), slog.Any("stderr", output.Stderr)) + slog.Info(output.Context, slog.String("stdout", output.Stdout), slog.Any("stderr", output.Stderr), slog.Any("cli", output.Cli)) } return diff --git a/drv/brew.go b/drv/brew.go index 155862b..072c490 100644 --- a/drv/brew.go +++ b/drv/brew.go @@ -8,17 +8,17 @@ import ( ) func (up BrewUpdater) GetBrewUID() (int, error) { - inf, err := os.Stat(up.Environment["HOMEBREW_PREFIX"]) + inf, err := os.Stat(up.BrewPrefix) if err != nil { return -1, err } if !inf.IsDir() { - return -1, fmt.Errorf("Brew prefix: %v, is not a dir.", up.Environment["HOMEBREW_PREFIX"]) + return -1, fmt.Errorf("Brew prefix: %v, is not a dir.", up.BrewPrefix) } stat, ok := inf.Sys().(*syscall.Stat_t) if !ok { - return -1, fmt.Errorf("Unable to retriev UID info for %v", up.Environment["HOMEBREW_PREFIX"]) + return -1, fmt.Errorf("Unable to retriev UID info for %v", up.BrewPrefix) } return int(stat.Uid), nil } @@ -42,19 +42,24 @@ func (up BrewUpdater) Update() (*[]CommandOutput, error) { return &final_output, nil } - out, err := lib.RunUID(up.BaseUser, []string{up.Environment["HOMEBREW_PATH"], "update"}, up.Environment) + cli := []string{up.BrewPath, "update"} + out, err := lib.RunUID(up.BaseUser, cli, up.Environment) tmpout := CommandOutput{}.New(out, err) + tmpout.Context = "Brew Update" + tmpout.Cli = cli + tmpout.Failure = err != nil if err != nil { tmpout.SetFailureContext("Brew update") final_output = append(final_output, *tmpout) return &final_output, err } - out, err = lib.RunUID(up.BaseUser, []string{up.Environment["HOMEBREW_PATH"], "upgrade"}, up.Environment) + cli = []string{up.BrewPath, "upgrade"} + out, err = lib.RunUID(up.BaseUser, cli, up.Environment) tmpout = CommandOutput{}.New(out, err) - if err != nil { - tmpout.SetFailureContext("Brew upgrade") - } + tmpout.Context = "Brew Upgrade" + tmpout.Cli = cli + tmpout.Failure = err != nil final_output = append(final_output, *tmpout) return &final_output, err } @@ -62,32 +67,39 @@ func (up BrewUpdater) Update() (*[]CommandOutput, error) { type BrewUpdater struct { Config DriverConfiguration BaseUser int - Environment map[string]string + Environment EnvironmentMap + BrewRepo string + BrewPrefix string + BrewCellar string + BrewPath string } func (up BrewUpdater) New(config UpdaterInitConfiguration) (BrewUpdater, error) { - brewPrefix, empty := os.LookupEnv("HOMEBREW_PREFIX") + up.Environment = config.Environment + brewPrefix, empty := up.Environment["HOMEBREW_PREFIX"] if empty || brewPrefix == "" { - brewPrefix = "/home/linuxbrew/.linuxbrew" + up.BrewPrefix = "/home/linuxbrew/.linuxbrew" + } else { + up.BrewPrefix = brewPrefix } - brewRepo, empty := os.LookupEnv("HOMEBREW_REPOSITORY") + brewRepo, empty := up.Environment["HOMEBREW_REPOSITORY"] if empty || brewRepo == "" { - brewRepo = fmt.Sprintf("%s/Homebrew", brewPrefix) + up.BrewRepo = fmt.Sprintf("%s/Homebrew", up.BrewPrefix) + } else { + up.BrewRepo = brewRepo } - brewCellar, empty := os.LookupEnv("HOMEBREW_CELLAR") + brewCellar, empty := up.Environment["HOMEBREW_CELLAR"] if empty || brewCellar == "" { - brewCellar = fmt.Sprintf("%s/Cellar", brewPrefix) + up.BrewCellar = fmt.Sprintf("%s/Cellar", up.BrewPrefix) + } else { + + up.BrewCellar = brewCellar } - brewPath, empty := os.LookupEnv("HOMEBREW_PATH") + brewPath, empty := up.Environment["HOMEBREW_PATH"] if empty || brewPath == "" { - brewPath = fmt.Sprintf("%s/bin/brew", brewPrefix) - } - - up.Environment = map[string]string{ - "HOMEBREW_PREFIX": brewPrefix, - "HOMEBREW_REPOSITORY": brewRepo, - "HOMEBREW_CELLAR": brewCellar, - "HOMEBREW_PATH": brewPath, + up.BrewPath = fmt.Sprintf("%s/bin/brew", up.BrewPrefix) + } else { + up.BrewPath = brewPath } up.Config = DriverConfiguration{ Title: "Brew", @@ -105,7 +117,7 @@ func (up BrewUpdater) New(config UpdaterInitConfiguration) (BrewUpdater, error) if err != nil { return up, err } - up.BaseUser = uid + return up, nil } diff --git a/drv/distrobox.go b/drv/distrobox.go index 958dfa1..277f30d 100644 --- a/drv/distrobox.go +++ b/drv/distrobox.go @@ -1,14 +1,13 @@ package drv import ( - "fmt" - "github.com/ublue-os/uupd/lib" ) type DistroboxUpdater struct { Config DriverConfiguration Tracker *TrackerConfiguration + binaryPath string users []lib.User usersEnabled bool } @@ -24,7 +23,7 @@ func (up DistroboxUpdater) Steps() int { return 0 } -func (up DistroboxUpdater) New(initconfig UpdaterInitConfiguration) (DistroboxUpdater, error) { +func (up DistroboxUpdater) New(config UpdaterInitConfiguration) (DistroboxUpdater, error) { userdesc := "Distroboxes for User:" up.Config = DriverConfiguration{ Title: "Distrobox", @@ -32,11 +31,18 @@ func (up DistroboxUpdater) New(initconfig UpdaterInitConfiguration) (DistroboxUp UserDescription: &userdesc, Enabled: true, MultiUser: true, - DryRun: initconfig.DryRun, + DryRun: config.DryRun, } up.usersEnabled = false up.Tracker = nil + binaryPath, empty := config.Environment["UUPD_DISTROBOX_BINARY"] + if empty || binaryPath == "" { + up.binaryPath = "/usr/bin/distrobox" + } else { + up.binaryPath = binaryPath + } + return up, nil } @@ -64,24 +70,26 @@ func (up *DistroboxUpdater) Update() (*[]CommandOutput, error) { return &finalOutput, nil } - // TODO: add env support for Flatpak and Distrobox updaters lib.ChangeTrackerMessageFancy(*up.Tracker.Writer, up.Tracker.Tracker, up.Tracker.Progress, lib.TrackerMessage{Title: up.Config.Title, Description: up.Config.Description}) - out, err := lib.RunUID(0, []string{"/usr/bin/distrobox", "upgrade", "-a"}, nil) + cli := []string{up.binaryPath, "upgrade", "-a"} + out, err := lib.RunUID(0, cli, nil) tmpout := CommandOutput{}.New(out, err) - if err != nil { - tmpout.SetFailureContext("System Distroboxes") - } + tmpout.Context = up.Config.Description + tmpout.Cli = cli + tmpout.Failure = err != nil finalOutput = append(finalOutput, *tmpout) err = nil for _, user := range up.users { up.Tracker.Tracker.IncrementSection(err) + context := *up.Config.UserDescription + " " + user.Name lib.ChangeTrackerMessageFancy(*up.Tracker.Writer, up.Tracker.Tracker, up.Tracker.Progress, lib.TrackerMessage{Title: up.Config.Title, Description: *up.Config.UserDescription + " " + user.Name}) - out, err := lib.RunUID(user.UID, []string{"/usr/bin/distrobox", "upgrade", "-a"}, nil) + cli := []string{up.binaryPath, "upgrade", "-a"} + out, err := lib.RunUID(user.UID, cli, nil) tmpout = CommandOutput{}.New(out, err) - if err != nil { - tmpout.SetFailureContext(fmt.Sprintf("Distroboxes for User: %s", user.Name)) - } + tmpout.Context = context + tmpout.Cli = cli + tmpout.Failure = err != nil finalOutput = append(finalOutput, *tmpout) } return &finalOutput, nil diff --git a/drv/flatpak.go b/drv/flatpak.go index e2a7137..371261c 100644 --- a/drv/flatpak.go +++ b/drv/flatpak.go @@ -1,7 +1,6 @@ package drv import ( - "fmt" "os/exec" "github.com/ublue-os/uupd/lib" @@ -10,6 +9,7 @@ import ( type FlatpakUpdater struct { Config DriverConfiguration Tracker *TrackerConfiguration + binaryPath string users []lib.User usersEnabled bool } @@ -25,7 +25,7 @@ func (up FlatpakUpdater) Steps() int { return 0 } -func (up FlatpakUpdater) New(initconfig UpdaterInitConfiguration) (FlatpakUpdater, error) { +func (up FlatpakUpdater) New(config UpdaterInitConfiguration) (FlatpakUpdater, error) { userdesc := "Apps for User:" up.Config = DriverConfiguration{ Title: "Flatpak", @@ -33,11 +33,18 @@ func (up FlatpakUpdater) New(initconfig UpdaterInitConfiguration) (FlatpakUpdate UserDescription: &userdesc, Enabled: true, MultiUser: true, - DryRun: initconfig.DryRun, + DryRun: config.DryRun, } up.usersEnabled = false up.Tracker = nil + binaryPath, empty := config.Environment["UUPD_FLATPAK_BINARY"] + if empty || binaryPath == "" { + up.binaryPath = "/usr/bin/flatpak" + } else { + up.binaryPath = binaryPath + } + return up, nil } @@ -66,23 +73,26 @@ func (up FlatpakUpdater) Update() (*[]CommandOutput, error) { } lib.ChangeTrackerMessageFancy(*up.Tracker.Writer, up.Tracker.Tracker, up.Tracker.Progress, lib.TrackerMessage{Title: up.Config.Title, Description: up.Config.Description}) - flatpakCmd := exec.Command("/usr/bin/flatpak", "update", "-y") + cli := []string{up.binaryPath, "update", "-y"} + flatpakCmd := exec.Command(cli[0], cli[1:]...) out, err := flatpakCmd.CombinedOutput() tmpout := CommandOutput{}.New(out, err) - if err != nil { - tmpout.SetFailureContext("Flatpak System Apps") - } + tmpout.Context = up.Config.Description + tmpout.Cli = cli + tmpout.Failure = err != nil finalOutput = append(finalOutput, *tmpout) err = nil for _, user := range up.users { up.Tracker.Tracker.IncrementSection(err) - lib.ChangeTrackerMessageFancy(*up.Tracker.Writer, up.Tracker.Tracker, up.Tracker.Progress, lib.TrackerMessage{Title: up.Config.Title, Description: *up.Config.UserDescription + " " + user.Name}) - out, err := lib.RunUID(user.UID, []string{"/usr/bin/flatpak", "update", "-y"}, nil) + context := *up.Config.UserDescription + " " + user.Name + lib.ChangeTrackerMessageFancy(*up.Tracker.Writer, up.Tracker.Tracker, up.Tracker.Progress, lib.TrackerMessage{Title: up.Config.Title, Description: context}) + cli := []string{up.binaryPath, "update", "-y"} + out, err := lib.RunUID(user.UID, cli, nil) tmpout = CommandOutput{}.New(out, err) - if err != nil { - tmpout.SetFailureContext(fmt.Sprintf("Flatpak User: %s", user.Name)) - } + tmpout.Context = context + tmpout.Cli = cli + tmpout.Failure = err != nil finalOutput = append(finalOutput, *tmpout) } return &finalOutput, nil diff --git a/drv/generic.go b/drv/generic.go index c708ad8..806035a 100644 --- a/drv/generic.go +++ b/drv/generic.go @@ -8,6 +8,8 @@ import ( "github.com/ublue-os/uupd/lib" ) +type EnvironmentMap map[string]string + type UpdaterInitConfiguration struct { DryRun bool Ci bool @@ -42,6 +44,7 @@ type CommandOutput struct { Failure bool Stderr error Context string + Cli []string } func (output CommandOutput) New(out []byte, err error) *CommandOutput { diff --git a/drv/system.go b/drv/system.go index 864f12d..8803334 100644 --- a/drv/system.go +++ b/drv/system.go @@ -38,19 +38,25 @@ type SystemUpdater struct { UpdateAvailable bool } -type SystemDriver int +type SystemVariation int const ( - Bootc SystemDriver = iota + Bootc SystemVariation = iota RpmOstree ) +type SystemDriver struct { + Variation SystemVariation + bootcBinaryPath string + rpmOstreeBinaryPath string +} + func (dr SystemDriver) Outdated() (bool, error) { oneMonthAgo := time.Now().AddDate(0, -1, 0) var timestamp time.Time - switch dr { + switch dr.Variation { case Bootc: - cmd := exec.Command("bootc", "status", "--format=json") + cmd := exec.Command(dr.bootcBinaryPath, "status", "--format=json") out, err := cmd.CombinedOutput() if err != nil { return false, err @@ -65,7 +71,7 @@ func (dr SystemDriver) Outdated() (bool, error) { return false, nil } case RpmOstree: - cmd := exec.Command("rpm-ostree", "status", "--json", "--booted") + cmd := exec.Command(dr.rpmOstreeBinaryPath, "status", "--json", "--booted") out, err := cmd.CombinedOutput() if err != nil { return false, err @@ -84,25 +90,28 @@ func (dr SystemDriver) Outdated() (bool, error) { func (dr SystemDriver) Update() (*[]CommandOutput, error) { var finalOutput = []CommandOutput{} var cmd *exec.Cmd = nil - switch dr { + var binaryPath string + switch dr.Variation { case Bootc: - cmd = exec.Command("/usr/bin/bootc", "upgrade") + binaryPath = dr.bootcBinaryPath case RpmOstree: - cmd = exec.Command("/usr/bin/rpm-ostree", "upgrade") + binaryPath = dr.rpmOstreeBinaryPath } + cli := []string{binaryPath, "upgrade"} + cmd = exec.Command(cli[0], cli[1:]...) out, err := cmd.CombinedOutput() tmpout := CommandOutput{}.New(out, err) - if err != nil { - tmpout.SetFailureContext("System update") - } + tmpout.Cli = cli + tmpout.Failure = err != nil + tmpout.Context = "System Update" finalOutput = append(finalOutput, *tmpout) return &finalOutput, err } func (dr SystemDriver) UpdateAvailable() (bool, error) { - switch dr { + switch dr.Variation { case Bootc: - cmd := exec.Command("/usr/bin/bootc", "upgrade", "--check") + cmd := exec.Command(dr.bootcBinaryPath, "upgrade", "--check") out, err := cmd.CombinedOutput() if err != nil { return true, err @@ -111,7 +120,7 @@ func (dr SystemDriver) UpdateAvailable() (bool, error) { case RpmOstree: // This function may or may not be accurate, rpm-ostree updgrade --check has issues... https://github.com/coreos/rpm-ostree/issues/1579 // Not worried because we will end up removing rpm-ostree from the equation soon - cmd := exec.Command("/usr/bin/rpm-ostree", "upgrade", "--check") + cmd := exec.Command(dr.rpmOstreeBinaryPath, "upgrade", "--check") out, err := cmd.CombinedOutput() if err != nil { return true, err @@ -129,8 +138,8 @@ func (up SystemUpdater) Steps() int { return 0 } -func BootcCompatible() (bool, error) { - cmd := exec.Command("bootc", "status", "--format=json") +func (dr SystemDriver) BootcCompatible() (bool, error) { + cmd := exec.Command(dr.bootcBinaryPath, "status", "--format=json") out, err := cmd.CombinedOutput() if err != nil { return false, nil @@ -143,12 +152,12 @@ func BootcCompatible() (bool, error) { return !(status.Status.Booted.Incompatible || status.Status.Staged.Incompatible), nil } -func (up SystemUpdater) New(initconfig UpdaterInitConfiguration) (SystemUpdater, error) { +func (up SystemUpdater) New(config UpdaterInitConfiguration) (SystemUpdater, error) { up.Config = DriverConfiguration{ Title: "System", Description: "System Updates", - Enabled: !initconfig.Ci, - DryRun: initconfig.DryRun, + Enabled: !config.Ci, + DryRun: config.DryRun, } if up.Config.DryRun { @@ -156,14 +165,28 @@ func (up SystemUpdater) New(initconfig UpdaterInitConfiguration) (SystemUpdater, return up, nil } - isBootc, err := BootcCompatible() + up.SystemDriver = SystemDriver{} + bootcBinaryPath, empty := config.Environment["UUPD_BOOTC_BINARY"] + if empty || bootcBinaryPath == "" { + up.SystemDriver.bootcBinaryPath = "/usr/bin/bootc" + } else { + up.SystemDriver.bootcBinaryPath = bootcBinaryPath + } + rpmOstreeBinaryPath, empty := config.Environment["UUPD_RPMOSTREE_BINARY"] + if empty || rpmOstreeBinaryPath == "" { + up.SystemDriver.rpmOstreeBinaryPath = "/usr/bin/rpm-ostree" + } else { + up.SystemDriver.rpmOstreeBinaryPath = rpmOstreeBinaryPath + } + + isBootc, err := up.SystemDriver.BootcCompatible() if err != nil { return up, err } if isBootc { - up.SystemDriver = Bootc + up.SystemDriver.Variation = Bootc } else { - up.SystemDriver = RpmOstree + up.SystemDriver.Variation = RpmOstree } outdated, err := up.SystemDriver.Outdated() @@ -179,19 +202,16 @@ func (up *SystemUpdater) Check() (bool, error) { if up.Config.DryRun { return true, nil } + updateAvailable, err := up.SystemDriver.UpdateAvailable() return updateAvailable, err } func (up SystemUpdater) Update() (*[]CommandOutput, error) { - var final_output = []CommandOutput{} - if up.Config.DryRun { - return &final_output, nil + return &[]CommandOutput{}, nil } out, err := up.SystemDriver.Update() - final_output = append(final_output, *out...) - - return &final_output, err + return out, err }