Skip to content

Commit bd08ecc

Browse files
committed
Merge branch 'gb/maint-submodule-env' into maint
* gb/maint-submodule-env: is_submodule_modified(): clear environment properly submodules: ensure clean environment when operating in a submodule shell setup: clear_local_git_env() function rev-parse: --local-env-vars option Refactor list of of repo-local env vars
2 parents 030bc0a + 5ce9086 commit bd08ecc

File tree

8 files changed

+69
-33
lines changed

8 files changed

+69
-33
lines changed

Documentation/git-rev-parse.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,12 @@ shown. If the pattern does not contain a globbing character (`?`,
148148
--is-bare-repository::
149149
When the repository is bare print "true", otherwise "false".
150150

151+
--local-env-vars::
152+
List the GIT_* environment variables that are local to the
153+
repository (e.g. GIT_DIR or GIT_WORK_TREE, but not GIT_EDITOR).
154+
Only the names of the variables are listed, not their value,
155+
even if they are set.
156+
151157
--short::
152158
--short=number::
153159
Instead of outputting the full SHA1 values of object names try to

builtin-rev-parse.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,13 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
455455
if (argc > 1 && !strcmp("--sq-quote", argv[1]))
456456
return cmd_sq_quote(argc - 2, argv + 2);
457457

458+
if (argc == 2 && !strcmp("--local-env-vars", argv[1])) {
459+
int i;
460+
for (i = 0; local_repo_env[i]; i++)
461+
printf("%s\n", local_repo_env[i]);
462+
return 0;
463+
}
464+
458465
if (argc > 1 && !strcmp("-h", argv[1]))
459466
usage(builtin_rev_parse_usage);
460467

cache.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,15 @@ static inline enum object_type object_type(unsigned int mode)
388388
#define GIT_NOTES_REF_ENVIRONMENT "GIT_NOTES_REF"
389389
#define GIT_NOTES_DEFAULT_REF "refs/notes/commits"
390390

391+
/*
392+
* Repository-local GIT_* environment variables
393+
* The array is NULL-terminated to simplify its usage in contexts such
394+
* environment creation or simple walk of the list.
395+
* The number of non-NULL entries is available as a macro.
396+
*/
397+
#define LOCAL_REPO_ENV_SIZE 8
398+
extern const char *const local_repo_env[LOCAL_REPO_ENV_SIZE + 1];
399+
391400
extern int is_bare_repository_cfg;
392401
extern int is_bare_repository(void);
393402
extern int is_inside_git_dir(void);

connect.c

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -607,18 +607,8 @@ struct child_process *git_connect(int fd[2], const char *url_orig,
607607
*arg++ = host;
608608
}
609609
else {
610-
/* remove these from the environment */
611-
const char *env[] = {
612-
ALTERNATE_DB_ENVIRONMENT,
613-
DB_ENVIRONMENT,
614-
GIT_DIR_ENVIRONMENT,
615-
GIT_WORK_TREE_ENVIRONMENT,
616-
GRAFT_ENVIRONMENT,
617-
INDEX_ENVIRONMENT,
618-
NO_REPLACE_OBJECTS_ENVIRONMENT,
619-
NULL
620-
};
621-
conn->env = env;
610+
/* remove repo-local variables from the environment */
611+
conn->env = local_repo_env;
622612
conn->use_shell = 1;
623613
}
624614
*arg++ = cmd.buf;

environment.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,23 @@ static char *work_tree;
6363
static const char *git_dir;
6464
static char *git_object_dir, *git_index_file, *git_refs_dir, *git_graft_file;
6565

66+
/*
67+
* Repository-local GIT_* environment variables
68+
* Remember to update local_repo_env_size in cache.h when
69+
* the size of the list changes
70+
*/
71+
const char * const local_repo_env[LOCAL_REPO_ENV_SIZE + 1] = {
72+
ALTERNATE_DB_ENVIRONMENT,
73+
CONFIG_ENVIRONMENT,
74+
DB_ENVIRONMENT,
75+
GIT_DIR_ENVIRONMENT,
76+
GIT_WORK_TREE_ENVIRONMENT,
77+
GRAFT_ENVIRONMENT,
78+
INDEX_ENVIRONMENT,
79+
NO_REPLACE_OBJECTS_ENVIRONMENT,
80+
NULL
81+
};
82+
6683
static void setup_git_env(void)
6784
{
6885
git_dir = getenv(GIT_DIR_ENVIRONMENT);

git-sh-setup.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,13 @@ get_author_ident_from_commit () {
172172
LANG=C LC_ALL=C sed -ne "$pick_author_script"
173173
}
174174
175+
# Clear repo-local GIT_* environment variables. Useful when switching to
176+
# another repository (e.g. when entering a submodule). See also the env
177+
# list in git_connect()
178+
clear_local_git_env() {
179+
unset $(git rev-parse --local-env-vars)
180+
}
181+
175182
# Make sure we are in a valid repository of a vintage we understand,
176183
# if we require to be in a git repository.
177184
if test -z "$NONGIT_OK"

git-submodule.sh

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ cmd_add()
222222

223223
module_clone "$path" "$realrepo" "$reference" || exit
224224
(
225-
unset GIT_DIR
225+
clear_local_git_env
226226
cd "$path" &&
227227
# ash fails to wordsplit ${branch:+-b "$branch"...}
228228
case "$branch" in
@@ -278,7 +278,7 @@ cmd_foreach()
278278
name=$(module_name "$path")
279279
(
280280
prefix="$prefix$path/"
281-
unset GIT_DIR
281+
clear_local_git_env
282282
cd "$path" &&
283283
eval "$@" &&
284284
if test -n "$recursive"
@@ -434,7 +434,7 @@ cmd_update()
434434
module_clone "$path" "$url" "$reference"|| exit
435435
subsha1=
436436
else
437-
subsha1=$(unset GIT_DIR; cd "$path" &&
437+
subsha1=$(clear_local_git_env; cd "$path" &&
438438
git rev-parse --verify HEAD) ||
439439
die "Unable to find current revision in submodule path '$path'"
440440
fi
@@ -454,7 +454,7 @@ cmd_update()
454454

455455
if test -z "$nofetch"
456456
then
457-
(unset GIT_DIR; cd "$path" &&
457+
(clear_local_git_env; cd "$path" &&
458458
git-fetch) ||
459459
die "Unable to fetch in submodule path '$path'"
460460
fi
@@ -477,22 +477,22 @@ cmd_update()
477477
;;
478478
esac
479479

480-
(unset GIT_DIR; cd "$path" && $command "$sha1") ||
480+
(clear_local_git_env; cd "$path" && $command "$sha1") ||
481481
die "Unable to $action '$sha1' in submodule path '$path'"
482482
say "Submodule path '$path': $msg '$sha1'"
483483
fi
484484

485485
if test -n "$recursive"
486486
then
487-
(unset GIT_DIR; cd "$path" && cmd_update $orig_args) ||
487+
(clear_local_git_env; cd "$path" && cmd_update $orig_args) ||
488488
die "Failed to recurse into submodule path '$path'"
489489
fi
490490
done
491491
}
492492

493493
set_name_rev () {
494494
revname=$( (
495-
unset GIT_DIR
495+
clear_local_git_env
496496
cd "$1" && {
497497
git describe "$2" 2>/dev/null ||
498498
git describe --tags "$2" 2>/dev/null ||
@@ -757,7 +757,7 @@ cmd_status()
757757
else
758758
if test -z "$cached"
759759
then
760-
sha1=$(unset GIT_DIR; cd "$path" && git rev-parse --verify HEAD)
760+
sha1=$(clear_local_git_env; cd "$path" && git rev-parse --verify HEAD)
761761
set_name_rev "$path" "$sha1"
762762
fi
763763
say "+$sha1 $displaypath$revname"
@@ -767,7 +767,7 @@ cmd_status()
767767
then
768768
(
769769
prefix="$displaypath/"
770-
unset GIT_DIR
770+
clear_local_git_env
771771
cd "$path" &&
772772
cmd_status $orig_args
773773
) ||
@@ -818,7 +818,7 @@ cmd_sync()
818818
if test -e "$path"/.git
819819
then
820820
(
821-
unset GIT_DIR
821+
clear_local_git_env
822822
cd "$path"
823823
remote=$(get_default_remote)
824824
say "Synchronizing submodule url for '$name'"

submodule.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -123,16 +123,19 @@ void show_submodule_summary(FILE *f, const char *path,
123123

124124
int is_submodule_modified(const char *path)
125125
{
126-
int len;
126+
int len, i;
127127
struct child_process cp;
128128
const char *argv[] = {
129129
"status",
130130
"--porcelain",
131131
NULL,
132132
};
133-
char *env[4];
133+
const char *env[LOCAL_REPO_ENV_SIZE + 3];
134134
struct strbuf buf = STRBUF_INIT;
135135

136+
for (i = 0; i < LOCAL_REPO_ENV_SIZE; i++)
137+
env[i] = local_repo_env[i];
138+
136139
strbuf_addf(&buf, "%s/.git/", path);
137140
if (!is_directory(buf.buf)) {
138141
strbuf_release(&buf);
@@ -143,16 +146,14 @@ int is_submodule_modified(const char *path)
143146
strbuf_reset(&buf);
144147

145148
strbuf_addf(&buf, "GIT_WORK_TREE=%s", path);
146-
env[0] = strbuf_detach(&buf, NULL);
149+
env[i++] = strbuf_detach(&buf, NULL);
147150
strbuf_addf(&buf, "GIT_DIR=%s/.git", path);
148-
env[1] = strbuf_detach(&buf, NULL);
149-
strbuf_addf(&buf, "GIT_INDEX_FILE");
150-
env[2] = strbuf_detach(&buf, NULL);
151-
env[3] = NULL;
151+
env[i++] = strbuf_detach(&buf, NULL);
152+
env[i] = NULL;
152153

153154
memset(&cp, 0, sizeof(cp));
154155
cp.argv = argv;
155-
cp.env = (const char *const *)env;
156+
cp.env = env;
156157
cp.git_cmd = 1;
157158
cp.no_stdin = 1;
158159
cp.out = -1;
@@ -165,9 +166,8 @@ int is_submodule_modified(const char *path)
165166
if (finish_command(&cp))
166167
die("git status --porcelain failed");
167168

168-
free(env[0]);
169-
free(env[1]);
170-
free(env[2]);
169+
for (i = LOCAL_REPO_ENV_SIZE; env[i]; i++)
170+
free((char *)env[i]);
171171
strbuf_release(&buf);
172172
return len != 0;
173173
}

0 commit comments

Comments
 (0)