diff --git a/README.md b/README.md index e7ad7d2..efafafb 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,11 @@ Import the contents of a tar archive into a resource document. `jx import ./test.tgz` + +`jx import repo/packages/build.jx.yaml ./gopkgs.tar.gz` + +![Import Doc](md-images/jx-import.gif) + Read a resource document from an http endpoint. `jx import http://localhost/resources` diff --git a/cmd/cli/main.go b/cmd/cli/main.go index 15302b3..7909604 100644 --- a/cmd/cli/main.go +++ b/cmd/cli/main.go @@ -125,6 +125,7 @@ func ImportSubCommand(cmd *flag.FlagSet, output io.Writer) (err error) { if err != nil { log.Fatal(err) } + defer outputTarget.Close() if len(documents) == 0 { documents = append(documents, resource.NewDocument()) diff --git a/internal/target/decl.go b/internal/target/decl.go index dbd1b43..7336f95 100644 --- a/internal/target/decl.go +++ b/internal/target/decl.go @@ -27,10 +27,11 @@ type DeclFile struct { Gzip bool `yaml:"gzip,omitempty" json:"gzip,omitempty"` Format string `yaml:"format,omitempty" json:"format,omitempty"` encoder resource.Encoder `yaml:"-" json:"-"` + closer func() error `yaml:"-" json:"-"` } func NewDeclFile() *DeclFile { - return &DeclFile{ Gzip: false } + return &DeclFile{ Gzip: false, closer: func() error { return nil } } } func NewFileDocTarget(u *url.URL, format string, gzip bool, fileUri bool) DocTarget { @@ -43,6 +44,7 @@ func NewFileDocTarget(u *url.URL, format string, gzip bool, fileUri bool) DocTar } else { t.Path = filepath.Join(u.Hostname(), u.Path) } + t.Open() return t } @@ -65,6 +67,7 @@ func init() { t.Format = FormatJson } } + t.Open() return t }) @@ -102,13 +105,10 @@ func init() { } - -func (d *DeclFile) Type() string { return "decl" } - -func (d *DeclFile) EmitResources(documents []*resource.Document, filter resource.ResourceSelector) (error) { +func (d *DeclFile) Open() error { var file *os.File var fileErr error - var fileWriter io.Writer + var fileWriter io.WriteCloser if d.Path == "" || d.Path == "-" { file = os.Stdout } else { @@ -116,9 +116,14 @@ func (d *DeclFile) EmitResources(documents []*resource.Document, filter resource if fileErr != nil { return fileErr } - defer func() { + d.closer = func() error { + d.encoder.Close() + fileWriter.Close() + if file != fileWriter { file.Close() - }() + } + return nil + } } if d.Gzip { @@ -136,6 +141,16 @@ func (d *DeclFile) EmitResources(documents []*resource.Document, filter resource d.encoder = resource.NewYAMLEncoder(fileWriter) } + return nil +} + +func (d *DeclFile) Close() error { + return d.closer() +} + +func (d *DeclFile) Type() string { return "decl" } + +func (d *DeclFile) EmitResources(documents []*resource.Document, filter resource.ResourceSelector) (error) { for _, doc := range documents { emitDoc := resource.NewDocument() if validationErr := doc.Validate(); validationErr != nil { diff --git a/internal/target/doctarget.go b/internal/target/doctarget.go index 2481dce..fb77e30 100644 --- a/internal/target/doctarget.go +++ b/internal/target/doctarget.go @@ -24,6 +24,7 @@ type DocTarget interface { Type() string EmitResources(documents []*resource.Document, filter resource.ResourceSelector) error + Close() error } func NewDocTarget(uri string) DocTarget { diff --git a/internal/target/tar.go b/internal/target/tar.go index 38368d7..912b781 100644 --- a/internal/target/tar.go +++ b/internal/target/tar.go @@ -22,16 +22,19 @@ _ "regexp" 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 } + 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 }) @@ -44,15 +47,13 @@ func init() { t.Path = filepath.Join(u.Hostname(), u.Path) } t.Gzip = true + t.Open() return t }) } - -func (t *Tar) Type() string { return "tar" } - -func (t *Tar) EmitResources(documents []*resource.Document, filter resource.ResourceSelector) error { +func (t *Tar) Open() error { file, fileErr := os.Create(t.Path) if fileErr != nil { return fileErr @@ -64,13 +65,22 @@ func (t *Tar) EmitResources(documents []*resource.Document, filter resource.Reso fileWriter = file } - tarWriter := tar.NewWriter(fileWriter) - defer func() { - tarWriter.Close() + t.writer = tar.NewWriter(fileWriter) + t.closer = func() error { + t.writer.Close() fileWriter.Close() - file.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" @@ -79,10 +89,10 @@ func (t *Tar) EmitResources(documents []*resource.Document, filter resource.Reso slog.Info("Tar.EmitResources", "file", f) hdr, fiErr := tar.FileInfoHeader(f.FileInfo(), "") slog.Info("Tar.EmitResources", "header", hdr, "err", fiErr) - if err := tarWriter.WriteHeader(hdr); err != nil { + if err := t.writer.WriteHeader(hdr); err != nil { log.Fatal(err) } - if _, err := tarWriter.Write([]byte(f.Content)); err != nil { + if _, err := t.writer.Write([]byte(f.Content)); err != nil { log.Fatal(err) } } diff --git a/internal/target/types_test.go b/internal/target/types_test.go index 82e3f53..370b928 100644 --- a/internal/target/types_test.go +++ b/internal/target/types_test.go @@ -17,6 +17,7 @@ type MockDocTarget struct { } func (m *MockDocTarget) Type() string { return m.InjectType() } +func (m *MockDocTarget) Close() error { return nil } func (m *MockDocTarget) EmitResources(documents []*resource.Document, filter resource.ResourceSelector) error { return m.InjectEmitResources(documents, filter) } func NewFooDocTarget() DocTarget { diff --git a/md-images/jx-import.gif b/md-images/jx-import.gif new file mode 100644 index 0000000..52d1ad0 Binary files /dev/null and b/md-images/jx-import.gif differ