I have a folder under TFS source control system, let's say under "$/My Project/Branches/Dev" path.
It was just recently moved from another location, which was "$/My Project/Dev".
Now when I request its history from the Source Control Explorer in VS I get the full history, where the described move operation was just one of the changesets.
But when I try to get the history using TFS SDK I only get the recent history started with the move of the folder. How can I get the full history?
I'm using the following code:
TeamFoundationServer tfs = TeamFoundationServerFactory.GetServer(tfsServerURL);
VersionControlServer vcs = (VersionControlServer)tfs.GetService(typeof(VersionControlServer));
// Null means All
VersionSpec versionFrom = null;
System.Collections.IEnumerable enumerable = vcs.QueryHistory(_tfsPath,
VersionSpec.Latest,
0,
RecursionType.Full,
"",
versionFrom,
VersionSpec.Latest,
Int32.MaxValue,
true,
true);
You are passing slotMode = true. Change the final parameter to false.
"Slot mode" means "query by path, not by history." It's useful if you only remember the old name of an item but not where you moved it to, or if >1 item has occupied a given path.
For future reference, if you want to see what parameters VS (or tf.exe) is passing to the server so you can mimic them, turn on tracing.
Related
I want to retrieve a list of all branches of a TFS workspace which are mapped locally. I already got a solution where I retrieve all branches of a VersionControlServer-Object, but that`s not what I want to get here. It should be a list specific for my workspace.
var branchObjects = m_VersionControlServer.QueryRootBranchObjects(RecursionType.Full);
List<string> branches = new List<string>();
foreach (var branch in branchObjects)
{
var branchName = branch.Properties.RootItem.Item;
branches.Add(branchName);
}
Do u got any ideas how to check which of the branches where mapped at the local workspace? An instance of the specific workspace-class is available.
You can achieve this with the TFS tf command line tool
tf workspaces /owner:* /computer:* /collection:https://tfs.yourdomain.com/DefaultCollection /format:xml
If you don't have tf.exe, refer to this page How to get tf.exe (TFS command line client)?
Assuming you know the local path of your workspace you can use:
var workspace = versionControlServer.TryGetWorkspace(...path...)
Or you can use the Workstation class to query local workspaces on your machine.
Then from the workspace you can get the workspaces from the QueryWorkspaceInfo method and from there the mappings WorkspaceInfo.Mappings property. And from there you can check whether your branchroots (which you've already got figured out) are mapped in any of the workspaces on the server. If you want to be able to look up server path, you'll need to call the WorkspacnInfo.GetWorkspace method and from there use the Workspace.Folders property.
I am trying to get the local workspace to sync up with the remote workspace. The remote workspace is WindowsMain/MainProject/Subproject and the local is C:/MainProject/Subproject the problem is when I run the code shown below it says that the local workspace isn't mapped. What am I doing wrong that makes it so that the code isn't found? (localpath is C:/MainProject/Subproject
TfsTeamProjectCollection tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://remoteserver:8080/tfs_proj/WindowsMain"), new UICredentialsProvider());
tfs.EnsureAuthenticated();
VersionControlServer vsStore = tfs.GetService<VersionControlServer>();
Workspace workspace = vsStore.GetWorkspace(localpath);
I'm not sure what is that you want exactly,
...but this is the code I used (and I remember having trouble finding the right solution at the time):
teamProjectCollection = new TfsTeamProjectCollection(new Uri(collectionUri), new TfsClientCredentials());
teamProjectCollection.Authenticate();
versionControl = teamProjectCollection.GetService<VersionControlServer>();
(note: the credentials like this are automatically picked from what
you use in VS)
then I get all the workspaces (in your case it may be just one) - that helps to get the right matching paths for server and client (the Workstation class does the same, if that doesn't work for some reason, this does)
versionControl.QueryWorkspaces(null, null, computerName)
.SelectMany(x => x.Folders); // returns IEnumerable<WorkingFolder>
pick the workspace you need and you have both local and server path
LocalSourcePath = folder.LocalItem;
ServerPath = folder.ServerItem;
...and then I use the ServerPath and the versionControl to actually download the files (and e.g. you can check them against the LocalSourcePath)...
foreach (Item item in
versionControl.GetItems(serverPath, VersionSpec.Latest, RecursionType.Full, DeletedState.NonDeleted, ItemType.Any, true).Items)
{
string target = Path.Combine(downloadPath, item.ServerItem.Substring(2));
if (item.ItemType == ItemType.Folder && !Directory.Exists(target))
{
Directory.CreateDirectory(target);
}
else if (item.ItemType == ItemType.File)
{
item.DownloadFile(target);
}
}
...this is probably slightly different for your case but you should be able to work out the specific details from this, hope it helps.
According to you code, you need to pass through a VersionControlServer object, and to obtain such an object you need to know the address of the Tfs server the workspace is mapped to.
If you can determine the physical path of the solution or project file, then you can query that file in TFS and you should see which workspace has been mapped to that local file location. Note: The mapped path for a workspace had to be unique.
Moreover, there is a more powerful way though, using the Workstation class. Ricci Gian Maria has written a quite extensive blog post about this topic.
Use the Workstation class to get the WorkspaceInfo for the path you're looking for, this will search the workpaces for all TFS servers registered on that workstation to see if there's a match:
Workstation workstation = Workstation.Current;
WorkspaceInfo info = workstation.GetLocalWorkspaceInfo(path);
More details please refer his blog: How to get TFS server address from a local folder mapped to a workspace
I'm writing a TFS plugin to automate merging of changesets related to a work item whenever said work item is changed from state "Resolved" to state "Closed". The following code is what I have so far:
C#
private void Action_ResolvedToClosed()
{
//Linq query for getting changesets associated with the current work item
var changeSets = WorkItem.Links
.OfType<ExternalLink>()
.Select(link =>
VersionControlServer.ArtifactProvider.GetChangeset(new Uri(link.LinkedArtifactUri))).ToList();
if (!changeSets.Any())
{
LOG_NOCHANGESETS(WorkItem.Id);
return;
}
Workspace workspace = VersionControlServer.GetWorkspace(<My Workspace>);
var source = URI_LOCAL; // $/<Project Name>/<Working Branch>
var destination = URI_DEV; // $/<Project Name>/<Development Branch>
// Merge applicable changesets
foreach (var versionSpec in changeSets.Select(changeset => new ChangesetVersionSpec(changeset.ChangesetId)))
{
workspace.Merge(source, destination, versionSpec, versionSpec);
workspace.CheckIn(workspace.GetPendingChanges(), "**Automated Merge**");
LOG_SUCCESS(versionSpec.ChangesetId, WorkItem.Id);
}
}
Is there a way to dynamically generate the workspace variable? Odds are I won't be the one actually making changes - the goal is to automate this process for our devs.
UPDATE: I'm pretty sure what I'm looking for in this second part is GetStatus, so it can be ignored. The paragraph above is my real question.
Secondary: I feel like automating merges can't be this simple. What happens if merge conflicts arise? Does Workspace.Merge fail gracefully? Are there any other glaring issues that someone with a bit more experience with the TFS API can point out?
First, it sounds like you want to query the user's workspace cache to get the appropriate Workspace and "realize" it. If
WorkspaceInfo workspaceInfo = Workstation.Current.GetLocalWorkspaceInfo(path);
Workspace workspace = workspaceInfo.GetWorkspace(new TfsTeamProjectCollection(workspaceInfo.ServerUri);
However, as you point out, you may prefer to create a temporary workspace. This will ensure that you do not conflict with any changes the user is trying to make in their own workspace. For example:
TfsTeamProjectCollection tpc = new TfsTeamProjectCollection(new Uri("http://server:8080/tfs/DefaultCollection"));
VersionControlServer vcs = tpc.GetService<VersionControlServer>();
Workspace workspace = vcs.CreateWorkspace("MERGE-TEMP");
workspace.Map("$/Merge-Source", #"C:\Temp\Merge\Source");
workspace.Map("$/Merge-Target", #"C:\Temp\Merge\Target");
Second, if you run into merge conflicts, they will be set in the workspace. You can query the NumConflicts method of the returned GetStatus. (Though you will not be able to Checkin untli you have resolved the conflicts.
Microsoft TFS client for VS 2010:
http://msdn.microsoft.com/en-us/library/microsoft.teamfoundation.versioncontrol.client.item(v=vs.100).aspx
I (i.e., my code) have a Changeset.
I iterate to a particular Change.
I have an Item in the Change.
Now, I wish to get all Changesets that had Changes for that item.
Could someone advise me the best way to do that?
I could iterate thro all the Changesets of the branch concerned, which would be very inefficient.
Edward is correct. And he has the credentials to back it up. (See his profile description)
VersionControlServer.QueryHistory is the method you need to use. There are several ways to use it and I'm only describing one below which assumes that the server path of that item is what is important to you...
First, you need the server path of the Item:
string serverPath = Item.ServerItem;
Next, if you don't already have a VersionControlServer object instantiated, you can get one from your TeamProject like this:
VersionControlServer VCServer = (VersionControlServer)this.TeamProject.Store.TeamProjectCollection.GetService(typeof(VersionControlServer));
Use the VersionControlServer QueryHistory(string, boolean) method to get other changesets associated with that server path:
VCServer.QueryHistory(serverPath, false);
I am trying to get a file by name from TFS. I am getting all the files from a location recursively and then looping through these to find a specific file. It appears that the VersionControl.Client.Item object does not expose the filename (or foldername).
tfs.EnsureAuthenticated();
VersionControlServer vcs = versionControlServer)tfs.GetService(typeof(VersionControlServer));
var allStaticFiles = vcs.GetItems(path + "*", RecursionType.Full).Items;
foreach (var staticFile in allStaticFiles)
{
if(staticFile == ?? // need the filename)
{
}
(Assuming TFS2008.)
The type of vcs.GetItems(...).Items is Item[].
So therefore staticFile is an Item instance.
The properties of Item are all server side because details of the path will depend on the client's workspace mapping (there can be multiple workspaces including this item on the same computer for the same user).
You can use Item.ServerItem to get the filename (take the last path element)
To the path, get a Workspace instance representing your current workspace and use one of its methods to map the ServerItem to a local path (there are a few with subtly different behaviour, without more context it is not clear which is the right one).