X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=run.go;h=89640cbf927d006fbae011c62213c559c976ddaf;hb=317438ff2d0e1d2ee397a89bf692350df068a723;hp=6bd7029752d8fac0d13c6bb1a26e95c67c208953;hpb=e935c1db3ae2ff6d920ff37802774ba2e85629f0;p=goredo.git diff --git a/run.go b/run.go index 6bd7029..89640cb 100644 --- a/run.go +++ b/run.go @@ -21,12 +21,14 @@ package main import ( "bufio" + "bytes" "crypto/rand" "encoding/hex" "errors" "flag" "fmt" "io" + "io/fs" "log" "os" "os/exec" @@ -131,46 +133,30 @@ func mkdirs(pth string) error { return os.MkdirAll(pth, os.FileMode(0777)) } -func isModified(cwd, redoDir, tgt string) (bool, *Inode, string, error) { - fdDep, err := os.Open(path.Join(redoDir, tgt+DepSuffix)) - if err != nil { - if os.IsNotExist(err) { - return false, nil, "", nil - } - return false, nil, "", ErrLine(err) +func isModified(depInfo *DepInfo, cwd, tgt string) ( + modified bool, ourInode *Inode, hshPrev []byte, err error, +) { + if depInfo == nil { + return } - defer fdDep.Close() - r := recfile.NewReader(fdDep) - var modified bool - var ourInode *Inode - var hshPrev string - for { - m, err := r.NextMap() - if err != nil { - if errors.Is(err, io.EOF) { - break - } - return false, nil, "", ErrLine(err) - } - if m["Type"] != DepTypeIfchange || m["Target"] != tgt { + for _, dep := range depInfo.ifchanges { + if dep.tgt != tgt { continue } ourInode, err = inodeFromFileByPath(path.Join(cwd, tgt)) if err != nil { if os.IsNotExist(err) { - return false, nil, "", nil + err = nil + return } - return false, nil, "", ErrLine(err) - } - theirInode, err := inodeFromRec(m) - if err != nil { - return false, nil, "", ErrLine(err) + err = ErrLine(err) + return } - hshPrev = m["Hash"] - modified = !ourInode.Equals(theirInode) + hshPrev = dep.hash + modified = !ourInode.Equals(dep.inode) break } - return modified, ourInode, hshPrev, nil + return } func syncDir(dir string) error { @@ -276,17 +262,25 @@ func runScript(tgtOrig string, errs chan error, forced, traced bool) error { return nil } - // Check if it was already built in parallel - if !forced { - if build, err := depReadBuild(path.Join(redoDir, tgt+DepSuffix)); err == nil && build == BuildUUID { + depInfo, err := depRead(path.Join(redoDir, tgt+DepSuffix)) + if err != nil { + if errors.Is(err, fs.ErrNotExist) { + err = nil + } else { lockRelease() - errs <- nil - return nil + return TgtError{tgtOrig, err} } } + // Check if it was already built in parallel + if !forced && depInfo != nil && depInfo.build == BuildUUID { + lockRelease() + errs <- nil + return nil + } + // Check if target is not modified externally - modified, inodePrev, hshPrev, err := isModified(cwd, redoDir, tgt) + modified, inodePrev, hshPrev, err := isModified(depInfo, cwd, tgt) if err != nil { lockRelease() return TgtError{tgtOrig, err} @@ -302,6 +296,7 @@ func runScript(tgtOrig string, errs chan error, forced, traced bool) error { }() return nil } + depInfo = nil // Start preparing .rec fdDep, err := tempfile(redoDir, tgt+DepSuffix) @@ -352,7 +347,7 @@ func runScript(tgtOrig string, errs chan error, forced, traced bool) error { runErr.DoFile = doFileRelPath } - if err = depWrite(fdDep, cwdOrig, doFileRelPath, ""); err != nil { + if err = depWrite(fdDep, cwdOrig, doFileRelPath, nil); err != nil { cleanup() return TgtError{tgtOrig, ErrLine(err)} } @@ -546,14 +541,7 @@ func runScript(tgtOrig string, errs chan error, forced, traced bool) error { } w := bufio.NewWriter(fdStderr) - var depInfo *DepInfo - fdDep, err := os.Open(fdDepPath) - if err != nil { - err = ErrLine(err) - goto Err - } - depInfo, err = depRead(fdDep) - fdDep.Close() + depInfo, err := depRead(fdDepPath) if err != nil { err = ErrLine(err) goto Err @@ -561,7 +549,7 @@ func runScript(tgtOrig string, errs chan error, forced, traced bool) error { for _, dep := range depInfo.ifchanges { fields = append(fields, recfile.Field{ Name: "Ifchange", - Value: dep["Target"], + Value: dep.tgt, }) } _, err = recfile.NewWriter(w).WriteFields(fields...) @@ -728,8 +716,8 @@ func runScript(tgtOrig string, errs chan error, forced, traced bool) error { goto Finish } } else { - var hsh string - if hshPrev != "" { + var hsh []byte + if hshPrev != nil { _, err = fd.Seek(0, io.SeekStart) if err != nil { err = ErrLine(err) @@ -740,7 +728,7 @@ func runScript(tgtOrig string, errs chan error, forced, traced bool) error { err = ErrLine(err) goto Finish } - if hsh == hshPrev { + if bytes.Equal(hsh, hshPrev) { tracef(CDebug, "%s has same hash, not renaming", tgtOrig) err = ErrLine(os.Remove(fd.Name())) if err != nil { @@ -756,7 +744,7 @@ func runScript(tgtOrig string, errs chan error, forced, traced bool) error { goto Finish } } - err = ErrLine(depWrite(fdDep, cwdOrig, tgt, hshPrev)) + err = ErrLine(depWrite(fdDep, cwdOrig, tgt, hsh)) if err != nil { goto Finish } @@ -804,25 +792,24 @@ func runScript(tgtOrig string, errs chan error, forced, traced bool) error { goto Finish } } + fdDep.Close() // Post-commit .rec sanitizing - fdDep.Close() - if fdDepR, err := os.Open(fdDepPath); err == nil { - depInfo, err := depRead(fdDepR) - fdDepR.Close() - if err != nil { - err = ErrLine(err) - goto Finish - } + if depInfo, err := depRead(fdDepPath); err == nil { ifchangeSeen := make(map[string]struct{}, len(depInfo.ifchanges)) for _, dep := range depInfo.ifchanges { - ifchangeSeen[dep["Target"]] = struct{}{} + ifchangeSeen[dep.tgt] = struct{}{} } for _, dep := range depInfo.ifcreates { if _, exists := ifchangeSeen[dep]; exists { tracef(CWarn, "simultaneous ifcreate and ifchange records: %s", tgt) } } + } else if errors.Is(err, fs.ErrNotExist) { + err = nil + } else { + err = ErrLine(err) + goto Finish } Finish: