public static bool CreateBackoutPackage(ConnectionData connData,
                                                List <SqlBuild.Objects.ObjectUpdates> objectUpdates,
                                                List <SqlBuild.Objects.ObjectUpdates> dontUpdate,
                                                List <string> manualScriptsCanNotUpdate, string sourceBuildZipFileName,
                                                string destinationBuildZipFileName, string sourceServer, string sourceDb,
                                                bool removeNewObjectsFromPackage, bool markManualScriptsAsRunOnce,
                                                bool dropNewRoutines, ref BackgroundWorker bg)
        {
            //Copy the source straight over...
            bool reportProgress = false;

            if (bg != null && bg.WorkerReportsProgress)
            {
                reportProgress = true;
                bg.ReportProgress(-1, "Copying package to destination...");
            }

            if (!CopyOriginalToBackout(sourceBuildZipFileName, destinationBuildZipFileName))
            {
                return(false);
            }

            //init working location for destination backout package
            string workingDir      = string.Empty;
            string projectPath     = string.Empty;
            string projectFileName = string.Empty;

            SqlBuildFileHelper.InitilizeWorkingDirectory(ref workingDir, ref projectPath, ref projectFileName);
            string message = $"Initialized working directory {workingDir}";

            log.LogDebug(message);
            if (reportProgress)
            {
                bg.ReportProgress(-1, "Initialized working directory");
            }


            //Extract destination package into working folder
            string result;
            bool   success = SqlBuildFileHelper.ExtractSqlBuildZipFile(destinationBuildZipFileName, ref workingDir,
                                                                       ref projectPath, ref projectFileName, out result);

            if (success)
            {
                log.LogDebug($"Successfully extracted build file {destinationBuildZipFileName} to {workingDir}");
            }
            else
            {
                log.LogError("Unable to proceed with Backout package. See previous errors");
                return(false);
            }

            //Load the build data
            SqlSyncBuildData buildData;

            if (reportProgress)
            {
                bg.ReportProgress(-1, "Loading project file for modification.");
            }
            bool successfulLoad = SqlBuildFileHelper.LoadSqlBuildProjectFile(out buildData, projectFileName, false);

            if (!successfulLoad)
            {
                log.LogError("Unable to load SBM project data");
                return(false);
            }

            ConnectionData tmpData = new ConnectionData();

            tmpData.DatabaseName       = sourceDb;
            tmpData.SQLServerName      = sourceServer;
            tmpData.Password           = connData.Password;
            tmpData.UserId             = connData.UserId;
            tmpData.AuthenticationType = connData.AuthenticationType;
            ObjectScriptHelper helper = new ObjectScriptHelper(tmpData);


            //Get the updated scripts...
            if (reportProgress)
            {
                bg.ReportProgress(-1, "Generating updated scripts.");
            }
            List <UpdatedObject> lstScripts = ObjectScriptHelper.ScriptDatabaseObjects(objectUpdates, tmpData, ref bg);

            //Log if some scripts were not updated properly...
            var notUpdated = from s in objectUpdates
                             where !(from u in lstScripts select s.ShortFileName).Contains(s.ShortFileName)
                             select s.ShortFileName;

            if (notUpdated.Any())
            {
                foreach (string file in notUpdated)
                {
                    log.LogError($"Unable to create new script for {file}");
                }

                return(false);
            }

            if (lstScripts.Count() != objectUpdates.Count())
            {
                log.LogError($"Not all scripts were updated. Expected {lstScripts.Count().ToString()}, only {objectUpdates.Count().ToString()} were updated");
                return(false);
            }

            //Save the updated scripts...
            DateTime updateTime   = DateTime.Now;
            bool     errorWriting = false;

            if (lstScripts != null)
            {
                foreach (UpdatedObject obj in lstScripts)
                {
                    try
                    {
                        File.WriteAllText(projectPath + obj.ScriptName, obj.ScriptContents);

                        //Update the buildData object with the update date/time and user;
                        var sr = from r in buildData.Script
                                 where r.FileName == obj.ScriptName
                                 select r;

                        if (sr.Any())
                        {
                            SqlSyncBuildData.ScriptRow row = sr.First();
                            row.DateModified = updateTime;
                            row.ModifiedBy   = System.Environment.UserName;
                        }
                    }
                    catch (Exception exe)
                    {
                        errorWriting = true;
                        log.LogError(exe, $"Unable to save updated script file to {obj.ScriptName}");
                    }
                }
            }

            //Update new object scripts: either remove or mark as run once
            if (dontUpdate != null)
            {
                foreach (SqlBuild.Objects.ObjectUpdates obj in dontUpdate)
                {
                    try
                    {
                        //Update the buildData object with the update date/time and user;
                        var sr = from r in buildData.Script
                                 where r.FileName == obj.ShortFileName
                                 select r;

                        if (sr.Any())
                        {
                            SqlSyncBuildData.ScriptRow row = sr.First();
                            if (obj.ObjectType == DbScriptDescription.StoredProcedure ||
                                obj.ObjectType == DbScriptDescription.UserDefinedFunction ||
                                obj.ObjectType == DbScriptDescription.Trigger ||
                                obj.ObjectType == DbScriptDescription.View)
                            {
                                if (dropNewRoutines)
                                {
                                    string   schema, objName;
                                    string[] arr = obj.SourceObject.Split(new char[] { '.' });
                                    schema  = arr[0];
                                    objName = arr[1];

                                    string str = CreateRoutineDropScript(schema, objName, obj.ObjectType);
                                    File.WriteAllText(projectPath + "DROP " + row.FileName, str);
                                    row.FileName     = "DROP " + row.FileName;
                                    row.DateModified = updateTime;
                                    row.ModifiedBy   = System.Environment.UserName;
                                }
                                else
                                {
                                    row.AllowMultipleRuns = false;
                                    row.DateModified      = updateTime;
                                    row.ModifiedBy        = System.Environment.UserName;
                                }
                            }
                            else if (removeNewObjectsFromPackage)
                            {
                                buildData.Script.RemoveScriptRow(row);
                            }
                            else
                            {
                                row.AllowMultipleRuns = false;
                                row.DateModified      = updateTime;
                                row.ModifiedBy        = System.Environment.UserName;
                            }
                        }
                    }
                    catch (Exception exe)
                    {
                        errorWriting = true;
                        if (removeNewObjectsFromPackage)
                        {
                            log.LogError(exe, $"Unable to remove new object script '{obj.ShortFileName}' from package");
                        }
                        else
                        {
                            log.LogError(exe, $"Unable to mark new object script {obj.ShortFileName} as run once");
                        }
                    }
                }
            }

            //Mark non-updated scripts as run-once
            if (manualScriptsCanNotUpdate != null)
            {
                foreach (string scr in manualScriptsCanNotUpdate)
                {
                    try
                    {
                        //Update the buildData object with the update date/time and user;
                        var sr = from r in buildData.Script
                                 where r.FileName == scr
                                 select r;

                        if (sr.Any())
                        {
                            if (markManualScriptsAsRunOnce)
                            {
                                SqlSyncBuildData.ScriptRow row = sr.First();
                                if (row.BuildOrder < 1000)
                                {
                                    row.AllowMultipleRuns = false;
                                    row.DateModified      = updateTime;
                                    row.ModifiedBy        = System.Environment.UserName;
                                }
                            }
                        }
                    }
                    catch (Exception exe)
                    {
                        errorWriting = true;
                        log.LogError(exe, $"Unable to mark script {scr} as run once");
                    }
                }
            }


            if (errorWriting)
            {
                return(false);
            }
            if (reportProgress)
            {
                bg.ReportProgress(-1, "Saving backout package.");
            }

            buildData.AcceptChanges();
            SqlBuildFileHelper.SaveSqlBuildProjectFile(ref buildData, projectFileName, destinationBuildZipFileName);


            return(true);
        }