Skip to content

Commit 63d3bf5

Browse files
author
Stephan Dilly
committed
Support stash-apply,stash-drop
1 parent 01a354e commit 63d3bf5

File tree

21 files changed

+669
-245
lines changed

21 files changed

+669
-245
lines changed

asyncgit/src/sync/commits_info.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,28 @@ use crate::error::Result;
33
use git2::{Commit, Error, Oid};
44
use scopetime::scope_time;
55

6+
/// identifies a single commit
7+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
8+
pub struct CommitId(Oid);
9+
10+
impl CommitId {
11+
/// create new CommitId
12+
pub fn new(id: Oid) -> Self {
13+
Self(id)
14+
}
15+
16+
///
17+
pub(crate) fn get_oid(self) -> Oid {
18+
self.0
19+
}
20+
}
21+
22+
impl ToString for CommitId {
23+
fn to_string(&self) -> String {
24+
self.0.to_string()
25+
}
26+
}
27+
628
///
729
#[derive(Debug)]
830
pub struct CommitInfo {
@@ -13,7 +35,7 @@ pub struct CommitInfo {
1335
///
1436
pub author: String,
1537
///
16-
pub hash: String,
38+
pub id: CommitId,
1739
}
1840

1941
///
@@ -44,7 +66,7 @@ pub fn get_commits_info(
4466
message,
4567
author,
4668
time: c.time().seconds(),
47-
hash: c.id().to_string(),
69+
id: CommitId(c.id()),
4870
}
4971
})
5072
.collect::<Vec<_>>();

asyncgit/src/sync/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@ pub mod status;
1111
mod tags;
1212
pub mod utils;
1313

14-
pub use commits_info::{get_commits_info, CommitInfo};
14+
pub use commits_info::{get_commits_info, CommitId, CommitInfo};
1515
pub use hooks::{hooks_commit_msg, hooks_post_commit, HookResult};
1616
pub use hunks::{stage_hunk, unstage_hunk};
1717
pub use logwalker::LogWalker;
1818
pub use reset::{
1919
reset_stage, reset_workdir_file, reset_workdir_folder,
2020
};
21-
pub use stash::stash_save;
21+
pub use stash::{get_stashes, stash_apply, stash_drop, stash_save};
2222
pub use tags::{get_tags, Tags};
2323
pub use utils::{
2424
commit, stage_add_all, stage_add_file, stage_addremoved,

asyncgit/src/sync/stash.rs

Lines changed: 81 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,71 @@
1-
use super::utils::repo;
2-
use crate::error::Result;
3-
use git2::{Oid, StashFlags};
1+
use super::{utils::repo, CommitId};
2+
use crate::error::{Error, Result};
3+
use git2::{Oid, Repository, StashFlags};
44
use scopetime::scope_time;
55

66
///
7-
#[allow(dead_code)]
8-
pub struct StashItem {
9-
pub msg: String,
10-
index: usize,
11-
id: Oid,
7+
pub fn get_stashes(repo_path: &str) -> Result<Vec<Oid>> {
8+
scope_time!("get_stashes");
9+
10+
let mut repo = repo(repo_path)?;
11+
12+
let mut list = Vec::new();
13+
14+
repo.stash_foreach(|_index, _msg, id| {
15+
list.push(*id);
16+
true
17+
})?;
18+
19+
Ok(list)
1220
}
1321

1422
///
15-
#[allow(dead_code)]
16-
pub struct StashItems(Vec<StashItem>);
23+
pub fn stash_drop(repo_path: &str, stash_id: CommitId) -> Result<()> {
24+
scope_time!("stash_drop");
25+
26+
let mut repo = repo(repo_path)?;
27+
28+
let index = get_stash_index(&mut repo, stash_id.get_oid())?;
29+
30+
repo.stash_drop(index)?;
31+
32+
Ok(())
33+
}
1734

1835
///
19-
#[allow(dead_code)]
20-
pub fn get_stashes(repo_path: &str) -> Result<StashItems> {
21-
scope_time!("get_stashes");
36+
pub fn stash_apply(
37+
repo_path: &str,
38+
stash_id: CommitId,
39+
) -> Result<()> {
40+
scope_time!("stash_apply");
2241

2342
let mut repo = repo(repo_path)?;
2443

25-
let mut list = Vec::new();
44+
let index = get_stash_index(&mut repo, stash_id.get_oid())?;
2645

27-
repo.stash_foreach(|index, msg, id| {
28-
list.push(StashItem {
29-
msg: msg.to_string(),
30-
index,
31-
id: *id,
32-
});
33-
true
46+
repo.stash_apply(index, None)?;
47+
48+
Ok(())
49+
}
50+
51+
fn get_stash_index(
52+
repo: &mut Repository,
53+
stash_id: Oid,
54+
) -> Result<usize> {
55+
let mut idx = None;
56+
57+
repo.stash_foreach(|index, _msg, id| {
58+
if *id == stash_id {
59+
idx = Some(index);
60+
false
61+
} else {
62+
true
63+
}
3464
})?;
3565

36-
Ok(StashItems(list))
66+
idx.ok_or_else(|| {
67+
Error::Generic("stash commit not found".to_string())
68+
})
3769
}
3870

3971
///
@@ -66,7 +98,10 @@ pub fn stash_save(
6698
#[cfg(test)]
6799
mod tests {
68100
use super::*;
69-
use crate::sync::tests::{get_statuses, repo_init};
101+
use crate::sync::{
102+
get_commits_info,
103+
tests::{get_statuses, repo_init},
104+
};
70105
use std::{fs::File, io::Write};
71106

72107
#[test]
@@ -80,10 +115,7 @@ mod tests {
80115
false
81116
);
82117

83-
assert_eq!(
84-
get_stashes(repo_path).unwrap().0.is_empty(),
85-
true
86-
);
118+
assert_eq!(get_stashes(repo_path).unwrap().is_empty(), true);
87119
}
88120

89121
#[test]
@@ -117,9 +149,28 @@ mod tests {
117149

118150
let res = get_stashes(repo_path)?;
119151

120-
assert_eq!(res.0.len(), 1);
121-
assert_eq!(res.0[0].msg, "On master: foo");
122-
assert_eq!(res.0[0].index, 0);
152+
assert_eq!(res.len(), 1);
153+
154+
let infos =
155+
get_commits_info(repo_path, &[res[0]], 100).unwrap();
156+
157+
assert_eq!(infos[0].message, "On master: foo");
158+
159+
Ok(())
160+
}
161+
162+
#[test]
163+
fn test_stash_nothing_untracked() -> Result<()> {
164+
let (_td, repo) = repo_init().unwrap();
165+
let root = repo.path().parent().unwrap();
166+
let repo_path = root.as_os_str().to_str().unwrap();
167+
168+
File::create(&root.join("foo.txt"))?
169+
.write_all(b"test\nfoo")?;
170+
171+
assert!(
172+
stash_save(repo_path, Some("foo"), false, false).is_err()
173+
);
123174

124175
Ok(())
125176
}

asyncgit/src/sync/tags.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
use super::utils::repo;
1+
use super::{utils::repo, CommitId};
22
use crate::error::Result;
33
use scopetime::scope_time;
44
use std::collections::HashMap;
55

66
/// hashmap of tag target commit hash to tag names
7-
pub type Tags = HashMap<String, Vec<String>>;
7+
pub type Tags = HashMap<CommitId, Vec<String>>;
88

99
/// returns `Tags` type filled with all tags found in repo
1010
pub fn get_tags(repo_path: &str) -> Result<Tags> {
1111
scope_time!("get_tags");
1212

1313
let mut res = Tags::new();
14-
let mut adder = |key: String, value: String| {
14+
let mut adder = |key, value: String| {
1515
if let Some(key) = res.get_mut(&key) {
1616
key.push(value)
1717
} else {
@@ -26,9 +26,8 @@ pub fn get_tags(repo_path: &str) -> Result<Tags> {
2626
let obj = repo.revparse_single(name)?;
2727

2828
if let Some(tag) = obj.as_tag() {
29-
let target_hash = tag.target_id().to_string();
3029
let tag_name = String::from(name);
31-
adder(target_hash, tag_name);
30+
adder(CommitId::new(tag.target_id()), tag_name);
3231
}
3332
}
3433
}
@@ -70,7 +69,7 @@ mod tests {
7069
repo.tag("b", &target, &sig, "", false).unwrap();
7170

7271
assert_eq!(
73-
get_tags(repo_path).unwrap()[&head_id.to_string()],
72+
get_tags(repo_path).unwrap()[&CommitId::new(head_id)],
7473
vec!["a", "b"]
7574
);
7675
}

0 commit comments

Comments
 (0)