github.com/akerouanton/docker@v1.11.0-rc3/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  }