use std::io::{Cursor, Error as IOError};
use tokio::io::{AsyncWrite, AsyncWriteExt};
use crate::errors::Result;
#[derive(Clone, Debug, Default)]
pub struct Config {
pub core: CoreConfig,
}
#[derive(Clone, Debug)]
pub struct CoreConfig {
/// If `true` this repository is assumed to be `bare` and has no working directory associated with it. If this is the case a number of commands that require a working directory will be disabled, such as git-add or git-merge.
///
/// This setting is automatically guessed by git-clone or git-init when the repository was created. By default a repository that ends in `/.git` is assumed to be not bare (bare = `false`), while all other repositories are assumed to be bare (bare = `true`).
pub bare: bool,
/// Tells Git if the executable bit of files in the working tree is to be honored.
///
/// Some filesystems lose the executable bit when a file that is marked as executable is checked out, or checks out a non-executable file with executable bit on. git-clone or git-init probe the filesystem to see if it handles the executable bit correctly and this variable is automatically set as necessary.
///
/// A repository, however, may be on a filesystem that handles the filemode correctly, and this variable is set to `true` when created, but later may be made accessible from another environment that loses the filemode (e.g. exporting ext4 via CIFS mount, visiting a Cygwin created repository with Git for Windows or Eclipse). In such a case it may be necessary to set this variable to `false`. See git-update-index.
///
/// The default is `true` (when core.filemode is not specified in the config file).
pub file_mode: bool,
/// Enable the reflog. Updates to a ref `<ref>` is logged to the file `$GIT_DIR/logs/<ref>`, by appending the new and old SHA-1, the date/time and the reason of the update, but only when the file exists. If this configuration variable is set to `true`, missing `$GIT_DIR/logs/<ref>` file is automatically created for branch heads (i.e. under `refs/heads/`), remote refs (i.e. under `refs/remotes/`), note refs (i.e. under `refs/notes/`), and the symbolic ref HEAD. If it is set to always, then a missing reflog is automatically created for any ref under `refs/`.
///
/// This information can be used to determine what commit was the tip of a branch "2 days ago".
///
/// This value is `true` by default in a repository that has a working directory associated with it, and `false` by default in a bare repository.
pub log_all_ref_updates: bool,
/// Internal variable identifying the repository format and layout version.
pub repository_format_version: u32,
}
impl Default for CoreConfig {
fn default() -> Self {
CoreConfig {
bare: false,
file_mode: true,
log_all_ref_updates: true,
repository_format_version: 0,
}
}
}
impl Config {
pub async fn parse() -> Result<Self> {
Ok(Config::default())
}
pub async fn to_string(self) -> Result<String, IOError> {
let mut buffer = Vec::new();
let mut cursor = Cursor::new(&mut buffer);
self.write(&mut cursor).await?;
Ok(String::from_utf8(buffer).unwrap())
}
pub async fn write<W: AsyncWrite + Unpin>(&self, mut w: W) -> Result<(), IOError> {
{
let core = &self.core;
w.write_all(b"[core]\n").await?;
w.write_all(format!("bare = {}\n", core.bare).as_bytes())
.await?;
w.write_all(format!("fileMode = {}\n", core.file_mode).as_bytes())
.await?;
w.write_all(format!("logAllRefUpdates = {}\n", core.log_all_ref_updates).as_bytes())
.await?;
w.write_all(
format!(
"repositoryFormatVersion = {}\n",
core.repository_format_version
)
.as_bytes(),
)
.await?;
}
Ok(())
}
}