1

What could be the best (as in performant, simple) way to iterate over TreeChanges in LibGit2Sharp?

If I access the .Patch property, I retrieve the full text of the changes. This is not quite enough for me... ideally I would like to be able to iterate over the diff lines, and per each line retrieve the status of the line (modified, added, deleted) and build my own output out of it.

Update:

Let's say I want to build my own diff output. What I'd like to do is to iterate over the changed lines, and during iteration I would check for the type of change (added, removed), and construct my output.

For example:

var diff = "";
foreach (LineChange line in changes) // Bogus class "LineChange"
{
    if (line.Type == LineChange.TYPE_ADDED)
        diff += "+";
    else
        diff += "-";

    diff += line.Content;
    diff += "\n";
}

The above is just a simple example what kind of flexibility I'm looking for. To be able to go through the changes, and run some logic along with it depending on the line change types. The Patch property is already "built", one way would be to parse it, but it seems silly that the library first builds the output, and then I parse it... I'd rather use the building ingredients directly.

I need this kind of functionality so that I can display a visual diff of changes which involves far more code and logic than the simple example I gave above.

Tower
  • 98,741
  • 129
  • 357
  • 507
  • 1
    Could you please add a quick sample of what you're after (*"I want to build my own diff output, in the correct order of lines as how they appear in the file"*) and what is already available? This would be very helpful as I'm not sure to clearly understand the "ordering" issue... – nulltoken Jun 08 '12 at 08:34
  • Not related to your question, but you should never concatenate strings in a loop like that, because it has terrible performance (O(n²)). Use `StringBuilder` (or `StringWriter`) instead. – svick Jun 12 '12 at 10:58

2 Answers2

2

As far as I can see, this information is not exposed by libgit2sharp, but it's provided by libgit2 in the case of blob diffs (but not for tree diffs). The relevant code is in ContentChanges.cs, specifically in the constructor and in the LineCallback() method (the code for tree diffs is in TreeChanges.cs).

Because of this, I think you have two options:

  1. Invoke the method git_diff_blobs(), that's used internally by ContentChanges, yourself, either using reflection (it's an internal method in NativeMethods), or by copying the PInvoke signature to your project. You will most likely also need Utf8Marshaler.
  2. Modify the code of ContentChanges, so that it fits your needs. If you do this, it might make sense to create a pull request for that change, so that others could use it too.
svick
  • 236,525
  • 50
  • 385
  • 514
2

@svick is right. It's not exposed.

It might be useful to open an issue/feature request to further discuss this topic. Indeed, exposing a full blown line based diffgram might not fit the current "grain" of the library. However, provided you can come up with a scenario/use case that would benefit most of the users, some research may be invested in order to widen the API.

Beside this option, there might be other solutions: post-process the current produced patch against the previous version of the file

  • See this SO question for potential leads
  • Neil Fraser's "Diff Strategies" paper is also a great source of strategies and potential caveats regarding what a diff tool might aim at
  • DiffPlex, as a working visualization tool, might be inspirational as well
  • With some more work, one might even achieve something similar to the following kind of visualization (from Perforce 4 viewer)

p4merge
(source: macworld.com)

Note: In order to ease this, it might be useful to expose in C# the libgit2 diffing options.

Community
  • 1
  • 1
nulltoken
  • 64,429
  • 20
  • 138
  • 130