I have the following function that is being called in a loop on two new projects to add to source control. Each iteration of the loop gets the source code, copies it to the folder, creates a tfs team project, creates a workspace for that project, and then tries to add the code to source control.
static void Main(string[] args) {
var tfsWorkItems = _<IWorkItems>();
var workItems = tfsWorkItems.GetProjectsToMigrate();
var tfs = _<ITfs>();
var logFilePath = new DirectoryInfo("C:\\log");
var workingDirectory = new DirectoryInfo("C:\\m");
Cleanup(workItems, tfs, logFilePath, workingDirectory);
var svn = _<ISvn>();
var app = _<IApplication>();
foreach (var workItem in workItems)
{
var root = Path.Combine(workingDirectory.FullName, workItem.Id.ToString());
var svnBase = Path.Combine(root, "s");
var localWorkspacePath = Path.Combine(root, "t");
var tfsBase = Path.Combine(localWorkspacePath, workItem.TfsProjectName, "Main");
var tfsProject = workItem.ProjectType.ToLower() == "php" ? Path.Combine(tfsBase, "src")
: tfsBase;
svn.CheckoutFromSvn(workItem.SvnLocation, svnBase);
app.CopyToTfsFolderStructure(svnBase, tfsProject);
tfs.CreateTeamProject(workItem.TfsProjectName, logFilePath);
tfs.CreateWorkspace(workItem.WorkspaceName, localWorkspacePath);
tfs.AddToSourceControl(workItem.WorkspaceName, localWorkspacePath, workItem.TfsProjectName);
}
}
There are two projects. The first project works correctly, but the second does not. The second project creates the project and workspace, but in AddToSourceControl
public void AddToSourceControl(string workspaceName, string localPath, string projectName) {
var tfs = new TfsTeamProjectCollection(_collection);
var vcs = tfs.GetService<VersionControlServer>();
var user = vcs.AuthorizedUser;
var workspace = vcs.GetWorkspace(workspaceName, user);
var serverPath = workspace.GetServerItemForLocalItem(Path.Combine(localPath, projectName, "Main"));
var itemSpec = new ItemSpec[] {
new ItemSpec(serverPath, RecursionType.Full)
};
workspace.PendAdd(serverPath, true);
// doesn't return anything
var pendingSets = vcs.QueryPendingSets(
itemSpec, workspace.Name, user, true);
var pendingChanges = pendingSets.Aggregate(new List<PendingChange>(), (acc, item) => {
acc.AddRange(item.PendingChanges);
return acc;
});
var parameters = new WorkspaceCheckInParameters(pendingChanges, "svn to tfs migration") {
OverrideGatedCheckIn = ((CheckInOptions2)vcs.SupportedFeatures & CheckInOptions2.OverrideGatedCheckIn) == CheckInOptions2.OverrideGatedCheckIn,
PolicyOverride = new PolicyOverrideInfo("migration triggered check-in", null),
SuppressEvent = true,
};
workspace.CheckIn(parameters);
}
workspace.PendAdd(serverPath, true)
always returns zero for the second project, regardless of which project is second. The first project always completes properly. It doesn't matter which project is second. The second project always returns zero items. I obviously want all projects to be added to source control correctly. What is going on here?
I have figured out a way around this problem. I have to create a separate console application that contained the code in the
AddToSourceControl
method and call the console application via theSystem.Diagnostics.Process
class. Something internally in the TFS API must not be getting released properly until the whole entire program exits.I was stucked with the command PenAdd and, like Wobuntu, the command :
solved the problem for me.
You need to call this method before the command PenAdd.
I had the same problem (even the MSDN sample did not work on my machine), but listening to non fatal errors gave me the hint to invoke Workstation.EnsureUpdateWorkspaceInfoCache before calling PendAdd. This solved it for me.
This is the correct solution and it worked for me.
I don't know why your application is not working, but the TFS API is capable of creating multiple workspaces and checking in from them without any need to dispose anything or call the GC or anything strange like that.
Here's an example program, modified from the one you posted to the connect site, that exhibits correct behavior:
So I would suggest that the problem lies elsewhere in your code. However, if you can produce a short, self-contained example that exhibits the problem without many layers of abstraction, that would be helpful.
Some helpful tips:
Make sure your workspace mappings are setup correctly: otherwise, calling
PendAdd
recursively will not, in fact, add anything.Make sure the files exist locally: for the same reason.
Listen for errors: The TFS API has several events that it can notify consumers of - one that is particularly useful is the "non fatal" error notifications. In many operations, one part of an operation can fail, and instead of exiting or throwing an exception, a "non fatal" will be raised and the operation will continue.
An example of this is when you're adding multiple paths to
PendAdd
and one of them fails (for example, because a path is locked.) Without listening to non fatal errors, you will not know that this path is excluded from the pending changes. (Though you will know that a path is excluded, due to looking at the return code.)If you have a
VersionControlServer vcs
:(Note that this example was taken from Buck Hodges' helpful client API example blog post.)