use std::ffi::OsString;
use std::path::Path;
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Stops {
pub no_commit: bool,
pub squash: bool,
pub edit: Option<bool>,
pub message: bool,
pub passed_on: Vec<OsString>,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Operation {
Merge,
Rebase,
Pick,
}
pub const HARMLESS_MERGE_OPTIONS: [&str; 21] = [
"-v", "--verbose", "--no-verbose", "--progress", "--no-progress", "--no-verify", "--verify", "--summary", "--no-summary",
"--no-signoff", "--no-verify-signatures", "--ff", "--no-ff", "--ff-only", "--allow-unrelated-histories", "--stat",
"--no-stat", "--log", "--no-log", "--quiet", "--autostash",
];
pub const HARMLESS_PULL_OPTIONS: [&str; 17] = [
"--rebase", "-r", "--no-rebase", "--rebase=true", "--rebase=false", "--rebase=merges", "--all", "--prune", "-p", "--no-prune",
"--tags", "-t", "--no-tags", "--force", "-f", "--no-recurse-submodules", "--ipv4",
];
pub const HARMLESS_PICK_OPTIONS: [&str; 13] = [
"-x", "--ff", "--allow-empty", "--allow-empty-message", "--keep-redundant-commits", "--rerere-autoupdate",
"--no-rerere-autoupdate", "--reference", "-q", "--quiet", "-v", "--verbose", "--no-verbose",
];
pub const VALUE_OPTIONS: [&str; 4] = ["-s", "--strategy", "-X", "--strategy-option"];
pub fn merge_stops(region: &[OsString], pull: bool) -> Option<Stops> {
let mut stops: Stops = Stops::default();
let mut tokens = region.iter();
while let Some(token) = tokens.next() {
let text: &str = token.to_str()?;
match text {
"--no-commit" => stops.no_commit = true,
"--commit" => stops.no_commit = false,
"--squash" => stops.squash = true,
"--no-squash" => stops.squash = false,
"-e" | "--edit" => stops.edit = Some(true),
"--no-edit" => stops.edit = Some(false),
"-m" | "--message" | "-F" | "--file" => {
tokens.next()?;
stops.message = true;
}
"--signoff" | "--no-gpg-sign" => stops.passed_on.push(token.clone()),
other if other.starts_with("--message=") || other.starts_with("--file=") => stops.message = true,
other if other.starts_with("-S") || other.starts_with("--gpg-sign") => stops.passed_on.push(token.clone()),
other if VALUE_OPTIONS.contains(&other) => {
tokens.next()?;
}
other if other.starts_with("--strategy=") || other.starts_with("--strategy-option=") => {}
other if HARMLESS_MERGE_OPTIONS.contains(&other) => {}
other if pull && HARMLESS_PULL_OPTIONS.contains(&other) => {}
other if other.starts_with('-') && other != "-" => return None,
_ => {}
}
}
return Some(stops);
}
pub fn pick_stops(region: &[OsString]) -> Option<(Stops, bool)> {
let mut stops: Stops = Stops::default();
let mut continuing: bool = false;
let mut tokens = region.iter();
while let Some(token) = tokens.next() {
let text: &str = token.to_str()?;
match text {
"-n" | "--no-commit" => stops.no_commit = true,
"-e" | "--edit" => stops.edit = Some(true),
"--no-edit" => stops.edit = Some(false),
"--continue" | "--skip" => continuing = true,
"-s" | "--signoff" => stops.passed_on.push(OsString::from("--signoff")),
"-m" | "--mainline" => {
tokens.next()?;
}
other if other.starts_with("--mainline=") || other.starts_with("--empty=") => {}
other if other.starts_with("-S") || other.starts_with("--gpg-sign") || other == "--no-gpg-sign" => stops.passed_on.push(token.clone()),
other if VALUE_OPTIONS.contains(&other) => {
tokens.next()?;
}
other if other.starts_with("--strategy=") || other.starts_with("--strategy-option=") => {}
other if HARMLESS_PICK_OPTIONS.contains(&other) => {}
other if other.starts_with('-') && other != "-" => return None,
_ => {}
}
}
return Some((stops, continuing));
}
pub fn saved_pick_stops(git_dir: &Path) -> Option<Stops> {
let text: String = std::fs::read_to_string(git_dir.join("sequencer/opts")).ok()?;
let mut stops: Stops = Stops::default();
for line in text.lines() {
let Some((name, value)) = line.split_once('=') else { continue };
match (name.trim(), value.trim()) {
("no-commit", "true") => stops.no_commit = true,
("edit", "true") => stops.edit = Some(true),
("edit", "false") => stops.edit = Some(false),
("signoff", "true") => stops.passed_on.push(OsString::from("--signoff")),
_ => {}
}
}
return Some(stops);
}