Add settings, cloud places, and optional archive-content indexing.
Keep official clients in charge of sync while Explorer can group locations, persist UI prefs, and list zip/rar/7z members without extracting them. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -9,12 +9,18 @@ public sealed class UsnChangeApplier
|
||||
private readonly IIndexStore _store;
|
||||
private readonly IFileSystemEnumerator _enumerator;
|
||||
private readonly ILogger<UsnChangeApplier> _logger;
|
||||
private readonly ArchiveContentsIndexer? _archives;
|
||||
|
||||
public UsnChangeApplier(IIndexStore store, IFileSystemEnumerator enumerator, ILogger<UsnChangeApplier> logger)
|
||||
public UsnChangeApplier(
|
||||
IIndexStore store,
|
||||
IFileSystemEnumerator enumerator,
|
||||
ILogger<UsnChangeApplier> logger,
|
||||
ArchiveContentsIndexer? archives = null)
|
||||
{
|
||||
_store = store;
|
||||
_enumerator = enumerator;
|
||||
_logger = logger;
|
||||
_archives = archives;
|
||||
}
|
||||
|
||||
public async Task<UsnReadStatus> ApplyAsync(Source source, IUsnJournal journal, CancellationToken cancellationToken)
|
||||
@@ -64,6 +70,7 @@ public sealed class UsnChangeApplier
|
||||
|
||||
var coalesced = Coalesce(records);
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
var expand = new List<IndexEntry>();
|
||||
await _store.RunWriteAsync(async s =>
|
||||
{
|
||||
foreach (var rec in coalesced)
|
||||
@@ -71,7 +78,11 @@ public sealed class UsnChangeApplier
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
try
|
||||
{
|
||||
await ApplyRecord(s, source, rec, now, cancellationToken).ConfigureAwait(false);
|
||||
var updated = await ApplyRecord(s, source, rec, now, cancellationToken).ConfigureAwait(false);
|
||||
if (updated is not null)
|
||||
{
|
||||
expand.Add(updated);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -82,10 +93,19 @@ public sealed class UsnChangeApplier
|
||||
await s.Sources.UpdateUsnAsync(source.Id, next.JournalId, next.NextUsn, cancellationToken).ConfigureAwait(false);
|
||||
}, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (_archives is { IsEnabled: true })
|
||||
{
|
||||
foreach (var archive in expand)
|
||||
{
|
||||
await _archives.ExpandIfNeededAsync(source, archive, now, source.ScanGeneration, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
return UsnReadStatus.Ok;
|
||||
}
|
||||
|
||||
private async Task ApplyRecord(IIndexStore store, Source source, UsnRecord rec, DateTimeOffset now, CancellationToken cancellationToken)
|
||||
private async Task<IndexEntry?> ApplyRecord(IIndexStore store, Source source, UsnRecord rec, DateTimeOffset now, CancellationToken cancellationToken)
|
||||
{
|
||||
var existing = rec.FileReferenceNumber != 0
|
||||
? await store.Entries.GetByFileIdAsync(source.Id, rec.FileReferenceNumber, cancellationToken).ConfigureAwait(false)
|
||||
@@ -96,9 +116,14 @@ public sealed class UsnChangeApplier
|
||||
if (existing is not null)
|
||||
{
|
||||
await store.Entries.TombstoneAsync(existing.Id, now, cancellationToken).ConfigureAwait(false);
|
||||
if (!existing.IsDirectory && ArchiveFormats.IsArchive(existing.Name))
|
||||
{
|
||||
await store.Entries.TombstoneByPathPrefixAsync(source.Id, existing.PathRel, now, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
var parent = rec.ParentFileReferenceNumber != 0
|
||||
@@ -115,9 +140,14 @@ public sealed class UsnChangeApplier
|
||||
if (existing is not null)
|
||||
{
|
||||
await store.Entries.TombstoneAsync(existing.Id, now, cancellationToken).ConfigureAwait(false);
|
||||
if (!existing.IsDirectory && ArchiveFormats.IsArchive(existing.Name))
|
||||
{
|
||||
await store.Entries.TombstoneByPathPrefixAsync(source.Id, existing.PathRel, now, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
var oldSize = existing is { IsDirectory: false } ? existing.SizeBytes : 0;
|
||||
@@ -150,7 +180,7 @@ public sealed class UsnChangeApplier
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await store.Entries.UpsertAsync(entry, cancellationToken).ConfigureAwait(false);
|
||||
entry.Id = await store.Entries.UpsertAsync(entry, cancellationToken).ConfigureAwait(false);
|
||||
if (!live.IsDirectory)
|
||||
{
|
||||
var delta = live.SizeBytes - oldSize;
|
||||
@@ -164,7 +194,14 @@ public sealed class UsnChangeApplier
|
||||
await store.Entries.ApplySizeDeltaToAncestorsAsync(parent?.Id, delta, 0, 0, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (ArchiveFormats.IsArchive(live.Name))
|
||||
{
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static List<UsnRecord> Coalesce(IReadOnlyList<UsnRecord> records)
|
||||
|
||||
Reference in New Issue
Block a user