-
Notifications
You must be signed in to change notification settings - Fork 0
/
find.go
147 lines (134 loc) · 4.09 KB
/
find.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// dcc - dependency-driven C/C++ compiler front end
//
// Copyright © A.Newman 2015.
//
// This source code is released under version 2 of the GNU Public License.
// See the file LICENSE for details.
//
package main
import (
"log"
"os"
"path/filepath"
)
// FindFile returns a path for a filename and a flag indicating if the
// file was actually found.
//
func FindFile(filename string) (string, bool) {
ofilename := filename
if DebugFind {
log.Printf("DEBUG FIND: FindFile %q", ofilename)
}
path, _, exists, err := FindFileFromCwd(filename)
if err == nil && exists {
if DebugFind {
log.Printf("DEBUG FIND: FindFile %q -> %q", filename, path)
}
return path, true
}
if err != nil {
log.Print(err)
}
if DebugFind {
log.Printf("DEBUG FIND: FindFile %q -> %q", filename, filename)
}
return filename, false
}
// FindFileFromCwd finds a file starting from the current directory and searching towards the root.
//
func FindFileFromCwd(filename string) (string, os.FileInfo, bool, error) {
if DebugFind {
log.Printf("DEBUG FIND: FindFileFromCwd %q", filename)
}
return FindFileFromDirectory(filename, MustGetwd())
}
// FindFileFromDirectory finds a file starting from the specified directory, search towards the root.
//
func FindFileFromDirectory(filename, dir string) (string, os.FileInfo, bool, error) {
if DebugFind {
log.Printf("DEBUG FIND: FindFileFromDirectory %q %q", filename, dir)
}
if !filepath.IsAbs(dir) {
path, err := filepath.Abs(dir)
if err != nil {
return "", nil, false, err
}
dir = path
}
paths := []string{dir}
for !platform.IsRoot(dir) {
dir = filepath.Dir(dir)
paths = append(paths, dir)
}
paths = append(paths, dir)
return FindFileOnPath(paths, filename)
}
// FindFileOnPath finds a file along a search path.
//
func FindFileOnPath(paths []string, filename string) (string, os.FileInfo, bool, error) {
if DebugFind {
log.Printf("DEBUG FIND: FindFileOnPath %q %q", paths, filename)
}
for _, dir := range paths {
if path, info, found, err := FindFileInDirectory(filename, dir); err != nil {
return "", nil, false, err
} else if found {
return path, info, true, nil
}
}
if DebugFind {
log.Printf("DEBUG FIND: %q not found", filename)
}
return "", nil, false, nil
}
func FindFileInDirectory(filename string, dirname string) (string, os.FileInfo, bool, error) {
try := func(dirname, filename string) (string, os.FileInfo, bool, error) {
path := filepath.Join(dirname, filename)
if DebugFind {
log.Printf("DEBUG FIND: FindFileInDirectory trying %q", path)
}
if info, err := Stat(path); err == nil {
if DebugFind {
log.Printf("DEBUG FIND: FindFileInDirectory returning %q", path)
}
return path, info, true, nil
} else if !os.IsNotExist(err) {
if DebugFind {
log.Printf("DEBUG FIND: FindFileInDirectory %q: %s", path, err.Error())
}
return path, nil, true, err
}
return "", nil, false, nil
}
tryAll := func() (string, os.FileInfo, bool, error) {
if path, info, found, err := try(dirname, OsAndArchSpecificFilename(filename)); err != nil || found {
return path, info, found, err
}
if path, info, found, err := try(dirname, OsSpecificFilename(filename)); err != nil || found {
return path, info, found, err
}
if path, info, found, err := try(dirname, ArchSpecificFilename(filename)); err != nil || found {
return path, info, found, err
}
return try(dirname, filename)
}
if path, info, found, err := tryAll(); err != nil || found {
return path, info, found, err
}
dirname = filepath.Join(dirname, DccDir)
if path, info, found, err := tryAll(); err != nil || found {
return path, info, found, err
}
return "", nil, false, nil
}
// FindLibrary finds a library file on a search path, either static or dynamic.
//
func FindLibrary(paths []string, name string) (string, os.FileInfo, bool, error) {
if path, info, found, err := FindFileOnPath(paths, platform.DynamicLibrary(name)); found || err != nil {
return path, info, found, err
}
if path, info, found, err := FindFileOnPath(paths, platform.StaticLibrary(name)); found || err != nil {
return path, info, found, err
}
return "", nil, false, nil
}