From c8ed4e5b0440876558d0794b92a9eec3844d27db Mon Sep 17 00:00:00 2001 From: altsem Date: Sun, 25 Feb 2024 21:57:05 +0100 Subject: [PATCH] remove git2 impl of push/fetch --- Cargo.lock | 71 ----- Cargo.toml | 1 - src/git/mod.rs | 7 +- src/git/remote.rs | 104 ------- src/keybinds.rs | 14 +- src/lib.rs | 362 ++++++++++++---------- src/snapshots/gitu__tests__fetch_all.snap | 12 +- src/snapshots/gitu__tests__pull.snap | 39 +++ src/snapshots/gitu__tests__push.snap | 12 +- 9 files changed, 258 insertions(+), 364 deletions(-) delete mode 100644 src/git/remote.rs create mode 100644 src/snapshots/gitu__tests__pull.snap diff --git a/Cargo.lock b/Cargo.lock index 6248911660..fa5f5ff7b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -120,17 +120,6 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" -[[package]] -name = "auth-git2" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41e7771d4ab6635cbd685ce8db215b29c78a468098126de77c57f3b2e6eb3757" -dependencies = [ - "dirs", - "git2", - "terminal-prompt", -] - [[package]] name = "autocfg" version = "1.1.0" @@ -457,27 +446,6 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" -[[package]] -name = "dirs" -version = "5.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" -dependencies = [ - "dirs-sys", -] - -[[package]] -name = "dirs-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" -dependencies = [ - "libc", - "option-ext", - "redox_users", - "windows-sys 0.48.0", -] - [[package]] name = "either" version = "1.10.0" @@ -569,7 +537,6 @@ dependencies = [ name = "gitu" version = "0.1.0" dependencies = [ - "auth-git2", "chrono", "clap", "criterion", @@ -767,17 +734,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "libredox" -version = "0.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" -dependencies = [ - "bitflags 2.4.2", - "libc", - "redox_syscall", -] - [[package]] name = "libssh2-sys" version = "0.3.0" @@ -946,12 +902,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "option-ext" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" - [[package]] name = "parking_lot" version = "0.12.1" @@ -1129,17 +1079,6 @@ dependencies = [ "bitflags 1.3.2", ] -[[package]] -name = "redox_users" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" -dependencies = [ - "getrandom", - "libredox", - "thiserror", -] - [[package]] name = "regex" version = "1.10.3" @@ -1426,16 +1365,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "terminal-prompt" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572818b3472910acbd5dff46a3413715c18e934b071ab2ba464a7b2c2af16376" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "thiserror" version = "1.0.57" diff --git a/Cargo.toml b/Cargo.toml index 6524c01a51..b584bd4398 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,6 @@ criterion = "0.5.1" pprof = { version = "0.13.0", features = ["flamegraph", "criterion"] } [dependencies] -auth-git2 = "0.5.3" chrono = "0.4.34" clap = { version = "4.5.1", features = ["derive"] } crossterm = "0.27.0" diff --git a/src/git/mod.rs b/src/git/mod.rs index 0a6e87658e..6bee8cd3ee 100644 --- a/src/git/mod.rs +++ b/src/git/mod.rs @@ -20,7 +20,6 @@ pub(crate) mod commit; pub(crate) mod diff; pub(crate) mod merge_status; pub(crate) mod rebase_status; -pub(crate) mod remote; // TODO Use only plumbing commands @@ -276,6 +275,12 @@ pub(crate) fn commit_amend_cmd() -> Command { pub(crate) fn commit_fixup_cmd(reference: &str) -> Command { git(&["commit", "--fixup", reference]) } +pub(crate) fn fetch_all_cmd() -> Command { + git(&["fetch", "--all"]) +} +pub(crate) fn push_cmd() -> Command { + git(&["push"]) +} pub(crate) fn pull_cmd() -> Command { git(&["pull"]) } diff --git a/src/git/remote.rs b/src/git/remote.rs deleted file mode 100644 index d99cbab01c..0000000000 --- a/src/git/remote.rs +++ /dev/null @@ -1,104 +0,0 @@ -use crate::Res; -use git2::FetchOptions; -use git2::PushOptions; -use git2::RemoteCallbacks; -use git2::Repository; - -pub(crate) fn fetch_upstream(repo: &Repository) -> Res { - let Ok(head) = repo.head() else { - return Err(Box::new(RemoteError::NoHead)); - }; - let Ok(upstream) = repo.branch_upstream_remote(head.name().unwrap()) else { - return Err(Box::new(RemoteError::NoUpstreamRemote)); - }; - - fetch(repo, repo.find_remote(upstream.as_str().unwrap()).unwrap()) -} - -pub(crate) fn fetch_all(repo: &Repository) -> Res { - for remote in repo.remotes()?.iter().flatten() { - fetch(repo, repo.find_remote(remote).unwrap())?; - } - - Ok("Fetched all".to_string()) -} - -fn fetch(repo: &Repository, mut remote: git2::Remote<'_>) -> Res { - { - let mut opts = FetchOptions::new(); - let mut callbacks = RemoteCallbacks::new(); - callbacks.credentials(|url, username_from_url, allowed_types| { - auth_git2::GitAuthenticator::default().credentials(&repo.config()?)( - url, - username_from_url, - allowed_types, - ) - }); - - opts.remote_callbacks(callbacks); - - let refspec_array = &remote.fetch_refspecs()?; - let refspecs = refspec_array.into_iter().flatten().collect::>(); - remote.fetch::<&str>(&refspecs, Some(&mut opts), None)?; - }; - - Ok(format!("Fetched {}", remote.name().unwrap())) -} - -pub(crate) fn push_upstream(repo: &Repository) -> Res { - let Ok(head) = repo.head() else { - return Err(Box::new(RemoteError::NoHead)); - }; - let Ok(upstream) = repo.branch_upstream_remote(head.name().unwrap()) else { - return Err(Box::new(RemoteError::NoUpstreamRemote)); - }; - - let mut remote = repo.find_remote(upstream.as_str().unwrap()).unwrap(); - let mut out_name = String::new(); - let mut out_status: Option = None; - - { - let mut opts = PushOptions::new(); - let mut callbacks = RemoteCallbacks::new(); - callbacks.credentials(|url, username_from_url, allowed_types| { - auth_git2::GitAuthenticator::default().credentials(&repo.config()?)( - url, - username_from_url, - allowed_types, - ) - }); - callbacks.push_update_reference(|name, status| { - out_name.push_str(name); - out_status = status.map(|s| s.to_string()); - Ok(()) - }); - opts.remote_callbacks(callbacks); - - remote.push::<&str>(&[head.name().unwrap()], Some(&mut opts))?; - } - - if let Some(status) = out_status { - return Err(Box::new(RemoteError::ResponseStatus(status))); - } - - Ok(format!("Pushed {} to {}", out_name, remote.name().unwrap())) -} - -#[derive(Debug)] -pub(crate) enum RemoteError { - NoHead, - NoUpstreamRemote, - ResponseStatus(String), -} - -impl std::fmt::Display for RemoteError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(match self { - RemoteError::NoHead => "No head", - RemoteError::NoUpstreamRemote => "No upstream remote", - RemoteError::ResponseStatus(status) => status, - }) - } -} - -impl std::error::Error for RemoteError {} diff --git a/src/keybinds.rs b/src/keybinds.rs index 2c9c0c1132..e69915b5ff 100644 --- a/src/keybinds.rs +++ b/src/keybinds.rs @@ -102,16 +102,15 @@ pub(crate) const KEYBINDS: &[Keybind] = &[ // Fetch Keybind::nomod(None, Char('f'), Submenu(Fetch)), Keybind::nomod(Fetch, Char('a'), FetchAll), - Keybind::nomod(Fetch, Char('u'), FetchUpstream), // Log Keybind::nomod(None, Char('l'), Submenu(Log)), Keybind::nomod(Log, Char('l'), LogCurrent), // Pull - Keybind::shift(None, Char('F'), Submenu(Pull)), - Keybind::nomod(Pull, Char('u'), PullUpstream), + Keybind::shift(None, Char('F'), Submenu(SubmenuOp::Pull)), + Keybind::nomod(SubmenuOp::Pull, Char('p'), Op::Pull), // Push - Keybind::shift(None, Char('P'), Submenu(Push)), - Keybind::nomod(Push, Char('u'), PushUpstream), + Keybind::shift(None, Char('P'), Submenu(SubmenuOp::Push)), + Keybind::nomod(SubmenuOp::Push, Char('p'), Op::Push), // Rebase Keybind::nomod(None, Char('r'), Submenu(Rebase)), Keybind::nomod(Rebase, Char('i'), Target(RebaseInteractive)), @@ -139,13 +138,12 @@ pub(crate) enum Op { ToggleSection, HalfPageUp, HalfPageDown, - PushUpstream, - PullUpstream, + Push, + Pull, Submenu(SubmenuOp), Commit, CommitAmend, FetchAll, - FetchUpstream, LogCurrent, RebaseAbort, RebaseContinue, diff --git a/src/lib.rs b/src/lib.rs index 457b1a252a..088d0c2cc5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -264,16 +264,9 @@ fn handle_op( } Submenu(op) => state.pending_submenu_op = op, LogCurrent => goto_log_screen(Rc::clone(&state.repo), &mut state.screens), - FetchAll => state.run_cmd(terminal, "git fetch --all", |state| { - git::remote::fetch_all(&state.repo) - })?, - FetchUpstream => state.run_cmd(terminal, "git fetch", |state| { - git::remote::fetch_upstream(&state.repo) - })?, - PullUpstream => state.run_external_cmd(terminal, &[], git::pull_cmd())?, - PushUpstream => state.run_cmd(terminal, "git push", |state| { - git::remote::push_upstream(&state.repo) - })?, + FetchAll => state.run_external_cmd(terminal, &[], git::fetch_all_cmd())?, + Pull => state.run_external_cmd(terminal, &[], git::pull_cmd())?, + Push => state.run_external_cmd(terminal, &[], git::push_cmd())?, Target(target_op) => { if let Some(act) = &state.screen_mut().get_selected_item().target_data.clone() { if let Some(mut closure) = closure_by_target_op(act, &target_op) { @@ -430,222 +423,276 @@ mod tests { #[test] fn no_repo() { - let (ref mut terminal, state, _dir) = setup_init(60, 20); - insta::assert_snapshot!(redact_hashes(terminal, &state.repo)); + let ctx = TestContext::setup_init(60, 20); + insta::assert_snapshot!(ctx.redact_buffer()); } #[test] fn help_menu() { - let (ref mut terminal, ref mut state, _dir) = setup_init(60, 20); - update(terminal, state, &[key('h')]).unwrap(); - insta::assert_snapshot!(redact_hashes(terminal, &state.repo)); + let mut ctx = TestContext::setup_init(60, 20); + ctx.update(&[key('h')]); + insta::assert_snapshot!(ctx.redact_buffer()); } #[test] fn fresh_init() { - let (ref mut terminal, ref mut state, _dir) = setup_init(60, 20); - update(terminal, state, &[key('g')]).unwrap(); - insta::assert_snapshot!(redact_hashes(terminal, &state.repo)); + let mut ctx = TestContext::setup_init(60, 20); + ctx.update(&[key('g')]); + insta::assert_snapshot!(ctx.redact_buffer()); } #[test] fn new_file() { - let (ref mut terminal, ref mut state, dir) = setup_init(60, 20); - run(dir.path(), &["touch", "new-file"]); - update(terminal, state, &[key('g')]).unwrap(); - insta::assert_snapshot!(redact_hashes(terminal, &state.repo)); + let mut ctx = TestContext::setup_init(60, 20); + run(ctx.dir.path(), &["touch", "new-file"]); + ctx.update(&[key('g')]); + insta::assert_snapshot!(ctx.redact_buffer()); } #[test] fn unstaged_changes() { - let (ref mut terminal, ref mut state, dir) = setup_init(60, 20); - commit(dir.path(), "testfile", "testing\ntesttest"); - fs::write(dir.child("testfile"), "test\ntesttest").expect("error writing to file"); + let mut ctx = TestContext::setup_init(60, 20); + commit(ctx.dir.path(), "testfile", "testing\ntesttest"); + fs::write(ctx.dir.child("testfile"), "test\ntesttest").expect("error writing to file"); - update(terminal, state, &[key('g')]).unwrap(); - insta::assert_snapshot!(redact_hashes(terminal, &state.repo)); + ctx.update(&[key('g')]); + insta::assert_snapshot!(ctx.redact_buffer()); } #[test] fn staged_file() { - let (ref mut terminal, ref mut state, dir) = setup_init(60, 20); - run(dir.path(), &["touch", "new-file"]); - run(dir.path(), &["git", "add", "new-file"]); - update(terminal, state, &[key('g')]).unwrap(); - insta::assert_snapshot!(redact_hashes(terminal, &state.repo)); + let mut ctx = TestContext::setup_init(60, 20); + run(ctx.dir.path(), &["touch", "new-file"]); + run(ctx.dir.path(), &["git", "add", "new-file"]); + ctx.update(&[key('g')]); + insta::assert_snapshot!(ctx.redact_buffer()); } #[test] fn log() { - let (ref mut terminal, ref mut state, dir, _remote_dir) = setup_clone(60, 20); - commit(dir.path(), "firstfile", "testing\ntesttest\n"); - commit(dir.path(), "secondfile", "testing\ntesttest\n"); - update(terminal, state, &[key('g'), key('l'), key('l')]).unwrap(); - insta::assert_snapshot!(redact_hashes(terminal, &state.repo)); + let mut ctx = TestContext::setup_clone(60, 20); + commit(ctx.dir.path(), "firstfile", "testing\ntesttest\n"); + commit(ctx.dir.path(), "secondfile", "testing\ntesttest\n"); + ctx.update(&[key('g'), key('l'), key('l')]); + insta::assert_snapshot!(ctx.redact_buffer()); } #[test] fn show() { - let (ref mut terminal, ref mut state, dir, _remote_dir) = setup_clone(60, 20); - commit(dir.path(), "firstfile", "This should be visible\n"); - update( - terminal, - state, - &[key('g'), key('l'), key('l'), key_code(KeyCode::Enter)], - ) - .unwrap(); - insta::assert_snapshot!(redact_hashes(terminal, &state.repo)); + let mut ctx = TestContext::setup_clone(60, 20); + commit(ctx.dir.path(), "firstfile", "This should be visible\n"); + ctx.update(&[key('g'), key('l'), key('l'), key_code(KeyCode::Enter)]); + insta::assert_snapshot!(ctx.redact_buffer()); } #[test] fn rebase_conflict() { - let (ref mut terminal, ref mut state, dir, _remote_dir) = setup_clone(60, 20); - commit(dir.path(), "new-file", "hello"); + let mut ctx = TestContext::setup_clone(60, 20); + commit(ctx.dir.path(), "new-file", "hello"); - run(dir.path(), &["git", "checkout", "-b", "other-branch"]); - commit(dir.path(), "new-file", "hey"); + run(ctx.dir.path(), &["git", "checkout", "-b", "other-branch"]); + commit(ctx.dir.path(), "new-file", "hey"); - run(dir.path(), &["git", "checkout", "main"]); - commit(dir.path(), "new-file", "hi"); + run(ctx.dir.path(), &["git", "checkout", "main"]); + commit(ctx.dir.path(), "new-file", "hi"); - run(dir.path(), &["git", "checkout", "other-branch"]); - run(dir.path(), &["git", "rebase", "main"]); + run(ctx.dir.path(), &["git", "checkout", "other-branch"]); + run(ctx.dir.path(), &["git", "rebase", "main"]); - update(terminal, state, &[key('g')]).unwrap(); - insta::assert_snapshot!(redact_hashes(terminal, &state.repo)); + ctx.update(&[key('g')]); + insta::assert_snapshot!(ctx.redact_buffer()); } #[test] fn merge_conflict() { - let (ref mut terminal, ref mut state, dir, _remote_dir) = setup_clone(60, 20); - commit(dir.path(), "new-file", "hello"); + let mut ctx = TestContext::setup_clone(60, 20); + commit(ctx.dir.path(), "new-file", "hello"); - run(dir.path(), &["git", "checkout", "-b", "other-branch"]); - commit(dir.path(), "new-file", "hey"); + run(ctx.dir.path(), &["git", "checkout", "-b", "other-branch"]); + commit(ctx.dir.path(), "new-file", "hey"); - run(dir.path(), &["git", "checkout", "main"]); - commit(dir.path(), "new-file", "hi"); + run(ctx.dir.path(), &["git", "checkout", "main"]); + commit(ctx.dir.path(), "new-file", "hi"); - run(dir.path(), &["git", "merge", "other-branch"]); + run(ctx.dir.path(), &["git", "merge", "other-branch"]); - update(terminal, state, &[key('g')]).unwrap(); - insta::assert_snapshot!(redact_hashes(terminal, &state.repo)); + ctx.update(&[key('g')]); + insta::assert_snapshot!(ctx.redact_buffer()); } #[test] fn moved_file() { - let (ref mut terminal, ref mut state, dir, _remote_dir) = setup_clone(60, 20); - commit(dir.path(), "new-file", "hello"); - run(dir.path(), &["git", "mv", "new-file", "moved-file"]); + let mut ctx = TestContext::setup_clone(60, 20); + commit(ctx.dir.path(), "new-file", "hello"); + run(ctx.dir.path(), &["git", "mv", "new-file", "moved-file"]); - update(terminal, state, &[key('g')]).unwrap(); - insta::assert_snapshot!(redact_hashes(terminal, &state.repo)); + ctx.update(&[key('g')]); + insta::assert_snapshot!(ctx.redact_buffer()); } #[test] fn hide_untracked() { - let (ref mut terminal, ref mut state, dir, _remote_dir) = setup_clone(60, 10); - let mut config = state.repo.config().unwrap(); + let mut ctx = TestContext::setup_clone(60, 10); + let mut config = ctx.state.repo.config().unwrap(); config.set_str("status.showUntrackedFiles", "off").unwrap(); - run(dir.path(), &["touch", "i-am-untracked"]); + run(ctx.dir.path(), &["touch", "i-am-untracked"]); - update(terminal, state, &[key('g')]).unwrap(); - insta::assert_snapshot!(redact_hashes(terminal, &state.repo)); + ctx.update(&[key('g')]); + insta::assert_snapshot!(ctx.redact_buffer()); } #[test] fn new_commit() { - let (ref mut terminal, ref mut state, dir, _remote_dir) = setup_clone(60, 10); - commit(dir.path(), "new-file", ""); + let mut ctx = TestContext::setup_clone(60, 10); + commit(ctx.dir.path(), "new-file", ""); - update(terminal, state, &[key('g')]).unwrap(); - insta::assert_snapshot!(redact_hashes(terminal, &state.repo)); + ctx.update(&[key('g')]); + insta::assert_snapshot!(ctx.redact_buffer()); } #[test] fn push() { - let (ref mut terminal, ref mut state, dir, _remote_dir) = setup_clone(60, 10); - commit(dir.path(), "new-file", ""); + let mut ctx = TestContext::setup_clone(60, 10); + commit(ctx.dir.path(), "new-file", ""); - update(terminal, state, &[key('P'), key('u')]).unwrap(); - insta::assert_snapshot!(redact_hashes(terminal, &state.repo)); - } - - #[test] - fn fetch_upstream() { - let (ref mut terminal, ref mut state, _dir, remote_dir) = setup_clone(60, 10); - clone_and_commit(&remote_dir, "remote-file", "hello"); - - update(terminal, state, &[key('f'), key('u')]).unwrap(); - insta::assert_snapshot!(redact_hashes(terminal, &state.repo)); + ctx.update(&[key('P'), key('p')]); + insta::assert_snapshot!(ctx.redact_buffer()); } #[test] fn fetch_all() { - let (ref mut terminal, ref mut state, _dir, remote_dir) = setup_clone(60, 10); - clone_and_commit(&remote_dir, "remote-file", "hello"); + let mut ctx = TestContext::setup_clone(60, 10); + clone_and_commit(&ctx.remote_dir, "remote-file", "hello"); - update(terminal, state, &[key('f'), key('a')]).unwrap(); - insta::assert_snapshot!(redact_hashes(terminal, &state.repo)); + ctx.update(&[key('f'), key('a')]); + insta::assert_snapshot!(ctx.redact_buffer()); } - fn setup_init(width: u16, height: u16) -> (Terminal, State, TempDir) { - let terminal = Terminal::new(TestBackend::new(width, height)).unwrap(); - let dir = TempDir::new().unwrap(); + #[test] + fn pull() { + let mut ctx = TestContext::setup_clone(60, 10); + clone_and_commit(&ctx.remote_dir, "remote-file", "hello"); + + ctx.update(&[key('F'), key('p')]); + insta::assert_snapshot!(ctx.redact_buffer()); + } + + struct TestContext { + terminal: Terminal, + state: State, + dir: TempDir, + remote_dir: TempDir, + } + + impl TestContext { + fn setup_init(width: u16, height: u16) -> Self { + let terminal = Terminal::new(TestBackend::new(width, height)).unwrap(); + let remote_dir = TempDir::new().unwrap(); + let dir = TempDir::new().unwrap(); + + set_env_vars(); + run(dir.path(), &["git", "init", "--initial-branch=main"]); + + let state = State::create( + Repository::open(dir.path()).unwrap(), + crate::Config { + dir: dir.path().into(), + }, + Rect::new(0, 0, width, height), + Args { + command: None, + status: false, + exit_immediately: false, + }, + ) + .unwrap(); + + set_config(state.repo.config().unwrap()); + + Self { + terminal, + state, + dir, + remote_dir, + } + } - set_env_vars(); - run(dir.path(), &["git", "init", "--initial-branch=main"]); + fn setup_clone(width: u16, height: u16) -> Self { + let terminal = Terminal::new(TestBackend::new(width, height)).unwrap(); + let remote_dir = TempDir::new().unwrap(); + let dir = TempDir::new().unwrap(); + + set_env_vars(); + run( + remote_dir.path(), + &["git", "init", "--bare", "--initial-branch=main"], + ); + clone_and_commit(&remote_dir, "initial-file", "hello"); + run( + dir.path(), + &["git", "clone", remote_dir.path().to_str().unwrap(), "."], + ); + + let state = State::create( + Repository::open(dir.path()).unwrap(), + crate::Config { + dir: dir.path().into(), + }, + Rect::new(0, 0, width, height), + Args { + command: None, + status: false, + exit_immediately: false, + }, + ) + .unwrap(); + + set_config(state.repo.config().unwrap()); + + Self { + terminal, + state, + dir, + remote_dir, + } + } - let state = State::create( - Repository::open(dir.path()).unwrap(), - crate::Config { - dir: dir.path().into(), - }, - Rect::new(0, 0, width, height), - Args { - command: None, - status: false, - exit_immediately: false, - }, - ) - .unwrap(); + fn update(&mut self, events: &[Event]) { + update(&mut self.terminal, &mut self.state, events).unwrap(); + } - set_config(state.repo.config().unwrap()); - (terminal, state, dir) + fn redact_buffer(&self) -> String { + let mut debug_output = format!("{:#?}", self.terminal.backend().buffer()); + + [&self.dir, &self.remote_dir] + .iter() + .flat_map(|dir| Repository::open(dir.path()).ok()) + .for_each(|repo| { + let mut revwalk = repo.revwalk().unwrap(); + revwalk.push_head().ok(); + revwalk + .flat_map(|maybe_oid| maybe_oid.and_then(|oid| repo.find_commit(oid))) + .for_each(|commit| { + let id = commit.as_object().id().to_string(); + let short = commit.as_object().short_id().unwrap(); + let short_id = short.as_str().unwrap(); + + debug_output = debug_output.replace(&id, &"_".repeat(id.len())); + debug_output = + debug_output.replace(short_id, &"_".repeat(short_id.len())); + }); + }); + + redact_temp_dir(&self.dir, &mut debug_output); + redact_temp_dir(&self.remote_dir, &mut debug_output); + + debug_output + } } - fn setup_clone(width: u16, height: u16) -> (Terminal, State, TempDir, TempDir) { - let terminal = Terminal::new(TestBackend::new(width, height)).unwrap(); - let remote_dir = TempDir::new().unwrap(); - let dir = TempDir::new().unwrap(); - - set_env_vars(); - run( - remote_dir.path(), - &["git", "init", "--bare", "--initial-branch=main"], - ); - clone_and_commit(&remote_dir, "initial-file", "hello"); - run( - dir.path(), - &["git", "clone", remote_dir.path().to_str().unwrap(), "."], - ); - - let state = State::create( - Repository::open(dir.path()).unwrap(), - crate::Config { - dir: dir.path().into(), - }, - Rect::new(0, 0, width, height), - Args { - command: None, - status: false, - exit_immediately: false, - }, - ) - .unwrap(); - - set_config(state.repo.config().unwrap()); - (terminal, state, dir, remote_dir) + fn redact_temp_dir(temp_dir: &TempDir, debug_output: &mut String) { + let text = temp_dir.path().to_str().unwrap(); + *debug_output = debug_output.replace(text, &" ".repeat(text.len())); } fn clone_and_commit(remote_dir: &TempDir, file_name: &str, file_content: &str) { @@ -707,23 +754,4 @@ mod tests { fn key_code(code: KeyCode) -> Event { Event::Key(KeyEvent::new(code, KeyModifiers::empty())) } - - fn redact_hashes(terminal: &mut Terminal, repo: &Repository) -> String { - let mut debug_output = format!("{:#?}", terminal.backend().buffer()); - - let mut revwalk = repo.revwalk().unwrap(); - revwalk.push_head().ok(); - revwalk - .flat_map(|maybe_oid| maybe_oid.and_then(|oid| repo.find_commit(oid))) - .for_each(|commit| { - let id = commit.as_object().id().to_string(); - let short = commit.as_object().short_id().unwrap(); - let short_id = short.as_str().unwrap(); - - debug_output = debug_output.replace(&id, &"_".repeat(id.len())); - debug_output = debug_output.replace(short_id, &"_".repeat(short_id.len())); - }); - - debug_output - } } diff --git a/src/snapshots/gitu__tests__fetch_all.snap b/src/snapshots/gitu__tests__fetch_all.snap index bfbedb1cbd..b5c032f8db 100644 --- a/src/snapshots/gitu__tests__fetch_all.snap +++ b/src/snapshots/gitu__tests__fetch_all.snap @@ -1,6 +1,6 @@ --- source: src/lib.rs -expression: "redact_hashes(terminal, &state.repo)" +expression: ctx.redact_buffer() --- Buffer { area: Rect { x: 0, y: 0, width: 60, height: 10 }, @@ -11,10 +11,10 @@ Buffer { " Recent commits ", " _______ main add initial-file ", " ", - " ", "────────────────────────────────────────────────────────────", "$ git fetch --all ", - "Fetched all ", + "From ", + " _______.._______ main -> origin/main ", ], styles: [ x: 0, y: 0, fg: Reset, bg: Rgb(80, 73, 69), underline: Reset, modifier: NONE, @@ -28,8 +28,8 @@ Buffer { x: 8, y: 4, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, x: 9, y: 4, fg: Rgb(169, 182, 101), bg: Reset, underline: Reset, modifier: NONE, x: 13, y: 4, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, - x: 0, y: 7, fg: Rgb(80, 73, 69), bg: Reset, underline: Reset, modifier: NONE, - x: 0, y: 8, fg: Rgb(125, 174, 163), bg: Reset, underline: Reset, modifier: NONE, - x: 17, y: 8, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 0, y: 6, fg: Rgb(80, 73, 69), bg: Reset, underline: Reset, modifier: NONE, + x: 0, y: 7, fg: Rgb(125, 174, 163), bg: Reset, underline: Reset, modifier: NONE, + x: 17, y: 7, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, ] } diff --git a/src/snapshots/gitu__tests__pull.snap b/src/snapshots/gitu__tests__pull.snap new file mode 100644 index 0000000000..9cd56ae3b4 --- /dev/null +++ b/src/snapshots/gitu__tests__pull.snap @@ -0,0 +1,39 @@ +--- +source: src/lib.rs +expression: ctx.redact_buffer() +--- +Buffer { + area: Rect { x: 0, y: 0, width: 60, height: 10 }, + content: [ + "🢒On branch main ", + " Your branch is up to date with 'origin/main'. ", + " ", + " Recent commits ", + " _______ main origin/main add remote-file ", + " _______ add initial-file ", + "────────────────────────────────────────────────────────────", + "$ git pull ", + "From ", + " _______.._______ main -> origin/main ", + ], + styles: [ + x: 0, y: 0, fg: Reset, bg: Rgb(80, 73, 69), underline: Reset, modifier: NONE, + x: 1, y: 0, fg: Rgb(216, 166, 87), bg: Rgb(80, 73, 69), underline: Reset, modifier: BOLD, + x: 15, y: 0, fg: Reset, bg: Rgb(80, 73, 69), underline: Reset, modifier: NONE, + x: 0, y: 1, fg: Reset, bg: Rgb(42, 40, 39), underline: Reset, modifier: NONE, + x: 0, y: 2, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 1, y: 3, fg: Rgb(216, 166, 87), bg: Reset, underline: Reset, modifier: BOLD, + x: 15, y: 3, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 1, y: 4, fg: Rgb(216, 166, 87), bg: Reset, underline: Reset, modifier: NONE, + x: 8, y: 4, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 9, y: 4, fg: Rgb(169, 182, 101), bg: Reset, underline: Reset, modifier: NONE, + x: 13, y: 4, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 14, y: 4, fg: Rgb(234, 105, 98), bg: Reset, underline: Reset, modifier: NONE, + x: 25, y: 4, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 1, y: 5, fg: Rgb(216, 166, 87), bg: Reset, underline: Reset, modifier: NONE, + x: 8, y: 5, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 0, y: 6, fg: Rgb(80, 73, 69), bg: Reset, underline: Reset, modifier: NONE, + x: 0, y: 7, fg: Rgb(125, 174, 163), bg: Reset, underline: Reset, modifier: NONE, + x: 10, y: 7, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + ] +} diff --git a/src/snapshots/gitu__tests__push.snap b/src/snapshots/gitu__tests__push.snap index 6cac96e8ea..75c1af21b5 100644 --- a/src/snapshots/gitu__tests__push.snap +++ b/src/snapshots/gitu__tests__push.snap @@ -1,6 +1,6 @@ --- source: src/lib.rs -expression: "redact_hashes(terminal, &state.repo)" +expression: ctx.redact_buffer() --- Buffer { area: Rect { x: 0, y: 0, width: 60, height: 10 }, @@ -11,10 +11,10 @@ Buffer { " Recent commits ", " _______ main origin/main add new-file ", " _______ add initial-file ", - " ", "────────────────────────────────────────────────────────────", "$ git push ", - "Pushed refs/heads/main to origin ", + "To ", + " _______.._______ main -> main ", ], styles: [ x: 0, y: 0, fg: Reset, bg: Rgb(80, 73, 69), underline: Reset, modifier: NONE, @@ -32,8 +32,8 @@ Buffer { x: 25, y: 4, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, x: 1, y: 5, fg: Rgb(216, 166, 87), bg: Reset, underline: Reset, modifier: NONE, x: 8, y: 5, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, - x: 0, y: 7, fg: Rgb(80, 73, 69), bg: Reset, underline: Reset, modifier: NONE, - x: 0, y: 8, fg: Rgb(125, 174, 163), bg: Reset, underline: Reset, modifier: NONE, - x: 10, y: 8, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 0, y: 6, fg: Rgb(80, 73, 69), bg: Reset, underline: Reset, modifier: NONE, + x: 0, y: 7, fg: Rgb(125, 174, 163), bg: Reset, underline: Reset, modifier: NONE, + x: 10, y: 7, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, ] }