Skip to content

Commit 0eee47f

Browse files
committed
add new remotes popup
1 parent ab75103 commit 0eee47f

15 files changed

+1375
-117
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414

1515
### Fixes
1616
* respect env vars like `GIT_CONFIG_GLOBAL` ([#2298](https://github.com/extrawurst/gitui/issues/2298))
17+
* update `gix-path` because previous version contained a vulnerability [[@robin-thoene](https://github.com/robin-thoene)] ([#2350](https://github.com/extrawurst/gitui/pull/2350))
18+
19+
### Added
20+
* add popups for viewing, adding, updating and removing remotes [[@robin-thoene](https://github.com/robin-thoene)] ([#2172](https://github.com/extrawurst/gitui/issues/2172))
1721

1822
## [0.26.3] - 2024-06-02
1923

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ log = "0.4"
3737
notify = "6.1"
3838
notify-debouncer-mini = "0.4"
3939
once_cell = "1"
40-
# pin until upgrading this does not introduce a duplicte dependency
40+
# pin until upgrading this does not introduce a duplicate dependency
4141
parking_lot_core = "=0.9.9"
4242
ratatui = { version = "0.28", default-features = false, features = [
4343
'crossterm',

asyncgit/src/sync/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,10 @@ pub use merge::{
7979
};
8080
pub use rebase::rebase_branch;
8181
pub use remotes::{
82-
get_default_remote, get_default_remote_for_fetch,
83-
get_default_remote_for_push, get_remotes, push::AsyncProgress,
84-
tags::PushTagsProgress,
82+
add_remote, delete_remote, get_default_remote,
83+
get_default_remote_for_fetch, get_default_remote_for_push,
84+
get_remote_url, get_remotes, push::AsyncProgress, rename_remote,
85+
tags::PushTagsProgress, update_remote_url, validate_remote_name,
8586
};
8687
pub(crate) use repository::repo;
8788
pub use repository::{RepoPath, RepoPathRef};

asyncgit/src/sync/remotes/mod.rs

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ use crate::{
1313
ProgressPercent,
1414
};
1515
use crossbeam_channel::Sender;
16-
use git2::{BranchType, FetchOptions, ProxyOptions, Repository};
16+
use git2::{
17+
BranchType, FetchOptions, ProxyOptions, Remote, Repository,
18+
};
1719
use scopetime::scope_time;
1820
use utils::bytes2string;
1921

@@ -32,6 +34,54 @@ pub fn proxy_auto<'a>() -> ProxyOptions<'a> {
3234
proxy
3335
}
3436

37+
///
38+
pub fn add_remote(
39+
repo_path: &RepoPath,
40+
name: &str,
41+
url: &str,
42+
) -> Result<()> {
43+
let repo = repo(repo_path)?;
44+
repo.remote(name, url)?;
45+
Ok(())
46+
}
47+
48+
///
49+
pub fn rename_remote(
50+
repo_path: &RepoPath,
51+
name: &str,
52+
new_name: &str,
53+
) -> Result<()> {
54+
let repo = repo(repo_path)?;
55+
repo.remote_rename(name, new_name)?;
56+
Ok(())
57+
}
58+
59+
///
60+
pub fn update_remote_url(
61+
repo_path: &RepoPath,
62+
name: &str,
63+
new_url: &str,
64+
) -> Result<()> {
65+
let repo = repo(repo_path)?;
66+
repo.remote_set_url(name, new_url)?;
67+
Ok(())
68+
}
69+
70+
///
71+
pub fn delete_remote(
72+
repo_path: &RepoPath,
73+
remote_name: &str,
74+
) -> Result<()> {
75+
let repo = repo(repo_path)?;
76+
repo.remote_delete(remote_name)?;
77+
Ok(())
78+
}
79+
80+
///
81+
pub fn validate_remote_name(name: &str) -> bool {
82+
Remote::is_valid_name(name)
83+
}
84+
3585
///
3686
pub fn get_remotes(repo_path: &RepoPath) -> Result<Vec<String>> {
3787
scope_time!("get_remotes");
@@ -44,6 +94,20 @@ pub fn get_remotes(repo_path: &RepoPath) -> Result<Vec<String>> {
4494
Ok(remotes)
4595
}
4696

97+
///
98+
pub fn get_remote_url(
99+
repo_path: &RepoPath,
100+
remote_name: &str,
101+
) -> Result<Option<String>> {
102+
let repo = repo(repo_path)?;
103+
let remote = repo.find_remote(remote_name)?.clone();
104+
let url = remote.url();
105+
if let Some(u) = url {
106+
return Ok(Some(u.to_string()));
107+
}
108+
Ok(None)
109+
}
110+
47111
/// tries to find origin or the only remote that is defined if any
48112
/// in case of multiple remotes and none named *origin* we fail
49113
pub fn get_default_remote(repo_path: &RepoPath) -> Result<String> {

src/app.rs

Lines changed: 61 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@ use crate::{
1212
popups::{
1313
AppOption, BlameFilePopup, BranchListPopup, CommitPopup,
1414
CompareCommitsPopup, ConfirmPopup, CreateBranchPopup,
15-
ExternalEditorPopup, FetchPopup, FileRevlogPopup,
16-
FuzzyFindPopup, HelpPopup, InspectCommitPopup,
17-
LogSearchPopupPopup, MsgPopup, OptionsPopup, PullPopup,
18-
PushPopup, PushTagsPopup, RenameBranchPopup, ResetPopup,
19-
RevisionFilesPopup, StashMsgPopup, SubmodulesListPopup,
20-
TagCommitPopup, TagListPopup,
15+
CreateRemotePopup, ExternalEditorPopup, FetchPopup,
16+
FileRevlogPopup, FuzzyFindPopup, HelpPopup,
17+
InspectCommitPopup, LogSearchPopupPopup, MsgPopup,
18+
OptionsPopup, PullPopup, PushPopup, PushTagsPopup,
19+
RemoteListPopup, RenameBranchPopup, RenameRemotePopup,
20+
ResetPopup, RevisionFilesPopup, StashMsgPopup,
21+
SubmodulesListPopup, TagCommitPopup, TagListPopup,
22+
UpdateRemoteUrlPopup,
2123
},
2224
queue::{
2325
Action, AppTabs, InternalEvent, NeedsUpdate, Queue,
@@ -86,6 +88,10 @@ pub struct App {
8688
fetch_popup: FetchPopup,
8789
tag_commit_popup: TagCommitPopup,
8890
create_branch_popup: CreateBranchPopup,
91+
create_remote_popup: CreateRemotePopup,
92+
rename_remote_popup: RenameRemotePopup,
93+
update_remote_url_popup: UpdateRemoteUrlPopup,
94+
remotes_popup: RemoteListPopup,
8995
rename_branch_popup: RenameBranchPopup,
9096
select_branch_popup: BranchListPopup,
9197
options_popup: OptionsPopup,
@@ -189,6 +195,10 @@ impl App {
189195
fetch_popup: FetchPopup::new(&env),
190196
tag_commit_popup: TagCommitPopup::new(&env),
191197
create_branch_popup: CreateBranchPopup::new(&env),
198+
create_remote_popup: CreateRemotePopup::new(&env),
199+
rename_remote_popup: RenameRemotePopup::new(&env),
200+
update_remote_url_popup: UpdateRemoteUrlPopup::new(&env),
201+
remotes_popup: RemoteListPopup::new(&env),
192202
rename_branch_popup: RenameBranchPopup::new(&env),
193203
select_branch_popup: BranchListPopup::new(&env),
194204
tags_popup: TagListPopup::new(&env),
@@ -484,6 +494,10 @@ impl App {
484494
tag_commit_popup,
485495
reset_popup,
486496
create_branch_popup,
497+
create_remote_popup,
498+
rename_remote_popup,
499+
update_remote_url_popup,
500+
remotes_popup,
487501
rename_branch_popup,
488502
select_branch_popup,
489503
revision_files_popup,
@@ -512,6 +526,10 @@ impl App {
512526
external_editor_popup,
513527
tag_commit_popup,
514528
select_branch_popup,
529+
remotes_popup,
530+
create_remote_popup,
531+
rename_remote_popup,
532+
update_remote_url_popup,
515533
submodule_popup,
516534
tags_popup,
517535
reset_popup,
@@ -646,6 +664,9 @@ impl App {
646664
if flags.contains(NeedsUpdate::BRANCHES) {
647665
self.select_branch_popup.update_branches()?;
648666
}
667+
if flags.contains(NeedsUpdate::REMOTES) {
668+
self.remotes_popup.update_remotes()?;
669+
}
649670

650671
Ok(())
651672
}
@@ -727,7 +748,19 @@ impl App {
727748
InternalEvent::TagCommit(id) => {
728749
self.tag_commit_popup.open(id)?;
729750
}
730-
751+
InternalEvent::CreateRemote => {
752+
self.create_remote_popup.open()?;
753+
}
754+
InternalEvent::RenameRemote(cur_name) => {
755+
self.rename_remote_popup.open(cur_name)?;
756+
}
757+
InternalEvent::UpdateRemoteUrl(remote_name, cur_url) => {
758+
self.update_remote_url_popup
759+
.open(remote_name, cur_url)?;
760+
}
761+
InternalEvent::ViewRemotes => {
762+
self.remotes_popup.open()?;
763+
}
731764
InternalEvent::CreateBranch => {
732765
self.create_branch_popup.open()?;
733766
}
@@ -926,6 +959,9 @@ impl App {
926959
Action::DeleteRemoteBranch(branch_ref) => {
927960
self.delete_remote_branch(&branch_ref)?;
928961
}
962+
Action::DeleteRemote(remote_name) => {
963+
self.delete_remote(&remote_name);
964+
}
929965
Action::DeleteTag(tag_name) => {
930966
self.delete_tag(tag_name)?;
931967
}
@@ -1015,6 +1051,24 @@ impl App {
10151051
Ok(())
10161052
}
10171053

1054+
fn delete_remote(&self, remote_name: &str) {
1055+
let res =
1056+
sync::delete_remote(&self.repo.borrow(), remote_name);
1057+
match res {
1058+
Ok(()) => {
1059+
self.queue.push(InternalEvent::Update(
1060+
NeedsUpdate::ALL | NeedsUpdate::REMOTES,
1061+
));
1062+
}
1063+
Err(e) => {
1064+
log::error!("delete remote: {}", e,);
1065+
self.queue.push(InternalEvent::ShowErrorMsg(
1066+
format!("delete remote error:\n{e}",),
1067+
));
1068+
}
1069+
}
1070+
}
1071+
10181072
fn commands(&self, force_all: bool) -> Vec<CommandInfo> {
10191073
let mut res = Vec::new();
10201074

src/keys/key_list.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@ pub struct KeysList {
118118
pub stage_unstage_item: GituiKeyEvent,
119119
pub tag_annotate: GituiKeyEvent,
120120
pub view_submodules: GituiKeyEvent,
121+
pub view_remotes: GituiKeyEvent,
122+
pub update_remote_name: GituiKeyEvent,
123+
pub update_remote_url: GituiKeyEvent,
124+
pub add_remote: GituiKeyEvent,
125+
pub delete_remote: GituiKeyEvent,
121126
pub view_submodule_parent: GituiKeyEvent,
122127
pub update_submodule: GituiKeyEvent,
123128
pub commit_history_next: GituiKeyEvent,
@@ -210,6 +215,11 @@ impl Default for KeysList {
210215
stage_unstage_item: GituiKeyEvent::new(KeyCode::Enter, KeyModifiers::empty()),
211216
tag_annotate: GituiKeyEvent::new(KeyCode::Char('a'), KeyModifiers::CONTROL),
212217
view_submodules: GituiKeyEvent::new(KeyCode::Char('S'), KeyModifiers::SHIFT),
218+
view_remotes: GituiKeyEvent::new(KeyCode::Char('r'), KeyModifiers::CONTROL),
219+
update_remote_name: GituiKeyEvent::new(KeyCode::Char('n'),KeyModifiers::NONE),
220+
update_remote_url: GituiKeyEvent::new(KeyCode::Char('u'),KeyModifiers::NONE),
221+
add_remote: GituiKeyEvent::new(KeyCode::Char('a'), KeyModifiers::NONE),
222+
delete_remote: GituiKeyEvent::new(KeyCode::Char('r'), KeyModifiers::NONE),
213223
view_submodule_parent: GituiKeyEvent::new(KeyCode::Char('p'), KeyModifiers::empty()),
214224
update_submodule: GituiKeyEvent::new(KeyCode::Char('u'), KeyModifiers::empty()),
215225
commit_history_next: GituiKeyEvent::new(KeyCode::Char('n'), KeyModifiers::CONTROL),

0 commit comments

Comments
 (0)