gitui/src/git_utils.rs

145 lines
3.3 KiB
Rust

use git2::{DiffFormat, DiffOptions, Repository, StatusOptions, StatusShow};
use std::path::Path;
use tui::layout::{Constraint, Direction, Layout, Rect};
///
#[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) -> Diff {
let repo = repo();
let mut opt = DiffOptions::new();
opt.pathspec(p);
let diff = repo.diff_index_to_workdir(None, 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();
}
/// use layouts to create a rects that
/// centers inside `r` and sizes `percent_x`/`percent_x` of `r`
pub fn centered_rect(percent_x: u16, percent_y: u16, r: Rect) -> Rect {
let popup_layout = Layout::default()
.direction(Direction::Vertical)
.constraints(
[
Constraint::Percentage((100 - percent_y) / 2),
Constraint::Percentage(percent_y),
Constraint::Percentage((100 - percent_y) / 2),
]
.as_ref(),
)
.split(r);
Layout::default()
.direction(Direction::Horizontal)
.constraints(
[
Constraint::Percentage((100 - percent_x) / 2),
Constraint::Percentage(percent_x),
Constraint::Percentage((100 - percent_x) / 2),
]
.as_ref(),
)
.split(popup_layout[1])[1]
}
///
pub fn index_empty() -> bool {
let repo = repo();
let statuses = repo
.statuses(Some(StatusOptions::default().show(StatusShow::Index)))
.unwrap();
statuses.is_empty()
}