From b6e3746645d9a4fdeb960c0c14e6ef4471f6e3da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Thu, 7 Jun 2018 15:49:38 +0100 Subject: [PATCH] cmd/fdroidcl: merge upgraade into install Now, install handles upgrades too. It will succeed if it can install a new app, upgrade an existing app, or if an app is already up to date. For the time being, this removes the "upgrade only if already installed" and "install only if not already installed" features, but those are very specific and likely not useful. They can be re-added as options if necessary. Fixes #23. --- adb/device.go | 17 ++-------- cmd/fdroidcl/endtoend_test.go | 16 +++++----- cmd/fdroidcl/install.go | 27 ++++++++++++---- cmd/fdroidcl/main.go | 7 ++-- cmd/fdroidcl/upgrade.go | 60 ----------------------------------- 5 files changed, 34 insertions(+), 93 deletions(-) delete mode 100644 cmd/fdroidcl/upgrade.go diff --git a/adb/device.go b/adb/device.go index 88e8b68..4dedfb0 100644 --- a/adb/device.go +++ b/adb/device.go @@ -136,13 +136,8 @@ func getAbis(props map[string]string) []string { var installFailureRegex = regexp.MustCompile(`^Failure \[INSTALL_(.+)\]$`) -func withOpts(cmd string, opts []string, args ...string) []string { - v := append([]string{cmd}, opts...) - return append(v, args...) -} - -func (d *Device) install(opts []string, path string) error { - cmd := d.AdbCmd(withOpts("install", opts, path)...) +func (d *Device) Install(path string) error { + cmd := d.AdbCmd(append([]string{"install", "-r"}, path)...) output, err := cmd.CombinedOutput() if err != nil { return err @@ -154,14 +149,6 @@ func (d *Device) install(opts []string, path string) error { return parseError(getFailureCode(installFailureRegex, line)) } -func (d *Device) Install(path string) error { - return d.install(nil, path) -} - -func (d *Device) Upgrade(path string) error { - return d.install([]string{"-r"}, path) -} - func getResultLine(output []byte) string { scanner := bufio.NewScanner(bytes.NewReader(output)) for scanner.Scan() { diff --git a/cmd/fdroidcl/endtoend_test.go b/cmd/fdroidcl/endtoend_test.go index 342f0d9..016117b 100644 --- a/cmd/fdroidcl/endtoend_test.go +++ b/cmd/fdroidcl/endtoend_test.go @@ -128,15 +128,15 @@ func TestCommands(t *testing.T) { t.Run("SearchUpgradable", func(t *testing.T) { mustSucceed(t, regexp.QuoteMeta(chosenApp), ``, cmdSearch, "-u", "-q") }) - t.Run("Upgrade", func(t *testing.T) { - mustSucceed(t, `Upgrading `+regexp.QuoteMeta(chosenApp), ``, - cmdUpgrade, chosenApp) + t.Run("InstallUpgrade", func(t *testing.T) { + mustSucceed(t, `Installing `+regexp.QuoteMeta(chosenApp), ``, + cmdInstall, chosenApp) }) t.Run("SearchUpgradableUpToDate", func(t *testing.T) { mustSucceed(t, ``, regexp.QuoteMeta(chosenApp), cmdSearch, "-u", "-q") }) - t.Run("UpgradeAlreadyInstalled", func(t *testing.T) { - mustFail(t, `is up to date$`, ``, cmdUpgrade, chosenApp) + t.Run("InstallUpToDate", func(t *testing.T) { + mustSucceed(t, `is up to date$`, ``, cmdInstall, chosenApp) }) t.Run("UninstallExisting", func(t *testing.T) { mustSucceed(t, `Uninstalling `+regexp.QuoteMeta(chosenApp), ``, @@ -149,14 +149,14 @@ func mustRun(t *testing.T, success bool, wantRe, negRe string, cmd *Command, arg stdout, stderr = &buf, &buf err := cmd.Run(args) out := buf.String() + if err != nil { + out += err.Error() + } if success && err != nil { t.Fatalf("unexpected error: %v\n%s", err, out) } else if !success && err == nil { t.Fatalf("expected error, got none\n%s", out) } - if err != nil { - out += err.Error() - } // Let '.' match newlines, and treat the output as a single line. wantRe = "(?sm)" + wantRe if !regexp.MustCompile(wantRe).MatchString(out) { diff --git a/cmd/fdroidcl/install.go b/cmd/fdroidcl/install.go index b492fc5..fa4711f 100644 --- a/cmd/fdroidcl/install.go +++ b/cmd/fdroidcl/install.go @@ -12,7 +12,7 @@ import ( var cmdInstall = &Command{ UsageLine: "install ", - Short: "Install an app", + Short: "Install or upgrade an app", } func init() { @@ -35,15 +35,30 @@ func runInstall(args []string) error { if err != nil { return err } + var toInstall []*fdroidcl.App for _, app := range apps { - if _, e := inst[app.ID]; e { - return fmt.Errorf("%s is already installed", app.ID) + p, e := inst[app.ID] + if !e { + // installing an app from scratch + toInstall = append(toInstall, app) + continue } + suggested := app.SuggestedApk(device) + if suggested == nil { + return fmt.Errorf("no suitable APKs found for %s", app.ID) + } + if p.VCode >= suggested.VCode { + fmt.Fprintf(stdout, "%s is up to date\n", app.ID) + // app is already up to date + continue + } + // upgrading an existing app + toInstall = append(toInstall, app) } - return downloadAndDo(apps, device, installApk) + return downloadAndDo(toInstall, device) } -func downloadAndDo(apps []*fdroidcl.App, device *adb.Device, doApk func(*adb.Device, *fdroidcl.Apk, string) error) error { +func downloadAndDo(apps []*fdroidcl.App, device *adb.Device) error { type downloaded struct { apk *fdroidcl.Apk path string @@ -61,7 +76,7 @@ func downloadAndDo(apps []*fdroidcl.App, device *adb.Device, doApk func(*adb.Dev toInstall[i] = downloaded{apk: apk, path: path} } for _, t := range toInstall { - if err := doApk(device, t.apk, t.path); err != nil { + if err := installApk(device, t.apk, t.path); err != nil { return err } } diff --git a/cmd/fdroidcl/main.go b/cmd/fdroidcl/main.go index 21943be..9a0e259 100644 --- a/cmd/fdroidcl/main.go +++ b/cmd/fdroidcl/main.go @@ -162,12 +162,11 @@ var commands = []*Command{ cmdUpdate, cmdSearch, cmdShow, - cmdList, - cmdDevices, - cmdDownload, cmdInstall, - cmdUpgrade, cmdUninstall, + cmdDownload, + cmdDevices, + cmdList, cmdDefaults, cmdVersion, } diff --git a/cmd/fdroidcl/upgrade.go b/cmd/fdroidcl/upgrade.go deleted file mode 100644 index e74652f..0000000 --- a/cmd/fdroidcl/upgrade.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2015, Daniel Martí -// See LICENSE for licensing information - -package main - -import ( - "fmt" - - "mvdan.cc/fdroidcl" - "mvdan.cc/fdroidcl/adb" -) - -var cmdUpgrade = &Command{ - UsageLine: "upgrade ", - Short: "Upgrade an app", -} - -func init() { - cmdUpgrade.Run = runUpgrade -} - -func runUpgrade(args []string) error { - if len(args) < 1 { - return fmt.Errorf("no package names given") - } - apps, err := findApps(args) - if err != nil { - return err - } - device, err := oneDevice() - if err != nil { - return err - } - inst, err := device.Installed() - if err != nil { - return err - } - for _, app := range apps { - p, e := inst[app.ID] - if !e { - return fmt.Errorf("%s is not installed", app.ID) - } - suggested := app.SuggestedApk(device) - if suggested == nil { - return fmt.Errorf("no suitable APKs found for %s", app.ID) - } - if p.VCode >= suggested.VCode { - return fmt.Errorf("%s is up to date", app.ID) - } - } - return downloadAndDo(apps, device, upgradeApk) -} - -func upgradeApk(device *adb.Device, apk *fdroidcl.Apk, path string) error { - fmt.Fprintf(stdout, "Upgrading %s\n", apk.AppID) - if err := device.Upgrade(path); err != nil { - return fmt.Errorf("could not upgrade %s: %v", apk.AppID, err) - } - return nil -}