| /* |
| * libgit2 "init" example - shows how to initialize a new repo |
| * |
| * Written by the libgit2 contributors |
| * |
| * To the extent possible under law, the author(s) have dedicated all copyright |
| * and related and neighboring rights to this software to the public domain |
| * worldwide. This software is distributed without any warranty. |
| * |
| * You should have received a copy of the CC0 Public Domain Dedication along |
| * with this software. If not, see |
| * <http://creativecommons.org/publicdomain/zero/1.0/>. |
| */ |
| |
| #![deny(warnings)] |
| |
| use git2::{Error, Repository, RepositoryInitMode, RepositoryInitOptions}; |
| use std::path::{Path, PathBuf}; |
| use structopt::StructOpt; |
| |
| #[derive(StructOpt)] |
| struct Args { |
| #[structopt(name = "directory")] |
| arg_directory: String, |
| #[structopt(name = "quiet", short, long)] |
| /// don't print information to stdout |
| flag_quiet: bool, |
| #[structopt(name = "bare", long)] |
| /// initialize a new bare repository |
| flag_bare: bool, |
| #[structopt(name = "dir", long = "template")] |
| /// use <dir> as an initialization template |
| flag_template: Option<String>, |
| #[structopt(name = "separate-git-dir", long)] |
| /// use <dir> as the .git directory |
| flag_separate_git_dir: Option<String>, |
| #[structopt(name = "initial-commit", long)] |
| /// create an initial empty commit |
| flag_initial_commit: bool, |
| #[structopt(name = "perms", long = "shared")] |
| /// permissions to create the repository with |
| flag_shared: Option<String>, |
| } |
| |
| fn run(args: &Args) -> Result<(), Error> { |
| let mut path = PathBuf::from(&args.arg_directory); |
| let repo = if !args.flag_bare |
| && args.flag_template.is_none() |
| && args.flag_shared.is_none() |
| && args.flag_separate_git_dir.is_none() |
| { |
| Repository::init(&path)? |
| } else { |
| let mut opts = RepositoryInitOptions::new(); |
| opts.bare(args.flag_bare); |
| if let Some(ref s) = args.flag_template { |
| opts.template_path(Path::new(s)); |
| } |
| |
| // If you specified a separate git directory, then initialize |
| // the repository at that path and use the second path as the |
| // working directory of the repository (with a git-link file) |
| if let Some(ref s) = args.flag_separate_git_dir { |
| opts.workdir_path(&path); |
| path = PathBuf::from(s); |
| } |
| |
| if let Some(ref s) = args.flag_shared { |
| opts.mode(parse_shared(s)?); |
| } |
| Repository::init_opts(&path, &opts)? |
| }; |
| |
| // Print a message to stdout like "git init" does |
| if !args.flag_quiet { |
| if args.flag_bare || args.flag_separate_git_dir.is_some() { |
| path = repo.path().to_path_buf(); |
| } else { |
| path = repo.workdir().unwrap().to_path_buf(); |
| } |
| println!("Initialized empty Git repository in {}", path.display()); |
| } |
| |
| if args.flag_initial_commit { |
| create_initial_commit(&repo)?; |
| println!("Created empty initial commit"); |
| } |
| |
| Ok(()) |
| } |
| |
| /// Unlike regular "git init", this example shows how to create an initial empty |
| /// commit in the repository. This is the helper function that does that. |
| fn create_initial_commit(repo: &Repository) -> Result<(), Error> { |
| // First use the config to initialize a commit signature for the user. |
| let sig = repo.signature()?; |
| |
| // Now let's create an empty tree for this commit |
| let tree_id = { |
| let mut index = repo.index()?; |
| |
| // Outside of this example, you could call index.add_path() |
| // here to put actual files into the index. For our purposes, we'll |
| // leave it empty for now. |
| |
| index.write_tree()? |
| }; |
| |
| let tree = repo.find_tree(tree_id)?; |
| |
| // Ready to create the initial commit. |
| // |
| // Normally creating a commit would involve looking up the current HEAD |
| // commit and making that be the parent of the initial commit, but here this |
| // is the first commit so there will be no parent. |
| repo.commit(Some("HEAD"), &sig, &sig, "Initial commit", &tree, &[])?; |
| |
| Ok(()) |
| } |
| |
| fn parse_shared(shared: &str) -> Result<RepositoryInitMode, Error> { |
| match shared { |
| "false" | "umask" => Ok(git2::RepositoryInitMode::SHARED_UMASK), |
| "true" | "group" => Ok(git2::RepositoryInitMode::SHARED_GROUP), |
| "all" | "world" => Ok(git2::RepositoryInitMode::SHARED_ALL), |
| _ => { |
| if shared.starts_with('0') { |
| match u32::from_str_radix(&shared[1..], 8).ok() { |
| Some(n) => Ok(RepositoryInitMode::from_bits_truncate(n)), |
| None => Err(Error::from_str("invalid octal value for --shared")), |
| } |
| } else { |
| Err(Error::from_str("unknown value for --shared")) |
| } |
| } |
| } |
| } |
| |
| fn main() { |
| let args = Args::from_args(); |
| match run(&args) { |
| Ok(()) => {} |
| Err(e) => println!("error: {}", e), |
| } |
| } |