From 06a8e86273778305f29d587881dc1c29dbfa888c Mon Sep 17 00:00:00 2001
From: Stephen Chung <schung@redhat.com>
Date: Thu, 14 Jul 2016 09:57:37 -0400
Subject: [PATCH] Create and insert metadata Entry's

Create Entry's that detail the file spec signature.

Signed-off-by: Stephen Chung <schung@redhat.com>
---
 walk.go | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 65 insertions(+), 1 deletion(-)

diff --git a/walk.go b/walk.go
index a1ef434..b6c4577 100644
--- a/walk.go
+++ b/walk.go
@@ -1,9 +1,12 @@
 package mtree
 
 import (
+	"fmt"
 	"os"
+	"os/user"
 	"path/filepath"
 	"sort"
+	"time"
 )
 
 // ExcludeFunc is the type of function called on each path walked to determine
@@ -25,7 +28,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
@@ -236,3 +244,59 @@ func readOrderedDirNames(dirname string) ([]string, error) {
 	sort.Strings(dirnames)
 	return append(names, dirnames...), nil
 }
+
+// signatureEntries is 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
+}