Example #1
0
 public WorkItemTypeInfo(TeamProjectInfo teamProject, string name, string description, int workItemCount, ICollection <string> workItemCategories, WorkItemTypeDefinition workItemTypeDefinition)
 {
     this.TeamProject            = teamProject;
     this.Name                   = name;
     this.Description            = description;
     this.WorkItemCount          = workItemCount;
     this.WorkItemCategories     = workItemCategories;
     this.WorkItemCategoriesList = this.WorkItemCategories == null ? null : string.Join(", ", this.WorkItemCategories);
     this.WorkItemTypeDefinition = workItemTypeDefinition;
 }
        private void Import(object argument)
        {
            var options = ImportOptions.None;

            if (this.Simulate)
            {
                options |= ImportOptions.Simulate;
            }
            if (this.SaveCopy)
            {
                options |= ImportOptions.SaveCopy;
            }
            var workItemTypes = new List <WorkItemConfigurationItem>();

            foreach (var workItemTypeFile in this.WorkItemTypeFiles)
            {
                try
                {
                    workItemTypes.Add(WorkItemTypeDefinition.FromFile(workItemTypeFile));
                }
                catch (Exception exc)
                {
                    this.Logger.Log(string.Format(CultureInfo.CurrentCulture, "An error occurred while loading the work item type from \"{0}\"", workItemTypeFile), exc);
                    MessageBox.Show(string.Format(CultureInfo.CurrentCulture, "An error occurred while loading the work item type from \"{0}\". See the log file for details", workItemTypeFile), "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
                }
            }
            var teamProjectsWithWorkItemTypes = this.SelectedTeamProjects.ToDictionary(p => p, p => workItemTypes);

            if (!options.HasFlag(ImportOptions.Simulate))
            {
                var result = MessageBox.Show("This will import the selected work item types. Are you sure you want to continue?", "Confirm Import", MessageBoxButton.YesNo, MessageBoxImage.Warning);
                if (result != MessageBoxResult.Yes)
                {
                    return;
                }
            }
            PerformImport(options, teamProjectsWithWorkItemTypes);
        }
        public static WorkItemConfiguration FromProcessTemplate(string processTemplateFileName)
        {
            // Load the process template XML.
            if (!File.Exists(processTemplateFileName))
            {
                throw new FileNotFoundException("The process template file does not exist: " + processTemplateFileName);
            }
            var processTemplate = new XmlDocument();

            processTemplate.Load(processTemplateFileName);
            var    baseDir                 = Path.GetDirectoryName(processTemplateFileName);
            var    items                   = new List <WorkItemConfigurationItem>();
            string processTemplateName     = null;
            var    processTemplateNameNode = processTemplate.SelectSingleNode("/ProcessTemplate/metadata/name");

            if (processTemplateNameNode != null)
            {
                processTemplateName = processTemplateNameNode.InnerText;
            }

            // Find the work item tracking XML file.
            var workItemFileNameAttribute = processTemplate.SelectSingleNode("/ProcessTemplate/groups/group[@id='WorkItemTracking']/taskList/@filename");

            if (workItemFileNameAttribute != null)
            {
                // Load the work item tracking XML.
                var workItemConfigurationTemplateFileName = Path.Combine(baseDir, workItemFileNameAttribute.InnerText);
                if (!File.Exists(workItemConfigurationTemplateFileName))
                {
                    throw new FileNotFoundException("The work item configuration file defined in the process template file does not exist: " + workItemConfigurationTemplateFileName);
                }
                var workItemConfigurationTemplate = new XmlDocument();
                workItemConfigurationTemplate.Load(workItemConfigurationTemplateFileName);

                // Find all work item type definition XML files.
                foreach (XmlAttribute witFileNameAttribute in workItemConfigurationTemplate.SelectNodes("/tasks/task[@id='WITs']/taskXml/WORKITEMTYPES/WORKITEMTYPE/@fileName"))
                {
                    var witFileName = Path.Combine(baseDir, witFileNameAttribute.InnerText);
                    items.Add(WorkItemTypeDefinition.FromFile(witFileName));
                }

                // Find the categories XML file.
                var categoriesFileNameAttribute = workItemConfigurationTemplate.SelectSingleNode("/tasks/task[@id='Categories']/taskXml/CATEGORIES/@fileName");
                if (categoriesFileNameAttribute != null)
                {
                    var categoriesFileName = Path.Combine(baseDir, categoriesFileNameAttribute.InnerText);
                    items.Add(WorkItemConfigurationItem.FromFile(categoriesFileName));
                }
                else
                {
                    // If the process template doesn't specify any categories (typically because it's an old
                    // process template from before Work Item Categories existed), load an empty list anyway.
                    // This will improve comparisons because a Team Project will always have a Work Item
                    // Categories configuration item (even if it's empty).
                    items.Add(WorkItemConfigurationItem.FromXml("<cat:CATEGORIES xmlns:cat=\"http://schemas.microsoft.com/VisualStudio/2008/workitemtracking/categories\"/>"));
                }

                // Find the common configuration XML file.
                var commonConfigurationFileNameAttribute = workItemConfigurationTemplate.SelectSingleNode("/tasks/task[@id='ProcessConfiguration']/taskXml/PROCESSCONFIGURATION/CommonConfiguration/@fileName");
                if (commonConfigurationFileNameAttribute != null)
                {
                    var commonConfigurationFileName = Path.Combine(baseDir, commonConfigurationFileNameAttribute.InnerText);
                    items.Add(WorkItemConfigurationItem.FromFile(commonConfigurationFileName));
                }

                // Find the agile configuration XML file.
                var agileConfigurationFileNameAttribute = workItemConfigurationTemplate.SelectSingleNode("/tasks/task[@id='ProcessConfiguration']/taskXml/PROCESSCONFIGURATION/AgileConfiguration/@fileName");
                if (agileConfigurationFileNameAttribute != null)
                {
                    var agileConfigurationFileName = Path.Combine(baseDir, agileConfigurationFileNameAttribute.InnerText);
                    items.Add(WorkItemConfigurationItem.FromFile(agileConfigurationFileName));
                }

                // Find the process configuration XML file.
                var processConfigurationFileNameAttribute = workItemConfigurationTemplate.SelectSingleNode("/tasks/task[@id='ProcessConfiguration']/taskXml/PROCESSCONFIGURATION/ProjectConfiguration/@fileName");
                if (processConfigurationFileNameAttribute != null)
                {
                    var processConfigurationFileName = Path.Combine(baseDir, processConfigurationFileNameAttribute.InnerText);
                    items.Add(WorkItemConfigurationItem.FromFile(processConfigurationFileName));
                }
            }

            return(new WorkItemConfiguration(processTemplateName, items));
        }
        private void ApplyTransformations(object argument)
        {
            var simulate = this.Simulate;
            var saveCopy = this.SaveCopy;

            if (!simulate)
            {
                var result = MessageBox.Show("This will apply the specified transformations to all selected Team Projects. Are you sure you want to continue?", "Confirm Transformation", MessageBoxButton.YesNo, MessageBoxImage.Warning);
                if (result != MessageBoxResult.Yes)
                {
                    return;
                }
            }
            var teamProjects    = this.SelectedTeamProjects.ToList();
            var transformations = this.Transformations.ToList();
            var task            = new ApplicationTask("Transforming work item configuration", teamProjects.Count, true);

            PublishStatus(new StatusEventArgs(task));
            var step   = 0;
            var worker = new BackgroundWorker();

            worker.DoWork += (sender, e) =>
            {
                var tfs   = GetSelectedTfsTeamProjectCollection();
                var store = tfs.GetService <WorkItemStore>();
                var numTransformations = 0;

                foreach (var teamProject in teamProjects)
                {
                    task.SetProgress(step++, string.Format(CultureInfo.CurrentCulture, "Processing Team Project \"{0}\"", teamProject.Name));
                    try
                    {
                        var project = store.Projects[teamProject.Name];

                        // Apply the transformations only if everything succeeded for the Team Project; cache them in the mean time.
                        var transformedItems = new List <WorkItemConfigurationItem>();
                        foreach (var transformation in transformations)
                        {
                            if (transformation.WorkItemConfigurationItemType == WorkItemConfigurationItemType.WorkItemType)
                            {
                                // Apply work item type definition transformation, which can apply to multiple work item type definitions (semicolon separated).
                                // If no work item type names are specified, apply to all work item types in the project.
                                var workItemTypeNames = (string.IsNullOrEmpty(transformation.WorkItemTypeNames) ? project.WorkItemTypes.Cast <WorkItemType>().Select(w => w.Name) : transformation.WorkItemTypeNames.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries));
                                foreach (var workItemTypeName in workItemTypeNames)
                                {
                                    // If the work item type has already been processed before, continue with that version.
                                    var itemToTransform = transformedItems.FirstOrDefault(w => string.Equals(w.Name, workItemTypeName, StringComparison.OrdinalIgnoreCase));
                                    if (itemToTransform == null)
                                    {
                                        // If the work item type wasn't processed yet, find the one with the specified name (if it exists).
                                        var wit = project.WorkItemTypes.Cast <WorkItemType>().FirstOrDefault(w => string.Equals(w.Name, workItemTypeName, StringComparison.OrdinalIgnoreCase));
                                        if (wit != null)
                                        {
                                            itemToTransform = WorkItemTypeDefinition.FromXml(wit.Export(false));
                                        }
                                    }
                                    if (itemToTransform != null)
                                    {
                                        task.Status = "Transforming " + itemToTransform.DisplayName;
                                        var transformed = WorkItemConfigurationTransformer.Transform(transformation.TransformationType, itemToTransform.XmlDefinition, transformation.TransformationXml);
                                        if (string.Equals(itemToTransform.XmlDefinition.DocumentElement.OuterXml, transformed.DocumentElement.OuterXml))
                                        {
                                            task.Status = "The transformation was applied but did not result in any changes, skipping.";
                                        }
                                        else
                                        {
                                            itemToTransform.XmlDefinition = transformed;
                                            transformedItems.Add(itemToTransform);
                                        }
                                    }
                                    else
                                    {
                                        task.Status = "Skipping \"{0}\": a work item type with this name was not found in the Team Project".FormatCurrent(workItemTypeName);
                                    }
                                }
                            }
                            else if (transformation.WorkItemConfigurationItemType == WorkItemConfigurationItemType.Categories)
                            {
                                var itemToTransform = transformedItems.FirstOrDefault(w => w.Type == WorkItemConfigurationItemType.Categories);
                                if (itemToTransform == null)
                                {
                                    itemToTransform = WorkItemConfigurationItemImportExport.GetCategories(project);
                                }
                                task.Status = "Transforming " + itemToTransform.DisplayName;
                                var transformed = WorkItemConfigurationTransformer.Transform(transformation.TransformationType, itemToTransform.XmlDefinition, transformation.TransformationXml);
                                if (string.Equals(itemToTransform.XmlDefinition.DocumentElement.OuterXml, transformed.DocumentElement.OuterXml))
                                {
                                    task.Status = "The transformation was applied but did not result in any changes, skipping.";
                                }
                                else
                                {
                                    itemToTransform.XmlDefinition = transformed;
                                    transformedItems.Add(itemToTransform);
                                }
                            }
                            else if (transformation.WorkItemConfigurationItemType == WorkItemConfigurationItemType.AgileConfiguration)
                            {
                                var itemToTransform = transformedItems.FirstOrDefault(w => w.Type == WorkItemConfigurationItemType.AgileConfiguration);
                                if (itemToTransform == null)
                                {
                                    itemToTransform = WorkItemConfigurationItemImportExport.GetAgileConfiguration(project);
                                }
                                if (itemToTransform != null)
                                {
                                    task.Status = "Transforming " + itemToTransform.DisplayName;
                                    var transformed = WorkItemConfigurationTransformer.Transform(transformation.TransformationType, itemToTransform.XmlDefinition, transformation.TransformationXml);
                                    if (string.Equals(itemToTransform.XmlDefinition.DocumentElement.OuterXml, transformed.DocumentElement.OuterXml))
                                    {
                                        task.Status = "The transformation was applied but did not result in any changes, skipping.";
                                    }
                                    else
                                    {
                                        itemToTransform.XmlDefinition = transformed;
                                        transformedItems.Add(itemToTransform);
                                    }
                                }
                            }
                            else if (transformation.WorkItemConfigurationItemType == WorkItemConfigurationItemType.CommonConfiguration)
                            {
                                var itemToTransform = transformedItems.FirstOrDefault(w => w.Type == WorkItemConfigurationItemType.CommonConfiguration);
                                if (itemToTransform == null)
                                {
                                    itemToTransform = WorkItemConfigurationItemImportExport.GetCommonConfiguration(project);
                                }
                                if (itemToTransform != null)
                                {
                                    task.Status = "Transforming " + itemToTransform.DisplayName;
                                    var transformed = WorkItemConfigurationTransformer.Transform(transformation.TransformationType, itemToTransform.XmlDefinition, transformation.TransformationXml);
                                    if (string.Equals(itemToTransform.XmlDefinition.DocumentElement.OuterXml, transformed.DocumentElement.OuterXml))
                                    {
                                        task.Status = "The transformation was applied but did not result in any changes, skipping.";
                                    }
                                    else
                                    {
                                        itemToTransform.XmlDefinition = transformed;
                                        transformedItems.Add(itemToTransform);
                                    }
                                }
                            }
                            else if (transformation.WorkItemConfigurationItemType == WorkItemConfigurationItemType.ProcessConfiguration)
                            {
                                var itemToTransform = transformedItems.FirstOrDefault(w => w.Type == WorkItemConfigurationItemType.ProcessConfiguration);
                                if (itemToTransform == null)
                                {
                                    itemToTransform = WorkItemConfigurationItemImportExport.GetProcessConfiguration(project);
                                }
                                if (itemToTransform != null)
                                {
                                    task.Status = "Transforming " + itemToTransform.DisplayName;
                                    var transformed = WorkItemConfigurationTransformer.Transform(transformation.TransformationType, itemToTransform.XmlDefinition, transformation.TransformationXml);
                                    if (string.Equals(itemToTransform.XmlDefinition.DocumentElement.OuterXml, transformed.DocumentElement.OuterXml))
                                    {
                                        task.Status = "The transformation was applied but did not result in any changes, skipping.";
                                    }
                                    else
                                    {
                                        itemToTransform.XmlDefinition = transformed;
                                        transformedItems.Add(itemToTransform);
                                    }
                                }
                            }
                            else
                            {
                                throw new ArgumentException("The Work Item Configuration Item Type is unknown: " + transformation.WorkItemConfigurationItemType.ToString());
                            }
                            if (task.IsCanceled)
                            {
                                break;
                            }
                        }

                        // Only apply the transformations if they all succeeded (i.e. there was no exception).
                        if (task.IsCanceled)
                        {
                            break;
                        }
                        else
                        {
                            var teamProjectsWithConfigurationItems = new Dictionary <TeamProjectInfo, List <WorkItemConfigurationItem> >()
                            {
                                { teamProject, transformedItems }
                            };
                            var options = ImportOptions.None;
                            if (simulate)
                            {
                                options |= ImportOptions.Simulate;
                            }
                            if (saveCopy)
                            {
                                options |= ImportOptions.SaveCopy;
                            }
                            WorkItemConfigurationItemImportExport.Import(this.Logger, task, false, store, teamProjectsWithConfigurationItems, options);
                        }
                        numTransformations += transformedItems.Count;
                    }
                    catch (Exception exc)
                    {
                        task.SetWarning(string.Format(CultureInfo.CurrentCulture, "An error occurred while processing Team Project \"{0}\"", teamProject.Name), exc);
                    }
                    if (task.IsCanceled)
                    {
                        task.Status = "Canceled";
                        break;
                    }
                }
                e.Result = numTransformations;
            };
            worker.RunWorkerCompleted += (sender, e) =>
            {
                if (e.Error != null)
                {
                    Logger.Log("An unexpected exception occurred while transforming work item configuration", e.Error);
                    task.SetError(e.Error);
                    task.SetComplete("An unexpected exception occurred");
                }
                else
                {
                    var numTransformations = (int)e.Result;
                    task.SetComplete("Applied transformation to " + numTransformations.ToCountString("work item configuration item"));
                }
            };
            worker.RunWorkerAsync();
        }
        private void GetWorkItemTypes(object argument)
        {
            var teamProjects = this.SelectedTeamProjects.ToList();
            var task         = new ApplicationTask("Retrieving work item types", teamProjects.Count, true);

            PublishStatus(new StatusEventArgs(task));
            var step   = 0;
            var worker = new BackgroundWorker();

            worker.DoWork += (sender, e) =>
            {
                var tfs   = GetSelectedTfsTeamProjectCollection();
                var store = tfs.GetService <WorkItemStore>();

                var results = new List <WorkItemTypeInfo>();
                foreach (var teamProject in teamProjects)
                {
                    task.SetProgress(step++, string.Format(CultureInfo.CurrentCulture, "Processing Team Project \"{0}\"", teamProject.Name));
                    try
                    {
                        var project       = store.Projects[teamProject.Name];
                        var categoriesXml = WorkItemConfigurationItemImportExport.GetCategoriesXml(project);
                        var categoryList  = WorkItemCategoryList.Load(categoriesXml);

                        foreach (WorkItemType workItemType in project.WorkItemTypes)
                        {
                            var parameters = new Dictionary <string, object>()
                            {
                                { "WorkItemType", workItemType.Name },
                                { "TeamProject", workItemType.Project.Name }
                            };
                            var workItemCount          = store.QueryCount("SELECT [System.Id] FROM WorkItems WHERE [System.WorkItemType] = @WorkItemType AND [System.TeamProject] = @TeamProject", parameters);
                            var referencingCategories  = categoryList.Categories.Where(c => c.WorkItemTypes.Concat(new WorkItemTypeReference[] { c.DefaultWorkItemType }).Any(w => string.Equals(w.Name, workItemType.Name, StringComparison.OrdinalIgnoreCase))).Select(c => c.Name);
                            var workItemTypeDefinition = WorkItemTypeDefinition.FromXml(workItemType.Export(false));
                            results.Add(new WorkItemTypeInfo(teamProject, workItemType.Name, workItemType.Description, workItemCount, referencingCategories.ToList(), workItemTypeDefinition));
                        }
                    }
                    catch (Exception exc)
                    {
                        task.SetWarning(string.Format(CultureInfo.CurrentCulture, "An error occurred while processing Team Project \"{0}\"", teamProject.Name), exc);
                    }
                    if (task.IsCanceled)
                    {
                        task.Status = "Canceled";
                        break;
                    }
                }
                e.Result = results;
            };
            worker.RunWorkerCompleted += (sender, e) =>
            {
                if (e.Error != null)
                {
                    Logger.Log("An unexpected exception occurred while retrieving work item types", e.Error);
                    task.SetError(e.Error);
                    task.SetComplete("An unexpected exception occurred");
                }
                else
                {
                    this.WorkItemTypes = (ICollection <WorkItemTypeInfo>)e.Result;
                    task.SetComplete("Retrieved " + this.WorkItemTypes.Count.ToCountString("work item type"));
                }
            };
            worker.RunWorkerAsync();
        }