use std::{collections::HashMap, env, ffi::OsString};
mod pull_request;
use self::pull_request::PullRequest;
use config::Config;
use git2::Repository;
use keep_a_changelog::{ChangeKind, ChangelogParseOptions};
use crate::Error;
use crate::PrTitle;
pub struct Client {
#[allow(dead_code)]
pub(crate) settings: Config,
pub(crate) git_repo: Repository,
pub(crate) owner: String,
pub(crate) repo: String,
pub(crate) branch: Option<String>,
pull_request: Option<PullRequest>,
pub(crate) changelog: OsString,
pub(crate) changelog_parse_options: ChangelogParseOptions,
pub(crate) changelog_update: Option<PrTitle>,
}
impl Client {
pub async fn new_with(settings: Config) -> Result<Self, Error> {
log::trace!(
"new_with settings: {:#?}",
settings
.clone()
.try_deserialize::<HashMap<String, String>>()?,
);
let cmd = settings
.get::<String>("command")
.map_err(|_| Error::CommandNotSet)?;
log::trace!("cmd: {:?}", cmd);
log::trace!("owner: {:?}", settings.get::<String>("username"));
let pcu_owner: String = settings
.get("username")
.map_err(|_| Error::EnvVarBranchNotSet)?;
let owner = env::var(pcu_owner).map_err(|_| Error::EnvVarBranchNotFound)?;
log::trace!("repo: {:?}", settings.get::<String>("reponame"));
let pcu_owner: String = settings
.get("reponame")
.map_err(|_| Error::EnvVarBranchNotSet)?;
let repo = env::var(pcu_owner).map_err(|_| Error::EnvVarBranchNotFound)?;
let (branch, pull_request) = if &cmd == "pull-request" {
log::trace!("branch: {:?}", settings.get::<String>("branch"));
let pcu_branch: String = settings
.get("branch")
.map_err(|_| Error::EnvVarBranchNotSet)?;
let branch = env::var(pcu_branch).map_err(|_| Error::EnvVarBranchNotFound)?;
let branch = if branch.is_empty() {
None
} else {
Some(branch)
};
let pull_request = PullRequest::new_pull_request_opt(&settings).await?;
(branch, pull_request)
} else {
let branch = None;
let pull_request = None;
(branch, pull_request)
};
log::trace!("log: {:?}", settings.get::<String>("log"));
let default_change_log: String = settings
.get("log")
.map_err(|_| Error::DefaultChangeLogNotSet)?;
let mut changelog = OsString::from(default_change_log);
if let Ok(files) = std::fs::read_dir(".") {
for file in files.into_iter().flatten() {
log::trace!("File: {:?}", file.path());
if file
.file_name()
.to_string_lossy()
.to_lowercase()
.contains("change")
&& file.file_type().unwrap().is_file()
{
changelog = file.file_name();
break;
}
}
};
let git_repo = git2::Repository::open(".")?;
let svs_root = settings
.get("dev_platform")
.unwrap_or_else(|_| "https://github.com/".to_string());
let prefix = settings
.get("version_prefix")
.unwrap_or_else(|_| "v".to_string());
let repo_url = Some(format!("{}{}/{}", svs_root, owner, repo));
let changelog_parse_options = ChangelogParseOptions {
url: repo_url,
head: Some("HEAD".to_string()),
tag_prefix: Some(prefix),
};
Ok(Self {
settings,
git_repo,
branch,
owner,
repo,
pull_request,
changelog,
changelog_parse_options,
changelog_update: None,
})
}
pub fn branch(&self) -> &str {
if let Some(branch) = self.branch.as_ref() {
branch
} else {
"main"
}
}
pub fn pull_request(&self) -> &str {
if let Some(pr) = self.pull_request.as_ref() {
&pr.pull_request
} else {
""
}
}
pub fn title(&self) -> &str {
if let Some(pr) = self.pull_request.as_ref() {
&pr.title
} else {
""
}
}
pub fn pr_number(&self) -> u64 {
if let Some(pr) = self.pull_request.as_ref() {
pr.pr_number
} else {
0
}
}
pub fn owner(&self) -> &str {
&self.owner
}
pub fn repo(&self) -> &str {
&self.repo
}
pub fn set_title(&mut self, title: &str) {
if self.pull_request.is_some() {
self.pull_request.as_mut().unwrap().title = title.to_string();
}
}
pub fn is_default_branch(&self) -> bool {
let default_branch = self
.settings
.get::<String>("default_branch")
.unwrap_or("main".to_string());
self.branch == Some(default_branch)
}
pub fn section(&self) -> Option<&str> {
if let Some(update) = &self.changelog_update {
if let Some(section) = &update.section {
match section {
ChangeKind::Added => Some("Added"),
ChangeKind::Changed => Some("Changed"),
ChangeKind::Deprecated => Some("Deprecated"),
ChangeKind::Fixed => Some("Fixed"),
ChangeKind::Removed => Some("Removed"),
ChangeKind::Security => Some("Security"),
}
} else {
None
}
} else {
None
}
}
pub fn entry(&self) -> Option<&str> {
if let Some(update) = &self.changelog_update {
Some(&update.entry)
} else {
None
}
}
pub fn changelog_as_str(&self) -> &str {
if let Some(cl) = &self.changelog.to_str() {
cl
} else {
""
}
}
pub fn set_changelog(&mut self, changelog: &str) {
self.changelog = changelog.into();
}
}