func rebaseArchiveEntries(srcContent ArchiveReader, oldBase, newBase string) Archive {
	rebased, w := io.Pipe()
	go func() {
		srcTar := tar.NewReader(srcContent)
		rebasedTar := tar.NewWriter(w)
		for {
			hdr, err := srcTar.Next()
			if err == io.EOF {
				rebasedTar.Close()
				w.Close()
				return
			}
			if err != nil {
				w.CloseWithError(err)
				return
			}
			hdr.Name = strings.Replace(hdr.Name, oldBase, newBase, 1)
			if err = rebasedTar.WriteHeader(hdr); err != nil {
				w.CloseWithError(err)
				return
			}
			if _, err = io.Copy(rebasedTar, srcTar); err != nil {
				w.CloseWithError(err)
				return
			}
		}
	}()
	return rebased
}
rebaseArchiveEntries rewrites the given srcContent archive replacing
an occurance of oldBase with newBase at the beginning of entry names.
package archive
import (
	"archive/tar"
	"errors"
	"io"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"strings"
	"github.com/fsouza/go-dockerclient/external/github.com/Sirupsen/logrus"
)
var (
	ErrNotDirectory      = errors.New("not a directory")
	ErrDirNotExists      = errors.New("no such directory")
	ErrCannotCopyDir     = errors.New("cannot copy directory")
	ErrInvalidCopySource = errors.New("invalid copy source content")
)
func PreserveTrailingDotOrSeparator(cleanedPath, originalPath string) string {
	if !SpecifiesCurrentDir(cleanedPath) && SpecifiesCurrentDir(originalPath) {
		if !HasTrailingPathSeparator(cleanedPath) {
			cleanedPath += string(filepath.Separator)
		}
		cleanedPath += "."
	}
	if !HasTrailingPathSeparator(cleanedPath) && HasTrailingPathSeparator(originalPath) {
		cleanedPath += string(filepath.Separator)
	}
	return cleanedPath
}
func AssertsDirectory(path string) bool {
	return HasTrailingPathSeparator(path) || SpecifiesCurrentDir(path)
}
func HasTrailingPathSeparator(path string) bool {
	return len(path) > 0 && os.IsPathSeparator(path[len(path)-1])
}
func SpecifiesCurrentDir(path string) bool {
	return filepath.Base(path) == "."
}
func SplitPathDirEntry(localizedPath string) (dir, base string) {
	normalizedPath := filepath.ToSlash(localizedPath)
	vol := filepath.VolumeName(normalizedPath)
	normalizedPath = normalizedPath[len(vol):]
	if normalizedPath == "/" {
		return filepath.FromSlash(vol + normalizedPath), "."
	}
	trimmedPath := vol + strings.TrimRight(normalizedPath, "/")
	dir = filepath.FromSlash(path.Dir(trimmedPath))
	base = filepath.FromSlash(path.Base(trimmedPath))
	return dir, base
}
func TarResource(sourcePath string) (content Archive, err error) {
	if _, err = os.Lstat(sourcePath); err != nil {
		return
	}
	if len(sourcePath) > 1 && HasTrailingPathSeparator(sourcePath) {
		trimmedPath := sourcePath[:len(sourcePath)-1]
		stat, err := os.Lstat(trimmedPath)
		if err != nil {
			return nil, err
		}
		if stat.Mode()&os.ModeSymlink != 0 {
			if sourcePath, err = filepath.EvalSymlinks(trimmedPath); err != nil {
				return nil, err
			}
		}
	}
	sourceDir, sourceBase := SplitPathDirEntry(sourcePath)
	filter := []string{sourceBase}
	logrus.Debugf("copying %q from %q", sourceBase, sourceDir)
	return TarWithOptions(sourceDir, &TarOptions{
		Compression:      Uncompressed,
		IncludeFiles:     filter,
		IncludeSourceDir: true,
	})
}
type CopyInfo struct {
	Path   string
	Exists bool
	IsDir  bool
}
func CopyInfoStatPath(path string, mustExist bool) (CopyInfo, error) {
	pathInfo := CopyInfo{Path: path}
	fileInfo, err := os.Lstat(path)
	if err == nil {
		pathInfo.Exists, pathInfo.IsDir = true, fileInfo.IsDir()
	} else if os.IsNotExist(err) && !mustExist {
		err = nil
	}
	return pathInfo, err
}
func PrepareArchiveCopy(srcContent ArchiveReader, srcInfo, dstInfo CopyInfo) (dstDir string, content Archive, err error) {
	dstDir, dstBase := SplitPathDirEntry(dstInfo.Path)
	_, srcBase := SplitPathDirEntry(srcInfo.Path)
	switch {
	case dstInfo.Exists && dstInfo.IsDir:
		return dstInfo.Path, ioutil.NopCloser(srcContent), nil
	case dstInfo.Exists && srcInfo.IsDir:
		return "", nil, ErrCannotCopyDir
	case dstInfo.Exists:
		return dstDir, rebaseArchiveEntries(srcContent, srcBase, dstBase), nil
	case srcInfo.IsDir:
		return dstDir, rebaseArchiveEntries(srcContent, srcBase, dstBase), nil
	case AssertsDirectory(dstInfo.Path):
		return "", nil, ErrDirNotExists
	default:
		return dstDir, rebaseArchiveEntries(srcContent, srcBase, dstBase), nil
	}
}