github.com/ahmet2mir/goreleaser@v0.180.3-0.20210927151101-8e5ee5a9b8c5/pkg/archive/zip/zip.go (about)

     1  // Package zip implements the Archive interface providing zip archiving
     2  // and compression.
     3  package zip
     4  
     5  import (
     6  	"archive/zip"
     7  	"compress/flate"
     8  	"io"
     9  	"os"
    10  
    11  	"github.com/goreleaser/goreleaser/pkg/config"
    12  )
    13  
    14  // Archive zip struct.
    15  type Archive struct {
    16  	z *zip.Writer
    17  }
    18  
    19  // New zip archive.
    20  func New(target io.Writer) Archive {
    21  	compressor := zip.NewWriter(target)
    22  	compressor.RegisterCompressor(zip.Deflate, func(out io.Writer) (io.WriteCloser, error) {
    23  		return flate.NewWriter(out, flate.BestCompression)
    24  	})
    25  	return Archive{
    26  		z: compressor,
    27  	}
    28  }
    29  
    30  // Close all closeables.
    31  func (a Archive) Close() error {
    32  	return a.z.Close()
    33  }
    34  
    35  // Add a file to the zip archive.
    36  func (a Archive) Add(f config.File) error {
    37  	file, err := os.Open(f.Source) // #nosec
    38  	if err != nil {
    39  		return err
    40  	}
    41  	defer file.Close()
    42  	info, err := os.Lstat(f.Source) // #nosec
    43  	if err != nil {
    44  		return err
    45  	}
    46  	if info.IsDir() {
    47  		return err
    48  	}
    49  	header, err := zip.FileInfoHeader(info)
    50  	if err != nil {
    51  		return err
    52  	}
    53  	header.Name = f.Destination
    54  	header.Method = zip.Deflate
    55  	if !f.Info.MTime.IsZero() {
    56  		header.Modified = f.Info.MTime
    57  	}
    58  	if f.Info.Mode != 0 {
    59  		header.SetMode(f.Info.Mode)
    60  	}
    61  	w, err := a.z.CreateHeader(header)
    62  	if err != nil {
    63  		return err
    64  	}
    65  	_, err = io.Copy(w, file)
    66  	return err
    67  }
    68  
    69  // TODO: test fileinfo stuff