// goredo -- djb's redo implementation on pure Go // Copyright (C) 2020-2024 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 . // .do finder package main import ( "io" "path" "strings" ) const ( EnvTopDir = "REDO_TOP_DIR" TopFile = "top" ) var TopDir string func existsDo(w io.Writer, fdDepName, cwd, pth string) (bool, error) { if FileExists(path.Join(cwd, pth)) { return true, nil } return false, ifcreate(w, fdDepName, pth) } func findDo(w io.Writer, fdDepName, cwd, tgt string) (string, int, error) { doFile := tgt + ".do" exists, err := existsDo(w, fdDepName, cwd, doFile) if err != nil { return "", 0, err } if exists { return doFile, 0, nil } doFileOrig := doFile levels := []string{} extsOrig := strings.Split(tgt, ".")[1:] dirAbsPrev := "" for { exts := extsOrig updir := path.Join(levels...) for len(exts) > 0 { doFile = strings.Join(append( []string{"default"}, append(exts, "do")..., ), ".") if len(levels) > 0 || (doFile != doFileOrig && doFile != tgt) { exists, err = existsDo(w, fdDepName, cwd, path.Join(updir, doFile)) if err != nil { return "", 0, err } if exists { return doFile, len(levels), nil } } exts = exts[1:] } doFile = "default.do" if len(levels) > 0 || (doFile != doFileOrig && doFile != tgt) { exists, err = existsDo(w, fdDepName, cwd, path.Join(updir, doFile)) if err != nil { return "", 0, err } if exists { return doFile, len(levels), nil } } levels = append(levels, "..") dirAbs := mustAbs(path.Join(cwd, updir)) if err != nil { panic(err) } if dirAbs == TopDir { break } if FileExists(path.Join(dirAbs, RedoDir, TopFile)) { break } if dirAbs == dirAbsPrev { break } dirAbsPrev = dirAbs } return "", 0, nil }