Beispiel #1
0
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
}
Beispiel #2
0
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
}
Beispiel #3
0
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
}
Beispiel #4
0
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
}
Beispiel #5
0
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
}
Beispiel #6
0
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
}
Beispiel #7
0
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
}
Beispiel #8
0
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
}
Beispiel #9
0
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
}
Beispiel #10
0
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
}