Skip to content

Commit 693fefe

Browse files
committed
Merge branch 'jn/maint-setup-fix'
* jn/maint-setup-fix: setup: split off a function to handle ordinary .git directories Revert "rehabilitate 'git index-pack' inside the object store" setup: do not forget working dir from subdir of gitdir t4111 (apply): refresh index before applying patches to it setup: split off get_device_or_die helper setup: split off a function to handle hitting ceiling in repo search setup: split off code to handle stumbling upon a repository setup: split off a function to checks working dir for .git file setup: split off $GIT_DIR-set case from setup_git_directory_gently tests: try git apply from subdir of toplevel t1501 (rev-parse): clarify Conflicts: builtin/index-pack.c
2 parents 1253164 + 98937be commit 693fefe

4 files changed

Lines changed: 581 additions & 282 deletions

File tree

builtin/index-pack.c

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -880,31 +880,17 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
880880
char *index_name_buf = NULL, *keep_name_buf = NULL;
881881
struct pack_idx_entry **idx_objects;
882882
unsigned char pack_sha1[20];
883+
int nongit;
883884

884885
if (argc == 2 && !strcmp(argv[1], "-h"))
885886
usage(index_pack_usage);
886887

887888
read_replace_refs = 0;
888889

889-
/*
890-
* We wish to read the repository's config file if any, and
891-
* for that it is necessary to call setup_git_directory_gently().
892-
* However if the cwd was inside .git/objects/pack/ then we need
893-
* to go back there or all the pack name arguments will be wrong.
894-
* And in that case we cannot rely on any prefix returned by
895-
* setup_git_directory_gently() either.
896-
*/
897-
{
898-
char cwd[PATH_MAX+1];
899-
int nongit;
900-
901-
if (!getcwd(cwd, sizeof(cwd)-1))
902-
die("Unable to get current working directory");
903-
setup_git_directory_gently(&nongit);
904-
git_config(git_index_pack_config, NULL);
905-
if (chdir(cwd))
906-
die("Cannot come back to cwd");
907-
}
890+
prefix = setup_git_directory_gently(&nongit);
891+
git_config(git_index_pack_config, NULL);
892+
if (prefix && chdir(prefix))
893+
die("Cannot come back to cwd");
908894

909895
for (i = 1; i < argc; i++) {
910896
const char *arg = argv[i];

setup.c

Lines changed: 124 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -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

476510
int git_config_perm(const char *var, const char *value)

0 commit comments

Comments
 (0)