func revs(cmd *cobra.Command, args []string) (err error) { if len(args) != 1 { return errors.New("`revs` requires a `file` argument") } path, err := validatePath(args[0]) if err != nil { return } arg := files.NewListRevisionsArg(path) dbx := files.New(config) res, err := dbx.ListRevisions(arg) if err != nil { return } long, _ := cmd.Flags().GetBool("long") if long { fmt.Printf("Revision\tSize\tLast modified\tPath\n") } for _, e := range res.Entries { if long { printFileMetadata(os.Stdout, e, long) } else { fmt.Printf("%s\n", e.Rev) } } return }
func put(cmd *cobra.Command, args []string) (err error) { if len(args) == 0 || len(args) > 2 { return errors.New("`put` requires `src` and/or `dst` arguments") } src := args[0] // Default `dst` to the base segment of the source path; use the second argument if provided. dst := "/" + path.Base(src) if len(args) == 2 { dst, err = validatePath(args[1]) if err != nil { return } } contents, err := os.Open(src) defer contents.Close() if err != nil { return } contentsInfo, err := contents.Stat() if err != nil { return } progressbar := &ioprogress.Reader{ Reader: contents, DrawFunc: ioprogress.DrawTerminalf(os.Stderr, func(progress, total int64) string { return fmt.Sprintf("Uploading %s/%s", humanize.IBytes(uint64(progress)), humanize.IBytes(uint64(total))) }), Size: contentsInfo.Size(), } commitInfo := files.NewCommitInfo(dst) commitInfo.Mode.Tag = "overwrite" // The Dropbox API only accepts timestamps in UTC with second precision. commitInfo.ClientModified = time.Now().UTC().Round(time.Second) dbx := files.New(config) if contentsInfo.Size() > chunkSize { return uploadChunked(dbx, progressbar, commitInfo, contentsInfo.Size()) } if _, err = dbx.Upload(commitInfo, progressbar); err != nil { return } return }
func get(cmd *cobra.Command, args []string) (err error) { if len(args) == 0 || len(args) > 2 { return errors.New("`get` requires `src` and/or `dst` arguments") } src, err := validatePath(args[0]) if err != nil { return } // Default `dst` to the base segment of the source path; use the second argument if provided. dst := path.Base(src) if len(args) == 2 { dst = args[1] } // If `dst` is a directory, append the source filename. if f, err := os.Stat(dst); err == nil && f.IsDir() { dst = path.Join(dst, path.Base(src)) } arg := files.NewDownloadArg(src) dbx := files.New(config) res, contents, err := dbx.Download(arg) defer contents.Close() if err != nil { return } f, err := os.Create(dst) defer f.Close() if err != nil { return } progressbar := &ioprogress.Reader{ Reader: contents, DrawFunc: ioprogress.DrawTerminalf(os.Stderr, func(progress, total int64) string { return fmt.Sprintf("Downloading %s/%s", humanize.IBytes(uint64(progress)), humanize.IBytes(uint64(total))) }), Size: int64(res.Size), } if _, err = io.Copy(f, progressbar); err != nil { return } return }
func rm(cmd *cobra.Command, args []string) error { if len(args) < 1 { return errors.New("rm: missing operand") } force, err := cmd.Flags().GetBool("force") if err != nil { return err } deletePaths := []string{} dbx := files.New(config) // Validate remove paths before executing removal for i := range args { path, err := validatePath(args[i]) if err != nil { return err } pathMetaData, err := getFileMetadata(dbx, path) if err != nil { return err } if _, ok := pathMetaData.(*files.FileMetadata); !ok { folderArg := files.NewListFolderArg(path) res, err := dbx.ListFolder(folderArg) if err != nil { return err } if len(res.Entries) != 0 && !force { return fmt.Errorf("rm: cannot remove ‘%s’: Directory not empty, use `--force` or `-f` to proceed", path) } } deletePaths = append(deletePaths, path) } // Execute removals for _, path := range deletePaths { arg := files.NewDeleteArg(path) if _, err = dbx.Delete(arg); err != nil { return err } } return nil }
func mkdir(cmd *cobra.Command, args []string) (err error) { if len(args) != 1 { return errors.New("`mkdir` requires a `directory` argument") } dst, err := validatePath(args[0]) if err != nil { return } arg := files.NewCreateFolderArg(dst) dbx := files.New(config) if _, err = dbx.CreateFolder(arg); err != nil { return } return }
func mv(cmd *cobra.Command, args []string) error { var destination string var argsToMove []string if len(args) > 2 { destination = args[len(args)-1] argsToMove = args[0 : len(args)-1] } else if len(args) == 2 { destination = args[1] argsToMove = append(argsToMove, args[0]) } else { return fmt.Errorf("mv command requires a source and a destination") } mvErrors := []error{} relocationArgs := []*files.RelocationArg{} for _, argument := range argsToMove { arg, err := makeRelocationArg(argument, destination+"/"+argument) if err != nil { relocationError := fmt.Errorf("Error validating move for %s to %s: %v", argument, destination, err) mvErrors = append(mvErrors, relocationError) } else { relocationArgs = append(relocationArgs, arg) } } dbx := files.New(config) for _, arg := range relocationArgs { if _, err := dbx.Move(arg); err != nil { moveError := fmt.Errorf("Move error: %v", arg) mvErrors = append(mvErrors, moveError) } } for _, mvError := range mvErrors { fmt.Fprintf(os.Stderr, "%v\n", mvError) } return nil }
func cp(cmd *cobra.Command, args []string) error { var destination string var argsToCopy []string if len(args) > 2 { destination = args[len(args)-1] argsToCopy = args[0 : len(args)-1] } else if len(args) == 2 { destination = args[1] argsToCopy = append(argsToCopy, args[0]) } else { return errors.New("cp requires a source and a destination") } cpErrors := []error{} relocationArgs := []*files.RelocationArg{} for _, argument := range argsToCopy { arg, err := makeRelocationArg(argument, destination+"/"+argument) if err != nil { relocationError := fmt.Errorf("Error validating copy for %s to %s: %v", argument, destination, err) cpErrors = append(cpErrors, relocationError) } else { relocationArgs = append(relocationArgs, arg) } } dbx := files.New(config) for _, arg := range relocationArgs { if _, err := dbx.Copy(arg); err != nil { copyError := fmt.Errorf("Copy error: %v", arg) cpErrors = append(cpErrors, copyError) } } for _, cpError := range cpErrors { fmt.Fprintf(os.Stderr, "%v\n", cpError) } return nil }
func restore(cmd *cobra.Command, args []string) (err error) { if len(args) != 2 { return errors.New("`restore` requires `file` and `revision` arguments") } path, err := validatePath(args[0]) if err != nil { return } rev := args[1] arg := files.NewRestoreArg(path, rev) dbx := files.New(config) if _, err = dbx.Restore(arg); err != nil { return } return }
func search(cmd *cobra.Command, args []string) (err error) { if len(args) == 0 { return errors.New("`search` requires a `query` argument") } // Parse path scope, if provided. var scope string if len(args) == 2 { scope = args[1] if !strings.HasPrefix(scope, "/") { return errors.New("`search` `path-scope` must begin with \"/\"") } } arg := files.NewSearchArg(scope, args[0]) dbx := files.New(config) res, err := dbx.Search(arg) if err != nil { return } long, _ := cmd.Flags().GetBool("long") if long { fmt.Printf("Revision\tSize\tLast modified\tPath\n") } for _, m := range res.Matches { switch f := m.Metadata.(type) { case *files.FileMetadata: printFileMetadata(os.Stdout, f, long) case *files.FolderMetadata: printFolderMetadata(os.Stdout, f, long) } } return }
func ls(cmd *cobra.Command, args []string) (err error) { path := "" if len(args) > 0 { if path, err = validatePath(args[0]); err != nil { return err } } dbx := files.New(config) arg := files.NewListFolderArg(path) res, err := dbx.ListFolder(arg) var entries []files.IsMetadata if err != nil { switch e := err.(type) { case files.ListFolderAPIError: // Don't treat a "not_folder" error as fatal; recover by sending a // get_metadata request for the same path and using that response instead. if e.EndpointError.Path.Tag == files.LookupErrorNotFolder { var metaRes files.IsMetadata metaRes, err = getFileMetadata(dbx, path) entries = []files.IsMetadata{metaRes} } else { return err } default: return err } // Return if there's an error other than "not_folder" or if the follow-up // metadata request fails. if err != nil { return err } } else { entries = res.Entries for res.HasMore { arg := files.NewListFolderContinueArg(res.Cursor) res, err = dbx.ListFolderContinue(arg) if err != nil { return err } entries = append(entries, res.Entries...) } } long, _ := cmd.Flags().GetBool("long") if long { w := new(tabwriter.Writer) w.Init(os.Stdout, 4, 8, 1, ' ', 0) fmt.Fprintf(w, "Revision\tSize\tLast modified\tPath\n") for _, entry := range entries { switch f := entry.(type) { case *files.FileMetadata: printFileMetadata(w, f, long) case *files.FolderMetadata: printFolderMetadata(w, f, long) } } w.Flush() } else { entryNames := listOfEntryNames(entries) golumns.Display(entryNames) } return err }