mirror of
https://github.com/moby/buildkit.git
synced 2026-11-06 05:16:45 +00:00
Currently, eStargz compression doesn't preserve the original tar metadata (header bytes and their order). This causes failure of `TestGetRemote` because an uncompressed blob converted from a gzip blob provides different digset against the one converted from eStargz blob even if their original tar (computed by differ) are the same. This commit solves this issue by fixing eStargz to preserve original tar's metadata that is modified by eStargz. Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
95 lines
2.4 KiB
Go
95 lines
2.4 KiB
Go
package cli
|
|
|
|
import (
|
|
"flag"
|
|
"strings"
|
|
)
|
|
|
|
type iterativeParser interface {
|
|
newFlagSet() (*flag.FlagSet, error)
|
|
useShortOptionHandling() bool
|
|
}
|
|
|
|
// To enable short-option handling (e.g., "-it" vs "-i -t") we have to
|
|
// iteratively catch parsing errors. This way we achieve LR parsing without
|
|
// transforming any arguments. Otherwise, there is no way we can discriminate
|
|
// combined short options from common arguments that should be left untouched.
|
|
// Pass `shellComplete` to continue parsing options on failure during shell
|
|
// completion when, the user-supplied options may be incomplete.
|
|
func parseIter(set *flag.FlagSet, ip iterativeParser, args []string, shellComplete bool) error {
|
|
for {
|
|
err := set.Parse(args)
|
|
if !ip.useShortOptionHandling() || err == nil {
|
|
if shellComplete {
|
|
return nil
|
|
}
|
|
return err
|
|
}
|
|
|
|
errStr := err.Error()
|
|
trimmed := strings.TrimPrefix(errStr, "flag provided but not defined: -")
|
|
if errStr == trimmed {
|
|
return err
|
|
}
|
|
|
|
// regenerate the initial args with the split short opts
|
|
argsWereSplit := false
|
|
for i, arg := range args {
|
|
// skip args that are not part of the error message
|
|
if name := strings.TrimLeft(arg, "-"); name != trimmed {
|
|
continue
|
|
}
|
|
|
|
// if we can't split, the error was accurate
|
|
shortOpts := splitShortOptions(set, arg)
|
|
if len(shortOpts) == 1 {
|
|
return err
|
|
}
|
|
|
|
// swap current argument with the split version
|
|
args = append(args[:i], append(shortOpts, args[i+1:]...)...)
|
|
argsWereSplit = true
|
|
break
|
|
}
|
|
|
|
// This should be an impossible to reach code path, but in case the arg
|
|
// splitting failed to happen, this will prevent infinite loops
|
|
if !argsWereSplit {
|
|
return err
|
|
}
|
|
|
|
// Since custom parsing failed, replace the flag set before retrying
|
|
newSet, err := ip.newFlagSet()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
*set = *newSet
|
|
}
|
|
}
|
|
|
|
func splitShortOptions(set *flag.FlagSet, arg string) []string {
|
|
shortFlagsExist := func(s string) bool {
|
|
for _, c := range s[1:] {
|
|
if f := set.Lookup(string(c)); f == nil {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
if !isSplittable(arg) || !shortFlagsExist(arg) {
|
|
return []string{arg}
|
|
}
|
|
|
|
separated := make([]string, 0, len(arg)-1)
|
|
for _, flagChar := range arg[1:] {
|
|
separated = append(separated, "-"+string(flagChar))
|
|
}
|
|
|
|
return separated
|
|
}
|
|
|
|
func isSplittable(flagArg string) bool {
|
|
return strings.HasPrefix(flagArg, "-") && !strings.HasPrefix(flagArg, "--") && len(flagArg) > 2
|
|
}
|