e75f06bb2b
This adds a bunch of general scaffolding and the beginning of a `build` command. The general engineering scaffolding includes: * Glide for dependency management. * A Makefile that runs govet and golint during builds. * Google's Glog library for logging. * Cobra for command line functionality. The Mu-specific scaffolding includes some packages: * mu/pkg/diag: A package for compiler-like diagnostics. It's fairly barebones at the moment, however we can embellish this over time. * mu/pkg/errors: A package containing Mu's predefined set of errors. * mu/pkg/workspace: A package containing workspace-related convenience helpers. in addition to a main entrypoint that simply wires up and invokes the CLI. From there, the mu/cmd package takes over, with the Cobra-defined CLI commands. Finally, the mu/pkg/compiler package actually implements the compiler behavior. Or, it will. For now, it simply parses a JSON or YAML Mufile into the core mu/pkg/api types, and prints out the result.
73 lines
1.5 KiB
Go
73 lines
1.5 KiB
Go
// Copyright 2016 Marapongo, Inc. All rights reserved.
|
|
|
|
package workspace
|
|
|
|
import (
|
|
"errors"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
)
|
|
|
|
const mufileBase = "Mu"
|
|
|
|
var mufileExts = []string{"json", "yaml"}
|
|
|
|
// DetectMufile locates the closest Mufile from the given path, searching "upwards" in the directory hierarchy. If
|
|
// no Mufile is found, a non-nil error is returned.
|
|
func DetectMufile(from string) (string, error) {
|
|
abs, err := filepath.Abs(from)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// It's possible the target is already the file we seek; if so, return right away.
|
|
if IsMufile(abs) {
|
|
return abs, nil
|
|
}
|
|
|
|
curr := abs
|
|
for {
|
|
// If the target is a directory, enumerate its files, checking each to see if it's a Mufile.
|
|
files, err := ioutil.ReadDir(curr)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
for _, file := range files {
|
|
path := filepath.Join(curr, file.Name())
|
|
if IsMufile(path) {
|
|
return path, nil
|
|
}
|
|
}
|
|
|
|
// If neither succeeded, keep looking in our parent directory.
|
|
curr = filepath.Dir(curr)
|
|
if os.IsPathSeparator(curr[len(curr)-1]) {
|
|
break
|
|
}
|
|
}
|
|
|
|
return "", errors.New("No Mufile found")
|
|
}
|
|
|
|
// IsMufile returns true if the path references what appears to be a valid Mufile.
|
|
func IsMufile(path string) bool {
|
|
info, err := os.Stat(path)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
|
|
// Directories can't be Mufiles.
|
|
if info.IsDir() {
|
|
return false
|
|
}
|
|
|
|
// Check all supported extensions.
|
|
for _, ext := range mufileExts {
|
|
if info.Name() == mufileBase+"."+ext {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|