Files
Junio C Hamano 2526487566 Merge branch 'ic/includeif-hostname'
The conditional configuration inclusion mechanism via 'includeIf'
has been extended to support matching the machine's hostname, and
the system's hostname as seen by Git can now be queried using 'git
var GIT_HOSTNAME'.

* ic/includeif-hostname:
  config: learn the "hostname:" includeIf condition
  t6500: get hostname from "git var"
  var: add GIT_HOSTNAME
2026-10-26 07:28:01 -07:00

404 lines
7.8 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 "parse-options.h"
#include "path.h"
#include "refs.h"
#include "run-command.h"
#include "strbuf.h"
#include "string-list.h"
static const char * const var_usage[] = {
N_("git var [-z] -l"),
N_("git var [-z] <variable>..."),
NULL
};
enum ident_part {
IDENT_NAME,
IDENT_MAIL,
IDENT_DATE,
};
static char *ident_part(const char *ident, enum ident_part part)
{
struct ident_split split;
if (!ident)
return NULL;
if (split_ident_line(&split, ident, strlen(ident)))
return NULL;
switch (part) {
case IDENT_NAME:
if (!split.name_begin || !split.name_end)
BUG("split_ident_line() gave NULL names???");
return xmemdupz(split.name_begin,
split.name_end - split.name_begin);
case IDENT_MAIL:
if (!split.mail_begin || !split.mail_end)
BUG("split_ident_line() gave NULL mail???");
return xmemdupz(split.mail_begin,
split.mail_end - split.mail_begin);
case IDENT_DATE:
if (!split.date_begin || !split.tz_end)
BUG("split_ident_line() gave NULL date/tz???");
return xmemdupz(split.date_begin,
split.tz_end - split.date_begin);
default:
BUG("unknown ident_part %d", part);
}
}
static char *committer(int ident_flag)
{
return xstrdup_or_null(git_committer_info(ident_flag));
}
static char *committer_name(int ident_flag)
{
return ident_part(git_committer_info(ident_flag), IDENT_NAME);
}
static char *committer_email(int ident_flag)
{
return ident_part(git_committer_info(ident_flag), IDENT_MAIL);
}
static char *committer_date(int ident_flag)
{
return ident_part(git_committer_info(ident_flag), IDENT_DATE);
}
static char *author(int ident_flag)
{
return xstrdup_or_null(git_author_info(ident_flag));
}
static char *author_name(int ident_flag)
{
return ident_part(git_author_info(ident_flag), IDENT_NAME);
}
static char *author_email(int ident_flag)
{
return ident_part(git_author_info(ident_flag), IDENT_MAIL);
}
static char *author_date(int ident_flag)
{
return ident_part(git_author_info(ident_flag), IDENT_DATE);
}
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(git_attr_global_file());
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 void git_config_val_global(struct string_list *list)
{
char *user, *xdg;
git_global_config_paths(&user, &xdg);
if (xdg && *xdg) {
normalize_path_copy(xdg, xdg);
string_list_append(list, xdg);
}
if (user && *user) {
normalize_path_copy(user, user);
string_list_append(list, user);
}
free(xdg);
free(user);
}
static char *hostname(int ident_flag UNUSED)
{
char buf[HOST_NAME_MAX + 1];
if (xgethostname(buf, sizeof(buf)))
return NULL;
return xstrdup(buf);
}
struct git_var {
const char *name;
char *(*read)(int);
void (*multiread)(struct string_list *);
};
static struct git_var git_vars[] = {
{
.name = "GIT_COMMITTER_IDENT",
.read = committer,
},
{
.name = "GIT_COMMITTER_NAME",
.read = committer_name,
},
{
.name = "GIT_COMMITTER_EMAIL",
.read = committer_email,
},
{
.name = "GIT_COMMITTER_DATE",
.read = committer_date,
},
{
.name = "GIT_AUTHOR_IDENT",
.read = author,
},
{
.name = "GIT_AUTHOR_NAME",
.read = author_name,
},
{
.name = "GIT_AUTHOR_EMAIL",
.read = author_email,
},
{
.name = "GIT_AUTHOR_DATE",
.read = author_date,
},
{
.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",
.multiread = git_config_val_global,
},
{
.name = "GIT_HOSTNAME",
.read = hostname,
},
{
.name = "",
.read = NULL,
},
};
static void list_vars(int nul_term)
{
struct git_var *ptr;
char delim = nul_term ? '\n' : '=';
char term = nul_term ? '\0' : '\n';
for (ptr = git_vars; ptr->read || ptr->multiread; ptr++) {
if (ptr->read) {
char *val = ptr->read(0);
if (val) {
printf("%s%c%s%c", ptr->name, delim, val, term);
free(val);
}
} else {
struct string_list list = STRING_LIST_INIT_DUP;
ptr->multiread(&list);
for (size_t i = 0; i < list.nr; i++)
printf("%s%c%s%c", ptr->name, delim,
list.items[i].string, term);
string_list_clear(&list, 0);
}
}
}
static const struct git_var *get_git_var(const char *var)
{
struct git_var *ptr;
for (ptr = git_vars; ptr->read || ptr->multiread; 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)
{
int *nul_term = cb;
char delim = *nul_term ? '\n' : '=';
char term = *nul_term ? '\0' : '\n';
if (value)
printf("%s%c%s%c", var, delim, value, term);
else
printf("%s%c", var, term);
return git_default_config(var, value, ctx, cb);
}
int cmd_var(int argc,
const char **argv,
const char *prefix,
struct repository *repo UNUSED)
{
int list = 0;
int nul_term = 0;
char delim;
char term;
struct option options[] = {
OPT_BOOL('l', NULL, &list,
N_("list all variables")),
OPT_BOOL('z', NULL, &nul_term,
N_("terminate entries with NUL")),
OPT_END(),
};
argc = parse_options(argc, argv, prefix, options,
var_usage, PARSE_OPT_STOP_AT_NON_OPTION);
if (list) {
if (argc)
usage_with_options(var_usage, options);
repo_config(the_repository, show_config, &nul_term);
list_vars(nul_term);
return 0;
}
if (!argc)
usage_with_options(var_usage, options);
repo_config(the_repository, git_default_config, NULL);
delim = nul_term ? '\n' : '=';
term = nul_term ? '\0' : '\n';
for (int i = 0; i < argc; i++) {
const struct git_var *git_var = get_git_var(argv[i]);
if (!git_var)
usage_with_options(var_usage, options);
if (git_var->read) {
char *val = git_var->read(IDENT_STRICT);
if (!val) {
if (argc == 1)
return 1;
continue;
}
if (argc == 1)
printf("%s%c", val, term);
else
printf("%s%c%s%c", git_var->name, delim,
val, term);
free(val);
} else {
struct string_list list = STRING_LIST_INIT_DUP;
git_var->multiread(&list);
if (argc == 1 && !list.nr) {
string_list_clear(&list, 0);
return 1;
}
for (size_t j = 0; j < list.nr; j++) {
if (argc == 1)
printf("%s%c", list.items[j].string,
term);
else
printf("%s%c%s%c", git_var->name, delim,
list.items[j].string, term);
}
string_list_clear(&list, 0);
}
}
return 0;
}