If you’ve ever done something with checking in items from the build, you (should) know how to check-in without triggering a new build (when using Continuous Integration). With TFS2010 you also have to take care of  the gated check-in feature being activated on build definitions. When the location of the pending change falls within the workspace mapping of a gated build definition, you’ll get a GatedCheckinException telling you need to queue a build a shelveset containing the pending changes to complete the check-in. This isn’t very useful when checking in files during the build…
With the following code it is possible to override the gated check-in option, and even support previous versions of TFS which did not have the gated check-in feature.
// Using temporary directory for the workspace mapping var dir = new DirectoryInfo(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString())); if (!dir.Exists) { dir.Create(); } try { var server = new Uri("http://<yourtfs>:8080/tfs"); var scc = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(server); scc.Authenticate(); // Query for workspaces and delete if found. var vcs = scc.GetService(typeof(VersionControlServer)) as VersionControlServer; var ws = vcs.QueryWorkspaces("temp", Environment.UserName, Environment.MachineName).FirstOrDefault(); if (ws != null) { ws.Delete(); } // Create the workspace with a mapping to the temporary folder. ws = vcs.CreateWorkspace("temp", Environment.UserName, string.Empty, new WorkingFolder[] { new WorkingFolder("$/TeamProject/SomeLocation", dir.FullName) }); ws.Get(); // Create a file and add it as a pending change. var file = Path.Combine(dir.FullName, "temp3.txt"); using (var stream = File.CreateText(file)) { stream.Write("Checking in new file: {0}.", DateTime.Now); } ws.PendAdd(file); // Finally check-in, don't trigger a Continuous Integration build and override gated check-in. var wip = new WorkspaceCheckInParameters(ws.GetPendingChanges(), "***NO_CI***") { // Enable the override of gated check-in when the server supports gated check-ins. OverrideGatedCheckIn = ((CheckInOptions2)vcs.SupportedFeatures & CheckInOptions2.OverrideGatedCheckIn) == CheckInOptions2.OverrideGatedCheckIn, PolicyOverride = new PolicyOverrideInfo("Check-in from the build.", null) }; ws.CheckIn(wip); } finally { if (dir.Exists) { dir.Attributes = FileAttributes.Normal; dir.Delete(true); } }
The sample is quite bulky. It also shows a way of creating temporary workspace mappings and add pending changes. If you know a better or easier way to do this, please let me know!
5 comments
I’m just curious, have you found a better way to accomplish this?
Jordan
What do you mean? Aren’t you satisfied with the provided solution?
manuelr
Wouldn’t using the TFS API’s “WorkspaceCheckInParameters” be the preferred solution: See http://blogs.msdn.com/b/phkelley/archive/2010/02/26/workspacecheckinparameters-and-shelvesetcheckinparameters.aspx
Dave Zimmerman
That’s the one I’m using? See line 35.
manuelr
On line 38 you compare vcs.SupportedFeatures to CheckInOptions2? Does supported features map to that enum? Does it map to other enums in the Microsoft.TeamFoundation.VersionControl.Client as well?
It would seem that that should map to Microsoft.TeamFoundation.VersionControl.Client.SupportedFeatures, especially since from VS 2012 it contains a value of 1919 or SupportedFeatures.All. However the MSDN is unclear on that.
A friend of mine asked the question on the MSDN forums, but the answers provided were not helpful. Perhaps you could answer the question in a clearer manner.
http://social.msdn.microsoft.com/Forums/en-US/tfsversioncontrol/thread/09cc6ecb-500c-4a9e-ab3f-8cecfbaae8ff/
Justin Dearing