TFS – Free Text search in History Objects

It’s a best practice to add comment when you do check-in to the source control. A text comment is associated with the change you made to the item. Some of the times you need to find a particular comment, but the View History tool available with Visual Studio/TFS is limited that you can’t make a search in the history results. Say you want to find all check-ins by a particular user πŸ™

History Tool in Visual Studio 2005

Here comes the purpose of this small add-in. It provides search within history comments and find a particular change-set instead of traversing the whole list. The plug-in goes one step forward and facilitates free text search in change-set fields. For example you can use change-set id, username or even date-time as search keywords!!!

The major steps involved in developing this add-in are:

  1. Writing an add-in for Visual Studio 2005,
  2. Getting file history from Team Foundation Server (TFS),
  3. Look for the selected item in the Visual Studio IDE,
  4. Free text search along with the tools to compare two files.

Visual Studio 2005 provides templates to build add-ins in few minutes. Refer www.devx.com for step-by-step guide for building Visual Studio app-ins. Additionally, you can download Visual Studio 2005 Automation Samples for detailed code illustrations with documentation.

Once you have completed the Visual Studio Add-in wizard the IDE generates Connect.cs file and dumps some code for basic functionality. The next step is to retrieve history from the TFS for selected file. Refer my previous post, Fetching file history from TFS to find out how to fetch file history objects from Version Control Server.

Moving forward we need to find out the currently selected item in the Visual Studio IDE. Visual Studio exposes various properties/objects allowing you to query almost any UI controls and get their status. The following code first finds the active window. If it is Source Control Explorer and then looks for the selected item within the same.

public static void GetServerUriAndItemPath(DTE2 appObj, ref string serverUri, ref string itemPath, ref bool isFolder)

{

isFolder = false;

// Get local workspace info

WorkspaceInfo[] wsInfo = Workstation.Current.GetAllLocalWorkspaceInfo();

if (wsInfo.Length == 0)

throw new TFSHistorySearchException(“No workspace found.”);

// Get server Uri

serverUri = wsInfo[0].ServerUri.AbsoluteUri;

// Get a reference to the Team Foundation Server.

TeamFoundationServer tfs = new TeamFoundationServer(serverUri);

VersionControlServer vcs = tfs.GetService(typeof(VersionControlServer)) as VersionControlServer;

//if Active Window is Source Control Explorer

if (appObj.ActiveWindow.Caption.StartsWith(“Source Control Explorer”))

{

VersionControlExt vce;

// The top level class used to access all other Team Foundation Version Control Extensiblity classes

vce = appObj.GetObject(“Microsoft.VisualStudio.TeamFoundation.VersionControl.VersionControlExt”) as VersionControlExt;

if (!vce.Explorer.Connected)

{

throw new TFSHistorySearchException(“Source control explorer is not connected to a Team Foundation Server”);

}

// Get all selected items

VersionControlExplorerItem []selectedItems = vce.Explorer.SelectedItems;

if (selectedItems.Length == 0)

throw new TFSHistorySearchException(“You must select one item.”);

if (selectedItems.Length > 1)

throw new TFSHistorySearchException(“Multiple items selected.”);

if (selectedItems[0].SourceServerPath.Equals(“$/”))

throw new TFSHistorySearchException(“Operation is not supported for the selected item.”);

//Take the 1st item

itemPath = selectedItems[0].SourceServerPath;

isFolder = selectedItems[0].IsFolder;

}

//if Active Window is Solution Explorer

else if (appObj.ActiveWindow.Caption.StartsWith(“Solution Explorer”))

{

isFolder = false;

if (appObj.SelectedItems.MultiSelect == true)

throw new TFSHistorySearchException(“Multiple items selected.”);

SelectedItem selectedItem = appObj.SelectedItems.Item(1);

SourceControl2 sc = (SourceControl2)appObj.SourceControl;

string fileName = String.Empty;

if (selectedItem.ProjectItem != null)

{

//Its a project file

fileName = selectedItem.ProjectItem.Properties.Item(“URL”).Value.ToString();

fileName = Regex.Replace(fileName, “file:///”, String.Empty, RegexOptions.IgnoreCase);

if (fileName.EndsWith(“\\”))

{

fileName = fileName.Substring(0, fileName.LastIndexOf(‘\\’));

isFolder = true;

}

try

{

Item item = vcs.GetItem(fileName);

itemPath = item.ServerItem;

}

catch (Microsoft.TeamFoundation.VersionControl.Client.VersionControlException ex)

{

throw new TFSHistorySearchException(“Item not under source control.”, ex);

}

}

else if (selectedItem.Project != null)

{

//Its a project

fileName = selectedItem.Project.FileName;

try

{

Item item = vcs.GetItem(fileName);

itemPath = item.ServerItem;

}

catch (Microsoft.TeamFoundation.VersionControl.Client.VersionControlException ex)

{

throw new TFSHistorySearchException(“Item not under source control.”, ex);

}

}

else

{

throw new TFSHistorySearchException(“Operation is not supported for the selected item.”);

}

}

else

{

throw new TFSHistorySearchException(“Operation is not supported for the selected item.”);

}

}

The following code is to compare two source code files and show visual difference. There is an API provided for the same.

public static void CompareLocal(string localPath, string sourceChangesetId, string serverUri, string srcPath)

{

TeamFoundationServer tfs = TeamFoundationServerFactory.GetServer(serverUri);

VersionControlServer vcs = tfs.GetService(typeof(VersionControlServer)) as VersionControlServer;

VersionSpec sourceVersion = VersionSpec.ParseSingleSpec(sourceChangesetId, vcs.TeamFoundationServer.AuthenticatedUserName);

Difference.VisualDiffItems(vcs, Difference.CreateTargetDiffItem(vcs, srcPath, sourceVersion, 0, sourceVersion), Difference.CreateTargetDiffItem(vcs, localPath, null, 0, null));

}

Once the add-in is installed, it appears in the Tools menu within Visual Studio 2005. Open Source Control Explorer and select an item. Launch the add-in from Tools menu.

When you search for the history of a File, you can also compare it with the local version or the latest version in the source control. These option are avaiable as context menu.

Compare options for search results (only for file types)

Following steps are required only if you download the code and try to deploy the solution to have hands on with the code.

  1. Copy the TFSHistorySearch.AddIn file to %userprofile%\My Documents\Visual Studio 2005\Addins\ directory.
  2. Update the full path of the assembly TFSHistorySearch.dll under Extensibility/Addin/Assembly x-path.
  3. Add reference of TFSHistorySearch.AddIn as link to the project.

Download Source code & Installer: TFSHistorySearch.zip ~700 KB
Download Installer only: TFSHistorySearch-Setup.zip ~400 KB

Implemented by: Jagdish.Vasani [at] Gmail [dot] com

– Ankit

Tagged on: , , , , ,

6 thoughts on “TFS – Free Text search in History Objects

  1. Antonio

    very usefull, thanks πŸ™‚

    I would be nice that I can click on changeset to see details

Leave a Reply

Your email address will not be published. Required fields are marked *