mirror of https://gitlab.com/basile.b/dexed.git
368 lines
10 KiB
D
368 lines
10 KiB
D
module cesetup;
|
|
|
|
import std.stdio;
|
|
import std.file: mkdirRecurse, exists, remove, rmdir, getSize, FileException;
|
|
import std.stream: File, FileMode;
|
|
import std.process: environment, executeShell;
|
|
import std.path: dirSeparator;
|
|
import std.string: strip, toLower, center, leftJustify, rightJustify;
|
|
import std.getopt;
|
|
|
|
version(X86) version(linux) version = nux32;
|
|
version(X86_64) version(linux) version = nux64;
|
|
version(X86) version(Windows)version = win32;
|
|
|
|
version(win32) enum exeExt = ".exe";
|
|
else enum exeExt = "";
|
|
|
|
alias ImpType = immutable ubyte[];
|
|
alias ResType = immutable Resource;
|
|
|
|
struct Resource
|
|
{
|
|
ImpType data;
|
|
immutable string destName;
|
|
immutable bool isExe;
|
|
}
|
|
|
|
Resource[] ceResources =
|
|
[
|
|
Resource(cast(ImpType) import("coedit" ~ exeExt), "coedit" ~ exeExt, true),
|
|
Resource(cast(ImpType) import("cesyms" ~ exeExt), "cesyms" ~ exeExt, true),
|
|
Resource(cast(ImpType) import("cetodo" ~ exeExt), "cetodo" ~ exeExt, true),
|
|
Resource(cast(ImpType) import("coedit.ico"), "coedit.ico", false),
|
|
Resource(cast(ImpType) import("coedit.png"), "coedit.png", false),
|
|
Resource(cast(ImpType) import("coedit.license.txt"), "coedit.license.txt", false)
|
|
];
|
|
|
|
Resource[] dcdResources =
|
|
[
|
|
Resource(cast(ImpType) import("dcd-server" ~ exeExt), "dcd-server" ~ exeExt, true),
|
|
Resource(cast(ImpType) import("dcd-client" ~ exeExt), "dcd-client" ~ exeExt, true),
|
|
Resource(cast(ImpType) import("dcd.license.txt"), "dcd.license.txt", false)
|
|
];
|
|
|
|
|
|
static struct Formater
|
|
{
|
|
private enum width = 48;
|
|
private static __gshared char[] separator;
|
|
|
|
static this()
|
|
{
|
|
separator.length = width + 4;
|
|
separator[] = '-';
|
|
separator[0] = '+';
|
|
separator[$-1] = '+';
|
|
}
|
|
|
|
static void justify(char A)(string s)
|
|
in
|
|
{
|
|
assert (s.length <= width, "too long to fit on a line...");
|
|
}
|
|
body
|
|
{
|
|
static if (A == 'L')
|
|
writeln("| ", leftJustify(s, width, ' '), " |");
|
|
else static if (A == 'C')
|
|
writeln("| ", center(s, width, ' '), " |");
|
|
else static if (A == 'R')
|
|
writeln("| ", rightJustify(s, width, ' '), " |");
|
|
else static assert(0, "invalid justification, L|C|R expected");
|
|
}
|
|
|
|
static void separate(){separator.writeln;}
|
|
|
|
static void emptyLine(){justify!'L'("");}
|
|
}
|
|
|
|
|
|
static immutable string exePath, appDataPath, shortCutPath;
|
|
version(linux) immutable bool asSu;
|
|
|
|
|
|
static this()
|
|
{
|
|
version(win32)
|
|
{
|
|
exePath = environment.get("PROGRAMFILES") ~ r"\Coedit\";
|
|
appDataPath = environment.get("APPDATA") ~ r"\Coedit\";
|
|
shortCutPath = environment.get("USERPROFILE") ~ r"\Desktop\";
|
|
}
|
|
else
|
|
{
|
|
asSu = environment.get("SUDO_USER") != "";
|
|
if (asSu)
|
|
{
|
|
exePath = "/usr/bin";
|
|
appDataPath = "/home/" ~ environment.get("SUDO_USER") ~ "/.config/Coedit/";
|
|
shortCutPath = "/usr/share/applications/";
|
|
}
|
|
else
|
|
{
|
|
exePath = "/home/" ~ environment.get("USER") ~ "/bin/";
|
|
appDataPath = "/home/" ~ environment.get("USER") ~ "/.config/Coedit/";
|
|
shortCutPath = "/home/" ~ environment.get("USER") ~ "/.local/share/applications/";
|
|
}
|
|
}
|
|
}
|
|
|
|
void main(string[] args)
|
|
{
|
|
bool nodcd;
|
|
bool uninstall;
|
|
bool listfiles;
|
|
|
|
getopt(args, config.passThrough,
|
|
"nodcd", &nodcd,
|
|
"u|uninstall", &uninstall,
|
|
"l|list", &listfiles
|
|
);
|
|
|
|
Formater.separate;
|
|
|
|
|
|
if (listfiles)
|
|
{
|
|
static immutable fmtRes = "%s installed: %s";
|
|
string fname;
|
|
|
|
Formater.separate;
|
|
Formater.justify!'C'("files list and status");
|
|
Formater.separate;
|
|
|
|
foreach(res; ceResources)
|
|
{
|
|
fname = res.isExe ? exePath ~ res.destName : appDataPath ~ res.destName;
|
|
writefln(fmtRes, fname, exists(fname));
|
|
}
|
|
foreach(res; dcdResources)
|
|
{
|
|
fname = res.isExe ? exePath ~ res.destName : appDataPath ~ res.destName;
|
|
writefln(fmtRes, fname, exists(fname));
|
|
}
|
|
|
|
Formater.separate;
|
|
return;
|
|
}
|
|
|
|
if (!uninstall) Formater.justify!'C'("Coedit 2 alpha 2 - setup");
|
|
else Formater.justify!'C'("Coedit uninstaller");
|
|
|
|
Formater.separate;
|
|
version(win32) Formater.justify!'L'("the setup program must be run as admin");
|
|
else
|
|
{
|
|
if(!asSu) Formater.justify!'L'("Coedit can also be setup globally (sudo)");
|
|
else Formater.justify!'L'("Coedit will be accessible from all the accounts");
|
|
}
|
|
|
|
Formater.separate;
|
|
Formater.justify!'L'("options:");
|
|
Formater.emptyLine;
|
|
Formater.justify!'L'("-l | --list: list files and status");
|
|
if (!uninstall)
|
|
{
|
|
if (!nodcd) Formater.justify!'L'("--nodcd: skip DCD setup");
|
|
Formater.justify!'L'("-u | --uninstall: uninstall");
|
|
}
|
|
else if (!nodcd) Formater.justify!'L'("--nodcd: do not remove DCD");
|
|
Formater.justify!'L'("press A to abort or another key to start...");
|
|
Formater.separate;
|
|
|
|
const string inp = readln.strip;
|
|
if (inp.toLower == "a") return;
|
|
|
|
Formater.separate;
|
|
|
|
size_t failures;
|
|
bool done;
|
|
if(!uninstall)
|
|
{
|
|
static immutable extractMsg = [": FAILURE", ": extracted"];
|
|
foreach(res; ceResources)
|
|
{
|
|
if (res.isExe)
|
|
done = installResource(res, exePath);
|
|
else
|
|
done = installResource(res, appDataPath);
|
|
Formater.justify!'L'(res.destName ~ extractMsg[done]);
|
|
failures += !done;
|
|
}
|
|
if (!nodcd) foreach(res; dcdResources)
|
|
{
|
|
if (res.isExe)
|
|
done = installResource(res, exePath);
|
|
else
|
|
done = installResource(res, appDataPath);
|
|
Formater.justify!'L'(res.destName ~ extractMsg[done]);
|
|
failures += !done;
|
|
}
|
|
|
|
Formater.separate;
|
|
if (failures)
|
|
Formater.justify!'L'("there are ERRORS, plz contact the support");
|
|
else
|
|
{
|
|
version(win32) win32PostInstall();
|
|
else nuxPostInstall();
|
|
Formater.justify!'L'("the files are correctly extracted...");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!asSu && exists("/usr/bin/coedit"))
|
|
{
|
|
Formater.separate;
|
|
Formater.justify!'L'("warning, CE seems to be installed with sudo");
|
|
Formater.justify!'L'("but the uninstaller is not launched with sudo.");
|
|
Formater.separate;
|
|
}
|
|
else if (asSu && exists("/home/" ~ environment.get("USER") ~ "/bin/coedit"))
|
|
{
|
|
Formater.separate;
|
|
Formater.justify!'L'("warning, CE seems not to be installed with sudo");
|
|
Formater.justify!'L'("...but the uninstaller is launched with sudo.");
|
|
Formater.separate;
|
|
}
|
|
static immutable rmMsg = [": FAILURE", ": deleted"];
|
|
foreach(res; ceResources)
|
|
{
|
|
if (res.isExe)
|
|
done = uninstallResource(res, exePath);
|
|
else
|
|
done = uninstallResource(res, appDataPath);
|
|
Formater.justify!'L'(res.destName ~ rmMsg[done]);
|
|
failures += !done;
|
|
}
|
|
if (!nodcd) foreach(res; dcdResources)
|
|
{
|
|
if (res.isExe)
|
|
done = uninstallResource(res, exePath);
|
|
else
|
|
done = uninstallResource(res, appDataPath);
|
|
Formater.justify!'L'(res.destName ~ rmMsg[done]);
|
|
failures += !done;
|
|
}
|
|
|
|
version(win32)
|
|
{
|
|
try rmdir(exePath);
|
|
catch(FileException e) failures++;
|
|
}
|
|
|
|
Formater.separate;
|
|
if (failures)
|
|
Formater.justify!'L'("there are ERRORS, plz contact the support");
|
|
else
|
|
{
|
|
version(win32) win32PostUninstall();
|
|
else nuxPostUninstall();
|
|
Formater.justify!'L'("the files are correctly removed...");
|
|
}
|
|
}
|
|
Formater.emptyLine;
|
|
Formater.justify!'R'("...press a key to exit");
|
|
Formater.separate;
|
|
readln;
|
|
}
|
|
|
|
string extractedName(Resource resource, string path)
|
|
{
|
|
return path ~ dirSeparator ~ resource.destName;
|
|
}
|
|
|
|
bool installResource(Resource resource, string path)
|
|
{
|
|
if (!path.exists)
|
|
mkdirRecurse(path);
|
|
if (!path.exists)
|
|
return false;
|
|
|
|
try
|
|
{
|
|
const string fname = extractedName(resource, path);
|
|
File f = new File(fname, FileMode.OutNew);
|
|
f.write(resource.data);
|
|
f.close;
|
|
|
|
version(win32) {}
|
|
else if (resource.isExe && fname.exists)
|
|
executeShell("chmod a+x " ~ fname);
|
|
}
|
|
catch (Exception e)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool uninstallResource(Resource resource, string path)
|
|
{
|
|
const string fname = extractedName(resource, path);
|
|
if (!fname.exists) return true;
|
|
else return tryRemove(fname);
|
|
}
|
|
|
|
bool tryRemove(string fname)
|
|
{
|
|
bool result = true;
|
|
try remove(fname);
|
|
catch (FileException e) {result = false;}
|
|
return result;
|
|
}
|
|
|
|
version(linux) void nuxPostInstall()
|
|
{
|
|
mkdirRecurse(shortCutPath);
|
|
File f = new File(shortCutPath ~ "coedit.desktop", FileMode.OutNew);
|
|
f.writeLine("[Desktop Entry]");
|
|
f.writeLine("Name=coedit");
|
|
f.writeLine("Exec=coedit %f");
|
|
f.writeLine("Icon=" ~ appDataPath ~ "/coedit.png");
|
|
f.writeLine("Type=Application");
|
|
f.writeLine("Categories=Utility;Application;Development;");
|
|
f.writeLine("Terminal=false");
|
|
f.close;
|
|
}
|
|
|
|
version(linux) void nuxPostUninstall()
|
|
{
|
|
tryRemove(shortCutPath ~ "coedit.desktop");
|
|
}
|
|
|
|
version (win32) void win32PostInstall()
|
|
{
|
|
import std.conv: to;
|
|
import std.random: uniform;
|
|
|
|
// shortcut prior to v 1 upd 2 was actually an url.
|
|
tryRemove(shortCutPath ~ "Coedit.url");
|
|
|
|
string target = exePath ~ "coedit.exe";
|
|
string vbsName;
|
|
do vbsName = environment.get("TEMP") ~ r"\cesh" ~ uniform(0,int.max).to!string ~ ".vbs";
|
|
while (vbsName.exists);
|
|
|
|
string vbsCode = "
|
|
set WshShell = CreateObject(\"WScript.shell\")
|
|
strDesktop = WshShell.SpecialFolders(\"Desktop\")
|
|
set lnk = WshShell.CreateShortcut(strDesktop + \"\\Coedit.lnk\")
|
|
lnk.TargetPath = \"%s\"
|
|
lnk.Save
|
|
";
|
|
File vbs = new File(vbsName, FileMode.OutNew);
|
|
vbs.writefln(vbsCode, target);
|
|
vbs.close;
|
|
executeShell(vbsName);
|
|
|
|
tryRemove(vbsName);
|
|
}
|
|
|
|
version (win32) void win32PostUninstall()
|
|
{
|
|
// shortcut prior to v 1 upd 2 was actually an url.
|
|
tryRemove(shortCutPath ~ "Coedit.url");
|
|
tryRemove(shortCutPath ~ "Coedit.lnk");
|
|
}
|