From 7782b7e4df32b283c92f08e70c3cf64c69a43fcd Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Sat, 16 Jan 2021 20:03:46 +0300 Subject: [PATCH 01/16] Fix recfile's schema --- dep.rec | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dep.rec b/dep.rec index 2691201..f0f6ced 100644 --- a/dep.rec +++ b/dep.rec @@ -1,11 +1,13 @@ %rec: Build %doc: Build session -%mandatory: Build +%key: Build %type: Build uuid %rec: Dependency %doc: Dependency information %mandatory: Type +%allowed: Target Ctime Hash +%unique: Type Target Ctime Hash %type: Type enum ifcreate ifchange always stamp -%type: Ctime regexp /\d+\.\d+/ +%type: Ctime regexp /[0-9]+\.[0-9]+/ %type: Hash regexp /[0-9a-f]{64}/ -- 2.44.0 From ebd96d2c56c742d9d00bccb9faee5fc1a7db664a Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Sat, 16 Jan 2021 20:57:04 +0300 Subject: [PATCH 02/16] More general Inode information tracking, explicit size check --- dep.go | 40 ++++++++------------ dep.rec | 8 ++-- doc/features.texi | 3 +- doc/news.texi | 7 +++- doc/state.texi | 4 +- inode.go | 94 +++++++++++++++++++++++++++++++++++++++++++++++ ood.go | 24 ++++++++---- run.go | 38 ++++++++++--------- usage.go | 2 +- 9 files changed, 162 insertions(+), 58 deletions(-) create mode 100644 inode.go diff --git a/dep.go b/dep.go index d7c874a..55613c7 100644 --- a/dep.go +++ b/dep.go @@ -23,14 +23,12 @@ import ( "bufio" "encoding/hex" "errors" - "fmt" "io" "os" "path" "path/filepath" "go.cypherpunks.ru/recfile" - "golang.org/x/sys/unix" "lukechampine.com/blake3" ) @@ -75,15 +73,6 @@ func stamp(fdDep, src *os.File) error { ) } -func fileCtime(fd *os.File) (string, error) { - var stat unix.Stat_t - if err := unix.Fstat(int(fd.Fd()), &stat); err != nil { - return "", err - } - sec, nsec := stat.Ctim.Unix() - return fmt.Sprintf("%d.%d", sec, nsec), nil -} - func fileHash(fd *os.File) (string, error) { h := blake3.New(32, nil) if _, err := io.Copy(h, bufio.NewReader(fd)); err != nil { @@ -106,7 +95,7 @@ func writeDep(fdDep *os.File, cwd, tgt string) error { if fi.IsDir() { return nil } - ts, err := fileCtime(fd) + inode, err := inodeFromFile(fd) if err != nil { return err } @@ -114,13 +103,13 @@ func writeDep(fdDep *os.File, cwd, tgt string) error { if err != nil { return err } - return recfileWrite( - fdDep, - recfile.Field{Name: "Type", Value: DepTypeIfchange}, - recfile.Field{Name: "Target", Value: tgt}, - recfile.Field{Name: "Ctime", Value: ts}, - recfile.Field{Name: "Hash", Value: hsh}, - ) + fields := []recfile.Field{ + {Name: "Type", Value: DepTypeIfchange}, + {Name: "Target", Value: tgt}, + {Name: "Hash", Value: hsh}, + } + fields = append(fields, inode.RecfileFields()...) + return recfileWrite(fdDep, fields...) } func writeDeps(fdDep *os.File, tgts []string) (err error) { @@ -142,12 +131,13 @@ func writeDeps(fdDep *os.File, tgts []string) (err error) { err = writeDep(fdDep, tgtDir, tgtRel) } else { trace(CDebug, "ifchange: %s <- %s (unexisting)", fdDep.Name(), tgtRel) - err = recfileWrite( - fdDep, - recfile.Field{Name: "Type", Value: DepTypeIfchange}, - recfile.Field{Name: "Target", Value: tgtRel}, - recfile.Field{Name: "Ctime", Value: "0.0"}, - ) + fields := []recfile.Field{ + {Name: "Type", Value: DepTypeIfchange}, + {Name: "Target", Value: tgtRel}, + } + inodeDummy := Inode{} + fields = append(fields, inodeDummy.RecfileFields()...) + err = recfileWrite(fdDep, fields...) } } return diff --git a/dep.rec b/dep.rec index f0f6ced..9f41434 100644 --- a/dep.rec +++ b/dep.rec @@ -6,8 +6,10 @@ %rec: Dependency %doc: Dependency information %mandatory: Type -%allowed: Target Ctime Hash -%unique: Type Target Ctime Hash +%allowed: Target Size CtimeSec CtimeNsec Hash +%unique: Type Target Size CtimeSec CtimeNsec Hash %type: Type enum ifcreate ifchange always stamp -%type: Ctime regexp /[0-9]+\.[0-9]+/ +%type: Size int +%type: CtimeSec int +%type: CtimeNsec int %type: Hash regexp /[0-9a-f]{64}/ diff --git a/doc/features.texi b/doc/features.texi index 9145312..2c5141e 100644 --- a/doc/features.texi +++ b/doc/features.texi @@ -12,7 +12,8 @@ @end itemize @item targets, dependency information and their directories are explicitly synced (can be disabled, should work faster) -@item file's change is detected by comparing its @code{ctime} and BLAKE3 hash +@item file's change is detected by comparing its size, @code{ctime} + and BLAKE3 hash @item files creation is @code{umask}-friendly (unlike @code{mkstemp()} used in @command{redo-c}) @item parallel build with jobs limit, optionally in infinite mode diff --git a/doc/news.texi b/doc/news.texi index 5484635..bc4322e 100644 --- a/doc/news.texi +++ b/doc/news.texi @@ -1,9 +1,12 @@ @node News @unnumbered News -@anchor{Release 0.13.0} -@section Release 0.13.0 +@anchor{Release 1.0.0} +@section Release 1.0.0 @itemize +@item + @code{Size} is stored in the state, for faster OOD detection. + Previous @command{goredo} state files won't work. @item @command{redo-whichdo} resembles @code{apenwarr/redo}'s one behaviour more. @end itemize diff --git a/doc/state.texi b/doc/state.texi index 5313ae1..fa7c28c 100644 --- a/doc/state.texi +++ b/doc/state.texi @@ -15,7 +15,9 @@ Target: foo.o.do Type: ifchange Target: default.o.do -Ctime: 1605721341.253305000 +Size: 123 +CtimeSec: 1605721341 +CtimeNsec: 253305000 Hash: f4929732f96f11e6d4ebe94536b5edef426d00ed0146853e37a87f4295e18eda Type: always diff --git a/inode.go b/inode.go new file mode 100644 index 0000000..81e77bb --- /dev/null +++ b/inode.go @@ -0,0 +1,94 @@ +/* +goredo -- 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 +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 . +*/ + +// Inode metainformation + +package main + +import ( + "errors" + "os" + "strconv" + + "go.cypherpunks.ru/recfile" + "golang.org/x/sys/unix" +) + +type Inode struct { + Size int64 + CtimeSec int64 + CtimeNsec int64 +} + +func (our *Inode) Equals(their *Inode) bool { + return (our.Size == their.Size) && + (our.CtimeSec == their.CtimeSec) && + (our.CtimeNsec == their.CtimeNsec) +} + +func (inode *Inode) RecfileFields() []recfile.Field { + return []recfile.Field{ + {Name: "Size", Value: strconv.FormatInt(inode.Size, 10)}, + {Name: "CtimeSec", Value: strconv.FormatInt(inode.CtimeSec, 10)}, + {Name: "CtimeNsec", Value: strconv.FormatInt(inode.CtimeNsec, 10)}, + } +} + +func inodeFromFile(fd *os.File) (*Inode, error) { + var fi os.FileInfo + fi, err := fd.Stat() + if err != nil { + return nil, err + } + var stat unix.Stat_t + err = unix.Fstat(int(fd.Fd()), &stat) + if err != nil { + return nil, err + } + sec, nsec := stat.Ctim.Unix() + return &Inode{Size: fi.Size(), CtimeSec: sec, CtimeNsec: nsec}, nil +} + +func inodeFromRec(m map[string]string) (*Inode, error) { + size := m["Size"] + ctimeSec := m["CtimeSec"] + ctimeNsec := m["CtimeNsec"] + if size == "" { + return nil, errors.New("Size is missing") + } + if ctimeSec == "" { + return nil, errors.New("CtimeSec is missing") + } + if ctimeNsec == "" { + return nil, errors.New("CtimeNsec is missing") + } + inode := Inode{} + var err error + inode.Size, err = strconv.ParseInt(size, 10, 64) + if err != nil { + return nil, err + } + inode.CtimeSec, err = strconv.ParseInt(ctimeSec, 10, 64) + if err != nil { + return nil, err + } + inode.CtimeNsec, err = strconv.ParseInt(ctimeNsec, 10, 64) + if err != nil { + return nil, err + } + return &inode, nil +} diff --git a/ood.go b/ood.go index 7f2adde..e75dd43 100644 --- a/ood.go +++ b/ood.go @@ -109,11 +109,14 @@ func isOOD(cwd, tgtOrig string, level int, seen map[string]struct{}) (bool, erro for _, m := range depInfo.ifchanges { dep := m["Target"] - theirTs := m["Ctime"] - theirHsh := m["Hash"] - if dep == "" || theirTs == "" { - return ood, TgtErr{tgtOrig, errors.New("invalid format of .dep")} + if dep == "" { + return ood, TgtErr{tgtOrig, errors.New("invalid format of .dep: missing Target")} + } + theirInode, err := inodeFromRec(m) + if err != nil { + return ood, TgtErr{tgtOrig, fmt.Errorf("invalid format of .dep: %v", err)} } + theirHsh := m["Hash"] trace(CDebug, "ood: %s%s -> %s: checking", indent, tgtOrig, dep) fd, err := os.Open(path.Join(cwd, dep)) @@ -127,14 +130,19 @@ func isOOD(cwd, tgtOrig string, level int, seen map[string]struct{}) (bool, erro } defer fd.Close() - ts, err := fileCtime(fd) + inode, err := inodeFromFile(fd) if err != nil { return ood, TgtErr{tgtOrig, err} } - if theirTs == ts { - trace(CDebug, "ood: %s%s -> %s: same ctime", indent, tgtOrig, dep) + if inode.Size != theirInode.Size { + trace(CDebug, "ood: %s%s -> %s: size differs", indent, tgtOrig, dep) + ood = true + goto Done + } + if inode.Equals(theirInode) { + trace(CDebug, "ood: %s%s -> %s: same inode", indent, tgtOrig, dep) } else { - trace(CDebug, "ood: %s%s -> %s: ctime differs", indent, tgtOrig, dep) + trace(CDebug, "ood: %s%s -> %s: inode differs", indent, tgtOrig, dep) hsh, err := fileHash(fd) if err != nil { return ood, TgtErr{tgtOrig, err} diff --git a/run.go b/run.go index d8e439d..1dc937d 100644 --- a/run.go +++ b/run.go @@ -101,24 +101,24 @@ func mkdirs(pth string) error { return os.MkdirAll(pth, os.FileMode(0777)) } -func isModified(cwd, redoDir, tgt string) (bool, string, error) { +func isModified(cwd, redoDir, tgt string) (bool, *Inode, error) { fdDep, err := os.Open(path.Join(redoDir, tgt+DepSuffix)) if err != nil { if os.IsNotExist(err) { - return false, "", nil + return false, nil, nil } - return false, "", err + return false, nil, err } defer fdDep.Close() r := recfile.NewReader(fdDep) - var ourTs string + var ourInode *Inode for { m, err := r.NextMap() if err != nil { if err == io.EOF { break } - return false, "", err + return false, nil, err } if m["Target"] != tgt { continue @@ -126,21 +126,25 @@ func isModified(cwd, redoDir, tgt string) (bool, string, error) { fd, err := os.Open(path.Join(cwd, tgt)) if err != nil { if os.IsNotExist(err) { - return false, "", nil + return false, nil, nil } - return false, "", err + return false, nil, err } - defer fd.Close() - ourTs, err = fileCtime(fd) + ourInode, err = inodeFromFile(fd) + fd.Close() if err != nil { - return false, "", err + return false, nil, err } - if ourTs != m["Ctime"] { - return true, ourTs, nil + theirInode, err := inodeFromRec(m) + if err != nil { + return false, nil, err + } + if !ourInode.Equals(theirInode) { + return true, ourInode, nil } break } - return false, ourTs, nil + return false, ourInode, nil } func syncDir(dir string) error { @@ -222,7 +226,7 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { } // Check if target is not modified externally - modified, tsPrev, err := isModified(cwd, redoDir, tgt) + modified, inodePrev, err := isModified(cwd, redoDir, tgt) if err != nil { lockRelease() return TgtErr{tgtOrig, err} @@ -462,11 +466,11 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { } // Was $1 touched? - if tsPrev != "" { + if inodePrev != nil { if fd, err := os.Open(path.Join(cwdOrig, tgt)); err == nil { - ts, err := fileCtime(fd) + inode, err := inodeFromFile(fd) fd.Close() - if err == nil && ts != tsPrev { + if err == nil && !inode.Equals(inodePrev) { runErr.Err = errors.New("$1 was explicitly touched") errs <- runErr fd.Close() diff --git a/usage.go b/usage.go index 8fa4aaa..ce838b4 100644 --- a/usage.go +++ b/usage.go @@ -26,7 +26,7 @@ import ( ) const ( - Version = "0.13.0" + Version = "1.0.0" Warranty = `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. -- 2.44.0 From 9cbb466ce80096c2c12c88be50e475265adb74b1 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Sat, 16 Jan 2021 21:14:15 +0300 Subject: [PATCH 03/16] REDO_INODE_NO_TRUST --- doc/faq.texi | 5 +++-- doc/features.texi | 5 +++-- doc/news.texi | 4 ++++ inode.go | 4 ++++ main.go | 1 + ood.go | 2 +- usage.go | 4 +++- 7 files changed, 19 insertions(+), 6 deletions(-) diff --git a/doc/faq.texi b/doc/faq.texi index 1c6def3..9b909a6 100644 --- a/doc/faq.texi +++ b/doc/faq.texi @@ -4,8 +4,9 @@ @anchor{Stamping} @section Hashing and stamping -All targets are checksummed if their @file{ctime} differs from the -previous one. @command{apenwarr/redo} gives +All targets are checksummed if no @env{REDO_INODE_NO_TRUST} environment +variable is set and target's @file{ctime} differs from the previous one. +@command{apenwarr/redo} gives @url{https://redo.readthedocs.io/en/latest/FAQImpl/#why-not-always-use-checksum-based-dependencies-instead-of-timestamps, many reasons} why every time checksumming is bad, but in my opinion in practice all of them do not apply. diff --git a/doc/features.texi b/doc/features.texi index 2c5141e..843222d 100644 --- a/doc/features.texi +++ b/doc/features.texi @@ -12,8 +12,9 @@ @end itemize @item targets, dependency information and their directories are explicitly synced (can be disabled, should work faster) -@item file's change is detected by comparing its size, @code{ctime} - and BLAKE3 hash +@item file's change is detected by comparing its size, @code{ctime} (if + @env{REDO_INODE_NO_TRUST} environment variable is not set) and + BLAKE3 hash @item files creation is @code{umask}-friendly (unlike @code{mkstemp()} used in @command{redo-c}) @item parallel build with jobs limit, optionally in infinite mode diff --git a/doc/news.texi b/doc/news.texi index bc4322e..3d5a651 100644 --- a/doc/news.texi +++ b/doc/news.texi @@ -7,6 +7,10 @@ @item @code{Size} is stored in the state, for faster OOD detection. Previous @command{goredo} state files won't work. +@item + Setting of @env{REDO_INODE_NO_TRUST} environment variable brings no + trust to file inode's information (except for its size), forcing its + checksum checking. @item @command{redo-whichdo} resembles @code{apenwarr/redo}'s one behaviour more. @end itemize diff --git a/inode.go b/inode.go index 81e77bb..2d929a2 100644 --- a/inode.go +++ b/inode.go @@ -28,6 +28,10 @@ import ( "golang.org/x/sys/unix" ) +const EnvInodeNoTrust = "REDO_INODE_NO_TRUST" + +var InodeTrust bool = false + type Inode struct { Size int64 CtimeSec int64 diff --git a/main.go b/main.go index 873582a..7d1c719 100644 --- a/main.go +++ b/main.go @@ -101,6 +101,7 @@ func main() { NoColor = os.Getenv(EnvNoColor) != "" NoSync = os.Getenv(EnvNoSync) == "1" + InodeTrust = os.Getenv(EnvInodeNoTrust) == "" TopDir = os.Getenv(EnvTopDir) if TopDir == "" { diff --git a/ood.go b/ood.go index e75dd43..5fe1104 100644 --- a/ood.go +++ b/ood.go @@ -139,7 +139,7 @@ func isOOD(cwd, tgtOrig string, level int, seen map[string]struct{}) (bool, erro ood = true goto Done } - if inode.Equals(theirInode) { + if InodeTrust && inode.Equals(theirInode) { trace(CDebug, "ood: %s%s -> %s: same inode", indent, tgtOrig, dep) } else { trace(CDebug, "ood: %s%s -> %s: inode differs", indent, tgtOrig, dep) diff --git a/usage.go b/usage.go index ce838b4..beb221f 100644 --- a/usage.go +++ b/usage.go @@ -91,5 +91,7 @@ Additional environment variables: NO_COLOR -- disable messages colouring REDO_NO_SYNC -- disable files/directories explicit filesystem syncing REDO_TOP_DIR -- do not search for .do above that directory - (it can contain .redo/top as an alternative)`) + (it can contain .redo/top as an alternative) + REDO_INODE_NO_TRUST -- do not trust inode information (except for size) + and always check file's hash`) } -- 2.44.0 From d17aadaecd4cd779f605c0c7d668d3caf80282a0 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Sat, 16 Jan 2021 21:28:48 +0300 Subject: [PATCH 04/16] Download link for 1.0.0 release --- doc/download.texi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/download.texi b/doc/download.texi index c6b581a..845c5d4 100644 --- a/doc/download.texi +++ b/doc/download.texi @@ -1,6 +1,10 @@ @multitable {XXXXX} {XXXX-XX-XX} {XXXX KiB} {link sign} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} @headitem Version @tab Date @tab Size @tab Tarball @tab SHA256 checksum +@item @ref{Release 1.0.0, 1.0.0} @tab 2021-01-16 @tab 338 KiB +@tab @url{download/goredo-1.0.0.tar.zst, link} @url{download/goredo-1.0.0.tar.zst.sig, sign} +@tab @code{8D99B8FC 1057AEF6 437BE131 2112781E 00030AFD D01DA2F0 E233B042 187A2F01} + @item @ref{Release 0.12.3, 0.12.3} @tab 2021-01-13 @tab 336 KiB @tab @url{download/goredo-0.12.3.tar.zst, link} @url{download/goredo-0.12.3.tar.zst.sig, sign} @tab @code{D735A273 12504914 EC4413AB C6719C52 800D5AA5 DEFB135E 87139629 9B2C720F} -- 2.44.0 From 49a98a74391054ee57a3544cd2c1d822c5d4f077 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Wed, 20 Jan 2021 12:09:13 +0300 Subject: [PATCH 05/16] Homebrew URL fix --- doc/install.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/install.texi b/doc/install.texi index 3544bc0..b32e83c 100644 --- a/doc/install.texi +++ b/doc/install.texi @@ -4,7 +4,7 @@ Possibly @command{goredo} package already exists for your distribution: @itemize @item @url{https://aur.archlinux.org/packages/goredo/, Arch Linux AUR} -@item macOS @url{https://github.com/Homebrew/homebrew-core/blob/master/Formula/goredo.rb, Homebrew} +@item macOS @url{https://formulae.brew.sh/formula/goredo, Homebrew} @end itemize Preferable way is to download tarball with the signature from website: -- 2.44.0 From cd29a67e26ef05f0ffadd83448f09886edef4111 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Wed, 20 Jan 2021 12:09:22 +0300 Subject: [PATCH 06/16] Seems everyone uses Kai Hendry's goredo initial description I have nothing against it, even like it. --- README | 2 +- cleanup.go | 2 +- dep.go | 2 +- do.go | 2 +- doc/index.texi | 6 ++++-- dot.go | 2 +- ifchange.go | 2 +- inode.go | 2 +- js.go | 2 +- log.go | 2 +- main.go | 2 +- makedist.sh | 3 ++- ood.go | 2 +- run.go | 2 +- status.go | 2 +- tmp.go | 2 +- usage.go | 2 +- 17 files changed, 21 insertions(+), 18 deletions(-) diff --git a/README b/README index f64ff9d..22489fa 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -goredo -- redo implementation on pure Go. +Go implementation of djb's redo, Makefile replacement that sucks less. See goredo.info and INSTALL for more information. goredo is free software: see the file COPYING for copying conditions. Home page: http://www.goredo.cypherpunks.ru/ diff --git a/cleanup.go b/cleanup.go index f75788a..2c4268c 100644 --- a/cleanup.go +++ b/cleanup.go @@ -1,5 +1,5 @@ /* -goredo -- redo implementation on pure Go +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 diff --git a/dep.go b/dep.go index 55613c7..a64da9e 100644 --- a/dep.go +++ b/dep.go @@ -1,5 +1,5 @@ /* -goredo -- redo implementation on pure Go +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 diff --git a/do.go b/do.go index 7d0ed51..516b143 100644 --- a/do.go +++ b/do.go @@ -1,5 +1,5 @@ /* -goredo -- redo implementation on pure Go +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 diff --git a/doc/index.texi b/doc/index.texi index 3b897d8..f7c8494 100644 --- a/doc/index.texi +++ b/doc/index.texi @@ -9,8 +9,10 @@ Copyright @copyright{} 2020-2021 @email{stargrave@@stargrave.org, Sergey Matveev @node Top @top -This is pure Go implementation of @url{http://cr.yp.to/redo.html, DJB's -redo} build system proposal. Originally it was just a rewrite of +Go implementation of @url{http://cr.yp.to/redo.html, djb's redo}, +Makefile replacement that @url{https://suckless.org/philosophy/, sucks less}. + +Originally it was just a rewrite of @url{https://github.com/leahneukirchen/redo-c, redo-c}, but later most features of @url{https://redo.readthedocs.io/en/latest/, apenwarr/redo} were also implemented. Why yet another implementation? It is feature diff --git a/dot.go b/dot.go index 04f329c..39c9019 100644 --- a/dot.go +++ b/dot.go @@ -1,5 +1,5 @@ /* -goredo -- redo implementation on pure Go +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 diff --git a/ifchange.go b/ifchange.go index 2108de2..f89da48 100644 --- a/ifchange.go +++ b/ifchange.go @@ -1,5 +1,5 @@ /* -goredo -- redo implementation on pure Go +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 diff --git a/inode.go b/inode.go index 2d929a2..45c3acb 100644 --- a/inode.go +++ b/inode.go @@ -1,5 +1,5 @@ /* -goredo -- redo implementation on pure Go +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 diff --git a/js.go b/js.go index a984669..2efdd16 100644 --- a/js.go +++ b/js.go @@ -1,5 +1,5 @@ /* -goredo -- redo implementation on pure Go +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 diff --git a/log.go b/log.go index bc0b79a..703f198 100644 --- a/log.go +++ b/log.go @@ -1,5 +1,5 @@ /* -goredo -- redo implementation on pure Go +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 diff --git a/main.go b/main.go index 7d1c719..734239b 100644 --- a/main.go +++ b/main.go @@ -1,5 +1,5 @@ /* -goredo -- redo implementation on pure Go +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 diff --git a/makedist.sh b/makedist.sh index ad38c99..10bcc85 100755 --- a/makedist.sh +++ b/makedist.sh @@ -107,7 +107,8 @@ Subject: goredo $release release announcement I am pleased to announce goredo $release release availability! -goredo is redo implementation on pure Go. +goredo is Go implementation of djb's redo, +Makefile replacement that sucks less. ------------------------ >8 ------------------------ diff --git a/ood.go b/ood.go index 5fe1104..912b6c6 100644 --- a/ood.go +++ b/ood.go @@ -1,5 +1,5 @@ /* -goredo -- redo implementation on pure Go +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 diff --git a/run.go b/run.go index 1dc937d..2fed7cf 100644 --- a/run.go +++ b/run.go @@ -1,5 +1,5 @@ /* -goredo -- redo implementation on pure Go +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 diff --git a/status.go b/status.go index d9e7f56..139ceb7 100644 --- a/status.go +++ b/status.go @@ -1,5 +1,5 @@ /* -goredo -- redo implementation on pure Go +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 diff --git a/tmp.go b/tmp.go index 8e8bff3..5b875bf 100644 --- a/tmp.go +++ b/tmp.go @@ -1,5 +1,5 @@ /* -goredo -- redo implementation on pure Go +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 diff --git a/usage.go b/usage.go index beb221f..5948b69 100644 --- a/usage.go +++ b/usage.go @@ -1,5 +1,5 @@ /* -goredo -- redo implementation on pure Go +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 -- 2.44.0 From b1380c4500760639f27a36db4c8aa6f1422f489a Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Wed, 20 Jan 2021 12:11:52 +0300 Subject: [PATCH 07/16] FreeBSD port availability --- doc/install.texi | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/install.texi b/doc/install.texi index b32e83c..40b39d6 100644 --- a/doc/install.texi +++ b/doc/install.texi @@ -4,6 +4,7 @@ Possibly @command{goredo} package already exists for your distribution: @itemize @item @url{https://aur.archlinux.org/packages/goredo/, Arch Linux AUR} +@item @url{https://www.freshports.org/devel/goredo/, FreeBSD ports} @item macOS @url{https://formulae.brew.sh/formula/goredo, Homebrew} @end itemize -- 2.44.0 From 7eabb39c54b96fca347a0576f501239d89bd8ec6 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Fri, 22 Jan 2021 13:57:34 +0300 Subject: [PATCH 08/16] cleanup -dry-run --- cleanup.go | 27 ++++++++++++++++++++------- doc/news.texi | 7 +++++++ usage.go | 4 ++-- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/cleanup.go b/cleanup.go index 2c4268c..61f028f 100644 --- a/cleanup.go +++ b/cleanup.go @@ -18,6 +18,7 @@ along with this program. If not, see . package main import ( + "flag" "fmt" "io" "log" @@ -33,6 +34,10 @@ const ( CleanupTmp = "tmp" ) +var ( + DryRun = flag.Bool("dry-run", false, "do no delete files during cleanup, just show them") +) + func redoDirClean(root, what string) error { root, err := filepath.Abs(root) if err != nil { @@ -57,15 +62,19 @@ func redoDirClean(root, what string) error { case CleanupLog: if strings.HasSuffix(fi.Name(), LogSuffix) { fmt.Println(pth) - if err = os.Remove(pth); err != nil { - return err + if !*DryRun { + if err = os.Remove(pth); err != nil { + return err + } } } case CleanupTmp: if strings.HasPrefix(fi.Name(), TmpPrefix) { fmt.Println(pth) - if err = os.Remove(pth); err != nil { - return err + if !*DryRun { + if err = os.Remove(pth); err != nil { + return err + } } } default: @@ -101,7 +110,9 @@ func cleanupWalker(root, what string) error { if fi.Name() == RedoDir { if what == CleanupFull { fmt.Println(pthRel) - err = os.RemoveAll(pth) + if !*DryRun { + err = os.RemoveAll(pth) + } } else { err = redoDirClean(pth, what) } @@ -116,8 +127,10 @@ func cleanupWalker(root, what string) error { if (what == CleanupTmp || what == CleanupFull) && strings.HasPrefix(fi.Name(), TmpPrefix) { fmt.Println(pthRel) - if err = os.Remove(pth); err != nil { - return err + if !*DryRun { + if err = os.Remove(pth); err != nil { + return err + } } } } diff --git a/doc/news.texi b/doc/news.texi index 3d5a651..99faeda 100644 --- a/doc/news.texi +++ b/doc/news.texi @@ -1,6 +1,13 @@ @node News @unnumbered News +@anchor{Release 1.1.0} +@section Release 1.1.0 +@itemize +@item + @command{redo-cleanup} has @option{-dry-run} option. +@end itemize + @anchor{Release 1.0.0} @section Release 1.0.0 @itemize diff --git a/usage.go b/usage.go index 5948b69..d31db40 100644 --- a/usage.go +++ b/usage.go @@ -26,7 +26,7 @@ import ( ) const ( - Version = "1.0.0" + Version = "1.1.0" Warranty = `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. @@ -61,7 +61,7 @@ You can create them by running: goredo -symlinks. forcefully and *sequentially* build specified targets * redo-always always build current target. Unusable outside .do -* redo-cleanup {full,log,tmp} [...] +* redo-cleanup [-dry-run] {full,log,tmp} [...] remove either all goredo's related temporary files, or kept stderr logs, or everything (including .redo directories) related * redo-dot target [...] -- 2.44.0 From 3f2777e6cef62cbcaa5382c105f76d60b2ecb3bf Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Sun, 24 Jan 2021 00:06:23 +0300 Subject: [PATCH 09/16] Download link for 1.1.0 release --- doc/download.texi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/download.texi b/doc/download.texi index 845c5d4..9dead3b 100644 --- a/doc/download.texi +++ b/doc/download.texi @@ -1,6 +1,10 @@ @multitable {XXXXX} {XXXX-XX-XX} {XXXX KiB} {link sign} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} @headitem Version @tab Date @tab Size @tab Tarball @tab SHA256 checksum +@item @ref{Release 1.1.0, 1.1.0} @tab 2021-01-24 @tab 338 KiB +@tab @url{download/goredo-1.1.0.tar.zst, link} @url{download/goredo-1.1.0.tar.zst.sig, sign} +@tab @code{63A9FEA6 66665D16 626171C8 65C11C48 C258EB7F A9112982 755E62B9 B5100570} + @item @ref{Release 1.0.0, 1.0.0} @tab 2021-01-16 @tab 338 KiB @tab @url{download/goredo-1.0.0.tar.zst, link} @url{download/goredo-1.0.0.tar.zst.sig, sign} @tab @code{8D99B8FC 1057AEF6 437BE131 2112781E 00030AFD D01DA2F0 E233B042 187A2F01} -- 2.44.0 From 9e1cd5bf6c54ecad62b38a4f9eb2192e2924e46c Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Thu, 28 Jan 2021 20:54:32 +0300 Subject: [PATCH 10/16] jdebp.eu domain does not exists anymore --- doc/index.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/index.texi b/doc/index.texi index f7c8494..fea353c 100644 --- a/doc/index.texi +++ b/doc/index.texi @@ -27,7 +27,7 @@ If you are not familiar with the redo, here are advisable links to read: @itemize @item @url{https://redo.readthedocs.io/en/latest/, apenwarr/redo documentation} -@item @url{http://jdebp.eu/FGA/introduction-to-redo.html, Introduction to redo} +@item @url{http://web.archive.org/web/20201231033027/http://jdebp.eu/FGA/introduction-to-redo.html, Introduction to redo} @item @url{https://apenwarr.ca/log/20101214, The only build system that might someday replace make... is djb redo} @item @url{https://habr.com/ru/post/517490/,, Make на мыло, redo сила} (on russian) @end itemize -- 2.44.0 From 16e534744c4a51dff41f8f1dc47ae7657125f5a1 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Thu, 28 Jan 2021 20:55:07 +0300 Subject: [PATCH 11/16] Remove closing of already closed file --- run.go | 1 - 1 file changed, 1 deletion(-) diff --git a/run.go b/run.go index 2fed7cf..f6a9042 100644 --- a/run.go +++ b/run.go @@ -473,7 +473,6 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { if err == nil && !inode.Equals(inodePrev) { runErr.Err = errors.New("$1 was explicitly touched") errs <- runErr - fd.Close() return } } -- 2.44.0 From f85b073ee154a49bbd7ca0b6b2a68add4968700c Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Thu, 28 Jan 2021 21:13:22 +0300 Subject: [PATCH 12/16] Pipes can fail at OS level, do not panic --- js.go | 6 +++--- main.go | 4 ++-- status.go | 3 ++- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/js.go b/js.go index 2efdd16..701d26d 100644 --- a/js.go +++ b/js.go @@ -92,7 +92,7 @@ func jsInit() { JSR, JSW, err = os.Pipe() if err != nil { - panic(err) + log.Fatalln(err) } for i := uint64(0); i < jobs; i++ { jsRelease("initial fill") @@ -101,7 +101,7 @@ func jsInit() { func jsReleaseNoLock() { if n, err := JSW.Write([]byte{0}); err != nil || n != 1 { - panic("can not write JSW") + log.Fatalln("can not write JSW:", err) } } @@ -124,7 +124,7 @@ func jsAcquire(ctx string) { } trace(CJS, "acquire for %s", ctx) if n, err := JSR.Read([]byte{0}); err != nil || n != 1 { - panic("can not read JSR") + log.Fatalln("can not read JSR:", err) } jsTokensM.Lock() jsTokens++ diff --git a/main.go b/main.go index 734239b..2007215 100644 --- a/main.go +++ b/main.go @@ -96,7 +96,7 @@ func main() { var err error Cwd, err = os.Getwd() if err != nil { - panic(err) + log.Fatalln(err) } NoColor = os.Getenv(EnvNoColor) != "" @@ -178,7 +178,7 @@ func main() { 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( diff --git a/status.go b/status.go index 139ceb7..e6c9b31 100644 --- a/status.go +++ b/status.go @@ -20,6 +20,7 @@ package main import ( "flag" "fmt" + "log" "os" ) @@ -57,7 +58,7 @@ func statusInit() { var err error r, FdStatus, err = os.Pipe() if err != nil { - panic(err) + log.Fatalln(err) } go func() { running := 0 -- 2.44.0 From 5ca39bfc0b769607db3f84213fc7f16f0c4019fa Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Fri, 29 Jan 2021 10:38:55 +0300 Subject: [PATCH 13/16] Change dependency files extension to .rec --- dep.go | 8 ++++---- doc/cmds.texi | 2 +- doc/faq.texi | 4 ++-- doc/news.texi | 9 +++++++++ doc/state.texi | 2 +- ood.go | 4 ++-- run.go | 8 ++++---- t/goredo-deps.t | 2 +- usage.go | 2 +- 9 files changed, 25 insertions(+), 16 deletions(-) diff --git a/dep.go b/dep.go index a64da9e..bbd7310 100644 --- a/dep.go +++ b/dep.go @@ -159,7 +159,7 @@ func depRead(fdDep *os.File) (*DepInfo, error) { } depInfo := DepInfo{} if b := m["Build"]; b == "" { - return nil, errors.New(".dep missing Build:") + return nil, errors.New(".rec missing Build:") } else { depInfo.build = b } @@ -177,7 +177,7 @@ func depRead(fdDep *os.File) (*DepInfo, error) { case DepTypeIfcreate: dep := m["Target"] if dep == "" { - return nil, errors.New("invalid format of .dep") + return nil, errors.New("invalid format of .rec") } depInfo.ifcreates = append(depInfo.ifcreates, dep) case DepTypeIfchange: @@ -186,11 +186,11 @@ func depRead(fdDep *os.File) (*DepInfo, error) { case DepTypeStamp: hsh := m["Hash"] if hsh == "" { - return nil, errors.New("invalid format of .dep") + return nil, errors.New("invalid format of .rec") } depInfo.stamp = hsh default: - return nil, errors.New("invalid format of .dep") + return nil, errors.New("invalid format of .rec") } } return &depInfo, nil diff --git a/doc/cmds.texi b/doc/cmds.texi index 1483b7f..abd0990 100644 --- a/doc/cmds.texi +++ b/doc/cmds.texi @@ -46,7 +46,7 @@ default.do @url{https://en.wikipedia.org/wiki/DOT_(graph_description_language), DOT} graph generator. For example to visualize your dependencies with GraphViz: @example -$ redo target [...] # to assure that **/.redo/*.dep are filled up +$ redo target [...] # to assure that **/.redo/*.rec are filled up $ redo-dot target [...] > whatever.dot $ dot -Tpng whatever.dot > whatever.png # possibly add -Gsplines=ortho @end example diff --git a/doc/faq.texi b/doc/faq.texi index 9b909a6..16fadaf 100644 --- a/doc/faq.texi +++ b/doc/faq.texi @@ -42,7 +42,7 @@ and transparently compressed, as ZFS with LZ4/Zstandard and Skein/BLAKE[23] algorithms demonstrate us. @command{goredo} includes @command{redo-stamp}, that really records the -stamp in the @file{.dep} file, but it does not play any role later. It +stamp in the @file{.rec} file, but it does not play any role later. It is stayed just for compatibility. @section Can removed .do lead to permanent errors of its non existence? @@ -52,7 +52,7 @@ assume that @file{.do}-less target now is an ordinary source-file? I have no confidence in such behaviour. So it is user's decision how to deal with it, probably it was just his inaccuracy mistake. If you really want to get rid of that dependency knowledge for @file{foo/bar} target, -then just remove @file{foo/.redo/bar.dep}. +then just remove @file{foo/.redo/bar.rec}. @section Does redo-always always rebuilds target? diff --git a/doc/news.texi b/doc/news.texi index 99faeda..7f67ba9 100644 --- a/doc/news.texi +++ b/doc/news.texi @@ -1,6 +1,15 @@ @node News @unnumbered News +@anchor{Release 1.2.0} +@section Release 1.2.0 +@itemize +@item + Dependency files @file{.dep} extension changed to @file{.rec}, to + reflect its recfile format nature and editors file type better + determination. +@end itemize + @anchor{Release 1.1.0} @section Release 1.1.0 @itemize diff --git a/doc/state.texi b/doc/state.texi index fa7c28c..4c84b41 100644 --- a/doc/state.texi +++ b/doc/state.texi @@ -3,7 +3,7 @@ Dependency and build state is kept inside @file{.redo} subdirectory in each directory related the build. Each corresponding target has its own, -recreated with every rebuild, @file{.dep} file. It is +recreated with every rebuild, @file{.rec} file. It is @url{https://www.gnu.org/software/recutils/, recfile}, that could have various dependency information. For example: diff --git a/ood.go b/ood.go index 912b6c6..0552e20 100644 --- a/ood.go +++ b/ood.go @@ -110,11 +110,11 @@ func isOOD(cwd, tgtOrig string, level int, seen map[string]struct{}) (bool, erro for _, m := range depInfo.ifchanges { dep := m["Target"] if dep == "" { - return ood, TgtErr{tgtOrig, errors.New("invalid format of .dep: missing Target")} + return ood, TgtErr{tgtOrig, errors.New("invalid format of .rec: missing Target")} } theirInode, err := inodeFromRec(m) if err != nil { - return ood, TgtErr{tgtOrig, fmt.Errorf("invalid format of .dep: %v", err)} + return ood, TgtErr{tgtOrig, fmt.Errorf("invalid format of .rec: %v", err)} } theirHsh := m["Hash"] trace(CDebug, "ood: %s%s -> %s: checking", indent, tgtOrig, dep) diff --git a/run.go b/run.go index f6a9042..25e8bac 100644 --- a/run.go +++ b/run.go @@ -51,7 +51,7 @@ const ( RedoDir = ".redo" LockSuffix = ".lock" - DepSuffix = ".dep" + DepSuffix = ".rec" TmpPrefix = ".redo." LogSuffix = ".log" ) @@ -204,7 +204,7 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { fdDep, err := os.Open(path.Join(redoDir, tgt+DepSuffix)) if err != nil { if os.IsNotExist(err) { - err = errors.New("was not built: no .dep") + err = errors.New("was not built: no .rec") } goto Finish } @@ -240,7 +240,7 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { return nil } - // Start preparing .dep + // Start preparing .rec fdDep, err := tempfile(redoDir, tgt+DepSuffix) if err != nil { lockRelease() @@ -542,7 +542,7 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { } } - // Commit .dep + // Commit .rec if !NoSync { err = fdDep.Sync() if err != nil { diff --git a/t/goredo-deps.t b/t/goredo-deps.t index 2e3ca5e..5ab869c 100755 --- a/t/goredo-deps.t +++ b/t/goredo-deps.t @@ -28,7 +28,7 @@ test_expect_success Rebuild "redo-ifchange sub/index.html" stat2=`stat sub/index.html` test_expect_success "Was not rebuild" '[ "$stat1" = "$stat2" ]' -tgts=`sed -n "s/^Target: //p" sub/.redo/index.html.dep | sort` +tgts=`sed -n "s/^Target: //p" sub/.redo/index.html.rec | sort` tgts=`echo $tgts` tgts_expected="../default.html.do" # .do itself tgts_expected="$tgts_expected default.do" # ifcreate diff --git a/usage.go b/usage.go index d31db40..affd454 100644 --- a/usage.go +++ b/usage.go @@ -26,7 +26,7 @@ import ( ) const ( - Version = "1.1.0" + Version = "1.2.0" Warranty = `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. -- 2.44.0 From ecb97c9a61e81465fa748b4324da0ddd12872fdc Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Thu, 28 Jan 2021 21:14:00 +0300 Subject: [PATCH 14/16] Reduce number of opened files while waiting for job slot --- doc/news.texi | 3 +++ run.go | 46 +++++++++++++++++++++++++++++++++------------- 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/doc/news.texi b/doc/news.texi index 7f67ba9..56b537d 100644 --- a/doc/news.texi +++ b/doc/news.texi @@ -8,6 +8,9 @@ Dependency files @file{.dep} extension changed to @file{.rec}, to reflect its recfile format nature and editors file type better determination. +@item + Reduce number of file descriptors kept open (1 instead of 4) while + waiting for job slot token. @end itemize @anchor{Release 1.1.0} diff --git a/run.go b/run.go index 25e8bac..af17eaa 100644 --- a/run.go +++ b/run.go @@ -246,6 +246,7 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { lockRelease() return TgtErr{tgtOrig, err} } + fdDepPath := fdDep.Name() cleanup := func() { lockRelease() fdDep.Close() @@ -292,6 +293,7 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { cleanup() return TgtErr{tgtOrig, err} } + fdDep.Close() trace(CWait, "%s", runErr.Name()) // Prepare command line @@ -316,7 +318,9 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { cleanup() return TgtErr{tgtOrig, err} } - tmpPath := fdStdout.Name() + ".3" // and for $3 + stdoutPath := fdStdout.Name() + fdStdout.Close() + tmpPath := stdoutPath + ".3" // and for $3 tmpPathRel, err := filepath.Rel(cwd, tmpPath) if err != nil { panic(err) @@ -330,7 +334,6 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { cmd := exec.Command(cmdName, args...) cmd.Dir = cwd - cmd.Stdout = fdStdout // cmd.Stdin reads from /dev/null by default cmd.Env = append(os.Environ(), fmt.Sprintf("%s=%d", EnvLevel, Level+1)) cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", EnvDirPrefix, dirPrefix)) @@ -342,10 +345,6 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { )) fdNum := 0 - cmd.ExtraFiles = append(cmd.ExtraFiles, fdDep) - cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%d", EnvDepFd, 3+fdNum)) - fdNum++ - if FdStatus == nil { cmd.Env = append(cmd.Env, fmt.Sprintf("%s=NO", EnvStatusFd)) } else { @@ -367,10 +366,6 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { } // Preparing stderr - stderr, err := cmd.StderrPipe() - if err != nil { - panic(err) - } var fdStderr *os.File if StderrKeep { fdStderr, err = os.OpenFile( @@ -396,6 +391,26 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { if FdStatus != nil { FdStatus.Write([]byte{StatusRun}) } + + started := time.Now() + runErr.Started = &started + fdStdout, err = os.OpenFile(stdoutPath, os.O_RDWR, os.FileMode(0666)) + if err != nil { + runErr.Err = err + errs <- runErr + return + } + cmd.Stdout = fdStdout + fdDep, err = os.OpenFile(fdDepPath, os.O_WRONLY|os.O_APPEND, os.FileMode(0666)) + if err != nil { + runErr.Err = err + errs <- runErr + return + } + cmd.ExtraFiles = append(cmd.ExtraFiles, fdDep) + cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%d", EnvDepFd, 3+fdNum)) + fdNum++ + defer func() { jsRelease(shCtx) lockRelease() @@ -413,9 +428,14 @@ func runScript(tgtOrig string, errs chan error, traced bool) error { } Jobs.Done() }() - started := time.Now() - runErr.Started = &started - err := cmd.Start() + stderr, err := cmd.StderrPipe() + if err != nil { + runErr.Err = err + errs <- runErr + return + } + started = time.Now() + err = cmd.Start() if err != nil { runErr.Err = err errs <- runErr -- 2.44.0 From fa0728d6bc790672982ba006961077371d2b552d Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Fri, 29 Jan 2021 11:14:44 +0300 Subject: [PATCH 15/16] Download link for 1.2.0 release --- doc/download.texi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/download.texi b/doc/download.texi index 9dead3b..f8e7369 100644 --- a/doc/download.texi +++ b/doc/download.texi @@ -1,6 +1,10 @@ @multitable {XXXXX} {XXXX-XX-XX} {XXXX KiB} {link sign} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} @headitem Version @tab Date @tab Size @tab Tarball @tab SHA256 checksum +@item @ref{Release 1.2.0, 1.2.0} @tab 2021-01-29 @tab 338 KiB +@tab @url{download/goredo-1.2.0.tar.zst, link} @url{download/goredo-1.2.0.tar.zst.sig, sign} +@tab @code{D0045DBA F60FB731 B3DB64AB 262E600A 3D68E487 D167A0F1 9DD614DA C6E57CD5} + @item @ref{Release 1.1.0, 1.1.0} @tab 2021-01-24 @tab 338 KiB @tab @url{download/goredo-1.1.0.tar.zst, link} @url{download/goredo-1.1.0.tar.zst.sig, sign} @tab @code{63A9FEA6 66665D16 626171C8 65C11C48 C258EB7F A9112982 755E62B9 B5100570} -- 2.44.0 From 312d2fc4059d8ad03c7fa5b853cdbcb7091e8e71 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Mon, 15 Feb 2021 12:11:12 +0300 Subject: [PATCH 16/16] ALT Linux port --- doc/install.texi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/install.texi b/doc/install.texi index 40b39d6..843384f 100644 --- a/doc/install.texi +++ b/doc/install.texi @@ -3,7 +3,8 @@ Possibly @command{goredo} package already exists for your distribution: @itemize -@item @url{https://aur.archlinux.org/packages/goredo/, Arch Linux AUR} +@item ALT Linux @url{http://www.sisyphus.ru/ru/srpm/Sisyphus/goredo, Sisyphus} +@item Arch Linux @url{https://aur.archlinux.org/packages/goredo/, AUR} @item @url{https://www.freshports.org/devel/goredo/, FreeBSD ports} @item macOS @url{https://formulae.brew.sh/formula/goredo, Homebrew} @end itemize -- 2.44.0