github.com/tooploox/oya@v0.0.21-0.20230524103240-1cda1861aad6/pkg/oyafile/imports.go (about)

     1  package oyafile
     2  
     3  import (
     4  	"os"
     5  	"path/filepath"
     6  
     7  	"github.com/pkg/errors"
     8  	"github.com/tooploox/oya/pkg/template"
     9  	"github.com/tooploox/oya/pkg/types"
    10  )
    11  
    12  type PackLoader interface {
    13  	Load(importPath types.ImportPath) (*Oyafile, bool, error)
    14  }
    15  
    16  func (oyafile *Oyafile) Build(loader PackLoader) error {
    17  	// Do not resolve imports when loading Oyafile. Sometimes, we need to load Oyafile before packs are ready to be imported.
    18  	if !oyafile.IsBuilt {
    19  		err := oyafile.resolveImports(loader)
    20  		if err != nil {
    21  			return err
    22  		}
    23  		oyafile.IsBuilt = true
    24  	}
    25  	return nil
    26  }
    27  
    28  func (oyafile *Oyafile) resolveImports(loader PackLoader) error {
    29  	for alias, importPath := range oyafile.Imports {
    30  		packOyafile, err := oyafile.loadPackOyafile(loader, importPath)
    31  		if err != nil {
    32  			return err
    33  		}
    34  		err = packOyafile.Build(loader)
    35  		if err != nil {
    36  			return err
    37  		}
    38  		err = oyafile.Values.UpdateScopeAt(string(alias),
    39  			func(scope template.Scope) template.Scope {
    40  				// Values in the main Oyafile overwrite values in the pack Oyafile.
    41  				merged := packOyafile.Values.Merge(scope)
    42  				merged = merged.Merge(aliasBuiltin(alias))
    43  				// Task is keeping a pointed to the scope.
    44  				packOyafile.Values.Replace(merged)
    45  				return merged
    46  			}, false)
    47  		if err != nil {
    48  			return errors.Wrapf(err, "error merging values for imported pack %v", alias)
    49  		}
    50  
    51  		oyafile.Tasks.ImportTasks(alias, packOyafile.Tasks)
    52  	}
    53  	return nil
    54  }
    55  
    56  func (oyafile *Oyafile) loadPackOyafile(loader PackLoader, importPath types.ImportPath) (*Oyafile, error) {
    57  	o, found, err := loader.Load(importPath)
    58  	if err != nil {
    59  		return nil, err
    60  	}
    61  	if found {
    62  		return o, nil
    63  	}
    64  
    65  	// Attempt to load the Oyafile using the local path.
    66  	fullImportPath := filepath.Join(oyafile.RootDir, string(importPath))
    67  	if isValidImportPath(fullImportPath) {
    68  		o, found, err := LoadFromDir(fullImportPath, oyafile.RootDir)
    69  		if err != nil {
    70  			return nil, err
    71  		}
    72  		if found {
    73  			return o, nil
    74  		}
    75  	}
    76  	return nil, errors.Errorf("missing pack %v", importPath)
    77  }
    78  
    79  func isValidImportPath(fullImportPath string) bool {
    80  	f, err := os.Stat(fullImportPath)
    81  	return err == nil && f.IsDir()
    82  }