[ALL] Rewrite some archive handling

Remove managed writing, simplify archive to archive handling, add ability to set modification date on files if in source rom.
This commit is contained in:
Matt Nadareski
2016-09-13 16:04:24 -07:00
parent 431ba78b39
commit 1dc45acca2
8 changed files with 58 additions and 150 deletions

View File

@@ -66,7 +66,8 @@ namespace SabreTools
Files = new Dictionary<string, List<Rom>>(),
};
DATFromDir dfd = new DATFromDir(inputs, datdata, false, false, true, false, true, "__temp__", _logger);
DATFromDir dfd = new DATFromDir(inputs, datdata, false /* noMD5 */, false /* noSHA1 */, true /* bare */,
false /* archivesAsFiles */, true /* enableGzip */, false /* addblanks */, "__temp__" /* tempdir */, _logger);
dfd.Start();
}

View File

@@ -47,10 +47,11 @@ namespace SabreTools
/// <param name="bare">True if the date should be omitted from the DAT, false otherwise</param>
/// <param name="archivesAsFiles">True if archives should be treated as files, false otherwise</param>
/// <param name="enableGzip">True if GZIP archives should be treated as files, false otherwise</param>
/// <param name="addblanks">True if blank items should be created for empty folders, false otherwise</param>
/// <param name="tempDir">Name of the directory to create a temp folder in (blank is current directory)</param>
/// <param name="nowrite">True if the file should not be written out, false otherwise (default)</param>
/// <param name="logger">Logger object for console and file output</param>
public DATFromDir(List<String> inputs, Dat datdata, bool noMD5, bool noSHA1, bool bare, bool archivesAsFiles, bool enableGzip, string tempDir, Logger logger, bool nowrite = false)
public DATFromDir(List<String> inputs, Dat datdata, bool noMD5, bool noSHA1, bool bare, bool archivesAsFiles, bool enableGzip, bool addblanks, string tempDir, Logger logger, bool nowrite = false)
{
_inputs = inputs;
_datdata = datdata;
@@ -61,7 +62,7 @@ namespace SabreTools
_enableGzip = enableGzip;
_tempDir = tempDir;
_logger = logger;
_addblanks = false; // This needs a proper flag later
_addblanks = addblanks;
_nowrite = nowrite;
}

View File

@@ -46,11 +46,12 @@ namespace SabreTools
/// <param name="bare">True if the date should be omitted from the DAT, false otherwise</param>
/// <param name="archivesAsFiles">True if archives should be treated as files, false otherwise</param>
/// <param name="enableGzip">True if GZIP archives should be treated as files, false otherwise</param>
/// <param name="addblanks">True if blank items should be created for empty folders, false otherwise</param>
/// <param name="tempDir">Name of the directory to create a temp folder in (blank is current directory)</param>
/// <param name="maxDegreeOfParallelism">Integer representing the maximum amount of parallelization to be used</param>
/// <param name="logger">Logger object for console and file output</param>
public DATFromDirParallel(string basePath, Dat datdata, bool noMD5, bool noSHA1, bool bare,
bool archivesAsFiles, bool enableGzip, string tempDir, int maxDegreeOfParallelism, Logger logger)
bool archivesAsFiles, bool enableGzip, bool addblanks, string tempDir, int maxDegreeOfParallelism, Logger logger)
{
_basePath = Path.GetFullPath(basePath);
_datdata = datdata;
@@ -61,7 +62,7 @@ namespace SabreTools
_bare = bare;
_archivesAsFiles = archivesAsFiles;
_enableGzip = enableGzip;
_addblanks = false; // This needs a proper flag later
_addblanks = addblanks;
_tempDir = tempDir;
_maxDegreeOfParallelism = maxDegreeOfParallelism;
_logger = logger;

View File

@@ -132,7 +132,8 @@ namespace SabreTools.Helper
// Then, loop through and check each of the inputs
_logger.User("Processing files:\n");
DATFromDir dfd = new DATFromDir(files, _datdata, false, false, false, false, true, "", _logger, true);
DATFromDir dfd = new DATFromDir(files, _datdata, false /* noMD5 */, false /* noSHA1 */, false /* bare */,
false /* archivesAsFiles */, true /* enableGzip */, false /* addblanks */, "" /* tempdir */, _logger, true /* nowrite */);
dfd.Start();
// Setup the fixdat
@@ -331,7 +332,7 @@ namespace SabreTools.Helper
}
else
{
FileTools.WriteToManagedArchive(input, _outdir, found);
FileTools.WriteToArchive(input, _outdir, found);
}
}
}
@@ -398,7 +399,7 @@ namespace SabreTools.Helper
}
else
{
FileTools.WriteToManagedArchive(newinput, _outdir, found);
FileTools.WriteToArchive(newinput, _outdir, found);
}
}
@@ -444,7 +445,7 @@ namespace SabreTools.Helper
}
else
{
FileTools.WriteToManagedArchive(input, _outdir, newfound);
FileTools.WriteToArchive(input, _outdir, newfound);
}
}
}
@@ -530,7 +531,7 @@ namespace SabreTools.Helper
}
else
{
FileTools.WriteToManagedArchive(outfile, _outdir, found);
FileTools.WriteToArchive(outfile, _outdir, found);
}
try
@@ -542,8 +543,7 @@ namespace SabreTools.Helper
}
else
{
string archiveFileName = Path.Combine(_outdir, found.Machine.Name + ".zip");
FileTools.CopyFileBetweenArchives(input, archiveFileName, rom.Name, found.Name, _logger);
FileTools.CopyFileBetweenArchives(input, _outdir, rom.Name, found, _logger);
}
}
}

View File

@@ -468,7 +468,7 @@ namespace SabreTools.Helper
switch (gc[1].Value)
{
case "name":
tempgamename = itemval;
tempgamename = (itemval.ToLowerInvariant().EndsWith(".zip") ? itemval.Remove(itemval.Length - 4) : itemval);
break;
case "description":
gamedesc = itemval;

View File

@@ -20,100 +20,65 @@ namespace SabreTools.Helper
/// <summary>
/// Copy a file to an output archive
/// </summary>
/// <param name="input">Input filename to be moved</param>
/// <param name="output">Output directory to build to</param>
/// <param name="inputFile">Input filename to be moved</param>
/// <param name="outputDirectory">Output directory to build to</param>
/// <param name="rom">RomData representing the new information</param>
public static void WriteToArchive(string input, string output, Rom rom)
/// <returns>True if the archive was written properly, false otherwise</returns>
public static bool WriteToArchive(string inputFile, string outputDirectory, Rom rom)
{
string archiveFileName = Path.Combine(output, rom.Machine + ".zip");
bool success = false;
// If the input file doesn't exist, return
if (!File.Exists(inputFile))
{
return success;
}
string archiveFileName = Path.Combine(outputDirectory, rom.Machine.Name + ".zip");
ZipArchive outarchive = null;
try
{
// If the archive doesn't exist, create it
if (!File.Exists(archiveFileName))
{
outarchive = ZipFile.Open(archiveFileName, ZipArchiveMode.Create);
}
else
{
outarchive = ZipFile.Open(archiveFileName, ZipArchiveMode.Update);
outarchive.Dispose();
}
if (File.Exists(input))
// Open the archive for writing
using (outarchive = ZipFile.Open(archiveFileName, ZipArchiveMode.Update))
{
if (outarchive.Mode == ZipArchiveMode.Create || outarchive.GetEntry(rom.Name) == null)
// If the archive doesn't already contain the entry, add it
if (outarchive.GetEntry(rom.Name) == null)
{
outarchive.CreateEntryFromFile(input, rom.Name, CompressionLevel.Optimal);
outarchive.CreateEntryFromFile(inputFile, rom.Name, CompressionLevel.Optimal);
}
}
else if (Directory.Exists(input))
{
foreach (string file in Directory.EnumerateFiles(input, "*", SearchOption.AllDirectories))
// If there's a Date attached to the rom, change the entry to that Date
if (!String.IsNullOrEmpty(rom.Date))
{
if (outarchive.Mode == ZipArchiveMode.Create || outarchive.GetEntry(file) == null)
DateTimeOffset dto = DateTimeOffset.Now;
if (DateTimeOffset.TryParse(rom.Date, out dto))
{
outarchive.CreateEntryFromFile(file, file, CompressionLevel.Optimal);
outarchive.GetEntry(rom.Name).LastWriteTime = dto;
}
}
}
success = true;
}
catch (Exception ex)
{
Console.WriteLine(ex);
success = false;
}
finally
{
outarchive?.Dispose();
}
}
/// <summary>
/// Copy a file to an output archive using SharpCompress
/// </summary>
/// <param name="input">Input filename to be moved</param>
/// <param name="output">Output directory to build to</param>
/// <param name="rom">RomData representing the new information</param>
public static void WriteToManagedArchive(string input, string output, Rom rom)
{
string archiveFileName = Path.Combine(output, rom.Machine.Name + ".zip");
// Delete an empty file first
if (File.Exists(archiveFileName) && new FileInfo(archiveFileName).Length == 0)
{
File.Delete(archiveFileName);
}
// Get if the file should be written out
bool newfile = File.Exists(archiveFileName) && new FileInfo(archiveFileName).Length != 0;
using (SharpCompress.Archive.Zip.ZipArchive archive = (newfile
? ArchiveFactory.Open(archiveFileName, Options.LookForHeader) as SharpCompress.Archive.Zip.ZipArchive
: ArchiveFactory.Create(ArchiveType.Zip) as SharpCompress.Archive.Zip.ZipArchive))
{
try
{
if (File.Exists(input))
{
archive.AddEntry(rom.Name, input);
}
else if (Directory.Exists(input))
{
archive.AddAllFromDirectory(input, "*", SearchOption.AllDirectories);
}
archive.SaveTo(archiveFileName + ".tmp", CompressionType.Deflate);
}
catch (Exception)
{
// Don't log archive write errors
}
}
if (File.Exists(archiveFileName + ".tmp"))
{
File.Delete(archiveFileName);
File.Move(archiveFileName + ".tmp", archiveFileName);
}
return success;
}
/// <summary>
@@ -423,82 +388,19 @@ namespace SabreTools.Helper
#region Archive-to-Archive Handling
/// <summary>
/// Attempt to copy a file between archives using SharpCompress
/// Attempt to copy a file between archives
/// </summary>
/// <param name="inputArchive">Source archive name</param>
/// <param name="outputArchive">Destination archive name</param>
/// <param name="outputDirectory">Destination archive name</param>
/// <param name="sourceEntryName">Input entry name</param>
/// <param name="destEntryName">Output entry name</param>
/// <param name="logger">Logger object for file and console output</param>
/// <returns>True if the copy was a success, false otherwise</returns>
public static bool CopyFileBetweenArchives(string inputArchive, string outputArchive,
string sourceEntryName, string destEntryName, Logger logger)
public static bool CopyFileBetweenArchives(string inputArchive, string outputDirectory,
string sourceEntryName, Rom destEntry, Logger logger)
{
bool success = false;
// First get the archive types
ArchiveType? iat = GetCurrentArchiveType(inputArchive, logger);
ArchiveType? oat = (File.Exists(outputArchive) ? GetCurrentArchiveType(outputArchive, logger) : ArchiveType.Zip);
// If we got back null (or the output is not a Zipfile), then it's not an archive, so we we return
if (iat == null || (oat == null || oat != ArchiveType.Zip) || inputArchive == outputArchive)
{
return success;
}
try
{
using (IReader reader = ReaderFactory.Open(File.OpenRead(inputArchive)))
{
if (iat == ArchiveType.Zip || iat == ArchiveType.SevenZip || iat == ArchiveType.Rar)
{
while (reader.MoveToNextEntry())
{
logger.Log("Current entry name: '" + reader.Entry.Key + "'");
if (reader.Entry != null && reader.Entry.Key.Contains(sourceEntryName))
{
// Get if the file should be written out
bool newfile = File.Exists(outputArchive) && new FileInfo(outputArchive).Length != 0;
using (SharpCompress.Archive.Zip.ZipArchive archive = (newfile
? ArchiveFactory.Open(outputArchive, Options.LookForHeader) as SharpCompress.Archive.Zip.ZipArchive
: ArchiveFactory.Create(ArchiveType.Zip) as SharpCompress.Archive.Zip.ZipArchive))
{
try
{
if (!archive.Entries.Contains(reader.Entry))
{
Stream tempstream = new MemoryStream();
reader.WriteEntryTo(tempstream);
archive.AddEntry(destEntryName, tempstream);
archive.SaveTo(outputArchive + ".tmp", CompressionType.Deflate);
}
}
catch (Exception)
{
// Don't log archive write errors
}
}
if (File.Exists(outputArchive + ".tmp"))
{
File.Delete(outputArchive);
File.Move(outputArchive + ".tmp", outputArchive);
}
success = true;
}
}
}
}
}
catch (Exception ex)
{
logger.Error(ex.ToString());
success = false;
}
return success;
string tempfile = ExtractSingleItemFromArchive(inputArchive, sourceEntryName, Path.GetTempPath(), logger);
return WriteToArchive(tempfile, outputDirectory, destEntry);
}
#endregion

View File

@@ -101,6 +101,7 @@ namespace SabreTools
/// <param name="bare">True if the date should be omitted from the DAT, false otherwise</param>
/// <param name="archivesAsFiles">True if archives should be treated as files, false otherwise</param>
/// <param name="enableGzip">True if GZIP archives should be treated as files, false otherwise</param>
/// <param name="addblanks">True if blank items should be created for empty folders, false otherwise</param>
/// <param name="tempDir">Name of the directory to create a temp folder in (blank is current directory</param>
/// <param name="maxDegreeOfParallelism">Integer representing the maximum amount of parallelization to be used</param>
private static void InitDatFromDir(List<string> inputs,
@@ -119,6 +120,7 @@ namespace SabreTools
bool bare,
bool archivesAsFiles,
bool enableGzip,
bool addblanks,
string tempDir,
int maxDegreeOfParallelism)
{
@@ -142,7 +144,7 @@ namespace SabreTools
// If the user has only set a single thread, use the original version
if (maxDegreeOfParallelism == 1)
{
DATFromDir dfd = new DATFromDir(inputs, basedat, noMD5, noSHA1, bare, archivesAsFiles, enableGzip, tempDir, _logger);
DATFromDir dfd = new DATFromDir(inputs, basedat, noMD5, noSHA1, bare, archivesAsFiles, enableGzip, addblanks, tempDir, _logger);
bool success = dfd.Start();
// If we failed, show the help
@@ -166,7 +168,7 @@ namespace SabreTools
datdata.Files = new Dictionary<string, List<Rom>>();
string basePath = Path.GetFullPath(path);
DATFromDirParallel dfd = new DATFromDirParallel(basePath, datdata, noMD5, noSHA1, bare, archivesAsFiles, enableGzip, tempDir, maxDegreeOfParallelism, _logger);
DATFromDirParallel dfd = new DATFromDirParallel(basePath, datdata, noMD5, noSHA1, bare, archivesAsFiles, enableGzip, addblanks, tempDir, maxDegreeOfParallelism, _logger);
bool success = dfd.Start();
// If it was a success, write the DAT out

View File

@@ -77,6 +77,7 @@ namespace SabreTools
// Set all default values
bool help = false,
add = false,
addblanks = false,
archivesAsFiles = false,
bare = false,
clean = false,
@@ -660,7 +661,7 @@ namespace SabreTools
else if (datfromdir)
{
InitDatFromDir(inputs, filename, name, description, category, version, author, forceunpack, outputFormat,
romba, superdat, noMD5, noSHA1, bare, archivesAsFiles, enableGzip, tempdir, maxParallelism);
romba, superdat, noMD5, noSHA1, bare, archivesAsFiles, enableGzip, addblanks, tempdir, maxParallelism);
}
// Split a DAT by extension