First half of replacing the stub text domain with a media collector. Nothing references this yet - the store is standalone and fully tested before anything depends on it. Blobs are addressed by SHA-256 and sharded two levels deep, so the same picture re-uploaded at a dozen addresses costs one file. Downloads stage in a sibling temp directory on the same volume and are promoted by rename, which is what keeps blobs/ free of truncated files: a crash leaves a stray .part that the next startup sweeps, never a half-image indistinguishable from a real one. The SQLite index holds provenance separately from content, so purging one source leaves blobs another source still references - that is what ref_count buys, and it is recomputed rather than incremented because the item upsert can replace a row pointing at a different blob. The seen_url journal deliberately outlives a purge: without that, the next run downloads again exactly what the user just deleted. Terminal outcomes are split from retryable ones so a flaky network does not permanently lose content. The showcase gives every item a dated, named path via hard links - a second name for one file, not a second file. Hard links are a filesystem privilege rather than a guarantee, so it degrades to copying and records which it achieved; the UI has to be able to admit that. Names suggested by the origin are treated as hostile: only the last path segment survives, Windows device names are pushed aside, and the extension comes from the sniffed kind, never from the remote. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
33 lines
1.5 KiB
XML
33 lines
1.5 KiB
XML
<Project Sdk="Microsoft.NET.Sdk">
|
|
<PropertyGroup>
|
|
<RootNamespace>AvParser.Infrastructure</RootNamespace>
|
|
<!-- [LibraryImport] generates pointer-based marshalling, so the source generator needs this.
|
|
It is here only for the hard-link P/Invokes in Media/HardLink.cs; the BCL has no wrapper
|
|
for CreateHardLink/link(2). Using [DllImport] instead would trip SYSLIB1054, which is an
|
|
error under TreatWarningsAsErrors. -->
|
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
</PropertyGroup>
|
|
|
|
<ItemGroup>
|
|
<ProjectReference Include="..\AvParser.Core\AvParser.Core.csproj" />
|
|
</ItemGroup>
|
|
|
|
<ItemGroup>
|
|
<!-- The feed parsing is internal on purpose — it is an implementation detail of the source,
|
|
not API — but it is also the part most worth testing against captured payloads. -->
|
|
<InternalsVisibleTo Include="AvParser.Infrastructure.Tests" />
|
|
</ItemGroup>
|
|
|
|
<ItemGroup>
|
|
<PackageReference Include="Microsoft.Data.Sqlite" />
|
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
|
<PackageReference Include="Microsoft.Extensions.Http" />
|
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
|
|
<!-- Signal<T> / operators. The UI-free half of the ReactiveUI stack — no Avalonia here. -->
|
|
<PackageReference Include="ReactiveUI.Primitives" />
|
|
<PackageReference Include="Serilog" />
|
|
<PackageReference Include="Serilog.Sinks.Console" />
|
|
<PackageReference Include="Serilog.Sinks.File" />
|
|
</ItemGroup>
|
|
</Project>
|