Example #1
0
        public void IsMigrationItemEqualsToHistory()
        {
            //arrange
            var step = new TestStep(ExecutionResult.Success);
            var positiveCaseStepName = MigrationHandler.StepIdentity(step);
            var positiveCaseVersion  = new Version("1.2.3.4");
            var negativeCaseVersion  = new Version("4.3.2.1");
            var migrationItem        = new MigrationItem(positiveCaseVersion, new TestStep(ExecutionResult.Success));
            var migrationHistory     = new MigrationHistory
            {
                Name    = positiveCaseStepName,
                Version = positiveCaseVersion.ToString()
            };

            //act
            var positiveCase = MigrationHandler.IsMigrationItemEqualsToHistory(migrationItem, migrationHistory);

            migrationHistory.Version = negativeCaseVersion.ToString();
            var negativeCase1 = MigrationHandler.IsMigrationItemEqualsToHistory(migrationItem, migrationHistory);

            migrationHistory.Version = positiveCaseVersion.ToString();
            migrationHistory.Name    = String.Empty;
            var negativeCase2 = MigrationHandler.IsMigrationItemEqualsToHistory(migrationItem, migrationHistory);

            //assert
            Assert.True(positiveCase && !negativeCase1 && !negativeCase2);
        }
Example #2
0
        static void Main(string[] args)
        {
            ConfigureSerilog();

            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

            var result = CommandLine.Parser.Default.ParseArguments <Options>(args)
                         .WithParsed <Options>(opts => options = opts)
                         .WithNotParsed <Options>((errs) => HandleParseError(errs));

            if (result.Tag != ParserResultType.Parsed)
            {
                Log.Logger.Error("Command line parameters error, press a key to continue!");
                Console.ReadKey();
                return;
            }

            Connection connection = new Connection(options.ServiceAddress, options.GetAccessToken());

            var importer = new WorkItemImporter(connection, options.OriginalIdField, options.TeamProject);

            //test one item
            MigrationItem mi = new MigrationItem();

            mi.OriginalId = "AA123";
            mi.WorkItemDestinationType = "Product Backlog Item";
            mi.AddVersion(new MigrationItemVersion()
            {
                AuthorEmail      = "*****@*****.**",
                Description      = "Description",
                Title            = "Title test",
                VersionTimestamp = new DateTime(2010, 01, 23, 22, 10, 32),
            });

            mi.AddVersion(new MigrationItemVersion()
            {
                AuthorEmail      = "*****@*****.**",
                Description      = "Description",
                Title            = "Title Modified",
                VersionTimestamp = new DateTime(2011, 01, 23, 22, 10, 32),
            });

            mi.AddVersion(new MigrationItemVersion()
            {
                AuthorEmail      = "*****@*****.**",
                Description      = "Description",
                Title            = "Title Modified Again",
                VersionTimestamp = new DateTime(2012, 01, 23, 22, 10, 32),
            });

            var importResult = importer.ImportWorkItemAsync(mi).Result;

            Log.Information("import result: {importResult}", importResult);

            if (Environment.UserInteractive)
            {
                Console.WriteLine("Execution completed, press a key to continue");
                Console.ReadKey();
            }
        }
        public async Task <Boolean> ImportWorkItemAsync(MigrationItem itemToMigrate)
        {
            var existingWorkItem = GetWorkItem(itemToMigrate.OriginalId);

            if (existingWorkItem != null)
            {
                Log.Information("A workitem with originalId {originalId} already exists, it will be deleted", itemToMigrate.OriginalId);
                connection.WorkItemStore.DestroyWorkItems(new[] { existingWorkItem.Id });
            }

            WorkItem workItem = CreateWorkItem(itemToMigrate);

            if (workItem == null)
            {
                return(false);
            }

            //now that we have work item, we need to start creating all the versions
            for (int i = 0; i < itemToMigrate.Versions.Count(); i++)
            {
                var version = itemToMigrate.GetVersionAt(i);
                workItem.Fields["System.ChangedDate"].Value = version.VersionTimestamp;
                workItem.Fields["System.ChangedBy"].Value   = version.AuthorEmail;
                if (i == 0)
                {
                    workItem.Fields["System.CreatedBy"].Value   = version.AuthorEmail;
                    workItem.Fields["System.CreatedDate"].Value = version.VersionTimestamp;
                }
                workItem.Title       = version.Title;
                workItem.Description = version.Description;
                var validation = workItem.Validate();
                if (validation.Count > 0)
                {
                    Log.Error("N°{errCount} validation errors for work Item {workItemId} originalId {originalId}", validation.Count, workItem.Id, itemToMigrate.OriginalId);
                    foreach (Field error in validation)
                    {
                        Log.Error("Version {version}: We have validation error for work Item {workItemId} originalId {originalId} - Field: {name} ErrorStatus {errorStatus} Value {value}", i, workItem.Id, itemToMigrate.OriginalId, error.Name, error.Status, error.Value);
                    }
                    return(false);
                }
                workItem.Save();
                if (i == 0)
                {
                    Log.Information("Saved for the first time Work Item for type {workItemType} with id {workItemId} related to original id {originalId}", workItem.Type.Name, workItem.Id, itemToMigrate.OriginalId);
                }
                else
                {
                    Log.Debug("Saved iteration {i} for original id {originalId}", i, itemToMigrate.OriginalId);
                }
            }

            return(true);
        }
Example #4
0
        private static void AddSongOfHealing(List <string> lines)
        {
            lines[0] = "-version 4";
            var newItems = new MigrationItem[]
            {
                new MigrationItem
                {
                    ID = 90
                }
            };
            var itemNames = new string[]
            {
                "Song of Healing"
            };

            for (var i = 0; i < lines.Count; i++)
            {
                var line = lines[i];
                if (line.StartsWith("-") || string.IsNullOrWhiteSpace(line))
                {
                    continue;
                }
                var updatedItemSections = line
                                          .Split(';')
                                          .Select(section => section.Split(',').Select(id =>
                {
                    var itemId = int.Parse(id);
                    if (itemId >= 90)
                    {
                        itemId += newItems.Length;
                    }
                    return(itemId);
                }).ToList()).ToList();
                lines[i] = string.Join(";", updatedItemSections.Select(section => string.Join(",", section)));
            }
            foreach (var item in newItems)
            {
                lines.Insert(item.ID * 5 + 1, $"- {itemNames[item.ID - 90]}");
                lines.Insert(item.ID * 5 + 2, string.Join(",", item.DependsOnItems));
                lines.Insert(item.ID * 5 + 3, string.Join(";", item.Conditionals.Select(c => string.Join(",", c))));
                lines.Insert(item.ID * 5 + 4, "0");
                lines.Insert(item.ID * 5 + 5, "0");
            }
            var requireSongOfHealing = new int[] { 83, 84, 88, 89 }; // kamaro, gidbo, goron, zora masks

            foreach (var id in requireSongOfHealing)
            {
                lines[id * 5 + 2] = lines[id * 5 + 2].Length == 0 ? "90" : "90," + lines[id * 5 + 2];
            }
        }
Example #5
0
        public void ApplyPermissionMigration()
        {
            var migrationVersion = new Version("1.3");
            var stepIdentity     = typeof(SetupDefaultMemberGroupsPermissionsStep).Name;

            if (!_migrationHistoryService.Exists(stepIdentity, migrationVersion))
            {
                var step          = DependencyResolver.Current.GetService <SetupDefaultMemberGroupsPermissionsStep>();
                var migrationItem = new MigrationItem(migrationVersion, step);
                var(executionHistory, executionResult) = MigrationHandler.TryExecuteSteps(migrationItem.AsEnumerableOfOne());
                if (executionResult.Type is ExecutionResultType.Success)
                {
                    _migrationHistoryService.Create(MigrationHandler.ToMigrationHistory(executionHistory));
                }
            }
        }
Example #6
0
        private static void AddIkanaScrubGoldRupee(List <string> lines)
        {
            lines[0] = "-version 5";
            var newItems = new MigrationItem[]
            {
                new MigrationItem
                {
                    ID             = 256,
                    DependsOnItems = new List <int> {
                        110, 89, 32
                    }                                              // east access, zora mask, ocean deed
                }
            };
            var itemNames = new string[]
            {
                "Ikana Scrub Gold Rupee"
            };

            for (var i = 0; i < lines.Count; i++)
            {
                var line = lines[i];
                if (line.StartsWith("-") || string.IsNullOrWhiteSpace(line))
                {
                    continue;
                }
                var updatedItemSections = line
                                          .Split(';')
                                          .Select(section => section.Split(',').Select(id =>
                {
                    var itemId = int.Parse(id);
                    if (itemId >= 256)
                    {
                        itemId += newItems.Length;
                    }
                    return(itemId);
                }).ToList()).ToList();
                lines[i] = string.Join(";", updatedItemSections.Select(section => string.Join(",", section)));
            }
            foreach (var item in newItems)
            {
                lines.Insert(item.ID * 5 + 1, $"- {itemNames[item.ID - 256]}");
                lines.Insert(item.ID * 5 + 2, string.Join(",", item.DependsOnItems));
                lines.Insert(item.ID * 5 + 3, string.Join(";", item.Conditionals.Select(c => string.Join(",", c))));
                lines.Insert(item.ID * 5 + 4, "0");
                lines.Insert(item.ID * 5 + 5, "0");
            }
        }
        private Task MigrateAsync(MigrationItem item)
        {
            _logger.LogTrace("{migrationKey} migration coming", item.MigrationKey);
            if (_tasks.TryGetValue(item.MigrationKey, out var task))
            {
                _logger.LogTrace("{migrationKey} task found", item.MigrationKey);
                if (!NeedRestart(task))
                {
                    _logger.LogTrace("{migrationKey} no need restart. current status : {status}",
                                     item.MigrationKey,
                                     task.Status);
                    return(task.ContinueWith(UpdateTcs));
                }
            }

            _logger.LogInformation("{migrationKey} has not started, try to run it", item.MigrationKey);
            _tasks[item.MigrationKey] = item.Tcs.Task;

            var migration = item.Migration;

            void UpdateTcs(Task migrationTask)
            {
                if (migrationTask.IsCompletedSuccessfully)
                {
                    _logger.LogTrace("{migrationKey} success", item.MigrationKey);
                    item.Tcs.SetResult(0);
                }
                else
                {
                    if (migrationTask.IsFaulted)
                    {
                        _logger.LogDebug("{migrationKey} failed", item.MigrationKey);

                        item.Tcs.SetException(migrationTask.Exception.InnerException);
                    }
                    else
                    {
                        _logger.LogDebug("{migrationKey} canceled", item.MigrationKey);
                        item.Tcs.SetCanceled();
                    }
                }
            }

            return(migration.MigrateAsync()
                   .ContinueWith(UpdateTcs));
Example #8
0
        private string ParseMigrationItem(MigrationItem item)
        {
            bool key = item.Name == "Id";

            // column switches
            var switches = "";

            if (key)
            {
                switches += ".PrimaryKey().Identity()";
            }

            if (item.SuggestedType == "string" && item.Length != 0)
            {
                switches += ".WithLength(" + item.Length + ")";
            }

            if (item.Nullable)
            {
                switches += ".Nullable()";
            }

            if (item.NotNull && !item.Nullable)
            {
                switches += ".NotNull()";
            }

            if (!String.IsNullOrEmpty(item.WithDefault))
            {
                if (item.SuggestedType == "string")
                {
                    switches += ".WithDefault(\"" + item.WithDefault + "\")";
                }
                else
                {
                    switches += ".WithDefault(" + item.WithDefault + ")";
                }
            }

            var line = String.Format(".Column<{0}>(\"{1}\"{2}{3})", item.SuggestedType, item.SuggestedName, String.IsNullOrEmpty(switches) ? "" : ", c => c", switches);

            return(line);
        }
        private WorkItem CreateWorkItem(MigrationItem migrationItem)
        {
            WorkItemType type = null;

            try
            {
                type = teamProject.WorkItemTypes[migrationItem.WorkItemDestinationType];
            }
            catch (WorkItemTypeDeniedOrNotExistException) { }//ignore the exception will be logged

            if (type == null)
            {
                Log.Error("Unable to find work item type {WorkItemDestinationType}", migrationItem.WorkItemDestinationType);
                return(null);
            }

            WorkItem workItem = new WorkItem(type);

            Log.Information("Created Work Item for type {workItemType} related to original id {originalId}", workItem.Type.Name, migrationItem.OriginalId);

            //now start creating basic value that we need, like the original id
            workItem[fieldWithOriginalId] = migrationItem.OriginalId;
            return(workItem);
        }
Example #10
0
        private static void AddMagicRequirements(List <string> lines)
        {
            lines[0] = "-version 8";
            var newItems = new MigrationItem[]
            {
                new MigrationItem
                {
                    ID           = 278,
                    Conditionals = new List <List <int> >
                    {
                        new List <int> {
                            11
                        },
                        new List <int> {
                            13
                        },
                    }
                },
            };
            var itemNames = new string[]
            {
                "Magic Meter"
            };

            for (var i = 0; i < lines.Count; i++)
            {
                var line = lines[i];
                if (line.StartsWith("-") || string.IsNullOrWhiteSpace(line))
                {
                    continue;
                }
                var updatedItemSections = line
                                          .Split(';')
                                          .Select(section => section.Split(',').Select(id =>
                {
                    var itemId = int.Parse(id);
                    if (itemId >= 278)
                    {
                        itemId += newItems.Length;
                    }
                    return(itemId);
                }).ToList()).ToList();
                lines[i] = string.Join(";", updatedItemSections.Select(section => string.Join(",", section)));
            }
            foreach (var item in newItems)
            {
                lines.Insert(item.ID * 5 + 1, $"- {itemNames[item.ID - 278]}");
                lines.Insert(item.ID * 5 + 2, string.Join(",", item.DependsOnItems));
                lines.Insert(item.ID * 5 + 3, string.Join(";", item.Conditionals.Select(c => string.Join(",", c))));
                lines.Insert(item.ID * 5 + 4, "0");
                lines.Insert(item.ID * 5 + 5, "0");
            }

            var requireMagic = new int[] { 2, 3, 4, 9 }; // fire arrow, ice arrow, light arrow, lens of truth

            for (var i = 0; i < lines.Count; i++)
            {
                if (i % 5 != 2 && i % 5 != 3)
                {
                    continue;
                }
                var line = lines[i];
                if (line.StartsWith("-") || string.IsNullOrWhiteSpace(line))
                {
                    continue;
                }
                var updatedItemSections = line
                                          .Split(';')
                                          .Select(section =>
                {
                    if (section.Split(',').Select(int.Parse).Intersect(requireMagic).Any())
                    {
                        section += ",278";
                    }
                    return(section);
                }).ToList();
                lines[i] = string.Join(";", updatedItemSections.Select(section => string.Join(",", section)));
            }
        }
Example #11
0
        private static void AddGreatFairies(List <string> lines)
        {
            lines[0] = "-version 7";
            var newItems = new MigrationItem[]
            {
                new MigrationItem
                {
                    ID           = 11,
                    Conditionals = new List <List <int> >
                    {
                        new List <int> {
                            0
                        },
                        new List <int> {
                            92
                        },
                        new List <int> {
                            93
                        },
                    }
                },
                new MigrationItem
                {
                    ID             = 12,
                    DependsOnItems = new List <int> {
                        104
                    },
                },
                new MigrationItem
                {
                    ID             = 13,
                    DependsOnItems = new List <int> {
                        107
                    },
                },
                new MigrationItem
                {
                    ID             = 14,
                    DependsOnItems = new List <int> {
                        112
                    },
                },
            };
            var itemNames = new string[]
            {
                "Great Fairy Magic Meter",
                "Great Fairy Spin Attack",
                "Great Fairy Extended Magic",
                "Great Fairy Double Defense"
            };

            for (var i = 0; i < lines.Count; i++)
            {
                var line = lines[i];
                if (line.StartsWith("-") || string.IsNullOrWhiteSpace(line))
                {
                    continue;
                }
                var updatedItemSections = line
                                          .Split(';')
                                          .Select(section => section.Split(',').Select(id =>
                {
                    var itemId = int.Parse(id);
                    if (itemId >= 11)
                    {
                        itemId += newItems.Length;
                    }
                    return(itemId);
                }).ToList()).ToList();
                lines[i] = string.Join(";", updatedItemSections.Select(section => string.Join(",", section)));
            }
            foreach (var item in newItems)
            {
                lines.Insert(item.ID * 5 + 1, $"- {itemNames[item.ID - 11]}");
                lines.Insert(item.ID * 5 + 2, string.Join(",", item.DependsOnItems));
                lines.Insert(item.ID * 5 + 3, string.Join(";", item.Conditionals.Select(c => string.Join(",", c))));
                lines.Insert(item.ID * 5 + 4, "0");
                lines.Insert(item.ID * 5 + 5, "0");
            }

            var updateItems = new MigrationItem[]
            {
                new MigrationItem
                {
                    ID = 76, // Great Fairy's Mask
                    // remove requirements
                }
            };

            foreach (var item in updateItems)
            {
                lines[item.ID * 5 + 2] = string.Join(",", item.DependsOnItems);
                lines[item.ID * 5 + 3] = string.Join(";", item.Conditionals.Select(c => string.Join(",", c)));
            }
        }
Example #12
0
        private static void AddPreClocktownChestLinkTrialChestsAndStartingItems(List <string> lines)
        {
            lines[0] = "-version 6";
            var newItems = new MigrationItem[]
            {
                new MigrationItem
                {
                    ID             = 267,
                    DependsOnItems = new List <int> {
                        261, 260, 10
                    }
                },
                new MigrationItem
                {
                    ID             = 268,
                    DependsOnItems = new List <int> {
                        261, 260, 10
                    }
                },
                new MigrationItem
                {
                    ID             = 269,
                    DependsOnItems = new List <int> {
                        261
                    }
                },
                new MigrationItem
                {
                    ID = 270,
                },
                new MigrationItem
                {
                    ID = 271,
                },
                new MigrationItem
                {
                    ID = 272,
                },
                new MigrationItem
                {
                    ID = 273,
                },
            };
            var itemNames = new string[]
            {
                "Link Trial 30 Arrows",
                "Link Trial 10 Bombchu",
                "Pre-Clocktown 10 Deku Nuts",
                "Starting Sword",
                "Starting Shield",
                "Starting Heart 1",
                "Starting Heart 2",
            };

            for (var i = 0; i < lines.Count; i++)
            {
                var line = lines[i];
                if (line.StartsWith("-") || string.IsNullOrWhiteSpace(line))
                {
                    continue;
                }
                var updatedItemSections = line
                                          .Split(';')
                                          .Select(section => section.Split(',').Select(id =>
                {
                    var itemId = int.Parse(id);
                    if (itemId >= 267)
                    {
                        itemId += newItems.Length;
                    }
                    return(itemId);
                }).ToList()).ToList();
                lines[i] = string.Join(";", updatedItemSections.Select(section => string.Join(",", section)));
            }
            foreach (var item in newItems)
            {
                lines.Insert(item.ID * 5 + 1, $"- {itemNames[item.ID - 267]}");
                lines.Insert(item.ID * 5 + 2, string.Join(",", item.DependsOnItems));
                lines.Insert(item.ID * 5 + 3, string.Join(";", item.Conditionals.Select(c => string.Join(",", c))));
                lines.Insert(item.ID * 5 + 4, "0");
                lines.Insert(item.ID * 5 + 5, "0");
            }
        }
Example #13
0
        private static void AddMoonItems(List <string> lines)
        {
            lines[0] = "-version 2";
            var newItems = new MigrationItem[]
            {
                new MigrationItem
                {
                    ID           = 255,
                    Conditionals = Enumerable.Range(68, 20).Select(i => new List <int> {
                        i
                    }).ToList()
                },
                new MigrationItem
                {
                    ID           = 256,
                    Conditionals = Enumerable.Range(68, 20).Combinations(2).Select(a => a.ToList()).ToList()
                },
                new MigrationItem
                {
                    ID           = 257,
                    Conditionals = Enumerable.Range(68, 20).Combinations(3).Select(a => a.ToList()).ToList()
                },
                new MigrationItem
                {
                    ID           = 258,
                    Conditionals = Enumerable.Range(68, 20).Combinations(4).Select(a => a.ToList()).ToList()
                },
                new MigrationItem
                {
                    ID             = 259,
                    DependsOnItems = new List <int>
                    {
                        97, 100, 103, 108, 113
                    }
                },
                new MigrationItem
                {
                    ID             = 260,
                    DependsOnItems = new List <int>
                    {
                        259, 0, 255
                    }
                },
                new MigrationItem
                {
                    ID             = 261,
                    DependsOnItems = new List <int>
                    {
                        259, 88, 256
                    }
                },
                new MigrationItem
                {
                    ID             = 262,
                    DependsOnItems = new List <int>
                    {
                        259, 89, 257
                    }
                },
                new MigrationItem
                {
                    ID             = 263,
                    DependsOnItems = new List <int>
                    {
                        259, 258, 114, 115, 2, 10
                    }
                },
                new MigrationItem
                {
                    ID             = 264,
                    DependsOnItems = new List <int>
                    {
                        259, 0, 88, 89, 114, 115, 2, 10
                    }
                    .Concat(Enumerable.Range(68, 20))
                    .ToList()
                }
            };
            var itemNames = new string[]
            {
                "One Mask", "Two Masks", "Three Masks", "Four Masks", "Moon Access", "Deku Trial HP", "Goron Trial HP", "Zora Trial HP", "Link Trial HP", "Fierce Deity's Mask"
            };

            for (var i = 0; i < lines.Count; i++)
            {
                var line = lines[i];
                if (line.StartsWith("-") || string.IsNullOrWhiteSpace(line))
                {
                    continue;
                }
                var updatedItemSections = line
                                          .Split(';')
                                          .Select(section => section.Split(',').Select(id =>
                {
                    var itemId = int.Parse(id);
                    if (itemId >= 255)
                    {
                        itemId += newItems.Length;
                    }
                    return(itemId);
                }).ToList()).ToList();
                lines[i] = string.Join(";", updatedItemSections.Select(section => string.Join(",", section)));
            }
            foreach (var item in newItems)
            {
                lines.Insert(item.ID * 5 + 1, $"- {itemNames[item.ID - 255]}");
                lines.Insert(item.ID * 5 + 2, string.Join(",", item.DependsOnItems));
                lines.Insert(item.ID * 5 + 3, string.Join(";", item.Conditionals.Select(c => string.Join(",", c))));
                lines.Insert(item.ID * 5 + 4, "0");
                lines.Insert(item.ID * 5 + 5, "0");
            }
        }
Example #14
0
        /// <summary>
        /// Called when the Generate Migrations command is run
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        private void MigrationsCallback(object sender, EventArgs e)
        {
            IntPtr              hierarchyPtr, selectionContainerPtr;
            uint                projectItemId;
            IVsMultiItemSelect  mis;
            IVsMonitorSelection monitorSelection = (IVsMonitorSelection)GetGlobalService(typeof(SVsShellMonitorSelection));

            monitorSelection.GetCurrentSelection(out hierarchyPtr, out projectItemId, out mis, out selectionContainerPtr);

            IVsHierarchy hierarchy = Marshal.GetTypedObjectForIUnknown(hierarchyPtr, typeof(IVsHierarchy)) as IVsHierarchy;

            if (hierarchy == null)
            {
                FireError("F**k knows why but it is broken, sorry");
                return;
            }
            object projObj;

            hierarchy.GetProperty(projectItemId, (int)__VSHPROPID.VSHPROPID_ExtObject, out projObj);

            ProjectItem projItem = projObj as ProjectItem;

            if (projItem == null)
            {
                FireError("The item you have selected is not playing nicely. Apologies");
                return;
            }

            var project    = projItem.ContainingProject;
            var migrations = new List <Migration>();


            var allClasses = GetProjectItems(project.ProjectItems).Where(v => v.Name.Contains(".cs"));

            // check for .cs extension on each,

            foreach (var c in allClasses)
            {
                var eles = c.FileCodeModel;
                if (eles == null)
                {
                    continue;
                }
                foreach (var ele in eles.CodeElements)
                {
                    if (ele is EnvDTE.CodeNamespace)
                    {
                        var ns = ele as EnvDTE.CodeNamespace;
                        // run through classes
                        foreach (var property in ns.Members)
                        {
                            var member = property as CodeType;
                            if (member == null)
                            {
                                continue;
                            }

                            // check all classes they derive from to see if any of them are migration classes, add them if so
                            migrations.AddRange(from object b in member.Bases select b as CodeClass into bClass where bClass != null && bClass.Name == "DataMigrationImpl" select new Migration(member));
                        }
                    }
                }
            }

            var model = projItem.FileCodeModel;

            if (model == null)
            {
                FireError("This class you have selected is weird and broken. Choose another one");
                return;
            }
            var elements = model.CodeElements;

            var classes = new List <Model>();

            // run through elements (they are done in a hierachy, so first we have using statements and the namespace) to find namespace
            foreach (var ele in elements)
            {
                if (ele is EnvDTE.CodeNamespace)
                {
                    var ns = ele as EnvDTE.CodeNamespace;
                    // run through classes
                    foreach (var c in ns.Members)
                    {
                        var member = c as CodeType;
                        if (member == null)
                        {
                            continue;
                        }

                        classes.Add(new Model()
                        {
                            Class = member, Name = member.Name
                        });
                    }
                }
            }

            if (!classes.Any())
            {
                FireError("No classes in the selected file!");
                return;
            }


            var vm      = new MigrationsViewModel(migrations, classes);
            var window  = new MigrationsWindow(vm);
            var success = window.ShowDialog();

            if (!success.GetValueOrDefault())
            {
                return;
            }

            CodeType selectedClass = vm.SelectedClass.Class;

            if (selectedClass == null)
            {
                FireError("No class to generate migrations from!");
                return;
            }

            // name of class
            var modelName = selectedClass.Name;
            // get code class
            var cc = selectedClass as CodeClass;
            // get all members of the class
            var members = cc.Members;

            bool contentPartRecord = false;

            foreach (var d in cc.Bases)
            {
                var dClass = d as CodeClass;
                if (dClass != null && dClass.Name == "ContentPartRecord")
                {
                    contentPartRecord = true;
                }
            }

            var props = new List <MigrationItem>();

            //iterate through to find properties
            foreach (var member in members)
            {
                var prop = member as CodeProperty;
                if (prop == null)
                {
                    continue;
                }

                if (prop.Access != vsCMAccess.vsCMAccessPublic)
                {
                    continue;
                }

                var type     = prop.Type;
                var name     = prop.Name;
                var fullName = type.AsFullName;
                var nullable = fullName.Contains(".Nullable<");
                var sType    = type.AsString.Replace("?", "");

                var sName = name;
                // if model, add _Id for nhibernate
                if (fullName.Contains(".Models.") || fullName.Contains(".Records."))
                {
                    sName += "_Id";
                    sType  = "int";
                }

                var mi = new MigrationItem()
                {
                    Name          = name,
                    SuggestedName = sName,
                    Type          = fullName,
                    SuggestedType = sType,
                    Nullable      = nullable,
                    Create        = true,
                };

                props.Add(mi);
            }

            var createMigrationFile = !String.IsNullOrEmpty(vm.NewMigration);

            if (!createMigrationFile)
            {
                if (vm.SelectedMigration == null)
                {
                    FireError("Select a migration or choose a new one!");
                    return;
                }
                var    mig  = vm.SelectedMigration.CodeType;
                string path = (string)mig.ProjectItem.Properties.Item("FullPath").Value;
                string text = File.ReadAllText(path);

                var  noTimesCreated = Regex.Matches(text, @"SchemaBuilder.Create\(""" + modelName + @""",").Count;
                var  noTimesDropped = Regex.Matches(text, @"SchemaBuilder.DropTable\(""" + modelName + @"""\)").Count;
                bool created        = noTimesCreated > noTimesDropped;

                if (noTimesCreated == 1 && noTimesDropped == 0)
                {
                    foreach (var p in props.Where(p => text.Contains(p.Name)))
                    {
                        p.Create = false;
                    }
                }

                if (created)
                {
                    foreach (var p in props)
                    {
                        var name         = p.Name;
                        var noDrops      = Regex.Matches(text, @".DropColumn\(""" + name).Count;
                        var noOccurences = Regex.Matches(text, name).Count;

                        if ((noOccurences - noDrops) > noDrops)
                        {
                            p.Create = false;
                        }
                    }
                }
            }

            // if a collection ignore
            foreach (var p in props)
            {
                if (p.Type.Contains("System.Collection"))
                {
                    p.Create = false;
                }
            }

            var bmvm      = new BuildMigrationsViewModel(props);
            var bmWindow  = new BuildMigrationsWindow(bmvm);
            var bmSuccess = bmWindow.ShowDialog();

            if (!bmSuccess.GetValueOrDefault())
            {
                return;
            }

            var sb          = new StringBuilder();
            var createTable = "SchemaBuilder.CreateTable(\"" + modelName + "\", t => t";

            sb.AppendLine(createTable);
            if (contentPartRecord)
            {
                sb.AppendLine("\t.ContentPartRecord()");
            }
            foreach (var p in bmvm.Migrations.Where(z => z.Create))
            {
                sb.AppendLine("\t" + ParseMigrationItem(p));
            }

            sb.AppendLine(");");

            var editViewModel = new EditMigrationsViewModel()
            {
                Migrations = sb.ToString()
            };

            var editWindow = new EditMigrationsWindow(editViewModel);
            var emSuccess  = editWindow.ShowDialog();

            if (!emSuccess.GetValueOrDefault())
            {
                return;
            }

            var migrationsCode = new StringBuilder();

            using (StringReader reader = new StringReader(editViewModel.Migrations))
            {
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    migrationsCode.AppendLine(line.Insert(0, "\t\t\t"));
                }
            }

            if (!createMigrationFile)
            {
                EditMigrations(vm.SelectedMigration.CodeType, migrationsCode.ToString());
            }
            else
            {
                var templates    = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), "OrchardTemplates");
                var newMigration = project.ProjectItems.AddFromFileCopy(templates + "\\Migrationsxxx.cs");
                Insert(newMigration.Properties.Item("FullPath").Value.ToString(), new[]
                {
                    new KeyValuePair <string, string>("$module$", project.Name),
                    new KeyValuePair <string, string>("$migrationName$", vm.NewMigration),
                    new KeyValuePair <string, string>("$code$", migrationsCode.ToString())
                });

                var cs = vm.NewMigration.EndsWith(".cs") ? "" : ".cs";
                newMigration.Name = vm.NewMigration + cs;
            }
        }
        private string ParseMigrationItem(MigrationItem item)
        {
            bool key = item.Name == "Id";

            // column switches
            var switches = "";

            if (key)
                switches += ".PrimaryKey().Identity()";

            if (item.SuggestedType == "string" && item.Length != 0)
                switches += ".WithLength(" + item.Length + ")";

            if (item.Nullable)
                switches += ".Nullable()";

            if (item.NotNull && !item.Nullable)
                switches += ".NotNull()";

            if (!String.IsNullOrEmpty(item.WithDefault))
            {
                if (item.SuggestedType == "string")
                    switches += ".WithDefault(\"" + item.WithDefault + "\")";
                else
                    switches += ".WithDefault(" + item.WithDefault + ")";
            }

            var line = String.Format(".Column<{0}>(\"{1}\"{2}{3})", item.SuggestedType, item.SuggestedName, String.IsNullOrEmpty(switches) ? "" : ", c => c", switches);

            return line;
        }
        /// <summary>
        /// Called when the Generate Migrations command is run
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        private void MigrationsCallback(object sender, EventArgs e)
        {
            IntPtr hierarchyPtr, selectionContainerPtr;
            uint projectItemId;
            IVsMultiItemSelect mis;
            IVsMonitorSelection monitorSelection = (IVsMonitorSelection)GetGlobalService(typeof(SVsShellMonitorSelection));
            monitorSelection.GetCurrentSelection(out hierarchyPtr, out projectItemId, out mis, out selectionContainerPtr);

            IVsHierarchy hierarchy = Marshal.GetTypedObjectForIUnknown(hierarchyPtr, typeof(IVsHierarchy)) as IVsHierarchy;
            if (hierarchy == null)
            {
                FireError("F**k knows why but it is broken, sorry");
                return;
            }
            object projObj;
            hierarchy.GetProperty(projectItemId, (int)__VSHPROPID.VSHPROPID_ExtObject, out projObj);

            ProjectItem projItem = projObj as ProjectItem;

            if (projItem == null)
            {
                FireError("The item you have selected is not playing nicely. Apologies");
                return;
            }

            var project = projItem.ContainingProject;
            var migrations = new List<Migration>();

            var allClasses = GetProjectItems(project.ProjectItems).Where(v => v.Name.Contains(".cs"));
            // check for .cs extension on each,

            foreach (var c in allClasses)
            {
                var eles = c.FileCodeModel;
                if (eles == null)
                    continue;
                foreach (var ele in eles.CodeElements)
                {
                    if (ele is EnvDTE.CodeNamespace)
                    {
                        var ns = ele as EnvDTE.CodeNamespace;
                        // run through classes
                        foreach (var property in ns.Members)
                        {
                            var member = property as CodeType;
                            if (member == null)
                                continue;

                            // check all classes they derive from to see if any of them are migration classes, add them if so
                            migrations.AddRange(from object b in member.Bases select b as CodeClass into bClass where bClass != null && bClass.Name == "DataMigrationImpl" select new Migration(member));
                        }
                    }
                }
            }

            var model = projItem.FileCodeModel;
            if (model == null)
            {
                FireError("This class you have selected is weird and broken. Choose another one");
                return;
            }
            var elements = model.CodeElements;

            var classes = new List<Model>();

            // run through elements (they are done in a hierachy, so first we have using statements and the namespace) to find namespace
            foreach (var ele in elements)
            {
                if (ele is EnvDTE.CodeNamespace)
                {
                    var ns = ele as EnvDTE.CodeNamespace;
                    // run through classes
                    foreach (var c in ns.Members)
                    {
                        var member = c as CodeType;
                        if (member == null)
                            continue;

                        classes.Add(new Model() { Class = member, Name = member.Name });
                    }
                }
            }

            if (!classes.Any())
            {
                FireError("No classes in the selected file!");
                return;
            }

            var vm = new MigrationsViewModel(migrations, classes);
            var window = new MigrationsWindow(vm);
            var success = window.ShowDialog();

            if (!success.GetValueOrDefault())
            {
                return;
            }

            CodeType selectedClass = vm.SelectedClass.Class;

            if (selectedClass == null)
            {
                FireError("No class to generate migrations from!");
                return;
            }

            // name of class
            var modelName = selectedClass.Name;
            // get code class
            var cc = selectedClass as CodeClass;
            // get all members of the class
            var members = cc.Members;

            bool contentPartRecord = false;
            foreach (var d in cc.Bases)
            {
                var dClass = d as CodeClass;
                if (dClass != null && dClass.Name == "ContentPartRecord")
                {
                    contentPartRecord = true;
                }

            }

            var props = new List<MigrationItem>();

            //iterate through to find properties
            foreach (var member in members)
            {
                var prop = member as CodeProperty;
                if (prop == null)
                    continue;

                if (prop.Access != vsCMAccess.vsCMAccessPublic)
                    continue;

                var type = prop.Type;
                var name = prop.Name;
                var fullName = type.AsFullName;
                var nullable = fullName.Contains(".Nullable<");
                var sType = type.AsString.Replace("?", "");

                var sName = name;
                // if model, add _Id for nhibernate
                if (fullName.Contains(".Models.") || fullName.Contains(".Records."))
                {
                    sName += "_Id";
                    sType = "int";
                }

                var mi = new MigrationItem()
                {
                    Name = name,
                    SuggestedName = sName,
                    Type = fullName,
                    SuggestedType = sType,
                    Nullable = nullable,
                    Create = true,
                };

                props.Add(mi);
            }

            var createMigrationFile = !String.IsNullOrEmpty(vm.NewMigration);

            if (!createMigrationFile)
            {
                if (vm.SelectedMigration == null)
                {
                    FireError("Select a migration or choose a new one!");
                    return;
                }
                var mig = vm.SelectedMigration.CodeType;
                string path = (string)mig.ProjectItem.Properties.Item("FullPath").Value;
                string text = File.ReadAllText(path);

                var noTimesCreated = Regex.Matches(text, @"SchemaBuilder.Create\(""" + modelName + @""",").Count;
                var noTimesDropped = Regex.Matches(text, @"SchemaBuilder.DropTable\(""" + modelName + @"""\)").Count;
                bool created = noTimesCreated > noTimesDropped;

                if (noTimesCreated == 1 && noTimesDropped == 0)
                {
                    foreach (var p in props.Where(p => text.Contains(p.Name)))
                    {
                        p.Create = false;
                    }
                }

                if (created)
                {
                    foreach (var p in props)
                    {
                        var name = p.Name;
                        var noDrops = Regex.Matches(text, @".DropColumn\(""" + name).Count;
                        var noOccurences = Regex.Matches(text, name).Count;

                        if ((noOccurences - noDrops) > noDrops)
                            p.Create = false;
                    }
                }
            }

            // if a collection ignore
            foreach (var p in props) if (p.Type.Contains("System.Collection")) p.Create = false;

            var bmvm = new BuildMigrationsViewModel(props);
            var bmWindow = new BuildMigrationsWindow(bmvm);
            var bmSuccess = bmWindow.ShowDialog();

            if (!bmSuccess.GetValueOrDefault())
            {
                return;
            }

            var sb = new StringBuilder();
            var createTable = "SchemaBuilder.CreateTable(\"" + modelName + "\", t => t";
            sb.AppendLine(createTable);
            if (contentPartRecord) sb.AppendLine("\t.ContentPartRecord()");
            foreach (var p in bmvm.Migrations.Where(z => z.Create))
            {
                sb.AppendLine("\t" + ParseMigrationItem(p));
            }

            sb.AppendLine(");");

            var editViewModel = new EditMigrationsViewModel()
            {
                Migrations = sb.ToString()
            };

            var editWindow = new EditMigrationsWindow(editViewModel);
            var emSuccess = editWindow.ShowDialog();

            if (!emSuccess.GetValueOrDefault())
            {
                return;
            }

            var migrationsCode = new StringBuilder();
            using (StringReader reader = new StringReader(editViewModel.Migrations))
            {
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    migrationsCode.AppendLine(line.Insert(0, "\t\t\t"));
                }
            }

            if (!createMigrationFile)
                EditMigrations(vm.SelectedMigration.CodeType, migrationsCode.ToString());
            else
            {
                var templates = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), "OrchardTemplates");
                var newMigration = project.ProjectItems.AddFromFileCopy(templates + "\\Migrationsxxx.cs");
                Insert(newMigration.Properties.Item("FullPath").Value.ToString(), new[]
                {
                    new KeyValuePair<string, string>("$module$", project.Name),
                    new KeyValuePair<string, string>("$migrationName$", vm.NewMigration),
                    new KeyValuePair<string, string>("$code$", migrationsCode.ToString())
                });

                var cs = vm.NewMigration.EndsWith(".cs") ? "" : ".cs";
                newMigration.Name = vm.NewMigration + cs;
            }
        }