From 4d8b9038f2bc1a2980bf3199dcb12c856e06f87c Mon Sep 17 00:00:00 2001 From: yangpeng Date: Tue, 17 Oct 2023 17:13:30 +0800 Subject: [PATCH] add only show errors option --- lib/command.go | 5 +- lib/command_manager.go | 8 +- lib/const.go | 1 + lib/cp.go | 52 +++-- lib/cp_test.go | 464 +++++++++++++++++++++++++++++++++++++ lib/object_tagging.go | 11 +- lib/object_tagging_test.go | 254 ++++++++++++++++++++ lib/option.go | 3 + lib/restore.go | 21 +- lib/restore_test.go | 207 +++++++++++++++++ lib/rm.go | 20 +- lib/rm_test.go | 76 ++++++ lib/set_acl.go | 11 +- lib/set_acl_test.go | 62 +++++ lib/set_meta.go | 11 +- lib/set_meta_test.go | 91 ++++++++ lib/sync.go | 2 +- lib/sync_test.go | 82 +++++++ 18 files changed, 1341 insertions(+), 40 deletions(-) diff --git a/lib/command.go b/lib/command.go index 7777bb73..df6a02b9 100644 --- a/lib/command.go +++ b/lib/command.go @@ -772,7 +772,10 @@ func (cmd *Command) updateMonitor(err error, monitor *Monitor) { } else { monitor.updateErrNum(1) } - fmt.Printf(monitor.progressBar(false, normalExit)) + onlyShowErrors, _ := GetBool(OptionOnlyShowErrors, cmd.options) + if !onlyShowErrors { + fmt.Printf(monitor.progressBar(false, normalExit)) + } } func (cmd *Command) report(msg string, err error, option *batchOptionType) { diff --git a/lib/command_manager.go b/lib/command_manager.go index f50baa2e..f59d58f1 100644 --- a/lib/command_manager.go +++ b/lib/command_manager.go @@ -59,9 +59,13 @@ func ParseAndRunCommand() error { LogError("%s.\n", err.Error()) return err } + onlyShowErrors, _ := GetBool(OptionOnlyShowErrors, options) if showElapse { - te := time.Now().UnixNano() - fmt.Printf("\n%.6f(s) elapsed\n", float64(te-ts)/1e9) + if !onlyShowErrors { + te := time.Now().UnixNano() + fmt.Printf("\n%.6f(s) elapsed\n", float64(te-ts)/1e9) + } + return nil } return nil diff --git a/lib/const.go b/lib/const.go index 9d015044..7f7ee860 100644 --- a/lib/const.go +++ b/lib/const.go @@ -105,6 +105,7 @@ const ( OptionCloudBoxID = "cloudBoxID" OptionQueryParam = "queryParam" OptionForcePathStyle = "forcePathStyle" + OptionOnlyShowErrors = "onlyShowErrors" ) // the elements show in stat object diff --git a/lib/cp.go b/lib/cp.go index 23eb1306..17548405 100644 --- a/lib/cp.go +++ b/lib/cp.go @@ -61,6 +61,7 @@ type copyOptionType struct { onlyCurrentDir bool disableDirObject bool disableAllSymlink bool + onlyShowErrors bool tagging string opType operationType bSyncCommand bool @@ -1295,6 +1296,7 @@ var copyCommand = CopyCommand{ OptionRegion, OptionCloudBoxID, OptionForcePathStyle, + OptionOnlyShowErrors, }, }, } @@ -1340,6 +1342,7 @@ func (cc *CopyCommand) RunCommand() error { cc.cpOption.onlyCurrentDir, _ = GetBool(OptionOnlyCurrentDir, cc.command.options) cc.cpOption.disableDirObject, _ = GetBool(OptionDisableDirObject, cc.command.options) cc.cpOption.disableAllSymlink, _ = GetBool(OptionDisableAllSymlink, cc.command.options) + cc.cpOption.onlyShowErrors, _ = GetBool(OptionOnlyShowErrors, cc.command.options) if cc.cpOption.enableSymlinkDir && cc.cpOption.disableAllSymlink { return fmt.Errorf("--enable-symlink-dir and --disable-all-symlink can't be both exist") @@ -1495,7 +1498,9 @@ func (cc *CopyCommand) RunCommand() error { endT := time.Now().UnixNano() / 1000 / 1000 if endT-startT > 0 { averSpeed := (cc.monitor.transferSize / (endT - startT)) * 1000 - fmt.Printf("\naverage speed %d(byte/s)\n", averSpeed) + if !cc.cpOption.onlyShowErrors { + fmt.Printf("\naverage speed %d(byte/s)\n", averSpeed) + } LogInfo("average speed %d(byte/s)\n", averSpeed) } @@ -1593,7 +1598,9 @@ func (cc *CopyCommand) checkCopyOptions(opType operationType) error { func (cc *CopyCommand) progressBar() { // fetch all reveal for signal := range chProgressSignal { - fmt.Printf(cc.monitor.progressBar(signal.finish, signal.exitStat)) + if !cc.cpOption.onlyShowErrors { + fmt.Printf(cc.monitor.progressBar(signal.finish, signal.exitStat)) + } } } @@ -1651,14 +1658,18 @@ func (cc *CopyCommand) uploadFiles(srcURLList []StorageURLer, destURL CloudURL) } else { if !cc.cpOption.ctnu { cc.closeProgress() - fmt.Printf(cc.monitor.progressBar(true, errExit)) + if !cc.cpOption.onlyShowErrors { + fmt.Printf(cc.monitor.progressBar(true, errExit)) + } return err } } } } cc.closeProgress() - fmt.Printf(cc.monitor.progressBar(true, normalExit)) + if !cc.cpOption.onlyShowErrors { + fmt.Printf(cc.monitor.progressBar(true, normalExit)) + } return listError } @@ -2379,7 +2390,9 @@ func (cc *CopyCommand) downloadFiles(srcURL CloudURL, destURL FileURL) error { func (cc *CopyCommand) formatResultPrompt(err error) error { cc.closeProgress() - fmt.Printf(cc.monitor.progressBar(true, normalExit)) + if !cc.cpOption.onlyShowErrors { + fmt.Printf(cc.monitor.progressBar(true, normalExit)) + } if err != nil && cc.cpOption.ctnu { return nil } @@ -2565,8 +2578,10 @@ func (cc *CopyCommand) ossDownloadFileRetry(bucket *oss.Bucket, objectName, file for i := 1; ; i++ { if i > 1 { time.Sleep(time.Duration(3) * time.Second) - if int64(i) >= retryTimes { - fmt.Printf("\nretry count:%d:get object to file:%s.\n", i-1, fileName) + if !cc.cpOption.onlyShowErrors { + if int64(i) >= retryTimes { + fmt.Printf("\nretry count:%d:get object to file:%s.\n", i-1, fileName) + } } } @@ -2595,8 +2610,10 @@ func (cc *CopyCommand) ossResumeDownloadRetry(bucket *oss.Bucket, objectName str for i := 1; ; i++ { if i > 1 { time.Sleep(time.Duration(3) * time.Second) - if int64(i) >= retryTimes { - fmt.Printf("\nretry count:%d:mulitpart download file:%s.\n", i-1, objectName) + if !cc.cpOption.onlyShowErrors { + if int64(i) >= retryTimes { + fmt.Printf("\nretry count:%d:mulitpart download file:%s.\n", i-1, objectName) + } } } @@ -2853,7 +2870,9 @@ func (cc *CopyCommand) waitRoutinueComplete(chError, chListError <-chan error, o ferr = err if !cc.cpOption.ctnu { cc.closeProgress() - fmt.Printf(cc.monitor.progressBar(true, errExit)) + if !cc.cpOption.onlyShowErrors { + fmt.Printf(cc.monitor.progressBar(true, errExit)) + } return err } } @@ -3018,8 +3037,10 @@ func (cc *CopyCommand) ossCopyObjectRetry(bucket *oss.Bucket, objectName, destBu for i := 1; ; i++ { if i > 1 { time.Sleep(time.Duration(3) * time.Second) - if int64(i) >= retryTimes { - fmt.Printf("\nretry count:%d,copy object:%s.\n", i-1, objectName) + if !cc.cpOption.onlyShowErrors { + if int64(i) >= retryTimes { + fmt.Printf("\nretry count:%d,copy object:%s.\n", i-1, objectName) + } } } _, err := bucket.CopyObjectTo(destBucketName, destObjectName, objectName, options...) @@ -3045,9 +3066,12 @@ func (cc *CopyCommand) ossResumeCopyRetry(bucketName, objectName, destBucketName for i := 1; ; i++ { if i > 1 { time.Sleep(time.Duration(3) * time.Second) - if int64(i) >= retryTimes { - fmt.Printf("\nretry count:%d, resume copy object:%s.\n", i-1, objectName) + if !cc.cpOption.onlyShowErrors { + if int64(i) >= retryTimes { + fmt.Printf("\nretry count:%d, resume copy object:%s.\n", i-1, objectName) + } } + } err := bucket.CopyFile(bucketName, objectName, destObjectName, partSize, options...) diff --git a/lib/cp_test.go b/lib/cp_test.go index 7875f8c4..26751992 100644 --- a/lib/cp_test.go +++ b/lib/cp_test.go @@ -6120,3 +6120,467 @@ func (s *OssutilCommandSuite) TestCloudBoxCreateAndDeleteBucket(c *C) { os.Remove(fileName) s.removeBucket(bucketName, true, c) } + +func (s *OssutilCommandSuite) TestCpCmdUpload(c *C) { + bucketName := bucketNamePrefix + randLowStr(10) + s.putBucket(bucketName, c) + + objectContent := randLowStr(1024 * 10) + fileName := "ossutil_test." + randLowStr(12) + s.createFile(fileName, objectContent, c) + cpFile := "ossutil_cp." + randLowStr(5) + + object := randLowStr(12) + out = os.Stdout + + os.Args = []string{"", "cp", fileName, CloudURLToString(bucketName, object), "-f", "--config-file=" + configFile} + var outFile *os.File + outFile, _ = os.OpenFile(cpFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + err := ParseAndRunCommand() + os.Stdout = out + c.Assert(err, IsNil) + outPut := s.readFile(cpFile, c) + testLogger.Println(outPut) + c.Assert(strings.Contains(outPut, "elapsed"), Equals, true) + c.Assert(strings.Contains(outPut, "Succeed"), Equals, true) + os.Remove(cpFile) +} + +func (s *OssutilCommandSuite) TestCpCmdCpObject(c *C) { + bucketName := bucketNamePrefix + randLowStr(10) + s.putBucket(bucketName, c) + + objectContent := randLowStr(1024 * 10) + fileName := "ossutil_test." + randLowStr(12) + s.createFile(fileName, objectContent, c) + cpFile := "ossutil_cp." + randLowStr(5) + object := randLowStr(12) + s.putObject(bucketName, object, fileName, c) + + out = os.Stdout + os.Args = []string{"", "cp", CloudURLToString(bucketName, object), CloudURLToString(bucketNameExist, object), "-f", "--config-file=" + configFile} + outFile, _ := os.OpenFile(cpFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + outFile = os.Stdout + err := ParseAndRunCommand() + os.Stdout = out + c.Assert(err, IsNil) + outPut := s.readFile(cpFile, c) + testLogger.Println(outPut) + c.Assert(strings.Contains(outPut, "elapsed"), Equals, true) + c.Assert(strings.Contains(outPut, "Succeed"), Equals, true) + os.Remove(cpFile) +} + +func (s *OssutilCommandSuite) TestCpCmdDownload(c *C) { + bucketName := bucketNamePrefix + randLowStr(10) + s.putBucket(bucketName, c) + objectContent := randLowStr(1024 * 10) + fileName := "ossutil_test." + randLowStr(12) + s.createFile(fileName, objectContent, c) + cpFile := "ossutil_cp." + randLowStr(5) + object := randLowStr(12) + s.putObject(bucketName, object, fileName, c) + + out = os.Stdout + downloadFileName = "ossutil_test_down." + randLowStr(12) + os.Args = []string{"", "cp", CloudURLToString(bucketName, object), downloadFileName, "-f", "--config-file=" + configFile} + var outFile *os.File + outFile, _ = os.OpenFile(cpFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + err := ParseAndRunCommand() + os.Stdout = out + c.Assert(err, IsNil) + outPut := s.readFile(cpFile, c) + testLogger.Println(outPut) + c.Assert(strings.Contains(outPut, "elapsed"), Equals, true) + c.Assert(strings.Contains(outPut, "Succeed"), Equals, true) + os.Remove(cpFile) +} + +func (s *OssutilCommandSuite) TestCpCmdError(c *C) { + bucketName := bucketNamePrefix + randLowStr(10) + s.putBucket(bucketName, c) + + fileName := "not_exist_file" + object := randLowStr(12) + out = os.Stdout + + os.Args = []string{"", "cp", fileName, CloudURLToString(bucketName, object), "-f", "--config-file=" + configFile} + var outFile *os.File + os.Stdout = outFile + err := ParseAndRunCommand() + os.Stdout = out + c.Assert(err, NotNil) +} + +func (s *OssutilCommandSuite) TestCpCmdCpObjectError(c *C) { + bucketName := bucketNamePrefix + randLowStr(10) + s.putBucket(bucketName, c) + + object := "not_exist_object" + out = os.Stdout + os.Args = []string{"", "cp", CloudURLToString(bucketName, object), CloudURLToString(bucketNameExist, object), "-f", "--config-file=" + configFile} + err := ParseAndRunCommand() + os.Stdout = out + c.Assert(err, NotNil) +} + +func (s *OssutilCommandSuite) TestCpCmdDownloadError(c *C) { + downloadFileName = "ossutil_test_down." + randLowStr(12) + bucketName := bucketNamePrefix + randLowStr(10) + s.putBucket(bucketName, c) + object := "not_exist_object" + out = os.Stdout + os.Args = []string{"", "cp", CloudURLToString(bucketName, object), CloudURLToString(bucketNameExist, object), "-f", "--config-file=" + configFile} + err := ParseAndRunCommand() + os.Stdout = out + c.Assert(err, NotNil) +} + +func (s *OssutilCommandSuite) TestCpCmdUploadWithOnlyShowErrors(c *C) { + bucketName := bucketNamePrefix + randLowStr(10) + s.putBucket(bucketName, c) + objectContent := randLowStr(1024 * 10) + fileName := "ossutil_test." + randLowStr(12) + s.createFile(fileName, objectContent, c) + cpFile := "ossutil_cp." + randLowStr(5) + + object := randLowStr(12) + out = os.Stdout + + os.Args = []string{"", "cp", fileName, CloudURLToString(bucketName, object), "-f", "--only-show-errors", "--config-file=" + configFile} + var outFile *os.File + outFile, _ = os.OpenFile(cpFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + err := ParseAndRunCommand() + os.Stdout = out + c.Assert(err, IsNil) + outPut := s.readFile(cpFile, c) + testLogger.Println(outPut) + c.Assert(outPut == "", Equals, true) + os.Remove(cpFile) +} + +func (s *OssutilCommandSuite) TestCpCmdUploadErrorWithOnlyShowErrors(c *C) { + bucketName := bucketNamePrefix + randLowStr(10) + s.putBucket(bucketName, c) + fileName := "not_exist_file" + object := randLowStr(12) + os.Args = []string{"", "cp", fileName, CloudURLToString(bucketName, object), "-f", "--only-show-errors", "--config-file=" + configFile} + err := ParseAndRunCommand() + c.Assert(err, NotNil) +} + +func (s *OssutilCommandSuite) TestCpCmdCpObjectWithOnlyShowErrors(c *C) { + bucketName := bucketNamePrefix + randLowStr(10) + s.putBucket(bucketName, c) + + objectContent := randLowStr(1024 * 10) + fileName := "ossutil_test." + randLowStr(12) + s.createFile(fileName, objectContent, c) + cpFile := "ossutil_cp." + randLowStr(5) + object := randLowStr(12) + s.putObject(bucketName, object, fileName, c) + + out = os.Stdout + os.Args = []string{"", "cp", CloudURLToString(bucketName, object), CloudURLToString(bucketNameExist, object), "-f", "--only-show-errors", "--config-file=" + configFile} + outFile, _ := os.OpenFile(cpFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + outFile = os.Stdout + err := ParseAndRunCommand() + os.Stdout = out + c.Assert(err, IsNil) + outPut := s.readFile(cpFile, c) + testLogger.Println(outPut) + c.Assert(outPut == "", Equals, true) + os.Remove(cpFile) +} + +func (s *OssutilCommandSuite) TestCpCmdDownloadWithOnlyShowErrors(c *C) { + bucketName := bucketNamePrefix + randLowStr(10) + s.putBucket(bucketName, c) + objectContent := randLowStr(1024 * 10) + fileName := "ossutil_test." + randLowStr(12) + s.createFile(fileName, objectContent, c) + cpFile := "ossutil_cp." + randLowStr(5) + object := randLowStr(12) + s.putObject(bucketName, object, fileName, c) + + out = os.Stdout + downloadFileName = "ossutil_test_down." + randLowStr(12) + os.Args = []string{"", "cp", CloudURLToString(bucketName, object), downloadFileName, "-f", "--only-show-errors", "--config-file=" + configFile} + var outFile *os.File + outFile, _ = os.OpenFile(cpFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + err := ParseAndRunCommand() + os.Stdout = out + c.Assert(err, IsNil) + outPut := s.readFile(cpFile, c) + testLogger.Println(outPut) + c.Assert(outPut == "", Equals, true) + os.Remove(cpFile) +} + +func (s *OssutilCommandSuite) TestCpCmdDownloadWithOnlyShowErrors2(c *C) { + bucketName := bucketNamePrefix + randLowStr(10) + s.putBucket(bucketName, c) + objectContent := randLowStr(1024 * 10) + fileName := "ossutil_test." + randLowStr(12) + s.createFile(fileName, objectContent, c) + cpFile := "ossutil_cp." + randLowStr(5) + object := randLowStr(12) + s.putObject(bucketName, object, fileName, c) + + out = os.Stdout + downloadFileName = "ossutil_test_down." + randLowStr(12) + os.Args = []string{"", "cp", fileName, CloudURLToString(bucketName, object), "--only-show-errors", "--config-file=" + configFile} + var outFile *os.File + outFile, _ = os.OpenFile(cpFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + err := ParseAndRunCommand() + os.Stdout = out + c.Assert(err, IsNil) + outPut := s.readFile(cpFile, c) + testLogger.Println(outPut) + //c.Assert(outPut == "", Equals, true) + os.Remove(cpFile) + + str := "" + cpDir := CheckpointDir + isTrue := true + routines := strconv.Itoa(Routines) + options := OptionMapType{ + "endpoint": &str, + "accessKeyID": &str, + "accessKeySecret": &str, + "configFile": &configFile, + "checkpointDir": &cpDir, + "routines": &routines, + "skipVerifyCert": &str, + } + options[OptionForce] = &isTrue + cpArgs := []string{fileName, CloudURLToString(bucketName, object)} + outFile, _ = os.OpenFile(cpFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + _, err = cm.RunCommand("cp", cpArgs, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut = s.readFile(cpFile, c) + testLogger.Println(outPut) + c.Assert(strings.Contains(outPut, "Succeed"), Equals, true) + os.Remove(cpFile) +} + +func (s *OssutilCommandSuite) TestCpCmdWithOnlyShowErrors(c *C) { + bucketName := bucketNamePrefix + randLowStr(10) + s.putBucket(bucketName, c) + objectContent := randLowStr(10) + fileName := "ossutil_test." + randLowStr(12) + s.createFile(fileName, objectContent, c) + cpFile := "ossutil_cp." + randLowStr(5) + object := randLowStr(12) + + str := "" + cpDir := CheckpointDir + isTrue := true + //isFalse := false + routines := strconv.Itoa(Routines) + options := OptionMapType{ + "endpoint": &str, + "accessKeyID": &str, + "accessKeySecret": &str, + "configFile": &configFile, + "checkpointDir": &cpDir, + "routines": &routines, + "skipVerifyCert": &str, + } + + cpArgs := []string{fileName, CloudURLToString(bucketName, object)} + var outFile *os.File + outFile, _ = os.OpenFile(cpFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + _, err := cm.RunCommand("cp", cpArgs, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut := s.readFile(cpFile, c) + testLogger.Println(outPut) + c.Assert(strings.Contains(outPut, "Succeed"), Equals, true) + os.Remove(cpFile) + s.getObject(bucketName, object, downloadFileName, c) + os.Remove(downloadFileName) + + options[OptionForce] = &isTrue + options[OptionOnlyShowErrors] = &isTrue + cpArgs = []string{fileName, CloudURLToString("demo-walker-6961", object)} + outFile, _ = os.OpenFile(cpFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + + _, err = cm.RunCommand("cp", cpArgs, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut = s.readFile(cpFile, c) + testLogger.Println(outPut) + c.Assert(outPut == "", Equals, true) + os.Remove(cpFile) + s.getObject(bucketName, object, downloadFileName, c) + os.Remove(downloadFileName) + + fileName2 := "ossutil_test2." + randLowStr(12) + objectContent2 := randLowStr(1024*10) + "2" + s.createFile(fileName2, objectContent2, c) + delete(options, OptionForce) + cpArgs = []string{fileName2, CloudURLToString(bucketName, object)} + outFile, _ = os.OpenFile(cpFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + _, err = cm.RunCommand("cp", cpArgs, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut = s.readFile(cpFile, c) + testLogger.Println(outPut) + c.Assert(strings.Contains(outPut, "cp: overwrite"), Equals, true) + os.Remove(cpFile) + + s.getObject(bucketName, object, downloadFileName, c) + downloadContent := s.readFile(downloadFileName, c) + c.Assert(downloadContent, Equals, objectContent) + os.Remove(downloadFileName) + os.Remove(fileName2) + options[OptionForce] = &isTrue + s.createFile(fileName2, objectContent2, c) + cpArgs = []string{fileName2, CloudURLToString(bucketName, object)} + outFile, _ = os.OpenFile(cpFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + _, err = cm.RunCommand("cp", cpArgs, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut = s.readFile(cpFile, c) + testLogger.Println(outPut) + c.Assert(outPut == "", Equals, true) + os.Remove(cpFile) + + s.getObject(bucketName, object, downloadFileName, c) + downloadContent = s.readFile(downloadFileName, c) + c.Assert(downloadContent, Equals, objectContent2) + os.Remove(downloadFileName) + os.Remove(fileName2) + + out = os.Stdout + downloadFileName = "ossutil_test_down." + randLowStr(12) + delete(options, OptionForce) + delete(options, OptionOnlyShowErrors) + cpArgs = []string{CloudURLToString(bucketName, object), downloadFileName} + outFile, _ = os.OpenFile(cpFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + _, err = cm.RunCommand("cp", cpArgs, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut = s.readFile(cpFile, c) + testLogger.Println(outPut) + c.Assert(strings.Contains(outPut, "Succeed"), Equals, true) + downloadOut := s.readFile(downloadFileName, c) + c.Assert(downloadOut, Equals, objectContent2) + os.Remove(cpFile) + + os.Remove(downloadFileName) + s.createFile(downloadFileName, content, c) + out = os.Stdout + options[OptionOnlyShowErrors] = &isTrue + cpArgs = []string{CloudURLToString(bucketName, object), downloadFileName} + outFile, _ = os.OpenFile(cpFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + _, err = cm.RunCommand("cp", cpArgs, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut = s.readFile(cpFile, c) + testLogger.Println(outPut) + c.Assert(strings.Contains(outPut, "cp: overwrite"), Equals, true) + downloadOut = s.readFile(downloadFileName, c) + c.Assert(downloadOut, Equals, content) + os.Remove(cpFile) + + out = os.Stdout + options[OptionForce] = &isTrue + cpArgs = []string{CloudURLToString(bucketName, object), downloadFileName} + outFile, _ = os.OpenFile(cpFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + _, err = cm.RunCommand("cp", cpArgs, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut = s.readFile(cpFile, c) + testLogger.Println(outPut) + c.Assert(outPut == "", Equals, true) + downloadOut = s.readFile(downloadFileName, c) + c.Assert(downloadOut, Equals, objectContent2) + os.Remove(cpFile) + + out = os.Stdout + delete(options, OptionForce) + delete(options, OptionOnlyShowErrors) + cpArgs = []string{CloudURLToString(bucketName, object), CloudURLToString(bucketNameExist, object)} + outFile, _ = os.OpenFile(cpFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + _, err = cm.RunCommand("cp", cpArgs, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut = s.readFile(cpFile, c) + testLogger.Println(outPut) + c.Assert(strings.Contains(outPut, "Succeed"), Equals, true) + os.Remove(cpFile) + + out = os.Stdout + options[OptionOnlyShowErrors] = &isTrue + cpArgs = []string{CloudURLToString(bucketName, object), CloudURLToString(bucketNameExist, object)} + outFile, _ = os.OpenFile(cpFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + _, err = cm.RunCommand("cp", cpArgs, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut = s.readFile(cpFile, c) + testLogger.Println(outPut) + c.Assert(strings.Contains(outPut, "cp: overwrite"), Equals, true) + os.Remove(cpFile) + + s.getObject(bucketNameExist, object, downloadFileName, c) + downloadContent = s.readFile(downloadFileName, c) + c.Assert(downloadContent, Equals, objectContent2) + os.Remove(downloadFileName) + + s.createFile(downloadFileName, content, c) + s.putObject(bucketNameExist, object, uploadFileName, c) + out = os.Stdout + options[OptionForce] = &isTrue + cpArgs = []string{CloudURLToString(bucketName, object), CloudURLToString(bucketNameExist, object)} + outFile, _ = os.OpenFile(cpFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + _, err = cm.RunCommand("cp", cpArgs, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut = s.readFile(cpFile, c) + testLogger.Println(outPut) + c.Assert(outPut == "", Equals, true) + s.getObject(bucketNameExist, object, downloadFileName, c) + downloadContent = s.readFile(downloadFileName, c) + c.Assert(downloadContent, Equals, objectContent2) + os.Remove(downloadFileName) + os.Remove(cpFile) +} diff --git a/lib/object_tagging.go b/lib/object_tagging.go index b4855628..5b025ed6 100644 --- a/lib/object_tagging.go +++ b/lib/object_tagging.go @@ -159,6 +159,7 @@ var objectTagCommand = ObjectTagCommand{ OptionRegion, OptionCloudBoxID, OptionForcePathStyle, + OptionOnlyShowErrors, }, }, } @@ -186,7 +187,7 @@ func (otc *ObjectTagCommand) RunCommand() error { if err != nil { return err } - + otc.reportOption.onlyShowErrors, _ = GetBool(OptionOnlyShowErrors, otc.command.options) strMethod, _ := GetString(OptionMethod, otc.command.options) if strMethod == "" { return fmt.Errorf("--method value is empty") @@ -351,7 +352,9 @@ func (otc *ObjectTagCommand) waitRoutinueComplete(chError, chListError <-chan er } else { ferr = err if !otc.reportOption.ctnu { - fmt.Printf(otc.monitor.progressBar(true, errExit)) + if !otc.reportOption.onlyShowErrors { + fmt.Printf(otc.monitor.progressBar(true, errExit)) + } return err } } @@ -362,7 +365,9 @@ func (otc *ObjectTagCommand) waitRoutinueComplete(chError, chListError <-chan er func (otc *ObjectTagCommand) formatResultPrompt(err error) error { if otc.method != "get" { - fmt.Printf(otc.monitor.progressBar(true, normalExit)) + if !otc.reportOption.onlyShowErrors { + fmt.Printf(otc.monitor.progressBar(true, normalExit)) + } } if err != nil && otc.reportOption.ctnu { diff --git a/lib/object_tagging_test.go b/lib/object_tagging_test.go index 364c3ae4..be9e8aa5 100644 --- a/lib/object_tagging_test.go +++ b/lib/object_tagging_test.go @@ -366,6 +366,260 @@ func (s *OssutilCommandSuite) TestObjectTaggingPayer(c *C) { os.Remove(fileName) } +func (s *OssutilCommandSuite) TestObjectTaggingSingleOperationPutWithOnlyShowErrors(c *C) { + bucketName := bucketNamePrefix + randLowStr(12) + s.putBucket(bucketName, c) + + fileName := "ossutil-test-file-" + randLowStr(5) + textBuffer := randStr(100) + s.createFile(fileName, textBuffer, c) + + object := "ossutil-test-object-" + randLowStr(5) + s.putObject(bucketName, object, fileName, c) + + // put tag + out = os.Stdout + ogFile := "ossutil_object_tagging." + randLowStr(5) + tagInfo := "key1#value1" + os.Args = []string{"", "object-tagging", "--method", "put", CloudURLToString(bucketName, object), tagInfo, "--only-show-errors", "--config-file=" + configFile} + var outFile *os.File + outFile, _ = os.OpenFile(ogFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + err := ParseAndRunCommand() + os.Stdout = out + c.Assert(err, IsNil) + outPut := s.readFile(ogFile, c) + testLogger.Println(outPut) + c.Assert(outPut == "", Equals, true) + os.Remove(ogFile) + + os.Remove(fileName) + + var str string + strMethod := "put" + recursive := true + routines := strconv.Itoa(Routines) + options := OptionMapType{ + "endpoint": &str, + "accessKeyID": &str, + "accessKeySecret": &str, + "stsToken": &str, + "configFile": &configFile, + "method": &strMethod, + "recursive": &recursive, + "routines": &routines, + } + + // get tag + resultfileName := "ossutil-test-result-" + randLowStr(5) + testResultFile, _ = os.OpenFile(resultfileName, os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0664) + oldStdout := os.Stdout + os.Stdout = testResultFile + + strMethod = "get" + tagArgs := []string{CloudURLToString(bucketName, "")} + _, err = cm.RunCommand("object-tagging", tagArgs, options) + c.Assert(err, IsNil) + os.Stdout = oldStdout + testResultFile.Close() + + // check file content + catBody := s.readFile(resultfileName, c) + c.Assert(strings.Contains(catBody, "key1"), Equals, true) + c.Assert(strings.Contains(catBody, "value1"), Equals, true) + + s.removeBucket(bucketName, true, c) +} + +func (s *OssutilCommandSuite) TestObjectTaggingSingleOperationDeleteWithOnlyShowErrors(c *C) { + bucketName := bucketNamePrefix + randLowStr(12) + s.putBucket(bucketName, c) + + fileName := "ossutil-test-file-" + randLowStr(5) + textBuffer := randStr(100) + s.createFile(fileName, textBuffer, c) + + object := "ossutil-test-object-" + randLowStr(5) + s.putObject(bucketName, object, fileName, c) + + // delete tag + out = os.Stdout + ogFile := "ossutil_object_tagging." + randLowStr(5) + tagInfo := "key1#value1" + os.Args = []string{"", "object-tagging", "--method", "delete", CloudURLToString(bucketName, object), tagInfo, "--only-show-errors", "--config-file=" + configFile} + var outFile *os.File + outFile, _ = os.OpenFile(ogFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + err := ParseAndRunCommand() + os.Stdout = out + c.Assert(err, IsNil) + outPut := s.readFile(ogFile, c) + testLogger.Println(outPut) + c.Assert(outPut == "", Equals, true) + os.Remove(ogFile) + os.Remove(fileName) + s.removeBucket(bucketName, true, c) +} + +func (s *OssutilCommandSuite) TestObjectTaggingBatchOperationPutWithOnlyShowErrors(c *C) { + bucketName := bucketNamePrefix + randLowStr(10) + s.putBucket(bucketName, c) + + bucketStr := CloudURLToString(bucketName, "") + + dir := "ossutil-test-dir-" + randLowStr(5) + subdir := "dir1" + contents := map[string]string{} + s.createTestFiles(dir, subdir, c, contents) + + // upload files + args := []string{dir, bucketStr} + cmdline := []string{"ossutil", "cp", dir, bucketStr, "-rf"} + showElapse, err := s.rawCPWithFilter(args, true, true, false, DefaultBigFileThreshold, CheckpointDir, cmdline, "", "") + c.Assert(err, IsNil) + c.Assert(showElapse, Equals, true) + + out = os.Stdout + ogFile := "ossutil_object_tagging." + randLowStr(5) + tagInfo := "key1#value1" + os.Args = []string{"", "object-tagging", "--method", "put", CloudURLToString(bucketName, ""), tagInfo, "-r", "--only-show-errors", "--config-file=" + configFile} + var outFile *os.File + outFile, _ = os.OpenFile(ogFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + err = ParseAndRunCommand() + os.Stdout = out + c.Assert(err, IsNil) + outPut := s.readFile(ogFile, c) + testLogger.Println(outPut) + c.Assert(outPut == "", Equals, true) + os.Remove(ogFile) + os.RemoveAll(dir) + s.removeBucket(bucketName, true, c) +} + +func (s *OssutilCommandSuite) TestObjectTaggingBatchOperationDeleteWithOnlyShowErrors(c *C) { + bucketName := bucketNamePrefix + randLowStr(10) + s.putBucket(bucketName, c) + + bucketStr := CloudURLToString(bucketName, "") + + dir := "ossutil-test-dir-" + randLowStr(5) + subdir := "dir1" + contents := map[string]string{} + s.createTestFiles(dir, subdir, c, contents) + + // upload files + args := []string{dir, bucketStr} + cmdline := []string{"ossutil", "cp", dir, bucketStr, "-rf"} + showElapse, err := s.rawCPWithFilter(args, true, true, false, DefaultBigFileThreshold, CheckpointDir, cmdline, "", "") + c.Assert(err, IsNil) + c.Assert(showElapse, Equals, true) + + out = os.Stdout + ogFile := "ossutil_object_tagging." + randLowStr(5) + tagInfo := "key1#value1" + os.Args = []string{"", "object-tagging", "--method", "delete", CloudURLToString(bucketName, ""), tagInfo, "-r", "--only-show-errors", "--config-file=" + configFile} + var outFile *os.File + outFile, _ = os.OpenFile(ogFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + err = ParseAndRunCommand() + os.Stdout = out + c.Assert(err, IsNil) + outPut := s.readFile(ogFile, c) + testLogger.Println(outPut) + c.Assert(outPut == "", Equals, true) + os.Remove(ogFile) + + os.RemoveAll(dir) + s.removeBucket(bucketName, true, c) +} + +func (s *OssutilCommandSuite) TestObjectTaggingBatchOperationWithOnlyShowErrors(c *C) { + bucketName := bucketNamePrefix + randLowStr(10) + s.putBucket(bucketName, c) + + bucketStr := CloudURLToString(bucketName, "") + + dir := "ossutil-test-dir-" + randLowStr(5) + subdir := "dir1" + contents := map[string]string{} + s.createTestFiles(dir, subdir, c, contents) + + // upload files + args := []string{dir, bucketStr} + cmdline := []string{"ossutil", "cp", dir, bucketStr, "-rf"} + showElapse, err := s.rawCPWithFilter(args, true, true, false, DefaultBigFileThreshold, CheckpointDir, cmdline, "", "") + c.Assert(err, IsNil) + c.Assert(showElapse, Equals, true) + + var str string + strMethod := "put" + recursive := true + routines := strconv.Itoa(Routines) + options := OptionMapType{ + "endpoint": &str, + "accessKeyID": &str, + "accessKeySecret": &str, + "stsToken": &str, + "configFile": &configFile, + "method": &strMethod, + "recursive": &recursive, + "routines": &routines, + } + cpFile := "ossutil_object_tagging" + randLowStr(5) + // put tag + var outFile *os.File + outFile, _ = os.OpenFile(cpFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + tagInfo := "key1#value1" + tagArgs := []string{CloudURLToString(bucketName, ""), tagInfo} + _, err = cm.RunCommand("object-tagging", tagArgs, options) + os.Stdout = out + c.Assert(err, IsNil) + + // get tag + resultfileName := "ossutil-test-result-" + randLowStr(5) + testResultFile, _ = os.OpenFile(resultfileName, os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0664) + oldStdout := os.Stdout + os.Stdout = testResultFile + + strMethod = "get" + options[OptionMethod] = &strMethod + tagArgs = []string{CloudURLToString(bucketName, "")} + _, err = cm.RunCommand("object-tagging", tagArgs, options) + c.Assert(err, IsNil) + os.Stdout = oldStdout + testResultFile.Close() + + catBody := s.readFile(resultfileName, c) + c.Assert(strings.Contains(catBody, "key1"), Equals, true) + c.Assert(strings.Contains(catBody, "value1"), Equals, true) + + out = os.Stdout + ogFile := "ossutil_object_tagging." + randLowStr(5) + strMethod = "delete" + options[OptionMethod] = &strMethod + options[OptionOnlyShowErrors] = &recursive + outFile, _ = os.OpenFile(ogFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + tagArgs = []string{CloudURLToString(bucketName, ""), tagInfo} + _, err = cm.RunCommand("object-tagging", tagArgs, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut := s.readFile(ogFile, c) + testLogger.Println(outPut) + c.Assert(outPut == "", Equals, true) + os.Remove(ogFile) + os.RemoveAll(dir) + s.removeBucket(bucketName, true, c) +} + func (s *OssutilCommandSuite) TestObjectTaggingHelpInfo(c *C) { options := OptionMapType{} diff --git a/lib/option.go b/lib/option.go index 979591cb..aad72185 100644 --- a/lib/option.go +++ b/lib/option.go @@ -284,6 +284,9 @@ var OptionMap = map[string]Option{ OptionForcePathStyle: Option{"", "--force-path-style", "", OptionTypeFlagTrue, "", "", "使用 path style 访问方式", "Use path-style access "}, + OptionOnlyShowErrors: Option{"", "--only-show-errors", "", OptionTypeFlagTrue, "", "", + "表示仅有错误时才输出", + "Indicates output only when there is an error."}, } func (T *Option) getHelp(language string) string { diff --git a/lib/restore.go b/lib/restore.go index 5a498e6e..4be35378 100644 --- a/lib/restore.go +++ b/lib/restore.go @@ -15,10 +15,11 @@ import ( ) type batchOptionType struct { - ctnu bool - reporter *Reporter - snapshotPath string - snapshotldb *leveldb.DB + ctnu bool + reporter *Reporter + snapshotPath string + snapshotldb *leveldb.DB + onlyShowErrors bool } var specChineseRestore = SpecText{ @@ -237,6 +238,7 @@ var restoreCommand = RestoreCommand{ OptionRegion, OptionCloudBoxID, OptionForcePathStyle, + OptionOnlyShowErrors, }, }, } @@ -264,7 +266,7 @@ func (rc *RestoreCommand) RunCommand() error { force, _ := GetBool(OptionForce, rc.command.options) objFileXml, _ := GetString(OptionObjectFile, rc.command.options) snapshotPath, _ := GetString(OptionSnapshotPath, rc.command.options) - + rc.reOption.onlyShowErrors, _ = GetBool(OptionOnlyShowErrors, rc.command.options) payer, _ := GetString(OptionRequestPayer, rc.command.options) if payer != "" { if payer != strings.ToLower(string(oss.Requester)) { @@ -564,7 +566,9 @@ func (rc *RestoreCommand) waitRoutinueComplete(chError, chListError <-chan error } else { ferr = err if !rc.reOption.ctnu { - fmt.Printf(rc.monitor.progressBar(true, errExit)) + if !rc.reOption.onlyShowErrors { + fmt.Printf(rc.monitor.progressBar(true, errExit)) + } return err } } @@ -574,7 +578,10 @@ func (rc *RestoreCommand) waitRoutinueComplete(chError, chListError <-chan error } func (rc *RestoreCommand) formatResultPrompt(err error) error { - fmt.Printf(rc.monitor.progressBar(true, normalExit)) + if !rc.reOption.onlyShowErrors { + fmt.Printf(rc.monitor.progressBar(true, normalExit)) + } + if err != nil && rc.reOption.ctnu { return nil } diff --git a/lib/restore_test.go b/lib/restore_test.go index 3aef0d75..14191a35 100644 --- a/lib/restore_test.go +++ b/lib/restore_test.go @@ -1289,3 +1289,210 @@ func (s *OssutilCommandSuite) TestRestoreProducer(c *C) { os.Remove(emptyContentFileName) } + +func (s *OssutilCommandSuite) TestRestoreObjectWithOnlyShowError(c *C) { + bucketName := bucketNamePrefix + randLowStr(10) + s.putBucketWithStorageClass(bucketName, StorageArchive, c) + + //put object to archive bucket + object := "恢复文件" + randStr(5) + data := randStr(20) + s.createFile(uploadFileName, data, c) + s.putObject(bucketName, object, uploadFileName, c) + + // get object status + objectStat := s.getStat(bucketName, object, c) + c.Assert(objectStat["X-Oss-Storage-Class"], Equals, StorageArchive) + _, ok := objectStat["X-Oss-Restore"] + c.Assert(ok, Equals, false) + + out = os.Stdout + cpFile := "ossutil_restore." + randLowStr(5) + os.Args = []string{"", "restore", CloudURLToString(bucketName, object), "--only-show-errors", "--config-file=" + configFile} + var outFile *os.File + outFile, _ = os.OpenFile(cpFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + err := ParseAndRunCommand() + os.Stdout = out + c.Assert(err, IsNil) + outPut := s.readFile(cpFile, c) + testLogger.Println(outPut) + c.Assert(outPut == "", Equals, true) + os.Remove(cpFile) + + // get object status + objectStat = s.getStat(bucketName, object, c) + c.Assert(objectStat["X-Oss-Storage-Class"], Equals, StorageArchive) + c.Assert(objectStat["X-Oss-Restore"], Equals, "ongoing-request=\"true\"") + s.removeBucket(bucketName, true, c) +} + +func (s *OssutilCommandSuite) TestRestoreObjectFileBasicWithOnlyShowErrors(c *C) { + bucketName := bucketNamePrefix + randLowStr(10) + s.putBucketWithStorageClass(bucketName, StorageArchive, c) + + data := randStr(20) + s.createFile(uploadFileName, data, c) + object1 := "restore" + randStr(5) + object2 := "restore" + randStr(5) + object3 := "restore" + randStr(5) + object4 := "restore" + randStr(5) + s.putObject(bucketName, object1, uploadFileName, c) + s.putObject(bucketName, object2, uploadFileName, c) + s.putObject(bucketName, object3, uploadFileName, c) + s.putObject(bucketName, object4, uploadFileName, c) + + objectStat := s.getStat(bucketName, object1, c) + c.Assert(objectStat["X-Oss-Storage-Class"], Equals, StorageArchive) + _, ok := objectStat["X-Oss-Restore"] + c.Assert(ok, Equals, false) + + objectStat = s.getStat(bucketName, object2, c) + c.Assert(objectStat["X-Oss-Storage-Class"], Equals, StorageArchive) + _, ok = objectStat["X-Oss-Restore"] + c.Assert(ok, Equals, false) + + content := object1 + "\n" + object2 + "\n" + object3 + "\n" + object4 + s.createFile(objectFileName, content, c) + + out = os.Stdout + cpFile := "ossutil_restore." + randLowStr(5) + os.Args = []string{"", "restore", CloudURLToString(bucketName, ""), fmt.Sprintf("--object-file=%s", objectFileName), "-f", "--only-show-errors", "--config-file=" + configFile} + var outFile *os.File + outFile, _ = os.OpenFile(cpFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + err := ParseAndRunCommand() + os.Stdout = out + c.Assert(err, IsNil) + outPut := s.readFile(cpFile, c) + testLogger.Println(outPut) + c.Assert(outPut == "", Equals, true) + os.Remove(cpFile) + + objectStat = s.getStat(bucketName, object1, c) + c.Assert(objectStat["X-Oss-Storage-Class"], Equals, StorageArchive) + c.Assert(objectStat["X-Oss-Restore"], Equals, "ongoing-request=\"true\"") + + objectStat = s.getStat(bucketName, object2, c) + c.Assert(objectStat["X-Oss-Storage-Class"], Equals, StorageArchive) + c.Assert(objectStat["X-Oss-Restore"], Equals, "ongoing-request=\"true\"") + + objectStat = s.getStat(bucketName, object3, c) + c.Assert(objectStat["X-Oss-Storage-Class"], Equals, StorageArchive) + c.Assert(objectStat["X-Oss-Restore"], Equals, "ongoing-request=\"true\"") + + objectStat = s.getStat(bucketName, object4, c) + c.Assert(objectStat["X-Oss-Storage-Class"], Equals, StorageArchive) + c.Assert(objectStat["X-Oss-Restore"], Equals, "ongoing-request=\"true\"") + + os.Remove(objectFileName) + s.removeBucket(bucketName, true, c) +} + +func (s *OssutilCommandSuite) TestRestoreObjectFileBasicWithOnlyShowErrorsAndForce(c *C) { + bucketName := bucketNamePrefix + randLowStr(10) + s.putBucketWithStorageClass(bucketName, StorageArchive, c) + + data := randStr(20) + s.createFile(uploadFileName, data, c) + object1 := "restore" + randStr(5) + object2 := "restore" + randStr(5) + object3 := "restore" + randStr(5) + object4 := "restore" + randStr(5) + s.putObject(bucketName, object1, uploadFileName, c) + s.putObject(bucketName, object2, uploadFileName, c) + s.putObject(bucketName, object3, uploadFileName, c) + s.putObject(bucketName, object4, uploadFileName, c) + + objectStat := s.getStat(bucketName, object1, c) + c.Assert(objectStat["X-Oss-Storage-Class"], Equals, StorageArchive) + _, ok := objectStat["X-Oss-Restore"] + c.Assert(ok, Equals, false) + + objectStat = s.getStat(bucketName, object2, c) + c.Assert(objectStat["X-Oss-Storage-Class"], Equals, StorageArchive) + _, ok = objectStat["X-Oss-Restore"] + c.Assert(ok, Equals, false) + + content := object1 + "\n" + object2 + "\n" + object3 + "\n" + object4 + s.createFile(objectFileName, content, c) + + str := "" + routines := strconv.Itoa(Routines) + isTrue := true + options := OptionMapType{ + "endpoint": &str, + "accessKeyID": &str, + "accessKeySecret": &str, + "stsToken": &str, + "configFile": &configFile, + "recursive": &isTrue, + "routines": &routines, + "objectFile": &objectFileName, + } + + out = os.Stdout + rpFile := "ossutil_restore." + randLowStr(5) + var outFile *os.File + outFile, _ = os.OpenFile(rpFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + args := []string{CloudURLToString(bucketName, "")} + _, err := cm.RunCommand("restore", args, options) + c.Assert(err, IsNil) + os.Stdout = out + c.Assert(err, IsNil) + outPut := s.readFile(rpFile, c) + testLogger.Println(outPut) + c.Assert(strings.Contains(outPut, "Do you really "), Equals, true) + os.Remove(rpFile) + + outFile, _ = os.OpenFile(rpFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + args = []string{CloudURLToString(bucketName, "")} + _, err = cm.RunCommand("restore", args, options) + c.Assert(err, IsNil) + os.Stdout = out + c.Assert(err, IsNil) + outPut = s.readFile(rpFile, c) + testLogger.Println(outPut) + c.Assert(strings.Contains(outPut, "Succeed"), Equals, true) + os.Remove(rpFile) + + objectStat = s.getStat(bucketName, object1, c) + c.Assert(objectStat["X-Oss-Storage-Class"], Equals, StorageArchive) + c.Assert(objectStat["X-Oss-Restore"], Equals, "ongoing-request=\"true\"") + + objectStat = s.getStat(bucketName, object2, c) + c.Assert(objectStat["X-Oss-Storage-Class"], Equals, StorageArchive) + c.Assert(objectStat["X-Oss-Restore"], Equals, "ongoing-request=\"true\"") + + objectStat = s.getStat(bucketName, object3, c) + c.Assert(objectStat["X-Oss-Storage-Class"], Equals, StorageArchive) + c.Assert(objectStat["X-Oss-Restore"], Equals, "ongoing-request=\"true\"") + + objectStat = s.getStat(bucketName, object4, c) + c.Assert(objectStat["X-Oss-Storage-Class"], Equals, StorageArchive) + c.Assert(objectStat["X-Oss-Restore"], Equals, "ongoing-request=\"true\"") + + outFile, _ = os.OpenFile(rpFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + options[OptionOnlyShowErrors] = &isTrue + options[OptionForce] = &isTrue + args = []string{CloudURLToString(bucketName, "")} + _, err = cm.RunCommand("restore", args, options) + c.Assert(err, IsNil) + os.Stdout = out + c.Assert(err, IsNil) + outPut = s.readFile(rpFile, c) + testLogger.Println(outPut) + c.Assert(outPut == "", Equals, true) + os.Remove(rpFile) + + os.Remove(objectFileName) + s.removeBucket(bucketName, true, c) +} diff --git a/lib/rm.go b/lib/rm.go index a9c60d3f..4372180e 100644 --- a/lib/rm.go +++ b/lib/rm.go @@ -20,8 +20,9 @@ type removeOptionType struct { typeSet int64 //version - versionId string - allVersions bool + versionId string + allVersions bool + onlyShowErrors bool } var specChineseRemove = SpecText{ @@ -343,6 +344,7 @@ var removeCommand = RemoveCommand{ OptionRegion, OptionCloudBoxID, OptionForcePathStyle, + OptionOnlyShowErrors, }, }, } @@ -415,7 +417,9 @@ func (rc *RemoveCommand) RunCommand() error { if err = rc.removeEntry(bucket, cloudURL); err != nil { exitStat = errExit } - fmt.Printf(rc.monitor.progressBar(true, exitStat)) + if !rc.rmOption.onlyShowErrors { + fmt.Printf(rc.monitor.progressBar(true, exitStat)) + } return err } @@ -427,7 +431,7 @@ func (rc *RemoveCommand) assembleOption(cloudURL CloudURL) error { toBucket, _ := GetBool(OptionBucket, rc.command.options) rc.rmOption.versionId, _ = GetString(OptionVersionId, rc.command.options) rc.rmOption.allVersions, _ = GetBool(OptionAllversions, rc.command.options) - + rc.rmOption.onlyShowErrors, _ = GetBool(OptionOnlyShowErrors, rc.command.options) if err := rc.checkOption(cloudURL, isMultipart, isAllType, toBucket); err != nil { return err } @@ -720,7 +724,9 @@ func (rc *RemoveCommand) ossDeleteObjectRetry(bucket *oss.Bucket, object string) func (rc *RemoveCommand) updateObjectMonitor(okNum, errNum int64) { rc.monitor.updateObjectNum(okNum) rc.monitor.updateErrObjectNum(errNum) - fmt.Printf(rc.monitor.progressBar(false, normalExit)) + if !rc.rmOption.onlyShowErrors { + fmt.Printf(rc.monitor.progressBar(false, normalExit)) + } } func (rc *RemoveCommand) batchDeleteObjects(bucket *oss.Bucket, cloudURL CloudURL) error { @@ -899,7 +905,9 @@ func (rc *RemoveCommand) updateUploadIdMonitor(err error) { } else { rc.monitor.updateErrUploadIdNum(1) } - fmt.Printf(rc.monitor.progressBar(false, normalExit)) + if !rc.rmOption.onlyShowErrors { + fmt.Printf(rc.monitor.progressBar(false, normalExit)) + } } func (rc *RemoveCommand) ossAbortMultipartUploadRetry(bucket *oss.Bucket, key, uploadId string) error { diff --git a/lib/rm_test.go b/lib/rm_test.go index 860391df..62ddf68a 100644 --- a/lib/rm_test.go +++ b/lib/rm_test.go @@ -1188,3 +1188,79 @@ func (s *OssutilCommandSuite) TestMultipartUploadsProducer(c *C) { c.Assert(true, Equals, false) } } + +func (s *OssutilCommandSuite) TestRemoveObjectsWithOnlyShowErrors(c *C) { + bucketName := bucketNamePrefix + randLowStr(10) + s.putBucket(bucketName, c) + + // put object + num := 2 + objectNames := []string{} + for i := 0; i < num; i++ { + object := fmt.Sprintf("remove%d", i) + s.putObject(bucketName, object, uploadFileName, c) + objectNames = append(objectNames, object) + } + + command := "rm" + args := []string{CloudURLToString(bucketName, "")} + ok := true + str := "" + options := OptionMapType{ + "endpoint": &str, + "accessKeyID": &str, + "accessKeySecret": &str, + "configFile": &configFile, + "recursive": &ok, + } + rmFile := "ossutil_rm." + randLowStr(5) + var outFile *os.File + outFile, _ = os.OpenFile(rmFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + _, err := cm.RunCommand(command, args, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut := s.readFile(rmFile, c) + testLogger.Println(outPut) + c.Assert(strings.Contains(outPut, "Do you really mean to remove recursively objects of"), Equals, true) + os.Remove(rmFile) + + options[OptionOnlyShowErrors] = &ok + outFile, _ = os.OpenFile(rmFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + _, err = cm.RunCommand(command, args, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut = s.readFile(rmFile, c) + testLogger.Println(outPut) + c.Assert(strings.Contains(outPut, "Do you really mean to remove recursively objects of"), Equals, true) + os.Remove(rmFile) + + options[OptionForce] = &ok + outFile, _ = os.OpenFile(rmFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + _, err = cm.RunCommand(command, args, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut = s.readFile(rmFile, c) + testLogger.Println(outPut) + c.Assert(outPut == "", Equals, true) + os.Remove(rmFile) + + delete(options, OptionOnlyShowErrors) + outFile, _ = os.OpenFile(rmFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + _, err = cm.RunCommand(command, args, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut = s.readFile(rmFile, c) + testLogger.Println(outPut) + c.Assert(strings.Contains(outPut, "Succeed"), Equals, true) + os.Remove(rmFile) + + s.removeBucket(bucketName, true, c) +} diff --git a/lib/set_acl.go b/lib/set_acl.go index 51960577..f0cebf36 100644 --- a/lib/set_acl.go +++ b/lib/set_acl.go @@ -263,6 +263,7 @@ var setACLCommand = SetACLCommand{ OptionRegion, OptionCloudBoxID, OptionForcePathStyle, + OptionOnlyShowErrors, }, }, } @@ -291,7 +292,7 @@ func (sc *SetACLCommand) RunCommand() error { routines, _ := GetInt(OptionRoutines, sc.command.options) encodingType, _ := GetString(OptionEncodingType, sc.command.options) versionId, _ := GetString(OptionVersionId, sc.command.options) - + sc.saOption.onlyShowErrors, _ = GetBool(OptionOnlyShowErrors, sc.command.options) var res bool res, sc.filters = getFilter(os.Args) if !res { @@ -515,7 +516,9 @@ func (sc *SetACLCommand) waitRoutinueComplete(chError, chListError <-chan error, } else { ferr = err if !sc.saOption.ctnu { - fmt.Printf(sc.monitor.progressBar(true, errExit)) + if !sc.saOption.onlyShowErrors { + fmt.Printf(sc.monitor.progressBar(true, errExit)) + } return err } } @@ -525,7 +528,9 @@ func (sc *SetACLCommand) waitRoutinueComplete(chError, chListError <-chan error, } func (sc *SetACLCommand) formatResultPrompt(err error) error { - fmt.Printf(sc.monitor.progressBar(true, normalExit)) + if !sc.saOption.onlyShowErrors { + fmt.Printf(sc.monitor.progressBar(true, normalExit)) + } if err != nil && sc.saOption.ctnu { return nil } diff --git a/lib/set_acl_test.go b/lib/set_acl_test.go index ced3fb4a..777799db 100644 --- a/lib/set_acl_test.go +++ b/lib/set_acl_test.go @@ -1303,3 +1303,65 @@ func (s *OssutilCommandSuite) TestSetObjectAclWithInvalidVersionArgs(c *C) { _, err = cm.RunCommand("set-acl", args, options) c.Assert(strings.Contains(err.Error(), "--version-id only work on single object"), Equals, true) } + +func (s *OssutilCommandSuite) TestSetObjectAclWithOnlyShowErrors(c *C) { + bucketName := bucketNamePrefix + "-set-alc-" + randLowStr(10) + objectName := randStr(12) + s.putBucket(bucketName, c) + textBufferV1 := randStr(100) + s.createFile(uploadFileName, textBufferV1, c) + s.putObject(bucketName, objectName, uploadFileName, c) + var str string + ok := true + options := OptionMapType{ + "endpoint": &str, + "accessKeyID": &str, + "accessKeySecret": &str, + "configFile": &configFile, + } + aclFile := "ossutil_set_acl." + randLowStr(5) + var outFile *os.File + + args := []string{CloudURLToString(bucketName, objectName), "private"} + outFile, _ = os.OpenFile(aclFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + _, err := cm.RunCommand("set-acl", args, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut := s.readFile(aclFile, c) + testLogger.Println(outPut) + c.Assert(outPut == "", Equals, true) + os.Remove(aclFile) + + options[OptionRecursion] = &ok + args = []string{CloudURLToString(bucketName, ""), "private"} + outFile, _ = os.OpenFile(aclFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + _, err = cm.RunCommand("set-acl", args, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut = s.readFile(aclFile, c) + testLogger.Println(outPut) + c.Assert(strings.Contains(outPut, "Do you really mean to"), Equals, true) + os.Remove(aclFile) + + options[OptionOnlyShowErrors] = &ok + options[OptionForce] = &ok + args = []string{CloudURLToString(bucketName, ""), "private"} + outFile, _ = os.OpenFile(aclFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + _, err = cm.RunCommand("set-acl", args, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut = s.readFile(aclFile, c) + testLogger.Println(outPut) + c.Assert(outPut == "", Equals, true) + os.Remove(aclFile) + + args = []string{CloudURLToString(bucketName, objectName), "err-private"} + _, err = cm.RunCommand("set-acl", args, options) + c.Assert(err, NotNil) +} diff --git a/lib/set_meta.go b/lib/set_meta.go index 2a9cef97..74e673f1 100644 --- a/lib/set_meta.go +++ b/lib/set_meta.go @@ -367,6 +367,7 @@ var setMetaCommand = SetMetaCommand{ OptionRegion, OptionCloudBoxID, OptionForcePathStyle, + OptionOnlyShowErrors, }, }, } @@ -399,7 +400,7 @@ func (sc *SetMetaCommand) RunCommand() error { versionId, _ := GetString(OptionVersionId, sc.command.options) objFileXml, _ := GetString(OptionObjectFile, sc.command.options) snapshotPath, _ := GetString(OptionSnapshotPath, sc.command.options) - + sc.smOption.onlyShowErrors, _ = GetBool(OptionOnlyShowErrors, sc.command.options) var err error // load snapshot sc.smOption.snapshotPath = snapshotPath @@ -760,7 +761,9 @@ func (sc *SetMetaCommand) waitRoutinueComplete(chError, chListError <-chan error } else { ferr = err if !sc.smOption.ctnu { - fmt.Printf(sc.monitor.progressBar(true, errExit)) + if !sc.smOption.onlyShowErrors { + fmt.Printf(sc.monitor.progressBar(true, errExit)) + } return err } } @@ -770,7 +773,9 @@ func (sc *SetMetaCommand) waitRoutinueComplete(chError, chListError <-chan error } func (sc *SetMetaCommand) formatResultPrompt(err error) error { - fmt.Printf(sc.monitor.progressBar(true, normalExit)) + if !sc.smOption.onlyShowErrors { + fmt.Printf(sc.monitor.progressBar(true, errExit)) + } if err != nil && sc.smOption.ctnu { return nil } diff --git a/lib/set_meta_test.go b/lib/set_meta_test.go index 4c841b49..ce17a107 100644 --- a/lib/set_meta_test.go +++ b/lib/set_meta_test.go @@ -2025,3 +2025,94 @@ func (s *OssutilCommandSuite) TestSetObjectMetaProducer(c *C) { os.Remove(emptyContentFileName) } + +func (s *OssutilCommandSuite) TestSetObjectMetaWithOnlyShowErrors(c *C) { + bucketName := bucketNamePrefix + "-set-meta-" + randLowStr(10) + objectName := randStr(12) + + s.putBucket(bucketName, c) + // put object v1 + textBufferV1 := randStr(100) + s.createFile(uploadFileName, textBufferV1, c) + s.putObject(bucketName, objectName, uploadFileName, c) + // begin set-meta from v2 + var str string + isTrue := true + options := OptionMapType{ + "endpoint": &str, + "accessKeyID": &str, + "accessKeySecret": &str, + "configFile": &configFile, + "update": &isTrue, + } + + aclFile := "ossutil_set_meta." + randLowStr(5) + var outFile *os.File + + args := []string{CloudURLToString(bucketName, objectName), "x-oss-object-acl:public-read-write#X-Oss-Meta-A:123#X-Oss-Meta-C:456"} + outFile, _ = os.OpenFile(aclFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + _, err := cm.RunCommand("set-meta", args, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut := s.readFile(aclFile, c) + testLogger.Println(outPut) + c.Assert(outPut == "", Equals, true) + os.Remove(aclFile) + + options[OptionRecursion] = &isTrue + args = []string{CloudURLToString(bucketName, ""), "x-oss-object-acl:public-read-write#X-Oss-Meta-A:123#X-Oss-Meta-C:456"} + outFile, _ = os.OpenFile(aclFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + _, err = cm.RunCommand("set-meta", args, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut = s.readFile(aclFile, c) + testLogger.Println(outPut) + c.Assert(strings.Contains(outPut, "Do you really mean to recursivlly set meta on"), Equals, true) + os.Remove(aclFile) + + options[OptionForce] = &isTrue + args = []string{CloudURLToString(bucketName, ""), "x-oss-object-acl:public-read-write#X-Oss-Meta-A:123#X-Oss-Meta-C:456"} + outFile, _ = os.OpenFile(aclFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + _, err = cm.RunCommand("set-meta", args, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut = s.readFile(aclFile, c) + testLogger.Println(outPut) + c.Assert(strings.Contains(outPut, "Total"), Equals, true) + os.Remove(aclFile) + + delete(options, OptionForce) + options[OptionOnlyShowErrors] = &isTrue + args = []string{CloudURLToString(bucketName, ""), "x-oss-object-acl:public-read-write#X-Oss-Meta-A:123#X-Oss-Meta-C:456"} + outFile, _ = os.OpenFile(aclFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + _, err = cm.RunCommand("set-meta", args, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut = s.readFile(aclFile, c) + testLogger.Println(outPut) + c.Assert(strings.Contains(outPut, "Do you really mean to recursivlly set meta on"), Equals, true) + os.Remove(aclFile) + + options[OptionForce] = &isTrue + args = []string{CloudURLToString(bucketName, ""), "x-oss-object-acl:public-read-write#X-Oss-Meta-A:123#X-Oss-Meta-C:456"} + outFile, _ = os.OpenFile(aclFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + _, err = cm.RunCommand("set-meta", args, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut = s.readFile(aclFile, c) + testLogger.Println(outPut) + c.Assert(outPut == "", Equals, true) + os.Remove(aclFile) + + s.removeBucket(bucketName, true, c) +} diff --git a/lib/sync.go b/lib/sync.go index 7b295542..7161ac03 100644 --- a/lib/sync.go +++ b/lib/sync.go @@ -429,7 +429,7 @@ var syncCommand = SyncCommand{ OptionRegion, OptionCloudBoxID, OptionForcePathStyle, - + OptionOnlyShowErrors, // The following options are only supported by sc command, not supported by cp command OptionDelete, OptionBackupDir, diff --git a/lib/sync_test.go b/lib/sync_test.go index 1d0887a0..14608d2f 100644 --- a/lib/sync_test.go +++ b/lib/sync_test.go @@ -2235,3 +2235,85 @@ func (s *OssutilCommandSuite) TestSyncUploadSubSymlinkDir(c *C) { os.RemoveAll(dirName) s.removeBucket(bucketName, true, c) } + +func (s *OssutilCommandSuite) TestSyncWithOnlyShowErrors(c *C) { + bucketName := bucketNamePrefix + randLowStr(10) + s.putBucket(bucketName, c) + + // dir1 + dirName := "testdir1-" + randLowStr(3) + fileName1 := "test-ossutil-file-" + randStr(3) + subDirName := "subdir1-" + randLowStr(4) + os.MkdirAll(dirName+string(os.PathSeparator)+subDirName+string(os.PathSeparator), 0755) + s.createFile(dirName+string(os.PathSeparator)+fileName1, "123", c) + + dirName2 := "dest-" + dirName + fileName2 := "test-ossutil-file-" + randStr(5) + os.MkdirAll(dirName2, 0755) + s.createFile(dirName2+string(os.PathSeparator)+fileName2, "123", c) + + // upload dir + syncArgs := []string{dirName2, CloudURLToString(bucketName, "")} + str := "" + cpDir := CheckpointDir + bForce := true + routines := strconv.Itoa(Routines) + options := OptionMapType{ + "endpoint": &str, + "accessKeyID": &str, + "accessKeySecret": &str, + "configFile": &configFile, + "checkpointDir": &cpDir, + "routines": &routines, + "force": &bForce, + OptionOnlyShowErrors: &bForce, + } + + syncFile := "ossutil_sync." + randLowStr(5) + var outFile *os.File + outFile, _ = os.OpenFile(syncFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + _, err := cm.RunCommand("sync", syncArgs, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut := s.readFile(syncFile, c) + testLogger.Println(outPut) + c.Assert(outPut == "", Equals, true) + os.Remove(syncFile) + + // download + backupDir := "test-backup-dir" + randLowStr(3) + options["backupDir"] = &backupDir + syncArgs = []string{CloudURLToString(bucketName, ""), dirName} + outFile, _ = os.OpenFile(syncFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + _, err = cm.RunCommand("sync", syncArgs, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut = s.readFile(syncFile, c) + testLogger.Println(outPut) + c.Assert(outPut == "", Equals, true) + os.Remove(syncFile) + + os.RemoveAll(backupDir) + options[OptionDelete] = &bForce + options["backupDir"] = &backupDir + syncArgs = []string{CloudURLToString(bucketName, ""), dirName} + outFile, _ = os.OpenFile(syncFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660) + defer outFile.Close() + os.Stdout = outFile + _, err = cm.RunCommand("sync", syncArgs, options) + os.Stdout = out + c.Assert(err, IsNil) + outPut = s.readFile(syncFile, c) + testLogger.Println(outPut) + c.Assert(strings.Contains(outPut, "object"), Equals, true) + os.Remove(syncFile) + + os.RemoveAll(dirName) + os.RemoveAll(dirName2) + os.RemoveAll(backupDir) + s.removeBucket(bucketName, true, c) +}