10 // copyDir copies the src directory contents into dst. Both directories
11 // should already exist.
12 func copyDir(dst, src string) error {
13 src, err := filepath.EvalSymlinks(src)
18 walkFn := func(path string, info os.FileInfo, err error) error {
27 if strings.HasPrefix(filepath.Base(path), ".") {
30 return filepath.SkipDir
36 // The "path" has the src prefixed to it. We need to join our
37 // destination with the path without the src on it.
38 dstPath := filepath.Join(dst, path[len(src):])
40 // we don't want to try and copy the same file over itself.
41 if eq, err := sameFile(path, dstPath); eq {
43 } else if err != nil {
47 // If we have a directory, make that subdirectory, then continue
50 if path == filepath.Join(src, dst) {
51 // dst is in src; don't walk it.
55 if err := os.MkdirAll(dstPath, 0755); err != nil {
62 // If the current path is a symlink, recreate the symlink relative to
64 if info.Mode()&os.ModeSymlink == os.ModeSymlink {
65 target, err := os.Readlink(path)
70 return os.Symlink(target, dstPath)
73 // If we have a file, copy the contents.
74 srcF, err := os.Open(path)
80 dstF, err := os.Create(dstPath)
86 if _, err := io.Copy(dstF, srcF); err != nil {
91 return os.Chmod(dstPath, info.Mode())
94 return filepath.Walk(src, walkFn)
97 // sameFile tried to determine if to paths are the same file.
98 // If the paths don't match, we lookup the inode on supported systems.
99 func sameFile(a, b string) (bool, error) {
104 aIno, err := inode(a)
106 if os.IsNotExist(err) {
112 bIno, err := inode(b)
114 if os.IsNotExist(err) {
120 if aIno > 0 && aIno == bIno {