X-Git-Url: http://www.git.cypherpunks.ru/?p=goredo.git;a=blobdiff_plain;f=main.go;h=4de78be52fa786830cfbb92862c1c495cd59140a;hp=f466faa376813377582889cd955c8d3324fa3aa4;hb=314f58ec690c7321535d6718e8d3a0ecb4cac019;hpb=bca646300f43c07ea51decd5620f34a39676e8c3 diff --git a/main.go b/main.go index f466faa..4de78be 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,6 @@ /* -goredo -- redo implementation on pure Go -Copyright (C) 2020 Sergey Matveev +goredo -- djb's redo implementation on pure Go +Copyright (C) 2020-2021 Sergey Matveev This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,6 +19,7 @@ package main import ( "bufio" + "bytes" "crypto/rand" "flag" "fmt" @@ -60,7 +61,7 @@ func mustParseFd(v, name string) *os.File { func main() { version := flag.Bool("version", false, "print version") warranty := flag.Bool("warranty", false, "print warranty information") - symlinks := flag.Bool("symlinks", false, "create necessary symlinks in current direcotyr") + symlinks := flag.Bool("symlinks", false, "create necessary symlinks in current directory") flag.Usage = usage flag.Parse() @@ -91,27 +92,30 @@ func main() { log.Println(err) } } - fmt.Println("no creating optional:", os.Args[0], "<- tai64nlocal") os.Exit(rc) } log.SetFlags(0) var err error - Cwd, err = unix.Getwd() + Cwd, err = os.Getwd() if err != nil { - panic(err) + log.Fatalln(err) } NoColor = os.Getenv(EnvNoColor) != "" NoSync = os.Getenv(EnvNoSync) == "1" + InodeTrust = os.Getenv(EnvInodeNoTrust) == "" TopDir = os.Getenv(EnvTopDir) - if TopDir != "" { + if TopDir == "" { + TopDir = "/" + } else { TopDir, err = filepath.Abs(TopDir) if err != nil { panic(err) } } + DirPrefix = os.Getenv(EnvDirPrefix) if *flagStderrKeep { mustSetenv(EnvStderrKeep, "1") @@ -119,6 +123,9 @@ func main() { if *flagStderrSilent { mustSetenv(EnvStderrSilent, "1") } + if *flagNoProgress { + mustSetenv(EnvNoProgress, "1") + } if *flagDebug { mustSetenv(EnvDebug, "1") } @@ -136,6 +143,7 @@ func main() { } StderrKeep = os.Getenv(EnvStderrKeep) == "1" StderrSilent = os.Getenv(EnvStderrSilent) == "1" + NoProgress = os.Getenv(EnvNoProgress) == "1" Debug = os.Getenv(EnvDebug) == "1" LogWait = os.Getenv(EnvLogWait) == "1" LogLock = os.Getenv(EnvLogLock) == "1" @@ -143,13 +151,57 @@ func main() { if Debug || os.Getenv(EnvLogPid) == "1" { MyPid = os.Getpid() } + var traced bool + if *flagTraceAll { + mustSetenv(EnvTrace, "1") + } if *flagTrace { - Trace = true + traced = true } else { - Trace = os.Getenv(EnvTrace) == "1" + traced = os.Getenv(EnvTrace) == "1" } // Those are internal envs + FdOODTgts, err = ioutil.TempFile("", "ood-tgts") + if err != nil { + panic(err) + } + if err = os.Remove(FdOODTgts.Name()); err != nil { + panic(err) + } + FdOODTgtsLock, err = ioutil.TempFile("", "ood-tgts.lock") + if err != nil { + panic(err) + } + if err = os.Remove(FdOODTgtsLock.Name()); err != nil { + panic(err) + } + + if v := os.Getenv(EnvOODTgtsFd); v != "" { + fd := mustParseFd(v, EnvOODTgtsFd) + fdLock := mustParseFd(v, EnvOODTgtsLockFd) + if err = unix.Flock(int(fdLock.Fd()), unix.LOCK_EX); err != nil { + panic(err) + } + if _, err = fd.Seek(0, os.SEEK_SET); err != nil { + panic(err) + } + tgtsRaw, err := ioutil.ReadAll(bufio.NewReader(fd)) + if err != nil { + panic(err) + } + unix.Flock(int(fdLock.Fd()), unix.LOCK_UN) + OODTgts = make(map[string]struct{}) + for _, tgtRaw := range bytes.Split(tgtsRaw, []byte{0}) { + t := string(tgtRaw) + if t == "" { + continue + } + OODTgts[t] = struct{}{} + trace(CDebug, "ood: known to be: %s", t) + } + } + StderrPrefix = os.Getenv(EnvStderrPrefix) if v := os.Getenv(EnvLevel); v != "" { Level, err = strconv.Atoi(v) @@ -160,44 +212,59 @@ func main() { panic("negative " + EnvLevel) } } + var fdDep *os.File if v := os.Getenv(EnvDepFd); v != "" { fdDep = mustParseFd(v, EnvDepFd) } + + tgts := flag.Args() BuildUUID = os.Getenv(EnvBuildUUID) if BuildUUID == "" { raw := new([16]byte) if _, err = io.ReadFull(rand.Reader, raw[:]); err != nil { - panic(err) + log.Fatalln(err) } raw[6] = (raw[6] & 0x0F) | uint8(4<<4) // version 4 BuildUUID = fmt.Sprintf( "%x-%x-%x-%x-%x", raw[0:4], raw[4:6], raw[6:8], raw[8:10], raw[10:], ) + if len(tgts) == 0 { + tgts = []string{"all"} + } } - tgts := flag.Args() - if len(tgts) == 0 { - tgts = []string{"all"} + statusInit() + + for i, tgt := range tgts { + if path.IsAbs(tgt) { + tgts[i] = cwdMustRel(tgt) + } } + ok := true err = nil cmdName := path.Base(os.Args[0]) - trace(CDebug, "[%s] run: %s %s [%s]", BuildUUID, cmdName, tgts, Cwd) + trace( + CDebug, "[%s] run: %s %s cwd:%s dirprefix:%s", + BuildUUID, cmdName, tgts, Cwd, DirPrefix, + ) CmdSwitch: switch cmdName { case "redo": for _, tgt := range tgts { - ok, err = ifchange([]string{tgt}, true) + ok, err = ifchange([]string{tgt}, true, traced) if err != nil || !ok { break } } case "redo-ifchange": - ok, err = ifchange(tgts, false) - writeDeps(fdDep, tgts) + ok, err = ifchange(tgts, false, traced) + if err == nil { + err = writeDeps(fdDep, tgts) + } case "redo-ifcreate": if fdDep == nil { log.Fatalln("no", EnvDepFd) @@ -243,18 +310,19 @@ CmdSwitch: log.Fatalln("single target expected") } var fdTmp *os.File - fdTmp, err = ioutil.TempFile("", "") + fdTmp, err = ioutil.TempFile("", "whichdo") if err != nil { break } - os.Remove(fdTmp.Name()) - var doFile string + if err = os.Remove(fdTmp.Name()); err != nil { + break + } cwd, tgt := cwdAndTgt(tgts[0]) - doFile, _, err = findDo(fdTmp, cwd, tgt) + doFile, upLevels, err := findDo(fdTmp, cwd, tgt) if err != nil { break } - _, err = fdTmp.Seek(0, 0) + _, err = fdTmp.Seek(0, os.SEEK_SET) if err != nil { break } @@ -269,11 +337,21 @@ CmdSwitch: } fmt.Println(cwdMustRel(cwd, m["Target"])) } - ok = doFile != "" - case "tai64nlocal": - bw := bufio.NewWriter(os.Stdout) - err = tai64nLocal(bw, os.Stdin) - bw.Flush() + if doFile == "" { + ok = false + } else { + p := make([]string, 0, upLevels+2) + p = append(p, cwd) + for i := 0; i < upLevels; i++ { + p = append(p, "..") + } + p = append(p, doFile) + rel, err := filepath.Rel(Cwd, path.Join(p...)) + if err != nil { + panic(err) + } + fmt.Println(rel) + } default: log.Fatalln("unknown command", cmdName) }