diff --git a/cmd/gomtree/main.go b/cmd/gomtree/main.go index a9d60fe..3ee1e43 100644 --- a/cmd/gomtree/main.go +++ b/cmd/gomtree/main.go @@ -75,7 +75,7 @@ func main() { } // -p - var rootPath string = "." + var rootPath = "." if *flPath != "" { rootPath = *flPath } diff --git a/tar.go b/tar.go index 97c6a33..0c83ef1 100644 --- a/tar.go +++ b/tar.go @@ -10,11 +10,15 @@ import ( "strings" ) +// Streamer interface that wraps an io.ReadCloser with a function that will +// return it's Hierarchy type Streamer interface { io.ReadCloser Hierarchy() (*DirectoryHierarchy, error) } +// NewTarStreamer streams a tar archive and creates a file hierarchy based off +// of the tar metadata headers func NewTarStreamer(r io.Reader, keywords []string) Streamer { pR, pW := io.Pipe() ts := &tarStream{ diff --git a/tar_test.go b/tar_test.go index 547e070..f1d011d 100644 --- a/tar_test.go +++ b/tar_test.go @@ -9,7 +9,7 @@ import ( "testing" ) -func ExampleTar() { +func ExampleStreamer() { fh, err := os.Open("./testdata/test.tar") if err != nil { // handle error ... diff --git a/walk.go b/walk.go index a3f3930..804050e 100644 --- a/walk.go +++ b/walk.go @@ -1,10 +1,13 @@ package mtree import ( + "fmt" "io" "os" + "os/user" "path/filepath" "sort" + "time" ) // ExcludeFunc is the type of function called on each path walked to determine @@ -19,7 +22,12 @@ var defaultSetKeywords = []string{"type=file", "nlink=1", "flags=none", "mode=06 // walked paths. The recommended default list is DefaultKeywords. func Walk(root string, exlcudes []ExcludeFunc, keywords []string) (*DirectoryHierarchy, error) { creator := dhCreator{DH: &DirectoryHierarchy{}} - // TODO insert signature and metadata comments first (user, machine, tree, date) + // insert signature and metadata comments first (user, machine, tree, date) + metadataEntries := signatureEntries(root) + for _, e := range metadataEntries { + e.Pos = len(creator.DH.Entries) + creator.DH.Entries = append(creator.DH.Entries, e) + } err := startWalk(&creator, root, func(path string, info os.FileInfo, err error) error { if err != nil { return err @@ -277,3 +285,59 @@ func readOrderedDirNames(dirname string) ([]string, error) { sort.Strings(dirnames) return append(names, dirnames...), nil } + +// signatureEntries is a simple helper function that returns a slice of Entry's +// that describe the metadata signature about the host. Items like date, user, +// machine, and tree (which is specified by argument `root`), are considered. +// These Entry's construct comments in the mtree specification, so if there is +// an error trying to obtain a particular metadata, we simply don't construct +// the Entry. +func signatureEntries(root string) []Entry { + var sigEntries []Entry + user, err := user.Current() + if err == nil { + userEntry := Entry{ + Type: CommentType, + Raw: fmt.Sprintf("#%16s%s", "user: ", user.Username), + } + sigEntries = append(sigEntries, userEntry) + } + + hostname, err := os.Hostname() + if err == nil { + hostEntry := Entry{ + Type: CommentType, + Raw: fmt.Sprintf("#%16s%s", "machine: ", hostname), + } + sigEntries = append(sigEntries, hostEntry) + } + + if tree := filepath.Clean(root); tree == "." || tree == ".." { + root, err := os.Getwd() + if err == nil { + // use parent directory of current directory + if tree == ".." { + root = filepath.Dir(root) + } + treeEntry := Entry{ + Type: CommentType, + Raw: fmt.Sprintf("#%16s%s", "tree: ", filepath.Clean(root)), + } + sigEntries = append(sigEntries, treeEntry) + } + } else { + treeEntry := Entry{ + Type: CommentType, + Raw: fmt.Sprintf("#%16s%s", "tree: ", filepath.Clean(root)), + } + sigEntries = append(sigEntries, treeEntry) + } + + dateEntry := Entry{ + Type: CommentType, + Raw: fmt.Sprintf("#%16s%s", "date: ", time.Now().Format("Mon Jan 2 15:04:05 2006")), + } + sigEntries = append(sigEntries, dateEntry) + + return sigEntries +}