Post merge master fixes

This commit is contained in:
Carl Johnsen
2025-06-24 14:38:58 +02:00
parent e55c36081f
commit bb87e94ffa
4 changed files with 55 additions and 31 deletions
@@ -1099,45 +1099,59 @@ namespace Duplicati.Library.Main.Database
/// Gets the minimal unique prefix entries for a given fileset ID.
/// This returns the roots of all unique paths in the fileset.
/// </summary>
/// <param name="filesetId">The fileset id</param>
/// <returns>The entries that are unique roots</returns>
public IList<IListFolderEntry> GetMinimalUniquePrefixEntries(long filesetId)
/// <param name="filesetId">The fileset id.</param>
/// <param name="token"> A cancellation token to cancel the operation.</param>
/// <returns>A task that when awaited returns a list of the entries that are unique roots.</returns>
public async IAsyncEnumerable<IListFolderEntry> GetMinimalUniquePrefixEntries(long filesetId, [EnumeratorCancellation] CancellationToken token)
{
var results = new List<IListFolderEntry>();
using var cmd = m_connection.CreateCommand();
await using var cmd = m_connection.CreateCommand();
cmd.SetCommandAndParameters(@"
WITH AllPaths AS (
SELECT fl.""ID"" AS ""FileID"",
SELECT
fl.""ID"" AS ""FileID"",
pp.""Prefix"" || fl.""Path"" AS ""FullPath"",
fl.""BlocksetID"",
b.""Length"",
fe.""Lastmodified""
FROM ""FilesetEntry"" fe
JOIN ""FileLookup"" fl ON fe.""FileID"" = fl.""ID""
JOIN ""PathPrefix"" pp ON fl.""PrefixID"" = pp.""ID""
LEFT JOIN ""Blockset"" b ON fl.""BlocksetID"" = b.""ID""
JOIN ""FileLookup"" fl
ON fe.""FileID"" = fl.""ID""
JOIN ""PathPrefix"" pp
ON fl.""PrefixID"" = pp.""ID""
LEFT JOIN ""Blockset"" b
ON fl.""BlocksetID"" = b.""ID""
WHERE fe.""FilesetID"" = @FilesetId
),
RootCandidates AS (
SELECT a1.*
FROM AllPaths a1
WHERE NOT EXISTS (
SELECT 1 FROM AllPaths a2
WHERE a2.""FullPath"" != a1.""FullPath""
AND a1.""FullPath"" LIKE a2.""FullPath"" || '%'
SELECT 1
FROM AllPaths a2
WHERE
a2.""FullPath"" != a1.""FullPath""
AND a1.""FullPath"" LIKE a2.""FullPath"" || '%'
)
)
SELECT ""FullPath"", ""Length"",
CASE WHEN ""BlocksetID"" = -100 THEN 1 ELSE 0 END AS ""IsDirectory"",
CASE WHEN ""BlocksetID"" = -200 THEN 1 ELSE 0 END AS ""IsSymlink"",
CASE
WHEN ""BlocksetID"" = -100
THEN 1
ELSE 0
END AS ""IsDirectory"",
CASE
WHEN ""BlocksetID"" = -200
THEN 1
ELSE 0
END AS ""IsSymlink"",
""Lastmodified""
FROM RootCandidates
ORDER BY ""FullPath""
");
cmd.SetParameterValue("@FilesetId", filesetId);
")
.SetTransaction(m_rtr)
.SetParameterValue("@FilesetId", filesetId);
foreach (var rd in cmd.ExecuteReaderEnumerable())
await foreach (var rd in cmd.ExecuteReaderEnumerableAsync(token))
{
var path = rd.ConvertValueToString(0) ?? string.Empty;
var size = rd.ConvertValueToInt64(1, -1);
@@ -1145,10 +1159,8 @@ namespace Duplicati.Library.Main.Database
var isSymlink = rd.GetInt32(3) != 0;
var lastModified = new DateTime(rd.ConvertValueToInt64(4, 0), DateTimeKind.Utc);
results.Add(new FolderEntry(path, size, isDir, isSymlink, lastModified));
yield return new FolderEntry(path, size, isDir, isSymlink, lastModified);
}
return results;
}
/// <summary>
@@ -63,7 +63,10 @@ internal static class ListFolderHandler
{
if (folders != null && folders.Length > 1)
throw new UserInformationException("When no folder is specified, only one folder can be listed", "MultipleFoldersFound");
var rootFolders = db.GetMinimalUniquePrefixEntries(filesetIds[0]);
var rootFolders = await db
.GetMinimalUniquePrefixEntries(filesetIds[0], result.TaskControl.ProgressToken)
.ToListAsync(cancellationToken: result.TaskControl.ProgressToken)
.ConfigureAwait(false);
result.Entries = new PaginatedResults<IListFolderEntry>(0, rootFolders.Count, 1, rootFolders.Count, rootFolders);
}
else
@@ -433,9 +433,9 @@ namespace Duplicati.Library.Main.Operation
await backendManager.DeleteAsync(vol.Name, vol.Size, true, m_result.TaskControl.ProgressToken).ConfigureAwait(false);
await backendManager.WaitForEmptyAsync(repairdb, m_result.TaskControl.ProgressToken).ConfigureAwait(false);
await repairdb.Transaction
.CommitAsync("ReplaceFaultyIndexFileCommit")
.CommitAsync("ReplaceFaultyIndexFileCommit", token: cancellationToken)
.ConfigureAwait(false);
m_results.RemoveResult(vol.Name);
m_result.RemoveResult(vol.Name);
}
}
catch (Exception ex)
+16 -7
View File
@@ -337,7 +337,8 @@ namespace Duplicati.UnitTest
]);
var result = await db
.GetMinimalUniquePrefixEntries(1).Select(e => e.Path, CancellationToken.None)
.GetMinimalUniquePrefixEntries(1, CancellationToken.None)
.Select(e => e.Path)
.ToListAsync()
.ConfigureAwait(false);
@@ -363,7 +364,8 @@ namespace Duplicati.UnitTest
]);
var result = await db
.GetMinimalUniquePrefixEntries(1).Select(e => e.Path, CancellationToken.None)
.GetMinimalUniquePrefixEntries(1, CancellationToken.None)
.Select(e => e.Path)
.ToListAsync()
.ConfigureAwait(false);
@@ -387,7 +389,8 @@ namespace Duplicati.UnitTest
]);
var result = await db
.GetMinimalUniquePrefixEntries(1).Select(e => e.Path, CancellationToken.None)
.GetMinimalUniquePrefixEntries(1, CancellationToken.None)
.Select(e => e.Path)
.ToListAsync()
.ConfigureAwait(false);
@@ -414,7 +417,8 @@ namespace Duplicati.UnitTest
]);
var result = await db
.GetMinimalUniquePrefixEntries(1).Select(e => e.Path, CancellationToken.None)
.GetMinimalUniquePrefixEntries(1, CancellationToken.None)
.Select(e => e.Path)
.ToListAsync()
.ConfigureAwait(false);
@@ -429,7 +433,7 @@ namespace Duplicati.UnitTest
}
[Test]
public void GetMinimalUniquePrefixEntries_ShouldReturnExpectedMinimalRoots()
public async Task GetMinimalUniquePrefixEntries_ShouldReturnExpectedMinimalRoots()
{
// Arrange: Prepare prefixes (minimal unique) and contents
var testPrefixes = new[]
@@ -448,10 +452,15 @@ namespace Duplicati.UnitTest
// Act
using var tempFile = new TempFile();
using var db = new LocalListDatabase(tempFile, 1);
await using var db = await LocalListDatabase.CreateAsync(tempFile, null, CancellationToken.None)
.ConfigureAwait(false);
SeedTestData(db, testPrefixes);
var resultItems = db.GetMinimalUniquePrefixEntries(1).ToList();
var resultItems = await db
.GetMinimalUniquePrefixEntries(1, CancellationToken.None)
.ToListAsync()
.ConfigureAwait(false);
var result = resultItems.Select(e => e.Path).ToList();
Assert.That(result, Does.Contain(@"C:\Downloads\testsource\AA\"));