/// <summary> /// Initializes a new instance of the <see cref="TeamFoundationServerInfo"/> class. /// </summary> /// <param name="name">The name of the Team Foundation Server.</param> /// <param name="uri">The URI of the Team Foundation Server.</param> /// <param name="majorVersion">The major version of the Team Foundation Server.</param> /// <param name="displayVersion">The display version of the Team Foundation Server.</param> /// <param name="shortDisplayVersion">The short display version of the Team Foundation Server.</param> public TeamFoundationServerInfo(string name, Uri uri, TfsMajorVersion majorVersion, string displayVersion, string shortDisplayVersion) { this.Name = name; this.Uri = uri; this.MajorVersion = majorVersion; this.DisplayVersion = displayVersion; this.ShortDisplayVersion = shortDisplayVersion; }
public IList <string> GetObjectTokens(TfsTeamProjectCollection tpc, TfsMajorVersion tfsVersion, string teamProjectName, string teamProjectUri) { return(this.objectTokenFactory(tpc, tfsVersion, teamProjectName, teamProjectUri)); }
public static void Apply(ApplicationTask task, TfsTeamProjectCollection tfs, TfsMajorVersion tfsVersion, string teamProjectName, SecurityGroupChange securityGroup) { var ims = tfs.GetService <IIdentityManagementService>(); var css = tfs.GetService <ICommonStructureService>(); var teamProject = css.GetProjectFromName(teamProjectName); var groupIdentityName = string.Format(CultureInfo.InvariantCulture, @"[{0}]\{1}", teamProjectName, securityGroup.Name); // Create the group if needed. var existingGroup = ims.ListApplicationGroups(teamProject.Uri, ReadIdentityOptions.IncludeReadFromSource).FirstOrDefault(g => string.Equals(g.DisplayName, groupIdentityName, StringComparison.OrdinalIgnoreCase)); var members = new List <TeamFoundationIdentity>(); IdentityDescriptor groupDescriptor; if (existingGroup == null) { // There is no existing group with the same name, create one. task.Status = "Creating new \"{0}\" security group".FormatCurrent(groupIdentityName); groupDescriptor = ims.CreateApplicationGroup(teamProject.Uri, securityGroup.Name, securityGroup.Description); } else { // We have an existing group with the same name, update the description. task.Status = "Updating existing \"{0}\" security group".FormatCurrent(groupIdentityName); groupDescriptor = existingGroup.Descriptor; var applicationGroupWithMembers = ims.ReadIdentity(groupDescriptor, MembershipQuery.Direct, ReadIdentityOptions.None); if (applicationGroupWithMembers.Members != null && applicationGroupWithMembers.Members.Any()) { members.AddRange(ims.ReadIdentities(applicationGroupWithMembers.Members, MembershipQuery.Direct, ReadIdentityOptions.None).Where(m => m != null)); } if (!string.IsNullOrEmpty(securityGroup.Description)) { ims.UpdateApplicationGroup(groupDescriptor, GroupProperty.Description, securityGroup.Description); } } // Set permissions. if (securityGroup.PermissionGroupChanges.SelectMany(g => g.PermissionChanges).Any(p => p.Action != PermissionChangeAction.None)) { var securityNamespaces = tfs.GetService <ISecurityService>().GetSecurityNamespaces(); foreach (var groupChange in securityGroup.PermissionGroupChanges.Where(g => g.PermissionChanges.Any(c => c.Action != PermissionChangeAction.None))) { foreach (var securityNamespace in securityNamespaces) { var factory = permissionGroupFactories.FirstOrDefault(f => f.AppliesTo(securityNamespace.Description.NamespaceId, groupChange.PermissionGroup.Scope)); if (factory != null) { var tokens = factory.GetObjectTokens(tfs, tfsVersion, teamProject.Name, teamProject.Uri); if (tokens != null) { foreach (var token in tokens) { ApplySecurityNamespacePermissions(token, groupDescriptor, securityNamespace, groupChange.PermissionChanges); } } } } } task.Status = "Applied security permissions"; } // Set members. if (securityGroup.RemoveAllUsers || !string.IsNullOrEmpty(securityGroup.UsersToAdd) || !string.IsNullOrEmpty(securityGroup.UsersToRemove)) { ApplyGroupMemberChanges(task, securityGroup, groupDescriptor, ims, members); task.Status = "Applied group member changes"; } }
public static void ExportPermissions(ILogger logger, ApplicationTask task, TfsTeamProjectCollection tfs, TfsMajorVersion tfsVersion, IList <SecurityGroupPermissionExportRequest> exportRequests) { if (exportRequests.Any()) { var step = 0; var securityNamespaces = tfs.GetService <ISecurityService>().GetSecurityNamespaces(); var ims = tfs.GetService <IIdentityManagementService>(); foreach (var exportRequest in exportRequests) { task.SetProgress(step++, string.Format(CultureInfo.CurrentCulture, "Exporting \"{0}\" permissions from Team Project \"{1}\"", exportRequest.SecurityGroup.Name, exportRequest.SecurityGroup.TeamProject.Name)); try { var identity = ims.ReadIdentity(IdentitySearchFactor.Identifier, exportRequest.SecurityGroup.Sid, MembershipQuery.None, ReadIdentityOptions.None); if (identity == null) { var message = "The security group \"{0}\" could not be retrieved.".FormatCurrent(exportRequest.SecurityGroup.FullName); logger.Log(message, TraceEventType.Warning); task.SetWarning(message); } else { var permissions = new List <PermissionChangePersistenceData>(); foreach (var securityNamespace in securityNamespaces) { foreach (var factory in permissionGroupFactories) { if (factory.AppliesTo(securityNamespace.Description.NamespaceId)) { var tokens = factory.GetObjectTokens(tfs, tfsVersion, exportRequest.SecurityGroup.TeamProject.Name, exportRequest.SecurityGroup.TeamProject.Uri.ToString()); if (tokens != null) { var permissionGroup = factory.GetPermissionGroup(securityNamespace); foreach (var token in tokens) { var acl = securityNamespace.QueryAccessControlList(token, new[] { identity.Descriptor }, false); foreach (var ace in acl.AccessControlEntries) { foreach (var permission in permissionGroup.Permissions) { var action = PermissionChangeAction.Inherit; if ((permission.PermissionBit & ace.Allow) == permission.PermissionBit) { action = PermissionChangeAction.Allow; } else if ((permission.PermissionBit & ace.Deny) == permission.PermissionBit) { action = PermissionChangeAction.Deny; } permissions.Add(new PermissionChangePersistenceData(permission.Scope, permission.PermissionConstant, action)); } } } } } } } Directory.CreateDirectory(Path.GetDirectoryName(exportRequest.FileName)); PermissionChangePersistenceData.Save(exportRequest.FileName, permissions); } } catch (Exception exc) { var message = string.Format(CultureInfo.CurrentCulture, "An error occurred while exporting \"{0}\" permissions from Team Project \"{1}\"", exportRequest.SecurityGroup.Name, exportRequest.SecurityGroup.TeamProject.Name); logger.Log(message, exc); task.SetError(message, exc); } if (task.IsCanceled) { task.Status = "Canceled"; break; } } } }
private static void NormalizeWorkItemTypeDefinition(XmlDocument normalizedXmlDefinition, TfsMajorVersion tfsMajorVersion) { var rawXml = normalizedXmlDefinition.OuterXml; // Replace "[Project]\" with "[project]\" everywhere. rawXml = rawXml.Replace(@"[Project]\", @"[project]\"); normalizedXmlDefinition.LoadXml(rawXml); // Remove the work item type refname if present, since it is not returned from the project. var workitemTypeNode = normalizedXmlDefinition.SelectSingleNode("//WORKITEMTYPE"); var refnameAttribute = workitemTypeNode.Attributes["refname"]; if (refnameAttribute != null) { workitemTypeNode.Attributes.Remove(refnameAttribute); } // Set the default page layout mode if needed. foreach (var pageNode in normalizedXmlDefinition.SelectNodes("//WORKITEMTYPE/FORM/WebLayout/Page").Cast <XmlElement>()) { AddAttributeIfNeeded(pageNode, "LayoutMode", "FirstColumnWide"); } // Remove all empty CustomControlOptions. foreach (var customControlOptionsNode in normalizedXmlDefinition.SelectNodes("//CustomControlOptions").Cast <XmlElement>().Where(n => !n.HasChildNodes)) { customControlOptionsNode.ParentNode.RemoveChild(customControlOptionsNode); } // Remove the "expanditems" attribute for ALLOWEDVALUES, SUGGESTEDVALUES and PROHIBITEDVALUES when it is true (the default). foreach (XmlAttribute expandItemsAttribute in normalizedXmlDefinition.SelectNodes("//ALLOWEDVALUES[@expanditems='true']/@expanditems | //SUGGESTEDVALUES[@expanditems='true']/@expanditems | //PROHIBITEDVALUES[@expanditems='true']/@expanditems")) { expandItemsAttribute.OwnerElement.Attributes.Remove(expandItemsAttribute); } // Remove global list references (these are typically lists of builds for the Team Project). foreach (XmlNode buildsGlobalList in normalizedXmlDefinition.SelectNodes("//WORKITEMTYPE/FIELDS/FIELD/SUGGESTEDVALUES[@filteritems='excludegroups' and count(GLOBALLIST) = 1]")) { buildsGlobalList.ParentNode.RemoveChild(buildsGlobalList); } // Normalize certain casing differences. foreach (XmlAttribute closedInErrorAttribute in normalizedXmlDefinition.SelectNodes("//DEFAULTREASON[@value='Closed in error']/@value | //REASON[@value='Closed in error']/@value")) { closedInErrorAttribute.Value = "Closed in Error"; } foreach (XmlAttribute overtakenByEventsAttribute in normalizedXmlDefinition.SelectNodes("//DEFAULTREASON[@value='Overtaken by events']/@value | //REASON[@value='Overtaken by events']/@value")) { overtakenByEventsAttribute.Value = "Overtaken by Events"; } foreach (XmlAttribute notFixedAttribute in normalizedXmlDefinition.SelectNodes("//DEFAULTREASON[@value='Not fixed']/@value | //REASON[@value='Not fixed']/@value")) { notFixedAttribute.Value = "Not Fixed"; } foreach (XmlAttribute reconsideringAttribute in normalizedXmlDefinition.SelectNodes("//DEFAULTREASON[@value='Reconsidering the feature']/@value | //REASON[@value='Reconsidering the feature']/@value")) { reconsideringAttribute.Value = "Reconsidering the Feature"; } foreach (XmlAttribute reconsideringAttribute in normalizedXmlDefinition.SelectNodes("//DEFAULTREASON[@value='Reconsidering the epic']/@value | //REASON[@value='Reconsidering the epic']/@value")) { reconsideringAttribute.Value = "Reconsidering the Epic"; } foreach (XmlAttribute fieldIdAttribute in normalizedXmlDefinition.SelectNodes("//WORKITEMTYPE/FIELDS/FIELD[@refname='System.Id']/@name")) { fieldIdAttribute.Value = "ID"; } // Add certain fields that are auto-generated if they're not present. var fieldDefinitionsNode = normalizedXmlDefinition.SelectSingleNode("//WORKITEMTYPE/FIELDS"); var highestMatchingTfsVersionWithSystemFields = SystemFields.Keys.OrderBy(v => (int)v).Last(v => v <= tfsMajorVersion); var currentSystemFields = SystemFields[highestMatchingTfsVersionWithSystemFields]; foreach (var refname in currentSystemFields.Keys) { var field = fieldDefinitionsNode.SelectSingleNode(string.Format(CultureInfo.InvariantCulture, "FIELD[@refname='{0}']", refname)); if (field == null) { field = normalizedXmlDefinition.CreateElement("FIELD"); foreach (var attributeEntry in currentSystemFields[refname]) { var attribute = normalizedXmlDefinition.CreateAttribute(attributeEntry.Key); attribute.Value = attributeEntry.Value; field.Attributes.Append(attribute); } fieldDefinitionsNode.AppendChild(field); } } // Process fields. foreach (XmlElement field in normalizedXmlDefinition.SelectNodes("//WORKITEMTYPE/FIELDS/FIELD")) { var refname = field.Attributes["refname"].Value; // The ALLOWEXISTINGVALUE rule, when applied to a field, is in fact a shortcut // to apply it to all its rules (within the field but also in workflow states and transitions). var allowExistingValueNode = field.SelectSingleNode("ALLOWEXISTINGVALUE"); if (allowExistingValueNode != null) { // The ALLOWEXISTINGVALUE doesn't make sense if there are only DEFAULT or COPY rules in the list, // in which case the ALLOWEXISTINGVALUE rule isn't present in an exported WITD. Predicate <XmlNode> predicate = parentNode => parentNode.ChildNodes.Cast <XmlNode>().Any(childNode => !(string.Equals(childNode.LocalName, "DEFAULT", StringComparison.OrdinalIgnoreCase) || string.Equals(childNode.LocalName, "COPY", StringComparison.OrdinalIgnoreCase))); foreach (var ruleElementName in FieldRuleElementNames) { AddElementIfNeeded(field.SelectSingleNode(ruleElementName), "ALLOWEXISTINGVALUE", predicate); } foreach (XmlNode fieldReference in normalizedXmlDefinition.SelectNodes(string.Format(CultureInfo.InvariantCulture, "//WORKITEMTYPE/WORKFLOW/STATES/STATE/FIELDS/FIELD[@refname='{0}'] | //WORKITEMTYPE/WORKFLOW/TRANSITIONS/TRANSITION/FIELDS/FIELD[@refname='{0}']", refname))) { AddElementIfNeeded(fieldReference, "ALLOWEXISTINGVALUE", predicate); } field.RemoveChild(allowExistingValueNode); } // Set the reportable and syncnamechanges attributes for certain system fields. SetAttributeIfNeeded(field, refname, KnownFieldsWithReportableDimension, "reportable", "dimension"); SetAttributeIfNeeded(field, refname, KnownFieldsWithReportableDetail, "reportable", "detail"); SetAttributeIfNeeded(field, refname, KnownFieldsWithReportableMeasure, "reportable", "measure"); SetAttributeIfNeeded(field, refname, KnownFieldsWithSyncNameChanges, "syncnamechanges", "true"); SetAttributeIfNeeded(field, refname, KnownFieldsWithFormulaSum, "formula", "sum"); // Certain system fields have added spaces to their names, remove the spaces to normalize them. // See http://blogs.msdn.com/b/greggboer/archive/2010/02/25/names-changed-for-core-wit-fields-and-implications-thereof.aspx for more information. if (KnownFieldsWithNamesToRemoveSpaces.Contains(refname)) { var nameAttribute = field.Attributes["name"]; nameAttribute.Value = nameAttribute.Value.Replace(" ", string.Empty); // The HyperLinkCount field not only had spaces removed but also a case change on the 'L'. if (string.Equals(nameAttribute.Value, "HyperlinkCount", StringComparison.OrdinalIgnoreCase)) { nameAttribute.Value = "HyperLinkCount"; } // The AreaID and IterationID field not only had spaces removed but also a case change on the 'D'. if (string.Equals(nameAttribute.Value, "AreaId", StringComparison.OrdinalIgnoreCase)) { nameAttribute.Value = "AreaID"; } if (string.Equals(nameAttribute.Value, "IterationId", StringComparison.OrdinalIgnoreCase)) { nameAttribute.Value = "IterationID"; } } } // Sort field definitions by "refname" everywhere. SortChildNodes(normalizedXmlDefinition.SelectSingleNode("//WORKITEMTYPE/FIELDS"), n => GetValue(n.Attributes["refname"])); foreach (XmlNode stateFieldsNode in normalizedXmlDefinition.SelectNodes("//WORKITEMTYPE/WORKFLOW/STATES/STATE/FIELDS")) { SortChildNodes(stateFieldsNode, n => GetValue(n.Attributes["refname"])); } foreach (XmlNode transitionFieldsNode in normalizedXmlDefinition.SelectNodes("//WORKITEMTYPE/WORKFLOW/TRANSITIONS/TRANSITION/FIELDS")) { SortChildNodes(transitionFieldsNode, n => GetValue(n.Attributes["refname"])); } // Sort workflow states by "value". SortChildNodes(normalizedXmlDefinition.SelectSingleNode("//WORKITEMTYPE/WORKFLOW/STATES"), n => GetValue(n.Attributes["value"])); // Sort transitions by combination of "from" and "to". SortChildNodes(normalizedXmlDefinition.SelectSingleNode("//WORKITEMTYPE/WORKFLOW/TRANSITIONS"), n => string.Concat(GetValue(n.Attributes["from"]), " -> ", GetValue(n.Attributes["to"]))); // Sort child nodes of fields anywhere. foreach (XmlNode field in normalizedXmlDefinition.SelectNodes("//FIELDS/FIELD")) { SortChildNodes(field); } // Sort child nodes of FIELD/WHEN, FIELD/WHENNOT, FIELD/WHENCHANGED, FIELD/WHENNOTCHANGED. foreach (XmlNode field in normalizedXmlDefinition.SelectNodes("//FIELDS/FIELD/WHEN")) { SortChildNodes(field); } foreach (XmlNode field in normalizedXmlDefinition.SelectNodes("//FIELDS/FIELD/WHENNOT")) { SortChildNodes(field); } foreach (XmlNode field in normalizedXmlDefinition.SelectNodes("//FIELDS/FIELD/WHENCHANGED")) { SortChildNodes(field); } foreach (XmlNode field in normalizedXmlDefinition.SelectNodes("//FIELDS/FIELD/WHENNOTCHANGED")) { SortChildNodes(field); } // Sort child nodes of allowed values. foreach (XmlNode allowedValuesList in normalizedXmlDefinition.SelectNodes("//ALLOWEDVALUES")) { SortChildNodes(allowedValuesList); } // Sort child nodes of suggested values. foreach (XmlNode suggestedValuesList in normalizedXmlDefinition.SelectNodes("//SUGGESTEDVALUES")) { SortChildNodes(suggestedValuesList); } // Sort child nodes of prohibited values. foreach (XmlNode prohibitedValuesList in normalizedXmlDefinition.SelectNodes("//PROHIBITEDVALUES")) { SortChildNodes(prohibitedValuesList); } // Sort child nodes of transitions. foreach (XmlNode transitionList in normalizedXmlDefinition.SelectNodes("//WORKITEMTYPE/WORKFLOW/TRANSITIONS/TRANSITION")) { SortChildNodes(transitionList); } // Sort child nodes of transition reasons. foreach (XmlNode transitionReasonList in normalizedXmlDefinition.SelectNodes("//WORKITEMTYPE/WORKFLOW/TRANSITIONS/TRANSITION/REASONS")) { SortChildNodes(transitionReasonList); } // Sort child nodes of transition actions. foreach (XmlNode transitionActionList in normalizedXmlDefinition.SelectNodes("//WORKITEMTYPE/WORKFLOW/TRANSITIONS/TRANSITION/ACTIONS")) { SortChildNodes(transitionActionList); } // Sort child nodes of links control options. foreach (XmlNode linksControlOptionList in normalizedXmlDefinition.SelectNodes("//LinksControlOptions")) { SortChildNodes(linksControlOptionList); } }
public static XmlDocument GetNormalizedXmlDefinition(WorkItemConfigurationItem item, TfsMajorVersion tfsMajorVersion) { var normalizedXmlDefinition = new XmlDocument(); normalizedXmlDefinition.LoadXml(item.XmlDefinition.OuterXml); // Perform pre-normalization. PreNormalizeXml(normalizedXmlDefinition); // Perform type-specific normalization. if (item.Type == WorkItemConfigurationItemType.WorkItemType) { NormalizeWorkItemTypeDefinition(normalizedXmlDefinition, tfsMajorVersion); } else if (item.Type == WorkItemConfigurationItemType.AgileConfiguration) { NormalizeAgileConfiguration(normalizedXmlDefinition); } else if (item.Type == WorkItemConfigurationItemType.CommonConfiguration) { NormalizeCommonConfiguration(normalizedXmlDefinition); } else if (item.Type == WorkItemConfigurationItemType.ProcessConfiguration) { NormalizeProcessConfiguration(normalizedXmlDefinition); } else if (item.Type == WorkItemConfigurationItemType.Categories) { NormalizeCategories(normalizedXmlDefinition); } // Perform other normalization after the specific normalization (nodes could have been added or removed). PostNormalizeXml(normalizedXmlDefinition); return(normalizedXmlDefinition); }
public static WorkItemConfigurationComparisonResult Compare(TfsMajorVersion tfsMajorVersion, WorkItemConfiguration source, WorkItemConfiguration target, bool ignoreCase) { var itemResults = new List <WorkItemConfigurationItemComparisonResult>(); var sourceItems = source.Items.ToList(); var targetItems = target.Items.ToList(); // Ignore TFS 2012 agile/common config when both source and target have TFS 2013 process config. if (sourceItems.Any(i => i.Type == WorkItemConfigurationItemType.ProcessConfiguration) && targetItems.Any(i => i.Type == WorkItemConfigurationItemType.ProcessConfiguration)) { sourceItems.RemoveAll(i => i.Type == WorkItemConfigurationItemType.CommonConfiguration || i.Type == WorkItemConfigurationItemType.AgileConfiguration); targetItems.RemoveAll(i => i.Type == WorkItemConfigurationItemType.CommonConfiguration || i.Type == WorkItemConfigurationItemType.AgileConfiguration); } // If the source doesn't have categories or agile/common/process config, ignore them in the target as well. if (!sourceItems.Any(i => i.Type == WorkItemConfigurationItemType.Categories)) { targetItems.RemoveAll(i => i.Type == WorkItemConfigurationItemType.Categories); } if (!sourceItems.Any(i => i.Type == WorkItemConfigurationItemType.AgileConfiguration)) { targetItems.RemoveAll(i => i.Type == WorkItemConfigurationItemType.AgileConfiguration); } if (!sourceItems.Any(i => i.Type == WorkItemConfigurationItemType.CommonConfiguration)) { targetItems.RemoveAll(i => i.Type == WorkItemConfigurationItemType.CommonConfiguration); } if (!sourceItems.Any(i => i.Type == WorkItemConfigurationItemType.ProcessConfiguration)) { targetItems.RemoveAll(i => i.Type == WorkItemConfigurationItemType.ProcessConfiguration); } foreach (var itemOnlyInSource in sourceItems.Where(s => !targetItems.Any(t => s.Type == t.Type && string.Equals(s.Name, t.Name, StringComparison.OrdinalIgnoreCase)))) { itemResults.Add(new WorkItemConfigurationItemComparisonResult(itemOnlyInSource.XmlDefinition, null, itemOnlyInSource.Name, itemOnlyInSource.Type, ComparisonStatus.ExistsOnlyInSource)); } var comparisonType = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; foreach (var targetItem in targetItems) { var sourceItem = sourceItems.FirstOrDefault(s => s.Type == targetItem.Type && string.Equals(s.Name, targetItem.Name, StringComparison.OrdinalIgnoreCase)); if (sourceItem == null) { itemResults.Add(new WorkItemConfigurationItemComparisonResult(null, targetItem.XmlDefinition, targetItem.Name, targetItem.Type, ComparisonStatus.ExistsOnlyInTarget)); } else { // To allow better comparisons between source XML files from Process Templates // and the actual exported work item configuration item, normalize and process some special cases. var sourceNormalizedXmlDefinition = XmlNormalizer.GetNormalizedXmlDefinition(sourceItem, tfsMajorVersion); var targetNormalizedXmlDefinition = XmlNormalizer.GetNormalizedXmlDefinition(targetItem, tfsMajorVersion); var partResults = new List <WorkItemConfigurationItemPartComparisonResult>(); var sourceParts = sourceItem.GetParts(sourceNormalizedXmlDefinition); var targetParts = targetItem.GetParts(targetNormalizedXmlDefinition); var totalSize = sourceParts.Sum(p => p.NormalizedXmlDefinition == null ? 0 : p.NormalizedXmlDefinition.OuterXml.Length); foreach (WorkItemConfigurationItemPart sourcePart in sourceParts) { var targetPart = targetParts.SingleOrDefault(p => p.Name == sourcePart.Name); ComparisonStatus status; if (targetPart == null) { status = ComparisonStatus.ExistsOnlyInSource; } else { status = string.Equals(XmlNormalizer.GetValue(sourcePart.NormalizedXmlDefinition), XmlNormalizer.GetValue(targetPart.NormalizedXmlDefinition), comparisonType) ? ComparisonStatus.AreEqual : ComparisonStatus.AreDifferent; } var relativeSize = (sourcePart.NormalizedXmlDefinition == null ? 0 : sourcePart.NormalizedXmlDefinition.OuterXml.Length) / (double)totalSize; partResults.Add(new WorkItemConfigurationItemPartComparisonResult(sourcePart.Name, status, relativeSize)); } itemResults.Add(new WorkItemConfigurationItemComparisonResult(sourceNormalizedXmlDefinition, targetNormalizedXmlDefinition, sourceItem.Name, sourceItem.Type, partResults)); } } return(new WorkItemConfigurationComparisonResult(source, target, itemResults)); }
private async Task <ICollection <BuildDefinitionTemplate> > GetBuildTemplatesAsync(TfsMajorVersion tfsVersion, bool fromBuildDefinitions) { var buildTemplates = new List <BuildDefinitionTemplate>(); using (var dialog = new TeamProjectPicker(TeamProjectPickerMode.SingleProject, false)) { var result = dialog.ShowDialog(Application.Current.MainWindow.GetIWin32Window()); if (result == System.Windows.Forms.DialogResult.OK && dialog.SelectedProjects != null && dialog.SelectedProjects.Length > 0) { var teamProjectCollection = dialog.SelectedTeamProjectCollection; var teamProject = dialog.SelectedProjects.First(); var buildServer = teamProjectCollection.GetClient <BuildHttpClient>(); if (fromBuildDefinitions) { var buildDefinitions = new List <BuildDefinition>(); if (tfsVersion == TfsMajorVersion.TeamServices) { // Use a single API call if available. var projectBuildDefinitions = await buildServer.GetFullDefinitionsAsync(project : teamProject.Name); buildDefinitions.AddRange(projectBuildDefinitions); } else { // Otherwise get the base info first and then individual details. var baseBuildDefinitions = await buildServer.GetDefinitionsAsync(project : teamProject.Name); foreach (var baseBuildDefinition in baseBuildDefinitions.Where(b => b.Type == DefinitionType.Build)) { var buildDefinition = await buildServer.GetDefinitionAsync(project : teamProject.Name, definitionId : baseBuildDefinition.Id); buildDefinitions.Add(buildDefinition); } } buildDefinitions = buildDefinitions.Where(b => b.Type == DefinitionType.Build).OrderBy(b => b.Name).ToList(); if (!buildDefinitions.Any()) { MessageBox.Show("The selected Team Project does not contain any build definitions.", "No Build Definitions", MessageBoxButton.OK, MessageBoxImage.Information); } else { foreach (var buildDefinition in buildDefinitions) { var template = new BuildDefinitionTemplate { Id = buildDefinition.Name.Replace(" ", ""), Name = buildDefinition.Name, Description = "Build template based on build definition \"{0}\" in Team Project \"{1}\"".FormatCurrent(buildDefinition.Name, teamProject.Name), Template = buildDefinition }; buildTemplates.Add(template); } } } else { var buildTemplatesFromProject = await buildServer.GetTemplatesAsync(project : teamProject.Name); buildTemplatesFromProject = buildTemplatesFromProject.Where(t => t.Template != null && t.Template.Project != null).OrderBy(t => t.Name).ToList(); if (!buildTemplatesFromProject.Any()) { MessageBox.Show("The selected Team Project does not contain any build templates.", "No Build Templates", MessageBoxButton.OK, MessageBoxImage.Information); } else { foreach (var buildTemplate in buildTemplatesFromProject) { buildTemplates.Add(buildTemplate); } } } } } if (buildTemplates.Any()) { var picker = new ItemsPickerDialog(); picker.ItemDisplayMemberPath = nameof(BuildDefinitionTemplate.Name); picker.Owner = Application.Current.MainWindow; picker.Title = fromBuildDefinitions ? "Select the build definitions to import" : "Select the build templates to import"; picker.SelectionMode = SelectionMode.Multiple; picker.AvailableItems = buildTemplates; if (picker.ShowDialog() == true) { return(picker.SelectedItems.Cast <BuildDefinitionTemplate>().ToArray()); } } return(new BuildDefinitionTemplate[0]); }