191201PX Refactoring database import to use process window/logging; unfinished yet.
This commit is contained in:
parent
575279e0c2
commit
7a65a110fc
|
@ -31,7 +31,7 @@ namespace dezentrale
|
|||
{
|
||||
public class Program
|
||||
{
|
||||
public static uint VersionNumber { get; private set; } = 0x19112700;
|
||||
public static uint VersionNumber { get; private set; } = 0x19120100;
|
||||
public static string VersionString { get; private set; } = $"{VersionNumber:x}";
|
||||
|
||||
public static string AppData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
||||
|
|
|
@ -27,8 +27,19 @@ namespace dezentrale.model
|
|||
|
||||
EMail,
|
||||
|
||||
// TODO: [Obsolete("Use ELogLevel.Error instead")]
|
||||
Error,
|
||||
}
|
||||
|
||||
public enum ELogLevel
|
||||
{
|
||||
Trace = -1,
|
||||
Debug = 0,
|
||||
Info = 1,
|
||||
Warning = 2,
|
||||
Error = 3,
|
||||
}
|
||||
|
||||
[XmlAttribute] public DateTime Timestamp { get; set; } = DateTime.Now;
|
||||
[XmlAttribute] public string LocalUser { get; set; } = Program.config.LocalUser;
|
||||
[XmlElement("SubEvent")] public List<LogSubEvent> SubEvents { get; set; } = new List<LogSubEvent>();
|
||||
|
|
|
@ -8,39 +8,156 @@ namespace dezentrale.model
|
|||
{
|
||||
public class ImportProcess : view.BackgroundProcess
|
||||
{
|
||||
|
||||
public MemberImportExport MemberImportSettings { get; set; } = null;
|
||||
public string MemberDir { get; set; } = null;
|
||||
public string InputDir { get; set; } = null;
|
||||
public ImportProcess()
|
||||
{
|
||||
Caption = "Database import";
|
||||
Steps = 20;
|
||||
Steps = 4;
|
||||
}
|
||||
protected override bool Run()
|
||||
{
|
||||
if (InputDir == null)
|
||||
{
|
||||
LogTarget.LogLine("Input directory not set.", view.ELogLevel.Error, "ImportProcess");
|
||||
{
|
||||
|
||||
LogTarget.StepStarted(0, "Preparing import");
|
||||
|
||||
if (MemberImportSettings == null)
|
||||
{
|
||||
LogTarget.LogLine("MemberImportExport data class not set.", LogEvent.ELogLevel.Error, "ImportProcess");
|
||||
return false;
|
||||
}
|
||||
if (MemberDir == null)
|
||||
{
|
||||
LogTarget.LogLine("Member directory not set.", LogEvent.ELogLevel.Error, "ImportProcess");
|
||||
return false;
|
||||
}
|
||||
if (InputDir == null)
|
||||
{
|
||||
LogTarget.LogLine("Input directory not set.", LogEvent.ELogLevel.Error, "ImportProcess");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*if (HgEnabled)
|
||||
|
||||
|
||||
|
||||
|
||||
LogTarget.StepStarted(1, "Fetching repository");
|
||||
|
||||
if (MemberImportSettings.HgEnabled)
|
||||
{
|
||||
RunProcess("hg", "init", inputDir);
|
||||
RunProcess("hg", "update null", inputDir);
|
||||
if (!RunProcess("hg", $"--config auth.rc.prefix={HgURL} --config auth.rc.username={HgUserName} --config auth.rc.password={HgPassword} pull {HgURL}", inputDir))
|
||||
MemberImportExport.RunProcess("hg", "init", InputDir, LogTarget);
|
||||
MemberImportExport.RunProcess("hg", "update null", InputDir, LogTarget);
|
||||
if (!MemberImportExport.RunProcess("hg", $"--config auth.rc.prefix={MemberImportSettings.HgURL} --config auth.rc.username={MemberImportSettings.HgUserName} --config auth.rc.password={MemberImportSettings.HgPassword} pull {MemberImportSettings.HgURL}", InputDir, LogTarget))
|
||||
return false;
|
||||
if (!RunProcess("hg", $"update", inputDir))
|
||||
if (!MemberImportExport.RunProcess("hg", $"update", InputDir, LogTarget))
|
||||
return false;
|
||||
}
|
||||
if (GpgEnabled)
|
||||
if (MemberImportSettings.GpgEnabled)
|
||||
{
|
||||
Console.WriteLine($"Import: Using GPG to decrypt {Path.Combine(inputDir, GpgFile)}");
|
||||
if (!Gpg($"--output {Path.Combine(inputDir, ZipFile)} --decrypt {Path.Combine(inputDir, GpgFile)}")) return false;
|
||||
Console.WriteLine($"Import: Using GPG to decrypt {Path.Combine(InputDir, MemberImportSettings.GpgFile)}");
|
||||
if (!MemberImportExport.Gpg($"--output {Path.Combine(InputDir, MemberImportSettings.ZipFile)} --decrypt {Path.Combine(InputDir, MemberImportSettings.GpgFile)}", MemberImportSettings.GpgPassword)) return false;
|
||||
}
|
||||
if (!Directory.Exists(MemberDir))
|
||||
{
|
||||
LogTarget.LogLine($"Cannot find directory '{MemberDir}'", LogEvent.ELogLevel.Error, "ImportProcess");
|
||||
return false;
|
||||
}
|
||||
if (!Directory.Exists(InputDir))
|
||||
{
|
||||
LogTarget.LogLine($"Cannot find directory '{InputDir}'", LogEvent.ELogLevel.Error, "ImportProcess");
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
LogTarget.StepStarted(2, $"Backupping Contents of {MemberDir}");
|
||||
|
||||
string[] filenames = Directory.GetFiles(MemberDir, "*.xml");
|
||||
LogTarget.LogLine($"Renaming {filenames.Length} xml files to xml.bak in {MemberDir}", LogEvent.ELogLevel.Info, "ImportProcess");
|
||||
|
||||
foreach (string f in filenames)
|
||||
{
|
||||
string fileName = Path.GetFileName(f);
|
||||
string backupName = $"{fileName}.bak";
|
||||
if (File.Exists(backupName)) File.Delete(backupName);
|
||||
File.Move(fileName, backupName);
|
||||
File.Delete(fileName);
|
||||
}
|
||||
|
||||
LogTarget.StepStarted(3, $"Unpacking {MemberImportSettings.ZipFile}");
|
||||
LogTarget.LogLine($"Extracting {Path.Combine(InputDir, MemberImportSettings.ZipFile)}", LogEvent.ELogLevel.Info, "ImportProcess");
|
||||
string inFile = Path.Combine(InputDir, MemberImportSettings.ZipFile);
|
||||
|
||||
|
||||
using (ZipInputStream s = new ZipInputStream(File.OpenRead(inFile)))
|
||||
{
|
||||
s.Password = MemberImportSettings.ZipPassword;
|
||||
|
||||
ZipEntry theEntry;
|
||||
while ((theEntry = s.GetNextEntry()) != null)
|
||||
{
|
||||
|
||||
Console.WriteLine(theEntry.Name);
|
||||
|
||||
string directoryName = Path.GetDirectoryName(theEntry.Name);
|
||||
string fileName = Path.GetFileName(theEntry.Name);
|
||||
|
||||
// create directory
|
||||
if (directoryName.Length > 0)
|
||||
{
|
||||
Directory.CreateDirectory(directoryName);
|
||||
}
|
||||
|
||||
if (fileName != String.Empty)
|
||||
{
|
||||
using (FileStream streamWriter = File.Create(Path.Combine(MemberDir, theEntry.Name)))
|
||||
{
|
||||
|
||||
int size = 2048;
|
||||
byte[] data = new byte[2048];
|
||||
while (true)
|
||||
{
|
||||
size = s.Read(data, 0, data.Length);
|
||||
if (size > 0)
|
||||
{
|
||||
streamWriter.Write(data, 0, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
LogTarget.StepCompleted(3, $"Unpacking {MemberImportSettings.ZipFile}", true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogTarget.LogLine($"Exception during import: {ex.Message}", LogEvent.ELogLevel.Error, "ImportProcess");
|
||||
return false;
|
||||
}
|
||||
Console.WriteLine($"Import: Extracting {Path.Combine(inputDir, ZipFile)}");
|
||||
if (ZipImport(memberDirectory, inputDir) != true) return false;*/
|
||||
return true;
|
||||
}
|
||||
private bool ZipImport()
|
||||
{
|
||||
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Exception during import: {ex.Message}");
|
||||
|
||||
// No need to rethrow the exception as for our purposes its handled.
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
public class MemberImportExport
|
||||
{
|
||||
|
@ -59,12 +176,21 @@ namespace dezentrale.model
|
|||
|
||||
|
||||
|
||||
private bool RunProcess(string cmd, string args, string workingDir = ".")
|
||||
public static bool RunProcess(string cmd, string args, string workingDir = ".", view.ILogger log = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Console.WriteLine($"cmd: {cmd} {args}");
|
||||
Console.WriteLine($"dir: {workingDir}");
|
||||
{
|
||||
if (log != null)
|
||||
{
|
||||
log.LogLine($"Running {cmd}", LogEvent.ELogLevel.Info, "RunProcess");
|
||||
log.LogRaw($"args: {cmd} {args}");
|
||||
log.LogRaw($"dir: {workingDir}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"cmd: {cmd} {args}");
|
||||
Console.WriteLine($"dir: {workingDir}");
|
||||
}
|
||||
Process p = new Process();
|
||||
|
||||
p.StartInfo.FileName = cmd;
|
||||
|
@ -80,15 +206,23 @@ namespace dezentrale.model
|
|||
p.WaitForExit();
|
||||
if (stdout.Length > 0)
|
||||
{
|
||||
Console.WriteLine("stdout:");
|
||||
Console.WriteLine(stdout);
|
||||
Console.WriteLine();
|
||||
if (log != null) log.LogRaw(stdout);
|
||||
else
|
||||
{
|
||||
Console.WriteLine("stdout:");
|
||||
Console.WriteLine(stdout);
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
if (stderr.Length > 0)
|
||||
{
|
||||
Console.WriteLine("stderr:");
|
||||
Console.WriteLine(stderr);
|
||||
Console.WriteLine();
|
||||
if (log != null) log.LogRaw(stderr);
|
||||
else
|
||||
{
|
||||
Console.WriteLine("stderr:");
|
||||
Console.WriteLine(stderr);
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
return p.ExitCode == 0;
|
||||
} catch (Exception ex)
|
||||
|
@ -98,9 +232,9 @@ namespace dezentrale.model
|
|||
|
||||
return false;
|
||||
}
|
||||
private bool Gpg(string args)
|
||||
public static bool Gpg(string args, string gpgPassword)
|
||||
{
|
||||
string argsFull = $"--batch --yes --passphrase \"{GpgPassword}\" {args}";
|
||||
string argsFull = $"--batch --yes --passphrase \"{gpgPassword}\" {args}";
|
||||
return RunProcess("gpg", argsFull);
|
||||
}
|
||||
public bool Export(string memberDirectory, string outputDir)
|
||||
|
@ -111,7 +245,7 @@ namespace dezentrale.model
|
|||
if (GpgEnabled)
|
||||
{
|
||||
Console.WriteLine($"Export: Using GPG to encrypt {Path.Combine(outputDir, GpgFile)}");
|
||||
if (!Gpg($"--output \"{Path.Combine(outputDir, GpgFile)}\" -c \"{tmpFile}\"")) return false;
|
||||
if (!Gpg($"--output \"{Path.Combine(outputDir, GpgFile)}\" -c \"{tmpFile}\"", GpgPassword)) return false;
|
||||
tmpFile = Path.Combine(outputDir, GpgFile);
|
||||
}
|
||||
if (HgEnabled)
|
||||
|
@ -136,7 +270,8 @@ namespace dezentrale.model
|
|||
[Obsolete]
|
||||
public bool Import(string memberDirectory, string inputDir)
|
||||
{
|
||||
if(HgEnabled)
|
||||
throw new NotImplementedException();
|
||||
/*if(HgEnabled)
|
||||
{
|
||||
RunProcess("hg", "init", inputDir);
|
||||
RunProcess("hg", "update null", inputDir);
|
||||
|
@ -148,11 +283,11 @@ namespace dezentrale.model
|
|||
if (GpgEnabled)
|
||||
{
|
||||
Console.WriteLine($"Import: Using GPG to decrypt {Path.Combine(inputDir, GpgFile)}");
|
||||
if (!Gpg($"--output {Path.Combine(inputDir, ZipFile)} --decrypt {Path.Combine(inputDir, GpgFile)}")) return false;
|
||||
if (!Gpg($"--output {Path.Combine(inputDir, ZipFile)} --decrypt {Path.Combine(inputDir, GpgFile)}", GpgPassword)) return false;
|
||||
}
|
||||
Console.WriteLine($"Import: Extracting {Path.Combine(inputDir, ZipFile)}");
|
||||
if (ZipImport(memberDirectory, inputDir) != true) return false;
|
||||
return true;
|
||||
return true;*/
|
||||
}
|
||||
private bool FilesCompare(string file1, string file2)
|
||||
{
|
||||
|
@ -334,11 +469,13 @@ namespace dezentrale.model
|
|||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/*
|
||||
[Obsolete]
|
||||
private bool ZipImport(string memberDirectory, string inputDir)
|
||||
{
|
||||
|
||||
|
||||
throw new NotImplementedException();
|
||||
/*
|
||||
if (!Directory.Exists(memberDirectory))
|
||||
{
|
||||
Console.WriteLine($"Cannot find directory '{memberDirectory}'");
|
||||
|
@ -415,6 +552,6 @@ namespace dezentrale.model
|
|||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,8 +22,6 @@ namespace dezentrale.view
|
|||
|
||||
public frmMain()
|
||||
{
|
||||
frmProcessWithLog p = new frmProcessWithLog(new HelloWorldProcess(), false);
|
||||
p.Show();
|
||||
this.SuspendLayout();
|
||||
this.Text = $"dezentrale-members Version {Program.VersionString}";
|
||||
this.StartPosition = FormStartPosition.CenterScreen;
|
||||
|
@ -138,11 +136,22 @@ namespace dezentrale.view
|
|||
{
|
||||
DialogResult dr = MessageBox.Show("Overwrite database?", "Warning\nImporting database from external source will overwrite all\nlocal changes! Really import?", MessageBoxButtons.YesNo);
|
||||
if(dr == DialogResult.Yes)
|
||||
{
|
||||
if (!Program.config.ImportExport.Import(Program.config.DbDirectory, Program.DmDirectory))
|
||||
{
|
||||
ImportProcess import = new ImportProcess()
|
||||
{
|
||||
MemberImportSettings = Program.config.ImportExport,
|
||||
MemberDir = Program.config.DbDirectory,
|
||||
InputDir = Program.DmDirectory,
|
||||
};
|
||||
frmProcessWithLog frmImport = new frmProcessWithLog(import, false);
|
||||
dr = frmImport.ShowDialog();
|
||||
MessageBox.Show("DialogResult=" + dr);
|
||||
//Reload member list
|
||||
//Reload moneytransfers, if loaded
|
||||
/*if (!Program.config.ImportExport.Import(Program.config.DbDirectory, Program.DmDirectory))
|
||||
{
|
||||
MessageBox.Show("Import failed!");
|
||||
}
|
||||
}*/
|
||||
Application.Restart();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,21 +6,15 @@ using System.Text;
|
|||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using dezentrale.model;
|
||||
|
||||
namespace dezentrale.view
|
||||
{
|
||||
public enum ELogLevel
|
||||
{
|
||||
Trace = -1,
|
||||
Debug = 0,
|
||||
Info = 1,
|
||||
Warning = 2,
|
||||
Error = 3,
|
||||
}
|
||||
|
||||
public interface ILogger
|
||||
{
|
||||
void Clear();
|
||||
void LogLine(string text, ELogLevel logLevel = ELogLevel.Info, string module = "");
|
||||
void LogRaw(string text);
|
||||
void LogLine(string text, LogEvent.ELogLevel logLevel = LogEvent.ELogLevel.Info, string module = "");
|
||||
}
|
||||
|
||||
public interface IProcessController : ILogger
|
||||
|
@ -65,7 +59,7 @@ namespace dezentrale.view
|
|||
{
|
||||
string stepName = ((i & 0x01) == 0) ? "Hello" : "World";
|
||||
LogTarget.StepStarted(i, stepName);
|
||||
LogTarget.LogLine(stepName, ELogLevel.Info, "HelloWorldProcess");
|
||||
LogTarget.LogLine(stepName, LogEvent.ELogLevel.Info, "HelloWorldProcess");
|
||||
Thread.Sleep(200);
|
||||
LogTarget.StepCompleted(i, stepName, (i & 0x01) == 0);
|
||||
Thread.Sleep(200);
|
||||
|
@ -75,6 +69,7 @@ namespace dezentrale.view
|
|||
}
|
||||
public class frmProcessWithLog : Form, IProcessController
|
||||
{
|
||||
private DialogResult toReturn = DialogResult.Cancel;
|
||||
private TextBox tbLog = null;
|
||||
private Label lblStepStatus = null;
|
||||
private PictureBox picStatus = null;
|
||||
|
@ -91,10 +86,19 @@ namespace dezentrale.view
|
|||
|
||||
private void printline(string line)
|
||||
{
|
||||
tbLog.Invoke(new Action(() => tbLog.AppendText(line + "\r\n")));
|
||||
// tbLog.Invoke(new Action(() =>
|
||||
tbLog.AppendText(line + "\r\n")
|
||||
// ))
|
||||
;
|
||||
Console.WriteLine(line);
|
||||
}
|
||||
public void LogLine(string text, ELogLevel logLevel, string module)
|
||||
public void LogRaw(string text)
|
||||
{
|
||||
printline(text);
|
||||
}
|
||||
|
||||
|
||||
public void LogLine(string text, LogEvent.ELogLevel logLevel, string module)
|
||||
{
|
||||
string output = $"{DateTime.Now} [{module}] {logLevel} {text}";
|
||||
printline(output);
|
||||
|
@ -108,6 +112,12 @@ namespace dezentrale.view
|
|||
this.Width = 800;
|
||||
this.Height = 600;
|
||||
|
||||
/* if (autoRun)
|
||||
{
|
||||
MessageBox.Show("autoRun=true leads to problems with Invoke on gui access from background thread");
|
||||
this.Close();
|
||||
return;
|
||||
}*/
|
||||
// build GUI
|
||||
//[TextBox Multiline ]
|
||||
//[Step display label ]
|
||||
|
@ -177,6 +187,8 @@ namespace dezentrale.view
|
|||
|
||||
if (autoRun)
|
||||
btnStart_Click(null,null);
|
||||
|
||||
this.FormClosing += (sender, e) => DialogResult = toReturn;
|
||||
}
|
||||
|
||||
private void btnStart_Click(object sender, EventArgs e)
|
||||
|
@ -201,18 +213,34 @@ namespace dezentrale.view
|
|||
|
||||
public void StepStarted(uint stepNumber, string stepDescription)
|
||||
{
|
||||
lblStepStatus.Invoke(new Action(() => lblStepStatus.Text = $"# {stepNumber}/{this.process.Steps} : {stepDescription}"));
|
||||
// lblStepStatus.Invoke(new Action(() =>
|
||||
lblStepStatus.Text = $"# {stepNumber + 1}/{this.process.Steps} : {stepDescription}"
|
||||
// ))
|
||||
;
|
||||
}
|
||||
public void StepCompleted(uint stepNumber, string stepDescription, bool success)
|
||||
{
|
||||
lblStepStatus.Invoke(new Action(() => lblStepStatus.Text = $"# {stepNumber}/{this.process.Steps} : Completed({success}) {stepDescription}"));
|
||||
// lblStepStatus.Invoke(new Action(() =>
|
||||
lblStepStatus.Text = $"# {stepNumber + 1}/{this.process.Steps} : Completed({success}) {stepDescription}"
|
||||
// ))
|
||||
;
|
||||
}
|
||||
public void ActionCompleted(bool success)
|
||||
{
|
||||
toReturn = success? DialogResult.Yes : DialogResult.No;
|
||||
btnCancel.Enabled = false;
|
||||
btnClose.Invoke(new Action(() => btnClose.Enabled = true ));
|
||||
picStatus.Invoke(new Action(() => picStatus.BackColor = (success ? Color.Green : Color.Red)));
|
||||
this.Invoke(new Action(() => this.Text = $"Process - {this.process.Caption}" + (success ? " (done)" : " (failed)")));
|
||||
// btnClose.Invoke(new Action(() =>
|
||||
btnClose.Enabled = true
|
||||
// ))
|
||||
;
|
||||
// picStatus.Invoke(new Action(() =>
|
||||
picStatus.BackColor = (success ? Color.Green : Color.Red)
|
||||
// ))
|
||||
;
|
||||
// this.Invoke(new Action(() =>
|
||||
this.Text = $"Process - {this.process.Caption}" + (success ? " (done)" : " (failed)")
|
||||
// ))
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue