Run the formatter over the face branch before it reaches CI
🐳 Android image / Build and push (push) Successful in 2s
Build and test / android-image (push) Successful in 2s
Build and test / Desktop (Linux) (push) Successful in 1h21m32s
Build and test / Layer separation (push) Successful in 37s
Traceability / Requirement traces (push) Successful in 25s
Build and test / Android (aarch64) (push) Failing after 33m58s

The merge of the SCRFD/MobileFaceNet work brought 69 rustfmt diffs across
dr-catalog, dr-face and dr-ui with it, so `cargo fmt --all -- --check` fails
on master and the Desktop job stops at its Format step — before clippy, the
tests or the release build have run at all. That makes the whole desktop
half of CI blind: a real compile error behind this would look exactly the
same from the outside. There was nothing behind it, as it turns out — with
the formatting fixed, clippy, the test suite and the release build all pass.

Every .rs hunk is `cargo fmt --all` on the pinned 1.92.0 toolchain, not a
hand edit, but it is worth being precise about what that moved, because it
is more than whitespace. Besides reflowing signatures and call chains,
rustfmt reordered the `pub mod` and `pub use` items in dr-face/src/lib.rs so
the `#[cfg(feature = "inference")]` entries sort in place, added the trailing
semicolon inside `let ... else { return }` bodies in identity_ui.rs, wrapped
a bare closure body in braces in cluster.rs, adjusted trailing commas, and
dropped a stray blank line at the end of identity_ui.rs. All of it is
semantically inert; none of it changes behaviour.

docs/traceability.md rides along because it has to. The matrix records each
TRACES tag by line number, and reflowing develop.rs, lib.rs, faces.rs,
identity.rs and identity_ui.rs moved them — FR-CAT-8, FR-CAT-9, FR-CULL-10,
FR-DEV-3, FR-DEV-3a and FR-DEV-3c all shift by a line or two. The matrix was
verified up to date on d777f7f before this commit, so this is drift these
formatting changes introduced, not pre-existing staleness being swept up.
Leaving it for a follow-up commit would hand traceability-check.yml a
failure caused entirely by a whitespace change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-27 13:12:49 +02:00
co-authored by Claude Opus 5
parent d777f7f44d
commit b846b312b8
18 changed files with 285 additions and 207 deletions
+13 -4
View File
@@ -247,7 +247,8 @@ impl FaceShardStore {
}
pub fn shard_path(&self, shard: u32) -> PathBuf {
self.dir.join(format!("shard-{}-{shard:04}.sqlite", self.client))
self.dir
.join(format!("shard-{}-{shard:04}.sqlite", self.client))
}
/// Every shard, with whether it is sealed.
@@ -300,7 +301,8 @@ impl FaceShardStore {
rusqlite::OpenFlags::SQLITE_OPEN_READ_ONLY | rusqlite::OpenFlags::SQLITE_OPEN_NO_MUTEX,
)?;
let mut q = src.prepare("SELECT file_id, model_id, faces_found, source_edge FROM indexed")?;
let mut q =
src.prepare("SELECT file_id, model_id, faces_found, source_edge FROM indexed")?;
let images: Vec<(i64, String, i64, i64)> = q
.query_map([], |r| Ok((r.get(0)?, r.get(1)?, r.get(2)?, r.get(3)?)))?
.collect::<Result<_, _>>()?;
@@ -357,7 +359,10 @@ impl FaceShardStore {
FROM faces WHERE file_id = ?1 AND model_id = ?2",
)?;
let faces: Vec<SharedFace> = q
.query_map(rusqlite::params![file_id as i64, model_id], read_shared_face)?
.query_map(
rusqlite::params![file_id as i64, model_id],
read_shared_face,
)?
.collect::<Result<_, _>>()?;
Ok(Some((faces, edge as u32)))
}
@@ -699,7 +704,11 @@ mod tests {
}
let shards = s.shards().unwrap();
assert!(shards.len() >= 2, "expected a seal, got {} shard(s)", shards.len());
assert!(
shards.len() >= 2,
"expected a seal, got {} shard(s)",
shards.len()
);
assert!(shards[0].sealed, "the first shard should be sealed");
assert!(
shards[0].bytes <= SHARD_MAX_BYTES,
+25 -27
View File
@@ -364,10 +364,7 @@ pub type StoredEmbedding = (FaceId, ImageId, Vec<u8>, f32);
/// Returned as raw f16 blobs rather than decoded vectors: the caller is
/// `dr-face`, which owns the decoding, and a catalog that widened them here
/// would double the memory of the one operation that holds them all at once.
pub fn embeddings(
conn: &Connection,
model_id: &str,
) -> Result<Vec<StoredEmbedding>, CatalogError> {
pub fn embeddings(conn: &Connection, model_id: &str) -> Result<Vec<StoredEmbedding>, CatalogError> {
let mut q = conn.prepare(
"SELECT id, image_id, embedding, crop_px FROM faces
WHERE model_id = ?1 ORDER BY id",
@@ -401,11 +398,7 @@ pub fn create_person(conn: &Connection, name: &str) -> Result<PersonId, CatalogE
}
/// Rename a person. The identity is untouched.
pub fn rename_person(
conn: &Connection,
person: PersonId,
name: &str,
) -> Result<(), CatalogError> {
pub fn rename_person(conn: &Connection, person: PersonId, name: &str) -> Result<(), CatalogError> {
conn.execute(
"UPDATE people SET name = ?2, revision = revision + 1, modified = ?3
WHERE id = ?1",
@@ -483,10 +476,7 @@ pub fn merge_people(
}
/// Follow a merge redirect to the person that outlived it.
pub fn resolve_person(
conn: &Connection,
person: PersonId,
) -> Result<PersonId, CatalogError> {
pub fn resolve_person(conn: &Connection, person: PersonId) -> Result<PersonId, CatalogError> {
let mut at = person;
// Bounded rather than `loop`: a redirect cycle would otherwise hang the UI
// thread, and a corrupt index is exactly the case this has to survive.
@@ -546,11 +536,7 @@ pub fn suggest(
}
/// The user says this face is this person.
pub fn confirm(
conn: &Connection,
face: FaceId,
person: PersonId,
) -> Result<(), CatalogError> {
pub fn confirm(conn: &Connection, face: FaceId, person: PersonId) -> Result<(), CatalogError> {
let tx = conn.unchecked_transaction()?;
// Confirming overrides an earlier rejection of the same pair: the user has
// changed their mind, and the newer judgement is the one that counts.
@@ -576,11 +562,7 @@ pub fn confirm(
/// Stored rather than implied by removal, so the next clustering pass does not
/// re-suggest it. This is user data in the same sense a confirmation is
/// (FR-CULL-12) — a judgement, just a negative one.
pub fn reject(
conn: &Connection,
face: FaceId,
person: PersonId,
) -> Result<(), CatalogError> {
pub fn reject(conn: &Connection, face: FaceId, person: PersonId) -> Result<(), CatalogError> {
let tx = conn.unchecked_transaction()?;
tx.execute(
"INSERT OR IGNORE INTO face_person_rejected (face_id, person_id)
@@ -601,7 +583,10 @@ pub fn reject(
/// the pool for the next clustering pass to place. Rejection is "not this
/// person", and is remembered.
pub fn unassign(conn: &Connection, face: FaceId) -> Result<(), CatalogError> {
conn.execute("DELETE FROM face_person WHERE face_id = ?1", [face.0 as i64])?;
conn.execute(
"DELETE FROM face_person WHERE face_id = ?1",
[face.0 as i64],
)?;
Ok(())
}
@@ -873,7 +858,13 @@ mod tests {
y: 0.1,
w: 0.2,
h: 0.3,
landmarks: [(0.1, 0.1), (0.2, 0.1), (0.15, 0.2), (0.12, 0.25), (0.18, 0.25)],
landmarks: [
(0.1, 0.1),
(0.2, 0.1),
(0.15, 0.2),
(0.12, 0.25),
(0.18, 0.25),
],
confidence: 0.9,
embedding: vec![seed; 1024],
crop_px: 180.0,
@@ -932,7 +923,11 @@ mod tests {
let got = for_image(&c, img).unwrap();
assert_eq!(got.len(), 1);
assert_eq!(got[0].person, Some(anna), "confirmation was lost on re-index");
assert_eq!(
got[0].person,
Some(anna),
"confirmation was lost on re-index"
);
assert!(got[0].confirmed);
}
@@ -962,7 +957,10 @@ mod tests {
assert_eq!(for_image(&c, img).unwrap()[0].person, None);
let again = suggest(&c, ids[0], anna, 0.95).unwrap();
assert!(!again, "clustering re-suggested a face the user pushed away");
assert!(
!again,
"clustering re-suggested a face the user pushed away"
);
}
#[test]