public void Check_BiDirectionality_Attach_Parent_To_Child() { Company company = CreateCompany(CompanyCreationType.NO_CHILDREN); // Attach parent to child // ReSharper disable once ObjectCreationAsStatement new CompanyIdentification { Identification = "1", Company = company }; Assert.AreEqual(1, company.Identifications.Count); foreach (CompanyIdentification identification in company.Identifications) { Assert.IsTrue(identification.IsTransient); } Company savedCompany = Repository.Merge(company); Assert.AreEqual(2, savedCompany.PersistenceVersion); Assert.AreEqual(1, savedCompany.Identifications.Count); foreach (CompanyIdentification identification in savedCompany.Identifications) { Assert.IsFalse(identification.IsTransient); } }
public void MergeCanDetectRenames() { // The environment is set up such that: // file b.txt is edited in the "rename" branch and // edited and renamed in the "rename_source" branch. // The edits are automergable. // We can rename "rename_source" into "rename" // if rename detection is enabled, // but the merge will fail with conflicts if this // change is not detected as a rename. string repoPath = SandboxMergeTestRepo(); using (var repo = new Repository(repoPath)) { Branch currentBranch = Commands.Checkout(repo, "rename_source"); Assert.NotNull(currentBranch); Branch branchToMerge = repo.Branches["rename"]; MergeResult result = repo.Merge(branchToMerge, Constants.Signature); Assert.Equal(MergeStatus.NonFastForward, result.Status); } }
internal static void Checkout(string repository, string branch, CheckoutModifiers mods = CheckoutModifiers.Force) { try { Log.InfoFormat("Checkout[{0}] {1}", branch, repository); using (var repo = new Repository(repository)) { if (IsValidBranch(repo.Branches[branch])) { repo.Merge(repo.Branches[branch], new Signature(Config.Instance.Username, Config.Instance.Username + "@joduska.me", DateTimeOffset.Now), new MergeOptions { FileConflictStrategy = CheckoutFileConflictStrategy.Theirs }); repo.Checkout(branch, new CheckoutOptions { CheckoutModifiers = mods }); } else { Log.WarnFormat("Branch[{0}] not found in {1}", branch, repository); } } } catch (Exception e) { Log.Warn(e); } }
/// <summary> /// Merges changes from a branch into the current HEAD of the repository /// </summary> /// <param name="path"></param> /// <param name="baseBranch"></param> /// <param name="mergeBranch"></param> /// <param name="name"></param> /// <param name="email"></param> /// <returns></returns> public bool Merge(string path, string mergeBranch, string name, string email) { if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(email)) { SetError("Commit failed: Git requires a commit name and email address."); return(false); } var repo = OpenRepository(path); if (repo == null) { return(false); } try { var sig = new Signature(name, email, DateTimeOffset.UtcNow); var branch = Repository.Branches[mergeBranch]; Repository.Merge(branch, sig); } catch (Exception ex) { SetError($"Failed to merge {mergeBranch}: {ex.Message}."); return(false); } return(true); }
public void Merge(string branchName) { using (var repo = new Repository(Path)) { repo.Merge(repo.Branches[branchName], Signature); } }
public void CanMergeIntoOrphanedBranch() { string path = CloneMergeTestRepo(); using (var repo = new Repository(path)) { repo.Refs.Add("HEAD", "refs/heads/orphan", true); // Remove entries from the working directory foreach (var entry in repo.Index.RetrieveStatus()) { repo.Index.Unstage(entry.FilePath); repo.Index.Remove(entry.FilePath, true); } // Assert that we have an empty working directory. Assert.False(repo.Index.RetrieveStatus().Any()); MergeResult result = repo.Merge("master", Constants.Signature); Assert.Equal(MergeStatus.FastForward, result.Status); Assert.Equal(masterBranchInitialId, result.Commit.Id.Sha); Assert.False(repo.Index.RetrieveStatus().Any()); } }
public void UpdateRepo() { loadRepo(); if (!(repo.Head?.IsTracking ?? false)) { throw new Exception("Cannot update while not on a tracked branch"); } Fetch(); var trackedBranch = repo.Head.TrackedBranch; var originalCommit = repo.Head.Tip; if (repo.Head.Commits.Count(c => c.Sha == trackedBranch.Tip.Sha) != 0) { logger.LogInformation("Repository is up to date"); return; } var mergeResult = repo.Merge(trackedBranch, getSignature()); switch (mergeResult.Status) { case MergeStatus.FastForward: case MergeStatus.NonFastForward: logger.LogInformation("Repository has been update successfully."); break; case MergeStatus.Conflicts: repo.Reset(ResetMode.Hard, originalCommit); throw new Exception("Merge introduced merge conflicts, please reset and try again."); default: break; } // TODO: Stage a update }
public void MergeWithTracked() { using (var repo = new Repository(Path)) { repo.Merge(repo.Head.TrackedBranch, Signature); } }
private static Branch ChangeCoreVersion(Repository repo, string cvStr, string nvStr, IEnumerable <Branch> modBranches) { Branch mergeBranch = MergeMods(repo, cvStr, modBranches); Branch nvBranch = repo.Branches[GetCoreBranchName(nvStr)]; repo.Merge(nvBranch, _sig, new MergeOptions { CommitOnSuccess = false, FindRenames = true, FileConflictStrategy = CheckoutFileConflictStrategy.Merge }); foreach (Conflict cnf in repo.Index.Conflicts) { // TODO // Conflict resolution: // If conflict is between CORE prev and CORE curr, prefer CORE curr // Else, prefer mergeBranch } repo.Commit("Stellaris version change: " + cvStr + " to " + nvStr, _sig, _sig, _cmtOpts); // TODO: Return new core branch // TODO: Only do mod merges as a final step // 1: Branch mods from their target versions // 2: Merge mods from the same target versions together // 3: Merge merged branches together // 4: If final CORE version is not the target version, merge with the CORE for that version return(mergeBranch); }
protected Company CreateFailedCompany(CompanyCreationType companyCreationType) { Company company = CreateCompany(companyCreationType); // ReSharper disable once ObjectCreationAsStatement new FailedCompany { FailingDate = Now, Company = company }; Company savedCompany; using (ITransaction trans = Session.BeginTransaction(IsolationLevel.ReadCommitted)) { savedCompany = Repository.Merge(company); trans.Commit(); } Session.Clear(); Assert.AreNotSame(company, savedCompany); Assert.IsNotNull(savedCompany.FailedCompany); Assert.IsTrue(savedCompany.IsFailed); return(savedCompany); }
public void Check_BiDirectionality_Add_Childs_To_Parent() { Company company = CreateCompany(CompanyCreationType.NO_CHILDREN); // Add child CompanyIdentification companyIdentification = new CompanyIdentification { Identification = "1" }; company.AddIdentification(companyIdentification); CompanyIdentification companyIdentification2 = new CompanyIdentification { Identification = "1" }; company.AddIdentification(companyIdentification2); Assert.AreEqual(2, company.Identifications.Count); foreach (CompanyIdentification identification in company.Identifications) { Assert.IsTrue(identification.IsTransient); } Company savedCompany = Repository.Merge(company); Assert.AreEqual(2, savedCompany.PersistenceVersion); Assert.AreEqual(2, savedCompany.Identifications.Count); foreach (CompanyIdentification identification in savedCompany.Identifications) { Assert.IsFalse(identification.IsTransient); } }
public bool Merge(BranchLabelModel merged) { Signature s = GetCurrentSignature(); MergeResult r = Repository.Merge(merged.Branch, s); return(r.Status != MergeStatus.Conflicts); }
public void Check_BiDirectionality_FailedCompany_Add_FailedCompany_To_Company2() { Company company = CreateCompany(CompanyCreationType.NO_CHILDREN); Company mergedCompany; using (ITransaction trans = Session.BeginTransaction(IsolationLevel.ReadCommitted)) { // 1. Attach company to session mergedCompany = Repository.Merge(company); // 2. Add FailedCompany // ReSharper disable once ObjectCreationAsStatement new FailedCompany { FailingDate = Now, Company = mergedCompany }; trans.Commit(); } // 4. Clear session Session.Clear(); // 5. Check Db status Company selectedCompany = Repository.GetById(mergedCompany.Id); Assert.IsNotNull(selectedCompany.FailedCompany); Assert.IsTrue(selectedCompany.IsFailed); }
public void Check_BiDirectionality_FailedCompany_Remove_FailedCompany_From_Company() { Company company = CreateFailedCompany(CompanyCreationType.NO_CHILDREN); Company mergedCompany; using (ITransaction trans = Session.BeginTransaction(IsolationLevel.ReadCommitted)) { // 1. Attach company to session mergedCompany = Repository.Merge(company); // 2. Remove FailedCompany FailedCompany failedCompany = mergedCompany.FailedCompany; mergedCompany.FailedCompany = null; // Due cascading delete isn't supported for one-to-one relation, // see https://nhibernate.jira.com/browse/NH-1262 FailedCompanyRepository.Delete(failedCompany); trans.Commit(); } // 4. Clear session Session.Clear(); // 5. Check Db status Company selectedCompany = Repository.GetById(mergedCompany.Id); Assert.IsNull(selectedCompany.FailedCompany); Assert.IsFalse(selectedCompany.IsFailed); }
public void Check_BiDirectionality_Remove_Childs_From_Parent() { Company company = CreateCompany(CompanyCreationType.WITH_2_CHILDREN); Company mergedCompany; using (ITransaction trans = Session.BeginTransaction(IsolationLevel.ReadCommitted)) { // 1. Attach company to session mergedCompany = Repository.Merge(company); // 2. Remove companyIdentification 1 foreach (CompanyIdentification identification in mergedCompany.Identifications.ToList()) { mergedCompany.RemoveIdentification(identification); } trans.Commit(); } // 4. Clear session Session.Clear(); // 5. Check Db status Company selectedCompany = Repository.GetById(mergedCompany.Id); Assert.IsFalse(selectedCompany.Identifications.Any()); }
public void Check_BiDirectionality_Remove_Child_From_Parent() { Company company = CreateCompany(CompanyCreationType.WITH_2_CHILDREN); Company mergedCompany; using (ITransaction trans = Session.BeginTransaction(IsolationLevel.ReadCommitted)) { // 1. Attach company to session mergedCompany = Repository.Merge(company); // 2. Remove companyIdentification 1 CompanyIdentification companyIdentification = mergedCompany .Identifications .SingleOrDefault(i => i.Identification == "1"); Assert.IsNotNull(companyIdentification); mergedCompany.RemoveIdentification(companyIdentification); trans.Commit(); } // 4. Clear session Session.Clear(); // 5. Check Db status Company selectedCompany = Repository.GetById(mergedCompany.Id); Assert.AreEqual(1, selectedCompany.Identifications.Count); }
public void CanFollowFirstParent() { string path = SandboxStandardTestRepo(); using (var repo = new Repository(path)) { var branch = repo.CreateBranch("branch"); // Make an earlier tag on master repo.Commit("A", Constants.Signature, Constants.Signature, new CommitOptions { AllowEmptyCommit = true }); repo.ApplyTag("firstParentTag"); // Make a later tag on branch Commands.Checkout(repo, branch); repo.Commit("B", Constants.Signature, Constants.Signature, new CommitOptions { AllowEmptyCommit = true }); repo.ApplyTag("mostRecentTag"); Commands.Checkout(repo, "master"); repo.Commit("C", Constants.Signature, Constants.Signature, new CommitOptions { AllowEmptyCommit = true }); repo.Merge(branch, Constants.Signature, new MergeOptions() { FastForwardStrategy = FastForwardStrategy.NoFastForward }); // With OnlyFollowFirstParent = false, the most recent tag reachable should be returned Assert.Equal("mostRecentTag-3-gf17be71", repo.Describe(repo.Head.Tip, new DescribeOptions { OnlyFollowFirstParent = false, Strategy = DescribeStrategy.Tags })); // With OnlyFollowFirstParent = true, the most recent tag on the current branch should be returned Assert.Equal("firstParentTag-2-gf17be71", repo.Describe(repo.Head.Tip, new DescribeOptions { OnlyFollowFirstParent = true, Strategy = DescribeStrategy.Tags })); } }
/// <returns>false if nothing needed to be merged, true if the merge was done. Throws exception if there is an error.</returns> private bool MergeTwoChangeSets(Revision head, Revision theirHead) { string chorusMergeFilePath = Path.Combine(ExecutionEnvironment.DirectoryOfExecutingAssembly, "ChorusMerge.exe"); #if MONO // The replace is only useful for use with the MonoDevelop environment whcih doesn't honor $(Configuration) in the csproj files. // When this is exported as an environment var it needs escaping to prevent the shell from replacing it with an empty string. // When MonoDevelop is fixed this can be removed. chorusMergeFilePath = chorusMergeFilePath.Replace("$(Configuration)", "\\$(Configuration)"); #endif using (new ShortTermEnvironmentalVariable("HGMERGE", '"' + chorusMergeFilePath + '"')) { // Theory has it that is a tossup on who ought to win, unless there is some more principled way to decide. // If 'they' end up being the right answer, or if it ends up being more exotic, // then be sure to change the alpha and beta info in the MergeSituation class. //using (new ShortTermEnvironmentalVariable(MergeOrder.kConflictHandlingModeEnvVarName, MergeOrder.ConflictHandlingModeChoices.TheyWin.ToString())) // Go with 'WeWin', since that is the default and that is how the alpha and beta data of MergeSituation is set, right before this method is called. using (new ShortTermEnvironmentalVariable(MergeOrder.kConflictHandlingModeEnvVarName, MergeOrder.ConflictHandlingModeChoices.WeWin.ToString())) { var didMerge = Repository.Merge(_localRepositoryPath, theirHead.Number.LocalRevisionNumber); FailureSimulator.IfTestRequestsItThrowNow("SychronizerAdjunct"); return(didMerge); } } }
private void btnMerge_Click(object sender, EventArgs e) { using (var repo = new Repository(fbdGitFolder.SelectedPath)) { Signature merger = new Signature("Tester", "*****@*****.**", DateTime.Now); repo.Merge(repo.Branches[cbBranches.Text], merger); } }
public MergeResult Merge(string commitish) { var commit = _repository.Lookup <Commit>(commitish); if (commit == null) { throw new GitTfsException("error: commit '" + commitish + "' can't be found and merged into!"); } return(_repository.Merge(commit, _repository.Config.BuildSignature(new DateTimeOffset(DateTime.Now)))); }
public void CanFastForwardRepos(bool shouldMergeOccurInDetachedHeadState) { const string firstBranchFileName = "first branch file.txt"; const string sharedBranchFileName = "first+second branch file.txt"; string path = CloneStandardTestRepo(); using (var repo = new Repository(path)) { // Reset the index and the working tree. repo.Reset(ResetMode.Hard); // Clean the working directory. repo.RemoveUntrackedFiles(); var firstBranch = repo.CreateBranch("FirstBranch"); firstBranch.Checkout(); // Commit with ONE new file to both first & second branch (SecondBranch is created on this commit). AddFileCommitToRepo(repo, sharedBranchFileName); var secondBranch = repo.CreateBranch("SecondBranch"); // Commit with ONE new file to first branch (FirstBranch moves forward as it is checked out, SecondBranch stays back one). AddFileCommitToRepo(repo, firstBranchFileName); if (shouldMergeOccurInDetachedHeadState) { // Detaches HEAD repo.Checkout(secondBranch.Tip); } else { secondBranch.Checkout(); } Assert.Equal(shouldMergeOccurInDetachedHeadState, repo.Info.IsHeadDetached); MergeResult mergeResult = repo.Merge(repo.Branches["FirstBranch"].Tip, Constants.Signature); Assert.Equal(MergeStatus.FastForward, mergeResult.Status); Assert.Equal(repo.Branches["FirstBranch"].Tip, mergeResult.Commit); Assert.Equal(repo.Branches["FirstBranch"].Tip, repo.Head.Tip); Assert.Equal(repo.Head.Tip, mergeResult.Commit); Assert.Equal(0, repo.Index.RetrieveStatus().Count()); Assert.Equal(shouldMergeOccurInDetachedHeadState, repo.Info.IsHeadDetached); if (!shouldMergeOccurInDetachedHeadState) { // Ensure HEAD is still attached and points to SecondBranch Assert.Equal(repo.Refs.Head.TargetIdentifier, secondBranch.CanonicalName); } } }
public void MergeCanSpecifyMergeFileFavorOption(MergeFileFavor fileFavorFlag) { const string conflictFile = "a.txt"; const string conflictBranchName = "conflicts"; string path = SandboxMergeTestRepo(); using (var repo = new Repository(path)) { Branch branch = repo.Branches[conflictBranchName]; Assert.NotNull(branch); MergeOptions mergeOptions = new MergeOptions() { MergeFileFavor = fileFavorFlag, }; MergeResult result = repo.Merge(branch, Constants.Signature, mergeOptions); Assert.Equal(MergeStatus.NonFastForward, result.Status); // Verify that the index and working directory are clean Assert.True(repo.Index.IsFullyMerged); Assert.False(repo.RetrieveStatus().IsDirty); // Get the blob containing the expected content. Blob expectedBlob = null; switch (fileFavorFlag) { case MergeFileFavor.Theirs: expectedBlob = repo.Lookup <Blob>("3dd9738af654bbf1c363f6c3bbc323bacdefa179"); break; case MergeFileFavor.Ours: expectedBlob = repo.Lookup <Blob>("610b16886ca829cebd2767d9196f3c4378fe60b5"); break; default: throw new Exception("Unexpected MergeFileFavor"); } Assert.NotNull(expectedBlob); // Verify the index has the expected contents IndexEntry entry = repo.Index[conflictFile]; Assert.NotNull(entry); Assert.Equal(expectedBlob.Id, entry.Id); // Verify the content of the file on disk matches what is expected. string expectedContent = expectedBlob.GetContentText(new FilteringOptions(conflictFile)); Assert.Equal(expectedContent, File.ReadAllText(Path.Combine(repo.Info.WorkingDirectory, conflictFile))); } }
public void CanForceFastForwardMergeThroughConfig() { string path = SandboxMergeTestRepo(); using (var repo = new Repository(path)) { repo.Config.Set("merge.ff", "only"); Commit commitToMerge = repo.Branches["normal_merge"].Tip; Assert.Throws <NonFastForwardException>(() => repo.Merge(commitToMerge, Constants.Signature, new MergeOptions())); } }
public void FastForwardNonFastForwardableMergeThrows() { string path = CloneMergeTestRepo(); using (var repo = new Repository(path)) { Commit commitToMerge = repo.Branches["normal_merge"].Tip; Assert.Throws <NonFastForwardException>(() => repo.Merge(commitToMerge, Constants.Signature, new MergeOptions() { FastForwardStrategy = FastForwardStrategy.FastForwardOnly })); } }
private MergeResult CheckoutAndMerge(Branch sourceBranch, Branch targetBranch) { Commands.Checkout(repo, sourceBranch); var mo = new MergeOptions() { CommitOnSuccess = false, FastForwardStrategy = FastForwardStrategy.NoFastForward }; var result = repo.Merge(targetBranch, new Signature("test", "*****@*****.**", DateTimeOffset.Now), mo); return(result); }
/// <summary> /// Merge branch into current branch. /// </summary> /// <param name="username">The user username.</param> /// <param name="email">The user email.</param> /// <param name="branchName">The branch to merge from.</param> public static void Merge(string username, string email, string branchName) { try { using (var repo = new Repository(repoPath)) { repo.Merge(repo.Branches[branchName], new Signature(username, email, new DateTimeOffset(DateTime.Now))); } } catch (Exception e) { Debug.Log("Error on pull : " + e.Message); } }
public void CanSpecifyConflictFileStrategy(CheckoutFileConflictStrategy conflictStrategy) { const string conflictFile = "a.txt"; const string conflictBranchName = "conflicts"; string path = SandboxMergeTestRepo(); using (var repo = new Repository(path)) { Branch branch = repo.Branches[conflictBranchName]; Assert.NotNull(branch); MergeOptions mergeOptions = new MergeOptions() { FileConflictStrategy = conflictStrategy, }; MergeResult result = repo.Merge(branch, Constants.Signature, mergeOptions); Assert.Equal(MergeStatus.Conflicts, result.Status); // Get the information on the conflict. Conflict conflict = repo.Index.Conflicts[conflictFile]; Assert.NotNull(conflict); Assert.NotNull(conflict.Theirs); Assert.NotNull(conflict.Ours); // Get the blob containing the expected content. Blob expectedBlob = null; switch (conflictStrategy) { case CheckoutFileConflictStrategy.Theirs: expectedBlob = repo.Lookup <Blob>(conflict.Theirs.Id); break; case CheckoutFileConflictStrategy.Ours: expectedBlob = repo.Lookup <Blob>(conflict.Ours.Id); break; default: throw new Exception("Unexpected FileConflictStrategy"); } Assert.NotNull(expectedBlob); // Check the content of the file on disk matches what is expected. string expectedContent = expectedBlob.GetContentText(new FilteringOptions(conflictFile)); Assert.Equal(expectedContent, File.ReadAllText(Path.Combine(repo.Info.WorkingDirectory, conflictFile))); } }
/// <returns>false if nothing needed to be merged, true if the merge was done. Throws exception if there is an error.</returns> private bool MergeTwoChangeSets(Revision head, Revision theirHead) { // Theory has it that is a tossup on who ought to win, unless there is some more principled way to decide. // If 'they' end up being the right answer, or if it ends up being more exotic, // then be sure to change the alpha and beta info in the MergeSituation class. //using (new ShortTermEnvironmentalVariable(MergeOrder.kConflictHandlingModeEnvVarName, MergeOrder.ConflictHandlingModeChoices.TheyWin.ToString())) // Go with 'WeWin', since that is the default and that is how the alpha and beta data of MergeSituation is set, right before this method is called. using (new ShortTermEnvironmentalVariable(MergeOrder.kConflictHandlingModeEnvVarName, MergeOrder.ConflictHandlingModeChoices.WeWin.ToString())) { var didMerge = Repository.Merge(_localRepositoryPath, theirHead.Number.LocalRevisionNumber); FailureSimulator.IfTestRequestsItThrowNow("SychronizerAdjunct"); return(didMerge); } }
public void CanMergeRepoNonFastForward(bool shouldMergeOccurInDetachedHeadState) { const string firstBranchFileName = "first branch file.txt"; const string secondBranchFileName = "second branch file.txt"; const string sharedBranchFileName = "first+second branch file.txt"; string path = CloneStandardTestRepo(); using (var repo = new Repository(path)) { var firstBranch = repo.CreateBranch("FirstBranch"); firstBranch.Checkout(); var originalTreeCount = firstBranch.Tip.Tree.Count; // Commit with ONE new file to both first & second branch (SecondBranch is created on this commit). AddFileCommitToRepo(repo, sharedBranchFileName); var secondBranch = repo.CreateBranch("SecondBranch"); // Commit with ONE new file to first branch (FirstBranch moves forward as it is checked out, SecondBranch stays back one). AddFileCommitToRepo(repo, firstBranchFileName); if (shouldMergeOccurInDetachedHeadState) { // Detaches HEAD repo.Checkout(secondBranch.Tip); } else { secondBranch.Checkout(); } // Commit with ONE new file to second branch (FirstBranch and SecondBranch now point to separate commits that both have the same parent commit). AddFileCommitToRepo(repo, secondBranchFileName); MergeResult mergeResult = repo.Merge(repo.Branches["FirstBranch"].Tip, Constants.Signature); Assert.Equal(MergeStatus.NonFastForward, mergeResult.Status); Assert.Equal(repo.Head.Tip, mergeResult.Commit); Assert.Equal(originalTreeCount + 3, mergeResult.Commit.Tree.Count); // Expecting original tree count plussed by the 3 added files. Assert.Equal(2, mergeResult.Commit.Parents.Count()); // Merge commit should have 2 parents Assert.Equal(shouldMergeOccurInDetachedHeadState, repo.Info.IsHeadDetached); if (!shouldMergeOccurInDetachedHeadState) { // Ensure HEAD is still attached and points to SecondBranch Assert.Equal(repo.Refs.Head.TargetIdentifier, secondBranch.CanonicalName); } } }
public void CanMergeCommittish(string committish, FastForwardStrategy strategy, MergeStatus expectedMergeStatus) { string path = CloneMergeTestRepo(); using (var repo = new Repository(path)) { MergeResult result = repo.Merge(committish, Constants.Signature, new MergeOptions() { FastForwardStrategy = strategy }); Assert.Equal(expectedMergeStatus, result.Status); Assert.False(repo.Index.RetrieveStatus().Any()); } }
public void CanFailOnFirstMergeConflict() { string path = SandboxMergeTestRepo(); using (var repo = new Repository(path)) { var mergeResult = repo.Merge("conflicts", Constants.Signature, new MergeOptions() { FailOnConflict = true, }); Assert.Equal(MergeStatus.Conflicts, mergeResult.Status); var master = repo.Branches["master"]; var branch = repo.Branches["conflicts"]; var mergeTreeResult = repo.ObjectDatabase.MergeCommits(master.Tip, branch.Tip, new MergeTreeOptions() { FailOnConflict = true }); Assert.Equal(MergeTreeStatus.Conflicts, mergeTreeResult.Status); Assert.Empty(mergeTreeResult.Conflicts); } }
public void CanConflictOnWhitespaceChangeMergeConflict(string branchName) { string path = SandboxMergeTestRepo(); using (var repo = new Repository(path)) { var mergeResult = repo.Merge(branchName, Constants.Signature, new MergeOptions()); Assert.Equal(MergeStatus.Conflicts, mergeResult.Status); var master = repo.Branches["master"]; var branch = repo.Branches[branchName]; var mergeTreeResult = repo.ObjectDatabase.MergeCommits(master.Tip, branch.Tip, new MergeTreeOptions()); Assert.Equal(MergeTreeStatus.Conflicts, mergeTreeResult.Status); } }
public void CanFastForwardCommit(bool fromDetachedHead, FastForwardStrategy fastForwardStrategy, string expectedCommitId, MergeStatus expectedMergeStatus) { string path = CloneMergeTestRepo(); using (var repo = new Repository(path)) { if(fromDetachedHead) { repo.Checkout(repo.Head.Tip.Id.Sha); } Commit commitToMerge = repo.Branches["fast_forward"].Tip; MergeResult result = repo.Merge(commitToMerge, Constants.Signature, new MergeOptions() { FastForwardStrategy = fastForwardStrategy }); Assert.Equal(expectedMergeStatus, result.Status); Assert.Equal(expectedCommitId, result.Commit.Id.Sha); Assert.False(repo.Index.RetrieveStatus().Any()); Assert.Equal(fromDetachedHead, repo.Info.IsHeadDetached); } }
public void FastForwardNonFastForwardableMergeThrows() { string path = CloneMergeTestRepo(); using (var repo = new Repository(path)) { Commit commitToMerge = repo.Branches["normal_merge"].Tip; Assert.Throws<NonFastForwardException>(() => repo.Merge(commitToMerge, Constants.Signature, new MergeOptions() { FastForwardStrategy = FastForwardStrategy.FastForwardOnly })); } }
public void MergeWithWorkDirConflictsThrows(bool shouldStage, FastForwardStrategy strategy) { // Merging the fast_forward branch results in a change to file // b.txt. In this test we modify the file in the working directory // and then attempt to perform a merge. We expect the merge to fail // due to merge conflicts. string committishToMerge = "fast_forward"; using (var repo = new Repository(SandboxMergeTestRepo())) { Touch(repo.Info.WorkingDirectory, "b.txt", "this is an alternate change"); if (shouldStage) { repo.Stage("b.txt"); } Assert.Throws<MergeConflictException>(() => repo.Merge(committishToMerge, Constants.Signature, new MergeOptions() { FastForwardStrategy = strategy })); } }
public void MergeReportsCheckoutProgress() { string repoPath = CloneMergeTestRepo(); using (var repo = new Repository(repoPath)) { Commit commitToMerge = repo.Branches["normal_merge"].Tip; bool wasCalled = false; MergeOptions options = new MergeOptions() { OnCheckoutProgress = (path, completed, total) => wasCalled = true, }; MergeResult result = repo.Merge(commitToMerge, Constants.Signature, options); Assert.True(wasCalled); } }
public void MergeCanDetectRenames() { // The environment is set up such that: // file b.txt is edited in the "rename" branch and // edited and renamed in the "rename_source" branch. // The edits are automergable. // We can rename "rename_source" into "rename" // if rename detection is enabled, // but the merge will fail with conflicts if this // change is not detected as a rename. string repoPath = CloneMergeTestRepo(); using (var repo = new Repository(repoPath)) { Branch currentBranch = repo.Checkout("rename_source"); Assert.NotNull(currentBranch); Branch branchToMerge = repo.Branches["rename"]; MergeResult result = repo.Merge(branchToMerge, Constants.Signature); Assert.Equal(MergeStatus.NonFastForward, result.Status); } }
public void CanForceNonFastForwardMergeThroughConfig() { string path = CloneMergeTestRepo(); using (var repo = new Repository(path)) { repo.Config.Set("merge.ff", "false"); Commit commitToMerge = repo.Branches["fast_forward"].Tip; MergeResult result = repo.Merge(commitToMerge, Constants.Signature, new MergeOptions()); Assert.Equal(MergeStatus.NonFastForward, result.Status); Assert.Equal("f58f780d5a0ae392efd4a924450b1bbdc0577d32", result.Commit.Id.Sha); Assert.False(repo.Index.RetrieveStatus().Any()); } }
public void CanForceFastForwardMergeThroughConfig() { string path = CloneMergeTestRepo(); using (var repo = new Repository(path)) { repo.Config.Set("merge.ff", "only"); Commit commitToMerge = repo.Branches["normal_merge"].Tip; Assert.Throws<NonFastForwardException>(() => repo.Merge(commitToMerge, Constants.Signature, new MergeOptions())); } }
public void MergeCanSpecifyMergeFileFavorOption(MergeFileFavor fileFavorFlag) { const string conflictFile = "a.txt"; const string conflictBranchName = "conflicts"; string path = SandboxMergeTestRepo(); using (var repo = new Repository(path)) { Branch branch = repo.Branches[conflictBranchName]; Assert.NotNull(branch); MergeOptions mergeOptions = new MergeOptions() { MergeFileFavor = fileFavorFlag, }; MergeResult result = repo.Merge(branch, Constants.Signature, mergeOptions); Assert.Equal(MergeStatus.NonFastForward, result.Status); // Verify that the index and working directory are clean Assert.True(repo.Index.IsFullyMerged); Assert.False(repo.RetrieveStatus().IsDirty); // Get the blob containing the expected content. Blob expectedBlob = null; switch (fileFavorFlag) { case MergeFileFavor.Theirs: expectedBlob = repo.Lookup<Blob>("3dd9738af654bbf1c363f6c3bbc323bacdefa179"); break; case MergeFileFavor.Ours: expectedBlob = repo.Lookup<Blob>("610b16886ca829cebd2767d9196f3c4378fe60b5"); break; default: throw new Exception("Unexpected MergeFileFavor"); } Assert.NotNull(expectedBlob); // Verify the index has the expected contents IndexEntry entry = repo.Index[conflictFile]; Assert.NotNull(entry); Assert.Equal(expectedBlob.Id, entry.Id); // Verify the content of the file on disk matches what is expected. string expectedContent = expectedBlob.GetContentText(new FilteringOptions(conflictFile)); Assert.Equal(expectedContent, File.ReadAllText(Path.Combine(repo.Info.WorkingDirectory, conflictFile))); } }
public void CanMergeAndNotCommit() { string path = CloneMergeTestRepo(); using (var repo = new Repository(path)) { Commit commitToMerge = repo.Branches["normal_merge"].Tip; MergeResult result = repo.Merge(commitToMerge, Constants.Signature, new MergeOptions() { CommitOnSuccess = false}); Assert.Equal(MergeStatus.NonFastForward, result.Status); Assert.Equal(null, result.Commit); RepositoryStatus repoStatus = repo.Index.RetrieveStatus(); // Verify that there is a staged entry. Assert.Equal(1, repoStatus.Count()); Assert.Equal(FileStatus.Staged, repo.Index.RetrieveStatus("b.txt")); } }
public void IsUpToDateMerge() { const string sharedBranchFileName = "first+second branch file.txt"; string path = CloneStandardTestRepo(); using (var repo = new Repository(path)) { var firstBranch = repo.CreateBranch("FirstBranch"); firstBranch.Checkout(); // Commit with ONE new file to both first & second branch (SecondBranch is created on this commit). AddFileCommitToRepo(repo, sharedBranchFileName); var secondBranch = repo.CreateBranch("SecondBranch"); secondBranch.Checkout(); MergeResult mergeResult = repo.Merge(repo.Branches["FirstBranch"].Tip, Constants.Signature); Assert.Equal(MergeStatus.UpToDate, mergeResult.Status); } }
public void MergeReportsCheckoutNotifications() { string repoPath = CloneMergeTestRepo(); using (var repo = new Repository(repoPath)) { Commit commitToMerge = repo.Branches["normal_merge"].Tip; bool wasCalled = false; CheckoutNotifyFlags actualNotifyFlags = CheckoutNotifyFlags.None; MergeOptions options = new MergeOptions() { OnCheckoutNotify = (path, notificationType) => { wasCalled = true; actualNotifyFlags = notificationType; return true; }, CheckoutNotifyFlags = CheckoutNotifyFlags.Updated, }; MergeResult result = repo.Merge(commitToMerge, Constants.Signature, options); Assert.True(wasCalled); Assert.Equal(CheckoutNotifyFlags.Updated, actualNotifyFlags); } }
public void CanMergeBranch(string branchName, FastForwardStrategy strategy, MergeStatus expectedMergeStatus) { string path = SandboxMergeTestRepo(); using (var repo = new Repository(path)) { Branch branch = repo. Branches[branchName]; MergeResult result = repo.Merge(branch, Constants.Signature, new MergeOptions() { FastForwardStrategy = strategy }); Assert.Equal(expectedMergeStatus, result.Status); Assert.False(repo.RetrieveStatus().Any()); } }
public void VerifyUpToDateMerge() { string path = CloneMergeTestRepo(); using (var repo = new Repository(path)) { Commit commitToMerge = repo.Branches["master"].Tip; MergeResult result = repo.Merge(commitToMerge, Constants.Signature, new MergeOptions() { FastForwardStrategy = FastForwardStrategy.NoFastFoward }); Assert.Equal(MergeStatus.UpToDate, result.Status); Assert.Equal(null, result.Commit); Assert.False(repo.Index.RetrieveStatus().Any()); } }
public void CanForceNonFastForwardMerge() { string path = SandboxMergeTestRepo(); using (var repo = new Repository(path)) { Commit commitToMerge = repo.Branches["fast_forward"].Tip; MergeResult result = repo.Merge(commitToMerge, Constants.Signature, new MergeOptions() { FastForwardStrategy = FastForwardStrategy.NoFastFoward }); Assert.Equal(MergeStatus.NonFastForward, result.Status); Assert.Equal("f58f780d5a0ae392efd4a924450b1bbdc0577d32", result.Commit.Id.Sha); Assert.False(repo.RetrieveStatus().Any()); } }
public void CanSpecifyConflictFileStrategy(CheckoutFileConflictStrategy conflictStrategy) { const string conflictFile = "a.txt"; const string conflictBranchName = "conflicts"; string path = CloneMergeTestRepo(); using (var repo = new Repository(path)) { Branch branch = repo.Branches[conflictBranchName]; Assert.NotNull(branch); MergeOptions mergeOptions = new MergeOptions() { FileConflictStrategy = conflictStrategy, }; MergeResult result = repo.Merge(branch, Constants.Signature, mergeOptions); Assert.Equal(MergeStatus.Conflicts, result.Status); // Get the information on the conflict. Conflict conflict = repo.Index.Conflicts[conflictFile]; Assert.NotNull(conflict); Assert.NotNull(conflict.Theirs); Assert.NotNull(conflict.Ours); // Get the blob containing the expected content. Blob expectedBlob = null; switch(conflictStrategy) { case CheckoutFileConflictStrategy.Theirs: expectedBlob = repo.Lookup<Blob>(conflict.Theirs.Id); break; case CheckoutFileConflictStrategy.Ours: expectedBlob = repo.Lookup<Blob>(conflict.Ours.Id); break; default: throw new Exception("Unexpected FileConflictStrategy"); } Assert.NotNull(expectedBlob); // Check the content of the file on disk matches what is expected. string expectedContent = expectedBlob.GetContentText(new FilteringOptions(conflictFile)); Assert.Equal(expectedContent, File.ReadAllText(Path.Combine(repo.Info.WorkingDirectory, conflictFile))); } }
public void CanNonFastForwardMergeCommit(bool fromDetachedHead, FastForwardStrategy fastForwardStrategy, MergeStatus expectedMergeStatus) { string path = SandboxMergeTestRepo(); using (var repo = new Repository(path)) { if (fromDetachedHead) { Commands.Checkout(repo, repo.Head.Tip.Id.Sha); } Commit commitToMerge = repo.Branches["normal_merge"].Tip; MergeResult result = repo.Merge(commitToMerge, Constants.Signature, new MergeOptions() { FastForwardStrategy = fastForwardStrategy }); Assert.Equal(expectedMergeStatus, result.Status); Assert.False(repo.RetrieveStatus().Any()); Assert.Equal(fromDetachedHead, repo.Info.IsHeadDetached); } }
public void ConflictingMergeReposBinary() { const string firstBranchFileName = "first branch file.bin"; const string secondBranchFileName = "second branch file.bin"; const string sharedBranchFileName = "first+second branch file.bin"; string path = CloneStandardTestRepo(); using (var repo = new Repository(path)) { var firstBranch = repo.CreateBranch("FirstBranch"); firstBranch.Checkout(); // Commit with ONE new file to both first & second branch (SecondBranch is created on this commit). AddFileCommitToRepo(repo, sharedBranchFileName); var secondBranch = repo.CreateBranch("SecondBranch"); // Commit with ONE new file to first branch (FirstBranch moves forward as it is checked out, SecondBranch stays back one). AddFileCommitToRepo(repo, firstBranchFileName); AddFileCommitToRepo(repo, sharedBranchFileName, "\0The first branches comment\0"); // Change file in first branch secondBranch.Checkout(); // Commit with ONE new file to second branch (FirstBranch and SecondBranch now point to separate commits that both have the same parent commit). AddFileCommitToRepo(repo, secondBranchFileName); AddFileCommitToRepo(repo, sharedBranchFileName, "\0The second branches comment\0"); // Change file in second branch MergeResult mergeResult = repo.Merge(repo.Branches["FirstBranch"].Tip, Constants.Signature); Assert.Equal(MergeStatus.Conflicts, mergeResult.Status); Assert.Equal(1, repo.Index.Conflicts.Count()); Conflict conflict = repo.Index.Conflicts.First(); var changes = repo.Diff.Compare(repo.Lookup<Blob>(conflict.Theirs.Id), repo.Lookup<Blob>(conflict.Ours.Id)); Assert.True(changes.IsBinaryComparison); } }
public void CanMergeIntoOrphanedBranch() { string path = CloneMergeTestRepo(); using (var repo = new Repository(path)) { repo.Refs.Add("HEAD", "refs/heads/orphan", true); // Remove entries from the working directory foreach(var entry in repo.Index.RetrieveStatus()) { repo.Index.Unstage(entry.FilePath); repo.Index.Remove(entry.FilePath, true); } // Assert that we have an empty working directory. Assert.False(repo.Index.RetrieveStatus().Any()); MergeResult result = repo.Merge("master", Constants.Signature); Assert.Equal(MergeStatus.FastForward, result.Status); Assert.Equal(masterBranchInitialId, result.Commit.Id.Sha); Assert.False(repo.Index.RetrieveStatus().Any()); } }
public void FastForwardMergeReportsCheckoutProgress() { string repoPath = SandboxMergeTestRepo(); using (var repo = new Repository(repoPath)) { Commit commitToMerge = repo.Branches["fast_forward"].Tip; bool wasCalled = false; MergeOptions options = new MergeOptions() { OnCheckoutProgress = (path, completed, total) => wasCalled = true, }; repo.Merge(commitToMerge, Constants.Signature, options); Assert.True(wasCalled); } }