func (p *Project) GetSortedInputNames() (sortedInputNames []string) {
	return p.sortedInputNames
}
GetSortedInputNames get sorted input names
package config
import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"sort"
	"strings"
	"github.com/joho/godotenv"
	"github.com/state-alchemists/zaruba/output"
	"github.com/state-alchemists/zaruba/utility"
	yaml "gopkg.in/yaml.v3"
)
type Project struct {
	Name                       string                       `yaml:"name,omitempty"`
	Includes                   []string                     `yaml:"includes,omitempty"`
	Inputs                     map[string]*Variable         `yaml:"inputs,omitempty"`
	Tasks                      map[string]*Task             `yaml:"tasks,omitempty"`
	RawEnvRefMap               map[string]map[string]*Env   `yaml:"envs,omitempty"`
	RawConfigRefMap            map[string]map[string]string `yaml:"configs,omitempty"`
	EnvRefMap                  map[string]*EnvRef           `yaml:"_envrefmap,omitempty"`
	ConfigRefMap               map[string]*ConfigRef        `yaml:"_configrefmap,omitempty"`
	IsInitialized              bool                         `yaml:"_isInitialized,omitempty"`
	StdoutChan                 chan string
	StdoutRowChan              chan []string
	StderrChan                 chan string
	StderrRowChan              chan []string
	fileLocation               string
	values                     map[string]string
	sortedTaskNames            []string
	sortedInputNames           []string
	maxPublishedTaskNameLength int
	Decoration                 *output.Decoration
	Util                       *utility.Util
}
func NewProject(decoration *output.Decoration, projectFile string, defaultIncludes []string) (p *Project, err error) {
	if os.Getenv("ZARUBA_HOME") == "" {
		executable, _ := os.Executable()
		os.Setenv("ZARUBA_HOME", filepath.Dir(executable))
	}
	p, err = loadProject(decoration, projectFile, defaultIncludes)
	if err != nil {
		return p, err
	}
	p.StdoutChan = make(chan string)
	p.StdoutRowChan = make(chan []string)
	p.StderrChan = make(chan string)
	p.StderrRowChan = make(chan []string)
	p.Decoration = decoration
	p.setSortedTaskNames()
	p.setSortedInputNames()
	p.linkToTasks()
	p.linkToInputs()
	p.setDefaultValues()
	if err = p.validateTask(); err != nil {
		return p, err
	}
	for _, taskName := range p.sortedTaskNames {
		task := p.Tasks[taskName]
		task.init()
	}
	return p, err
}
func loadRawProject(projectFile string) (p *Project, err error) {
	parsedProjectFile, _ := filepath.Abs(os.ExpandEnv(projectFile))
	p = &Project{
		Includes:                   []string{},
		RawEnvRefMap:               map[string]map[string]*Env{},
		RawConfigRefMap:            map[string]map[string]string{},
		Tasks:                      map[string]*Task{},
		Inputs:                     map[string]*Variable{},
		values:                     map[string]string{},
		EnvRefMap:                  map[string]*EnvRef{},
		ConfigRefMap:               map[string]*ConfigRef{},
		IsInitialized:              false,
		maxPublishedTaskNameLength: 17,
		Util:                       utility.NewUtil(),
	}
	keyValidator := NewKeyValidator(parsedProjectFile)
	b, err := keyValidator.Validate()
	if err != nil {
		return p, err
	}
	if err = yaml.Unmarshal(b, p); err != nil {
		return p, fmt.Errorf("error parsing YAML '%s': %s", parsedProjectFile, err)
	}
	return p, nil
}
func loadProject(d *output.Decoration, projectFile string, defaultIncludes []string) (p *Project, err error) {
	parsedProjectFile, _ := filepath.Abs(os.ExpandEnv(projectFile))
	p, err = loadRawProject(parsedProjectFile)
	if err != nil {
		return p, err
	}
	p.include(parsedProjectFile, defaultIncludes)
	p.fileLocation = parsedProjectFile
	p.setTaskFileLocation()
	p.setInputFileLocation()
	p.setProjectEnvRefMap()
	p.setProjectConfigRefMap()
	if err = p.cascadeIncludes(d); err != nil {
		return p, err
	}
	return p, err
}
func (p *Project) include(parsedProjectFile string, defaultIncludes []string) {
	for _, script := range defaultIncludes {
		if strings.Trim(script, " ") == "" {
			continue
		}
		parsedScript, _ := filepath.Abs(os.ExpandEnv(script))
		if parsedScript == parsedProjectFile {
			continue
		}
		shouldIncludeParsedScript := true
		for _, currentInclude := range p.Includes {
			parsedCurrentInclude, _ := filepath.Abs(os.ExpandEnv(currentInclude))
			if parsedScript == parsedCurrentInclude {
				shouldIncludeParsedScript = false
				break
			}
		}
		if shouldIncludeParsedScript {
			p.Includes = append(p.Includes, parsedScript)
		}
	}
}
func (p *Project) GetName() (name string) {
	if p.Name != "" {
		return p.Name
	}
	return filepath.Base(filepath.Dir(p.fileLocation))
}
func (p *Project) GetFileLocation() (fileLocation string) {
	return p.fileLocation
}