mirror of
https://github.com/gitui-org/gitui
synced 2026-05-24 09:28:21 +00:00
108 lines
2.3 KiB
Rust
108 lines
2.3 KiB
Rust
use super::{
|
|
diff::{get_diff_raw, HunkHeader},
|
|
utils::repo,
|
|
};
|
|
use crate::hash;
|
|
use git2::{ApplyLocation, ApplyOptions, Diff};
|
|
use log::error;
|
|
use scopetime::scope_time;
|
|
|
|
///
|
|
pub fn stage_hunk(
|
|
repo_path: &str,
|
|
file_path: String,
|
|
hunk_hash: u64,
|
|
) -> bool {
|
|
scope_time!("stage_hunk");
|
|
|
|
let repo = repo(repo_path);
|
|
|
|
let diff = get_diff_raw(&repo, &file_path, false, false).unwrap();
|
|
|
|
let mut opt = ApplyOptions::new();
|
|
opt.hunk_callback(|hunk| {
|
|
let header = HunkHeader::from(hunk.unwrap());
|
|
hash(&header) == hunk_hash
|
|
});
|
|
|
|
repo.apply(&diff, ApplyLocation::Index, Some(&mut opt))
|
|
.is_ok()
|
|
}
|
|
|
|
fn find_hunk_index(diff: &Diff, hunk_hash: u64) -> Option<usize> {
|
|
let mut result = None;
|
|
|
|
let mut hunk_count = 0;
|
|
|
|
let foreach_result = diff.foreach(
|
|
&mut |_, _| true,
|
|
None,
|
|
Some(&mut |_, hunk| {
|
|
let header = HunkHeader::from(hunk);
|
|
if hash(&header) == hunk_hash {
|
|
result = Some(hunk_count);
|
|
}
|
|
hunk_count += 1;
|
|
true
|
|
}),
|
|
None,
|
|
);
|
|
|
|
if foreach_result.is_ok() {
|
|
result
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
///
|
|
pub fn unstage_hunk(
|
|
repo_path: &str,
|
|
file_path: String,
|
|
hunk_hash: u64,
|
|
) -> bool {
|
|
scope_time!("revert_hunk");
|
|
|
|
let repo = repo(repo_path);
|
|
|
|
let diff = get_diff_raw(&repo, &file_path, true, false).unwrap();
|
|
let diff_count_positive = diff.deltas().len();
|
|
|
|
let hunk_index = find_hunk_index(&diff, hunk_hash);
|
|
|
|
if hunk_index.is_none() {
|
|
error!("hunk not found");
|
|
return false;
|
|
}
|
|
|
|
let diff = get_diff_raw(&repo, &file_path, true, true).unwrap();
|
|
|
|
assert_eq!(diff.deltas().len(), diff_count_positive);
|
|
|
|
let mut count = 0;
|
|
{
|
|
let mut hunk_idx = 0;
|
|
let mut opt = ApplyOptions::new();
|
|
opt.hunk_callback(|_hunk| {
|
|
let res = if hunk_idx == hunk_index.unwrap() {
|
|
count += 1;
|
|
true
|
|
} else {
|
|
false
|
|
};
|
|
|
|
hunk_idx += 1;
|
|
|
|
res
|
|
});
|
|
if repo
|
|
.apply(&diff, ApplyLocation::Index, Some(&mut opt))
|
|
.is_err()
|
|
{
|
|
error!("apply failed");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
count == 1
|
|
}
|