summaryrefslogtreecommitdiff
path: root/stddirs.go
diff options
context:
space:
mode:
Diffstat (limited to 'stddirs.go')
-rw-r--r--stddirs.go190
1 files changed, 190 insertions, 0 deletions
diff --git a/stddirs.go b/stddirs.go
new file mode 100644
index 0000000..581af87
--- /dev/null
+++ b/stddirs.go
@@ -0,0 +1,190 @@
+package planr
+
+import (
+ "os"
+ "log"
+ "path"
+ "path/filepath"
+)
+
+// Standard Directories:
+//
+// Planr relies on a standard directory structure to resolve paths to source code
+// These directories can be overridden via environmental variables //
+// Directories:
+// - `.` root directory
+// - `src` contains source code
+// - `planr` contains test metadata (also called configuration directory)
+// - `planr/rubric` contains test case configuration
+// - `planr/tests` contains source code for test cases
+// - `planr/build` contains all files written during the build process (ephemeral)
+
+// Env overrides
+const (
+ ENV_CONFIG_DIR="PLANR_CONFIG_DIR"
+ ENV_SRC_DIR="PLANR_SRC_DIR"
+ ENV_BUILD_DIR="PLANR_BUILD_DIR"
+)
+
+// Try these search directories
+var CONFIG_SEARCH_DIRS = [] string {
+ "planr",
+ ".planr",
+}
+
+// Path are relative to the "planr" project config directory
+const (
+ DEFAULT_PATH_SRC="../src"
+ DEFAULT_PATH_BUILD="build"
+ DEFAULT_PATH_RUBRIC="rubric"
+ DEFAULT_PATH_TESTS="tests"
+)
+
+type DirConfig struct {
+ src string
+ config string
+ build string
+
+ // Config falls back to the config found in the parent directory if the env variable hasn't been overridden
+ pdFallback string
+}
+
+func dieDirAbsent(name, path string) {
+ if !directoryExists(path) {
+ log.Fatalf("Could not find %s directory tried %s", name, path)
+ }
+}
+
+func dirFromEnv(name, env string) *string {
+ if dir, isSet := os.LookupEnv(env); isSet {
+
+ dieDirAbsent(name, dir)
+
+ return &dir
+ }
+
+ return nil
+}
+
+func (c *DirConfig) SetSrc(srcDir string) {
+ dieDirAbsent("src", srcDir)
+ c.src = abs(srcDir)
+}
+
+func (c *DirConfig) SetConfig(configDir string) {
+ dieDirAbsent("planr (config)", configDir)
+ c.config = abs(configDir)
+}
+
+func (c *DirConfig) SetBuild(buildDir string) {
+ dieDirAbsent("build", buildDir)
+ c.build = abs(buildDir)
+}
+
+func (c *DirConfig) SetConfigFromTree(cdir string) {
+ var configDir string
+
+ found := traverseUp(cdir, func (path string) bool {
+
+ for _, dir := range CONFIG_SEARCH_DIRS {
+ configDir = filepath.Join(path, dir)
+
+ if directoryExists(configDir) {
+ return true
+ }
+ }
+
+ return false
+ });
+
+
+ if found {
+ c.pdFallback = configDir
+ }
+}
+
+func (c DirConfig) Config() string {
+ if c.config != "" {
+ return c.config
+ }
+
+ if dir := dirFromEnv("config", ENV_CONFIG_DIR); dir != nil {
+ c.config = abs(*dir)
+ return c.config
+ }
+
+ if c.pdFallback == "" {
+ log.Fatal("Could not find planr directory");
+ }
+
+ c.config = abs(c.pdFallback);
+ return c.config
+}
+
+func (c DirConfig) Src() string {
+ if c.src != "" {
+ return c.src
+ }
+
+ if dir := dirFromEnv("src", ENV_SRC_DIR); dir != nil {
+ c.src = *dir
+ return c.src
+ }
+
+ // set path relative to config
+ dir := c.Config()
+ return path.Join(dir, DEFAULT_PATH_SRC)
+}
+
+func abs(path string) string {
+ apath, err := filepath.Abs(path)
+
+ if err != nil {
+ log.Fatalf("Could not find path %s", path)
+ }
+
+ return apath
+}
+
+func (c DirConfig) Build() string {
+ if c.build != "" {
+ return c.build
+ }
+
+ if dir := dirFromEnv("build", ENV_BUILD_DIR); dir != nil {
+ c.build = *dir
+ return c.build
+ }
+
+ dir := c.Config()
+ return path.Join(dir, DEFAULT_PATH_BUILD)
+}
+
+func (c DirConfig) CleanBuild() {
+ build := c.Build()
+
+ if err := os.RemoveAll(build); err != nil {
+ log.Fatalf("Cannot build directory %v\n", err)
+ }
+
+}
+
+func (c DirConfig) MkBuild() {
+ build := c.Build()
+
+ if err := os.Mkdir(build, 0755); err != nil {
+ log.Fatalf("Could not create build directory %v\n", err)
+ }
+}
+
+func (c DirConfig) Rubric() string {
+ rubric := path.Join(c.Config(), DEFAULT_PATH_RUBRIC)
+ dieDirAbsent("rubric", rubric)
+ return rubric
+}
+
+func (c DirConfig) Tests() string {
+ tests := path.Join(c.Config(), DEFAULT_PATH_TESTS)
+ dieDirAbsent("tests", tests)
+ return tests
+}