Skip to content

Commit eac0a85

Browse files
authored
Improve CLI experience by avoiding version gaps (#204)
* improve CLI experience by avoiding version gaps Signed-off-by: Asra Ali <[email protected]> * fix init Signed-off-by: Asra Ali <[email protected]> * regenerate Signed-off-by: Asra Ali <[email protected]> * Address comments Signed-off-by: Asra Ali <[email protected]>
1 parent ab254c0 commit eac0a85

File tree

3 files changed

+32
-26
lines changed

3 files changed

+32
-26
lines changed

local_store.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ func (m *memoryStore) SetMeta(name string, meta json.RawMessage) error {
6363
return nil
6464
}
6565

66+
func (m *memoryStore) FileIsStaged(name string) bool {
67+
_, ok := m.stagedMeta[name]
68+
return ok
69+
}
70+
6671
func (m *memoryStore) WalkStagedTargets(paths []string, targetsFn TargetsWalkFunc) error {
6772
if len(paths) == 0 {
6873
for path, data := range m.files {
@@ -91,6 +96,10 @@ func (m *memoryStore) Commit(consistentSnapshot bool, versions map[string]int, h
9196
for _, path := range paths {
9297
m.meta[path] = meta
9398
}
99+
// Remove from staged metadata.
100+
// This will prompt incrementing version numbers again now that we've
101+
// successfully committed the metadata to the local store.
102+
delete(m.stagedMeta, name)
94103
}
95104
return nil
96105
}
@@ -170,6 +179,11 @@ func (f *fileSystemStore) SetMeta(name string, meta json.RawMessage) error {
170179
return nil
171180
}
172181

182+
func (f *fileSystemStore) FileIsStaged(name string) bool {
183+
_, err := os.Stat(filepath.Join(f.stagedDir(), name))
184+
return err == nil
185+
}
186+
173187
func (f *fileSystemStore) createDirs() error {
174188
for _, dir := range []string{"keys", "repository", "staged/targets"} {
175189
if err := os.MkdirAll(filepath.Join(f.dir, dir), 0755); err != nil {

repo.go

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,15 @@ type LocalStore interface {
5050
// If paths is empty, all staged target files will be walked.
5151
WalkStagedTargets(paths []string, targetsFn TargetsWalkFunc) error
5252

53+
// FileIsStaged determines if a metadata file is currently staged, to avoid incrementing
54+
// version numbers repeatedly while staged.
55+
FileIsStaged(filename string) bool
56+
5357
// Commit is used to publish staged files to the repository
58+
//
59+
// This will also reset the staged meta to signal incrementing version numbers.
60+
// TUF 1.0 requires that the root metadata version numbers in the repository does not
61+
// gaps. To avoid this, we will only increment the number once until we commit.
5462
Commit(bool, map[string]int, map[string]data.Hashes) error
5563

5664
// GetSigners return a list of signers for a role.
@@ -74,11 +82,6 @@ type Repo struct {
7482
meta map[string]json.RawMessage
7583
prefix string
7684
indent string
77-
78-
// TUF 1.0 requires that the root metadata version numbers in the
79-
// repository does not have any gaps. To avoid this, we will only
80-
// increment the number once until we commit.
81-
versionUpdated map[string]struct{}
8285
}
8386

8487
func NewRepo(local LocalStore, hashAlgorithms ...string) (*Repo, error) {
@@ -91,7 +94,6 @@ func NewRepoIndent(local LocalStore, prefix string, indent string, hashAlgorithm
9194
hashAlgorithms: hashAlgorithms,
9295
prefix: prefix,
9396
indent: indent,
94-
versionUpdated: make(map[string]struct{}),
9597
}
9698

9799
var err error
@@ -112,6 +114,8 @@ func (r *Repo) Init(consistentSnapshot bool) error {
112114
}
113115
root := data.NewRoot()
114116
root.ConsistentSnapshot = consistentSnapshot
117+
// Set root version to 1 for a new root.
118+
root.Version = 1
115119
err = r.setTopLevelMeta("root.json", root)
116120
if err == nil {
117121
fmt.Println("Repository initialized")
@@ -218,9 +222,8 @@ func (r *Repo) SetThreshold(keyRole string, t int) error {
218222
return nil
219223
}
220224
role.Threshold = t
221-
if _, ok := r.versionUpdated["root.json"]; !ok {
225+
if !r.local.FileIsStaged("root.json") {
222226
root.Version++
223-
r.versionUpdated["root.json"] = struct{}{}
224227
}
225228
return r.setTopLevelMeta("root.json", root)
226229
}
@@ -256,7 +259,6 @@ func (r *Repo) SetTimestampVersion(v int) error {
256259
return err
257260
}
258261
ts.Version = v
259-
r.versionUpdated["timestamp.json"] = struct{}{}
260262
return r.setTopLevelMeta("timestamp.json", ts)
261263
}
262264

@@ -275,7 +277,6 @@ func (r *Repo) SetSnapshotVersion(v int) error {
275277
}
276278

277279
s.Version = v
278-
r.versionUpdated["snapshot.json"] = struct{}{}
279280
return r.setTopLevelMeta("snapshot.json", s)
280281
}
281282

@@ -401,9 +402,8 @@ func (r *Repo) AddVerificationKeyWithExpiration(keyRole string, pk *data.PublicK
401402
}
402403

403404
root.Expires = expires.Round(time.Second)
404-
if _, ok := r.versionUpdated["root.json"]; !ok {
405+
if !r.local.FileIsStaged("root.json") {
405406
root.Version++
406-
r.versionUpdated["root.json"] = struct{}{}
407407
}
408408

409409
return r.setTopLevelMeta("root.json", root)
@@ -507,9 +507,8 @@ func (r *Repo) RevokeKeyWithExpires(keyRole, id string, expires time.Time) error
507507
}
508508
}
509509
root.Expires = expires.Round(time.Second)
510-
if _, ok := r.versionUpdated["root.json"]; !ok {
510+
if !r.local.FileIsStaged("root.json") {
511511
root.Version++
512-
r.versionUpdated["root.json"] = struct{}{}
513512
}
514513

515514
err = r.setTopLevelMeta("root.json", root)
@@ -744,9 +743,8 @@ func (r *Repo) AddTargetsWithExpires(paths []string, custom json.RawMessage, exp
744743
return err
745744
}
746745
t.Expires = expires.Round(time.Second)
747-
if _, ok := r.versionUpdated["targets.json"]; !ok {
746+
if !r.local.FileIsStaged("targets.json") {
748747
t.Version++
749-
r.versionUpdated["targets.json"] = struct{}{}
750748
}
751749

752750
err = r.setTopLevelMeta("targets.json", t)
@@ -806,9 +804,8 @@ func (r *Repo) RemoveTargetsWithExpires(paths []string, expires time.Time) error
806804
}
807805
}
808806
t.Expires = expires.Round(time.Second)
809-
if _, ok := r.versionUpdated["targets.json"]; !ok {
807+
if !r.local.FileIsStaged("targets.json") {
810808
t.Version++
811-
r.versionUpdated["targets.json"] = struct{}{}
812809
}
813810

814811
err = r.setTopLevelMeta("targets.json", t)
@@ -858,9 +855,8 @@ func (r *Repo) SnapshotWithExpires(expires time.Time) error {
858855
}
859856
}
860857
snapshot.Expires = expires.Round(time.Second)
861-
if _, ok := r.versionUpdated["snapshot.json"]; !ok {
858+
if !r.local.FileIsStaged("snapshot.json") {
862859
snapshot.Version++
863-
r.versionUpdated["snapshot.json"] = struct{}{}
864860
}
865861
err = r.setTopLevelMeta("snapshot.json", snapshot)
866862
if err == nil {
@@ -894,9 +890,8 @@ func (r *Repo) TimestampWithExpires(expires time.Time) error {
894890
return err
895891
}
896892
timestamp.Expires = expires.Round(time.Second)
897-
if _, ok := r.versionUpdated["timestamp.json"]; !ok {
893+
if !r.local.FileIsStaged("timestamp.json") {
898894
timestamp.Version++
899-
r.versionUpdated["timestamp.json"] = struct{}{}
900895
}
901896

902897
err = r.setTopLevelMeta("timestamp.json", timestamp)
@@ -1028,9 +1023,6 @@ func (r *Repo) Commit() error {
10281023

10291024
err = r.local.Commit(root.ConsistentSnapshot, versions, hashes)
10301025
if err == nil {
1031-
// We can start incrementing version numbers again now that we've
1032-
// successfully committed the metadata to the local store.
1033-
r.versionUpdated = make(map[string]struct{})
10341026
fmt.Println("Committed successfully")
10351027
}
10361028
return err

repo_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ func (rs *RepoSuite) TestAddPrivateKey(c *C) {
499499
newRoot, err := r.root()
500500
c.Assert(err, IsNil)
501501
c.Assert(oldRoot, DeepEquals, newRoot)
502-
if _, ok := r.versionUpdated["root.json"]; ok {
502+
if r.local.FileIsStaged("root.json") {
503503
c.Fatal("root should not be marked dirty")
504504
}
505505
}

0 commit comments

Comments
 (0)