Merge pull request #81 from flynn/prevent-clean-new-repo

repo: Prevent cleaning a new repository
diff --git a/cmd/tuf/clean.go b/cmd/tuf/clean.go
index 650489e..39f62d0 100644
--- a/cmd/tuf/clean.go
+++ b/cmd/tuf/clean.go
@@ -1,6 +1,9 @@
 package main
 
 import (
+	"fmt"
+	"os"
+
 	"github.com/flynn/go-tuf"
 	"github.com/flynn/go-tuf/Godeps/_workspace/src/github.com/flynn/go-docopt"
 )
@@ -14,5 +17,10 @@
 }
 
 func cmdClean(args *docopt.Args, repo *tuf.Repo) error {
-	return repo.Clean()
+	err := repo.Clean()
+	if err == tuf.ErrNewRepository {
+		fmt.Fprintln(os.Stderr, "tuf: refusing to clean new repository")
+		return nil
+	}
+	return err
 }
diff --git a/errors.go b/errors.go
index 3b11904..c471dc4 100644
--- a/errors.go
+++ b/errors.go
@@ -6,7 +6,10 @@
 	"time"
 )
 
-var ErrInitNotAllowed = errors.New("tuf: repository already initialized")
+var (
+	ErrInitNotAllowed = errors.New("tuf: repository already initialized")
+	ErrNewRepository  = errors.New("tuf: repository not yet committed")
+)
 
 type ErrMissingMetadata struct {
 	Name string
diff --git a/local_store.go b/local_store.go
index 8d7fb1c..c151ef3 100644
--- a/local_store.go
+++ b/local_store.go
@@ -400,6 +400,12 @@
 }
 
 func (f *fileSystemStore) Clean() error {
+	_, err := os.Stat(filepath.Join(f.repoDir(), "root.json"))
+	if os.IsNotExist(err) {
+		return ErrNewRepository
+	} else if err != nil {
+		return err
+	}
 	if err := os.RemoveAll(f.stagedDir()); err != nil {
 		return err
 	}
diff --git a/repo_test.go b/repo_test.go
index e407ab0..af024b7 100644
--- a/repo_test.go
+++ b/repo_test.go
@@ -491,6 +491,9 @@
 	// don't use consistent snapshots to make the checks simpler
 	c.Assert(r.Init(false), IsNil)
 
+	// cleaning with nothing staged or committed should fail
+	c.Assert(r.Clean(), Equals, ErrNewRepository)
+
 	// generating keys should stage root.json and create repo dirs
 	genKey(c, r, "root")
 	genKey(c, r, "targets")
@@ -500,6 +503,9 @@
 	tmp.assertEmpty("repository")
 	tmp.assertEmpty("staged/targets")
 
+	// cleaning with nothing committed should fail
+	c.Assert(r.Clean(), Equals, ErrNewRepository)
+
 	// adding a non-existent file fails
 	c.Assert(r.AddTarget("foo.txt", nil), Equals, ErrFileNotFound{tmp.stagedTargetPath("foo.txt")})
 	tmp.assertEmpty("repository")