Pull in new changes from minio-io/objectdriver and minio-io/donut

This commit is contained in:
Harshavardhana 2015-04-06 22:29:10 -07:00
parent 81e2dafe36
commit 649f1104dd
19 changed files with 615 additions and 505 deletions

8
Godeps/Godeps.json generated
View File

@ -23,12 +23,12 @@
}, },
{ {
"ImportPath": "github.com/minio-io/cli", "ImportPath": "github.com/minio-io/cli",
"Comment": "1.2.0-100-g6d6f8d3", "Comment": "1.2.0-102-gecb385c",
"Rev": "6d6f8d3cc162bfcb60379888e2f37d73ff6a6253" "Rev": "ecb385c3fefd53678e3b6beba6a608fb7c8dfac1"
}, },
{ {
"ImportPath": "github.com/minio-io/donut", "ImportPath": "github.com/minio-io/donut",
"Rev": "1df31a9834eb6acef9ff0fb7ee3e597776faf966" "Rev": "2841ca4edd6a31fce7184027e85d2bee673b49f0"
}, },
{ {
"ImportPath": "github.com/minio-io/erasure", "ImportPath": "github.com/minio-io/erasure",
@ -40,7 +40,7 @@
}, },
{ {
"ImportPath": "github.com/minio-io/objectdriver", "ImportPath": "github.com/minio-io/objectdriver",
"Rev": "d5a77b2d8a48a0d8906db1757bbac861199ef6a1" "Rev": "8173914f6082348048d175c7d08bff03adde2111"
}, },
{ {
"ImportPath": "github.com/stretchr/objx", "ImportPath": "github.com/stretchr/objx",

View File

@ -67,7 +67,7 @@ func compileTime() time.Time {
return info.ModTime() return info.ModTime()
} }
// Creates a new cli Application with some reasonable defaults for Name, Usage, Version and Action. // NewApp - Creates a new cli Application with some reasonable defaults for Name, Usage, Version and Action.
func NewApp() *App { func NewApp() *App {
return &App{ return &App{
Name: os.Args[0], Name: os.Args[0],
@ -80,12 +80,37 @@ func NewApp() *App {
} }
} }
// Entry point to the cli app. Parses the arguments slice and routes to the proper flag/args combination // getNewContext -
func (a *App) Run(arguments []string) (err error) { func (a *App) getNewContext(arguments []string) (*Context, error) {
if a.Author != "" || a.Email != "" { // parse flags
a.Authors = append(a.Authors, Author{Name: a.Author, Email: a.Email}) set := flagSet(a.Name, a.Flags)
} set.SetOutput(ioutil.Discard)
context := NewContext(a, set, set)
err := set.Parse(arguments[1:])
if err != nil {
fmt.Fprintf(a.Writer, "Incorrect Usage.\n\n")
ShowAppHelp(context)
fmt.Fprintln(a.Writer)
return nil, err
}
nerr := normalizeFlags(a.Flags, set)
if nerr != nil {
fmt.Fprintln(a.Writer, nerr)
ShowAppHelp(context)
fmt.Fprintln(a.Writer)
return nil, nerr
}
return context, nil
}
// Run - Entry point to the cli app. Parses the arguments slice and routes to the proper flag/args combination
func (a *App) Run(arguments []string) (err error) {
// Comment this out as its not going to be used
// if a.Author != "" || a.Email != "" {
// a.Authors = append(a.Authors, Author{Name: a.Author, Email: a.Email})
//}
if HelpPrinter == nil { if HelpPrinter == nil {
defer func() { defer func() {
HelpPrinter = nil HelpPrinter = nil
@ -123,36 +148,12 @@ func (a *App) Run(arguments []string) (err error) {
a.appendFlag(VersionFlag) a.appendFlag(VersionFlag)
} }
// parse flags context, err := a.getNewContext(arguments)
set := flagSet(a.Name, a.Flags)
set.SetOutput(ioutil.Discard)
err = set.Parse(arguments[1:])
nerr := normalizeFlags(a.Flags, set)
if nerr != nil {
fmt.Fprintln(a.Writer, nerr)
context := NewContext(a, set, set)
ShowAppHelp(context)
fmt.Fprintln(a.Writer)
return nerr
}
context := NewContext(a, set, set)
if err != nil { if err != nil {
fmt.Fprintf(a.Writer, "Incorrect Usage.\n\n")
ShowAppHelp(context)
fmt.Fprintln(a.Writer)
return err return err
} }
if checkCompletions(context) { if checkCompletions(context) || checkHelp(context) || checkVersion(context) {
return nil
}
if checkHelp(context) {
return nil
}
if checkVersion(context) {
return nil return nil
} }
@ -186,7 +187,7 @@ func (a *App) Run(arguments []string) (err error) {
return nil return nil
} }
// Another entry point to the cli app, takes care of passing arguments and error handling // RunAndExitOnError - Another entry point to the cli app, takes care of passing arguments and error handling
func (a *App) RunAndExitOnError() { func (a *App) RunAndExitOnError() {
if err := a.Run(os.Args); err != nil { if err := a.Run(os.Args); err != nil {
fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, err)
@ -194,7 +195,7 @@ func (a *App) RunAndExitOnError() {
} }
} }
// Invokes the subcommand given the context, parses ctx.Args() to generate command-specific flags // RunAsSubcommand - Invokes the subcommand given the context, parses ctx.Args() to generate command-specific flags
func (a *App) RunAsSubcommand(ctx *Context) (err error) { func (a *App) RunAsSubcommand(ctx *Context) (err error) {
// append help to commands // append help to commands
if len(a.Commands) > 0 { if len(a.Commands) > 0 {
@ -280,7 +281,7 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) {
return nil return nil
} }
// Returns the named command on App. Returns nil if the command does not exist // Command - Returns the named command on App. Returns nil if the command does not exist
func (a *App) Command(name string) *Command { func (a *App) Command(name string) *Command {
for _, c := range a.Commands { for _, c := range a.Commands {
if c.HasName(name) { if c.HasName(name) {

View File

@ -23,7 +23,7 @@ func ExampleApp() {
} }
app.Author = "Harrison" app.Author = "Harrison"
app.Email = "harrison@lolwut.com" app.Email = "harrison@lolwut.com"
app.Authors = []cli.Author{cli.Author{Name: "Oliver Allen", Email: "oliver@toyshop.com"}} app.Authors = []cli.Author{{Name: "Oliver Allen", Email: "oliver@toyshop.com"}}
app.Run(os.Args) app.Run(os.Args)
// Output: // Output:
// Hello Jeremy // Hello Jeremy
@ -401,7 +401,7 @@ func TestApp_BeforeFunc(t *testing.T) {
} }
app.Commands = []cli.Command{ app.Commands = []cli.Command{
cli.Command{ {
Name: "sub", Name: "sub",
Action: func(c *cli.Context) { Action: func(c *cli.Context) {
subcommandRun = true subcommandRun = true
@ -467,7 +467,7 @@ func TestApp_AfterFunc(t *testing.T) {
} }
app.Commands = []cli.Command{ app.Commands = []cli.Command{
cli.Command{ {
Name: "sub", Name: "sub",
Action: func(c *cli.Context) { Action: func(c *cli.Context) {
subcommandRun = true subcommandRun = true
@ -578,7 +578,7 @@ func TestAppCommandNotFound(t *testing.T) {
} }
app.Commands = []cli.Command{ app.Commands = []cli.Command{
cli.Command{ {
Name: "bar", Name: "bar",
Action: func(c *cli.Context) { Action: func(c *cli.Context) {
subcommandRun = true subcommandRun = true
@ -601,7 +601,7 @@ func TestGlobalFlagsInSubcommands(t *testing.T) {
} }
app.Commands = []cli.Command{ app.Commands = []cli.Command{
cli.Command{ {
Name: "foo", Name: "foo",
Subcommands: []cli.Command{ Subcommands: []cli.Command{
{ {

93
Godeps/_workspace/src/github.com/minio-io/cli/bool.go generated vendored Normal file
View File

@ -0,0 +1,93 @@
package cli
import (
"flag"
"fmt"
"os"
"strconv"
"strings"
)
// BoolFlag - a flag of bool type
type BoolFlag struct {
Name string
Usage string
EnvVar string
Hide bool
}
// String -
func (f BoolFlag) String() string {
return withEnvHint(f.EnvVar, fmt.Sprintf("%s\t%v", prefixedNames(f.Name), f.Usage))
}
// Apply -
func (f BoolFlag) Apply(set *flag.FlagSet) {
val := false
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
envValBool, err := strconv.ParseBool(envVal)
if err == nil {
val = envValBool
}
break
}
}
}
eachName(f.Name, func(name string) {
set.Bool(name, val, f.Usage)
})
}
func (f BoolFlag) getName() string {
return f.Name
}
func (f BoolFlag) isNotHidden() bool {
return !f.Hide
}
// BoolTFlag - a flag of bool environment type
type BoolTFlag struct {
Name string
Usage string
EnvVar string
Hide bool
}
// String -
func (f BoolTFlag) String() string {
return withEnvHint(f.EnvVar, fmt.Sprintf("%s\t%v", prefixedNames(f.Name), f.Usage))
}
// Apply -
func (f BoolTFlag) Apply(set *flag.FlagSet) {
val := true
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
envValBool, err := strconv.ParseBool(envVal)
if err == nil {
val = envValBool
break
}
}
}
}
eachName(f.Name, func(name string) {
set.Bool(name, val, f.Usage)
})
}
func (f BoolTFlag) getName() string {
return f.Name
}
func (f BoolTFlag) isNotHidden() bool {
return !f.Hide
}

View File

@ -38,11 +38,14 @@ type Command struct {
HideHelp bool HideHelp bool
// Boolean to hide this command from help or completion // Boolean to hide this command from help or completion
Hide bool Hide bool
// CustomHelpTemplate the text template for the command help topic.
// cli.go uses text/template to render templates. You can
// render custom help text by setting this variable.
CustomHelpTemplate string
} }
// Invokes the command given the context, parses ctx.Args() to generate command-specific flags // Run - Invokes the command given the context, parses ctx.Args() to generate command-specific flags
func (c Command) Run(ctx *Context) error { func (c Command) Run(ctx *Context) error {
if len(c.Subcommands) > 0 || c.Before != nil || c.After != nil { if len(c.Subcommands) > 0 || c.Before != nil || c.After != nil {
return c.startApp(ctx) return c.startApp(ctx)
} }
@ -121,6 +124,7 @@ func (c Command) Run(ctx *Context) error {
return nil return nil
} }
// Names - returns collection of all name, shortname and aliases
func (c Command) Names() []string { func (c Command) Names() []string {
names := []string{c.Name} names := []string{c.Name}
@ -131,7 +135,7 @@ func (c Command) Names() []string {
return append(names, c.Aliases...) return append(names, c.Aliases...)
} }
// Returns true if Command.Name or Command.ShortName matches given name // HasName - Returns true if Command.Name or Command.ShortName matches given name
func (c Command) HasName(name string) bool { func (c Command) HasName(name string) bool {
for _, n := range c.Names() { for _, n := range c.Names() {
if n == name { if n == name {

View File

@ -21,97 +21,97 @@ type Context struct {
globalSetFlags map[string]bool globalSetFlags map[string]bool
} }
// Creates a new context. For use in when invoking an App or Command action. // NewContext - Creates a new context. For use in when invoking an App or Command action.
func NewContext(app *App, set *flag.FlagSet, globalSet *flag.FlagSet) *Context { func NewContext(app *App, set *flag.FlagSet, globalSet *flag.FlagSet) *Context {
return &Context{App: app, flagSet: set, globalSet: globalSet} return &Context{App: app, flagSet: set, globalSet: globalSet}
} }
// Looks up the value of a local int flag, returns 0 if no int flag exists // Int - Looks up the value of a local int flag, returns 0 if no int flag exists
func (c *Context) Int(name string) int { func (c *Context) Int(name string) int {
return lookupInt(name, c.flagSet) return lookupInt(name, c.flagSet)
} }
// Looks up the value of a local time.Duration flag, returns 0 if no time.Duration flag exists // Duration - Looks up the value of a local time.Duration flag, returns 0 if no time.Duration flag exists
func (c *Context) Duration(name string) time.Duration { func (c *Context) Duration(name string) time.Duration {
return lookupDuration(name, c.flagSet) return lookupDuration(name, c.flagSet)
} }
// Looks up the value of a local float64 flag, returns 0 if no float64 flag exists // Float64 - Looks up the value of a local float64 flag, returns 0 if no float64 flag exists
func (c *Context) Float64(name string) float64 { func (c *Context) Float64(name string) float64 {
return lookupFloat64(name, c.flagSet) return lookupFloat64(name, c.flagSet)
} }
// Looks up the value of a local bool flag, returns false if no bool flag exists // Bool - Looks up the value of a local bool flag, returns false if no bool flag exists
func (c *Context) Bool(name string) bool { func (c *Context) Bool(name string) bool {
return lookupBool(name, c.flagSet) return lookupBool(name, c.flagSet)
} }
// Looks up the value of a local boolT flag, returns false if no bool flag exists // BoolT - Looks up the value of a local boolT flag, returns false if no bool flag exists
func (c *Context) BoolT(name string) bool { func (c *Context) BoolT(name string) bool {
return lookupBoolT(name, c.flagSet) return lookupBoolT(name, c.flagSet)
} }
// Looks up the value of a local string flag, returns "" if no string flag exists // String Looks up the value of a local string flag, returns "" if no string flag exists
func (c *Context) String(name string) string { func (c *Context) String(name string) string {
return lookupString(name, c.flagSet) return lookupString(name, c.flagSet)
} }
// Looks up the value of a local string slice flag, returns nil if no string slice flag exists // StringSlice - Looks up the value of a local string slice flag, returns nil if no string slice flag exists
func (c *Context) StringSlice(name string) []string { func (c *Context) StringSlice(name string) []string {
return lookupStringSlice(name, c.flagSet) return lookupStringSlice(name, c.flagSet)
} }
// Looks up the value of a local int slice flag, returns nil if no int slice flag exists // IntSlice - Looks up the value of a local int slice flag, returns nil if no int slice flag exists
func (c *Context) IntSlice(name string) []int { func (c *Context) IntSlice(name string) []int {
return lookupIntSlice(name, c.flagSet) return lookupIntSlice(name, c.flagSet)
} }
// Looks up the value of a local generic flag, returns nil if no generic flag exists // Generic - Looks up the value of a local generic flag, returns nil if no generic flag exists
func (c *Context) Generic(name string) interface{} { func (c *Context) Generic(name string) interface{} {
return lookupGeneric(name, c.flagSet) return lookupGeneric(name, c.flagSet)
} }
// Looks up the value of a global int flag, returns 0 if no int flag exists // GlobalInt - Looks up the value of a global int flag, returns 0 if no int flag exists
func (c *Context) GlobalInt(name string) int { func (c *Context) GlobalInt(name string) int {
return lookupInt(name, c.globalSet) return lookupInt(name, c.globalSet)
} }
// Looks up the value of a global time.Duration flag, returns 0 if no time.Duration flag exists // GlobalDuration - Looks up the value of a global time.Duration flag, returns 0 if no time.Duration flag exists
func (c *Context) GlobalDuration(name string) time.Duration { func (c *Context) GlobalDuration(name string) time.Duration {
return lookupDuration(name, c.globalSet) return lookupDuration(name, c.globalSet)
} }
// Looks up the value of a global bool flag, returns false if no bool flag exists // GlobalBool - Looks up the value of a global bool flag, returns false if no bool flag exists
func (c *Context) GlobalBool(name string) bool { func (c *Context) GlobalBool(name string) bool {
return lookupBool(name, c.globalSet) return lookupBool(name, c.globalSet)
} }
// Looks up the value of a global string flag, returns "" if no string flag exists // GlobalString - Looks up the value of a global string flag, returns "" if no string flag exists
func (c *Context) GlobalString(name string) string { func (c *Context) GlobalString(name string) string {
return lookupString(name, c.globalSet) return lookupString(name, c.globalSet)
} }
// Looks up the value of a global string slice flag, returns nil if no string slice flag exists // GlobalStringSlice - Looks up the value of a global string slice flag, returns nil if no string slice flag exists
func (c *Context) GlobalStringSlice(name string) []string { func (c *Context) GlobalStringSlice(name string) []string {
return lookupStringSlice(name, c.globalSet) return lookupStringSlice(name, c.globalSet)
} }
// Looks up the value of a global int slice flag, returns nil if no int slice flag exists // GlobalIntSlice - Looks up the value of a global int slice flag, returns nil if no int slice flag exists
func (c *Context) GlobalIntSlice(name string) []int { func (c *Context) GlobalIntSlice(name string) []int {
return lookupIntSlice(name, c.globalSet) return lookupIntSlice(name, c.globalSet)
} }
// Looks up the value of a global generic flag, returns nil if no generic flag exists // GlobalGeneric - Looks up the value of a global generic flag, returns nil if no generic flag exists
func (c *Context) GlobalGeneric(name string) interface{} { func (c *Context) GlobalGeneric(name string) interface{} {
return lookupGeneric(name, c.globalSet) return lookupGeneric(name, c.globalSet)
} }
// Returns the number of flags set // NumFlags - Returns the number of flags set
func (c *Context) NumFlags() int { func (c *Context) NumFlags() int {
return c.flagSet.NFlag() return c.flagSet.NFlag()
} }
// Determines if the flag was actually set // IsSet - Determines if the flag was actually set
func (c *Context) IsSet(name string) bool { func (c *Context) IsSet(name string) bool {
if c.setFlags == nil { if c.setFlags == nil {
c.setFlags = make(map[string]bool) c.setFlags = make(map[string]bool)
@ -122,7 +122,7 @@ func (c *Context) IsSet(name string) bool {
return c.setFlags[name] == true return c.setFlags[name] == true
} }
// Determines if the global flag was actually set // GlobalIsSet - Determines if the global flag was actually set
func (c *Context) GlobalIsSet(name string) bool { func (c *Context) GlobalIsSet(name string) bool {
if c.globalSetFlags == nil { if c.globalSetFlags == nil {
c.globalSetFlags = make(map[string]bool) c.globalSetFlags = make(map[string]bool)
@ -133,7 +133,7 @@ func (c *Context) GlobalIsSet(name string) bool {
return c.globalSetFlags[name] == true return c.globalSetFlags[name] == true
} }
// Returns a slice of flag names used in this context. // FlagNames - Returns a slice of flag names used in this context.
func (c *Context) FlagNames() (names []string) { func (c *Context) FlagNames() (names []string) {
for _, flag := range c.Command.Flags { for _, flag := range c.Command.Flags {
name := strings.Split(flag.getName(), ",")[0] name := strings.Split(flag.getName(), ",")[0]
@ -145,7 +145,7 @@ func (c *Context) FlagNames() (names []string) {
return return
} }
// Returns a slice of global flag names used by the app. // GlobalFlagNames - Returns a slice of global flag names used by the app.
func (c *Context) GlobalFlagNames() (names []string) { func (c *Context) GlobalFlagNames() (names []string) {
for _, flag := range c.App.Flags { for _, flag := range c.App.Flags {
name := strings.Split(flag.getName(), ",")[0] name := strings.Split(flag.getName(), ",")[0]
@ -157,15 +157,16 @@ func (c *Context) GlobalFlagNames() (names []string) {
return return
} }
// Args - slice of string
type Args []string type Args []string
// Returns the command line arguments associated with the context. // Args - Returns the command line arguments associated with the context.
func (c *Context) Args() Args { func (c *Context) Args() Args {
args := Args(c.flagSet.Args()) args := Args(c.flagSet.Args())
return args return args
} }
// Returns the nth argument, or else a blank string // Get - Returns the nth argument, or else a blank string
func (a Args) Get(n int) string { func (a Args) Get(n int) string {
if len(a) > n { if len(a) > n {
return a[n] return a[n]
@ -173,12 +174,12 @@ func (a Args) Get(n int) string {
return "" return ""
} }
// Returns the first argument, or else a blank string // First - Returns the first argument, or else a blank string
func (a Args) First() string { func (a Args) First() string {
return a.Get(0) return a.Get(0)
} }
// Return the rest of the arguments (not the first one) // Tail - Return the rest of the arguments (not the first one)
// or else an empty string slice // or else an empty string slice
func (a Args) Tail() []string { func (a Args) Tail() []string {
if len(a) >= 2 { if len(a) >= 2 {
@ -187,12 +188,12 @@ func (a Args) Tail() []string {
return []string{} return []string{}
} }
// Checks if there are any arguments present // Present - Checks if there are any arguments present
func (a Args) Present() bool { func (a Args) Present() bool {
return len(a) != 0 return len(a) != 0
} }
// Swaps arguments at the given indexes // Swap - swaps arguments at the given indexes
func (a Args) Swap(from, to int) error { func (a Args) Swap(from, to int) error {
if from >= len(a) || to >= len(a) { if from >= len(a) || to >= len(a) {
return errors.New("index out of range") return errors.New("index out of range")

View File

@ -0,0 +1,51 @@
package cli
import (
"flag"
"fmt"
"os"
"strings"
"time"
)
// DurationFlag - a flag of time.Duration type
type DurationFlag struct {
Name string
Value time.Duration
Usage string
EnvVar string
Hide bool
}
// String -
func (f DurationFlag) String() string {
return withEnvHint(f.EnvVar, fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(f.Name), f.Value, f.Usage))
}
// Apply -
func (f DurationFlag) Apply(set *flag.FlagSet) {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
envValDuration, err := time.ParseDuration(envVal)
if err == nil {
f.Value = envValDuration
break
}
}
}
}
eachName(f.Name, func(name string) {
set.Duration(name, f.Value, f.Usage)
})
}
func (f DurationFlag) getName() string {
return f.Name
}
func (f DurationFlag) isNotHidden() bool {
return !f.Hide
}

View File

@ -4,26 +4,25 @@ import (
"flag" "flag"
"fmt" "fmt"
"os" "os"
"strconv"
"strings" "strings"
"time"
) )
// This flag enables bash-completion for all commands and subcommands // BashCompletionFlag - This flag enables bash-completion for all commands and subcommands
// it is hidden by default
var BashCompletionFlag = BoolFlag{ var BashCompletionFlag = BoolFlag{
Name: "generate-bash-completion", Name: "generate-bash-completion",
Hide: true, Hide: true,
} }
// This flag prints the version for the application // VersionFlag - This flag prints the version for the application
var VersionFlag = BoolFlag{ var VersionFlag = BoolFlag{
Name: "version, v", Name: "version, v",
Usage: "print the version", Usage: "print the version",
} }
// This flag prints the help for all commands and subcommands // HelpFlay - This flag prints the help for all commands and subcommands
// Set to the zero value (BoolFlag{}) to disable flag -- keeps subcommand // Set to the zero value (BoolFlag{}) to disable flag -- keeps subcommand
// unless HideHelp is set to true) // unless HideHelp is set to true) it is hidden by default
var HelpFlag = BoolFlag{ var HelpFlag = BoolFlag{
Name: "help, h", Name: "help, h",
Usage: "show help", Usage: "show help",
@ -107,369 +106,6 @@ func (f GenericFlag) isNotHidden() bool {
return !f.Hide return !f.Hide
} }
type StringSlice []string
func (f *StringSlice) Set(value string) error {
*f = append(*f, value)
return nil
}
func (f *StringSlice) String() string {
return fmt.Sprintf("%s", *f)
}
func (f *StringSlice) Value() []string {
return *f
}
type StringSliceFlag struct {
Name string
Value *StringSlice
Usage string
EnvVar string
Hide bool
}
func (f StringSliceFlag) String() string {
firstName := strings.Trim(strings.Split(f.Name, ",")[0], " ")
pref := prefixFor(firstName)
return withEnvHint(f.EnvVar, fmt.Sprintf("%s [%v]\t%v", prefixedNames(f.Name), pref+firstName+" option "+pref+firstName+" option", f.Usage))
}
func (f StringSliceFlag) Apply(set *flag.FlagSet) {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
newVal := &StringSlice{}
for _, s := range strings.Split(envVal, ",") {
s = strings.TrimSpace(s)
newVal.Set(s)
}
f.Value = newVal
break
}
}
}
eachName(f.Name, func(name string) {
set.Var(f.Value, name, f.Usage)
})
}
func (f StringSliceFlag) getName() string {
return f.Name
}
func (f StringSliceFlag) isNotHidden() bool {
return !f.Hide
}
type IntSlice []int
func (f *IntSlice) Set(value string) error {
tmp, err := strconv.Atoi(value)
if err != nil {
return err
} else {
*f = append(*f, tmp)
}
return nil
}
func (f *IntSlice) String() string {
return fmt.Sprintf("%d", *f)
}
func (f *IntSlice) Value() []int {
return *f
}
type IntSliceFlag struct {
Name string
Value *IntSlice
Usage string
EnvVar string
Hide bool
}
func (f IntSliceFlag) String() string {
firstName := strings.Trim(strings.Split(f.Name, ",")[0], " ")
pref := prefixFor(firstName)
return withEnvHint(f.EnvVar, fmt.Sprintf("%s [%v]\t%v", prefixedNames(f.Name), pref+firstName+" option "+pref+firstName+" option", f.Usage))
}
func (f IntSliceFlag) Apply(set *flag.FlagSet) {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
newVal := &IntSlice{}
for _, s := range strings.Split(envVal, ",") {
s = strings.TrimSpace(s)
err := newVal.Set(s)
if err != nil {
fmt.Fprintf(os.Stderr, err.Error())
}
}
f.Value = newVal
break
}
}
}
eachName(f.Name, func(name string) {
set.Var(f.Value, name, f.Usage)
})
}
func (f IntSliceFlag) getName() string {
return f.Name
}
func (f IntSliceFlag) isNotHidden() bool {
return !f.Hide
}
type BoolFlag struct {
Name string
Usage string
EnvVar string
Hide bool
}
func (f BoolFlag) String() string {
return withEnvHint(f.EnvVar, fmt.Sprintf("%s\t%v", prefixedNames(f.Name), f.Usage))
}
func (f BoolFlag) Apply(set *flag.FlagSet) {
val := false
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
envValBool, err := strconv.ParseBool(envVal)
if err == nil {
val = envValBool
}
break
}
}
}
eachName(f.Name, func(name string) {
set.Bool(name, val, f.Usage)
})
}
func (f BoolFlag) getName() string {
return f.Name
}
func (f BoolFlag) isNotHidden() bool {
return !f.Hide
}
type BoolTFlag struct {
Name string
Usage string
EnvVar string
Hide bool
}
func (f BoolTFlag) String() string {
return withEnvHint(f.EnvVar, fmt.Sprintf("%s\t%v", prefixedNames(f.Name), f.Usage))
}
func (f BoolTFlag) Apply(set *flag.FlagSet) {
val := true
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
envValBool, err := strconv.ParseBool(envVal)
if err == nil {
val = envValBool
break
}
}
}
}
eachName(f.Name, func(name string) {
set.Bool(name, val, f.Usage)
})
}
func (f BoolTFlag) getName() string {
return f.Name
}
func (f BoolTFlag) isNotHidden() bool {
return !f.Hide
}
type StringFlag struct {
Name string
Value string
Usage string
EnvVar string
Hide bool
}
func (f StringFlag) String() string {
var fmtString string
fmtString = "%s %v\t%v"
if len(f.Value) > 0 {
fmtString = "%s \"%v\"\t%v"
} else {
fmtString = "%s %v\t%v"
}
return withEnvHint(f.EnvVar, fmt.Sprintf(fmtString, prefixedNames(f.Name), f.Value, f.Usage))
}
func (f StringFlag) Apply(set *flag.FlagSet) {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
f.Value = envVal
break
}
}
}
eachName(f.Name, func(name string) {
set.String(name, f.Value, f.Usage)
})
}
func (f StringFlag) getName() string {
return f.Name
}
func (f StringFlag) isNotHidden() bool {
return !f.Hide
}
type IntFlag struct {
Name string
Value int
Usage string
EnvVar string
Hide bool
}
func (f IntFlag) String() string {
return withEnvHint(f.EnvVar, fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(f.Name), f.Value, f.Usage))
}
func (f IntFlag) Apply(set *flag.FlagSet) {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
envValInt, err := strconv.ParseInt(envVal, 0, 64)
if err == nil {
f.Value = int(envValInt)
break
}
}
}
}
eachName(f.Name, func(name string) {
set.Int(name, f.Value, f.Usage)
})
}
func (f IntFlag) getName() string {
return f.Name
}
func (f IntFlag) isNotHidden() bool {
return !f.Hide
}
type DurationFlag struct {
Name string
Value time.Duration
Usage string
EnvVar string
Hide bool
}
func (f DurationFlag) String() string {
return withEnvHint(f.EnvVar, fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(f.Name), f.Value, f.Usage))
}
func (f DurationFlag) Apply(set *flag.FlagSet) {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
envValDuration, err := time.ParseDuration(envVal)
if err == nil {
f.Value = envValDuration
break
}
}
}
}
eachName(f.Name, func(name string) {
set.Duration(name, f.Value, f.Usage)
})
}
func (f DurationFlag) getName() string {
return f.Name
}
func (f DurationFlag) isNotHidden() bool {
return !f.Hide
}
type Float64Flag struct {
Name string
Value float64
Usage string
EnvVar string
Hide bool
}
func (f Float64Flag) String() string {
return withEnvHint(f.EnvVar, fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(f.Name), f.Value, f.Usage))
}
func (f Float64Flag) Apply(set *flag.FlagSet) {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
envValFloat, err := strconv.ParseFloat(envVal, 10)
if err == nil {
f.Value = float64(envValFloat)
}
}
}
}
eachName(f.Name, func(name string) {
set.Float64(name, f.Value, f.Usage)
})
}
func (f Float64Flag) getName() string {
return f.Name
}
func (f Float64Flag) isNotHidden() bool {
return !f.Hide
}
func prefixFor(name string) (prefix string) { func prefixFor(name string) (prefix string) {
if len(name) == 1 { if len(name) == 1 {
prefix = "-" prefix = "-"

View File

@ -0,0 +1,50 @@
package cli
import (
"flag"
"fmt"
"os"
"strconv"
"strings"
)
// Float64Flag - a flag of floating number type
type Float64Flag struct {
Name string
Value float64
Usage string
EnvVar string
Hide bool
}
// String -
func (f Float64Flag) String() string {
return withEnvHint(f.EnvVar, fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(f.Name), f.Value, f.Usage))
}
// Apply -
func (f Float64Flag) Apply(set *flag.FlagSet) {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
envValFloat, err := strconv.ParseFloat(envVal, 10)
if err == nil {
f.Value = float64(envValFloat)
}
}
}
}
eachName(f.Name, func(name string) {
set.Float64(name, f.Value, f.Usage)
})
}
func (f Float64Flag) getName() string {
return f.Name
}
func (f Float64Flag) isNotHidden() bool {
return !f.Hide
}

View File

@ -1,6 +1,9 @@
package cli package cli
import "fmt" import (
"fmt"
"os"
)
// The text template for the Default help topic. // The text template for the Default help topic.
// cli.go uses text/template to render templates. You can // cli.go uses text/template to render templates. You can
@ -31,7 +34,7 @@ GLOBAL OPTIONS:
// The text template for the command help topic. // The text template for the command help topic.
// cli.go uses text/template to render templates. You can // cli.go uses text/template to render templates. You can
// render custom help text by setting this variable. // render custom help text by setting this variable.
var CommandHelpTemplate = `NAME: var DefaultCommandHelpTemplate = `NAME:
{{.Name}} - {{.Usage}} {{.Name}} - {{.Usage}}
USAGE: USAGE:
@ -48,7 +51,7 @@ OPTIONS:
// The text template for the subcommand help topic. // The text template for the subcommand help topic.
// cli.go uses text/template to render templates. You can // cli.go uses text/template to render templates. You can
// render custom help text by setting this variable. // render custom help text by setting this variable.
var SubcommandHelpTemplate = `NAME: var DefaultSubcommandHelpTemplate = `NAME:
{{.Name}} - {{.Usage}} {{.Name}} - {{.Usage}}
USAGE: USAGE:
@ -95,11 +98,13 @@ var helpSubcommand = Command{
// Prints help for the App // Prints help for the App
type helpPrinter func(templ string, data interface{}) type helpPrinter func(templ string, data interface{})
var HelpPrinter helpPrinter = nil // HelpPrinter - prints help for the app
var HelpPrinter helpPrinter
// Prints version for the App // Prints version for the App
var VersionPrinter = printVersion var VersionPrinter = printVersion
// ShowAppHelp - Prints the list of subcommands for the app
func ShowAppHelp(c *Context) { func ShowAppHelp(c *Context) {
// Make a copy of c.App context // Make a copy of c.App context
app := *c.App app := *c.App
@ -118,7 +123,7 @@ func ShowAppHelp(c *Context) {
HelpPrinter(AppHelpTemplate, app) HelpPrinter(AppHelpTemplate, app)
} }
// Prints the list of subcommands as the default app completion method // DefaultAppComplete - Prints the list of subcommands as the default app completion method
func DefaultAppComplete(c *Context) { func DefaultAppComplete(c *Context) {
for _, command := range c.App.Commands { for _, command := range c.App.Commands {
if command.isNotHidden() { if command.isNotHidden() {
@ -129,7 +134,13 @@ func DefaultAppComplete(c *Context) {
} }
} }
// Prints help for the given command // ShowCommandHelpAndExit - exits with code after showing help
func ShowCommandHelpAndExit(c *Context, command string, code int) {
ShowCommandHelp(c, command)
os.Exit(code)
}
// ShowCommandHelp - Prints help for the given command
func ShowCommandHelp(c *Context, command string) { func ShowCommandHelp(c *Context, command string) {
// show the subcommand help for a command with subcommands // show the subcommand help for a command with subcommands
if command == "" { if command == "" {
@ -147,7 +158,7 @@ func ShowCommandHelp(c *Context, command string) {
app.Commands = append(app.Commands, command) app.Commands = append(app.Commands, command)
} }
} }
HelpPrinter(SubcommandHelpTemplate, app) HelpPrinter(DefaultSubcommandHelpTemplate, app)
return return
} }
@ -161,7 +172,11 @@ func ShowCommandHelp(c *Context, command string) {
c0.Flags = append(c0.Flags, flag) c0.Flags = append(c0.Flags, flag)
} }
} }
HelpPrinter(CommandHelpTemplate, c0) if c0.CustomHelpTemplate != "" {
HelpPrinter(c0.CustomHelpTemplate, c0)
} else {
HelpPrinter(DefaultCommandHelpTemplate, c0)
}
return return
} }
} }
@ -173,12 +188,12 @@ func ShowCommandHelp(c *Context, command string) {
} }
} }
// Prints help for the given subcommand // ShowSubcommandHelp - Prints help for the given subcommand
func ShowSubcommandHelp(c *Context) { func ShowSubcommandHelp(c *Context) {
ShowCommandHelp(c, c.Command.Name) ShowCommandHelp(c, c.Command.Name)
} }
// Prints the version number of the App // ShowVersion - Prints the version number of the App
func ShowVersion(c *Context) { func ShowVersion(c *Context) {
VersionPrinter(c) VersionPrinter(c)
} }
@ -187,7 +202,7 @@ func printVersion(c *Context) {
fmt.Fprintf(c.App.Writer, "%v version %v\n", c.App.Name, c.App.Version) fmt.Fprintf(c.App.Writer, "%v version %v\n", c.App.Name, c.App.Version)
} }
// Prints the lists of commands within a given context // ShowCompletions - Prints the lists of commands within a given context
func ShowCompletions(c *Context) { func ShowCompletions(c *Context) {
a := c.App a := c.App
if a != nil && a.BashComplete != nil { if a != nil && a.BashComplete != nil {
@ -195,7 +210,7 @@ func ShowCompletions(c *Context) {
} }
} }
// Prints the custom completions for a given command // ShowCommandCompletions - Prints the custom completions for a given command
func ShowCommandCompletions(ctx *Context, command string) { func ShowCommandCompletions(ctx *Context, command string) {
c := ctx.App.Command(command) c := ctx.App.Command(command)
if c != nil && c.BashComplete != nil { if c != nil && c.BashComplete != nil {

51
Godeps/_workspace/src/github.com/minio-io/cli/int.go generated vendored Normal file
View File

@ -0,0 +1,51 @@
package cli
import (
"flag"
"fmt"
"os"
"strconv"
"strings"
)
// IntFlag - a flag of integer type
type IntFlag struct {
Name string
Value int
Usage string
EnvVar string
Hide bool
}
// String -
func (f IntFlag) String() string {
return withEnvHint(f.EnvVar, fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(f.Name), f.Value, f.Usage))
}
// Apply -
func (f IntFlag) Apply(set *flag.FlagSet) {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
envValInt, err := strconv.ParseInt(envVal, 0, 64)
if err == nil {
f.Value = int(envValInt)
break
}
}
}
}
eachName(f.Name, func(name string) {
set.Int(name, f.Value, f.Usage)
})
}
func (f IntFlag) getName() string {
return f.Name
}
func (f IntFlag) isNotHidden() bool {
return !f.Hide
}

View File

@ -0,0 +1,81 @@
package cli
import (
"flag"
"fmt"
"os"
"strconv"
"strings"
)
// IntSlice - a type of integer slice
type IntSlice []int
// Set -
func (f *IntSlice) Set(value string) error {
tmp, err := strconv.Atoi(value)
if err != nil {
return err
}
*f = append(*f, tmp)
return nil
}
// String -
func (f *IntSlice) String() string {
return fmt.Sprintf("%d", *f)
}
// Value -
func (f *IntSlice) Value() []int {
return *f
}
// IntSliceFlag - a type of integer slice flag
type IntSliceFlag struct {
Name string
Value *IntSlice
Usage string
EnvVar string
Hide bool
}
// String -
func (f IntSliceFlag) String() string {
firstName := strings.Trim(strings.Split(f.Name, ",")[0], " ")
pref := prefixFor(firstName)
return withEnvHint(f.EnvVar, fmt.Sprintf("%s [%v]\t%v", prefixedNames(f.Name), pref+firstName+" option "+pref+firstName+" option", f.Usage))
}
// Apply -
func (f IntSliceFlag) Apply(set *flag.FlagSet) {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
newVal := &IntSlice{}
for _, s := range strings.Split(envVal, ",") {
s = strings.TrimSpace(s)
err := newVal.Set(s)
if err != nil {
fmt.Fprintf(os.Stderr, err.Error())
}
}
f.Value = newVal
break
}
}
}
eachName(f.Name, func(name string) {
set.Var(f.Value, name, f.Usage)
})
}
func (f IntSliceFlag) getName() string {
return f.Name
}
func (f IntSliceFlag) isNotHidden() bool {
return !f.Hide
}

View File

@ -0,0 +1,54 @@
package cli
import (
"flag"
"fmt"
"os"
"strings"
)
// StringFlag - a string flag type
type StringFlag struct {
Name string
Value string
Usage string
EnvVar string
Hide bool
}
func (f StringFlag) String() string {
var fmtString string
fmtString = "%s %v\t%v"
if len(f.Value) > 0 {
fmtString = "%s \"%v\"\t%v"
} else {
fmtString = "%s %v\t%v"
}
return withEnvHint(f.EnvVar, fmt.Sprintf(fmtString, prefixedNames(f.Name), f.Value, f.Usage))
}
// Apply -
func (f StringFlag) Apply(set *flag.FlagSet) {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
f.Value = envVal
break
}
}
}
eachName(f.Name, func(name string) {
set.String(name, f.Value, f.Usage)
})
}
func (f StringFlag) getName() string {
return f.Name
}
func (f StringFlag) isNotHidden() bool {
return !f.Hide
}

View File

@ -0,0 +1,73 @@
package cli
import (
"flag"
"fmt"
"os"
"strings"
)
// StringSlice - type
type StringSlice []string
// Set -
func (f *StringSlice) Set(value string) error {
*f = append(*f, value)
return nil
}
// String -
func (f *StringSlice) String() string {
return fmt.Sprintf("%s", *f)
}
// Value -
func (f *StringSlice) Value() []string {
return *f
}
// StringSliceFlag - a string slice flag type
type StringSliceFlag struct {
Name string
Value *StringSlice
Usage string
EnvVar string
Hide bool
}
// String -
func (f StringSliceFlag) String() string {
firstName := strings.Trim(strings.Split(f.Name, ",")[0], " ")
pref := prefixFor(firstName)
return withEnvHint(f.EnvVar, fmt.Sprintf("%s [%v]\t%v", prefixedNames(f.Name), pref+firstName+" option "+pref+firstName+" option", f.Usage))
}
// Apply -
func (f StringSliceFlag) Apply(set *flag.FlagSet) {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
newVal := &StringSlice{}
for _, s := range strings.Split(envVal, ",") {
s = strings.TrimSpace(s)
newVal.Set(s)
}
f.Value = newVal
break
}
}
}
eachName(f.Name, func(name string) {
set.Var(f.Value, name, f.Usage)
})
}
func (f StringSliceFlag) getName() string {
return f.Name
}
func (f StringSliceFlag) isNotHidden() bool {
return !f.Hide
}

View File

@ -7,8 +7,8 @@
"Deps": [ "Deps": [
{ {
"ImportPath": "github.com/minio-io/cli", "ImportPath": "github.com/minio-io/cli",
"Comment": "1.2.0-101-g1a25bbd", "Comment": "1.2.0-102-gecb385c",
"Rev": "1a25bbdce2344b0063ea0476bceb4a4adbe4492a" "Rev": "ecb385c3fefd53678e3b6beba6a608fb7c8dfac1"
}, },
{ {
"ImportPath": "github.com/minio-io/erasure", "ImportPath": "github.com/minio-io/erasure",

View File

@ -97,18 +97,18 @@ func (b bucket) GetObject(objectName string) (reader io.ReadCloser, size int64,
if !ok { if !ok {
return nil, 0, os.ErrNotExist return nil, 0, os.ErrNotExist
} }
objectMetata, err := object.GetObjectMetadata() objectMetadata, err := object.GetObjectMetadata()
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err
} }
if objectName == "" || writer == nil || len(objectMetata) == 0 { if objectName == "" || writer == nil || len(objectMetadata) == 0 {
return nil, 0, errors.New("invalid argument") return nil, 0, errors.New("invalid argument")
} }
size, err = strconv.ParseInt(objectMetata["size"], 10, 64) size, err = strconv.ParseInt(objectMetadata["size"], 10, 64)
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err
} }
go b.readEncodedData(b.normalizeObjectName(objectName), writer, objectMetata) go b.readEncodedData(b.normalizeObjectName(objectName), writer, objectMetadata)
return reader, size, nil return reader, size, nil
} }
@ -128,7 +128,7 @@ func (b bucket) PutObject(objectName string, objectData io.Reader, metadata map[
defer writer.Close() defer writer.Close()
} }
summer := md5.New() summer := md5.New()
objectMetata := make(map[string]string) objectMetadata := make(map[string]string)
switch len(writers) == 1 { switch len(writers) == 1 {
case true: case true:
mw := io.MultiWriter(writers[0], summer) mw := io.MultiWriter(writers[0], summer)
@ -136,7 +136,7 @@ func (b bucket) PutObject(objectName string, objectData io.Reader, metadata map[
if err != nil { if err != nil {
return err return err
} }
objectMetata["size"] = strconv.FormatInt(totalLength, 10) objectMetadata["size"] = strconv.FormatInt(totalLength, 10)
case false: case false:
k, m, err := b.getDataAndParity(len(writers)) k, m, err := b.getDataAndParity(len(writers))
if err != nil { if err != nil {
@ -146,20 +146,25 @@ func (b bucket) PutObject(objectName string, objectData io.Reader, metadata map[
if err != nil { if err != nil {
return err return err
} }
objectMetata["blockSize"] = strconv.Itoa(10 * 1024 * 1024) objectMetadata["blockSize"] = strconv.Itoa(10 * 1024 * 1024)
objectMetata["chunkCount"] = strconv.Itoa(chunkCount) objectMetadata["chunkCount"] = strconv.Itoa(chunkCount)
objectMetata["erasureK"] = strconv.FormatUint(uint64(k), 10) objectMetadata["erasureK"] = strconv.FormatUint(uint64(k), 10)
objectMetata["erasureM"] = strconv.FormatUint(uint64(m), 10) objectMetadata["erasureM"] = strconv.FormatUint(uint64(m), 10)
objectMetata["erasureTechnique"] = "Cauchy" objectMetadata["erasureTechnique"] = "Cauchy"
objectMetata["size"] = strconv.Itoa(totalLength) objectMetadata["size"] = strconv.Itoa(totalLength)
} }
dataMd5sum := summer.Sum(nil) dataMd5sum := summer.Sum(nil)
objectMetata["created"] = time.Now().Format(time.RFC3339Nano) objectMetadata["created"] = time.Now().Format(time.RFC3339Nano)
objectMetata["md5"] = hex.EncodeToString(dataMd5sum) objectMetadata["md5"] = hex.EncodeToString(dataMd5sum)
objectMetata["bucket"] = b.name if _, ok := metadata["expectedMd5Sum"]; ok {
objectMetata["object"] = objectName if err := b.isMD5SumEqual(metadata["expectedMd5sum"], objectMetadata["md5"]); err != nil {
objectMetata["contentType"] = strings.TrimSpace(contentType) return err
if err := b.writeDonutObjectMetadata(b.normalizeObjectName(objectName), objectMetata); err != nil { }
}
objectMetadata["bucket"] = b.name
objectMetadata["object"] = objectName
objectMetadata["contentType"] = strings.TrimSpace(contentType)
if err := b.writeDonutObjectMetadata(b.normalizeObjectName(objectName), objectMetadata); err != nil {
return err return err
} }
return nil return nil

View File

@ -19,6 +19,7 @@ package donut
import ( import (
"bytes" "bytes"
"crypto/md5" "crypto/md5"
"encoding/base64"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"errors" "errors"
@ -29,9 +30,28 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/minio-io/iodine"
"github.com/minio-io/minio/pkg/utils/split" "github.com/minio-io/minio/pkg/utils/split"
) )
func (b bucket) isMD5SumEqual(expectedMD5Sum, actualMD5Sum string) error {
if strings.TrimSpace(expectedMD5Sum) != "" && strings.TrimSpace(actualMD5Sum) != "" {
expectedMD5SumBytes, err := base64.StdEncoding.DecodeString(expectedMD5Sum)
if err != nil {
return iodine.New(err, nil)
}
actualMD5SumBytes, err := hex.DecodeString(actualMD5Sum)
if err != nil {
return iodine.New(err, nil)
}
if !bytes.Equal(expectedMD5SumBytes, actualMD5SumBytes) {
return iodine.New(errors.New("bad digest, md5sum mismatch"), nil)
}
return nil
}
return iodine.New(errors.New("invalid argument"), nil)
}
func (b bucket) writeDonutObjectMetadata(objectName string, objectMetadata map[string]string) error { func (b bucket) writeDonutObjectMetadata(objectName string, objectMetadata map[string]string) error {
if len(objectMetadata) == 0 { if len(objectMetadata) == 0 {
return errors.New("invalid argument") return errors.New("invalid argument")

View File

@ -11,7 +11,7 @@
}, },
{ {
"ImportPath": "github.com/minio-io/donut", "ImportPath": "github.com/minio-io/donut",
"Rev": "1df31a9834eb6acef9ff0fb7ee3e597776faf966" "Rev": "2841ca4edd6a31fce7184027e85d2bee673b49f0"
}, },
{ {
"ImportPath": "github.com/minio-io/erasure", "ImportPath": "github.com/minio-io/erasure",

View File

@ -17,9 +17,6 @@
package donut package donut
import ( import (
"bytes"
"encoding/base64"
"encoding/hex"
"errors" "errors"
"io" "io"
"os" "os"
@ -302,34 +299,12 @@ func (d donutDriver) CreateObject(bucketName, objectName, contentType, expectedM
} }
metadata := make(map[string]string) metadata := make(map[string]string)
metadata["contentType"] = contentType metadata["contentType"] = contentType
if strings.TrimSpace(expectedMd5sum) != "" {
metadata["expectedMd5sum"] = expectedMd5sum
}
err := d.donut.PutObject(bucketName, objectName, ioutil.NopCloser(reader), metadata) err := d.donut.PutObject(bucketName, objectName, ioutil.NopCloser(reader), metadata)
if err != nil { if err != nil {
return iodine.New(err, errParams) return iodine.New(err, errParams)
} }
if strings.TrimSpace(expectedMd5sum) != "" {
objectMetadata, err := d.donut.GetObjectMetadata(bucketName, objectName)
if err != nil {
return iodine.New(err, errParams)
}
expectedMd5sumBytes, err := base64.StdEncoding.DecodeString(expectedMd5sum)
if err != nil {
return iodine.New(err, errParams)
}
if _, ok := objectMetadata["md5"]; !ok {
return iodine.New(errors.New("corrupted metadata"), nil)
}
actualMd5sumBytes, err := hex.DecodeString(objectMetadata["md5"])
if err != nil {
return iodine.New(err, errParams)
}
if !bytes.Equal(expectedMd5sumBytes, actualMd5sumBytes) {
return drivers.BadDigest{
Md5: expectedMd5sum,
Bucket: bucketName,
Key: objectName,
}
}
}
return nil return nil
} }