mirror of
https://github.com/gitui-org/gitui
synced 2026-05-24 09:28:21 +00:00
193 lines
4.1 KiB
Rust
193 lines
4.1 KiB
Rust
use git2::{
|
|
build::CheckoutBuilder, DiffFormat, DiffOptions, IndexAddOption,
|
|
ObjectType, Repository, StatusOptions, StatusShow,
|
|
};
|
|
use std::path::Path;
|
|
|
|
///
|
|
#[derive(Copy, Clone, PartialEq)]
|
|
pub enum DiffLineType {
|
|
None,
|
|
Header,
|
|
Add,
|
|
Delete,
|
|
}
|
|
|
|
impl Default for DiffLineType {
|
|
fn default() -> Self {
|
|
DiffLineType::None
|
|
}
|
|
}
|
|
|
|
///
|
|
#[derive(Default, PartialEq)]
|
|
pub struct DiffLine {
|
|
pub content: String,
|
|
pub line_type: DiffLineType,
|
|
}
|
|
|
|
///
|
|
#[derive(Default, PartialEq)]
|
|
pub struct Diff(pub Vec<DiffLine>);
|
|
|
|
///
|
|
pub fn get_diff(p: &Path, stage: bool) -> Diff {
|
|
let repo = repo();
|
|
|
|
let mut opt = DiffOptions::new();
|
|
opt.pathspec(p);
|
|
|
|
let diff = if !stage {
|
|
// diff against stage
|
|
repo.diff_index_to_workdir(None, Some(&mut opt)).unwrap()
|
|
} else {
|
|
// diff against head
|
|
let ref_head = repo.head().unwrap();
|
|
let parent =
|
|
repo.find_commit(ref_head.target().unwrap()).unwrap();
|
|
let tree = parent.tree().unwrap();
|
|
repo.diff_tree_to_index(
|
|
Some(&tree),
|
|
Some(&repo.index().unwrap()),
|
|
Some(&mut opt),
|
|
)
|
|
.unwrap()
|
|
};
|
|
|
|
let mut res = Vec::new();
|
|
|
|
diff.print(DiffFormat::Patch, |_delta, _hunk, line| {
|
|
let origin = line.origin();
|
|
|
|
if origin != 'F' {
|
|
let line_type = match origin {
|
|
'H' => DiffLineType::Header,
|
|
'<' | '-' => DiffLineType::Delete,
|
|
'>' | '+' => DiffLineType::Add,
|
|
_ => DiffLineType::None,
|
|
};
|
|
|
|
let diff_line = DiffLine {
|
|
content: String::from_utf8_lossy(line.content())
|
|
.to_string(),
|
|
line_type,
|
|
};
|
|
|
|
if line_type == DiffLineType::Header && res.len() > 0 {
|
|
res.push(DiffLine {
|
|
content: "\n".to_string(),
|
|
line_type: DiffLineType::None,
|
|
});
|
|
}
|
|
|
|
res.push(diff_line);
|
|
}
|
|
true
|
|
})
|
|
.unwrap();
|
|
|
|
Diff(res)
|
|
}
|
|
|
|
///
|
|
pub fn repo() -> Repository {
|
|
let repo = Repository::init("./").unwrap();
|
|
|
|
if repo.is_bare() {
|
|
panic!("bare repo")
|
|
}
|
|
|
|
repo
|
|
}
|
|
|
|
///
|
|
pub fn commit(msg: &String) {
|
|
let repo = repo();
|
|
|
|
let signature = repo.signature().unwrap();
|
|
let reference = repo.head().unwrap();
|
|
let mut index = repo.index().unwrap();
|
|
let tree_id = index.write_tree().unwrap();
|
|
let tree = repo.find_tree(tree_id).unwrap();
|
|
let parent =
|
|
repo.find_commit(reference.target().unwrap()).unwrap();
|
|
|
|
repo.commit(
|
|
Some("HEAD"),
|
|
&signature,
|
|
&signature,
|
|
msg.as_str(),
|
|
&tree,
|
|
&[&parent],
|
|
)
|
|
.unwrap();
|
|
}
|
|
|
|
///
|
|
pub fn index_empty() -> bool {
|
|
let repo = repo();
|
|
|
|
let statuses = repo
|
|
.statuses(Some(
|
|
StatusOptions::default().show(StatusShow::Index),
|
|
))
|
|
.unwrap();
|
|
|
|
statuses.is_empty()
|
|
}
|
|
|
|
pub fn stage_add(path: &Path) -> bool {
|
|
let repo = repo();
|
|
|
|
let mut index = repo.index().unwrap();
|
|
|
|
let cb = &mut |p: &Path, _matched_spec: &[u8]| -> i32 {
|
|
if p == path {
|
|
0
|
|
} else {
|
|
1
|
|
}
|
|
};
|
|
let cb = Some(cb as &mut git2::IndexMatchedPath);
|
|
|
|
let flags = IndexAddOption::DISABLE_PATHSPEC_MATCH
|
|
| IndexAddOption::CHECK_PATHSPEC;
|
|
|
|
if let Ok(_) = index.add_all(path, flags, cb) {
|
|
index.write().unwrap();
|
|
return true;
|
|
}
|
|
|
|
false
|
|
}
|
|
|
|
pub fn stage_reset(path: &Path) -> bool {
|
|
let repo = repo();
|
|
|
|
let reference = repo.head().unwrap();
|
|
let obj = repo
|
|
.find_object(
|
|
reference.target().unwrap(),
|
|
Some(ObjectType::Commit),
|
|
)
|
|
.unwrap();
|
|
|
|
if let Ok(_) = repo.reset_default(Some(&obj), &[path]) {
|
|
return true;
|
|
}
|
|
|
|
false
|
|
}
|
|
|
|
pub fn index_reset(path: &Path) -> bool {
|
|
let repo = repo();
|
|
|
|
let mut checkout_opts = CheckoutBuilder::new();
|
|
checkout_opts.path(&path).force();
|
|
|
|
if let Ok(_) = repo.checkout_head(Some(&mut checkout_opts)) {
|
|
return true;
|
|
}
|
|
|
|
false
|
|
}
|