@@ -313,6 +313,115 @@ const char *read_gitfile_gently(const char *path)
313313 return path ;
314314}
315315
316+ static const char * setup_explicit_git_dir (const char * gitdirenv ,
317+ const char * work_tree_env , int * nongit_ok )
318+ {
319+ static char buffer [1024 + 1 ];
320+ const char * retval ;
321+
322+ if (PATH_MAX - 40 < strlen (gitdirenv ))
323+ die ("'$%s' too big" , GIT_DIR_ENVIRONMENT );
324+ if (!is_git_directory (gitdirenv )) {
325+ if (nongit_ok ) {
326+ * nongit_ok = 1 ;
327+ return NULL ;
328+ }
329+ die ("Not a git repository: '%s'" , gitdirenv );
330+ }
331+ if (!work_tree_env ) {
332+ retval = set_work_tree (gitdirenv );
333+ /* config may override worktree */
334+ if (check_repository_format_gently (nongit_ok ))
335+ return NULL ;
336+ return retval ;
337+ }
338+ if (check_repository_format_gently (nongit_ok ))
339+ return NULL ;
340+ retval = get_relative_cwd (buffer , sizeof (buffer ) - 1 ,
341+ get_git_work_tree ());
342+ if (!retval || !* retval )
343+ return NULL ;
344+ set_git_dir (make_absolute_path (gitdirenv ));
345+ if (chdir (work_tree_env ) < 0 )
346+ die_errno ("Could not chdir to '%s'" , work_tree_env );
347+ strcat (buffer , "/" );
348+ return retval ;
349+ }
350+
351+ static int cwd_contains_git_dir (const char * * gitfile_dirp )
352+ {
353+ const char * gitfile_dir = read_gitfile_gently (DEFAULT_GIT_DIR_ENVIRONMENT );
354+ * gitfile_dirp = gitfile_dir ;
355+ if (gitfile_dir ) {
356+ if (set_git_dir (gitfile_dir ))
357+ die ("Repository setup failed" );
358+ return 1 ;
359+ }
360+ return is_git_directory (DEFAULT_GIT_DIR_ENVIRONMENT );
361+ }
362+
363+ static const char * setup_discovered_git_dir (const char * work_tree_env ,
364+ int offset , int len , char * cwd , int * nongit_ok )
365+ {
366+ int root_len ;
367+
368+ inside_git_dir = 0 ;
369+ if (!work_tree_env )
370+ inside_work_tree = 1 ;
371+ root_len = offset_1st_component (cwd );
372+ git_work_tree_cfg = xstrndup (cwd , offset > root_len ? offset : root_len );
373+ if (check_repository_format_gently (nongit_ok ))
374+ return NULL ;
375+ if (offset == len )
376+ return NULL ;
377+
378+ /* Make "offset" point to past the '/', and add a '/' at the end */
379+ offset ++ ;
380+ cwd [len ++ ] = '/' ;
381+ cwd [len ] = 0 ;
382+ return cwd + offset ;
383+ }
384+
385+ static const char * setup_bare_git_dir (const char * work_tree_env ,
386+ int offset , int len , char * cwd , int * nongit_ok )
387+ {
388+ int root_len ;
389+
390+ inside_git_dir = 1 ;
391+ if (!work_tree_env )
392+ inside_work_tree = 0 ;
393+ if (offset != len ) {
394+ if (chdir (cwd ))
395+ die_errno ("Cannot come back to cwd" );
396+ root_len = offset_1st_component (cwd );
397+ cwd [offset > root_len ? offset : root_len ] = '\0' ;
398+ set_git_dir (cwd );
399+ } else
400+ set_git_dir ("." );
401+ check_repository_format_gently (nongit_ok );
402+ return NULL ;
403+ }
404+
405+ static const char * setup_nongit (const char * cwd , int * nongit_ok )
406+ {
407+ if (!nongit_ok )
408+ die ("Not a git repository (or any of the parent directories): %s" , DEFAULT_GIT_DIR_ENVIRONMENT );
409+ if (chdir (cwd ))
410+ die_errno ("Cannot come back to cwd" );
411+ * nongit_ok = 1 ;
412+ return NULL ;
413+ }
414+
415+ static dev_t get_device_or_die (const char * path , const char * prefix )
416+ {
417+ struct stat buf ;
418+ if (stat (path , & buf ))
419+ die_errno ("failed to stat '%s%s%s'" ,
420+ prefix ? prefix : "" ,
421+ prefix ? "/" : "" , path );
422+ return buf .st_dev ;
423+ }
424+
316425/*
317426 * We cannot decide in this function whether we are in the work tree or
318427 * not, since the config can only be read _after_ this function was called.
@@ -324,10 +433,9 @@ const char *setup_git_directory_gently(int *nongit_ok)
324433 static char cwd [PATH_MAX + 1 ];
325434 const char * gitdirenv ;
326435 const char * gitfile_dir ;
327- int len , offset , ceil_offset , root_len ;
436+ int len , offset , ceil_offset ;
328437 dev_t current_device = 0 ;
329438 int one_filesystem = 1 ;
330- struct stat buf ;
331439
332440 /*
333441 * Let's assume that we are in a git repository.
@@ -343,38 +451,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
343451 * validation.
344452 */
345453 gitdirenv = getenv (GIT_DIR_ENVIRONMENT );
346- if (gitdirenv ) {
347- if (PATH_MAX - 40 < strlen (gitdirenv ))
348- die ("'$%s' too big" , GIT_DIR_ENVIRONMENT );
349- if (is_git_directory (gitdirenv )) {
350- static char buffer [1024 + 1 ];
351- const char * retval ;
352-
353- if (!work_tree_env ) {
354- retval = set_work_tree (gitdirenv );
355- /* config may override worktree */
356- if (check_repository_format_gently (nongit_ok ))
357- return NULL ;
358- return retval ;
359- }
360- if (check_repository_format_gently (nongit_ok ))
361- return NULL ;
362- retval = get_relative_cwd (buffer , sizeof (buffer ) - 1 ,
363- get_git_work_tree ());
364- if (!retval || !* retval )
365- return NULL ;
366- set_git_dir (make_absolute_path (gitdirenv ));
367- if (chdir (work_tree_env ) < 0 )
368- die_errno ("Could not chdir to '%s'" , work_tree_env );
369- strcat (buffer , "/" );
370- return retval ;
371- }
372- if (nongit_ok ) {
373- * nongit_ok = 1 ;
374- return NULL ;
375- }
376- die ("Not a git repository: '%s'" , gitdirenv );
377- }
454+ if (gitdirenv )
455+ return setup_explicit_git_dir (gitdirenv , work_tree_env , nongit_ok );
378456
379457 if (!getcwd (cwd , sizeof (cwd )- 1 ))
380458 die_errno ("Unable to read current working directory" );
@@ -396,49 +474,21 @@ const char *setup_git_directory_gently(int *nongit_ok)
396474 */
397475 offset = len = strlen (cwd );
398476 one_filesystem = !git_env_bool ("GIT_DISCOVERY_ACROSS_FILESYSTEM" , 0 );
399- if (one_filesystem ) {
400- if (stat ("." , & buf ))
401- die_errno ("failed to stat '.'" );
402- current_device = buf .st_dev ;
403- }
477+ if (one_filesystem )
478+ current_device = get_device_or_die ("." , NULL );
404479 for (;;) {
405- gitfile_dir = read_gitfile_gently (DEFAULT_GIT_DIR_ENVIRONMENT );
406- if (gitfile_dir ) {
407- if (set_git_dir (gitfile_dir ))
408- die ("Repository setup failed" );
409- break ;
410- }
411- if (is_git_directory (DEFAULT_GIT_DIR_ENVIRONMENT ))
412- break ;
413- if (is_git_directory ("." )) {
414- inside_git_dir = 1 ;
415- if (!work_tree_env )
416- inside_work_tree = 0 ;
417- if (offset != len ) {
418- root_len = offset_1st_component (cwd );
419- cwd [offset > root_len ? offset : root_len ] = '\0' ;
420- set_git_dir (cwd );
421- } else
422- set_git_dir ("." );
423- check_repository_format_gently (nongit_ok );
424- return NULL ;
425- }
480+ if (cwd_contains_git_dir (& gitfile_dir ))
481+ return setup_discovered_git_dir (work_tree_env , offset ,
482+ len , cwd , nongit_ok );
483+ if (is_git_directory ("." ))
484+ return setup_bare_git_dir (work_tree_env , offset ,
485+ len , cwd , nongit_ok );
426486 while (-- offset > ceil_offset && cwd [offset ] != '/' );
427- if (offset <= ceil_offset ) {
428- if (nongit_ok ) {
429- if (chdir (cwd ))
430- die_errno ("Cannot come back to cwd" );
431- * nongit_ok = 1 ;
432- return NULL ;
433- }
434- die ("Not a git repository (or any of the parent directories): %s" , DEFAULT_GIT_DIR_ENVIRONMENT );
435- }
487+ if (offset <= ceil_offset )
488+ return setup_nongit (cwd , nongit_ok );
436489 if (one_filesystem ) {
437- if (stat (".." , & buf )) {
438- cwd [offset ] = '\0' ;
439- die_errno ("failed to stat '%s/..'" , cwd );
440- }
441- if (buf .st_dev != current_device ) {
490+ dev_t parent_device = get_device_or_die (".." , cwd );
491+ if (parent_device != current_device ) {
442492 if (nongit_ok ) {
443493 if (chdir (cwd ))
444494 die_errno ("Cannot come back to cwd" );
@@ -455,22 +505,6 @@ const char *setup_git_directory_gently(int *nongit_ok)
455505 die_errno ("Cannot change to '%s/..'" , cwd );
456506 }
457507 }
458-
459- inside_git_dir = 0 ;
460- if (!work_tree_env )
461- inside_work_tree = 1 ;
462- root_len = offset_1st_component (cwd );
463- git_work_tree_cfg = xstrndup (cwd , offset > root_len ? offset : root_len );
464- if (check_repository_format_gently (nongit_ok ))
465- return NULL ;
466- if (offset == len )
467- return NULL ;
468-
469- /* Make "offset" point to past the '/', and add a '/' at the end */
470- offset ++ ;
471- cwd [len ++ ] = '/' ;
472- cwd [len ] = 0 ;
473- return cwd + offset ;
474508}
475509
476510int git_config_perm (const char * var , const char * value )
0 commit comments