use std::ffi::OsString;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SequencerState {
InProgress,
NotInProgress,
}
pub const SEQUENCER_HEAD_FILES: &[&str] = &["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD"];
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct SequencerFacts {
pub merge_head: bool,
pub cherry_pick_head: bool,
pub revert_head: bool,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct SequencerOutputError;
impl std::fmt::Display for SequencerOutputError {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
return formatter.write_str(
"git rev-parse --git-path did not print the three sequencer head paths of one Git directory",
);
}
}
impl std::error::Error for SequencerOutputError {}
pub fn sequencer_query_arguments(global_prefix: &[OsString]) -> Vec<OsString> {
let mut arguments: Vec<OsString> = global_prefix.to_vec();
arguments.push(OsString::from("rev-parse"));
arguments.push(OsString::from("--path-format=absolute"));
for name in SEQUENCER_HEAD_FILES {
arguments.push(OsString::from("--git-path"));
arguments.push(OsString::from(name));
}
return arguments;
}
pub fn sequencer_head_paths(stdout: &[u8]) -> Result<Vec<Vec<u8>>, SequencerOutputError> {
let mut fixed: usize = 0;
for name in SEQUENCER_HEAD_FILES {
fixed += name.len() + 1;
}
if stdout.len() < fixed {
return Err(SequencerOutputError);
}
if !(stdout.len() - fixed).is_multiple_of(SEQUENCER_HEAD_FILES.len()) {
return Err(SequencerOutputError);
}
let directory_length: usize = (stdout.len() - fixed) / SEQUENCER_HEAD_FILES.len();
let directory: &[u8] = &stdout[..directory_length];
let mut paths: Vec<Vec<u8>> = Vec::<Vec<u8>>::new();
let mut offset: usize = 0;
for name in SEQUENCER_HEAD_FILES {
let mut path: Vec<u8> = directory.to_vec();
path.extend_from_slice(name.as_bytes());
let end: usize = offset + path.len();
if &stdout[offset..end] != path.as_slice() || stdout[end] != b'\n' {
return Err(SequencerOutputError);
}
offset = end + 1;
paths.push(path);
}
return Ok(paths);
}
pub fn sequencer_state(facts: SequencerFacts) -> SequencerState {
if facts.merge_head || facts.cherry_pick_head || facts.revert_head {
return SequencerState::InProgress;
}
return SequencerState::NotInProgress;
}
pub fn sequencer_state_when_query_fails() -> SequencerState {
return SequencerState::NotInProgress;
}
#[cfg(test)]
#[path = "rule_commit_sequencer_tests.rs"]
mod tests;