public override IEnumerator Run(bool beta)
        {
            yield return(Status("Preparing installation of Julia", false, "", false));

            string root = AhornHelper.RootPath;
            string tmp  = Path.Combine(root, "tmp");

            if (!Directory.Exists(tmp))
            {
                Directory.CreateDirectory(tmp);
            }

            string julia = Path.Combine(root, "julia");

            if (Directory.Exists(julia))
            {
                Directory.Delete(julia, true);
            }

            if (PlatformHelper.Is(Platform.Windows))
            {
                string zipPath = Path.Combine(tmp, "juliadownload.zip");
                if (File.Exists(zipPath))
                {
                    File.Delete(zipPath);
                }

                string url;

                if (PlatformHelper.Is(Platform.Bits64))
                {
                    url = beta ?
                          "https://julialang-s3.julialang.org/bin/winnt/x64/1.6/julia-1.6.0-rc3-win64.zip" :
                          "https://julialang-s3.julialang.org/bin/winnt/x64/1.5/julia-1.5.4-win64.zip";
                }
                else
                {
                    url = beta ?
                          "https://julialang-s3.julialang.org/bin/winnt/x86/1.6/julia-1.6.0-rc3-win32.zip" :
                          "https://julialang-s3.julialang.org/bin/winnt/x86/1.5/julia-1.5.4-win32.zip";
                }

                try {
                    yield return(Status($"Downloading {url}", false, "download", false));

                    using (FileStream zipStream = File.Open(zipPath, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete)) {
                        yield return(Download(url, 0, zipStream));

                        zipStream.Seek(0, SeekOrigin.Begin);

                        yield return(Status("Unzipping Julia", false, "download", false));

                        using (ZipArchive zip = new ZipArchive(zipStream, ZipArchiveMode.Read)) {
                            yield return(Unpack(zip, julia, beta ? "julia-1.6.0-rc3/" : "julia-1.5.4/"));
                        }
                    }
                } finally {
                    if (File.Exists(zipPath))
                    {
                        File.Delete(zipPath);
                    }
                }

                string launcher = Path.Combine(root, "launch-local-julia.bat");
                if (File.Exists(launcher))
                {
                    File.Delete(launcher);
                }
                File.WriteAllText(launcher, @"
@echo off
setlocal EnableDelayedExpansion
set ""JULIA_DEPOT_PATH=%~dp0\julia-depot""
set ""AHORN_GLOBALENV=%LocalAppData%\Ahorn\env""
set ""AHORN_ENV=%~dp0\ahorn-env""
""%~dp0\julia\bin\julia.exe"" %*
"
                                  .TrimStart().Replace("\r\n", "\n").Replace("\n", "\r\n")
                                  );
            }
            else if (PlatformHelper.Is(Platform.Linux))
            {
                string tarPath = Path.Combine(tmp, "juliadownload.tar.gz");
                if (File.Exists(tarPath))
                {
                    File.Delete(tarPath);
                }

                string url;

                string lsPath = ProcessHelper.Read("which", "ls", out _).Trim().Split('\n').FirstOrDefault()?.Trim();
                bool   musl   = !string.IsNullOrEmpty(lsPath) && ProcessHelper.Read("ldd", lsPath, out _).Contains("musl");

                if (PlatformHelper.Is(Platform.ARM))
                {
                    url = beta ?
                          "https://julialang-s3.julialang.org/bin/linux/aarch64/1.6/julia-1.6.0-rc3-linux-aarch64.tar.gz" :
                          "https://julialang-s3.julialang.org/bin/linux/aarch64/1.5/julia-1.5.4-linux-aarch64.tar.gz";
                }
                else if (musl)
                {
                    url = beta ?
                          "https://julialang-s3.julialang.org/bin/musl/x64/1.6/julia-1.6.0-rc3-musl-x86_64.tar.gz" :
                          "https://julialang-s3.julialang.org/bin/musl/x64/1.5/julia-1.5.4-musl-x86_64.tar.gz";
                }
                else if (PlatformHelper.Is(Platform.Bits64))
                {
                    url = beta ?
                          "https://julialang-s3.julialang.org/bin/linux/x64/1.6/julia-1.6.0-rc3-linux-x86_64.tar.gz" :
                          "https://julialang-s3.julialang.org/bin/linux/x64/1.5/julia-1.5.4-linux-x86_64.tar.gz";
                }
                else
                {
                    url = beta ?
                          "https://julialang-s3.julialang.org/bin/linux/x86/1.6/julia-1.6.0-rc3-linux-i686.tar.gz" :
                          "https://julialang-s3.julialang.org/bin/linux/x86/1.5/julia-1.5.4-linux-i686.tar.gz";
                }

                try {
                    yield return(Status($"Downloading {url}", false, "download", false));

                    using (FileStream tarStream = File.Open(tarPath, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete))
                        yield return(Download(url, 0, tarStream));

                    yield return(Status("Extracting Julia", false, "download", false));

                    yield return(Status("", false, "download", false));

                    using (Process process = ProcessHelper.Wrap("tar", $"-xvf \"{tarPath}\" -C \"{root}\"")) {
                        process.Start();
                        for (string line; (line = process.StandardOutput.ReadLine()) != null;)
                        {
                            yield return(Status(line, false, "download", true));
                        }
                        process.WaitForExit();
                        if (process.ExitCode != 0)
                        {
                            throw new Exception("tar encountered a fatal error:\n" + process.StandardError.ReadToEnd());
                        }
                        yield return(Status("Julia archive extracted", false, "download", true));
                    }

                    yield return(Status("Moving Julia", false, "download", false));

                    Directory.Move(Path.Combine(root, beta ? "julia-1.6.0-rc3" : "julia-1.5.4"), julia);
                } finally {
                    if (File.Exists(tarPath))
                    {
                        File.Delete(tarPath);
                    }
                }

                string launcher = Path.Combine(root, "launch-local-julia.sh");
                if (File.Exists(launcher))
                {
                    File.Delete(launcher);
                }
                File.WriteAllText(launcher, @"
#!/bin/sh
ROOTDIR=$(dirname ""$0"")
export JULIA_DEPOT_PATH=""${ROOTDIR}/julia-depot""
if [ ! -z ""${XDG_CONFIG_HOME}"" ]; then
    export AHORN_GLOBALENV=""${XDG_CONFIG_HOME}/Ahorn/env""
else
    export AHORN_GLOBALENV=""${HOME}/.config/Ahorn/env""
fi
export AHORN_ENV=""${ROOTDIR}/ahorn-env""
""${ROOTDIR}/julia/bin/julia"" $@
"
                                  .TrimStart().Replace("\r\n", "\n")
                                  );

                ProcessHelper.Read("chmod", $"a+x \"{launcher}\"", out _);
            }
            else if (PlatformHelper.Is(Platform.MacOS))
            {
                string dmgPath = Path.Combine(tmp, "juliadownload.dmg");
                if (File.Exists(dmgPath))
                {
                    File.Delete(dmgPath);
                }

                string mount = Path.Combine(tmp, "juliamount");
                if (Directory.Exists(mount))
                {
                    Directory.Delete(mount);
                }

                string url = beta ?
                             "https://julialang-s3.julialang.org/bin/mac/x64/1.6/julia-1.6.0-rc3-mac64.dmg" :
                             "https://julialang-s3.julialang.org/bin/mac/x64/1.5/julia-1.5.4-mac64.dmg";

                bool mounted = false;

                try {
                    yield return(Status($"Downloading {url}", false, "download", false));

                    using (FileStream dmgStream = File.Open(dmgPath, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete))
                        yield return(Download(url, 0, dmgStream));

                    yield return(Status("Mounting Julia", false, "download", false));

                    using (Process process = ProcessHelper.Wrap("hdiutil", $"attach -mountpoint \"{mount}\" \"{dmgPath}\"")) {
                        process.Start();
                        for (string line; (line = process.StandardOutput.ReadLine()) != null;)
                        {
                            yield return(Status(line, false, "download", false));
                        }
                        process.WaitForExit();
                        if (process.ExitCode != 0)
                        {
                            throw new Exception("hdiutil attach encountered a fatal error:\n" + process.StandardError.ReadToEnd());
                        }
                    }
                    mounted = true;

                    yield return(Status("Copying Julia", false, "download", false));

                    yield return(Status("", false, "download", false));

                    using (Process process = ProcessHelper.Wrap("cp", $"-rvf \"{Path.Combine(mount, beta ? "Julia-1.6.app" : "Julia-1.5.app", "Contents", "Resources", "julia")}\" \"{julia}\"")) {
                        process.Start();
                        for (string line; (line = process.StandardOutput.ReadLine()) != null;)
                        {
                            yield return(Status(line, false, "download", true));
                        }
                        process.WaitForExit();
                        if (process.ExitCode != 0)
                        {
                            throw new Exception("cp encountered a fatal error:\n" + process.StandardError.ReadToEnd());
                        }
                        yield return(Status("Julia copied", false, "download", true));
                    }

                    yield return(Status("Unmounting Julia", false, "download", false));

                    using (Process process = ProcessHelper.Wrap("hdiutil", $"detach \"{mount}\"")) {
                        process.Start();
                        for (string line; (line = process.StandardOutput.ReadLine()) != null;)
                        {
                            yield return(Status(line, false, "download", false));
                        }
                        process.WaitForExit();
                        if (process.ExitCode != 0)
                        {
                            throw new Exception("hdiutil detach encountered a fatal error:\n" + process.StandardError.ReadToEnd());
                        }
                    }
                    mounted = false;
                } finally {
                    if (mounted)
                    {
                        try {
                            using (Process process = ProcessHelper.Wrap("hdiutil", $"detach \"{mount}\"")) {
                                process.Start();
                                process.WaitForExit();
                                if (process.ExitCode != 0)
                                {
                                    throw new Exception("hdiutil detach encountered a fatal error:\n" + process.StandardError.ReadToEnd());
                                }
                            }
                        } catch (Exception e) {
                            Console.Error.WriteLine("Error unmounting Julia dmg in installer finally clause");
                            Console.Error.WriteLine(e);
                        }
                    }

                    if (File.Exists(dmgPath))
                    {
                        File.Delete(dmgPath);
                    }

                    if (Directory.Exists(mount))
                    {
                        Directory.Delete(mount);
                    }
                }

                string launcher = Path.Combine(root, "launch-local-julia.sh");
                if (File.Exists(launcher))
                {
                    File.Delete(launcher);
                }
                File.WriteAllText(launcher, @"
#!/bin/sh
ROOTDIR=$(dirname ""$0"")
export JULIA_DEPOT_PATH=""${ROOTDIR}/julia-depot""
if [ ! -z ""${XDG_CONFIG_HOME}"" ]; then
    export AHORN_GLOBALENV=""${XDG_CONFIG_HOME}/Ahorn/env""
else
    export AHORN_GLOBALENV=""${HOME}/.config/Ahorn/env""
fi
export AHORN_ENV=""${ROOTDIR}/ahorn-env""
""${ROOTDIR}/julia/bin/julia"" $@
"
                                  .TrimStart().Replace("\r\n", "\n")
                                  );

                ProcessHelper.Read("chmod", $"a+x \"{launcher}\"", out _);
            }
            else
            {
                throw new PlatformNotSupportedException($"Unsupported platform: {PlatformHelper.Current}");
            }
        }
Example #2
0
        public override IEnumerator Run()
        {
            yield return(Status("Preparing installation of Ahorn-VHD", false, "", false));

            if (!PlatformHelper.Is(Platform.Windows | Platform.Bits64))
            {
                yield return(Status("Unsupported platform.", 1f, "error", false));

                throw new PlatformNotSupportedException($"Platform not supported: {PlatformHelper.Current}");
            }

            string vhd = AhornHelper.VHDPath;

            if (File.Exists(vhd))
            {
                yield return(Status("Ahorn-VHD already exists - please delete it before reinstalling.", 1f, "error", false));

                throw new Exception("Ahorn-VHD already exists.");
            }

            string archive = vhd + ".7z";
            bool   tmpPerm = File.Exists(archive);

            try {
                if (tmpPerm)
                {
                    yield return(Status($"{Path.GetFileName(archive)} already exists - reusing and preserving", false, "", false));
                }
                else
                {
                    const string url = "https://0x0ade.ga/ahornvhd/files/ahornvhd.7z";
                    yield return(Status($"Downloading {url} to {archive}", false, "download", false));

                    string tmp = archive + ".part";
                    if (File.Exists(tmp))
                    {
                        File.Delete(tmp);
                    }
                    using (FileStream stream = File.Open(tmp, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
                        yield return(Download(url, 0, stream));

                    File.Move(tmp, archive);
                }

                string sevenzip = Path.Combine(Program.RootDirectory, "7zr.exe");

                if (!File.Exists(sevenzip))
                {
                    const string url = "https://raw.githubusercontent.com/EverestAPI/Olympus/main/lib-windows/7zr.exe";
                    yield return(Status($"Couldn't find 7zr.exe, downloading from {url}", false, "download", false));

                    using (FileStream stream = File.Open(sevenzip, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
                        yield return(Download(url, 0, stream));
                }

                yield return(Status("Extracting ahornvhd.7z", false, "download", false));

                using (Process process = ProcessHelper.Wrap(sevenzip, $"x \"{archive}\" \"-o{Path.GetDirectoryName(vhd)}\" {Path.GetFileName(vhd)} -bb3")) {
                    process.Start();
                    for (string line; (line = process.StandardOutput.ReadLine()) != null;)
                    {
                        yield return(Status(line, false, "download", false));
                    }
                    process.WaitForExit();
                    if (process.ExitCode != 0)
                    {
                        throw new Exception("7zr encountered a fatal error:\n" + process.StandardError.ReadToEnd());
                    }
                    if (!File.Exists(vhd))
                    {
                        throw new Exception($"File not extracted: {vhd}");
                    }
                    yield return(Status("ahornvhd.7z extracted", false, "download", false));
                }
            } finally {
                if (!tmpPerm && File.Exists(archive))
                {
                    File.Delete(archive);
                }
            }

            yield return(Cmds.Get <CmdAhornMountAhornVHD>().Run());

            yield return(Cmds.Get <CmdAhornInstallAhorn>().Run());
        }