Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,12 +228,18 @@ All `--sort`, `--reverse`, `--time`, and `--time-format` flags work with both `l
### Sharing

```sh
$ dbxcli share link create /file.txt # create or return an existing shared link
$ dbxcli share link update <url> --allow-download # update shared link settings
$ dbxcli share list link # list existing shared links
$ dbxcli share-link create /file.txt # create or return an existing shared link
$ dbxcli share-link info <url> # display shared link information
$ dbxcli share-link list # list existing shared links
$ dbxcli share-link list /file.txt # list direct shared links for a path
$ dbxcli share-link revoke <url> # revoke a shared link
$ dbxcli share-link update <url> --allow-download # update shared link settings
$ dbxcli share list link # deprecated compatibility command
$ dbxcli share list folder # list shared folders
```

New and changed commands should write command results to stdout. Status, progress, warnings, diagnostics, and verbose logs should go to stderr.

### Team management

```sh
Expand Down
22 changes: 22 additions & 0 deletions cmd/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,25 @@ func commandOutputFormat(cmd *cobra.Command) output.Format {
}
return output.FormatText
}

func commandVerbose(cmd *cobra.Command) bool {
if cmd == nil {
return false
}
verbose, err := cmd.Flags().GetBool("verbose")
if err == nil {
return verbose
}
verbose, err = cmd.InheritedFlags().GetBool("verbose")
if err == nil {
return verbose
}
verbose, err = cmd.PersistentFlags().GetBool("verbose")
return err == nil && verbose
}

func commandVerboseStatus(cmd *cobra.Command, format string, args ...any) {
if commandVerbose(cmd) {
commandOutput(cmd).Status(format, args...)
}
}
36 changes: 36 additions & 0 deletions cmd/output_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,39 @@ func TestCommandOutputHonorsInheritedJSONFlag(t *testing.T) {
t.Fatalf("stdout = %q, want %q", got, want)
}
}

func TestCommandVerboseHonorsInheritedVerboseFlag(t *testing.T) {
root := &cobra.Command{}
root.PersistentFlags().BoolP("verbose", "v", false, "")

cmd := &cobra.Command{}
root.AddCommand(cmd)

if err := root.PersistentFlags().Set("verbose", "true"); err != nil {
t.Fatalf("set verbose: %v", err)
}

if !commandVerbose(cmd) {
t.Fatal("commandVerbose = false, want true")
}
}

func TestCommandVerboseStatusWritesOnlyWhenVerbose(t *testing.T) {
var stderr bytes.Buffer
cmd := &cobra.Command{}
cmd.Flags().Bool("verbose", false, "")
cmd.SetErr(&stderr)

commandVerboseStatus(cmd, "done %s", "quietly")
if got := stderr.String(); got != "" {
t.Fatalf("stderr = %q, want empty", got)
}

if err := cmd.Flags().Set("verbose", "true"); err != nil {
t.Fatalf("set verbose: %v", err)
}
commandVerboseStatus(cmd, "done %s", "loudly")
if got, want := stderr.String(), "done loudly\n"; got != want {
t.Fatalf("stderr = %q, want %q", got, want)
}
}
108 changes: 84 additions & 24 deletions cmd/share-list-links.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,61 +15,121 @@
package cmd

import (
"errors"
"fmt"
"io"

"github.com/dropbox/dropbox-sdk-go-unofficial/v6/dropbox/sharing"
"github.com/spf13/cobra"
)

func shareListLinks(cmd *cobra.Command, args []string) (err error) {
return shareLinkList(cmd, args)
}

func shareLinkList(cmd *cobra.Command, args []string) error {
if len(args) > 1 {
return errors.New("`share-link list` accepts at most one `path` argument")
}

arg := sharing.NewListSharedLinksArg()
if len(args) == 1 {
path, err := validatePath(args[0])
if err != nil {
return err
}
arg.Path = path
arg.DirectOnly = true
}

dbx := sharing.New(config)
res, err := dbx.ListSharedLinks(arg)
dbx := newSharedLinkClient(config)
links, err := listSharedLinks(dbx, arg)
if err != nil {
return
return err
}

printLinks(res.Links)
if arg.Path != "" {
commandVerboseStatus(cmd, "Listed %d shared links for %s", len(links), arg.Path)
} else {
commandVerboseStatus(cmd, "Listed %d shared links", len(links))
}

for res.HasMore {
arg = sharing.NewListSharedLinksArg()
arg.Cursor = res.Cursor
return commandOutput(cmd).RenderText(func(w io.Writer) error {
return renderSharedLinks(w, links)
})
}

res, err = dbx.ListSharedLinks(arg)
func listSharedLinks(dbx sharedLinkClient, arg *sharing.ListSharedLinksArg) ([]sharing.IsSharedLinkMetadata, error) {
var links []sharing.IsSharedLinkMetadata
for {
res, err := dbx.ListSharedLinks(arg)
if err != nil {
return
return nil, err
}
links = append(links, res.Links...)

printLinks(res.Links)
if !res.HasMore {
break
}
if res.Cursor == "" {
return nil, errors.New("shared link list has more results but no cursor")
}
arg = sharing.NewListSharedLinksArg()
arg.Cursor = res.Cursor
}

return
return links, nil
}

func printLinks(links []sharing.IsSharedLinkMetadata) {
func renderSharedLinks(out io.Writer, links []sharing.IsSharedLinkMetadata) error {
for _, l := range links {
switch sl := l.(type) {
case *sharing.FileLinkMetadata:
printLink(sl.SharedLinkMetadata)
case *sharing.FolderLinkMetadata:
printLink(sl.SharedLinkMetadata)
default:
fmt.Printf("found unknown shared link type")
name, url, ok := sharedLinkDisplay(l)
if !ok {
return errors.New("found unknown shared link type")
}
if _, err := fmt.Fprintf(out, "%s\t%s\n", name, url); err != nil {
return err
}
}

return nil
}

func printLink(sl sharing.SharedLinkMetadata) {
fmt.Printf("%v\t%v\n", sl.Name, sl.Url)
func sharedLinkDisplay(link sharing.IsSharedLinkMetadata) (name string, url string, ok bool) {
switch sl := link.(type) {
case *sharing.FileLinkMetadata:
return sharedLinkMetadataDisplay(sl.SharedLinkMetadata)
case *sharing.FolderLinkMetadata:
return sharedLinkMetadataDisplay(sl.SharedLinkMetadata)
case *sharing.SharedLinkMetadata:
return sharedLinkMetadataDisplay(*sl)
default:
return "", "", false
}
}

var shareListLinksCmd = &cobra.Command{
Use: "link",
func sharedLinkMetadataDisplay(sl sharing.SharedLinkMetadata) (name string, url string, ok bool) {
name = sl.Name
if name == "" {
name = sl.PathLower
}
return name, sl.Url, sl.Url != ""
}

var shareLinkListCmd = &cobra.Command{
Use: "list [path]",
Short: "List shared links",
RunE: shareListLinks,
RunE: shareLinkList,
}

var shareListLinksCmd = &cobra.Command{
Use: "link",
Short: "List shared links",
Deprecated: "use `dbxcli share-link list` instead",
RunE: shareListLinks,
}

func init() {
shareLinkCmd.AddCommand(shareLinkListCmd)
shareListCmd.AddCommand(shareListLinksCmd)
}
Loading