2017-08-23 01:56:15 +02:00
|
|
|
package engine
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/pulumi/pulumi-fabric/pkg/encoding"
|
|
|
|
"github.com/pulumi/pulumi-fabric/pkg/pack"
|
|
|
|
"github.com/pulumi/pulumi-fabric/pkg/util/contract"
|
|
|
|
"github.com/pulumi/pulumi-fabric/pkg/workspace"
|
|
|
|
)
|
|
|
|
|
|
|
|
// detectPackage returns a package given the path, or returns an error if one could not be located.
|
2017-08-23 19:58:35 +02:00
|
|
|
func (eng *Engine) detectPackage(path string) (*pack.Package, error) {
|
|
|
|
pkgpath, err := workspace.DetectPackage(path, eng.Diag())
|
2017-08-23 01:56:15 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Errorf("could not locate a package to load: %v", err)
|
|
|
|
} else if pkgpath == "" {
|
|
|
|
return nil, errors.Errorf("no package found at: %v", err)
|
|
|
|
}
|
2017-08-23 19:58:35 +02:00
|
|
|
pkg, _ := eng.readPackage(pkgpath)
|
2017-08-23 01:56:15 +02:00
|
|
|
contract.Assert(pkg != nil)
|
|
|
|
return pkg, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// readPackageFromArg reads a package from an argument value. It can be "-" to request reading from Stdin, and is
|
|
|
|
// interpreted as a path otherwise. If an error occurs, it is printed to Stderr, and the returned value will be nil.
|
|
|
|
// In addition to the package, a root directory is returned that the compiler should be formed over, if any.
|
2017-08-23 19:58:35 +02:00
|
|
|
func (eng *Engine) readPackageFromArg(arg string) (*pack.Package, string) {
|
2017-08-23 01:56:15 +02:00
|
|
|
// If the arg is simply "-", read from stdin.
|
|
|
|
if arg == "-" {
|
2017-08-23 19:58:35 +02:00
|
|
|
return eng.readPackageFromStdin(), ""
|
2017-08-23 01:56:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Read the package from a file.
|
2017-08-23 19:58:35 +02:00
|
|
|
return eng.readPackage(arg)
|
2017-08-23 01:56:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// readPackageFromStdin attempts to read a package from Stdin; if an error occurs, it will be printed to Stderr, and
|
|
|
|
// the returned value will be nil.
|
2017-08-23 19:58:35 +02:00
|
|
|
func (eng *Engine) readPackageFromStdin() *pack.Package {
|
2017-08-23 01:56:15 +02:00
|
|
|
// If stdin, read the package from text, and then create a compiler using the working directory.
|
|
|
|
b, err := ioutil.ReadAll(os.Stdin)
|
|
|
|
if err != nil {
|
2017-08-23 19:58:35 +02:00
|
|
|
fmt.Fprintf(eng.Stderr, "error: could not read from stdin\n")
|
|
|
|
fmt.Fprintf(eng.Stderr, " %v\n", err)
|
2017-08-23 01:56:15 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-08-23 19:58:35 +02:00
|
|
|
return eng.DecodePackage(encoding.Marshalers[".json"], b, "stdin")
|
2017-08-23 01:56:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// readPackage attempts to read a package from the given path; if an error occurs, it will be printed to Stderr, and
|
|
|
|
// the returned value will be nil. If the path is a directory, nil is returned.
|
2017-08-23 19:58:35 +02:00
|
|
|
func (eng *Engine) readPackage(path string) (*pack.Package, string) {
|
2017-08-23 01:56:15 +02:00
|
|
|
// If it's a directory, bail early.
|
|
|
|
info, err := os.Stat(path)
|
|
|
|
if err != nil {
|
2017-08-23 19:58:35 +02:00
|
|
|
fmt.Fprintf(eng.Stderr, "error: could not read path '%v': %v\n", path, err)
|
2017-08-23 01:56:15 +02:00
|
|
|
return nil, ""
|
|
|
|
}
|
|
|
|
if info.IsDir() {
|
|
|
|
return nil, path
|
|
|
|
}
|
|
|
|
|
|
|
|
// Lookup the marshaler for this format.
|
|
|
|
ext := filepath.Ext(path)
|
|
|
|
m, has := encoding.Marshalers[ext]
|
|
|
|
if !has {
|
2017-08-23 19:58:35 +02:00
|
|
|
fmt.Fprintf(eng.Stderr, "error: no marshaler found for file format '%v'\n", ext)
|
2017-08-23 01:56:15 +02:00
|
|
|
return nil, ""
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read the contents.
|
|
|
|
b, err := ioutil.ReadFile(path)
|
|
|
|
if err != nil {
|
2017-08-23 19:58:35 +02:00
|
|
|
fmt.Fprintf(eng.Stderr, "error: a problem occurred when reading file '%v'\n", path)
|
|
|
|
fmt.Fprintf(eng.Stderr, " %v\n", err)
|
2017-08-23 01:56:15 +02:00
|
|
|
return nil, ""
|
|
|
|
}
|
|
|
|
|
2017-08-23 19:58:35 +02:00
|
|
|
return eng.DecodePackage(m, b, path), filepath.Dir(path)
|
2017-08-23 01:56:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// DecodePackage turns a byte array into a package using the given marshaler. If an error occurs, it is printed to
|
|
|
|
// Stderr, and the returned package value will be nil.
|
2017-08-23 19:58:35 +02:00
|
|
|
func (eng *Engine) DecodePackage(m encoding.Marshaler, b []byte, path string) *pack.Package {
|
2017-08-23 01:56:15 +02:00
|
|
|
// Unmarshal the contents into a fresh package.
|
|
|
|
pkg, err := encoding.Decode(m, b)
|
|
|
|
if err != nil {
|
2017-08-23 19:58:35 +02:00
|
|
|
fmt.Fprintf(eng.Stderr, "error: a problem occurred when unmarshaling file '%v'\n", path)
|
|
|
|
fmt.Fprintf(eng.Stderr, " %v\n", err)
|
2017-08-23 01:56:15 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return pkg
|
|
|
|
}
|