1
2
3
4
5 package bootstrap_test
6
7 import (
8 "io"
9 "io/fs"
10 "os"
11 "path/filepath"
12 "strings"
13 )
14
15
16
17
18
19 func overlayDir(dstRoot, srcRoot string) error {
20 dstRoot = filepath.Clean(dstRoot)
21 if err := os.MkdirAll(dstRoot, 0777); err != nil {
22 return err
23 }
24
25 srcRoot, err := filepath.Abs(srcRoot)
26 if err != nil {
27 return err
28 }
29
30 return filepath.WalkDir(srcRoot, func(srcPath string, entry fs.DirEntry, err error) error {
31 if err != nil || srcPath == srcRoot {
32 return err
33 }
34 if filepath.Base(srcPath) == "testdata" {
35
36 return fs.SkipDir
37 }
38
39 suffix := strings.TrimPrefix(srcPath, srcRoot)
40 for len(suffix) > 0 && suffix[0] == filepath.Separator {
41 suffix = suffix[1:]
42 }
43 dstPath := filepath.Join(dstRoot, suffix)
44
45 info, err := entry.Info()
46 if err != nil {
47 return err
48 }
49 perm := info.Mode() & os.ModePerm
50 if info.Mode()&os.ModeSymlink != 0 {
51 info, err = os.Stat(srcPath)
52 if err != nil {
53 return err
54 }
55 perm = info.Mode() & os.ModePerm
56 }
57
58
59
60 if info.IsDir() {
61 return os.MkdirAll(dstPath, perm|0200)
62 }
63
64
65
66 if err := os.Link(srcPath, dstPath); err == nil {
67 return nil
68 }
69
70
71 src, err := os.Open(srcPath)
72 if err != nil {
73 return err
74 }
75 defer src.Close()
76
77 dst, err := os.OpenFile(dstPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm)
78 if err != nil {
79 return err
80 }
81
82 _, err = io.Copy(dst, src)
83 if closeErr := dst.Close(); err == nil {
84 err = closeErr
85 }
86 return err
87 })
88 }
89
View as plain text