Path completion for sync command (#208)

Follow up to #207.
This commit is contained in:
Pieter Noordhuis 2023-02-20 14:31:59 +01:00 committed by GitHub
parent 6c93c96bd1
commit 7bf212e54a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 109 additions and 0 deletions

82
cmd/sync/completion.go Normal file
View File

@ -0,0 +1,82 @@
package sync
import (
"context"
"fmt"
"path"
"strings"
"github.com/databricks/databricks-sdk-go"
"github.com/databricks/databricks-sdk-go/service/workspace"
"github.com/spf13/cobra"
)
// List directories or repos under the specified path.
// Returns a channel such that we can list multiple paths in parallel.
func fetchDirs(ctx context.Context, wsc *databricks.WorkspaceClient, path string) <-chan []string {
ch := make(chan []string, 1)
go func() {
defer close(ch)
files, err := wsc.Workspace.ListAll(ctx, workspace.List{
Path: path,
})
if err != nil {
return
}
// Filter directories and repos.
// We're interested only in paths we can sync to.
dirs := []string{}
for _, file := range files {
switch file.ObjectType {
case workspace.ObjectTypeDirectory, workspace.ObjectTypeRepo:
dirs = append(dirs, file.Path)
}
}
ch <- dirs
}()
return ch
}
func completeRemotePath(
ctx context.Context,
wsc *databricks.WorkspaceClient,
toComplete string,
) ([]string, cobra.ShellCompDirective) {
me, err := wsc.CurrentUser.Me(ctx)
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
prefixes := []string{
path.Clean(fmt.Sprintf("/Users/%s", me.UserName)) + "/",
path.Clean(fmt.Sprintf("/Repos/%s", me.UserName)) + "/",
}
validPrefix := false
for _, p := range prefixes {
if strings.HasPrefix(toComplete, p) {
validPrefix = true
}
}
if !validPrefix {
return prefixes, cobra.ShellCompDirectiveNoSpace
}
// If the user is TAB-ing their way through a path, the path in `toComplete`
// is valid and we should list nested directories.
// If the path in `toComplete` is incomplete, however,
// then we should list adjacent directories.
nested := fetchDirs(ctx, wsc, toComplete)
adjacent := fetchDirs(ctx, wsc, path.Dir(toComplete))
dirs := <-nested
if dirs == nil {
dirs = <-adjacent
}
return dirs, cobra.ShellCompDirectiveNoSpace
}

View File

@ -103,6 +103,33 @@ var syncCmd = &cobra.Command{
return s.RunOnce(ctx) return s.RunOnce(ctx)
}, },
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
err := root.TryConfigureBundle(cmd, args)
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
// No completion in the context of a bundle.
// Source and destination paths are taken from bundle configuration.
b := bundle.GetOrNil(cmd.Context())
if b != nil {
return nil, cobra.ShellCompDirectiveNoFileComp
}
switch len(args) {
case 0:
return nil, cobra.ShellCompDirectiveFilterDirs
case 1:
wsc, err := databricks.NewWorkspaceClient()
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
return completeRemotePath(cmd.Context(), wsc, toComplete)
default:
return nil, cobra.ShellCompDirectiveNoFileComp
}
},
} }
// project files polling interval // project files polling interval