Skip to content

Commit 7c49bb8

Browse files
committed
Cover unchanged file drift for #1735
1 parent acdb99b commit 7c49bb8

3 files changed

Lines changed: 42 additions & 0 deletions

File tree

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
category: fixed
3+
issues:
4+
- 1735
5+
affected:
6+
- src/CodeIndex/Database/DbWriter.cs
7+
- tests/CodeIndex.Tests/PreparedCommandCacheTests.cs
8+
---
9+
10+
## English
11+
12+
- **Locked in atomic unchanged-file reuse (#1735)**`GetUnchangedFileId` now has regression coverage ensuring checksum drift does not touch stale file metadata.
13+
14+
## 日本語
15+
16+
- **未変更ファイル再利用の atomic 契約を固定しました (#1735)**`GetUnchangedFileId` に checksum drift 時に古い file metadata を touch しない regression coverage を追加しました。

src/CodeIndex/Database/DbWriter.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,8 @@ private void RunPassiveWalCheckpoint()
482482
if (!SymbolExtractorVersionMatchesCurrent(language))
483483
return null;
484484

485+
// Keep the unchanged check and timestamp touch in one SQLite statement so
486+
// concurrent row drift cannot slip between a SELECT and a later UPDATE (#1735).
485487
var cmd = RentCommand(
486488
@"UPDATE files
487489
SET modified = CASE

tests/CodeIndex.Tests/PreparedCommandCacheTests.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,30 @@ public void DbWriter_WithCache_GetUnchangedFileIdTouchUpdatesTimestamp()
346346
Assert.Equal(touched, reader.GetDateTime(0));
347347
}
348348

349+
[Fact]
350+
public void DbWriter_WithCache_GetUnchangedFileIdDoesNotTouchWhenChecksumDrifts_Issue1735()
351+
{
352+
var writer = new DbWriter(_db);
353+
var initial = new DateTime(2025, 1, 1, 0, 0, 0, DateTimeKind.Utc);
354+
var touched = new DateTime(2025, 6, 1, 0, 0, 0, DateTimeKind.Utc);
355+
356+
writer.UpsertFile(new FileRecord
357+
{
358+
Path = "src/drift.py", Lang = "python", Size = 1, Lines = 1,
359+
Checksum = "old_checksum", Modified = initial,
360+
});
361+
362+
Assert.Null(writer.GetUnchangedFileId("src/drift.py", touched, "new_checksum"));
363+
364+
using var cmd = _db.Connection.CreateCommand();
365+
cmd.CommandText = "SELECT modified, checksum FROM files WHERE path = @p";
366+
cmd.Parameters.AddWithValue("@p", "src/drift.py");
367+
using var reader = cmd.ExecuteReader();
368+
Assert.True(reader.Read());
369+
Assert.Equal(initial, reader.GetDateTime(0));
370+
Assert.Equal("old_checksum", reader.GetString(1));
371+
}
372+
349373
[Fact]
350374
public void DbReader_WithCache_ReusesCSharpResolutionCommandsAcrossReaders()
351375
{

0 commit comments

Comments
 (0)