forked from Masterminds/glide
/
strip.go
159 lines (135 loc) · 3.4 KB
/
strip.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
150
151
152
153
154
155
156
157
158
159
// Package strip removes Godeps/_workspace and undoes the Godep rewrites. This
// essentially removes the old style (pre-vendor) Godep vendoring.
//
// Note, this functionality is deprecated. Once more projects use the Godep
// support for the core vendoring this will no longer be needed.
package strip
import (
"bytes"
"go/ast"
"go/parser"
"go/printer"
"go/token"
"os"
"path/filepath"
"strconv"
"strings"
"github.com/Masterminds/glide/msg"
)
var godepMark = map[string]bool{}
var vPath = "vendor"
// GodepWorkspace removes any Godeps/_workspace directories and makes sure
// any rewrites are undone.
// Note, this is not concuccency safe.
func GodepWorkspace(v string) error {
vPath = v
if _, err := os.Stat(vPath); err != nil {
if os.IsNotExist(err) {
msg.Debug("Vendor directory does not exist.")
}
return err
}
err := filepath.Walk(vPath, stripGodepWorkspaceHandler)
if err != nil {
return err
}
// Walk the marked projects to make sure rewrites are undone.
for k := range godepMark {
msg.Info("Removing Godep rewrites for %s", k)
err := filepath.Walk(k, rewriteGodepfilesHandler)
if err != nil {
return err
}
}
return nil
}
func stripGodepWorkspaceHandler(path string, info os.FileInfo, err error) error {
// Skip the base vendor directory
if path == vPath {
return nil
}
name := info.Name()
p := filepath.Dir(path)
pn := filepath.Base(p)
if name == "_workspace" && pn == "Godeps" {
if _, err := os.Stat(path); err == nil {
if info.IsDir() {
// Marking this location to make sure rewrites are undone.
pp := filepath.Dir(p)
godepMark[pp] = true
msg.Info("Removing: %s", path)
if err := os.RemoveAll(path); err != nil {
return err
}
return filepath.SkipDir
}
msg.Debug("%s is not a directory. Skipping removal", path)
return nil
}
}
return nil
}
func rewriteGodepfilesHandler(path string, info os.FileInfo, err error) error {
name := info.Name()
if info.IsDir() {
if name == "testdata" || name == "vendor" {
return filepath.SkipDir
}
return nil
}
if e := filepath.Ext(path); e != ".go" {
return nil
}
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, path, nil, parser.ParseComments)
if err != nil {
return err
}
var changed bool
for _, s := range f.Imports {
n, err := strconv.Unquote(s.Path.Value)
if err != nil {
return err
}
q := rewriteGodepImport(n)
if q != name {
s.Path.Value = strconv.Quote(q)
changed = true
}
}
if !changed {
return nil
}
printerConfig := &printer.Config{Mode: printer.TabIndent | printer.UseSpaces, Tabwidth: 8}
var buffer bytes.Buffer
if err = printerConfig.Fprint(&buffer, fset, f); err != nil {
return err
}
fset = token.NewFileSet()
f, err = parser.ParseFile(fset, name, &buffer, parser.ParseComments)
ast.SortImports(fset, f)
tpath := path + ".temp"
t, err := os.Create(tpath)
if err != nil {
return err
}
if err = printerConfig.Fprint(t, fset, f); err != nil {
return err
}
if err = t.Close(); err != nil {
return err
}
msg.Debug("Rewriting Godep imports for %s", path)
// This is required before the rename on windows.
if err = os.Remove(path); err != nil {
return err
}
return os.Rename(tpath, path)
}
func rewriteGodepImport(n string) string {
if !strings.Contains(n, "Godeps/_workspace/src") {
return n
}
i := strings.LastIndex(n, "Godeps/_workspace/src")
return strings.TrimPrefix(n[i:], "Godeps/_workspace/src/")
}