package main import ( "log" "os" "path" "path/filepath" "regexp" "strconv" "strings" "time" "github.com/go-git/go-git/v5" ) 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 } func main() { log.SetFlags(log.Lmicroseconds) var 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: %d\n", SCAN_INTERVAL.Milliseconds()) // 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 doRun(ROOT) for { log.Printf("Running at %s", time.Now().Format(time.RFC3339)) time.Sleep(SCAN_INTERVAL) doRun(ROOT) } } func doRun(root string) { log.Printf("Opening repository at %s...", root) worktree, err := OpenRepositoryAndWorktree(root) if err != nil { log.Printf("error opening repository at %s: %v", root, err) return } log.Printf("Checking for changes in %s...", root) files, err := GetNumChangedFiles(worktree) if err != nil { log.Printf("error checking for changes in %s: %v", root, err) return } if files == 0 { log.Printf("No changes in %s", root) return } log.Printf("Staging %d files in %s...", files, root) err = AddAll(worktree) if err != nil { log.Printf("error staging files in %s: %v", root, err) return } log.Printf("Committing changes in %s...", root) err = CommitUpdate(worktree) if err != nil { log.Printf("error committing changes in %s: %v", root, err) return } log.Printf("Done committing updates in %s", root) } func OpenRepositoryAndWorktree(root string) (*git.Worktree, error) { repository, err := git.PlainOpen(root) if err != nil { return nil, err } worktree, err := repository.Worktree() if err != nil { return nil, err } return worktree, nil } func HasChanges(worktree *git.Worktree) (bool, error) { status, err := worktree.Status() if err != nil { return false, err } return !status.IsClean(), nil } func GetNumChangedFiles(worktree *git.Worktree) (int, error) { status, err := worktree.Status() if err != nil { return 0, err } return len(status), nil } func AddAll(worktree *git.Worktree) error { err := worktree.AddGlob("*") if err != nil { return err } return nil } func CommitUpdate(worktree *git.Worktree) error { _, err := worktree.Commit("Update", &git.CommitOptions{}) if err != nil { return err } return nil }