Skip to content

Commit 53d4888

Browse files
Nanako Shiraishigitster
authored andcommitted
git init: optionally allow a directory argument
When starting a new repository, I see my students often say % git init newrepo and curse git. They could say % mkdir newrepo; cd newrepo; git init but allowing it as an obvious short-cut may be nicer. Signed-off-by: Nanako Shiraishi <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 0ad8ff2 commit 53d4888

File tree

3 files changed

+129
-9
lines changed

3 files changed

+129
-9
lines changed

Documentation/git-init.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ git-init - Create an empty git repository or reinitialize an existing one
88

99
SYNOPSIS
1010
--------
11-
'git init' [-q | --quiet] [--bare] [--template=<template_directory>] [--shared[=<permissions>]]
11+
'git init' [-q | --quiet] [--bare] [--template=<template_directory>] [--shared[=<permissions>]] [directory]
1212

1313

1414
OPTIONS
@@ -74,6 +74,9 @@ By default, the configuration flag receive.denyNonFastForwards is enabled
7474
in shared repositories, so that you cannot force a non fast-forwarding push
7575
into it.
7676

77+
If you name a (possibly non-existent) directory at the end of the command
78+
line, the command is run inside the directory (possibly after creating it).
79+
7780
--
7881

7982

builtin-init-db.c

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ static int guess_repository_type(const char *git_dir)
371371
}
372372

373373
static const char init_db_usage[] =
374-
"git init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]]";
374+
"git init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]] [directory]";
375375

376376
/*
377377
* If you want to, you can share the DB area with any number of branches.
@@ -384,27 +384,67 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
384384
const char *git_dir;
385385
const char *template_dir = NULL;
386386
unsigned int flags = 0;
387+
int bare_given = 0;
387388
int i;
388389

389390
for (i = 1; i < argc; i++, argv++) {
390391
const char *arg = argv[1];
391392
if (!prefixcmp(arg, "--template="))
392393
template_dir = arg+11;
393-
else if (!strcmp(arg, "--bare")) {
394-
static char git_dir[PATH_MAX+1];
395-
is_bare_repository_cfg = 1;
396-
setenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir,
397-
sizeof(git_dir)), 0);
398-
} else if (!strcmp(arg, "--shared"))
394+
else if (!strcmp(arg, "--bare"))
395+
bare_given = is_bare_repository_cfg = 1;
396+
else if (!strcmp(arg, "--shared"))
399397
init_shared_repository = PERM_GROUP;
400398
else if (!prefixcmp(arg, "--shared="))
401399
init_shared_repository = git_config_perm("arg", arg+9);
402400
else if (!strcmp(arg, "-q") || !strcmp(arg, "--quiet"))
403401
flags |= INIT_DB_QUIET;
404-
else
402+
else if (arg[0] == '-')
405403
usage(init_db_usage);
404+
else
405+
break;
406406
}
407407

408+
if (i == argc - 1) {
409+
int mkdir_tried = 0;
410+
retry:
411+
if (chdir(argv[1]) < 0) {
412+
if (!mkdir_tried) {
413+
int saved;
414+
/*
415+
* At this point we haven't read any configuration,
416+
* and we know shared_repository should always be 0;
417+
* but just in case we play safe.
418+
*/
419+
saved = shared_repository;
420+
shared_repository = 0;
421+
switch (safe_create_leading_directories_const(argv[1])) {
422+
case -3:
423+
errno = EEXIST;
424+
/* fallthru */
425+
case -1:
426+
die_errno("cannot mkdir %s", argv[1]);
427+
break;
428+
default:
429+
break;
430+
}
431+
shared_repository = saved;
432+
if (mkdir(argv[1], 0777) < 0)
433+
die_errno("cannot mkdir %s", argv[1]);
434+
mkdir_tried = 1;
435+
goto retry;
436+
}
437+
die_errno("cannot chdir to %s", argv[1]);
438+
}
439+
} else if (i < argc - 1) {
440+
usage(init_db_usage);
441+
}
442+
if (bare_given == 1) {
443+
static char git_dir[PATH_MAX+1];
444+
445+
setenv(GIT_DIR_ENVIRONMENT,
446+
getcwd(git_dir, sizeof(git_dir)), 0);
447+
}
408448
if (init_shared_repository != -1)
409449
shared_repository = init_shared_repository;
410450

t/t0001-init.sh

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,4 +208,81 @@ test_expect_success 'init rejects insanely long --template' '
208208
)
209209
'
210210

211+
test_expect_success 'init creates a new directory' '
212+
rm -fr newdir &&
213+
(
214+
git init newdir &&
215+
test -d newdir/.git/refs
216+
)
217+
'
218+
219+
test_expect_success 'init creates a new bare directory' '
220+
rm -fr newdir &&
221+
(
222+
git init --bare newdir &&
223+
test -d newdir/refs
224+
)
225+
'
226+
227+
test_expect_success 'init recreates a directory' '
228+
rm -fr newdir &&
229+
(
230+
mkdir newdir &&
231+
git init newdir &&
232+
test -d newdir/.git/refs
233+
)
234+
'
235+
236+
test_expect_success 'init recreates a new bare directory' '
237+
rm -fr newdir &&
238+
(
239+
mkdir newdir &&
240+
git init --bare newdir &&
241+
test -d newdir/refs
242+
)
243+
'
244+
245+
test_expect_success 'init creates a new deep directory' '
246+
rm -fr newdir &&
247+
(
248+
# Leading directories should honor umask while
249+
# the repository itself should follow "shared"
250+
umask 002 &&
251+
git init --bare --shared=0660 newdir/a/b/c &&
252+
test -d newdir/a/b/c/refs &&
253+
ls -ld newdir/a newdir/a/b > lsab.out &&
254+
! grep -v "^drwxrw[sx]r-x" ls.out &&
255+
ls -ld newdir/a/b/c > lsc.out &&
256+
! grep -v "^drwxrw[sx]---" lsc.out
257+
)
258+
'
259+
260+
test_expect_success 'init notices EEXIST (1)' '
261+
rm -fr newdir &&
262+
(
263+
>newdir &&
264+
test_must_fail git init newdir &&
265+
test -f newdir
266+
)
267+
'
268+
269+
test_expect_success 'init notices EEXIST (2)' '
270+
rm -fr newdir &&
271+
(
272+
mkdir newdir &&
273+
>newdir/a
274+
test_must_fail git init newdir/a/b &&
275+
test -f newdir/a
276+
)
277+
'
278+
279+
test_expect_success POSIXPERM 'init notices EPERM' '
280+
rm -fr newdir &&
281+
(
282+
mkdir newdir &&
283+
chmod -w newdir &&
284+
test_must_fail git init newdir/a/b
285+
)
286+
'
287+
211288
test_done

0 commit comments

Comments
 (0)