@matheusbsbs / matheus-bagliano / commits / 53d4888593
Fork 0

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>

Nanako Shiraishi committed Jul 25, 2009 at 06:59 UTC 53d48885931614a43e414e1272a7f126f8d0c901
3 files changed +129 -9
Documentation/git-init.txt
+4 -1
@@ -8,7 +8,7 @@ git-init - Create an empty git repository or reinitialize an existing one
8
9 SYNOPSIS
10 --------
11 -'git init' [-q | --quiet] [--bare] [--template=<template_directory>] [--shared[=<permissions>]]
11 +'git init' [-q | --quiet] [--bare] [--template=<template_directory>] [--shared[=<permissions>]] [directory]
12
13
14 OPTIONS
@@ -74,6 +74,9 @@ By default, the configuration flag receive.denyNonFastForwards is enabled
74 in shared repositories, so that you cannot force a non fast-forwarding push
75 into it.
76
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 +
80 --
81
82
builtin-init-db.c
+48 -8
@@ -371,7 +371,7 @@ static int guess_repository_type(const char *git_dir)
371 }
372
373 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]";
375
376 /*
377 * 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)
384 const char *git_dir;
385 const char *template_dir = NULL;
386 unsigned int flags = 0;
387 + int bare_given = 0;
388 int i;
389
390 for (i = 1; i < argc; i++, argv++) {
391 const char *arg = argv[1];
392 if (!prefixcmp(arg, "--template="))
393 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"))
397 init_shared_repository = PERM_GROUP;
398 else if (!prefixcmp(arg, "--shared="))
399 init_shared_repository = git_config_perm("arg", arg+9);
400 else if (!strcmp(arg, "-q") || !strcmp(arg, "--quiet"))
401 flags |= INIT_DB_QUIET;
404 - else
402 + else if (arg[0] == '-')
403 usage(init_db_usage);
404 + else
405 + break;
406 }
407
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 + }
448 if (init_shared_repository != -1)
449 shared_repository = init_shared_repository;
450
t/t0001-init.sh
+77
@@ -208,4 +208,81 @@ test_expect_success 'init rejects insanely long --template' '
208 )
209 '
210
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 +
288 test_done