Skip to content

Commit 800a953

Browse files
authored
Merge pull request libgit2#6984 from libgit2/ethomson/cli
CLI: introduce `init` command
2 parents 838875e + 9f61001 commit 800a953

File tree

4 files changed

+182
-29
lines changed

4 files changed

+182
-29
lines changed

src/cli/cmd.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,6 @@ extern int cmd_config(int argc, char **argv);
3232
extern int cmd_hash_object(int argc, char **argv);
3333
extern int cmd_help(int argc, char **argv);
3434
extern int cmd_index_pack(int argc, char **argv);
35+
extern int cmd_init(int argc, char **argv);
3536

3637
#endif /* CLI_cmd_h__ */

src/cli/cmd_init.c

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
* Copyright (C) the libgit2 contributors. All rights reserved.
3+
*
4+
* This file is part of libgit2, distributed under the GNU GPL v2 with
5+
* a Linking Exception. For full terms see the included COPYING file.
6+
*/
7+
8+
#include <stdio.h>
9+
#include <git2.h>
10+
#include "common.h"
11+
#include "cmd.h"
12+
#include "error.h"
13+
#include "sighandler.h"
14+
#include "progress.h"
15+
16+
#include "fs_path.h"
17+
#include "futils.h"
18+
19+
#define COMMAND_NAME "init"
20+
21+
static char *branch, *git_dir, *template_dir, *path;
22+
static int quiet, bare;
23+
24+
static const cli_opt_spec opts[] = {
25+
CLI_COMMON_OPT,
26+
27+
{ CLI_OPT_TYPE_SWITCH, "quiet", 'q', &quiet, 1,
28+
CLI_OPT_USAGE_DEFAULT, NULL, "quiet mode; don't display informational messages" },
29+
{ CLI_OPT_TYPE_SWITCH, "bare", 0, &bare, 1,
30+
CLI_OPT_USAGE_DEFAULT, NULL, "don't create a working directory" },
31+
{ CLI_OPT_TYPE_VALUE, "initial-branch", 'b', &branch, 0,
32+
CLI_OPT_USAGE_DEFAULT, "name", "initial branch name" },
33+
{ CLI_OPT_TYPE_VALUE, "separate-git-dir", 0, &git_dir, 0,
34+
CLI_OPT_USAGE_DEFAULT, "git-dir", "path to separate git directory" },
35+
{ CLI_OPT_TYPE_VALUE, "template", 0, &template_dir, 0,
36+
CLI_OPT_USAGE_DEFAULT, "template-dir", "path to git directory templates" },
37+
{ CLI_OPT_TYPE_LITERAL },
38+
{ CLI_OPT_TYPE_ARG, "directory", 0, &path, 0,
39+
CLI_OPT_USAGE_DEFAULT, "directory", "directory to create repository in" },
40+
{ 0 }
41+
};
42+
43+
static void print_help(void)
44+
{
45+
cli_opt_usage_fprint(stdout, PROGRAM_NAME, COMMAND_NAME, opts, 0);
46+
printf("\n");
47+
48+
printf("Create a new git repository.\n");
49+
printf("\n");
50+
51+
printf("Options:\n");
52+
53+
cli_opt_help_fprint(stdout, opts);
54+
}
55+
56+
int cmd_init(int argc, char **argv)
57+
{
58+
git_repository *repo = NULL;
59+
git_repository_init_options init_opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
60+
cli_opt invalid_opt;
61+
const char *repo_path;
62+
int ret = 0;
63+
64+
if (cli_opt_parse(&invalid_opt, opts, argv + 1, argc - 1, CLI_OPT_PARSE_GNU))
65+
return cli_opt_usage_error(COMMAND_NAME, opts, &invalid_opt);
66+
67+
if (cli_opt__show_help) {
68+
print_help();
69+
return 0;
70+
}
71+
72+
init_opts.flags |= GIT_REPOSITORY_INIT_MKPATH |
73+
GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE;
74+
75+
if (bare && git_dir)
76+
return cli_error_usage("the '--bare' and '--separate-git-dir' options cannot be used together");
77+
78+
if (bare)
79+
init_opts.flags |= GIT_REPOSITORY_INIT_BARE;
80+
81+
init_opts.template_path = template_dir;
82+
init_opts.initial_head = branch;
83+
84+
if (git_dir) {
85+
init_opts.flags |= GIT_REPOSITORY_INIT_NO_DOTGIT_DIR;
86+
init_opts.workdir_path = path;
87+
88+
repo_path = git_dir;
89+
} else {
90+
repo_path = path;
91+
}
92+
93+
if (git_repository_init_ext(&repo, repo_path, &init_opts) < 0) {
94+
ret = cli_error_git();
95+
} else if (!quiet) {
96+
printf("Initialized empty Git repository in %s\n",
97+
git_repository_path(repo));
98+
}
99+
100+
git_repository_free(repo);
101+
return ret;
102+
}

src/cli/main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const cli_cmd_spec cli_cmds[] = {
3737
{ "hash-object", cmd_hash_object, "Hash a raw object and product its object ID" },
3838
{ "help", cmd_help, "Display help information" },
3939
{ "index-pack", cmd_index_pack, "Create an index for a packfile" },
40+
{ "init", cmd_init, "Create a new git repository" },
4041
{ NULL }
4142
};
4243

src/cli/opt_usage.c

Lines changed: 78 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,81 @@
88
#include "common.h"
99
#include "str.h"
1010

11-
static int print_spec_name(git_str *out, const cli_opt_spec *spec)
11+
#define is_switch_or_value(spec) \
12+
((spec)->type == CLI_OPT_TYPE_SWITCH || \
13+
(spec)->type == CLI_OPT_TYPE_VALUE)
14+
15+
static int print_spec_args(git_str *out, const cli_opt_spec *spec)
1216
{
13-
if (spec->type == CLI_OPT_TYPE_VALUE && spec->alias &&
14-
!(spec->usage & CLI_OPT_USAGE_VALUE_OPTIONAL) &&
15-
!(spec->usage & CLI_OPT_USAGE_SHOW_LONG))
16-
return git_str_printf(out, "-%c <%s>", spec->alias, spec->value_name);
17-
if (spec->type == CLI_OPT_TYPE_VALUE && spec->alias &&
18-
!(spec->usage & CLI_OPT_USAGE_SHOW_LONG))
19-
return git_str_printf(out, "-%c [<%s>]", spec->alias, spec->value_name);
20-
if (spec->type == CLI_OPT_TYPE_VALUE &&
21-
!(spec->usage & CLI_OPT_USAGE_VALUE_OPTIONAL))
22-
return git_str_printf(out, "--%s[=<%s>]", spec->name, spec->value_name);
23-
if (spec->type == CLI_OPT_TYPE_VALUE)
24-
return git_str_printf(out, "--%s=<%s>", spec->name, spec->value_name);
17+
GIT_ASSERT(!is_switch_or_value(spec));
18+
2519
if (spec->type == CLI_OPT_TYPE_ARG)
2620
return git_str_printf(out, "<%s>", spec->value_name);
2721
if (spec->type == CLI_OPT_TYPE_ARGS)
2822
return git_str_printf(out, "<%s>...", spec->value_name);
2923
if (spec->type == CLI_OPT_TYPE_LITERAL)
3024
return git_str_printf(out, "--");
31-
if (spec->alias && !(spec->usage & CLI_OPT_USAGE_SHOW_LONG))
25+
26+
GIT_ASSERT(!"unknown option spec type");
27+
return -1;
28+
}
29+
30+
GIT_INLINE(int) print_spec_alias(git_str *out, const cli_opt_spec *spec)
31+
{
32+
GIT_ASSERT(is_switch_or_value(spec) && spec->alias);
33+
34+
if (spec->type == CLI_OPT_TYPE_VALUE &&
35+
!(spec->usage & CLI_OPT_USAGE_VALUE_OPTIONAL))
36+
return git_str_printf(out, "-%c <%s>", spec->alias, spec->value_name);
37+
else if (spec->type == CLI_OPT_TYPE_VALUE)
38+
return git_str_printf(out, "-%c [<%s>]", spec->alias, spec->value_name);
39+
else
3240
return git_str_printf(out, "-%c", spec->alias);
33-
if (spec->name)
41+
}
42+
43+
GIT_INLINE(int) print_spec_name(git_str *out, const cli_opt_spec *spec)
44+
{
45+
GIT_ASSERT(is_switch_or_value(spec) && spec->name);
46+
47+
if (spec->type == CLI_OPT_TYPE_VALUE &&
48+
!(spec->usage & CLI_OPT_USAGE_VALUE_OPTIONAL))
49+
return git_str_printf(out, "--%s=<%s>", spec->name, spec->value_name);
50+
else if (spec->type == CLI_OPT_TYPE_VALUE)
51+
return git_str_printf(out, "--%s[=<%s>]", spec->name, spec->value_name);
52+
else
3453
return git_str_printf(out, "--%s", spec->name);
54+
}
55+
56+
GIT_INLINE(int) print_spec_full(git_str *out, const cli_opt_spec *spec)
57+
{
58+
int error = 0;
59+
60+
if (is_switch_or_value(spec)) {
61+
if (spec->alias)
62+
error |= print_spec_alias(out, spec);
63+
64+
if (spec->alias && spec->name)
65+
error |= git_str_printf(out, ", ");
66+
67+
if (spec->name)
68+
error |= print_spec_name(out, spec);
69+
} else {
70+
error |= print_spec_args(out, spec);
71+
}
72+
73+
return error;
74+
}
75+
76+
GIT_INLINE(int) print_spec(git_str *out, const cli_opt_spec *spec)
77+
{
78+
if (is_switch_or_value(spec)) {
79+
if (spec->alias && !(spec->usage & CLI_OPT_USAGE_SHOW_LONG))
80+
return print_spec_alias(out, spec);
81+
else
82+
return print_spec_name(out, spec);
83+
}
3584

36-
GIT_ASSERT(0);
85+
return print_spec_args(out, spec);
3786
}
3887

3988
/*
@@ -56,7 +105,7 @@ int cli_opt_usage_fprint(
56105
int error;
57106

58107
/* TODO: query actual console width. */
59-
int console_width = 80;
108+
int console_width = 78;
60109

61110
if ((error = git_str_printf(&usage, "usage: %s", command)) < 0)
62111
goto done;
@@ -88,7 +137,7 @@ int cli_opt_usage_fprint(
88137
if (!optional && !choice && next_choice)
89138
git_str_putc(&opt, '(');
90139

91-
if ((error = print_spec_name(&opt, spec)) < 0)
140+
if ((error = print_spec(&opt, spec)) < 0)
92141
goto done;
93142

94143
if (!optional && choice && !next_choice)
@@ -113,11 +162,11 @@ int cli_opt_usage_fprint(
113162
git_str_putc(&usage, ' ');
114163

115164
linelen = prefixlen;
116-
} else {
117-
git_str_putc(&usage, ' ');
118-
linelen += git_str_len(&opt) + 1;
119165
}
120166

167+
git_str_putc(&usage, ' ');
168+
linelen += git_str_len(&opt) + 1;
169+
121170
git_str_puts(&usage, git_str_cstr(&opt));
122171

123172
if (git_str_oom(&usage)) {
@@ -169,13 +218,13 @@ int cli_opt_help_fprint(
169218

170219
git_str_printf(&help, " ");
171220

172-
if ((error = print_spec_name(&help, spec)) < 0)
221+
if ((error = print_spec_full(&help, spec)) < 0)
173222
goto done;
174223

175-
if (spec->help)
176-
git_str_printf(&help, ": %s", spec->help);
177-
178224
git_str_printf(&help, "\n");
225+
226+
if (spec->help)
227+
git_str_printf(&help, " %s\n", spec->help);
179228
}
180229

181230
/* Display the remaining arguments */
@@ -192,13 +241,13 @@ int cli_opt_help_fprint(
192241

193242
git_str_printf(&help, " ");
194243

195-
if ((error = print_spec_name(&help, spec)) < 0)
244+
if ((error = print_spec_full(&help, spec)) < 0)
196245
goto done;
197246

198-
if (spec->help)
199-
git_str_printf(&help, ": %s", spec->help);
200-
201247
git_str_printf(&help, "\n");
248+
249+
if (spec->help)
250+
git_str_printf(&help, " %s\n", spec->help);
202251
}
203252

204253
if (git_str_oom(&help) ||

0 commit comments

Comments
 (0)