<commit_before>﻿using Quinstance;
using Quinstance.Quin3d;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Text;

namespace Quinstance
{
    public class Program
    {
        static bool cleanup = false,
                    keep = false;

        static char sep = Path.DirectorySeparatorChar;

        static string exe_name = Assembly.GetEntryAssembly().GetName().Name,
                      tmp_dir = exe_name + "_temp",
                      tmp_path = Path.GetTempPath() + tmp_dir + sep,
                      tld;

        static Dictionary<string, List<string>> deletables = new Dictionary<string, List<string>>() {
            { "dirs", new List<string>() }, { "files", new List<string>() }
        };

        static void Main(string[] args)
        {
            List<string>
                paths = new List<string>(),
                fgds = new List<string>();

            try {
                ParseArgs(ref args, ref paths, ref fgds);
            }
            catch (ArgumentException e) {
                Console.WriteLine(e.Message);
                Console.WriteLine();
                PrintUsage();
#if DEBUG
                Console.Write("Press any key to exit: ");
                Console.ReadKey();
#endif
                return;
            }
            catch (InvalidDataException e) {
                Console.WriteLine(e.Message);
                Console.WriteLine();
#if DEBUG
                Console.Write("Press any key to exit: ");
                Console.ReadKey();
#endif
                return;
            }

            string map_in = Path.GetFullPath(paths.First());
            tld = Path.GetDirectoryName(map_in);

            if (cleanup) {
                CleanUp(map_in);
                return;
            }

            // Checking for directory write access ahead of time like this is
            // hardly foolproof, since that access could change by the time we
            // try to write the real files, but it's better than nothing at all.
            try {
                Directory.CreateDirectory(tmp_path + sep);
                File.Open(tmp_path + sep + exe_name + "_access_check", FileMode.CreateNew).Close();
                File.Delete(tmp_path + sep + exe_name + "_access_check");
            }
            catch (UnauthorizedAccessException) {
                Console.WriteLine("Couldn't access temp directory " + tmp_path + "! Please use -t to specify another.");
                PrintUsage();
                return;
            }
            catch (IOException) {
                Console.WriteLine("Couldn't access temp directory " + tmp_path + "! Please use -t to specify another.");
                PrintUsage();
                return;
            }
            deletables["dirs"].Add(tmp_path + sep);

            string map_preprocessed = tmp_path + sep + Path.GetFileNameWithoutExtension(map_in) + ".vmf";

            Console.Write("Preprocessing FGDs...");
            foreach (string fgd in fgds)
                PreprocessFgd(fgd);
            Console.WriteLine("done!");

            Console.Write("Preprocessing map and instances...");
            try {
                PreprocessMap(map_in);
            }
            catch (InvalidDataException e) {
                Console.Write("error: ");
                Console.WriteLine(e.Message);
                return;
            }
            Console.WriteLine("done!");

            CollapseInstances(map_preprocessed, fgds.Select(x => tmp_path + sep + Path.GetFileName(x)).ToList());

            Console.Write("Postprocessing map...");
            PostprocessMap(map_preprocessed.Replace(".vmf", ".temp.vmf"));
            Console.WriteLine("done!");

            string map_postprocessed = map_preprocessed.Replace(".vmf", ".temp.map");

            // To avoid unnecessary work above when writing map_postprocessed,
            // we only spit out users' requested output during the final copy.
            string map_final;
            if (paths.Count == 2)
                map_final = paths[1];
            else
                map_final = tld + sep + Path.GetFileName(map_postprocessed);

            // Setting the working directory to the location of the input map
            // means that whether paths[1] is relative or absolute, users will
            // find the output file where they expect to.
            Directory.SetCurrentDirectory(tld + sep);
            if (File.Exists(map_final))
                File.Delete(map_final);
            File.Copy(map_postprocessed, map_final);
            deletables["files"].Add(map_postprocessed);

            if (!keep) {
                Console.Write("Deleting temp files...");
                foreach (string file in deletables["files"])
                    File.Delete(file);

                // We can't delete a directory until its subdirectories are gone,
                // but we know everything in this list is an absolute path, which
                // means sorting by length and reversing the list is enough.
                deletables["dirs"].Sort();
                deletables["dirs"].Reverse();

                bool del_success = true;
                foreach (string dir in deletables["dirs"]) {
                    try {
                        Directory.Delete(dir);
                    }
                    catch (IOException e) {
                        del_success = false;
                        Console.Write("\nError deleting directory " + tmp_path + ": ");
                        Console.WriteLine(e.Message);
                    }
                }
                if (del_success)
                    Console.WriteLine("done!");
            } else {
                Console.WriteLine("Keeping temp files in " + tmp_path + '!');
            }
#if DEBUG
            Console.Write("Press any key to exit:");
            Console.ReadKey();
#endif
        }

        static void CleanUp(string map_in)
        {
            string path = Path.GetDirectoryName(map_in),
                   temp = path + sep + Path.GetFileNameWithoutExtension(map_in) + ".temp",
                   temp_map = temp + ".map",
                   temp_bsp = temp + ".bsp",
                   temp_lin = temp + ".lin",
                   temp_prt = temp + ".prt",
                   temp_pts = temp + ".pts";

            Console.Write("Cleaning up...");

            if (File.Exists(temp_map))
                File.Delete(temp_map);
<commit_msg>Check for attached debugger when exiting<commit_after>﻿using Quinstance;
using Quinstance.Quin3d;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Text;

namespace Quinstance
{
    public class Program
    {
        static bool cleanup = false,
                    keep = false;

        static char sep = Path.DirectorySeparatorChar;

        static string exe_name = Assembly.GetEntryAssembly().GetName().Name,
                      tmp_dir = exe_name + "_temp",
                      tmp_path = Path.GetTempPath() + tmp_dir + sep,
                      tld;

        static Dictionary<string, List<string>> deletables = new Dictionary<string, List<string>>() {
            { "dirs", new List<string>() }, { "files", new List<string>() }
        };

        static void Main(string[] args)
        {
            List<string>
                paths = new List<string>(),
                fgds = new List<string>();

            try {
                ParseArgs(ref args, ref paths, ref fgds);
            }
            catch (ArgumentException e) {
                Console.WriteLine(e.Message);
                Console.WriteLine();
                PrintUsage();

                if (System.Diagnostics.Debugger.IsAttached)
                {
                    Console.Write("Press any key to exit: ");
                    Console.ReadKey();
                }

                return;
            }
            catch (InvalidDataException e) {
                Console.WriteLine(e.Message);
                Console.WriteLine();

                if (System.Diagnostics.Debugger.IsAttached)
                {
                    Console.Write("Press any key to exit: ");
                    Console.ReadKey();
                }

                return;
            }

            string map_in = Path.GetFullPath(paths.First());
            tld = Path.GetDirectoryName(map_in);

            if (cleanup) {
                CleanUp(map_in);
                return;
            }

            // Checking for directory write access ahead of time like this is
            // hardly foolproof, since that access could change by the time we
            // try to write the real files, but it's better than nothing at all.
            try {
                Directory.CreateDirectory(tmp_path + sep);
                File.Open(tmp_path + sep + exe_name + "_access_check", FileMode.CreateNew).Close();
                File.Delete(tmp_path + sep + exe_name + "_access_check");
            }
            catch (UnauthorizedAccessException) {
                Console.WriteLine("Couldn't access temp directory " + tmp_path + "! Please use -t to specify another.");
                PrintUsage();
                return;
            }
            catch (IOException) {
                Console.WriteLine("Couldn't access temp directory " + tmp_path + "! Please use -t to specify another.");
                PrintUsage();
                return;
            }
            deletables["dirs"].Add(tmp_path + sep);

            string map_preprocessed = tmp_path + sep + Path.GetFileNameWithoutExtension(map_in) + ".vmf";

            Console.Write("Preprocessing FGDs...");
            foreach (string fgd in fgds)
                PreprocessFgd(fgd);
            Console.WriteLine("done!");

            Console.Write("Preprocessing map and instances...");
            try {
                PreprocessMap(map_in);
            }
            catch (InvalidDataException e) {
                Console.Write("error: ");
                Console.WriteLine(e.Message);
                return;
            }
            Console.WriteLine("done!");

            CollapseInstances(map_preprocessed, fgds.Select(x => tmp_path + sep + Path.GetFileName(x)).ToList());

            Console.Write("Postprocessing map...");
            PostprocessMap(map_preprocessed.Replace(".vmf", ".temp.vmf"));
            Console.WriteLine("done!");

            string map_postprocessed = map_preprocessed.Replace(".vmf", ".temp.map");

            // To avoid unnecessary work above when writing map_postprocessed,
            // we only spit out users' requested output during the final copy.
            string map_final;
            if (paths.Count == 2)
                map_final = paths[1];
            else
                map_final = tld + sep + Path.GetFileName(map_postprocessed);

            // Setting the working directory to the location of the input map
            // means that whether paths[1] is relative or absolute, users will
            // find the output file where they expect to.
            Directory.SetCurrentDirectory(tld + sep);
            if (File.Exists(map_final))
                File.Delete(map_final);
            File.Copy(map_postprocessed, map_final);
            deletables["files"].Add(map_postprocessed);

            if (!keep) {
                Console.Write("Deleting temp files...");
                foreach (string file in deletables["files"])
                    File.Delete(file);

                // We can't delete a directory until its subdirectories are gone,
                // but we know everything in this list is an absolute path, which
                // means sorting by length and reversing the list is enough.
                deletables["dirs"].Sort();
                deletables["dirs"].Reverse();

                bool del_success = true;
                foreach (string dir in deletables["dirs"]) {
                    try {
                        Directory.Delete(dir);
                    }
                    catch (IOException e) {
                        del_success = false;
                        Console.Write("\nError deleting directory " + tmp_path + ": ");
                        Console.WriteLine(e.Message);
                    }
                }
                if (del_success)
                    Console.WriteLine("done!");
            } else {
                Console.WriteLine("Keeping temp files in " + tmp_path + '!');
            }

            if (System.Diagnostics.Debugger.IsAttached)
            {
                Console.Write("Press any key to exit: ");
                Console.ReadKey();
            }
        }

        static void CleanUp(string map_in)
        {
            string path = Path.GetDirectoryName(map_in),
                   temp = path + sep + Path.GetFileNameWithoutExtension(map_in) + ".temp",
                   temp_map = temp + ".map",
                   temp_bsp = temp + ".bsp",
                   temp_lin = temp + ".lin",
                   temp_prt = temp + ".prt",
                   temp_pts = temp + ".pts";

            Console.Write("Cleaning up...");

            if (File.Exists(temp_map))
                File.Delete(temp_map);

{'fraction_non_alphanumeric': 0.10093861740166865, 'fraction_numerical': 0.0005959475566150178, 'mean_word_length': 1.4714653902798234, 'pattern_counts': {'":': 2, '<': 21, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3266754', 'n_tokens_mistral': 3390, 'n_tokens_neox': 3169, 'n_words': 846}