Partially Revert "Remove support for leading path separators in targets"

In order to generate metadata that's compatible with go-tuf 0.9,
the targets metadata still needs the leading slash. This reverts
rewriting the targets, but preserves the `loadTargets` workaround
so the transitional go-tuf can continue to parse 0.9 and 1.0 style
metadata.

This reverts commit 9d564c6f984962fe8e4f86568f6419efc8cbe091.

Change-Id: Ib89e635a6961329589822089611ca47c627eb5fa
diff --git a/client/client_test.go b/client/client_test.go
index e6f8929..5b7e400 100644
--- a/client/client_test.go
+++ b/client/client_test.go
@@ -81,9 +81,9 @@
 }
 
 var targetFiles = map[string][]byte{
-	"foo.txt": []byte("foo"),
-	"bar.txt": []byte("bar"),
-	"baz.txt": []byte("baz"),
+	"/foo.txt": []byte("foo"),
+	"/bar.txt": []byte("bar"),
+	"/baz.txt": []byte("baz"),
 }
 
 func (s *ClientSuite) SetUpTest(c *C) {
@@ -269,7 +269,7 @@
 	files, err := s.newClient(c).Update()
 	c.Assert(err, IsNil)
 	c.Assert(files, HasLen, 1)
-	assertFiles(c, files, []string{"foo.txt"})
+	assertFiles(c, files, []string{"/foo.txt"})
 }
 
 func (s *ClientSuite) TestMissingRemoteMetadata(c *C) {
@@ -355,14 +355,14 @@
 	client := s.newClient(c)
 	files, err := client.Update()
 	c.Assert(err, IsNil)
-	assertFiles(c, files, []string{"foo.txt"})
+	assertFiles(c, files, []string{"/foo.txt"})
 
 	s.addRemoteTarget(c, "bar.txt")
 	s.addRemoteTarget(c, "baz.txt")
 
 	files, err = client.Update()
 	c.Assert(err, IsNil)
-	assertFiles(c, files, []string{"bar.txt", "baz.txt"})
+	assertFiles(c, files, []string{"/bar.txt", "/baz.txt"})
 
 	// Adding the same exact file should not lead to an update
 	s.addRemoteTarget(c, "bar.txt")
@@ -766,7 +766,7 @@
 		// check update is ok
 		targets, err := client.Update()
 		c.Assert(err, IsNil)
-		assertFiles(c, targets, []string{"foo.txt", "bar.txt", "baz.txt"})
+		assertFiles(c, targets, []string{"/foo.txt", "/bar.txt", "/baz.txt"})
 
 		// check can download files
 		for name, data := range targetFiles {
@@ -791,15 +791,15 @@
 func (s *ClientSuite) TestDownloadUnknownTarget(c *C) {
 	client := s.updatedClient(c)
 	var dest testDestination
-	c.Assert(client.Download("nonexistent", &dest), Equals, ErrUnknownTarget{"nonexistent"})
+	c.Assert(client.Download("/nonexistent", &dest), Equals, ErrUnknownTarget{"/nonexistent"})
 	c.Assert(dest.deleted, Equals, true)
 }
 
 func (s *ClientSuite) TestDownloadNoExist(c *C) {
 	client := s.updatedClient(c)
-	delete(s.remote.targets, "foo.txt")
+	delete(s.remote.targets, "/foo.txt")
 	var dest testDestination
-	c.Assert(client.Download("foo.txt", &dest), Equals, ErrNotFound{"foo.txt"})
+	c.Assert(client.Download("/foo.txt", &dest), Equals, ErrNotFound{"/foo.txt"})
 	c.Assert(dest.deleted, Equals, true)
 }
 
@@ -817,19 +817,19 @@
 func (s *ClientSuite) TestDownloadWrongSize(c *C) {
 	client := s.updatedClient(c)
 	remoteFile := &fakeFile{buf: bytes.NewReader([]byte("wrong-size")), size: 10}
-	s.remote.targets["foo.txt"] = remoteFile
+	s.remote.targets["/foo.txt"] = remoteFile
 	var dest testDestination
-	c.Assert(client.Download("foo.txt", &dest), DeepEquals, ErrWrongSize{"foo.txt", 10, 3})
+	c.Assert(client.Download("/foo.txt", &dest), DeepEquals, ErrWrongSize{"/foo.txt", 10, 3})
 	c.Assert(remoteFile.bytesRead, Equals, 0)
 	c.Assert(dest.deleted, Equals, true)
 }
 
 func (s *ClientSuite) TestDownloadTargetTooLong(c *C) {
 	client := s.updatedClient(c)
-	remoteFile := s.remote.targets["foo.txt"]
+	remoteFile := s.remote.targets["/foo.txt"]
 	remoteFile.buf = bytes.NewReader([]byte("foo-ooo"))
 	var dest testDestination
-	c.Assert(client.Download("foo.txt", &dest), IsNil)
+	c.Assert(client.Download("/foo.txt", &dest), IsNil)
 	c.Assert(remoteFile.bytesRead, Equals, 3)
 	c.Assert(dest.deleted, Equals, false)
 	c.Assert(dest.String(), Equals, "foo")
@@ -837,19 +837,19 @@
 
 func (s *ClientSuite) TestDownloadTargetTooShort(c *C) {
 	client := s.updatedClient(c)
-	remoteFile := s.remote.targets["foo.txt"]
+	remoteFile := s.remote.targets["/foo.txt"]
 	remoteFile.buf = bytes.NewReader([]byte("fo"))
 	var dest testDestination
-	c.Assert(client.Download("foo.txt", &dest), DeepEquals, ErrWrongSize{"foo.txt", 2, 3})
+	c.Assert(client.Download("/foo.txt", &dest), DeepEquals, ErrWrongSize{"/foo.txt", 2, 3})
 	c.Assert(dest.deleted, Equals, true)
 }
 
 func (s *ClientSuite) TestDownloadTargetCorruptData(c *C) {
 	client := s.updatedClient(c)
-	remoteFile := s.remote.targets["foo.txt"]
+	remoteFile := s.remote.targets["/foo.txt"]
 	remoteFile.buf = bytes.NewReader([]byte("corrupt"))
 	var dest testDestination
-	assertWrongHash(c, client.Download("foo.txt", &dest))
+	assertWrongHash(c, client.Download("/foo.txt", &dest))
 	c.Assert(dest.deleted, Equals, true)
 }
 
@@ -857,7 +857,7 @@
 	client := s.updatedClient(c)
 	files, err := client.Targets()
 	c.Assert(err, IsNil)
-	assertFiles(c, files, []string{"foo.txt"})
+	assertFiles(c, files, []string{"/foo.txt"})
 
 	s.addRemoteTarget(c, "bar.txt")
 	s.addRemoteTarget(c, "baz.txt")
@@ -865,5 +865,5 @@
 	c.Assert(err, IsNil)
 	files, err = client.Targets()
 	c.Assert(err, IsNil)
-	assertFiles(c, files, []string{"foo.txt", "bar.txt", "baz.txt"})
+	assertFiles(c, files, []string{"/foo.txt", "/bar.txt", "/baz.txt"})
 }
diff --git a/repo_test.go b/repo_test.go
index 32c11aa..817eac2 100644
--- a/repo_test.go
+++ b/repo_test.go
@@ -102,7 +102,7 @@
 func (RepoSuite) TestInit(c *C) {
 	local := MemoryStore(
 		make(map[string]json.RawMessage),
-		map[string][]byte{"foo.txt": []byte("foo")},
+		map[string][]byte{"/foo.txt": []byte("foo")},
 	)
 	r, err := NewRepo(local)
 	c.Assert(err, IsNil)
@@ -365,7 +365,7 @@
 }
 
 func (RepoSuite) TestCommit(c *C) {
-	files := map[string][]byte{"foo.txt": []byte("foo"), "bar.txt": []byte("bar")}
+	files := map[string][]byte{"/foo.txt": []byte("foo"), "/bar.txt": []byte("bar")}
 	local := MemoryStore(make(map[string]json.RawMessage), files)
 	r, err := NewRepo(local)
 	c.Assert(err, IsNil)
@@ -405,7 +405,7 @@
 	// commit with an invalid targets hash in snapshot.json
 	c.Assert(r.Snapshot(CompressionTypeNone), IsNil)
 	c.Assert(r.AddTarget("bar.txt", nil), IsNil)
-	c.Assert(r.Commit(), DeepEquals, errors.New("tuf: invalid targets.json in snapshot.json: wrong length, expected 763 got 937"))
+	c.Assert(r.Commit(), DeepEquals, errors.New("tuf: invalid targets.json in snapshot.json: wrong length, expected 764 got 939"))
 
 	// commit with an invalid timestamp
 	c.Assert(r.Snapshot(CompressionTypeNone), IsNil)
@@ -432,7 +432,7 @@
 }
 
 func (RepoSuite) TestCommitVersions(c *C) {
-	files := map[string][]byte{"foo.txt": []byte("foo")}
+	files := map[string][]byte{"/foo.txt": []byte("foo")}
 	local := MemoryStore(make(map[string]json.RawMessage), files)
 	r, err := NewRepo(local)
 	c.Assert(err, IsNil)
@@ -442,7 +442,7 @@
 	genKey(c, r, "snapshot")
 	genKey(c, r, "timestamp")
 
-	c.Assert(r.AddTarget("foo.txt", nil), IsNil)
+	c.Assert(r.AddTarget("/foo.txt", nil), IsNil)
 	c.Assert(r.Snapshot(CompressionTypeNone), IsNil)
 	c.Assert(r.Timestamp(), IsNil)
 	c.Assert(r.Commit(), IsNil)
@@ -623,8 +623,8 @@
 	t, err := r.targets()
 	c.Assert(err, IsNil)
 	c.Assert(t.Targets, HasLen, 1)
-	if _, ok := t.Targets["foo.txt"]; !ok {
-		c.Fatal("missing target file: foo.txt")
+	if _, ok := t.Targets["/foo.txt"]; !ok {
+		c.Fatal("missing target file: /foo.txt")
 	}
 
 	// Snapshot() stages snapshot.json
@@ -772,13 +772,13 @@
 	t, err := newRepo.targets()
 	c.Assert(err, IsNil)
 	c.Assert(t.Targets, HasLen, 1)
-	if _, ok := t.Targets["dir/bar.txt"]; !ok {
+	if _, ok := t.Targets["/dir/bar.txt"]; !ok {
 		c.Fatal("missing targets file: dir/bar.txt")
 	}
 }
 
 func (RepoSuite) TestExpiresAndVersion(c *C) {
-	files := map[string][]byte{"foo.txt": []byte("foo")}
+	files := map[string][]byte{"/foo.txt": []byte("foo")}
 	local := MemoryStore(make(map[string]json.RawMessage), files)
 	r, err := NewRepo(local)
 	c.Assert(err, IsNil)
@@ -893,7 +893,7 @@
 }
 
 func (RepoSuite) TestHashAlgorithm(c *C) {
-	files := map[string][]byte{"foo.txt": []byte("foo")}
+	files := map[string][]byte{"/foo.txt": []byte("foo")}
 	local := MemoryStore(make(map[string]json.RawMessage), files)
 	type hashTest struct {
 		args     []string
@@ -925,7 +925,7 @@
 		timestamp, err := r.timestamp()
 		c.Assert(err, IsNil)
 		for name, file := range map[string]data.FileMeta{
-			"foo.txt":       targets.Targets["foo.txt"].FileMeta,
+			"foo.txt":       targets.Targets["/foo.txt"].FileMeta,
 			"root.json":     snapshot.Meta["root.json"].FileMeta,
 			"targets.json":  snapshot.Meta["targets.json"].FileMeta,
 			"snapshot.json": timestamp.Meta["snapshot.json"].FileMeta,
@@ -1032,7 +1032,7 @@
 	c.Assert(r.Snapshot(CompressionTypeNone), IsNil)
 	c.Assert(r.Timestamp(), IsNil)
 	c.Assert(r.Commit(), IsNil)
-	assertRepoTargets("foo.txt", "bar.txt")
+	assertRepoTargets("/foo.txt", "/bar.txt")
 	tmp.assertExists("repository/targets/foo.txt")
 	tmp.assertExists("repository/targets/bar.txt")
 
@@ -1040,7 +1040,7 @@
 	count := 10
 	files := make([]string, count)
 	for i := 0; i < count; i++ {
-		files[i] = fmt.Sprintf("file%d.txt", i)
+		files[i] = fmt.Sprintf("/file%d.txt", i)
 		tmp.writeStagedTarget(files[i], "data")
 	}
 	c.Assert(r.AddTargets(nil, nil), IsNil)
@@ -1069,9 +1069,9 @@
 
 func (RepoSuite) TestCustomTargetMetadata(c *C) {
 	files := map[string][]byte{
-		"foo.txt": []byte("foo"),
-		"bar.txt": []byte("bar"),
-		"baz.txt": []byte("baz"),
+		"/foo.txt": []byte("foo"),
+		"/bar.txt": []byte("bar"),
+		"/baz.txt": []byte("baz"),
 	}
 	local := MemoryStore(make(map[string]json.RawMessage), files)
 	r, err := NewRepo(local)
@@ -1081,7 +1081,7 @@
 	assertCustomMeta := func(file string, custom *json.RawMessage) {
 		t, err := r.targets()
 		c.Assert(err, IsNil)
-		target, ok := t.Targets[file]
+		target, ok := t.Targets["/"+file]
 		if !ok {
 			c.Fatalf("missing target file: %s", file)
 		}
diff --git a/util/util.go b/util/util.go
index 18f788f..c84a57d 100644
--- a/util/util.go
+++ b/util/util.go
@@ -13,7 +13,6 @@
 	"io/ioutil"
 	"path"
 	"strconv"
-	"strings"
 
 	"github.com/flynn/go-tuf/data"
 )
@@ -236,14 +235,7 @@
 }
 
 func NormalizeTarget(p string) string {
-	// FIXME(TUF-0.9) TUF-1.0 is considering banning paths that begin with
-	// a leading path separator, to avoid surprising behavior when joining
-	// target and delgated paths. python-tuf raises an exception if any
-	// path starts with '/', but since we need to be cross compatible with
-	// TUF-0.9 we still need to support leading slashes. For now, we will
-	// just strip them out, but eventually we should also consider turning
-	// them into an error.
-	return strings.TrimPrefix(path.Join("/", p), "/")
+	return path.Join("/", p)
 }
 
 func VersionedPath(p string, version int) string {
diff --git a/util/util_test.go b/util/util_test.go
index 2f3b593..57e7b75 100644
--- a/util/util_test.go
+++ b/util/util_test.go
@@ -163,12 +163,12 @@
 
 func (UtilSuite) TestNormalizeTarget(c *C) {
 	for before, after := range map[string]string{
-		"":                    "",
-		"foo.txt":             "foo.txt",
-		"/bar.txt":            "bar.txt",
-		"foo//bar.txt":        "foo/bar.txt",
-		"/with/./a/dot":       "with/a/dot",
-		"/with/double/../dot": "with/dot",
+		"":                    "/",
+		"foo.txt":             "/foo.txt",
+		"/bar.txt":            "/bar.txt",
+		"foo//bar.txt":        "/foo/bar.txt",
+		"/with/./a/dot":       "/with/a/dot",
+		"/with/double/../dot": "/with/dot",
 	} {
 		c.Assert(NormalizeTarget(before), Equals, after)
 	}