From c4ec65d94e956e07dd17b2e2cc0fce4d489d0fa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Tue, 5 Feb 2019 22:27:42 +0000 Subject: [PATCH] support F-Droid's CSV export in install Easy enough to do; we just read from stdin when given no arguments, and convert the CSV fields to the argument string format. Fixes #30. --- README.md | 2 +- install.go | 42 ++++++++++++++++++++++++++++++------- main.go | 12 +++++++++-- testdata/scripts/cmds.txt | 4 ++++ testdata/scripts/device.txt | 9 ++++++++ 5 files changed, 59 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 9530732..944218a 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Install an app: update Update the index search [] Search available apps show Show detailed info about an app - install Install or upgrade apps + install [] Install or upgrade apps uninstall Uninstall an app download Download an app devices List connected devices diff --git a/install.go b/install.go index 99cc312..49cd982 100644 --- a/install.go +++ b/install.go @@ -4,7 +4,9 @@ package main import ( + "encoding/csv" "fmt" + "io" "os" "mvdan.cc/fdroidcl/adb" @@ -12,8 +14,15 @@ import ( ) var cmdInstall = &Command{ - UsageLine: "install ", + UsageLine: "install []", Short: "Install or upgrade apps", + Long: ` +Install or upgrade apps. When given no arguments, it reads a comma-separated +list of apps to install from standard input, like: + + packageName,versionCode,versionName + foo.bar,120,1.2.0 +`[1:], } var ( @@ -26,12 +35,8 @@ func init() { } func runInstall(args []string) error { - if *installUpdates { - if len(args) > 0 { - return fmt.Errorf("-u can only be used without arguments") - } - } else if len(args) < 1 { - return fmt.Errorf("no package names given") + if *installUpdates && len(args) > 0 { + return fmt.Errorf("-u can only be used without arguments") } device, err := oneDevice() if err != nil { @@ -54,6 +59,29 @@ func runInstall(args []string) error { return downloadAndDo(apps, device) } + if len(args) == 0 { + // The CSV input is as follows: + // + // packageName,versionCode,versionName + // foo.bar,120,1.2.0 + // ... + + r := csv.NewReader(os.Stdin) + r.FieldsPerRecord = 3 + r.Read() + for { + record, err := r.Read() + if err == io.EOF { + break + } + if err != nil { + return fmt.Errorf("error parsing CSV: %v", err) + } + // convert "foo.bar,120" into "foo.bar:120" for findApps + args = append(args, record[0]+":"+record[1]) + } + } + apps, err := findApps(args) if err != nil { return err diff --git a/main.go b/main.go index 7cd0614..708179e 100644 --- a/main.go +++ b/main.go @@ -96,9 +96,12 @@ type Command struct { // The first word in the line is taken to be the command name. UsageLine string - // Short is the short description. + // Short is the short, single-line description. Short string + // Long is an optional longer version of the Short description. + Long string + Fset flag.FlagSet } @@ -113,7 +116,12 @@ func (c *Command) Name() string { } func (c *Command) usage() { - fmt.Fprintf(os.Stderr, "usage: %s %s\n", cmdName, c.UsageLine) + fmt.Fprintf(os.Stderr, "usage: %s %s\n\n", cmdName, c.UsageLine) + if c.Long == "" { + fmt.Fprintf(os.Stderr, "%s.\n", c.Short) + } else { + fmt.Fprint(os.Stderr, c.Long) + } anyFlags := false c.Fset.VisitAll(func(f *flag.Flag) { anyFlags = true }) if anyFlags { diff --git a/testdata/scripts/cmds.txt b/testdata/scripts/cmds.txt index 1e518f6..1d5d11a 100644 --- a/testdata/scripts/cmds.txt +++ b/testdata/scripts/cmds.txt @@ -18,8 +18,12 @@ stderr '^usage: fdroidcl \[-h' ! fdroidcl search -h stderr '^usage: fdroidcl search .*regexp' +stderr '^Search available apps.' stderr '-i.*Filter installed apps' +! fdroidcl install -h +stderr 'When given no arguments' + ! fdroidcl ! fdroidcl install -u some.app diff --git a/testdata/scripts/device.txt b/testdata/scripts/device.txt index 0856851..4950845 100644 --- a/testdata/scripts/device.txt +++ b/testdata/scripts/device.txt @@ -24,6 +24,11 @@ fdroidcl search -i -q fdroidcl search -u -q ! stdout 'org\.vi_server\.red_screen' +# install via csv input works as expected +stdin applist.csv +fdroidcl install -n +stdout 'install org\.vi_server\.red_screen:1' + # install version code 1 fdroidcl install org.vi_server.red_screen:1 stdout 'Downloading.*red_screen_1.apk' @@ -57,3 +62,7 @@ stdout 'is up to date' # uninstall an app that exists fdroidcl uninstall org.vi_server.red_screen + +-- applist.csv -- +packageName,versionCode,versionName +org.vi_server.red_screen,1,1.0