From 4db16f58c7720257eea9ffb7d4e76809f2c403f0 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Tue, 27 Jun 2023 16:18:55 +0000 Subject: [PATCH 1/8] var: mark unused parameters in git_var callbacks We abstract the set of variables into a table, with a "read" callback to provide the value of each. Each callback takes a "flag" argument, but most callbacks don't make use of it. This flag is a bit odd. It may be set to IDENT_STRICT, which make sense for ident-based callbacks, but is just confusing for things like GIT_EDITOR. At first glance, it seems like this is just a hack to let us directly stick the generic git_committer_info() and git_author_info() functions into our table. And we'd be better off to wrap them with local functions which pass IDENT_STRICT, and have our callbacks take no option at all. But that doesn't quite work. We pass IDENT_STRICT when the caller asks for a specific variable, but otherwise do not (so that "git var -l" does not bail if the committer ident cannot be formed). So we really do need to pass in the flag to each invocation, even if the individual callback doesn't care about it. Let's mark the unused ones so that -Wunused-parameter does not complain. And while we're here, let's rename them so that it's clear that the flag values we get will be from the IDENT_* set. That may prevent confusion for future readers of the code. Another option would be to define our own local "strict" flag for the callbacks, and then have wrappers that translate that to IDENT_STRICT where it matters. But that would be more boilerplate for little gain (most functions would still ignore the "strict" flag anyway). Signed-off-by: Jeff King Signed-off-by: brian m. carlson Signed-off-by: Junio C Hamano --- builtin/var.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/builtin/var.c b/builtin/var.c index 2149998980..10ee62f84c 100644 --- a/builtin/var.c +++ b/builtin/var.c @@ -12,17 +12,17 @@ static const char var_usage[] = "git var (-l | )"; -static const char *editor(int flag) +static const char *editor(int ident_flag UNUSED) { return git_editor(); } -static const char *sequence_editor(int flag) +static const char *sequence_editor(int ident_flag UNUSED) { return git_sequence_editor(); } -static const char *pager(int flag) +static const char *pager(int ident_flag UNUSED) { const char *pgm = git_pager(1); @@ -31,7 +31,7 @@ static const char *pager(int flag) return pgm; } -static const char *default_branch(int flag) +static const char *default_branch(int ident_flag UNUSED) { return git_default_branch_name(1); } From d6546af75c3cda2815f2e4d5322dd7a41cc0963b Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Tue, 27 Jun 2023 16:18:56 +0000 Subject: [PATCH 2/8] t: add a function to check executable bit In line with our other helper functions for paths, let's add a function to check whether a path is executable, and if not, print a suitable error message. Document this function, and note that it must only be used under the POSIXPERM prerequisite, since it doesn't otherwise work on Windows. Signed-off-by: brian m. carlson Signed-off-by: Junio C Hamano --- t/README | 6 ++++++ t/test-lib-functions.sh | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/t/README b/t/README index bdfac4cceb..3e155011de 100644 --- a/t/README +++ b/t/README @@ -1098,6 +1098,12 @@ see test-lib-functions.sh for the full list and their options. the symbolic link in the file system and a part that does; then only the latter part need be protected by a SYMLINKS prerequisite (see below). + - test_path_is_executable + + This tests whether a file is executable and prints an error message + if not. This must be used only under the POSIXPERM prerequisite + (see below). + - test_oid_init This function loads facts and useful object IDs related to the hash diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh index 6e19ebc922..2ef579edf3 100644 --- a/t/test-lib-functions.sh +++ b/t/test-lib-functions.sh @@ -901,6 +901,15 @@ test_path_is_symlink () { fi } +test_path_is_executable () { + test "$#" -ne 1 && BUG "1 param" + if ! test -x "$1" + then + echo "$1 is not executable" + false + fi +} + # Check if the directory exists and is empty as expected, barf otherwise. test_dir_is_empty () { test "$#" -ne 1 && BUG "1 param" From 1e6572122702cbf0e3b6d3226f73e6b8b45e6e37 Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Tue, 27 Jun 2023 16:18:57 +0000 Subject: [PATCH 3/8] var: add support for listing the shell On most Unix systems, finding a suitable shell is easy: one simply uses "sh" with an appropriate PATH value. However, in many Windows environments, the shell is shipped alongside Git, and it may or may not be in PATH, even if Git is. In such an environment, it can be very helpful to query Git for the shell it's using, since other tools may want to use the same shell as well. To help them out, let's add a variable, GIT_SHELL_PATH, that points to the location of the shell. On Unix, we know our shell must be executable to be functional, so assume that the distributor has correctly configured their environment, and use that as a basic test. On Git for Windows, we know that our shell will be one of a few fixed values, all of which end in "sh" (such as "bash"). This seems like it might be a nice test on Unix as well, since it is customary for all shells to end in "sh", but there probably exist such systems that don't have such a configuration, so be careful here not to break them. Signed-off-by: brian m. carlson Signed-off-by: Junio C Hamano --- Documentation/git-var.txt | 3 +++ builtin/var.c | 6 ++++++ t/t0007-git-var.sh | 15 +++++++++++++++ 3 files changed, 24 insertions(+) diff --git a/Documentation/git-var.txt b/Documentation/git-var.txt index f40202b8e3..f0f647e14a 100644 --- a/Documentation/git-var.txt +++ b/Documentation/git-var.txt @@ -71,6 +71,9 @@ endif::git-default-pager[] GIT_DEFAULT_BRANCH:: The name of the first branch created in newly initialized repositories. +GIT_SHELL_PATH:: + The path of the binary providing the POSIX shell for commands which use the shell. + SEE ALSO -------- linkgit:git-commit-tree[1] diff --git a/builtin/var.c b/builtin/var.c index 10ee62f84c..bd340c5717 100644 --- a/builtin/var.c +++ b/builtin/var.c @@ -36,6 +36,11 @@ static const char *default_branch(int ident_flag UNUSED) return git_default_branch_name(1); } +static const char *shell_path(int ident_flag UNUSED) +{ + return SHELL_PATH; +} + struct git_var { const char *name; const char *(*read)(int); @@ -47,6 +52,7 @@ static struct git_var git_vars[] = { { "GIT_SEQUENCE_EDITOR", sequence_editor }, { "GIT_PAGER", pager }, { "GIT_DEFAULT_BRANCH", default_branch }, + { "GIT_SHELL_PATH", shell_path }, { "", NULL }, }; diff --git a/t/t0007-git-var.sh b/t/t0007-git-var.sh index eeb8539c1b..e35f07afcb 100755 --- a/t/t0007-git-var.sh +++ b/t/t0007-git-var.sh @@ -147,6 +147,21 @@ test_expect_success 'get GIT_SEQUENCE_EDITOR with configuration and environment ) ' +test_expect_success POSIXPERM 'GIT_SHELL_PATH points to a valid executable' ' + shellpath=$(git var GIT_SHELL_PATH) && + test_path_is_executable "$shellpath" +' + +# We know in this environment that our shell will be one of a few fixed values +# that all end in "sh". +test_expect_success MINGW 'GIT_SHELL_PATH points to a suitable shell' ' + shellpath=$(git var GIT_SHELL_PATH) && + case "$shellpath" in + *sh) ;; + *) return 1;; + esac +' + # For git var -l, we check only a representative variable; # testing the whole output would make our test too brittle with # respect to unrelated changes in the test suite's environment. From f74c90dcf7ed8ef7994ab583de089dba2a2b1a22 Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Tue, 27 Jun 2023 16:18:58 +0000 Subject: [PATCH 4/8] var: format variable structure with C99 initializers Right now, we have only two items in our variable struct. However, in the future, we're going to add two more items. To help keep our diffs nice and tidy and make this structure easier to read, switch to use C99-style initializers for our data. Signed-off-by: brian m. carlson Signed-off-by: Junio C Hamano --- builtin/var.c | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/builtin/var.c b/builtin/var.c index bd340c5717..379564a399 100644 --- a/builtin/var.c +++ b/builtin/var.c @@ -46,14 +46,38 @@ struct git_var { const char *(*read)(int); }; static struct git_var git_vars[] = { - { "GIT_COMMITTER_IDENT", git_committer_info }, - { "GIT_AUTHOR_IDENT", git_author_info }, - { "GIT_EDITOR", editor }, - { "GIT_SEQUENCE_EDITOR", sequence_editor }, - { "GIT_PAGER", pager }, - { "GIT_DEFAULT_BRANCH", default_branch }, - { "GIT_SHELL_PATH", shell_path }, - { "", NULL }, + { + .name = "GIT_COMMITTER_IDENT", + .read = git_committer_info, + }, + { + .name = "GIT_AUTHOR_IDENT", + .read = git_author_info, + }, + { + .name = "GIT_EDITOR", + .read = editor, + }, + { + .name = "GIT_SEQUENCE_EDITOR", + .read = sequence_editor, + }, + { + .name = "GIT_PAGER", + .read = pager, + }, + { + .name = "GIT_DEFAULT_BRANCH", + .read = default_branch, + }, + { + .name = "GIT_SHELL_PATH", + .read = shell_path, + }, + { + .name = "", + .read = NULL, + }, }; static void list_vars(void) From cdd489eaf9cd3c46c30b485601e2bcb989586274 Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Tue, 27 Jun 2023 16:18:59 +0000 Subject: [PATCH 5/8] var: adjust memory allocation for strings Right now, all of our values are constants whose allocation is managed elsewhere. However, in the future, we'll have some variables whose memory we will need to free. To keep things consistent, let's make each of our functions allocate its own memory and make the caller responsible for freeing it. Signed-off-by: brian m. carlson Signed-off-by: Junio C Hamano --- builtin/var.c | 45 +++++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/builtin/var.c b/builtin/var.c index 379564a399..d6f9f495c9 100644 --- a/builtin/var.c +++ b/builtin/var.c @@ -12,47 +12,57 @@ static const char var_usage[] = "git var (-l | )"; -static const char *editor(int ident_flag UNUSED) +static char *committer(int ident_flag) { - return git_editor(); + return xstrdup_or_null(git_committer_info(ident_flag)); } -static const char *sequence_editor(int ident_flag UNUSED) +static char *author(int ident_flag) { - return git_sequence_editor(); + return xstrdup_or_null(git_author_info(ident_flag)); } -static const char *pager(int ident_flag UNUSED) +static char *editor(int ident_flag UNUSED) +{ + return xstrdup_or_null(git_editor()); +} + +static char *sequence_editor(int ident_flag UNUSED) +{ + return xstrdup_or_null(git_sequence_editor()); +} + +static char *pager(int ident_flag UNUSED) { const char *pgm = git_pager(1); if (!pgm) pgm = "cat"; - return pgm; + return xstrdup(pgm); } -static const char *default_branch(int ident_flag UNUSED) +static char *default_branch(int ident_flag UNUSED) { - return git_default_branch_name(1); + return xstrdup_or_null(git_default_branch_name(1)); } -static const char *shell_path(int ident_flag UNUSED) +static char *shell_path(int ident_flag UNUSED) { - return SHELL_PATH; + return xstrdup(SHELL_PATH); } struct git_var { const char *name; - const char *(*read)(int); + char *(*read)(int); }; static struct git_var git_vars[] = { { .name = "GIT_COMMITTER_IDENT", - .read = git_committer_info, + .read = committer, }, { .name = "GIT_AUTHOR_IDENT", - .read = git_author_info, + .read = author, }, { .name = "GIT_EDITOR", @@ -83,11 +93,13 @@ static struct git_var git_vars[] = { static void list_vars(void) { struct git_var *ptr; - const char *val; + char *val; for (ptr = git_vars; ptr->read; ptr++) - if ((val = ptr->read(0))) + if ((val = ptr->read(0))) { printf("%s=%s\n", ptr->name, val); + free(val); + } } static const struct git_var *get_git_var(const char *var) @@ -113,7 +125,7 @@ static int show_config(const char *var, const char *value, void *cb) int cmd_var(int argc, const char **argv, const char *prefix UNUSED) { const struct git_var *git_var; - const char *val; + char *val; if (argc != 2) usage(var_usage); @@ -134,6 +146,7 @@ int cmd_var(int argc, const char **argv, const char *prefix UNUSED) return 1; printf("%s\n", val); + free(val); return 0; } From 15780bb4f0cb07624ca6bac3c430ef07e9501663 Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Tue, 27 Jun 2023 16:19:00 +0000 Subject: [PATCH 6/8] attr: expose and rename accessor functions Right now, the functions which determine the current system and global gitattributes files are not exposed. We'd like to use them in a future commit, but they're not ideally named. Rename them to something more suitable as a public interface, expose them, and document them. Signed-off-by: brian m. carlson Signed-off-by: Junio C Hamano --- attr.c | 14 +++++++------- attr.h | 9 +++++++++ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/attr.c b/attr.c index d45d34058d..66203ce322 100644 --- a/attr.c +++ b/attr.c @@ -870,7 +870,7 @@ static struct attr_stack *read_attr(struct index_state *istate, return res; } -static const char *git_etc_gitattributes(void) +const char *git_attr_system_file(void) { static const char *system_wide; if (!system_wide) @@ -878,7 +878,7 @@ static const char *git_etc_gitattributes(void) return system_wide; } -static const char *get_home_gitattributes(void) +const char *git_attr_global_file(void) { if (!git_attributes_file) git_attributes_file = xdg_config_home("attributes"); @@ -886,7 +886,7 @@ static const char *get_home_gitattributes(void) return git_attributes_file; } -static int git_attr_system(void) +int git_attr_system_is_enabled(void) { return !git_env_bool("GIT_ATTR_NOSYSTEM", 0); } @@ -920,14 +920,14 @@ static void bootstrap_attr_stack(struct index_state *istate, push_stack(stack, e, NULL, 0); /* system-wide frame */ - if (git_attr_system()) { - e = read_attr_from_file(git_etc_gitattributes(), flags); + if (git_attr_system_is_enabled()) { + e = read_attr_from_file(git_attr_system_file(), flags); push_stack(stack, e, NULL, 0); } /* home directory */ - if (get_home_gitattributes()) { - e = read_attr_from_file(get_home_gitattributes(), flags); + if (git_attr_global_file()) { + e = read_attr_from_file(git_attr_global_file(), flags); push_stack(stack, e, NULL, 0); } diff --git a/attr.h b/attr.h index 676bd17ce2..2b745df405 100644 --- a/attr.h +++ b/attr.h @@ -227,4 +227,13 @@ void git_attr_set_direction(enum git_attr_direction new_direction); void attr_start(void); +/* Return the system gitattributes file. */ +const char *git_attr_system_file(void); + +/* Return the global gitattributes file, if any. */ +const char *git_attr_global_file(void); + +/* Return whether the system gitattributes file is enabled and should be used. */ +int git_attr_system_is_enabled(void); + #endif /* ATTR_H */ From 576a37fccbf2a46d98a6dd367dbb3d1636e62f57 Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Tue, 27 Jun 2023 16:19:01 +0000 Subject: [PATCH 7/8] var: add attributes files locations Currently, there are some programs which would like to read and parse the gitattributes files at the global or system levels. However, it's not always obvious where these files live, especially for the system file, which may have been hard-coded at compile time or computed dynamically based on the runtime prefix. It's not reasonable to expect all callers of Git to intuitively know where the Git distributor or user has configured these locations to be, so add some entries to allow us to determine their location. Honor the GIT_ATTR_NOSYSTEM environment variable if one is specified. Expose the accessor functions in a way that we can reuse them from within the var code. In order to make our paths consistent on Windows and also use the same form as paths use in "git rev-parse", let's normalize the path before we return it. This results in Windows-style paths that use slashes, which is convenient for making our tests function in a consistent way across platforms. Note that this requires that some of our values be freed, so let's add a flag about whether the value needs to be freed and use it accordingly. Signed-off-by: brian m. carlson Signed-off-by: Junio C Hamano --- Documentation/git-var.txt | 6 ++++++ builtin/var.c | 29 +++++++++++++++++++++++++++++ t/t0007-git-var.sh | 20 ++++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/Documentation/git-var.txt b/Documentation/git-var.txt index f0f647e14a..dfbe5cb52b 100644 --- a/Documentation/git-var.txt +++ b/Documentation/git-var.txt @@ -74,6 +74,12 @@ GIT_DEFAULT_BRANCH:: GIT_SHELL_PATH:: The path of the binary providing the POSIX shell for commands which use the shell. +GIT_ATTR_SYSTEM:: + The path to the system linkgit:gitattributes[5] file, if one is enabled. + +GIT_ATTR_GLOBAL:: + The path to the global (per-user) linkgit:gitattributes[5] file. + SEE ALSO -------- linkgit:git-commit-tree[1] diff --git a/builtin/var.c b/builtin/var.c index d6f9f495c9..79f7bdf55f 100644 --- a/builtin/var.c +++ b/builtin/var.c @@ -4,6 +4,7 @@ * Copyright (C) Eric Biederman, 2005 */ #include "builtin.h" +#include "attr.h" #include "config.h" #include "editor.h" #include "ident.h" @@ -51,6 +52,26 @@ static char *shell_path(int ident_flag UNUSED) return xstrdup(SHELL_PATH); } +static char *git_attr_val_system(int ident_flag UNUSED) +{ + if (git_attr_system_is_enabled()) { + char *file = xstrdup(git_attr_system_file()); + normalize_path_copy(file, file); + return file; + } + return NULL; +} + +static char *git_attr_val_global(int ident_flag UNUSED) +{ + char *file = xstrdup(git_attr_global_file()); + if (file) { + normalize_path_copy(file, file); + return file; + } + return NULL; +} + struct git_var { const char *name; char *(*read)(int); @@ -84,6 +105,14 @@ static struct git_var git_vars[] = { .name = "GIT_SHELL_PATH", .read = shell_path, }, + { + .name = "GIT_ATTR_SYSTEM", + .read = git_attr_val_system, + }, + { + .name = "GIT_ATTR_GLOBAL", + .read = git_attr_val_global, + }, { .name = "", .read = NULL, diff --git a/t/t0007-git-var.sh b/t/t0007-git-var.sh index e35f07afcb..374d9f49e9 100755 --- a/t/t0007-git-var.sh +++ b/t/t0007-git-var.sh @@ -162,6 +162,26 @@ test_expect_success MINGW 'GIT_SHELL_PATH points to a suitable shell' ' esac ' +test_expect_success 'GIT_ATTR_SYSTEM produces expected output' ' + test_must_fail env GIT_ATTR_NOSYSTEM=1 git var GIT_ATTR_SYSTEM && + ( + sane_unset GIT_ATTR_NOSYSTEM && + systempath=$(git var GIT_ATTR_SYSTEM) && + test "$systempath" != "" + ) +' + +test_expect_success 'GIT_ATTR_GLOBAL points to the correct location' ' + TRASHDIR="$(test-tool path-utils normalize_path_copy "$(pwd)")" && + globalpath=$(XDG_CONFIG_HOME="$TRASHDIR/.config" git var GIT_ATTR_GLOBAL) && + test "$globalpath" = "$TRASHDIR/.config/git/attributes" && + ( + sane_unset XDG_CONFIG_HOME && + globalpath=$(HOME="$TRASHDIR" git var GIT_ATTR_GLOBAL) && + test "$globalpath" = "$TRASHDIR/.config/git/attributes" + ) +' + # For git var -l, we check only a representative variable; # testing the whole output would make our test too brittle with # respect to unrelated changes in the test suite's environment. From ed773a18c6e92ae4f4e016f4529d6bdfbbbd56d8 Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Tue, 27 Jun 2023 16:19:02 +0000 Subject: [PATCH 8/8] var: add config file locations Much like with attributes files, sometimes programs would like to know the location of configuration files at the global or system levels. However, it isn't always clear where these may live, especially for the system file, which may have been hard-coded at compile time or computed dynamically based on the runtime prefix. Since other parties cannot intuitively know how Git was compiled and where it looks for these files, help them by providing variables that can be queried. Because we have multiple paths for global config values, print them in order from highest to lowest priority, and be sure to split on newlines so that "git var -l" produces two entries for the global value. However, be careful not to split all values on newlines, since our editor values could well contain such characters, and we don't want to split them in such a case. Note in the documentation that some values may contain multiple paths and that callers should be prepared for that fact. This helps people write code that will continue to work in the event we allow multiple items elsewhere in the future. Signed-off-by: brian m. carlson Signed-off-by: Junio C Hamano --- Documentation/git-var.txt | 14 +++++++++ builtin/var.c | 57 +++++++++++++++++++++++++++++++++- t/t0007-git-var.sh | 65 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+), 1 deletion(-) diff --git a/Documentation/git-var.txt b/Documentation/git-var.txt index dfbe5cb52b..c38fb3968b 100644 --- a/Documentation/git-var.txt +++ b/Documentation/git-var.txt @@ -80,6 +80,20 @@ GIT_ATTR_SYSTEM:: GIT_ATTR_GLOBAL:: The path to the global (per-user) linkgit:gitattributes[5] file. +GIT_CONFIG_SYSTEM:: + The path to the system configuration file, if one is enabled. + +GIT_CONFIG_GLOBAL:: + The path to the global (per-user) configuration files, if any. + +Most path values contain only one value. However, some can contain multiple +values, which are separated by newlines, and are listed in order from highest to +lowest priority. Callers should be prepared for any such path value to contain +multiple items. + +Note that paths are printed even if they do not exist, but not if they are +disabled by other environment variables. + SEE ALSO -------- linkgit:git-commit-tree[1] diff --git a/builtin/var.c b/builtin/var.c index 79f7bdf55f..ef45710a20 100644 --- a/builtin/var.c +++ b/builtin/var.c @@ -72,9 +72,45 @@ static char *git_attr_val_global(int ident_flag UNUSED) return NULL; } +static char *git_config_val_system(int ident_flag UNUSED) +{ + if (git_config_system()) { + char *file = git_system_config(); + normalize_path_copy(file, file); + return file; + } + return NULL; +} + +static char *git_config_val_global(int ident_flag UNUSED) +{ + struct strbuf buf = STRBUF_INIT; + char *user, *xdg; + size_t unused; + + git_global_config(&user, &xdg); + if (xdg && *xdg) { + normalize_path_copy(xdg, xdg); + strbuf_addf(&buf, "%s\n", xdg); + } + if (user && *user) { + normalize_path_copy(user, user); + strbuf_addf(&buf, "%s\n", user); + } + free(xdg); + free(user); + strbuf_trim_trailing_newline(&buf); + if (buf.len == 0) { + strbuf_release(&buf); + return NULL; + } + return strbuf_detach(&buf, &unused); +} + struct git_var { const char *name; char *(*read)(int); + int multivalued; }; static struct git_var git_vars[] = { { @@ -113,6 +149,15 @@ static struct git_var git_vars[] = { .name = "GIT_ATTR_GLOBAL", .read = git_attr_val_global, }, + { + .name = "GIT_CONFIG_SYSTEM", + .read = git_config_val_system, + }, + { + .name = "GIT_CONFIG_GLOBAL", + .read = git_config_val_global, + .multivalued = 1, + }, { .name = "", .read = NULL, @@ -126,7 +171,17 @@ static void list_vars(void) for (ptr = git_vars; ptr->read; ptr++) if ((val = ptr->read(0))) { - printf("%s=%s\n", ptr->name, val); + if (ptr->multivalued && *val) { + struct string_list list = STRING_LIST_INIT_DUP; + int i; + + string_list_split(&list, val, '\n', -1); + for (i = 0; i < list.nr; i++) + printf("%s=%s\n", ptr->name, list.items[i].string); + string_list_clear(&list, 0); + } else { + printf("%s=%s\n", ptr->name, val); + } free(val); } } diff --git a/t/t0007-git-var.sh b/t/t0007-git-var.sh index 374d9f49e9..8cb597f99c 100755 --- a/t/t0007-git-var.sh +++ b/t/t0007-git-var.sh @@ -182,6 +182,49 @@ test_expect_success 'GIT_ATTR_GLOBAL points to the correct location' ' ) ' +test_expect_success 'GIT_CONFIG_SYSTEM points to the correct location' ' + TRASHDIR="$(test-tool path-utils normalize_path_copy "$(pwd)")" && + test_must_fail env GIT_CONFIG_NOSYSTEM=1 git var GIT_CONFIG_SYSTEM && + ( + sane_unset GIT_CONFIG_NOSYSTEM && + systempath=$(git var GIT_CONFIG_SYSTEM) && + test "$systempath" != "" && + systempath=$(GIT_CONFIG_SYSTEM=/dev/null git var GIT_CONFIG_SYSTEM) && + if test_have_prereq MINGW + then + test "$systempath" = "nul" + else + test "$systempath" = "/dev/null" + fi && + systempath=$(GIT_CONFIG_SYSTEM="$TRASHDIR/gitconfig" git var GIT_CONFIG_SYSTEM) && + test "$systempath" = "$TRASHDIR/gitconfig" + ) +' + +test_expect_success 'GIT_CONFIG_GLOBAL points to the correct location' ' + TRASHDIR="$(test-tool path-utils normalize_path_copy "$(pwd)")" && + HOME="$TRASHDIR" XDG_CONFIG_HOME="$TRASHDIR/foo" git var GIT_CONFIG_GLOBAL >actual && + echo "$TRASHDIR/foo/git/config" >expected && + echo "$TRASHDIR/.gitconfig" >>expected && + test_cmp expected actual && + ( + sane_unset XDG_CONFIG_HOME && + HOME="$TRASHDIR" git var GIT_CONFIG_GLOBAL >actual && + echo "$TRASHDIR/.config/git/config" >expected && + echo "$TRASHDIR/.gitconfig" >>expected && + test_cmp expected actual && + globalpath=$(GIT_CONFIG_GLOBAL=/dev/null git var GIT_CONFIG_GLOBAL) && + if test_have_prereq MINGW + then + test "$globalpath" = "nul" + else + test "$globalpath" = "/dev/null" + fi && + globalpath=$(GIT_CONFIG_GLOBAL="$TRASHDIR/gitconfig" git var GIT_CONFIG_GLOBAL) && + test "$globalpath" = "$TRASHDIR/gitconfig" + ) +' + # For git var -l, we check only a representative variable; # testing the whole output would make our test too brittle with # respect to unrelated changes in the test suite's environment. @@ -199,6 +242,28 @@ test_expect_success 'git var -l lists config' ' test_cmp expect actual.bare ' +test_expect_success 'git var -l lists multiple global configs' ' + TRASHDIR="$(test-tool path-utils normalize_path_copy "$(pwd)")" && + HOME="$TRASHDIR" XDG_CONFIG_HOME="$TRASHDIR/foo" git var -l >actual && + grep "^GIT_CONFIG_GLOBAL=" actual >filtered && + echo "GIT_CONFIG_GLOBAL=$TRASHDIR/foo/git/config" >expected && + echo "GIT_CONFIG_GLOBAL=$TRASHDIR/.gitconfig" >>expected && + test_cmp expected filtered +' + +test_expect_success 'git var -l does not split multiline editors' ' + ( + GIT_EDITOR="!f() { + echo Hello! + }; f" && + export GIT_EDITOR && + echo "GIT_EDITOR=$GIT_EDITOR" >expected && + git var -l >var && + sed -n -e "/^GIT_EDITOR/,\$p" var | head -n 3 >actual && + test_cmp expected actual + ) +' + test_expect_success 'listing and asking for variables are exclusive' ' test_must_fail git var -l GIT_COMMITTER_IDENT '