예제 #1
0
        public void StartMigration(bool isNotIncludeClosed, bool isNotIncludeRemoved, bool isIncludeHistoryComment, bool isIncludeHistoryLink, bool shouldFixMultilineFields)
        {
            if (workItemIdMap == null)
            {
                throw new InvalidFieldValueException(nameof(workItemIdMap) + " is not set");
            }


            if (FieldMap == null)
            {
                throw new InvalidFieldValueException(nameof(FieldMap) + " is not set");
            }


            logger.InfoFormat("--------------------------------Migration from '{0}' to '{1}' Start----------------------------------------------", sourceTFS.project.Name, targetTFS.project.Name);

            Log("Generating Areas & Iterations...");
            SetupAreasAndIterations();


            Log("Copying Team Queries...");
            CopyTeamQueries();

            Log("Copying Work Items...");
            WorkItemMigration mig = new WorkItemMigration(sourceTFS, targetTFS);

            mig.WorkitemTemplateMap = FieldMap;
            mig.UsersMap            = Usermap;
            mig.WorkItemIdMap       = workItemIdMap;
            mig.CopyWorkItems(isNotIncludeClosed, isNotIncludeRemoved, isIncludeHistoryComment, isIncludeHistoryLink, shouldFixMultilineFields);

            Log("Copying Test Plans...");
            TestPlanMigration tcm = new TestPlanMigration(sourceTFS, targetTFS);

            tcm.UsersMap      = Usermap;
            tcm.WorkItemIdMap = workItemIdMap;
            tcm.CopyTestPlans();

            Log("Project Migrated");
            logger.Info("--------------------------------Migration END----------------------------------------------");
        }
예제 #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();
                }
            }
        }