Files
git-tfs/GitTfs/Commands/Verify.cs
2012-05-22 16:34:48 -04:00

124 lines
4.1 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using NDesk.Options;
using Sep.Git.Tfs.Core;
using Sep.Git.Tfs.Core.TfsInterop;
using StructureMap;
namespace Sep.Git.Tfs.Commands
{
[Pluggable("verify")]
[RequiresValidGitRepository]
public class Verify : GitTfsCommand
{
private readonly Globals _globals;
private readonly TreeVerifier _verifier;
public Verify(Globals globals, TreeVerifier verifier)
{
_globals = globals;
_verifier = verifier;
}
public OptionSet OptionSet
{
get { return new OptionSet(); }
}
public int Run()
{
return Run("HEAD");
}
private int Run(string commitish)
{
// Warn, based on core.autocrlf or core.safecrlf value?
// -- autocrlf=true or safecrlf=true: TFS may have CRLF where git has LF
var parents = _globals.Repository.GetLastParentTfsCommits(commitish);
if(parents.IsEmpty())
throw new GitTfsException("No TFS parents found to compare!");
foreach(var parent in parents)
{
_verifier.Verify(parent);
}
return GitTfsExitCodes.OK;
}
}
public class TreeVerifier
{
private readonly TextWriter _stdout;
private readonly ITfsHelper _tfs;
public TreeVerifier(TextWriter stdout, ITfsHelper tfs)
{
_stdout = stdout;
_tfs = tfs;
}
public void Verify(TfsChangesetInfo changeset)
{
_stdout.WriteLine("Comparing TFS changeset " + changeset.ChangesetId + " to git commit " + changeset.GitCommit);
var tfsTree = changeset.Remote.GetChangeset(changeset.ChangesetId).GetTree().ToDictionary(entry => entry.FullName.ToLowerInvariant().Replace("/",@"\"));
var gitTree = changeset.Remote.Repository.GetCommit(changeset.GitCommit).GetTree().ToDictionary(entry => entry.Entry.Path.ToLowerInvariant());
var all = tfsTree.Keys.Union(gitTree.Keys);
var inBoth = tfsTree.Keys.Intersect(gitTree.Keys);
var tfsOnly = tfsTree.Keys.Except(gitTree.Keys);
var gitOnly = gitTree.Keys.Except(tfsTree.Keys);
var foundDiff = false;
foreach(var file in all.OrderBy(x => x))
{
if(tfsTree.ContainsKey(file))
{
if(gitTree.ContainsKey(file))
{
if (Compare(tfsTree[file], gitTree[file]))
foundDiff = true;
}
else
{
_stdout.WriteLine("Only in TFS: " + tfsTree[file].FullName);
foundDiff = true;
}
}
else
{
_stdout.WriteLine("Only in git: " + gitTree[file].FullName);
foundDiff = true;
}
}
if(!foundDiff)
_stdout.WriteLine("No differences!");
}
private bool Compare(TfsTreeEntry tfsTreeEntry, GitTreeEntry gitTreeEntry)
{
var different = false;
if (tfsTreeEntry.FullName.Replace("/",@"\") != gitTreeEntry.FullName)
{
_stdout.WriteLine("Name case mismatch:");
_stdout.WriteLine(" TFS: " + tfsTreeEntry.FullName);
_stdout.WriteLine(" git: " + gitTreeEntry.FullName);
different = true;
}
if(Hash(tfsTreeEntry) != Hash(gitTreeEntry))
{
_stdout.WriteLine(gitTreeEntry.FullName + " differs.");
different = true;
}
return different;
}
private string Hash(ITreeEntry treeEntry)
{
using (var stream = treeEntry.OpenRead())
return BitConverter.ToString(new MD5CryptoServiceProvider().ComputeHash(stream));
}
}
}