Merge "jiri: Allow deletion+creation of projects with the same path during update."
diff --git a/cl.go b/cl.go
index f5dc422..9460338 100644
--- a/cl.go
+++ b/cl.go
@@ -16,6 +16,7 @@
 	"v.io/jiri/gitutil"
 	"v.io/jiri/jiri"
 	"v.io/jiri/project"
+	"v.io/jiri/runutil"
 	"v.io/jiri/tool"
 	"v.io/x/lib/cmdline"
 )
@@ -97,10 +98,10 @@
 	if err != nil {
 		return nil, err
 	}
-	data, err := jirix.Run().ReadFile(file)
+	data, err := jirix.NewSeq().ReadFile(file)
 	var branches []string
 	if err != nil {
-		if !os.IsNotExist(err) {
+		if !runutil.IsNotExist(err) {
 			return nil, err
 		}
 		if branch != remoteBranchFlag {
@@ -163,9 +164,10 @@
 	if err := jirix.Git().FetchRefspec("origin", remoteBranchFlag); err != nil {
 		return err
 	}
+	s := jirix.NewSeq()
 	for _, branch := range branches {
 		cleanupFn := func() error { return cleanupBranch(jirix, branch) }
-		if err := jirix.Run().Function(cleanupFn, "Cleaning up branch %q", branch); err != nil {
+		if err := s.Call(cleanupFn, "Cleaning up branch %q", branch).Done(); err != nil {
 			return err
 		}
 		if branch == originalBranch {
@@ -209,12 +211,11 @@
 	if err != nil {
 		return err
 	}
-	metadataDir := filepath.Join(topLevel, jiri.ProjectMetaDir)
-	if err := jirix.Run().RemoveAll(filepath.Join(metadataDir, branch)); err != nil {
-		return err
-	}
+	s := jirix.NewSeq()
 	// Remove the branch from all dependency paths.
-	fileInfos, err := jirix.Run().ReadDir(metadataDir)
+	metadataDir := filepath.Join(topLevel, jiri.ProjectMetaDir)
+	fileInfos, err := s.RemoveAll(filepath.Join(metadataDir, branch)).
+		ReadDir(metadataDir)
 	if err != nil {
 		return err
 	}
@@ -226,9 +227,9 @@
 		if err != nil {
 			return err
 		}
-		data, err := jirix.Run().ReadFile(file)
+		data, err := s.ReadFile(file)
 		if err != nil {
-			if !os.IsNotExist(err) {
+			if !runutil.IsNotExist(err) {
 				return err
 			}
 			continue
@@ -237,7 +238,7 @@
 		for i, tmpBranch := range branches {
 			if branch == tmpBranch {
 				data := []byte(strings.Join(append(branches[:i], branches[i+1:]...), "\n"))
-				if err := jirix.Run().WriteFile(file, data, os.FileMode(0644)); err != nil {
+				if err := s.WriteFile(file, data, os.FileMode(0644)).Done(); err != nil {
 					return err
 				}
 				break
@@ -406,8 +407,8 @@
 		if err != nil {
 			return err
 		}
-		if _, err := jirix.Run().Stat(file); err != nil {
-			if !os.IsNotExist(err) {
+		if _, err := jirix.NewSeq().Stat(file); err != nil {
+			if !runutil.IsNotExist(err) {
 				return err
 			}
 			return fmt.Errorf(`Failed to export the branch %q to Gerrit because its ancestor %q has not been exported to Gerrit yet.
@@ -483,9 +484,9 @@
 	if err != nil {
 		return false, err
 	}
-	bytes, err := review.jirix.Run().ReadFile(file)
+	bytes, err := review.jirix.NewSeq().ReadFile(file)
 	if err != nil {
-		if os.IsNotExist(err) {
+		if runutil.IsNotExist(err) {
 			return true, nil
 		}
 		return false, err
@@ -653,7 +654,7 @@
 			if err != nil {
 				return err
 			}
-			message, err := review.jirix.Run().ReadFile(file)
+			message, err := review.jirix.NewSeq().ReadFile(file)
 			if err != nil {
 				return err
 			}
@@ -763,12 +764,13 @@
 	if err != nil {
 		return fmt.Errorf("Getwd() failed: %v", err)
 	}
-	defer collect.Error(func() error { return review.jirix.Run().Chdir(wd) }, &e)
+	defer collect.Error(func() error { return review.jirix.NewSeq().Chdir(wd).Done() }, &e)
 	topLevel, err := review.jirix.Git().TopLevel()
 	if err != nil {
 		return err
 	}
-	if err := review.jirix.Run().Chdir(topLevel); err != nil {
+	s := review.jirix.NewSeq()
+	if err := s.Chdir(topLevel).Done(); err != nil {
 		return err
 	}
 	defer collect.Error(func() error { return review.cleanup(stashed) }, &e)
@@ -779,9 +781,9 @@
 	message := messageFlag
 	if message == "" {
 		// Message was not passed in flag.  Attempt to read it from file.
-		data, err := review.jirix.Run().ReadFile(file)
+		data, err := s.ReadFile(file)
 		if err != nil {
-			if !os.IsNotExist(err) {
+			if !runutil.IsNotExist(err) {
 				return err
 			}
 		} else {
@@ -835,7 +837,7 @@
 	if err != nil {
 		return "", err
 	}
-	bytes, err := review.jirix.Run().ReadFile(file)
+	bytes, err := review.jirix.NewSeq().ReadFile(file)
 	if err != nil {
 		return "", err
 	}
@@ -868,13 +870,14 @@
 	if err != nil {
 		return err
 	}
+	s := review.jirix.NewSeq()
 	// For the initial commit where the commit message file doesn't exist,
 	// add/remove labels after users finish editing the commit message.
 	//
 	// This behavior is consistent with how Change-ID is added for the
 	// initial commit so we don't confuse users.
-	if _, err := review.jirix.Run().Stat(file); err != nil {
-		if os.IsNotExist(err) {
+	if _, err := s.Stat(file); err != nil {
+		if runutil.IsNotExist(err) {
 			newMessage = review.processLabels(newMessage)
 			if err := review.jirix.Git().CommitAmendWithMessage(newMessage); err != nil {
 				return err
@@ -888,10 +891,8 @@
 		return err
 	}
 	newMetadataDir := filepath.Join(topLevel, jiri.ProjectMetaDir, review.CLOpts.Branch)
-	if err := review.jirix.Run().MkdirAll(newMetadataDir, os.FileMode(0755)); err != nil {
-		return err
-	}
-	if err := review.jirix.Run().WriteFile(file, []byte(newMessage), 0644); err != nil {
+	if err := s.MkdirAll(newMetadataDir, os.FileMode(0755)).
+		WriteFile(file, []byte(newMessage), 0644).Done(); err != nil {
 		return err
 	}
 	return nil
@@ -946,6 +947,7 @@
 		}
 	}()
 
+	s := jirix.NewSeq()
 	// Record the dependent CLs for the new branch. The dependent CLs
 	// are recorded in a <dependencyPathFileName> file as a
 	// newline-separated list of branch names.
@@ -955,14 +957,14 @@
 	}
 	branches = append(branches, originalBranch)
 	newMetadataDir := filepath.Join(topLevel, jiri.ProjectMetaDir, newBranch)
-	if err := jirix.Run().MkdirAll(newMetadataDir, os.FileMode(0755)); err != nil {
+	if err := s.MkdirAll(newMetadataDir, os.FileMode(0755)).Done(); err != nil {
 		return err
 	}
 	file, err := getDependencyPathFileName(jirix, newBranch)
 	if err != nil {
 		return err
 	}
-	if err := jirix.Run().WriteFile(file, []byte(strings.Join(branches, "\n")), os.FileMode(0644)); err != nil {
+	if err := s.WriteFile(file, []byte(strings.Join(branches, "\n")), os.FileMode(0644)).Done(); err != nil {
 		return err
 	}
 
@@ -1020,15 +1022,16 @@
 		if forceOriginalBranch {
 			jirix.Git().CheckoutBranch(originalBranch, gitutil.ForceOpt(true))
 		}
-		jirix.Run().Chdir(originalWd)
+		jirix.NewSeq().Chdir(originalWd)
 	}()
 
+	s := jirix.NewSeq()
 	// Switch to an existing directory in master so we can run commands.
 	topLevel, err := jirix.Git().TopLevel()
 	if err != nil {
 		return err
 	}
-	if err := jirix.Run().Chdir(topLevel); err != nil {
+	if err := s.Chdir(topLevel).Done(); err != nil {
 		return err
 	}
 
diff --git a/cl_test.go b/cl_test.go
index 19f3674..327767b 100644
--- a/cl_test.go
+++ b/cl_test.go
@@ -17,6 +17,7 @@
 	"v.io/jiri/gitutil"
 	"v.io/jiri/jiri"
 	"v.io/jiri/jiritest"
+	"v.io/jiri/runutil"
 )
 
 // assertCommitCount asserts that the commit count between two
@@ -34,7 +35,7 @@
 // assertFileContent asserts that the content of the given file
 // matches the expected content.
 func assertFileContent(t *testing.T, jirix *jiri.X, file, want string) {
-	got, err := jirix.Run().ReadFile(file)
+	got, err := jirix.NewSeq().ReadFile(file)
 	if err != nil {
 		t.Fatalf("%v\n", err)
 	}
@@ -45,9 +46,10 @@
 
 // assertFilesExist asserts that the files exist.
 func assertFilesExist(t *testing.T, jirix *jiri.X, files []string) {
+	s := jirix.NewSeq()
 	for _, file := range files {
-		if _, err := jirix.Run().Stat(file); err != nil {
-			if os.IsNotExist(err) {
+		if _, err := s.Stat(file); err != nil {
+			if runutil.IsNotExist(err) {
 				t.Fatalf("expected file %v to exist but it did not", file)
 			}
 			t.Fatalf("%v", err)
@@ -57,8 +59,9 @@
 
 // assertFilesDoNotExist asserts that the files do not exist.
 func assertFilesDoNotExist(t *testing.T, jirix *jiri.X, files []string) {
+	s := jirix.NewSeq()
 	for _, file := range files {
-		if _, err := jirix.Run().Stat(file); err != nil && !os.IsNotExist(err) {
+		if _, err := s.Stat(file); err != nil && !runutil.IsNotExist(err) {
 			t.Fatalf("%v", err)
 		} else if err == nil {
 			t.Fatalf("expected file %v to not exist but it did", file)
@@ -114,7 +117,8 @@
 
 // commitFile commits a file with the specified content into a branch
 func commitFile(t *testing.T, jirix *jiri.X, filename string, content string) {
-	if err := jirix.Run().WriteFile(filename, []byte(content), 0644); err != nil {
+	s := jirix.NewSeq()
+	if err := s.WriteFile(filename, []byte(content), 0644).Done(); err != nil {
 		t.Fatalf("%v", err)
 	}
 	commitMessage := "Commit " + filename
@@ -134,7 +138,8 @@
 
 // createRepo creates a new repository with the given prefix.
 func createRepo(t *testing.T, jirix *jiri.X, prefix string) string {
-	repoPath, err := jirix.Run().TempDir(jirix.Root, "repo-"+prefix)
+	s := jirix.NewSeq()
+	repoPath, err := s.TempDir(jirix.Root, "repo-"+prefix)
 	if err != nil {
 		t.Fatalf("TempDir() failed: %v", err)
 	}
@@ -144,7 +149,7 @@
 	if err := jirix.Git().Init(repoPath); err != nil {
 		t.Fatalf("%v", err)
 	}
-	if err := jirix.Run().MkdirAll(filepath.Join(repoPath, jiri.ProjectMetaDir), os.FileMode(0755)); err != nil {
+	if err := s.MkdirAll(filepath.Join(repoPath, jiri.ProjectMetaDir), os.FileMode(0755)).Done(); err != nil {
 		t.Fatalf("%v", err)
 	}
 	return repoPath
@@ -159,14 +164,14 @@
 // installCommitMsgHook links the gerrit commit-msg hook into a different repo.
 func installCommitMsgHook(t *testing.T, jirix *jiri.X, repoPath string) {
 	hookLocation := path.Join(repoPath, ".git/hooks/commit-msg")
-	if err := jirix.Run().WriteFile(hookLocation, []byte(commitMsgHook), 0755); err != nil {
+	if err := jirix.NewSeq().WriteFile(hookLocation, []byte(commitMsgHook), 0755).Done(); err != nil {
 		t.Fatalf("WriteFile(%v) failed: %v", hookLocation, err)
 	}
 }
 
 // chdir changes the runtime working directory and traps any errors.
 func chdir(t *testing.T, jirix *jiri.X, path string) {
-	if err := jirix.Run().Chdir(path); err != nil {
+	if err := jirix.NewSeq().Chdir(path).Done(); err != nil {
 		_, file, line, _ := runtime.Caller(1)
 		t.Fatalf("%s: %d: Chdir(%v) failed: %v", file, line, path, err)
 	}
@@ -489,6 +494,7 @@
 func TestLabelsInCommitMessage(t *testing.T) {
 	fake, repoPath, _, gerritPath, cleanup := setupTest(t, true)
 	defer cleanup()
+	s := fake.X.NewSeq()
 	branch := "my-branch"
 	if err := fake.X.Git().CreateAndCheckoutBranch(branch); err != nil {
 		t.Fatalf("%v", err)
@@ -520,7 +526,7 @@
 	if err != nil {
 		t.Fatalf("%v", err)
 	}
-	bytes, err := fake.X.Run().ReadFile(file)
+	bytes, err := s.ReadFile(file)
 	if err != nil {
 		t.Fatalf("%v\n", err)
 	}
@@ -553,7 +559,7 @@
 	}
 	expectedRef = gerrit.Reference(review.CLOpts)
 	assertFilesPushedToRef(t, fake.X, repoPath, gerritPath, expectedRef, files)
-	bytes, err = fake.X.Run().ReadFile(file)
+	bytes, err = s.ReadFile(file)
 	if err != nil {
 		t.Fatalf("%v\n", err)
 	}
@@ -581,7 +587,7 @@
 	}
 	expectedRef = gerrit.Reference(review.CLOpts)
 	assertFilesPushedToRef(t, fake.X, repoPath, gerritPath, expectedRef, files)
-	bytes, err = fake.X.Run().ReadFile(file)
+	bytes, err = s.ReadFile(file)
 	if err != nil {
 		t.Fatalf("%v\n", err)
 	}
@@ -598,6 +604,7 @@
 func TestDirtyBranch(t *testing.T) {
 	fake, _, _, gerritPath, cleanup := setupTest(t, true)
 	defer cleanup()
+	s := fake.X.NewSeq()
 	branch := "my-branch"
 	if err := fake.X.Git().CreateAndCheckoutBranch(branch); err != nil {
 		t.Fatalf("%v", err)
@@ -606,7 +613,7 @@
 	commitFiles(t, fake.X, files)
 	assertStashSize(t, fake.X, 0)
 	stashedFile, stashedFileContent := "stashed-file", "stashed-file content"
-	if err := fake.X.Run().WriteFile(stashedFile, []byte(stashedFileContent), 0644); err != nil {
+	if err := s.WriteFile(stashedFile, []byte(stashedFileContent), 0644).Done(); err != nil {
 		t.Fatalf("WriteFile(%v, %v) failed: %v", stashedFile, stashedFileContent, err)
 	}
 	if err := fake.X.Git().Add(stashedFile); err != nil {
@@ -617,18 +624,18 @@
 	}
 	assertStashSize(t, fake.X, 1)
 	modifiedFile, modifiedFileContent := "file1", "modified-file content"
-	if err := fake.X.Run().WriteFile(modifiedFile, []byte(modifiedFileContent), 0644); err != nil {
+	if err := s.WriteFile(modifiedFile, []byte(modifiedFileContent), 0644).Done(); err != nil {
 		t.Fatalf("WriteFile(%v, %v) failed: %v", modifiedFile, modifiedFileContent, err)
 	}
 	stagedFile, stagedFileContent := "file2", "staged-file content"
-	if err := fake.X.Run().WriteFile(stagedFile, []byte(stagedFileContent), 0644); err != nil {
+	if err := s.WriteFile(stagedFile, []byte(stagedFileContent), 0644).Done(); err != nil {
 		t.Fatalf("WriteFile(%v, %v) failed: %v", stagedFile, stagedFileContent, err)
 	}
 	if err := fake.X.Git().Add(stagedFile); err != nil {
 		t.Fatalf("%v", err)
 	}
 	untrackedFile, untrackedFileContent := "file3", "untracked-file content"
-	if err := fake.X.Run().WriteFile(untrackedFile, []byte(untrackedFileContent), 0644); err != nil {
+	if err := s.WriteFile(untrackedFile, []byte(untrackedFileContent), 0644).Done(); err != nil {
 		t.Fatalf("WriteFile(%v, %v) failed: %v", untrackedFile, untrackedFileContent, err)
 	}
 	review, err := newReview(fake.X, gerrit.CLOpts{Remote: gerritPath})
@@ -664,13 +671,14 @@
 func TestRunInSubdirectory(t *testing.T) {
 	fake, repoPath, _, gerritPath, cleanup := setupTest(t, true)
 	defer cleanup()
+	s := fake.X.NewSeq()
 	branch := "my-branch"
 	if err := fake.X.Git().CreateAndCheckoutBranch(branch); err != nil {
 		t.Fatalf("%v", err)
 	}
 	subdir := "sub/directory"
 	subdirPerms := os.FileMode(0744)
-	if err := fake.X.Run().MkdirAll(subdir, subdirPerms); err != nil {
+	if err := s.MkdirAll(subdir, subdirPerms).Done(); err != nil {
 		t.Fatalf("MkdirAll(%v, %v) failed: %v", subdir, subdirPerms, err)
 	}
 	files := []string{path.Join(subdir, "file1")}
diff --git a/snapshot.go b/snapshot.go
index 21c0032..16da995 100644
--- a/snapshot.go
+++ b/snapshot.go
@@ -17,6 +17,7 @@
 	"v.io/jiri/gitutil"
 	"v.io/jiri/jiri"
 	"v.io/jiri/project"
+	"v.io/jiri/runutil"
 	"v.io/x/lib/cmdline"
 )
 
@@ -133,7 +134,7 @@
 	switch _, err := jirix.Run().Stat(dir); {
 	case err == nil:
 		return dir, nil
-	case !os.IsNotExist(err):
+	case !runutil.IsNotExist(err):
 		return "", err
 	case remoteFlag:
 		if err := jirix.Run().MkdirAll(dir, 0755); err != nil {
@@ -274,7 +275,7 @@
 	for _, label := range args {
 		labelDir := filepath.Join(snapshotDir, "labels", label)
 		if _, err := jirix.Run().Stat(labelDir); err != nil {
-			if !os.IsNotExist(err) {
+			if !runutil.IsNotExist(err) {
 				return err
 			}
 			failed = true