Partially Revert "Repo LocalStore should not mix staged and committed metadata"

It turns out I misunderstood the purpose of Repo, it is solely
responsible for creating, staging, and committing staged data.
The actual bug I was fixing was commits create the
versioned/hashed-prefix files, and we weren't committing in
all the places we needed to. By decoupling staged and committed
metadata, it broke the CLI tools from being able to read
metadata in between invocations.

This reverts commit ccf981beeae03896732aad4438d1074b991e9c3b

Test: This adds a test to make sure we can always interact
with staged metadata with new repositories.

Change-Id: I4f8933f2f13385a349441c78c874b388f5ffed96
diff --git a/client/client_test.go b/client/client_test.go
index ef94ab2..86ea025 100644
--- a/client/client_test.go
+++ b/client/client_test.go
@@ -724,7 +724,7 @@
 	targets.Signatures[0].Method = "xxxxxxx"
 	tamperedJSON, err := json.Marshal(targets)
 	c.Assert(err, IsNil)
-	s.store.SetStagedMeta("targets.json", tamperedJSON)
+	s.store.SetMeta("targets.json", tamperedJSON)
 	s.store.Commit(false, nil, nil)
 	s.syncRemote(c)
 	_, err = client.Update()
@@ -734,7 +734,7 @@
 	targets.Signatures[0].Method = "xxx"
 	tamperedJSON, err = json.Marshal(targets)
 	c.Assert(err, IsNil)
-	s.store.SetStagedMeta("targets.json", tamperedJSON)
+	s.store.SetMeta("targets.json", tamperedJSON)
 	s.store.Commit(false, nil, nil)
 	s.syncRemote(c)
 	_, err = client.Update()
diff --git a/local_store.go b/local_store.go
index 68cb609..34293be 100644
--- a/local_store.go
+++ b/local_store.go
@@ -35,14 +35,17 @@
 }
 
 func (m *memoryStore) GetMeta() (map[string]json.RawMessage, error) {
-	return m.meta, nil
+	meta := make(map[string]json.RawMessage, len(m.meta)+len(m.stagedMeta))
+	for key, value := range m.meta {
+		meta[key] = value
+	}
+	for key, value := range m.stagedMeta {
+		meta[key] = value
+	}
+	return meta, nil
 }
 
-func (m *memoryStore) GetStagedMeta() (map[string]json.RawMessage, error) {
-	return m.stagedMeta, nil
-}
-
-func (m *memoryStore) SetStagedMeta(name string, meta json.RawMessage) error {
+func (m *memoryStore) SetMeta(name string, meta json.RawMessage) error {
 	m.stagedMeta[name] = meta
 	return nil
 }
@@ -144,26 +147,17 @@
 func (f *fileSystemStore) GetMeta() (map[string]json.RawMessage, error) {
 	meta := make(map[string]json.RawMessage)
 	var err error
-	for _, name := range topLevelManifests {
-		path := filepath.Join(f.repoDir(), name)
-		if _, err := os.Stat(path); os.IsNotExist(err) {
-			continue
-		}
-		meta[name], err = ioutil.ReadFile(path)
-		if err != nil {
-			return nil, err
-		}
+	notExists := func(path string) bool {
+		_, err := os.Stat(path)
+		return os.IsNotExist(err)
 	}
-	return meta, nil
-}
-
-func (f *fileSystemStore) GetStagedMeta() (map[string]json.RawMessage, error) {
-	meta := make(map[string]json.RawMessage)
-	var err error
 	for _, name := range topLevelManifests {
 		path := filepath.Join(f.stagedDir(), name)
-		if _, err := os.Stat(path); os.IsNotExist(err) {
-			continue
+		if notExists(path) {
+			path = filepath.Join(f.repoDir(), name)
+			if notExists(path) {
+				continue
+			}
 		}
 		meta[name], err = ioutil.ReadFile(path)
 		if err != nil {
@@ -173,7 +167,7 @@
 	return meta, nil
 }
 
-func (f *fileSystemStore) SetStagedMeta(name string, meta json.RawMessage) error {
+func (f *fileSystemStore) SetMeta(name string, meta json.RawMessage) error {
 	if err := f.createDirs(); err != nil {
 		return err
 	}
diff --git a/repo.go b/repo.go
index 58069e7..6b507f1 100644
--- a/repo.go
+++ b/repo.go
@@ -39,8 +39,7 @@
 
 type LocalStore interface {
 	GetMeta() (map[string]json.RawMessage, error)
-	GetStagedMeta() (map[string]json.RawMessage, error)
-	SetStagedMeta(string, json.RawMessage) error
+	SetMeta(string, json.RawMessage) error
 
 	// WalkStagedTargets calls targetsFn for each staged target file in paths.
 	//
@@ -397,7 +396,7 @@
 		return err
 	}
 	r.meta[name] = b
-	return r.local.SetStagedMeta(name, b)
+	return r.local.SetMeta(name, b)
 }
 
 func (r *Repo) Sign(name string) error {
@@ -427,7 +426,7 @@
 		return err
 	}
 	r.meta[name] = b
-	return r.local.SetStagedMeta(name, b)
+	return r.local.SetMeta(name, b)
 }
 
 // getSigningKeys returns available signing keys.
diff --git a/repo_test.go b/repo_test.go
index 339d8f0..b506ebc 100644
--- a/repo_test.go
+++ b/repo_test.go
@@ -241,7 +241,7 @@
 	}
 
 	// check root.json got staged
-	meta, err := local.GetStagedMeta()
+	meta, err := local.GetMeta()
 	c.Assert(err, IsNil)
 	rootJSON, ok := meta["root.json"]
 	if !ok {
@@ -331,6 +331,8 @@
 	c.Assert(r.Sign("root.json"), Equals, ErrInsufficientKeys{"root.json"})
 
 	checkSigIDs := func(keyIDs ...string) {
+		meta, err := local.GetMeta()
+		c.Assert(err, IsNil)
 		rootJSON, ok := meta["root.json"]
 		if !ok {
 			c.Fatal("missing root.json")
@@ -669,6 +671,28 @@
 	tmp.assertEmpty("staged")
 }
 
+func (RepoSuite) TestCommitFileSystemWithNewRepositories(c *C) {
+	tmp := newTmpDir(c)
+
+	newRepo := func() *Repo {
+		local := FileSystemStore(tmp.path, nil)
+		r, err := NewRepo(local)
+		c.Assert(err, IsNil)
+		return r
+	}
+
+	genKey(c, newRepo(), "root")
+	genKey(c, newRepo(), "targets")
+	genKey(c, newRepo(), "snapshot")
+	genKey(c, newRepo(), "timestamp")
+
+	tmp.writeStagedTarget("foo.txt", "foo")
+	c.Assert(newRepo().AddTarget("foo.txt", nil), IsNil)
+	c.Assert(newRepo().Snapshot(CompressionTypeNone), IsNil)
+	c.Assert(newRepo().Timestamp(), IsNil)
+	c.Assert(newRepo().Commit(), IsNil)
+}
+
 func (RepoSuite) TestConsistentSnapshot(c *C) {
 	tmp := newTmpDir(c)
 	local := FileSystemStore(tmp.path, nil)