Skip to content

Commit 29e6baa

Browse files
author
Stephan Dilly
committed
stashing support
1 parent 2f54a60 commit 29e6baa

File tree

8 files changed

+349
-17
lines changed

8 files changed

+349
-17
lines changed

assets/stashing.drawio

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<mxfile host="app.diagrams.net" modified="2020-05-19T12:41:55.023Z" agent="5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1 Safari/605.1.15" etag="G_7kN2nuUboj_f0S3bPh" version="13.1.3" type="device" pages="2"><diagram id="hAseTAaTBIQ-p2lVXsqS" name="Page-1">7Vlbk5owFP41zLQPO0NAUB+97LZ92Je1l+coEegGQiGu2l/f3CBEcNzuiLK2L5p8JyTk+87JSYLlzpLdpxxm0SMJELYcO9hZ7txynOHIZ78c2EvAc8cSCPM4kBDQwCL+jRRoK3QTB6gwGlJCMI0zE1yRNEUramAwz8nWbLYm2Bw1gyFqAIsVxE30RxzQSKIjZ6jxzygOo3Jk4Kv5JbBsrGZSRDAg2xrk3lvuLCeEylKymyHMuSt5kc89HLFWL5ajlL7mgadvOMToyV8+foFPYA6+D4Y/71QvLxBv1ITVy9J9yUBONmmAeCe25U63UUzRIoMrbt0yyRkW0QSzGmBF1R3KKdodfU9QzZ55DSIJovmeNSkfsBVhpceo6lbT7/oKi2rUOyUIleRh1bVmhRUUMX9BktNDkoBJ0qhJUuV4BkmgK5LcBkkLCummaFDFJk1NPgqak2c0I5jkDElJylpO1zHGBxDEcZiy6oqRhBg+5RTGLFYnypDEQcCHaRXAlKgDDVocddAmQVcKDNoUKKI4DXuqwZqkdKFeCpxDEO+kIK0LR1eC+E1B4AvqqRgdBIQzvnJEjPu3cA/8Yc+yWylar1gamiy1pDe31ZM6S2+guVO69fx2KMK18xto24f5mJNdZDBl5ZCKmUtsWQIiC7IzhMLZ2MvDtgwzu+ilpvV8aZ9BYO+0wBfNl6C5h4yYdJbDurO/xgmSpcmGRoxiURbapjDpIqtitKa9C8K2jf5lo7C5zZxkGd6boVhTwv+14Ufc6UqyPGHGPFzCD+wFbSlia+kjL3IKbe72d2uYxGwQ8XhCUlII3o0mhbg84A3sbKfH1UHtHV5TeGzeHBWH8KpW8uAJJhgy52X+Yh6fucfoO9UWVG1Lqd/UjaO7kXRXljL3lGZJd2UWzs9q0v05DES1HgIcFR7PDToMDFiGAofU+sVBMyC4UYUEN9aCgltEWHC8DAwO2gKpzU0GyGvYq0wVcTpkPB40uiXQTNt7jXs1WAZRZRrUTCqWtBQ1Gyw0HtaGP1RVVCtp66DpcKpdwzPfU27qYKm7+vEBeI2lbp6T7HYV8MBpBbyLKtA8Qj/EGIFbzfavuda7bAgMWwVonhBvVIDqMvp6Coz+b4pPZYrrq1R2fLZLlAO+z0BadWFyfG2pvL/O2bgzzlo+PnnTneXNBW/Cye1NSnO4euY7x9v05bfK0p0rt1yzNGRh/+G/o0nb+nJhUVo/r8lrrVvdjTqnv69ddDPqvOsPbGe5MASXujC01BlZ22qnY/f+Dw==</diagram><diagram id="o9nFayAMEWxc9pClOnIG" name="Page-2">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</diagram></mxfile>

asyncgit/src/sync/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ mod hooks;
66
mod hunks;
77
mod logwalker;
88
mod reset;
9+
mod stash;
910
pub mod status;
1011
mod tags;
1112
pub mod utils;

asyncgit/src/sync/stash.rs

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#![allow(dead_code)]
2+
use super::utils::repo;
3+
use crate::error::Result;
4+
use git2::{Oid, StashFlags};
5+
use scopetime::scope_time;
6+
7+
///
8+
pub struct StashItem {
9+
pub msg: String,
10+
index: usize,
11+
id: Oid,
12+
}
13+
14+
///
15+
pub struct StashItems(Vec<StashItem>);
16+
17+
///
18+
pub fn get_stashes(repo_path: &str) -> Result<StashItems> {
19+
scope_time!("get_stashes");
20+
21+
let mut repo = repo(repo_path)?;
22+
23+
let mut list = Vec::new();
24+
25+
repo.stash_foreach(|index, msg, id| {
26+
list.push(StashItem {
27+
msg: msg.to_string(),
28+
index,
29+
id: *id,
30+
});
31+
true
32+
})?;
33+
34+
Ok(StashItems(list))
35+
}
36+
37+
// private just for testing right now
38+
fn stash_save(repo_path: &str, message: &str) -> Result<()> {
39+
scope_time!("stash_save");
40+
41+
let mut repo = repo(repo_path)?;
42+
43+
let sig = repo.signature()?;
44+
45+
let options = StashFlags::INCLUDE_UNTRACKED;
46+
47+
repo.stash_save(&sig, message, Some(options))?;
48+
49+
Ok(())
50+
}
51+
52+
#[cfg(test)]
53+
mod tests {
54+
use super::*;
55+
use crate::sync::tests::{get_statuses, repo_init};
56+
use std::{fs::File, io::Write};
57+
58+
#[test]
59+
fn test_smoke() {
60+
let (_td, repo) = repo_init().unwrap();
61+
let root = repo.path().parent().unwrap();
62+
let repo_path = root.as_os_str().to_str().unwrap();
63+
64+
assert_eq!(stash_save(repo_path, "").is_ok(), false);
65+
66+
assert_eq!(
67+
get_stashes(repo_path).unwrap().0.is_empty(),
68+
true
69+
);
70+
}
71+
72+
#[test]
73+
fn test_stashing() -> Result<()> {
74+
let (_td, repo) = repo_init().unwrap();
75+
let root = repo.path().parent().unwrap();
76+
let repo_path = root.as_os_str().to_str().unwrap();
77+
78+
File::create(&root.join("foo.txt"))?
79+
.write_all(b"test\nfoo")?;
80+
81+
assert_eq!(get_statuses(repo_path), (1, 0));
82+
83+
stash_save(repo_path, "stashname")?;
84+
85+
assert_eq!(get_statuses(repo_path), (0, 0));
86+
87+
Ok(())
88+
}
89+
90+
#[test]
91+
fn test_stashes() -> Result<()> {
92+
let (_td, repo) = repo_init().unwrap();
93+
let root = repo.path().parent().unwrap();
94+
let repo_path = root.as_os_str().to_str().unwrap();
95+
96+
File::create(&root.join("foo.txt"))?
97+
.write_all(b"test\nfoo")?;
98+
99+
stash_save(repo_path, "foo")?;
100+
101+
let res = get_stashes(repo_path)?;
102+
103+
assert_eq!(res.0.len(), 1);
104+
assert_eq!(res.0[0].msg, "On master: foo");
105+
assert_eq!(res.0[0].index, 0);
106+
107+
Ok(())
108+
}
109+
}

src/app.rs

+43-17
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::{
88
keys,
99
queue::{InternalEvent, NeedsUpdate, Queue},
1010
strings,
11-
tabs::{Revlog, Status},
11+
tabs::{Revlog, Stashing, Status},
1212
ui::style::Theme,
1313
};
1414
use asyncgit::{sync, AsyncNotification, CWD};
@@ -38,6 +38,7 @@ pub struct App {
3838
tab: usize,
3939
revlog: Revlog,
4040
status_tab: Status,
41+
stashing_tab: Stashing,
4142
queue: Queue,
4243
theme: Theme,
4344
}
@@ -60,6 +61,7 @@ impl App {
6061
tab: 0,
6162
revlog: Revlog::new(&sender, &theme),
6263
status_tab: Status::new(&sender, &queue, &theme),
64+
stashing_tab: Stashing::new(&queue, &theme),
6365
queue,
6466
theme,
6567
}
@@ -81,11 +83,13 @@ impl App {
8183

8284
self.draw_tabs(f, chunks_main[0]);
8385

84-
if self.tab == 0 {
85-
self.status_tab.draw(f, chunks_main[1]);
86-
} else {
87-
self.revlog.draw(f, chunks_main[1]);
88-
}
86+
//TODO: macro because of generic draw call
87+
match self.tab {
88+
0 => self.status_tab.draw(f, chunks_main[1]),
89+
1 => self.revlog.draw(f, chunks_main[1]),
90+
2 => self.stashing_tab.draw(f, chunks_main[1]),
91+
_ => panic!("unknown tab"),
92+
};
8993

9094
Self::draw_commands(
9195
f,
@@ -141,13 +145,15 @@ impl App {
141145
pub fn update(&mut self) {
142146
trace!("update");
143147
self.status_tab.update();
148+
self.stashing_tab.update();
144149
}
145150

146151
///
147152
pub fn update_git(&mut self, ev: AsyncNotification) {
148153
trace!("update_git: {:?}", ev);
149154

150155
self.status_tab.update_git(ev);
156+
self.stashing_tab.update_git(ev);
151157

152158
match ev {
153159
AsyncNotification::Diff => (),
@@ -166,12 +172,16 @@ impl App {
166172
pub fn any_work_pending(&self) -> bool {
167173
self.status_tab.anything_pending()
168174
|| self.revlog.any_work_pending()
175+
|| self.stashing_tab.anything_pending()
169176
}
170177
}
171178

172179
// private impls
173180
impl App {
174-
accessors!(self, [msg, reset, commit, help, revlog, status_tab]);
181+
accessors!(
182+
self,
183+
[msg, reset, commit, help, revlog, status_tab, stashing_tab]
184+
);
175185

176186
fn check_quit(&mut self, ev: Event) -> bool {
177187
if let Event::Key(e) = ev {
@@ -183,17 +193,29 @@ impl App {
183193
false
184194
}
185195

196+
fn get_tabs(&mut self) -> Vec<&mut dyn Component> {
197+
vec![
198+
&mut self.status_tab,
199+
&mut self.revlog,
200+
&mut self.stashing_tab,
201+
]
202+
}
203+
186204
fn toggle_tabs(&mut self) {
187-
self.tab += 1;
188-
self.tab %= 2;
189-
190-
if self.tab == 1 {
191-
self.status_tab.hide();
192-
self.revlog.show();
193-
} else {
194-
self.status_tab.show();
195-
self.revlog.hide();
205+
let mut new_tab = self.tab + 1;
206+
{
207+
let tabs = self.get_tabs();
208+
new_tab %= tabs.len();
209+
210+
for (i, t) in tabs.into_iter().enumerate() {
211+
if new_tab == i {
212+
t.show();
213+
} else {
214+
t.hide();
215+
}
216+
}
196217
}
218+
self.tab = new_tab;
197219
}
198220

199221
fn update_commands(&mut self) {
@@ -327,7 +349,11 @@ impl App {
327349
f.render_widget(
328350
Tabs::default()
329351
.block(Block::default().borders(Borders::BOTTOM))
330-
.titles(&[strings::TAB_STATUS, strings::TAB_LOG])
352+
.titles(&[
353+
strings::TAB_STATUS,
354+
strings::TAB_LOG,
355+
strings::TAB_STASHING,
356+
])
331357
.style(Style::default())
332358
.highlight_style(
333359
self.theme

src/strings.rs

+12
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ pub static TITLE_DIFF: &str = "Diff: ";
33
pub static TITLE_INDEX: &str = "Staged Changes [2]";
44

55
pub static TAB_STATUS: &str = "Status";
6+
pub static TAB_STASHING: &str = "Stashing";
67
pub static TAB_LOG: &str = "Log";
78
pub static TAB_DIVIDER: &str = " | ";
89

@@ -16,13 +17,17 @@ pub static RESET_MSG: &str = "confirm file reset?";
1617

1718
pub static HELP_TITLE: &str = "Help: all commands";
1819

20+
pub static STASHING_FILES_TITLE: &str = "Files to Stash";
21+
pub static STASHING_OPTIONS_TITLE: &str = "Options";
22+
1923
pub mod commands {
2024
use crate::components::CommandText;
2125

2226
static CMD_GROUP_GENERAL: &str = "General";
2327
static CMD_GROUP_DIFF: &str = "Diff";
2428
static CMD_GROUP_CHANGES: &str = "Changes";
2529
static CMD_GROUP_COMMIT: &str = "Commit";
30+
static CMD_GROUP_STASHING: &str = "Stashing";
2631

2732
///
2833
pub static TOGGLE_TABS: CommandText = CommandText::new(
@@ -152,4 +157,11 @@ pub mod commands {
152157
"resets the file in question",
153158
CMD_GROUP_GENERAL,
154159
);
160+
161+
///
162+
pub static STASHING_SAVE: CommandText = CommandText::new(
163+
"Save [s]",
164+
"creates a new stash",
165+
CMD_GROUP_STASHING,
166+
);
155167
}

src/tabs/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
mod revlog;
2+
mod stashing;
23
mod status;
34

45
pub use revlog::Revlog;
6+
pub use stashing::Stashing;
57
pub use status::Status;

0 commit comments

Comments
 (0)