CLI Definition in Rust

Writing CLIs in Rust is an absolute pleasure. Using a crate like structopt, you can define the structure of your CLI and it handles cleaning the input and converting it to an appropriate type.

#[derive(Debug, StructOpt)]
#[structopt(name = "TGit", about = "HedonHermDev's implementation of Git")]
pub enum CLI {

    #[structopt(
    name = "init",
    about = "Initialize an empty git repository"
    )]
    Init { git_dir: Option<PathBuf> },

    #[structopt(name = "cat-file", about = "Cat the contents of a git object")]
    CatFile {
        #[structopt(
            name = "pretty_print",
            short = "p",
            about = "Pretty print the contents"
        )]
        pretty_print: bool,
        #[structopt(name = "OBJECT SHA")]
        object_sha: String,
    },

   // -- snip --
}

impl CLI {
    pub async fn run() -> Result<()> {
        let args: Self = Self::from_args();

        match args {
            CLI::Init { git_dir } => commands::init(git_dir).await,

            CLI::CatFile {
                pretty_print,
                object_sha,
            } => commands::cat_file(pretty_print, object_sha).await,
        }
    }
}

The above code should be fairly legible even if you don’t understand Rust. It defines the CLI as a set of subcommands with each command getting its arguments as a struct. This leverages the power of Rust’s enums. Now, we can write functions that ex ecute the above subcommands in the commands.rs file. For the init and the cat-file command, the implementation looks something like this:

pub async fn init(git_dir: Option<PathBuf>) -> Result<()> {

// -- snip --

}

pub async fn cat_file(pretty_print: bool, object_sha: String)
-> Result<()> {

// -- snip --

}

Similar functions are defined for the other commands.

Next

Move on to [[git/implementation]] to read about the implementation of the object storage of git.