]> Cypherpunks.ru repositories - goredo.git/blobdiff - buildlog.go
Download link for 2.6.2 release
[goredo.git] / buildlog.go
index cdbf6ba2ec0595f90f782d41a5cc3827293b82ce..f04efa41e2bf269251b2c56824eaa4d3e48e9581 100644 (file)
@@ -1,19 +1,17 @@
-/*
-goredo -- djb's redo implementation on pure Go
-Copyright (C) 2020-2022 Sergey Matveev <stargrave@stargrave.org>
-
-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
-the Free Software Foundation, version 3 of the License.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
+// goredo -- djb's redo implementation on pure Go
+// Copyright (C) 2020-2024 Sergey Matveev <stargrave@stargrave.org>
+//
+// 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
+// the Free Software Foundation, version 3 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 package main
 
@@ -23,9 +21,9 @@ import (
        "flag"
        "fmt"
        "io"
+       "io/fs"
        "os"
        "path"
-       "path/filepath"
        "sort"
        "strconv"
        "strings"
@@ -38,8 +36,7 @@ import (
 const HumanTimeFmt = "2006-01-02 15:04:05.000000000 Z07:00"
 
 type BuildLogJob struct {
-       dir      string
-       tgt      string
+       tgt      *Tgt
        started  time.Time
        exitCode int
        rec      map[string][]string
@@ -75,15 +72,16 @@ func init() {
        buildLogSeen = make(map[string]struct{})
 }
 
-func parseBuildLogRec(dir, tgt string) (map[string][]string, error) {
-       fd, err := os.Open(path.Join(dir, RedoDir, tgt+LogRecSuffix))
+func parseBuildLogRec(tgt *Tgt) (map[string][]string, error) {
+       h, t := path.Split(tgt.a)
+       fd, err := os.Open(path.Join(h, RedoDir, t+LogRecSuffix))
        if err != nil {
-               return nil, err
+               return nil, ErrLine(err)
        }
        r := recfile.NewReader(bufio.NewReader(fd))
        rec, err := r.NextMapWithSlice()
        fd.Close()
-       return rec, err
+       return rec, ErrLine(err)
 }
 
 func depthPrefix(depth int) string {
@@ -94,39 +92,35 @@ func depthPrefix(depth int) string {
 }
 
 func showBuildLogSub(sub *BuildLogJob, depth int) error {
-       abs, err := filepath.Abs(path.Join(sub.dir, sub.tgt))
-       if err != nil {
-               return err
-       }
-       if _, ok := buildLogSeen[abs]; ok {
+       if _, ok := buildLogSeen[sub.tgt.rel]; ok {
                return nil
        }
-       buildLogSeen[abs] = struct{}{}
+       buildLogSeen[sub.tgt.rel] = struct{}{}
        dp := depthPrefix(depth)
        fmt.Printf(
                "%s%s%s\n",
                sub.rec["Started"][0], dp,
-               colourize(CRedo, "redo "+sub.tgt),
+               colourize(CRedo, "redo "+sub.tgt.rel),
        )
-       if err := showBuildLog(sub.dir, sub.tgt, sub.rec, depth+1); err != nil {
+       if err := showBuildLog(sub.tgt, sub.rec, depth+1); err != nil {
                return err
        }
        durationSec, durationNsec, err := durationToInts(sub.rec["Duration"][0])
        if err != nil {
-               return err
+               return ErrLine(err)
        }
        if sub.exitCode > 0 {
                fmt.Printf(
                        "%s%s%s (code: %d) (%d.%ds)\n\n",
                        sub.rec["Finished"][0], dp,
-                       colourize(CErr, "err "+sub.tgt),
+                       colourize(CErr, "err "+sub.tgt.rel),
                        sub.exitCode, durationSec, durationNsec,
                )
        } else {
                fmt.Printf(
                        "%s%s%s (%d.%ds)\n\n",
                        sub.rec["Finished"][0], dp,
-                       colourize(CRedo, "done "+sub.tgt),
+                       colourize(CRedo, "done "+sub.tgt.rel),
                        durationSec, durationNsec,
                )
        }
@@ -144,7 +138,7 @@ func durationToInts(d string) (int64, int64, error) {
 func showBuildLogCmd(m map[string][]string, depth int) error {
        started, err := tai64n.Decode(m["Started"][0])
        if err != nil {
-               return err
+               return ErrLine(err)
        }
        dp := depthPrefix(depth)
        fmt.Printf(
@@ -156,11 +150,11 @@ func showBuildLogCmd(m map[string][]string, depth int) error {
        }
        finished, err := tai64n.Decode(m["Finished"][0])
        if err != nil {
-               return err
+               return ErrLine(err)
        }
        durationSec, durationNsec, err := durationToInts(m["Duration"][0])
        if err != nil {
-               return err
+               return ErrLine(err)
        }
        fmt.Printf(
                "%s%sStarted:\t%s\n%s%sFinished:\t%s\n%s%sDuration:\t%d.%ds\n\n",
@@ -171,11 +165,10 @@ func showBuildLogCmd(m map[string][]string, depth int) error {
        return nil
 }
 
-func showBuildLog(dir, tgt string, buildLogRec map[string][]string, depth int) error {
+func showBuildLog(tgt *Tgt, buildLogRec map[string][]string, depth int) error {
        var err error
-       dirNormalized, tgtNormalized := cwdAndTgt(path.Join(dir, tgt))
        if *flagBuildLogCommands || *flagBuildLogRecursive {
-               buildLogRec, err = parseBuildLogRec(dirNormalized, tgtNormalized)
+               buildLogRec, err = parseBuildLogRec(tgt)
                if err != nil {
                        return err
                }
@@ -185,9 +178,10 @@ func showBuildLog(dir, tgt string, buildLogRec map[string][]string, depth int) e
                        return err
                }
        }
-       fd, err := os.Open(path.Join(dirNormalized, RedoDir, tgtNormalized+LogSuffix))
+       tgtH, tgtT := path.Split(tgt.a)
+       fd, err := os.Open(path.Join(tgtH, RedoDir, tgtT+LogSuffix))
        if err != nil {
-               return err
+               return ErrLine(err)
        }
        if !*flagBuildLogRecursive {
                w := bufio.NewWriter(os.Stdout)
@@ -195,20 +189,20 @@ func showBuildLog(dir, tgt string, buildLogRec map[string][]string, depth int) e
                fd.Close()
                if err != nil {
                        w.Flush()
-                       return err
+                       return ErrLine(err)
                }
-               return w.Flush()
+               return ErrLine(w.Flush())
        }
        defer fd.Close()
        subs := make([]*BuildLogJob, 0, len(buildLogRec["Ifchange"]))
-       for _, dep := range buildLogRec["Ifchange"] {
-               subDir, subTgt := cwdAndTgt(path.Join(dirNormalized, dep))
-               if subDir == dirNormalized && subTgt == tgtNormalized {
+       for _, depPath := range buildLogRec["Ifchange"] {
+               dep := NewTgt(path.Join(tgtH, depPath))
+               if dep.rel == tgt.rel {
                        continue
                }
-               rec, err := parseBuildLogRec(subDir, subTgt)
+               rec, err := parseBuildLogRec(dep)
                if err != nil {
-                       if os.IsNotExist(err) {
+                       if errors.Is(err, fs.ErrNotExist) {
                                continue
                        }
                        return err
@@ -218,17 +212,16 @@ func showBuildLog(dir, tgt string, buildLogRec map[string][]string, depth int) e
                }
                started, err := tai64n.Decode(rec["Started"][0])
                if err != nil {
-                       return err
+                       return ErrLine(err)
                }
                var exitCode int
                if len(rec["ExitCode"]) > 0 {
                        exitCode, err = strconv.Atoi(rec["ExitCode"][0])
                        if err != nil {
-                               return err
+                               return ErrLine(err)
                        }
                }
                subs = append(subs, &BuildLogJob{
-                       dir:      dirNormalized,
                        tgt:      dep,
                        started:  started,
                        exitCode: exitCode,
@@ -248,13 +241,13 @@ func showBuildLog(dir, tgt string, buildLogRec map[string][]string, depth int) e
        for {
                if !scanner.Scan() {
                        if err = scanner.Err(); err != nil {
-                               return err
+                               return ErrLine(err)
                        }
                        break
                }
                text = scanner.Text()
                if text[0] != '@' {
-                       return errors.New("unexpected non-TAI64Ned string")
+                       return ErrLine(errors.New("unexpected non-TAI64Ned string"))
                }
                sep = strings.IndexByte(text, byte(' '))
                if sep == -1 {
@@ -262,7 +255,7 @@ func showBuildLog(dir, tgt string, buildLogRec map[string][]string, depth int) e
                }
                t, err = tai64n.Decode(text[1:sep])
                if err != nil {
-                       return err
+                       return ErrLine(err)
                }
                for sub != nil && t.After(sub.started) {
                        if err = showBuildLogSub(sub, depth); err != nil {