Skip to content

Commit

Permalink
Merge pull request #1445 from montag451/file-push-pull-comp
Browse files Browse the repository at this point in the history
incus: Improve completion for `file push` and `file pull`
  • Loading branch information
stgraber authored Dec 2, 2024
2 parents 1e6cf48 + d09af53 commit 0192192
Show file tree
Hide file tree
Showing 15 changed files with 154 additions and 35 deletions.
6 changes: 3 additions & 3 deletions cmd/incus/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ func (c *cmdClusterList) Command() *cobra.Command {

cmd.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) == 0 {
return c.global.cmpRemotes(false)
return c.global.cmpRemotes(toComplete, false)
}

return nil, cobra.ShellCompDirectiveNoFileComp
Expand Down Expand Up @@ -791,7 +791,7 @@ func (c *cmdClusterEnable) Command() *cobra.Command {

cmd.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) == 0 {
return c.global.cmpRemotes(false)
return c.global.cmpRemotes(toComplete, false)
}

return nil, cobra.ShellCompDirectiveNoFileComp
Expand Down Expand Up @@ -1095,7 +1095,7 @@ Pre-defined column shorthand chars:

cmd.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) == 0 {
return c.global.cmpRemotes(false)
return c.global.cmpRemotes(toComplete, false)
}

return nil, cobra.ShellCompDirectiveNoFileComp
Expand Down
4 changes: 2 additions & 2 deletions cmd/incus/cluster_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ incus cluster group create g1 < config.yaml

cmd.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) == 0 {
return c.global.cmpRemotes(false)
return c.global.cmpRemotes(toComplete, false)
}

return nil, cobra.ShellCompDirectiveNoFileComp
Expand Down Expand Up @@ -481,7 +481,7 @@ Pre-defined column shorthand chars:

cmd.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) == 0 {
return c.global.cmpRemotes(false)
return c.global.cmpRemotes(toComplete, false)
}

return nil, cobra.ShellCompDirectiveNoFileComp
Expand Down
127 changes: 114 additions & 13 deletions cmd/incus/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ package main

import (
"fmt"
"io/fs"
"os"
"path/filepath"
"regexp"
"strings"

Expand Down Expand Up @@ -71,7 +74,7 @@ func (g *cmdGlobal) cmpClusterGroups(toComplete string) ([]string, cobra.ShellCo
}

if !strings.Contains(toComplete, ":") {
remotes, directives := g.cmpRemotes(false)
remotes, directives := g.cmpRemotes(toComplete, false)
results = append(results, remotes...)
cmpDirectives |= directives
}
Expand Down Expand Up @@ -192,7 +195,7 @@ func (g *cmdGlobal) cmpClusterMembers(toComplete string) ([]string, cobra.ShellC
}

if !strings.Contains(toComplete, ":") {
remotes, directives := g.cmpRemotes(false)
remotes, directives := g.cmpRemotes(toComplete, false)
results = append(results, remotes...)
cmpDirectives |= directives
}
Expand Down Expand Up @@ -230,7 +233,7 @@ func (g *cmdGlobal) cmpImages(toComplete string) ([]string, cobra.ShellCompDirec
}

if !strings.Contains(toComplete, ":") {
remotes, directives := g.cmpRemotes(true)
remotes, directives := g.cmpRemotes(toComplete, true)
results = append(results, remotes...)
cmpDirectives |= directives
}
Expand Down Expand Up @@ -330,12 +333,16 @@ func (g *cmdGlobal) cmpInstances(toComplete string) ([]string, cobra.ShellCompDi
name = fmt.Sprintf("%s:%s", resource.remote, instName)
}

if !strings.HasPrefix(name, toComplete) {
continue
}

results = append(results, name)
}
}

if !strings.Contains(toComplete, ":") {
remotes, directives := g.cmpRemotes(false)
remotes, directives := g.cmpRemotes(toComplete, false)
results = append(results, remotes...)
cmpDirectives |= directives
}
Expand Down Expand Up @@ -375,7 +382,7 @@ func (g *cmdGlobal) cmpInstancesAndSnapshots(toComplete string) ([]string, cobra
}

if !strings.Contains(toComplete, ":") {
remotes, directives := g.cmpRemotes(false)
remotes, directives := g.cmpRemotes(toComplete, false)
results = append(results, remotes...)
cmpDirectives |= directives
}
Expand Down Expand Up @@ -453,7 +460,7 @@ func (g *cmdGlobal) cmpNetworkACLs(toComplete string) ([]string, cobra.ShellComp
}

if !strings.Contains(toComplete, ":") {
remotes, directives := g.cmpRemotes(false)
remotes, directives := g.cmpRemotes(toComplete, false)
results = append(results, remotes...)
cmpDirectives |= directives
}
Expand Down Expand Up @@ -607,7 +614,7 @@ func (g *cmdGlobal) cmpNetworks(toComplete string) ([]string, cobra.ShellCompDir
}

if !strings.Contains(toComplete, ":") {
remotes, directives := g.cmpRemotes(false)
remotes, directives := g.cmpRemotes(toComplete, false)
results = append(results, remotes...)
cmpDirectives |= directives
}
Expand Down Expand Up @@ -789,7 +796,7 @@ func (g *cmdGlobal) cmpNetworkZones(toComplete string) ([]string, cobra.ShellCom
}

if !strings.Contains(toComplete, ":") {
remotes, directives := g.cmpRemotes(false)
remotes, directives := g.cmpRemotes(toComplete, false)
results = append(results, remotes...)
cmpDirectives |= directives
}
Expand Down Expand Up @@ -882,7 +889,7 @@ func (g *cmdGlobal) cmpProfiles(toComplete string, includeRemotes bool) ([]strin
}

if includeRemotes && !strings.Contains(toComplete, ":") {
remotes, directives := g.cmpRemotes(false)
remotes, directives := g.cmpRemotes(toComplete, false)
results = append(results, remotes...)
cmpDirectives |= directives
}
Expand Down Expand Up @@ -940,26 +947,34 @@ func (g *cmdGlobal) cmpProjects(toComplete string) ([]string, cobra.ShellCompDir
}

if !strings.Contains(toComplete, ":") {
remotes, directives := g.cmpRemotes(false)
remotes, directives := g.cmpRemotes(toComplete, false)
results = append(results, remotes...)
cmpDirectives |= directives
}

return results, cmpDirectives
}

func (g *cmdGlobal) cmpRemotes(includeAll bool) ([]string, cobra.ShellCompDirective) {
func (g *cmdGlobal) cmpRemotes(toComplete string, includeAll bool) ([]string, cobra.ShellCompDirective) {
results := []string{}

for remoteName, rc := range g.conf.Remotes {
if !includeAll && rc.Protocol != "incus" && rc.Protocol != "" {
continue
}

if !strings.HasPrefix(remoteName, toComplete) {
continue
}

results = append(results, fmt.Sprintf("%s:", remoteName))
}

return results, cobra.ShellCompDirectiveNoSpace
if len(results) > 0 {
return results, cobra.ShellCompDirectiveNoSpace
}

return results, cobra.ShellCompDirectiveNoFileComp
}

func (g *cmdGlobal) cmpRemoteNames() ([]string, cobra.ShellCompDirective) {
Expand Down Expand Up @@ -1056,7 +1071,7 @@ func (g *cmdGlobal) cmpStoragePools(toComplete string) ([]string, cobra.ShellCom
}

if !strings.Contains(toComplete, ":") {
remotes, _ := g.cmpRemotes(false)
remotes, _ := g.cmpRemotes(toComplete, false)
results = append(results, remotes...)
}

Expand Down Expand Up @@ -1210,3 +1225,89 @@ func (g *cmdGlobal) cmpStoragePoolVolumes(poolName string) ([]string, cobra.Shel

return volumes, cobra.ShellCompDirectiveNoFileComp
}

func isSymlinkToDir(path string, d fs.DirEntry) bool {
if d.Type()&fs.ModeSymlink == 0 {
return false
}

info, err := os.Stat(path)
if err != nil || !info.IsDir() {
return false
}

return true
}

func (g *cmdGlobal) cmpFiles(toComplete string, includeLocalFiles bool) ([]string, cobra.ShellCompDirective) {
instances, directives := g.cmpInstances(toComplete)
for i := range instances {
if strings.HasSuffix(instances[i], ":") {
continue
}

instances[i] += "/"
}

if len(instances) == 0 {
if includeLocalFiles {
return nil, cobra.ShellCompDirectiveDefault
}

return instances, directives
}

directives |= cobra.ShellCompDirectiveNoSpace

if !includeLocalFiles {
return instances, directives
}

var files []string
sep := string(filepath.Separator)
dir, prefix := filepath.Split(toComplete)
switch prefix {
case ".":
files = append(files, dir+"."+sep)
fallthrough
case "..":
files = append(files, dir+".."+sep)
directives |= cobra.ShellCompDirectiveNoSpace
}

root, err := filepath.EvalSymlinks(filepath.Dir(dir))
if err != nil {
return append(instances, files...), directives
}

_ = filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error {
if err != nil || path == root {
return err
}

base := filepath.Base(path)
if strings.HasPrefix(base, prefix) {
file := dir + base
switch {
case d.IsDir():
directives |= cobra.ShellCompDirectiveNoSpace
file += sep
case isSymlinkToDir(path, d):
directives |= cobra.ShellCompDirectiveNoSpace
if base == prefix {
file += sep
}
}

files = append(files, file)
}

if d.IsDir() {
return fs.SkipDir
}

return nil
})

return append(instances, files...), directives
}
2 changes: 1 addition & 1 deletion cmd/incus/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ The pull transfer mode is the default as it is compatible with all server versio
}

if len(args) == 1 {
return c.global.cmpRemotes(false)
return c.global.cmpRemotes(toComplete, false)
}

return nil, cobra.ShellCompDirectiveNoFileComp
Expand Down
18 changes: 18 additions & 0 deletions cmd/incus/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -475,8 +475,17 @@ func (c *cmdFilePull) Command() *cobra.Command {

cmd.Flags().BoolVarP(&c.file.flagMkdir, "create-dirs", "p", false, i18n.G("Create any directories necessary"))
cmd.Flags().BoolVarP(&c.file.flagRecursive, "recursive", "r", false, i18n.G("Recursively transfer files"))

cmd.RunE = c.Run

cmd.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) == 0 {
return c.global.cmpFiles(toComplete, false)
}

return c.global.cmpFiles(toComplete, true)
}

return cmd
}

Expand Down Expand Up @@ -697,8 +706,17 @@ func (c *cmdFilePush) Command() *cobra.Command {
cmd.Flags().IntVar(&c.file.flagUID, "uid", -1, i18n.G("Set the file's uid on push")+"``")
cmd.Flags().IntVar(&c.file.flagGID, "gid", -1, i18n.G("Set the file's gid on push")+"``")
cmd.Flags().StringVar(&c.file.flagMode, "mode", "", i18n.G("Set the file's perms on push")+"``")

cmd.RunE = c.Run

cmd.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) == 0 {
return nil, cobra.ShellCompDirectiveDefault
}

return c.global.cmpFiles(toComplete, true)
}

return cmd
}

Expand Down
4 changes: 2 additions & 2 deletions cmd/incus/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ It requires the source to be an alias and for it to be public.`))
}

if len(args) == 1 {
return c.global.cmpRemotes(false)
return c.global.cmpRemotes(toComplete, false)
}

return nil, cobra.ShellCompDirectiveNoFileComp
Expand Down Expand Up @@ -680,7 +680,7 @@ Directory import is only available on Linux and must be performed as root.`))
}

if len(args) == 1 {
return c.global.cmpRemotes(false)
return c.global.cmpRemotes(toComplete, false)
}

return nil, cobra.ShellCompDirectiveNoFileComp
Expand Down
2 changes: 1 addition & 1 deletion cmd/incus/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ incus list -c ns,user.comment:comment

cmd.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) == 0 {
return c.global.cmpRemotes(false)
return c.global.cmpRemotes(toComplete, false)
}

return nil, cobra.ShellCompDirectiveNoFileComp
Expand Down
2 changes: 1 addition & 1 deletion cmd/incus/move.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ incus move <instance>/<old snapshot name> <instance>/<new snapshot name>
}

if len(args) == 1 {
return c.global.cmpRemotes(false)
return c.global.cmpRemotes(toComplete, false)
}

return nil, cobra.ShellCompDirectiveNoFileComp
Expand Down
4 changes: 2 additions & 2 deletions cmd/incus/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ incus network create bar network=baz --type ovn
return nil, cobra.ShellCompDirectiveNoFileComp
}

return c.global.cmpRemotes(false)
return c.global.cmpRemotes(toComplete, false)
}

return cmd
Expand Down Expand Up @@ -1079,7 +1079,7 @@ u - Used by (count)`))
return nil, cobra.ShellCompDirectiveNoFileComp
}

return c.global.cmpRemotes(false)
return c.global.cmpRemotes(toComplete, false)
}

return cmd
Expand Down
2 changes: 1 addition & 1 deletion cmd/incus/network_acl.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func (c *cmdNetworkACLList) Command() *cobra.Command {

cmd.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) == 0 {
return c.global.cmpRemotes(false)
return c.global.cmpRemotes(toComplete, false)
}

return nil, cobra.ShellCompDirectiveNoFileComp
Expand Down
2 changes: 1 addition & 1 deletion cmd/incus/network_zone.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ Pre-defined column shorthand chars:

cmd.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) == 0 {
return c.global.cmpRemotes(false)
return c.global.cmpRemotes(toComplete, false)
}

return nil, cobra.ShellCompDirectiveNoFileComp
Expand Down
Loading

0 comments on commit 0192192

Please sign in to comment.