github.com/kngu9/glide@v0.0.0-20160505135211-e73500c73591/path/path.go (about)

     1  // Package path contains path and environment utilities for Glide.
     2  //
     3  // This includes tools to find and manipulate Go path variables, as well as
     4  // tools for copying from one path to another.
     5  package path
     6  
     7  import (
     8  	"fmt"
     9  	"io"
    10  	"os"
    11  	"path/filepath"
    12  	"strings"
    13  )
    14  
    15  // DefaultGlideFile is the default name for the glide.yaml file.
    16  const DefaultGlideFile = "glide.yaml"
    17  
    18  // VendorDir is the name of the directory that holds vendored dependencies.
    19  //
    20  // As of Go 1.5, this is always vendor.
    21  var VendorDir = "vendor"
    22  
    23  // HomeDir is the home directory for Glide.
    24  //
    25  // HomeDir is where cache files and other configuration data are stored.
    26  var HomeDir = "$HOME/.glide"
    27  
    28  // GlideFile is the name of the Glide file.
    29  //
    30  // Setting this is not concurrency safe. For consistency, it should really
    31  // only be set once, at startup, or not at all.
    32  var GlideFile = DefaultGlideFile
    33  
    34  // LockFile is the default name for the lock file.
    35  const LockFile = "glide.lock"
    36  
    37  // Home returns the Glide home directory ($GLIDE_HOME or ~/.glide, typically).
    38  //
    39  // This normalizes to an absolute path, and passes through os.ExpandEnv.
    40  func Home() string {
    41  	h := os.ExpandEnv(HomeDir)
    42  	var err error
    43  	if h, err = filepath.Abs(HomeDir); err != nil {
    44  		return HomeDir
    45  	}
    46  	return h
    47  }
    48  
    49  // Vendor calculates the path to the vendor directory.
    50  //
    51  // Based on working directory, VendorDir and GlideFile, this attempts to
    52  // guess the location of the vendor directory.
    53  func Vendor() (string, error) {
    54  	cwd, err := os.Getwd()
    55  	if err != nil {
    56  		return "", err
    57  	}
    58  
    59  	// Find the directory that contains glide.yaml
    60  	yamldir, err := GlideWD(cwd)
    61  	if err != nil {
    62  		return cwd, err
    63  	}
    64  
    65  	gopath := filepath.Join(yamldir, VendorDir)
    66  
    67  	return gopath, nil
    68  }
    69  
    70  // Glide gets the path to the closest glide file.
    71  func Glide() (string, error) {
    72  	cwd, err := os.Getwd()
    73  	if err != nil {
    74  		return "", err
    75  	}
    76  
    77  	// Find the directory that contains glide.yaml
    78  	yamldir, err := GlideWD(cwd)
    79  	if err != nil {
    80  		return cwd, err
    81  	}
    82  
    83  	gf := filepath.Join(yamldir, GlideFile)
    84  	return gf, nil
    85  }
    86  
    87  // GlideWD finds the working directory of the glide.yaml file, starting at dir.
    88  //
    89  // If the glide file is not found in the current directory, it recurses up
    90  // a directory.
    91  func GlideWD(dir string) (string, error) {
    92  	fullpath := filepath.Join(dir, GlideFile)
    93  
    94  	if _, err := os.Stat(fullpath); err == nil {
    95  		return dir, nil
    96  	}
    97  
    98  	base := filepath.Dir(dir)
    99  	if base == dir {
   100  		return "", fmt.Errorf("Cannot resolve parent of %s", base)
   101  	}
   102  
   103  	return GlideWD(base)
   104  }
   105  
   106  // Gopath gets GOPATH from environment and return the most relevant path.
   107  //
   108  // A GOPATH can contain a colon-separated list of paths. This retrieves the
   109  // GOPATH and returns only the FIRST ("most relevant") path.
   110  //
   111  // This should be used carefully. If, for example, you are looking for a package,
   112  // you may be better off using Gopaths.
   113  func Gopath() string {
   114  	gopaths := Gopaths()
   115  	if len(gopaths) == 0 {
   116  		return ""
   117  	}
   118  	return gopaths[0]
   119  }
   120  
   121  // Gopaths retrieves the Gopath as a list when there is more than one path
   122  // listed in the Gopath.
   123  func Gopaths() []string {
   124  	p := os.Getenv("GOPATH")
   125  	p = strings.Trim(p, string(filepath.ListSeparator))
   126  	return filepath.SplitList(p)
   127  }
   128  
   129  // Basepath returns the current working directory.
   130  //
   131  // If there is an error getting the working directory, this returns ".", which
   132  // should function in cases where the directory is unlinked... Then again,
   133  // maybe not.
   134  func Basepath() string {
   135  	base, err := os.Getwd()
   136  	if err != nil {
   137  		return "."
   138  	}
   139  	return base
   140  }
   141  
   142  // StripBasepath removes the base directory from a passed in path.
   143  func StripBasepath(p string) string {
   144  	bp := Basepath()
   145  	return strings.TrimPrefix(p, bp+string(os.PathSeparator))
   146  }
   147  
   148  // IsLink returns true if the given FileInfo references a link.
   149  func IsLink(fi os.FileInfo) bool {
   150  	return fi.Mode()&os.ModeSymlink == os.ModeSymlink
   151  }
   152  
   153  // HasLock returns true if this can stat a lockfile at the givin location.
   154  func HasLock(basepath string) bool {
   155  	_, err := os.Stat(filepath.Join(basepath, LockFile))
   156  	return err == nil
   157  }
   158  
   159  // IsDirectoryEmpty checks if a directory is empty.
   160  func IsDirectoryEmpty(dir string) (bool, error) {
   161  	f, err := os.Open(dir)
   162  	if err != nil {
   163  		return false, err
   164  	}
   165  	defer f.Close()
   166  
   167  	_, err = f.Readdir(1)
   168  
   169  	if err == io.EOF {
   170  		return true, nil
   171  	}
   172  
   173  	return false, err
   174  }
   175  
   176  // CopyDir copies an entire source directory to the dest directory.
   177  //
   178  // This is akin to `cp -a src/* dest/`
   179  //
   180  // We copy the directory here rather than jumping out to a shell so we can
   181  // support multiple operating systems.
   182  func CopyDir(source string, dest string) error {
   183  
   184  	// get properties of source dir
   185  	si, err := os.Stat(source)
   186  	if err != nil {
   187  		return err
   188  	}
   189  
   190  	err = os.MkdirAll(dest, si.Mode())
   191  	if err != nil {
   192  		return err
   193  	}
   194  
   195  	d, _ := os.Open(source)
   196  
   197  	objects, err := d.Readdir(-1)
   198  
   199  	for _, obj := range objects {
   200  
   201  		sp := filepath.Join(source, "/", obj.Name())
   202  
   203  		dp := filepath.Join(dest, "/", obj.Name())
   204  
   205  		if obj.IsDir() {
   206  			err = CopyDir(sp, dp)
   207  			if err != nil {
   208  				return err
   209  			}
   210  		} else {
   211  			// perform copy
   212  			err = CopyFile(sp, dp)
   213  			if err != nil {
   214  				return err
   215  			}
   216  		}
   217  
   218  	}
   219  	return nil
   220  }
   221  
   222  // CopyFile copies a source file to a destination.
   223  //
   224  // It follows symbolic links and retains modes.
   225  func CopyFile(source string, dest string) error {
   226  	ln, err := os.Readlink(source)
   227  	if err == nil {
   228  		return os.Symlink(ln, dest)
   229  	}
   230  	s, err := os.Open(source)
   231  	if err != nil {
   232  		return err
   233  	}
   234  
   235  	defer s.Close()
   236  
   237  	d, err := os.Create(dest)
   238  	if err != nil {
   239  		return err
   240  	}
   241  
   242  	defer d.Close()
   243  
   244  	_, err = io.Copy(d, s)
   245  	if err != nil {
   246  		return err
   247  	}
   248  
   249  	si, err := os.Stat(source)
   250  	if err != nil {
   251  		return err
   252  	}
   253  	err = os.Chmod(dest, si.Mode())
   254  
   255  	return err
   256  }