Skip to content
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

feat: use gix for parsing git information in mitre/git plugin #663

Merged
merged 1 commit into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
804 changes: 802 additions & 2 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 1 addition & 3 deletions hipcheck-common/src/chunk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,7 @@ mod test {
let res = match chunk_with_size(query, 10) {
Ok(r) => r,
Err(e) => {
println!("{e}");
assert!(false);
return;
panic!("{e}");
patrickjcasey marked this conversation as resolved.
Show resolved Hide resolved
}
};
assert_eq!(res.len(), 4);
Expand Down
23 changes: 10 additions & 13 deletions hipcheck/src/policy_exprs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ mod tests {
let program =
"(eq 3 (count (filter (gt 8.0) (foreach (sub 1.0) [1.0 2.0 10.0 20.0 30.0]))))";
let context = Value::Null;
let expr = parse(&program).unwrap();
let expr = parse(program).unwrap();
println!("EXPR: {:?}", &expr);
let expr = FunctionResolver::std().run(expr).unwrap();
let expr = TypeFixer::std().run(expr).unwrap();
Expand Down Expand Up @@ -352,13 +352,12 @@ mod tests {
#[test]
fn type_lambda() {
let program = "(gt #t)";
let expr = parse(&program).unwrap();
let expr = parse(program).unwrap();
let expr = FunctionResolver::std().run(expr).unwrap();
let expr = TypeFixer::std().run(expr).unwrap();
let res_ty = TypeChecker::default().run(&expr);
let Ok(Type::Lambda(l_ty)) = res_ty else {
assert!(false);
return;
panic!();
};
let ret_ty = l_ty.get_return_type();
assert_eq!(ret_ty, Ok(ReturnableType::Primitive(PrimitiveType::Bool)));
Expand All @@ -368,7 +367,7 @@ mod tests {
fn type_filter_bad_lambda_array() {
// Should fail because can't compare ints and bools
let program = "(filter (gt #t) [1 2])";
let expr = parse(&program).unwrap();
let expr = parse(program).unwrap();
let expr = FunctionResolver::std().run(expr).unwrap();
let expr = TypeFixer::std().run(expr).unwrap();
let res_ty = TypeChecker::default().run(&expr);
Expand All @@ -386,7 +385,7 @@ mod tests {
fn type_array_mixed_types() {
// Should fail because array elts must have one primitive type
let program = "(count [#t 2])";
let mut expr = parse(&program).unwrap();
let mut expr = parse(program).unwrap();
expr = FunctionResolver::std().run(expr).unwrap();
let res_ty = TypeChecker::default().run(&expr);
assert_eq!(
Expand All @@ -403,26 +402,24 @@ mod tests {
fn type_propagate_unknown() {
// Type for array should be unknown because we can't know ident type
let program = "(max [])";
let mut expr = parse(&program).unwrap();
let mut expr = parse(program).unwrap();
expr = FunctionResolver::std().run(expr).unwrap();
let res_ty = TypeChecker::default().run(&expr);
let Ok(Type::Function(f_ty)) = res_ty else {
assert!(false);
return;
panic!()
};
assert_eq!(f_ty.get_return_type(), Ok(ReturnableType::Unknown));
}

#[test]
fn type_not() {
let program = "(not $)";
let mut expr = parse(&program).unwrap();
let mut expr = parse(program).unwrap();
expr = FunctionResolver::std().run(expr).unwrap();
let res_ty = TypeChecker::default().run(&expr);
println!("RESTY: {res_ty:?}");
let Ok(Type::Function(f_ty)) = res_ty else {
assert!(false);
return;
panic!()
};
let ret_ty = f_ty.get_return_type();
assert_eq!(ret_ty, Ok(ReturnableType::Primitive(PrimitiveType::Bool)));
Expand All @@ -433,7 +430,7 @@ mod tests {
let programs = vec!["(not $)", "(gt 0)", "(filter (gt 0) $/alpha)"];

for program in programs {
let mut expr = parse(&program).unwrap();
let mut expr = parse(program).unwrap();
expr = FunctionResolver::std().run(expr).unwrap();
expr = TypeFixer::std().run(expr).unwrap();
let string = expr.to_string();
Expand Down
5 changes: 4 additions & 1 deletion plugins/git/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@ clap = { version = "4.5.23", features = ["derive"] }
hipcheck-sdk = { version = "0.2.0", path = "../../sdk/rust", features = [
"macros",
] }
gix = { version = "0.68.0", default-features = false, features = [
"basic",
"max-performance",
] }
jiff = { version = "0.1.14", features = ["serde"] }
log = "0.4.22"
nom = "7.1.3"
once_cell = "1.10.0"
schemars = { version = "0.8.21", features = ["url"] }
semver = "1.0.9"
Expand Down
99 changes: 77 additions & 22 deletions plugins/git/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use serde::{Deserialize, Serialize};
use std::{
fmt::{self, Display, Formatter},
hash::Hash,
sync::Arc,
};

/// A locally stored git repo, with optional additional details
Expand All @@ -21,15 +20,44 @@ pub struct DetailedGitRepo {
}

/// Commits as they come directly out of `git log`.
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
pub struct RawCommit {
pub hash: String,

pub author: Contributor,
pub written_on: Result<String, String>,
pub written_on: Result<jiff::Timestamp, String>,

pub committer: Contributor,
pub committed_on: Result<String, String>,
pub committed_on: Result<jiff::Timestamp, String>,
}

impl TryFrom<gix::Commit<'_>> for RawCommit {
type Error = anyhow::Error;

fn try_from(value: gix::Commit<'_>) -> Result<Self, Self::Error> {
let commit_author = value.author()?;
let author = Contributor {
name: commit_author.name.to_string(),
email: commit_author.email.to_string(),
};
let written_on =
jiff::Timestamp::from_second(commit_author.time.seconds).map_err(|x| x.to_string());
let commit_committer = value.committer()?;
let committer = Contributor {
name: commit_committer.name.to_string(),
email: commit_committer.email.to_string(),
};
let committed_on =
jiff::Timestamp::from_second(commit_committer.time.seconds).map_err(|x| x.to_string());

Ok(Self {
hash: value.id().to_string(),
author,
written_on,
committer,
committed_on,
})
}
}

/// Commits as understood in Hipcheck's data model.
Expand All @@ -39,12 +67,20 @@ pub struct RawCommit {
#[derive(Debug, Serialize, Clone, PartialEq, Eq, Hash, JsonSchema)]
pub struct Commit {
pub hash: String,

pub written_on: Result<String, String>,

pub committed_on: Result<String, String>,
}

impl From<RawCommit> for Commit {
fn from(value: RawCommit) -> Self {
Self {
hash: value.hash,
written_on: value.written_on.map(|x| x.to_string()),
committed_on: value.committed_on.map(|x| x.to_string()),
}
}
}

impl Display for Commit {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}", self.hash)
Expand Down Expand Up @@ -98,39 +134,58 @@ pub struct CommitDiff {
pub diff: Diff,
}

impl CommitDiff {
pub fn new(commit: Commit, diff: Diff) -> Self {
Self { commit, diff }
}
}

impl Display for CommitDiff {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(
f,
"{} +{} -{}",
self.commit,
self.diff
.additions
.map(|n| n.to_string())
.as_deref()
.unwrap_or("<unknown>"),
self.diff
.deletions
.map(|n| n.to_string())
.as_deref()
.unwrap_or("<unknown>")
self.commit, self.diff.additions, self.diff.deletions
)
}
}

/// A set of changes in a commit.
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
pub struct Diff {
pub additions: Option<i64>,
pub deletions: Option<i64>,
pub additions: i64,
pub deletions: i64,
pub file_diffs: Vec<FileDiff>,
}

/// A set of changes to a specific file in a commit.
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
pub struct FileDiff {
pub file_name: Arc<String>,
pub additions: Option<i64>,
pub deletions: Option<i64>,
pub file_name: String,
pub additions: i64,
pub deletions: i64,
pub patch: String,
}

impl FileDiff {
pub fn new(file_name: String) -> Self {
Self {
file_name,
additions: 0,
deletions: 0,
patch: String::new(),
}
}

pub fn increment_additions(&mut self, additions: i64) {
self.additions += additions
}

pub fn increment_deletions(&mut self, deletions: i64) {
self.deletions += deletions
}

pub fn set_patch(&mut self, patch_data: String) {
self.patch = patch_data;
}
}
Loading
Loading