@@ -12,12 +12,9 @@ import (
1212 "strings"
1313
1414 "github.com/docker/cli/cli-plugins/metadata"
15- "github.com/docker/cli/internal/lazyregexp"
1615 "github.com/spf13/cobra"
1716)
1817
19- var pluginNameRe = lazyregexp .New ("^[a-z][a-z0-9]*$" )
20-
2118// Plugin represents a potential plugin with all it's metadata.
2219type Plugin struct {
2320 metadata.Metadata
@@ -85,8 +82,8 @@ func newPlugin(c pluginCandidate, cmds []*cobra.Command) (Plugin, error) {
8582 }
8683
8784 // Now apply the candidate tests, so these update p.Err.
88- if ! pluginNameRe . MatchString (p .Name ) {
89- p .Err = newPluginError ("plugin candidate %q did not match %q" , p .Name , pluginNameRe . String () )
85+ if ! isValidPluginName (p .Name ) {
86+ p .Err = newPluginError ("plugin candidate %q did not match %q" , p .Name , pluginNameFormat )
9087 return p , nil
9188 }
9289
@@ -147,3 +144,26 @@ func (p *Plugin) RunHook(ctx context.Context, hookData HookPluginData) ([]byte,
147144
148145 return hookCmdOutput , nil
149146}
147+
148+ // pluginNameFormat is used as part of errors for invalid plugin-names.
149+ // We should consider making this less technical ("must start with "a-z",
150+ // and only consist of lowercase alphanumeric characters").
151+ const pluginNameFormat = `^[a-z][a-z0-9]*$`
152+
153+ func isValidPluginName (s string ) bool {
154+ if len (s ) == 0 {
155+ return false
156+ }
157+ // first character must be a-z
158+ if c := s [0 ]; c < 'a' || c > 'z' {
159+ return false
160+ }
161+ // followed by a-z or 0-9
162+ for i := 1 ; i < len (s ); i ++ {
163+ c := s [i ]
164+ if (c < 'a' || c > 'z' ) && (c < '0' || c > '9' ) {
165+ return false
166+ }
167+ }
168+ return true
169+ }
0 commit comments