]> Cypherpunks.ru repositories - gostls13.git/commitdiff
archive/zip: add AddFS method to zip Writer
authorMauri de Souza Meneguzzo <mauri870@gmail.com>
Thu, 27 Jul 2023 23:11:59 +0000 (23:11 +0000)
committerGopher Robot <gobot@golang.org>
Mon, 31 Jul 2023 18:10:41 +0000 (18:10 +0000)
The method AddFS can be used to add the contents of a fs.FS filesystem
to a zip archive.
This method walks the directory tree starting at the root of the filesystem
and adds each file to the archive.

Fixes #54898

Change-Id: I80511cbd91a1d7e09ee52d2d1b09fb5eed25f45f
GitHub-Last-Rev: 1e17f2e6bae60cf5168d687dd1357ab58a883675
GitHub-Pull-Request: golang/go#61602
Reviewed-on: https://go-review.googlesource.com/c/go/+/513438
Reviewed-by: David Chase <drchase@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@google.com>

api/next/54898.txt [new file with mode: 0644]
src/archive/zip/writer.go
src/archive/zip/writer_test.go

diff --git a/api/next/54898.txt b/api/next/54898.txt
new file mode 100644 (file)
index 0000000..44133bd
--- /dev/null
@@ -0,0 +1 @@
+pkg archive/zip, method (*Writer) AddFS(fs.FS) error #54898
index 3b23cc3391d9e676a6735266fa8bb76a73ace755..0e81c6a5d7c71396d1744fa2c95f6c4f511ce3f8 100644 (file)
@@ -11,6 +11,7 @@ import (
        "hash"
        "hash/crc32"
        "io"
+       "io/fs"
        "strings"
        "unicode/utf8"
 )
@@ -495,6 +496,41 @@ func (w *Writer) RegisterCompressor(method uint16, comp Compressor) {
        w.compressors[method] = comp
 }
 
+// AddFS adds the files from fs.FS to the archive.
+// It walks the directory tree starting at the root of the filesystem
+// adding each file to the zip using deflate while maintaining the directory structure.
+func (w *Writer) AddFS(fsys fs.FS) error {
+       return fs.WalkDir(fsys, ".", func(name string, d fs.DirEntry, err error) error {
+               if err != nil {
+                       return err
+               }
+               if d.IsDir() {
+                       return nil
+               }
+               info, err := d.Info()
+               if err != nil {
+                       return err
+               }
+               h, err := FileInfoHeader(info)
+               if err != nil {
+                       return err
+               }
+               h.Name = name
+               h.Method = Deflate
+               fw, err := w.CreateHeader(h)
+               if err != nil {
+                       return err
+               }
+               f, err := fsys.Open(name)
+               if err != nil {
+                       return err
+               }
+               defer f.Close()
+               _, err = io.Copy(fw, f)
+               return err
+       })
+}
+
 func (w *Writer) compressor(method uint16) Compressor {
        comp := w.compressors[method]
        if comp == nil {
index 2b73eca814f621a9a0289f24cf0b6bbe8df35c6c..5250bc112ee0e4c7c0c4183363bfeed2e9bace1a 100644 (file)
@@ -16,6 +16,7 @@ import (
        "os"
        "strings"
        "testing"
+       "testing/fstest"
        "time"
 )
 
@@ -602,3 +603,48 @@ func BenchmarkCompressedZipGarbage(b *testing.B) {
                }
        })
 }
+
+func writeTestsToFS(tests []WriteTest) fs.FS {
+       fsys := fstest.MapFS{}
+       for _, wt := range tests {
+               fsys[wt.Name] = &fstest.MapFile{
+                       Data: wt.Data,
+                       Mode: wt.Mode,
+               }
+       }
+       return fsys
+}
+
+func TestWriterAddFS(t *testing.T) {
+       buf := new(bytes.Buffer)
+       w := NewWriter(buf)
+       tests := []WriteTest{
+               {
+                       Name: "file.go",
+                       Data: []byte("hello"),
+                       Mode: 0644,
+               },
+               {
+                       Name: "subfolder/another.go",
+                       Data: []byte("world"),
+                       Mode: 0644,
+               },
+       }
+       err := w.AddFS(writeTestsToFS(tests))
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       if err := w.Close(); err != nil {
+               t.Fatal(err)
+       }
+
+       // read it back
+       r, err := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len()))
+       if err != nil {
+               t.Fatal(err)
+       }
+       for i, wt := range tests {
+               testReadFile(t, r.File[i], &wt)
+       }
+}