- Initial commit.

This commit is contained in:
2024-05-31 19:52:04 +02:00
commit 27d3e52b46
16 changed files with 1029 additions and 0 deletions
+77
View File
@@ -0,0 +1,77 @@
package zip
import (
"archive/zip"
"fmt"
"io"
"io/fs"
"os"
"strings"
"git.sa-roci.de/oss/go_zipper"
)
const ArchiveExt = ".zip"
// NewZipper makes a new Zipper.
func NewZipper(zipFilename string) zipper.Zipper {
if !strings.HasSuffix(strings.ToLower(zipFilename), ArchiveExt) {
zipFilename += ArchiveExt
}
z := zZipper{
Zipper: zipper.NewBaseZipper(zipFilename),
}
z.SetCompressor(z)
return z
}
type zZipper struct {
zipper.Zipper
}
func (z zZipper) OpenWriter(zipFile *os.File) error {
z.SetWriter(zip.NewWriter(zipFile))
return nil
}
func (z zZipper) MultiFileSupported() bool {
return true
}
func (z zZipper) Compress(fileToZip *os.File, pathInArchive string) (err error) {
// Get the file information
var info fs.FileInfo
if info, err = fileToZip.Stat(); err != nil {
return err
}
var header *zip.FileHeader
if header, err = zip.FileInfoHeader(info); err != nil {
return err
}
filename := info.Name()
// Using FileInfoHeader() above only uses the basename of the file. If we want
// to preserve the folder structure we can overwrite this with the full path.
if len(pathInArchive) > 0 || strings.Contains(filename, "/") || strings.Contains(filename, "\\") {
header.Name = zipper.PrependPath(filename, pathInArchive)
}
// Change to deflate to gain better compression
// see http://golang.org/pkg/archive/zip/#pkg-constants
header.Method = zip.Deflate
if zipWriter, ok := z.GetWriter().(*zip.Writer); ok {
var writer io.Writer
if writer, err = zipWriter.CreateHeader(header); err != nil {
return err
}
_, err = io.Copy(writer, fileToZip)
} else {
err = fmt.Errorf("unable to access compressor")
}
return
}
+60
View File
@@ -0,0 +1,60 @@
package zip
import (
"archive/zip"
"io"
"os"
"git.sa-roci.de/oss/go_zipper"
)
// NewUnzipper makes a new Unzipper.
func NewUnzipper(zipFilename string) zipper.Unzipper {
uz := zUnzipper{
Unzipper: zipper.NewBaseUnzipper(zipFilename),
}
uz.SetDecompressor(uz)
return uz
}
type zUnzipper struct {
zipper.Unzipper
}
func (uz zUnzipper) OpenReader(zipFile *os.File) (err error) {
var reader *zip.ReadCloser
if reader, err = zip.OpenReader(zipFile.Name()); err == nil {
uz.SetReader(reader)
}
return
}
func (uz zUnzipper) Decompress(targetFolderPathInFileSystem string) (err error) {
if zipReader, ok := uz.GetReader().(*zip.ReadCloser); ok {
if err = zipper.MakeSurePathExists(targetFolderPathInFileSystem+"/dummy.file", 0644); err == nil {
for _, entry := range zipReader.File {
outputPath := zipper.PrependPath(entry.Name, targetFolderPathInFileSystem)
if !entry.FileInfo().IsDir() {
if err = zipper.MakeSurePathExists(outputPath, 0644); err == nil {
var dstFile *os.File
if dstFile, err = os.OpenFile(outputPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, entry.Mode()); err == nil {
defer dstFile.Close()
var archivedFileData io.ReadCloser
if archivedFileData, err = entry.Open(); err == nil {
defer archivedFileData.Close()
_, err = io.Copy(dstFile, archivedFileData)
}
}
}
} else {
err = zipper.MakeSurePathExists(outputPath+"/dummy.file", 0644)
}
if err != nil {
break
}
}
}
}
return
}
+92
View File
@@ -0,0 +1,92 @@
package zip
import (
"io/fs"
"os"
"path/filepath"
"testing"
)
const (
content = "test-content"
)
func TestZipper(t *testing.T) {
archiveFolder := "testdata"
archiveFilename := archiveFolder + "/dummy"
testFileName := "testZipper.data"
if os.WriteFile(testFileName, []byte(content), 0644) == nil {
defer os.Remove(testFileName)
}
z := NewZipper(archiveFilename)
if z.GetWriter() != nil {
t.Log("Found unexpected writer")
t.Fail()
}
// Test adding files
if z.AddZipFiles([]string{testFileName}, "testfolder") != nil {
t.Log("Unable to add a single file")
t.Fail()
}
// Test adding more files than allowed
if z.AddFileToZip(testFileName, "testfolder/more") != nil {
t.Log("Unexpectedly failed in adding more than one file")
t.Fail()
}
z.Close()
uz := NewUnzipper(archiveFilename + ArchiveExt)
if uz.ExtractFiles("") != nil {
t.Log("Failed to extract files")
t.Fail()
} else {
if data, err := os.ReadFile("testfolder/" + testFileName); err != nil {
t.Log("Expected extracted file #1 is missing")
t.Fail()
} else if string(data) != content {
t.Logf("Unexpected extracted file #1 content: '%s'", string(data))
t.Fail()
}
if data, err := os.ReadFile("testfolder/more/" + testFileName); err != nil {
t.Log("Expected extracted file #2 is missing")
t.Fail()
} else if string(data) != content {
t.Logf("Unexpected extracted file #2 content: '%s'", string(data))
t.Fail()
}
}
// Clean up
removeRecursive("testfolder")
os.Remove(archiveFilename + ArchiveExt)
os.Remove(archiveFolder)
}
func removeRecursive(path string) {
filepath.Walk(path, deleteFiles)
filepath.WalkDir(path, deleteFolders)
filepath.WalkDir(path, deleteFolders)
filepath.WalkDir(path, deleteFolders)
}
func deleteFiles(path string, info fs.FileInfo, errIn error) (err error) {
if errIn != nil {
return
}
if !info.IsDir() {
err = os.Remove(path)
}
return err
}
func deleteFolders(path string, info fs.DirEntry, errIn error) (err error) {
if errIn != nil {
return
}
os.Remove(path)
return
}