Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,15 @@ private async Task<ScanDiscoveryResult> EnrichWithMetadataAsync(
pinnedAuthority,
discovery,
candidate);
// The lease deliberately separates stable byte access from public media
// identity, and the single-path overload collapses the two. On Linux the
// metadata path is a /proc descriptor link with no extension, so collapsing
// it makes the probe's audio-extension guard reject the candidate before
// ffprobe runs.
var metadata = await metadataService.ExtractFileMetadataAsync(
pinnedMetadataFile.MetadataPath);
new MetadataFileSource(
pinnedMetadataFile.MetadataPath,
candidate));
if (metadata != null
&& ScanFileDiscovery.MetadataMatchesAudiobook(metadata, audiobook))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public async Task ScanAsync_CaseDistinctMetadataFolders_RemainConflicting()
var lowerFile = Path.Join(lowerDirectory, "part-b.m4b");
var metadata = new Mock<IMetadataService>(MockBehavior.Strict);
metadata.Setup(service => service.ExtractFileMetadataAsync(
It.IsAny<string>()))
It.IsAny<MetadataFileSource>()))
.ReturnsAsync(MatchingMetadata());
Init(services => services.WithSingleton<IMetadataService>(metadata.Object));
Directory.CreateDirectory(upperDirectory);
Expand Down Expand Up @@ -65,7 +65,7 @@ await _applicationSettingsRepository.SaveAsync(
Assert.Contains(result.Diagnostics, diagnostic =>
diagnostic.Code == "MetadataAttributionConflict");
metadata.Verify(
service => service.ExtractFileMetadataAsync(It.IsAny<string>()),
service => service.ExtractFileMetadataAsync(It.IsAny<MetadataFileSource>()),
Times.Exactly(2));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,14 @@ public async Task ScanAsync_MetadataReplacementAndRestore_ReadsPinnedFileGenerat
"unrelated.m4b",
"Original Book");
var displaced = Path.Join(root, "original-generation.bin");
var observedSources = new List<MetadataFileSource>();
var metadata = new Mock<IMetadataService>(MockBehavior.Strict);
metadata.Setup(service => service.ExtractFileMetadataAsync(
It.IsAny<string>()))
.Returns<string>(async extractionPath =>
It.IsAny<MetadataFileSource>()))
.Returns<MetadataFileSource>(async fileSource =>
{
observedSources.Add(fileSource);
var extractionPath = fileSource.ReadPath;
var displacedOriginal = false;
try
{
Expand Down Expand Up @@ -190,8 +193,17 @@ public async Task ScanAsync_MetadataReplacementAndRestore_ReadsPinnedFileGenerat
await _audiobookFileRepository.GetByAudiobookIdAsync(audiobook.Id));
Assert.Equal("Original Book", await File.ReadAllTextAsync(candidate));
metadata.Verify(
service => service.ExtractFileMetadataAsync(It.IsAny<string>()),
service => service.ExtractFileMetadataAsync(It.IsAny<MetadataFileSource>()),
Times.Once);

// The two halves of the source do different jobs and both matter here. ReadPath is the
// pinned generation, which is what the assertions above prove was read even while the
// visible file was swapped. PublicPath is the file as a person sees it, and it has to
// keep its real name: on Linux ReadPath is a /proc descriptor link with no extension,
// so anything deriving identity from it loses the extension entirely.
var observed = Assert.Single(observedSources);
Assert.Equal(candidate, observed.PublicPath);
Assert.Equal(".m4b", Path.GetExtension(observed.PublicPath));
}

[Fact]
Expand Down