+// 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
import (
"path"
"path/filepath"
+ "sync"
)
-var TgtCache = make(map[string]*Tgt)
+var (
+ TgtCache = make(map[string]*Tgt)
+ TgtCacheM sync.RWMutex
+)
func mustAbs(pth string) string {
pth, err := filepath.Abs(pth)
return mustRel(Cwd, path.Join(paths...))
}
+func pathSplit(a string) (h, t string) {
+ h, t = path.Split(a)
+ if len(h) > 1 {
+ h = h[:len(h)-1]
+ }
+ return
+}
+
type Tgt struct {
- // a/h/t resemble zsh'es :a, :h, :t modifiers
a string // absolute path
- h string // head of the path, directory
- t string // tail of the path, only name
rel string // relative to Cwd
dep string // path to dependency file
}
func NewTgt(tgt string) *Tgt {
a := mustAbs(tgt)
- if TgtCache != nil {
- if t := TgtCache[a]; t != nil {
- return t
- }
+ TgtCacheM.RLock()
+ cached := TgtCache[a]
+ TgtCacheM.RUnlock()
+ if cached != nil {
+ return cached
}
- t := Tgt{a: a}
- t.h, t.t = path.Split(t.a)
- if len(t.h) > 1 {
- t.h = t.h[:len(t.h)-1]
+ h, t := pathSplit(a)
+ res := Tgt{
+ a: a,
+ rel: mustRel(Cwd, a),
+ dep: path.Join(h, RedoDir, t+DepSuffix),
}
- t.rel = mustRel(Cwd, t.a)
- if TgtCache != nil {
- TgtCache[a] = &t
- }
- return &t
+ TgtCacheM.Lock()
+ TgtCache[a] = &res
+ TgtCacheM.Unlock()
+ return &res
}
func (tgt *Tgt) String() string {
return tgt.rel
}
-func (tgt *Tgt) Dep() string {
- if tgt.dep == "" {
- tgt.dep = path.Join(tgt.h, RedoDir, tgt.t+DepSuffix)
- }
- return tgt.dep
-}
-
func (tgt *Tgt) RelTo(cwd string) string {
return mustRel(cwd, tgt.a)
}