Пример #1
0
        private static void Main(string[] args)
        {
            var options = new Options();

            if (Parser.Default.ParseArguments(args, options))
            {
                var sourceTfsUrl      = options.SourceTfsCollectionUrl;
                var targetTfsUrl      = options.TargetTfsCollectionUrl;
                var sourceProjectName = options.SourceProjectName;
                var targetProjectName = options.TargetProjectName;

                var sourceProject = Utils.Utils.GetWorkItemStore(sourceTfsUrl, false).Projects[sourceProjectName];

                var targetProject = Utils.Utils.GetWorkItemStore(targetTfsUrl, false).Projects[targetProjectName];

                Dictionary <string, string> manualMappings = new Dictionary <string, string>();
                if (options.ManualMappings != null && options.ManualMappings.Count > 0)
                {
                    foreach (var manualMapping in options.ManualMappings)
                    {
                        var split = manualMapping.Split(':');
                        manualMappings.Add(split[0], split[1]);
                    }
                }
                List <WorkItemTypeMapping> workItemMappings = Utils.Utils.CreateWorkItemTypeMapping(sourceProject.WorkItemTypes, targetProject.WorkItemTypes, manualMappings);
                WorkItemStoreMapping       wism             = new WorkItemStoreMapping()
                {
                    WorkItemTypeMapping = workItemMappings.Where(t => options.WorkItemTypes.Contains(t.SourceWorkItemType)).ToArray()
                };

                XmlSerializer serializer = new XmlSerializer(typeof(WorkItemStoreMapping), new Type[] { typeof(WorkItemFieldMapping), typeof(WorkItemTypeMapping) });

                using (var sw = new StreamWriter(options.Output))
                {
                    serializer.Serialize(sw, wism);
                }

                List <WorkItemType> missingTargetWorkItemTypes = new List <WorkItemType>();
                List <WorkItemType> mappedSourceWorkItemTypes  = new List <WorkItemType>();

                foreach (WorkItemType sourceWorkItemType in sourceProject.WorkItemTypes.Cast <WorkItemType>().Where(t => options.WorkItemTypes.Contains(t.Name)))
                {
                    Console.WriteLine("------");
                    var query = targetProject.WorkItemTypes.Cast <WorkItemType>().Where(p => p.Name == sourceWorkItemType.Name);
                    var targetWorkItemType = query.FirstOrDefault();
                    if (targetWorkItemType != null)
                    {
                        var missingOnTargetSite = sourceWorkItemType.FieldDefinitions.Cast <FieldDefinition>().Except(targetWorkItemType.FieldDefinitions.Cast <FieldDefinition>(), new FieldDefinitionComparer());

                        if (missingOnTargetSite.Any())
                        {
                            Console.WriteLine("Missing fields on SourceWorkItemType {0}", sourceWorkItemType.Name);
                            foreach (var missingField in missingOnTargetSite)
                            {
                                Console.WriteLine("\t" + missingField.ReferenceName);
                            }

                            var possibleReplacements = targetWorkItemType.FieldDefinitions.Cast <FieldDefinition>().Except(sourceWorkItemType.FieldDefinitions.Cast <FieldDefinition>(), new FieldDefinitionComparer());
                            if (possibleReplacements.Any())
                            {
                                Console.WriteLine("Unmapped fields on target site:");
                                foreach (var possibleReplacementField in possibleReplacements)
                                {
                                    Console.WriteLine("\t" + possibleReplacementField.ReferenceName);
                                }
                            }
                        }
                        mappedSourceWorkItemTypes.Add(targetWorkItemType);
                    }
                    else if (manualMappings.ContainsKey(sourceWorkItemType.Name))
                    {
                        Console.WriteLine($"Manual Mapping {sourceWorkItemType.Name}:{manualMappings[sourceWorkItemType.Name]} was added with the commandline");
                        mappedSourceWorkItemTypes.Add(targetWorkItemType);
                    }
                    else
                    {
                        Console.WriteLine($"targetWorkItemtype {sourceWorkItemType.Name} was missing on targetProject");
                        missingTargetWorkItemTypes.Add(sourceWorkItemType);
                    }
                }

                var unmappedTargetWorkItemTypes = new List <WorkItemType>();
                foreach (WorkItemType targetWorkItemType in targetProject.WorkItemTypes)
                {
                    if (!mappedSourceWorkItemTypes.Contains(targetWorkItemType) && !manualMappings.ContainsValue(targetWorkItemType.Name))
                    {
                        unmappedTargetWorkItemTypes.Add(targetWorkItemType);
                    }
                }

                Console.WriteLine("Unmapped WorkItemType on SourceProject: ");
                foreach (var wi in missingTargetWorkItemTypes)
                {
                    Console.WriteLine(wi.Name);
                }

                Console.WriteLine("Unmapped WorkItemType on TargetProject: ");
                foreach (var wi in unmappedTargetWorkItemTypes)
                {
                    Console.WriteLine(wi.Name);
                }

                Console.WriteLine("You can manually add mapping by using the --Mapping command line switch");

                if (!options.AutoClose)
                {
                    Console.WriteLine("push the <any> key to quit");
                    Console.ReadKey();
                }
            }
        }
Пример #2
0
        private static void Main(string[] args)
        {
            var options = new Options();

            if (Parser.Default.ParseArguments(args, options))
            {
                if (options.AddLinksToOldWorkItems && options.SourceTfsCollectionUrl != options.TargetTfsCollectionUrl)
                {
                    Console.WriteLine("You can't keep links to old work items if you are not migrating within the same tfs collection!");
                    Environment.Exit(1);
                }

                var    initialPosition     = Console.CursorTop;
                string workItemMappingFile = options.WorkItemMappingFile;

                bool cloneWorkItems = options.CloneWorkItems;
                bool cloneQueries   = options.CloneQueries;
                bool cloneTestPlans = options.CloneTestPlans;

                var sourceTfsUrl      = options.SourceTfsCollectionUrl;
                var targetTfsUrl      = options.TargetTfsCollectionUrl;
                var sourceProjectName = options.SourceProjectName;
                var targetProjectName = options.TargetProjectName;

                string connectionstring;
                if (!string.IsNullOrWhiteSpace(options.ConnectionString))
                {
                    connectionstring = options.ConnectionString;
                }
                else
                {
                    connectionstring = ConfigurationManager.ConnectionStrings["VSOMigrDB"]?.ConnectionString;
                }

                if (string.IsNullOrWhiteSpace(connectionstring))
                {
                    throw new Exception("connectionstring was not valid");
                }

                Dictionary <int, string> invalidWorkItems = new Dictionary <int, string>();
                var targetWorkitemStore = Utils.Utils.GetWorkItemStore(targetTfsUrl, true);
                var stopwatch           = Stopwatch.StartNew();
                if (options.CloneAreas)
                {
                    if (string.IsNullOrEmpty(options.AreaRoot))
                    {
                        if (Utils.Utils.GetWorkItems(targetWorkitemStore, targetProjectName).Count > 0)
                        {
                            Console.WriteLine("there are already workitems in the project, cloning areas an iterations will destroy previous work!");
                            Environment.Exit(1);
                        }
                    }
                    Utils.Utils.CopyAreaNodes(sourceTfsUrl, sourceProjectName, targetTfsUrl, targetProjectName, options.AreaRoot);
                }
                if (options.CloneIterations)
                {
                    Utils.Utils.CopyIterationNodes(sourceTfsUrl, sourceProjectName, targetTfsUrl, targetProjectName, options.IterationRoot);
                }

                if (cloneWorkItems)
                {
                    WorkItemStoreMapping wism = Utils.Utils.ReadWorkItemMappingFile(workItemMappingFile);

                    targetWorkitemStore = Utils.Utils.GetWorkItemStore(targetTfsUrl, true);
                    var sourceWorkitemStore = Utils.Utils.GetWorkItemStore(sourceTfsUrl, false);

                    var            targetProject = targetWorkitemStore.Projects[targetProjectName];
                    var            sourceProject = sourceWorkitemStore.Projects[sourceProjectName];
                    NodeCollection targetAreaNodeCollection;
                    NodeCollection targetIterationNodeCollection;
                    if (string.IsNullOrEmpty(options.AreaRoot))
                    {
                        targetAreaNodeCollection = targetProject.AreaRootNodes;
                    }
                    else
                    {
                        targetAreaNodeCollection = targetProject.FindNodeInSubTree(options.AreaRoot, Node.TreeType.Area).ChildNodes;
                    }

                    if (string.IsNullOrEmpty(options.IterationRoot))
                    {
                        targetIterationNodeCollection = targetProject.IterationRootNodes;
                    }
                    else
                    {
                        targetIterationNodeCollection = targetProject.FindNodeInSubTree(options.IterationRoot, Node.TreeType.Iteration).ChildNodes;
                    }

                    var areaNodeMap      = Utils.Utils.GetNodeMap(sourceProject.AreaRootNodes, targetAreaNodeCollection, !options.CloneAreas);
                    var iterationNodeMap = Utils.Utils.GetNodeMap(sourceProject.IterationRootNodes, targetIterationNodeCollection, !options.CloneIterations);

                    var  mapping      = new Dictionary <int, int>();
                    var  notLinkedYet = 0;
                    var  exceptions   = new List <string>();
                    var  retryIdx     = 0;
                    bool done         = false;
                    while (retryIdx < 10 && !done)
                    {
                        try
                        {
                            using (var ctx = new Data.VSOMigrDB(connectionstring))
                            {
                                //regenerate mapping
                                mapping = ctx.WorkItemRevisions.Where(t => t.Migrated && t.Revision == 0 && t.NewId != 0).ToDictionary(wir => wir.OriginalId, wir => wir.NewId);
                                var revisionOperations = ctx.WorkItemRevisions.Where(t => !t.Migrated && t.Project == sourceProjectName).OrderBy(t => t.Changed).ThenBy(t => t.Revision).ToList();
                                var count   = revisionOperations.Count();
                                int counter = 0;
                                foreach (var wiRev in revisionOperations)
                                {
                                    if (!invalidWorkItems.ContainsKey(wiRev.OriginalId))
                                    {
                                        counter++;
                                        Console.SetCursorPosition(0, initialPosition);
                                        Console.WriteLine(counter + "/" + count);

                                        if (wiRev.Kind == "link")
                                        {
                                            if (!mapping.ContainsKey(wiRev.OriginalId))
                                            {
                                                ////if (options.AddLinksToOldWorkItems)
                                                ////{
                                                ////    var a = int.Parse(wiRev.ChangedFields);
                                                ////    //ChangedFields contains the target id of the link
                                                ////    //OriginalId contains original source id of link
                                                ////    //TargetId contains the migrated source id of the link//this one will always be empty, so ignore it
                                                ////    //1. check if one of the 2 id's was migrated, if none was migrated ignore link we don't need to do anything
                                                ////    //2. if source id of link was migrated
                                                ////    //3. if target id of link was migrated
                                                ////    //var sourceWorkItem = sourceWorkitemStore.GetWorkItem(wiRev.OriginalId);
                                                ////    //var sourceWorkItemLinkHistoryRev = sourceWorkItem.WorkItemLinkHistory.Cast<WorkItemLink>().Where(wil => wil.RemovedDate.Year == 9999 && wil.TargetId.ToString() == wiRev.ChangedFields).First();
                                                ////    //var linkTypeEnd = targetWorkitemStore.WorkItemLinkTypes.LinkTypeEnds[sourceWorkItemLinkHistoryRev.LinkTypeEnd.Name];
                                                ////    //var workItemLink = new WorkItemLink(linkTypeEnd, mapping[sourceWorkItemLinkHistoryRev.SourceId], mapping[sourceWorkItemLinkHistoryRev.TargetId]);
                                                ////    //workItemLink.ChangedDate = sourceWorkItemLinkHistoryRev.ChangedDate;
                                                ////    //targetWorkItem.WorkItemLinks.Add(workItemLink);
                                                ////    //var errors = targetWorkItem.Validate();
                                                ////    //if (errors.Count == 0)
                                                ////    //{
                                                ////    //    targetWorkItem.Save();
                                                ////    //}
                                                ////    //else
                                                ////    //{
                                                ////    //    invalidWorkItems.Add(wiRev.OriginalId, string.Join(Environment.NewLine, errors.Cast<Field>().Select(f => f.ReferenceName + " " + f.Status.ToString())));
                                                ////    //}
                                                ////}
                                                ////else
                                                ////{
                                                //this item was not migrated, maybe you didn't want it?
                                                continue;
                                                ////}
                                            }
                                            else
                                            {
                                                var targetWorkItem = targetWorkitemStore.GetWorkItem(mapping[wiRev.OriginalId]);
                                                var sourceWorkItem = sourceWorkitemStore.GetWorkItem(wiRev.OriginalId);

                                                var sourceWorkItemLinkHistoryRev = sourceWorkItem.WorkItemLinkHistory.Cast <WorkItemLink>().Where(wil => wil.RemovedDate.Year == 9999 && wil.TargetId.ToString() == wiRev.ChangedFields).First();

                                                if (mapping.ContainsKey(sourceWorkItemLinkHistoryRev.TargetId))
                                                {
                                                    if (targetWorkitemStore.GetWorkItem(mapping[sourceWorkItemLinkHistoryRev.TargetId]).WorkItemLinks.Cast <WorkItemLink>().Where(wil => wil.TargetId == targetWorkItem.Id || wil.SourceId == targetWorkItem.Id).Any())
                                                    {
                                                        //Link exists already.
                                                        continue;
                                                    }
                                                    else
                                                    {
                                                        var linkTypeEnd  = targetWorkitemStore.WorkItemLinkTypes.LinkTypeEnds[sourceWorkItemLinkHistoryRev.LinkTypeEnd.Name];
                                                        var workItemLink = new WorkItemLink(linkTypeEnd, mapping[sourceWorkItemLinkHistoryRev.SourceId], mapping[sourceWorkItemLinkHistoryRev.TargetId])
                                                        {
                                                            ChangedDate = sourceWorkItemLinkHistoryRev.ChangedDate
                                                        };
                                                        targetWorkItem.WorkItemLinks.Add(workItemLink);

                                                        var errors = targetWorkItem.Validate();
                                                        if (errors.Count == 0)
                                                        {
                                                            targetWorkItem.Save();
                                                        }
                                                        else
                                                        {
                                                            invalidWorkItems.Add(wiRev.OriginalId, string.Join(Environment.NewLine, errors.Cast <Field>().Select(f => f.ReferenceName + " " + f.Status.ToString())));
                                                        }
                                                    }
                                                }
                                                else
                                                {
                                                    // target of the link was not migrated, check if we want to link to old workitems
                                                    if (options.AddLinksToOldWorkItems)
                                                    {
                                                        //how can we check that we will migrate this one or not....
                                                        //add a link to sourceWorkItemLinkHistoryRev.TargetId
                                                        if (sourceWorkitemStore.GetWorkItem(sourceWorkItemLinkHistoryRev.TargetId).WorkItemLinks.Cast <WorkItemLink>().Where(wil => wil.TargetId == targetWorkItem.Id || wil.SourceId == targetWorkItem.Id).Any())
                                                        {
                                                            continue;
                                                        }
                                                        else
                                                        {
                                                            var linkTypeEnd  = targetWorkitemStore.WorkItemLinkTypes.LinkTypeEnds[sourceWorkItemLinkHistoryRev.LinkTypeEnd.Name];
                                                            var workItemLink = new WorkItemLink(linkTypeEnd, targetWorkItem.Id, sourceWorkItemLinkHistoryRev.TargetId)
                                                            {
                                                                ChangedDate = sourceWorkItemLinkHistoryRev.ChangedDate
                                                            };
                                                            targetWorkItem.WorkItemLinks.Add(workItemLink);

                                                            var errors = targetWorkItem.Validate();
                                                            if (errors.Count == 0)
                                                            {
                                                                targetWorkItem.Save();
                                                            }
                                                            else
                                                            {
                                                                invalidWorkItems.Add(wiRev.OriginalId, string.Join(Environment.NewLine, errors.Cast <Field>().Select(f => f.ReferenceName + " " + f.Status.ToString())));
                                                            }
                                                        }
                                                    }
                                                    else
                                                    {
                                                        continue;
                                                    }
                                                }
                                            }
                                        }
                                        else if (wiRev.Kind == "revision")
                                        {
                                            var sourceWorkItem = sourceWorkitemStore.GetWorkItem(wiRev.OriginalId);
                                            var sourceWiRev    = sourceWorkItem.Revisions[wiRev.Revision];

                                            bool     isNew = false;
                                            WorkItem targetWorkItem;
                                            if (wiRev.Revision == 0)
                                            {
                                                var workItemTypeMapping = wism.WorkItemTypeMapping.Where(p => p.SourceWorkItemType == sourceWorkItem.Type.Name).FirstOrDefault();
                                                if (workItemTypeMapping != null)
                                                {
                                                    var targetWorkItemTypeName = workItemTypeMapping.TargetWorkItemType;
                                                    targetWorkItem = new WorkItem(targetProject.WorkItemTypes[targetWorkItemTypeName]);
                                                    isNew          = true;
                                                }
                                                else
                                                {
                                                    Trace.WriteLine($"{sourceWorkItem.Type.Name} was not found in the WorkItemMappingFile");
                                                    continue;
                                                }
                                            }
                                            else
                                            {
                                                if (!mapping.ContainsKey(wiRev.OriginalId))
                                                {
                                                    //this work item was not migrated, maybe you didn't want it?
                                                    continue;
                                                }
                                                else
                                                {
                                                    targetWorkItem = targetWorkitemStore.GetWorkItem(mapping[wiRev.OriginalId]);
                                                }
                                            }

                                            Utils.Utils.CopyFields(sourceWiRev, targetWorkItem, areaNodeMap, iterationNodeMap, targetProject, sourceProject, wism, isNew, options.AreaRoot, options.IterationRoot);

                                            if (targetWorkItem.Fields[CoreField.ChangedDate].Value != null)
                                            {
                                                if (targetWorkItem.Fields[CoreField.ChangedDate].OriginalValue != null)
                                                {
                                                    if ((DateTime)targetWorkItem.Fields[CoreField.ChangedDate].Value < (DateTime)targetWorkItem.Fields[CoreField.ChangedDate].OriginalValue)
                                                    {
                                                        Trace.WriteLine("PROBLEM!!!");
                                                        //problem!!!
                                                    }
                                                }
                                            }
                                            else
                                            {
                                                Trace.WriteLine("WTF!!");
                                            }

                                            var errors = targetWorkItem.Validate();
                                            if (errors.Count == 0)
                                            {
                                                targetWorkItem.Save();
                                                if (isNew)
                                                {
                                                    mapping.Add(sourceWorkItem.Id, targetWorkItem.Id);
                                                    wiRev.NewId = targetWorkItem.Id;
                                                }
                                                wiRev.Migrated = true;
                                            }
                                            else
                                            {
                                                invalidWorkItems.Add(wiRev.OriginalId, string.Join(Environment.NewLine, errors.Cast <Field>().Select(f => f.ReferenceName + " " + f.Status.ToString())));
                                            }
                                        }
                                        ctx.SaveChanges();
                                    }
                                }
                                done = true;
                            }
                        }
                        catch (Exception ex)
                        {
                            retryIdx++;
                            Console.SetCursorPosition(0, initialPosition + 2);
                            Console.WriteLine("retry index: {0}", retryIdx);
                            Console.SetCursorPosition(0, initialPosition + 3);
                            Console.WriteLine(ex.ToString());
                            exceptions.Add(ex.ToString());
                            Thread.Sleep(TimeSpan.FromSeconds(60 * retryIdx));
                            done = false;
                        }
                    }

                    using (var sw = new StreamWriter(options.LogFile))
                    {
                        sw.WriteLine("{0} links not yet done!", notLinkedYet);
                        sw.WriteLine("Elapsed seconds: " + stopwatch.Elapsed.TotalSeconds);
                        sw.WriteLine("retries: " + retryIdx);
                        foreach (var ex in exceptions)
                        {
                            sw.WriteLine(ex);
                        }

                        foreach (var kvp in invalidWorkItems)
                        {
                            sw.WriteLine(kvp.Key + ": " + kvp.Value);
                        }
                    }
                }

                if (cloneTestPlans)
                {
                    Dictionary <int, int> mapping;
                    using (var ctx = new Data.VSOMigrDB(connectionstring))
                    {
                        mapping = ctx.WorkItemRevisions.Where(t => t.Migrated && t.Revision == 0 && t.NewId != 0).ToDictionary(wir => wir.OriginalId, wir => wir.NewId);
                    }

                    var testPlanMigration = new TestPlanMigration(sourceTfsUrl, targetTfsUrl, sourceProjectName, targetProjectName, mapping);
                    testPlanMigration.CopyTestPlans();
                }

                if (cloneQueries)
                {
                    var targetTuple = Utils.Utils.GetShareQueryFolder(targetTfsUrl, targetProjectName);

                    var sourceTuple = Utils.Utils.GetShareQueryFolder(sourceTfsUrl, sourceProjectName);

                    Utils.Utils.CopySubStuff(sourceTuple.Item2, targetTuple.Item2);

                    targetTuple.Item1.QueryHierarchy.Save();
                }

                if (!options.AutoClose)
                {
                    Console.WriteLine("push the <any> key to quit");
                    Console.ReadKey();
                }
            }
        }