use crate::repo_read_layout::dot_git_target;
use crate::service_protocol::Cleanup;
use std::path::{Path, PathBuf};
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Intent {
pub seq: u64,
pub repository: PathBuf,
pub common_dir: PathBuf,
pub reference: String,
pub old: String,
pub new: String,
pub ids: Vec<String>,
pub commits: Vec<String>,
pub paths: Vec<String>,
pub derived: bool,
pub cleanup: Option<Cleanup>,
pub index: PathBuf,
pub git_dir: PathBuf,
}
pub fn intent_text(intent: &Intent) -> String {
let cleanup: String = match intent.cleanup.as_ref() {
Some(found) => format!("{}\t{}\t{}", found.git_dir.display(), found.scratch.display(), u8::from(found.reftable)),
None => String::new(),
};
return format!(
"seq={}\nrepository={}\ncommon={}\nref={}\nold={}\nnew={}\nids={}\ncommits={}\npaths={}\nderived={}\ncleanup={}\nindex={}\ngitdir={}\n",
intent.seq,
intent.repository.display(),
intent.common_dir.display(),
intent.reference,
intent.old,
intent.new,
intent.ids.join("\t"),
intent.commits.join("\t"),
intent.paths.join("\t"),
u8::from(intent.derived),
cleanup,
intent.index.display(),
intent.git_dir.display(),
);
}
pub(crate) fn git_dir_of_worktree(repository: &Path) -> PathBuf {
return match dot_git_target(repository) {
Some(Some((git_dir, _))) => git_dir,
Some(None) | None => repository.join(".git"),
};
}
pub(crate) fn intent_value<'a>(text: &'a str, key: &str) -> Option<&'a str> {
for line in text.lines() {
if let Some(rest) = line.strip_prefix(key)
&& let Some(found) = rest.strip_prefix('=')
{
return Some(found);
}
}
return None;
}
pub(crate) fn intent_list(text: &str, key: &str) -> Option<Vec<String>> {
let found: &str = intent_value(text, key)?;
let mut items: Vec<String> = Vec::new();
for item in found.split('\t') {
if !item.is_empty() {
items.push(item.to_string());
}
}
return Some(items);
}
pub(crate) fn parse_cleanup(entry: &str) -> Option<Cleanup> {
let mut parts = entry.split('\t');
let (git_dir, scratch, reftable) = (parts.next()?, parts.next()?, parts.next()?);
return Some(Cleanup { git_dir: PathBuf::from(git_dir), scratch: PathBuf::from(scratch), reftable: reftable == "1" });
}
pub fn parse_intent(text: &str) -> Option<Intent> {
let index: PathBuf = match intent_value(text, "index") {
Some(named) => PathBuf::from(named),
None => PathBuf::from(intent_value(text, "repository").unwrap_or("")).join(".git").join("index"),
};
let repository: PathBuf = PathBuf::from(intent_value(text, "repository")?);
let worktree_git_dir: PathBuf = match intent_value(text, "gitdir") {
Some(named) => PathBuf::from(named),
None => git_dir_of_worktree(repository.as_path()),
};
return Some(Intent {
seq: intent_value(text, "seq")?.parse().ok()?,
repository,
common_dir: PathBuf::from(intent_value(text, "common")?),
reference: intent_value(text, "ref")?.to_string(),
old: intent_value(text, "old")?.to_string(),
new: intent_value(text, "new")?.to_string(),
ids: intent_list(text, "ids")?,
commits: intent_list(text, "commits")?,
paths: intent_list(text, "paths")?,
derived: intent_value(text, "derived") == Some("1"),
index,
git_dir: worktree_git_dir,
cleanup: intent_value(text, "cleanup").and_then(parse_cleanup),
});
}