package main import ( "log" "os" "os/exec" "path" "path/filepath" "regexp" "strconv" "strings" "time" ) var timeUnits = map[string]int64{ "ms": 1, "s": 1000, "m": 1000 * 60, "h": 1000 * 60 * 60, "d": 1000 * 60 * 60 * 24, "M": 1000 * 60 * 60 * 24 * 30, "y": 1000 * 60 * 60 * 24 * 365, } var valueRegex, _ = regexp.Compile(`\d+`) var unitRegex, _ = regexp.Compile(`[a-zA-Z]+`) func parseDuration(date string) int64 { var milliseconds int64 = 0 date = strings.TrimSpace(date) var parts = strings.Split(date, "_") for _, part := range parts { part = strings.TrimSpace(part) log.Printf("Parsing date part: %s\n", part) var value = valueRegex.FindString(part) var unit = unitRegex.FindString(part) if value == "" || unit == "" { log.Println("Invalid date part: " + part) continue } if _, ok := timeUnits[unit]; !ok { log.Println("Invalid date unit: " + unit) continue } log.Printf("Part %s parsed as: Value: %s, Unit: %s\n", part, value, unit) var valueMs, _ = strconv.ParseInt(value, 10, 16) valueMs = valueMs * timeUnits[unit] milliseconds += valueMs log.Printf("Adding %dms to duration, now: %d\n", valueMs, milliseconds) } return milliseconds } func getEnv(key, def string) string { var value, exists = os.LookupEnv(key) if exists { return value } return def } var ROOT string func main() { log.SetFlags(log.Lmicroseconds) ROOT = filepath.ToSlash(strings.TrimSpace(getEnv("ROOT", "/tmp"))) ROOT = path.Clean(ROOT) var SCAN_INTERVAL = time.Duration(parseDuration(getEnv("SCAN_INTERVAL", "1m")) * 1e6) log.Println("Input args parsed as:") log.Printf("ROOT: %s\n", ROOT) log.Printf("SCAN_INTERVAL: %.0fs\n", SCAN_INTERVAL.Seconds()) // This shit DOES NOT run correctly on windows // It absolutely butchers CRLF -> LF // And shits the bed // Thinking there are changed files // Making empty commits // And other stupid shit // It does run on unix though for { log.Printf("Running at %s", time.Now().Format(time.RFC3339)) doRun() time.Sleep(SCAN_INTERVAL) } } func doRun() { status, err := doStatus() if err != nil { log.Println("Error executing doStatus:", err) return } if status == "" { log.Printf("Nothing to commit") return } log.Println("Changes detected") res, err := doAddAll() if err != nil { log.Println("Error executing doAddAll:", err) return } log.Println("Changes added to index:", res) _, err = setIdentity() if err != nil { log.Println("Error setting identity:", err) } res, err = doCommit() if err != nil { log.Println("Error executing doCommitAll:", err) return } log.Println("Changes committed:", res) } func doStatus() (string, error) { gitStatus := exec.Command("git", "status", "-s") gitStatus.Dir = ROOT out, err := gitStatus.CombinedOutput() if err != nil { return string(out), err } return string(out), nil } func doAddAll() (string, error) { gitAdd := exec.Command("git", "add", ".") gitAdd.Dir = ROOT out, err := gitAdd.CombinedOutput() if err != nil { return string(out), err } return string(out), nil } func doCommit() (string, error) { gitCommit := exec.Command("git", "commit", "-am", "Update") gitCommit.Dir = ROOT out, err := gitCommit.CombinedOutput() if err != nil { return string(out), err } return string(out), nil } func setIdentity() (string, error) { res, err := setUsername() if err != nil { log.Println("Error executing setUsername:", err) return string(res), err } res, err = setEmail() if err != nil { log.Println("Error executing setEmail:", err) return string(res), err } return "", nil } func setUsername() (string, error) { gitConfig := exec.Command("git", "config", "user.name", "system") gitConfig.Dir = ROOT out, err := gitConfig.CombinedOutput() if err != nil { return string(out), err } return string(out), nil } func setEmail() (string, error) { gitConfig := exec.Command("git", "config", "user.email", "system@localhost") gitConfig.Dir = ROOT out, err := gitConfig.CombinedOutput() if err != nil { return string(out), err } return string(out), nil }