text: var assert = require("assert");
  var path = require("path");
  var promisify = require("promisify-node");
  var fse = promisify(require("fs-extra"));
  var local = path.join.bind(path, __dirname);
  
  fse.ensureDir = promisify(fse.ensureDir);
  
  describe("Merge", function() {
    var NodeGit = require("../../");
    var RepoUtils = require("../utils/repository_setup");
  
    var reposPath = local("../repos/merge");
    var ourBranchName = "ours";
    var theirBranchName = "theirs";
  
    beforeEach(function() {
      var test = this;
      return RepoUtils.createRepository(reposPath)
        .then(function(repo) {
          test.repository = repo;
        });
    });
  
    it("can cleanly merge 2 files", function() {
      var ourFileName = "ourNewFile.txt";
      var theirFileName = "theirNewFile.txt";
  
      var ourFileContent = "I like Toll Roads. I have an EZ-Pass!";
      var theirFileContent = "I'm skeptical about Toll Roads";
  
      var ourSignature = NodeGit.Signature.create
            ("Ron Paul", "RonPaul@TollRoadsRBest.info", 123456789, 60);
      var theirSignature = NodeGit.Signature.create
            ("Greg Abbott", "Gregggg@IllTollYourFace.us", 123456789, 60);
  
      var repository = this.repository;
      var ourCommit;
      var theirCommit;
      var ourBranch;
      var theirBranch;
  
      return fse.writeFile(path.join(repository.workdir(), ourFileName),
          ourFileContent)
        // Load up the repository index and make our initial commit to HEAD
        .then(function() {
          return repository.refreshIndex();
        })
        .then(function(index) {
          return index.addByPath(ourFileName)
            .then(function() {
              return index.write();
            })
            .then(function() {
              return index.writeTree();
            });
        })
        .then(function(oid) {
          assert.equal(oid.toString(),
            "11ead82b1135b8e240fb5d61e703312fb9cc3d6a");
  
          return repository.createCommit("HEAD", ourSignature,
            ourSignature, "we made a commit", oid, []);
        })
        .then(function(commitOid) {
          assert.equal(commitOid.toString(),
            "91a183f87842ebb7a9b08dad8bc2473985796844");
  
          return repository.getCommit(commitOid).then(function(commit) {
            ourCommit = commit;
          }).then(function() {
            return repository.createBranch(ourBranchName, commitOid)
              .then(function(branch) {
                ourBranch = branch;
                return repository.createBranch(theirBranchName, commitOid);
              });
          });
        })
        .then(function(branch) {
          theirBranch = branch;
          return fse.writeFile(path.join(repository.workdir(), theirFileName),
            theirFileContent);
        })
        .then(function() {
          return repository.refreshIndex();
        })
        .then(function(index) {
          return index.addByPath(theirFileName)
            .then(function() {
              return index.write();
            })
            .then(function() {
              return index.writeTree();
            });
        })
        .then(function(oid) {
          assert.equal(oid.toString(),
            "76631cb5a290dafe2959152626bb90f2a6d8ec94");
  
          return repository.createCommit(theirBranch.name(), theirSignature,
            theirSignature, "they made a commit", oid, [ourCommit]);
        })
        .then(function(commitOid) {
          assert.equal(commitOid.toString(),
            "0e9231d489b3f4303635fc4b0397830da095e7e7");
  
          return repository.getCommit(commitOid).then(function(commit) {
            theirCommit = commit;
          });
        })
        .then(function() {
          return NodeGit.Merge.commits(repository, ourCommit, theirCommit);
        })
        .then(function(index) {
          assert(!index.hasConflicts());
          return index.writeTreeTo(repository);
        })
        .then(function(oid) {
          assert.equal(oid.toString(),
            "76631cb5a290dafe2959152626bb90f2a6d8ec94");
  
          return repository.createCommit(ourBranch.name(), ourSignature,
            ourSignature, "we merged their commit", oid,
            [ourCommit, theirCommit]);
        })
        .then(function(commitId) {
          assert.equal(commitId.toString(),
            "eedee554af34dd4001d8abc799cb55bb7e56a58b");
        });
    });
  
    it("can fast-forward using the convenience method", function() {
      var ourFileName = "ourNewFile.txt";
      var theirFileName = "theirNewFile.txt";
  
      var ourFileContent = "I like Toll Roads. I have an EZ-Pass!";
      var theirFileContent = "I'm skeptical about Toll Roads";
  
      var ourSignature = NodeGit.Signature.create
      ("Ron Paul", "RonPaul@TollRoadsRBest.info", 123456789, 60);
      var theirSignature = NodeGit.Signature.create
      ("Greg Abbott", "Gregggg@IllTollYourFace.us", 123456789, 60);
  
      var repository = this.repository;
      var ourCommit;
      var theirCommit;
      var ourBranch;
      var theirBranch;
  
      return fse.writeFile(
        path.join(repository.workdir(), ourFileName),
        ourFileContent)
      // Load up the repository index and make our initial commit to HEAD
      .then(function() {
        return repository.refreshIndex();
      })
      .then(function(index) {
        return index.addByPath(ourFileName)
          .then(function() {
            return index.write();
          })
          .then(function() {
            return index.writeTree();
          });
      })
      .then(function(oid) {
        assert.equal(oid.toString(),
        "11ead82b1135b8e240fb5d61e703312fb9cc3d6a");
  
        return repository.createCommit("HEAD", ourSignature,
        ourSignature, "we made a commit", oid, []);
      })
      .then(function(commitOid) {
        assert.equal(commitOid.toString(),
        "91a183f87842ebb7a9b08dad8bc2473985796844");
  
        return repository.getCommit(commitOid).then(function(commit) {
          ourCommit = commit;
        }).then(function() {
          return repository.createBranch(ourBranchName, commitOid)
          .then(function(branch) {
            ourBranch = branch;
            return repository.createBranch(theirBranchName, commitOid);
          });
        });
      })
      .then(function(branch) {
        theirBranch = branch;
        return fse.writeFile(path.join(repository.workdir(), theirFileName),
        theirFileContent);
      })
      .then(function() {
        return repository.refreshIndex();
      })
      .then(function(index) {
        return index.addByPath(theirFileName)
          .then(function() {
            return index.write();
          })
          .then(function() {
            return index.writeTree();
          });
      })
      .then(function(oid) {
        assert.equal(oid.toString(),
        "76631cb5a290dafe2959152626bb90f2a6d8ec94");
  
        return repository.createCommit(theirBranch.name(), theirSignature,
        theirSignature, "they made a commit", oid, [ourCommit]);
      })
      .then(function(commitOid) {
        assert.equal(commitOid.toString(),
        "0e9231d489b3f4303635fc4b0397830da095e7e7");
  
        return repository.getCommit(commitOid).then(function(commit) {
          theirCommit = commit;
        });
      })
      .then(function() {
        var opts = {checkoutStrategy: NodeGit.Checkout.STRATEGY.FORCE};
        return repository.checkoutBranch(ourBranchName, opts);
      })
      .then(function() {
        return repository.mergeBranches(
          ourBranchName,
          theirBranchName,
          ourSignature);
      })
      .then(function(oid) {
        assert.equal(oid.toString(),
        "0e9231d489b3f4303635fc4b0397830da095e7e7");
  
        return repository.getBranchCommit(ourBranchName)
          .then(function(branchCommit) {
            assert.equal(oid.toString(), branchCommit.toString());
          });
      })
      .then(function() {
        return repository.getStatus();
      })
      .then(function(statuses) {
        // make sure we didn't change the index
        assert.equal(statuses.length, 0);
      });
    });
  
    it("can merge --no-ff a fast-forward using the convenience method",
      function() {
      var ourFileName = "ourNewFile.txt";
      var theirFileName = "theirNewFile.txt";
  
      var ourFileContent = "I like Toll Roads. I have an EZ-Pass!";
      var theirFileContent = "I'm skeptical about Toll Roads";
  
      var ourSignature = NodeGit.Signature.create
      ("Ron Paul", "RonPaul@TollRoadsRBest.info", 123456789, 60);
      var theirSignature = NodeGit.Signature.create
      ("Greg Abbott", "Gregggg@IllTollYourFace.us", 123456789, 60);
  
      var repository = this.repository;
      var ourCommit;
      var theirCommit;
      var ourBranch;
      var theirBranch;
  
      return fse.writeFile(
        path.join(repository.workdir(), ourFileName),
        ourFileContent)
      // Load up the repository index and make our initial commit to HEAD
      .then(function() {
        return repository.refreshIndex();
      })
      .then(function(index) {
        return index.addByPath(ourFileName)
          .then(function() {
            return index.write();
          })
          .then(function() {
            return index.writeTree();
          });
      })
      .then(function(oid) {
        assert.equal(oid.toString(),
        "11ead82b1135b8e240fb5d61e703312fb9cc3d6a");
  
        return repository.createCommit("HEAD", ourSignature,
        ourSignature, "we made a commit", oid, []);
      })
      .then(function(commitOid) {
        assert.equal(commitOid.toString(),
        "91a183f87842ebb7a9b08dad8bc2473985796844");
  
        return repository.getCommit(commitOid).then(function(commit) {
          ourCommit = commit;
        }).then(function() {
          return repository.createBranch(ourBranchName, commitOid)
          .then(function(branch) {
            ourBranch = branch;
            return repository.createBranch(theirBranchName, commitOid);
          });
        });
      })
      .then(function(branch) {
        theirBranch = branch;
        return fse.writeFile(path.join(repository.workdir(), theirFileName),
        theirFileContent);
      })
      .then(function() {
        return repository.refreshIndex();
      })
      .then(function(index) {
        return index.addByPath(theirFileName)
          .then(function() {
            return index.write();
          })
          .then(function() {
            return index.writeTree();
          });
      })
      .then(function(oid) {
        assert.equal(oid.toString(),
        "76631cb5a290dafe2959152626bb90f2a6d8ec94");
  
        return repository.createCommit(theirBranch.name(), theirSignature,
        theirSignature, "they made a commit", oid, [ourCommit]);
      })
      .then(function(commitOid) {
        assert.equal(commitOid.toString(),
        "0e9231d489b3f4303635fc4b0397830da095e7e7");
  
        return repository.getCommit(commitOid).then(function(commit) {
          theirCommit = commit;
        });
      })
      .then(function() {
        var opts = {
          checkoutStrategy: NodeGit.Checkout.STRATEGY.SAFE |
            NodeGit.Checkout.STRATEGY.RECREATE_MISSING
        };
        return repository.checkoutBranch(ourBranchName, opts);
      })
      .then(function() {
        return repository.mergeBranches(
          ourBranchName,
          theirBranchName,
          ourSignature,
          NodeGit.Merge.PREFERENCE.NO_FASTFORWARD);
      })
      .then(function(oid) {
        assert.equal(oid.toString(),
        "6806d22d2b6c0095b29dc5ec51829caeb67861f1");
  
        return repository.getBranchCommit(ourBranchName)
          .then(function(branchCommit) {
            assert.equal(oid.toString(), branchCommit.toString());
          });
      })
      .then(function() {
        return repository.getStatus();
      })
      .then(function(statuses) {
        // make sure we didn't change the index
        assert.equal(statuses.length, 0);
      });
    });
  
    it("can merge --no-ff a non-fast-forward using the convenience method",
      function() {
      var initialFileName = "initialFile.txt";
      var ourFileName = "ourNewFile.txt";
      var theirFileName = "theirNewFile.txt";
  
      var initialFileContent = "I'd like to drive somewhere";
      var ourFileContent = "I like Toll Roads. I have an EZ-Pass!";
      var theirFileContent = "I'm skeptical about Toll Roads";
  
      var ourSignature = NodeGit.Signature.create
      ("Ron Paul", "RonPaul@TollRoadsRBest.info", 123456789, 60);
      var theirSignature = NodeGit.Signature.create
      ("Greg Abbott", "Gregggg@IllTollYourFace.us", 123456789, 60);
  
      var repository = this.repository;
      var initialCommit;
      var ourCommit;
      var theirCommit;
      var ourBranch;
      var theirBranch;
  
      return fse.writeFile(
        path.join(repository.workdir(), initialFileName),
        initialFileContent)
      // Load up the repository index and make our initial commit to HEAD
      .then(function() {
        return repository.refreshIndex();
      })
      .then(function(index) {
        return index.addByPath(initialFileName)
          .then(function() {
            return index.write();
          })
          .then(function() {
            return index.writeTree();
          });
      })
      .then(function(oid) {
        assert.equal(oid.toString(),
        "21a553813e2f670815b649eef51eeadb253a5d0c");
  
        return repository.createCommit("HEAD", ourSignature,
        ourSignature, "initial commit", oid, []);
      })
      .then(function(commitOid) {
        assert.equal(commitOid.toString(),
        "af66a9c799a10a23319ee4318c8bb2021521f539");
  
        return repository.getCommit(commitOid).then(function(commit) {
          initialCommit = commit;
        }).then(function() {
          return repository.createBranch(ourBranchName, commitOid)
          .then(function(branch) {
            ourBranch = branch;
            return repository.createBranch(theirBranchName, commitOid);
          });
        });
      })
      .then(function(branch) {
        theirBranch = branch;
      })
      .then(function() {
        return fse.writeFile(path.join(repository.workdir(), ourFileName),
        ourFileContent);
      })
      .then(function() {
        return repository.refreshIndex();
      })
      .then(function(index) {
        return index.addByPath(ourFileName)
          .then(function() {
            return index.write();
          })
          .then(function() {
            return index.writeTree();
          });
      })
      .then(function(oid) {
        assert.equal(oid.toString(),
        "af60aa06b3537f75b427f6268a130c842c84a137");
  
        return repository.createCommit(ourBranch.name(), ourSignature,
          ourSignature, "we made a commit", oid, [initialCommit]);
      })
      .then(function(commitOid) {
        assert.equal(commitOid.toString(),
          "7ce31c05427659986d50abfb90c8f7db88ef4fa1");
  
        return repository.getCommit(commitOid).then(function(commit) {
          ourCommit = commit;
        });
      })
      .then(function() {
        return fse.writeFile(path.join(repository.workdir(), theirFileName),
        theirFileContent);
      })
      .then(function() {
        return repository.refreshIndex();
      })
      .then(function(index) {
        return index.addByPath(theirFileName)
          .then(function() {
            return index.write();
          })
          .then(function() {
            return index.writeTree();
          });
      })
      .then(function(oid) {
        assert.equal(oid.toString(),
        "f007361737a2ca00a0e80fc2daf55064463173b4");
  
        return repository.createCommit(theirBranch.name(), theirSignature,
        theirSignature, "they made a commit", oid, [initialCommit]);
      })
      .then(function(commitOid) {
        assert.equal(commitOid.toString(),
        "b588f0eef1809226f8f7db542940749da15ae1de");
  
        return repository.getCommit(commitOid).then(function(commit) {
          theirCommit = commit;
        });
      })
      .then(function() {
        var opts = {checkoutStrategy: NodeGit.Checkout.STRATEGY.FORCE};
        return repository.checkoutBranch(ourBranchName, opts);
      })
      .then(function() {
        return repository.mergeBranches(
          ourBranchName,
          theirBranchName,
          ourSignature,
          NodeGit.Merge.PREFERENCE.NO_FASTFORWARD);
      })
      .then(function(commitId) {
        assert.equal(commitId.toString(),
        "5384feb481d9c29081b3a0c1478fcc24a3953efa");
      })
      .then(function() {
        return repository.getStatus();
      })
      .then(function(statuses) {
        // make sure we didn't change the index
        assert.equal(statuses.length, 0);
      });
    });
  
    it("can merge --ff-only a fast-forward using the convenience method",
      function() {
      var ourFileName = "ourNewFile.txt";
      var theirFileName = "theirNewFile.txt";
  
      var ourFileContent = "I like Toll Roads. I have an EZ-Pass!";
      var theirFileContent = "I'm skeptical about Toll Roads";
  
      var ourSignature = NodeGit.Signature.create
      ("Ron Paul", "RonPaul@TollRoadsRBest.info", 123456789, 60);
      var theirSignature = NodeGit.Signature.create
      ("Greg Abbott", "Gregggg@IllTollYourFace.us", 123456789, 60);
  
      var repository = this.repository;
      var ourCommit;
      var theirCommit;
      var ourBranch;
      var theirBranch;
  
      return fse.writeFile(
        path.join(repository.workdir(), ourFileName),
        ourFileContent)
      // Load up the repository index and make our initial commit to HEAD
      .then(function() {
        return repository.refreshIndex();
      })
      .then(function(index) {
        return index.addByPath(ourFileName)
          .then(function() {
            return index.write();
          })
          .then(function() {
            return index.writeTree();
          });
      })
      .then(function(oid) {
        assert.equal(oid.toString(),
        "11ead82b1135b8e240fb5d61e703312fb9cc3d6a");
  
        return repository.createCommit("HEAD", ourSignature,
        ourSignature, "we made a commit", oid, []);
      })
      .then(function(commitOid) {
        assert.equal(commitOid.toString(),
        "91a183f87842ebb7a9b08dad8bc2473985796844");
  
        return repository.getCommit(commitOid).then(function(commit) {
          ourCommit = commit;
        }).then(function() {
          return repository.createBranch(ourBranchName, commitOid)
          .then(function(branch) {
            ourBranch = branch;
            return repository.createBranch(theirBranchName, commitOid);
          });
        });
      })
      .then(function(branch) {
        theirBranch = branch;
        return fse.writeFile(path.join(repository.workdir(), theirFileName),
        theirFileContent);
      })
      .then(function() {
        return repository.refreshIndex();
      })
      .then(function(index) {
        return index.addByPath(theirFileName)
          .then(function() {
            return index.write();
          })
          .then(function() {
            return index.writeTree();
          });
      })
      .then(function(oid) {
        assert.equal(oid.toString(),
        "76631cb5a290dafe2959152626bb90f2a6d8ec94");
  
        return repository.createCommit(theirBranch.name(), theirSignature,
        theirSignature, "they made a commit", oid, [ourCommit]);
      })
      .then(function(commitOid) {
        assert.equal(commitOid.toString(),
        "0e9231d489b3f4303635fc4b0397830da095e7e7");
  
        return repository.getCommit(commitOid).then(function(commit) {
          theirCommit = commit;
        });
      })
      .then(function() {
        var opts = {checkoutStrategy: NodeGit.Checkout.STRATEGY.FORCE};
        return repository.checkoutBranch(ourBranchName, opts);
      })
      .then(function() {
        return repository.mergeBranches(
          ourBranchName,
          theirBranchName,
          ourSignature,
          NodeGit.Merge.PREFERENCE.FASTFORWARD_ONLY);
      })
      .then(function(oid) {
        assert.equal(oid.toString(),
        "0e9231d489b3f4303635fc4b0397830da095e7e7");
  
        return repository.getBranchCommit(ourBranchName)
          .then(function(branchCommit) {
            assert.equal(oid.toString(), branchCommit.toString());
          });
      })
      .then(function() {
        return repository.getStatus();
      })
      .then(function(statuses) {
        // make sure we didn't change the index
        assert.equal(statuses.length, 0);
      });
    });
  
    it("doesn't merge --ff-only a non-fast-forward using the convenience method",
      function() {
      var initialFileName = "initialFile.txt";
      var ourFileName = "ourNewFile.txt";
      var theirFileName = "theirNewFile.txt";
  
      var initialFileContent = "I'd like to drive somewhere";
      var ourFileContent = "I like Toll Roads. I have an EZ-Pass!";
      var theirFileContent = "I'm skeptical about Toll Roads";
  
      var ourSignature = NodeGit.Signature.create
      ("Ron Paul", "RonPaul@TollRoadsRBest.info", 123456789, 60);
      var theirSignature = NodeGit.Signature.create
      ("Greg Abbott", "Gregggg@IllTollYourFace.us", 123456789, 60);
  
      var repository = this.repository;
      var initialCommit;
      var ourCommit;
      var theirCommit;
      var ourBranch;
      var theirBranch;
  
      return fse.writeFile(
        path.join(repository.workdir(), initialFileName),
        initialFileContent)
      // Load up the repository index and make our initial commit to HEAD
      .then(function() {
        return repository.refreshIndex();
      })
      .then(function(index) {
        return index.addByPath(initialFileName)
          .then(function() {
            return index.write();
          })
          .then(function() {
            return index.writeTree();
          });
      })
      .then(function(oid) {
        assert.equal(oid.toString(),
        "21a553813e2f670815b649eef51eeadb253a5d0c");
  
        return repository.createCommit("HEAD", ourSignature,
        ourSignature, "initial commit", oid, []);
      })
      .then(function(commitOid) {
        assert.equal(commitOid.toString(),
        "af66a9c799a10a23319ee4318c8bb2021521f539");
  
        return repository.getCommit(commitOid).then(function(commit) {
          initialCommit = commit;
        }).then(function() {
          return repository.createBranch(ourBranchName, commitOid)
          .then(function(branch) {
            ourBranch = branch;
            return repository.createBranch(theirBranchName, commitOid);
          });
        });
      })
      .then(function(branch) {
        theirBranch = branch;
      })
      .then(function() {
        return fse.writeFile(path.join(repository.workdir(), ourFileName),
        ourFileContent);
      })
      .then(function() {
        return repository.refreshIndex();
      })
      .then(function(index) {
        return index.addByPath(ourFileName)
          .then(function() {
            return index.write();
          })
          .then(function() {
            return index.writeTree();
          });
      })
      .then(function(oid) {
        assert.equal(oid.toString(),
        "af60aa06b3537f75b427f6268a130c842c84a137");
  
        return repository.createCommit(ourBranch.name(), ourSignature,
          ourSignature, "we made a commit", oid, [initialCommit]);
      })
      .then(function(commitOid) {
        assert.equal(commitOid.toString(),
          "7ce31c05427659986d50abfb90c8f7db88ef4fa1");
  
        return repository.getCommit(commitOid).then(function(commit) {
          ourCommit = commit;
        });
      })
      .then(function() {
        return fse.writeFile(path.join(repository.workdir(), theirFileName),
        theirFileContent);
      })
      .then(function() {
        return repository.refreshIndex();
      })
      .then(function(index) {
        return index.addByPath(theirFileName)
          .then(function() {
            return index.write();
          })
          .then(function() {
            return index.writeTree();
          });
      })
      .then(function(oid) {
        assert.equal(oid.toString(),
        "f007361737a2ca00a0e80fc2daf55064463173b4");
  
        return repository.createCommit(theirBranch.name(), theirSignature,
        theirSignature, "they made a commit", oid, [initialCommit]);
      })
      .then(function(commitOid) {
        assert.equal(commitOid.toString(),
        "b588f0eef1809226f8f7db542940749da15ae1de");
  
        return repository.getCommit(commitOid).then(function(commit) {
          theirCommit = commit;
        });
      })
      .then(function() {
        var opts = {checkoutStrategy: NodeGit.Checkout.STRATEGY.FORCE};
        return repository.checkoutBranch(ourBranchName, opts);
      })
      .then(function() {
        return repository.mergeBranches(
          ourBranchName,
          theirBranchName,
          ourSignature,
          NodeGit.Merge.PREFERENCE.FASTFORWARD_ONLY);
      })
      .then(function(commitId) {
        assert.equal(commitId.toString(),
        "7ce31c05427659986d50abfb90c8f7db88ef4fa1");
      })
      .then(function() {
        return repository.getStatus();
      })
      .then(function(statuses) {
        // make sure we didn't change the index
        assert.equal(statuses.length, 0);
      });
    });
  
    it("can merge cleanly using the convenience method", function() {
      var initialFileName = "initialFile.txt";
      var ourFileName = "ourNewFile.txt";
      var theirFileName = "theirNewFile.txt";
  
      var initialFileContent = "I'd like to drive somewhere";
      var ourFileContent = "I like Toll Roads. I have an EZ-Pass!";
      var theirFileContent = "I'm skeptical about Toll Roads";
  
      var ourSignature = NodeGit.Signature.create
      ("Ron Paul", "RonPaul@TollRoadsRBest.info", 123456789, 60);
      var theirSignature = NodeGit.Signature.create
      ("Greg Abbott", "Gregggg@IllTollYourFace.us", 123456789, 60);
  
      var repository = this.repository;
      var initialCommit;
      var ourCommit;
      var theirCommit;
      var ourBranch;
      var theirBranch;
  
      return fse.writeFile(
        path.join(repository.workdir(), initialFileName),
        initialFileContent)
      // Load up the repository index and make our initial commit to HEAD
      .then(function() {
        return repository.refreshIndex();
      })
      .then(function(index) {
        return index.addByPath(initialFileName)
          .then(function() {
            return index.write();
          })
          .then(function() {
            return index.writeTree();
          });
      })
      .then(function(oid) {
        assert.equal(oid.toString(),
        "21a553813e2f670815b649eef51eeadb253a5d0c");
  
        return repository.createCommit("HEAD", ourSignature,
        ourSignature, "initial commit", oid, []);
      })
      .then(function(commitOid) {
        assert.equal(commitOid.toString(),
        "af66a9c799a10a23319ee4318c8bb2021521f539");
  
        return repository.getCommit(commitOid).then(function(commit) {
          initialCommit = commit;
        }).then(function() {
          return repository.createBranch(ourBranchName, commitOid)
          .then(function(branch) {
            ourBranch = branch;
            return repository.createBranch(theirBranchName, commitOid);
          });
        });
      })
      .then(function(branch) {
        theirBranch = branch;
      })
      .then(function() {
        return fse.writeFile(path.join(repository.workdir(), ourFileName),
        ourFileContent);
      })
      .then(function() {
        return repository.refreshIndex();
      })
      .then(function(index) {
        return index.addByPath(ourFileName)
          .then(function() {
            return index.write();
          })
          .then(function() {
            return index.writeTree();
          });
      })
      .then(function(oid) {
        assert.equal(oid.toString(),
        "af60aa06b3537f75b427f6268a130c842c84a137");
  
        return repository.createCommit(ourBranch.name(), ourSignature,
          ourSignature, "we made a commit", oid, [initialCommit]);
      })
      .then(function(commitOid) {
        assert.equal(commitOid.toString(),
          "7ce31c05427659986d50abfb90c8f7db88ef4fa1");
  
        return repository.getCommit(commitOid).then(function(commit) {
          ourCommit = commit;
        });
      })
      .then(function() {
        return fse.writeFile(path.join(repository.workdir(), theirFileName),
        theirFileContent);
      })
      .then(function() {
        return repository.refreshIndex();
      })
      .then(function(index) {
        return index.addByPath(theirFileName)
          .then(function() {
            return index.write();
          })
          .then(function(){
            return index.writeTree();
          });
      })
      .then(function(oid) {
        assert.equal(oid.toString(),
        "f007361737a2ca00a0e80fc2daf55064463173b4");
  
        return repository.createCommit(theirBranch.name(), theirSignature,
        theirSignature, "they made a commit", oid, [initialCommit]);
      })
      .then(function(commitOid) {
        assert.equal(commitOid.toString(),
        "b588f0eef1809226f8f7db542940749da15ae1de");
  
        return repository.getCommit(commitOid).then(function(commit) {
          theirCommit = commit;
        });
      })
      .then(function() {
        return repository.mergeBranches(ourBranchName, theirBranchName,
          ourSignature);
      })
      .then(function(commitId) {
        assert.equal(commitId.toString(),
        "5384feb481d9c29081b3a0c1478fcc24a3953efa");
      });
    });
  
    it("can merge 2 branchs with conflicts on a single file", function () {
      var baseFileContent = "All Bobs are created equal. ish.\n";
      var ourFileContent = "Big Bobs are best, IMHO.\n";
      var theirFileContent = "Nobody expects the small Bobquisition!\n";
      var finalFileContent =
        "Big Bobs are beautiful, and the small are unexpected!\n";
  
      var baseSignature = NodeGit.Signature.create
            ("Peaceful Bob", "justchill@bob.net", 123456789, 60);
      var ourSignature = NodeGit.Signature.create
            ("Big Bob", "impressive@bob.net", 123456789, 60);
      var theirSignature = NodeGit.Signature.create
            ("Small Bob", "underestimated@bob.net", 123456789, 60);
  
      var repository = this.repository;
      var baseCommit;
      var baseCommitOid;
      var ourCommit;
      var theirCommit;
      var ourBranch;
      var theirBranch;
      var fileName = "newFile.txt";
  
      return fse.writeFile(path.join(repository.workdir(), fileName),
        baseFileContent)
        .then(function() {
          return repository.refreshIndex();
        })
        .then(function(index) {
          return index.addByPath(fileName)
            .then(function() {
              return index.write();
            })
            .then(function() {
              return index.writeTree();
            });
        })
        .then(function(oid) {
          assert.equal(oid.toString(),
            "ea2f6521fb8097a881f43796946ac1603e1f4d75");
  
          return repository.createCommit("HEAD", baseSignature,
          baseSignature, "bobs are all ok", oid, []);
        })
        .then(function(commitOid) {
          assert.equal(commitOid.toString(),
            "a9b202f7612273fb3a68f718304298704eaeb735");
          baseCommitOid = commitOid;
  
          return repository.getCommit(commitOid).then(function(commit) {
            baseCommit = commit;
          });
        })
        .then(function() {
          return repository.createBranch(ourBranchName, baseCommitOid)
            .then(function(branch) {
              ourBranch = branch;
            });
        })
        .then(function() {
          return repository.createBranch(theirBranchName, baseCommitOid)
            .then(function(branch) {
              theirBranch = branch;
            });
        })
        .then(function() {
          return fse.writeFile(path.join(repository.workdir(), fileName),
            ourFileContent);
        })
        .then(function() {
          return repository.refreshIndex();
        })
        .then(function(index) {
          return index.addByPath(fileName)
            .then(function() {
              return index.write();
            })
            .then(function() {
              return index.writeTree();
            });
        })
        .then(function(oid) {
          assert.equal(oid.toString(),
            "c39b1e38b09085856cec7e7ff33e90f5a537d8a5");
  
          return repository.createCommit(ourBranch.name(), ourSignature,
            ourSignature, "lol big bobs :yesway:", oid, [baseCommit]);
        })
        .then(function(commitOid) {
          assert.equal(commitOid.toString(),
            "935a89c09ad757a9dde2c0257f6f1e379f71816f");
  
          return repository.getCommit(commitOid).then(function(commit) {
            ourCommit = commit;
          });
        })
        .then(function() {
          return fse.writeFile(path.join(repository.workdir(), fileName),
            theirFileContent);
        })
        .then(function() {
          return repository.refreshIndex();
        })
        .then(function(index) {
          return index.addByPath(fileName)
            .then(function() {
              return index.write();
            })
            .then(function() {
              return index.writeTree();
            });
        })
        .then(function(oid) {
          assert.equal(oid.toString(),
            "d1a894a9a4a8c820eb66c82cdd7e6b76c8f713cb");
  
          return repository.createCommit(theirBranch.name(), theirSignature,
            theirSignature, "lol big bobs :poop:", oid, [baseCommit]);
        })
        .then(function(commitOid) {
          assert.equal(commitOid.toString(),
            "bebb9ec2e0684c7cb7c1e1601c7d5a8f52b8b123");
  
          return repository.getCommit(commitOid).then(function(commit) {
            theirCommit = commit;
          });
        })
        .then(function() {
          return NodeGit.Reference.lookup(repository, "HEAD")
            .then(function(head) {
              return head.symbolicSetTarget(ourBranch.name(), "");
            });
        })
        .then(function() {
          return NodeGit.Merge.commits(repository, ourCommit, theirCommit, null);
        })
        .then(function(index) {
          assert(index.hasConflicts());
          fse.writeFileSync(path.join(repository.workdir(), fileName),
            finalFileContent);
        })
        .then(function() {
          return repository.refreshIndex();
        })
        .then(function(index) {
          return index.addByPath(fileName)
            .then(function() {
              return index.write();
            })
            .then(function() {
              return index.writeTree();
            });
        })
        .then(function(oid) {
          assert.equal(oid.toString(),
            "b1cd49a27cd33b99ab6dad2fb82b3174812a8b47");
  
          return repository.createCommit(ourBranch.name(), baseSignature,
            baseSignature, "Stop this bob sized fued", oid,
            [ourCommit, theirCommit]);
        })
        .then(function(commitId) {
          assert.equal(commitId.toString(),
            "49014ccabf5125f9b69316acde36f891dfdb8b5c");
        });
    });
  
    it("leaves repo in MERGE state after a standard merge with conflicts fails",
    function() {
      var fileName = "everyonesFile.txt";
  
      var baseFileContent = "How do you feel about Toll Roads?\n";
      var ourFileContent = "I like Toll Roads. I have an EZ-Pass!\n";
      var theirFileContent = "I'm skeptical about Toll Roads\n";
  
      var expectedConflictedFileContent =
        "How do you feel about Toll Roads?\n" +
        "<<<<<<< HEAD\n" +
        "I like Toll Roads. I have an EZ-Pass!\n" +
        "=======\n" +
        "I'm skeptical about Toll Roads\n" +
        ">>>>>>> theirs\n";
  
      var conflictSolvedFileContent =
        "How do you feel about Toll Roads?\n" +
        "He's skeptical about Toll Roads,\n" +
        "but I like Toll Roads. I have an EZ-Pass!\n";
  
      var ourSignature = NodeGit.Signature.create
            ("Ron Paul", "RonPaul@TollRoadsRBest.info", 123456789, 60);
      var theirSignature = NodeGit.Signature.create
            ("Greg Abbott", "Gregggg@IllTollYourFace.us", 123456789, 60);
  
      var repository = this.repository;
      var initialCommit;
      var ourBranch;
      var theirBranch;
  
      var repoGitPath = repository.path();
      if (!~repoGitPath.indexOf("/.git")) {
        repoGitPath = path.join(repoGitPath, ".git");
      }
  
      return fse.writeFile(path.join(repository.workdir(), fileName),
        baseFileContent)
        .then(function() {
          return repository.refreshIndex();
        })
        .then(function(index) {
          return index.addByPath(fileName)
            .then(function() {
              return index.write();
            })
            .then(function() {
              return index.writeTree();
            });
        })
        .then(function(oid) {
          assert.equal(oid.toString(),
            "044704f62399fecbe22da6d7d47b14e52625630e");
  
          return repository.createCommit("HEAD", ourSignature,
            ourSignature, "initial commit", oid, []);
        })
        .then(function(commitOid) {
          assert.equal(commitOid.toString(),
            "80111c46ac73b857a3493b24c81df08639b5de99");
  
          return repository.getCommit(commitOid).then(function(commit) {
            initialCommit = commit;
          }).then(function() {
            return repository.createBranch(ourBranchName, commitOid)
              .then(function(branch) {
                ourBranch = branch;
                return repository.createBranch(theirBranchName, commitOid);
              });
          });
        })
        .then(function(branch) {
          theirBranch = branch;
          return fse.writeFile(path.join(repository.workdir(), fileName),
            baseFileContent + theirFileContent);
        })
        .then(function() {
          return repository.refreshIndex();
        })
        .then(function(index) {
          return index.addByPath(fileName)
            .then(function() {
              return index.write();
            })
            .then(function() {
              return index.writeTree();
            });
        })
        .then(function(oid) {
          assert.equal(oid.toString(),
            "b826e989aca7647bea64810f0a2a38acbbdd4c1a");
  
          return repository.createCommit(theirBranch.name(), theirSignature,
            theirSignature, "they made a commit", oid, [initialCommit]);
        })
        .then(function(commitOid) {
          assert.equal(commitOid.toString(),
            "b3c355bb606ec7da87174dfa1a0b0c0e3dc97bc0");
  
          return fse.writeFile(path.join(repository.workdir(), fileName),
            baseFileContent + ourFileContent);
        })
        .then(function() {
          return repository.refreshIndex();
        })
        .then(function(index) {
          return index.addByPath(fileName)
            .then(function() {
              return index.write();
            })
            .then(function() {
              return index.writeTree();
            });
        })
        .then(function(oid) {
          assert.equal(oid.toString(),
            "e7fe41bf7c0c28766887a63ffe2f03f624276fbe");
  
            return repository.createCommit(ourBranch.name(), ourSignature,
              ourSignature, "we made a commit", oid, [initialCommit]);
        })
        .then(function(commitOid) {
          assert.equal(commitOid.toString(),
            "28cfeb17f66132edb3c4dacb7ff38e8dd48a1844");
  
          //return repository.getCommit(commitOid)
  
          var opts = {
            checkoutStrategy: NodeGit.Checkout.STRATEGY.FORCE
          };
  
          return repository.checkoutBranch(ourBranchName, opts);
        })
        .then(function() {
          return repository.getHeadCommit();
        })
        .then(function(commit) {
          assert.equal(commit.id().toString(),
            "28cfeb17f66132edb3c4dacb7ff38e8dd48a1844");
  
          return repository.getReference(theirBranchName);
        })
        .then(function(theirRef) {
          return NodeGit.AnnotatedCommit.fromRef(repository, theirRef);
        })
        .then(function(theirAnnotatedCommit) {
          return NodeGit.Merge(repository, theirAnnotatedCommit);
        })
        .then(function(result) {
          assert.equal(result, 0);
  
          assert.equal(repository.state(),
            NodeGit.Repository.STATE.MERGE);
          // verify the convenience method
          assert.ok(repository.isMerging());
  
          assert.ok(fse.existsSync(path.join(repoGitPath, "MERGE_HEAD")));
          assert.ok(fse.existsSync(path.join(repoGitPath, "MERGE_MSG")));
          assert.ok(fse.existsSync(path.join(repoGitPath, "MERGE_MODE")));
  
          return fse.readFile(path.join(repoGitPath, "MERGE_HEAD"), "utf-8");
        })
        .then(function(mergeHeadContents) {
          assert.equal(mergeHeadContents,
            "b3c355bb606ec7da87174dfa1a0b0c0e3dc97bc0\n");
  
          return fse.readFile(path.join(repository.workdir(), fileName), "utf-8");
        })
        .then(function(fileContent) {
          assert.equal(fileContent, expectedConflictedFileContent);
  
          return fse.writeFile(path.join(repository.workdir(), fileName),
            conflictSolvedFileContent);
        })
        .then(function() {
          return repository.refreshIndex();
        })
        .then(function(index) {
          return index.addByPath(fileName)
            .then(function() {
              return index.write();
            })
            .then(function() {
              return index.writeTree();
            });
        })
        .then(function(oid) {
          return Promise.all([
            repository.getBranchCommit(ourBranchName),
            repository.getBranchCommit("MERGE_HEAD")
          ])
            .then(function(commits) {
              var msg = fse.readFileSync(path.join(repoGitPath, "MERGE_MSG"),
                "utf-8");
              assert.ok(msg);
  
              return repository.createCommit(ourBranch.name(), ourSignature,
                ourSignature, msg, oid, [commits[0], commits[1]]);
            });
        })
        .then(function(commitOid) {
          assert.equal(commitOid.toString(),
            "03ba156a7a1660f179b6b2dbc6a542fcf88d022d");
  
          // merge isn't cleaned up automatically
          assert.ok(fse.existsSync(path.join(repoGitPath, "MERGE_HEAD")));
          assert.ok(fse.existsSync(path.join(repoGitPath, "MERGE_MSG")));
          assert.ok(fse.existsSync(path.join(repoGitPath, "MERGE_MODE")));
  
          assert.equal(repository.stateCleanup(), 0);
  
          assert.ok(!fse.existsSync(path.join(repoGitPath, "MERGE_HEAD")));
          assert.ok(!fse.existsSync(path.join(repoGitPath, "MERGE_MSG")));
          assert.ok(!fse.existsSync(path.join(repoGitPath, "MERGE_MODE")));
  
          assert.equal(repository.state(),
            NodeGit.Repository.STATE.NONE);
          // verify the convenience method
          assert.ok(repository.isDefaultState());
        });
    });
  });
  