Repo LocalStore should not mix staged and committed metadata

The Repo struct is responsible for updating TUF metadata on
the local system. It implements a staging model, where multiple
metadata changes can be staged before comitting to the actual
repository. This is to support the ability to use keys on isolated
machines to sign the metadata.

Unfortunately the LocalStore implementation mixed together the
GetMeta method to return both committed and staged metadata,
which resulted in tests getting confused about treating staged
metadata as being committed, without actually committing the
metadata. This patch changes this behavior in order to have
separate APIs to read staged metadata when it is actually needed.

Change-Id: Ic443f5b90963158fa569d2a40479f59cd7eea11a
diff --git a/client/client_test.go b/client/client_test.go
index 4cc4906..0f786b9 100644
--- a/client/client_test.go
+++ b/client/client_test.go
@@ -696,7 +696,8 @@
 	targets.Signatures[0].Method = "xxxxxxx"
 	tamperedJSON, err := json.Marshal(targets)
 	c.Assert(err, IsNil)
-	s.store.SetMeta("targets.json", tamperedJSON)
+	s.store.SetStagedMeta("targets.json", tamperedJSON)
+	s.store.Commit(true, nil)
 	s.syncRemote(c)
 	_, err = client.Update()
 	assertWrongHash(c, err)
@@ -705,7 +706,8 @@
 	targets.Signatures[0].Method = "xxx"
 	tamperedJSON, err = json.Marshal(targets)
 	c.Assert(err, IsNil)
-	s.store.SetMeta("targets.json", tamperedJSON)
+	s.store.SetStagedMeta("targets.json", tamperedJSON)
+	s.store.Commit(true, nil)
 	s.syncRemote(c)
 	_, err = client.Update()
 	c.Assert(err, DeepEquals, ErrWrongSize{"targets.json", int64(len(tamperedJSON)), int64(len(targetsJSON))})
diff --git a/local_store.go b/local_store.go
index ede2946..c018a76 100644
--- a/local_store.go
+++ b/local_store.go
@@ -20,24 +20,30 @@
 		meta = make(map[string]json.RawMessage)
 	}
 	return &memoryStore{
-		meta:    meta,
-		files:   files,
-		signers: make(map[string][]sign.Signer),
+		meta:       meta,
+		stagedMeta: make(map[string]json.RawMessage),
+		files:      files,
+		signers:    make(map[string][]sign.Signer),
 	}
 }
 
 type memoryStore struct {
-	meta    map[string]json.RawMessage
-	files   map[string][]byte
-	signers map[string][]sign.Signer
+	meta       map[string]json.RawMessage
+	stagedMeta map[string]json.RawMessage
+	files      map[string][]byte
+	signers    map[string][]sign.Signer
 }
 
 func (m *memoryStore) GetMeta() (map[string]json.RawMessage, error) {
 	return m.meta, nil
 }
 
-func (m *memoryStore) SetMeta(name string, meta json.RawMessage) error {
-	m.meta[name] = meta
+func (m *memoryStore) GetStagedMeta() (map[string]json.RawMessage, error) {
+	return m.stagedMeta, nil
+}
+
+func (m *memoryStore) SetStagedMeta(name string, meta json.RawMessage) error {
+	m.stagedMeta[name] = meta
 	return nil
 }
 
@@ -64,6 +70,9 @@
 }
 
 func (m *memoryStore) Commit(bool, map[string]data.Hashes) error {
+	for name, meta := range m.stagedMeta {
+		m.meta[name] = meta
+	}
 	return nil
 }
 
@@ -112,17 +121,10 @@
 func (f *fileSystemStore) GetMeta() (map[string]json.RawMessage, error) {
 	meta := make(map[string]json.RawMessage)
 	var err error
-	notExists := func(path string) bool {
-		_, err := os.Stat(path)
-		return os.IsNotExist(err)
-	}
 	for _, name := range topLevelManifests {
-		path := filepath.Join(f.stagedDir(), name)
-		if notExists(path) {
-			path = filepath.Join(f.repoDir(), name)
-			if notExists(path) {
-				continue
-			}
+		path := filepath.Join(f.repoDir(), name)
+		if _, err := os.Stat(path); os.IsNotExist(err) {
+			continue
 		}
 		meta[name], err = ioutil.ReadFile(path)
 		if err != nil {
@@ -132,7 +134,23 @@
 	return meta, nil
 }
 
-func (f *fileSystemStore) SetMeta(name string, meta json.RawMessage) error {
+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.repoDir(), name)
+		if _, err := os.Stat(path); os.IsNotExist(err) {
+			continue
+		}
+		meta[name], err = ioutil.ReadFile(path)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return meta, nil
+}
+
+func (f *fileSystemStore) SetStagedMeta(name string, meta json.RawMessage) error {
 	if err := f.createDirs(); err != nil {
 		return err
 	}
diff --git a/repo.go b/repo.go
index dc1ee26..01416a2 100644
--- a/repo.go
+++ b/repo.go
@@ -39,7 +39,8 @@
 
 type LocalStore interface {
 	GetMeta() (map[string]json.RawMessage, error)
-	SetMeta(string, json.RawMessage) error
+	GetStagedMeta() (map[string]json.RawMessage, error)
+	SetStagedMeta(string, json.RawMessage) error
 
 	// WalkStagedTargets calls targetsFn for each staged target file in paths.
 	//
@@ -376,7 +377,7 @@
 		return err
 	}
 	r.meta[name] = b
-	return r.local.SetMeta(name, b)
+	return r.local.SetStagedMeta(name, b)
 }
 
 func (r *Repo) Sign(name string) error {
@@ -406,7 +407,7 @@
 		return err
 	}
 	r.meta[name] = b
-	return r.local.SetMeta(name, b)
+	return r.local.SetStagedMeta(name, b)
 }
 
 // getSigningKeys returns available signing keys.
diff --git a/repo_test.go b/repo_test.go
index 346121a..f4628b2 100644
--- a/repo_test.go
+++ b/repo_test.go
@@ -234,7 +234,7 @@
 	}
 
 	// check root.json got staged
-	meta, err := local.GetMeta()
+	meta, err := local.GetStagedMeta()
 	c.Assert(err, IsNil)
 	rootJSON, ok := meta["root.json"]
 	if !ok {