Programmatically get a diff between two versions of a file in TFS
Asked Answered
P

2

11

I'm trying to write a code which, given a path to an item in the TFS repository and two revisions, would compute a difference between the contents file had at these two moments. For now the code might look like this:

using (var projectCollection = new TfsTeamProjectCollection(new Uri(repositoryUrl)))
{
    projectCollection.EnsureAuthenticated();
    var versionControlServer = (VersionControlServer)projectCollection.GetService(typeof(VersionControlServer));

    string path = "$/MyProject/path/to/file.xml"

    var before = new DiffItemVersionedFile(versionControlServer, path, VersionSpec.ParseSingleSpec(minRevision.ToString(), null));
    var after = new DiffItemVersionedFile(versionControlServer, path, VersionSpec.ParseSingleSpec(maxRevision.ToString(), null));

    using (var stream = new MemoryStream())
    using (var writer = new StreamWriter(stream))
    {
        var options = new DiffOptions();
        options.Flags = DiffOptionFlags.EnablePreambleHandling;
        options.OutputType = DiffOutputType.Unified;
        options.TargetEncoding = Encoding.UTF8;
        options.SourceEncoding = Encoding.UTF8;
        options.StreamWriter = writer;
        Difference.DiffFiles(versionControlServer, before, after, options, path, true);
        writer.Flush();

        var reader = new StreamReader(stream);
        var diff = reader.ReadToEnd();
    }
}

But once this code is executed, the variable diff is an empty string even though I know for sure the file has been modified between minRevision and maxRevision.

This code will also throw an exception if the file didn't exist at minRevision or was deleted in maxRevision, but this seems to be a problem to solve later, once I get this thing working with files which were only edited.

EDIT

Having checked temp files, I'm sure both versions of the file are downloaded correctly. Something is wrong with the computation of the diff or with writing the diff to a stream or with copying the diff to a string.

Prohibition answered 29/6, 2012 at 14:3 Comment(0)
P
9

Solved. The problem was the reader. After I changed the last two lines to

var diff = Encoding.UTF8.GetString(stream.ToArray());

I got some diff at last.

Prohibition answered 29/6, 2012 at 14:34 Comment(1)
TFS stores the file encoding - instead of assuming UTF8 it might be useful to use that instead.Leckie
A
3

I know you accepted your answer, and this was asked in 2012, but I recently had to do the same thing, but much prefer using a StreamReader vs .ToArray()

The answer is that you have to reset the MemoryStream before you start reading from it.

add this

stream.Position = 0;

right after you flush the writer

Ainu answered 8/11, 2015 at 20:6 Comment(2)
Thanks, I guess it was the most direct answer to my. However, I still stand by my solution. ToArray() and GetString() will copy the data twice. But StreamReader.ReadToEnd() internally uses a StringBuilder (link) so it copies the data twice as well. But in theory my solution should perform better, because ToArray() knows the size of the memory stream while StreamReader doesn't, so it may need to grow the buffer as it goes.Prohibition
@kamilk, good point about growing the buffer. I wanted StreamReader for its very convenient .ReadLine()Ainu

© 2022 - 2024 — McMap. All rights reserved.