mirror of
https://github.com/vbatts/go-mtree.git
synced 2024-11-25 09:35:39 +00:00
tar: flatten the pseudo-tree only after readHeaders() is done
Flattening within the readHeaders() function call was problematic because readHeaders() is called as a goroutine; thus, as the main program was calling `tdh.writeTo(os.Stdout)`, readHeaders() was still in the process of flattening the tree structure. To get around this, we now call flatten in ts.Hierarchy(), such that only when the main program is ready to retrieve a "valid" DirectoryHierarchy from the archive, should we flatten the tree. Signed-off-by: Stephen Chung <schung@redhat.com>
This commit is contained in:
parent
822f319224
commit
6a37331074
1 changed files with 16 additions and 5 deletions
21
tar.go
21
tar.go
|
@ -2,6 +2,7 @@ package mtree
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"archive/tar"
|
"archive/tar"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
@ -29,11 +30,13 @@ func NewTarStreamer(r io.Reader, keywords []string) Streamer {
|
||||||
tarReader: tar.NewReader(pR),
|
tarReader: tar.NewReader(pR),
|
||||||
keywords: keywords,
|
keywords: keywords,
|
||||||
}
|
}
|
||||||
go ts.readHeaders() // I don't like this
|
|
||||||
|
go ts.readHeaders()
|
||||||
return ts
|
return ts
|
||||||
}
|
}
|
||||||
|
|
||||||
type tarStream struct {
|
type tarStream struct {
|
||||||
|
root *Entry
|
||||||
creator dhCreator
|
creator dhCreator
|
||||||
pipeReader *io.PipeReader
|
pipeReader *io.PipeReader
|
||||||
pipeWriter *io.PipeWriter
|
pipeWriter *io.PipeWriter
|
||||||
|
@ -50,7 +53,7 @@ func (ts *tarStream) readHeaders() {
|
||||||
Raw: "# .",
|
Raw: "# .",
|
||||||
Type: CommentType,
|
Type: CommentType,
|
||||||
}
|
}
|
||||||
root := Entry{
|
ts.root = &Entry{
|
||||||
Name: ".",
|
Name: ".",
|
||||||
Type: RelativeType,
|
Type: RelativeType,
|
||||||
Prev: &rootComment,
|
Prev: &rootComment,
|
||||||
|
@ -67,7 +70,6 @@ func (ts *tarStream) readHeaders() {
|
||||||
for {
|
for {
|
||||||
hdr, err := ts.tarReader.Next()
|
hdr, err := ts.tarReader.Next()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
flatten(&root, &ts.creator, ts.keywords)
|
|
||||||
ts.pipeReader.CloseWithError(err)
|
ts.pipeReader.CloseWithError(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -162,12 +164,12 @@ func (ts *tarStream) readHeaders() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if filepath.Dir(filepath.Clean(hdr.Name)) == "." {
|
if filepath.Dir(filepath.Clean(hdr.Name)) == "." {
|
||||||
root.Set = &s
|
ts.root.Set = &s
|
||||||
} else {
|
} else {
|
||||||
e.Set = &s
|
e.Set = &s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = populateTree(&root, &e, hdr)
|
err = populateTree(ts.root, &e, hdr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ts.setErr(err)
|
ts.setErr(err)
|
||||||
}
|
}
|
||||||
|
@ -209,6 +211,7 @@ func populateTree(root, e *Entry, hdr *tar.Header) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
// TODO: what about directory/file names with "/" in it?
|
||||||
dirNames := strings.Split(wd, "/")
|
dirNames := strings.Split(wd, "/")
|
||||||
parent := root
|
parent := root
|
||||||
for _, name := range dirNames[1:] {
|
for _, name := range dirNames[1:] {
|
||||||
|
@ -259,6 +262,9 @@ func populateTree(root, e *Entry, hdr *tar.Header) error {
|
||||||
// creator: a dhCreator that helps with the '/set' keyword
|
// creator: a dhCreator that helps with the '/set' keyword
|
||||||
// keywords: keywords specified by the user that should be evaluated
|
// keywords: keywords specified by the user that should be evaluated
|
||||||
func flatten(root *Entry, creator *dhCreator, keywords []string) {
|
func flatten(root *Entry, creator *dhCreator, keywords []string) {
|
||||||
|
if root == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
if root.Prev != nil {
|
if root.Prev != nil {
|
||||||
// root.Prev != nil implies root is a directory
|
// root.Prev != nil implies root is a directory
|
||||||
creator.DH.Entries = append(creator.DH.Entries,
|
creator.DH.Entries = append(creator.DH.Entries,
|
||||||
|
@ -317,6 +323,7 @@ func flatten(root *Entry, creator *dhCreator, keywords []string) {
|
||||||
}
|
}
|
||||||
creator.DH.Entries = append(creator.DH.Entries, dotEntry)
|
creator.DH.Entries = append(creator.DH.Entries, dotEntry)
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// filter takes in a pointer to an Entry, and returns a slice of Entry's that
|
// filter takes in a pointer to an Entry, and returns a slice of Entry's that
|
||||||
|
@ -387,5 +394,9 @@ func (ts *tarStream) Hierarchy() (*DirectoryHierarchy, error) {
|
||||||
if ts.err != nil && ts.err != io.EOF {
|
if ts.err != nil && ts.err != io.EOF {
|
||||||
return nil, ts.err
|
return nil, ts.err
|
||||||
}
|
}
|
||||||
|
if ts.root == nil {
|
||||||
|
return nil, fmt.Errorf("root Entry not found. Nothing to flatten")
|
||||||
|
}
|
||||||
|
flatten(ts.root, &ts.creator, ts.keywords)
|
||||||
return ts.creator.DH, nil
|
return ts.creator.DH, nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue