Override Gated Check-in using the TFS API

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…

image

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(&quot;http://<yourtfs>:8080/tfs&quot;);
    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(&quot;temp&quot;, Environment.UserName, Environment.MachineName).FirstOrDefault();
    if (ws != null)
    {
        ws.Delete();
    }

    // Create the workspace with a mapping to the temporary folder.
    ws = vcs.CreateWorkspace(&quot;temp&quot;, Environment.UserName, string.Empty, new WorkingFolder[] { new WorkingFolder(&quot;$/TeamProject/SomeLocation&quot;, dir.FullName) });
    ws.Get();

    // Create a file and add it as a pending change.
    var file = Path.Combine(dir.FullName, &quot;temp3.txt&quot;);
    using (var stream = File.CreateText(file))
    {
        stream.Write(&quot;Checking in new file: {0}.&quot;, 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(), &quot;***NO_CI***&quot;)
    {
        // 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(&quot;Check-in from the build.&quot;, 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!