@@ -406,35 +406,53 @@ static void update_linked_gitdir(const char *gitfile, const char *gitdir)
406406/*
407407 * Try to read the location of the git directory from the .git file,
408408 * 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).
409414 */
410- const char * read_gitfile (const char * path )
415+ const char * read_gitfile_gently (const char * path , int * return_error_code )
411416{
412- char * buf ;
413- char * dir ;
417+ int error_code = 0 ;
418+ char * buf = NULL ;
419+ char * dir = NULL ;
414420 const char * slash ;
415421 struct stat st ;
416422 int fd ;
417423 ssize_t len ;
418424
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+ }
423433 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+ }
426438 buf = xmalloc (st .st_size + 1 );
427439 len = read_in_full (fd , buf , st .st_size );
428440 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+ }
431445 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+ }
434450 while (buf [len - 1 ] == '\n' || buf [len - 1 ] == '\r' )
435451 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+ }
438456 buf [len ] = '\0' ;
439457 dir = buf + 8 ;
440458
@@ -448,14 +466,42 @@ const char *read_gitfile(const char *path)
448466 free (buf );
449467 buf = dir ;
450468 }
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+ }
455473 update_linked_gitdir (path , dir );
456474 path = real_path (dir );
457475
476+ cleanup_return :
458477 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+
459505 return path ;
460506}
461507
0 commit comments