c:\temp> tf folderdiff /?
TF - Team Foundation Version Control Tool
Copyright (c) Microsoft Corporation. All rights reserved.
Displays a visual representation of the differences between files in two server
folders, in a server folder and a local folder, or in two local folders.
tf folderdiff [sourcePath] targetPath [/recursive] [/noprompt]
[/server:serverName:port] [/filter:filter]
[/filterLocalPathsOnly]
[/view:same,different,sourceOnly,targetOnly]
C:\temp> tf folderdiff 1 2 /noprompt
===========================================================================
Items That Exist Only in C:\temp\1
===========================================================================
C:\temp\1\baz
===========================================================================
Items That Exist Only in C:\temp\2
===========================================================================
C:\temp\2\bar
===========================================================================
Show Items That Have Different Contents
===========================================================================
C:\temp\1\quux -
C:\temp\2\quux
===========================================================================
Summary: 1 folders, 4 files, 1 source, 1 target, 1 different, 0 with errors
===========================================================================
Edit: if it wasn't obvious, the default view is sourceOnly + targetOnly + different. I had a file named "foo" with the same contents in both folders.
I realize a command line tool is not an API per se, but unfortunately it's the best option here. Otherwise you need to crawl the tree yourself -- there is no folder diff in the version control API. All you get is a 15+ confusing methods that operate on individual items.
On the plus side, if all of the files you want to compare are going to be checked in, that means you can do the computation without any costly disk I/O. (TFS stores a hash of every file's contents). Quick Powershell example:
function Compare-TfsDir([string] $dir1, [string] $dir2, [switch] $includeEqual)
{
$dir1 = $dir1.ToLower()
$dir2 = $dir2.ToLower()
filter Decorate($dir)
{
$_ | add-member noteproperty RelativePath $_.ServerItem.ToLower().Replace($dir, "") -passthru |
add-member noteproperty HashString ($_.HashValue | %{ "{0:X2}" -f $_ } | join-string) -passthru
}
$items1 = $tfs.vcs.GetItems($dir1, $tfs.VCS_RecursionType::Full).Items | Decorate $dir1
$items2 = $tfs.vcs.GetItems($dir2, $tfs.VCS_RecursionType::Full).Items | Decorate $dir2
$dirComp = compare -IncludeEqual -Property RelativePath $items1 $items2
"---Tree Comparison---"
$dirComp | ? { $_.SideIndicator -ne "==" } | ft -auto RelativePath, SideIndicator
$both = $dirComp | ? { $_.SideIndicator -eq "==" } | % { $_.RelativePath } | Linq-ToSet
filter InBoth { if ($both.Contains($_.RelativePath)) {$_} }
$contentComp = compare -inc:$includeEqual -Property HashString, RelativePath `
($items1 | InBoth) ($items2 | InBoth)
"---Content Comparison---"
$contentComp | ? { $_.SideIndicator -ne "<=" } | ft -auto RelativePath, SideIndicator
}
Unfortunately, doing something like this would take 5X as many lines of code if you need to support local vs server diffs.