1
0
mirror of https://github.com/minio/mc.git synced 2025-11-14 23:42:27 +03:00

Code cleanup and standardizing in accordance with Golang coding guidelines

This commit is contained in:
Harshavardhana
2015-03-05 01:13:24 -08:00
parent d6aaf2b7c5
commit c1af2ccf67
11 changed files with 161 additions and 132 deletions

View File

@@ -18,6 +18,7 @@ package main
import (
"encoding/json"
"net/http"
"os"
"os/user"
"path"
@@ -33,6 +34,13 @@ func getAuthFilePath() (string, error) {
return path.Join(u.HomeDir, Auth), nil
}
func getNewClient(auth *s3.Auth) (*s3.Client, error) {
return &s3.Client{
Auth: auth,
Transport: http.DefaultTransport,
}, nil
}
func getAWSEnvironment() (auth *s3.Auth, err error) {
var s3Auth *os.File
var accessKey, secretKey, endpoint string

View File

@@ -2,6 +2,7 @@ package main
import (
"encoding/json"
"fmt"
"log"
"os"
"path"
@@ -17,16 +18,22 @@ func parseConfigureInput(c *cli.Context) (auth *s3.Auth, err error) {
pathstyle := c.Bool("pathstyle")
if accessKey == "" {
return nil, configAccessErr
return nil, errAccess
}
if secretKey == "" {
return nil, configSecretErr
return nil, errSecret
}
if endpoint == "" {
return nil, configEndpointErr
return nil, errEndpoint
}
auth = &s3.Auth{
AccessKey: accessKey,
SecretAccessKey: secretKey,
Endpoint: endpoint,
S3ForcePathStyle: pathstyle,
}
auth = s3.NewAuth(accessKey, secretKey, endpoint, pathstyle)
return auth, nil
}
@@ -39,7 +46,7 @@ func doConfigure(c *cli.Context) {
log.Fatal(err)
}
jAuth, err = json.Marshal(auth)
jAuth, err = json.MarshalIndent(auth, "", " ")
if err != nil {
log.Fatal(err)
}
@@ -51,11 +58,10 @@ func doConfigure(c *cli.Context) {
if err != nil {
log.Fatal(err)
}
_, err = s3File.Write(jAuth)
if err != nil {
log.Fatal(err)
}
log.Println("Written!", path.Join(home, Auth))
log.Println("Now run ``mc --help`` to read on other options")
fmt.Println("")
fmt.Println("Configuration written to", path.Join(home, Auth))
}

View File

@@ -56,8 +56,7 @@ import (
"time"
)
// See http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?RESTAuthentication.html
// Auth - see http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?RESTAuthentication.html
type Auth struct {
AccessKey string
SecretAccessKey string
@@ -73,7 +72,8 @@ type Auth struct {
S3ForcePathStyle bool
}
type TlsConfig struct {
// TLSConfig - TLS cert and key configuration
type TLSConfig struct {
CertPEMBlock []byte
KeyPEMBlock []byte
}
@@ -85,14 +85,13 @@ func (a *Auth) endpoint() string {
if a.Endpoint != "" {
if strings.HasSuffix(a.Endpoint, "amazonaws.com") {
return "https://" + a.Endpoint
} else {
return "http://" + a.Endpoint
}
return "http://" + a.Endpoint
}
return "https://" + standardUSRegionAWS
}
func (a *Auth) loadKeys(cert string, key string) (*TlsConfig, error) {
func (a *Auth) loadKeys(cert string, key string) (*TLSConfig, error) {
certBlock, err := ioutil.ReadFile(cert)
if err != nil {
return nil, err
@@ -101,13 +100,13 @@ func (a *Auth) loadKeys(cert string, key string) (*TlsConfig, error) {
if err != nil {
return nil, err
}
t := &TlsConfig{}
t := &TLSConfig{}
t.CertPEMBlock = certBlock
t.KeyPEMBlock = keyBlock
return t, nil
}
func (a *Auth) getTlsTransport() (*http.Transport, error) {
func (a *Auth) getTLSTransport() (*http.Transport, error) {
if a.CertPEM == "" || a.KeyPEM == "" {
return &http.Transport{
Dial: (&net.Dialer{
@@ -139,7 +138,7 @@ func (a *Auth) getTlsTransport() (*http.Transport, error) {
return transport, nil
}
func (a *Auth) SignRequest(req *http.Request) {
func (a *Auth) signRequest(req *http.Request) {
if date := req.Header.Get("Date"); date == "" {
req.Header.Set("Date", time.Now().UTC().Format(http.TimeFormat))
}
@@ -203,7 +202,7 @@ func hasPrefixCaseInsensitive(s, pfx string) bool {
}
func (a *Auth) writeCanonicalizedAmzHeaders(buf *bytes.Buffer, req *http.Request) {
amzHeaders := make([]string, 0)
var amzHeaders []string
vals := make(map[string][]string)
for k, vv := range req.Header {
if hasPrefixCaseInsensitive(k, "x-amz-") {

View File

@@ -134,15 +134,15 @@ func TestBucketFromHostname(t *testing.T) {
}
}
func TestSignRequest(t *testing.T) {
func TestsignRequest(t *testing.T) {
r := req("GET /foo HTTP/1.1\n\n")
auth := &Auth{AccessKey: "key", SecretAccessKey: "secretkey"}
auth.SignRequest(r)
auth.signRequest(r)
if r.Header.Get("Date") == "" {
t.Error("expected a Date set")
}
r.Header.Set("Date", "Sat, 02 Apr 2011 04:23:52 GMT")
auth.SignRequest(r)
auth.signRequest(r)
if e, g := r.Header.Get("Authorization"), "AWS key:kHpCR/N7Rw3PwRlDd8+5X40CFVc="; e != g {
t.Errorf("got header %q; expected %q", g, e)
}

View File

@@ -59,8 +59,9 @@ import (
"time"
)
// Total max object list
const (
MAX_OBJECT_LIST = 1000
MaxKeys = 1000
)
// Client is an Amazon S3 client.
@@ -69,6 +70,7 @@ type Client struct {
Transport http.RoundTripper // or nil for the default
}
// Bucket - carries s3 bucket reply header
type Bucket struct {
Name string
CreationDate string // 2006-02-03T16:45:09.000Z
@@ -83,26 +85,26 @@ func (c *Client) transport() http.RoundTripper {
// bucketURL returns the URL prefix of the bucket, with trailing slash
func (c *Client) bucketURL(bucket string) string {
var url_ string
var url string
if IsValidBucket(bucket) && !strings.Contains(bucket, ".") {
// if localhost forcePathStyle
if strings.Contains(c.endpoint(), "localhost") || strings.Contains(bucket, "127.0.0.1") {
url_ = fmt.Sprintf("%s/%s", c.endpoint(), bucket)
url = fmt.Sprintf("%s/%s", c.endpoint(), bucket)
goto ret
}
if !c.S3ForcePathStyle {
if strings.Contains(c.endpoint(), "amazonaws.com") {
url_ = fmt.Sprintf("https://%s.%s/", bucket, strings.TrimPrefix(c.endpoint(), "https://"))
url = fmt.Sprintf("https://%s.%s/", bucket, strings.TrimPrefix(c.endpoint(), "https://"))
} else {
url_ = fmt.Sprintf("http://%s.%s/", bucket, strings.TrimPrefix(c.endpoint(), "http://"))
url = fmt.Sprintf("http://%s.%s/", bucket, strings.TrimPrefix(c.endpoint(), "http://"))
}
} else {
url_ = fmt.Sprintf("%s/%s", c.endpoint(), bucket)
url = fmt.Sprintf("%s/%s", c.endpoint(), bucket)
}
}
ret:
return url_
return url
}
func (c *Client) keyURL(bucket, key string) string {
@@ -113,8 +115,8 @@ func (c *Client) keyURL(bucket, key string) string {
return c.bucketURL(bucket) + key
}
func newReq(url_ string) *http.Request {
req, err := http.NewRequest("GET", url_, nil)
func newReq(url string) *http.Request {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
panic(fmt.Sprintf("s3 client; invalid URL: %v", err))
}
@@ -122,20 +124,6 @@ func newReq(url_ string) *http.Request {
return req
}
func (c *Client) Buckets() ([]*Bucket, error) {
req := newReq(c.endpoint() + "/")
c.Auth.SignRequest(req)
res, err := c.transport().RoundTrip(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
return nil, fmt.Errorf("s3: Unexpected status code %d fetching bucket list", res.StatusCode)
}
return parseListAllMyBuckets(res.Body)
}
func parseListAllMyBuckets(r io.Reader) ([]*Bucket, error) {
type allMyBuckets struct {
Buckets struct {
@@ -149,11 +137,28 @@ func parseListAllMyBuckets(r io.Reader) ([]*Bucket, error) {
return res.Buckets.Bucket, nil
}
// Returns 0, "", os.ErrNotExist if not on S3, otherwise reterr is real.
/// Object API operations
// Buckets - Get list of buckets
func (c *Client) Buckets() ([]*Bucket, error) {
req := newReq(c.endpoint() + "/")
c.Auth.signRequest(req)
res, err := c.transport().RoundTrip(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
return nil, fmt.Errorf("s3: Unexpected status code %d fetching bucket list", res.StatusCode)
}
return parseListAllMyBuckets(res.Body)
}
// Stat - returns 0, "", os.ErrNotExist if not on S3
func (c *Client) Stat(key, bucket string) (size int64, date string, reterr error) {
req := newReq(c.keyURL(bucket, key))
req.Method = "HEAD"
c.Auth.SignRequest(req)
c.Auth.signRequest(req)
res, err := c.transport().RoundTrip(req)
if err != nil {
return 0, "", err
@@ -175,14 +180,15 @@ func (c *Client) Stat(key, bucket string) (size int64, date string, reterr error
return 0, "", fmt.Errorf("s3: Unexpected status code %d statting object %v", res.StatusCode, key)
}
// PutBucket - create new bucket
func (c *Client) PutBucket(bucket string) error {
var url_ string
var url string
if IsValidBucket(bucket) && !strings.Contains(bucket, ".") {
url_ = fmt.Sprintf("%s/%s", c.endpoint(), bucket)
url = fmt.Sprintf("%s/%s", c.endpoint(), bucket)
}
req := newReq(url_)
req := newReq(url)
req.Method = "PUT"
c.Auth.SignRequest(req)
c.Auth.signRequest(req)
res, err := c.transport().RoundTrip(req)
if err != nil {
return err
@@ -193,13 +199,13 @@ func (c *Client) PutBucket(bucket string) error {
}
if res.StatusCode != http.StatusOK {
// res.Write(os.Stderr)
return fmt.Errorf("Got response code %d from s3", res.StatusCode)
}
return nil
}
// Put - upload new object to bucket
func (c *Client) Put(bucket, key string, md5 hash.Hash, size int64, body io.Reader) error {
req := newReq(c.keyURL(bucket, key))
req.Method = "PUT"
@@ -211,7 +217,7 @@ func (c *Client) Put(bucket, key string, md5 hash.Hash, size int64, body io.Read
encoder.Close()
req.Header.Set("Content-MD5", b64.String())
}
c.Auth.SignRequest(req)
c.Auth.signRequest(req)
req.Body = ioutil.NopCloser(body)
res, err := c.transport().RoundTrip(req)
@@ -229,12 +235,14 @@ func (c *Client) Put(bucket, key string, md5 hash.Hash, size int64, body io.Read
return nil
}
// Item - object item list
type Item struct {
Key string
LastModified string
Size int64
}
// Prefix - common prefix
type Prefix struct {
Prefix string
}
@@ -258,14 +266,14 @@ type listBucketResults struct {
CommonPrefixes []*Prefix
}
// BucketLocation returns the S3 endpoint to be used with the given bucket.
// BucketLocation - returns the S3 endpoint to be used with the given bucket.
func (c *Client) BucketLocation(bucket string) (location string, err error) {
if !strings.HasSuffix(c.endpoint(), "amazonaws.com") {
return "", errors.New("BucketLocation not implemented for non-Amazon S3 endpoints")
}
url_ := fmt.Sprintf("%s/%s/?location", c.endpoint(), url.QueryEscape(bucket))
req := newReq(url_)
c.Auth.SignRequest(req)
urlReq := fmt.Sprintf("%s/%s/?location", c.endpoint(), url.QueryEscape(bucket))
req := newReq(urlReq)
c.Auth.signRequest(req)
res, err := c.transport().RoundTrip(req)
if err != nil {
return
@@ -285,7 +293,7 @@ func (c *Client) BucketLocation(bucket string) (location string, err error) {
// 'marker' value). If the length of the returned items is equal to
// maxKeys, there is no indication whether or not the returned list is truncated.
func (c *Client) GetBucket(bucket string, startAt, prefix, delimiter string, maxKeys int) (items []*Item, prefixes []*Prefix, err error) {
var url_ string
var urlReq string
var buffer bytes.Buffer
if maxKeys <= 0 {
@@ -295,8 +303,8 @@ func (c *Client) GetBucket(bucket string, startAt, prefix, delimiter string, max
marker := startAt
for len(items) < maxKeys {
fetchN := maxKeys - len(items)
if fetchN > MAX_OBJECT_LIST {
fetchN = MAX_OBJECT_LIST
if fetchN > MaxKeys {
fetchN = MaxKeys
}
var bres listBucketResults
buffer.WriteString(fmt.Sprintf("%s?max-keys=%d", c.bucketURL(bucket), fetchN))
@@ -311,15 +319,15 @@ func (c *Client) GetBucket(bucket string, startAt, prefix, delimiter string, max
buffer.WriteString(fmt.Sprintf("&delimiter=%s", url.QueryEscape(delimiter)))
}
url_ = buffer.String()
urlReq = buffer.String()
// Try the enumerate three times, since Amazon likes to close
// https connections a lot, and Go sucks at dealing with it:
// https://code.google.com/p/go/issues/detail?id=3514
const maxTries = 5
for try := 1; try <= maxTries; try++ {
time.Sleep(time.Duration(try-1) * 100 * time.Millisecond)
req := newReq(url_)
c.Auth.SignRequest(req)
req := newReq(urlReq)
c.Auth.signRequest(req)
res, err := c.transport().RoundTrip(req)
if err != nil {
if try < maxTries {
@@ -380,7 +388,6 @@ func (c *Client) GetBucket(bucket string, startAt, prefix, delimiter string, max
}
if !bres.IsTruncated {
// log.Printf("Not truncated. so breaking. items = %d; len Contents = %d, url = %s", len(items), len(bres.Contents), url_)
break
}
if len(items) == 0 {
@@ -390,9 +397,10 @@ func (c *Client) GetBucket(bucket string, startAt, prefix, delimiter string, max
return items, prefixes, nil
}
// Get - download a requested object from a given bucket
func (c *Client) Get(bucket, key string) (body io.ReadCloser, size int64, err error) {
req := newReq(c.keyURL(bucket, key))
c.Auth.SignRequest(req)
c.Auth.signRequest(req)
res, err := c.transport().RoundTrip(req)
if err != nil {
return
@@ -423,7 +431,7 @@ func (c *Client) GetPartial(bucket, key string, offset, length int64) (rc io.Rea
} else {
req.Header.Set("Range", fmt.Sprintf("bytes=%d-", offset))
}
c.Auth.SignRequest(req)
c.Auth.signRequest(req)
res, err := c.transport().RoundTrip(req)
if err != nil {
@@ -445,7 +453,7 @@ func (c *Client) GetPartial(bucket, key string, offset, length int64) (rc io.Rea
func (c *Client) Delete(bucket, key string) error {
req := newReq(c.keyURL(bucket, key))
req.Method = "DELETE"
c.Auth.SignRequest(req)
c.Auth.signRequest(req)
res, err := c.transport().RoundTrip(req)
if err != nil {
return err
@@ -461,23 +469,13 @@ func (c *Client) Delete(bucket, key string) error {
}
*/
func NewAuth(accessKey, secretKey, endpoint string, style bool) (auth *Auth) {
auth = &Auth{
AccessKey: accessKey,
SecretAccessKey: secretKey,
Endpoint: endpoint,
S3ForcePathStyle: style,
}
return
}
func NewS3Client(auth *Auth) (client *Client) {
// NewClient - get new client
func NewClient(auth *Auth) (client *Client) {
client = &Client{auth, http.DefaultTransport}
return
}
// IsValid reports whether bucket is a valid bucket name, per Amazon's naming restrictions.
//
// IsValidBucket reports whether bucket is a valid bucket name, per Amazon's naming restrictions.
// See http://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html
func IsValidBucket(bucket string) bool {
if len(bucket) < 3 || len(bucket) > 63 {
@@ -533,7 +531,7 @@ type xmlError struct {
XMLName xml.Name `xml:"Error"`
Code string
Message string
RequestId string
RequestID string
Bucket string
Endpoint string
StringToSignBytes string

View File

@@ -19,17 +19,16 @@ package main
import "errors"
// fs
var fsPathErr = errors.New("Arguments missing <S3Path> or <LocalPath>")
var fsUriErr = errors.New("Invalid URI scheme")
var fsKeyErr = errors.New("Key is needed to get the file")
var errFspath = errors.New("Arguments missing <S3Path> or <LocalPath>")
var errFsuri = errors.New("Invalid uri scheme")
var errFskey = errors.New("Key is needed to get the file")
// configure
var configAccessErr = errors.New("accesskey is mandatory")
var configSecretErr = errors.New("secretkey is mandatory")
var configEndpointErr = errors.New("endpoint is missing")
var errAccess = errors.New("accesskey is mandatory")
var errSecret = errors.New("secretkey is mandatory")
var errEndpoint = errors.New("endpoint is mandatory")
// common
var missingAccessSecretErr = errors.New("You can configure your credentials by running `mc configure`")
var missingAccessErr = errors.New("Partial credentials found in the env, missing : AWS_ACCESS_KEY_ID")
var missingSecretErr = errors.New("Partial credentials found in the env, missing : AWS_SECRET_ACCESS_KEY")
var invalidBucketErr = errors.New("Invalid bucket name")
var errMissingaccess = errors.New("Partial credentials found in the env, missing : AWS_ACCESS_KEY_ID")
var errMissingsecret = errors.New("Partial credentials found in the env, missing : AWS_SECRET_ACCESS_KEY")
var errInvalidbucket = errors.New("Invalid bucket name")

View File

@@ -17,6 +17,7 @@
package main
import (
"fmt"
"io"
"log"
"os"
@@ -37,16 +38,16 @@ import (
func parseCpOptions(c *cli.Context) (fsoptions fsOptions, err error) {
switch len(c.Args()) {
case 1:
return fsOptions{}, fsPathErr
return fsOptions{}, errFspath
case 2:
if strings.HasPrefix(c.Args().Get(0), "s3://") {
uri := uri.ParseURI(c.Args().Get(0))
if uri.Scheme == "" {
return fsOptions{}, fsUriErr
return fsOptions{}, errFsuri
}
fsoptions.bucket = uri.Server
if uri.Path == "" {
return fsOptions{}, fsKeyErr
return fsOptions{}, errFskey
}
fsoptions.key = strings.TrimPrefix(uri.Path, "/")
if c.Args().Get(1) == "." {
@@ -59,7 +60,7 @@ func parseCpOptions(c *cli.Context) (fsoptions fsOptions, err error) {
} else if strings.HasPrefix(c.Args().Get(1), "s3://") {
uri := uri.ParseURI(c.Args().Get(1))
if uri.Scheme == "" {
return fsOptions{}, fsUriErr
return fsOptions{}, errFsuri
}
fsoptions.bucket = uri.Server
if uri.Path == "" {
@@ -72,7 +73,7 @@ func parseCpOptions(c *cli.Context) (fsoptions fsOptions, err error) {
fsoptions.isput = true
}
default:
return fsOptions{}, fsPathErr
return fsOptions{}, errFspath
}
return
}
@@ -87,13 +88,18 @@ func startBar(size int64) *pb.ProgressBar {
func doFsCopy(c *cli.Context) {
var auth *s3.Auth
var s3c *s3.Client
var err error
var bodyFile *os.File
auth, err = getAWSEnvironment()
if err != nil {
log.Fatal(err)
}
s3c := s3.NewS3Client(auth)
s3c, err = getNewClient(auth)
if err != nil {
log.Fatal(err)
}
var fsoptions fsOptions
fsoptions, err = parseCpOptions(c)
if err != nil {
@@ -119,6 +125,7 @@ func doFsCopy(c *cli.Context) {
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s uploaded -- to bucket:%s", fsoptions.key, fsoptions.bucket)
} else if fsoptions.isget {
var objectReader io.ReadCloser
var objectSize int64

View File

@@ -93,6 +93,7 @@ func getBucketAndObject(p string) (bucket, object string) {
func doFsList(c *cli.Context) {
var err error
var auth *s3.Auth
var s3c *s3.Client
var items []*s3.Item
var prefixes []*s3.Prefix
@@ -102,7 +103,10 @@ func doFsList(c *cli.Context) {
}
var buckets []*s3.Bucket
s3c := s3.NewS3Client(auth)
s3c, err = getNewClient(auth)
if err != nil {
log.Fatal(err)
}
switch len(c.Args()) {
case 1:
input := c.Args().Get(0)
@@ -111,7 +115,7 @@ func doFsList(c *cli.Context) {
}
bucket, object := getBucketAndObject(input)
if object == "" {
items, prefixes, err = s3c.GetBucket(bucket, "", "", string(delimiter), s3.MAX_OBJECT_LIST)
items, prefixes, err = s3c.GetBucket(bucket, "", "", string(delimiter), s3.MaxKeys)
if err != nil {
log.Fatal(err)
}
@@ -122,7 +126,7 @@ func doFsList(c *cli.Context) {
var size int64
size, date, err = s3c.Stat(object, bucket)
if err != nil {
items, prefixes, err = s3c.GetBucket(bucket, "", object, string(delimiter), s3.MAX_OBJECT_LIST)
items, prefixes, err = s3c.GetBucket(bucket, "", object, string(delimiter), s3.MaxKeys)
if err != nil {
log.Fatal(err)
}

View File

@@ -27,7 +27,7 @@ func doFsMb(c *cli.Context) {
switch len(c.Args()) {
case 1:
if !s3.IsValidBucket(c.Args().Get(0)) {
log.Fatalf("%s: (%s)", invalidBucketErr, c.Args().Get(0))
log.Fatalf("%s: (%s)", errInvalidbucket, c.Args().Get(0))
}
default:
log.Fatal("Needs an argument <BucketName>")
@@ -35,11 +35,12 @@ func doFsMb(c *cli.Context) {
bucketName := c.Args().Get(0)
var err error
var auth *s3.Auth
var s3c *s3.Client
auth, err = getAWSEnvironment()
if err != nil {
log.Fatal(err)
}
s3c := s3.NewS3Client(auth)
s3c, err = getNewClient(auth)
err = s3c.PutBucket(bucketName)
if err != nil {
log.Fatal(err)

View File

@@ -20,35 +20,35 @@ import (
"github.com/codegangsta/cli"
)
var Cp = cli.Command{
var cp = cli.Command{
Name: "cp",
Usage: "",
Description: `Copies a local file or Object to another location locally or in S3.`,
Action: doFsCopy,
}
var Ls = cli.Command{
var ls = cli.Command{
Name: "ls",
Usage: "",
Description: `List Objects and common prefixes under a prefix or all Buckets`,
Action: doFsList,
}
var Mb = cli.Command{
var mb = cli.Command{
Name: "mb",
Usage: "",
Description: "Creates an S3 bucket",
Action: doFsMb,
}
var Sync = cli.Command{
var sync = cli.Command{
Name: "sync",
Usage: "",
Description: "Syncs directories and S3 prefixes",
Action: doFsSync,
}
var Configure = cli.Command{
var configure = cli.Command{
Name: "configure",
Usage: "",
Description: `Configure minio client configuration data. If your config
@@ -88,14 +88,15 @@ type fsOptions struct {
isput bool
}
const (
Auth = ".auth"
)
var options = []cli.Command{
Cp,
Ls,
Mb,
Sync,
Configure,
cp,
ls,
mb,
sync,
configure,
}
// Common authentication file
const (
Auth = ".minio/auth.json"
)

View File

@@ -17,6 +17,7 @@
package main
import (
"fmt"
"log"
"os"
"path"
@@ -27,18 +28,6 @@ import (
"github.com/minio-io/mc/pkg/s3"
)
var s3c *s3.Client
func init() {
var auth *s3.Auth
var err error
auth, err = getAWSEnvironment()
if err != nil {
log.Fatal(err)
}
s3c = s3.NewS3Client(auth)
}
func isValidBucketName(p string) {
if path.IsAbs(p) {
log.Fatal("directory bucketname cannot be absolute")
@@ -47,11 +36,15 @@ func isValidBucketName(p string) {
log.Fatal("Relative directory references not supported")
}
if !s3.IsValidBucket(p) {
log.Fatal(invalidBucketErr)
log.Fatal(errInvalidbucket)
}
}
func putWalk(p string, info os.FileInfo, err error) error {
type walk struct {
s3 *s3.Client
}
func (w *walk) putWalk(p string, info os.FileInfo, err error) error {
if info.IsDir() {
return nil
}
@@ -64,15 +57,28 @@ func putWalk(p string, info os.FileInfo, err error) error {
bodyFile, err := os.Open(p)
defer bodyFile.Close()
err = s3c.Put(bucketname, key, nil, info.Size(), bodyFile)
err = w.s3.Put(bucketname, key, nil, info.Size(), bodyFile)
if err != nil {
return err
}
log.Printf("%s uploaded -- to bucket:%s", key, bucketname)
fmt.Printf("%s uploaded -- to bucket:%s\n", key, bucketname)
return nil
}
func doFsSync(c *cli.Context) {
var auth *s3.Auth
var s3c *s3.Client
var err error
auth, err = getAWSEnvironment()
if err != nil {
log.Fatal(err)
}
s3c, err = getNewClient(auth)
if err != nil {
log.Fatal(err)
}
p := &walk{s3c}
switch len(c.Args()) {
case 1:
input := path.Clean(c.Args().Get(0))
@@ -90,7 +96,7 @@ func doFsSync(c *cli.Context) {
if err != nil {
log.Fatal(err)
}
err = filepath.Walk(input, putWalk)
err = filepath.Walk(input, p.putWalk)
if err != nil {
log.Fatal(err)
}