mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-03-27 21:39:20 +02:00
This reverts back to using `git archive` for the source archives... but will keep supporting extra files. ##### How it works: Basically, we run `git archive` as before. Then, we make a backup of the generated archive, and create a new one copying by reading from the backup and writing into the new one. Finally, we write the extra files to the new one as well. This only happens if the configuration does have extra files, otherwise, just the simple `git archive` will be run. PS: we can't just append to the archive because weird tar format paddings et al. --------- Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> Signed-off-by: Carlos A Becker <caarlos0@users.noreply.github.com>
106 lines
2.2 KiB
Go
106 lines
2.2 KiB
Go
// Package tar implements the Archive interface providing tar archiving.
|
|
package tar
|
|
|
|
import (
|
|
"archive/tar"
|
|
"fmt"
|
|
"io"
|
|
"io/fs"
|
|
"os"
|
|
|
|
"github.com/goreleaser/goreleaser/pkg/config"
|
|
)
|
|
|
|
// Archive as tar.
|
|
type Archive struct {
|
|
tw *tar.Writer
|
|
files map[string]bool
|
|
}
|
|
|
|
// New tar archive.
|
|
func New(target io.Writer) Archive {
|
|
return Archive{
|
|
tw: tar.NewWriter(target),
|
|
files: map[string]bool{},
|
|
}
|
|
}
|
|
|
|
// Copying creates a new tar with the contents of the given tar.
|
|
func Copying(source io.Reader, target io.Writer) (Archive, error) {
|
|
w := New(target)
|
|
r := tar.NewReader(source)
|
|
for {
|
|
h, err := r.Next()
|
|
if err == io.EOF || h == nil {
|
|
break
|
|
}
|
|
|
|
w.files[h.Name] = true
|
|
if err := w.tw.WriteHeader(h); err != nil {
|
|
return w, err
|
|
}
|
|
if _, err := io.Copy(w.tw, r); err != nil {
|
|
return w, err
|
|
}
|
|
}
|
|
return w, nil
|
|
}
|
|
|
|
// Close all closeables.
|
|
func (a Archive) Close() error {
|
|
return a.tw.Close()
|
|
}
|
|
|
|
// Add file to the archive.
|
|
func (a Archive) Add(f config.File) error {
|
|
if _, ok := a.files[f.Destination]; ok {
|
|
return &fs.PathError{Err: fs.ErrExist, Path: f.Destination, Op: "add"}
|
|
}
|
|
a.files[f.Destination] = true
|
|
info, err := os.Lstat(f.Source) // #nosec
|
|
if err != nil {
|
|
return fmt.Errorf("%s: %w", f.Source, err)
|
|
}
|
|
var link string
|
|
if info.Mode()&os.ModeSymlink != 0 {
|
|
link, err = os.Readlink(f.Source) // #nosec
|
|
if err != nil {
|
|
return fmt.Errorf("%s: %w", f.Source, err)
|
|
}
|
|
}
|
|
header, err := tar.FileInfoHeader(info, link)
|
|
if err != nil {
|
|
return fmt.Errorf("%s: %w", f.Source, err)
|
|
}
|
|
header.Name = f.Destination
|
|
if !f.Info.ParsedMTime.IsZero() {
|
|
header.ModTime = f.Info.ParsedMTime
|
|
}
|
|
if f.Info.Mode != 0 {
|
|
header.Mode = int64(f.Info.Mode)
|
|
}
|
|
if f.Info.Owner != "" {
|
|
header.Uid = 0
|
|
header.Uname = f.Info.Owner
|
|
}
|
|
if f.Info.Group != "" {
|
|
header.Gid = 0
|
|
header.Gname = f.Info.Group
|
|
}
|
|
if err = a.tw.WriteHeader(header); err != nil {
|
|
return fmt.Errorf("%s: %w", f.Source, err)
|
|
}
|
|
if info.IsDir() || info.Mode()&os.ModeSymlink != 0 {
|
|
return nil
|
|
}
|
|
file, err := os.Open(f.Source) // #nosec
|
|
if err != nil {
|
|
return fmt.Errorf("%s: %w", f.Source, err)
|
|
}
|
|
defer file.Close()
|
|
if _, err := io.Copy(a.tw, file); err != nil {
|
|
return fmt.Errorf("%s: %w", f.Source, err)
|
|
}
|
|
return nil
|
|
}
|