mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-11 05:57:08 +08:00
vendor: update to compose-go 1.13.4
Signed-off-by: Nick Sieger <nick@nicksieger.com>
This commit is contained in:
12
vendor/github.com/compose-spec/compose-go/loader/full-example.yml
generated
vendored
12
vendor/github.com/compose-spec/compose-go/loader/full-example.yml
generated
vendored
@ -1,7 +1,13 @@
|
||||
name: Full_Example_project_name
|
||||
name: full_example_project_name
|
||||
services:
|
||||
foo:
|
||||
|
||||
bar:
|
||||
build:
|
||||
dockerfile_inline: |
|
||||
FROM alpine
|
||||
RUN echo "hello" > /world.txt
|
||||
|
||||
foo:
|
||||
build:
|
||||
context: ./dir
|
||||
dockerfile: Dockerfile
|
||||
@ -15,6 +21,8 @@ services:
|
||||
- foo
|
||||
- bar
|
||||
labels: [FOO=BAR]
|
||||
additional_contexts:
|
||||
foo: /bar
|
||||
secrets:
|
||||
- secret1
|
||||
- source: secret2
|
||||
|
11
vendor/github.com/compose-spec/compose-go/loader/interpolate.go
generated
vendored
11
vendor/github.com/compose-spec/compose-go/loader/interpolate.go
generated
vendored
@ -22,6 +22,7 @@ import (
|
||||
|
||||
interp "github.com/compose-spec/compose-go/interpolation"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var interpolateTypeCastMapping = map[interp.Path]interp.Cast{
|
||||
@ -114,9 +115,15 @@ func toFloat32(value string) (interface{}, error) {
|
||||
// should match http://yaml.org/type/bool.html
|
||||
func toBoolean(value string) (interface{}, error) {
|
||||
switch strings.ToLower(value) {
|
||||
case "y", "yes", "true", "on":
|
||||
case "true":
|
||||
return true, nil
|
||||
case "n", "no", "false", "off":
|
||||
case "false":
|
||||
return false, nil
|
||||
case "y", "yes", "on":
|
||||
logrus.Warnf("%q for boolean is not supported by YAML 1.2, please use `true`", value)
|
||||
return true, nil
|
||||
case "n", "no", "off":
|
||||
logrus.Warnf("%q for boolean is not supported by YAML 1.2, please use `false`", value)
|
||||
return false, nil
|
||||
default:
|
||||
return nil, errors.Errorf("invalid boolean: %s", value)
|
||||
|
153
vendor/github.com/compose-spec/compose-go/loader/loader.go
generated
vendored
153
vendor/github.com/compose-spec/compose-go/loader/loader.go
generated
vendored
@ -37,7 +37,7 @@ import (
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"gopkg.in/yaml.v2"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// Options supported by Load
|
||||
@ -69,7 +69,7 @@ type Options struct {
|
||||
}
|
||||
|
||||
func (o *Options) SetProjectName(name string, imperativelySet bool) {
|
||||
o.projectName = NormalizeProjectName(name)
|
||||
o.projectName = name
|
||||
o.projectNameImperativelySet = imperativelySet
|
||||
}
|
||||
|
||||
@ -138,6 +138,14 @@ func ParseYAML(source []byte) (map[string]interface{}, error) {
|
||||
if err := yaml.Unmarshal(source, &cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stringMap, ok := cfg.(map[string]interface{})
|
||||
if ok {
|
||||
converted, err := convertToStringKeysRecursive(stringMap, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return converted.(map[string]interface{}), nil
|
||||
}
|
||||
cfgMap, ok := cfg.(map[interface{}]interface{})
|
||||
if !ok {
|
||||
return nil, errors.Errorf("Top-level object must be a mapping")
|
||||
@ -185,7 +193,7 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types.
|
||||
}
|
||||
dict, err := parseConfig(file.Content, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("parsing %s: %w", file.Filename, err)
|
||||
}
|
||||
configDict = dict
|
||||
file.Config = dict
|
||||
@ -194,7 +202,7 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types.
|
||||
|
||||
if !opts.SkipValidation {
|
||||
if err := schema.Validate(configDict); err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("validating %s: %w", file.Filename, err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -233,7 +241,7 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types.
|
||||
}
|
||||
|
||||
if !opts.SkipNormalization {
|
||||
err = normalize(project, opts.ResolvePaths)
|
||||
err = Normalize(project, opts.ResolvePaths)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -246,40 +254,82 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types.
|
||||
}
|
||||
}
|
||||
|
||||
if len(opts.Profiles) > 0 {
|
||||
project.ApplyProfiles(opts.Profiles)
|
||||
if profiles, ok := project.Environment[consts.ComposeProfiles]; ok && len(opts.Profiles) == 0 {
|
||||
opts.Profiles = strings.Split(profiles, ",")
|
||||
}
|
||||
project.ApplyProfiles(opts.Profiles)
|
||||
|
||||
err = project.ResolveServicesEnvironment(opts.discardEnvFiles)
|
||||
|
||||
return project, err
|
||||
}
|
||||
|
||||
func InvalidProjectNameErr(v string) error {
|
||||
return fmt.Errorf(
|
||||
"%q is not a valid project name: it must contain only "+
|
||||
"characters from [a-z0-9_-] and start with [a-z0-9]", v,
|
||||
)
|
||||
}
|
||||
|
||||
// projectName determines the canonical name to use for the project considering
|
||||
// the loader Options as well as `name` fields in Compose YAML fields (which
|
||||
// also support interpolation).
|
||||
//
|
||||
// TODO(milas): restructure loading so that we don't need to re-parse the YAML
|
||||
// here, as it's both wasteful and makes this code error-prone.
|
||||
func projectName(details types.ConfigDetails, opts *Options) (string, error) {
|
||||
projectName, projectNameImperativelySet := opts.GetProjectName()
|
||||
var pjNameFromConfigFile string
|
||||
|
||||
for _, configFile := range details.ConfigFiles {
|
||||
yml, err := ParseYAML(configFile.Content)
|
||||
if err != nil {
|
||||
return "", nil
|
||||
// if user did NOT provide a name explicitly, then see if one is defined
|
||||
// in any of the config files
|
||||
if !projectNameImperativelySet {
|
||||
var pjNameFromConfigFile string
|
||||
for _, configFile := range details.ConfigFiles {
|
||||
yml, err := ParseYAML(configFile.Content)
|
||||
if err != nil {
|
||||
// HACK: the way that loading is currently structured, this is
|
||||
// a duplicative parse just for the `name`. if it fails, we
|
||||
// give up but don't return the error, knowing that it'll get
|
||||
// caught downstream for us
|
||||
return "", nil
|
||||
}
|
||||
if val, ok := yml["name"]; ok && val != "" {
|
||||
sVal, ok := val.(string)
|
||||
if !ok {
|
||||
// HACK: see above - this is a temporary parsed version
|
||||
// that hasn't been schema-validated, but we don't want
|
||||
// to be the ones to actually report that, so give up,
|
||||
// knowing that it'll get caught downstream for us
|
||||
return "", nil
|
||||
}
|
||||
pjNameFromConfigFile = sVal
|
||||
}
|
||||
}
|
||||
if val, ok := yml["name"]; ok && val != "" {
|
||||
pjNameFromConfigFile = yml["name"].(string)
|
||||
if !opts.SkipInterpolation {
|
||||
interpolated, err := interp.Interpolate(
|
||||
map[string]interface{}{"name": pjNameFromConfigFile},
|
||||
*opts.Interpolate,
|
||||
)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
pjNameFromConfigFile = interpolated["name"].(string)
|
||||
}
|
||||
}
|
||||
if !opts.SkipInterpolation {
|
||||
interpolated, err := interp.Interpolate(map[string]interface{}{"name": pjNameFromConfigFile}, *opts.Interpolate)
|
||||
if err != nil {
|
||||
return "", err
|
||||
pjNameFromConfigFile = NormalizeProjectName(pjNameFromConfigFile)
|
||||
if pjNameFromConfigFile != "" {
|
||||
projectName = pjNameFromConfigFile
|
||||
}
|
||||
pjNameFromConfigFile = interpolated["name"].(string)
|
||||
}
|
||||
pjNameFromConfigFile = NormalizeProjectName(pjNameFromConfigFile)
|
||||
if !projectNameImperativelySet && pjNameFromConfigFile != "" {
|
||||
projectName = pjNameFromConfigFile
|
||||
}
|
||||
|
||||
if projectName == "" {
|
||||
return "", errors.New("project name must not be empty")
|
||||
}
|
||||
|
||||
if NormalizeProjectName(projectName) != projectName {
|
||||
return "", InvalidProjectNameErr(projectName)
|
||||
}
|
||||
|
||||
// TODO(milas): this should probably ALWAYS set (overriding any existing)
|
||||
if _, ok := details.Environment[consts.ComposeProjectName]; !ok && projectName != "" {
|
||||
details.Environment[consts.ComposeProjectName] = projectName
|
||||
}
|
||||
@ -304,6 +354,8 @@ func parseConfig(b []byte, opts *Options) (map[string]interface{}, error) {
|
||||
return yml, err
|
||||
}
|
||||
|
||||
const extensions = "#extensions" // Using # prefix, we prevent risk to conflict with an actual yaml key
|
||||
|
||||
func groupXFieldsIntoExtensions(dict map[string]interface{}) map[string]interface{} {
|
||||
extras := map[string]interface{}{}
|
||||
for key, value := range dict {
|
||||
@ -316,7 +368,7 @@ func groupXFieldsIntoExtensions(dict map[string]interface{}) map[string]interfac
|
||||
}
|
||||
}
|
||||
if len(extras) > 0 {
|
||||
dict["extensions"] = extras
|
||||
dict[extensions] = extras
|
||||
}
|
||||
return dict
|
||||
}
|
||||
@ -355,7 +407,7 @@ func loadSections(filename string, config map[string]interface{}, configDetails
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
extensions := getSection(config, "extensions")
|
||||
extensions := getSection(config, extensions)
|
||||
if len(extensions) > 0 {
|
||||
cfg.Extensions = extensions
|
||||
}
|
||||
@ -450,6 +502,22 @@ func createTransformHook(additionalTransformers ...Transformer) mapstructure.Dec
|
||||
|
||||
// keys need to be converted to strings for jsonschema
|
||||
func convertToStringKeysRecursive(value interface{}, keyPrefix string) (interface{}, error) {
|
||||
if mapping, ok := value.(map[string]interface{}); ok {
|
||||
for key, entry := range mapping {
|
||||
var newKeyPrefix string
|
||||
if keyPrefix == "" {
|
||||
newKeyPrefix = key
|
||||
} else {
|
||||
newKeyPrefix = fmt.Sprintf("%s.%s", keyPrefix, key)
|
||||
}
|
||||
convertedEntry, err := convertToStringKeysRecursive(entry, newKeyPrefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mapping[key] = convertedEntry
|
||||
}
|
||||
return mapping, nil
|
||||
}
|
||||
if mapping, ok := value.(map[interface{}]interface{}); ok {
|
||||
dict := make(map[string]interface{})
|
||||
for key, entry := range mapping {
|
||||
@ -501,7 +569,7 @@ func formatInvalidKeyError(keyPrefix string, key interface{}) error {
|
||||
func LoadServices(filename string, servicesDict map[string]interface{}, workingDir string, lookupEnv template.Mapping, opts *Options) ([]types.ServiceConfig, error) {
|
||||
var services []types.ServiceConfig
|
||||
|
||||
x, ok := servicesDict["extensions"]
|
||||
x, ok := servicesDict[extensions]
|
||||
if ok {
|
||||
// as a top-level attribute, "services" doesn't support extensions, and a service can be named `x-foo`
|
||||
for k, v := range x.(map[string]interface{}) {
|
||||
@ -541,16 +609,17 @@ func loadServiceWithExtends(filename, name string, servicesDict map[string]inter
|
||||
}
|
||||
|
||||
if serviceConfig.Extends != nil && !opts.SkipExtends {
|
||||
baseServiceName := *serviceConfig.Extends["service"]
|
||||
baseServiceName := serviceConfig.Extends.Service
|
||||
var baseService *types.ServiceConfig
|
||||
if file := serviceConfig.Extends["file"]; file == nil {
|
||||
file := serviceConfig.Extends.File
|
||||
if file == "" {
|
||||
baseService, err = loadServiceWithExtends(filename, baseServiceName, servicesDict, workingDir, lookupEnv, opts, ct)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
// Resolve the path to the imported file, and load it.
|
||||
baseFilePath := absPath(workingDir, *file)
|
||||
baseFilePath := absPath(workingDir, file)
|
||||
|
||||
b, err := os.ReadFile(baseFilePath)
|
||||
if err != nil {
|
||||
@ -569,10 +638,10 @@ func loadServiceWithExtends(filename, name string, servicesDict map[string]inter
|
||||
}
|
||||
|
||||
// Make paths relative to the importing Compose file. Note that we
|
||||
// make the paths relative to `*file` rather than `baseFilePath` so
|
||||
// that the resulting paths won't be absolute if `*file` isn't an
|
||||
// make the paths relative to `file` rather than `baseFilePath` so
|
||||
// that the resulting paths won't be absolute if `file` isn't an
|
||||
// absolute path.
|
||||
baseFileParent := filepath.Dir(*file)
|
||||
baseFileParent := filepath.Dir(file)
|
||||
if baseService.Build != nil {
|
||||
baseService.Build.Context = resolveBuildContextPath(baseFileParent, baseService.Build.Context)
|
||||
}
|
||||
@ -583,12 +652,17 @@ func loadServiceWithExtends(filename, name string, servicesDict map[string]inter
|
||||
}
|
||||
baseService.Volumes[i].Source = resolveMaybeUnixPath(vol.Source, baseFileParent, lookupEnv)
|
||||
}
|
||||
|
||||
for i, envFile := range baseService.EnvFile {
|
||||
baseService.EnvFile[i] = resolveMaybeUnixPath(envFile, baseFileParent, lookupEnv)
|
||||
}
|
||||
}
|
||||
|
||||
serviceConfig, err = _merge(baseService, serviceConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
serviceConfig.Extends = nil
|
||||
}
|
||||
|
||||
return serviceConfig, nil
|
||||
@ -996,14 +1070,15 @@ var transformDependsOnConfig TransformerFunc = func(data interface{}) (interface
|
||||
}
|
||||
}
|
||||
|
||||
var transformExtendsConfig TransformerFunc = func(data interface{}) (interface{}, error) {
|
||||
switch data.(type) {
|
||||
var transformExtendsConfig TransformerFunc = func(value interface{}) (interface{}, error) {
|
||||
switch value.(type) {
|
||||
case string:
|
||||
data = map[string]interface{}{
|
||||
"service": data,
|
||||
}
|
||||
return map[string]interface{}{"service": value}, nil
|
||||
case map[string]interface{}:
|
||||
return value, nil
|
||||
default:
|
||||
return value, errors.Errorf("invalid type %T for extends", value)
|
||||
}
|
||||
return transformMappingOrListFunc("=", true)(data)
|
||||
}
|
||||
|
||||
var transformServiceVolumeConfig TransformerFunc = func(data interface{}) (interface{}, error) {
|
||||
|
2
vendor/github.com/compose-spec/compose-go/loader/merge.go
generated
vendored
2
vendor/github.com/compose-spec/compose-go/loader/merge.go
generated
vendored
@ -130,7 +130,7 @@ func _merge(baseService *types.ServiceConfig, overrideService *types.ServiceConf
|
||||
if overrideService.Command != nil {
|
||||
baseService.Command = overrideService.Command
|
||||
}
|
||||
if overrideService.HealthCheck != nil {
|
||||
if overrideService.HealthCheck != nil && overrideService.HealthCheck.Test != nil {
|
||||
baseService.HealthCheck.Test = overrideService.HealthCheck.Test
|
||||
}
|
||||
if overrideService.Entrypoint != nil {
|
||||
|
76
vendor/github.com/compose-spec/compose-go/loader/normalize.go
generated
vendored
76
vendor/github.com/compose-spec/compose-go/loader/normalize.go
generated
vendored
@ -20,6 +20,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/compose-spec/compose-go/errdefs"
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
@ -27,8 +28,8 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// normalize compose project by moving deprecated attributes to their canonical position and injecting implicit defaults
|
||||
func normalize(project *types.Project, resolvePaths bool) error {
|
||||
// Normalize compose project by moving deprecated attributes to their canonical position and injecting implicit defaults
|
||||
func Normalize(project *types.Project, resolvePaths bool) error {
|
||||
absWorkingDir, err := filepath.Abs(project.WorkingDir)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -71,17 +72,26 @@ func normalize(project *types.Project, resolvePaths bool) error {
|
||||
}
|
||||
|
||||
if s.Build != nil {
|
||||
if s.Build.Dockerfile == "" {
|
||||
if s.Build.Dockerfile == "" && s.Build.DockerfileInline == "" {
|
||||
s.Build.Dockerfile = "Dockerfile"
|
||||
}
|
||||
localContext := absPath(project.WorkingDir, s.Build.Context)
|
||||
if _, err := os.Stat(localContext); err == nil {
|
||||
if resolvePaths {
|
||||
if resolvePaths {
|
||||
// Build context might be a remote http/git context. Unfortunately supported "remote"
|
||||
// syntax is highly ambiguous in moby/moby and not defined by compose-spec,
|
||||
// so let's assume runtime will check
|
||||
localContext := absPath(project.WorkingDir, s.Build.Context)
|
||||
if _, err := os.Stat(localContext); err == nil {
|
||||
s.Build.Context = localContext
|
||||
}
|
||||
// } else {
|
||||
// might be a remote http/git context. Unfortunately supported "remote" syntax is highly ambiguous
|
||||
// in moby/moby and not defined by compose-spec, so let's assume runtime will check
|
||||
for name, path := range s.Build.AdditionalContexts {
|
||||
if strings.Contains(path, "://") { // `docker-image://` or any builder specific context type
|
||||
continue
|
||||
}
|
||||
path = absPath(project.WorkingDir, path)
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
s.Build.AdditionalContexts[name] = path
|
||||
}
|
||||
}
|
||||
}
|
||||
s.Build.Args = s.Build.Args.Resolve(fn)
|
||||
}
|
||||
@ -90,6 +100,41 @@ func normalize(project *types.Project, resolvePaths bool) error {
|
||||
}
|
||||
s.Environment = s.Environment.Resolve(fn)
|
||||
|
||||
if s.Extends != nil && s.Extends.File != "" {
|
||||
s.Extends.File = absPath(project.WorkingDir, s.Extends.File)
|
||||
}
|
||||
|
||||
for _, link := range s.Links {
|
||||
parts := strings.Split(link, ":")
|
||||
if len(parts) == 2 {
|
||||
link = parts[0]
|
||||
}
|
||||
s.DependsOn = setIfMissing(s.DependsOn, link, types.ServiceDependency{
|
||||
Condition: types.ServiceConditionStarted,
|
||||
Restart: true,
|
||||
})
|
||||
}
|
||||
|
||||
for _, namespace := range []string{s.NetworkMode, s.Ipc, s.Pid, s.Uts, s.Cgroup} {
|
||||
if strings.HasPrefix(namespace, types.ServicePrefix) {
|
||||
name := namespace[len(types.ServicePrefix):]
|
||||
s.DependsOn = setIfMissing(s.DependsOn, name, types.ServiceDependency{
|
||||
Condition: types.ServiceConditionStarted,
|
||||
Restart: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for _, vol := range s.VolumesFrom {
|
||||
if !strings.HasPrefix(vol, types.ContainerPrefix) {
|
||||
spec := strings.Split(vol, ":")
|
||||
s.DependsOn = setIfMissing(s.DependsOn, spec[0], types.ServiceDependency{
|
||||
Condition: types.ServiceConditionStarted,
|
||||
Restart: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
err := relocateLogDriver(&s)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -126,9 +171,20 @@ func normalize(project *types.Project, resolvePaths bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// setIfMissing adds a ServiceDependency for service if not already defined
|
||||
func setIfMissing(d types.DependsOnConfig, service string, dep types.ServiceDependency) types.DependsOnConfig {
|
||||
if d == nil {
|
||||
d = types.DependsOnConfig{}
|
||||
}
|
||||
if _, ok := d[service]; !ok {
|
||||
d[service] = dep
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
func relocateScale(s *types.ServiceConfig) error {
|
||||
scale := uint64(s.Scale)
|
||||
if scale != 1 {
|
||||
if scale > 1 {
|
||||
logrus.Warn("`scale` is deprecated. Use the `deploy.replicas` element")
|
||||
if s.Deploy == nil {
|
||||
s.Deploy = &types.DeployConfig{}
|
||||
|
22
vendor/github.com/compose-spec/compose-go/loader/validate.go
generated
vendored
22
vendor/github.com/compose-spec/compose-go/loader/validate.go
generated
vendored
@ -32,6 +32,28 @@ func checkConsistency(project *types.Project) error {
|
||||
return errors.Wrapf(errdefs.ErrInvalid, "service %q has neither an image nor a build context specified", s.Name)
|
||||
}
|
||||
|
||||
if s.Build != nil {
|
||||
if s.Build.DockerfileInline != "" && s.Build.Dockerfile != "" {
|
||||
return errors.Wrapf(errdefs.ErrInvalid, "service %q declares mutualy exclusive dockerfile and dockerfile_inline", s.Name)
|
||||
}
|
||||
|
||||
if len(s.Build.Platforms) > 0 && s.Platform != "" {
|
||||
var found bool
|
||||
for _, platform := range s.Build.Platforms {
|
||||
if platform == s.Platform {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return errors.Wrapf(errdefs.ErrInvalid, "service.build.platforms MUST include service.platform %q ", s.Platform)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if s.NetworkMode != "" && len(s.Networks) > 0 {
|
||||
return errors.Wrap(errdefs.ErrInvalid, fmt.Sprintf("service %s declares mutually exclusive `network_mode` and `networks`", s.Name))
|
||||
}
|
||||
for network := range s.Networks {
|
||||
if _, ok := project.Networks[network]; !ok {
|
||||
return errors.Wrap(errdefs.ErrInvalid, fmt.Sprintf("service %q refers to undefined network %s", s.Name, network))
|
||||
|
2
vendor/github.com/compose-spec/compose-go/loader/windows_path.go
generated
vendored
2
vendor/github.com/compose-spec/compose-go/loader/windows_path.go
generated
vendored
@ -44,7 +44,7 @@ func isAbs(path string) (b bool) {
|
||||
|
||||
// volumeNameLen returns length of the leading volume name on Windows.
|
||||
// It returns 0 elsewhere.
|
||||
//nolint: gocyclo
|
||||
// nolint: gocyclo
|
||||
func volumeNameLen(path string) int {
|
||||
if len(path) < 2 {
|
||||
return 0
|
||||
|
Reference in New Issue
Block a user