Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added lines and deleted lines in content changes #1790

32 changes: 30 additions & 2 deletions LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.IO;
using LibGit2Sharp.Tests.TestHelpers;
bording marked this conversation as resolved.
Show resolved Hide resolved
using System.IO;
using System.Linq;
using System.Text;
using LibGit2Sharp.Tests.TestHelpers;
using Xunit;

namespace LibGit2Sharp.Tests
Expand Down Expand Up @@ -202,6 +202,34 @@ public void ComparingBlobsWithNoSpacesIndentHeuristicOptionMakesNoDifference()
}
}

[Fact]
public void DiffSetsTheAddedAndDeletedLinesCorrectly()
{
var path = SandboxStandardTestRepoGitDir();

using (var repo = new Repository(path))
{
var oldContent =
@"1
2
3
4";

var newContent =
@"1
2
3
5";
var oldBlob = repo.ObjectDatabase.CreateBlob(new MemoryStream(Encoding.UTF8.GetBytes(oldContent)));
var newBlob = repo.ObjectDatabase.CreateBlob(new MemoryStream(Encoding.UTF8.GetBytes(newContent)));

ContentChanges changes = repo.Diff.Compare(oldBlob, newBlob);

Assert.Single(changes.AddedLines);
bording marked this conversation as resolved.
Show resolved Hide resolved
Assert.Single(changes.DeletedLines);
}
}

static string CanonicalChangedLines(ContentChanges changes)
{
// Create an ordered representation of lines that have been added or removed
Expand Down
24 changes: 22 additions & 2 deletions LibGit2Sharp.Tests/DiffTreeToTargetFixture.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using LibGit2Sharp.Tests.TestHelpers;
bording marked this conversation as resolved.
Show resolved Hide resolved
using System.IO;
using System.Linq;
using System.Text;
using LibGit2Sharp.Tests.TestHelpers;
using Xunit;

namespace LibGit2Sharp.Tests
Expand All @@ -17,7 +17,7 @@ private static void SetUpSimpleDiffContext(IRepository repo)

File.AppendAllText(fullpath, "world\n");

Commands.Stage(repo,fullpath);
Commands.Stage(repo, fullpath);

File.AppendAllText(fullpath, "!!!\n");
}
Expand Down Expand Up @@ -509,5 +509,25 @@ public void CanCompareANullTreeAgainstTheWorkdirAndTheIndex()
}
}
}

[Fact]
public void CompareSetsCorrectAddedAndDeletedLines()
{
string repoPath = InitNewRepository();

using (var repo = new Repository(repoPath))
{
SetUpSimpleDiffContext(repo);

using (var changes = repo.Diff.Compare<Patch>(repo.Head.Tip.Tree,
DiffTargets.WorkingDirectory | DiffTargets.Index))
{
foreach (var entry in changes)
{
Assert.Equal(2, entry.AddedLines.Count());
}
}
}
}
}
}
67 changes: 52 additions & 15 deletions LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
using System;
using LibGit2Sharp.Tests.TestHelpers;
bording marked this conversation as resolved.
Show resolved Hide resolved
using System;
using System.IO;
using System.Linq;
using System.Text;
using LibGit2Sharp.Tests.TestHelpers;
using Xunit;
using Xunit.Extensions;

namespace LibGit2Sharp.Tests
{
Expand All @@ -20,7 +19,7 @@ public void ComparingATreeAgainstItselfReturnsNoDifference()
{
Tree tree = repo.Head.Tip.Tree;

using(var changes = repo.Diff.Compare<TreeChanges>(tree, tree))
using (var changes = repo.Diff.Compare<TreeChanges>(tree, tree))
{
Assert.Empty(changes);
}
Expand Down Expand Up @@ -112,13 +111,13 @@ public void CanDetectABinaryChange()

File.AppendAllText(filepath, "abcdef");

using(var patch = repo.Diff.Compare<Patch>(commit.Tree, DiffTargets.WorkingDirectory, new[] { filename }))
using (var patch = repo.Diff.Compare<Patch>(commit.Tree, DiffTargets.WorkingDirectory, new[] { filename }))
Assert.True(patch[filename].IsBinaryComparison);

Commands.Stage(repo, filename);
var commit2 = repo.Commit("Update binary file", Constants.Signature, Constants.Signature);

using(var patch2 = repo.Diff.Compare<Patch>(commit.Tree, commit2.Tree, new[] { filename }))
using (var patch2 = repo.Diff.Compare<Patch>(commit.Tree, commit2.Tree, new[] { filename }))
Assert.True(patch2[filename].IsBinaryComparison);
}
}
Expand All @@ -138,13 +137,13 @@ public void CanDetectABinaryDeletion()

File.Delete(filepath);

using(var patch = repo.Diff.Compare<Patch>(commit.Tree, DiffTargets.WorkingDirectory, new [] {filename}))
using (var patch = repo.Diff.Compare<Patch>(commit.Tree, DiffTargets.WorkingDirectory, new[] { filename }))
Assert.True(patch[filename].IsBinaryComparison);

Commands.Remove(repo, filename);
var commit2 = repo.Commit("Delete binary file", Constants.Signature, Constants.Signature);

using(var patch2 = repo.Diff.Compare<Patch>(commit.Tree, commit2.Tree, new[] { filename }))
using (var patch2 = repo.Diff.Compare<Patch>(commit.Tree, commit2.Tree, new[] { filename }))
Assert.True(patch2[filename].IsBinaryComparison);
}
}
Expand Down Expand Up @@ -704,7 +703,7 @@ public void CanIncludeUnmodifiedEntriesWhenEnabled()
Touch(repo.Info.WorkingDirectory, "a.txt", "abc\ndef\n");
Touch(repo.Info.WorkingDirectory, "b.txt", "abc\ndef\n");

Commands.Stage(repo, new[] {"a.txt", "b.txt"});
Commands.Stage(repo, new[] { "a.txt", "b.txt" });
Commit old = repo.Commit("Initial", Constants.Signature, Constants.Signature);

File.AppendAllText(Path.Combine(repo.Info.WorkingDirectory, "b.txt"), "ghi\njkl\n");
Expand All @@ -728,12 +727,12 @@ public void CanDetectTheExactRenamingExactCopyingOfNonModifiedAndModifiedFilesWh
var path = Repository.Init(scd.DirectoryPath);
using (var repo = new Repository(path))
{
const string originalPath = "original.txt";
const string renamedPath = "renamed.txt";
const string originalPath = "original.txt";
const string renamedPath = "renamed.txt";
const string originalPath2 = "original2.txt";
const string copiedPath1 = "copied.txt";
const string copiedPath1 = "copied.txt";
const string originalPath3 = "original3.txt";
const string copiedPath2 = "copied2.txt";
const string copiedPath2 = "copied2.txt";

Touch(repo.Info.WorkingDirectory, originalPath, "a\nb\nc\nd\n");
Touch(repo.Info.WorkingDirectory, originalPath2, "1\n2\n3\n4\n");
Expand Down Expand Up @@ -986,7 +985,7 @@ public void CanHandleTwoTreeEntryChangesWithTheSamePathUsingSimilarityNone()
Assert.Single(changes.Deleted);
Assert.Single(changes.TypeChanged);

TreeEntryChanges change = changes.Single(c => c.Path== path);
TreeEntryChanges change = changes.Single(c => c.Path == path);
Assert.Equal(Mode.SymbolicLink, change.OldMode);
Assert.Equal(Mode.NonExecutableFile, change.Mode);
Assert.Equal(ChangeKind.TypeChanged, change.Status);
Expand Down Expand Up @@ -1087,7 +1086,7 @@ public void ComparingReliesOnProvidedConfigEntriesIfAny()
using (var repo = new Repository(path))
{
SetFilemode(repo, true);
using(var changes = repo.Diff.Compare<TreeChanges>(new[] { file }))
using (var changes = repo.Diff.Compare<TreeChanges>(new[] { file }))
{
Assert.Single(changes);

Expand Down Expand Up @@ -1147,6 +1146,44 @@ public void RetrievingDiffChangesMustAlwaysBeCaseSensitive()
}
}

[Fact]
public void RetrievingDiffContainsRightAmountOfAddedAndDeletedLines()
{
ObjectId treeOldOid, treeNewOid;

string repoPath = InitNewRepository();

using (var repo = new Repository(repoPath))
{
Blob oldContent = OdbHelper.CreateBlob(repo, "awesome content\n");
Blob newContent = OdbHelper.CreateBlob(repo, "more awesome content\n");

var td = new TreeDefinition()
.Add("A.TXT", oldContent, Mode.NonExecutableFile)
.Add("a.txt", oldContent, Mode.NonExecutableFile);

treeOldOid = repo.ObjectDatabase.CreateTree(td).Id;

td = new TreeDefinition()
.Add("A.TXT", newContent, Mode.NonExecutableFile)
.Add("a.txt", newContent, Mode.NonExecutableFile);

treeNewOid = repo.ObjectDatabase.CreateTree(td).Id;
}

using (var repo = new Repository(repoPath))
{
using (var changes = repo.Diff.Compare<Patch>(repo.Lookup<Tree>(treeOldOid), repo.Lookup<Tree>(treeNewOid)))
{
foreach (var entry in changes)
{
Assert.Single(entry.AddedLines);
Assert.Single(entry.DeletedLines);
}
}
}
}

[Fact]
public void UsingPatienceAlgorithmCompareOptionProducesPatienceDiff()
{
Expand Down
17 changes: 17 additions & 0 deletions LibGit2Sharp/ContentChanges.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Text;
Expand All @@ -22,6 +23,9 @@ protected ContentChanges()

internal unsafe ContentChanges(Repository repo, Blob oldBlob, Blob newBlob, GitDiffOptions options)
{
AddedLines = new List<Line>();
bording marked this conversation as resolved.
Show resolved Hide resolved
DeletedLines = new List<Line>();

Proxy.git_diff_blobs(repo.Handle,
oldBlob != null ? oldBlob.Id : null,
newBlob != null ? newBlob.Id : null,
Expand Down Expand Up @@ -51,6 +55,17 @@ internal void AppendToPatch(string patch)
/// </summary>
public virtual int LinesDeleted { get; internal set; }

/// <summary>
/// The list of added lines.
/// </summary>
public virtual List<Line> AddedLines { get; internal set; }
bording marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// The list of deleted lines.
/// </summary>
public virtual List<Line> DeletedLines { get; internal set; }
bording marked this conversation as resolved.
Show resolved Hide resolved


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the extra line

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still need to clean up this extra line break.

/// <summary>
/// The patch corresponding to these changes.
/// </summary>
Expand Down Expand Up @@ -95,11 +110,13 @@ private unsafe int LineCallback(git_diff_delta* delta, GitDiffHunk hunk, GitDiff
switch (line.lineOrigin)
{
case GitDiffLineOrigin.GIT_DIFF_LINE_ADDITION:
AddedLines.Add(new Line(line.NewLineNo, decodedContent));
LinesAdded++;
prefix = Encoding.ASCII.GetString(new[] { (byte)line.lineOrigin });
break;

case GitDiffLineOrigin.GIT_DIFF_LINE_DELETION:
DeletedLines.Add(new Line(line.OldLineNo, decodedContent));
LinesDeleted++;
prefix = Encoding.ASCII.GetString(new[] { (byte)line.lineOrigin });
break;
Expand Down
28 changes: 28 additions & 0 deletions LibGit2Sharp/Line.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace LibGit2Sharp
{
/// <summary>
/// Represents a line with line number and content.
/// </summary>
public struct Line
{
/// <summary>
/// The line number of the original line in the blob.
/// </summary>
public int LineNumber { get; }

/// <summary>
/// The content of the line in the original blob.
/// </summary>
public string Content { get; }

internal Line(int lineNumber, string content)
{
LineNumber = lineNumber;
Content = content;
}
}
}
13 changes: 10 additions & 3 deletions LibGit2Sharp/Patch.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
using LibGit2Sharp.Core;
using LibGit2Sharp.Core.Handles;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Text;
using LibGit2Sharp.Core;
using LibGit2Sharp.Core.Handles;

namespace LibGit2Sharp
{
Expand Down Expand Up @@ -68,6 +68,11 @@ private unsafe int PrintCallBack(git_diff_delta* delta, GitDiffHunk hunk, GitDif
PatchEntryChanges currentChange = this[filePath];
string prefix = string.Empty;

string decodedContent = LaxUtf8Marshaler.FromNative(line.content, (int)line.contentLen);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this when this appears to be the same as the patchPart declaration on line 59?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should able to be removed. You can just use the existing patchPart instead.


currentChange.AddedLines = currentChange.AddedLines ?? new List<Line>();
bording marked this conversation as resolved.
Show resolved Hide resolved
currentChange.DeletedLines = currentChange.DeletedLines ?? new List<Line>();

switch (line.lineOrigin)
{
case GitDiffLineOrigin.GIT_DIFF_LINE_CONTEXT:
Expand All @@ -77,12 +82,14 @@ private unsafe int PrintCallBack(git_diff_delta* delta, GitDiffHunk hunk, GitDif
case GitDiffLineOrigin.GIT_DIFF_LINE_ADDITION:
linesAdded++;
currentChange.LinesAdded++;
currentChange.AddedLines.Add(new Line(line.NewLineNo, decodedContent));
prefix = "+";
break;

case GitDiffLineOrigin.GIT_DIFF_LINE_DELETION:
linesDeleted++;
currentChange.LinesDeleted++;
currentChange.DeletedLines.Add(new Line(line.OldLineNo, decodedContent));
prefix = "-";
break;
}
Expand Down Expand Up @@ -168,7 +175,7 @@ public virtual string Content
/// </summary>
/// <param name="patch"><see cref="Patch"/>.</param>
/// <returns>The patch content as string.</returns>
public static implicit operator string (Patch patch)
public static implicit operator string(Patch patch)
{
return patch.fullPatchBuilder.ToString();
}
Expand Down