async_git/porcelain/
init.rs

1use std::env;
2use std::path::PathBuf;
3
4use futures::future::TryFutureExt;
5use tokio::fs::{self};
6
7use crate::errors::Result;
8use crate::config::Config;
9
10#[derive(Debug, StructOpt)]
11pub struct InitOptions {
12    /// Specify the directory from which templates will be used.
13    #[structopt(long = "template")]
14    template: Option<PathBuf>,
15
16    /// Create a bare repository.
17    #[structopt(long = "bare")]
18    bare: bool,
19
20    /// The directory where the git repository should be initialized.
21    ///
22    /// If you don't provide this value, the current working directory will be used.
23    /// If the directory you provided doesn't exist, it will be created.
24    directory: Option<PathBuf>,
25}
26
27pub async fn init_cmd(options: InitOptions) -> Result<()> {
28    let mut target_directory = match options.directory {
29        Some(dir) => dir,
30        None => env::current_dir()?,
31    };
32
33    if !options.bare {
34        target_directory.push(".git");
35    }
36
37    fs::create_dir_all(&target_directory).await?;
38
39    // make contents of the git directory
40    try_join!(
41        fs::create_dir(target_directory.join("branches")),
42        fs::create_dir(target_directory.join("objects")),
43        fs::create_dir(target_directory.join("refs")).and_then(|_| async {
44            try_join!(
45                fs::create_dir(target_directory.join("refs").join("tags")),
46                fs::create_dir(target_directory.join("refs").join("heads"))
47            )
48        }),
49        crate::util::init_file(
50            target_directory.join("description"),
51            "Unnamed repository; edit this file 'description' to name the repository.\n"
52        ),
53        crate::util::init_file(target_directory.join("HEAD"), "ref: refs/heads/master\n"),
54        Config::default()
55            .to_string()
56            .and_then(|config| crate::util::init_file(target_directory.join("config"), config)),
57    )?;
58
59    Ok(())
60}