| | |
| | |
| | |
| |
|
| | package bootstrap_test |
| |
|
| | import ( |
| | "io" |
| | "io/fs" |
| | "os" |
| | "path/filepath" |
| | "strings" |
| | ) |
| |
|
| | |
| | |
| | |
| | |
| | func overlayDir(dstRoot, srcRoot string) error { |
| | dstRoot = filepath.Clean(dstRoot) |
| | if err := os.MkdirAll(dstRoot, 0777); err != nil { |
| | return err |
| | } |
| |
|
| | srcRoot, err := filepath.Abs(srcRoot) |
| | if err != nil { |
| | return err |
| | } |
| |
|
| | return filepath.WalkDir(srcRoot, func(srcPath string, entry fs.DirEntry, err error) error { |
| | if err != nil || srcPath == srcRoot { |
| | return err |
| | } |
| | if filepath.Base(srcPath) == "testdata" { |
| | |
| | return fs.SkipDir |
| | } |
| |
|
| | suffix := strings.TrimPrefix(srcPath, srcRoot) |
| | for len(suffix) > 0 && suffix[0] == filepath.Separator { |
| | suffix = suffix[1:] |
| | } |
| | dstPath := filepath.Join(dstRoot, suffix) |
| |
|
| | info, err := entry.Info() |
| | if err != nil { |
| | return err |
| | } |
| | perm := info.Mode() & os.ModePerm |
| | if info.Mode()&os.ModeSymlink != 0 { |
| | info, err = os.Stat(srcPath) |
| | if err != nil { |
| | return err |
| | } |
| | perm = info.Mode() & os.ModePerm |
| | } |
| |
|
| | |
| | |
| | if info.IsDir() { |
| | return os.MkdirAll(dstPath, perm|0200) |
| | } |
| |
|
| | |
| | |
| | if err := os.Link(srcPath, dstPath); err == nil { |
| | return nil |
| | } |
| |
|
| | |
| | src, err := os.Open(srcPath) |
| | if err != nil { |
| | return err |
| | } |
| | defer src.Close() |
| |
|
| | dst, err := os.OpenFile(dstPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm) |
| | if err != nil { |
| | return err |
| | } |
| |
|
| | _, err = io.Copy(dst, src) |
| | if closeErr := dst.Close(); err == nil { |
| | err = closeErr |
| | } |
| | return err |
| | }) |
| | } |
| |
|