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 <nanako3@lavabit.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Nanako Shiraishi 2009-07-25 06:59:28 +09:00 committed by Junio C Hamano
parent 0ad8ff2cd1
commit 53d4888593
3 changed files with 129 additions and 9 deletions

View File

@ -8,7 +8,7 @@ git-init - Create an empty git repository or reinitialize an existing one
SYNOPSIS SYNOPSIS
-------- --------
'git init' [-q | --quiet] [--bare] [--template=<template_directory>] [--shared[=<permissions>]] 'git init' [-q | --quiet] [--bare] [--template=<template_directory>] [--shared[=<permissions>]] [directory]
OPTIONS OPTIONS
@ -74,6 +74,9 @@ By default, the configuration flag receive.denyNonFastForwards is enabled
in shared repositories, so that you cannot force a non fast-forwarding push in shared repositories, so that you cannot force a non fast-forwarding push
into it. into it.
If you name a (possibly non-existent) directory at the end of the command
line, the command is run inside the directory (possibly after creating it).
-- --

View File

@ -371,7 +371,7 @@ static int guess_repository_type(const char *git_dir)
} }
static const char init_db_usage[] = static const char init_db_usage[] =
"git init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]]"; "git init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]] [directory]";
/* /*
* If you want to, you can share the DB area with any number of branches. * 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)
const char *git_dir; const char *git_dir;
const char *template_dir = NULL; const char *template_dir = NULL;
unsigned int flags = 0; unsigned int flags = 0;
int bare_given = 0;
int i; int i;
for (i = 1; i < argc; i++, argv++) { for (i = 1; i < argc; i++, argv++) {
const char *arg = argv[1]; const char *arg = argv[1];
if (!prefixcmp(arg, "--template=")) if (!prefixcmp(arg, "--template="))
template_dir = arg+11; template_dir = arg+11;
else if (!strcmp(arg, "--bare")) { else if (!strcmp(arg, "--bare"))
static char git_dir[PATH_MAX+1]; bare_given = is_bare_repository_cfg = 1;
is_bare_repository_cfg = 1; else if (!strcmp(arg, "--shared"))
setenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir,
sizeof(git_dir)), 0);
} else if (!strcmp(arg, "--shared"))
init_shared_repository = PERM_GROUP; init_shared_repository = PERM_GROUP;
else if (!prefixcmp(arg, "--shared=")) else if (!prefixcmp(arg, "--shared="))
init_shared_repository = git_config_perm("arg", arg+9); init_shared_repository = git_config_perm("arg", arg+9);
else if (!strcmp(arg, "-q") || !strcmp(arg, "--quiet")) else if (!strcmp(arg, "-q") || !strcmp(arg, "--quiet"))
flags |= INIT_DB_QUIET; flags |= INIT_DB_QUIET;
else else if (arg[0] == '-')
usage(init_db_usage); usage(init_db_usage);
else
break;
} }
if (i == argc - 1) {
int mkdir_tried = 0;
retry:
if (chdir(argv[1]) < 0) {
if (!mkdir_tried) {
int saved;
/*
* At this point we haven't read any configuration,
* and we know shared_repository should always be 0;
* but just in case we play safe.
*/
saved = shared_repository;
shared_repository = 0;
switch (safe_create_leading_directories_const(argv[1])) {
case -3:
errno = EEXIST;
/* fallthru */
case -1:
die_errno("cannot mkdir %s", argv[1]);
break;
default:
break;
}
shared_repository = saved;
if (mkdir(argv[1], 0777) < 0)
die_errno("cannot mkdir %s", argv[1]);
mkdir_tried = 1;
goto retry;
}
die_errno("cannot chdir to %s", argv[1]);
}
} else if (i < argc - 1) {
usage(init_db_usage);
}
if (bare_given == 1) {
static char git_dir[PATH_MAX+1];
setenv(GIT_DIR_ENVIRONMENT,
getcwd(git_dir, sizeof(git_dir)), 0);
}
if (init_shared_repository != -1) if (init_shared_repository != -1)
shared_repository = init_shared_repository; shared_repository = init_shared_repository;

View File

@ -208,4 +208,81 @@ test_expect_success 'init rejects insanely long --template' '
) )
' '
test_expect_success 'init creates a new directory' '
rm -fr newdir &&
(
git init newdir &&
test -d newdir/.git/refs
)
'
test_expect_success 'init creates a new bare directory' '
rm -fr newdir &&
(
git init --bare newdir &&
test -d newdir/refs
)
'
test_expect_success 'init recreates a directory' '
rm -fr newdir &&
(
mkdir newdir &&
git init newdir &&
test -d newdir/.git/refs
)
'
test_expect_success 'init recreates a new bare directory' '
rm -fr newdir &&
(
mkdir newdir &&
git init --bare newdir &&
test -d newdir/refs
)
'
test_expect_success 'init creates a new deep directory' '
rm -fr newdir &&
(
# Leading directories should honor umask while
# the repository itself should follow "shared"
umask 002 &&
git init --bare --shared=0660 newdir/a/b/c &&
test -d newdir/a/b/c/refs &&
ls -ld newdir/a newdir/a/b > lsab.out &&
! grep -v "^drwxrw[sx]r-x" ls.out &&
ls -ld newdir/a/b/c > lsc.out &&
! grep -v "^drwxrw[sx]---" lsc.out
)
'
test_expect_success 'init notices EEXIST (1)' '
rm -fr newdir &&
(
>newdir &&
test_must_fail git init newdir &&
test -f newdir
)
'
test_expect_success 'init notices EEXIST (2)' '
rm -fr newdir &&
(
mkdir newdir &&
>newdir/a
test_must_fail git init newdir/a/b &&
test -f newdir/a
)
'
test_expect_success POSIXPERM 'init notices EPERM' '
rm -fr newdir &&
(
mkdir newdir &&
chmod -w newdir &&
test_must_fail git init newdir/a/b
)
'
test_done test_done