From c9546ec81bde76f6402313ca05e4f112036467c8 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Sun, 23 Jun 2019 03:37:55 +0200 Subject: [PATCH] feat: add support for completer in snaps (#1055) * feat: add support for completer in snaps * test: add completer test --- internal/pipe/snapcraft/mybin-completer.bash | 0 internal/pipe/snapcraft/snapcraft.go | 25 +++++++++++-- internal/pipe/snapcraft/snapcraft_test.go | 39 +++++++++++++++++++- pkg/config/config.go | 7 ++-- www/content/snapcraft.md | 5 +++ 5 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 internal/pipe/snapcraft/mybin-completer.bash diff --git a/internal/pipe/snapcraft/mybin-completer.bash b/internal/pipe/snapcraft/mybin-completer.bash new file mode 100644 index 00000000000..e69de29bb2d diff --git a/internal/pipe/snapcraft/snapcraft.go b/internal/pipe/snapcraft/snapcraft.go index 05e93307eaf..cda86ff8cb8 100644 --- a/internal/pipe/snapcraft/snapcraft.go +++ b/internal/pipe/snapcraft/snapcraft.go @@ -50,9 +50,10 @@ type Metadata struct { // AppMetadata for the binaries that will be in the snap package type AppMetadata struct { - Command string - Plugs []string `yaml:",omitempty"` - Daemon string `yaml:",omitempty"` + Command string + Plugs []string `yaml:",omitempty"` + Daemon string `yaml:",omitempty"` + Completer string `yaml:",omitempty"` } const defaultNameTemplate = "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" @@ -199,6 +200,7 @@ func create(ctx *context.Context, snap config.Snapcraft, arch string, binaries [ appMetadata := AppMetadata{ Command: name, } + completerPath := "" if configAppMetadata, ok := snap.Apps[name]; ok { appMetadata.Plugs = configAppMetadata.Plugs appMetadata.Daemon = configAppMetadata.Daemon @@ -206,6 +208,10 @@ func create(ctx *context.Context, snap config.Snapcraft, arch string, binaries [ appMetadata.Command, configAppMetadata.Args, }, " ")) + if configAppMetadata.Completer != "" { + completerPath = configAppMetadata.Completer + appMetadata.Completer = filepath.Base(completerPath) + } } metadata.Apps[name] = appMetadata metadata.Plugs = snap.Plugs @@ -220,6 +226,19 @@ func create(ctx *context.Context, snap config.Snapcraft, arch string, binaries [ if err := os.Chmod(destBinaryPath, 0555); err != nil { return errors.Wrap(err, "failed to change binary permissions") } + + if completerPath != "" { + destCompleterPath := filepath.Join(primeDir, filepath.Base(completerPath)) + log.WithField("src", completerPath). + WithField("dst", destCompleterPath). + Debug("linking") + if err := os.Link(completerPath, destCompleterPath); err != nil { + return errors.Wrap(err, "failed to link completer") + } + if err := os.Chmod(destCompleterPath, 0444); err != nil { + return errors.Wrap(err, "failed to change completer permissions") + } + } } if _, ok := metadata.Apps[metadata.Name]; !ok { diff --git a/internal/pipe/snapcraft/snapcraft_test.go b/internal/pipe/snapcraft/snapcraft_test.go index 5d5f417f2b8..d8b8042aeb8 100644 --- a/internal/pipe/snapcraft/snapcraft_test.go +++ b/internal/pipe/snapcraft/snapcraft_test.go @@ -245,7 +245,6 @@ func TestNoSnapcraftInPath(t *testing.T) { assert.EqualError(t, Pipe{}.Run(ctx), ErrNoSnapcraft.Error()) } - func TestRunNoArguments(t *testing.T) { folder, err := ioutil.TempDir("", "archivetest") assert.NoError(t, err) @@ -282,6 +281,44 @@ func TestRunNoArguments(t *testing.T) { assert.Equal(t, "mybin", metadata.Apps["mybin"].Command) } +func TestCompleter(t *testing.T) { + folder, err := ioutil.TempDir("", "archivetest") + require.NoError(t, err) + var dist = filepath.Join(folder, "dist") + require.NoError(t, os.Mkdir(dist, 0755)) + require.NoError(t, err) + var ctx = context.New(config.Project{ + ProjectName: "testprojectname", + Dist: dist, + Snapcrafts: []config.Snapcraft{ + { + NameTemplate: "foo_{{.Arch}}", + Summary: "test summary", + Description: "test description", + Apps: map[string]config.SnapcraftAppMetadata{ + "mybin": { + Daemon: "simple", + Args: "", + Completer: "mybin-completer.bash", + }, + }, + Builds: []string{"foo"}, + }, + }, + }) + ctx.Git.CurrentTag = "v1.2.3" + ctx.Version = "v1.2.3" + addBinaries(t, ctx, "foo", dist, "mybin") + require.NoError(t, Pipe{}.Run(ctx)) + yamlFile, err := ioutil.ReadFile(filepath.Join(dist, "foo_amd64", "prime", "meta", "snap.yaml")) + require.NoError(t, err) + var metadata Metadata + err = yaml.Unmarshal(yamlFile, &metadata) + require.NoError(t, err) + assert.Equal(t, "mybin", metadata.Apps["mybin"].Command) + assert.Equal(t, "mybin-completer.bash", metadata.Apps["mybin"].Completer) +} + func TestDefault(t *testing.T) { var ctx = context.New(config.Project{ Builds: []config.Build{ diff --git a/pkg/config/config.go b/pkg/config/config.go index f1dc5f6d36d..6c0691f030a 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -215,9 +215,10 @@ type Sign struct { // SnapcraftAppMetadata for the binaries that will be in the snap package type SnapcraftAppMetadata struct { - Plugs []string - Daemon string - Args string + Plugs []string + Daemon string + Args string + Completer string `yaml:",omitempty"` } // Snapcraft config diff --git a/www/content/snapcraft.md b/www/content/snapcraft.md index 3fde4d415f7..0d1ac956e1d 100644 --- a/www/content/snapcraft.md +++ b/www/content/snapcraft.md @@ -112,6 +112,11 @@ snapcrafts: # If you any to pass args to your binary, you can add them with the # args option. args: --foo + + # Bash completion snippet. More information about completion here: + # https://docs.snapcraft.io/tab-completion-for-snaps. + completer: drumroll-completion.bash + # Allows plugs to be configured. Plugs like system-files and personal-files # require this. # Default is empty.