async-git 0.0.0-squat-name

Pure-rust async implementation of git built on tokio
Documentation
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(())
    }
}