Improved handling of corrupt backup files

This commit is contained in:
Antony Corbett
2022-07-30 09:21:50 +01:00
parent cf606192af
commit c44ad75b85
11 changed files with 259 additions and 160 deletions

View File

@@ -1,4 +1,9 @@
REM Run from dev command line
@ECHO OFF
VERIFY ON
D:
cd \ProjectsPersonal\JWLMerge
rd JWLMerge\bin /q /s
@@ -6,18 +11,43 @@ rd JWLMergeCLI\bin /q /s
rd Installer\Output /q /s
rd Installer\Staging /q /s
REM build / publish
ECHO.
ECHO Publishing JWLMerge
dotnet publish JWLMerge\JWLMerge.csproj -p:PublishProfile=FolderProfile -c:Release
IF %ERRORLEVEL% NEQ 0 goto ERROR
ECHO.
ECHO Publishing JWLMergeCLI
dotnet publish JWLMergeCLI\JWLMergeCLI.csproj -p:PublishProfile=FolderProfile -c:Release
IF %ERRORLEVEL% NEQ 0 goto ERROR
md Installer\Staging
REM copy items into staging area
ECHO.
ECHO Copying JWLMergeCLI items into staging area
xcopy JWLMergeCLI\bin\Release\net6.0\publish\*.* Installer\Staging /q /s /y /d
ECHO Copying JWLMerge items into staging area
xcopy JWLMerge\bin\Release\net6.0-windows\publish\*.* Installer\Staging /q /s /y /d
REM Create installer
"C:\Program Files (x86)\Inno Setup 6\iscc" Installer\jwlmergesetup.iss
ECHO.
ECHO Creating installer
"D:\Program Files (x86)\Inno Setup 6\iscc" Installer\jwlmergesetup.iss
IF %ERRORLEVEL% NEQ 0 goto ERROR
REM create portable zip
powershell Compress-Archive -Path Installer\Staging\* -DestinationPath Installer\Output\JWLMergePortable.zip
ECHO.
ECHO Creating portable zip
powershell Compress-Archive -Path Installer\Staging\* -DestinationPath Installer\Output\JWLMergePortable.zip
IF %ERRORLEVEL% NEQ 0 goto ERROR
goto SUCCESS
:ERROR
ECHO.
ECHO ******************
ECHO An ERROR occurred!
ECHO ******************
:SUCCESS
PAUSE

View File

@@ -86,7 +86,7 @@ namespace JWLMerge.BackupFileServices
{
throw new ArgumentNullException(nameof(backup));
}
backup.Database.TagMaps.RemoveAll(x => x.TagId == 1);
}

View File

@@ -23,10 +23,13 @@
/// <returns>Number of rows removed.</returns>
public int Clean()
{
return CleanBlockRanges() + CleanLocations();
// see also DatabaseForeignKeyChecker
return CleanBlockRanges() +
CleanTagMaps() +
CleanLocations();
}
private HashSet<int> GetUserMarkIdsInUse()
private HashSet<int> GetValidUserMarkIds()
{
var result = new HashSet<int>();
@@ -38,6 +41,42 @@
return result;
}
private HashSet<int> GetValidTagIds()
{
var result = new HashSet<int>();
foreach (var tag in _database.Tags)
{
result.Add(tag.TagId);
}
return result;
}
private HashSet<int> GetValidNoteIds()
{
var result = new HashSet<int>();
foreach (var note in _database.Notes)
{
result.Add(note.NoteId);
}
return result;
}
private HashSet<int> GetValidLocationIds()
{
var result = new HashSet<int>();
foreach (var location in _database.Locations)
{
result.Add(location.LocationId);
}
return result;
}
private HashSet<int> GetLocationIdsInUse()
{
var result = new HashSet<int>();
@@ -106,6 +145,33 @@
return removed;
}
private int CleanTagMaps()
{
var removed = 0;
var tagMaps = _database.TagMaps;
if (tagMaps.Any())
{
var tagIds = GetValidTagIds();
var noteIds = GetValidNoteIds();
var locationIds = GetValidLocationIds();
foreach (var tag in Enumerable.Reverse(tagMaps))
{
if (!tagIds.Contains(tag.TagId) ||
(tag.NoteId != null && !noteIds.Contains(tag.NoteId.Value)) ||
(tag.LocationId != null && !locationIds.Contains(tag.LocationId.Value)))
{
Log.Logger.Debug($"Removing redundant tag map entry: {tag.TagMapId}");
tagMaps.Remove(tag);
++removed;
}
}
}
return removed;
}
/// <summary>
/// Cleans the block ranges.
/// </summary>
@@ -118,7 +184,7 @@
if (ranges.Any())
{
var userMarkIdsFound = new HashSet<int>();
var userMarkIds = GetUserMarkIdsInUse();
var userMarkIds = GetValidUserMarkIds();
foreach (var range in Enumerable.Reverse(ranges))
{

View File

@@ -5,8 +5,6 @@
internal static class DatabaseForeignKeyChecker
{
// todo: call this as part of the sanity check when loading backup files.
// Also perform auto cleanup
public static void Execute(Database database)
{
CheckBlockRangeValidity(database);

View File

@@ -1,47 +1,48 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Nullable>Enable</Nullable>
<Platforms>AnyCPU</Platforms>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Nullable>Enable</Nullable>
<AnalysisLevel>latest-recommended</AnalysisLevel>
<Platforms>AnyCPU</Platforms>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\SolutionInfo.cs" Link="Properties\SolutionInfo.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\SolutionInfo.cs" Link="Properties\SolutionInfo.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<None Include="..\.editorconfig" Link=".editorconfig" />
</ItemGroup>
<ItemGroup>
<None Include="..\.editorconfig" Link=".editorconfig" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Data.Sqlite" Version="5.0.6" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Serilog" Version="2.10.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Data.Sqlite" Version="5.0.6" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Serilog" Version="2.10.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\JWLMerge.ExcelServices\JWLMerge.ExcelServices.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\JWLMerge.ExcelServices\JWLMerge.ExcelServices.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@@ -1,26 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Nullable>Enable</Nullable>
<Platforms>AnyCPU</Platforms>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Nullable>Enable</Nullable>
<AnalysisLevel>latest-recommended</AnalysisLevel>
<Platforms>AnyCPU</Platforms>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\SolutionInfo.cs" Link="Properties\SolutionInfo.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\SolutionInfo.cs" Link="Properties\SolutionInfo.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="ClosedXML" Version="0.95.4" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="ClosedXML" Version="0.95.4" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<None Include="..\.editorconfig" Link=".editorconfig" />
</ItemGroup>
<ItemGroup>
<None Include="..\.editorconfig" Link=".editorconfig" />
</ItemGroup>
</Project>

View File

@@ -1,26 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Nullable>Enable</Nullable>
<IsPackable>false</IsPackable>
<Platforms>AnyCPU</Platforms>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Nullable>Enable</Nullable>
<IsPackable>false</IsPackable>
<AnalysisLevel>latest-recommended</AnalysisLevel>
<Platforms>AnyCPU</Platforms>
</PropertyGroup>
<ItemGroup>
<None Include="..\.editorconfig" Link=".editorconfig" />
</ItemGroup>
<ItemGroup>
<None Include="..\.editorconfig" Link=".editorconfig" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
<PackageReference Include="MSTest.TestAdapter" Version="2.1.1" />
<PackageReference Include="MSTest.TestFramework" Version="2.1.1" />
<PackageReference Include="coverlet.collector" Version="1.3.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
<PackageReference Include="MSTest.TestAdapter" Version="2.1.1" />
<PackageReference Include="MSTest.TestFramework" Version="2.1.1" />
<PackageReference Include="coverlet.collector" Version="1.3.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\JWLMerge.BackupFileServices\JWLMerge.BackupFileServices.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\JWLMerge.BackupFileServices\JWLMerge.BackupFileServices.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,58 +1,59 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Nullable>Enable</Nullable>
<ApplicationIcon>JWLMerge.ico</ApplicationIcon>
<Platforms>AnyCPU</Platforms>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\SolutionInfo.cs" Link="Properties\SolutionInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="..\.editorconfig" Link=".editorconfig" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MaterialDesignThemes" Version="4.1.0" />
<PackageReference Include="Microsoft.AppCenter.Analytics" Version="4.4.0" />
<PackageReference Include="Microsoft.AppCenter.Crashes" Version="4.4.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.1" />
<PackageReference Include="Microsoft.Toolkit.Mvvm" Version="7.0.2" />
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
<PackageReference Include="Microsoft.Windows.Compatibility" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\JWLMerge.BackupFileServices\JWLMerge.BackupFileServices.csproj" />
<ProjectReference Include="..\JWLMerge.ExcelServices\JWLMerge.ExcelServices.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Settings.Designer.cs">
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<None Update="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Nullable>Enable</Nullable>
<AnalysisLevel>latest-recommended</AnalysisLevel>
<ApplicationIcon>JWLMerge.ico</ApplicationIcon>
<Platforms>AnyCPU</Platforms>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\SolutionInfo.cs" Link="Properties\SolutionInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="..\.editorconfig" Link=".editorconfig" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MaterialDesignThemes" Version="4.1.0" />
<PackageReference Include="Microsoft.AppCenter.Analytics" Version="4.4.0" />
<PackageReference Include="Microsoft.AppCenter.Crashes" Version="4.4.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.1" />
<PackageReference Include="Microsoft.Toolkit.Mvvm" Version="7.0.2" />
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
<PackageReference Include="Microsoft.Windows.Compatibility" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\JWLMerge.BackupFileServices\JWLMerge.BackupFileServices.csproj" />
<ProjectReference Include="..\JWLMerge.ExcelServices\JWLMerge.ExcelServices.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Settings.Designer.cs">
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<None Update="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
<!-- Add this as a new ItemGroup, replacing paths and names appropriately -->

View File

@@ -535,7 +535,7 @@ namespace JWLMerge.ViewModel
await Task.Run(() =>
{
count = _backupFileService.RedactNotes(file.BackupFile);
_backupFileService.WriteNewDatabase(file.BackupFile, filePath!, filePath!);
_backupFileService.WriteNewDatabaseWithClean(file.BackupFile, filePath!, filePath!);
});
_windowService.Close(filePath!);
@@ -582,7 +582,7 @@ namespace JWLMerge.ViewModel
await Task.Run(() =>
{
_backupFileService.RemoveFavourites(file!.BackupFile);
_backupFileService.WriteNewDatabase(file.BackupFile, filePath!, filePath!);
_backupFileService.WriteNewDatabaseWithClean(file.BackupFile, filePath!, filePath!);
});
_snackbarService.Enqueue("Favourites removed successfully");

View File

@@ -1,19 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Nullable>Enable</Nullable>
<ApplicationIcon>JWLMerge.ico</ApplicationIcon>
<Platforms>AnyCPU</Platforms>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\SolutionInfo.cs" Link="Properties\SolutionInfo.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\JWLMerge.BackupFileServices\JWLMerge.BackupFileServices.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Nullable>Enable</Nullable>
<ApplicationIcon>JWLMerge.ico</ApplicationIcon>
<AnalysisLevel>latest-recommended</AnalysisLevel>
<Platforms>AnyCPU</Platforms>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\SolutionInfo.cs" Link="Properties\SolutionInfo.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\JWLMerge.BackupFileServices\JWLMerge.BackupFileServices.csproj" />
</ItemGroup>
</Project>

View File

@@ -6,4 +6,4 @@
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("2.0.0.10")]
[assembly: AssemblyVersion("2.0.0.12")]