package main import ( "gopkg.in/yaml.v2" "io/ioutil" "log" "math/rand" "os" "path/filepath" "strings" "syscall" "time" ) // settings const const ( permission = 0775 directory = ".realize" file = "realize.yaml" fileOut = "outputs.log" fileErr = "errors.log" fileLog = "logs.log" ) // random string preference const ( letterIdxBits = 6 // 6 bits to represent a letter index letterIdxMask = 1<= 0; { if remain == 0 { cache, remain = src.Int63(), letterIdxMax } if idx := int(cache & letterIdxMask); idx < len(letterBytes) { b[i] = letterBytes[idx] i-- } cache >>= letterIdxBits remain-- } return string(b) } // Wdir return the current working directory func (s Settings) wdir() string { dir, err := os.Getwd() s.validate(err) return filepath.Base(dir) } // Flimit defines the max number of watched files func (s *Settings) flimit() error { var rLimit syscall.Rlimit rLimit.Max = uint64(s.FileLimit) rLimit.Cur = uint64(s.FileLimit) return syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit) } // Delete realize folder func (s *Settings) del(d string) error { _, err := os.Stat(d) if !os.IsNotExist(err) { return os.RemoveAll(d) } return err } // Path cleaner func (s Settings) path(path string) string { return strings.Replace(filepath.Clean(path), "\\", "/", -1) } // Validate checks a fatal error func (s Settings) validate(err error) error { if err != nil { s.fatal(err, "") } return nil } // Read from config file func (s *Settings) read(out interface{}) error { localConfigPath := s.file // backward compatibility path := filepath.Join(directory, s.file) if _, err := os.Stat(path); err == nil { localConfigPath = path } content, err := s.stream(localConfigPath) if err == nil { err = yaml.Unmarshal(content, out) return err } return err } // Record create and unmarshal the yaml config file func (s *Settings) record(out interface{}) error { y, err := yaml.Marshal(out) if err != nil { return err } if _, err := os.Stat(directory); os.IsNotExist(err) { if err = os.Mkdir(directory, permission); err != nil { return s.write(s.file, y) } } return s.write(filepath.Join(directory, s.file), y) } // Stream return a byte stream of a given file func (s Settings) stream(file string) ([]byte, error) { _, err := os.Stat(file) if err != nil { return nil, err } content, err := ioutil.ReadFile(file) s.validate(err) return content, err } // Fatal prints a fatal error with its additional messages func (s Settings) fatal(err error, msg ...interface{}) { if len(msg) > 0 && err != nil { log.Fatalln(red.regular(msg...), err.Error()) } else if err != nil { log.Fatalln(err.Error()) } } // Write a file func (s Settings) write(name string, data []byte) error { err := ioutil.WriteFile(name, data, permission) return s.validate(err) } // Name return the project name or the path of the working dir func (s Settings) name(name string, path string) string { if name == "" && path == "" { return s.wdir() } else if path != "/" { return filepath.Base(path) } return name } // Create a new file and return its pointer func (s Settings) create(path string, name string) *os.File { var file string if _, err := os.Stat(directory); err == nil { file = filepath.Join(path, directory, name) } else { file = filepath.Join(path, name) } out, err := os.OpenFile(file, os.O_APPEND|os.O_WRONLY|os.O_CREATE|os.O_SYNC, permission) s.validate(err) return out }