Skip to content

Commit

Permalink
Allow copying multiple commits (#1288)
Browse files Browse the repository at this point in the history
  • Loading branch information
remique committed Sep 19, 2022
1 parent 9534e4c commit e0fa63c
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* file blame at right revision from commit-details [[@heiskane](https://github.com/heiskane)] ([#1122](https://github.com/extrawurst/gitui/issues/1122))
* add `regex-fancy` and `regex-onig` features to allow building Syntect with Onigumara regex engine instead of the default engine based on fancy-regex [[@jirutka](https://github.com/jirutka)]
* add `vendor-openssl` feature to allow building without vendored openssl [[@jirutka](https://github.com/jirutka)]
* allow copying marked commits [[@remique](https://github.com/remique)] ([#1288](https://github.com/extrawurst/gitui/issues/1288))

### Fixes
* remove insecure dependency `ansi_term` ([#1290](https://github.com/extrawurst/gitui/issues/1290))
Expand Down
100 changes: 91 additions & 9 deletions src/components/commitlist.rs
Expand Up @@ -34,7 +34,7 @@ pub struct CommitList {
branch: Option<String>,
count_total: usize,
items: ItemBatch,
marked: Vec<CommitId>,
marked: Vec<(usize, CommitId)>,
scroll_state: (Instant, f32),
tags: Option<Tags>,
current_size: Cell<(u16, u16)>,
Expand Down Expand Up @@ -134,7 +134,7 @@ impl CommitList {
}

///
pub fn marked(&self) -> &[CommitId] {
pub fn marked(&self) -> &[(usize, CommitId)] {
&self.marked
}

Expand All @@ -143,11 +143,85 @@ impl CommitList {
self.marked.clear();
}

///
pub fn marked_indexes(&self) -> Vec<usize> {
let (indexes, _): (Vec<usize>, Vec<_>) =
self.marked.iter().copied().unzip();

indexes
}

///
pub fn marked_commits(&self) -> Vec<CommitId> {
let (_, commits): (Vec<_>, Vec<CommitId>) =
self.marked.iter().copied().unzip();

commits
}

fn marked_consecutive(&self) -> bool {
let marked = self.marked_indexes();

for i in 1..marked.len() {
if marked[i - 1] + 1 != marked[i] {
return false;
}
}

true
}

pub fn copy_marked_hashes(&self) -> Result<()> {
if self.marked_consecutive() {
let m = self.marked_indexes();

let first = self.items.iter().nth(m[0]);

let last = self.items.iter().nth(m[m.len() - 1]);

if let (Some(f), Some(l)) = (first, last) {
let yank =
format!("{}^..{}", f.hash_short, l.hash_short);
crate::clipboard::copy_string(&yank)?;
};
} else {
let separate = self
.marked_indexes()
.iter()
.map(|e| {
self.items
.iter()
.nth(*e)
.map_or_else(String::new, |le| {
le.hash_short.to_string()
})
})
.join(" ");

crate::clipboard::copy_string(&separate)?;
}

Ok(())
}

pub fn copy_entry_hash(&self) -> Result<()> {
if let Some(e) = self.items.iter().nth(
self.selection.saturating_sub(self.items.index_offset()),
) {
crate::clipboard::copy_string(&e.hash_short)?;
match self.marked_count() {
0 => {
if let Some(e) = self.items.iter().nth(
self.selection
.saturating_sub(self.items.index_offset()),
) {
crate::clipboard::copy_string(&e.hash_short)?;
}
}
1 => {
if let Some(e) =
self.items.iter().nth(self.marked_indexes()[0])
{
crate::clipboard::copy_string(&e.hash_short)?;
}
}
_ => {}
}
Ok(())
}
Expand Down Expand Up @@ -191,10 +265,17 @@ impl CommitList {
fn mark(&mut self) {
if let Some(e) = self.selected_entry() {
let id = e.id;
let selected = self
.selection
.saturating_sub(self.items.index_offset());
if self.is_marked(&id).unwrap_or_default() {
self.marked.retain(|marked| marked != &id);
self.marked.retain(|marked| marked.1 != id);
} else {
self.marked.push(id);
self.marked.push((selected, id));

self.marked.sort_unstable_by(|first, second| {
first.0.cmp(&second.0)
});
}
}
}
Expand Down Expand Up @@ -227,7 +308,8 @@ impl CommitList {
if self.marked.is_empty() {
None
} else {
let found = self.marked.iter().any(|entry| entry == id);
let found =
self.marked.iter().any(|entry| entry.1 == *id);
Some(found)
}
}
Expand Down
12 changes: 8 additions & 4 deletions src/tabs/revlog.rs
Expand Up @@ -165,7 +165,11 @@ impl Revlog {
}

fn copy_commit_hash(&self) -> Result<()> {
self.list.copy_entry_hash()?;
if self.list.marked_count() > 1 {
self.list.copy_marked_hashes()?;
} else {
self.list.copy_entry_hash()?;
}
Ok(())
}

Expand Down Expand Up @@ -328,7 +332,7 @@ impl Component for Revlog {
self.queue.push(InternalEvent::OpenPopup(
StackablePopupOpen::CompareCommits(
InspectCommitOpen::new(
self.list.marked()[0],
self.list.marked()[0].1,
),
),
));
Expand All @@ -339,8 +343,8 @@ impl Component for Revlog {
self.queue.push(InternalEvent::OpenPopup(
StackablePopupOpen::CompareCommits(
InspectCommitOpen {
commit_id: marked[0],
compare_id: Some(marked[1]),
commit_id: marked[0].1,
compare_id: Some(marked[1].1),
tags: None,
},
),
Expand Down
2 changes: 1 addition & 1 deletion src/tabs/stashlist.rs
Expand Up @@ -78,7 +78,7 @@ impl StashList {
fn drop_stash(&mut self) {
if self.list.marked_count() > 0 {
self.queue.push(InternalEvent::ConfirmAction(
Action::StashDrop(self.list.marked().to_vec()),
Action::StashDrop(self.list.marked_commits()),
));
} else if let Some(e) = self.list.selected_entry() {
self.queue.push(InternalEvent::ConfirmAction(
Expand Down

0 comments on commit e0fa63c

Please sign in to comment.