// DisableRemoteManifestPush disables pushes to the remote manifest // repository. func (fake FakeJiriRoot) DisableRemoteManifestPush() error { dir := gitutil.RootDirOpt(filepath.Join(fake.remote, manifestProjectPath)) if err := gitutil.New(fake.X.NewSeq(), dir).CheckoutBranch("master"); err != nil { return err } return nil }
// EnableRemoteManifestPush enables pushes to the remote manifest // repository. func (fake FakeJiriRoot) EnableRemoteManifestPush() error { dir := gitutil.RootDirOpt(filepath.Join(fake.remote, manifestProjectPath)) if !gitutil.New(fake.X.NewSeq(), dir).BranchExists("non-master") { if err := gitutil.New(fake.X.NewSeq(), dir).CreateBranch("non-master"); err != nil { return err } } if err := gitutil.New(fake.X.NewSeq(), dir).CheckoutBranch("non-master"); err != nil { return err } return nil }
func (fake FakeJiriRoot) writeManifest(manifest *project.Manifest, dir, path string) error { git := gitutil.New(fake.X.NewSeq(), gitutil.RootDirOpt(dir)) if err := manifest.ToFile(fake.X, path); err != nil { return err } if err := git.Add(path); err != nil { return err } if err := git.Commit(); err != nil { return err } return nil }
// CreateRemoteProject creates a new remote project. func (fake FakeJiriRoot) CreateRemoteProject(name string) error { projectDir := filepath.Join(fake.remote, name) if err := fake.X.NewSeq().MkdirAll(projectDir, os.FileMode(0700)).Done(); err != nil { return err } if err := gitutil.New(fake.X.NewSeq()).Init(projectDir); err != nil { return err } if err := gitutil.New(fake.X.NewSeq(), gitutil.RootDirOpt(projectDir)).CommitWithMessage("initial commit"); err != nil { return err } fake.Projects[name] = projectDir return nil }
func setProjectState(jirix *jiri.X, state *ProjectState, checkDirty bool, ch chan<- error) { var err error switch state.Project.Protocol { case "git": scm := gitutil.New(jirix.NewSeq(), gitutil.RootDirOpt(state.Project.Path)) var branches []string branches, state.CurrentBranch, err = scm.GetBranches() if err != nil { ch <- err return } for _, branch := range branches { file := filepath.Join(state.Project.Path, jiri.ProjectMetaDir, branch, ".gerrit_commit_message") hasFile := true if _, err := jirix.NewSeq().Stat(file); err != nil { if !runutil.IsNotExist(err) { ch <- err return } hasFile = false } state.Branches = append(state.Branches, BranchState{ Name: branch, HasGerritMessage: hasFile, }) } if checkDirty { state.HasUncommitted, err = scm.HasUncommittedChanges() if err != nil { ch <- err return } state.HasUntracked, err = scm.HasUntrackedFiles() if err != nil { ch <- err return } } default: ch <- UnsupportedProtocolErr(state.Project.Protocol) return } ch <- nil }
// TestUpdateUniverseWithRevision checks that UpdateUniverse will pull remote // projects at the specified revision. func TestUpdateUniverseWithRevision(t *testing.T) { localProjects, fake, cleanup := setupUniverse(t) defer cleanup() s := fake.X.NewSeq() // Set project 1's revision in the manifest to the current revision. git := gitutil.New(s, gitutil.RootDirOpt(fake.Projects[localProjects[1].Name])) rev, err := git.CurrentRevision() if err != nil { t.Fatal(err) } m, err := fake.ReadRemoteManifest() if err != nil { t.Fatal(err) } projects := []project.Project{} for _, p := range m.Projects { if p.Name == localProjects[1].Name { p.Revision = rev } projects = append(projects, p) } m.Projects = projects if err := fake.WriteRemoteManifest(m); err != nil { t.Fatal(err) } // Update README in all projects. for _, remoteProjectDir := range fake.Projects { writeReadme(t, fake.X, remoteProjectDir, "new revision") } // Check that calling UpdateUniverse() updates all projects except for // project 1. if err := fake.UpdateUniverse(false); err != nil { t.Fatal(err) } for i, p := range localProjects { if i == 1 { checkReadme(t, fake.X, p, "initial readme") } else { checkReadme(t, fake.X, p, "new revision") } } }
// TestCreatePushRemote checks that creating a snapshot with the -push-remote // flag causes the snapshot to be committed and pushed upstream. func TestCreatePushRemote(t *testing.T) { resetFlags() defer resetFlags() fake, cleanup := jiritest.NewFakeJiriRoot(t) defer cleanup() fake.EnableRemoteManifestPush() defer fake.DisableRemoteManifestPush() manifestDir := filepath.Join(fake.X.Root, "manifest") snapshotDir := filepath.Join(manifestDir, "snapshot") label := "test" git := gitutil.New(fake.X.NewSeq(), gitutil.RootDirOpt(manifestDir)) commitCount, err := git.CountCommits("master", "") if err != nil { t.Fatalf("git.CountCommits(\"master\", \"\") failed: %v", err) } // Create snapshot with -push-remote flag set to true. snapshotDirFlag = snapshotDir pushRemoteFlag = true if err := runSnapshotCreate(fake.X, []string{label}); err != nil { t.Fatalf("%v", err) } // Check that repo has one new commit. newCommitCount, err := git.CountCommits("master", "") if err != nil { t.Fatalf("git.CountCommits(\"master\", \"\") failed: %v", err) } if got, want := newCommitCount, commitCount+1; got != want { t.Errorf("unexpected commit count: got %v want %v", got, want) } // Check that new label is commited. labelFile := filepath.Join(snapshotDir, "labels", label) if !git.IsFileCommitted(labelFile) { t.Errorf("expected file %v to be committed but it was not", labelFile) } }
// TestUpdateUniverseRemoteBranch checks that UpdateUniverse can pull from a // non-master remote branch. func TestUpdateUniverseRemoteBranch(t *testing.T) { localProjects, fake, cleanup := setupUniverse(t) defer cleanup() s := fake.X.NewSeq() if err := fake.UpdateUniverse(false); err != nil { t.Fatal(err) } // Commit to master branch of a project 1. writeReadme(t, fake.X, fake.Projects[localProjects[1].Name], "master commit") // Create and checkout a new branch of project 1 and make a new commit. git := gitutil.New(s, gitutil.RootDirOpt(fake.Projects[localProjects[1].Name])) if err := git.CreateAndCheckoutBranch("non-master"); err != nil { t.Fatal(err) } writeReadme(t, fake.X, fake.Projects[localProjects[1].Name], "non-master commit") // Point the manifest to the new non-master branch. m, err := fake.ReadRemoteManifest() if err != nil { t.Fatal(err) } projects := []project.Project{} for _, p := range m.Projects { if p.Name == localProjects[1].Name { p.RemoteBranch = "non-master" } projects = append(projects, p) } m.Projects = projects if err := fake.WriteRemoteManifest(m); err != nil { t.Fatal(err) } // Check that UpdateUniverse pulls the commit from the non-master branch. if err := fake.UpdateUniverse(false); err != nil { t.Fatal(err) } checkReadme(t, fake.X, localProjects[1], "non-master commit") }
func TestRunP(t *testing.T) { fake, cleanup := jiritest.NewFakeJiriRoot(t) defer cleanup() projects := addProjects(t, fake) dir, sh := buildJiri(t), gosh.NewShell(t) if got, want := len(projects), 5; got != want { t.Errorf("got %v, want %v", got, want) } cwd, err := os.Getwd() if err != nil { t.Fatal(err) } defer os.Chdir(cwd) chdir := func(dir string) { if err := os.Chdir(dir); err != nil { t.Fatal(err) } } manifestKey := strings.Replace(string(projects[0].Key()), "r.a", "manifest", -1) keys := []string{manifestKey} for _, p := range projects { keys = append(keys, string(p.Key())) } chdir(projects[0].Path) got := run(sh, dir, "jiri", "runp", "--show-name-prefix", "-v", "echo") hdr := "Project Names: manifest r.a r.b r.c r.t1 r.t2\n" hdr += "Project Keys: " + strings.Join(keys, " ") + "\n" if want := hdr + "manifest: \nr.a: \nr.b: \nr.c: \nr.t1: \nr.t2:"; got != want { t.Errorf("got %v, want %v", got, want) } got = run(sh, dir, "jiri", "runp", "-v", "--interactive=false", "basename", "$(", "jiri", "project", "info", "-f", "{{.Project.Path}}", ")") if want := hdr + "manifest\nr.a\nr.b\nr.c\nr.t1\nr.t2"; got != want { t.Errorf("got %v, want %v", got, want) } got = run(sh, dir, "jiri", "runp", "--interactive=false", "git", "rev-parse", "--abbrev-ref", "HEAD") if want := "master\nmaster\nmaster\nmaster\nmaster\nmaster"; got != want { t.Errorf("got %v, want %v", got, want) } got = run(sh, dir, "jiri", "runp", "-interactive=false", "--show-name-prefix=true", "git", "rev-parse", "--abbrev-ref", "HEAD") if want := "manifest: master\nr.a: master\nr.b: master\nr.c: master\nr.t1: master\nr.t2: master"; got != want { t.Errorf("got %v, want %v", got, want) } got = run(sh, dir, "jiri", "runp", "--interactive=false", "--show-key-prefix=true", "git", "rev-parse", "--abbrev-ref", "HEAD") if want := strings.Join(keys, ": master\n") + ": master"; got != want { t.Errorf("got %v, want %v", got, want) } uncollated := run(sh, dir, "jiri", "runp", "--interactive=false", "--collate-stdout=false", "--show-name-prefix=true", "git", "rev-parse", "--abbrev-ref", "HEAD") split := strings.Split(uncollated, "\n") sort.Strings(split) got = strings.TrimSpace(strings.Join(split, "\n")) if want := "manifest: master\nr.a: master\nr.b: master\nr.c: master\nr.t1: master\nr.t2: master"; got != want { t.Errorf("got %v, want %v", got, want) } got = run(sh, dir, "jiri", "runp", "--show-name-prefix", "--projects=r.t[12]", "echo") if want := "r.t1: \nr.t2:"; got != want { t.Errorf("got %v, want %v", got, want) } rb := projects[1].Path rc := projects[2].Path t1 := projects[3].Path s := fake.X.NewSeq() newfile := func(dir, file string) { testfile := filepath.Join(dir, file) _, err := s.Create(testfile) if err != nil { t.Errorf("failed to create %s: %v", testfile, err) } } git := func(dir string) *gitutil.Git { return gitutil.New(fake.X.NewSeq(), gitutil.RootDirOpt(dir)) } newfile(rb, "untracked.go") got = run(sh, dir, "jiri", "runp", "--has-untracked", "--show-name-prefix", "echo") if want := "r.b:"; got != want { t.Errorf("got %v, want %v", got, want) } got = run(sh, dir, "jiri", "runp", "--has-untracked=false", "--show-name-prefix", "echo") if want := "manifest: \nr.a: \nr.c: \nr.t1: \nr.t2:"; got != want { t.Errorf("got %v, want %v", got, want) } newfile(rc, "uncommitted.go") if err := git(rc).Add("uncommitted.go"); err != nil { t.Error(err) } got = run(sh, dir, "jiri", "runp", "--has-uncommitted", "--show-name-prefix", "echo") if want := "r.c:"; got != want { t.Errorf("got %v, want %v", got, want) } got = run(sh, dir, "jiri", "runp", "--has-uncommitted=false", "--show-name-prefix", "echo") if want := "manifest: \nr.a: \nr.b: \nr.t1: \nr.t2:"; got != want { t.Errorf("got %v, want %v", got, want) } // test ordering of has-<x> flags newfile(rc, "untracked.go") got = run(sh, dir, "jiri", "runp", "--has-untracked", "--has-uncommitted", "--show-name-prefix", "echo") if want := "r.c:"; got != want { t.Errorf("got %v, want %v", got, want) } got = run(sh, dir, "jiri", "runp", "--has-uncommitted", "--has-untracked", "--show-name-prefix", "echo") if want := "r.c:"; got != want { t.Errorf("got %v, want %v", got, want) } git(rb).CreateAndCheckoutBranch("a1") git(rb).CreateAndCheckoutBranch("b2") git(rc).CreateAndCheckoutBranch("b2") git(t1).CreateAndCheckoutBranch("a1") chdir(rc) // Just the projects with branch b2. got = run(sh, dir, "jiri", "runp", "--show-name-prefix", "echo") if want := "r.b: \nr.c:"; got != want { t.Errorf("got %v, want %v", got, want) } // All projects since --projects takes precendence over branches. got = run(sh, dir, "jiri", "runp", "--projects=.*", "--show-name-prefix", "echo") if want := "manifest: \nr.a: \nr.b: \nr.c: \nr.t1: \nr.t2:"; got != want { t.Errorf("got %v, want %v", got, want) } if err := s.MkdirAll(filepath.Join(rb, ".jiri", "a1"), os.FileMode(0755)).Done(); err != nil { t.Fatal(err) } newfile(rb, filepath.Join(".jiri", "a1", ".gerrit_commit_message")) git(rb).CheckoutBranch("a1") git(t1).CheckoutBranch("a1") chdir(t1) got = run(sh, dir, "jiri", "runp", "--has-gerrit-message", "--show-name-prefix", "echo") if want := "r.b:"; got != want { t.Errorf("got %v, want %v", got, want) } got = run(sh, dir, "jiri", "runp", "--has-gerrit-message=false", "--show-name-prefix", "echo") if want := "r.t1:"; got != want { t.Errorf("got %v, want %v", got, want) } }
// TestLocalProjects tests the behavior of the LocalProjects method with // different ScanModes. func TestLocalProjects(t *testing.T) { jirix, cleanup := jiritest.NewX(t) defer cleanup() // Create some projects. numProjects, projectPaths := 3, []string{} for i := 0; i < numProjects; i++ { s := jirix.NewSeq() name := projectName(i) path := filepath.Join(jirix.Root, name) if err := s.MkdirAll(path, 0755).Done(); err != nil { t.Fatal(err) } // Initialize empty git repository. The commit is necessary, otherwise // "git rev-parse master" fails. git := gitutil.New(s, gitutil.RootDirOpt(path)) if err := git.Init(path); err != nil { t.Fatal(err) } if err := git.Commit(); err != nil { t.Fatal(err) } // Write project metadata. p := project.Project{ Path: path, Name: name, } if err := project.InternalWriteMetadata(jirix, p, path); err != nil { t.Fatalf("writeMetadata %v %v) failed: %v\n", p, path, err) } projectPaths = append(projectPaths, path) } // Create a latest update snapshot but only tell it about the first project. manifest := project.Manifest{ Projects: []project.Project{ { Name: projectName(0), Path: projectPaths[0], }, }, } if err := jirix.NewSeq().MkdirAll(jirix.UpdateHistoryDir(), 0755).Done(); err != nil { t.Fatalf("MkdirAll(%v) failed: %v", jirix.UpdateHistoryDir(), err) } if err := manifest.ToFile(jirix, jirix.UpdateHistoryLatestLink()); err != nil { t.Fatalf("manifest.ToFile(%v) failed: %v", jirix.UpdateHistoryLatestLink(), err) } // LocalProjects with scanMode = FastScan should only find the first // project. foundProjects, err := project.LocalProjects(jirix, project.FastScan) if err != nil { t.Fatalf("LocalProjects(%v) failed: %v", project.FastScan, err) } checkProjectsMatchPaths(t, foundProjects, projectPaths[:1]) // LocalProjects with scanMode = FullScan should find all projects. foundProjects, err = project.LocalProjects(jirix, project.FullScan) if err != nil { t.Fatalf("LocalProjects(%v) failed: %v", project.FastScan, err) } checkProjectsMatchPaths(t, foundProjects, projectPaths[:]) // Check that deleting a project forces LocalProjects to run a full scan, // even if FastScan is specified. if err := jirix.NewSeq().RemoveAll(projectPaths[0]).Done(); err != nil { t.Fatalf("RemoveAll(%v) failed: %v", projectPaths[0]) } foundProjects, err = project.LocalProjects(jirix, project.FastScan) if err != nil { t.Fatalf("LocalProjects(%v) failed: %v", project.FastScan, err) } checkProjectsMatchPaths(t, foundProjects, projectPaths[1:]) }
func TestMultiPart(t *testing.T) { fake, cleanup := jiritest.NewFakeJiriRoot(t) defer cleanup() projects := addProjects(t, fake) origCleanupFlag, origCurrentProjectFlag := cleanupMultiPartFlag, currentProjectFlag defer func() { cleanupMultiPartFlag, currentProjectFlag = origCleanupFlag, origCurrentProjectFlag }() cleanupMultiPartFlag, currentProjectFlag = false, false name, err := gitutil.New(fake.X.NewSeq()).CurrentBranchName() if err != nil { t.Fatal(err) } if name == "master" { // The test cases below assume that they are run on a feature-branch, // but this is not necessarily always the case when running under // jenkins, so if it's run on a master branch it will create // a feature branch. if err := gitutil.New(fake.X.NewSeq()).CreateAndCheckoutBranch("feature-branch"); err != nil { t.Fatal(err) } defer func() { git := gitutil.New(fake.X.NewSeq()) git.CheckoutBranch("master", gitutil.ForceOpt(true)) git.DeleteBranch("feature-branch", gitutil.ForceOpt(true)) }() } cwd, err := os.Getwd() if err != nil { t.Fatal(err) } defer os.Chdir(cwd) relchdir := func(dir string) { chdir(t, fake.X, dir) } initMP := func() *multiPart { mp, err := initForMultiPart(fake.X) if err != nil { _, file, line, _ := runtime.Caller(1) t.Fatalf("%s:%d: %v", filepath.Base(file), line, err) } return mp } wr := func(mp *multiPart) *multiPart { return mp } git := func(dir string) *gitutil.Git { return gitutil.New(fake.X.NewSeq(), gitutil.RootDirOpt(dir)) } cleanupMultiPartFlag = true if got, want := initMP(), wr(&multiPart{clean: true}); !reflect.DeepEqual(got, want) { t.Errorf("got %#v, want %#v", got, want) } currentProjectFlag = true if got, want := initMP(), wr(&multiPart{clean: true, current: true}); !reflect.DeepEqual(got, want) { t.Errorf("got %#v, want %#v", got, want) } cleanupMultiPartFlag, currentProjectFlag = false, false // Test metadata generation. ra := projects[0].Path rb := projects[1].Path rc := projects[2].Path t1 := projects[3].Path git(ra).CreateAndCheckoutBranch("a1") relchdir(ra) if got, want := initMP(), wr(&multiPart{current: true, currentKey: projects[0].Key(), currentBranch: "a1"}); !reflect.DeepEqual(got, want) { t.Errorf("got %#v, want %#v", got, want) } git(rb).CreateAndCheckoutBranch("a1") mp := initMP() if mp.current != false || mp.clean != false { t.Errorf("current or clean not false: %v, %v", mp.current, mp.clean) } if got, want := len(mp.keys), 2; got != want { t.Errorf("got %v, want %v", got, want) } tmp := &multiPart{ keys: project.ProjectKeys{projects[0].Key(), projects[1].Key()}, } for i, k := range mp.keys { if got, want := k, tmp.keys[i]; got != want { t.Errorf("got %v, want %v", got, want) } } if got, want := len(mp.states), 2; got != want { t.Errorf("got %v, want %v", got, want) } git(rc).CreateAndCheckoutBranch("a1") git(t1).CreateAndCheckoutBranch("a2") mp = initMP() if got, want := len(mp.keys), 3; got != want { t.Errorf("got %v, want %v", got, want) } if err := mp.writeMultiPartMetadata(fake.X); err != nil { t.Fatal(err) } hasMetaData := func(total int, branch string, projectPaths ...string) { _, file, line, _ := runtime.Caller(1) loc := fmt.Sprintf("%s:%d", filepath.Base(file), line) for i, dir := range projectPaths { filename := filepath.Join(dir, jiri.ProjectMetaDir, branch, multiPartMetaDataFileName) msg, err := ioutil.ReadFile(filename) if err != nil { t.Fatalf("%s: %v", loc, err) } if got, want := string(msg), fmt.Sprintf("MultiPart: %d/%d\n", i+1, total); got != want { t.Errorf("%v: got %v, want %v", dir, got, want) } } } hasNoMetaData := func(branch string, projectPaths ...string) { _, file, line, _ := runtime.Caller(1) loc := fmt.Sprintf("%s:%d", filepath.Base(file), line) for _, dir := range projectPaths { filename := filepath.Join(fake.X.Root, dir, jiri.ProjectMetaDir, branch, multiPartMetaDataFileName) _, err := os.Stat(filename) if !os.IsNotExist(err) { t.Fatalf("%s: %s should not exist", loc, filename) } } } newFile := func(dir, file string) { testfile := filepath.Join(dir, file) _, err := fake.X.NewSeq().Create(testfile) if err != nil { t.Errorf("failed to create %s: %v", testfile, err) } } hasMetaData(len(mp.keys), "a1", ra, rb, rc) hasNoMetaData(t1, "a2") if err := mp.cleanMultiPartMetadata(fake.X); err != nil { t.Fatal(err) } hasNoMetaData(ra, "a1", rb, rc, t1) // Test CL messages. for _, p := range projects { // Install commit hook so that Change-Id is written. installCommitMsgHook(t, fake.X, p.Path) } // Create a fake jiri root for the fake gerrit repos. gerritFake, gerritCleanup := jiritest.NewFakeJiriRoot(t) defer gerritCleanup() relchdir(ra) if err := mp.writeMultiPartMetadata(fake.X); err != nil { t.Fatal(err) } hasMetaData(len(mp.keys), "a1", ra, rb, rc) gitAddFiles := func(name string, repos ...string) { for _, dir := range repos { newFile(dir, name) if err := git(dir).Add(name); err != nil { t.Error(err) } } } gitCommit := func(msg string, repos ...string) { for _, dir := range repos { committer := git(dir).NewCommitter(false) if err := committer.Commit(msg); err != nil { t.Error(err) } } } gitAddFiles("new-file", ra, rb, rc) _, err = initForMultiPart(fake.X) if err == nil || !strings.Contains(err.Error(), "uncommitted changes:") { t.Fatalf("expected an error about uncommitted changes: got %v", err) } gitCommit("oh multipart test\n", ra, rb, rc) bodyMessage := "xyz\n\na simple message\n" messageFile := filepath.Join(fake.X.Root, jiri.RootMetaDir, "message-body") if err := ioutil.WriteFile(messageFile, []byte(bodyMessage), 0666); err != nil { t.Fatal(err) } mp = initMP() setTopicFlag = false commitMessageBodyFlag = messageFile testCommitMsgs := func(branch string, cls ...*project.Project) { _, file, line, _ := runtime.Caller(1) loc := fmt.Sprintf("%s:%d", filepath.Base(file), line) total := len(cls) for index, p := range cls { // Create a new gerrit repo each time we commit, since we can't // push more than once to the fake gerrit repo without actually // running gerrit. gp := createRepoFromOrigin(t, gerritFake.X, "gerrit", p.Remote) defer os.Remove(gp) relchdir(p.Path) review, err := newReview(fake.X, *p, gerrit.CLOpts{ Presubmit: gerrit.PresubmitTestTypeNone, Remote: gp, }) if err != nil { t.Fatalf("%v: %v: %v", loc, p.Path, err) } // use the default commit message if err := review.run(); err != nil { t.Fatalf("%v: %v, %v", loc, p.Path, err) } filename, err := getCommitMessageFileName(fake.X, branch) if err != nil { t.Fatalf("%v: %v", loc, err) } msg, err := ioutil.ReadFile(filename) if err != nil { t.Fatalf("%v: %v", loc, err) } if total < 2 { if strings.Contains(string(msg), "MultiPart") { t.Errorf("%v: commit message contains MultiPart when it should not: %v", loc, string(msg)) } continue } expected := fmt.Sprintf("\nMultiPart: %d/%d\n", index+1, total) if !strings.Contains(string(msg), expected) { t.Errorf("%v: commit message for %v does not contain %v: %v", loc, p.Path, expected, string(msg)) } if got, want := string(msg), bodyMessage+"PresubmitTest: none"+expected+"Change-Id: I0000000000000000000000000000000000000000"; got != want { t.Errorf("got %v, want %v", got, want) } } } testCommitMsgs("a1", projects[0], projects[1], projects[2]) cl := mp.commandline("", []string{"-r=alice"}) expected := []string{ "runp", "--interactive", "--projects=" + string(projects[0].Key()) + "," + string(projects[1].Key()) + "," + string(projects[2].Key()), "jiri", "cl", "mail", "--current-project-only=true", "-r=alice", } if got, want := strings.Join(cl, " "), strings.Join(expected, " "); got != want { t.Errorf("got %v, want %v", got, want) } cl = mp.commandline(projects[0].Key(), []string{"-r=bob"}) expected[2] = "--projects=" + string(projects[1].Key()) + "," + string(projects[2].Key()) expected[len(expected)-1] = "-r=bob" if got, want := strings.Join(cl, " "), strings.Join(expected, " "); got != want { t.Errorf("got %v, want %v", got, want) } git(rb).CreateAndCheckoutBranch("a2") gitAddFiles("new-file1", ra, rc) gitCommit("oh multipart test: 2\n", ra, rc) mp = initMP() if err := mp.writeMultiPartMetadata(fake.X); err != nil { t.Fatal(err) } hasMetaData(len(mp.keys), "a1", ra, rc) testCommitMsgs("a1", projects[0], projects[2]) git(ra).CreateAndCheckoutBranch("a2") mp = initMP() if err := mp.writeMultiPartMetadata(fake.X); err != nil { t.Fatal(err) } hasNoMetaData(rc) testCommitMsgs("a1", projects[2]) }