Skip to content

fix for linux hooks #386

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Nov 1, 2020
Merged
102 changes: 95 additions & 7 deletions asyncgit/src/sync/hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::{
};

const HOOK_POST_COMMIT: &str = ".git/hooks/post-commit";
const HOOK_PRE_COMMIT: &str = ".git/hooks/pre-commit";
const HOOK_COMMIT_MSG: &str = ".git/hooks/commit-msg";
const HOOK_COMMIT_MSG_TEMP_FILE: &str = ".git/COMMIT_EDITMSG";

Expand Down Expand Up @@ -45,6 +46,21 @@ pub fn hooks_commit_msg(
}
}

/// this hook is documented here https://git-scm.com/docs/githooks#_pre_commit
///
pub fn hooks_pre_commit(repo_path: &str) -> Result<HookResult> {
scope_time!("hooks_pre_commit");

let work_dir = work_dir_as_string(repo_path)?;

if hook_runable(work_dir.as_str(), HOOK_PRE_COMMIT) {
let res = run_hook(work_dir.as_str(), HOOK_PRE_COMMIT, &[]);

Ok(res)
} else {
Ok(HookResult::Ok)
}
}
///
pub fn hooks_post_commit(repo_path: &str) -> Result<HookResult> {
scope_time!("hooks_post_commit");
Expand Down Expand Up @@ -94,13 +110,8 @@ fn run_hook(
hook_script: &str,
args: &[&str],
) -> HookResult {
let mut bash_args = vec![hook_script.to_string()];
bash_args.extend_from_slice(
&args
.iter()
.map(|x| (*x).to_string())
.collect::<Vec<String>>(),
);
let arg_str = format!("{} {}", hook_script, args.join(" "));
let bash_args = vec!["-c".to_string(), arg_str];

let output = Command::new("bash")
.args(bash_args)
Expand Down Expand Up @@ -204,6 +215,83 @@ exit 0
assert_eq!(msg, String::from("test"));
}

#[test]
fn test_pre_commit_sh() {
let (_td, repo) = repo_init().unwrap();
let root = repo.path().parent().unwrap();
let repo_path = root.as_os_str().to_str().unwrap();

let hook = b"#!/bin/sh
exit 0
";

create_hook(root, HOOK_PRE_COMMIT, hook);
let res = hooks_pre_commit(repo_path).unwrap();
assert_eq!(res, HookResult::Ok);
}

#[test]
fn test_pre_commit_fail_sh() {
let (_td, repo) = repo_init().unwrap();
let root = repo.path().parent().unwrap();
let repo_path = root.as_os_str().to_str().unwrap();

let hook = b"#!/bin/sh
echo 'rejected'
exit 1
";

create_hook(root, HOOK_PRE_COMMIT, hook);
let res = hooks_pre_commit(repo_path).unwrap();
assert!(res != HookResult::Ok);
}

#[test]
fn test_pre_commit_py() {
let (_td, repo) = repo_init().unwrap();
let root = repo.path().parent().unwrap();
let repo_path = root.as_os_str().to_str().unwrap();

// mirror how python pre-commmit sets itself up
#[cfg(not(windows))]
let hook = b"#!/usr/bin/env python
import sys
sys.exit(0)
";
#[cfg(windows)]
let hook = b"#!/bin/env python.exe
import sys
sys.exit(0)
";

create_hook(root, HOOK_PRE_COMMIT, hook);
let res = hooks_pre_commit(repo_path).unwrap();
assert_eq!(res, HookResult::Ok);
}

#[test]
fn test_pre_commit_fail_py() {
let (_td, repo) = repo_init().unwrap();
let root = repo.path().parent().unwrap();
let repo_path = root.as_os_str().to_str().unwrap();

// mirror how python pre-commmit sets itself up
#[cfg(not(windows))]
let hook = b"#!/usr/bin/env python
import sys
sys.exit(1)
";
#[cfg(windows)]
let hook = b"#!/bin/env python.exe
import sys
sys.exit(1)
";

create_hook(root, HOOK_PRE_COMMIT, hook);
let res = hooks_pre_commit(repo_path).unwrap();
assert!(res != HookResult::Ok);
}

#[test]
fn test_hooks_commit_msg_reject() {
let (_td, repo) = repo_init().unwrap();
Expand Down
4 changes: 3 additions & 1 deletion asyncgit/src/sync/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ pub use commit_details::{
pub use commit_files::get_commit_files;
pub use commits_info::{get_commits_info, CommitId, CommitInfo};
pub use diff::get_diff_commit;
pub use hooks::{hooks_commit_msg, hooks_post_commit, HookResult};
pub use hooks::{
hooks_commit_msg, hooks_post_commit, hooks_pre_commit, HookResult,
};
pub use hunks::{reset_hunk, stage_hunk, unstage_hunk};
pub use ignore::add_to_ignore;
pub use logwalker::LogWalker;
Expand Down
10 changes: 10 additions & 0 deletions src/components/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,16 @@ impl CommitComponent {
}

fn commit_msg(&mut self, msg: String) -> Result<()> {
if let HookResult::NotOk(e) = sync::hooks_pre_commit(CWD)? {
log::error!("pre-commit hook error: {}", e);
self.queue.borrow_mut().push_back(
InternalEvent::ShowErrorMsg(format!(
"pre-commit hook error:\n{}",
e
)),
);
return Ok(());
}
let mut msg = msg;
if let HookResult::NotOk(e) =
sync::hooks_commit_msg(CWD, &mut msg)?
Expand Down
33 changes: 23 additions & 10 deletions src/components/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ use super::{
};
use crate::{keys::SharedKeyConfig, strings, ui};
use crossterm::event::Event;
use std::convert::TryFrom;
use tui::{
backend::Backend,
layout::{Alignment, Rect},
text::{Span, Spans},
text::Span,
widgets::{Block, BorderType, Borders, Clear, Paragraph, Wrap},
Frame,
};
use ui::style::SharedTheme;

pub struct MsgComponent {
title: String,
msg: String,
Expand All @@ -32,17 +32,30 @@ impl DrawableComponent for MsgComponent {
if !self.visible {
return Ok(());
}
let txt = Spans::from(
self.msg
.split('\n')
.map(|string| Span::raw::<String>(string.to_string()))
.collect::<Vec<Span>>(),
);

let area = ui::centered_rect_absolute(65, 25, f.size());
// determine the maximum width of text block
let lens = self
.msg
.split('\n')
.map(str::len)
.collect::<Vec<usize>>();
let mut max = lens.iter().max().expect("max") + 2;
if max > std::u16::MAX as usize {
max = std::u16::MAX as usize;
}
let mut width =
u16::try_from(max).expect("cant fail due to check above");
// dont overflow screen, and dont get too narrow
if width > f.size().width {
width = f.size().width
} else if width < 60 {
width = 60
}

let area = ui::centered_rect_absolute(width, 25, f.size());
f.render_widget(Clear, area);
f.render_widget(
Paragraph::new(txt)
Paragraph::new(self.msg.clone())
.block(
Block::default()
.title(Span::styled(
Expand Down