<commit_before>﻿// This file is part of Mystery Dungeon eXtended.

// Copyright (C) 2015 Pikablu

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.

// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

using Microsoft.Win32;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace RaileyBuilder
{
    class ServerInstaller
    {
        private static readonly string[] ProgramFilesDirectories = new string[] {
            "Program Files (x86)",
            "Program Files"
        };

        private static readonly string GitSubdirectory = @"Git\bin\git.exe";
        private static readonly string MySQLSubdirectory = @"MySQL\MySQL Server 5.6\bin\mysql.exe";

        private static readonly string ServerURI = @"https://github.com/pmdcp/Server";

        public string ServerFolder { get; private set; }

        readonly string GitPath;
        readonly string MySQLPath;

        Reporter reporter;

        public ServerInstaller(string serverFolder, Reporter reporter)
        {
            this.ServerFolder = serverFolder;

            this.reporter = reporter;

            GitPath = FindAmbiguousExecutable(GitSubdirectory);
            MySQLPath = FindAmbiguousExecutable(MySQLSubdirectory);
        }

        private string FindAmbiguousExecutable(string subFolder)
        {
            DriveInfo[] drives = DriveInfo.GetDrives();
            foreach (DriveInfo drive in drives)
            {
                foreach (string programFilesDirectory in ProgramFilesDirectories)
                {
                    string testPath = Path.Combine(drive.Name, programFilesDirectory, subFolder);
                    if (File.Exists(testPath))
                    {
                        return testPath;
                    }
                }
            }

            throw new FileNotFoundException("Unable to find: " + subFolder);
        }

        public bool IsInstallDirectoryEmpty()
        {
            if (Directory.Exists(ServerFolder) == false)
            {
                return true;
            }

            if (Directory.EnumerateFiles(ServerFolder).FirstOrDefault() == null && Directory.EnumerateDirectories(ServerFolder).FirstOrDefault() == null)
            {
                return true;
            }

            return false;
        }

        private async Task<int> ExecuteAsync(string executable, string arguments)
        {
            ProcessStartInfo startInfo = new ProcessStartInfo(executable, arguments);
            startInfo.UseShellExecute = false;
            startInfo.WorkingDirectory = ServerFolder;
            startInfo.CreateNoWindow = true;
            startInfo.RedirectStandardOutput = true;
            Process exec = Process.Start(startInfo);
            string output = await exec.StandardOutput.ReadToEndAsync();

            reporter.WriteProgramOutputToLog(executable, arguments, output);

            return exec.ExitCode;
        }

        private string ReadRegistryKey(string subKeyName, string keyName)
        {
            using (RegistryKey subKey = Registry.LocalMachine.OpenSubKey(subKeyName))
            {
                if (subKey != null)
                {
                    Object o = subKey.GetValue(keyName);
                    if (o != null)
                    {
                        return o as string;
                    }
                }
            }

            return null;
        }

        public async Task UpdateServerAsync()
        {
            reporter.WriteToLog("Checking existing server installation...");
            reporter.UpdateProgress("Checking existing server installation...", 0);

            if (IsInstallDirectoryEmpty())
            {
                reporter.ReportError("There is no server here! Install one first.");
                return;
            }

            reporter.WriteToLog("Pulling latest changes...");
            reporter.UpdateProgress("Pulling latest changes...", 15);

            await ExecuteAsync(GitPath, "pull upstream --recurse-submodules");

            reporter.WriteToLog("Download complete!");

            reporter.UpdateProgress("Building server...", 70);
            bool buildResult = await PerformBuildAsync();
            if (!buildResult)
            {
                return;
            }

            reporter.UpdateProgress("Server update has been completed!", 100);
        }

        public async Task InstallServerAsync()
        {
            reporter.UpdateProgress("Starting server installation", 0);
            reporter.WriteToLog("Starting server installation");
            reporter.WriteToLog("MySQL Path: " + MySQLPath);
            reporter.WriteToLog("Git Path: " + GitPath);
            reporter.WriteToLog("Checking input data...");

            if (!IsInstallDirectoryEmpty())
            {
                reporter.ReportError("Installation directory is not empty. Please select an empty directory and try again!");
                return;
            }

            if (Directory.Exists(ServerFolder) == false)
            {
                Directory.CreateDirectory(ServerFolder);
            }

            reporter.WriteToLog("Preparing to download latest server files...");
            reporter.UpdateProgress("Downloading latest server files...", 10);

            if (!File.Exists(GitPath))
            {
                reporter.ReportError("Unable to find Git client. Make sure you've installed GitHub for Desktop!");
                return;
            }

            await ExecuteAsync(GitPath, string.Format("clone --recursive {0} {1}", "\"" + ServerURI + "\"", "\"" + ServerFolder + "\""));

            reporter.WriteToLog("Download complete!");

            reporter.UpdateProgress("Building server (Release)", 30);
            bool buildResult = await PerformBuildAsync();
            if (!buildResult)
            {
                return;
            }<commit_msg>Fixed git not found error message, added check for mysql<commit_after>﻿// This file is part of Mystery Dungeon eXtended.

// Copyright (C) 2015 Pikablu

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.

// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

using Microsoft.Win32;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace RaileyBuilder
{
    class ServerInstaller
    {
        private static readonly string[] ProgramFilesDirectories = new string[] {
            "Program Files (x86)",
            "Program Files"
        };

        private static readonly string GitSubdirectory = @"Git\bin\git.exe";
        private static readonly string MySQLSubdirectory = @"MySQL\MySQL Server 5.6\bin\mysql.exe";

        private static readonly string ServerURI = @"https://github.com/pmdcp/Server";

        public string ServerFolder { get; private set; }

        readonly string GitPath;
        readonly string MySQLPath;

        Reporter reporter;

        public ServerInstaller(string serverFolder, Reporter reporter)
        {
            this.ServerFolder = serverFolder;

            this.reporter = reporter;

            GitPath = FindAmbiguousExecutable(GitSubdirectory);
            MySQLPath = FindAmbiguousExecutable(MySQLSubdirectory);
        }

        private string FindAmbiguousExecutable(string subFolder)
        {
            DriveInfo[] drives = DriveInfo.GetDrives();
            foreach (DriveInfo drive in drives)
            {
                foreach (string programFilesDirectory in ProgramFilesDirectories)
                {
                    string testPath = Path.Combine(drive.Name, programFilesDirectory, subFolder);
                    if (File.Exists(testPath))
                    {
                        return testPath;
                    }
                }
            }

            throw new FileNotFoundException("Unable to find: " + subFolder);
        }

        public bool IsInstallDirectoryEmpty()
        {
            if (Directory.Exists(ServerFolder) == false)
            {
                return true;
            }

            if (Directory.EnumerateFiles(ServerFolder).FirstOrDefault() == null && Directory.EnumerateDirectories(ServerFolder).FirstOrDefault() == null)
            {
                return true;
            }

            return false;
        }

        private async Task<int> ExecuteAsync(string executable, string arguments)
        {
            ProcessStartInfo startInfo = new ProcessStartInfo(executable, arguments);
            startInfo.UseShellExecute = false;
            startInfo.WorkingDirectory = ServerFolder;
            startInfo.CreateNoWindow = true;
            startInfo.RedirectStandardOutput = true;
            Process exec = Process.Start(startInfo);
            string output = await exec.StandardOutput.ReadToEndAsync();

            reporter.WriteProgramOutputToLog(executable, arguments, output);

            return exec.ExitCode;
        }

        private string ReadRegistryKey(string subKeyName, string keyName)
        {
            using (RegistryKey subKey = Registry.LocalMachine.OpenSubKey(subKeyName))
            {
                if (subKey != null)
                {
                    Object o = subKey.GetValue(keyName);
                    if (o != null)
                    {
                        return o as string;
                    }
                }
            }

            return null;
        }

        public async Task UpdateServerAsync()
        {
            reporter.WriteToLog("Checking existing server installation...");
            reporter.UpdateProgress("Checking existing server installation...", 0);

            if (IsInstallDirectoryEmpty())
            {
                reporter.ReportError("There is no server here! Install one first.");
                return;
            }

            reporter.WriteToLog("Pulling latest changes...");
            reporter.UpdateProgress("Pulling latest changes...", 15);

            await ExecuteAsync(GitPath, "pull upstream --recurse-submodules");

            reporter.WriteToLog("Download complete!");

            reporter.UpdateProgress("Building server...", 70);
            bool buildResult = await PerformBuildAsync();
            if (!buildResult)
            {
                return;
            }

            reporter.UpdateProgress("Server update has been completed!", 100);
        }

        public async Task InstallServerAsync()
        {
            reporter.UpdateProgress("Starting server installation", 0);
            reporter.WriteToLog("Starting server installation");
            reporter.WriteToLog("MySQL Path: " + MySQLPath);
            reporter.WriteToLog("Git Path: " + GitPath);
            reporter.WriteToLog("Checking input data...");

            if (!File.Exists(GitPath))
            {
                reporter.ReportError("Unable to find Git client. Make sure you've installed msysgit!");
                return;
            }

            if (!File.Exists(MySQLPath))
            {
                reporter.ReportError("Unable to find MySQL. Make sure you've installed MySQL!");
                return;
            }

            if (!IsInstallDirectoryEmpty())
            {
                reporter.ReportError("Installation directory is not empty. Please select an empty directory and try again!");
                return;
            }

            if (Directory.Exists(ServerFolder) == false)
            {
                Directory.CreateDirectory(ServerFolder);
            }

            reporter.WriteToLog("Preparing to download latest server files...");
            reporter.UpdateProgress("Downloading latest server files...", 10);

            await ExecuteAsync(GitPath, string.Format("clone --recursive {0} {1}", "\"" + ServerURI + "\"", "\"" + ServerFolder + "\""));

            reporter.WriteToLog("Download complete!");

            reporter.UpdateProgress("Building server (Release)", 30);
            bool buildResult = await PerformBuildAsync();
            if (!buildResult)
            {
                return;
            }
{'fraction_non_alphanumeric': 0.08717263891980118, 'fraction_numerical': 0.003857852956450775, 'mean_word_length': 1.8976784178847808, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1985149', 'n_tokens_mistral': 3276, 'n_tokens_neox': 3081, 'n_words': 913}