// Copyright 2024 Matthew Rich . All rights reserved. package target import ( _ "context" _ "encoding/json" _ "fmt" _ "gopkg.in/yaml.v3" "net/url" "path/filepath" "decl/internal/resource" "compress/gzip" "archive/tar" _ "regexp" "os" "io" "log" "log/slog" ) type Tar struct { Path string `yaml:"path" json:"path"` Gzip bool `yaml:"gzip" json:"gzip"` writer *tar.Writer `yaml:"-" json:"-"` closer func() error `yaml:"-" json:"-"` } func NewTar() *Tar { return &Tar{ Gzip: false, closer: func() error { return nil } } } func init() { TargetTypes.Register([]string{"tar"}, func(u *url.URL) DocTarget { t := NewTar() t.Path,_ = filepath.Abs(filepath.Join(u.Hostname(), u.Path)) t.Open() return t }) TargetTypes.Register([]string{"tar.gz", "tgz"}, func(u *url.URL) DocTarget { t := NewTar() if u.Scheme == "file" { fileAbsolutePath, _ := filepath.Abs(filepath.Join(u.Hostname(), u.RequestURI())) t.Path = fileAbsolutePath } else { t.Path = filepath.Join(u.Hostname(), u.Path) } t.Gzip = true t.Open() return t }) } func (t *Tar) Open() error { file, fileErr := os.Create(t.Path) if fileErr != nil { return fileErr } var fileWriter io.WriteCloser if t.Gzip { fileWriter = gzip.NewWriter(file) } else { fileWriter = file } t.writer = tar.NewWriter(fileWriter) t.closer = func() error { t.writer.Close() fileWriter.Close() return file.Close() } return nil } func (t *Tar) Close() error { return t.closer() } func (t *Tar) Type() string { return "tar" } func (t *Tar) EmitResources(documents []*resource.Document, filter resource.ResourceSelector) error { for _,document := range documents { for _,res := range document.Filter(func(d *resource.Declaration) bool { return d.Type == "file" }) { var f *resource.File = res.Attributes.(*resource.File) slog.Info("Tar.EmitResources", "file", f) hdr, fiErr := tar.FileInfoHeader(f.FileInfo(), "") slog.Info("Tar.EmitResources", "header", hdr, "err", fiErr) if err := t.writer.WriteHeader(hdr); err != nil { log.Fatal(err) } if _, err := t.writer.Write([]byte(f.Content)); err != nil { log.Fatal(err) } } } return nil }