forked from constabulary/gb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
install.go
149 lines (126 loc) · 3.19 KB
/
install.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
148
149
package gb
import (
"fmt"
"os"
"path/filepath"
"time"
)
// Install stores a copy of the compiled file in Project.Pkgdir
func Install(pkg *Package, t PkgTarget) PkgTarget {
if pkg.SkipInstall {
return t
}
if pkg.isMain() {
Debugf("%v is a main package, not installing", pkg)
return t
}
if pkg.Scope == "test" {
Debugf("%v is test scoped, not installing", pkg)
return t
}
i := install{
PkgTarget: t,
dest: pkgfile(pkg),
}
i.target = newTarget(i.install, t)
return &i
}
// cachePackage returns a PkgTarget representing the cached output of
// pkg.
func cachedPackage(pkg *Package) *cachedPkgTarget {
return &cachedPkgTarget{
pkg: pkg,
}
}
type cachedPkgTarget struct {
pkg *Package
}
func (c *cachedPkgTarget) Pkgfile() string {
return pkgfile(c.pkg)
}
func (c *cachedPkgTarget) String() string {
return fmt.Sprintf("cached %v", c.pkg.ImportPath)
}
func (c *cachedPkgTarget) Result() error {
// TODO(dfc) _, err := os.Stat(c.Pkgfile())
return nil
}
type install struct {
target
PkgTarget
dest string
}
func (i *install) String() string {
return fmt.Sprintf("cache %v", i.PkgTarget)
}
func (i *install) install() error {
return copyfile(i.dest, i.Pkgfile())
}
func (i *install) Result() error {
return i.target.Result()
}
// pkgdir returns the destination for object cached for this Package.
func pkgdir(pkg *Package) string {
if pkg.Scope == "test" {
panic("pkgdir called with test scope")
}
return filepath.Join(pkg.Pkgdir(), filepath.Dir(filepath.FromSlash(pkg.ImportPath)))
}
func pkgfile(pkg *Package) string {
return filepath.Join(pkgdir(pkg), filepath.Base(filepath.FromSlash(pkg.ImportPath))+".a")
}
// isStale returns true if the source pkg is considered to be stale with
// respect to its installed version.
func isStale(pkg *Package) bool {
if pkg.Force {
return true
}
if pkg.Scope == "test" {
// tests are always stale, they are never installed
return true
}
// Package is stale if completely unbuilt.
var built time.Time
if fi, err := os.Stat(pkgfile(pkg)); err == nil {
built = fi.ModTime()
}
if built.IsZero() {
return true
}
olderThan := func(file string) bool {
fi, err := os.Stat(file)
return err != nil || fi.ModTime().After(built)
}
// As a courtesy to developers installing new versions of the compiler
// frequently, define that packages are stale if they are
// older than the compiler, and commands if they are older than
// the linker. This heuristic will not work if the binaries are
// back-dated, as some binary distributions may do, but it does handle
// a very common case.
if olderThan(pkg.tc.compiler()) {
return true
}
if pkg.IsCommand() && olderThan(pkg.tc.linker()) {
return true
}
// Package is stale if a dependency is newer.
for _, p := range pkg.Imports() {
if olderThan(pkgfile(p)) {
return true
}
}
srcs := stringList(pkg.GoFiles, pkg.CFiles, pkg.CXXFiles, pkg.MFiles, pkg.HFiles, pkg.SFiles, pkg.CgoFiles, pkg.SysoFiles, pkg.SwigFiles, pkg.SwigCXXFiles)
for _, src := range srcs {
if olderThan(filepath.Join(pkg.Dir, src)) {
return true
}
}
return false
}
func stringList(args ...[]string) []string {
var l []string
for _, arg := range args {
l = append(l, arg...)
}
return l
}