package planr import ( "log" "os" "io" "path" "path/filepath" "strings" ) /* CONFIG DIRECTORY */ // Consumes path // Returns true if traversal should halt type traversalFunc func(path string) bool; // Traverse up until the root is reached // Calls traverseFunc each iteration // Returns true if prematurely stopped func traverseUp(reference string, shouldStop traversalFunc) bool { cursor := reference for !shouldStop(cursor) { if filepath.ToSlash(cursor) == "/" { return false } cursor = filepath.Join(cursor, "..") } return true } func directoryExists(path string) bool { info, err := os.Stat(path) if err != nil { if !os.IsNotExist(err) { log.Fatal(err) } return false; } return info.IsDir() } // Find the configuration directory // Uses: // 1. PlANR_DIRECTORY env if set // 2. planr // 3. .planr func ConfigDir() string { // Return environmental override if set if dir, isSet := os.LookupEnv("PLANR_DIRECTORY"); isSet { if !directoryExists(dir) { log.Fatalf("Cannot find planr directory %s", dir); } return dir; } cwd, err := os.Getwd() if err != nil { log.Fatal(err) } var rubricDir string rubric_search_dirs := [2]string{ "planr", ".planr", } found := traverseUp(cwd, func (path string) bool { for _, dir := range rubric_search_dirs { rubricDir = filepath.Join(path, dir) if directoryExists(rubricDir) { return true } } return false }); if !found { log.Fatal("Could not find planr directory"); } return rubricDir } func JoinConfigDir(path_ string, file string) string { if path.IsAbs(path_) { return path.Join(path_, file) } return path.Join(ConfigDir(), path_, file) } func RootDir() string { return path.Join(ConfigDir(), "..") } // Find rubric directory at PLANR_DIR/rubric func RubricDir() string { rubricDir := path.Join(ConfigDir(), "rubric"); if !directoryExists(rubricDir) { log.Fatal("Could not find the rubric directory inside of planr") } return rubricDir } func BuildDir() string { buildDir := path.Join(ConfigDir(), "build") if !directoryExists(buildDir) { err := os.Mkdir(buildDir, 0755) if err != nil { log.Fatalf("Cannot create build directory %v\n", err) } } return buildDir } func CleanBuildDir() { buildDir := path.Join(ConfigDir(), "build") if err := os.RemoveAll(buildDir); err != nil { log.Fatalf("Cannot clean (removeAll) in build directory %v\n", err) } } func (ac AdapterConfig) Dir() string { dir := BuildDir() dir = path.Join(dir, ac.Name) if !directoryExists(dir) { err := os.Mkdir(dir, 0755) if err != nil { log.Fatalf("Cannot create build/%s directory %v\n", ac.Name, err) } } return dir } func basename(path string) string { ext := filepath.Ext(path) return path[0:len(path) - len(ext)] } func cname(root string, path string) string { rel, err := filepath.Rel(root, path) if err != nil { log.Fatal(err) } rel = filepath.ToSlash(rel) parts := strings.Split(rel, "/") n := len(parts) if n == 0 { return "" } parts[n-1] = basename(parts[n-1]) return strings.Join(parts, ".") } func collectUnits(root string, cfgs []AdapterConfig) []TestCase { tcs := make([]TestCase, 0) collectFromDir(root, nil, cfgs, &tcs) for i := range tcs { tcs[i].Cname = cname(root, tcs[i].Path) } return tcs } const DEFAULTS = "defaults.toml" // Collects the units from the configuration tree // TODO: Cleanup func collectFromDir( dir string, defaults *Defaults, cfgs []AdapterConfig, units *[]TestCase, ) { fp, err := os.Open(dir) if err != nil { log.Fatal(err) } // Process defaults for this directory if a defaults.toml is found defaultsPath := path.Join(dir, DEFAULTS) if info, err := os.Stat(defaultsPath); err == nil && !info.IsDir() { d := DecodeDefaults(defaultsPath, cfgs) // inherit the properties not defined in this defaults if defaults != nil { d.Inherit(defaults) } defaults = &d } // Read the entries in this directory for { dirs, err := fp.ReadDir(100) if err == io.EOF { break } else if err != nil { log.Fatal(err) } for _, ent := range dirs { child := path.Join(dir, ent.Name()) nm := ent.Name() if ent.IsDir() { collectFromDir(child, defaults, cfgs, units) } else { if nm == DEFAULTS { continue } // Decode a unit config := DecodeConfig(child, cfgs) config.Inherit(*defaults) tc := TestCase { Path: child, Config: config, } *units = append(*units, tc) } } } }