dmdb/core/ImportProcess.cs

163 lines
6.8 KiB
C#

using System;
using System.IO;
using ICSharpCode.SharpZipLib.Zip;
using dezentrale.model;
namespace dezentrale.core
{
//! \short Import functionality for the database contents
//! \brief The normal export workflow is to pull the newest commits from mercurial
//! or git and update/checkout them. After that, there is a packed zip file
//! available that will be unpacked to the data directory
public class ImportProcess : ImportExportBase
{
public ImportProcess()
{
Caption = "Database import";
Steps = 5;
}
//! \short Run import
//! \brief Requests mercurial/git commits from remote, applies them
//! locally, then decrypts using gpg and unzips the result to
//! the member directory.
//! \return true if the import was successful.
//! \note This may corrupt your local db if it fails!
//! \todo Recover from failure by restoring backups
protected override bool Run()
{
LogTarget.StepStarted(0, "Preparing import");
if (ImportExportSettings == 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;
} else if (!Directory.Exists(MemberDir))
{
LogTarget.LogLine($"Cannot find directory '{MemberDir}'", LogEvent.ELogLevel.Error, "ImportProcess");
return false;
}
if (InputDir == null)
{
LogTarget.LogLine("Input directory not set.", LogEvent.ELogLevel.Error, "ImportProcess");
return false;
}
else if (!Directory.Exists(InputDir))
{
LogTarget.LogLine($"Cannot find directory '{InputDir}'", LogEvent.ELogLevel.Error, "ImportProcess");
return false;
}
LogTarget.StepStarted(1, "Fetching repository");
if (ImportExportSettings.HgEnabled)
{
RunProcess("hg", "init", InputDir, LogTarget);
RunProcess("hg", "update null", InputDir, LogTarget);
if (!RunProcess("hg", $"--config auth.rc.prefix={ImportExportSettings.HgURL} --config auth.rc.username={ImportExportSettings.HgUserName} --config auth.rc.password={ImportExportSettings.HgPassword} pull {ImportExportSettings.HgURL}", InputDir, LogTarget))
return false;
if (!RunProcess("hg", $"update", InputDir, LogTarget))
return false;
}
if (ImportExportSettings.GpgEnabled)
{
LogTarget.StepStarted(2, $"Decrypting {ImportExportSettings.GpgFile}");
LogTarget.LogLine($"Import: Using GPG to decrypt {Path.Combine(InputDir, ImportExportSettings.GpgFile)}", LogEvent.ELogLevel.Info, "ImportProcess");
if (!Gpg($"--output {Path.Combine(InputDir, ImportExportSettings.ZipFile)} --decrypt {Path.Combine(InputDir, ImportExportSettings.GpgFile)}", ImportExportSettings.GpgPassword, LogTarget)) return false;
}
try
{
LogTarget.StepStarted(3, $"Backupping Contents of {MemberDir}");
string[] filenames = Directory.GetFiles(MemberDir, "*.xml");
LogTarget.LogLine($"Backing up all xml in {MemberDir} ({filenames.Length} files)", LogEvent.ELogLevel.Info, "ImportProcess");
foreach (string f in filenames)
{
//LogTarget.LogLine($"Creating backup of {f}", LogEvent.ELogLevel.Trace, "ImportProcess");
XmlData.CreateBackup(f, false, "DbImport", true);
}
foreach (string f in filenames)
{
//LogTarget.LogLine($"Deleting backupped {f}", LogEvent.ELogLevel.Trace, "ImportProcess");
File.Delete(f);
}
System.Threading.Thread.Sleep(10);
LogTarget.StepStarted(4, $"Unpacking {ImportExportSettings.ZipFile}");
LogTarget.LogLine($"Extracting {Path.Combine(InputDir, ImportExportSettings.ZipFile)}", LogEvent.ELogLevel.Info, "ImportProcess");
string inFile = Path.Combine(InputDir, ImportExportSettings.ZipFile);
using (ZipInputStream s = new ZipInputStream(File.OpenRead(inFile)))
{
s.Password = ImportExportSettings.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(4, $"Unpacking {ImportExportSettings.ZipFile}", true);
Program.config.LastDbImport = DateTime.Now;
XmlData.SaveToFile(Program.ConfigFile, Program.config);
LogTarget.LogLine("Import complete!", LogEvent.ELogLevel.Info, "ImportProcess");
}
catch (Exception ex)
{
LogTarget.LogLine($"Exception during import: {ex.Message}", LogEvent.ELogLevel.Error, "ImportProcess");
return false;
}
return true;
}
}
}