properly keep track of current working directory

Various failure modes in the repository detection code path currently quote the wrong directory in their error message. The working directory is changed iteratively to the parent directory until a git repository is found. If the working directory cannot be changed to the parent directory for some reason, the detection gives up and prints an error message. The error message should report the current working directory. Instead of continually updating the 'cwd' variable, which is actually used to remember the original working directory, the 'offset' variable is used to keep track of the current working directory. At the point where the affected error handling code is called, 'offset' already points to the end of the parent of the working directory, rather than the current working directory. Fix this by explicitly using a variable 'offset_parent' and update 'offset' concurrently with the call to chdir. In a similar fashion, the function get_device_or_die() would print the original working directory in case of a failure, rather than the current working directory. Fix this as well by making use of the 'offset' variable. Lastly, replace the phrase 'mount parent' with 'mount point'. The former appears to be a typo. Signed-off-by: Clemens Buchacher <drizzd@aon.at> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Clemens Buchacher committed Apr 13, 2012 at 01:11 UTC 2565b43bd2634ffd6bda06236d664288aeb8eb6a
1 file changed +13 -9
setup.c
+13 -9
@@ -569,13 +569,15 @@ static const char *setup_nongit(const char *cwd, int *nongit_ok)
569 return NULL;
570 }
571
572 -static dev_t get_device_or_die(const char *path, const char *prefix)
572 +static dev_t get_device_or_die(const char *path, const char *prefix, int prefix_len)
573 {
574 struct stat buf;
575 - if (stat(path, &buf))
576 - die_errno("failed to stat '%s%s%s'",
575 + if (stat(path, &buf)) {
576 + die_errno("failed to stat '%*s%s%s'",
577 + prefix_len,
578 prefix ? prefix : "",
579 prefix ? "/" : "", path);
580 + }
581 return buf.st_dev;
582 }
583
@@ -589,7 +591,7 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
591 static char cwd[PATH_MAX+1];
592 const char *gitdirenv, *ret;
593 char *gitfile;
592 - int len, offset, ceil_offset;
594 + int len, offset, offset_parent, ceil_offset;
595 dev_t current_device = 0;
596 int one_filesystem = 1;
597
@@ -631,7 +633,7 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
633 */
634 one_filesystem = !git_env_bool("GIT_DISCOVERY_ACROSS_FILESYSTEM", 0);
635 if (one_filesystem)
634 - current_device = get_device_or_die(".", NULL);
636 + current_device = get_device_or_die(".", NULL, 0);
637 for (;;) {
638 gitfile = (char*)read_gitfile(DEFAULT_GIT_DIR_ENVIRONMENT);
639 if (gitfile)
@@ -653,11 +655,12 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
655 if (is_git_directory("."))
656 return setup_bare_git_dir(cwd, offset, len, nongit_ok);
657
656 - while (--offset > ceil_offset && cwd[offset] != '/');
657 - if (offset <= ceil_offset)
658 + offset_parent = offset;
659 + while (--offset_parent > ceil_offset && cwd[offset_parent] != '/');
660 + if (offset_parent <= ceil_offset)
661 return setup_nongit(cwd, nongit_ok);
662 if (one_filesystem) {
660 - dev_t parent_device = get_device_or_die("..", cwd);
663 + dev_t parent_device = get_device_or_die("..", cwd, offset);
664 if (parent_device != current_device) {
665 if (nongit_ok) {
666 if (chdir(cwd))
@@ -666,7 +669,7 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
669 return NULL;
670 }
671 cwd[offset] = '\0';
669 - die("Not a git repository (or any parent up to mount parent %s)\n"
672 + die("Not a git repository (or any parent up to mount point %s)\n"
673 "Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).", cwd);
674 }
675 }
@@ -674,6 +677,7 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
677 cwd[offset] = '\0';
678 die_errno("Cannot change to '%s/..'", cwd);
679 }
680 + offset = offset_parent;
681 }
682 }
683