]> Cypherpunks.ru repositories - goredo.git/blob - do.go
Download link for 2.6.2 release
[goredo.git] / do.go
1 // goredo -- djb's redo implementation on pure Go
2 // Copyright (C) 2020-2024 Sergey Matveev <stargrave@stargrave.org>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, version 3 of the License.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16 // .do finder
17
18 package main
19
20 import (
21         "io"
22         "path"
23         "strings"
24 )
25
26 const (
27         EnvTopDir = "REDO_TOP_DIR"
28         TopFile   = "top"
29 )
30
31 var TopDir string
32
33 func existsDo(w io.Writer, fdDepName, cwd, pth string) (bool, error) {
34         if FileExists(path.Join(cwd, pth)) {
35                 return true, nil
36         }
37         return false, ifcreate(w, fdDepName, pth)
38 }
39
40 func findDo(w io.Writer, fdDepName, cwd, tgt string) (string, int, error) {
41         doFile := tgt + ".do"
42         exists, err := existsDo(w, fdDepName, cwd, doFile)
43         if err != nil {
44                 return "", 0, err
45         }
46         if exists {
47                 return doFile, 0, nil
48         }
49         doFileOrig := doFile
50         levels := []string{}
51         extsOrig := strings.Split(tgt, ".")[1:]
52         dirAbsPrev := ""
53         for {
54                 exts := extsOrig
55                 updir := path.Join(levels...)
56                 for len(exts) > 0 {
57                         doFile = strings.Join(append(
58                                 []string{"default"}, append(exts, "do")...,
59                         ), ".")
60                         if len(levels) > 0 || (doFile != doFileOrig && doFile != tgt) {
61                                 exists, err = existsDo(w, fdDepName, cwd, path.Join(updir, doFile))
62                                 if err != nil {
63                                         return "", 0, err
64                                 }
65                                 if exists {
66                                         return doFile, len(levels), nil
67                                 }
68                         }
69                         exts = exts[1:]
70                 }
71                 doFile = "default.do"
72                 if len(levels) > 0 || (doFile != doFileOrig && doFile != tgt) {
73                         exists, err = existsDo(w, fdDepName, cwd, path.Join(updir, doFile))
74                         if err != nil {
75                                 return "", 0, err
76                         }
77                         if exists {
78                                 return doFile, len(levels), nil
79                         }
80                 }
81                 levels = append(levels, "..")
82                 dirAbs := mustAbs(path.Join(cwd, updir))
83                 if err != nil {
84                         panic(err)
85                 }
86                 if dirAbs == TopDir {
87                         break
88                 }
89                 if FileExists(path.Join(dirAbs, RedoDir, TopFile)) {
90                         break
91                 }
92                 if dirAbs == dirAbsPrev {
93                         break
94                 }
95                 dirAbsPrev = dirAbs
96         }
97         return "", 0, nil
98 }