Use flaggy for CLI argument parsing
This commit is contained in:
@@ -2,6 +2,9 @@ module git.javil.eu/jacob1123/docspell-cli
|
|||||||
|
|
||||||
go 1.23.4
|
go 1.23.4
|
||||||
|
|
||||||
require bazil.org/fuse v0.0.0-20230120002735-62a210ff1fd5
|
require (
|
||||||
|
bazil.org/fuse v0.0.0-20230120002735-62a210ff1fd5
|
||||||
|
github.com/integrii/flaggy v1.5.2
|
||||||
|
)
|
||||||
|
|
||||||
require golang.org/x/sys v0.4.0 // indirect
|
require golang.org/x/sys v0.4.0 // indirect
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
bazil.org/fuse v0.0.0-20230120002735-62a210ff1fd5 h1:A0NsYy4lDBZAC6QiYeJ4N+XuHIKBpyhAVRMHRQZKTeQ=
|
bazil.org/fuse v0.0.0-20230120002735-62a210ff1fd5 h1:A0NsYy4lDBZAC6QiYeJ4N+XuHIKBpyhAVRMHRQZKTeQ=
|
||||||
bazil.org/fuse v0.0.0-20230120002735-62a210ff1fd5/go.mod h1:gG3RZAMXCa/OTes6rr9EwusmR1OH1tDDy+cg9c5YliY=
|
bazil.org/fuse v0.0.0-20230120002735-62a210ff1fd5/go.mod h1:gG3RZAMXCa/OTes6rr9EwusmR1OH1tDDy+cg9c5YliY=
|
||||||
|
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||||
|
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/integrii/flaggy v1.5.2 h1:bWV20MQEngo4hWhno3i5Z9ISPxLPKj9NOGNwTWb/8IQ=
|
||||||
|
github.com/integrii/flaggy v1.5.2/go.mod h1:dO13u7SYuhk910nayCJ+s1DeAAGC1THCMj1uSFmwtQ8=
|
||||||
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c h1:u6SKchux2yDvFQnDHS3lPnIRmfVJ5Sxy3ao2SIdysLQ=
|
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c h1:u6SKchux2yDvFQnDHS3lPnIRmfVJ5Sxy3ao2SIdysLQ=
|
||||||
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
|
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
|
||||||
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
|
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
|
||||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
|||||||
@@ -2,13 +2,14 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/integrii/flaggy"
|
||||||
)
|
)
|
||||||
|
|
||||||
type config struct {
|
type config struct {
|
||||||
@@ -38,80 +39,84 @@ type DocspellItem struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
parser, commands := newCLIParser()
|
||||||
if len(os.Args) < 2 {
|
if len(os.Args) < 2 {
|
||||||
printUsage(os.Stderr)
|
parser.ShowHelp()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if err := parser.ParseArgs(os.Args[1:]); err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
|
||||||
switch os.Args[1] {
|
switch {
|
||||||
case "import":
|
case commands.importCommand.Used:
|
||||||
if isHelpRequest(os.Args[2:]) {
|
|
||||||
runImportCommand(config{}, "", os.Args[2:])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cfg, password := loadConfigAndPassword()
|
cfg, password := loadConfigAndPassword()
|
||||||
runImportCommand(cfg, password, os.Args[2:])
|
runImportCommand(cfg, password, os.Args[2:])
|
||||||
case "mount":
|
case commands.mountCommand.Used:
|
||||||
if isHelpRequest(os.Args[2:]) {
|
|
||||||
_ = runMountCommand(os.Args[2:], config{}, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cfg, password := loadConfigAndPassword()
|
cfg, password := loadConfigAndPassword()
|
||||||
if err := runMountCommand(os.Args[2:], cfg, password); err != nil {
|
if err := runMountCommand(os.Args[2:], cfg, password); err != nil {
|
||||||
fmt.Fprintln(os.Stderr, "mount failed:", err)
|
fmt.Fprintln(os.Stderr, "mount failed:", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
case "get-path":
|
case commands.getPathCommand.Used:
|
||||||
if isHelpRequest(os.Args[2:]) {
|
|
||||||
_ = runGetPathCommand(os.Args[2:], config{}, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cfg, password := loadConfigAndPassword()
|
cfg, password := loadConfigAndPassword()
|
||||||
if err := runGetPathCommand(os.Args[2:], cfg, password); err != nil {
|
if err := runGetPathCommand(os.Args[2:], cfg, password); err != nil {
|
||||||
fmt.Fprintln(os.Stderr, "get-path failed:", err)
|
fmt.Fprintln(os.Stderr, "get-path failed:", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
case "get-url":
|
case commands.getURLCommand.Used:
|
||||||
if isHelpRequest(os.Args[2:]) {
|
|
||||||
_ = runGetURLCommand(os.Args[2:], config{}, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cfg, password := loadConfigAndPassword()
|
cfg, password := loadConfigAndPassword()
|
||||||
if err := runGetURLCommand(os.Args[2:], cfg, password); err != nil {
|
if err := runGetURLCommand(os.Args[2:], cfg, password); err != nil {
|
||||||
fmt.Fprintln(os.Stderr, "get-url failed:", err)
|
fmt.Fprintln(os.Stderr, "get-url failed:", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
case "-h", "--help", "help":
|
|
||||||
printUsage(os.Stdout)
|
|
||||||
default:
|
default:
|
||||||
fmt.Fprintf(os.Stderr, "unknown command %q\n\n", os.Args[1])
|
parser.ShowHelp()
|
||||||
printUsage(os.Stderr)
|
|
||||||
os.Exit(2)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func isHelpRequest(args []string) bool {
|
type cliCommands struct {
|
||||||
for _, arg := range args {
|
importCommand *flaggy.Subcommand
|
||||||
if arg == "-h" || arg == "--help" {
|
mountCommand *flaggy.Subcommand
|
||||||
return true
|
getPathCommand *flaggy.Subcommand
|
||||||
}
|
getURLCommand *flaggy.Subcommand
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func printUsage(out *os.File) {
|
func newCLIParser() (*flaggy.Parser, cliCommands) {
|
||||||
name := filepath.Base(os.Args[0])
|
parser := flaggy.NewParser(filepath.Base(os.Args[0]))
|
||||||
fmt.Fprintf(out, `Usage:
|
parser.Description = "Docspell import, archive, mount, and helper CLI"
|
||||||
%[1]s <command> [flags]
|
parser.ShowHelpOnUnexpected = true
|
||||||
|
parser.DisableShowVersionWithVersion()
|
||||||
|
|
||||||
Commands:
|
commands := cliCommands{
|
||||||
import Scan configured import folders, archive confirmed files, and optionally upload missing files
|
importCommand: flaggy.NewSubcommand("import"),
|
||||||
mount Expose Docspell search results as a read-only FUSE filesystem
|
mountCommand: flaggy.NewSubcommand("mount"),
|
||||||
get-path Resolve a Docspell item ID or URL to the local mounted path
|
getPathCommand: flaggy.NewSubcommand("get-path"),
|
||||||
get-url Resolve a local mounted path, item ID, or item URL to a Docspell web URL
|
getURLCommand: flaggy.NewSubcommand("get-url"),
|
||||||
|
}
|
||||||
|
commands.importCommand.Description = "Scan configured import folders, archive confirmed files, and optionally upload missing files"
|
||||||
|
commands.mountCommand.Description = "Expose Docspell search results as a read-only FUSE filesystem"
|
||||||
|
commands.getPathCommand.Description = "Resolve a Docspell item ID or URL to the local mounted path"
|
||||||
|
commands.getURLCommand.Description = "Resolve a local mounted path, item ID, or item URL to a Docspell web URL"
|
||||||
|
|
||||||
Run "%[1]s <command> -h" for command-specific help.
|
var uploadMissing bool
|
||||||
`, name)
|
commands.importCommand.Bool(&uploadMissing, "", "upload-missing", "true, to upload files to docspell that do not yet exist there")
|
||||||
|
var query, mountPoint, itemIDOrURL, pathOrID string
|
||||||
|
authHeader := defaultDocspellAuthHeader
|
||||||
|
limit := 1000
|
||||||
|
commands.mountCommand.String(&query, "", "query", "Docspell item query to expose")
|
||||||
|
commands.mountCommand.Int(&limit, "", "limit", "number of items to fetch per API request")
|
||||||
|
commands.mountCommand.String(&authHeader, "", "auth-header", "HTTP header used for the Docspell auth token")
|
||||||
|
commands.mountCommand.AddPositionalValue(&mountPoint, "mountpoint", 1, false, "mount point, overriding mountPath from config")
|
||||||
|
commands.getPathCommand.AddPositionalValue(&itemIDOrURL, "item-id-or-url", 1, true, "Docspell item ID or web URL")
|
||||||
|
commands.getURLCommand.AddPositionalValue(&pathOrID, "local-path-or-item-id", 1, true, "local mounted path, item ID, or item URL")
|
||||||
|
|
||||||
|
parser.AttachSubcommand(commands.importCommand, 1)
|
||||||
|
parser.AttachSubcommand(commands.mountCommand, 1)
|
||||||
|
parser.AttachSubcommand(commands.getPathCommand, 1)
|
||||||
|
parser.AttachSubcommand(commands.getURLCommand, 1)
|
||||||
|
return parser, commands
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadConfigAndPassword() (config, string) {
|
func loadConfigAndPassword() (config, string) {
|
||||||
@@ -145,9 +150,8 @@ func loadConfigAndPassword() (config, string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runImportCommand(cfg config, password string, args []string) {
|
func runImportCommand(cfg config, password string, args []string) {
|
||||||
importFlags := flag.NewFlagSet("import", flag.ExitOnError)
|
options, err := parseImportOptions(args)
|
||||||
uploadMissing := importFlags.Bool("upload-missing", os.Getenv("DS_CC_UPLOAD_MISSING") == "true", "true, to upload files to docspell that do not yet exist there")
|
if err != nil {
|
||||||
if err := importFlags.Parse(args); err != nil {
|
|
||||||
fmt.Println("Error parsing flags:", err)
|
fmt.Println("Error parsing flags:", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
@@ -161,7 +165,7 @@ func runImportCommand(cfg config, password string, args []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Settings:")
|
fmt.Println("Settings:")
|
||||||
if *uploadMissing {
|
if options.uploadMissing {
|
||||||
fmt.Println(" - UPLOAD files? YES")
|
fmt.Println(" - UPLOAD files? YES")
|
||||||
fmt.Println(" files not existing in Docspell will be uploaded and will be re-checked in the next run.")
|
fmt.Println(" files not existing in Docspell will be uploaded and will be re-checked in the next run.")
|
||||||
} else {
|
} else {
|
||||||
@@ -211,7 +215,7 @@ func runImportCommand(cfg config, password string, args []string) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fmt.Println(" Files does not exist, yet")
|
fmt.Println(" Files does not exist, yet")
|
||||||
if *uploadMissing {
|
if options.uploadMissing {
|
||||||
fmt.Print(" ...uploading file..")
|
fmt.Print(" ...uploading file..")
|
||||||
cmd = exec.Command("dsc", "-f", "json", "upload", path)
|
cmd = exec.Command("dsc", "-f", "json", "upload", path)
|
||||||
output, err := cmd.Output()
|
output, err := cmd.Output()
|
||||||
@@ -244,6 +248,20 @@ func runImportCommand(cfg config, password string, args []string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type importOptions struct {
|
||||||
|
uploadMissing bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseImportOptions(args []string) (importOptions, error) {
|
||||||
|
options := importOptions{uploadMissing: os.Getenv("DS_CC_UPLOAD_MISSING") == "true"}
|
||||||
|
parser := flaggy.NewParser("import")
|
||||||
|
parser.Description = "Scan configured import folders, archive confirmed files, and optionally upload missing files"
|
||||||
|
parser.DisableShowVersionWithVersion()
|
||||||
|
parser.ShowHelpOnUnexpected = true
|
||||||
|
parser.Bool(&options.uploadMissing, "", "upload-missing", "true, to upload files to docspell that do not yet exist there")
|
||||||
|
return options, parser.ParseArgs(args)
|
||||||
|
}
|
||||||
|
|
||||||
func handleExistingFile(cfg config, fileExistsResponse FileExistsResult) error {
|
func handleExistingFile(cfg config, fileExistsResponse FileExistsResult) error {
|
||||||
// File exists in Docspell
|
// File exists in Docspell
|
||||||
items := fileExistsResponse.Items
|
items := fileExistsResponse.Items
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@@ -15,6 +14,7 @@ import (
|
|||||||
"bazil.org/fuse"
|
"bazil.org/fuse"
|
||||||
"bazil.org/fuse/fs"
|
"bazil.org/fuse/fs"
|
||||||
"bazil.org/fuse/fuseutil"
|
"bazil.org/fuse/fuseutil"
|
||||||
|
"github.com/integrii/flaggy"
|
||||||
)
|
)
|
||||||
|
|
||||||
type docspellFS struct {
|
type docspellFS struct {
|
||||||
@@ -54,42 +54,32 @@ type mountedItemMetadata struct {
|
|||||||
const mountMetadataFileName = ".docspell-cli-metadata.json"
|
const mountMetadataFileName = ".docspell-cli-metadata.json"
|
||||||
|
|
||||||
func runMountCommand(args []string, cfg config, password string) error {
|
func runMountCommand(args []string, cfg config, password string) error {
|
||||||
fsFlags := flag.NewFlagSet("mount", flag.ExitOnError)
|
options, err := parseMountOptions(args, cfg)
|
||||||
query := fsFlags.String("query", cfg.MountQuery, "Docspell item query to expose")
|
if err != nil {
|
||||||
limit := fsFlags.Int("limit", 1000, "number of items to fetch per API request")
|
|
||||||
authHeader := fsFlags.String("auth-header", defaultDocspellAuthHeader, "HTTP header used for the Docspell auth token")
|
|
||||||
if err := fsFlags.Parse(args); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
mountPoint := cfg.MountPath
|
if options.mountPoint == "" {
|
||||||
if fsFlags.NArg() > 1 {
|
|
||||||
return fmt.Errorf("usage: %s mount [flags] [mountpoint]", filepath.Base(os.Args[0]))
|
|
||||||
}
|
|
||||||
if fsFlags.NArg() == 1 {
|
|
||||||
mountPoint = fsFlags.Arg(0)
|
|
||||||
}
|
|
||||||
if mountPoint == "" {
|
|
||||||
return fmt.Errorf("mount point missing: pass one or set MountPath in config")
|
return fmt.Errorf("mount point missing: pass one or set MountPath in config")
|
||||||
}
|
}
|
||||||
if os.Getenv("DOCSPELL_CLI_MOUNT_FOREGROUND") != "1" {
|
if os.Getenv("DOCSPELL_CLI_MOUNT_FOREGROUND") != "1" {
|
||||||
return startMountInBackground(args, mountPoint, false)
|
return startMountInBackground(args, options.mountPoint, false)
|
||||||
}
|
}
|
||||||
if err := os.MkdirAll(mountPoint, 0755); err != nil {
|
if err := os.MkdirAll(options.mountPoint, 0755); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
client := NewDocspellClient(cfg.DocspellURL, *authHeader)
|
client := NewDocspellClient(cfg.DocspellURL, options.authHeader)
|
||||||
if err := client.Login(context.Background(), cfg.User, password); err != nil {
|
if err := client.Login(context.Background(), cfg.User, password); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
items, err := client.SearchItems(context.Background(), *query, *limit)
|
items, err := client.SearchItems(context.Background(), options.query, options.limit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("search items: %w", err)
|
return fmt.Errorf("search items: %w", err)
|
||||||
}
|
}
|
||||||
root := buildMountTree(context.Background(), client, items)
|
root := buildMountTree(context.Background(), client, items)
|
||||||
|
|
||||||
conn, err := fuse.Mount(
|
conn, err := fuse.Mount(
|
||||||
mountPoint,
|
options.mountPoint,
|
||||||
fuse.FSName("docspell"),
|
fuse.FSName("docspell"),
|
||||||
fuse.Subtype("docspell-cli"),
|
fuse.Subtype("docspell-cli"),
|
||||||
fuse.ReadOnly(),
|
fuse.ReadOnly(),
|
||||||
@@ -99,10 +89,35 @@ func runMountCommand(args []string, cfg config, password string) error {
|
|||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
fmt.Printf("Mounted %d items read-only at %s. Unmount with: fusermount -u %s\n", len(items), mountPoint, mountPoint)
|
fmt.Printf("Mounted %d items read-only at %s. Unmount with: fusermount -u %s\n", len(items), options.mountPoint, options.mountPoint)
|
||||||
return fs.Serve(conn, &docspellFS{root: root})
|
return fs.Serve(conn, &docspellFS{root: root})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type mountOptions struct {
|
||||||
|
query string
|
||||||
|
limit int
|
||||||
|
authHeader string
|
||||||
|
mountPoint string
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseMountOptions(args []string, cfg config) (mountOptions, error) {
|
||||||
|
options := mountOptions{
|
||||||
|
query: cfg.MountQuery,
|
||||||
|
limit: 1000,
|
||||||
|
authHeader: defaultDocspellAuthHeader,
|
||||||
|
mountPoint: cfg.MountPath,
|
||||||
|
}
|
||||||
|
parser := flaggy.NewParser("mount")
|
||||||
|
parser.Description = "Expose Docspell search results as a read-only FUSE filesystem"
|
||||||
|
parser.DisableShowVersionWithVersion()
|
||||||
|
parser.ShowHelpOnUnexpected = true
|
||||||
|
parser.String(&options.query, "", "query", "Docspell item query to expose")
|
||||||
|
parser.Int(&options.limit, "", "limit", "number of items to fetch per API request")
|
||||||
|
parser.String(&options.authHeader, "", "auth-header", "HTTP header used for the Docspell auth token")
|
||||||
|
parser.AddPositionalValue(&options.mountPoint, "mountpoint", 1, false, "mount point, overriding mountPath from config")
|
||||||
|
return options, parser.ParseArgs(args)
|
||||||
|
}
|
||||||
|
|
||||||
func startMountInBackground(args []string, mountPoint string, quiet bool) error {
|
func startMountInBackground(args []string, mountPoint string, quiet bool) error {
|
||||||
mountPoint = cleanMountPath(mountPoint)
|
mountPoint = cleanMountPath(mountPoint)
|
||||||
if isMounted(mountPoint) {
|
if isMounted(mountPoint) {
|
||||||
@@ -133,18 +148,15 @@ func startMountInBackground(args []string, mountPoint string, quiet bool) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runGetPathCommand(args []string, cfg config, password string) error {
|
func runGetPathCommand(args []string, cfg config, password string) error {
|
||||||
flags := flag.NewFlagSet("get-path", flag.ExitOnError)
|
itemIDOrURL, err := parseSingleArgumentCommand("get-path", "item-id-or-url", "Docspell item ID or web URL", args)
|
||||||
if err := flags.Parse(args); err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if flags.NArg() != 1 {
|
|
||||||
return fmt.Errorf("usage: %s get-path <item-id-or-url>", filepath.Base(os.Args[0]))
|
|
||||||
}
|
|
||||||
mountPoint, err := ensureMounted(cfg, password)
|
mountPoint, err := ensureMounted(cfg, password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
id := itemIDFromURLOrID(flags.Arg(0))
|
id := itemIDFromURLOrID(itemIDOrURL)
|
||||||
if path, err := friendlyLocalPathForItemID(mountPoint, id); err == nil && path != "" {
|
if path, err := friendlyLocalPathForItemID(mountPoint, id); err == nil && path != "" {
|
||||||
fmt.Println(path)
|
fmt.Println(path)
|
||||||
return nil
|
return nil
|
||||||
@@ -183,16 +195,11 @@ func readMountMetadata(mountPoint string) (mountMetadata, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runGetURLCommand(args []string, cfg config, password string) error {
|
func runGetURLCommand(args []string, cfg config, password string) error {
|
||||||
flags := flag.NewFlagSet("get-url", flag.ExitOnError)
|
id, err := parseSingleArgumentCommand("get-url", "local-path-or-item-id", "local mounted path, item ID, or item URL", args)
|
||||||
if err := flags.Parse(args); err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if flags.NArg() != 1 {
|
|
||||||
return fmt.Errorf("usage: %s get-url <local-path-or-item-id>", filepath.Base(os.Args[0]))
|
|
||||||
}
|
|
||||||
id := flags.Arg(0)
|
|
||||||
if strings.Contains(id, string(os.PathSeparator)) || strings.HasPrefix(id, ".") {
|
if strings.Contains(id, string(os.PathSeparator)) || strings.HasPrefix(id, ".") {
|
||||||
var err error
|
|
||||||
id, err = itemIDFromLocalPath(id, cfg)
|
id, err = itemIDFromLocalPath(id, cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -202,6 +209,15 @@ func runGetURLCommand(args []string, cfg config, password string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseSingleArgumentCommand(commandName, argName, argDescription string, args []string) (string, error) {
|
||||||
|
var value string
|
||||||
|
parser := flaggy.NewParser(commandName)
|
||||||
|
parser.DisableShowVersionWithVersion()
|
||||||
|
parser.ShowHelpOnUnexpected = true
|
||||||
|
parser.AddPositionalValue(&value, argName, 1, true, argDescription)
|
||||||
|
return value, parser.ParseArgs(args)
|
||||||
|
}
|
||||||
|
|
||||||
func ensureMounted(cfg config, password string) (string, error) {
|
func ensureMounted(cfg config, password string) (string, error) {
|
||||||
mountPoint := cleanMountPath(cfg.MountPath)
|
mountPoint := cleanMountPath(cfg.MountPath)
|
||||||
if mountPoint == "" {
|
if mountPoint == "" {
|
||||||
|
|||||||
Reference in New Issue
Block a user