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).
(details *types.ConfigDetails, opts *Options)
| 673 | // the loader Options as well as `name` fields in Compose YAML fields (which |
| 674 | // also support interpolation). |
| 675 | func projectName(details *types.ConfigDetails, opts *Options) error { |
| 676 | defer func() { |
| 677 | if details.Environment == nil { |
| 678 | details.Environment = map[string]string{} |
| 679 | } |
| 680 | details.Environment[consts.ComposeProjectName] = opts.projectName |
| 681 | }() |
| 682 | |
| 683 | if opts.projectNameImperativelySet { |
| 684 | if NormalizeProjectName(opts.projectName) != opts.projectName { |
| 685 | return InvalidProjectNameErr(opts.projectName) |
| 686 | } |
| 687 | return nil |
| 688 | } |
| 689 | |
| 690 | type named struct { |
| 691 | Name string `yaml:"name"` |
| 692 | } |
| 693 | |
| 694 | // if user did NOT provide a name explicitly, then see if one is defined |
| 695 | // in any of the config files |
| 696 | var pjNameFromConfigFile string |
| 697 | for _, configFile := range details.ConfigFiles { |
| 698 | content := configFile.Content |
| 699 | if content == nil { |
| 700 | // This can be hit when Filename is set but Content is not. One |
| 701 | // example is when using ToConfigFiles(). |
| 702 | d, err := os.ReadFile(configFile.Filename) |
| 703 | if err != nil { |
| 704 | return fmt.Errorf("failed to read file %q: %w", configFile.Filename, err) |
| 705 | } |
| 706 | content = d |
| 707 | configFile.Content = d |
| 708 | } |
| 709 | var n named |
| 710 | r := bytes.NewReader(content) |
| 711 | decoder := yaml.NewDecoder(r) |
| 712 | for { |
| 713 | err := decoder.Decode(&n) |
| 714 | if err != nil && errors.Is(err, io.EOF) { |
| 715 | break |
| 716 | } |
| 717 | if err != nil { |
| 718 | // HACK: the way that loading is currently structured, this is |
| 719 | // a duplicative parse just for the `name`. if it fails, we |
| 720 | // give up but don't return the error, knowing that it'll get |
| 721 | // caught downstream for us |
| 722 | break |
| 723 | } |
| 724 | if n.Name != "" { |
| 725 | pjNameFromConfigFile = n.Name |
| 726 | } |
| 727 | } |
| 728 | } |
| 729 | if !opts.SkipInterpolation { |
| 730 | interpolated, err := interp.Interpolate( |
| 731 | map[string]interface{}{"name": pjNameFromConfigFile}, |
| 732 | *opts.Interpolate, |
no test coverage detected
searching dependent graphs…