1
2
3
4
5 package copyutil
6
7 import (
8 "bytes"
9 "fmt"
10 "os"
11 "path/filepath"
12 "strings"
13
14 "github.com/sergi/go-diff/diffmatchpatch"
15 "sigs.k8s.io/kustomize/kyaml/errors"
16 "sigs.k8s.io/kustomize/kyaml/filesys"
17 "sigs.k8s.io/kustomize/kyaml/sets"
18 )
19
20
21 func CopyDir(fSys filesys.FileSystem, src string, dst string) error {
22 return errors.Wrap(fSys.Walk(src, func(path string, info os.FileInfo, err error) error {
23 if err != nil {
24 return err
25 }
26
27 if path != src {
28 rel := strings.TrimPrefix(path, src)
29 if IsDotGitFolder(rel) {
30 return nil
31 }
32 }
33
34
35
36
37 copyTo := strings.TrimPrefix(path, src)
38
39
40 if info.IsDir() {
41 return errors.Wrap(fSys.MkdirAll(filepath.Join(dst, copyTo)))
42 }
43
44
45 b, err := fSys.ReadFile(filepath.Join(src, copyTo))
46 if err != nil {
47 return errors.Wrap(err)
48 }
49 err = fSys.WriteFile(filepath.Join(dst, copyTo), b)
50 if err != nil {
51 return errors.Wrap(err)
52 }
53
54 return nil
55 }))
56 }
57
58
59
60
61
62 func Diff(sourceDir, destDir string) (sets.String, error) {
63
64 upstreamFiles := sets.String{}
65 err := filepath.Walk(sourceDir, func(path string, info os.FileInfo, err error) error {
66 if err != nil {
67 return err
68 }
69
70
71 if IsDotGitFolder(path) {
72 return nil
73 }
74
75 upstreamFiles.Insert(strings.TrimPrefix(strings.TrimPrefix(path, sourceDir), string(filepath.Separator)))
76 return nil
77 })
78 if err != nil {
79 return sets.String{}, err
80 }
81
82
83 localFiles := sets.String{}
84 err = filepath.Walk(destDir, func(path string, info os.FileInfo, err error) error {
85 if err != nil {
86 return err
87 }
88
89
90 if IsDotGitFolder(path) {
91 return nil
92 }
93
94 localFiles.Insert(strings.TrimPrefix(strings.TrimPrefix(path, destDir), string(filepath.Separator)))
95 return nil
96 })
97 if err != nil {
98 return sets.String{}, err
99 }
100
101
102 diff := upstreamFiles.SymmetricDifference(localFiles)
103
104
105 for _, f := range upstreamFiles.Intersection(localFiles).List() {
106 fi, err := os.Stat(filepath.Join(destDir, f))
107 if err != nil {
108 return diff, err
109 }
110 if fi.Mode().IsDir() {
111
112 continue
113 }
114
115
116 b1, err := os.ReadFile(filepath.Join(destDir, f))
117 if err != nil {
118 return diff, err
119 }
120 b2, err := os.ReadFile(filepath.Join(sourceDir, f))
121 if err != nil {
122 return diff, err
123 }
124 if !bytes.Equal(b1, b2) {
125 fmt.Println(PrettyFileDiff(string(b1), string(b2)))
126 diff.Insert(f)
127 }
128 }
129
130 return diff, nil
131 }
132
133
134
135 func IsDotGitFolder(path string) bool {
136 cleanPath := filepath.ToSlash(filepath.Clean(path))
137 for _, c := range strings.Split(cleanPath, "/") {
138 if c == ".git" {
139 return true
140 }
141 }
142 return false
143 }
144
145
146 func PrettyFileDiff(s1, s2 string) string {
147 dmp := diffmatchpatch.New()
148 wSrc, wDst, warray := dmp.DiffLinesToRunes(s1, s2)
149 diffs := dmp.DiffMainRunes(wSrc, wDst, false)
150 diffs = dmp.DiffCharsToLines(diffs, warray)
151 return dmp.DiffPrettyText(diffs)
152 }
153
154
155
156 func SyncFile(src, dst string) error {
157 srcFileInfo, err := os.Stat(src)
158 if err != nil {
159
160 if err = deleteFile(dst); err != nil {
161 return err
162 }
163 return nil
164 }
165
166 input, err := os.ReadFile(src)
167 if err != nil {
168 return err
169 }
170
171 var filePerm os.FileMode
172
173
174 dstFileInfo, err := os.Stat(dst)
175 if err != nil {
176
177 filePerm = srcFileInfo.Mode().Perm()
178 } else {
179 filePerm = dstFileInfo.Mode().Perm()
180 }
181
182 err = os.WriteFile(dst, input, filePerm)
183 if err != nil {
184 return err
185 }
186
187 return nil
188 }
189
190
191 func deleteFile(path string) error {
192 if _, err := os.Stat(path); err != nil {
193
194 return nil
195 }
196 return os.Remove(path)
197 }
198
View as plain text