git/builtin/var.c
Olamide Caleb Bello 32fadb3779 environment: move "core.attributesFile" into repo-setting
When handling multiple repositories within the same process, relying on
global state for accessing the "core.attributesFile" configuration can
lead to incorrect values being used. It also makes it harder to isolate
repositories and hinders the libification of git.
The functions `bootstrap_attr_stack()` and `git_attr_val_system()`
retrieve "core.attributesFile" via `git_attr_global_file()`
which reads from global state `git_attributes_file`.

Move the "core.attributesFile" configuration into the
`struct repo_settings` instead of relying on the global state.
A new function `repo_settings_get_attributesfile_path()` is added
and used to retrieve this setting in a repository-scoped manner.
The functions to retrieve "core.attributesFile" are replaced with
the new accessor function `repo_settings_get_attributesfile_path()`
This improves multi-repository behaviour and aligns with the goal of
libifying of Git.

Note that in `bootstrap_attr_stack()`, the `index_state` is used only
if it exists, else we default to `the_repository`.

Based-on-patch-by: Ayush Chandekar <ayu.chandekar@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-04 15:05:10 +09:00

249 lines
4.5 KiB
C

/*
* GIT - The information manager from hell
*
* Copyright (C) Eric Biederman, 2005
*/
#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "attr.h"
#include "config.h"
#include "editor.h"
#include "environment.h"
#include "ident.h"
#include "pager.h"
#include "refs.h"
#include "path.h"
#include "strbuf.h"
#include "run-command.h"
static const char var_usage[] = "git var (-l | <variable>)";
static char *committer(int ident_flag)
{
return xstrdup_or_null(git_committer_info(ident_flag));
}
static char *author(int ident_flag)
{
return xstrdup_or_null(git_author_info(ident_flag));
}
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(the_repository, 1);
if (!pgm)
pgm = "cat";
return xstrdup(pgm);
}
static char *default_branch(int ident_flag UNUSED)
{
return repo_default_branch_name(the_repository, 1);
}
static char *shell_path(int ident_flag UNUSED)
{
return git_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_or_null(repo_settings_get_attributesfile_path(the_repository));
if (file) {
normalize_path_copy(file, file);
return file;
}
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_paths(&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[] = {
{
.name = "GIT_COMMITTER_IDENT",
.read = committer,
},
{
.name = "GIT_AUTHOR_IDENT",
.read = author,
},
{
.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 = "GIT_ATTR_SYSTEM",
.read = git_attr_val_system,
},
{
.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,
},
};
static void list_vars(void)
{
struct git_var *ptr;
char *val;
for (ptr = git_vars; ptr->read; ptr++)
if ((val = ptr->read(0))) {
if (ptr->multivalued && *val) {
struct string_list list = STRING_LIST_INIT_DUP;
string_list_split(&list, val, "\n", -1);
for (size_t 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);
}
}
static const struct git_var *get_git_var(const char *var)
{
struct git_var *ptr;
for (ptr = git_vars; ptr->read; ptr++) {
if (strcmp(var, ptr->name) == 0) {
return ptr;
}
}
return NULL;
}
static int show_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
if (value)
printf("%s=%s\n", var, value);
else
printf("%s\n", var);
return git_default_config(var, value, ctx, cb);
}
int cmd_var(int argc,
const char **argv,
const char *prefix UNUSED,
struct repository *repo UNUSED)
{
const struct git_var *git_var;
char *val;
show_usage_if_asked(argc, argv, var_usage);
if (argc != 2)
usage(var_usage);
if (strcmp(argv[1], "-l") == 0) {
repo_config(the_repository, show_config, NULL);
list_vars();
return 0;
}
repo_config(the_repository, git_default_config, NULL);
git_var = get_git_var(argv[1]);
if (!git_var)
usage(var_usage);
val = git_var->read(IDENT_STRICT);
if (!val)
return 1;
printf("%s\n", val);
free(val);
return 0;
}