From e4e303479b62e474c52ee1f9edd265d7333117d9 Mon Sep 17 00:00:00 2001 From: Jonathan Nieder Date: Sat, 24 Jul 2010 06:19:44 -0500 Subject: setup: split off $GIT_DIR-set case from setup_git_directory_gently If $GIT_DIR is set, setup_git_directory_gently does not have to do any repository discovery at all. Split off a function for the validation it still does do, in the hope that this will make setup_git_directory_gently proper less daunting to read. Signed-off-by: Jonathan Nieder Signed-off-by: Junio C Hamano --- setup.c | 69 +++++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 37 insertions(+), 32 deletions(-) (limited to 'setup.c') diff --git a/setup.c b/setup.c index 2769160527..16bee6d485 100644 --- a/setup.c +++ b/setup.c @@ -313,6 +313,41 @@ const char *read_gitfile_gently(const char *path) return path; } +static const char *setup_explicit_git_dir(const char *gitdirenv, + const char *work_tree_env, int *nongit_ok) +{ + static char buffer[1024 + 1]; + const char *retval; + + if (PATH_MAX - 40 < strlen(gitdirenv)) + die("'$%s' too big", GIT_DIR_ENVIRONMENT); + if (!is_git_directory(gitdirenv)) { + if (nongit_ok) { + *nongit_ok = 1; + return NULL; + } + die("Not a git repository: '%s'", gitdirenv); + } + if (!work_tree_env) { + retval = set_work_tree(gitdirenv); + /* config may override worktree */ + if (check_repository_format_gently(nongit_ok)) + return NULL; + return retval; + } + if (check_repository_format_gently(nongit_ok)) + return NULL; + retval = get_relative_cwd(buffer, sizeof(buffer) - 1, + get_git_work_tree()); + if (!retval || !*retval) + return NULL; + set_git_dir(make_absolute_path(gitdirenv)); + if (chdir(work_tree_env) < 0) + die_errno ("Could not chdir to '%s'", work_tree_env); + strcat(buffer, "/"); + return retval; +} + /* * We cannot decide in this function whether we are in the work tree or * not, since the config can only be read _after_ this function was called. @@ -343,38 +378,8 @@ const char *setup_git_directory_gently(int *nongit_ok) * validation. */ gitdirenv = getenv(GIT_DIR_ENVIRONMENT); - if (gitdirenv) { - if (PATH_MAX - 40 < strlen(gitdirenv)) - die("'$%s' too big", GIT_DIR_ENVIRONMENT); - if (is_git_directory(gitdirenv)) { - static char buffer[1024 + 1]; - const char *retval; - - if (!work_tree_env) { - retval = set_work_tree(gitdirenv); - /* config may override worktree */ - if (check_repository_format_gently(nongit_ok)) - return NULL; - return retval; - } - if (check_repository_format_gently(nongit_ok)) - return NULL; - retval = get_relative_cwd(buffer, sizeof(buffer) - 1, - get_git_work_tree()); - if (!retval || !*retval) - return NULL; - set_git_dir(make_absolute_path(gitdirenv)); - if (chdir(work_tree_env) < 0) - die_errno ("Could not chdir to '%s'", work_tree_env); - strcat(buffer, "/"); - return retval; - } - if (nongit_ok) { - *nongit_ok = 1; - return NULL; - } - die("Not a git repository: '%s'", gitdirenv); - } + if (gitdirenv) + return setup_explicit_git_dir(gitdirenv, work_tree_env, nongit_ok); if (!getcwd(cwd, sizeof(cwd)-1)) die_errno("Unable to read current working directory"); -- cgit v1.2.1 From 93a00542eaeb40c31b4de2497f5413a2fc0f36f4 Mon Sep 17 00:00:00 2001 From: Jonathan Nieder Date: Sat, 24 Jul 2010 06:20:15 -0500 Subject: setup: split off a function to checks working dir for .git file The repository discovery procedure looks something like this: while (same filesystem) { check .git in working dir check . chdir(..) } Add a function for the first step to make the actual code look a bit closer to that pseudocode. Signed-off-by: Jonathan Nieder Signed-off-by: Junio C Hamano --- setup.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'setup.c') diff --git a/setup.c b/setup.c index 16bee6d485..3d25d0f205 100644 --- a/setup.c +++ b/setup.c @@ -348,6 +348,18 @@ static const char *setup_explicit_git_dir(const char *gitdirenv, return retval; } +static int cwd_contains_git_dir(const char **gitfile_dirp) +{ + const char *gitfile_dir = read_gitfile_gently(DEFAULT_GIT_DIR_ENVIRONMENT); + *gitfile_dirp = gitfile_dir; + if (gitfile_dir) { + if (set_git_dir(gitfile_dir)) + die("Repository setup failed"); + return 1; + } + return is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT); +} + /* * We cannot decide in this function whether we are in the work tree or * not, since the config can only be read _after_ this function was called. @@ -407,13 +419,7 @@ const char *setup_git_directory_gently(int *nongit_ok) current_device = buf.st_dev; } for (;;) { - gitfile_dir = read_gitfile_gently(DEFAULT_GIT_DIR_ENVIRONMENT); - if (gitfile_dir) { - if (set_git_dir(gitfile_dir)) - die("Repository setup failed"); - break; - } - if (is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT)) + if (cwd_contains_git_dir(&gitfile_dir)) break; if (is_git_directory(".")) { inside_git_dir = 1; -- cgit v1.2.1 From 68698da540acb0c891b810396d704fef3643c576 Mon Sep 17 00:00:00 2001 From: Jonathan Nieder Date: Sat, 24 Jul 2010 06:25:32 -0500 Subject: setup: split off code to handle stumbling upon a repository If a repository is found as an ancestor of the original working directory, it is assumed by default to be bare. Handle this case with its own function. Signed-off-by: Jonathan Nieder Signed-off-by: Junio C Hamano --- setup.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) (limited to 'setup.c') diff --git a/setup.c b/setup.c index 3d25d0f205..ec11c46266 100644 --- a/setup.c +++ b/setup.c @@ -360,6 +360,24 @@ static int cwd_contains_git_dir(const char **gitfile_dirp) return is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT); } +static const char *setup_bare_git_dir(const char *work_tree_env, + int offset, int len, char *cwd, int *nongit_ok) +{ + int root_len; + + inside_git_dir = 1; + if (!work_tree_env) + inside_work_tree = 0; + if (offset != len) { + root_len = offset_1st_component(cwd); + cwd[offset > root_len ? offset : root_len] = '\0'; + set_git_dir(cwd); + } else + set_git_dir("."); + check_repository_format_gently(nongit_ok); + return NULL; +} + /* * We cannot decide in this function whether we are in the work tree or * not, since the config can only be read _after_ this function was called. @@ -421,19 +439,9 @@ const char *setup_git_directory_gently(int *nongit_ok) for (;;) { if (cwd_contains_git_dir(&gitfile_dir)) break; - if (is_git_directory(".")) { - inside_git_dir = 1; - if (!work_tree_env) - inside_work_tree = 0; - if (offset != len) { - root_len = offset_1st_component(cwd); - cwd[offset > root_len ? offset : root_len] = '\0'; - set_git_dir(cwd); - } else - set_git_dir("."); - check_repository_format_gently(nongit_ok); - return NULL; - } + if (is_git_directory(".")) + return setup_bare_git_dir(work_tree_env, offset, + len, cwd, nongit_ok); while (--offset > ceil_offset && cwd[offset] != '/'); if (offset <= ceil_offset) { if (nongit_ok) { -- cgit v1.2.1 From f161edebb64f08bfc615fd9c28ebae3333255e2e Mon Sep 17 00:00:00 2001 From: Jonathan Nieder Date: Sat, 24 Jul 2010 06:26:41 -0500 Subject: setup: split off a function to handle hitting ceiling in repo search Perhaps some day, other similar conditions (hitting the mount point, hitting the root of the file system) will share this code. Signed-off-by: Jonathan Nieder Signed-off-by: Junio C Hamano --- setup.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'setup.c') diff --git a/setup.c b/setup.c index ec11c46266..9fc05e2c0a 100644 --- a/setup.c +++ b/setup.c @@ -378,6 +378,16 @@ static const char *setup_bare_git_dir(const char *work_tree_env, return NULL; } +static const char *setup_nongit(const char *cwd, int *nongit_ok) +{ + if (!nongit_ok) + die("Not a git repository (or any of the parent directories): %s", DEFAULT_GIT_DIR_ENVIRONMENT); + if (chdir(cwd)) + die_errno("Cannot come back to cwd"); + *nongit_ok = 1; + return NULL; +} + /* * We cannot decide in this function whether we are in the work tree or * not, since the config can only be read _after_ this function was called. @@ -443,15 +453,8 @@ const char *setup_git_directory_gently(int *nongit_ok) return setup_bare_git_dir(work_tree_env, offset, len, cwd, nongit_ok); while (--offset > ceil_offset && cwd[offset] != '/'); - if (offset <= ceil_offset) { - if (nongit_ok) { - if (chdir(cwd)) - die_errno("Cannot come back to cwd"); - *nongit_ok = 1; - return NULL; - } - die("Not a git repository (or any of the parent directories): %s", DEFAULT_GIT_DIR_ENVIRONMENT); - } + if (offset <= ceil_offset) + return setup_nongit(cwd, nongit_ok); if (one_filesystem) { if (stat("..", &buf)) { cwd[offset] = '\0'; -- cgit v1.2.1 From 60c98d1e80a65c9a893733f7bceda463ef3cb6f7 Mon Sep 17 00:00:00 2001 From: Jonathan Nieder Date: Sat, 24 Jul 2010 06:27:58 -0500 Subject: setup: split off get_device_or_die helper This does not eliminate any code, but it skims some off of the main loop of setup_git_directory_gently so that can be understood more easily. Signed-off-by: Jonathan Nieder Signed-off-by: Junio C Hamano --- setup.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'setup.c') diff --git a/setup.c b/setup.c index 9fc05e2c0a..5fb9c54ba6 100644 --- a/setup.c +++ b/setup.c @@ -388,6 +388,16 @@ static const char *setup_nongit(const char *cwd, int *nongit_ok) return NULL; } +static dev_t get_device_or_die(const char *path, const char *prefix) +{ + struct stat buf; + if (stat(path, &buf)) + die_errno("failed to stat '%s%s%s'", + prefix ? prefix : "", + prefix ? "/" : "", path); + return buf.st_dev; +} + /* * We cannot decide in this function whether we are in the work tree or * not, since the config can only be read _after_ this function was called. @@ -402,7 +412,6 @@ const char *setup_git_directory_gently(int *nongit_ok) int len, offset, ceil_offset, root_len; dev_t current_device = 0; int one_filesystem = 1; - struct stat buf; /* * Let's assume that we are in a git repository. @@ -441,11 +450,8 @@ const char *setup_git_directory_gently(int *nongit_ok) */ offset = len = strlen(cwd); one_filesystem = !git_env_bool("GIT_DISCOVERY_ACROSS_FILESYSTEM", 0); - if (one_filesystem) { - if (stat(".", &buf)) - die_errno("failed to stat '.'"); - current_device = buf.st_dev; - } + if (one_filesystem) + current_device = get_device_or_die(".", NULL); for (;;) { if (cwd_contains_git_dir(&gitfile_dir)) break; @@ -456,11 +462,8 @@ const char *setup_git_directory_gently(int *nongit_ok) if (offset <= ceil_offset) return setup_nongit(cwd, nongit_ok); if (one_filesystem) { - if (stat("..", &buf)) { - cwd[offset] = '\0'; - die_errno("failed to stat '%s/..'", cwd); - } - if (buf.st_dev != current_device) { + dev_t parent_device = get_device_or_die("..", cwd); + if (parent_device != current_device) { if (nongit_ok) { if (chdir(cwd)) die_errno("Cannot come back to cwd"); -- cgit v1.2.1 From 8fc0ae80f6938e409e0efa45d6d504c6137744e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sat, 24 Jul 2010 06:29:41 -0500 Subject: setup: do not forget working dir from subdir of gitdir MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v1.6.1.3~4^2 (Fix gitdir detection when in subdir of gitdir, 2009-01-16) did not go far enough: when a git directory is an ancestor of the original working directory, not only should GIT_DIR be set to point to the .git directory, but the original working directory should be restored before carrying out the relevant command. This way, the effect of running a git command from a subdir of .git will be the same whether or not GIT_DIR is explicitly set. Noticed while investigating v1.6.0.3~1 (rehabilitate 'git index-pack' inside the object store, 2008-10-20). Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Jonathan Nieder Signed-off-by: Junio C Hamano --- setup.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'setup.c') diff --git a/setup.c b/setup.c index 5fb9c54ba6..5734a1f1c1 100644 --- a/setup.c +++ b/setup.c @@ -369,6 +369,8 @@ static const char *setup_bare_git_dir(const char *work_tree_env, if (!work_tree_env) inside_work_tree = 0; if (offset != len) { + if (chdir(cwd)) + die_errno("Cannot come back to cwd"); root_len = offset_1st_component(cwd); cwd[offset > root_len ? offset : root_len] = '\0'; set_git_dir(cwd); -- cgit v1.2.1 From 98937bef1bf1c8eea90c209c601d4338a43a3479 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sat, 24 Jul 2010 07:11:58 -0500 Subject: setup: split off a function to handle ordinary .git directories Finish the clean-up of setup_git_directory_gently() by splitting the last case of validation+setup (global variables, prefix, check_format, set_git_dir) into its own function. Now setup_git_git_directory_gently itself takes care of discovery only and the functions that pick up from there are nearby in the source file so they can be easily compared. Signed-off-by: Jonathan Nieder Signed-off-by: Junio C Hamano --- setup.c | 43 +++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 18 deletions(-) (limited to 'setup.c') diff --git a/setup.c b/setup.c index 5734a1f1c1..d19aa7d7a9 100644 --- a/setup.c +++ b/setup.c @@ -360,6 +360,28 @@ static int cwd_contains_git_dir(const char **gitfile_dirp) return is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT); } +static const char *setup_discovered_git_dir(const char *work_tree_env, + int offset, int len, char *cwd, int *nongit_ok) +{ + int root_len; + + inside_git_dir = 0; + if (!work_tree_env) + inside_work_tree = 1; + root_len = offset_1st_component(cwd); + git_work_tree_cfg = xstrndup(cwd, offset > root_len ? offset : root_len); + if (check_repository_format_gently(nongit_ok)) + return NULL; + if (offset == len) + return NULL; + + /* Make "offset" point to past the '/', and add a '/' at the end */ + offset++; + cwd[len++] = '/'; + cwd[len] = 0; + return cwd + offset; +} + static const char *setup_bare_git_dir(const char *work_tree_env, int offset, int len, char *cwd, int *nongit_ok) { @@ -411,7 +433,7 @@ const char *setup_git_directory_gently(int *nongit_ok) static char cwd[PATH_MAX+1]; const char *gitdirenv; const char *gitfile_dir; - int len, offset, ceil_offset, root_len; + int len, offset, ceil_offset; dev_t current_device = 0; int one_filesystem = 1; @@ -456,7 +478,8 @@ const char *setup_git_directory_gently(int *nongit_ok) current_device = get_device_or_die(".", NULL); for (;;) { if (cwd_contains_git_dir(&gitfile_dir)) - break; + return setup_discovered_git_dir(work_tree_env, offset, + len, cwd, nongit_ok); if (is_git_directory(".")) return setup_bare_git_dir(work_tree_env, offset, len, cwd, nongit_ok); @@ -482,22 +505,6 @@ const char *setup_git_directory_gently(int *nongit_ok) die_errno("Cannot change to '%s/..'", cwd); } } - - inside_git_dir = 0; - if (!work_tree_env) - inside_work_tree = 1; - root_len = offset_1st_component(cwd); - git_work_tree_cfg = xstrndup(cwd, offset > root_len ? offset : root_len); - if (check_repository_format_gently(nongit_ok)) - return NULL; - if (offset == len) - return NULL; - - /* Make "offset" point to past the '/', and add a '/' at the end */ - offset++; - cwd[len++] = '/'; - cwd[len] = 0; - return cwd + offset; } int git_config_perm(const char *var, const char *value) -- cgit v1.2.1