diff --git a/CHANGELIST.md b/CHANGELIST.md index dff0cea7..6da421b9 100644 --- a/CHANGELIST.md +++ b/CHANGELIST.md @@ -121,6 +121,7 @@ - Disable all UI elements on protect scan - Account for menu items for disable/enable - Allow check and IRD most of the time +- Check for partial dumps ### 3.2.4 (2024-11-24) diff --git a/MPF.Frontend/DumpEnvironment.cs b/MPF.Frontend/DumpEnvironment.cs index 118a7c6b..243d010c 100644 --- a/MPF.Frontend/DumpEnvironment.cs +++ b/MPF.Frontend/DumpEnvironment.cs @@ -151,12 +151,12 @@ namespace MPF.Frontend { // If a complete dump exists from a different program InternalProgram? programFound = null; - if (programFound == null && _internalProgram != InternalProgram.Aaru) + if (programFound == null && _internalProgram != InternalProgram.Redumper) { - var processor = new Processors.Aaru(_system, _type); + var processor = new Processors.Redumper(_system, _type); var missingFiles = processor.FoundAllFiles(outputDirectory, outputFilename); if (missingFiles.Count == 0) - programFound = InternalProgram.Aaru; + programFound = InternalProgram.Redumper; } if (programFound == null && _internalProgram != InternalProgram.DiscImageCreator) { @@ -165,13 +165,42 @@ namespace MPF.Frontend if (missingFiles.Count == 0) programFound = InternalProgram.DiscImageCreator; } + if (programFound == null && _internalProgram != InternalProgram.Aaru) + { + var processor = new Processors.Aaru(_system, _type); + var missingFiles = processor.FoundAllFiles(outputDirectory, outputFilename); + if (missingFiles.Count == 0) + programFound = InternalProgram.Aaru; + } + + return programFound; + } + + /// + /// Check output path for partial logs from all dumping programs + /// + public InternalProgram? CheckForPartialProgram(string? outputDirectory, string outputFilename) + { + // If a complete dump exists from a different program + InternalProgram? programFound = null; if (programFound == null && _internalProgram != InternalProgram.Redumper) { var processor = new Processors.Redumper(_system, _type); - var missingFiles = processor.FoundAllFiles(outputDirectory, outputFilename); - if (missingFiles.Count == 0) + if (processor.FoundAnyFiles(outputDirectory, outputFilename)) programFound = InternalProgram.Redumper; } + if (programFound == null && _internalProgram != InternalProgram.DiscImageCreator) + { + var processor = new Processors.DiscImageCreator(_system, _type); + if (processor.FoundAnyFiles(outputDirectory, outputFilename)) + programFound = InternalProgram.DiscImageCreator; + } + if (programFound == null && _internalProgram != InternalProgram.Aaru) + { + var processor = new Processors.Aaru(_system, _type); + if (processor.FoundAnyFiles(outputDirectory, outputFilename)) + programFound = InternalProgram.Aaru; + } return programFound; } @@ -300,6 +329,15 @@ namespace MPF.Frontend return _processor.FoundAllFiles(outputDirectory, outputFilename).Count == 0; } + /// + public bool FoundAnyFiles(string? outputDirectory, string outputFilename) + { + if (_processor == null) + return false; + + return _processor.FoundAnyFiles(outputDirectory, outputFilename); + } + /// public string? GetDefaultExtension(MediaType? mediaType) { diff --git a/MPF.Frontend/ViewModels/MainViewModel.cs b/MPF.Frontend/ViewModels/MainViewModel.cs index 903932cd..06a7bae9 100644 --- a/MPF.Frontend/ViewModels/MainViewModel.cs +++ b/MPF.Frontend/ViewModels/MainViewModel.cs @@ -2211,9 +2211,9 @@ namespace MPF.Frontend.ViewModels var outputDirectory = Path.GetDirectoryName(_environment!.OutputPath); string outputFilename = Path.GetFileName(_environment.OutputPath); - // If a complete dump already exists - bool foundFiles = _environment.FoundAllFiles(outputDirectory, outputFilename); - if (foundFiles && _displayUserMessage != null) + // If a complete or partial dump already exists + bool foundAllFiles = _environment.FoundAllFiles(outputDirectory, outputFilename); + if (foundAllFiles && _displayUserMessage != null) { bool? mbresult = _displayUserMessage("Overwrite?", "A complete dump already exists! Are you sure you want to overwrite?", 2, true); if (mbresult != true) @@ -2224,17 +2224,45 @@ namespace MPF.Frontend.ViewModels } else { - // If a complete dump exists from a different program - InternalProgram? programFound = _environment.CheckForMatchingProgram(outputDirectory, outputFilename); - if (programFound != null && _displayUserMessage != null) + // If a partial dump exists + bool foundAnyFiles = _environment.FoundAnyFiles(outputDirectory, outputFilename); + if (foundAnyFiles && _displayUserMessage != null) { - bool? mbresult = _displayUserMessage("Overwrite?", $"A complete dump from {programFound} already exists! Dumping here may cause issues. Are you sure you want to overwrite?", 2, true); + bool? mbresult = _displayUserMessage("Overwrite?", $"A partial dump already exists! Dumping here may cause issues. Are you sure you want to overwrite?", 2, true); if (mbresult != true) { LogLn("Dumping aborted!"); return false; } } + else + { + // If a complete dump exists from a different program + InternalProgram? completeProgramFound = _environment.CheckForMatchingProgram(outputDirectory, outputFilename); + if (completeProgramFound != null && _displayUserMessage != null) + { + bool? mbresult = _displayUserMessage("Overwrite?", $"A complete dump from {completeProgramFound} already exists! Dumping here may cause issues. Are you sure you want to overwrite?", 2, true); + if (mbresult != true) + { + LogLn("Dumping aborted!"); + return false; + } + } + else + { + // If a partial dump exists from a different program + InternalProgram? partialProgramFound = _environment.CheckForPartialProgram(outputDirectory, outputFilename); + if (partialProgramFound != null && _displayUserMessage != null) + { + bool? mbresult = _displayUserMessage("Overwrite?", $"A partial dump from {partialProgramFound} already exists! Dumping here may cause issues. Are you sure you want to overwrite?", 2, true); + if (mbresult != true) + { + LogLn("Dumping aborted!"); + return false; + } + } + } + } } // Validate that at least some space exists diff --git a/MPF.Processors.Test/AaruTests.cs b/MPF.Processors.Test/AaruTests.cs index d6428965..e214c6e3 100644 --- a/MPF.Processors.Test/AaruTests.cs +++ b/MPF.Processors.Test/AaruTests.cs @@ -127,6 +127,30 @@ namespace MPF.Processors.Test #endregion + #region CheckExistingFiles + + [Fact] + public void CheckExistingFiles_Invalid_Filled() + { + string? baseDirectory = null; + string baseFilename = string.Empty; + var processor = new Aaru(RedumpSystem.IBMPCcompatible, MediaType.CDROM); + var actual = processor.CheckExistingFiles(baseDirectory, baseFilename); + Assert.False(actual); + } + + [Fact] + public void CheckExistingFiles_Valid_Empty() + { + string? baseDirectory = Path.Combine(Environment.CurrentDirectory, "TestData", "Aaru", "CDROM"); + string baseFilename = "test"; + var processor = new Aaru(RedumpSystem.IBMPCcompatible, MediaType.CDROM); + var actual = processor.CheckExistingFiles(baseDirectory, baseFilename); + Assert.True(actual); + } + + #endregion + #region GetDeleteableFilePaths [Fact] diff --git a/MPF.Processors.Test/CleanRipTests.cs b/MPF.Processors.Test/CleanRipTests.cs index a6386141..14f0c505 100644 --- a/MPF.Processors.Test/CleanRipTests.cs +++ b/MPF.Processors.Test/CleanRipTests.cs @@ -112,6 +112,30 @@ namespace MPF.Processors.Test #endregion + #region CheckExistingFiles + + [Fact] + public void CheckExistingFiles_Invalid_Filled() + { + string? baseDirectory = null; + string baseFilename = string.Empty; + var processor = new CleanRip(RedumpSystem.NintendoGameCube, MediaType.DVD); + var actual = processor.CheckExistingFiles(baseDirectory, baseFilename); + Assert.False(actual); + } + + [Fact] + public void CheckExistingFiles_Valid_Empty() + { + string? baseDirectory = Path.Combine(Environment.CurrentDirectory, "TestData", "CleanRip", "DVD"); + string baseFilename = "test"; + var processor = new CleanRip(RedumpSystem.NintendoGameCube, MediaType.DVD); + var actual = processor.CheckExistingFiles(baseDirectory, baseFilename); + Assert.True(actual); + } + + #endregion + #region GetDeleteableFilePaths [Fact] diff --git a/MPF.Processors.Test/DiscImageCreatorTests.cs b/MPF.Processors.Test/DiscImageCreatorTests.cs index ca36649c..79a564ed 100644 --- a/MPF.Processors.Test/DiscImageCreatorTests.cs +++ b/MPF.Processors.Test/DiscImageCreatorTests.cs @@ -181,6 +181,30 @@ namespace MPF.Processors.Test #endregion + #region CheckExistingFiles + + [Fact] + public void CheckExistingFiles_Invalid_Filled() + { + string? baseDirectory = null; + string baseFilename = string.Empty; + var processor = new DiscImageCreator(RedumpSystem.IBMPCcompatible, MediaType.CDROM); + var actual = processor.CheckExistingFiles(baseDirectory, baseFilename); + Assert.False(actual); + } + + [Fact] + public void CheckExistingFiles_Valid_Empty() + { + string? baseDirectory = Path.Combine(Environment.CurrentDirectory, "TestData", "DiscImageCreator", "CDROM"); + string baseFilename = "test"; + var processor = new DiscImageCreator(RedumpSystem.IBMPCcompatible, MediaType.CDROM); + var actual = processor.CheckExistingFiles(baseDirectory, baseFilename); + Assert.True(actual); + } + + #endregion + #region GetDeleteableFilePaths [Fact] diff --git a/MPF.Processors.Test/PS3CFWTests.cs b/MPF.Processors.Test/PS3CFWTests.cs index 5786d14b..9f8708bb 100644 --- a/MPF.Processors.Test/PS3CFWTests.cs +++ b/MPF.Processors.Test/PS3CFWTests.cs @@ -91,6 +91,30 @@ namespace MPF.Processors.Test #endregion + #region CheckExistingFiles + + [Fact] + public void CheckExistingFiles_Invalid_Filled() + { + string? baseDirectory = null; + string baseFilename = string.Empty; + var processor = new PS3CFW(RedumpSystem.SonyPlayStation3, MediaType.BluRay); + var actual = processor.CheckExistingFiles(baseDirectory, baseFilename); + Assert.False(actual); + } + + [Fact] + public void CheckExistingFiles_Valid_Empty() + { + string? baseDirectory = Path.Combine(Environment.CurrentDirectory, "TestData", "PS3CFW", "BluRay"); + string baseFilename = "test"; + var processor = new PS3CFW(RedumpSystem.SonyPlayStation3, MediaType.BluRay); + var actual = processor.CheckExistingFiles(baseDirectory, baseFilename); + Assert.True(actual); + } + + #endregion + #region GetDeleteableFilePaths [Fact] diff --git a/MPF.Processors.Test/RedumperTests.cs b/MPF.Processors.Test/RedumperTests.cs index e26149fc..1780cb4e 100644 --- a/MPF.Processors.Test/RedumperTests.cs +++ b/MPF.Processors.Test/RedumperTests.cs @@ -124,6 +124,30 @@ namespace MPF.Processors.Test #endregion + #region CheckExistingFiles + + [Fact] + public void CheckExistingFiles_Invalid_Filled() + { + string? baseDirectory = null; + string baseFilename = string.Empty; + var processor = new Redumper(RedumpSystem.IBMPCcompatible, MediaType.CDROM); + var actual = processor.CheckExistingFiles(baseDirectory, baseFilename); + Assert.False(actual); + } + + [Fact] + public void CheckExistingFiles_Valid_Empty() + { + string? baseDirectory = Path.Combine(Environment.CurrentDirectory, "TestData", "Redumper", "CDROM"); + string baseFilename = "test"; + var processor = new Redumper(RedumpSystem.IBMPCcompatible, MediaType.CDROM); + var actual = processor.CheckExistingFiles(baseDirectory, baseFilename); + Assert.True(actual); + } + + #endregion + #region GetDeleteableFilePaths [Fact] diff --git a/MPF.Processors.Test/UmdImageCreatorTests.cs b/MPF.Processors.Test/UmdImageCreatorTests.cs index d25fb513..90b4d33b 100644 --- a/MPF.Processors.Test/UmdImageCreatorTests.cs +++ b/MPF.Processors.Test/UmdImageCreatorTests.cs @@ -91,6 +91,30 @@ namespace MPF.Processors.Test #endregion + #region CheckExistingFiles + + [Fact] + public void CheckExistingFiles_Invalid_Filled() + { + string? baseDirectory = null; + string baseFilename = string.Empty; + var processor = new UmdImageCreator(RedumpSystem.SonyPlayStationPortable, MediaType.UMD); + var actual = processor.CheckExistingFiles(baseDirectory, baseFilename); + Assert.False(actual); + } + + [Fact] + public void CheckExistingFiles_Valid_Empty() + { + string? baseDirectory = Path.Combine(Environment.CurrentDirectory, "TestData", "UmdImageCreator", "UMD"); + string baseFilename = "test"; + var processor = new UmdImageCreator(RedumpSystem.SonyPlayStationPortable, MediaType.UMD); + var actual = processor.CheckExistingFiles(baseDirectory, baseFilename); + Assert.True(actual); + } + + #endregion + #region GetDeleteableFilePaths [Fact] diff --git a/MPF.Processors.Test/XboxBackupCreatorTests.cs b/MPF.Processors.Test/XboxBackupCreatorTests.cs index d7e3ecc1..362719ed 100644 --- a/MPF.Processors.Test/XboxBackupCreatorTests.cs +++ b/MPF.Processors.Test/XboxBackupCreatorTests.cs @@ -91,6 +91,30 @@ namespace MPF.Processors.Test #endregion + #region CheckExistingFiles + + [Fact] + public void CheckExistingFiles_Invalid_Filled() + { + string? baseDirectory = null; + string baseFilename = string.Empty; + var processor = new XboxBackupCreator(RedumpSystem.MicrosoftXbox, MediaType.DVD); + var actual = processor.CheckExistingFiles(baseDirectory, baseFilename); + Assert.False(actual); + } + + [Fact] + public void CheckExistingFiles_Valid_Empty() + { + string? baseDirectory = Path.Combine(Environment.CurrentDirectory, "TestData", "XboxBackupCreator", "DVD"); + string baseFilename = "test"; + var processor = new XboxBackupCreator(RedumpSystem.MicrosoftXbox, MediaType.DVD); + var actual = processor.CheckExistingFiles(baseDirectory, baseFilename); + Assert.True(actual); + } + + #endregion + #region GetDeleteableFilePaths [Fact] diff --git a/MPF.Processors/BaseProcessor.cs b/MPF.Processors/BaseProcessor.cs index eee42aa3..f6264ffe 100644 --- a/MPF.Processors/BaseProcessor.cs +++ b/MPF.Processors/BaseProcessor.cs @@ -191,6 +191,22 @@ namespace MPF.Processors return CheckRequiredFiles(outputDirectory, outputFilename); } + /// + /// Ensures that no potential output files have been created + /// + /// Output folder to write to + /// Output filename to use as the base path + /// Processor object representing how to process the outputs + /// True if any dumping files exist, False if none + public bool FoundAnyFiles(string? outputDirectory, string outputFilename) + { + // Sanitize the output filename to strip off any potential extension + outputFilename = Path.GetFileNameWithoutExtension(outputFilename); + + // Finally, let the parameters say if all files exist + return CheckExistingFiles(outputDirectory, outputFilename); + } + /// /// Generate artifacts and return them as a dictionary /// @@ -394,6 +410,39 @@ namespace MPF.Processors return missingFiles; } + /// + /// Validate if any output files exist + /// + /// Base directory to check + /// Base filename template to use + /// True if any dumping files exist, False if none + internal bool CheckExistingFiles(string? baseDirectory, string baseFilename) + { + // Assemble a base path + string basePath = baseFilename; + if (!string.IsNullOrEmpty(baseDirectory)) + basePath = Path.Combine(baseDirectory, basePath); + + // Get the list of output files + var outputFiles = GetOutputFiles(baseDirectory, baseFilename); + if (outputFiles.Count == 0) + return false; + + // Check for the log file + if (File.Exists($"{basePath}_logs.zip")) + return true; + + // Check all output files + foreach (var outputFile in outputFiles) + { + // Use the built-in existence function + if (outputFile.Exists(baseDirectory ?? string.Empty)) + return true; + } + + return false; + } + /// /// Generate a list of all deleteable file paths ///