<commit_before>package config

import (
	"io/ioutil"

	"gopkg.in/flant/yaml.v2"
	"github.com/flant/dapp/pkg/config/ruby_marshal_config"
)

func LoadDappfile(dappfilePath string) (interface{}, error) {
	data, err := ioutil.ReadFile(dappfilePath)
	if err != nil {
		return nil, err
	}

	config := &ruby_marshal_config.Config{}
	err = yaml.Unmarshal([]byte(data), &config)
	if err != nil {
		return nil, err
	}

	config = &ruby_marshal_config.Config{
		Dimg: []ruby_marshal_config.Dimg{
			{
				Name:    "assets",
				Builder: "shell",
				GitArtifact: ruby_marshal_config.GitArtifact{
					Local: []ruby_marshal_config.GitArtifactLocal{
						{
							Export: []ruby_marshal_config.GitArtifactLocalExport{
								{
									ArtifactBaseExport: ruby_marshal_config.ArtifactBaseExport{
										Cwd:   "/",
										To:    "/app",
										Owner: "app",
										ExcludePaths: []string{
											".helm",
											"Vagrantfile",
										},
									},
									StageDependencies: ruby_marshal_config.StageDependencies{
										Install: []string{
											"package.json",
										},
									},
								},
							},
						},
					},
				},
			},
		},
	}

	return config, nil
}<commit_msg>Config: парсинг 'dappfile.yaml' * применение go templates;   * поддержка всех методов `sprig`;   * `include` из helm. * деление по `---`.<commit_after>package config

import (
	"bytes"
	"github.com/Masterminds/sprig"
	"text/template"
	"io/ioutil"
	"bufio"
	"strings"
	"gopkg.in/flant/yaml.v2"
	"fmt"
)

func LoadDappfile(dappfilePath string) (interface{}, error) {
	dappfileYaml, err := parseYaml(dappfilePath)
	if err != nil {
		return "", err
	}

	scanner := bufio.NewScanner(strings.NewReader(dappfileYaml))
	scanner.Split(splitYAMLDocument)

	dimgs := []*Dimg{}
	for scanner.Scan() {
		config := &Dimg{}
		err = yaml.Unmarshal(scanner.Bytes(), &config)
		if err != nil {
			return nil, err
		}
		dimgs = append(dimgs, config)
	}

	for _, dimg := range dimgs {
		out, _ := yaml.Marshal(dimg)
		fmt.Printf("%+v\n\n", string(out))
	}

	return dappfileYaml, err
}

func parseYaml(dappfilePath string) (string, error) {
	data, err := ioutil.ReadFile(dappfilePath)
	if err != nil {
		return "", err
	}

	tmpl := template.New("dappfile")
	tmpl.Funcs(funcMap(tmpl))
	if _, err := tmpl.Parse(string(data)); err != nil {
		return "", err
	}
	return executeTemplate(tmpl, "dappfile", nil)
}

func funcMap(tmpl *template.Template) template.FuncMap {
	funcMap := sprig.TxtFuncMap()
	funcMap["include"] = func(name string, data interface{}) (string, error) {
		return executeTemplate(tmpl, name, data)
	}
	return funcMap
}

func executeTemplate(tmpl *template.Template, name string, data interface{}) (string, error) {
	buf := bytes.NewBuffer(nil)
	if err := tmpl.ExecuteTemplate(buf, name, data); err != nil {
		return "", err
	}
	return buf.String(), nil
}

func splitYAMLDocument(data []byte, atEOF bool) (advance int, token []byte, err error) {
	yamlSeparator := "\n---"

	if atEOF && len(data) == 0 {
		return 0, nil, nil
	}
	sep := len([]byte(yamlSeparator))
	if i := bytes.Index(data, []byte(yamlSeparator)); i >= 0 {
		i += sep
		after := data[i:]
		if len(after) == 0 {
			if atEOF {
				return len(data), data[:len(data)-sep], nil
			}
			return 0, nil, nil
		}
		if j := bytes.IndexByte(after, '\n'); j >= 0 {
			return i + j + 1, data[0 : i-sep], nil
		}
		return 0, nil, nil
	}
	if atEOF {
		return len(data), data, nil
	}
	return 0, nil, nil
}
{'fraction_non_alphanumeric': 0.1554524361948956, 'fraction_numerical': 0.0034802784222737818, 'mean_word_length': 3.1554216867469878, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4000990', 'n_tokens_mistral': 1535, 'n_tokens_neox': 1271, 'n_words': 277}