blob: 6f8698d2d057347a41a3476b395a447c1be485a8 [file] [log] [blame]
package path
import (
"bytes"
"go/ast"
"go/parser"
"go/printer"
"go/token"
"os"
"path/filepath"
"strconv"
"strings"
"github.com/Masterminds/glide/msg"
)
// StripVcs removes VCS metadata (.git, .hg, .bzr, .svn) from the vendor/
// directory.
func StripVcs() error {
if _, err := os.Stat(VendorDir); err != nil {
if os.IsNotExist(err) {
msg.Debug("Vendor directory does not exist.")
}
return err
}
return filepath.Walk(VendorDir, stripHandler)
}
func stripHandler(path string, info os.FileInfo, err error) error {
name := info.Name()
if name == ".git" || name == ".bzr" || name == ".svn" || name == ".hg" {
if _, err := os.Stat(path); err == nil {
if info.IsDir() {
msg.Info("Removing: %s", path)
return os.RemoveAll(path)
}
msg.Debug("%s is not a directory. Skipping removal", path)
return nil
}
}
return nil
}
// StripVendor removes nested vendor and Godeps/_workspace/ directories.
func StripVendor() error {
if _, err := os.Stat(VendorDir); err != nil {
if os.IsNotExist(err) {
msg.Debug("Vendor directory does not exist.")
}
return err
}
err := filepath.Walk(VendorDir, stripVendorHandler)
if err != nil {
return err
}
return StripGodepWorkspace()
}
func stripVendorHandler(path string, info os.FileInfo, err error) error {
// Skip the base vendor directory
if path == VendorDir {
return nil
}
name := info.Name()
if name == "vendor" {
if _, err := os.Stat(path); err == nil {
if info.IsDir() {
msg.Info("Removing: %s", path)
return os.RemoveAll(path)
}
msg.Debug("%s is not a directory. Skipping removal", path)
return nil
}
}
return nil
}
var godepMark = map[string]bool{}
// StripGodepWorkspace removes any Godeps/_workspace directories and makes sure
// any rewrites are undone.
// Note, this is not concuccency safe.
func StripGodepWorkspace() error {
if _, err := os.Stat(VendorDir); err != nil {
if os.IsNotExist(err) {
msg.Debug("Vendor directory does not exist.")
}
return err
}
err := filepath.Walk(VendorDir, 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 == VendorDir {
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 name == "testdata" || name == "vendor" {
return filepath.SkipDir
}
if info.IsDir() {
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/")
}