diff --git a/aliases.go b/aliases.go index dfcaa512..f6ab6056 100644 --- a/aliases.go +++ b/aliases.go @@ -37,7 +37,7 @@ func aliasExpand(aliasedURL string, aliases map[string]string) (newURL string, e url, err := url.Parse(aliasedURL) if err != nil { // Not a valid URL. Return error - return "", iodine.New(errInvalidURL{aliasedURL}, nil) + return "", iodine.New(errInvalidURL{url: aliasedURL}, nil) } // Not an aliased URL @@ -47,7 +47,7 @@ func aliasExpand(aliasedURL string, aliases map[string]string) (newURL string, e for aliasName, expandedURL := range aliases { if !isValidAliasName(aliasName) { - return "", iodine.New(errInvalidAliasName{alias: aliasName}, nil) + return "", iodine.New(errInvalidAliasName{name: aliasName}, nil) } if strings.HasPrefix(aliasedURL, aliasName) { // Match found. Expand it. diff --git a/cmd-common.go b/cmd-common.go index b67bd949..795dcc0d 100644 --- a/cmd-common.go +++ b/cmd-common.go @@ -18,7 +18,6 @@ package main import ( "net/url" - "path" "time" "io" @@ -47,19 +46,6 @@ func startBar(size int64) *pb.ProgressBar { return bar } -func getMcBashCompletionFilename() (string, error) { - configDir, err := getMcConfigDir() - if err != nil { - return "", err - } - return path.Join(configDir, "mc.bash_completion"), nil -} - -func mustGetMcBashCompletionFilename() string { - p, _ := getMcBashCompletionFilename() - return p -} - type clientManager interface { getSourceReader(urlStr string) (reader io.ReadCloser, length int64, md5hex string, err error) getTargetWriter(urlStr string, md5Hex string, length int64) (io.WriteCloser, error) @@ -104,8 +90,7 @@ func (manager mcClientManager) getTargetWriter(urlStr string, md5Hex string, len return targetClnt.Put(bucket, object, md5Hex, length) } -// getNewClient gets a new client -// TODO refactor this to be more testable +// getNewClient gives a new client interface func (manager mcClientManager) getNewClient(urlStr string, debug bool) (clnt client.Client, err error) { u, err := url.Parse(urlStr) if err != nil { diff --git a/cmd-common_test.go b/cmd-common_test.go index 3819d863..3678efcb 100644 --- a/cmd-common_test.go +++ b/cmd-common_test.go @@ -17,7 +17,6 @@ package main import ( - "strings" "time" "github.com/cheggaaa/pb" @@ -35,13 +34,3 @@ func (s *MySuite) TestStatusBar(c *C) { c.Assert(bar.NotPrint, Equals, true) c.Assert(bar.ShowSpeed, Equals, true) } - -func (s *MySuite) TestBashCompletionFilename(c *C) { - file, err := getMcBashCompletionFilename() - c.Assert(err, IsNil) - c.Assert(file, Not(Equals), "mc.bash_completion") - c.Assert(strings.HasSuffix(file, "mc.bash_completion"), Equals, true) - - file2 := mustGetMcBashCompletionFilename() - c.Assert(file, Equals, file2) -} diff --git a/cmd-config.go b/cmd-config.go index 7a7017b1..09a819df 100644 --- a/cmd-config.go +++ b/cmd-config.go @@ -17,7 +17,6 @@ package main import ( - "bytes" "net/url" "os" "path" @@ -141,11 +140,21 @@ func writeConfig(config qdb.Store) error { func saveConfig(ctx *cli.Context) error { switch ctx.Args().Get(0) { case "generate": - err := writeConfig(generateNewConfig()) + if isMcConfigExist() { + return iodine.New(errConfigExists{}, nil) + } + err := writeConfig(newConfig()) if err != nil { return iodine.New(err, nil) } return nil + case "check": + // verify if the binary can load config file + configStore, err := getMcConfig() + if err != nil || configStore == nil { + return iodine.New(err, nil) + } + return nil default: configStore, err := parseConfigInput(ctx) if err != nil { @@ -155,9 +164,8 @@ func saveConfig(ctx *cli.Context) error { } } -func generateNewConfig() (config qdb.Store) { +func newConfig() (config qdb.Store) { configStore := qdb.NewStore(mcCurrentConfigVersion) - s3Auth := make(map[string]string) localAuth := make(map[string]string) @@ -192,12 +200,15 @@ func parseConfigInput(ctx *cli.Context) (config qdb.Store, err error) { aliasName := alias[0] url := strings.TrimSuffix(alias[1], "/") if strings.HasPrefix(aliasName, "http") { - return nil, iodine.New(errInvalidAliasName{alias: aliasName}, nil) + return nil, iodine.New(errInvalidAliasName{name: aliasName}, nil) } if !strings.HasPrefix(url, "http") { return nil, iodine.New(errInvalidURL{url: url}, nil) } aliases := configStore.GetMapString("Aliases") + if _, ok := aliases[aliasName]; ok { + return nil, iodine.New(errAliasExists{name: aliasName}, nil) + } aliases[aliasName] = url configStore.SetMapString("Aliases", aliases) return configStore, nil @@ -233,8 +244,8 @@ func getHostConfig(requestURL string) (map[string]string, error) { return nil, iodine.New(errNoMatchingHost{}, nil) } -// saveConfigCmd writes config file to disk -func saveConfigCmd(ctx *cli.Context) { +// doConfigCmd is the handler for "mc config" sub-command. +func doConfigCmd(ctx *cli.Context) { // show help if nothing is set if len(ctx.Args()) < 1 && !ctx.IsSet("completion") && !ctx.IsSet("alias") { cli.ShowCommandHelpAndExit(ctx, "config", 1) // last argument is exit code @@ -245,49 +256,14 @@ func saveConfigCmd(ctx *cli.Context) { console.Fatalln("mc: Unable to identify config file path") } err = saveConfig(ctx) - if os.IsExist(iodine.ToError(err)) { + switch iodine.ToError(err).(type) { + case errConfigExists: log.Debug.Println(iodine.New(err, nil)) console.Fatalln("mc: Configuration file " + configPath + " already exists") - } - if err != nil { + default: + // unexpected error log.Debug.Println(iodine.New(err, nil)) console.Fatalln("mc: Unable to generate config file", configPath) } console.Infoln("mc: Configuration written to " + configPath + ". Please update your access credentials.") } - -// doConfigCmd is the handler for "mc config" sub-command. -func doConfigCmd(ctx *cli.Context) { - // treat bash completion separately here - switch true { - case ctx.Bool("completion") == true: - var b bytes.Buffer - if os.Getenv("SHELL") != "/bin/bash" { - console.Fatalln("mc: Unsupported shell for bash completion detected.. exiting") - } - b.WriteString(mcBashCompletion) - f, err := getMcBashCompletionFilename() - if err != nil { - log.Debug.Println(iodine.New(err, nil)) - console.Fatalln("mc: Unable to identify bash completion path") - } - fl, err := os.OpenFile(f, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) - defer fl.Close() - if err != nil { - log.Debug.Println(iodine.New(err, nil)) - console.Fatalln("mc: Unable to create bash completion file") - } - _, err = fl.Write(b.Bytes()) - if err != nil { - log.Debug.Println(iodine.New(err, nil)) - console.Fatalln("mc: Unable to write to bash completion file") - } - msg := "\nConfiguration written to " + f - msg = msg + "\n\n$ source ${HOME}/.mc/mc.bash_completion\n" - msg = msg + "$ echo 'source ${HOME}/.mc/mc.bash_completion' >> ${HOME}/.bashrc" - console.Infoln(msg) - default: - // rest of the arguments get passed down - saveConfigCmd(ctx) - } -} diff --git a/cmd-options.go b/cmd-options.go index 8146cf82..751973ea 100644 --- a/cmd-options.go +++ b/cmd-options.go @@ -152,10 +152,6 @@ EXAMPLES: Name: "alias", Usage: "Add URL aliases into config", }, - cli.BoolFlag{ - Name: "completion", - Usage: "Generate bash completion \"" + mustGetMcBashCompletionFilename() + "\" file.", - }, }, CustomHelpTemplate: `NAME: mc {{.Name}} - {{.Usage}} @@ -173,8 +169,8 @@ EXAMPLES: 1. Generate mc config $ mc config generate - 2. Generate bash completion - $ mc config --completion + 2. Verify configuration + $ mc config check 3. Add alias URLs $ mc config --alias "zek https://s3.amazonaws.com/" @@ -229,20 +225,3 @@ var ( }, } ) - -var ( - mcBashCompletion = `#!/bin/bash - -_mc_completion() { - local cur prev opts base - COMPREPLY=() - cur="${COMP_WORDS[COMP_CWORD]}" - prev="${COMP_WORDS[COMP_CWORD-1]}" - opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-bash-completion ) - COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) - return 0 -} - -complete -F _mc_completion mc -` -) diff --git a/errors.go b/errors.go index f9442635..8302e608 100644 --- a/errors.go +++ b/errors.go @@ -50,11 +50,11 @@ func (e errInvalidGlobURL) Error() string { } type errInvalidAliasName struct { - alias string + name string } func (e errInvalidAliasName) Error() string { - return "Not a valid alias name: " + e.alias + " Valid examples are: Area51, Grand-Nagus.." + return "Not a valid alias name: " + e.name + " Valid examples are: Area51, Grand-Nagus.." } type errInvalidAuth struct{} @@ -68,3 +68,34 @@ type errNoMatchingHost struct{} func (e errNoMatchingHost) Error() string { return "No matching host found." } + +type errConfigExists struct{} + +func (e errConfigExists) Error() string { + return "Config exists" +} + +// errAliasExists - alias exists +type errAliasExists struct { + name string +} + +func (e errAliasExists) Error() string { + return fmt.Sprintf("alias: %s exists", e.name) +} + +// errAliasNotFound - alias not found +type errAliasNotFound struct { + name string +} + +func (e errAliasNotFound) Error() string { + return fmt.Sprintf("alias: %s exists", e.name) +} + +// errInvalidAuthKeys - invalid authorization keys +type errInvalidAuthKeys struct{} + +func (e errInvalidAuthKeys) Error() string { + return fmt.Sprintf("invalid authorization keys") +} diff --git a/main.go b/main.go index 96e442f3..8af0c242 100644 --- a/main.go +++ b/main.go @@ -86,7 +86,6 @@ func main() { app.Commands = options app.Flags = flags app.Author = "Minio.io" - app.EnableBashCompletion = false app.Before = func(ctx *cli.Context) error { globalQuietFlag = ctx.GlobalBool("quiet") globalDebugFlag = ctx.GlobalBool("debug")