diff --git a/LibGit2Sharp.Tests/MergeFixture.cs b/LibGit2Sharp.Tests/MergeFixture.cs index 7b1fda718..484128a25 100644 --- a/LibGit2Sharp.Tests/MergeFixture.cs +++ b/LibGit2Sharp.Tests/MergeFixture.cs @@ -669,6 +669,54 @@ public void CanSpecifyConflictFileStrategy(CheckoutFileConflictStrategy conflict } } + [Theory] + [InlineData(CheckoutFileConflictStrategy.Merge)] + [InlineData(CheckoutFileConflictStrategy.Diff3)] + [InlineData(CheckoutFileConflictStrategy.ZDiff3)] + public void CanSpecifyMergeConflictFileStrategy(CheckoutFileConflictStrategy conflictStrategy) + { + const string conflictFile = "a.txt"; + const string expectedFileFormat = "a.{0}.txt"; + const string conflictBranchName = "conflicts"; + const string resultsBranchName = "results"; + + string expectedFileName = string.Format(expectedFileFormat, conflictStrategy.ToString().ToLower()); + string path = SandboxMergeConflictTestRepo(); + + using (var repo = new Repository(path)) + { + Branch branch = repo.Branches[conflictBranchName]; + Assert.NotNull(branch); + + // Ensure the working directory is clean before merging + repo.Reset(ResetMode.Hard); + repo.RemoveUntrackedFiles(); + + 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); + + Commit expectedCommit = repo.Branches[resultsBranchName].Tip; + Blob expectedBlob = (Blob)expectedCommit[expectedFileName].Target; + string expectedContent = expectedBlob.GetContentText(new FilteringOptions(expectedFileName)); + + // Verify the content of the file on disk contains conflict markers. + string fileContent = File.ReadAllText(Path.Combine(repo.Info.WorkingDirectory, conflictFile)); + Assert.Equal(expectedContent, fileContent); + } + } + [Theory] [InlineData(MergeFileFavor.Ours)] [InlineData(MergeFileFavor.Theirs)] diff --git a/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/a.txt b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/a.txt new file mode 100644 index 000000000..ac92cd6c0 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/a.txt @@ -0,0 +1,7 @@ +A +B +C +D +E +F +G \ No newline at end of file diff --git a/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/HEAD b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/HEAD new file mode 100644 index 000000000..b870d8262 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/main diff --git a/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/config b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/config new file mode 100644 index 000000000..8ad0b1bad --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/config @@ -0,0 +1,6 @@ +[core] + repositoryformatversion = 0 + filemode = false + bare = false + logallrefupdates = true + ignorecase = true diff --git a/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/index b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/index new file mode 100644 index 000000000..36023028e Binary files /dev/null and b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/index differ diff --git a/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/info/refs b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/info/refs new file mode 100644 index 000000000..c02e5d754 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/info/refs @@ -0,0 +1,3 @@ +cd4b13da8859445f4357c1e24d92b483ffe2dc85 refs/heads/conflicts +0076e9fe99d1c2df56cd939a897db42d714b088b refs/heads/main +139641856b0ef7941f583972614c1df9bb26939b refs/heads/results diff --git a/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/info/commit-graph b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/info/commit-graph new file mode 100644 index 000000000..f561a0815 Binary files /dev/null and b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/info/commit-graph differ diff --git a/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/info/packs b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/info/packs new file mode 100644 index 000000000..dd0211e7e --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/info/packs @@ -0,0 +1,3 @@ +P pack-5fd168964fc34fdc1e4a50ae098e21799dd906a4.pack +P pack-9ea8f8acf571abc3f715ea91223671d542aacb6c.pack + diff --git a/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/pack/pack-5fd168964fc34fdc1e4a50ae098e21799dd906a4.idx b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/pack/pack-5fd168964fc34fdc1e4a50ae098e21799dd906a4.idx new file mode 100644 index 000000000..775aec8e7 Binary files /dev/null and b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/pack/pack-5fd168964fc34fdc1e4a50ae098e21799dd906a4.idx differ diff --git a/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/pack/pack-5fd168964fc34fdc1e4a50ae098e21799dd906a4.pack b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/pack/pack-5fd168964fc34fdc1e4a50ae098e21799dd906a4.pack new file mode 100644 index 000000000..1cf4cb9ea Binary files /dev/null and b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/pack/pack-5fd168964fc34fdc1e4a50ae098e21799dd906a4.pack differ diff --git a/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/pack/pack-5fd168964fc34fdc1e4a50ae098e21799dd906a4.rev b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/pack/pack-5fd168964fc34fdc1e4a50ae098e21799dd906a4.rev new file mode 100644 index 000000000..e640dbcea Binary files /dev/null and b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/pack/pack-5fd168964fc34fdc1e4a50ae098e21799dd906a4.rev differ diff --git a/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/pack/pack-9ea8f8acf571abc3f715ea91223671d542aacb6c.idx b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/pack/pack-9ea8f8acf571abc3f715ea91223671d542aacb6c.idx new file mode 100644 index 000000000..718705056 Binary files /dev/null and b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/pack/pack-9ea8f8acf571abc3f715ea91223671d542aacb6c.idx differ diff --git a/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/pack/pack-9ea8f8acf571abc3f715ea91223671d542aacb6c.mtimes b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/pack/pack-9ea8f8acf571abc3f715ea91223671d542aacb6c.mtimes new file mode 100644 index 000000000..8717541c1 Binary files /dev/null and b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/pack/pack-9ea8f8acf571abc3f715ea91223671d542aacb6c.mtimes differ diff --git a/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/pack/pack-9ea8f8acf571abc3f715ea91223671d542aacb6c.pack b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/pack/pack-9ea8f8acf571abc3f715ea91223671d542aacb6c.pack new file mode 100644 index 000000000..a1a8cc755 Binary files /dev/null and b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/pack/pack-9ea8f8acf571abc3f715ea91223671d542aacb6c.pack differ diff --git a/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/pack/pack-9ea8f8acf571abc3f715ea91223671d542aacb6c.rev b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/pack/pack-9ea8f8acf571abc3f715ea91223671d542aacb6c.rev new file mode 100644 index 000000000..fa4458d12 Binary files /dev/null and b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/objects/pack/pack-9ea8f8acf571abc3f715ea91223671d542aacb6c.rev differ diff --git a/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/packed-refs b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/packed-refs new file mode 100644 index 000000000..2848696a9 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/mergeconflict_testrepo_wd/dot_git/packed-refs @@ -0,0 +1,4 @@ +# pack-refs with: peeled fully-peeled sorted +cd4b13da8859445f4357c1e24d92b483ffe2dc85 refs/heads/conflicts +0076e9fe99d1c2df56cd939a897db42d714b088b refs/heads/main +139641856b0ef7941f583972614c1df9bb26939b refs/heads/results diff --git a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs index e9429d562..1f24f4f98 100644 --- a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs +++ b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs @@ -36,6 +36,7 @@ static BaseFixture() public static string ShallowTestRepoPath { get; private set; } public static string MergedTestRepoWorkingDirPath { get; private set; } public static string MergeTestRepoWorkingDirPath { get; private set; } + public static string MergeConflictTestRepoWorkingDirPath { get; private set; } public static string MergeRenamesTestRepoWorkingDirPath { get; private set; } public static string RevertTestRepoWorkingDirPath { get; private set; } public static string SubmoduleTestRepoWorkingDirPath { get; private set; } @@ -81,6 +82,7 @@ private static void SetUpTestEnvironment() MergedTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "mergedrepo_wd"); MergeRenamesTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "mergerenames_wd"); MergeTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "merge_testrepo_wd"); + MergeConflictTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "mergeconflict_testrepo_wd"); RevertTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "revert_testrepo_wd"); SubmoduleTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "submodule_wd"); SubmoduleTargetTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "submodule_target_wd"); @@ -201,6 +203,11 @@ protected string SandboxMergeTestRepo() return Sandbox(MergeTestRepoWorkingDirPath); } + protected string SandboxMergeConflictTestRepo() + { + return Sandbox(MergeConflictTestRepoWorkingDirPath); + } + protected string SandboxRevertTestRepo() { return Sandbox(RevertTestRepoWorkingDirPath); diff --git a/LibGit2Sharp/CheckoutFileConflictStrategy.cs b/LibGit2Sharp/CheckoutFileConflictStrategy.cs index 9d53745e7..29726517a 100644 --- a/LibGit2Sharp/CheckoutFileConflictStrategy.cs +++ b/LibGit2Sharp/CheckoutFileConflictStrategy.cs @@ -33,6 +33,11 @@ public enum CheckoutFileConflictStrategy /// /// Write diff3 formated files for conflicts. /// - Diff3 + Diff3, + + /// + /// Write zdiff3 formated files for conflicts. + /// + ZDiff3 } } diff --git a/LibGit2Sharp/Core/GitCheckoutOpts.cs b/LibGit2Sharp/Core/GitCheckoutOpts.cs index 053258565..56592e612 100644 --- a/LibGit2Sharp/Core/GitCheckoutOpts.cs +++ b/LibGit2Sharp/Core/GitCheckoutOpts.cs @@ -105,6 +105,11 @@ internal enum CheckoutStrategy /// GIT_CHECKOUT_DONT_WRITE_INDEX = (1 << 23), + /// + /// Include common ancestor data in zdiff3 format for conflicts + /// + GIT_CHECKOUT_CONFLICT_STYLE_ZDIFF3 = (1 << 25), + // THE FOLLOWING OPTIONS ARE NOT YET IMPLEMENTED /// diff --git a/LibGit2Sharp/Core/GitCheckoutOptsWrapper.cs b/LibGit2Sharp/Core/GitCheckoutOptsWrapper.cs index 0fba82754..56adcb243 100644 --- a/LibGit2Sharp/Core/GitCheckoutOptsWrapper.cs +++ b/LibGit2Sharp/Core/GitCheckoutOptsWrapper.cs @@ -78,6 +78,10 @@ internal static CheckoutStrategy CheckoutStrategyFromFileConflictStrategy(Checko case CheckoutFileConflictStrategy.Diff3: flags = CheckoutStrategy.GIT_CHECKOUT_CONFLICT_STYLE_DIFF3; break; + + case CheckoutFileConflictStrategy.ZDiff3: + flags = CheckoutStrategy.GIT_CHECKOUT_CONFLICT_STYLE_ZDIFF3; + break; } return flags; diff --git a/LibGit2Sharp/Core/GitMergeOpts.cs b/LibGit2Sharp/Core/GitMergeOpts.cs index 48675a2d0..5f823e133 100644 --- a/LibGit2Sharp/Core/GitMergeOpts.cs +++ b/LibGit2Sharp/Core/GitMergeOpts.cs @@ -194,5 +194,10 @@ internal enum GitMergeFileFlag /// Take extra time to find minimal diff /// GIT_MERGE_FILE_DIFF_MINIMAL = (1 << 7), + + /// + /// Create zdiff3 ("zealous diff3")-style files + /// + GIT_MERGE_FILE_STYLE_ZDIFF3 = (1 << 8), } }