From 463d1a4b6b05296ba9c04596131f2b3f02f2fa48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Thu, 19 Sep 2024 10:39:05 +0100 Subject: [PATCH] dirhash: forward to golang.org/x/mod/sumdb/dirhash It seems like x/mod/sumdb/dirhash appeared way back in 2019, and we had not noticed until now. --- dirhash/hash.go | 96 ++++--------------------------- dirhash/hash_test.go | 134 ------------------------------------------- 2 files changed, 12 insertions(+), 218 deletions(-) delete mode 100644 dirhash/hash_test.go diff --git a/dirhash/hash.go b/dirhash/hash.go index 61d8face..62518915 100644 --- a/dirhash/hash.go +++ b/dirhash/hash.go @@ -1,103 +1,31 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package dirhash defines hashes over directory trees. +// Package dirhash is a thin forwarding layer on top of +// [golang.org/x/mod/sumdb/dirhash]. See that package for documentation. +// +// Deprecated: use [golang.org/x/mod/sumdb/dirhash] instead. package dirhash import ( - "archive/zip" - "crypto/sha256" - "encoding/base64" - "errors" - "fmt" "io" - "os" - "path/filepath" - "sort" - "strings" + + "golang.org/x/mod/sumdb/dirhash" ) -var DefaultHash = Hash1 +var DefaultHash = dirhash.Hash1 -type Hash func(files []string, open func(string) (io.ReadCloser, error)) (string, error) +type Hash = dirhash.Hash func Hash1(files []string, open func(string) (io.ReadCloser, error)) (string, error) { - h := sha256.New() - files = append([]string(nil), files...) - sort.Strings(files) - for _, file := range files { - if strings.Contains(file, "\n") { - return "", errors.New("filenames with newlines are not supported") - } - r, err := open(file) - if err != nil { - return "", err - } - hf := sha256.New() - _, err = io.Copy(hf, r) - r.Close() - if err != nil { - return "", err - } - fmt.Fprintf(h, "%x %s\n", hf.Sum(nil), file) - } - return "h1:" + base64.StdEncoding.EncodeToString(h.Sum(nil)), nil + return dirhash.Hash1(files, open) } func HashDir(dir, prefix string, hash Hash) (string, error) { - files, err := DirFiles(dir, prefix) - if err != nil { - return "", err - } - osOpen := func(name string) (io.ReadCloser, error) { - return os.Open(filepath.Join(dir, strings.TrimPrefix(name, prefix))) - } - return hash(files, osOpen) + return dirhash.HashDir(dir, prefix, hash) } func DirFiles(dir, prefix string) ([]string, error) { - var files []string - dir = filepath.Clean(dir) - err := filepath.Walk(dir, func(file string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if info.IsDir() { - return nil - } - rel := file - if dir != "." { - rel = file[len(dir)+1:] - } - f := filepath.Join(prefix, rel) - files = append(files, filepath.ToSlash(f)) - return nil - }) - if err != nil { - return nil, err - } - return files, nil + return dirhash.DirFiles(dir, prefix) } func HashZip(zipfile string, hash Hash) (string, error) { - z, err := zip.OpenReader(zipfile) - if err != nil { - return "", err - } - defer z.Close() - var files []string - zfiles := make(map[string]*zip.File) - for _, file := range z.File { - files = append(files, file.Name) - zfiles[file.Name] = file - } - zipOpen := func(name string) (io.ReadCloser, error) { - f := zfiles[name] - if f == nil { - return nil, fmt.Errorf("file %q not found in zip", name) // should never happen - } - return f.Open() - } - return hash(files, zipOpen) + return dirhash.HashZip(zipfile, hash) } diff --git a/dirhash/hash_test.go b/dirhash/hash_test.go deleted file mode 100644 index c4f7c227..00000000 --- a/dirhash/hash_test.go +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package dirhash - -import ( - "archive/zip" - "crypto/sha256" - "encoding/base64" - "fmt" - "io" - "os" - "path/filepath" - "strings" - "testing" -) - -func h(s string) string { - return fmt.Sprintf("%x", sha256.Sum256([]byte(s))) -} - -func htop(k string, s string) string { - sum := sha256.Sum256([]byte(s)) - return k + ":" + base64.StdEncoding.EncodeToString(sum[:]) -} - -func TestHash1(t *testing.T) { - files := []string{"xyz", "abc"} - open := func(name string) (io.ReadCloser, error) { - return io.NopCloser(strings.NewReader("data for " + name)), nil - } - want := htop("h1", fmt.Sprintf("%s %s\n%s %s\n", h("data for abc"), "abc", h("data for xyz"), "xyz")) - out, err := Hash1(files, open) - if err != nil { - t.Fatal(err) - } - if out != want { - t.Errorf("Hash1(...) = %s, want %s", out, want) - } - - _, err = Hash1([]string{"xyz", "a\nbc"}, open) - if err == nil { - t.Error("Hash1: expected error on newline in filenames") - } -} - -func TestHashDir(t *testing.T) { - dir, err := os.MkdirTemp("", "dirhash-test-") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(dir) - if err := os.WriteFile(filepath.Join(dir, "xyz"), []byte("data for xyz"), 0o666); err != nil { - t.Fatal(err) - } - if err := os.WriteFile(filepath.Join(dir, "abc"), []byte("data for abc"), 0o666); err != nil { - t.Fatal(err) - } - want := htop("h1", fmt.Sprintf("%s %s\n%s %s\n", h("data for abc"), "prefix/abc", h("data for xyz"), "prefix/xyz")) - out, err := HashDir(dir, "prefix", Hash1) - if err != nil { - t.Fatalf("HashDir: %v", err) - } - if out != want { - t.Errorf("HashDir(...) = %s, want %s", out, want) - } -} - -func TestHashZip(t *testing.T) { - f, err := os.CreateTemp("", "dirhash-test-") - if err != nil { - t.Fatal(err) - } - defer os.Remove(f.Name()) - defer f.Close() - - z := zip.NewWriter(f) - w, err := z.Create("prefix/xyz") - if err != nil { - t.Fatal(err) - } - w.Write([]byte("data for xyz")) - w, err = z.Create("prefix/abc") - if err != nil { - t.Fatal(err) - } - w.Write([]byte("data for abc")) - if err := z.Close(); err != nil { - t.Fatal(err) - } - if err := f.Close(); err != nil { - t.Fatal(err) - } - - want := htop("h1", fmt.Sprintf("%s %s\n%s %s\n", h("data for abc"), "prefix/abc", h("data for xyz"), "prefix/xyz")) - out, err := HashZip(f.Name(), Hash1) - if err != nil { - t.Fatalf("HashDir: %v", err) - } - if out != want { - t.Errorf("HashDir(...) = %s, want %s", out, want) - } -} - -func TestDirFiles(t *testing.T) { - dir, err := os.MkdirTemp("", "dirfiles-test-") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(dir) - if err := os.WriteFile(filepath.Join(dir, "xyz"), []byte("data for xyz"), 0o666); err != nil { - t.Fatal(err) - } - if err := os.WriteFile(filepath.Join(dir, "abc"), []byte("data for abc"), 0o666); err != nil { - t.Fatal(err) - } - if err := os.Mkdir(filepath.Join(dir, "subdir"), 0o777); err != nil { - t.Fatal(err) - } - if err := os.WriteFile(filepath.Join(dir, "subdir", "xyz"), []byte("data for subdir xyz"), 0o666); err != nil { - t.Fatal(err) - } - prefix := "foo/bar@v2.3.4" - out, err := DirFiles(dir, prefix) - if err != nil { - t.Fatalf("DirFiles: %v", err) - } - for _, file := range out { - if !strings.HasPrefix(file, prefix) { - t.Errorf("Dir file = %s, want prefix %s", file, prefix) - } - } -}