Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/default_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ root.remote_menu=["M"]
remote_menu.add_remote=["a"]
remote_menu.remove_remote=["K"]
remote_menu.rename_remote=["r"]
remote_menu.show_remote=["l"]
remote_menu.quit = ["q", "esc"]

root.reset_menu = ["X"]
Expand Down
10 changes: 10 additions & 0 deletions src/git/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,16 @@ pub(crate) fn branches(repo: &git2::Repository, filter: Option<git2::BranchType>
.collect())
}

pub(crate) fn remotes(repo: &git2::Repository) -> Res<Vec<Ref>> {
Ok(repo
.remotes()
.map_err(Error::ListGitReferences)?
.into_iter()
.flatten()
.map(|remote_name| Ref::Remote(remote_name.to_string()))
.collect())
}

pub(crate) fn tags(repo: &git2::Repository) -> Res<Vec<Ref>> {
Ok(repo
.tag_names(None)
Expand Down
2 changes: 2 additions & 0 deletions src/ops/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ pub(crate) enum Op {
RemoveRemote,
Rename,
RenameRemote,
ShowRemote,
ShowRefs,
Stash,
StashApply,
Expand Down Expand Up @@ -218,6 +219,7 @@ impl Op {
Op::AddRemote => Box::new(remote::AddRemote),
Op::RemoveRemote => Box::new(remote::RemoveRemote),
Op::RenameRemote => Box::new(remote::RenameRemote),
Op::ShowRemote => Box::new(remote::ShowRemote),

Op::Merge => Box::new(merge::Merge),
Op::MergeAbort => Box::new(merge::MergeAbort),
Expand Down
66 changes: 53 additions & 13 deletions src/ops/remote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ use std::{process::Command, rc::Rc};
use crate::{
Res,
app::{App, PromptParams, State},
git,
item_data::ItemData,
picker::{PickerParams, PickerState},
term::Term,
};

Expand Down Expand Up @@ -44,12 +46,15 @@ pub(crate) struct RenameRemote;
impl OpTrait for RenameRemote {
fn get_action(&self, _target: &ItemData) -> Option<Action> {
Some(Rc::new(|app: &mut App, term: &mut Term| {
let remote_name = app.prompt(
let remote_name = app.pick(
term,
&PromptParams {
prompt: "Rename remote",
..Default::default()
},
PickerState::with_remotes(PickerParams {
prompt: "Choose remote to rename".into(),
refs: &git::remotes(&app.state.repo)?,
exclude_ref: None,
default: None,
allow_custom_input: false,
}),
)?;

let new_remote_name = app.prompt(
Expand All @@ -60,7 +65,10 @@ impl OpTrait for RenameRemote {
},
)?;

rename_remote(app, term, &remote_name, &new_remote_name)?;
if let Some(result) = remote_name {
rename_remote(app, term, result.display(), &new_remote_name)?;
}

Ok(())
}))
}
Expand All @@ -70,20 +78,52 @@ impl OpTrait for RenameRemote {
}
}

pub(crate) struct ShowRemote;
impl OpTrait for ShowRemote {
fn get_action(&self, _target: &ItemData) -> Option<Action> {
Some(Rc::new(|app: &mut App, term: &mut Term| {
let _ = app.pick(
term,
PickerState::with_remotes(PickerParams {
prompt: "Remotes".into(),
refs: &git::remotes(&app.state.repo)?,
exclude_ref: None,
default: None,
allow_custom_input: false,
}),
)?;

Ok(())
}))
}

fn display(&self, _state: &State) -> String {
"show remotes".to_string()
}
}

pub(crate) struct RemoveRemote;
impl OpTrait for RemoveRemote {
fn get_action(&self, _target: &ItemData) -> Option<Action> {
Some(Rc::new(|app: &mut App, term: &mut Term| {
let remote_name = app.prompt(
let result = app.pick(
term,
&PromptParams {
prompt: "Delete remote",
..Default::default()
},
PickerState::with_remotes(PickerParams {
prompt: "Remotes".into(),
refs: &git::remotes(&app.state.repo)?,
exclude_ref: None,
default: None,
allow_custom_input: false,
}),
)?;

app.confirm(term, "Really delete remote (y or n)")?;
remove_remote(app, term, &remote_name)?;
if let Some(remote_name) = result {
// TODO: Would be nice to show which remote is acting upon.
// But app.confirm expects an 'static str which complicates things a bit.
app.confirm(term, "Really delete remote (y or n) >")?;
remove_remote(app, term, remote_name.display())?;
return Ok(());
}

Ok(())
}))
Expand Down
15 changes: 15 additions & 0 deletions src/picker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,21 @@ impl PickerState {
state
}

pub(crate) fn with_remotes(params: PickerParams) -> Self {
let items = params
.refs
.iter()
.map(|name| {
PickerItem::new(
name.shorthand().to_string(),
PickerData::Item(name.shorthand().to_string().clone()),
)
})
.collect();

Self::new(params.prompt, items, params.allow_custom_input)
}

/// Create a picker showing only local branches by shorthand name.
/// The default branch (if any) is listed first. The exclude_ref is omitted.
pub(crate) fn with_branches(params: PickerParams) -> Self {
Expand Down
2 changes: 1 addition & 1 deletion src/tests/remote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ fn add_remote() {

#[test]
fn rename_remote_name_prompt() {
snapshot!(setup_clone!(), "Mr");
snapshot!(setup_clone!(), "Mrorigin<enter>");
}

#[test]
Expand Down
4 changes: 2 additions & 2 deletions src/tests/snapshots/gitu__tests__remote__remote_menu.snap
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ expression: ctx.redact_buffer()
|
|
|
|
────────────────────────────────────────────────────────────────────────────────|
Remote |
a add remote |
K remove remote |
r rename remote |
l show remotes |
q/esc Quit/Close |
styles_hash: f0b3d15664a45e6
styles_hash: eead60180401b8f7
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ expression: ctx.redact_buffer()
|
|
────────────────────────────────────────────────────────────────────────────────|
? Rename remote: › █ |
styles_hash: 802b36a3883cd0c0
? Rename to: › █ |
styles_hash: d234beab6b72dd64