Merge branch 'gb/maint-submodule-env'

* 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
This commit is contained in:
Junio C Hamano 2010-03-07 12:47:17 -08:00
commit 9317dc4f05
8 changed files with 69 additions and 33 deletions

View File

@ -148,6 +148,12 @@ shown. If the pattern does not contain a globbing character (`?`,
--is-bare-repository:: --is-bare-repository::
When the repository is bare print "true", otherwise "false". When the repository is bare print "true", otherwise "false".
--local-env-vars::
List the GIT_* environment variables that are local to the
repository (e.g. GIT_DIR or GIT_WORK_TREE, but not GIT_EDITOR).
Only the names of the variables are listed, not their value,
even if they are set.
--short:: --short::
--short=number:: --short=number::
Instead of outputting the full SHA1 values of object names try to Instead of outputting the full SHA1 values of object names try to

View File

@ -455,6 +455,13 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
if (argc > 1 && !strcmp("--sq-quote", argv[1])) if (argc > 1 && !strcmp("--sq-quote", argv[1]))
return cmd_sq_quote(argc - 2, argv + 2); return cmd_sq_quote(argc - 2, argv + 2);
if (argc == 2 && !strcmp("--local-env-vars", argv[1])) {
int i;
for (i = 0; local_repo_env[i]; i++)
printf("%s\n", local_repo_env[i]);
return 0;
}
if (argc > 1 && !strcmp("-h", argv[1])) if (argc > 1 && !strcmp("-h", argv[1]))
usage(builtin_rev_parse_usage); usage(builtin_rev_parse_usage);

View File

@ -388,6 +388,15 @@ static inline enum object_type object_type(unsigned int mode)
#define GIT_NOTES_REF_ENVIRONMENT "GIT_NOTES_REF" #define GIT_NOTES_REF_ENVIRONMENT "GIT_NOTES_REF"
#define GIT_NOTES_DEFAULT_REF "refs/notes/commits" #define GIT_NOTES_DEFAULT_REF "refs/notes/commits"
/*
* Repository-local GIT_* environment variables
* The array is NULL-terminated to simplify its usage in contexts such
* environment creation or simple walk of the list.
* The number of non-NULL entries is available as a macro.
*/
#define LOCAL_REPO_ENV_SIZE 8
extern const char *const local_repo_env[LOCAL_REPO_ENV_SIZE + 1];
extern int is_bare_repository_cfg; extern int is_bare_repository_cfg;
extern int is_bare_repository(void); extern int is_bare_repository(void);
extern int is_inside_git_dir(void); extern int is_inside_git_dir(void);

View File

@ -582,18 +582,8 @@ struct child_process *git_connect(int fd[2], const char *url_orig,
*arg++ = host; *arg++ = host;
} }
else { else {
/* remove these from the environment */ /* remove repo-local variables from the environment */
const char *env[] = { conn->env = local_repo_env;
ALTERNATE_DB_ENVIRONMENT,
DB_ENVIRONMENT,
GIT_DIR_ENVIRONMENT,
GIT_WORK_TREE_ENVIRONMENT,
GRAFT_ENVIRONMENT,
INDEX_ENVIRONMENT,
NO_REPLACE_OBJECTS_ENVIRONMENT,
NULL
};
conn->env = env;
conn->use_shell = 1; conn->use_shell = 1;
} }
*arg++ = cmd.buf; *arg++ = cmd.buf;

View File

@ -63,6 +63,23 @@ static char *work_tree;
static const char *git_dir; static const char *git_dir;
static char *git_object_dir, *git_index_file, *git_refs_dir, *git_graft_file; static char *git_object_dir, *git_index_file, *git_refs_dir, *git_graft_file;
/*
* Repository-local GIT_* environment variables
* Remember to update local_repo_env_size in cache.h when
* the size of the list changes
*/
const char * const local_repo_env[LOCAL_REPO_ENV_SIZE + 1] = {
ALTERNATE_DB_ENVIRONMENT,
CONFIG_ENVIRONMENT,
DB_ENVIRONMENT,
GIT_DIR_ENVIRONMENT,
GIT_WORK_TREE_ENVIRONMENT,
GRAFT_ENVIRONMENT,
INDEX_ENVIRONMENT,
NO_REPLACE_OBJECTS_ENVIRONMENT,
NULL
};
static void setup_git_env(void) static void setup_git_env(void)
{ {
git_dir = getenv(GIT_DIR_ENVIRONMENT); git_dir = getenv(GIT_DIR_ENVIRONMENT);

View File

@ -172,6 +172,13 @@ get_author_ident_from_commit () {
LANG=C LC_ALL=C sed -ne "$pick_author_script" LANG=C LC_ALL=C sed -ne "$pick_author_script"
} }
# Clear repo-local GIT_* environment variables. Useful when switching to
# another repository (e.g. when entering a submodule). See also the env
# list in git_connect()
clear_local_git_env() {
unset $(git rev-parse --local-env-vars)
}
# Make sure we are in a valid repository of a vintage we understand, # Make sure we are in a valid repository of a vintage we understand,
# if we require to be in a git repository. # if we require to be in a git repository.
if test -z "$NONGIT_OK" if test -z "$NONGIT_OK"

View File

@ -222,7 +222,7 @@ cmd_add()
module_clone "$path" "$realrepo" "$reference" || exit module_clone "$path" "$realrepo" "$reference" || exit
( (
unset GIT_DIR clear_local_git_env
cd "$path" && cd "$path" &&
# ash fails to wordsplit ${branch:+-b "$branch"...} # ash fails to wordsplit ${branch:+-b "$branch"...}
case "$branch" in case "$branch" in
@ -278,7 +278,7 @@ cmd_foreach()
name=$(module_name "$path") name=$(module_name "$path")
( (
prefix="$prefix$path/" prefix="$prefix$path/"
unset GIT_DIR clear_local_git_env
cd "$path" && cd "$path" &&
eval "$@" && eval "$@" &&
if test -n "$recursive" if test -n "$recursive"
@ -434,7 +434,7 @@ cmd_update()
module_clone "$path" "$url" "$reference"|| exit module_clone "$path" "$url" "$reference"|| exit
subsha1= subsha1=
else else
subsha1=$(unset GIT_DIR; cd "$path" && subsha1=$(clear_local_git_env; cd "$path" &&
git rev-parse --verify HEAD) || git rev-parse --verify HEAD) ||
die "Unable to find current revision in submodule path '$path'" die "Unable to find current revision in submodule path '$path'"
fi fi
@ -454,7 +454,7 @@ cmd_update()
if test -z "$nofetch" if test -z "$nofetch"
then then
(unset GIT_DIR; cd "$path" && (clear_local_git_env; cd "$path" &&
git-fetch) || git-fetch) ||
die "Unable to fetch in submodule path '$path'" die "Unable to fetch in submodule path '$path'"
fi fi
@ -477,14 +477,14 @@ cmd_update()
;; ;;
esac esac
(unset GIT_DIR; cd "$path" && $command "$sha1") || (clear_local_git_env; cd "$path" && $command "$sha1") ||
die "Unable to $action '$sha1' in submodule path '$path'" die "Unable to $action '$sha1' in submodule path '$path'"
say "Submodule path '$path': $msg '$sha1'" say "Submodule path '$path': $msg '$sha1'"
fi fi
if test -n "$recursive" if test -n "$recursive"
then then
(unset GIT_DIR; cd "$path" && cmd_update $orig_args) || (clear_local_git_env; cd "$path" && cmd_update $orig_args) ||
die "Failed to recurse into submodule path '$path'" die "Failed to recurse into submodule path '$path'"
fi fi
done done
@ -492,7 +492,7 @@ cmd_update()
set_name_rev () { set_name_rev () {
revname=$( ( revname=$( (
unset GIT_DIR clear_local_git_env
cd "$1" && { cd "$1" && {
git describe "$2" 2>/dev/null || git describe "$2" 2>/dev/null ||
git describe --tags "$2" 2>/dev/null || git describe --tags "$2" 2>/dev/null ||
@ -760,7 +760,7 @@ cmd_status()
else else
if test -z "$cached" if test -z "$cached"
then then
sha1=$(unset GIT_DIR; cd "$path" && git rev-parse --verify HEAD) sha1=$(clear_local_git_env; cd "$path" && git rev-parse --verify HEAD)
set_name_rev "$path" "$sha1" set_name_rev "$path" "$sha1"
fi fi
say "+$sha1 $displaypath$revname" say "+$sha1 $displaypath$revname"
@ -770,7 +770,7 @@ cmd_status()
then then
( (
prefix="$displaypath/" prefix="$displaypath/"
unset GIT_DIR clear_local_git_env
cd "$path" && cd "$path" &&
cmd_status $orig_args cmd_status $orig_args
) || ) ||
@ -821,7 +821,7 @@ cmd_sync()
if test -e "$path"/.git if test -e "$path"/.git
then then
( (
unset GIT_DIR clear_local_git_env
cd "$path" cd "$path"
remote=$(get_default_remote) remote=$(get_default_remote)
say "Synchronizing submodule url for '$name'" say "Synchronizing submodule url for '$name'"

View File

@ -123,16 +123,19 @@ void show_submodule_summary(FILE *f, const char *path,
int is_submodule_modified(const char *path) int is_submodule_modified(const char *path)
{ {
int len; int len, i;
struct child_process cp; struct child_process cp;
const char *argv[] = { const char *argv[] = {
"status", "status",
"--porcelain", "--porcelain",
NULL, NULL,
}; };
char *env[4]; const char *env[LOCAL_REPO_ENV_SIZE + 3];
struct strbuf buf = STRBUF_INIT; struct strbuf buf = STRBUF_INIT;
for (i = 0; i < LOCAL_REPO_ENV_SIZE; i++)
env[i] = local_repo_env[i];
strbuf_addf(&buf, "%s/.git/", path); strbuf_addf(&buf, "%s/.git/", path);
if (!is_directory(buf.buf)) { if (!is_directory(buf.buf)) {
strbuf_release(&buf); strbuf_release(&buf);
@ -143,16 +146,14 @@ int is_submodule_modified(const char *path)
strbuf_reset(&buf); strbuf_reset(&buf);
strbuf_addf(&buf, "GIT_WORK_TREE=%s", path); strbuf_addf(&buf, "GIT_WORK_TREE=%s", path);
env[0] = strbuf_detach(&buf, NULL); env[i++] = strbuf_detach(&buf, NULL);
strbuf_addf(&buf, "GIT_DIR=%s/.git", path); strbuf_addf(&buf, "GIT_DIR=%s/.git", path);
env[1] = strbuf_detach(&buf, NULL); env[i++] = strbuf_detach(&buf, NULL);
strbuf_addf(&buf, "GIT_INDEX_FILE"); env[i] = NULL;
env[2] = strbuf_detach(&buf, NULL);
env[3] = NULL;
memset(&cp, 0, sizeof(cp)); memset(&cp, 0, sizeof(cp));
cp.argv = argv; cp.argv = argv;
cp.env = (const char *const *)env; cp.env = env;
cp.git_cmd = 1; cp.git_cmd = 1;
cp.no_stdin = 1; cp.no_stdin = 1;
cp.out = -1; cp.out = -1;
@ -165,9 +166,8 @@ int is_submodule_modified(const char *path)
if (finish_command(&cp)) if (finish_command(&cp))
die("git status --porcelain failed"); die("git status --porcelain failed");
free(env[0]); for (i = LOCAL_REPO_ENV_SIZE; env[i]; i++)
free(env[1]); free((char *)env[i]);
free(env[2]);
strbuf_release(&buf); strbuf_release(&buf);
return len != 0; return len != 0;
} }