Create symlinks for Copyfile and Linkfile entries.

Change-Id: Idc45362eb75842bafe1b8292cb6ec2ff34e4f854
diff --git a/populate/e2e_test.go b/populate/e2e_test.go
index 9f141cf..6cd51d2 100644
--- a/populate/e2e_test.go
+++ b/populate/e2e_test.go
@@ -134,6 +134,56 @@
 	return &fix, nil
 }
 
+func TestCopyEntries(t *testing.T) {
+	fixture, err := newFixture()
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer fixture.Cleanup()
+
+	// We avoid talking to gitiles by inserting entries into the
+	// cache manually.
+	if err := fixture.cache.Tree.Add(gitID(ids[0]), &gitiles.Tree{
+		ID: ids[0],
+		Entries: []gitiles.TreeEntry{
+			{
+				Mode: 0100644,
+				Name: "a",
+				Type: "blob",
+				ID:   ids[1],
+				Size: newInt(42),
+			},
+		},
+	}); err != nil {
+		t.Fatal(err)
+	}
+
+	if err := fixture.addWorkspace("m", &manifest.Manifest{
+		Project: []manifest.Project{{
+			Name:     "platform/project",
+			Path:     "p",
+			Revision: ids[0],
+			Copyfile: []manifest.Copyfile{
+				{Src: "a", Dest: "bla"},
+			},
+		}}}); err != nil {
+		t.Fatalf("addWorkspace: %v", err)
+	}
+
+	ws := filepath.Join(fixture.dir, "ws")
+	roRoot := filepath.Join(fixture.dir, "mnt", "m")
+	if _, _, err := Checkout(roRoot, ws); err != nil {
+		t.Fatalf("Checkout: %v", err)
+	}
+
+	if dest, err := os.Readlink(filepath.Join(ws, "bla")); err != nil {
+		t.Fatal(err)
+	} else if want := filepath.Join(roRoot, "bla"); dest != want {
+		t.Fatalf("Readlink(ws/sub): got %q, want %q", dest, want)
+	}
+
+}
+
 func TestFUSESymlink(t *testing.T) {
 	fixture, err := newFixture()
 	if err != nil {
diff --git a/populate/populate.go b/populate/populate.go
index 37cd82c..1654efd 100644
--- a/populate/populate.go
+++ b/populate/populate.go
@@ -109,6 +109,13 @@
 			}
 		}
 	}
+
+	for _, c := range ro.copied {
+		if err := os.Symlink(filepath.Join(roRoot, c), filepath.Join(rwRoot, c)); err != nil && !os.IsExist(err) {
+			return err
+		}
+	}
+
 	return nil
 }
 
diff --git a/populate/populate_test.go b/populate/populate_test.go
index 141d458..bc4f0d4 100644
--- a/populate/populate_test.go
+++ b/populate/populate_test.go
@@ -145,9 +145,10 @@
 		children: map[string]*repoTree{
 			"build": buildT,
 		},
-		entries: map[string]*fileInfo{
-			"Makefile":   &fileInfo{},
-			"Android.bp": &fileInfo{},
+		entries: map[string]*fileInfo{},
+		copied: []string{
+			"Android.bp",
+			"Makefile",
 		},
 	}
 
diff --git a/populate/repotree.go b/populate/repotree.go
index 283350e..94f068c 100644
--- a/populate/repotree.go
+++ b/populate/repotree.go
@@ -22,6 +22,7 @@
 	"log"
 	"os"
 	"path/filepath"
+	"sort"
 	"strings"
 
 	git "github.com/libgit2/git2go"
@@ -35,9 +36,6 @@
 type fileInfo struct {
 	// the SHA1 of the file. This can be nil if getting it was too expensive.
 	sha1 *git.Oid
-
-	// We can't do chtimes on symlinks.
-	isLink bool
 }
 
 // repoTree is a nested set of Git repositories.
@@ -47,6 +45,9 @@
 
 	// files in this repository.
 	entries map[string]*fileInfo
+
+	// paths that are instantiated with Copyfile or Linkfile.
+	copied []string
 }
 
 // findParentRepo recursively finds the deepest child that is a prefix
@@ -102,12 +103,13 @@
 
 	for _, p := range mf.Project {
 		for _, c := range p.Copyfile {
-			root.entries[c.Dest] = &fileInfo{}
+			root.copied = append(root.copied, c.Dest)
 		}
 		for _, c := range p.Linkfile {
-			root.entries[c.Dest] = &fileInfo{}
+			root.copied = append(root.copied, c.Dest)
 		}
 	}
+	sort.Strings(root.copied)
 	return root, nil
 }
 
@@ -132,10 +134,6 @@
 		}
 
 		t.entries[e.Name] = fi
-
-		if e.Target != nil {
-			fi.isLink = true
-		}
 	}
 
 	return nil