mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
7a7357dae1
This enables docker cp and ADD/COPY docker build support for LCOW. Originally, the graphdriver.Get() interface returned a local path to the container root filesystem. This does not work for LCOW, so the Get() method now returns an interface that LCOW implements to support copying to and from the container. Signed-off-by: Akash Gupta <akagup@microsoft.com>
100 lines
2.4 KiB
Go
100 lines
2.4 KiB
Go
package remotecontext
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/docker/docker/builder"
|
|
"github.com/docker/docker/pkg/containerfs"
|
|
"github.com/docker/docker/pkg/pools"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// NewLazySource creates a new LazyContext. LazyContext defines a hashed build
|
|
// context based on a root directory. Individual files are hashed first time
|
|
// they are asked. It is not safe to call methods of LazyContext concurrently.
|
|
func NewLazySource(root containerfs.ContainerFS) (builder.Source, error) {
|
|
return &lazySource{
|
|
root: root,
|
|
sums: make(map[string]string),
|
|
}, nil
|
|
}
|
|
|
|
type lazySource struct {
|
|
root containerfs.ContainerFS
|
|
sums map[string]string
|
|
}
|
|
|
|
func (c *lazySource) Root() containerfs.ContainerFS {
|
|
return c.root
|
|
}
|
|
|
|
func (c *lazySource) Close() error {
|
|
return nil
|
|
}
|
|
|
|
func (c *lazySource) Hash(path string) (string, error) {
|
|
cleanPath, fullPath, err := normalize(path, c.root)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
fi, err := c.root.Lstat(fullPath)
|
|
if err != nil {
|
|
return "", errors.WithStack(err)
|
|
}
|
|
|
|
relPath, err := Rel(c.root, fullPath)
|
|
if err != nil {
|
|
return "", errors.WithStack(convertPathError(err, cleanPath))
|
|
}
|
|
|
|
sum, ok := c.sums[relPath]
|
|
if !ok {
|
|
sum, err = c.prepareHash(relPath, fi)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
}
|
|
|
|
return sum, nil
|
|
}
|
|
|
|
func (c *lazySource) prepareHash(relPath string, fi os.FileInfo) (string, error) {
|
|
p := c.root.Join(c.root.Path(), relPath)
|
|
h, err := NewFileHash(p, relPath, fi)
|
|
if err != nil {
|
|
return "", errors.Wrapf(err, "failed to create hash for %s", relPath)
|
|
}
|
|
if fi.Mode().IsRegular() && fi.Size() > 0 {
|
|
f, err := c.root.Open(p)
|
|
if err != nil {
|
|
return "", errors.Wrapf(err, "failed to open %s", relPath)
|
|
}
|
|
defer f.Close()
|
|
if _, err := pools.Copy(h, f); err != nil {
|
|
return "", errors.Wrapf(err, "failed to copy file data for %s", relPath)
|
|
}
|
|
}
|
|
sum := hex.EncodeToString(h.Sum(nil))
|
|
c.sums[relPath] = sum
|
|
return sum, nil
|
|
}
|
|
|
|
// Rel makes a path relative to base path. Same as `filepath.Rel` but can also
|
|
// handle UUID paths in windows.
|
|
func Rel(basepath containerfs.ContainerFS, targpath string) (string, error) {
|
|
// filepath.Rel can't handle UUID paths in windows
|
|
if basepath.OS() == "windows" {
|
|
pfx := basepath.Path() + `\`
|
|
if strings.HasPrefix(targpath, pfx) {
|
|
p := strings.TrimPrefix(targpath, pfx)
|
|
if p == "" {
|
|
p = "."
|
|
}
|
|
return p, nil
|
|
}
|
|
}
|
|
return basepath.Rel(basepath.Path(), targpath)
|
|
}
|