test selection reindexing

[?]
Jun 1, 2025, 12:53 PM
ESMM3FELOBYIX7FUNOU37FYKRJHFU2IMX6LY6EGJTVPTBDU3SEEQC

Dependencies

  • [2] YBJRDOTC make all repo actions async
  • [3] 4WO3ZJM2 show untracked files' contents
  • [4] V55EAIWQ add src file LRU cache
  • [5] NRCUG4R2 load changed files src when selected
  • [6] Y5ATDI2H convert changed file diffs and load src only if any needs it
  • [7] ZVI4AWER woot contents_diff
  • [8] JE44NYHM display log files diffs
  • [9] 4ELJZGRJ load and store all change diffs at once
  • [10] HC7ROIBC move main diffs state out of cursor
  • [11] BFN2VHZS refactor file stuff into sub-mod
  • [12] WGID4LS4 absolutely slayed testing with iced task
  • [13] VCNKFNUF app init test
  • [14] ACDXXAX2 refactor main's updates into smaller fns
  • [15] I56UGW7U make record test, fix log update
  • [16] KMB6FND3 test view update fn rather than direct fn calls
  • [17] YYKXNBFL test: add untracked file
  • [18] 5CYU7UT7 test: rm added file
  • [19] FDDPOH5R add arrow controls
  • [20] AMPZ2BXK show changed files diffs (only Edit atm)
  • [21] WT3GA27P add cursor with selection
  • [22] KM5PSZ4A watch repo once loaded
  • [23] AHWWRC73 navigate log entries
  • [24] ONRCENKT rm unnecessary state from repo's internal state
  • [25] OQ6HSAWH show record log
  • [26] 23SFYK4Q big view refactor into a new crate
  • [*] 6YZAVBWU Initial commit

Change contents

  • replacement in inflorescence/src/test.rs at line 2
    [15.1320][16.34:87]()
    use crate::{cursor, init, task, update, Msg, State};
    [15.1320]
    [15.1428]
    use crate::{cursor, init, reindex_selection, task, update, Msg, State};
  • replacement in inflorescence/src/test.rs at line 5
    [15.1488][13.2552:2578](),[13.2552][13.2552:2578]()
    use libflorescence::repo;
    [15.1488]
    [15.1489]
    use libflorescence::prelude::pijul;
  • edit in inflorescence/src/test.rs at line 9
    [15.1581]
    [13.2643]
    use libflorescence::{file, repo};
  • replacement in inflorescence/src/test.rs at line 265
    [17.159][17.159:187]()
    /// Test add untracked file
    [17.159]
    [17.187]
    /// Test add and rm untracked file
  • replacement in inflorescence/src/test.rs at line 329
    [17.2098][17.2098:2189]()
    Msg::FromRepo(repo::MsgOut::AddedUntrackedFile { path }) if path == file_to_record
    [17.2098]
    [17.2189]
    Msg::FromRepo(repo::MsgOut::AddedUntrackedFile { path })
    if path == file_to_record
  • replacement in inflorescence/src/test.rs at line 371
    [18.630][18.630:716]()
    Msg::FromRepo(repo::MsgOut::RmedAddedFile { path }) if path == file_to_record
    [18.630]
    [18.716]
    Msg::FromRepo(repo::MsgOut::RmedAddedFile { path })
    if path == file_to_record
  • edit in inflorescence/src/test.rs at line 384
    [17.2710]
    [17.2710]
    /// When the repo is refreshed we try to re-index the selection if it's still
    /// present.
    ///
    /// If the selection is still present we must perform different actions
    /// depending on the selection type:
    ///
    /// - untracked file: We should start loading the file
    /// - changed file: Load the file if the diff has any contents
    /// - log change: Request the diffs
    ///
    /// If the selection is not present any more, no action must be taken.
    #[test(tokio::test)]
    async fn test_reindex_selection() {
    let TestState {
    mut state,
    tasks: _tasks,
    fs_watch_task: _,
    id: _,
    repo: _,
    } = setup_state().await;
    let repo::State {
    dir_name: _,
    channel: _,
    untracked_files,
    changed_files,
    log,
    } = &state.repo.as_ref().unwrap();
    // _________________________________________________________________________
    // Case: no current selection
    assert!(state.cursor.selection.is_none());
    let task = reindex_selection(
    &mut state.cursor,
    &mut state.files,
    untracked_files,
    changed_files,
    log,
    );
    assert!(state.cursor.selection.is_none());
    assert!(state.files.diffs_cache.inner.is_empty());
    assert!(task.is_none());
    // _________________________________________________________________________
    // Case: untracked file selection present after refresh, index is increased
  • edit in inflorescence/src/test.rs at line 435
    [17.2711]
    [15.4747]
    let untracked_files = BTreeSet::from_iter([
    "untracked_0.rs".to_string(),
    "untracked_1.rs".to_string(),
    "untracked_2.rs".to_string(),
    ]);
    state.cursor.selection = Some(cursor::Selection::UntrackedFile {
    ix: 0,
    path: "untracked_1.rs".to_string(),
    });
    let task = reindex_selection(
    &mut state.cursor,
    &mut state.files,
    &untracked_files,
    changed_files,
    log,
    );
    assert!(state.cursor.selection.is_some());
    assert_matches!(
    state.cursor.selection.as_ref().unwrap(),
    libflorescence::cursor::Selection::UntrackedFile { ix, path }
    if *ix == 1 && path == "untracked_1.rs"
    );
    assert!(task.is_none());
    assert_eq!(state.files.diffs_cache.inner.len(), 1);
    assert_matches!(
    state.files.diffs_cache.inner.peek(&file::Id {
    path: "untracked_1.rs".to_string(),
    file_kind: file::Kind::Untracked
    }),
    Some(file::Diff::Loading)
    );
    // Clear the cache for next test case
    state.files.diffs_cache.inner.clear();
    // _________________________________________________________________________
    // Case: untracked file selection not present after refresh
    state.cursor.selection = Some(cursor::Selection::UntrackedFile {
    ix: 0,
    path: "untracked_gone.rs".to_string(),
    });
    let task = reindex_selection(
    &mut state.cursor,
    &mut state.files,
    &untracked_files,
    changed_files,
    log,
    );
    assert!(state.cursor.selection.is_none());
    assert!(task.is_none());
    assert!(state.files.diffs_cache.inner.is_empty());
    // _________________________________________________________________________
    // Case: changed file selection present after refresh, index is decreased,
    // file has diffs with contents
    let changed_files = repo::ChangedFiles::from_iter([
    (
    "changed_0.rs".to_string(),
    BTreeSet::from_iter([repo::ChangedFileDiff::Add]),
    ),
    ("changed_1.rs".to_string(), BTreeSet::new()),
    ("changed_2.rs".to_string(), BTreeSet::new()),
    ]);
    state.cursor.selection = Some(cursor::Selection::ChangedFile {
    ix: 1,
    path: "changed_0.rs".to_string(),
    });
    let task = reindex_selection(
    &mut state.cursor,
    &mut state.files,
    &untracked_files,
    &changed_files,
    log,
    );
    assert!(state.cursor.selection.is_some());
    assert_matches!(
    state.cursor.selection.as_ref().unwrap(),
    libflorescence::cursor::Selection::ChangedFile { ix, path }
    if *ix == 0 && path == "changed_0.rs"
    );
    assert!(task.is_none());
    assert_eq!(state.files.diffs_cache.inner.len(), 1);
    assert_matches!(
    state.files.diffs_cache.inner.peek(&file::Id {
    path: "changed_0.rs".to_string(),
    file_kind: file::Kind::Changed
    }),
    Some(file::Diff::Loading)
    );
    // Clear the cache for next test case
    state.files.diffs_cache.inner.clear();
    // _________________________________________________________________________
    // Case: changed file selection present after refresh, index is the same,
    // but file has no diffs with contents
    state.cursor.selection = Some(cursor::Selection::ChangedFile {
    ix: 1,
    path: "changed_1.rs".to_string(),
    });
    let task = reindex_selection(
    &mut state.cursor,
    &mut state.files,
    &untracked_files,
    &changed_files,
    log,
    );
    assert!(state.cursor.selection.is_some());
    assert_matches!(
    state.cursor.selection.as_ref().unwrap(),
    libflorescence::cursor::Selection::ChangedFile { ix, path }
    if *ix == 1 && path == "changed_1.rs"
    );
    assert!(task.is_none());
    assert!(state.files.diffs_cache.inner.is_empty());
    // _________________________________________________________________________
    // Case: changed file selection not present after refresh
    state.cursor.selection = Some(cursor::Selection::ChangedFile {
    ix: 0,
    path: "changed_gone.rs".to_string(),
    });
    let task = reindex_selection(
    &mut state.cursor,
    &mut state.files,
    &untracked_files,
    &changed_files,
    log,
    );
    assert!(state.cursor.selection.is_none());
    assert!(task.is_none());
    assert!(state.files.diffs_cache.inner.is_empty());
    // _________________________________________________________________________
    // Case: log selection present after refresh
    let change_hash = |bytes: &[u8]| {
    let mut hasher = pijul::pristine::Hasher::default();
    hasher.update(bytes);
    hasher.finish()
    };
    let change_hash_0 = change_hash(&[0]);
    let change_hash_1 = change_hash(&[1]);
    let change_hash_2 = change_hash(&[2]);
    let log = vec![
    repo::LogEntry {
    hash: change_hash_0,
    message: "".to_string(),
    file_paths: vec![],
    },
    repo::LogEntry {
    hash: change_hash_1,
    message: "".to_string(),
    file_paths: vec![],
    },
    repo::LogEntry {
    hash: change_hash_2,
    message: "".to_string(),
    file_paths: vec![],
    },
    ];
    state.cursor.selection = Some(cursor::Selection::LogChange {
    ix: 0,
    hash: change_hash_2,
    message: "".to_string(),
    diffs: None,
    file: None,
    });
    let task = reindex_selection(
    &mut state.cursor,
    &mut state.files,
    &untracked_files,
    &changed_files,
    &log,
    );
    assert!(state.cursor.selection.is_some());
    assert_matches!(
    state.cursor.selection.as_ref().unwrap(),
    libflorescence::cursor::Selection::LogChange { ix, hash, .. }
    if *ix == 2 && *hash == change_hash_2
    );
    assert!(task.is_some());
    assert!(state.files.diffs_cache.inner.is_empty());
    // _________________________________________________________________________
    // Case: log selection not present after refresh
    state.cursor.selection = Some(cursor::Selection::UntrackedFile {
    ix: 0,
    path: "log_gone.rs".to_string(),
    });
    let task = reindex_selection(
    &mut state.cursor,
    &mut state.files,
    &untracked_files,
    &changed_files,
    &log,
    );
    assert!(state.cursor.selection.is_none());
    assert!(task.is_none());
    assert!(state.files.diffs_cache.inner.is_empty());
    }
  • edit in inflorescence/src/task.rs at line 29
    [12.705]
    [12.705]
    }
    pub fn is_none(&self) -> bool {
    self.stream.is_none()
    }
    pub fn is_some(&self) -> bool {
    self.stream.is_some()
  • replacement in inflorescence/src/main.rs at line 29
    [12.5338][12.5338:5369]()
    use std::collections::HashMap;
    [12.5338]
    [12.5369]
    use std::collections::{BTreeSet, HashMap};
  • replacement in inflorescence/src/main.rs at line 482
    [14.9475][14.9475:9641]()
    let task = if let Some(selection) = state.cursor.selection.take() {
    // Try to find the file with the same name. If not found, remove
    // selection
    [14.9475]
    [14.9641]
    let task = reindex_selection(
    &mut state.cursor,
    &mut state.files,
    untracked_files,
    changed_files,
    log,
    );
    state.repo = Some(repo);
    task
    }
    /// Try to find the file with the same name. If not found, remove selection
    fn reindex_selection(
    cursor: &mut cursor::State,
    files: &mut file::State,
    untracked_files: &BTreeSet<String>,
    changed_files: &repo::ChangedFiles,
    log: &repo::Log,
    ) -> Task<Msg> {
    if let Some(selection) = cursor.selection.take() {
  • edit in inflorescence/src/main.rs at line 506
    [14.9757][14.9757:10021](),[11.784][2.15249:15250](),[4.5309][2.15249:15250](),[14.10021][2.15249:15250](),[7.14023][2.15249:15250](),[2.15249][2.15249:15250]()
    file::load_src_file_if_not_cached(
    &mut state.files,
    file::Id {
    path: path.clone(),
    file_kind: file::Kind::Untracked,
    },
    );
  • replacement in inflorescence/src/main.rs at line 512
    [14.10299][14.10299:10329]()
    path,
    [14.10299]
    [14.10329]
    path: path.clone(),
  • edit in inflorescence/src/main.rs at line 514
    [14.10353]
    [14.10353]
    if selection.is_some() {
    file::load_src_file_if_not_cached(
    files,
    file::Id {
    path,
    file_kind: file::Kind::Untracked,
    },
    );
    }
  • edit in inflorescence/src/main.rs at line 528
    [14.10473][14.10473:10597](),[14.10597][11.785:929](),[10.1629][11.785:929](),[11.929][7.14292:14344](),[7.14292][7.14292:14344](),[7.14344][14.10598:10662](),[11.996][7.14408:14439](),[14.10662][7.14408:14439](),[7.14408][7.14408:14439](),[6.2576][4.5507:5534](),[7.14439][4.5507:5534](),[4.5507][4.5507:5534](),[8.13481][3.8120:8142](),[3.8120][3.8120:8142](),[3.8142][14.10663:10682]()
    if let Some(diffs) = changed_files.get(&path) {
    if diff::any_diff_has_contents(diffs) {
    file::load_src_file_if_not_cached(
    &mut state.files,
    file::Id {
    path: path.clone(),
    file_kind: file::Kind::Changed,
    },
    );
    }
    }
  • edit in inflorescence/src/main.rs at line 538
    [14.11112]
    [14.11112]
    if selection.is_some() {
    if let Some(diffs) = changed_files.get(&path) {
    if diff::any_diff_has_contents(diffs) {
    file::load_src_file_if_not_cached(
    files,
    file::Id {
    path: path.clone(),
    file_kind: file::Kind::Changed,
    },
    );
    }
    }
    }
  • edit in inflorescence/src/main.rs at line 562
    [14.11348][14.11348:11538]()
    // Request to get the diffs
    let task = Task::done(Msg::View(app::Msg::ToRepo(
    repo::MsgIn::GetChangeDiffs { hash },
    )));
  • edit in inflorescence/src/main.rs at line 588
    [14.12568]
    [5.3992]
    let task = if selection.is_some() {
    // Request to get the diffs
    Task::done(Msg::View(app::Msg::ToRepo(
    repo::MsgIn::GetChangeDiffs { hash },
    )))
    } else {
    Task::none()
    };
  • edit in inflorescence/src/main.rs at line 601
    [14.12628]
    [9.9662]
    cursor.selection = selection;
  • edit in inflorescence/src/main.rs at line 604
    [9.9663][14.12629:12673]()
    state.cursor.selection = selection;
  • replacement in inflorescence/src/main.rs at line 607
    [14.12720][14.12720:12727](),[14.12727][8.15737:15738](),[8.15737][8.15737:15738](),[8.15738][14.12728:12757](),[14.12757][8.15803:15804](),[2.16426][8.15803:15804](),[8.15804][14.12758:12767]()
    };
    state.repo = Some(repo);
    task
    [14.12720]
    [14.12767]
    }