using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using remote = Tango.DAL.Remote.DB;
using local = Tango.DAL.Local.DB;
using Tango.Settings;
using Tango.Synchronization.Local;
using Tango.Core;
namespace Tango.Synchronization.Remote
{
/// <summary>
/// Represents a remote database to SQLite file synchronizer.
/// </summary>
public class RemoteDBSynchronizer
{
/// <summary>
/// Synchronizes the specified SQLite file by a machine serial number.
/// </summary>
/// <param name="sqliteDbFile">The SQLite database file.</param>
/// <param name="serialNumber">The machine serial number.</param>
/// <param name="overrideLocal">if set to <c>true</c> will erase the SQLite file before performing the synchronization.</param>
/// <returns></returns>
public static List<Diff> Synchronize(String sqliteDbFile, String serialNumber, bool overrideLocal = false)
{
if (overrideLocal)
{
SQLiteDataBase sqlite = new SQLiteDataBase(sqliteDbFile);
sqlite.LoadTables();
sqlite.ClearDataBase();
}
using (var remoteDB = new remote.RemoteDB(SettingsManager.Default.GetOrCreate<CoreSettings>().DataSource))
{
using (var localDB = new local.LocalDB(sqliteDbFile))
{
RemoteDBComparer comparer = new RemoteDBComparer(remoteDB, localDB, serialNumber);
var diffs = comparer.Compare();
foreach (var diff in diffs)
{
diff.Commit();
}
remoteDB.SaveChanges();
localDB.SaveChanges();
return diffs;
}
}
}
/// <summary>
/// Synchronizes the specified SQLite file by a machine serial number.
/// </summary>
/// <param name="sqliteDbFile">The SQLite database file.</param>
/// <param name="serialNumber">The machine serial number.</param>
/// <param name="overrideLocal">if set to <c>true</c> will erase the SQLite file before performing the synchronization.</param>
/// <returns></returns>
public static Task<List<Diff>> SynchronizeAsync(String sqliteDBFile, String serialNumber, bool overrideLocalpre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long *///------------------------------------------------------------------------------
// <copyright file="TangoBuildCommand.cs" company="Company">
// Copyright (c) Company. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
using System;
using System.ComponentModel.Design;
using System.Globalization;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using System.Collections.Generic;
using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio;
using System.Linq;
using TestStack.White.UIItems.Finders;
using TestStack.White.InputDevices;
using TestStack.White.UIItems;
using VSLangProj;
using System.Runtime.InteropServices;
using TestStack.White.WindowsAPI;
using System.IO;
namespace Tango.BuildExtensions
{
/// <summary>
/// Command handler
/// </summary>
internal sealed class TangoBuildCommand : VSIXBase
{
private IList<Project> _projects;
private TestStack.White.Application _application;
private TestStack.White.UIItems.WindowItems.Window _window;
private System.Diagnostics.Process _vsProcess;
private const String dalProjectName = "Tango.DAL.Remote";
private const String edmxModelName = "RemoteADO.edmx";
private const String observablesGeneratorProjectName = "Tango.DBObservablesGenerator.CLI";
private const String observablesProjectName = "Tango.BL";
private const String observablesContextName = "ObservablesContext.cs";
private const String pmrGeneratorProjectName = "Tango.PMRGenerator.CLI";
private const String pmrProjectName = "Tango.PMR";
private const String protoCliProjectName = "Tango.Protobuf.CLI";
private const String sqliteProjectName = "Tango.SQLiteGenerator.CLI";
#region Redundant
/// <summary>
/// Command ID.
/// </summary>
public const int CommandId = 0x0100;
/// <summary>
/// Command menu group (command set GUID).
/// </summary>
public static readonly Guid CommandSet = new Guid("c03a7b01-8109-4ec5-8f90-858bed027e5d");
/// <summary>
/// VS Package that provides this command, not null.
/// </summary>
private readonly Package package;
/// <summary>
/// Initializes a new instance of the <see cref="TangoBuildCommand"/> class.
/// Adds our command handlers for menu (commands must exist in the command table file)
/// </summary>
/// <param name="package">Owner package, not null.</param>
private TangoBuildCommand(Package package) : base(package)
{
if (package == null)
{
throw new ArgumentNullException("package");
}
this.package = package;
OleMenuCommandService commandService = this.ServiceProvider.GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
if (commandService != null)
{
var menuCommandID = new CommandID(CommandSet, CommandId);
var menuItem = new MenuCommand(this.MenuItemCallback, menuCommandID);
commandService.AddCommand(menuItem);
}
}
/// <summary>
/// Gets the instance of the command.
/// </summary>
public static TangoBuildCommand Instance
{
get;
private set;
}
/// <summary>
/// Gets the service provider from the owner package.
/// </summary>
private IServiceProvider ServiceProvider
{
get
{
return this.package;
}
}
/// <summary>
/// Initializes the singleton instance of the command.
/// </summary>
/// <param name="package">Owner package, not null.</param>
public static void Initialize(Package package)
{
Instance = new TangoBuildCommand(package);
}
/// <summary>
/// This function is the callback used to execute the command when the menu item is clicked.
/// See the constructor to see how the menu item is associated with this function using
/// OleMenuCommandService service and MenuCommand class.
/// </summary>
/// <param name="sender">Event sender.</param>
/// <param name="e">Event args.</param>
private void MenuItemCallback(object sender, EventArgs e)
{
Start();
}
#endregion
#region Main
private void Start()
{
BuildForm buildForm = new BuildForm();
if (buildForm.ShowDialog() != System.Windows.Forms.DialogResult.OK) return;
#pragma warning disable VSTHRD105 // Avoid method overloads that assume TaskScheduler.Current
System.Threading.Tasks.Task.Factory.StartNew(() =>
#pragma warning restore VSTHRD105 // Avoid method overloads that assume TaskScheduler.Current
{
_projects = GetSolutionProjects().ToList();
String vsWindowTitle = DTE.DTE.MainWindow.Caption;
_vsProcess = System.Diagnostics.Process.GetProcesses().ToList().SingleOrDefault(x => x.MainWindowTitle == vsWindowTitle);
_application = TestStack.White.Application.Attach(_vsProcess);
_window = _application.GetWindow(vsWindowTitle);
OpenVSProgress("Tango Build Engine", "Initializing...", true);
String current_startup_project = DTE.Solution.Properties.Item("StartupProject").Value.ToString();
try
{
if (buildForm.UpdateDataBaseEntities)
{
UpdateDatabaseEntities();
}
if (buildForm.GenerateAndBuildObservables)
{
GenerateAndBuildObservables();
}
if (buildForm.GenerateAutoPmrMessages)
{
GenerateAutoPMRMessages();
}
if (buildForm.UpdateAndBuildPmrMessages)
{
UpdateAndBuildPmrMessages();
}
if (buildForm.GenerateSQLite)
{
GenerateSQLite();
}
if (buildForm.BuildSolution)
{
BuildSolution();
}
SetVSProgress("Done!");
Wait(1000);
CloseVSProgress();
}
catch (Exception ex)
{
ShowMessage(ex.Message);
}
finally
{
CloseVSProgress();
DTE.Solution.Properties.Item("StartupProject").Value = current_startup_project;
}
});
}
private void UpdateDatabaseEntities()
{
var project = _projects.SingleOrDefault(x => x.Name == dalProjectName);
if (project == null)
{
throw new NullReferenceException("Could not find the Tango solution!");
}
var projectItems = project.ProjectItems.OfType<ProjectItem>().ToList();
SetVSProgress("Locating " + edmxModelName + " scheme...");
var items = GetProjectItems(project);
var edmx = GetProjectItems(project).SingleOrDefault(x => x.Name == edmxModelName);
if (edmx == null)
{
throw new NullReferenceException("Could not locate " + edmxModelName + "!");
}
SetVSProgress("Expanding diagram...");
edmx.ExpandView();
SetVSProgress("Opening EDMX diagram window...");
Window win = edmx.Open(EnvDTE.Constants.vsViewKindPrimary);
win.Visible = true;
SetVSProgress("Waiting for EDMX diagram window...");
_window.WaitTill(() => _window.Get(SearchCriteria.ByText(edmxModelName + " [Diagram1]")) != null);
SetVSProgress("Cleaning up EDMX scheme...");
DTE.MainWindow.Activate();
DTE.ExecuteCommand("Edit.SelectAll");
Keyboard.Instance.PressSpecialKey(KeyboardInput.SpecialKeys.DELETE);
WaitForWindowOpen("Delete Unmapped Tables and Views").PressKey(KeyboardInput.SpecialKeys.RETURN);
WaitForWindowClose("Delete Unmapped Tables and Views");
_window.WaitWhileBusy();
SetVSProgress("Reinitializing EDMX scheme...");
var window = WindowInfo.GetWindow(edmxModelName + " [Diagram1]*");
window.SetActive();
Keyboard.Instance.HoldKey(KeyboardInput.SpecialKeys.SHIFT);
Keyboard.Instance.PressSpecialKey(KeyboardInput.SpecialKeys.F10);
Keyboard.Instance.LeaveAllKeys();
Wait(100);
for (int i = 0; i < 7; i++)
{
Keyboard.Instance.PressSpecialKey(KeyboardInput.SpecialKeys.DOWN);
Wait(10);
}
Keyboard.Instance.PressSpecialKey(KeyboardInput.SpecialKeys.RETURN);
var updateWindow = WaitForWindowOpen("Update Wizard");
_window.WaitWhileBusy();
Wait(1000);
updateWindow.PressKey(KeyboardInput.SpecialKeys.SPACE);
Wait(50);
updateWindow.PressKey(KeyboardInput.SpecialKeys.RETURN);
SetVSProgress("Generating EDMX scheme...");
WaitForWindowClose("Update Wizard");
_window.WaitWhileBusy();
SetVSProgress("Saving changes...");
win.Close(vsSaveChanges.vsSaveChangesYes);
_window.WaitWhileBusy();
foreach (var template in edmx.ProjectItems.OfType<ProjectItem>().Where(x => x.Name.EndsWith(".tt")))
{
SetVSProgress("Running custom tool for " + template.Name + "...");
(template.Object as VSProjectItem).RunCustomTool();
_window.WaitWhileBusy();
}
_window.WaitWhileBusy();
SetVSProgress("Building project " + dalProjectName + "...");
DTE.Solution.SolutionBuild.BuildProject("Debug", project.FullName, true);
if (DTE.Solution.SolutionBuild.LastBuildInfo > 0)
{
throw new ExternalException(dalProjectName + " failed to build!");
}
}
private void GenerateAndBuildObservables()
{
var project = _projects.SingleOrDefault(x => x.Name == observablesGeneratorProjectName);
if (project == null)
{
throw new NullReferenceException("Could not locate project " + observablesGeneratorProjectName);
}
SetVSProgress("Building project " + observablesGeneratorProjectName + "...");
DTE.Solution.SolutionBuild.BuildProject("Debug", project.FullName, true);
DTE.Solution.Properties.Item("StartupProject").Value = observablesGeneratorProjectName;
SetVSProgress("Executing observables generator...");
DTE.ExecuteCommand("Debug.Start");
WaitForWindowOpen("Tango Observables Generator");
WaitForWindowClose("Tango Observables Generator");
var observablesProject = _projects.SingleOrDefault(x => x.Name == observablesProjectName);
if (observablesProject == null)
{
throw new NullReferenceException("Could not locate project " + observablesProjectName);
}
SetVSProgress("Updating " + observablesProjectName + "...");
foreach (var file in Directory.GetFiles(Path.GetDirectoryName(observablesProject.FileName), "*.cs", SearchOption.AllDirectories))
{
String parentFolderName = Path.GetFileName(Path.GetDirectoryName(file));
if (parentFolderName != "Debug" && parentFolderName != "Release" && parentFolderName != "obj")
{
SetVSProgress("Adding/Updating file " + Path.GetFileName(file) + "...");
observablesProject.ProjectItems.AddFromFile(file);
Wait(10);
}
}
SetVSProgress("Building project " + observablesProjectName + "...");
DTE.Solution.SolutionBuild.BuildProject("Debug", observablesProject.FullName, true);
if (DTE.Solution.SolutionBuild.LastBuildInfo > 0)
{
throw new ExternalException(observablesProjectName + " failed to build!");
}
project = _projects.SingleOrDefault(x => x.Name == observablesProjectName);
if (project == null)
{
throw new NullReferenceException("Could not locate project " + observablesProjectName);
}
SetVSProgress("Generating views for ObservablesContext...");
var views_file = GetProjectItems(project).SingleOrDefault(x => x.Name == observablesContextName);
if (views_file == null)
{
throw new NullReferenceException("Could not locate " + observablesContextName + "!");
}
Wait(1000);
DTE.MainWindow.Activate();
ExpandSolutionExplorerNode($"Tango\\{observablesProjectName}");
Wait(1000);
SelectSolutionExplorerNode($"Tango\\{observablesProjectName}\\{observablesContextName}");
Wait(1000);
Keyboard.Instance.HoldKey(KeyboardInput.SpecialKeys.SHIFT);
Keyboard.Instance.PressSpecialKey(KeyboardInput.SpecialKeys.F10);
Keyboard.Instance.LeaveAllKeys();
Wait(1000);
for (int i = 0; i < 3; i++)
{
Keyboard.Instance.PressSpecialKey(KeyboardInput.SpecialKeys.DOWN);
Wait(100);
}
Keyboard.Instance.PressSpecialKey(KeyboardInput.SpecialKeys.RIGHT);
Wait(100);
for (int i = 0; i < 3; i++)
{
Keyboard.Instance.PressSpecialKey(KeyboardInput.SpecialKeys.DOWN);
Wait(100);
}
Keyboard.Instance.PressSpecialKey(KeyboardInput.SpecialKeys.RETURN);
_window.WaitWhileBusy();
}
private void GenerateAutoPMRMessages()
{
var project = _projects.SingleOrDefault(x => x.Name == pmrGeneratorProjectName);
if (project == null)
{
throw new NullReferenceException("Could not locate project " + pmrGeneratorProjectName);
}
SetVSProgress("Building project " + pmrGeneratorProjectName + "...");
DTE.Solution.SolutionBuild.BuildProject("Debug", project.FullName, true);
DTE.Solution.Properties.Item("StartupProject").Value = pmrGeneratorProjectName;
SetVSProgress("Executing PMR generator...");
DTE.ExecuteCommand("Debug.Start");
WaitForWindowOpen("Tango PMR Generator");
WaitForWindowClose("Tango PMR Generator");
}
private void UpdateAndBuildPmrMessages()
{
var protoProject = _projects.SingleOrDefault(x => x.Name == protoCliProjectName);
if (protoProject == null)
{
throw new NullReferenceException("Could not locate project " + protoCliProjectName);
}
SetVSProgress("Building project " + protoCliProjectName + "...");
DTE.Solution.SolutionBuild.BuildProject("Debug", protoProject.FullName, true);
if (DTE.Solution.SolutionBuild.LastBuildInfo > 0)
{
throw new ExternalException(protoCliProjectName + " failed to build!");
}
DTE.Solution.Properties.Item("StartupProject").Value = protoCliProjectName;
SetVSProgress("Executing Tango Proto Compiler...");
DTE.ExecuteCommand("Debug.Start");
WaitForWindowOpen("Tango Protobuf Compiler");
WaitForWindowClose("Tango Protobuf Compiler");
var project = _projects.SingleOrDefault(x => x.Name == pmrProjectName);
if (project == null)
{
throw new NullReferenceException("Could not locate project " + pmrProjectName);
}
SetVSProgress("Updating " + pmrProjectName + "...");
foreach (var file in Directory.GetFiles(Path.GetDirectoryName(project.FileName), "*.cs", SearchOption.AllDirectories))
{
String parentFolderName = Path.GetFileName(Path.GetDirectoryName(file));
if (parentFolderName != "Debug" && parentFolderName != "Release" && parentFolderName != "obj")
{
SetVSProgress("Adding/Updating file " + Path.GetFileName(file) + "...");
project.ProjectItems.AddFromFile(file);
Wait(10);
}
}
SetVSProgress("Building project " + pmrProjectName + "...");
DTE.Solution.SolutionBuild.BuildProject("Debug", project.FullName, true);
if (DTE.Solution.SolutionBuild.LastBuildInfo > 0)
{
throw new ExternalException(pmrProjectName + " failed to build!");
}
}
private void GenerateSQLite()
{
var project = _projects.SingleOrDefault(x => x.Name == sqliteProjectName);
if (project == null)
{
throw new NullReferenceException("Could not locate project " + sqliteProjectName);
}
SetVSProgress("Building project " + sqliteProjectName + "...");
DTE.Solution.SolutionBuild.BuildProject("Debug", project.FullName, true);
DTE.Solution.Properties.Item("StartupProject").Value = sqliteProjectName;
SetVSProgress("Executing SQLite generator...");
DTE.ExecuteCommand("Debug.Start");
WaitForWindowOpen("Tango SQLite Generator");
WaitForWindowClose("Tango SQLite Generator");
}
private void BuildSolution()
{
SetVSProgress("Building solution...");
DTE.Solution.SolutionBuild.Build(true);
if (DTE.Solution.SolutionBuild.LastBuildInfo > 0)
{
throw new ExternalException("Error building solution!");
}
}
#endregion
}
}