@@ -7,17 +7,14 @@ import (
77 "errors"
88 "fmt"
99 "io"
10- "io/fs"
1110 "log"
1211 "os"
1312 "os/exec"
1413 "path"
15- "path/filepath"
16- "sort"
1714 "strings"
18- "sync"
1915
2016 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
17+ "github.com/chime/mani-diffy/pkg/digest"
2118 "github.com/chime/mani-diffy/pkg/kustomize"
2219 yamlutil "k8s.io/apimachinery/pkg/util/yaml"
2320)
@@ -192,11 +189,9 @@ func EmptyManifest(manifest string) (bool, error) {
192189func GenerateHash (crd * v1alpha1.Application , ignoreValueFile string ) (string , error ) {
193190 finalHash := sha256 .New ()
194191
195- crdHash , err := generateHashOnCrd (crd )
196- if err != nil {
192+ if _ , err := finalHash .Write ([]byte (crd .String ())); err != nil {
197193 return "" , err
198194 }
199- fmt .Fprintf (finalHash , "%x\n " , crdHash )
200195
201196 if crd .Spec .Source .Kustomize != nil {
202197 return "" , kustomize .ErrNotSupported
@@ -230,165 +225,12 @@ func GenerateHash(crd *v1alpha1.Application, ignoreValueFile string) (string, er
230225}
231226
232227func generalHashFunction (dirFilepath string ) ([]byte , error ) {
233- m , err := sha256Dir ( dirFilepath )
234- if err != nil {
228+ h := sha256 . New ( )
229+ if err := digest . Digest ( dirFilepath , h ); err != nil {
235230 log .Println (err )
236231 return []byte {}, err
237232 }
238- var paths []string
239- for path := range m {
240- paths = append (paths , path )
241- }
242- // Not sure if needed but I'm sorting for deterministic behavior
243- sort .Strings (paths )
244- hash := sha256 .New ()
245- for _ , path := range paths {
246- // if a single file, just return the hash
247- if len (paths ) == 1 {
248- value := m [path ]
249- slice := value [:]
250- return slice , nil
251- }
252- fmt .Fprintf (hash , "%x %s\n " , m [path ], path )
253- }
254- // log.Printf("FINAL HASH: %v\n", hex.EncodeToString(hash.Sum(nil)))
255- return hash .Sum (nil ), nil
256- }
257-
258- // A result is the product of reading and summing a file using MD5.
259- type result struct {
260- path string
261- sum [sha256 .Size ]byte
262- err error
263- }
264-
265- type nonRegularFile struct {
266- fileName string
267- isDir bool
268- }
269-
270- func resolvesTo (filePath string ) (nonRegularFile , error ) {
271- fileData := nonRegularFile {}
272- info , err := os .Lstat (filePath )
273- if err != nil {
274- return fileData , fmt .Errorf ("failed to lstat file: %w" , err )
275- }
276-
277- if info .IsDir () {
278- fileData .fileName = filePath
279- fileData .isDir = true
280- return fileData , nil
281- }
282-
283- if info .Mode ()& fs .ModeSymlink != 0 {
284- fileName , err := os .Readlink (filePath )
285- if err != nil {
286- return fileData , fmt .Errorf ("failed to follow symlink: %w" , err )
287- }
288- fileName = strings .ReplaceAll (filePath , info .Name (), fileName )
289- fileData .fileName = fileName
290- fileInfo , err := os .Lstat (fileName )
291- if err != nil {
292- return fileData , fmt .Errorf ("failed to lstat file: %w" , err )
293- }
294- if fileInfo .IsDir () {
295- fileData .isDir = true
296- return fileData , nil
297- }
298- }
299- return fileData , nil
300- }
301-
302- // sumFiles starts goroutines to walk the directory tree at root and digest each
303- // regular file. These goroutines send the results of the digests on the result
304- // channel and send the result of the walk on the error channel. If done is
305- // closed, sumFiles abandons its work.
306- func sumFiles (done <- chan struct {}, root string ) (<- chan result , <- chan error ) {
307- // For each regular file, start a goroutine that sums the file and sends
308- // the result on c. Send the result of the walk on errc.
309- c := make (chan result )
310- errc := make (chan error , 1 )
311- go func () { // HL
312- var wg sync.WaitGroup
313- err := filepath .Walk (root , func (path string , info os.FileInfo , err error ) error {
314- if err != nil {
315- return fmt .Errorf ("error walking the file path %s: %w" , root , err )
316- }
317- if ! info .Mode ().IsRegular () {
318- resolvedInfo , err := resolvesTo (root )
319- if err != nil {
320- return err
321- }
322- if resolvedInfo .isDir {
323- // TODO: figure out how to handle dirs and
324- // symlinked dirs
325- return nil
326- }
327- path = resolvedInfo .fileName
328- }
329- wg .Add (1 )
330- go func () { // HL
331- data , err := os .ReadFile (path )
332- select {
333- case c <- result {path , sha256 .Sum256 (data ), err }: // HL
334- case <- done : // HL
335- }
336- wg .Done ()
337- }()
338- // Abort the walk if done is closed.
339- select {
340- case <- done : // HL
341- return errors .New ("walk canceled" )
342- default :
343- return nil
344- }
345- })
346- // Walk has returned, so all calls to wg.Add are done. Start a
347- // goroutine to close c once all the sends are done.
348- go func () { // HL
349- wg .Wait ()
350- close (c ) // HL
351- }()
352- // No select needed here, since errc is buffered.
353- errc <- err // HL
354- }()
355- return c , errc
356- }
357-
358- // sha256Dir reads all the files in the file tree rooted at root and returns a map
359- // from file path to the sha256 sum of the file's contents. If the directory walk
360- // fails or any read operation fails, sha256Dir returns an error. In that case,
361- // sha256Dir does not wait for inflight read operations to complete.
362- func sha256Dir (root string ) (map [string ][sha256 .Size ]byte , error ) {
363- // sha256Dir closes the done channel when it returns; it may do so before
364- // receiving all the values from c and errc.
365- done := make (chan struct {}) // HLdone
366- defer close (done ) // HLdone
367-
368- c , errc := sumFiles (done , root ) // HLdone
369-
370- m := make (map [string ][sha256 .Size ]byte )
371- for r := range c { // HLrange
372- if r .err != nil {
373- return nil , r .err
374- }
375- m [r .path ] = r .sum
376- }
377- if err := <- errc ; err != nil {
378- return nil , err
379- }
380- return m , nil
381- }
382-
383- func generateHashOnCrd (crd * v1alpha1.Application ) (string , error ) {
384- hash := sha256 .New ()
385- crdString := crd .String ()
386- crdByte := []byte (crdString )
387- if _ , err := hash .Write (crdByte ); err != nil {
388- return "" , fmt .Errorf ("error generating hash for the %s crd: %w" , crd .ObjectMeta .Name , err )
389- }
390- sum := hash .Sum (nil )
391- return hex .EncodeToString (sum ), nil
233+ return h .Sum (nil ), nil
392234}
393235
394236func Run (crd * v1alpha1.Application , output string , skipRenderKey string , ignoreValueFile string ) error {
0 commit comments