github.com/anthonymayer/glide@v0.0.0-20160224162501-bff8b50d232e/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  // IsLink returns true if the given FileInfo references a link.
   143  func IsLink(fi os.FileInfo) bool {
   144  	return fi.Mode()&os.ModeSymlink == os.ModeSymlink
   145  }
   146  
   147  // HasLock returns true if this can stat a lockfile at the givin location.
   148  func HasLock(basepath string) bool {
   149  	_, err := os.Stat(filepath.Join(basepath, LockFile))
   150  	return err == nil
   151  }
   152  
   153  // IsDirectoryEmpty checks if a directory is empty.
   154  func IsDirectoryEmpty(dir string) (bool, error) {
   155  	f, err := os.Open(dir)
   156  	if err != nil {
   157  		return false, err
   158  	}
   159  	defer f.Close()
   160  
   161  	_, err = f.Readdir(1)
   162  
   163  	if err == io.EOF {
   164  		return true, nil
   165  	}
   166  
   167  	return false, err
   168  }
   169  
   170  // CopyDir copies an entire source directory to the dest directory.
   171  //
   172  // This is akin to `cp -a src/* dest/`
   173  //
   174  // We copy the directory here rather than jumping out to a shell so we can
   175  // support multiple operating systems.
   176  func CopyDir(source string, dest string) error {
   177  
   178  	// get properties of source dir
   179  	si, err := os.Stat(source)
   180  	if err != nil {
   181  		return err
   182  	}
   183  
   184  	err = os.MkdirAll(dest, si.Mode())
   185  	if err != nil {
   186  		return err
   187  	}
   188  
   189  	d, _ := os.Open(source)
   190  
   191  	objects, err := d.Readdir(-1)
   192  
   193  	for _, obj := range objects {
   194  
   195  		sp := filepath.Join(source, "/", obj.Name())
   196  
   197  		dp := filepath.Join(dest, "/", obj.Name())
   198  
   199  		if obj.IsDir() {
   200  			err = CopyDir(sp, dp)
   201  			if err != nil {
   202  				return err
   203  			}
   204  		} else {
   205  			// perform copy
   206  			err = CopyFile(sp, dp)
   207  			if err != nil {
   208  				return err
   209  			}
   210  		}
   211  
   212  	}
   213  	return nil
   214  }
   215  
   216  // CopyFile copies a source file to a destination.
   217  //
   218  // It follows symbolic links and retains modes.
   219  func CopyFile(source string, dest string) error {
   220  	ln, err := os.Readlink(source)
   221  	if err == nil {
   222  		return os.Symlink(ln, dest)
   223  	}
   224  	s, err := os.Open(source)
   225  	if err != nil {
   226  		return err
   227  	}
   228  
   229  	defer s.Close()
   230  
   231  	d, err := os.Create(dest)
   232  	if err != nil {
   233  		return err
   234  	}
   235  
   236  	defer d.Close()
   237  
   238  	_, err = io.Copy(d, s)
   239  	if err != nil {
   240  		return err
   241  	}
   242  
   243  	si, err := os.Stat(source)
   244  	if err != nil {
   245  		return err
   246  	}
   247  	err = os.Chmod(dest, si.Mode())
   248  
   249  	return err
   250  }