Skip to content

Commit

Permalink
matches for pull + list in
Browse files Browse the repository at this point in the history
  • Loading branch information
Emmanuel Odeke committed Apr 3, 2015
1 parent fcf3239 commit 8487a59
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 13 deletions.
13 changes: 13 additions & 0 deletions README.md
Expand Up @@ -88,6 +88,13 @@ Run it without any arguments to pull all of the files from the current path:
$ drive pull
```

Pulling by matches is also supported

```shell
$ cd ~/myDrive/content/2015
$ drive pull --matches vines docx
```

To force download from paths that otherwise would be marked with no-changes

```shell
Expand Down Expand Up @@ -318,6 +325,12 @@ Pass in a directory path to list files in that directory:
$ drive list photos
```

To list matches

```shell
$ drive list --matches mp4 go
```

The `-trashed` option can be specified to show trashed files in the listing:

```shell
Expand Down
44 changes: 39 additions & 5 deletions cmd/drive/main.go
Expand Up @@ -141,6 +141,7 @@ type listCmd struct {
shared *bool
inTrash *bool
version *bool
matches *bool
owners *bool
quiet *bool
}
Expand All @@ -158,13 +159,25 @@ func (cmd *listCmd) Flags(fs *flag.FlagSet) *flag.FlagSet {
cmd.noPrompt = fs.Bool("no-prompt", false, "shows no prompt before pagination")
cmd.owners = fs.Bool("owners", false, "shows the owner names per file")
cmd.recursive = fs.Bool("r", false, "recursively list subdirectories")
cmd.matches = fs.Bool("matches", false, "list by prefix")
cmd.quiet = fs.Bool(drive.QuietKey, false, "if set, do not log anything but errors")

return fs
}

func (cmd *listCmd) Run(args []string) {
sources, context, path := preprocessArgs(args)
var path string
var sources []string
var context *config.Context

if !*cmd.matches {
sources, context, path = preprocessArgs(args)
} else {
cwd, err := os.Getwd()
exitWithError(err)
sources = args
_, context, path = preprocessArgs([]string{cwd})
}

typeMask := 0
if *cmd.directories {
Expand All @@ -189,7 +202,7 @@ func (cmd *listCmd) Run(args []string) {
typeMask |= drive.Minimal
}

exitWithError(drive.New(context, &drive.Options{
options := drive.Options{
Depth: *cmd.depth,
Hidden: *cmd.hidden,
InTrash: *cmd.inTrash,
Expand All @@ -200,7 +213,13 @@ func (cmd *listCmd) Run(args []string) {
Sources: sources,
TypeMask: typeMask,
Quiet: *cmd.quiet,
}).List())
}

if *cmd.matches {
exitWithError(drive.New(context, &options).ListMatches())
} else {
exitWithError(drive.New(context, &options).List())
}
}

type statCmd struct {
Expand Down Expand Up @@ -233,6 +252,7 @@ type pullCmd struct {
export *string
force *bool
hidden *bool
matches *bool
noPrompt *bool
noClobber *bool
recursive *bool
Expand All @@ -253,14 +273,26 @@ func (cmd *pullCmd) Flags(fs *flag.FlagSet) *flag.FlagSet {
cmd.ignoreChecksum = fs.Bool(drive.CLIOptionIgnoreChecksum, false, drive.DescIgnoreChecksum)
cmd.ignoreConflict = fs.Bool(drive.CLIOptionIgnoreConflict, false, drive.DescIgnoreConflict)
cmd.exportsDir = fs.String("export-dir", "", "directory to place exports")
cmd.matches = fs.Bool("matches", false, "search by prefix")
cmd.piped = fs.Bool("piped", false, "if true, read content from stdin")
cmd.quiet = fs.Bool(drive.QuietKey, false, "if set, do not log anything but errors")

return fs
}

func (cmd *pullCmd) Run(args []string) {
sources, context, path := preprocessArgs(args)
var path string
var sources []string
var context *config.Context

if !*cmd.matches {
sources, context, path = preprocessArgs(args)
} else {
cwd, err := os.Getwd()
exitWithError(err)
sources = args
_, context, path = preprocessArgs([]string{cwd})
}

// Filter out empty strings.
exports := drive.NonEmptyStrings(strings.Split(*cmd.export, ","))
Expand All @@ -281,7 +313,9 @@ func (cmd *pullCmd) Run(args []string) {
Quiet: *cmd.quiet,
}

if *cmd.piped {
if *cmd.matches {
exitWithError(drive.New(context, options).PullMatches())
} else if *cmd.piped {
exitWithError(drive.New(context, options).PullPiped())
} else {
exitWithError(drive.New(context, options).Pull())
Expand Down
39 changes: 33 additions & 6 deletions src/changes.go
Expand Up @@ -83,6 +83,31 @@ func (g *Commands) pathResolve() (relPath, absPath string, err error) {
return
}

func (g *Commands) resolveToLocalFile(relToRoot, fsPath string) (local *File, err error) {
if g.opts.IgnoreRegexp != nil && g.opts.IgnoreRegexp.Match([]byte(relToRoot)) {
err = fmt.Errorf("\n'%s' is set to be ignored yet is being processed. Use `%s` to override this\n", relToRoot, ForceKey)
return
}

localinfo, _ := os.Stat(fsPath)
if localinfo != nil {
local = NewLocalFile(fsPath, localinfo)
}

return
}

func (g *Commands) byRemoteResolve(relToRoot, fsPath string, r *File, isPush bool) (cl []*Change, err error) {
var l *File
l, err = g.resolveToLocalFile(relToRoot, fsPath)
if err != nil {
g.log.LogErrf("%v\n", err)
return cl, nil
}

return g.doChangeListRecv(relToRoot, fsPath, l, r, isPush)
}

func (g *Commands) changeListResolve(relToRoot, fsPath string, isPush bool) (cl []*Change, err error) {
var r, l *File
r, err = g.rem.FindByPath(relToRoot)
Expand All @@ -93,17 +118,19 @@ func (g *Commands) changeListResolve(relToRoot, fsPath string, isPush bool) (cl
}
}

if g.opts.IgnoreRegexp != nil && g.opts.IgnoreRegexp.Match([]byte(relToRoot)) {
g.log.LogErrf("\n'%s' is set to be ignored yet is being processed. Use `%s` to override this\n", relToRoot, ForceKey)
l, err = g.resolveToLocalFile(relToRoot, fsPath)
if err != nil {
g.log.LogErrf("%s: %v\n", relToRoot, err)
return cl, nil
}

localinfo, _ := os.Stat(fsPath)
if localinfo != nil {
l = NewLocalFile(fsPath, localinfo)
}
return g.doChangeListRecv(relToRoot, fsPath, l, r, isPush)
}

func (g *Commands) doChangeListRecv(relToRoot, fsPath string, l, r *File, isPush bool) (cl []*Change, err error) {
if l == nil && r == nil {
err = fmt.Errorf("'%s' aka '%s' doesn't exist locally nor remotely",
relToRoot, fsPath)
err = fmt.Errorf("'%s' aka '%s' doesn't exist locally nor remotely",
relToRoot, fsPath)
return
Expand Down
35 changes: 33 additions & 2 deletions src/list.go
Expand Up @@ -45,8 +45,39 @@ type traversalSt struct {
inTrash bool
}

func (g *Commands) List() (err error) {
func (g *Commands) ListMatches() (error) {
matches, err := g.rem.FindMatches(g.opts.Path, g.opts.Sources, g.opts.InTrash)
if err != nil {
return err
}

spin := g.playabler()
spin.play()

for match := range matches {
if match == nil {
continue
}

travSt := traversalSt{
depth: g.opts.Depth,
file: match,
headPath: g.opts.Path,
inTrash: g.opts.InTrash,
mask: g.opts.TypeMask,
}

if !g.breadthFirst(travSt, spin) {
break
}
}

spin.stop()

return nil
}

func (g *Commands) List() (err error) {
resolver := g.rem.FindByPath
if g.opts.InTrash {
resolver = g.rem.FindByPathTrashed
Expand Down Expand Up @@ -92,7 +123,7 @@ func (g *Commands) List() (err error) {
depth: g.opts.Depth,
file: kv.value.(*File),
headPath: kv.key,
inTrash: false,
inTrash: g.opts.InTrash,
mask: g.opts.TypeMask,
}

Expand Down
39 changes: 39 additions & 0 deletions src/pull.go
Expand Up @@ -75,6 +75,45 @@ func (g *Commands) Pull() (err error) {
return g.playPullChangeList(nonConflicts, g.opts.Exports)
}

func (g *Commands) PullMatches() (err error) {
var cl []*Change
matches, err := g.rem.FindMatches(g.opts.Path, g.opts.Sources, false)

if err != nil {
return err
}

p := g.opts.Path
if p == "/" {
p = ""
}

for match := range matches {
if match == nil {
continue
}
relToRoot := "/" + match.Name
fsPath := g.context.AbsPathOf(relToRoot)

ccl, cErr := g.byRemoteResolve(relToRoot, fsPath, match, false)
if cErr != nil {
continue
}

cl = append(cl, ccl...)
}

if len(cl) < 1 {
return fmt.Errorf("no matches found!")
}

ok := printChangeList(g.log, cl, !g.opts.canPrompt(), g.opts.NoClobber)
if ok {
return g.playPullChangeList(cl, g.opts.Exports)
}
return nil
}

func (g *Commands) PullPiped() (err error) {
// Cannot pull asynchronously because the pull order must be maintained
for _, relToRootPath := range g.opts.Sources {
Expand Down

0 comments on commit 8487a59

Please sign in to comment.