Create and use ParentablePath

This commit is contained in:
Matt Nadareski
2020-07-26 23:39:33 -07:00
parent 3edd40b238
commit 5838c6f5c3
8 changed files with 135 additions and 90 deletions

View File

@@ -1072,7 +1072,7 @@ particular DAT.";
Globals.Logger.Error("This feature is not yet implemented: import"); Globals.Logger.Error("This feature is not yet implemented: import");
// First ensure the inputs and database connection // First ensure the inputs and database connection
Inputs = DirectoryExtensions.GetFilesOnly(Inputs); Inputs = DirectoryExtensions.GetFilesOnly(Inputs).Select(p => p.CurrentPath).ToList();
SqliteConnection dbc = new SqliteConnection(_connectionString); SqliteConnection dbc = new SqliteConnection(_connectionString);
SqliteCommand slc = new SqliteCommand(); SqliteCommand slc = new SqliteCommand();
dbc.Open(); dbc.Open();
@@ -1349,7 +1349,7 @@ particular DAT.";
Globals.Logger.Error("This feature is not yet implemented: merge"); Globals.Logger.Error("This feature is not yet implemented: merge");
// Verify that the inputs are valid directories // Verify that the inputs are valid directories
Inputs = DirectoryExtensions.GetDirectoriesOnly(Inputs); Inputs = DirectoryExtensions.GetDirectoriesOnly(Inputs).Select(p => p.CurrentPath).ToList();
// Loop over all input directories // Loop over all input directories
foreach (string input in Inputs) foreach (string input in Inputs)

View File

@@ -249,8 +249,8 @@ namespace SabreTools.Library.DatFiles
bool onlySame) bool onlySame)
{ {
// Ensure we only have files in the inputs // Ensure we only have files in the inputs
List<string> inputFileNames = DirectoryExtensions.GetFilesOnly(inputPaths, appendparent: true); List<ParentablePath> inputFileNames = DirectoryExtensions.GetFilesOnly(inputPaths, appendparent: true);
List<string> baseFileNames = DirectoryExtensions.GetFilesOnly(basePaths); List<ParentablePath> baseFileNames = DirectoryExtensions.GetFilesOnly(basePaths);
// If we're in standard update mode, run through all of the inputs // If we're in standard update mode, run through all of the inputs
if (updateMode == UpdateMode.None) if (updateMode == UpdateMode.None)
@@ -318,7 +318,7 @@ namespace SabreTools.Library.DatFiles
/// <param name="inputs">Paths to DATs to parse</param> /// <param name="inputs">Paths to DATs to parse</param>
/// <param name="filter">Filter object to be passed to the DatItem level</param> /// <param name="filter">Filter object to be passed to the DatItem level</param>
/// <returns>List of DatData objects representing headers</returns> /// <returns>List of DatData objects representing headers</returns>
private List<DatHeader> PopulateUserData(List<string> inputs, Filter filter) private List<DatHeader> PopulateUserData(List<ParentablePath> inputs, Filter filter)
{ {
DatFile[] datFiles = new DatFile[inputs.Count]; DatFile[] datFiles = new DatFile[inputs.Count];
InternalStopwatch watch = new InternalStopwatch("Processing individual DATs"); InternalStopwatch watch = new InternalStopwatch("Processing individual DATs");
@@ -326,8 +326,8 @@ namespace SabreTools.Library.DatFiles
// Parse all of the DATs into their own DatFiles in the array // Parse all of the DATs into their own DatFiles in the array
Parallel.For(0, inputs.Count, Globals.ParallelOptions, i => Parallel.For(0, inputs.Count, Globals.ParallelOptions, i =>
{ {
string input = inputs[i]; var input = inputs[i];
Globals.Logger.User($"Adding DAT: {input.Split('¬')[0]}"); Globals.Logger.User($"Adding DAT: {input.CurrentPath}");
datFiles[i] = Create(DatHeader.CloneFiltering()); datFiles[i] = Create(DatHeader.CloneFiltering());
datFiles[i].Parse(input, i, keep: true); datFiles[i].Parse(input, i, keep: true);
}); });
@@ -358,7 +358,7 @@ namespace SabreTools.Library.DatFiles
/// <param name="updateFields">List of Fields representing what should be updated [only for base replacement]</param> /// <param name="updateFields">List of Fields representing what should be updated [only for base replacement]</param>
/// <param name="onlySame">True if descriptions should only be replaced if the game name is the same, false otherwise</param> /// <param name="onlySame">True if descriptions should only be replaced if the game name is the same, false otherwise</param>
private void BaseReplace( private void BaseReplace(
List<string> inputFileNames, List<ParentablePath> inputFileNames,
string outDir, string outDir,
bool inplace, bool inplace,
Filter filter, Filter filter,
@@ -423,9 +423,9 @@ namespace SabreTools.Library.DatFiles
}; };
// We want to try to replace each item in each input DAT from the base // We want to try to replace each item in each input DAT from the base
foreach (string path in inputFileNames) foreach (ParentablePath path in inputFileNames)
{ {
Globals.Logger.User($"Replacing items in '{path.Split('¬')[0]}' from the base DAT"); Globals.Logger.User($"Replacing items in '{path.CurrentPath}' from the base DAT");
// First we parse in the DAT internally // First we parse in the DAT internally
DatFile intDat = Create(DatHeader.CloneFiltering()); DatFile intDat = Create(DatHeader.CloneFiltering());
@@ -844,15 +844,15 @@ namespace SabreTools.Library.DatFiles
/// <param name="inputFileNames">Names of the input files</param> /// <param name="inputFileNames">Names of the input files</param>
/// <param name="outDir">Optional param for output directory</param> /// <param name="outDir">Optional param for output directory</param>
/// <param name="inplace">True if the output files should overwrite their inputs, false otherwise</param> /// <param name="inplace">True if the output files should overwrite their inputs, false otherwise</param>
private void DiffAgainst(List<string> inputFileNames, string outDir, bool inplace) private void DiffAgainst(List<ParentablePath> inputFileNames, string outDir, bool inplace)
{ {
// For comparison's sake, we want to use CRC as the base ordering // For comparison's sake, we want to use CRC as the base ordering
Items.BucketBy(BucketedBy.CRC, DedupeType.Full); Items.BucketBy(BucketedBy.CRC, DedupeType.Full);
// Now we want to compare each input DAT against the base // Now we want to compare each input DAT against the base
foreach (string path in inputFileNames) foreach (ParentablePath path in inputFileNames)
{ {
Globals.Logger.User($"Comparing '{path.Split('¬')[0]}' to base DAT"); Globals.Logger.User($"Comparing '{path.CurrentPath}' to base DAT");
// First we parse in the DAT internally // First we parse in the DAT internally
DatFile intDat = Create(); DatFile intDat = Create();
@@ -896,7 +896,7 @@ namespace SabreTools.Library.DatFiles
/// <param name="outDir">Output directory to write the DATs to</param> /// <param name="outDir">Output directory to write the DATs to</param>
/// <param name="inplace">True if cascaded diffs are outputted in-place, false otherwise</param> /// <param name="inplace">True if cascaded diffs are outputted in-place, false otherwise</param>
/// <param name="skip">True if the first cascaded diff file should be skipped on output, false otherwise</param> /// <param name="skip">True if the first cascaded diff file should be skipped on output, false otherwise</param>
private void DiffCascade(List<string> inputs, List<DatHeader> datHeaders, string outDir, bool inplace, bool skip) private void DiffCascade(List<ParentablePath> inputs, List<DatHeader> datHeaders, string outDir, bool inplace, bool skip)
{ {
// Create a list of DatData objects representing output files // Create a list of DatData objects representing output files
List<DatFile> outDats = new List<DatFile>(); List<DatFile> outDats = new List<DatFile>();
@@ -979,7 +979,7 @@ namespace SabreTools.Library.DatFiles
/// <param name="inputs">List of inputs to write out from</param> /// <param name="inputs">List of inputs to write out from</param>
/// <param name="outDir">Output directory to write the DATs to</param> /// <param name="outDir">Output directory to write the DATs to</param>
/// <param name="diff">Non-zero flag for diffing mode, zero otherwise</param> /// <param name="diff">Non-zero flag for diffing mode, zero otherwise</param>
private void DiffNoCascade(List<string> inputs, string outDir, UpdateMode diff) private void DiffNoCascade(List<ParentablePath> inputs, string outDir, UpdateMode diff)
{ {
InternalStopwatch watch = new InternalStopwatch("Initializing all output DATs"); InternalStopwatch watch = new InternalStopwatch("Initializing all output DATs");
@@ -1071,7 +1071,7 @@ namespace SabreTools.Library.DatFiles
if (diff.HasFlag(UpdateMode.DiffNoDupesOnly)) if (diff.HasFlag(UpdateMode.DiffNoDupesOnly))
{ {
DatItem newrom = item.Clone() as DatItem; DatItem newrom = item.Clone() as DatItem;
newrom.MachineName += $" ({Path.GetFileNameWithoutExtension(inputs[item.IndexId].Split('¬')[0])})"; newrom.MachineName += $" ({Path.GetFileNameWithoutExtension(inputs[item.IndexId].CurrentPath)})";
outerDiffData.Items.Add(key, newrom); outerDiffData.Items.Add(key, newrom);
} }
@@ -1084,7 +1084,7 @@ namespace SabreTools.Library.DatFiles
if (item.DupeType.HasFlag(DupeType.External)) if (item.DupeType.HasFlag(DupeType.External))
{ {
DatItem newrom = item.Clone() as DatItem; DatItem newrom = item.Clone() as DatItem;
newrom.MachineName += $" ({Path.GetFileNameWithoutExtension(inputs[item.IndexId].Split('¬')[0])})"; newrom.MachineName += $" ({Path.GetFileNameWithoutExtension(inputs[item.IndexId].CurrentPath)})";
dupeData.Items.Add(key, newrom); dupeData.Items.Add(key, newrom);
} }
@@ -1125,7 +1125,7 @@ namespace SabreTools.Library.DatFiles
/// </summary> /// </summary>
/// <param name="inputs">List of inputs to write out from</param> /// <param name="inputs">List of inputs to write out from</param>
/// <param name="outDir">Output directory to write the DATs to</param> /// <param name="outDir">Output directory to write the DATs to</param>
private void MergeNoDiff(List<string> inputs, string outDir) private void MergeNoDiff(List<ParentablePath> inputs, string outDir)
{ {
// If we're in SuperDAT mode, prefix all games with their respective DATs // If we're in SuperDAT mode, prefix all games with their respective DATs
if (DatHeader.Type == "SuperDAT") if (DatHeader.Type == "SuperDAT")
@@ -1137,8 +1137,8 @@ namespace SabreTools.Library.DatFiles
foreach (DatItem item in items) foreach (DatItem item in items)
{ {
DatItem newItem = item; DatItem newItem = item;
string filename = inputs[newItem.IndexId].Split('¬')[0]; string filename = inputs[newItem.IndexId].CurrentPath;
string rootpath = inputs[newItem.IndexId].Split('¬')[1]; string rootpath = inputs[newItem.IndexId].ParentPath;
rootpath += (string.IsNullOrWhiteSpace(rootpath) ? string.Empty : Path.DirectorySeparatorChar.ToString()); rootpath += (string.IsNullOrWhiteSpace(rootpath) ? string.Empty : Path.DirectorySeparatorChar.ToString());
filename = filename.Remove(0, rootpath.Length); filename = filename.Remove(0, rootpath.Length);
@@ -1165,13 +1165,13 @@ namespace SabreTools.Library.DatFiles
/// <param name="outDir">Optional param for output directory</param> /// <param name="outDir">Optional param for output directory</param>
/// <param name="inplace">True if the output files should overwrite their inputs, false otherwise</param> /// <param name="inplace">True if the output files should overwrite their inputs, false otherwise</param>
/// <param name="filter">Filter object to be passed to the DatItem level</param> /// <param name="filter">Filter object to be passed to the DatItem level</param>
private void Update(List<string> inputFileNames, string outDir, bool inplace, Filter filter) private void Update(List<ParentablePath> inputFileNames, string outDir, bool inplace, Filter filter)
{ {
// Iterate over the files // Iterate over the files
foreach (string file in inputFileNames) foreach (ParentablePath file in inputFileNames)
{ {
DatFile innerDatdata = Create(DatHeader); DatFile innerDatdata = Create(DatHeader);
Globals.Logger.User($"Processing '{Path.GetFileName(file.Split('¬')[0])}'"); Globals.Logger.User($"Processing '{Path.GetFileName(file.CurrentPath)}'");
innerDatdata.Parse(file, keep: true, innerDatdata.Parse(file, keep: true,
keepext: innerDatdata.DatHeader.DatFormat.HasFlag(DatFormat.TSV) keepext: innerDatdata.DatHeader.DatFormat.HasFlag(DatFormat.TSV)
|| innerDatdata.DatHeader.DatFormat.HasFlag(DatFormat.CSV) || innerDatdata.DatHeader.DatFormat.HasFlag(DatFormat.CSV)
@@ -1197,7 +1197,7 @@ namespace SabreTools.Library.DatFiles
public static DatFile CreateAndParse(string filename) public static DatFile CreateAndParse(string filename)
{ {
DatFile datFile = Create(); DatFile datFile = Create();
datFile.Parse(filename); datFile.Parse(new ParentablePath(filename));
return datFile; return datFile;
} }
@@ -1208,27 +1208,26 @@ namespace SabreTools.Library.DatFiles
/// <param name="indexId">Index ID for the DAT</param> /// <param name="indexId">Index ID for the DAT</param>
/// <param name="keep">True if full pathnames are to be kept, false otherwise (default)</param> /// <param name="keep">True if full pathnames are to be kept, false otherwise (default)</param>
/// <param name="keepext">True if original extension should be kept, false otherwise (default)</param> /// <param name="keepext">True if original extension should be kept, false otherwise (default)</param>
public void Parse(string filename, int indexId = 0, bool keep = false, bool keepext = false) public void Parse(ParentablePath filename, int indexId = 0, bool keep = false, bool keepext = false)
{ {
// Check if we have a split path and get the filename accordingly // Get the current path from the filename
if (filename.Contains("¬")) string currentPath = filename.CurrentPath;
filename = filename.Split('¬')[0];
// Check the file extension first as a safeguard // Check the file extension first as a safeguard
if (!PathExtensions.HasValidDatExtension(filename)) if (!PathExtensions.HasValidDatExtension(currentPath))
return; return;
// If the output filename isn't set already, get the internal filename // If the output filename isn't set already, get the internal filename
DatHeader.FileName = (string.IsNullOrWhiteSpace(DatHeader.FileName) ? (keepext ? Path.GetFileName(filename) : Path.GetFileNameWithoutExtension(filename)) : DatHeader.FileName); DatHeader.FileName = (string.IsNullOrWhiteSpace(DatHeader.FileName) ? (keepext ? Path.GetFileName(currentPath) : Path.GetFileNameWithoutExtension(currentPath)) : DatHeader.FileName);
// If the output type isn't set already, get the internal output type // If the output type isn't set already, get the internal output type
DatHeader.DatFormat = (DatHeader.DatFormat == 0 ? filename.GetDatFormat() : DatHeader.DatFormat); DatHeader.DatFormat = (DatHeader.DatFormat == 0 ? currentPath.GetDatFormat() : DatHeader.DatFormat);
Items.SetBucketedBy(BucketedBy.CRC); // Setting this because it can reduce issues later Items.SetBucketedBy(BucketedBy.CRC); // Setting this because it can reduce issues later
// Now parse the correct type of DAT // Now parse the correct type of DAT
try try
{ {
Create(filename.GetDatFormat(), this)?.ParseFile(filename, indexId, keep); Create(currentPath.GetDatFormat(), this)?.ParseFile(currentPath, indexId, keep);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -2551,10 +2550,10 @@ namespace SabreTools.Library.DatFiles
return; return;
// Get only files from the inputs // Get only files from the inputs
List<string> files = DirectoryExtensions.GetFilesOnly(inputs, appendparent: true); List<ParentablePath> files = DirectoryExtensions.GetFilesOnly(inputs, appendparent: true);
// Loop over the input files // Loop over the input files
foreach (string file in files) foreach (ParentablePath file in files)
{ {
// Create and fill the new DAT // Create and fill the new DAT
Parse(file); Parse(file);
@@ -3059,10 +3058,6 @@ namespace SabreTools.Library.DatFiles
Items.BucketBy(BucketedBy.Game, DedupeType.None, norename: true); Items.BucketBy(BucketedBy.Game, DedupeType.None, norename: true);
// TODO: How can the size be negative when dealing with Int64?
if (Items.Statistics.TotalSize < 0)
Items.Statistics.TotalSize = Int64.MaxValue + Items.Statistics.TotalSize;
var consoleOutput = BaseReport.Create(StatReportFormat.None, null, true, true); var consoleOutput = BaseReport.Create(StatReportFormat.None, null, true, true);
consoleOutput.ReplaceStatistics(DatHeader.FileName, Items.Keys.Count(), Items.Statistics); consoleOutput.ReplaceStatistics(DatHeader.FileName, Items.Keys.Count(), Items.Statistics);
} }

View File

@@ -5,7 +5,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using NaturalSort;
using SabreTools.Library.Data; using SabreTools.Library.Data;
using SabreTools.Library.DatItems; using SabreTools.Library.DatItems;
using SabreTools.Library.Tools; using SabreTools.Library.Tools;
@@ -97,8 +97,16 @@ namespace SabreTools.Library.DatFiles
/// </summary> /// </summary>
private FilterItem<string> RebuildTo = new FilterItem<string>(); private FilterItem<string> RebuildTo = new FilterItem<string>();
// TODO: Machine.Devices - List<string> /// <summary>
// TODO: Machine.SlotOptions - List<string> /// Include or exclude machine devices
/// </summary>
private FilterItem<string> Devices = new FilterItem<string>();
/// <summary>
/// Include or exclude machine slotoptions
/// </summary>
private FilterItem<string> SlotOptions = new FilterItem<string>();
// TODO: Machine.Infos - List<KeyValuePair<string, string>> // TODO: Machine.Infos - List<KeyValuePair<string, string>>
/// <summary> /// <summary>
@@ -463,6 +471,20 @@ namespace SabreTools.Library.DatFiles
RebuildTo.PositiveSet.Add(value); RebuildTo.PositiveSet.Add(value);
break; break;
case Field.Devices:
if (negate)
Devices.NegativeSet.Add(value);
else
Devices.PositiveSet.Add(value);
break;
case Field.SlotOptions:
if (negate)
SlotOptions.NegativeSet.Add(value);
else
SlotOptions.PositiveSet.Add(value);
break;
case Field.MachineType: case Field.MachineType:
if (negate) if (negate)
MachineTypes.Negative |= value.AsMachineType(); MachineTypes.Negative |= value.AsMachineType();
@@ -1085,6 +1107,30 @@ namespace SabreTools.Library.DatFiles
if (this.RebuildTo.MatchesNegativeSet(item.RebuildTo) == true) if (this.RebuildTo.MatchesNegativeSet(item.RebuildTo) == true)
return false; return false;
// Filter on devices
bool anyPositiveDevice = false;
bool anyNegativeDevice = false;
foreach (string device in item.Devices)
{
anyPositiveDevice |= this.Devices.MatchesPositiveSet(device) == true;
anyNegativeDevice |= this.Devices.MatchesNegativeSet(device) == false;
}
if (!anyPositiveDevice || anyNegativeDevice)
return false;
// Filter on slot options
bool anyPositiveSlotOption = false;
bool anyNegativeSlotOption = false;
foreach (string device in item.SlotOptions)
{
anyPositiveSlotOption |= this.SlotOptions.MatchesPositiveSet(device) == true;
anyNegativeSlotOption |= this.SlotOptions.MatchesNegativeSet(device) == false;
}
if (!anyPositiveSlotOption || anyNegativeSlotOption)
return false;
// Filter on machine type // Filter on machine type
if (this.MachineTypes.MatchesPositive(MachineType.NULL, item.MachineType) == false) if (this.MachineTypes.MatchesPositive(MachineType.NULL, item.MachineType) == false)
return false; return false;

View File

@@ -35,11 +35,6 @@ namespace SabreTools.Library.DatFiles
#region Publically available fields #region Publically available fields
/// <summary>
/// DatStats object for reporting
/// </summary>
public DatStats Statistics { get; set; }
/// <summary> /// <summary>
/// Get the keys from the file dictionary /// Get the keys from the file dictionary
/// </summary> /// </summary>
@@ -63,6 +58,11 @@ namespace SabreTools.Library.DatFiles
} }
} }
/// <summary>
/// DatStats object for reporting
/// </summary>
public DatStats Statistics { get; private set; }
#endregion #endregion
#region Accessors #region Accessors
@@ -263,19 +263,6 @@ namespace SabreTools.Library.DatFiles
Statistics = new DatStats(); Statistics = new DatStats();
} }
/// <summary>
/// Constructor for statistics only
/// </summary>
/// <param name="stats">Existing statistics to pre-populate</param>
public ItemDictionary(DatStats stats)
{
bucketedBy = BucketedBy.Default;
mergedBy = DedupeType.None;
items = new Dictionary<string, List<DatItem>>();
Statistics = stats;
}
#endregion #endregion
#region Custom Functionality #region Custom Functionality

View File

@@ -21,7 +21,7 @@ namespace SabreTools.Library.Help
public string Name { get; protected set; } public string Name { get; protected set; }
public List<string> Flags { get; protected set; } public List<string> Flags { get; protected set; }
public string Description { get; protected set; } public string Description { get; protected set; }
public string LongDescription { get; protected set; } // TODO: Use this to generate README.1ST? public string LongDescription { get; protected set; }
public Dictionary<string, Feature> Features { get; protected set; } public Dictionary<string, Feature> Features { get; protected set; }
#endregion #endregion

View File

@@ -62,21 +62,24 @@ namespace SabreTools.Library.Tools
/// Retrieve a list of just directories from inputs /// Retrieve a list of just directories from inputs
/// </summary> /// </summary>
/// <param name="inputs">List of strings representing directories and files</param> /// <param name="inputs">List of strings representing directories and files</param>
/// <param name="appendparent">True if the parent name should be appended after the special character "¬", false otherwise (default)</param> /// <param name="appendparent">True if the parent name should be included in the ParentablePath, false otherwise (default)</param>
/// <returns>List of strings representing just directories from the inputs</returns> /// <returns>List of strings representing just directories from the inputs</returns>
public static List<string> GetDirectoriesOnly(List<string> inputs, bool appendparent = false) public static List<ParentablePath> GetDirectoriesOnly(List<string> inputs, bool appendparent = false)
{ {
List<string> outputs = new List<string>(); List<ParentablePath> outputs = new List<ParentablePath>();
foreach (string input in inputs) foreach (string input in inputs)
{ {
if (Directory.Exists(input)) if (Directory.Exists(input))
{ {
// Get the parent path in case of appending
string parentPath = Path.GetFullPath(input);
List<string> directories = GetDirectoriesOrdered(input); List<string> directories = GetDirectoriesOrdered(input);
foreach (string dir in directories) foreach (string dir in directories)
{ {
try try
{ {
outputs.Add(Path.GetFullPath(dir) + (appendparent ? $"¬{Path.GetFullPath(input)}" : string.Empty)); outputs.Add(new ParentablePath(Path.GetFullPath(dir), appendparent ? parentPath : string.Empty));
} }
catch (PathTooLongException) catch (PathTooLongException)
{ {
@@ -130,13 +133,16 @@ namespace SabreTools.Library.Tools
/// Retrieve a list of just files from inputs /// Retrieve a list of just files from inputs
/// </summary> /// </summary>
/// <param name="inputs">List of strings representing directories and files</param> /// <param name="inputs">List of strings representing directories and files</param>
/// <param name="appendparent">True if the parent name should be appended after the special character "¬", false otherwise (default)</param> /// <param name="appendparent">True if the parent name should be be included in the ParentablePath, false otherwise (default)</param>
/// <returns>List of strings representing just files from the inputs</returns> /// <returns>List of strings representing just files from the inputs</returns>
public static List<string> GetFilesOnly(List<string> inputs, bool appendparent = false) public static List<ParentablePath> GetFilesOnly(List<string> inputs, bool appendparent = false)
{ {
List<string> outputs = new List<string>(); List<ParentablePath> outputs = new List<ParentablePath>();
foreach (string input in inputs) foreach (string input in inputs)
{ {
// Get the parent path in case of appending
string parentPath = Path.GetFullPath(input);
if (Directory.Exists(input)) if (Directory.Exists(input))
{ {
List<string> files = GetFilesOrdered(input); List<string> files = GetFilesOrdered(input);
@@ -144,7 +150,7 @@ namespace SabreTools.Library.Tools
{ {
try try
{ {
outputs.Add(Path.GetFullPath(file) + (appendparent ? $"¬{Path.GetFullPath(input)}" : string.Empty)); outputs.Add(new ParentablePath(Path.GetFullPath(file), appendparent ? parentPath : string.Empty));
} }
catch (PathTooLongException) catch (PathTooLongException)
{ {
@@ -160,7 +166,7 @@ namespace SabreTools.Library.Tools
{ {
try try
{ {
outputs.Add(Path.GetFullPath(input) + (appendparent ? $"¬{Path.GetFullPath(input)}" : string.Empty)); outputs.Add(new ParentablePath(Path.GetFullPath(input), appendparent ? parentPath : string.Empty));
} }
catch (PathTooLongException) catch (PathTooLongException)
{ {

View File

@@ -0,0 +1,17 @@
namespace SabreTools.Library.Tools
{
/// <summary>
/// A path that optionally contains a parent root
/// </summary>
public class ParentablePath
{
public string CurrentPath { get; set; }
public string ParentPath { get; set; }
public ParentablePath(string currentPath, string parentPath = null)
{
CurrentPath = currentPath;
ParentPath = parentPath;
}
}
}

View File

@@ -40,36 +40,32 @@ namespace SabreTools.Library.Tools
/// <param name="path">Input combined path to use</param> /// <param name="path">Input combined path to use</param>
/// <param name="sanitize">True if path separators should be converted to '-', false otherwise</param> /// <param name="sanitize">True if path separators should be converted to '-', false otherwise</param>
/// <returns>Subpath for the file</returns> /// <returns>Subpath for the file</returns>
public static string GetNormalizedFileName(string path, bool sanitize) public static string GetNormalizedFileName(ParentablePath path, bool sanitize)
{ {
// Check that we have a combined path first // Check that we have a combined path first
if (!path.Contains("¬")) if (string.IsNullOrWhiteSpace(path.ParentPath))
{ {
string filename = Path.GetFileName(path); string filename = Path.GetFileName(path.CurrentPath);
if (sanitize) if (sanitize)
filename = filename.Replace(Path.DirectorySeparatorChar, '-').Replace(Path.AltDirectorySeparatorChar, '-'); filename = filename.Replace(Path.DirectorySeparatorChar, '-').Replace(Path.AltDirectorySeparatorChar, '-');
return filename; return filename;
} }
// First separate out the parts
string child = path.Split('¬')[0];
string parent = path.Split('¬')[1];
// If the parts are the same, return the filename from the first part // If the parts are the same, return the filename from the first part
if (string.Equals(child, parent, StringComparison.Ordinal)) if (string.Equals(path.CurrentPath, path.ParentPath, StringComparison.Ordinal))
{ {
string filename = Path.GetFileName(child); string filename = Path.GetFileName(path.CurrentPath);
if (sanitize) if (sanitize)
filename = filename.Replace(Path.DirectorySeparatorChar, '-').Replace(Path.AltDirectorySeparatorChar, '-'); filename = filename.Replace(Path.DirectorySeparatorChar, '-').Replace(Path.AltDirectorySeparatorChar, '-');
return filename; return filename;
} }
// Otherwise, remove the parent from the child and return the remainder // Otherwise, remove the path.ParentPath from the path.CurrentPath and return the remainder
else else
{ {
string filename = child.Remove(0, parent.Length + 1); string filename = path.CurrentPath.Remove(0, path.ParentPath.Length + 1);
if (sanitize) if (sanitize)
filename = filename.Replace(Path.DirectorySeparatorChar, '-').Replace(Path.AltDirectorySeparatorChar, '-'); filename = filename.Replace(Path.DirectorySeparatorChar, '-').Replace(Path.AltDirectorySeparatorChar, '-');
@@ -84,36 +80,34 @@ namespace SabreTools.Library.Tools
/// <param name="inputpath">Input path to create output for</param> /// <param name="inputpath">Input path to create output for</param>
/// <param name="inplace">True if the output file should go to the same input folder, false otherwise</param> /// <param name="inplace">True if the output file should go to the same input folder, false otherwise</param>
/// <returns>Complete output path</returns> /// <returns>Complete output path</returns>
public static string GetOutputPath(string outDir, string inputpath, bool inplace) public static string GetOutputPath(string outDir, ParentablePath inputPath, bool inplace)
{ {
// First, we need to ensure the output directory // First, we need to ensure the output directory
outDir = DirectoryExtensions.Ensure(outDir); outDir = DirectoryExtensions.Ensure(outDir);
// Check if we have a split path or not // Check if we have a split path or not
bool splitpath = inputpath.Contains("¬"); bool splitpath = !string.IsNullOrWhiteSpace(inputPath.ParentPath);
// If we have a split path, we need to treat the input separately // If we have a split path, we need to treat the input separately
if (splitpath) if (splitpath)
{ {
string[] split = inputpath.Split('¬');
// If we have an inplace output, use the directory name from the input path // If we have an inplace output, use the directory name from the input path
if (inplace) if (inplace)
{ {
outDir = Path.GetDirectoryName(split[0]); outDir = Path.GetDirectoryName(inputPath.CurrentPath);
} }
// TODO: Should this be the default? Always create a subfolder if a folder is found? // TODO: Should this be the default? Always create a subfolder if a folder is found?
// If we are processing a path that is coming from a directory and we are outputting to the current directory, we want to get the subfolder to write to // If we are processing a path that is coming from a directory and we are outputting to the current directory, we want to get the subfolder to write to
else if (split[0].Length != split[1].Length && outDir == Environment.CurrentDirectory) else if (inputPath.CurrentPath.Length != inputPath.ParentPath.Length && outDir == Environment.CurrentDirectory)
{ {
outDir = Path.GetDirectoryName(Path.Combine(outDir, split[0].Remove(0, Path.GetDirectoryName(split[1]).Length + 1))); outDir = Path.GetDirectoryName(Path.Combine(outDir, inputPath.CurrentPath.Remove(0, Path.GetDirectoryName(inputPath.ParentPath).Length + 1)));
} }
// If we are processing a path that is coming from a directory, we want to get the subfolder to write to // If we are processing a path that is coming from a directory, we want to get the subfolder to write to
else if (split[0].Length != split[1].Length) else if (inputPath.CurrentPath.Length != inputPath.ParentPath.Length)
{ {
outDir = Path.GetDirectoryName(Path.Combine(outDir, split[0].Remove(0, split[1].Length + 1))); outDir = Path.GetDirectoryName(Path.Combine(outDir, inputPath.CurrentPath.Remove(0, inputPath.ParentPath.Length + 1)));
} }
// If we are processing a single file from the root of a directory, we just use the output directory // If we are processing a single file from the root of a directory, we just use the output directory
@@ -128,7 +122,7 @@ namespace SabreTools.Library.Tools
// If we have an inplace output, use the directory name from the input path // If we have an inplace output, use the directory name from the input path
if (inplace) if (inplace)
{ {
outDir = Path.GetDirectoryName(inputpath); outDir = Path.GetDirectoryName(inputPath.CurrentPath);
} }
// Otherwise, just use the supplied output directory // Otherwise, just use the supplied output directory