github.com/wulonghui/docker@v1.8.0-rc2/pkg/archive/changes_other.go (about) 1 // +build !linux 2 3 package archive 4 5 import ( 6 "fmt" 7 "os" 8 "path/filepath" 9 "runtime" 10 "strings" 11 12 "github.com/docker/docker/pkg/system" 13 ) 14 15 func collectFileInfoForChanges(oldDir, newDir string) (*FileInfo, *FileInfo, error) { 16 var ( 17 oldRoot, newRoot *FileInfo 18 err1, err2 error 19 errs = make(chan error, 2) 20 ) 21 go func() { 22 oldRoot, err1 = collectFileInfo(oldDir) 23 errs <- err1 24 }() 25 go func() { 26 newRoot, err2 = collectFileInfo(newDir) 27 errs <- err2 28 }() 29 30 // block until both routines have returned 31 for i := 0; i < 2; i++ { 32 if err := <-errs; err != nil { 33 return nil, nil, err 34 } 35 } 36 37 return oldRoot, newRoot, nil 38 } 39 40 func collectFileInfo(sourceDir string) (*FileInfo, error) { 41 root := newRootFileInfo() 42 43 err := filepath.Walk(sourceDir, func(path string, f os.FileInfo, err error) error { 44 if err != nil { 45 return err 46 } 47 48 // Rebase path 49 relPath, err := filepath.Rel(sourceDir, path) 50 if err != nil { 51 return err 52 } 53 54 // As this runs on the daemon side, file paths are OS specific. 55 relPath = filepath.Join(string(os.PathSeparator), relPath) 56 57 // See https://github.com/golang/go/issues/9168 - bug in filepath.Join. 58 // Temporary workaround. If the returned path starts with two backslashes, 59 // trim it down to a single backslash. Only relevant on Windows. 60 if runtime.GOOS == "windows" { 61 if strings.HasPrefix(relPath, `\\`) { 62 relPath = relPath[1:] 63 } 64 } 65 66 if relPath == string(os.PathSeparator) { 67 return nil 68 } 69 70 parent := root.LookUp(filepath.Dir(relPath)) 71 if parent == nil { 72 return fmt.Errorf("collectFileInfo: Unexpectedly no parent for %s", relPath) 73 } 74 75 info := &FileInfo{ 76 name: filepath.Base(relPath), 77 children: make(map[string]*FileInfo), 78 parent: parent, 79 } 80 81 s, err := system.Lstat(path) 82 if err != nil { 83 return err 84 } 85 info.stat = s 86 87 info.capability, _ = system.Lgetxattr(path, "security.capability") 88 89 parent.children[info.name] = info 90 91 return nil 92 }) 93 if err != nil { 94 return nil, err 95 } 96 return root, nil 97 }