160 lines
6.5 KiB
C#
160 lines
6.5 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);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogTarget.LogLine($"Exception during import: {ex.Message}", LogEvent.ELogLevel.Error, "ImportProcess");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
}
|