diff --git a/common-methods.go b/common-methods.go index 33cc4d4a..827cb72d 100644 --- a/common-methods.go +++ b/common-methods.go @@ -167,7 +167,7 @@ func getNewClient(urlStr string, auth hostConfig) (client.Client, *probe.Error) s3Config.AppVersion = mcVersion s3Config.AppComments = []string{os.Args[0], runtime.GOOS, runtime.GOARCH} s3Config.HostURL = urlStr - s3Config.Debug = globalDebugFlag + s3Config.Debug = globalDebug s3Client, err := s3.New(s3Config) if err != nil { diff --git a/config-version-main.go b/config-version-main.go index 15d28c16..2c747a79 100644 --- a/config-version-main.go +++ b/config-version-main.go @@ -61,7 +61,7 @@ func mainConfigVersion(ctx *cli.Context) { // convert interface{} back to its original struct newConf := config.Data().(*configV6) type Version string - if globalJSONFlag { + if globalJSON { tB, e := json.Marshal( struct { Version Version `json:"version"` diff --git a/cp-main.go b/cp-main.go index ad5c7c52..6989b539 100644 --- a/cp-main.go +++ b/cp-main.go @@ -139,13 +139,13 @@ func doCopy(cpURLs copyURLs, progressReader *barSend, accountingReader *accounte return } - if !globalQuietFlag && !globalJSONFlag { + if !globalQuiet && !globalJSON { progressReader.SetCaption(cpURLs.SourceContent.URL.String() + ": ") } reader, length, err := getSource(cpURLs.SourceContent.URL.String()) if err != nil { - if !globalQuietFlag && !globalJSONFlag { + if !globalQuiet && !globalJSON { progressReader.ErrorGet(length) } cpURLs.Error = err.Trace(cpURLs.SourceContent.URL.String()) @@ -154,18 +154,18 @@ func doCopy(cpURLs copyURLs, progressReader *barSend, accountingReader *accounte } var newReader io.ReadCloser - if globalQuietFlag || globalJSONFlag { + if globalQuiet || globalJSON { printMsg(copyMessage{ Source: cpURLs.SourceContent.URL.String(), Target: cpURLs.TargetContent.URL.String(), Length: cpURLs.SourceContent.Size, }) // No accounting necessary for JSON output. - if globalJSONFlag { + if globalJSON { newReader = reader } // Proxy reader to accounting reader only during quiet mode. - if globalQuietFlag { + if globalQuiet { newReader = accountingReader.NewProxyReader(reader) } } else { @@ -175,7 +175,7 @@ func doCopy(cpURLs copyURLs, progressReader *barSend, accountingReader *accounte defer newReader.Close() if err := putTarget(cpURLs.TargetContent.URL.String(), length, newReader); err != nil { - if !globalQuietFlag && !globalJSONFlag { + if !globalQuiet && !globalJSON { progressReader.ErrorPut(length) } cpURLs.Error = err.Trace(cpURLs.TargetContent.URL.String()) @@ -189,7 +189,7 @@ func doCopy(cpURLs copyURLs, progressReader *barSend, accountingReader *accounte // doCopyFake - Perform a fake copy to update the progress bar appropriately. func doCopyFake(cURLs copyURLs, progressReader *barSend) { - if !globalQuietFlag && !globalJSONFlag { + if !globalQuiet && !globalJSON { progressReader.Progress(cURLs.SourceContent.Size) } } @@ -211,7 +211,7 @@ func doPrepareCopyURLs(session *sessionV5, trapCh <-chan bool) { dataFP := session.NewDataWriter() var scanBar scanBarFunc - if !globalQuietFlag && !globalJSONFlag { // set up progress bar + if !globalQuiet && !globalJSON { // set up progress bar scanBar = scanBarFactory() } @@ -227,7 +227,7 @@ func doPrepareCopyURLs(session *sessionV5, trapCh <-chan bool) { } if cpURLs.Error != nil { // Print in new line and adjust to top so that we don't print over the ongoing scan bar - if !globalQuietFlag && !globalJSONFlag { + if !globalQuiet && !globalJSON { console.Eraseline() } if strings.Contains(cpURLs.Error.ToGoError().Error(), " is a folder.") { @@ -244,7 +244,7 @@ func doPrepareCopyURLs(session *sessionV5, trapCh <-chan bool) { fatalIf(probe.NewError(err), "Unable to prepare URL for copying. Error in JSON marshaling.") } fmt.Fprintln(dataFP, string(jsonData)) - if !globalQuietFlag && !globalJSONFlag { + if !globalQuiet && !globalJSON { scanBar(cpURLs.SourceContent.URL.String()) } @@ -252,7 +252,7 @@ func doPrepareCopyURLs(session *sessionV5, trapCh <-chan bool) { totalObjects++ case <-trapCh: // Print in new line and adjust to top so that we don't print over the ongoing scan bar - if !globalQuietFlag && !globalJSONFlag { + if !globalQuiet && !globalJSON { console.Eraseline() } session.Delete() // If we are interrupted during the URL scanning, we drop the session. @@ -276,7 +276,7 @@ func doCopySession(session *sessionV5) { // Enable progress bar reader only during default mode. var progressReader *barSend - if !globalQuietFlag && !globalJSONFlag { // set up progress bar + if !globalQuiet && !globalJSON { // set up progress bar progressReader = newProgressBar(session.Header.TotalBytes) } @@ -302,10 +302,10 @@ func doCopySession(session *sessionV5) { select { case cpURLs, ok := <-statusCh: // Receive status. if !ok { // We are done here. Top level function has returned. - if !globalQuietFlag && !globalJSONFlag { + if !globalQuiet && !globalJSON { progressReader.Finish() } - if globalQuietFlag { + if globalQuiet { accntStat := accntReader.Stat() cpStatMessage := copyStatMessage{ Total: accntStat.Total, @@ -321,7 +321,7 @@ func doCopySession(session *sessionV5) { session.Save() } else { // Print in new line and adjust to top so that we don't print over the ongoing progress bar - if !globalQuietFlag && !globalJSONFlag { + if !globalQuiet && !globalJSON { console.Eraseline() } errorIf(cpURLs.Error.Trace(cpURLs.SourceContent.URL.String()), @@ -342,7 +342,7 @@ func doCopySession(session *sessionV5) { session.CloseAndDie() } case <-trapCh: // Receive interrupt notification. - if !globalQuietFlag && !globalJSONFlag { + if !globalQuiet && !globalJSON { console.Eraseline() } session.CloseAndDie() diff --git a/error.go b/error.go index 3171dd3d..1dce6c8e 100644 --- a/error.go +++ b/error.go @@ -44,7 +44,7 @@ func fatalIf(err *probe.Error, msg string) { if err == nil { return } - if globalJSONFlag { + if globalJSON { errorMsg := errorMessage{ Message: msg, Type: "fatal", @@ -54,7 +54,7 @@ func fatalIf(err *probe.Error, msg string) { }, SysInfo: err.SysInfo, } - if globalDebugFlag { + if globalDebug { errorMsg.CallTrace = err.CallTrace } json, err := json.Marshal(struct { @@ -70,7 +70,7 @@ func fatalIf(err *probe.Error, msg string) { console.Println(string(json)) console.Fatalln() } - if !globalDebugFlag { + if !globalDebug { console.Fatalln(fmt.Sprintf("%s %s", msg, err.ToGoError())) } console.Fatalln(fmt.Sprintf("%s %s", msg, err)) @@ -81,7 +81,7 @@ func errorIf(err *probe.Error, msg string) { if err == nil { return } - if globalJSONFlag { + if globalJSON { errorMsg := errorMessage{ Message: msg, Type: "error", @@ -91,7 +91,7 @@ func errorIf(err *probe.Error, msg string) { }, SysInfo: err.SysInfo, } - if globalDebugFlag { + if globalDebug { errorMsg.CallTrace = err.CallTrace } json, err := json.Marshal(struct { @@ -107,7 +107,7 @@ func errorIf(err *probe.Error, msg string) { console.Println(string(json)) return } - if !globalDebugFlag { + if !globalDebug { console.Errorln(fmt.Sprintf("%s %s", msg, err.ToGoError())) return } diff --git a/globals.go b/globals.go index b9c7a071..d73e572a 100644 --- a/globals.go +++ b/globals.go @@ -17,11 +17,7 @@ // This package contains all the global variables and constants. ONLY TO BE ACCESSED VIA GET/SET FUNCTIONS. package main -var ( - globalQuietFlag = false // Quiet flag set via command line - globalJSONFlag = false // Json flag set via command line - globalDebugFlag = false // Debug flag set via command line -) +import "github.com/minio/mc/pkg/console" // mc configuration related constants. const ( @@ -44,3 +40,29 @@ const ( // default host globalExampleHostURL = "YOUR-EXAMPLE.COM" ) + +var ( + globalQuiet = false // Quiet flag set via command line + globalJSON = false // Json flag set via command line + globalDebug = false // Debug flag set via command line + globalNoColor = false // Debug flag set via command line + // WHEN YOU ADD NEXT GLOBAL FLAG, MAKE SURE TO ALSO UPDATE SESSION CODE AND CODE BELOW. +) + +// Set global states. NOTE: It is deliberately kept monolithic to ensure we dont miss out any flags. +func setGlobals(quiet, debug, json, noColor bool) { + globalQuiet = quiet + globalDebug = debug + globalJSON = json + globalNoColor = noColor + + // Enable debug messages if requested. + if globalDebug == true { + console.DebugPrint = true + } + + // Disable colorified messages if requested. + if globalNoColor == true { + console.SetColorOff() + } +} diff --git a/main.go b/main.go index 23419b62..c25184cb 100644 --- a/main.go +++ b/main.go @@ -24,7 +24,6 @@ import ( "strconv" "github.com/minio/cli" - "github.com/minio/mc/pkg/console" "github.com/minio/minio-xl/pkg/probe" "github.com/minio/pb" "github.com/olekukonko/ts" @@ -110,18 +109,12 @@ func getSystemData() map[string]string { func registerBefore(ctx *cli.Context) error { setMcConfigDir(ctx.GlobalString("config-folder")) - globalQuietFlag = ctx.GlobalBool("quiet") - globalDebugFlag = ctx.GlobalBool("debug") - globalJSONFlag = ctx.GlobalBool("json") - if globalDebugFlag { - console.NoDebugPrint = false - } - - // Disable color themes. - if ctx.GlobalBool("no-color") == true { - console.SetColorOff() - } + // Set global states from global flags. + setGlobals(ctx.GlobalBool("quiet"), + ctx.GlobalBool("debug"), + ctx.GlobalBool("json"), + ctx.GlobalBool("no-color")) // Verify golang runtime. verifyMCRuntime() @@ -190,10 +183,10 @@ func main() { app.ExtraInfo = func() map[string]string { if _, e := ts.GetSize(); e != nil { - globalQuietFlag = true + globalQuiet = true } - if globalDebugFlag { + if globalDebug { return getSystemData() } return make(map[string]string) diff --git a/mc_test.go b/mc_test.go index 8f74223d..022a4cc3 100644 --- a/mc_test.go +++ b/mc_test.go @@ -50,7 +50,7 @@ func (s *TestSuite) SetUpSuite(c *C) { console.IsTesting = true // do not set it elsewhere, leads to data races since this is a global flag - globalQuietFlag = true // quiet is set to turn of progress bar + globalQuiet = true // quiet is set to turn of progress bar tmpDir, e := ioutil.TempDir(os.TempDir(), "cmd-") c.Assert(e, IsNil) diff --git a/mirror-main.go b/mirror-main.go index 6ed8cd03..f8c573af 100644 --- a/mirror-main.go +++ b/mirror-main.go @@ -128,13 +128,13 @@ func doMirror(sURLs mirrorURLs, progressReader *barSend, accountingReader *accou return } - if !globalQuietFlag && !globalJSONFlag { + if !globalQuiet && !globalJSON { progressReader.SetCaption(sURLs.SourceContent.URL.String() + ": ") } reader, length, err := getSource(sURLs.SourceContent.URL.String()) if err != nil { - if !globalQuietFlag && !globalJSONFlag { + if !globalQuiet && !globalJSON { progressReader.ErrorGet(int64(length)) } sURLs.Error = err.Trace(sURLs.SourceContent.URL.String()) @@ -148,15 +148,15 @@ func doMirror(sURLs mirrorURLs, progressReader *barSend, accountingReader *accou } var newReader io.ReadCloser - if globalQuietFlag || globalJSONFlag { + if globalQuiet || globalJSON { printMsg(mirrorMessage{ Source: sURLs.SourceContent.URL.String(), Targets: targetURLs, }) - if globalJSONFlag { + if globalJSON { newReader = reader } - if globalQuietFlag { + if globalQuiet { newReader = accountingReader.NewProxyReader(reader) } } else { @@ -167,7 +167,7 @@ func doMirror(sURLs mirrorURLs, progressReader *barSend, accountingReader *accou err = putTargets(targetURLs, length, newReader) if err != nil { - if !globalQuietFlag && !globalJSONFlag { + if !globalQuiet && !globalJSON { progressReader.ErrorPut(int64(length)) } sURLs.Error = err.Trace(targetURLs...) @@ -181,7 +181,7 @@ func doMirror(sURLs mirrorURLs, progressReader *barSend, accountingReader *accou // doMirrorFake - Perform a fake mirror to update the progress bar appropriately. func doMirrorFake(sURLs mirrorURLs, progressReader *barSend) { - if !globalDebugFlag && !globalJSONFlag { + if !globalDebug && !globalJSON { progressReader.Progress(sURLs.SourceContent.Size) } } @@ -197,7 +197,7 @@ func doPrepareMirrorURLs(session *sessionV5, isForce bool, trapCh <-chan bool) { dataFP := session.NewDataWriter() var scanBar scanBarFunc - if !globalQuietFlag && !globalJSONFlag { // set up progress bar + if !globalQuiet && !globalJSON { // set up progress bar scanBar = scanBarFactory() } @@ -212,7 +212,7 @@ func doPrepareMirrorURLs(session *sessionV5, isForce bool, trapCh <-chan bool) { } if sURLs.Error != nil { // Print in new line and adjust to top so that we don't print over the ongoing scan bar - if !globalQuietFlag && !globalJSONFlag { + if !globalQuiet && !globalJSON { console.Eraseline() } errorIf(sURLs.Error.Trace(), "Unable to prepare URLs for mirroring.") @@ -227,7 +227,7 @@ func doPrepareMirrorURLs(session *sessionV5, isForce bool, trapCh <-chan bool) { fatalIf(probe.NewError(err), "Unable to marshal URLs into JSON.") } fmt.Fprintln(dataFP, string(jsonData)) - if !globalQuietFlag && !globalJSONFlag { + if !globalQuiet && !globalJSON { scanBar(sURLs.SourceContent.URL.String()) } @@ -235,7 +235,7 @@ func doPrepareMirrorURLs(session *sessionV5, isForce bool, trapCh <-chan bool) { totalObjects++ case <-trapCh: // Print in new line and adjust to top so that we don't print over the ongoing scan bar - if !globalQuietFlag && !globalJSONFlag { + if !globalQuiet && !globalJSON { console.Eraseline() } session.Delete() // If we are interrupted during the URL scanning, we drop the session. @@ -261,7 +261,7 @@ func doMirrorSession(session *sessionV5) { // Set up progress bar. var progressReader *barSend - if !globalQuietFlag && !globalJSONFlag { + if !globalQuiet && !globalJSON { progressReader = newProgressBar(session.Header.TotalBytes) } @@ -286,7 +286,7 @@ func doMirrorSession(session *sessionV5) { select { case sURLs, ok := <-statusCh: // Receive status. if !ok { // We are done here. Top level function has returned. - if !globalQuietFlag && !globalJSONFlag { + if !globalQuiet && !globalJSON { progressReader.Finish() } else { accntStat := accntReader.Stat() @@ -304,7 +304,7 @@ func doMirrorSession(session *sessionV5) { session.Save() } else { // Print in new line and adjust to top so that we don't print over the ongoing progress bar - if !globalQuietFlag && !globalJSONFlag { + if !globalQuiet && !globalJSON { console.Eraseline() } errorIf(sURLs.Error.Trace(), fmt.Sprintf("Failed to mirror ā€˜%s’.", sURLs.SourceContent.URL.String())) @@ -325,7 +325,7 @@ func doMirrorSession(session *sessionV5) { } case <-trapCh: // Receive interrupt notification. // Print in new line and adjust to top so that we don't print over the ongoing progress bar - if !globalQuietFlag && !globalJSONFlag { + if !globalQuiet && !globalJSON { console.Eraseline() } session.CloseAndDie() diff --git a/pkg/console/console.go b/pkg/console/console.go index 57f3dd27..f9e8f078 100644 --- a/pkg/console/console.go +++ b/pkg/console/console.go @@ -29,9 +29,9 @@ import ( ) var ( - // NoDebugPrint defines if the input should be printed in debug or not. By default it's set to true. - NoDebugPrint = true - // IsTesting this flag indicates if IsExited should be set or not, false by default. + // DebugPrint enables/disables console debug printing. + DebugPrint = false + // IsTesting this flag indicates if IsExited should be set or not. IsTesting = false // IsExited sets this boolean value if Fatal is called when IsTesting is enabled. IsExited = false @@ -153,21 +153,21 @@ var ( // Debug prints a debug message without a new line // Debug prints a debug message. Debug = func(data ...interface{}) { - if !NoDebugPrint { + if !DebugPrint { consolePrint("Debug", Theme["Debug"], data...) } } // Debugf prints a debug message with a new line. Debugf = func(format string, data ...interface{}) { - if !NoDebugPrint { + if !DebugPrint { consolePrintf("Debug", Theme["Debug"], format, data...) } } // Debugln prints a debug message with a new line. Debugln = func(data ...interface{}) { - if !NoDebugPrint { + if !DebugPrint { consolePrintln("Debug", Theme["Debug"], data...) } } diff --git a/print.go b/print.go index 240d1eeb..49b3207c 100644 --- a/print.go +++ b/print.go @@ -26,7 +26,7 @@ type message interface { // printMsg prints message string or JSON structure depending on the type of output console. func printMsg(msg message) { - if !globalJSONFlag { + if !globalJSON { console.Println(msg.String()) } else { console.Println(msg.JSON()) diff --git a/session-main.go b/session-main.go index 4092d7bc..5870e917 100644 --- a/session-main.go +++ b/session-main.go @@ -230,7 +230,7 @@ func mainSession(ctx *cli.Context) { fatalIf(errDummy().Trace(), "Loaded session is nil.") // Restore the state of global variables from this previous session. - s.RestoreGlobals() + s.restoreGlobals() savedCwd, e := os.Getwd() fatalIf(probe.NewError(e), "Unable to determine current working folder.") diff --git a/session-v5.go b/session-v5.go index c2165abc..e67a565a 100644 --- a/session-v5.go +++ b/session-v5.go @@ -127,6 +127,50 @@ func (s sessionV5) JSON() string { return string(sessionBytes) } +// loadSessionV5 - reads session file if exists and re-initiates internal variables +func loadSessionV5(sid string) (*sessionV5, *probe.Error) { + if !isSessionDirExists() { + return nil, errInvalidArgument().Trace() + } + sessionFile, err := getSessionFile(sid) + if err != nil { + return nil, err.Trace(sid) + } + + if _, err := os.Stat(sessionFile); err != nil { + return nil, probe.NewError(err) + } + + s := &sessionV5{} + s.Header = &sessionV5Header{} + s.SessionID = sid + s.Header.Version = "5" + qs, err := quick.New(s.Header) + if err != nil { + return nil, err.Trace(sid, s.Header.Version) + } + err = qs.Load(sessionFile) + if err != nil { + return nil, err.Trace(sid, s.Header.Version) + } + + s.mutex = new(sync.Mutex) + s.Header = qs.Data().(*sessionV5Header) + + sessionDataFile, err := getSessionDataFile(s.SessionID) + if err != nil { + return nil, err.Trace(sid, s.Header.Version) + } + + var e error + dataFile, e := os.Open(sessionDataFile) + fatalIf(probe.NewError(e), "Unable to open session data file \""+sessionDataFile+"\".") + + s.DataFP = &sessionDataFP{false, dataFile} + + return s, nil +} + // newSessionV5 provides a new session. func newSessionV5() *sessionV5 { s := &sessionV5{} @@ -151,6 +195,10 @@ func newSessionV5() *sessionV5 { fatalIf(probe.NewError(e), "Unable to create session data file \""+sessionDataFile+"\".") s.DataFP = &sessionDataFP{false, dataFile} + + // Capture state of global flags. + s.setGlobals() + return s } @@ -200,11 +248,23 @@ func (s *sessionV5) Save() *probe.Error { return qs.Save(sessionFile).Trace(sessionFile) } +// setGlobals captures the state of global variables into session header. +// Used by newSession. +func (s *sessionV5) setGlobals() { + s.Header.GlobalBoolFlags["quiet"] = globalQuiet + s.Header.GlobalBoolFlags["debug"] = globalDebug + s.Header.GlobalBoolFlags["json"] = globalJSON + s.Header.GlobalBoolFlags["noColor"] = globalNoColor +} + // RestoreGlobals restores the state of global variables. -func (s *sessionV5) RestoreGlobals() { - globalQuietFlag = s.Header.GlobalBoolFlags["quiet"] - globalJSONFlag = s.Header.GlobalBoolFlags["json"] - globalDebugFlag = s.Header.GlobalBoolFlags["debug"] +// Used by resumeSession. +func (s sessionV5) restoreGlobals() { + quiet := s.Header.GlobalBoolFlags["quiet"] + debug := s.Header.GlobalBoolFlags["debug"] + json := s.Header.GlobalBoolFlags["json"] + noColor := s.Header.GlobalBoolFlags["noColor"] + setGlobals(quiet, debug, json, noColor) } // Close ends this session and removes all associated session files. @@ -265,50 +325,6 @@ func (s sessionV5) CloseAndDie() { os.Exit(0) } -// loadSessionV5 - reads session file if exists and re-initiates internal variables -func loadSessionV5(sid string) (*sessionV5, *probe.Error) { - if !isSessionDirExists() { - return nil, errInvalidArgument().Trace() - } - sessionFile, err := getSessionFile(sid) - if err != nil { - return nil, err.Trace(sid) - } - - if _, err := os.Stat(sessionFile); err != nil { - return nil, probe.NewError(err) - } - - s := &sessionV5{} - s.Header = &sessionV5Header{} - s.SessionID = sid - s.Header.Version = "5" - qs, err := quick.New(s.Header) - if err != nil { - return nil, err.Trace(sid, s.Header.Version) - } - err = qs.Load(sessionFile) - if err != nil { - return nil, err.Trace(sid, s.Header.Version) - } - - s.mutex = new(sync.Mutex) - s.Header = qs.Data().(*sessionV5Header) - - sessionDataFile, err := getSessionDataFile(s.SessionID) - if err != nil { - return nil, err.Trace(sid, s.Header.Version) - } - - var e error - dataFile, e := os.Open(sessionDataFile) - fatalIf(probe.NewError(e), "Unable to open session data file \""+sessionDataFile+"\".") - - s.DataFP = &sessionDataFP{false, dataFile} - - return s, nil -} - // Create a factory function to simplify checking if an // object has been copied or not. // isCopied(URL) -> true or false