Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package minio-client for openSUSE:Factory checked in at 2024-06-24 20:52:23 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/minio-client (Old) and /work/SRC/openSUSE:Factory/.minio-client.new.18349 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "minio-client" Mon Jun 24 20:52:23 2024 rev:84 rq:1182577 version:20240620T145054Z Changes: -------- --- /work/SRC/openSUSE:Factory/minio-client/minio-client.changes 2024-06-17 19:28:45.924652259 +0200 +++ /work/SRC/openSUSE:Factory/.minio-client.new.18349/minio-client.changes 2024-06-24 20:53:12.848135524 +0200 @@ -1,0 +2,12 @@ +Sat Jun 22 10:07:34 UTC 2024 - opensuse_buildservice@ojkastl.de + +- Update to version 20240620T145054Z: + * make 'mc admin service restart' more descriptive of what it + does (#4965) + * list versions including DEL marker when figuring out Stat() + (#4951) + * enable batch expiry option in trace (#4964) + * fix: support 'mc put --if-not-exists' (#4963) + * Adding support for Hex keys (#4962) + +------------------------------------------------------------------- Old: ---- mc-20240612T143403Z.obscpio New: ---- mc-20240620T145054Z.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ minio-client.spec ++++++ --- /var/tmp/diff_new_pack.uZEvXv/_old 2024-06-24 20:53:13.708166991 +0200 +++ /var/tmp/diff_new_pack.uZEvXv/_new 2024-06-24 20:53:13.712167137 +0200 @@ -22,7 +22,7 @@ %define binary_name minio-client Name: minio-client -Version: 20240612T143403Z +Version: 20240620T145054Z Release: 0 Summary: Client for MinIO License: AGPL-3.0-only ++++++ _service ++++++ --- /var/tmp/diff_new_pack.uZEvXv/_old 2024-06-24 20:53:13.740168161 +0200 +++ /var/tmp/diff_new_pack.uZEvXv/_new 2024-06-24 20:53:13.744168308 +0200 @@ -5,7 +5,7 @@ <param name="exclude">.git</param> <param name="changesgenerate">enable</param> <param name="versionformat">@PARENT_TAG@</param> - <param name="revision">RELEASE.2024-06-12T14-34-03Z</param> + <param name="revision">RELEASE.2024-06-20T14-50-54Z</param> <param name="match-tag">RELEASE.*</param> <param name="versionrewrite-pattern">RELEASE\.(.*)-(.*)-(.*)-(.*)-(.*)</param> <param name="versionrewrite-replacement">\1\2\3\4\5</param> @@ -19,7 +19,7 @@ <param name="compression">gz</param> </service> <service name="go_modules" mode="manual"> - <param name="archive">mc-20240612T143403Z.obscpio</param> + <param name="archive">mc-20240620T145054Z.obscpio</param> </service> </services> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.uZEvXv/_old 2024-06-24 20:53:13.764169039 +0200 +++ /var/tmp/diff_new_pack.uZEvXv/_new 2024-06-24 20:53:13.764169039 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/minio/mc</param> - <param name="changesrevision">e7c9a733c680fe62066d24e8718f81938b4f6606</param></service></servicedata> + <param name="changesrevision">dda9e96887a452b60f23ef18ea68e8898836c017</param></service></servicedata> (No newline at EOF) ++++++ mc-20240612T143403Z.obscpio -> mc-20240620T145054Z.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/cmd/admin-service-restart.go new/mc-20240620T145054Z/cmd/admin-service-restart.go --- old/mc-20240612T143403Z/cmd/admin-service-restart.go 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/cmd/admin-service-restart.go 2024-06-20 16:50:54.000000000 +0200 @@ -67,12 +67,13 @@ Status string `json:"status"` ServerURL string `json:"serverURL"` Result madmin.ServiceActionResult `json:"result"` + TimeTaken time.Duration `json:"timeTaken"` } // String colorized service restart command message. func (s serviceRestartCommand) String() string { var s1 strings.Builder - s1.WriteString("Restart command successfully sent to `" + s.ServerURL + "`. Type Ctrl-C to quit or wait to follow the status of the restart process.") + s1.WriteString("Restart command successfully acknowledged by `" + s.ServerURL + "` in " + timeDurationToHumanizedDuration(s.TimeTaken).StringShort() + ". Type Ctrl-C to quit or wait to follow the status of the restart process.") if len(s.Result.Results) > 0 { s1.WriteString("\n") @@ -119,7 +120,7 @@ // String colorized service restart message. func (s serviceRestartMessage) String() string { if s.Err == nil { - return console.Colorize("ServiceRestart", fmt.Sprintf("\nRestarted `%s` successfully in %s", s.ServerURL, timeDurationToHumanizedDuration(s.TimeTaken).StringShort())) + return console.Colorize("ServiceRestart", fmt.Sprintf("\nEstablished quorum on `%s` successfully in %s", s.ServerURL, timeDurationToHumanizedDuration(s.TimeTaken).StringShort())) } return console.Colorize("FailedServiceRestart", "Failed to restart `"+s.ServerURL+"`. error: "+s.Err.Error()) } @@ -159,6 +160,7 @@ client, err := newAdminClient(aliasedURL) fatalIf(err, "Unable to initialize admin connection.") + t := time.Now() // Restart the specified MinIO server result, e := client.ServiceAction(ctxt, madmin.ServiceActionOpts{ Action: madmin.ServiceActionRestart, @@ -171,7 +173,7 @@ fatalIf(probe.NewError(e), "Unable to restart the server.") // Success.. - printMsg(serviceRestartCommand{Status: "success", ServerURL: aliasedURL, Result: result}) + printMsg(serviceRestartCommand{Status: "success", ServerURL: aliasedURL, Result: result, TimeTaken: time.Since(t)}) // Start pinging the service until it is ready @@ -191,7 +193,7 @@ printProgress() mark = "." - t := time.Now() + t = time.Now() for { healthCtx, healthCancel := context.WithTimeout(ctxt, 2*time.Second) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/cmd/admin-trace.go new/mc-20240620T145054Z/cmd/admin-trace.go --- old/mc-20240612T143403Z/cmd/admin-trace.go 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/cmd/admin-trace.go 2024-06-20 16:50:54.000000000 +0200 @@ -169,6 +169,7 @@ "resync": traceCallTypes["replication-resync"], "brep": traceCallTypes["batch-replication"], "brot": traceCallTypes["batch-keyrotation"], + "bexp": traceCallTypes["batch-expiration"], } func traceCallsHelp() string { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/cmd/client-s3.go new/mc-20240620T145054Z/cmd/client-s3.go --- old/mc-20240612T143403Z/cmd/client-s3.go 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/cmd/client-s3.go 2024-06-20 16:50:54.000000000 +0200 @@ -1168,6 +1168,11 @@ opts.SendContentMd5 = true } + if putOpts.ifNotExists { + // Only supported in newer MinIO releases. + opts.SetMatchETagExcept("*") + } + ui, e := c.api.PutObject(ctx, bucket, object, reader, size, opts) if e != nil { errResponse := minio.ToErrorResponse(e) @@ -1716,7 +1721,7 @@ nonRecursive := false maxKeys := 1 - for objectStat := range c.listObjectWrapper(ctx, bucket, path, nonRecursive, opts.timeRef, false, false, false, maxKeys, opts.isZip) { + for objectStat := range c.listObjectWrapper(ctx, bucket, path, nonRecursive, opts.timeRef, opts.includeVersions, opts.includeVersions, false, maxKeys, opts.isZip) { if objectStat.Err != nil { return nil, probe.NewError(objectStat.Err) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/cmd/client.go new/mc-20240620T145054Z/cmd/client.go --- old/mc-20240612T143403Z/cmd/client.go 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/cmd/client.go 2024-06-20 16:50:54.000000000 +0200 @@ -62,6 +62,7 @@ multipartSize uint64 multipartThreads uint concurrentStream bool + ifNotExists bool } // StatOptions holds options of the HEAD operation @@ -71,6 +72,7 @@ sse encrypt.ServerSide timeRef time.Time versionID string + includeVersions bool isZip bool ignoreBucketExists bool } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/cmd/common-methods.go new/mc-20240620T145054Z/cmd/common-methods.go --- old/mc-20240612T143403Z/cmd/common-methods.go 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/cmd/common-methods.go 2024-06-20 16:50:54.000000000 +0200 @@ -494,6 +494,7 @@ isPreserve: uploadOpts.preserve, multipartSize: multipartSize, multipartThreads: uint(multipartThreads), + ifNotExists: uploadOpts.ifNotExists, } if isReadAt(reader) || length == 0 { @@ -576,4 +577,5 @@ multipartSize string multipartThreads string updateProgressTotal bool + ifNotExists bool } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/cmd/cp-main.go new/mc-20240620T145054Z/cmd/cp-main.go --- old/mc-20240612T143403Z/cmd/cp-main.go 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/cmd/cp-main.go 2024-06-20 16:50:54.000000000 +0200 @@ -264,6 +264,7 @@ multipartSize: copyOpts.multipartSize, multipartThreads: copyOpts.multipartThreads, updateProgressTotal: copyOpts.updateProgressTotal, + ifNotExists: copyOpts.ifNotExists, }) if copyOpts.isMvCmd && urls.Error == nil { rmManager.add(ctx, sourceAlias, sourceURL.String()) @@ -557,4 +558,5 @@ updateProgressTotal bool multipartSize string multipartThreads string + ifNotExists bool } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/cmd/encryption-methods.go new/mc-20240620T145054Z/cmd/encryption-methods.go --- old/mc-20240612T143403Z/cmd/encryption-methods.go 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/cmd/encryption-methods.go 2024-06-20 16:50:54.000000000 +0200 @@ -18,9 +18,11 @@ package cmd import ( + "bytes" "encoding/base64" + "encoding/hex" + "fmt" "sort" - "strconv" "strings" "github.com/minio/cli" @@ -194,41 +196,49 @@ key string, err *probe.Error, ) { - if keyType == sseS3 { - alias, prefix = splitKey(sseKey) + sseKeyBytes := []byte(sseKey) + + separatorIndex := bytes.LastIndex(sseKeyBytes, []byte("=")) + if separatorIndex < 0 { + err = errSSEKeyMissing().Trace(sseKey) return } - var path string - alias, path = splitKey(sseKey) - splitPath := strings.Split(path, "=") - if len(splitPath) == 0 { + encodedKey := string(sseKeyBytes[separatorIndex+1:]) + if separatorIndex == len(sseKeyBytes)-1 { err = errSSEKeyMissing().Trace(sseKey) return } - aliasPlusPrefix := strings.Join(splitPath[:len(splitPath)-1], "=") - prefix = strings.Replace(aliasPlusPrefix, alias+"/", "", 1) - key = splitPath[len(splitPath)-1] - - if keyType == sseC { - keyB, de := base64.RawStdEncoding.DecodeString(key) - if de != nil { - err = errSSEClientKeyFormat("One of the inserted keys was " + strconv.Itoa(len(key)) + " bytes and did not have valid base64 raw encoding.").Trace(sseKey) - return - } - key = string(keyB) - if len(key) != 32 { - err = errSSEClientKeyFormat("The plain text key was " + strconv.Itoa(len(key)) + " bytes but should be 32 bytes long").Trace(sseKey) - return - } + alias, prefix = splitKey(string(sseKeyBytes[:separatorIndex])) + + if keyType == sseS3 { + return } if keyType == sseKMS { - if !validKMSKeyName(key) { - err = errSSEKMSKeyFormat("One of the inserted keys was " + strconv.Itoa(len(key)) + " bytes and did not have a valid KMS key name.").Trace(sseKey) - return + if !validKMSKeyName(encodedKey) { + err = errSSEKMSKeyFormat(fmt.Sprintf("Key (%s) is badly formatted.", encodedKey)).Trace(sseKey) } + return + } + + var keyB []byte + var decodeError error + if len(encodedKey) == 64 { + keyB, decodeError = hex.DecodeString(encodedKey) + } else { + keyB, decodeError = base64.RawStdEncoding.DecodeString(encodedKey) + } + + if decodeError != nil { + err = errSSEClientKeyFormat(fmt.Sprintf("Key (%s) was neither base64 raw encoded nor hex encoded.", encodedKey)).Trace(sseKey) + } + + key = string(keyB) + if len(key) != 32 { + err = errSSEClientKeyFormat(fmt.Sprintf("Plain text from key (%s) is only %d bytes, but should be 32 bytes.", encodedKey, len(key))).Trace(sseKey) + return } return diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/cmd/encryption-methods_test.go new/mc-20240620T145054Z/cmd/encryption-methods_test.go --- old/mc-20240612T143403Z/cmd/encryption-methods_test.go 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/cmd/encryption-methods_test.go 2024-06-20 16:50:54.000000000 +0200 @@ -28,6 +28,7 @@ baseObject := "object_name" sseKey := "MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDA" sseKeyPlain := "01234567890123456789012345678900" + sseHexKey := "3031323334353637383930313233343536373839303132333435363738393030" // INVALID KEYS sseKeyInvalidShort := "MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2" @@ -46,6 +47,14 @@ success bool }{ { + encryptionKey: fmt.Sprintf("%s/%s/%s=%s", baseAlias, basePrefix, baseObject, sseHexKey), + keyPlain: sseKeyPlain, + alias: baseAlias, + prefix: basePrefix, + object: baseObject, + success: true, + }, + { encryptionKey: fmt.Sprintf("%s/%s/%s=%s", baseAlias, basePrefix, baseObject, sseKey), keyPlain: sseKeyPlain, alias: baseAlias, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/cmd/find-main.go new/mc-20240620T145054Z/cmd/find-main.go --- old/mc-20240612T143403Z/cmd/find-main.go 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/cmd/find-main.go 2024-06-20 16:50:54.000000000 +0200 @@ -207,21 +207,21 @@ // ease of repurposing. type findContext struct { *cli.Context - execCmd string - ignorePattern string - namePattern string - pathPattern string - regexPattern *regexp.Regexp - maxDepth uint - printFmt string - olderThan string - newerThan string - largerSize uint64 - smallerSize uint64 - watch bool - withOlderVersions bool - matchMeta map[string]*regexp.Regexp - matchTags map[string]*regexp.Regexp + execCmd string + ignorePattern string + namePattern string + pathPattern string + regexPattern *regexp.Regexp + maxDepth uint + printFmt string + olderThan string + newerThan string + largerSize uint64 + smallerSize uint64 + watch bool + withVersions bool + matchMeta map[string]*regexp.Regexp + matchTags map[string]*regexp.Regexp // Internal values targetAlias string @@ -295,25 +295,25 @@ } return doFind(ctx, &findContext{ - Context: cliCtx, - maxDepth: cliCtx.Uint("maxdepth"), - execCmd: cliCtx.String("exec"), - printFmt: cliCtx.String("print"), - namePattern: cliCtx.String("name"), - pathPattern: cliCtx.String("path"), - regexPattern: regMatch, - ignorePattern: cliCtx.String("ignore"), - withOlderVersions: withVersions, - olderThan: olderThan, - newerThan: newerThan, - largerSize: largerSize, - smallerSize: smallerSize, - watch: cliCtx.Bool("watch"), - targetAlias: targetAlias, - targetURL: args[0], - targetFullURL: targetFullURL, - clnt: clnt, - matchMeta: getRegexMap(cliCtx, "metadata"), - matchTags: getRegexMap(cliCtx, "tags"), + Context: cliCtx, + maxDepth: cliCtx.Uint("maxdepth"), + execCmd: cliCtx.String("exec"), + printFmt: cliCtx.String("print"), + namePattern: cliCtx.String("name"), + pathPattern: cliCtx.String("path"), + regexPattern: regMatch, + ignorePattern: cliCtx.String("ignore"), + withVersions: withVersions, + olderThan: olderThan, + newerThan: newerThan, + largerSize: largerSize, + smallerSize: smallerSize, + watch: cliCtx.Bool("watch"), + targetAlias: targetAlias, + targetURL: args[0], + targetFullURL: targetFullURL, + clnt: clnt, + matchMeta: getRegexMap(cliCtx, "metadata"), + matchTags: getRegexMap(cliCtx, "tags"), }) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/cmd/find.go new/mc-20240620T145054Z/cmd/find.go --- old/mc-20240612T143403Z/cmd/find.go 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/cmd/find.go 2024-06-20 16:50:54.000000000 +0200 @@ -272,7 +272,7 @@ defer watchFind(ctxCtx, ctx) lstOptions := ListOptions{ - WithOlderVersions: ctx.withOlderVersions, + WithOlderVersions: ctx.withVersions, WithDeleteMarkers: false, Recursive: true, ShowDir: DirFirst, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/cmd/flags.go new/mc-20240620T145054Z/cmd/flags.go --- old/mc-20240612T143403Z/cmd/flags.go 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/cmd/flags.go 2024-06-20 16:50:54.000000000 +0200 @@ -97,7 +97,7 @@ var encCFlag = cli.StringSliceFlag{ Name: "enc-c", - Usage: "encrypt/decrypt objects using client provided keys. (multiple keys can be provided) Format: Raw base64 encoding.", + Usage: "encrypt/decrypt objects using client provided keys. (multiple keys can be provided) Formats: RawBase64 or Hex.", } var encKSMFlag = cli.StringSliceFlag{ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/cmd/get-main.go new/mc-20240620T145054Z/cmd/get-main.go --- old/mc-20240612T143403Z/cmd/get-main.go 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/cmd/get-main.go 2024-06-20 16:50:54.000000000 +0200 @@ -27,7 +27,12 @@ // get command flags. var ( - getFlags = []cli.Flag{} + getFlags = []cli.Flag{ + cli.StringFlag{ + Name: "version-id, vid", + Usage: "get a specific version of an object", + }, + } ) // Get command. @@ -50,10 +55,10 @@ EXAMPLES: 1. Get an object from MinIO storage to local file system - {{.Prompt}} {{.HelpName}} play/mybucket/object path-to/object + {{.Prompt}} {{.HelpName}} play/mybucket/object path-to/object 2. Get an object from MinIO storage using encryption - {{.Prompt}} {{.HelpName}} --enc-c "play/mybucket/object=MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDA" play/mybucket/object path-to/object + {{.Prompt}} {{.HelpName}} --enc-c "play/mybucket/object=MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDA" play/mybucket/object path-to/object `, } @@ -94,6 +99,7 @@ targetURL: targetURL, encKeyDB: encryptionKeys, ignoreBucketExistsCheck: true, + versionID: cliCtx.String("version-id"), } for getURLs := range prepareGetURLs(ctx, opts) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/cmd/legalhold-info.go new/mc-20240620T145054Z/cmd/legalhold-info.go --- old/mc-20240612T143403Z/cmd/legalhold-info.go 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/cmd/legalhold-info.go 2024-06-20 16:50:54.000000000 +0200 @@ -129,7 +129,7 @@ } // showLegalHoldInfo - show legalhold for one or many objects within a given prefix, with or without versioning -func showLegalHoldInfo(ctx context.Context, urlStr, versionID string, timeRef time.Time, withOlderVersions, recursive bool) error { +func showLegalHoldInfo(ctx context.Context, urlStr, versionID string, timeRef time.Time, withVersions, recursive bool) error { clnt, err := newClient(urlStr) if err != nil { fatalIf(err.Trace(), "Unable to parse the provided url.") @@ -142,7 +142,7 @@ } prefixPath = strings.TrimPrefix(prefixPath, "./") - if !recursive && !withOlderVersions { + if !recursive && !withVersions { lhold, err := clnt.GetObjectLegalHold(ctx, versionID) if err != nil { fatalIf(err.Trace(urlStr), "Failed to show legal hold information of `"+urlStr+"`.") @@ -167,7 +167,7 @@ objectsFound := false lstOptions := ListOptions{Recursive: recursive, ShowDir: DirNone} if !timeRef.IsZero() { - lstOptions.WithOlderVersions = withOlderVersions + lstOptions.WithOlderVersions = withVersions lstOptions.TimeRef = timeRef } for content := range clnt.List(ctx, lstOptions) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/cmd/legalhold-set.go new/mc-20240620T145054Z/cmd/legalhold-set.go --- old/mc-20240612T143403Z/cmd/legalhold-set.go 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/cmd/legalhold-set.go 2024-06-20 16:50:54.000000000 +0200 @@ -82,7 +82,7 @@ } // setLegalHold - Set legalhold for all objects within a given prefix. -func setLegalHold(ctx context.Context, urlStr, versionID string, timeRef time.Time, withOlderVersions, recursive bool, lhold minio.LegalHoldStatus) error { +func setLegalHold(ctx context.Context, urlStr, versionID string, timeRef time.Time, withVersions, recursive bool, lhold minio.LegalHoldStatus) error { clnt, err := newClient(urlStr) if err != nil { fatalIf(err.Trace(), "Unable to parse the provided url.") @@ -95,7 +95,7 @@ } prefixPath = strings.TrimPrefix(prefixPath, "./") - if !recursive && !withOlderVersions { + if !recursive && !withVersions { err = clnt.PutObjectLegalHold(ctx, versionID, lhold) if err != nil { errorIf(err.Trace(urlStr), "Failed to set legal hold on `"+urlStr+"` successfully") @@ -119,7 +119,7 @@ objectsFound := false lstOptions := ListOptions{Recursive: recursive, ShowDir: DirNone} if !timeRef.IsZero() { - lstOptions.WithOlderVersions = withOlderVersions + lstOptions.WithOlderVersions = withVersions lstOptions.TimeRef = timeRef } for content := range clnt.List(ctx, lstOptions) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/cmd/ls-main.go new/mc-20240620T145054Z/cmd/ls-main.go --- old/mc-20240612T143403Z/cmd/ls-main.go 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/cmd/ls-main.go 2024-06-20 16:50:54.000000000 +0200 @@ -170,24 +170,24 @@ isRecursive := cliCtx.Bool("recursive") isIncomplete := cliCtx.Bool("incomplete") - withOlderVersions := cliCtx.Bool("versions") + withVersions := cliCtx.Bool("versions") isSummary := cliCtx.Bool("summarize") listZip := cliCtx.Bool("zip") timeRef := parseRewindFlag(cliCtx.String("rewind")) - if listZip && (withOlderVersions || !timeRef.IsZero()) { + if listZip && (withVersions || !timeRef.IsZero()) { fatalIf(errInvalidArgument().Trace(args...), "Zip file listing can only be performed on the latest version") } storageClasss := cliCtx.String("storage-class") opts := doListOptions{ - timeRef: timeRef, - isRecursive: isRecursive, - isIncomplete: isIncomplete, - isSummary: isSummary, - withOlderVersions: withOlderVersions, - listZip: listZip, - filter: storageClasss, + timeRef: timeRef, + isRecursive: isRecursive, + isIncomplete: isIncomplete, + isSummary: isSummary, + withVersions: withVersions, + listZip: listZip, + filter: storageClasss, } return args, opts } @@ -218,7 +218,7 @@ fatalIf(err.Trace(targetURL), "Unable to initialize target `"+targetURL+"`.") if !strings.HasSuffix(targetURL, string(clnt.GetURL().Separator)) { var st *ClientContent - st, err = clnt.Stat(ctx, StatOptions{incomplete: opts.isIncomplete}) + st, err = clnt.Stat(ctx, StatOptions{incomplete: opts.isIncomplete, includeVersions: opts.withVersions}) if st != nil && err == nil && st.Type.IsDir() { targetURL = targetURL + string(clnt.GetURL().Separator) clnt, err = newClient(targetURL) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/cmd/ls.go new/mc-20240620T145054Z/cmd/ls.go --- old/mc-20240612T143403Z/cmd/ls.go 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/cmd/ls.go 2024-06-20 16:50:54.000000000 +0200 @@ -207,13 +207,13 @@ } type doListOptions struct { - timeRef time.Time - isRecursive bool - isIncomplete bool - isSummary bool - withOlderVersions bool - listZip bool - filter string + timeRef time.Time + isRecursive bool + isIncomplete bool + isSummary bool + withVersions bool + listZip bool + filter string } // doList - list all entities inside a folder. @@ -230,7 +230,7 @@ Recursive: o.isRecursive, Incomplete: o.isIncomplete, TimeRef: o.timeRef, - WithOlderVersions: o.withOlderVersions || !o.timeRef.IsZero(), + WithOlderVersions: o.withVersions || !o.timeRef.IsZero(), WithDeleteMarkers: true, ShowDir: DirNone, ListZip: o.listZip, @@ -247,7 +247,7 @@ if lastPath != content.URL.Path { // Print any object in the current list before reinitializing it - printObjectVersions(clnt.GetURL(), perObjectVersions, o.withOlderVersions) + printObjectVersions(clnt.GetURL(), perObjectVersions, o.withVersions) lastPath = content.URL.Path perObjectVersions = []*ClientContent{} } @@ -257,7 +257,7 @@ totalObjects++ } - printObjectVersions(clnt.GetURL(), perObjectVersions, o.withOlderVersions) + printObjectVersions(clnt.GetURL(), perObjectVersions, o.withVersions) if o.isSummary { printMsg(summaryMessage{ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/cmd/put-main.go new/mc-20240620T145054Z/cmd/put-main.go --- old/mc-20240612T143403Z/cmd/put-main.go 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/cmd/put-main.go 2024-06-20 16:50:54.000000000 +0200 @@ -41,6 +41,11 @@ Usage: "each part size", Value: "16MiB", }, + cli.BoolFlag{ + Name: "if-not-exists", + Usage: "upload only if object does not exist", + Hidden: true, + }, } ) @@ -68,19 +73,19 @@ EXAMPLES: 1. Put an object from local file system to S3 storage - {{.Prompt}} {{.HelpName}} path-to/object play/mybucket + {{.Prompt}} {{.HelpName}} path-to/object play/mybucket 2. Put an object from local file system to S3 bucket with name - {{.Prompt}} {{.HelpName}} path-to/object play/mybucket/object + {{.Prompt}} {{.HelpName}} path-to/object play/mybucket/object 3. Put an object from local file system to S3 bucket under a prefix - {{.Prompt}} {{.HelpName}} path-to/object play/mybucket/object-prefix/ + {{.Prompt}} {{.HelpName}} path-to/object play/mybucket/object-prefix/ - 4. Put an object to MinIO storage using sse-c encryption - {{.Prompt}} {{.HelpName}} --enc-c "play/mybucket/object=MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDA" path-to/object play/mybucket/object + 4. Put an object to MinIO storage using sse-c encryption + {{.Prompt}} {{.HelpName}} --enc-c "play/mybucket/object=MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDA" path-to/object play/mybucket/object - 5. Put an object to MinIO storage using sse-kms encryption - {{.Prompt}} {{.HelpName}} --enc-kms path-to/object play/mybucket/object + 5. Put an object to MinIO storage using sse-kms encryption + {{.Prompt}} {{.HelpName}} --enc-kms path-to/object play/mybucket/object `, } @@ -93,11 +98,13 @@ ctx, cancelPut := context.WithCancel(globalContext) defer cancelPut() + // part size size := cliCtx.String("s") if size == "" { - size = "16mb" + size = "32MiB" } + _, perr := humanize.ParseBytes(size) if perr != nil { fatalIf(probe.NewError(perr), "Unable to parse part size") @@ -175,10 +182,11 @@ encryptionKeys: encryptionKeys, multipartSize: size, multipartThreads: strconv.Itoa(threads), + ifNotExists: cliCtx.Bool("if-not-exists"), }) if urls.Error != nil { - e = urls.Error.ToGoError() - showLastProgressBar(pg, e) + showLastProgressBar(pg, urls.Error.ToGoError()) + fatalIf(urls.Error.Trace(), "unable to upload") return } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/cmd/retention-clear.go new/mc-20240620T145054Z/cmd/retention-clear.go --- old/mc-20240612T143403Z/cmd/retention-clear.go 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/cmd/retention-clear.go 2024-06-20 16:50:54.000000000 +0200 @@ -114,8 +114,8 @@ } // Clear Retention for one object/version or many objects within a given prefix, bypass governance is always enabled -func clearRetention(ctx context.Context, target, versionID string, timeRef time.Time, withOlderVersions, isRecursive bool) error { - return applyRetention(ctx, lockOpClear, target, versionID, timeRef, withOlderVersions, isRecursive, "", 0, minio.Days, true) +func clearRetention(ctx context.Context, target, versionID string, timeRef time.Time, withVersions, isRecursive bool) error { + return applyRetention(ctx, lockOpClear, target, versionID, timeRef, withVersions, isRecursive, "", 0, minio.Days, true) } func clearBucketLock(urlStr string) error { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/cmd/retention-common.go new/mc-20240620T145054Z/cmd/retention-common.go --- old/mc-20240612T143403Z/cmd/retention-common.go 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/cmd/retention-common.go 2024-06-20 16:50:54.000000000 +0200 @@ -178,7 +178,7 @@ } // Apply Retention for one object/version or many objects within a given prefix. -func applyRetention(ctx context.Context, op lockOpType, target, versionID string, timeRef time.Time, withOlderVersions, isRecursive bool, +func applyRetention(ctx context.Context, op lockOpType, target, versionID string, timeRef time.Time, withVersions, isRecursive bool, mode minio.RetentionMode, validity uint64, unit minio.ValidityUnit, bypassGovernance bool, ) error { clnt, err := newClient(target) @@ -207,7 +207,7 @@ } alias, urlStr, _ := mustExpandAlias(target) - if versionID != "" || !isRecursive && !withOlderVersions { + if versionID != "" || !isRecursive && !withVersions { err := setRetentionSingle(ctx, op, alias, urlStr, versionID, mode, until, bypassGovernance) fatalIf(err.Trace(), "Unable to set retention on `%s`", target) return nil @@ -215,7 +215,7 @@ lstOptions := ListOptions{Recursive: isRecursive, ShowDir: DirNone} if !timeRef.IsZero() { - lstOptions.WithOlderVersions = withOlderVersions + lstOptions.WithOlderVersions = withVersions lstOptions.WithDeleteMarkers = true lstOptions.TimeRef = timeRef } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/cmd/retention-info.go new/mc-20240620T145054Z/cmd/retention-info.go --- old/mc-20240612T143403Z/cmd/retention-info.go 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/cmd/retention-info.go 2024-06-20 16:50:54.000000000 +0200 @@ -300,7 +300,7 @@ } // Get Retention for one object/version or many objects within a given prefix. -func getRetention(ctx context.Context, target, versionID string, timeRef time.Time, withOlderVersions, isRecursive bool) error { +func getRetention(ctx context.Context, target, versionID string, timeRef time.Time, withVersions, isRecursive bool) error { clnt, err := newClient(target) if err != nil { fatalIf(err.Trace(), "Unable to parse the provided url.") @@ -314,7 +314,7 @@ } alias, urlStr, _ := mustExpandAlias(target) - if versionID != "" || !isRecursive && !withOlderVersions { + if versionID != "" || !isRecursive && !withVersions { err := infoRetentionSingle(ctx, alias, urlStr, versionID, false) if err != nil { if _, ok := err.ToGoError().(ObjectNameEmpty); ok { @@ -327,7 +327,7 @@ lstOptions := ListOptions{Recursive: isRecursive, ShowDir: DirNone} if !timeRef.IsZero() { - lstOptions.WithOlderVersions = withOlderVersions + lstOptions.WithOlderVersions = withVersions lstOptions.WithDeleteMarkers = true lstOptions.TimeRef = timeRef } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/cmd/retention-set.go new/mc-20240620T145054Z/cmd/retention-set.go --- old/mc-20240612T143403Z/cmd/retention-set.go 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/cmd/retention-set.go 2024-06-20 16:50:54.000000000 +0200 @@ -128,10 +128,10 @@ } // Set Retention for one object/version or many objects within a given prefix. -func setRetention(ctx context.Context, target, versionID string, timeRef time.Time, withOlderVersions, isRecursive bool, +func setRetention(ctx context.Context, target, versionID string, timeRef time.Time, withVersions, isRecursive bool, mode minio.RetentionMode, validity uint64, unit minio.ValidityUnit, bypassGovernance bool, ) error { - return applyRetention(ctx, lockOpSet, target, versionID, timeRef, withOlderVersions, isRecursive, mode, validity, unit, bypassGovernance) + return applyRetention(ctx, lockOpSet, target, versionID, timeRef, withVersions, isRecursive, mode, validity, unit, bypassGovernance) } func setBucketLock(urlStr string, mode minio.RetentionMode, validity uint64, unit minio.ValidityUnit) error { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/cmd/suite_test.go new/mc-20240620T145054Z/cmd/suite_test.go --- old/mc-20240612T143403Z/cmd/suite_test.go 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/cmd/suite_test.go 2024-06-20 16:50:54.000000000 +0200 @@ -84,6 +84,9 @@ // MC_TEST_ENABLE_HTTPS=true // needs to be set in order to run these tests if protocol == "https://" { + PutObjectWithSSECHexKey(t) + GetObjectWithSSEC(t) + PutObjectWithSSEC(t) PutObjectWithSSECPartialPrefixMatch(t) PutObjectWithSSECMultipart(t) @@ -207,7 +210,8 @@ bucketList = make([]string, 0) userList = make(map[string]TestUser, 0) - // KMS + // ENCRYPTION + sseHexKey = "8fe4d820587c427d5cc207d75cb76f3c6874808174b04050fa209206bfd08ebb" sseBaseEncodedKey = "MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDA" invalidSSEBaseEncodedKey = "MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5" sseBaseEncodedKey2 = "MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5YWE" @@ -1292,6 +1296,22 @@ fatalIfErrorWMsg(err, out, t) } +func PutObjectWithSSECHexKey(t *testing.T) { + file := createFile(newTestFile{ + addToGlobalFileMap: false, + tag: "encputhex", + sizeInMBS: 1, + }) + + out, err := RunMC( + "cp", + "--enc-c="+sseTestBucket+"="+sseHexKey, + file.diskFile.Name(), + sseTestBucket+"/"+file.fileNameWithoutPath, + ) + fatalIfErrorWMsg(err, out, t) +} + func PutObjectWithSSEC(t *testing.T) { file := createFile(newTestFile{ addToGlobalFileMap: false, @@ -1340,6 +1360,36 @@ fatalIfNoErrorWMsg(err, out, t) } +func GetObjectWithSSECHexKey(t *testing.T) { + file := createFile(newTestFile{ + addToGlobalFileMap: false, + tag: "encgethex", + sizeInMBS: 1, + }) + + out, err := RunMC( + "cp", + "--enc-c="+sseTestBucket+"="+sseHexKey, + file.diskFile.Name(), + sseTestBucket+"/"+file.fileNameWithoutPath, + ) + fatalIfErrorWMsg(err, out, t) + + out, err = RunMC( + "cp", + "--enc-c="+sseTestBucket+"="+sseHexKey, + sseTestBucket+"/"+file.fileNameWithoutPath, + file.diskFile.Name()+".download", + ) + fatalIfErrorWMsg(err, out, t) + + md5s, err := openFileAndGetMd5Sum(file.diskFile.Name() + ".download") + fatalIfError(err, t) + if md5s != file.md5Sum { + fatalMsgOnly(fmt.Sprintf("expecting md5sum (%s) but got sum (%s)", file.md5Sum, md5s), t) + } +} + func GetObjectWithSSEC(t *testing.T) { file := createFile(newTestFile{ addToGlobalFileMap: false, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/cmd/tag-list.go new/mc-20240620T145054Z/cmd/tag-list.go --- old/mc-20240612T143403Z/cmd/tag-list.go 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/cmd/tag-list.go 2024-06-20 16:50:54.000000000 +0200 @@ -147,14 +147,14 @@ } // parseTagListSyntax performs command-line input validation for tag list command. -func parseTagListSyntax(ctx *cli.Context) (targetURL, versionID string, timeRef time.Time, withOlderVersions, recursive bool) { +func parseTagListSyntax(ctx *cli.Context) (targetURL, versionID string, timeRef time.Time, withVersions, recursive bool) { if len(ctx.Args()) != 1 { showCommandHelpAndExit(ctx, globalErrorExitStatus) } targetURL = ctx.Args().Get(0) versionID = ctx.String("version-id") - withOlderVersions = ctx.Bool("versions") + withVersions = ctx.Bool("versions") rewind := ctx.String("rewind") recursive = ctx.Bool("recursive") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/cmd/tree-main.go new/mc-20240620T145054Z/cmd/tree-main.go --- old/mc-20240612T143403Z/cmd/tree-main.go 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/cmd/tree-main.go 2024-06-20 16:50:54.000000000 +0200 @@ -294,13 +294,13 @@ clnt, err := newClientFromAlias(targetAlias, targetURL) fatalIf(err.Trace(targetURL), "Unable to initialize target `"+targetURL+"`.") opts := doListOptions{ - timeRef: timeRef, - isRecursive: true, - isIncomplete: false, - isSummary: false, - withOlderVersions: false, - listZip: false, - filter: "*", + timeRef: timeRef, + isRecursive: true, + isIncomplete: false, + isSummary: false, + withVersions: false, + listZip: false, + filter: "*", } if e := doList(ctx, clnt, opts); e != nil { cErr = e diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/cmd/typed-errors.go new/mc-20240620T145054Z/cmd/typed-errors.go --- old/mc-20240612T143403Z/cmd/typed-errors.go 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/cmd/typed-errors.go 2024-06-20 16:50:54.000000000 +0200 @@ -187,7 +187,7 @@ type sseClientKeyFormatErr error var errSSEClientKeyFormat = func(msg string) *probe.Error { - m := "Encryption key should be 44 bytes raw base64 encoded key." + m := "Encryption key should be either raw base64 encoded or hex encoded. " m += msg return probe.NewError(sseClientKeyFormatErr(errors.New(m))).Untrace() } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/functional-tests.sh new/mc-20240620T145054Z/functional-tests.sh --- old/mc-20240612T143403Z/functional-tests.sh 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/functional-tests.sh 2024-06-20 16:50:54.000000000 +0200 @@ -1038,7 +1038,6 @@ test_copy_object_preserve_filesystem_attr test_find test_find_empty - test_bucket_replication if [ -z "$MINT_MODE" ]; then test_watch_object fi diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/go.mod new/mc-20240620T145054Z/go.mod --- old/mc-20240612T143403Z/go.mod 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/go.mod 2024-06-20 16:50:54.000000000 +0200 @@ -19,7 +19,7 @@ github.com/minio/colorjson v1.0.7 github.com/minio/filepath v1.0.0 github.com/minio/md5-simd v1.1.2 // indirect - github.com/minio/minio-go/v7 v7.0.70 + github.com/minio/minio-go/v7 v7.0.72-0.20240618070918-0b004e328e1e github.com/mitchellh/go-homedir v1.1.0 github.com/pkg/xattr v0.4.9 github.com/posener/complete v1.2.3 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mc-20240612T143403Z/go.sum new/mc-20240620T145054Z/go.sum --- old/mc-20240612T143403Z/go.sum 2024-06-12 16:34:03.000000000 +0200 +++ new/mc-20240620T145054Z/go.sum 2024-06-20 16:50:54.000000000 +0200 @@ -134,8 +134,8 @@ github.com/minio/madmin-go/v3 v3.0.55-0.20240603092915-420a67132c32/go.mod h1:IFAwr0XMrdsLovxAdCcuq/eoL4nRuMVQQv0iubJANQw= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= -github.com/minio/minio-go/v7 v7.0.70 h1:1u9NtMgfK1U42kUxcsl5v0yj6TEOPR497OAQxpJnn2g= -github.com/minio/minio-go/v7 v7.0.70/go.mod h1:4yBA8v80xGA30cfM3fz0DKYMXunWl/AV/6tWEs9ryzo= +github.com/minio/minio-go/v7 v7.0.72-0.20240618070918-0b004e328e1e h1:Ye/gsaKgKD9lg1BgjG5fsGZdKevVpJO9bzqQg7badV8= +github.com/minio/minio-go/v7 v7.0.72-0.20240618070918-0b004e328e1e/go.mod h1:4yBA8v80xGA30cfM3fz0DKYMXunWl/AV/6tWEs9ryzo= github.com/minio/mux v1.9.0 h1:dWafQFyEfGhJvK6AwLOt83bIG5bxKxKJnKMCi0XAaoA= github.com/minio/mux v1.9.0/go.mod h1:1pAare17ZRL5GpmNL+9YmqHoWnLmMZF9C/ioUCfy0BQ= github.com/minio/pkg/v3 v3.0.0 h1:0vOKHgwpya//mb7RH0i1lyPMH2IBBF5hJMNY5Bk2WlY= ++++++ mc.obsinfo ++++++ --- /var/tmp/diff_new_pack.uZEvXv/_old 2024-06-24 20:53:14.068180163 +0200 +++ /var/tmp/diff_new_pack.uZEvXv/_new 2024-06-24 20:53:14.072180309 +0200 @@ -1,5 +1,5 @@ name: mc -version: 20240612T143403Z -mtime: 1718202843 -commit: e7c9a733c680fe62066d24e8718f81938b4f6606 +version: 20240620T145054Z +mtime: 1718895054 +commit: dda9e96887a452b60f23ef18ea68e8898836c017 ++++++ vendor.tar.gz ++++++ /work/SRC/openSUSE:Factory/minio-client/vendor.tar.gz /work/SRC/openSUSE:Factory/.minio-client.new.18349/vendor.tar.gz differ: char 5, line 1