/redo-ifchange
/redo-ifcreate
/redo-log
+/redo-ood
+/redo-sources
/redo-stamp
+/redo-targets
/redo-whichdo
/tai64nlocal
/VERSION
Display @url{http://cr.yp.to/libtai/tai64.html, TAI64N} timestamped
last @command{stderr} of the target.
+@item redo-targets, redo-sources, redo-ood
+ List known targets, sources and out-of-date targets.
+
@item redo-stamp
Record stamp dependency. Nothing more, dummy. Read about
@ref{Stamping, stamping} in the FAQ.
@anchor{Release 1.3.0}
@section Release 1.3.0
@itemize
+@item
+ Experimental @command{redo-sources}, @command{redo-targets} and
+ @command{redo-ood} commands.
@item
Repetitive OOD determination optimization: pass all already known to
be OOD targets to redoing targets.
"path"
"path/filepath"
"runtime"
+ "sort"
"strconv"
"go.cypherpunks.ru/recfile"
"redo-ifchange",
"redo-ifcreate",
"redo-log",
+ "redo-ood",
+ "redo-sources",
"redo-stamp",
+ "redo-targets",
"redo-whichdo",
} {
fmt.Println(os.Args[0], "<-", cmdName)
}
fmt.Println(rel)
}
+ case "redo-targets":
+ tgts, err = targetsWalker(Cwd)
+ sort.Strings(tgts)
+ for _, tgt := range tgts {
+ fmt.Println(tgt)
+ }
+ case "redo-ood":
+ tgts, err = targetsWalker(Cwd)
+ sort.Strings(tgts)
+ var ood bool
+ for _, tgt := range tgts {
+ ood, err = isOOD(Cwd, tgt, 0, nil)
+ if err != nil {
+ break
+ }
+ if ood {
+ fmt.Println(tgt)
+ }
+ }
+ case "redo-sources":
+ tgts, err = sourcesWalker()
+ sort.Strings(tgts)
+ for _, tgt := range tgts {
+ fmt.Println(tgt)
+ }
default:
log.Fatalln("unknown command", cmdName)
}
--- /dev/null
+/*
+goredo -- djb's redo implementation on pure Go
+Copyright (C) 2020-2021 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
+
+import (
+ "os"
+ "path"
+ "path/filepath"
+ "strings"
+)
+
+func sourcesWalker() ([]string, error) {
+ tgts, err := targetsWalker(Cwd)
+ if err != nil {
+ return nil, err
+ }
+ srcs := make(map[string]struct{}, 1<<10)
+ for _, tgt := range tgts {
+ cwd, f := path.Split(tgt)
+ fdDep, err := os.Open(path.Join(cwd, RedoDir, f+DepSuffix))
+ if err != nil {
+ return nil, err
+ }
+ depInfo, err := depRead(fdDep)
+ fdDep.Close()
+ for _, m := range depInfo.ifchanges {
+ tgt = m["Target"]
+ if !strings.HasSuffix(tgt, ".do") && isSrc(cwd, tgt) {
+ pth, err := filepath.Abs(path.Join(cwd, tgt))
+ if err != nil {
+ panic(err)
+ }
+ srcs[cwdMustRel(pth)] = struct{}{}
+ }
+ }
+ }
+ tgts = make([]string, 0, len(srcs))
+ for tgt := range srcs {
+ tgts = append(tgts, tgt)
+ }
+ return tgts, nil
+}
--- /dev/null
+/*
+goredo -- djb's redo implementation on pure Go
+Copyright (C) 2020-2021 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
+
+import (
+ "io"
+ "os"
+ "path"
+ "path/filepath"
+ "strings"
+)
+
+func targetsWalker(root string) ([]string, error) {
+ root, err := filepath.Abs(root)
+ if err != nil {
+ panic(err)
+ }
+ dir, err := os.Open(root)
+ if err != nil {
+ return nil, err
+ }
+ defer dir.Close()
+ tgts := make([]string, 0, 1<<10)
+ for {
+ fis, err := dir.Readdir(1 << 10)
+ if err != nil {
+ if err == io.EOF {
+ break
+ }
+ return tgts, err
+ }
+ for _, fi := range fis {
+ if !fi.IsDir() {
+ continue
+ }
+ pth := path.Join(root, fi.Name())
+ if fi.Name() == RedoDir {
+ redoDir, err := os.Open(pth)
+ if err != nil {
+ return tgts, err
+ }
+ redoFis, err := redoDir.Readdir(0)
+ if err != nil {
+ return tgts, err
+ }
+ for _, redoFi := range redoFis {
+ name := redoFi.Name()
+ if strings.HasSuffix(name, DepSuffix) {
+ name = cwdMustRel(root, name)
+ tgts = append(tgts, name[:len(name)-len(DepSuffix)])
+ }
+ }
+ redoDir.Close()
+ } else {
+ subTgts, err := targetsWalker(pth)
+ tgts = append(tgts, subTgts...)
+ if err != nil {
+ return tgts, err
+ }
+ }
+ }
+ }
+ return tgts, dir.Close()
+}
Display .do search paths for specified target. Exits successfully
if the last .do in output if the found existing one.`
+ case "redo-targets":
+ d = `Usage: redo-targets
+
+List all currently known targets.`
+ case "redo-sources":
+ d = `Usage: redo-sources
+
+List all currently known source files.`
+ case "redo-ood":
+ d = `Usage: redo-ood
+
+List all currently known out-of-date targets.`
default:
d = `Usage: goredo -symlinks
Available commands: redo, redo-always, redo-cleanup, redo-dot,
redo-ifchange, redo-ifcreate, redo-log, redo-stamp, redo-whichdo.`
}
- fmt.Fprintf(os.Stderr, "%s\n\nOptions:\n", d)
+ fmt.Fprintf(os.Stderr, "%s\n\nCommon options:\n", d)
flag.PrintDefaults()
fmt.Fprintln(os.Stderr, `
Additional environment variables: