setup: add gentle version of read_gitfile
read_gitfile will die on most error cases. This makes it unsuitable for speculative calls. Extract the core logic and provide a gentle version that returns NULL on failure. The first usecase of the new gentle version will be to probe for submodules during git clean. Helped-by: Junio C Hamano <gitster@pobox.com> Helped-by: Jeff King <peff@peff.net> Signed-off-by: Erik Elfström <erik.elfstrom@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Erik Elfström committed
Jun 9, 2015 at 20:24 UTC
a93bedada88dc15b0143708e1cb87c8fe9b9c705
2 files changed
+75
-20
cache.h
+10
-1
@@ -446,7 +446,16 @@ extern int get_common_dir(struct strbuf *sb, const char *gitdir);
446
extern const char *get_git_namespace(void);
447
extern const char *strip_namespace(const char *namespaced_ref);
448
extern const char *get_git_work_tree(void);
449
-extern const char *read_gitfile(const char *path);
449
+
450
+#define READ_GITFILE_ERR_STAT_FAILED 1
451
+#define READ_GITFILE_ERR_NOT_A_FILE 2
452
+#define READ_GITFILE_ERR_OPEN_FAILED 3
453
+#define READ_GITFILE_ERR_READ_FAILED 4
454
+#define READ_GITFILE_ERR_INVALID_FORMAT 5
455
+#define READ_GITFILE_ERR_NO_PATH 6
456
+#define READ_GITFILE_ERR_NOT_A_REPO 7
457
+extern const char *read_gitfile_gently(const char *path, int *return_error_code);
458
+#define read_gitfile(path) read_gitfile_gently((path), NULL)
459
extern const char *resolve_gitdir(const char *suspect);
460
extern void set_git_work_tree(const char *tree);
461
setup.c
+65
-19
@@ -406,35 +406,53 @@ static void update_linked_gitdir(const char *gitfile, const char *gitdir)
406
/*
407
* Try to read the location of the git directory from the .git file,
408
* return path to git directory if found.
409
+ *
410
+ * On failure, if return_error_code is not NULL, return_error_code
411
+ * will be set to an error code and NULL will be returned. If
412
+ * return_error_code is NULL the function will die instead (for most
413
+ * cases).
414
*/
410
-const char *read_gitfile(const char *path)
415
+const char *read_gitfile_gently(const char *path, int *return_error_code)
416
{
412
- char *buf;
413
- char *dir;
417
+ int error_code = 0;
418
+ char *buf = NULL;
419
+ char *dir = NULL;
420
const char *slash;
421
struct stat st;
422
int fd;
423
ssize_t len;
424
419
- if (stat(path, &st))
420
- return NULL;
421
- if (!S_ISREG(st.st_mode))
422
- return NULL;
425
+ if (stat(path, &st)) {
426
+ error_code = READ_GITFILE_ERR_STAT_FAILED;
427
+ goto cleanup_return;
428
+ }
429
+ if (!S_ISREG(st.st_mode)) {
430
+ error_code = READ_GITFILE_ERR_NOT_A_FILE;
431
+ goto cleanup_return;
432
+ }
433
fd = open(path, O_RDONLY);
424
- if (fd < 0)
425
- die_errno("Error opening '%s'", path);
434
+ if (fd < 0) {
435
+ error_code = READ_GITFILE_ERR_OPEN_FAILED;
436
+ goto cleanup_return;
437
+ }
438
buf = xmalloc(st.st_size + 1);
439
len = read_in_full(fd, buf, st.st_size);
440
close(fd);
429
- if (len != st.st_size)
430
- die("Error reading %s", path);
441
+ if (len != st.st_size) {
442
+ error_code = READ_GITFILE_ERR_READ_FAILED;
443
+ goto cleanup_return;
444
+ }
445
buf[len] = '\0';
432
- if (!starts_with(buf, "gitdir: "))
433
- die("Invalid gitfile format: %s", path);
446
+ if (!starts_with(buf, "gitdir: ")) {
447
+ error_code = READ_GITFILE_ERR_INVALID_FORMAT;
448
+ goto cleanup_return;
449
+ }
450
while (buf[len - 1] == '\n' || buf[len - 1] == '\r')
451
len--;
436
- if (len < 9)
437
- die("No path in gitfile: %s", path);
452
+ if (len < 9) {
453
+ error_code = READ_GITFILE_ERR_NO_PATH;
454
+ goto cleanup_return;
455
+ }
456
buf[len] = '\0';
457
dir = buf + 8;
458
@@ -448,14 +466,42 @@ const char *read_gitfile(const char *path)
466
free(buf);
467
buf = dir;
468
}
451
-
452
- if (!is_git_directory(dir))
453
- die("Not a git repository: %s", dir);
454
-
469
+ if (!is_git_directory(dir)) {
470
+ error_code = READ_GITFILE_ERR_NOT_A_REPO;
471
+ goto cleanup_return;
472
+ }
473
update_linked_gitdir(path, dir);
474
path = real_path(dir);
475
476
+cleanup_return:
477
free(buf);
478
+
479
+ if (return_error_code)
480
+ *return_error_code = error_code;
481
+
482
+ if (error_code) {
483
+ if (return_error_code)
484
+ return NULL;
485
+
486
+ switch (error_code) {
487
+ case READ_GITFILE_ERR_STAT_FAILED:
488
+ case READ_GITFILE_ERR_NOT_A_FILE:
489
+ return NULL;
490
+ case READ_GITFILE_ERR_OPEN_FAILED:
491
+ die_errno("Error opening '%s'", path);
492
+ case READ_GITFILE_ERR_READ_FAILED:
493
+ die("Error reading %s", path);
494
+ case READ_GITFILE_ERR_INVALID_FORMAT:
495
+ die("Invalid gitfile format: %s", path);
496
+ case READ_GITFILE_ERR_NO_PATH:
497
+ die("No path in gitfile: %s", path);
498
+ case READ_GITFILE_ERR_NOT_A_REPO:
499
+ die("Not a git repository: %s", dir);
500
+ default:
501
+ assert(0);
502
+ }
503
+ }
504
+
505
return path;
506
}
507