public void GetUnifiedDiff(ref SqlSync.SqlBuild.SqlSyncBuildData leftBuildData, string leftTempFilePath, string rightBuildZipPath, out List <FileCompareResults> onlyInLeft, out List <FileCompareResults> onlyInRight, out List <FileCompareResults> modified, out string rightFileTempDirectory) { this.extractPathLeftFile = leftTempFilePath; string tmpDir = System.IO.Path.GetTempPath(); this.extractPathRightFile = tmpDir + @"SqlsyncCompare-" + System.Guid.NewGuid().ToString().Replace("-", ""); Directory.CreateDirectory(this.extractPathRightFile); rightFileTempDirectory = this.extractPathRightFile; ZipHelper.UnpackZipPackage(this.extractPathRightFile, rightBuildZipPath, false); SqlSync.SqlBuild.SqlSyncBuildData rightBuildData = new SqlSyncBuildData(); rightBuildData.ReadXml(Path.Combine(this.extractPathRightFile, XmlFileNames.MainProjectFile)); //TODO: wrap load failure. List <FileCompareResults> filesOnlyInLeft = GetFileListDiff(leftBuildData, rightBuildData, true); List <FileCompareResults> filesOnlyInRight = GetFileListDiff(rightBuildData, leftBuildData, false); List <FileCompareResults> commonFiles = GetCommonFileList(leftBuildData, rightBuildData); modified = ProcessUnifiedDiff(this.extractPathLeftFile, this.extractPathRightFile, commonFiles); onlyInRight = GetFileContents(this.extractPathRightFile, filesOnlyInRight); onlyInLeft = GetFileContents(this.extractPathLeftFile, filesOnlyInLeft); }
private void mnuImportScripts_Click(object sender, EventArgs e) { if (lstFiles.SelectedItems.Count == 0) { return; } List <string> files = new List <string>(); for (int i = 0; i < lstFiles.SelectedItems.Count; i++) { if (lstFiles.SelectedItems[i].SubItems[3].Text.Length > 0) { files.Add(lstFiles.SelectedItems[i].SubItems[3].Text); } } bool isValid; string path = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location); SqlSync.Validator.SchemaValidator validator = new SqlSync.Validator.SchemaValidator(); string importFileXml = string.Empty; if (File.Exists(this.rightTempFilePath + XmlFileNames.MainProjectFile)) { importFileXml = this.rightTempFilePath + XmlFileNames.MainProjectFile; } string valErrorMessage; isValid = SqlBuildFileHelper.ValidateAgainstSchema(importFileXml, out valErrorMessage); if (isValid == false) { MessageBox.Show("Unable to Import. Invalid Build File Schema?"); return; } SqlSyncBuildData importData; if (File.Exists(importFileXml)) { importData = new SqlSyncBuildData(); importData.ReadXml(this.rightTempFilePath + XmlFileNames.MainProjectFile); importData.AcceptChanges(); foreach (SqlSyncBuildData.ScriptRow row in importData.Script) { if (files.Contains(row.FileName) == false) { row.Delete(); } } importData.Script.AcceptChanges(); importData.AcceptChanges(); } else { return; } string[] arrFiles = new string[files.Count]; files.CopyTo(arrFiles); SqlBuild.ImportListForm frmImport = new SqlBuild.ImportListForm(importData, this.rightTempFilePath, this.buildData, arrFiles); if (DialogResult.OK != frmImport.ShowDialog()) { return; } string[] addedFileNames; double importStartNumber = SqlBuild.SqlBuildFileHelper.ImportSqlScriptFile(ref this.buildData, importData, this.rightTempFilePath, lastBuildNumber, this.leftTempFilePath, this.leftTempFilePath + XmlFileNames.MainProjectFile, this.leftZipFilePath, false, out addedFileNames); if (importStartNumber > 0) { StringBuilder sb = new StringBuilder(); sb.Append("Import Successful\r\n"); sb.Append("New file indexes start at: " + importStartNumber.ToString() + "\r\n\r\n"); MessageBox.Show(sb.ToString(), "Import Successful", MessageBoxButtons.OK, MessageBoxIcon.Information); this.refreshProjectList = true; this.lastBuildNumber = this.lastBuildNumber + addedFileNames.Length; } else { if (importStartNumber == (double)ImportFileStatus.Canceled) { MessageBox.Show("Import Canceled", "Import Canceled", MessageBoxButtons.OK, MessageBoxIcon.Information); } else if (importStartNumber == (double)ImportFileStatus.UnableToImport) { MessageBox.Show("Unable to Import the requested file", "Import Failed", MessageBoxButtons.OK, MessageBoxIcon.Information); } else if (importStartNumber == (double)ImportFileStatus.NoRowsImported) { MessageBox.Show("No rows were selected for import", "None selected", MessageBoxButtons.OK, MessageBoxIcon.Information); } } btnCompare_Click(null, EventArgs.Empty); }
private void saveBuildDetailsForSelectedRowsToolStripMenuItem_Click(object sender, EventArgs e) { if (this.dgMaster.SelectedCells.Count == 0) { return; } List <SqlSyncBuildData.BuildRow> rows = new List <SqlSyncBuildData.BuildRow>(); for (int i = 0; i < this.dgMaster.SelectedCells.Count; i++) { SqlSyncBuildData.BuildRow row = (SqlSyncBuildData.BuildRow)((System.Data.DataRowView) this.dgMaster.SelectedCells[i].OwningRow.DataBoundItem).Row; if (!rows.Contains(row)) { rows.Add(row); } } if (DialogResult.OK == saveFileDialog1.ShowDialog()) { try { //Perform a deep copy of the build data... SqlSyncBuildData data = new SqlSyncBuildData(); using (StringReader sr = new StringReader("<?xml version=\"1.0\" standalone=\"yes\"?>" + this.sqlSyncBuildData1.GetXml())) { data.ReadXml(sr); } //Get ID's for selected rows... StringBuilder sb = new StringBuilder("("); foreach (SqlSyncBuildData.BuildRow row in rows) { sb.Append("'" + row.BuildId.ToString() + "',"); } sb.Length = sb.Length - 1; sb.Append(")"); //Filter out any rows that were not selected System.Data.DataView view = data.Build.DefaultView; view.RowFilter = data.Build.BuildIdColumn.ColumnName + " not in " + sb.ToString(); //Delete the non-selected rows from the build data copy object. while (view.Count > 0) { DataRow[] kids = view[0].Row.GetChildRows("Builds_Build"); for (int j = 0; j < kids.Length; j++) { kids[j].Delete(); } view[0].Row.Delete(); } //Save the file... string fileName = saveFileDialog1.FileName; data.AcceptChanges(); data.WriteXml(fileName); if (DialogResult.Yes == MessageBox.Show("Saved history to " + fileName + "\r\nOpen this file?", "Save Complete", MessageBoxButtons.YesNo, MessageBoxIcon.Question)) { System.Diagnostics.Process.Start(fileName); } } catch (Exception exe) { MessageBox.Show("There was an error saving the history.\r\n" + exe.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } }
/// <summary> /// Performs the database scripts execution against the specified server/ database settings /// </summary> /// <param name="serverName">Name of the SQL server to target</param> /// <param name="overrides">List of database override settings to use in execution</param> /// <returns></returns> internal async Task <int> RunDatabaseBuild() { this.returnValue = (int)RunnerReturn.BuildResultInconclusive; ConnectionData connData = null; BackgroundWorker bg = null; DoWorkEventArgs e = null; SqlBuildRunData runData = new SqlBuildRunData(); string targetDatabase = overrides[0].OverrideDbTarget; string loggingDirectory = Path.Combine(ThreadedExecution.WorkingDirectory, server, targetDatabase); try { //Start setting properties on the object that contains the run configuration data. runData.BuildType = "Other"; if (!string.IsNullOrEmpty(cmdArgs.Description)) { runData.BuildDescription = cmdArgs.Description; } else { runData.BuildDescription = "Threaded Multi-Database. Run ID:" + ThreadedExecution.RunID; } runData.IsTrial = this.isTrial; runData.RunScriptOnly = false; runData.TargetDatabaseOverrides = overrides; runData.Server = this.server; runData.IsTransactional = cmdArgs.Transactional; if (this.cmdArgs.LogToDatabaseName.Length > 0) { runData.LogToDatabaseName = this.cmdArgs.LogToDatabaseName; } runData.PlatinumDacPacFileName = cmdArgs.DacPacArgs.PlatinumDacpac; runData.BuildRevision = cmdArgs.BuildRevision; runData.DefaultScriptTimeout = cmdArgs.DefaultScriptTimeout; runData.AllowObjectDelete = cmdArgs.AllowObjectDelete; //Initilize the logging directory for this run if (!Directory.Exists(loggingDirectory)) { Directory.CreateDirectory(loggingDirectory); } if (forceCustomDacpac) { runData.ForceCustomDacpac = true; //This will set the BuildData and BuildFileName and ProjectFileName properties on runData var status = DacPacHelper.UpdateBuildRunDataForDacPacSync(ref runData, server, targetDatabase, this.authType, this.username, this.password, loggingDirectory, cmdArgs.BuildRevision, cmdArgs.DefaultScriptTimeout, cmdArgs.AllowObjectDelete); switch (status) { case DacpacDeltasStatus.Success: //nothing to do break; case DacpacDeltasStatus.InSync: case DacpacDeltasStatus.OnlyPostDeployment: log.LogInformation($"Target database {targetDatabase} is already in sync with {cmdArgs.DacPacArgs.PlatinumDacpac}. Nothing to do!"); this.returnValue = (int)RunnerReturn.DacpacDatabasesInSync; break; default: log.LogError($"Error creating custom dacpac and scripts for {targetDatabase}. No update was performed"); this.returnValue = (int)RunnerReturn.PackageCreationError; return((int)RunnerReturn.PackageCreationError);; } } else { runData.ForceCustomDacpac = false; //Get a full copy of the build data to work with (avoid threading sync issues) SqlSyncBuildData buildData = new SqlSyncBuildData(); string xml = "<?xml version=\"1.0\" standalone=\"yes\"?>\r\n" + ThreadedExecution.BuildData.GetXml(); using (StringReader sr = new StringReader(xml)) { buildData.ReadXml(sr); } //Clear out any existing ComittedScript data.. just log what is relevent to this run. buildData.CommittedScript.Clear(); runData.BuildData = buildData; runData.ProjectFileName = Path.Combine(loggingDirectory, Path.GetFileName(ThreadedExecution.ProjectFileName)); runData.BuildFileName = ThreadedExecution.BuildZipFileName; } //Create a connection object.. all we need is the server here, the DB will be filled in at execution time connData = new ConnectionData(server, ""); if (this.cmdArgs.AuthenticationArgs.UserName.Length > 0 && this.cmdArgs.AuthenticationArgs.Password.Length > 0) { connData.UserId = cmdArgs.AuthenticationArgs.UserName; connData.Password = cmdArgs.AuthenticationArgs.Password; } connData.AuthenticationType = this.cmdArgs.AuthenticationArgs.AuthenticationType; //Set the log file name string logFile = Path.Combine(loggingDirectory, "ExecutionLog.log"); //Create the objects that will handle the event communication back. bg = new BackgroundWorker(); //bg.ProgressChanged += Bg_ProgressChanged; bg.WorkerReportsProgress = true; e = new DoWorkEventArgs(null); } catch (Exception exe) { log.LogError(exe, $"Error Initializing run for {this.TargetTag}"); WriteErrorLog(loggingDirectory, exe.ToString()); this.returnValue = (int)ExecutionReturn.RunInitializationError; return((int)ExecutionReturn.RunInitializationError);; } log.LogDebug("Initializing run for " + this.TargetTag + ". Starting \"ProcessBuild\""); try { //Initilize the run helper object and kick it off. SqlBuildHelper helper = new SqlBuildHelper(connData, true, string.Empty, cmdArgs.Transactional); //don't need an "external" log for this, it's all external! helper.BuildCommittedEvent += new BuildCommittedEventHandler(helper_BuildCommittedEvent); helper.BuildErrorRollBackEvent += new EventHandler(helper_BuildErrorRollBackEvent); helper.BuildSuccessTrialRolledBackEvent += new EventHandler(helper_BuildSuccessTrialRolledBackEvent); await Task.Run(() => { helper.ProcessBuild(runData, bg, e, ThreadedExecution.BatchColl, this.buildRequestedBy, cmdArgs.TimeoutRetryCount); }); } catch (Exception exe) { log.LogError("Error Processing run for " + this.TargetTag, exe); WriteErrorLog(loggingDirectory, exe.ToString()); this.returnValue = (int)ExecutionReturn.ProcessBuildError; return((int)ExecutionReturn.ProcessBuildError);; } return(0); }