mirror of
https://github.com/minio/mc.git
synced 2025-11-16 11:02:34 +03:00
Deprecate bash-completion support
This commit is contained in:
@@ -37,7 +37,7 @@ func aliasExpand(aliasedURL string, aliases map[string]string) (newURL string, e
|
|||||||
url, err := url.Parse(aliasedURL)
|
url, err := url.Parse(aliasedURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Not a valid URL. Return error
|
// Not a valid URL. Return error
|
||||||
return "", iodine.New(errInvalidURL{aliasedURL}, nil)
|
return "", iodine.New(errInvalidURL{url: aliasedURL}, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not an aliased URL
|
// Not an aliased URL
|
||||||
@@ -47,7 +47,7 @@ func aliasExpand(aliasedURL string, aliases map[string]string) (newURL string, e
|
|||||||
|
|
||||||
for aliasName, expandedURL := range aliases {
|
for aliasName, expandedURL := range aliases {
|
||||||
if !isValidAliasName(aliasName) {
|
if !isValidAliasName(aliasName) {
|
||||||
return "", iodine.New(errInvalidAliasName{alias: aliasName}, nil)
|
return "", iodine.New(errInvalidAliasName{name: aliasName}, nil)
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(aliasedURL, aliasName) {
|
if strings.HasPrefix(aliasedURL, aliasName) {
|
||||||
// Match found. Expand it.
|
// Match found. Expand it.
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"path"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"io"
|
"io"
|
||||||
@@ -47,19 +46,6 @@ func startBar(size int64) *pb.ProgressBar {
|
|||||||
return bar
|
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 {
|
type clientManager interface {
|
||||||
getSourceReader(urlStr string) (reader io.ReadCloser, length int64, md5hex string, err error)
|
getSourceReader(urlStr string) (reader io.ReadCloser, length int64, md5hex string, err error)
|
||||||
getTargetWriter(urlStr string, md5Hex string, length int64) (io.WriteCloser, 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)
|
return targetClnt.Put(bucket, object, md5Hex, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getNewClient gets a new client
|
// getNewClient gives a new client interface
|
||||||
// TODO refactor this to be more testable
|
|
||||||
func (manager mcClientManager) getNewClient(urlStr string, debug bool) (clnt client.Client, err error) {
|
func (manager mcClientManager) getNewClient(urlStr string, debug bool) (clnt client.Client, err error) {
|
||||||
u, err := url.Parse(urlStr)
|
u, err := url.Parse(urlStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cheggaaa/pb"
|
"github.com/cheggaaa/pb"
|
||||||
@@ -35,13 +34,3 @@ func (s *MySuite) TestStatusBar(c *C) {
|
|||||||
c.Assert(bar.NotPrint, Equals, true)
|
c.Assert(bar.NotPrint, Equals, true)
|
||||||
c.Assert(bar.ShowSpeed, 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)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
@@ -141,11 +140,21 @@ func writeConfig(config qdb.Store) error {
|
|||||||
func saveConfig(ctx *cli.Context) error {
|
func saveConfig(ctx *cli.Context) error {
|
||||||
switch ctx.Args().Get(0) {
|
switch ctx.Args().Get(0) {
|
||||||
case "generate":
|
case "generate":
|
||||||
err := writeConfig(generateNewConfig())
|
if isMcConfigExist() {
|
||||||
|
return iodine.New(errConfigExists{}, nil)
|
||||||
|
}
|
||||||
|
err := writeConfig(newConfig())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return iodine.New(err, nil)
|
return iodine.New(err, nil)
|
||||||
}
|
}
|
||||||
return 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:
|
default:
|
||||||
configStore, err := parseConfigInput(ctx)
|
configStore, err := parseConfigInput(ctx)
|
||||||
if err != nil {
|
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)
|
configStore := qdb.NewStore(mcCurrentConfigVersion)
|
||||||
|
|
||||||
s3Auth := make(map[string]string)
|
s3Auth := make(map[string]string)
|
||||||
localAuth := 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]
|
aliasName := alias[0]
|
||||||
url := strings.TrimSuffix(alias[1], "/")
|
url := strings.TrimSuffix(alias[1], "/")
|
||||||
if strings.HasPrefix(aliasName, "http") {
|
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") {
|
if !strings.HasPrefix(url, "http") {
|
||||||
return nil, iodine.New(errInvalidURL{url: url}, nil)
|
return nil, iodine.New(errInvalidURL{url: url}, nil)
|
||||||
}
|
}
|
||||||
aliases := configStore.GetMapString("Aliases")
|
aliases := configStore.GetMapString("Aliases")
|
||||||
|
if _, ok := aliases[aliasName]; ok {
|
||||||
|
return nil, iodine.New(errAliasExists{name: aliasName}, nil)
|
||||||
|
}
|
||||||
aliases[aliasName] = url
|
aliases[aliasName] = url
|
||||||
configStore.SetMapString("Aliases", aliases)
|
configStore.SetMapString("Aliases", aliases)
|
||||||
return configStore, nil
|
return configStore, nil
|
||||||
@@ -233,8 +244,8 @@ func getHostConfig(requestURL string) (map[string]string, error) {
|
|||||||
return nil, iodine.New(errNoMatchingHost{}, nil)
|
return nil, iodine.New(errNoMatchingHost{}, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// saveConfigCmd writes config file to disk
|
// doConfigCmd is the handler for "mc config" sub-command.
|
||||||
func saveConfigCmd(ctx *cli.Context) {
|
func doConfigCmd(ctx *cli.Context) {
|
||||||
// show help if nothing is set
|
// show help if nothing is set
|
||||||
if len(ctx.Args()) < 1 && !ctx.IsSet("completion") && !ctx.IsSet("alias") {
|
if len(ctx.Args()) < 1 && !ctx.IsSet("completion") && !ctx.IsSet("alias") {
|
||||||
cli.ShowCommandHelpAndExit(ctx, "config", 1) // last argument is exit code
|
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")
|
console.Fatalln("mc: Unable to identify config file path")
|
||||||
}
|
}
|
||||||
err = saveConfig(ctx)
|
err = saveConfig(ctx)
|
||||||
if os.IsExist(iodine.ToError(err)) {
|
switch iodine.ToError(err).(type) {
|
||||||
|
case errConfigExists:
|
||||||
log.Debug.Println(iodine.New(err, nil))
|
log.Debug.Println(iodine.New(err, nil))
|
||||||
console.Fatalln("mc: Configuration file " + configPath + " already exists")
|
console.Fatalln("mc: Configuration file " + configPath + " already exists")
|
||||||
}
|
default:
|
||||||
if err != nil {
|
// unexpected error
|
||||||
log.Debug.Println(iodine.New(err, nil))
|
log.Debug.Println(iodine.New(err, nil))
|
||||||
console.Fatalln("mc: Unable to generate config file", configPath)
|
console.Fatalln("mc: Unable to generate config file", configPath)
|
||||||
}
|
}
|
||||||
console.Infoln("mc: Configuration written to " + configPath + ". Please update your access credentials.")
|
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -152,10 +152,6 @@ EXAMPLES:
|
|||||||
Name: "alias",
|
Name: "alias",
|
||||||
Usage: "Add URL aliases into config",
|
Usage: "Add URL aliases into config",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "completion",
|
|
||||||
Usage: "Generate bash completion \"" + mustGetMcBashCompletionFilename() + "\" file.",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
CustomHelpTemplate: `NAME:
|
CustomHelpTemplate: `NAME:
|
||||||
mc {{.Name}} - {{.Usage}}
|
mc {{.Name}} - {{.Usage}}
|
||||||
@@ -173,8 +169,8 @@ EXAMPLES:
|
|||||||
1. Generate mc config
|
1. Generate mc config
|
||||||
$ mc config generate
|
$ mc config generate
|
||||||
|
|
||||||
2. Generate bash completion
|
2. Verify configuration
|
||||||
$ mc config --completion
|
$ mc config check
|
||||||
|
|
||||||
3. Add alias URLs
|
3. Add alias URLs
|
||||||
$ mc config --alias "zek https://s3.amazonaws.com/"
|
$ 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
|
|
||||||
`
|
|
||||||
)
|
|
||||||
|
|||||||
35
errors.go
35
errors.go
@@ -50,11 +50,11 @@ func (e errInvalidGlobURL) Error() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type errInvalidAliasName struct {
|
type errInvalidAliasName struct {
|
||||||
alias string
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e errInvalidAliasName) Error() 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{}
|
type errInvalidAuth struct{}
|
||||||
@@ -68,3 +68,34 @@ type errNoMatchingHost struct{}
|
|||||||
func (e errNoMatchingHost) Error() string {
|
func (e errNoMatchingHost) Error() string {
|
||||||
return "No matching host found."
|
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")
|
||||||
|
}
|
||||||
|
|||||||
1
main.go
1
main.go
@@ -86,7 +86,6 @@ func main() {
|
|||||||
app.Commands = options
|
app.Commands = options
|
||||||
app.Flags = flags
|
app.Flags = flags
|
||||||
app.Author = "Minio.io"
|
app.Author = "Minio.io"
|
||||||
app.EnableBashCompletion = false
|
|
||||||
app.Before = func(ctx *cli.Context) error {
|
app.Before = func(ctx *cli.Context) error {
|
||||||
globalQuietFlag = ctx.GlobalBool("quiet")
|
globalQuietFlag = ctx.GlobalBool("quiet")
|
||||||
globalDebugFlag = ctx.GlobalBool("debug")
|
globalDebugFlag = ctx.GlobalBool("debug")
|
||||||
|
|||||||
Reference in New Issue
Block a user