[RombaSharp/] Space, the final frontier

This commit is contained in:
Matt Nadareski
2019-02-08 20:31:07 -08:00
parent dde93eec67
commit eee15bbc32
4 changed files with 2338 additions and 2338 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -21,362 +21,362 @@ using StreamWriter = System.IO.StreamWriter;
namespace RombaSharp namespace RombaSharp
{ {
public partial class RombaSharp public partial class RombaSharp
{ {
#region Helper methods #region Helper methods
/// <summary> /// <summary>
/// Gets all valid DATs that match in the DAT root /// Gets all valid DATs that match in the DAT root
/// </summary> /// </summary>
/// <param name="inputs">List of input strings to check for, presumably file names</param> /// <param name="inputs">List of input strings to check for, presumably file names</param>
/// <returns>Dictionary of hash/full path for each of the valid DATs</returns> /// <returns>Dictionary of hash/full path for each of the valid DATs</returns>
private static Dictionary<string, string> GetValidDats(List<string> inputs) private static Dictionary<string, string> GetValidDats(List<string> inputs)
{ {
// Get a dictionary of filenames that actually exist in the DATRoot, logging which ones are not // Get a dictionary of filenames that actually exist in the DATRoot, logging which ones are not
List<string> datRootDats = Directory.EnumerateFiles(_dats, "*", SearchOption.AllDirectories).ToList(); List<string> datRootDats = Directory.EnumerateFiles(_dats, "*", SearchOption.AllDirectories).ToList();
List<string> lowerCaseDats = datRootDats.ConvertAll(i => Path.GetFileName(i).ToLowerInvariant()); List<string> lowerCaseDats = datRootDats.ConvertAll(i => Path.GetFileName(i).ToLowerInvariant());
Dictionary<string, string> foundDats = new Dictionary<string, string>(); Dictionary<string, string> foundDats = new Dictionary<string, string>();
foreach (string input in inputs) foreach (string input in inputs)
{ {
if (lowerCaseDats.Contains(input.ToLowerInvariant())) if (lowerCaseDats.Contains(input.ToLowerInvariant()))
{ {
string fullpath = Path.GetFullPath(datRootDats[lowerCaseDats.IndexOf(input.ToLowerInvariant())]); string fullpath = Path.GetFullPath(datRootDats[lowerCaseDats.IndexOf(input.ToLowerInvariant())]);
string sha1 = Utilities.ByteArrayToString(Utilities.GetFileInfo(fullpath).SHA1); string sha1 = Utilities.ByteArrayToString(Utilities.GetFileInfo(fullpath).SHA1);
foundDats.Add(sha1, fullpath); foundDats.Add(sha1, fullpath);
} }
else else
{ {
Globals.Logger.Warning("The file '{0}' could not be found in the DAT root", input); Globals.Logger.Warning("The file '{0}' could not be found in the DAT root", input);
} }
} }
return foundDats; return foundDats;
} }
/// <summary> /// <summary>
/// Initialize the Romba application from XML config /// Initialize the Romba application from XML config
/// </summary> /// </summary>
private static void InitializeConfiguration() private static void InitializeConfiguration()
{ {
// Get default values if they're not written // Get default values if they're not written
int workers = 4, int workers = 4,
verbosity = 1, verbosity = 1,
cores = 4, cores = 4,
port = 4003; port = 4003;
string logdir = "logs", string logdir = "logs",
tmpdir = "tmp", tmpdir = "tmp",
webdir = "web", webdir = "web",
baddir = "bad", baddir = "bad",
dats = "dats", dats = "dats",
db = "db", db = "db",
connectionString = ""; connectionString = "";
Dictionary<string, Tuple<long, bool>> depots = new Dictionary<string, Tuple<long, bool>>(); Dictionary<string, Tuple<long, bool>> depots = new Dictionary<string, Tuple<long, bool>>();
// Get the XML text reader for the configuration file, if possible // Get the XML text reader for the configuration file, if possible
XmlReader xtr = Utilities.GetXmlTextReader(_config); XmlReader xtr = Utilities.GetXmlTextReader(_config);
// Now parse the XML file for settings // Now parse the XML file for settings
if (xtr != null) if (xtr != null)
{ {
xtr.MoveToContent(); xtr.MoveToContent();
while (!xtr.EOF) while (!xtr.EOF)
{ {
// We only want elements // We only want elements
if (xtr.NodeType != XmlNodeType.Element) if (xtr.NodeType != XmlNodeType.Element)
{ {
xtr.Read(); xtr.Read();
continue; continue;
} }
switch (xtr.Name) switch (xtr.Name)
{ {
case "workers": case "workers":
workers = xtr.ReadElementContentAsInt(); workers = xtr.ReadElementContentAsInt();
break; break;
case "logdir": case "logdir":
logdir = xtr.ReadElementContentAsString(); logdir = xtr.ReadElementContentAsString();
break; break;
case "tmpdir": case "tmpdir":
tmpdir = xtr.ReadElementContentAsString(); tmpdir = xtr.ReadElementContentAsString();
break; break;
case "webdir": case "webdir":
webdir = xtr.ReadElementContentAsString(); webdir = xtr.ReadElementContentAsString();
break; break;
case "baddir": case "baddir":
baddir = xtr.ReadElementContentAsString(); baddir = xtr.ReadElementContentAsString();
break; break;
case "verbosity": case "verbosity":
verbosity = xtr.ReadElementContentAsInt(); verbosity = xtr.ReadElementContentAsInt();
break; break;
case "cores": case "cores":
cores = xtr.ReadElementContentAsInt(); cores = xtr.ReadElementContentAsInt();
break; break;
case "dats": case "dats":
dats = xtr.ReadElementContentAsString(); dats = xtr.ReadElementContentAsString();
break; break;
case "db": case "db":
db = xtr.ReadElementContentAsString(); db = xtr.ReadElementContentAsString();
break; break;
case "depot": case "depot":
XmlReader subreader = xtr.ReadSubtree(); XmlReader subreader = xtr.ReadSubtree();
if (subreader != null) if (subreader != null)
{ {
string root = ""; string root = "";
long maxsize = -1; long maxsize = -1;
bool online = true; bool online = true;
while (!subreader.EOF) while (!subreader.EOF)
{ {
// We only want elements // We only want elements
if (subreader.NodeType != XmlNodeType.Element) if (subreader.NodeType != XmlNodeType.Element)
{ {
subreader.Read(); subreader.Read();
continue; continue;
} }
switch (subreader.Name) switch (subreader.Name)
{ {
case "root": case "root":
root = subreader.ReadElementContentAsString(); root = subreader.ReadElementContentAsString();
break; break;
case "maxsize": case "maxsize":
maxsize = subreader.ReadElementContentAsLong(); maxsize = subreader.ReadElementContentAsLong();
break; break;
case "online": case "online":
online = subreader.ReadElementContentAsBoolean(); online = subreader.ReadElementContentAsBoolean();
break; break;
default: default:
subreader.Read(); subreader.Read();
break; break;
} }
} }
try try
{ {
depots.Add(root, new Tuple<long, bool>(maxsize, online)); depots.Add(root, new Tuple<long, bool>(maxsize, online));
} }
catch catch
{ {
// Ignore add errors // Ignore add errors
} }
} }
xtr.Skip(); xtr.Skip();
break; break;
case "port": case "port":
port = xtr.ReadElementContentAsInt(); port = xtr.ReadElementContentAsInt();
break; break;
default: default:
xtr.Read(); xtr.Read();
break; break;
} }
} }
} }
// Now validate the values given // Now validate the values given
if (workers < 1) if (workers < 1)
{ {
workers = 1; workers = 1;
} }
if (workers > 8) if (workers > 8)
{ {
workers = 8; workers = 8;
} }
if (!Directory.Exists(logdir)) if (!Directory.Exists(logdir))
{ {
Directory.CreateDirectory(logdir); Directory.CreateDirectory(logdir);
} }
if (!Directory.Exists(tmpdir)) if (!Directory.Exists(tmpdir))
{ {
Directory.CreateDirectory(tmpdir); Directory.CreateDirectory(tmpdir);
} }
if (!Directory.Exists(webdir)) if (!Directory.Exists(webdir))
{ {
Directory.CreateDirectory(webdir); Directory.CreateDirectory(webdir);
} }
if (!Directory.Exists(baddir)) if (!Directory.Exists(baddir))
{ {
Directory.CreateDirectory(baddir); Directory.CreateDirectory(baddir);
} }
if (verbosity < 0) if (verbosity < 0)
{ {
verbosity = 0; verbosity = 0;
} }
if (verbosity > 3) if (verbosity > 3)
{ {
verbosity = 3; verbosity = 3;
} }
if (cores < 1) if (cores < 1)
{ {
cores = 1; cores = 1;
} }
if (cores > 16) if (cores > 16)
{ {
cores = 16; cores = 16;
} }
if (!Directory.Exists(dats)) if (!Directory.Exists(dats))
{ {
Directory.CreateDirectory(dats); Directory.CreateDirectory(dats);
} }
db = Path.GetFileNameWithoutExtension(db) + ".sqlite"; db = Path.GetFileNameWithoutExtension(db) + ".sqlite";
connectionString = "Data Source=" + db + ";Version = 3;"; connectionString = "Data Source=" + db + ";Version = 3;";
foreach (string key in depots.Keys) foreach (string key in depots.Keys)
{ {
if (!Directory.Exists(key)) if (!Directory.Exists(key))
{ {
Directory.CreateDirectory(key); Directory.CreateDirectory(key);
File.CreateText(Path.Combine(key, ".romba_size")); File.CreateText(Path.Combine(key, ".romba_size"));
File.CreateText(Path.Combine(key, ".romba_size.backup")); File.CreateText(Path.Combine(key, ".romba_size.backup"));
} }
else else
{ {
if (!File.Exists(Path.Combine(key, ".romba_size"))) if (!File.Exists(Path.Combine(key, ".romba_size")))
{ {
File.CreateText(Path.Combine(key, ".romba_size")); File.CreateText(Path.Combine(key, ".romba_size"));
} }
if (!File.Exists(Path.Combine(key, ".romba_size.backup"))) if (!File.Exists(Path.Combine(key, ".romba_size.backup")))
{ {
File.CreateText(Path.Combine(key, ".romba_size.backup")); File.CreateText(Path.Combine(key, ".romba_size.backup"));
} }
} }
} }
if (port < 0) if (port < 0)
{ {
port = 0; port = 0;
} }
if (port > 65535) if (port > 65535)
{ {
port = 65535; port = 65535;
} }
// Finally set all of the fields // Finally set all of the fields
Globals.MaxThreads = workers; Globals.MaxThreads = workers;
_logdir = logdir; _logdir = logdir;
_tmpdir = tmpdir; _tmpdir = tmpdir;
_webdir = webdir; _webdir = webdir;
_baddir = baddir; _baddir = baddir;
_verbosity = verbosity; _verbosity = verbosity;
_cores = cores; _cores = cores;
_dats = dats; _dats = dats;
_db = db; _db = db;
_connectionString = connectionString; _connectionString = connectionString;
_depots = depots; _depots = depots;
_port = port; _port = port;
} }
/// <summary> /// <summary>
/// Add a new DAT to the database /// Add a new DAT to the database
/// </summary> /// </summary>
/// <param name="dat">DatFile hash information to add</param> /// <param name="dat">DatFile hash information to add</param>
/// <param name="dbc">Database connection to use</param> /// <param name="dbc">Database connection to use</param>
private static void AddDatToDatabase(Rom dat, SqliteConnection dbc) private static void AddDatToDatabase(Rom dat, SqliteConnection dbc)
{ {
// Get the dat full path // Get the dat full path
string fullpath = Path.Combine(_dats, (dat.MachineName == "dats" ? "" : dat.MachineName), dat.Name); string fullpath = Path.Combine(_dats, (dat.MachineName == "dats" ? "" : dat.MachineName), dat.Name);
// Parse the Dat if possible // Parse the Dat if possible
Globals.Logger.User("Adding from '" + dat.Name + "'"); Globals.Logger.User("Adding from '" + dat.Name + "'");
DatFile tempdat = new DatFile(); DatFile tempdat = new DatFile();
tempdat.Parse(fullpath, 0, 0); tempdat.Parse(fullpath, 0, 0);
// If the Dat wasn't empty, add the information // If the Dat wasn't empty, add the information
SqliteCommand slc = new SqliteCommand(); SqliteCommand slc = new SqliteCommand();
if (tempdat.Count != 0) if (tempdat.Count != 0)
{ {
string crcquery = "INSERT OR IGNORE INTO crc (crc) VALUES"; string crcquery = "INSERT OR IGNORE INTO crc (crc) VALUES";
string md5query = "INSERT OR IGNORE INTO md5 (md5) VALUES"; string md5query = "INSERT OR IGNORE INTO md5 (md5) VALUES";
string sha1query = "INSERT OR IGNORE INTO sha1 (sha1) VALUES"; string sha1query = "INSERT OR IGNORE INTO sha1 (sha1) VALUES";
string crcsha1query = "INSERT OR IGNORE INTO crcsha1 (crc, sha1) VALUES"; string crcsha1query = "INSERT OR IGNORE INTO crcsha1 (crc, sha1) VALUES";
string md5sha1query = "INSERT OR IGNORE INTO md5sha1 (md5, sha1) VALUES"; string md5sha1query = "INSERT OR IGNORE INTO md5sha1 (md5, sha1) VALUES";
// Loop through the parsed entries // Loop through the parsed entries
foreach (string romkey in tempdat.Keys) foreach (string romkey in tempdat.Keys)
{ {
foreach (DatItem datItem in tempdat[romkey]) foreach (DatItem datItem in tempdat[romkey])
{ {
Globals.Logger.Verbose("Checking and adding file '{0}'", datItem.Name); Globals.Logger.Verbose("Checking and adding file '{0}'", datItem.Name);
if (datItem.ItemType == ItemType.Rom) if (datItem.ItemType == ItemType.Rom)
{ {
Rom rom = (Rom)datItem; Rom rom = (Rom)datItem;
if (!String.IsNullOrWhiteSpace(rom.CRC)) if (!String.IsNullOrWhiteSpace(rom.CRC))
{ {
crcquery += " (\"" + rom.CRC + "\"),"; crcquery += " (\"" + rom.CRC + "\"),";
} }
if (!String.IsNullOrWhiteSpace(rom.MD5)) if (!String.IsNullOrWhiteSpace(rom.MD5))
{ {
md5query += " (\"" + rom.MD5 + "\"),"; md5query += " (\"" + rom.MD5 + "\"),";
} }
if (!String.IsNullOrWhiteSpace(rom.SHA1)) if (!String.IsNullOrWhiteSpace(rom.SHA1))
{ {
sha1query += " (\"" + rom.SHA1 + "\"),"; sha1query += " (\"" + rom.SHA1 + "\"),";
if (!String.IsNullOrWhiteSpace(rom.CRC)) if (!String.IsNullOrWhiteSpace(rom.CRC))
{ {
crcsha1query += " (\"" + rom.CRC + "\", \"" + rom.SHA1 + "\"),"; crcsha1query += " (\"" + rom.CRC + "\", \"" + rom.SHA1 + "\"),";
} }
if (!String.IsNullOrWhiteSpace(rom.MD5)) if (!String.IsNullOrWhiteSpace(rom.MD5))
{ {
md5sha1query += " (\"" + rom.MD5 + "\", \"" + rom.SHA1 + "\"),"; md5sha1query += " (\"" + rom.MD5 + "\", \"" + rom.SHA1 + "\"),";
} }
} }
} }
else if (datItem.ItemType == ItemType.Disk) else if (datItem.ItemType == ItemType.Disk)
{ {
Disk disk = (Disk)datItem; Disk disk = (Disk)datItem;
if (!String.IsNullOrWhiteSpace(disk.MD5)) if (!String.IsNullOrWhiteSpace(disk.MD5))
{ {
md5query += " (\"" + disk.MD5 + "\"),"; md5query += " (\"" + disk.MD5 + "\"),";
} }
if (!String.IsNullOrWhiteSpace(disk.SHA1)) if (!String.IsNullOrWhiteSpace(disk.SHA1))
{ {
sha1query += " (\"" + disk.SHA1 + "\"),"; sha1query += " (\"" + disk.SHA1 + "\"),";
if (!String.IsNullOrWhiteSpace(disk.MD5)) if (!String.IsNullOrWhiteSpace(disk.MD5))
{ {
md5sha1query += " (\"" + disk.MD5 + "\", \"" + disk.SHA1 + "\"),"; md5sha1query += " (\"" + disk.MD5 + "\", \"" + disk.SHA1 + "\"),";
} }
} }
} }
} }
} }
// Now run the queries after fixing them // Now run the queries after fixing them
if (crcquery != "INSERT OR IGNORE INTO crc (crc) VALUES") if (crcquery != "INSERT OR IGNORE INTO crc (crc) VALUES")
{ {
slc = new SqliteCommand(crcquery.TrimEnd(','), dbc); slc = new SqliteCommand(crcquery.TrimEnd(','), dbc);
slc.ExecuteNonQuery(); slc.ExecuteNonQuery();
} }
if (md5query != "INSERT OR IGNORE INTO md5 (md5) VALUES") if (md5query != "INSERT OR IGNORE INTO md5 (md5) VALUES")
{ {
slc = new SqliteCommand(md5query.TrimEnd(','), dbc); slc = new SqliteCommand(md5query.TrimEnd(','), dbc);
slc.ExecuteNonQuery(); slc.ExecuteNonQuery();
} }
if (sha1query != "INSERT OR IGNORE INTO sha1 (sha1) VALUES") if (sha1query != "INSERT OR IGNORE INTO sha1 (sha1) VALUES")
{ {
slc = new SqliteCommand(sha1query.TrimEnd(','), dbc); slc = new SqliteCommand(sha1query.TrimEnd(','), dbc);
slc.ExecuteNonQuery(); slc.ExecuteNonQuery();
} }
if (crcsha1query != "INSERT OR IGNORE INTO crcsha1 (crc, sha1) VALUES") if (crcsha1query != "INSERT OR IGNORE INTO crcsha1 (crc, sha1) VALUES")
{ {
slc = new SqliteCommand(crcsha1query.TrimEnd(','), dbc); slc = new SqliteCommand(crcsha1query.TrimEnd(','), dbc);
slc.ExecuteNonQuery(); slc.ExecuteNonQuery();
} }
if (md5sha1query != "INSERT OR IGNORE INTO md5sha1 (md5, sha1) VALUES") if (md5sha1query != "INSERT OR IGNORE INTO md5sha1 (md5, sha1) VALUES")
{ {
slc = new SqliteCommand(md5sha1query.TrimEnd(','), dbc); slc = new SqliteCommand(md5sha1query.TrimEnd(','), dbc);
slc.ExecuteNonQuery(); slc.ExecuteNonQuery();
} }
} }
string datquery = "INSERT OR IGNORE INTO dat (hash) VALUES (\"" + dat.SHA1 + "\")"; string datquery = "INSERT OR IGNORE INTO dat (hash) VALUES (\"" + dat.SHA1 + "\")";
slc = new SqliteCommand(datquery, dbc); slc = new SqliteCommand(datquery, dbc);
slc.ExecuteNonQuery(); slc.ExecuteNonQuery();
slc.Dispose(); slc.Dispose();
} }
#endregion #endregion
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -14,389 +14,389 @@ using Alphaleonis.Win32.Filesystem;
namespace RombaSharp namespace RombaSharp
{ {
/// <summary> /// <summary>
/// Entry class for the RombaSharp application /// Entry class for the RombaSharp application
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// In the database, we want to enable "offline mode". That is, when a user does an operation /// In the database, we want to enable "offline mode". That is, when a user does an operation
/// that needs to read from the depot themselves, if the depot folder cannot be found, the /// that needs to read from the depot themselves, if the depot folder cannot be found, the
/// user is prompted to reconnect the depot OR skip that depot entirely. /// user is prompted to reconnect the depot OR skip that depot entirely.
/// </remarks> /// </remarks>
public partial class RombaSharp public partial class RombaSharp
{ {
// General settings // General settings
private static string _logdir; // Log folder location private static string _logdir; // Log folder location
private static string _tmpdir; // Temp folder location private static string _tmpdir; // Temp folder location
private static string _webdir; // Web frontend location private static string _webdir; // Web frontend location
private static string _baddir; // Fail-to-unpack file folder location private static string _baddir; // Fail-to-unpack file folder location
private static int _verbosity; // Verbosity of the output private static int _verbosity; // Verbosity of the output
private static int _cores; // Forced CPU cores private static int _cores; // Forced CPU cores
// DatRoot settings // DatRoot settings
private static string _dats; // DatRoot folder location private static string _dats; // DatRoot folder location
private static string _db; // Database name private static string _db; // Database name
// Depot settings // Depot settings
private static Dictionary<string, Tuple<long, bool>> _depots; // Folder location, Max size private static Dictionary<string, Tuple<long, bool>> _depots; // Folder location, Max size
// Server settings // Server settings
private static int _port; // Web server port private static int _port; // Web server port
// Other private variables // Other private variables
private static string _config = "config.xml"; private static string _config = "config.xml";
private static string _dbSchema = "rombasharp"; private static string _dbSchema = "rombasharp";
private static string _connectionString; private static string _connectionString;
private static Help _help; private static Help _help;
/// <summary> /// <summary>
/// Entry class for the RombaSharp application /// Entry class for the RombaSharp application
/// </summary> /// </summary>
public static void Main(string[] args) public static void Main(string[] args)
{ {
// Perform initial setup and verification // Perform initial setup and verification
Globals.Logger = new Logger(true, "romba.log"); Globals.Logger = new Logger(true, "romba.log");
InitializeConfiguration(); InitializeConfiguration();
DatabaseTools.EnsureDatabase(_dbSchema, _db, _connectionString); DatabaseTools.EnsureDatabase(_dbSchema, _db, _connectionString);
// Create a new Help object for this program // Create a new Help object for this program
_help = RombaSharp.RetrieveHelp(); _help = RombaSharp.RetrieveHelp();
// Get the location of the script tag, if it exists // Get the location of the script tag, if it exists
int scriptLocation = (new List<string>(args)).IndexOf("--script"); int scriptLocation = (new List<string>(args)).IndexOf("--script");
// If output is being redirected or we are in script mode, don't allow clear screens // If output is being redirected or we are in script mode, don't allow clear screens
if (!Console.IsOutputRedirected && scriptLocation == -1) if (!Console.IsOutputRedirected && scriptLocation == -1)
{ {
Console.Clear(); Console.Clear();
Build.PrepareConsole("RombaSharp"); Build.PrepareConsole("RombaSharp");
} }
// Now we remove the script tag because it messes things up // Now we remove the script tag because it messes things up
if (scriptLocation > -1) if (scriptLocation > -1)
{ {
List<string> newargs = new List<string>(args); List<string> newargs = new List<string>(args);
newargs.RemoveAt(scriptLocation); newargs.RemoveAt(scriptLocation);
args = newargs.ToArray(); args = newargs.ToArray();
} }
// Credits take precidence over all // Credits take precidence over all
if ((new List<string>(args)).Contains("--credits")) if ((new List<string>(args)).Contains("--credits"))
{ {
_help.OutputCredits(); _help.OutputCredits();
Globals.Logger.Close(); Globals.Logger.Close();
return; return;
} }
// If there's no arguments, show help // If there's no arguments, show help
if (args.Length == 0) if (args.Length == 0)
{ {
_help.OutputGenericHelp(); _help.OutputGenericHelp();
Globals.Logger.Close(); Globals.Logger.Close();
return; return;
} }
// User flags // User flags
bool copy = false, bool copy = false,
fixdatOnly = false, fixdatOnly = false,
logOnly = false, logOnly = false,
noDb = false, noDb = false,
onlyNeeded = false, onlyNeeded = false,
skipInitialScan = false, skipInitialScan = false,
useGolangZip = false; useGolangZip = false;
// User inputs // User inputs
string backup = "", string backup = "",
description = "", description = "",
missingSha1s = "", missingSha1s = "",
name = "", name = "",
newdat = "", newdat = "",
old = "", old = "",
outdat = "", outdat = "",
resume = "", resume = "",
source = ""; source = "";
int include7Zips = 1, int include7Zips = 1,
includeGZips = 1, includeGZips = 1,
includeZips = 1, includeZips = 1,
subworkers = 0, subworkers = 0,
workers = 0; workers = 0;
long size = -1; long size = -1;
List<string> dats = new List<string>(); List<string> dats = new List<string>();
List<string> depot = new List<string>(); List<string> depot = new List<string>();
List<string> inputs = new List<string>(); List<string> inputs = new List<string>();
// Get the first argument as a feature flag // Get the first argument as a feature flag
string feature = args[0]; string feature = args[0];
// Verify that the flag is valid // Verify that the flag is valid
if (!_help.TopLevelFlag(feature)) if (!_help.TopLevelFlag(feature))
{ {
Globals.Logger.User("'{0}' is not valid feature flag", feature); Globals.Logger.User("'{0}' is not valid feature flag", feature);
_help.OutputIndividualFeature(feature); _help.OutputIndividualFeature(feature);
Globals.Logger.Close(); Globals.Logger.Close();
return; return;
} }
// Now get the proper name for the feature // Now get the proper name for the feature
feature = _help.GetFeatureName(feature); feature = _help.GetFeatureName(feature);
// If we had the help feature first // If we had the help feature first
if (feature == "Help") if (feature == "Help")
{ {
// If we had something else after help // If we had something else after help
if (args.Length > 1) if (args.Length > 1)
{ {
_help.OutputIndividualFeature(args[1]); _help.OutputIndividualFeature(args[1]);
Globals.Logger.Close(); Globals.Logger.Close();
return; return;
} }
// Otherwise, show generic help // Otherwise, show generic help
else else
{ {
_help.OutputGenericHelp(); _help.OutputGenericHelp();
Globals.Logger.Close(); Globals.Logger.Close();
return; return;
} }
} }
// Now verify that all other flags are valid // Now verify that all other flags are valid
for (int i = 1; i < args.Length; i++) for (int i = 1; i < args.Length; i++)
{ {
// Verify that the current flag is proper for the feature // Verify that the current flag is proper for the feature
if (!_help[feature].ValidateInput(args[i])) if (!_help[feature].ValidateInput(args[i]))
{ {
// Everything else is treated as a generic input // Everything else is treated as a generic input
inputs.Add(args[i]); inputs.Add(args[i]);
} }
} }
// Now loop through all inputs // Now loop through all inputs
Dictionary<string, Feature> features = _help.GetEnabledFeatures(); Dictionary<string, Feature> features = _help.GetEnabledFeatures();
foreach (KeyValuePair<string, Feature> feat in features) foreach (KeyValuePair<string, Feature> feat in features)
{ {
// Check all of the flag names and translate to arguments // Check all of the flag names and translate to arguments
switch (feat.Key) switch (feat.Key)
{ {
#region User Flags #region User Flags
case "copy": case "copy":
copy = true; copy = true;
break; break;
case "fixdatOnly": case "fixdatOnly":
fixdatOnly = true; fixdatOnly = true;
break; break;
case "log-only": case "log-only":
logOnly = true; logOnly = true;
break; break;
case "no-db": case "no-db":
noDb = true; noDb = true;
break; break;
case "only-needed": case "only-needed":
onlyNeeded = true; onlyNeeded = true;
break; break;
case "skip-initial-scan": case "skip-initial-scan":
skipInitialScan = true; skipInitialScan = true;
break; break;
case "use-golang-zip": case "use-golang-zip":
useGolangZip = true; useGolangZip = true;
break; break;
#endregion #endregion
#region User Int32 Inputs #region User Int32 Inputs
case "include-7zips": case "include-7zips":
include7Zips = (int)feat.Value.GetValue() == Int32.MinValue ? (int)feat.Value.GetValue() : 0; include7Zips = (int)feat.Value.GetValue() == Int32.MinValue ? (int)feat.Value.GetValue() : 0;
break; break;
case "include-gzips": case "include-gzips":
includeGZips = (int)feat.Value.GetValue() == Int32.MinValue ? (int)feat.Value.GetValue() : 0; includeGZips = (int)feat.Value.GetValue() == Int32.MinValue ? (int)feat.Value.GetValue() : 0;
break; break;
case "include-zips": case "include-zips":
includeZips = (int)feat.Value.GetValue() == Int32.MinValue ? (int)feat.Value.GetValue() : 0; includeZips = (int)feat.Value.GetValue() == Int32.MinValue ? (int)feat.Value.GetValue() : 0;
break; break;
case "subworkers": case "subworkers":
subworkers = (int)feat.Value.GetValue() == Int32.MinValue ? (int)feat.Value.GetValue() : _cores; subworkers = (int)feat.Value.GetValue() == Int32.MinValue ? (int)feat.Value.GetValue() : _cores;
break; break;
case "workers": case "workers":
workers = (int)feat.Value.GetValue() == Int32.MinValue ? (int)feat.Value.GetValue() : _cores; workers = (int)feat.Value.GetValue() == Int32.MinValue ? (int)feat.Value.GetValue() : _cores;
break; break;
#endregion #endregion
#region User Int64 Inputs #region User Int64 Inputs
case "size": case "size":
size = (long)feat.Value.GetValue() == Int64.MinValue ? (long)feat.Value.GetValue() : 0; size = (long)feat.Value.GetValue() == Int64.MinValue ? (long)feat.Value.GetValue() : 0;
break; break;
#endregion #endregion
#region User List<string> Inputs #region User List<string> Inputs
case "dats": case "dats":
dats.AddRange((List<string>)feat.Value.GetValue()); dats.AddRange((List<string>)feat.Value.GetValue());
break; break;
case "depot": case "depot":
depot.AddRange((List<string>)feat.Value.GetValue()); depot.AddRange((List<string>)feat.Value.GetValue());
break; break;
#endregion #endregion
#region User String Inputs #region User String Inputs
case "backup": case "backup":
backup = (string)feat.Value.GetValue(); backup = (string)feat.Value.GetValue();
break; break;
case "description": case "description":
description = (string)feat.Value.GetValue(); description = (string)feat.Value.GetValue();
break; break;
case "missingSha1s": case "missingSha1s":
missingSha1s = (string)feat.Value.GetValue(); missingSha1s = (string)feat.Value.GetValue();
break; break;
case "name": case "name":
name = (string)feat.Value.GetValue(); name = (string)feat.Value.GetValue();
break; break;
case "new": case "new":
newdat = (string)feat.Value.GetValue(); newdat = (string)feat.Value.GetValue();
break; break;
case "old": case "old":
old = (string)feat.Value.GetValue(); old = (string)feat.Value.GetValue();
break; break;
case "out": case "out":
outdat = (string)feat.Value.GetValue(); outdat = (string)feat.Value.GetValue();
break; break;
case "resume": case "resume":
resume = (string)feat.Value.GetValue(); resume = (string)feat.Value.GetValue();
break; break;
case "source": case "source":
source = (string)feat.Value.GetValue(); source = (string)feat.Value.GetValue();
break; break;
#endregion #endregion
} }
} }
// Now take care of each mode in succesion // Now take care of each mode in succesion
switch(feature) switch(feature)
{ {
case "Help": case "Help":
// No-op as this should be caught // No-op as this should be caught
break; break;
// Adds ROM files from the specified directories to the ROM archive // Adds ROM files from the specified directories to the ROM archive
case "Archive": case "Archive":
VerifyInputs(inputs, feature); VerifyInputs(inputs, feature);
InitArchive(inputs, onlyNeeded, resume, includeZips, workers, includeGZips, include7Zips, skipInitialScan, useGolangZip, noDb); InitArchive(inputs, onlyNeeded, resume, includeZips, workers, includeGZips, include7Zips, skipInitialScan, useGolangZip, noDb);
break; break;
// For each specified DAT file it creates the torrentzip files // For each specified DAT file it creates the torrentzip files
case "Build": case "Build":
VerifyInputs(inputs, feature); VerifyInputs(inputs, feature);
InitBuild(inputs, outdat, fixdatOnly, copy, workers, subworkers); InitBuild(inputs, outdat, fixdatOnly, copy, workers, subworkers);
break; break;
// Cancels current long-running job // Cancels current long-running job
case "Cancel": case "Cancel":
InitCancel(); InitCancel();
break; break;
// Prints dat stats // Prints dat stats
case "DatStats": case "DatStats":
VerifyInputs(inputs, feature); VerifyInputs(inputs, feature);
InitDatStats(inputs); InitDatStats(inputs);
break; break;
// Prints db stats // Prints db stats
case "DbStats": case "DbStats":
InitDbStats(); InitDbStats();
break; break;
// Creates a DAT file with those entries that are in -new DAT // Creates a DAT file with those entries that are in -new DAT
case "Diffdat": case "Diffdat":
InitDiffDat(outdat, old, newdat, name, description); InitDiffDat(outdat, old, newdat, name, description);
break; break;
// Creates a DAT file for the specified input directory and saves it to the -out filename // Creates a DAT file for the specified input directory and saves it to the -out filename
case "Dir2Dat": case "Dir2Dat":
InitDir2Dat(outdat, source, name, description); InitDir2Dat(outdat, source, name, description);
break; break;
// Creates a DAT file with those entries that are in -new DAT // Creates a DAT file with those entries that are in -new DAT
case "EDiffdat": case "EDiffdat":
InitEDiffDat(outdat, old, newdat); InitEDiffDat(outdat, old, newdat);
break; break;
// Exports db to export.csv // Exports db to export.csv
case "Export": case "Export":
InitExport(); InitExport();
break; break;
// For each specified DAT file it creates a fix DAT // For each specified DAT file it creates a fix DAT
case "Fixdat": case "Fixdat":
VerifyInputs(inputs, feature); VerifyInputs(inputs, feature);
InitFixdat(inputs, outdat, fixdatOnly, workers, subworkers); InitFixdat(inputs, outdat, fixdatOnly, workers, subworkers);
break; break;
// Import a database from a formatted CSV file // Import a database from a formatted CSV file
case "Import": case "Import":
VerifyInputs(inputs, feature); VerifyInputs(inputs, feature);
InitImport(inputs); InitImport(inputs);
break; break;
// For each specified hash it looks up any available information // For each specified hash it looks up any available information
case "Lookup": case "Lookup":
VerifyInputs(inputs, feature); VerifyInputs(inputs, feature);
InitLookup(inputs, size, outdat); InitLookup(inputs, size, outdat);
break; break;
// Prints memory stats // Prints memory stats
case "Memstats": case "Memstats":
InitMemstats(); InitMemstats();
break; break;
// Merges depot // Merges depot
case "Merge": case "Merge":
VerifyInputs(inputs, feature); VerifyInputs(inputs, feature);
InitMerge(inputs, onlyNeeded, resume, workers, skipInitialScan); InitMerge(inputs, onlyNeeded, resume, workers, skipInitialScan);
break; break;
// Create miss and have file // Create miss and have file
case "Miss": case "Miss":
VerifyInputs(inputs, feature); VerifyInputs(inputs, feature);
InitMiss(inputs); InitMiss(inputs);
break; break;
// Shows progress of the currently running command // Shows progress of the currently running command
case "Progress": case "Progress":
InitProgress(); InitProgress();
break; break;
// Moves DAT index entries for orphaned DATs // Moves DAT index entries for orphaned DATs
case "Purge Backup": case "Purge Backup":
InitPurgeBackup(backup, workers, depot, dats, logOnly); InitPurgeBackup(backup, workers, depot, dats, logOnly);
break; break;
// Deletes DAT index entries for orphaned DATs // Deletes DAT index entries for orphaned DATs
case "Purge Delete": case "Purge Delete":
InitPurgeDelete(workers, depot, dats, logOnly); InitPurgeDelete(workers, depot, dats, logOnly);
break; break;
// Refreshes the DAT index from the files in the DAT master directory tree // Refreshes the DAT index from the files in the DAT master directory tree
case "Refresh DATs": case "Refresh DATs":
InitRefreshDats(workers, missingSha1s); InitRefreshDats(workers, missingSha1s);
break; break;
// Rescan a specific depot // Rescan a specific depot
case "Rescan Depots": case "Rescan Depots":
VerifyInputs(inputs, feature); VerifyInputs(inputs, feature);
InitRescanDepots(inputs); InitRescanDepots(inputs);
break; break;
// Gracefully shuts down server // Gracefully shuts down server
case "Shutdown": case "Shutdown":
InitShutdown(); InitShutdown();
break; break;
// Prints version // Prints version
case "Version": case "Version":
InitVersion(); InitVersion();
break; break;
// If nothing is set, show the help // If nothing is set, show the help
default: default:
_help.OutputGenericHelp(); _help.OutputGenericHelp();
break; break;
} }
Globals.Logger.Close(); Globals.Logger.Close();
return; return;
} }
private static void VerifyInputs(List<string> inputs, string feature) private static void VerifyInputs(List<string> inputs, string feature)
{ {
if (inputs.Count == 0) if (inputs.Count == 0)
{ {
Globals.Logger.Error("This feature requires at least one input"); Globals.Logger.Error("This feature requires at least one input");
_help.OutputIndividualFeature(feature); _help.OutputIndividualFeature(feature);
Environment.Exit(0); Environment.Exit(0);
} }
} }
} }
} }