diff --git a/common-methods.go b/common-methods.go index 10bee2fb..212c66c5 100644 --- a/common-methods.go +++ b/common-methods.go @@ -104,7 +104,7 @@ func putTargets(targetURLs []string, length int64, reader io.Reader) <-chan erro func getNewClient(urlStr string, auth *hostConfig) (clnt client.Client, err error) { url, err := client.Parse(urlStr) if err != nil { - return nil, iodine.New(errInvalidURL{URL: urlStr}, nil) + return nil, iodine.New(errInvalidURL{URL: urlStr}, map[string]string{"URL": urlStr}) } switch url.Type { case client.Object: // Minio and S3 compatible object storage @@ -138,12 +138,7 @@ func getNewClient(urlStr string, auth *hostConfig) (clnt client.Client, err erro // url2Stat - Returns client, config and its stat Content from the URL func url2Stat(urlStr string) (client client.Client, content *client.Content, err error) { - config, err := getHostConfig(urlStr) - if err != nil { - return nil, nil, iodine.New(err, map[string]string{"URL": urlStr}) - } - - client, err = getNewClient(urlStr, config) + client, err = url2Client(urlStr) if err != nil { return nil, nil, iodine.New(err, map[string]string{"URL": urlStr}) } @@ -160,21 +155,21 @@ func url2Client(url string) (client.Client, error) { // Empty source arg? urlParse, err := client.Parse(url) if err != nil { - return nil, iodine.New(err, nil) + return nil, iodine.New(err, map[string]string{"URL": url}) } if urlParse.Path == "" { - return nil, iodine.New(errInvalidURL{URL: url}, nil) + return nil, iodine.New(errInvalidURL{URL: url}, map[string]string{"URL": url}) } urlonfig, err := getHostConfig(url) if err != nil { - return nil, iodine.New(err, nil) + return nil, iodine.New(err, map[string]string{"URL": url}) } client, err := getNewClient(url, urlonfig) if err != nil { - return nil, iodine.New(err, nil) + return nil, iodine.New(err, map[string]string{"URL": url}) } return client, nil @@ -184,7 +179,7 @@ func url2Client(url string) (client.Client, error) { func source2Client(sourceURL string) (client.Client, error) { sourceClient, err := url2Client(sourceURL) if err != nil { - return nil, iodine.New(errInvalidSource{URL: sourceURL}, nil) + return nil, iodine.New(errInvalidSource{URL: sourceURL}, map[string]string{"URL": sourceURL}) } return sourceClient, nil } @@ -193,7 +188,7 @@ func source2Client(sourceURL string) (client.Client, error) { func target2Client(targetURL string) (client.Client, error) { targetClient, err := url2Client(targetURL) if err != nil { - return nil, iodine.New(errInvalidTarget{URL: targetURL}, nil) + return nil, iodine.New(errInvalidTarget{URL: targetURL}, map[string]string{"URL": targetURL}) } return targetClient, nil } diff --git a/cp-url.go b/cp-url.go index 3cc69963..82791882 100644 --- a/cp-url.go +++ b/cp-url.go @@ -79,14 +79,10 @@ func isTargetURLDir(targetURL string) bool { if strings.HasSuffix(targetURLParse.String(), string(targetURLParse.Separator)) { return true } - targetClient, err := target2Client(targetURL) + _, targetContent, err := url2Stat(targetURL) if err != nil { return false } - targetContent, err := targetClient.Stat() - if err != nil { // Cannot stat target - return false - } if !targetContent.Type.IsDir() { // Target is a dir. Type B return false } @@ -124,13 +120,7 @@ func prepareCopyURLsTypeA(sourceURL string, targetURL string) <-chan cpURLs { cpURLsCh := make(chan cpURLs, 10000) go func(sourceURL, targetURL string, cpURLsCh chan cpURLs) { defer close(cpURLsCh) - sourceClient, err := source2Client(sourceURL) - if err != nil { - cpURLsCh <- cpURLs{Error: iodine.New(err, nil)} - return - } - // Source exists? - sourceContent, err := sourceClient.Stat() + _, sourceContent, err := url2Stat(sourceURL) if err != nil { // Source does not exist or insufficient privileges. cpURLsCh <- cpURLs{Error: iodine.New(err, nil)} @@ -167,13 +157,7 @@ func prepareCopyURLsTypeB(sourceURL string, targetURL string) <-chan cpURLs { cpURLsCh := make(chan cpURLs, 10000) go func(sourceURL, targetURL string, cpURLsCh chan cpURLs) { defer close(cpURLsCh) - sourceClient, err := source2Client(sourceURL) - if err != nil { - cpURLsCh <- cpURLs{Error: iodine.New(err, nil)} - return - } - - sourceContent, err := sourceClient.Stat() + _, sourceContent, err := url2Stat(sourceURL) if err != nil { // Source does not exist or insufficient privileges. cpURLsCh <- cpURLs{Error: iodine.New(err, nil)} @@ -186,14 +170,11 @@ func prepareCopyURLsTypeB(sourceURL string, targetURL string) <-chan cpURLs { return } - targetClient, err := target2Client(targetURL) + _, targetContent, err := url2Stat(targetURL) if err != nil { cpURLsCh <- cpURLs{Error: iodine.New(err, nil)} return } - - // Target exist? - targetContent, err := targetClient.Stat() if err == nil { if !targetContent.Type.IsDir() { // Target exists, but is not a directory. @@ -237,14 +218,7 @@ func prepareCopyURLsTypeC(sourceURL, targetURL string) <-chan cpURLs { // add `/` after trimming off `...` to emulate directories sourceURL = stripRecursiveURL(sourceURL) - sourceClient, err := source2Client(sourceURL) - if err != nil { - cpURLsCh <- cpURLs{Error: iodine.New(err, nil)} - return - } - - // Source exist? - sourceContent, err := sourceClient.Stat() + sourceClient, sourceContent, err := url2Stat(sourceURL) if err != nil { // Source does not exist or insufficient privileges. cpURLsCh <- cpURLs{Error: iodine.New(err, nil)} @@ -257,14 +231,8 @@ func prepareCopyURLsTypeC(sourceURL, targetURL string) <-chan cpURLs { return } - targetClient, err := target2Client(targetURL) - if err != nil { - cpURLsCh <- cpURLs{Error: iodine.New(err, nil)} - return - } - + _, targetContent, err := url2Stat(targetURL) // Target exist? - targetContent, err := targetClient.Stat() if err != nil { // Target does not exist. cpURLsCh <- cpURLs{Error: iodine.New(errTargetNotFound{URL: targetURL}, nil)} @@ -330,28 +298,27 @@ func prepareCopyURLsTypeD(sourceURLs []string, targetURL string) <-chan cpURLs { cpURLsCh := make(chan cpURLs, 10000) go func(sourceURLs []string, targetURL string, cpURLsCh chan cpURLs) { defer close(cpURLsCh) - targetClient, err := target2Client(targetURL) - if err != nil { - cpURLsCh <- cpURLs{Error: iodine.New(err, nil)} - return - } - // Target exist? - targetContent, err := targetClient.Stat() - if err != nil { - // Target does not exist. - cpURLsCh <- cpURLs{Error: iodine.New(errTargetNotFound{URL: targetURL}, nil)} - return - } - if !targetContent.Type.IsDir() { - // Target exists, but is not a directory. - cpURLsCh <- cpURLs{Error: iodine.New(errTargetIsNotDir{URL: targetURL}, nil)} - return - } + if sourceURLs == nil { // Source list is empty. cpURLsCh <- cpURLs{Error: iodine.New(errSourceListEmpty{}, nil)} return } + + _, targetContent, err := url2Stat(targetURL) + // Target exist? + if err != nil { + // Target does not exist. + cpURLsCh <- cpURLs{Error: iodine.New(errTargetNotFound{URL: targetURL}, nil)} + return + } + + if !targetContent.Type.IsDir() { + // Target exists, but is not a directory. + cpURLsCh <- cpURLs{Error: iodine.New(errTargetIsNotDir{URL: targetURL}, nil)} + return + } + for _, sourceURL := range sourceURLs { // Target is directory. Possibilities are only Type B and C // Is it a recursive URL "..."? diff --git a/pkg/client/client.go b/pkg/client/client.go index 9afe702b..f278388a 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -46,7 +46,7 @@ type ContentOnChannel struct { Err error } -// Content - object content list +// Content container for content metadata type Content struct { Name string Time time.Time diff --git a/print-structs.go b/print-structs.go index b81c2119..dfba9c8b 100644 --- a/print-structs.go +++ b/print-structs.go @@ -24,12 +24,13 @@ import ( "github.com/minio/minio/pkg/iodine" ) -// ErrorMessage container for message reason encapsulation +// ErrorMessage container for error reason encapsulation type ErrorMessage struct { Message string `json:"message"` Error error `json:"error"` } +// String string printer for error message func (e ErrorMessage) String() string { var message string if e.Error != nil { @@ -53,6 +54,7 @@ type Content struct { Name string `json:"name"` } +// String string printer for Content metadata func (c Content) String() string { message := console.Time("[%s] ", c.Time) message = message + console.Size("%6s ", c.Size) @@ -70,6 +72,7 @@ type InfoMessage struct { Message string `json:"message"` } +// String string printer for informational message func (i InfoMessage) String() string { return i.Message } @@ -81,6 +84,7 @@ type CopyMessage struct { Target string `json:"target"` } +// String string printer for copy message func (c CopyMessage) String() string { return fmt.Sprintf("‘%s’ -> ‘%s’", c.Source, c.Target) } @@ -88,6 +92,7 @@ func (c CopyMessage) String() string { // SyncMessage container for file sync messages, inherits CopyMessage type SyncMessage CopyMessage +// String string printer for sync message func (s SyncMessage) String() string { return fmt.Sprintf("‘%s’ -> ‘%s’", s.Source, s.Target) } diff --git a/sync-url.go b/sync-url.go index efd10c16..41338b6d 100644 --- a/sync-url.go +++ b/sync-url.go @@ -150,13 +150,8 @@ func prepareSyncURLsTypeC(sourceURL string, targetURLs []string) <-chan syncURLs } // add `/` after trimming off `...` to emulate directories sourceURL = stripRecursiveURL(sourceURL) - sourceClient, err := source2Client(sourceURL) - if err != nil { - syncURLsCh <- syncURLs{Error: iodine.New(err, nil)} - return - } + sourceClient, sourceContent, err := url2Stat(sourceURL) // Source exist? - sourceContent, err := sourceClient.Stat() if err != nil { // Source does not exist or insufficient privileges. syncURLsCh <- syncURLs{Error: iodine.New(err, nil)} @@ -170,14 +165,8 @@ func prepareSyncURLsTypeC(sourceURL string, targetURLs []string) <-chan syncURLs } for _, targetURL := range targetURLs { - targetClient, err := target2Client(targetURL) - if err != nil { - syncURLsCh <- syncURLs{Error: iodine.New(err, nil)} - return - } - + _, targetContent, err := url2Stat(targetURL) // Target exist? - targetContent, err := targetClient.Stat() if err != nil { // Target does not exist. syncURLsCh <- syncURLs{Error: iodine.New(errTargetNotFound{URL: targetURL}, nil)}