blob: 39d54e1a8b1a578b3497b0e138264fe334f63857 [file] [log] [blame]
// 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)
return os.RemoveAll(path)
}
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/")
}