use std::fs;
use sley_config::remotes::{self, RemoteEditError, SetUrlKind, SetUrlOp};
use sley_config::{ConfigEntry, ConfigSection, GitConfig};
use crate::{GitError, Repository, Result};
impl Repository {
pub fn load_repo_config(&self) -> Result<GitConfig> {
self.config()
}
pub fn save_repo_config(&self, config: &GitConfig) -> Result<()> {
let bytes = if config.preamble.is_empty()
&& config.suffix.is_empty()
&& config.sections.iter().all(|section| {
section.preamble.is_empty()
&& section
.entries
.iter()
.all(|entry| entry.preamble.is_empty() && entry.comment.is_none())
}) {
config.to_canonical_bytes()
} else {
config.to_preserved_bytes()
};
fs::write(self.common_dir().join("config"), bytes)?;
Ok(())
}
pub fn add_remote(&self, name: &str, url: &str) -> Result<()> {
let mut config = self.load_repo_config()?;
remotes::add_remote_with_fetch(&mut config, name, url, &[]).map_err(remote_edit_error)?;
self.save_repo_config(&config)
}
pub fn remove_remote(&self, name: &str) -> Result<()> {
let mut config = self.load_repo_config()?;
remotes::remove_remote(&mut config, name).map_err(remote_edit_error)?;
self.save_repo_config(&config)
}
pub fn set_remote_url(&self, name: &str, url: &str) -> Result<()> {
let mut config = self.load_repo_config()?;
remotes::set_url(&mut config, name, SetUrlKind::Fetch, SetUrlOp::Set { url })
.map_err(set_url_error)?;
self.save_repo_config(&config)
}
pub fn init_mirror(path: impl AsRef<std::path::Path>) -> Result<Self> {
let repo = Repository::init_bare(path)?;
let mut config = repo.load_repo_config()?;
config.sections.push(ConfigSection::new(
"remote",
Some("origin".into()),
vec![
ConfigEntry::new("fetch", Some("+refs/*:refs/*".into())),
ConfigEntry::new("mirror", Some("true".into())),
],
));
repo.save_repo_config(&config)?;
Ok(repo)
}
}
fn remote_edit_error(err: RemoteEditError) -> GitError {
match err {
RemoteEditError::AlreadyExists => GitError::Command("remote already exists".into()),
RemoteEditError::NotFound => GitError::remote_not_found("remote not found"),
}
}
fn set_url_error(err: remotes::SetUrlError) -> GitError {
match err {
remotes::SetUrlError::RemoteNotFound => GitError::remote_not_found("remote not found"),
remotes::SetUrlError::NoMatch => GitError::not_found("remote url did not match"),
remotes::SetUrlError::DeleteNoMatch => GitError::not_found("remote url did not match"),
remotes::SetUrlError::DeleteAllFetchUrls => {
GitError::Command("cannot delete every fetch url".into())
}
remotes::SetUrlError::MultipleValues => {
GitError::Command("remote has multiple url values".into())
}
}
}