Handle absent Project.Path attributes.

Change-Id: I1ae28e7cfbb1eb6574b43e1812684ff2ee82564a
diff --git a/cmd/slothfs-deref-repo/main.go b/cmd/slothfs-deref-repo/main.go
index ee2432d..74140d2 100644
--- a/cmd/slothfs-deref-repo/main.go
+++ b/cmd/slothfs-deref-repo/main.go
@@ -41,7 +41,7 @@
 
 	mf.Filter()
 	for i, p := range mf.Project {
-		repoPath := filepath.Join(top, p.Path, ".git")
+		repoPath := filepath.Join(top, p.GetPath(), ".git")
 		repo, err := git.OpenRepository(repoPath)
 		if err != nil {
 			continue
diff --git a/fs/manifestfs.go b/fs/manifestfs.go
index b5b6ebc..3f60986 100644
--- a/fs/manifestfs.go
+++ b/fs/manifestfs.go
@@ -108,10 +108,10 @@
 	clonablePaths := map[string]bool{}
 	revmap := map[string]*manifest.Project{}
 	for i, p := range r.options.Manifest.Project {
-		revmap[p.Path] = &r.options.Manifest.Project[i]
+		revmap[p.GetPath()] = &r.options.Manifest.Project[i]
 
 		if p.CloneDepth == "" {
-			clonablePaths[p.Path] = true
+			clonablePaths[p.GetPath()] = true
 		}
 	}
 
@@ -162,7 +162,7 @@
 	// have directories to attach the copy/link nodes to.
 	for _, p := range r.options.Manifest.Project {
 		for _, cp := range p.Copyfile {
-			srcNode, left := fsConn.Node(r.Inode(), filepath.Join(p.Path, cp.Src))
+			srcNode, left := fsConn.Node(r.Inode(), filepath.Join(p.GetPath(), cp.Src))
 			if len(left) > 0 {
 				return fmt.Errorf("Copyfile(%s): source %s does not exist", p.Name, cp.Src)
 			}
@@ -189,7 +189,7 @@
 				return fmt.Errorf("Linkfile(%s): directory for dest %s does not exist.", p.Name, lf.Dest)
 			}
 
-			src := filepath.Join(p.Path, lf.Src)
+			src := filepath.Join(p.GetPath(), lf.Src)
 			rel, err := filepath.Rel(filepath.Dir(lf.Dest), src)
 			if err != nil {
 				return err
@@ -226,7 +226,7 @@
 		go func(p manifest.Project) {
 			revID, err := git.NewOid(p.Revision)
 			if err != nil {
-				out <- resultT{p.Path, nil, err}
+				out <- resultT{p.GetPath(), nil, err}
 				return
 			}
 
@@ -251,7 +251,7 @@
 				}
 			}
 
-			out <- resultT{p.Path, tree, err}
+			out <- resultT{p.GetPath(), tree, err}
 		}(p)
 	}
 
diff --git a/manifest/parser.go b/manifest/parser.go
index 55c8f4f..a3a4aed 100644
--- a/manifest/parser.go
+++ b/manifest/parser.go
@@ -79,6 +79,7 @@
 	}
 	return Parse(content)
 }
+
 func (mf *Manifest) ProjectRevision(p *Project) string {
 	if p.Revision != "" {
 		return p.Revision
diff --git a/manifest/parser_test.go b/manifest/parser_test.go
index 0228487..c778b74 100644
--- a/manifest/parser_test.go
+++ b/manifest/parser_test.go
@@ -19,6 +19,10 @@
 	"testing"
 )
 
+func newString(s string) *string {
+	return &s
+}
+
 var aospManifest = `<?xml version="1.0" encoding="UTF-8"?>
 <manifest>
   <remote  name="aosp"
@@ -55,7 +59,7 @@
 		},
 		Project: []Project{
 			{
-				Path:         "build",
+				Path:         newString("build"),
 				Name:         "platform/build",
 				GroupsString: "pdk,tradefed",
 				Groups: map[string]bool{
@@ -70,7 +74,7 @@
 				},
 			},
 			{
-				Path:         "build/soong",
+				Path:         newString("build/soong"),
 				Name:         "platform/build/soong",
 				GroupsString: "pdk,tradefed",
 				Groups: map[string]bool{
diff --git a/manifest/types.go b/manifest/types.go
index ea11d5e..91796a7 100644
--- a/manifest/types.go
+++ b/manifest/types.go
@@ -31,7 +31,7 @@
 // Project represents a single git repository that should be stitched
 // into the checkout.
 type Project struct {
-	Path         string          `xml:"path,attr"`
+	Path         *string         `xml:"path,attr"`
 	Name         string          `xml:"name,attr"`
 	Remote       string          `xml:"remote,attr,omitempty"`
 	Copyfile     []Copyfile      `xml:"copyfile,omitempty"`
@@ -53,6 +53,14 @@
 	CloneURL string `xml:"clone-url,attr,omitempty"`
 }
 
+// GetPath provides the path where to place the repository.
+func (p *Project) GetPath() string {
+	if p.Path != nil {
+		return *p.Path
+	}
+	return p.Name
+}
+
 // Remote describes a host where a set of projects is hosted.
 type Remote struct {
 	Alias    string `xml:"alias,attr"`
diff --git a/populate/e2e_test.go b/populate/e2e_test.go
index 6bbcddc..5ced2a3 100644
--- a/populate/e2e_test.go
+++ b/populate/e2e_test.go
@@ -163,7 +163,7 @@
 	if err := fixture.addWorkspace("m", &manifest.Manifest{
 		Project: []manifest.Project{{
 			Name:     "platform/project",
-			Path:     "p",
+			Path:     newString("p"),
 			Revision: ids[0],
 			Copyfile: []manifest.Copyfile{
 				{Src: "a", Dest: "bla"},
@@ -214,7 +214,7 @@
 		if err := fixture.addWorkspace(fmt.Sprintf("m%d", i), &manifest.Manifest{
 			Project: []manifest.Project{{
 				Name:     "platform/project",
-				Path:     "p",
+				Path:     newString("p"),
 				Revision: ids[0],
 			}}}); err != nil {
 			t.Fatalf("addWorkspace(%d): %v", i, err)
@@ -300,7 +300,7 @@
 		if err := fixture.addWorkspace(fmt.Sprintf("m%d", i), &manifest.Manifest{
 			Project: []manifest.Project{{
 				Name:     "platform/project",
-				Path:     "p",
+				Path:     newString("p"),
 				Revision: ids[i],
 			}}}); err != nil {
 			t.Fatalf("addWorkspace(%d): %v", i, err)
@@ -408,7 +408,7 @@
 	if err := fixture.addWorkspace("m1", &manifest.Manifest{
 		Project: []manifest.Project{{
 			Name:     "platform/project",
-			Path:     "project",
+			Path:     newString("project"),
 			Revision: ids[0],
 		}}}); err != nil {
 		t.Fatalf("addWorkspace(m1): %v", err)
@@ -418,11 +418,11 @@
 		Project: []manifest.Project{
 			{
 				Name:     "platform/project",
-				Path:     "project",
+				Path:     newString("project"),
 				Revision: ids[1],
 			}, {
 				Name:     "platform/sub",
-				Path:     "sub",
+				Path:     newString("sub"),
 				Revision: ids[2],
 			}},
 	}); err != nil {
diff --git a/populate/repotree.go b/populate/repotree.go
index 6ebce37..ede6d6b 100644
--- a/populate/repotree.go
+++ b/populate/repotree.go
@@ -78,7 +78,7 @@
 
 	var byDepth [][]*manifest.Project
 	for i, p := range mf.Project {
-		l := len(strings.Split(p.Path, "/"))
+		l := len(strings.Split(p.GetPath(), "/"))
 		for len(byDepth) <= l {
 			byDepth = append(byDepth, nil)
 		}
@@ -94,9 +94,9 @@
 	for _, projs := range byDepth {
 		for _, p := range projs {
 			childTree := makeRepoTree()
-			treesByPath[p.Path] = childTree
+			treesByPath[p.GetPath()] = childTree
 
-			parent, key := root.findParentRepo(p.Path)
+			parent, key := root.findParentRepo(p.GetPath())
 			parent.children[key] = childTree
 		}
 	}