AspansQulyp/tests/notes.rs
deni.reyton 45de8f9f51 Qulyp: локальный менеджер паролей на Rust + egui
- Шифрованный файл .qulyp: Argon2id + XChaCha20-Poly1305, атомарная запись и .bak
- Записи с TOTP, папками, избранным и историей паролей; генератор паролей
- Синхронизация через облачную папку с послезаписным слиянием и ручное слияние файлов
- Автоблокировка, автоочистка буфера обмена, тёмная/светлая тема
- Сборка под Windows и Linux, CI для Gitea Actions
- Заметки проекта в notes/ с лимитами строк (tests/notes.rs)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:32:11 +05:00

42 lines
1.6 KiB
Rust

//! Заметки проекта не должны разрастаться: каждый файл в `notes/` объявляет
//! лимит строк в первой строке (`<!-- limit: N -->`), тест следит за ним.
use std::fs;
use std::path::Path;
#[test]
fn notes_fit_their_line_limits() {
let dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("notes");
let mut problems = Vec::new();
let mut checked = 0;
for entry in fs::read_dir(&dir).expect("папка notes/") {
let path = entry.unwrap().path();
if path.extension().is_none_or(|e| e != "md") {
continue;
}
let name = path.file_name().unwrap().to_string_lossy().into_owned();
let text = fs::read_to_string(&path).unwrap();
let first = text.lines().next().unwrap_or_default();
let limit = first
.trim()
.strip_prefix("<!-- limit:")
.and_then(|s| s.strip_suffix("-->"))
.and_then(|s| s.trim().parse::<usize>().ok());
let Some(limit) = limit else {
problems.push(format!("{name}: нет заголовка `<!-- limit: N -->`"));
continue;
};
let lines = text.lines().count();
if lines > limit {
problems.push(format!(
"{name}: {lines} строк при лимите {limit} — сократите (LOG.md: перенесите старое в notes/archive/)"
));
}
checked += 1;
}
assert!(checked > 0, "в notes/ нет ни одного .md");
assert!(problems.is_empty(), "\n{}", problems.join("\n"));
}