add src file LRU cache

[?]
Apr 22, 2025, 9:02 AM
V55EAIWQXWER2HWKZHPJBV7DDJMSPSPWSO3FSSAYODJHVDBHUN6QC

Dependencies

  • [2] 6YZAVBWU Initial commit
  • [3] IQDCHWCP load a pijul repo
  • [4] SWWE2R6M display basic repo stuff
  • [5] UB2ITZJS refresh changed files on FS changes
  • [6] S2NVIFXR allow to enter record msg
  • [7] YBJRDOTC make all repo actions async
  • [8] KM5PSZ4A watch repo once loaded
  • [9] 2VUX5BTD load identity
  • [10] A5YBC77V record!
  • [11] D7A7MSIH allow to defer or abandon record, add buttons
  • [12] 4WO3ZJM2 show untracked files' contents
  • [13] BJXUYQ2Y show untracked file contents in read-only text editor
  • [14] PTFDJ567 add untracked files encoding
  • [15] AMPZ2BXK show changed files diffs (only Edit atm)
  • [16] EC3TVL4X add untracked files
  • [17] AXSXZQDG fix updating changed file contents, styling
  • [18] WT3GA27P add cursor with selection
  • [19] KT5UYXGK fix selection after adding file, add changed file diffs
  • [20] W7IUT3ZV start recording impl

Change contents

  • edit in crates/flowers_ui/src/main.rs at line 3
    [15.1220]
    [4.4814]
    use clru::{CLruCache, WeightScale};
  • edit in crates/flowers_ui/src/main.rs at line 21
    [15.1427]
    [5.351]
    use std::num::NonZero;
  • edit in crates/flowers_ui/src/main.rs at line 29
    [2.2835]
    [15.1428]
    // Invariant: Must be non-zero
    const SRC_FILES_CACHE_CAPACITY: usize = 1024 * 1024 * 1024;
  • replacement in crates/flowers_ui/src/main.rs at line 74
    [9.678][12.1604:1795]()
    let (untracked_file_load_tx, untracked_file_load_rx) =
    watch::channel("".to_string());
    let untracked_file_load_rx =
    WatchStream::from_changes(untracked_file_load_rx);
    [9.678]
    [12.1795]
    let (src_file_load_tx, src_file_load_rx) = watch::channel("".to_string());
    let untracked_file_load_rx = WatchStream::from_changes(src_file_load_rx);
  • replacement in crates/flowers_ui/src/main.rs at line 79
    [12.1917][12.1917:2084]()
    .map(move |path| (repo_path_clone.clone(), path))
    .then(|(repo_path, path)| async {
    load_untracked_file(repo_path, path).await
    [12.1917]
    [12.2084]
    .map(move |file_path| (repo_path_clone.clone(), file_path))
    .then(|(repo_path, file_path)| async {
    load_src_file(repo_path, file_path).await
  • edit in crates/flowers_ui/src/main.rs at line 85
    [12.2126]
    [12.2126]
    let src_files_cache_capacity =
    NonZero::new(SRC_FILES_CACHE_CAPACITY).unwrap();
  • replacement in crates/flowers_ui/src/main.rs at line 103
    [6.130][12.2268:2347]()
    untracked_file_contents: None,
    untracked_file_load_tx,
    [6.130]
    [15.1455]
    src_files_cache: CLruCache::with_scale(
    src_files_cache_capacity,
    SrcFileCacheWeight,
    ),
    src_file_load_tx,
  • replacement in crates/flowers_ui/src/main.rs at line 123
    [11.58][12.2348:2459]()
    untracked_file_contents: Option<UntrackedFileContents>,
    untracked_file_load_tx: watch::Sender<String>,
    [11.58]
    [15.1513]
    src_files_cache: SrcFilesCache,
    src_file_load_tx: watch::Sender<String>,
  • edit in crates/flowers_ui/src/main.rs at line 128
    [11.60]
    [11.60]
    type SrcFilesCache =
    CLruCache<String, SrcFile, std::hash::RandomState, SrcFileCacheWeight>;
  • edit in crates/flowers_ui/src/main.rs at line 133
    [11.78]
    [12.2460]
    enum SrcFile {
    Loading,
    Loaded(FileEditorContent),
    }
    #[derive(Debug)]
    struct SrcFileCacheWeight;
    impl WeightScale<String, SrcFile> for SrcFileCacheWeight {
    fn weight(&self, key: &String, value: &SrcFile) -> usize {
    let key_weight = key.as_bytes().len();
    let value_weight = match value {
    SrcFile::Loading => 0,
    SrcFile::Loaded(file_editor_content) => match file_editor_content {
    FileEditorContent::Decoded(content) => {
    content.text().as_bytes().len()
    }
    FileEditorContent::ShortBase64(string) => {
    string.as_bytes().len()
    }
    FileEditorContent::UnknownEncoding => 0,
    },
    };
    key_weight + value_weight
    }
    }
    #[derive(Debug)]
  • edit in crates/flowers_ui/src/main.rs at line 181
    [15.1689]
    [14.507]
    #[derive(Debug)]
    enum ChangedFileDiffWithContents {
    Add,
    Edit {
    line: usize,
    deleted: bool,
    content: FileEditorContent,
    },
    Replacement {
    line: usize,
    /// Deleted line
    change_contents: FileEditorContent,
    /// Added lines
    replacement_contents: FileEditorContent,
    },
    }
    #[derive(Debug)]
    pub enum ChangedFileDiffWithoutContents {
    Move,
    Del,
    Undel,
    SolveNameConflict,
    UnsolveNameConflict,
    SolveOrderConflict,
    UnsolveOrderConflict,
    ResurrectZombines,
    AddRoot,
    DelRoot,
    }
  • replacement in crates/flowers_ui/src/main.rs at line 243
    [11.216][14.526:552]()
    LoadedUntrackedFile {
    [11.216]
    [14.552]
    LoadedSrcFile {
  • replacement in crates/flowers_ui/src/main.rs at line 248
    [14.647][13.68:122](),[12.2792][13.68:122]()
    UntrackedFileContentsAction(text_editor::Action),
    [14.647]
    [15.1804]
    UntrackedFileContentsAction {
    path: String,
    action: text_editor::Action,
    },
  • replacement in crates/flowers_ui/src/main.rs at line 260
    [7.6312][7.6312:6347](),[7.6347][12.2793:3001](),[12.3001][7.6410:6487](),[7.6410][7.6410:6487]()
    let untracked_file_selection =
    |repo: &repo::State,
    ix: usize,
    untracked_file_contents: &mut Option<UntrackedFileContents>,
    untracked_file_load_tx: &watch::Sender<String>|
    -> cursor::Selection {
    let path = repo.untracked_files.iter().nth(ix).unwrap().clone();
    [7.6312]
    [12.3002]
    let untracked_file_selection = |repo: &repo::State,
    ix: usize,
    src_files_cache: &mut SrcFilesCache,
    src_file_load_tx: &watch::Sender<
    String,
    >|
    -> cursor::Selection {
    let path = repo.untracked_files.iter().nth(ix).unwrap().clone();
  • replacement in crates/flowers_ui/src/main.rs at line 269
    [12.3003][12.3003:3212]()
    // Load the file
    untracked_file_load_tx.send(path.clone()).unwrap();
    *untracked_file_contents =
    Some(UntrackedFileContents::Loading { path: path.clone() });
    [12.3003]
    [12.3212]
    // Load the file
    load_src_file_if_not_cached(src_files_cache, src_file_load_tx, &path);
  • replacement in crates/flowers_ui/src/main.rs at line 272
    [12.3213][7.6487:6556](),[7.6487][7.6487:6556]()
    cursor::Selection::UntrackedFile { ix, path }
    };
    [12.3213]
    [7.6556]
    cursor::Selection::UntrackedFile { ix, path }
    };
  • replacement in crates/flowers_ui/src/main.rs at line 318
    [12.3406][12.3406:3553]()
    &mut state.untracked_file_contents,
    &state.untracked_file_load_tx,
    [12.3406]
    [12.3553]
    &mut state.src_files_cache,
    &state.src_file_load_tx,
  • replacement in crates/flowers_ui/src/main.rs at line 330
    [12.3732][12.3732:3871]()
    &mut state.untracked_file_contents,
    &state.untracked_file_load_tx,
    [12.3732]
    [12.3871]
    &mut state.src_files_cache,
    &state.src_file_load_tx,
  • replacement in crates/flowers_ui/src/main.rs at line 351
    [12.4046][12.4046:4185]()
    &mut state.untracked_file_contents,
    &state.untracked_file_load_tx,
    [12.4046]
    [12.4185]
    &mut state.src_files_cache,
    &state.src_file_load_tx,
  • replacement in crates/flowers_ui/src/main.rs at line 374
    [12.4353][12.4353:4484]()
    &mut state.untracked_file_contents,
    &state.untracked_file_load_tx,
    [12.4353]
    [12.4484]
    &mut state.src_files_cache,
    &state.src_file_load_tx,
  • replacement in crates/flowers_ui/src/main.rs at line 393
    [12.4656][12.4656:4795]()
    &mut state.untracked_file_contents,
    &state.untracked_file_load_tx,
    [12.4656]
    [12.4795]
    &mut state.src_files_cache,
    &state.src_file_load_tx,
  • replacement in crates/flowers_ui/src/main.rs at line 405
    [12.4958][12.4958:5089]()
    &mut state.untracked_file_contents,
    &state.untracked_file_load_tx,
    [12.4958]
    [12.5089]
    &mut state.src_files_cache,
    &state.src_file_load_tx,
  • replacement in crates/flowers_ui/src/main.rs at line 421
    [12.5260][12.5260:5399]()
    &mut state.untracked_file_contents,
    &state.untracked_file_load_tx,
    [12.5260]
    [12.5399]
    &mut state.src_files_cache,
    &state.src_file_load_tx,
  • replacement in crates/flowers_ui/src/main.rs at line 440
    [12.5579][12.5579:5718]()
    &mut state.untracked_file_contents,
    &state.untracked_file_load_tx,
    [12.5579]
    [12.5718]
    &mut state.src_files_cache,
    &state.src_file_load_tx,
  • replacement in crates/flowers_ui/src/main.rs at line 457
    [12.5889][12.5889:6157]()
    state.untracked_file_load_tx.send(path.clone()).unwrap();
    state.untracked_file_contents =
    Some(UntrackedFileContents::Loading {
    path: path.clone(),
    });
    [12.5889]
    [12.6157]
    load_src_file_if_not_cached(
    &mut state.src_files_cache,
    &state.src_file_load_tx,
    path,
    );
  • replacement in crates/flowers_ui/src/main.rs at line 501
    [12.6371][12.6371:6494]()
    &mut state.untracked_file_contents,
    &state.untracked_file_load_tx,
    [12.6371]
    [12.6494]
    &mut state.src_files_cache,
    &state.src_file_load_tx,
  • replacement in crates/flowers_ui/src/main.rs at line 635
    [9.1055][14.648:687]()
    Message::LoadedUntrackedFile {
    [9.1055]
    [14.687]
    Message::LoadedSrcFile {
  • replacement in crates/flowers_ui/src/main.rs at line 657
    [13.298][12.6579:6814](),[14.1466][12.6579:6814](),[12.6579][12.6579:6814](),[12.6814][13.299:402](),[13.402][14.1467:1508](),[14.1508][13.448:480](),[13.448][13.448:480](),[13.480][12.6894:7059](),[12.6894][12.6894:7059](),[12.7059][14.1509:1541](),[14.1541][12.7082:7208](),[12.7082][12.7082:7208](),[12.7208][13.481:584](),[13.584][14.1542:1583](),[14.1583][13.630:662](),[13.630][13.630:662](),[13.662][12.7288:7310](),[12.7288][12.7288:7310]()
    match &state.untracked_file_contents {
    Some(UntrackedFileContents::Loading { path: loading_path }) => {
    if &path == loading_path {
    state.untracked_file_contents =
    Some(UntrackedFileContents::Loaded {
    path,
    content,
    });
    }
    }
    // Reloaded file
    Some(UntrackedFileContents::Loaded {
    path: loaded_path,
    content: _,
    }) => {
    if &path == loaded_path {
    state.untracked_file_contents =
    Some(UntrackedFileContents::Loaded {
    path,
    content,
    });
    }
    [14.1466]
    [12.7310]
    match state.src_files_cache.get(&path) {
    Some(SrcFile::Loading | SrcFile::Loaded(_)) => {
    src_files_cache_put(
    &mut state.src_files_cache,
    path,
    SrcFile::Loaded(content),
    );
  • replacement in crates/flowers_ui/src/main.rs at line 669
    [13.712][13.712:770]()
    Message::UntrackedFileContentsAction(action) => {
    [13.712]
    [13.770]
    Message::UntrackedFileContentsAction { path, action } => {
  • replacement in crates/flowers_ui/src/main.rs at line 672
    [13.830][13.830:890](),[13.890][14.1584:1650](),[14.1650][13.924:1003](),[13.924][13.924:1003]()
    if let Some(UntrackedFileContents::Loaded {
    content: FileEditorContent::Decoded(content),
    ..
    }) = &mut state.untracked_file_contents
    [13.830]
    [13.1003]
    if let Some(SrcFile::Loaded(
    FileEditorContent::Decoded(mut content),
    ..,
    )) = state.src_files_cache.pop(&path)
  • edit in crates/flowers_ui/src/main.rs at line 678
    [14.1696]
    [15.1995]
    src_files_cache_put(
    &mut state.src_files_cache,
    path,
    SrcFile::Loaded(FileEditorContent::Decoded(content)),
    );
  • edit in crates/flowers_ui/src/main.rs at line 714
    [7.14932]
    [8.359]
    src_files_cache_clear(&mut state.src_files_cache);
  • edit in crates/flowers_ui/src/main.rs at line 758
    [7.15249]
    [7.15249]
    src_files_cache_clear(&mut state.src_files_cache);
  • replacement in crates/flowers_ui/src/main.rs at line 766
    [12.7479][12.7479:7648]()
    state
    .untracked_file_load_tx
    .send(path.clone())
    .unwrap();
    [12.7479]
    [12.7648]
    load_src_file_if_not_cached(
    &mut state.src_files_cache,
    &state.src_file_load_tx,
    &path,
    );
  • replacement in crates/flowers_ui/src/main.rs at line 892
    [12.8146][12.8146:8227]()
    async fn load_untracked_file(repo_path: PathBuf, file_path: String) -> Message {
    [12.8146]
    [12.8227]
    async fn load_src_file(repo_path: PathBuf, file_path: String) -> Message {
  • replacement in crates/flowers_ui/src/main.rs at line 897
    [14.1756][12.8337:8376](),[12.8337][12.8337:8376]()
    Message::LoadedUntrackedFile {
    [14.1756]
    [12.8376]
    Message::LoadedSrcFile {
  • edit in crates/flowers_ui/src/main.rs at line 907
    [2.3224]
    [3.1456]
    fn load_src_file_if_not_cached(
    cache: &mut SrcFilesCache,
    load_tx: &watch::Sender<String>,
    path: &str,
    ) {
    if !cache.contains(path) {
    src_files_cache_put(cache, path.to_string(), SrcFile::Loading);
    load_tx.send(path.to_string()).unwrap();
    }
    }
    fn src_files_cache_put(cache: &mut SrcFilesCache, key: String, value: SrcFile) {
    if let Err((key, value)) = cache.put_with_weight(key, value) {
    let kv_weight = SrcFileCacheWeight.weight(&key, &value);
    info!("Source file cache is too small to hold {key}. Resizing cache to to {kv_weight} fit it.");
    cache.resize(NonZero::new(kv_weight).unwrap());
    let res = cache.put_with_weight(key, value);
    assert!(res.is_ok());
    }
    }
    fn src_files_cache_clear(cache: &mut SrcFilesCache) {
    cache.clear();
    }
  • replacement in crates/flowers_ui/src/main.rs at line 1000
    [12.8696][12.8696:8862](),[12.8862][14.1780:1878]()
    let diff = match &state.untracked_file_contents {
    Some(UntrackedFileContents::Loaded {
    path: loaded_path,
    content,
    }) if loaded_path == path => match content {
    [12.8696]
    [14.1878]
    let diff = match &state.src_files_cache.peek(path) {
    Some(SrcFile::Loaded(content)) => match content {
  • replacement in crates/flowers_ui/src/main.rs at line 1005
    [14.2020][13.1206:1281](),[13.1206][13.1206:1281]()
    .on_action(Message::UntrackedFileContentsAction)),
    [14.2020]
    [14.2021]
    .on_action(|action| Message::UntrackedFileContentsAction{path: path.clone(),action})),
  • replacement in crates/flowers_ui/src/main.rs at line 1013
    [13.1281][12.9217:9266](),[14.2326][12.9217:9266](),[12.9217][12.9217:9266]()
    _ => el(text("Loading...")),
    [14.2326]
    [12.9266]
    Some(SrcFile::Loading) => el(text("Loading...")),
    None => panic!("Unexpectedly, the src file {path} is not even being loaded"),
  • edit in crates/flowers_ui/Cargo.toml at line 20
    [2.3680]
    [2.3681]
    [dependencies.clru]
    workspace = true
  • edit in Cargo.toml at line 28
    [10.5661]
    [14.2368]
    [workspace.dependencies.clru]
    version = "0.6"
  • edit in Cargo.lock at line 842
    [2.17426]
    [2.17426]
    name = "clru"
    version = "0.6.2"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "cbd0f76e066e64fdc5631e3bb46381254deab9ef1158292f27c8c57e3bf3fe59"
    [[package]]
  • edit in Cargo.lock at line 1601
    [2.29995]
    [2.29995]
    "clru",