func()

in load.go [120:254]


func (s *Spec) SubstituteArgs(env map[string]string, opts ...SubstituteOpt) error {
	var cfg SubstituteConfig

	cfg.AllowArg = DisallowAllUndeclared

	for _, o := range opts {
		o(&cfg)
	}

	lex := shell.NewLex('\\')
	// force the shell lexer to skip unresolved env vars so they aren't
	// replaced with ""
	lex.SkipUnsetEnv = true

	var errs []error
	appendErr := func(err error) {
		errs = append(errs, err)
	}

	args := make(map[string]string)
	for k, v := range s.Args {
		args[k] = v
	}
	for k, v := range env {
		if _, ok := args[k]; !ok {
			if !knownArg(k) && !cfg.AllowArg(k) {
				appendErr(fmt.Errorf("%w: %q", errUnknownArg, k))
			}

			// if the build arg isn't present in args by opt-in, skip
			// and don't automatically inject a value
			continue
		}

		args[k] = v
	}

	for name, src := range s.Sources {
		if err := src.processBuildArgs(lex, args, cfg.AllowArg); err != nil {
			appendErr(errors.Wrapf(err, "source %q", name))
		}
		s.Sources[name] = src
	}

	for src, patchList := range s.Patches {
		for i, patch := range patchList {
			updated, err := expandArgs(lex, patch.Path, args, cfg.AllowArg)
			if err != nil {
				appendErr(errors.Wrapf(err, "patch %s path %d", src, i))
			}
			s.Patches[src][i].Path = updated
		}
	}

	updated, err := expandArgs(lex, s.Version, args, cfg.AllowArg)
	if err != nil {
		appendErr(errors.Wrap(err, "version"))
	}
	s.Version = updated

	updated, err = expandArgs(lex, s.Revision, args, cfg.AllowArg)
	if err != nil {
		appendErr(errors.Wrap(err, "revision"))
	}
	s.Revision = updated

	if err := s.Build.processBuildArgs(lex, args, cfg.AllowArg); err != nil {
		appendErr(errors.Wrap(err, "build"))
	}

	if s.Build.NetworkMode != "" {
		updated, err := expandArgs(lex, s.Build.NetworkMode, args, cfg.AllowArg)
		if err != nil {
			appendErr(fmt.Errorf("error performing shell expansion on build network mode: %s: %w", s.Build.NetworkMode, err))
		}
		s.Build.NetworkMode = updated
	}

	for i, step := range s.Build.Steps {
		bs := &step
		if err := bs.processBuildArgs(lex, args, cfg.AllowArg); err != nil {
			appendErr(errors.Wrapf(err, "step index %d", i))
		}
		s.Build.Steps[i] = *bs
	}

	for _, t := range s.Tests {
		if err := t.processBuildArgs(lex, args, cfg.AllowArg); err != nil {
			appendErr(err)
		}
	}

	for name, t := range s.Targets {
		if err := t.processBuildArgs(lex, args, cfg.AllowArg); err != nil {
			appendErr(errors.Wrapf(err, "target %s", name))
		}
		s.Targets[name] = t
	}

	if s.PackageConfig != nil {
		if err := s.PackageConfig.processBuildArgs(lex, args, cfg.AllowArg); err != nil {
			appendErr(errors.Wrap(err, "package config"))
		}
	}

	if err := s.Image.processBuildArgs(lex, args, cfg.AllowArg); err != nil {
		appendErr(errors.Wrap(err, "package config"))
	}

	if err := s.Dependencies.processBuildArgs(lex, args, cfg.AllowArg); err != nil {
		appendErr(errors.Wrap(err, "dependencies"))
	}

	for k, v := range s.Provides {
		for i, ver := range v.Version {
			updated, err := expandArgs(lex, ver, args, cfg.AllowArg)
			if err != nil {
				appendErr(errors.Wrapf(err, "provides %s version %d", k, i))
			}
			s.Provides[k].Version[i] = updated
		}
	}

	for k, v := range s.Replaces {
		for i, ver := range v.Version {
			updated, err := expandArgs(lex, ver, args, cfg.AllowArg)
			if err != nil {
				appendErr(errors.Wrapf(err, "replaces %s version %d", k, i))
			}
			s.Replaces[k].Version[i] = updated
		}
	}

	return goerrors.Join(errs...)
}