changes_other.go 2.0 KB

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