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); }