git-codereview: add test for pending
Fixes #9352
Change-Id: I9714c58ead93d8ec91a09e40a04b1a4e2f075c54
Reviewed-on: https://go-review.googlesource.com/1961
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
diff --git a/git-codereview/branch.go b/git-codereview/branch.go
index ad82a46..9c9d8e7 100644
--- a/git-codereview/branch.go
+++ b/git-codereview/branch.go
@@ -116,9 +116,9 @@
// We want to save the info about the *first* commit
// after the branch point, and the log is ordered
// starting at the most recent and working backward.
- b.commitHash = hash
- b.shortCommitHash = shortHash
- b.parentHash = parent
+ b.commitHash = strings.TrimSpace(hash)
+ b.shortCommitHash = strings.TrimSpace(shortHash)
+ b.parentHash = strings.TrimSpace(parent)
b.subject = subject
b.message = msg
for _, line := range strings.Split(msg, "\n") {
diff --git a/git-codereview/pending.go b/git-codereview/pending.go
index 96220d4..e4e2a96 100644
--- a/git-codereview/pending.go
+++ b/git-codereview/pending.go
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// TODO(rsc): Tests
-
package main
import (
@@ -42,7 +40,9 @@
if b.current {
b.staged, b.unstaged, b.untracked = LocalChanges()
}
- b.committed = getLines("git", "diff", "--name-only", b.parentHash, b.commitHash)
+ if b.parentHash != "" && b.commitHash != "" {
+ b.committed = getLines("git", "diff", "--name-only", b.parentHash, b.commitHash)
+ }
if !pendingLocal {
b.g, b.gerr = b.GerritChange("DETAILED_LABELS", "CURRENT_REVISION", "MESSAGES", "DETAILED_ACCOUNTS")
}
@@ -165,8 +165,7 @@
}
fmt.Fprintf(&buf, "\n")
if text := b.errors(); text != "" {
- // TODO(rsc): Test
- fmt.Fprintf(&buf, "\tERROR: %s", strings.Replace(text, "\n", "\n\t", -1))
+ fmt.Fprintf(&buf, "\tERROR: %s\n\n", strings.Replace(strings.TrimSpace(text), "\n", "\n\t", -1))
}
if b.message != "" {
msg := strings.TrimRight(b.message, "\r\n")
@@ -220,7 +219,11 @@
fmt.Fprintf(&buf, "\n")
}
- os.Stdout.Write(buf.Bytes())
+ if stdoutTrap != nil {
+ stdoutTrap.Write(buf.Bytes())
+ } else {
+ os.Stdout.Write(buf.Bytes())
+ }
}
// errors returns any errors that should be displayed
@@ -233,8 +236,8 @@
fmt.Fprintf(&buf, "\tDo not commit directly to %s branch.\n", b.Name)
} else if b.commitsAhead > 1 {
fmt.Fprintf(&buf, "Branch contains %d commits not on origin/%s.\n", b.commitsAhead, b.OriginBranch())
- fmt.Fprint(&buf, "\tThere should be at most one.\n")
- fmt.Fprint(&buf, "\tUse 'git change', not 'git commit'.\n")
+ fmt.Fprintf(&buf, "\tThere should be at most one.\n")
+ fmt.Fprintf(&buf, "\tUse 'git change', not 'git commit'.\n")
fmt.Fprintf(&buf, "\tRun 'git log %s..%s' to list commits.\n", b.OriginBranch(), b.Name)
}
return buf.String()
diff --git a/git-codereview/pending_test.go b/git-codereview/pending_test.go
new file mode 100644
index 0000000..b1030e2
--- /dev/null
+++ b/git-codereview/pending_test.go
@@ -0,0 +1,283 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "regexp"
+ "strings"
+ "testing"
+)
+
+func TestPendingNone(t *testing.T) {
+ gt := newGitTest(t)
+ defer gt.done()
+
+ testPending(t, `
+ master (current branch)
+
+ `)
+}
+
+func TestPendingNoneBranch(t *testing.T) {
+ gt := newGitTest(t)
+ defer gt.done()
+
+ trun(t, gt.client, "git", "checkout", "-b", "work")
+
+ testPending(t, `
+ work (current branch)
+
+ `)
+}
+
+func TestPendingBasic(t *testing.T) {
+ gt := newGitTest(t)
+ defer gt.done()
+ gt.work(t)
+
+ testPending(t, `
+ work REVHASH (current branch)
+ msg
+
+ Change-Id: I123456789
+
+ Files in this change:
+ file
+
+ `)
+}
+
+func TestPendingComplex(t *testing.T) {
+ gt := newGitTest(t)
+ defer gt.done()
+ gt.work(t)
+
+ write(t, gt.server+"/file", "v2")
+ trun(t, gt.server, "git", "commit", "-a", "-m", "v2")
+
+ write(t, gt.server+"/file", "v3")
+ trun(t, gt.server, "git", "commit", "-a", "-m", "v3")
+
+ trun(t, gt.client, "git", "fetch")
+ trun(t, gt.client, "git", "checkout", "-b", "work3ignored", "-t", "origin/master")
+
+ write(t, gt.server+"/file", "v4")
+ trun(t, gt.server, "git", "commit", "-a", "-m", "v4")
+
+ trun(t, gt.client, "git", "fetch")
+ trun(t, gt.client, "git", "checkout", "-b", "work2", "-t", "origin/master")
+ write(t, gt.client+"/file", "modify")
+ write(t, gt.client+"/file1", "new")
+ trun(t, gt.client, "git", "add", "file", "file1")
+ trun(t, gt.client, "git", "commit", "-m", "some changes")
+ write(t, gt.client+"/file1", "modify")
+ write(t, gt.client+"/afile1", "new")
+ trun(t, gt.client, "git", "add", "file1", "afile1")
+ write(t, gt.client+"/file1", "modify again")
+ write(t, gt.client+"/file", "modify again")
+ write(t, gt.client+"/bfile", "untracked")
+
+ testPending(t, `
+ work REVHASH (5 behind)
+ msg
+
+ Change-Id: I123456789
+
+ Files in this change:
+ file
+
+ work2 REVHASH (current branch)
+ some changes
+
+ Files in this change:
+ file
+ file1
+ Files staged:
+ afile1
+ file1
+ Files unstaged:
+ file
+ file1
+ Files untracked:
+ bfile
+
+ `)
+}
+
+func TestPendingErrors(t *testing.T) {
+ gt := newGitTest(t)
+ defer gt.done()
+
+ gt.work(t)
+ write(t, gt.client+"/file", "v2")
+ trun(t, gt.client, "git", "commit", "-a", "-m", "v2")
+
+ trun(t, gt.client, "git", "checkout", "master")
+ write(t, gt.client+"/file", "v3")
+ trun(t, gt.client, "git", "commit", "-a", "-m", "v3")
+
+ testPending(t, `
+ master REVHASH (current branch)
+ ERROR: Branch contains 1 commit not on origin/master.
+ Do not commit directly to master branch.
+
+ v3
+
+ Files in this change:
+ file
+
+ work REVHASH
+ ERROR: Branch contains 2 commits not on origin/origin/master.
+ There should be at most one.
+ Use 'git change', not 'git commit'.
+ Run 'git log origin/master..work' to list commits.
+
+ msg
+
+ Change-Id: I123456789
+
+ Files in this change:
+ file
+
+`)
+}
+
+func TestPendingGerrit(t *testing.T) {
+ gt := newGitTest(t)
+ defer gt.done()
+ gt.work(t)
+
+ srv := newGerritServer(t)
+ defer srv.done()
+
+ // Test error from Gerrit server.
+ testPending(t, `
+ work REVHASH (current branch)
+ msg
+
+ Change-Id: I123456789
+
+ Files in this change:
+ file
+
+ `)
+
+ setJSON := func(json string) {
+ srv.setReply("/a/changes/proj~master~I123456789", gerritReply{body: ")]}'\n" + json})
+ }
+
+ setJSON(`{
+ "current_revision": "` + CurrentBranch().CommitHash() + `",
+ "status": "MERGED",
+ "_number": 1234,
+ "owner": {"_id": 42},
+ "labels": {
+ "Code-Review": {
+ "all": [
+ {
+ "_id": 42,
+ "value": 0
+ },
+ {
+ "_id": 43,
+ "name": "George Opher",
+ "value": -2
+ },
+ {
+ "_id": 44,
+ "name": "Grace Emlin",
+ "value": 1
+ }
+ ]
+ },
+ "Other-Label": {
+ "all": [
+ {
+ "_account_id": 42,
+ "name": "The Owner",
+ "value": 2
+ }
+ ]
+ }
+ }
+ }`)
+
+ testPending(t, `
+ work REVHASH http://127.0.0.1:PORT/1234 (current branch, mailed, submitted)
+ msg
+
+ Change-Id: I123456789
+
+ Code-Review:
+ +1 Grace Emlin
+ -2 George Opher
+ Other-Label:
+ +2 The Owner
+ Files in this change:
+ file
+
+ `)
+
+}
+
+func testPending(t *testing.T, want string) {
+ // fake auth information to avoid Gerrit error
+ if auth.host == "" {
+ auth.host = "gerrit.fake"
+ auth.user = "not-a-user"
+ defer func() {
+ auth.host = ""
+ auth.user = ""
+ }()
+ }
+
+ want = strings.Replace(want, "\n\t", "\n", -1)
+ want = strings.Replace(want, "\n\t", "\n", -1)
+ want = strings.TrimPrefix(want, "\n")
+
+ testMain(t, "pending")
+ out := stdout.Bytes()
+
+ out = regexp.MustCompile(`\b[0-9a-f]{7}\b`).ReplaceAllLiteral(out, []byte("REVHASH"))
+ out = regexp.MustCompile(`\b127\.0\.0\.1:\d+\b`).ReplaceAllLiteral(out, []byte("127.0.0.1:PORT"))
+
+ if string(out) != want {
+ t.Errorf("invalid pending output:\n%s\nwant:\n%s", out, want)
+ if d, err := diff([]byte(want), out); err == nil {
+ t.Errorf("diff want actual:\n%s", d)
+ }
+ }
+}
+
+func diff(b1, b2 []byte) (data []byte, err error) {
+ f1, err := ioutil.TempFile("", "gofmt")
+ if err != nil {
+ return
+ }
+ defer os.Remove(f1.Name())
+ defer f1.Close()
+
+ f2, err := ioutil.TempFile("", "gofmt")
+ if err != nil {
+ return
+ }
+ defer os.Remove(f2.Name())
+ defer f2.Close()
+
+ f1.Write(b1)
+ f2.Write(b2)
+
+ data, err = exec.Command("diff", "-u", f1.Name(), f2.Name()).CombinedOutput()
+ if len(data) > 0 {
+ // diff exits with a non-zero status when the files don't match.
+ // Ignore that failure as long as we get output.
+ err = nil
+ }
+ return
+
+}