2 * libgit2 "init" example - shows how to initialize a new repo
4 * Written by the libgit2 contributors
6 * To the extent possible under law, the author(s) have dedicated all copyright
7 * and related and neighboring rights to this software to the public domain
8 * worldwide. This software is distributed without any warranty.
10 * You should have received a copy of the CC0 Public Domain Dedication along
11 * with this software. If not, see
12 * <http://creativecommons.org/publicdomain/zero/1.0/>.
20 extern crate serde_derive
;
23 use git2
::{Repository, RepositoryInitOptions, RepositoryInitMode, Error}
;
24 use std
::path
::{PathBuf, Path}
;
26 #[derive(Deserialize)]
28 arg_directory
: String
,
31 flag_template
: Option
<String
>,
32 flag_separate_git_dir
: Option
<String
>,
33 flag_initial_commit
: bool
,
34 flag_shared
: Option
<String
>,
37 fn run(args
: &Args
) -> Result
<(), Error
> {
38 let mut path
= PathBuf
::from(&args
.arg_directory
);
39 let repo
= if !args
.flag_bare
&& args
.flag_template
.is_none() &&
40 args
.flag_shared
.is_none() &&
41 args
.flag_separate_git_dir
.is_none() {
42 try
!(Repository
::init(&path
))
44 let mut opts
= RepositoryInitOptions
::new();
45 opts
.bare(args
.flag_bare
);
46 if let Some(ref s
) = args
.flag_template
{
47 opts
.template_path(Path
::new(s
));
50 // If you specified a separate git directory, then initialize
51 // the repository at that path and use the second path as the
52 // working directory of the repository (with a git-link file)
53 if let Some(ref s
) = args
.flag_separate_git_dir
{
54 opts
.workdir_path(&path
);
55 path
= PathBuf
::from(s
);
58 if let Some(ref s
) = args
.flag_shared
{
59 opts
.mode(try
!(parse_shared(s
)));
61 try
!(Repository
::init_opts(&path
, &opts
))
64 // Print a message to stdout like "git init" does
66 if args
.flag_bare
|| args
.flag_separate_git_dir
.is_some() {
67 path
= repo
.path().to_path_buf();
69 path
= repo
.workdir().unwrap().to_path_buf();
71 println
!("Initialized empty Git repository in {}", path
.display());
74 if args
.flag_initial_commit
{
75 try
!(create_initial_commit(&repo
));
76 println
!("Created empty initial commit");
82 /// Unlike regular "git init", this example shows how to create an initial empty
83 /// commit in the repository. This is the helper function that does that.
84 fn create_initial_commit(repo
: &Repository
) -> Result
<(), Error
> {
85 // First use the config to initialize a commit signature for the user.
86 let sig
= try
!(repo
.signature());
88 // Now let's create an empty tree for this commit
90 let mut index
= try
!(repo
.index());
92 // Outside of this example, you could call index.add_path()
93 // here to put actual files into the index. For our purposes, we'll
94 // leave it empty for now.
96 try
!(index
.write_tree())
99 let tree
= try
!(repo
.find_tree(tree_id
));
101 // Ready to create the initial commit.
103 // Normally creating a commit would involve looking up the current HEAD
104 // commit and making that be the parent of the initial commit, but here this
105 // is the first commit so there will be no parent.
106 try
!(repo
.commit(Some("HEAD"), &sig
, &sig
, "Initial commit", &tree
, &[]));
111 fn parse_shared(shared
: &str) -> Result
<RepositoryInitMode
, Error
> {
113 "false" | "umask" => Ok(git2
::REPOSITORY_INIT_SHARED_UMASK
),
114 "true" | "group" => Ok(git2
::REPOSITORY_INIT_SHARED_GROUP
),
115 "all" | "world" => Ok(git2
::REPOSITORY_INIT_SHARED_ALL
),
117 if shared
.starts_with('
0'
) {
118 match u32::from_str_radix(&shared
[1..], 8).ok() {
120 Ok(RepositoryInitMode
::from_bits_truncate(n
))
123 Err(Error
::from_str("invalid octal value for --shared"))
127 Err(Error
::from_str("unknown value for --shared"))
134 const USAGE
: &'
static str = "
135 usage: init [options] <directory>
138 -q, --quiet don't print information to stdout
139 --bare initialize a new bare repository
140 --template <dir> use <dir> as an initialization template
141 --separate-git-dir <dir> use <dir> as the .git directory
142 --initial-commit create an initial empty commit
143 --shared <perms> permissions to create the repository with
146 let args
= Docopt
::new(USAGE
).and_then(|d
| d
.deserialize())
147 .unwrap_or_else(|e
| e
.exit());
150 Err(e
) => println
!("error: {}", e
),