From ddeea0c3e367919434ce6ed809a7f4514192c4f8 Mon Sep 17 00:00:00 2001
From: Jon Burggraaf <jon.burggraaf@metrics.ca>
Date: Fri, 6 May 2022 13:04:46 -0400
Subject: [PATCH] Make GIT_DIFF_SHOW_BINARY flag settable by users through
 CompareOptions

Give users access to GIT_DIFF_SHOW_BINARY flag through CompareOptions to allow Patch data to contain binary deltas.

Add 2 test cases to verify default behaviour has not changed and that when the new option is exercised patches contains binary delta info as expected
---
 LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs | 56 +++++++++++++++++++++
 LibGit2Sharp/CompareOptions.cs              |  6 +++
 LibGit2Sharp/Diff.cs                        |  5 ++
 3 files changed, 67 insertions(+)

diff --git a/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs b/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs
index 0fe7adee1..2d2fccb66 100644
--- a/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs
+++ b/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs
@@ -148,6 +148,62 @@ public void CanDetectABinaryDeletion()
             }
         }
 
+        [Fact]
+        public void CanProvideBinaryDeflateDeltaInfo()
+        {
+            using (var repo = new Repository(SandboxStandardTestRepo()))
+            {
+                const string filename = "newBin.file";
+                var filepath = Path.Combine(repo.Info.WorkingDirectory, filename);
+
+                CreateBinaryFile(filepath);
+
+                var compareOptions = new CompareOptions();
+                compareOptions.ShowBinary = true;                
+                using (Patch patch = repo.Diff.Compare<Patch>(repo.Commits.FirstOrDefault().Tree, DiffTargets.WorkingDirectory, null, null, compareOptions))
+                {
+                    var withBinaryDeltaDiff = new StringBuilder()
+                        .Append("diff --git a/newBin.file b/newBin.file\n")
+                        .Append("new file mode 100644\n")
+                        .Append("index 0000000000000000000000000000000000000000..689732707188cb8aedfe69d84c9536fd5655d814\n")
+                        .Append("GIT binary patch\n")
+                        .Append("literal 4000\n")
+                        .Append("dc%1FSF%19!3<IEc{zX^D9!O{|RaI40Uk|E93%LLQ\n\n")
+                        .Append("literal 0\n")
+                        .Append("Hc$@<O00001");
+
+                    Assert.True(patch[filename].IsBinaryComparison);
+                    Assert.Contains(withBinaryDeltaDiff.ToString(), patch[filename].Patch.Trim());
+                }
+
+            }
+        }
+
+        [Fact]
+        public void DoesNotProvideBinaryDeflateDeltaInfoByDefault()
+        {
+            using (var repo = new Repository(SandboxStandardTestRepo()))
+            {
+                const string filename = "newBin.file";
+                var filepath = Path.Combine(repo.Info.WorkingDirectory, filename);
+
+                CreateBinaryFile(filepath);
+
+                var compareOptions = new CompareOptions();
+                using (Patch patch = repo.Diff.Compare<Patch>(repo.Commits.FirstOrDefault().Tree, DiffTargets.WorkingDirectory, null, null, compareOptions))
+                {
+                    var noBinaryDeltaDiff = new StringBuilder()
+                        .Append("diff --git a/newBin.file b/newBin.file\n")
+                        .Append("new file mode 100644\n")
+                        .Append("index 0000000..6897327\n")
+                        .Append("Binary files /dev/null and b/newBin.file differ");
+
+                    Assert.True(patch[filename].IsBinaryComparison);
+                    Assert.Equal(noBinaryDeltaDiff.ToString(), patch[filename].Patch.Trim());
+                }
+            }
+        }
+
         /*
          * $ git diff 9fd738e..HEAD -- "1" "2/"
          * diff --git a/1/branch_file.txt b/1/branch_file.txt
diff --git a/LibGit2Sharp/CompareOptions.cs b/LibGit2Sharp/CompareOptions.cs
index fb4234439..784c00794 100644
--- a/LibGit2Sharp/CompareOptions.cs
+++ b/LibGit2Sharp/CompareOptions.cs
@@ -50,5 +50,11 @@ public CompareOptions()
         /// By default, this option will be false.
         /// </summary>
         public bool IndentHeuristic { get; set; }
+
+        /// <summary>
+        /// Include the necessary deflate / delta information so that `git-apply`
+        /// can apply given diff information to binary files.
+        /// </summary>
+        public bool ShowBinary { get; set; }
     }
 }
diff --git a/LibGit2Sharp/Diff.cs b/LibGit2Sharp/Diff.cs
index 087ee8d6d..efe98f2a4 100644
--- a/LibGit2Sharp/Diff.cs
+++ b/LibGit2Sharp/Diff.cs
@@ -63,6 +63,11 @@ private static GitDiffOptions BuildOptions(DiffModifiers diffOptions, FilePath[]
                 options.Flags |= GitDiffOptionFlags.GIT_DIFF_DISABLE_PATHSPEC_MATCH;
             }
 
+            if (compareOptions.ShowBinary)
+            {
+                options.Flags |= GitDiffOptionFlags.GIT_DIFF_SHOW_BINARY;
+            }
+
             if (compareOptions.IndentHeuristic)
             {
                 options.Flags |= GitDiffOptionFlags.GIT_DIFF_INDENT_HEURISTIC;