threads / patch / 65022

patch, 2 partsmailmap: reduce global state

Subject: [GSOC PATCH 0/2] mailmap: reduce global state

## tl;dr

9 messages between Feb 19, 2026 and Feb 20, 2026. Diffs are folded; open one to read it.

replies: 8people: 2as markdown or json

Burak Kaan Karaçay· Feb 19, 2026, 12:59 UTC · lore
Hi,

I am an applicant for GSoC 2026, aiming for the "Refactoring in order to reduce Git's global state" project. I have already submitted my microproject, so please treat this series simply as an extra familiarization exercise to better understand the codebase and the goals of the project.

The project description mainly focuses on 'environment.c' but I noticed that an Outreachy intern is currently working in that area. To avoid stepping on anyone's toes or duplicating work, I decided to look for other subsystems and chose 'mailmap.c', which currently relies on 'the_repository' and global configuration variables.

This patch series aims to reduce the global variable dependency of the mailmap subsystem:

  - Patch 1 eliminates the implicit 'the_repository' dependency in the
    'read_mailmap' and 'read_mailmap_blob' functions by adding a
    'struct repository' parameter.
  - Patch 2 removes the 'git_mailmap_file' and 'git_mailmap_blob' global
    variables, shifting to on-demand configuration reading via the config
    set helpers and using local variables.
Thanks.
Burak Kaan Karaçay (2):
  mailmap: stop using the_repository
  mailmap: drop global config variables
 builtin/blame.c         |  2 +-
 builtin/cat-file.c      |  2 +-
 builtin/check-mailmap.c |  4 ++--
 builtin/commit.c        |  2 +-
 builtin/log.c           |  2 +-
 builtin/shortlog.c      |  2 +-
 environment.c           | 19 -------------------
 mailmap.c               | 30 +++++++++++++++++++-----------
 mailmap.h               |  8 +++-----
 pretty.c                |  2 +-
 ref-filter.c            |  2 +-
 11 files changed, 31 insertions(+), 44 deletions(-)
-- 
2.52.0
Burak Kaan Karaçay· Feb 19, 2026, 12:59 UTC · re: Burak Kaan Karaçay · lore

[GSOC PATCH 1/2] mailmap: stop using the_repository

The 'read_mailmap' and 'read_mailmap_blob' functions rely on the global 'the_repository' variable. Update both functions to accept a 'struct repository' parameter.

Update all callers to pass 'the_repository' to retain the current behavior.

Signed-off-by: Burak Kaan Karaçay <bkkaracay@gmail.com>
---
 builtin/blame.c         |  2 +-
 builtin/cat-file.c      |  2 +-
 builtin/check-mailmap.c |  4 ++--
 builtin/commit.c        |  2 +-
 builtin/log.c           |  2 +-
 builtin/shortlog.c      |  2 +-
 mailmap.c               | 11 ++++++-----
 mailmap.h               |  5 +++--
 pretty.c                |  2 +-
 ref-filter.c            |  2 +-
 10 files changed, 18 insertions(+), 16 deletions(-)
Show changes to 10 files +18 −16

builtin/blame.c, builtin/cat-file.c, builtin/check-mailmap.c, builtin/commit.c, builtin/log.c, builtin/shortlog.c, mailmap.c, mailmap.h, pretty.c, ref-filter.c

diff --git a/builtin/blame.c b/builtin/blame.c
index eac2fe7320..f3a11eff44 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -1252,7 +1252,7 @@ int cmd_blame(int argc,
 	sb.xdl_opts = xdl_opts;
 	sb.no_whole_file_rename = no_whole_file_rename;
 
-	read_mailmap(&mailmap);
+	read_mailmap(the_repository, &mailmap);
 
 	sb.found_guilty_entry = &found_guilty_entry;
 	sb.found_guilty_entry_data = &pi;
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index df8e87a81f..d298e95797 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -1105,7 +1105,7 @@ int cmd_cat_file(int argc,
 	opt_epts = (opt == 'e' || opt == 'p' || opt == 't' || opt == 's');
 
 	if (use_mailmap)
-		read_mailmap(&mailmap);
+		read_mailmap(the_repository, &mailmap);
 
 	switch (batch.objects_filter.choice) {
 	case LOFC_DISABLED:
diff --git a/builtin/check-mailmap.c b/builtin/check-mailmap.c
index 9cc5c59830..3f2a39cae0 100644
--- a/builtin/check-mailmap.c
+++ b/builtin/check-mailmap.c
@@ -63,9 +63,9 @@ int cmd_check_mailmap(int argc,
 	if (argc == 0 && !use_stdin)
 		die(_("no contacts specified"));
 
-	read_mailmap(&mailmap);
+	read_mailmap(the_repository, &mailmap);
 	if (mailmap_blob)
-		read_mailmap_blob(&mailmap, mailmap_blob);
+		read_mailmap_blob(the_repository, &mailmap, mailmap_blob);
 	if (mailmap_file)
 		read_mailmap_file(&mailmap, mailmap_file, 0);
 
diff --git a/builtin/commit.c b/builtin/commit.c
index 9e3a09d532..3700f66ba9 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1155,7 +1155,7 @@ static const char *find_author_by_nickname(const char *name)
 	setup_revisions(ac, av, &revs, NULL);
 	revs.mailmap = xmalloc(sizeof(struct string_list));
 	string_list_init_nodup(revs.mailmap);
-	read_mailmap(revs.mailmap);
+	read_mailmap(the_repository, revs.mailmap);
 
 	if (prepare_revision_walk(&revs))
 		die(_("revision walk setup failed"));
diff --git a/builtin/log.c b/builtin/log.c
index 8ab6d3a943..ff0227e32d 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -336,7 +336,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
 	if (mailmap) {
 		rev->mailmap = xmalloc(sizeof(struct string_list));
 		string_list_init_nodup(rev->mailmap);
-		read_mailmap(rev->mailmap);
+		read_mailmap(the_repository, rev->mailmap);
 	}
 
 	if (rev->pretty_given && rev->commit_format == CMIT_FMT_RAW) {
diff --git a/builtin/shortlog.c b/builtin/shortlog.c
index d80bf1a7d0..6b2a0b93b5 100644
--- a/builtin/shortlog.c
+++ b/builtin/shortlog.c
@@ -357,7 +357,7 @@ void shortlog_init(struct shortlog *log)
 {
 	memset(log, 0, sizeof(*log));
 
-	read_mailmap(&log->mailmap);
+	read_mailmap(the_repository, &log->mailmap);
 
 	log->list.strdup_strings = 1;
 	log->wrap = DEFAULT_WRAPLEN;
diff --git a/mailmap.c b/mailmap.c
index 37fd158a51..6628975f30 100644
--- a/mailmap.c
+++ b/mailmap.c
@@ -183,7 +183,8 @@ static void read_mailmap_string(struct string_list *map, char *buf)
 	}
 }
 
-int read_mailmap_blob(struct string_list *map, const char *name)
+int read_mailmap_blob(struct repository *repo, struct string_list *map,
+                      const char *name)
 {
 	struct object_id oid;
 	char *buf;
@@ -192,10 +193,10 @@ int read_mailmap_blob(struct string_list *map, const char *name)
 
 	if (!name)
 		return 0;
-	if (repo_get_oid(the_repository, name, &oid) < 0)
+	if (repo_get_oid(repo, name, &oid) < 0)
 		return 0;
 
-	buf = odb_read_object(the_repository->objects, &oid, &type, &size);
+	buf = odb_read_object(repo->objects, &oid, &type, &size);
 	if (!buf)
 		return error("unable to read mailmap object at %s", name);
 	if (type != OBJ_BLOB) {
@@ -209,7 +210,7 @@ int read_mailmap_blob(struct string_list *map, const char *name)
 	return 0;
 }
 
-int read_mailmap(struct string_list *map)
+int read_mailmap(struct repository *repo, struct string_list *map)
 {
 	int err = 0;
 
@@ -224,7 +225,7 @@ int read_mailmap(struct string_list *map)
 					 startup_info->have_repository ?
 					 MAILMAP_NOFOLLOW : 0);
 	if (startup_info->have_repository)
-		err |= read_mailmap_blob(map, git_mailmap_blob);
+		err |= read_mailmap_blob(repo, map, git_mailmap_blob);
 	err |= read_mailmap_file(map, git_mailmap_file, 0);
 	return err;
 }
diff --git a/mailmap.h b/mailmap.h
index 908365e1bf..11346835cb 100644
--- a/mailmap.h
+++ b/mailmap.h
@@ -11,9 +11,10 @@ extern char *git_mailmap_blob;
 
 int read_mailmap_file(struct string_list *map, const char *filename,
 		      unsigned flags);
-int read_mailmap_blob(struct string_list *map, const char *name);
+int read_mailmap_blob(struct repository *repo, struct string_list *map,
+                      const char *name);
 
-int read_mailmap(struct string_list *map);
+int read_mailmap(struct repository *repo, struct string_list *map);
 void clear_mailmap(struct string_list *map);
 
 int map_user(struct string_list *map,
diff --git a/pretty.c b/pretty.c
index e0646bbc5d..ebf4da4834 100644
--- a/pretty.c
+++ b/pretty.c
@@ -781,7 +781,7 @@ static int mailmap_name(const char **email, size_t *email_len,
 	static struct string_list *mail_map;
 	if (!mail_map) {
 		CALLOC_ARRAY(mail_map, 1);
-		read_mailmap(mail_map);
+		read_mailmap(the_repository, mail_map);
 	}
 	return mail_map->nr && map_user(mail_map, email, email_len, name, name_len);
 }
diff --git a/ref-filter.c b/ref-filter.c
index 3917c4ccd9..d7a23a7b61 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1753,7 +1753,7 @@ static void grab_person(const char *who, struct atom_value *val, int deref, void
 		    (starts_with(name + wholen, "email") &&
 		    (atom->u.email_option.option & EO_MAILMAP))) {
 			if (!mailmap.items)
-				read_mailmap(&mailmap);
+				read_mailmap(the_repository, &mailmap);
 			strbuf_addstr(&mailmap_buf, buf);
 			apply_mailmap_to_header(&mailmap_buf, headers, &mailmap);
 			wholine = find_wholine(who, wholen, mailmap_buf.buf);
-- 
2.52.0
Burak Kaan Karaçay· Feb 19, 2026, 12:59 UTC · re: Burak Kaan Karaçay · lore

[GSOC PATCH 2/2] mailmap: drop global config variables

The 'mailmap.file' and 'mailmap.blob' configurations are currently parsed and stored in the global variables 'git_mailmap_file' and 'git_mailmap_blob'. Since these values are typically only needed once when initializing a mailmap, there is no need to keep them as global state throughout the lifetime of the Git process.

To reduce global state, remove these global variables and instead use 'repo_config_get_*' functions to read the configuration on demand.

Signed-off-by: Burak Kaan Karaçay <bkkaracay@gmail.com>
---
 environment.c | 19 -------------------
 mailmap.c     | 21 ++++++++++++++-------
 mailmap.h     |  3 ---
 3 files changed, 14 insertions(+), 29 deletions(-)
Show changes to 3 files +14 −29

environment.c, mailmap.c, mailmap.h

diff --git a/environment.c b/environment.c
index 0026eb2274..2764d8f481 100644
--- a/environment.c
+++ b/environment.c
@@ -647,22 +647,6 @@ static int git_default_push_config(const char *var, const char *value)
 	return 0;
 }
 
-static int git_default_mailmap_config(const char *var, const char *value)
-{
-	if (!strcmp(var, "mailmap.file")) {
-		FREE_AND_NULL(git_mailmap_file);
-		return git_config_pathname(&git_mailmap_file, var, value);
-	}
-
-	if (!strcmp(var, "mailmap.blob")) {
-		FREE_AND_NULL(git_mailmap_blob);
-		return git_config_string(&git_mailmap_blob, var, value);
-	}
-
-	/* Add other config variables here and to Documentation/config.adoc. */
-	return 0;
-}
-
 static int git_default_attr_config(const char *var, const char *value)
 {
 	if (!strcmp(var, "attr.tree")) {
@@ -697,9 +681,6 @@ int git_default_config(const char *var, const char *value,
 	if (starts_with(var, "push."))
 		return git_default_push_config(var, value);
 
-	if (starts_with(var, "mailmap."))
-		return git_default_mailmap_config(var, value);
-
 	if (starts_with(var, "attr."))
 		return git_default_attr_config(var, value);
 
diff --git a/mailmap.c b/mailmap.c
index 6628975f30..cdae3f65bc 100644
--- a/mailmap.c
+++ b/mailmap.c
@@ -7,9 +7,7 @@
 #include "object-name.h"
 #include "odb.h"
 #include "setup.h"
-
-char *git_mailmap_file;
-char *git_mailmap_blob;
+#include "config.h"
 
 struct mailmap_info {
 	char *name;
@@ -213,20 +211,29 @@ int read_mailmap_blob(struct repository *repo, struct string_list *map,
 int read_mailmap(struct repository *repo, struct string_list *map)
 {
 	int err = 0;
+	char *mailmap_file = NULL, *mailmap_blob = NULL;
+
+	repo_config_get_pathname(repo, "mailmap.file", &mailmap_file);
+	repo_config_get_string(repo, "mailmap.blob", &mailmap_blob);
 
 	map->strdup_strings = 1;
 	map->cmp = namemap_cmp;
 
-	if (!git_mailmap_blob && is_bare_repository())
-		git_mailmap_blob = xstrdup("HEAD:.mailmap");
+	if (!mailmap_blob && is_bare_repository())
+		mailmap_blob = xstrdup("HEAD:.mailmap");
 
 	if (!startup_info->have_repository || !is_bare_repository())
 		err |= read_mailmap_file(map, ".mailmap",
 					 startup_info->have_repository ?
 					 MAILMAP_NOFOLLOW : 0);
 	if (startup_info->have_repository)
-		err |= read_mailmap_blob(repo, map, git_mailmap_blob);
-	err |= read_mailmap_file(map, git_mailmap_file, 0);
+		err |= read_mailmap_blob(repo, map, mailmap_blob);
+	
+	err |= read_mailmap_file(map, mailmap_file, 0);
+
+	free(mailmap_file);
+	free(mailmap_blob);
+
 	return err;
 }
 
diff --git a/mailmap.h b/mailmap.h
index 11346835cb..36d5d10daf 100644
--- a/mailmap.h
+++ b/mailmap.h
@@ -3,9 +3,6 @@
 
 struct string_list;
 
-extern char *git_mailmap_file;
-extern char *git_mailmap_blob;
-
 /* Flags for read_mailmap_file() */
 #define MAILMAP_NOFOLLOW (1<<0)
 
-- 
2.52.0
Junio C Hamano· Feb 19, 2026, 21:22 UTC · re: Burak Kaan Karaçay · lore

Re: [GSOC PATCH 0/2] mailmap: reduce global state

Burak Kaan Karaçay <bkkaracay@gmail.com> writes:
Show 10 quoted lines
> This patch series aims to reduce the global variable dependency of the
> mailmap subsystem:
>
>   - Patch 1 eliminates the implicit 'the_repository' dependency in the
>     'read_mailmap' and 'read_mailmap_blob' functions by adding a
>     'struct repository' parameter.
>
>   - Patch 2 removes the 'git_mailmap_file' and 'git_mailmap_blob' global
>     variables, shifting to on-demand configuration reading via the config
>     set helpers and using local variables.

These are surprisingly simple and straight-forward, as the final destination has nothing to do with any global, and not even part of a long-lived structure like "repo", but just a simple string_list mailmap. Nicely done.

Will queue.
Junio C Hamano· Feb 19, 2026, 22:50 UTC · re: Junio C Hamano · lore

Re: [GSOC PATCH 0/2] mailmap: reduce global state

Junio C Hamano <gitster@pobox.com> writes:
Show 19 quoted lines
> Burak Kaan Karaçay <bkkaracay@gmail.com> writes:
>
>> This patch series aims to reduce the global variable dependency of the
>> mailmap subsystem:
>>
>>   - Patch 1 eliminates the implicit 'the_repository' dependency in the
>>     'read_mailmap' and 'read_mailmap_blob' functions by adding a
>>     'struct repository' parameter.
>>
>>   - Patch 2 removes the 'git_mailmap_file' and 'git_mailmap_blob' global
>>     variables, shifting to on-demand configuration reading via the config
>>     set helpers and using local variables.
>
> These are surprisingly simple and straight-forward, as the final
> destination has nothing to do with any global, and not even part of
> a long-lived structure like "repo", but just a simple string_list
> mailmap.  Nicely done.
>
> Will queue.
Oops, not so fast.  "make hdr-check" catches a problem in this topic.
    mailmap.h:11:30: error: 'struct repository' declared inside parameter list will not be visible outside of this definition or
    declaration [-Werror]
Burak Kaan Karaçay· Feb 20, 2026, 06:04 UTC · re: Burak Kaan Karaçay · lore

[GSOC PATCH v2 0/2] mailmap: reduce global state

Hi,

This patch series aims to reduce the global variable dependency of the mailmap subsystem:

  - Patch 1 eliminates the implicit 'the_repository' dependency in the
    'read_mailmap' and 'read_mailmap_blob' functions by adding a
    'struct repository' parameter.
  - Patch 2 removes the 'git_mailmap_file' and 'git_mailmap_blob' global
    variables, shifting to on-demand configuration reading via the config
    set helpers and using local variables.
    
Changes in v2:
  - Forward declare 'struct repository' in mailmap.h
  - Fix whitespace problems
Thanks to Junio for the kind words and for catching the 'make hdr-check' issue.
Burak Kaan Karaçay (2):
  mailmap: stop using the_repository
  mailmap: drop global config variables
 builtin/blame.c         |  2 +-
 builtin/cat-file.c      |  2 +-
 builtin/check-mailmap.c |  4 ++--
 builtin/commit.c        |  2 +-
 builtin/log.c           |  2 +-
 builtin/shortlog.c      |  2 +-
 environment.c           | 19 -------------------
 mailmap.c               | 30 +++++++++++++++++++-----------
 mailmap.h               |  9 ++++-----
 pretty.c                |  2 +-
 ref-filter.c            |  2 +-
 11 files changed, 32 insertions(+), 44 deletions(-)
-- 
2.52.0
Burak Kaan Karaçay· Feb 20, 2026, 06:04 UTC · re: Burak Kaan Karaçay · lore

[GSOC PATCH v2 1/2] mailmap: stop using the_repository

The 'read_mailmap' and 'read_mailmap_blob' functions rely on the global 'the_repository' variable. Update both functions to accept a 'struct repository' parameter.

Update all callers to pass 'the_repository' to retain the current behavior.

Signed-off-by: Burak Kaan Karaçay <bkkaracay@gmail.com>
---
 builtin/blame.c         |  2 +-
 builtin/cat-file.c      |  2 +-
 builtin/check-mailmap.c |  4 ++--
 builtin/commit.c        |  2 +-
 builtin/log.c           |  2 +-
 builtin/shortlog.c      |  2 +-
 mailmap.c               | 11 ++++++-----
 mailmap.h               |  6 ++++--
 pretty.c                |  2 +-
 ref-filter.c            |  2 +-
 10 files changed, 19 insertions(+), 16 deletions(-)
Show changes to 10 files +19 −16

builtin/blame.c, builtin/cat-file.c, builtin/check-mailmap.c, builtin/commit.c, builtin/log.c, builtin/shortlog.c, mailmap.c, mailmap.h, pretty.c, ref-filter.c

diff --git a/builtin/blame.c b/builtin/blame.c
index eac2fe7320..f3a11eff44 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -1252,7 +1252,7 @@ int cmd_blame(int argc,
 	sb.xdl_opts = xdl_opts;
 	sb.no_whole_file_rename = no_whole_file_rename;
 
-	read_mailmap(&mailmap);
+	read_mailmap(the_repository, &mailmap);
 
 	sb.found_guilty_entry = &found_guilty_entry;
 	sb.found_guilty_entry_data = &pi;
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index df8e87a81f..d298e95797 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -1105,7 +1105,7 @@ int cmd_cat_file(int argc,
 	opt_epts = (opt == 'e' || opt == 'p' || opt == 't' || opt == 's');
 
 	if (use_mailmap)
-		read_mailmap(&mailmap);
+		read_mailmap(the_repository, &mailmap);
 
 	switch (batch.objects_filter.choice) {
 	case LOFC_DISABLED:
diff --git a/builtin/check-mailmap.c b/builtin/check-mailmap.c
index 9cc5c59830..3f2a39cae0 100644
--- a/builtin/check-mailmap.c
+++ b/builtin/check-mailmap.c
@@ -63,9 +63,9 @@ int cmd_check_mailmap(int argc,
 	if (argc == 0 && !use_stdin)
 		die(_("no contacts specified"));
 
-	read_mailmap(&mailmap);
+	read_mailmap(the_repository, &mailmap);
 	if (mailmap_blob)
-		read_mailmap_blob(&mailmap, mailmap_blob);
+		read_mailmap_blob(the_repository, &mailmap, mailmap_blob);
 	if (mailmap_file)
 		read_mailmap_file(&mailmap, mailmap_file, 0);
 
diff --git a/builtin/commit.c b/builtin/commit.c
index 9e3a09d532..3700f66ba9 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1155,7 +1155,7 @@ static const char *find_author_by_nickname(const char *name)
 	setup_revisions(ac, av, &revs, NULL);
 	revs.mailmap = xmalloc(sizeof(struct string_list));
 	string_list_init_nodup(revs.mailmap);
-	read_mailmap(revs.mailmap);
+	read_mailmap(the_repository, revs.mailmap);
 
 	if (prepare_revision_walk(&revs))
 		die(_("revision walk setup failed"));
diff --git a/builtin/log.c b/builtin/log.c
index 8ab6d3a943..ff0227e32d 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -336,7 +336,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
 	if (mailmap) {
 		rev->mailmap = xmalloc(sizeof(struct string_list));
 		string_list_init_nodup(rev->mailmap);
-		read_mailmap(rev->mailmap);
+		read_mailmap(the_repository, rev->mailmap);
 	}
 
 	if (rev->pretty_given && rev->commit_format == CMIT_FMT_RAW) {
diff --git a/builtin/shortlog.c b/builtin/shortlog.c
index d80bf1a7d0..6b2a0b93b5 100644
--- a/builtin/shortlog.c
+++ b/builtin/shortlog.c
@@ -357,7 +357,7 @@ void shortlog_init(struct shortlog *log)
 {
 	memset(log, 0, sizeof(*log));
 
-	read_mailmap(&log->mailmap);
+	read_mailmap(the_repository, &log->mailmap);
 
 	log->list.strdup_strings = 1;
 	log->wrap = DEFAULT_WRAPLEN;
diff --git a/mailmap.c b/mailmap.c
index 37fd158a51..cf70956675 100644
--- a/mailmap.c
+++ b/mailmap.c
@@ -183,7 +183,8 @@ static void read_mailmap_string(struct string_list *map, char *buf)
 	}
 }
 
-int read_mailmap_blob(struct string_list *map, const char *name)
+int read_mailmap_blob(struct repository *repo, struct string_list *map,
+		      const char *name)
 {
 	struct object_id oid;
 	char *buf;
@@ -192,10 +193,10 @@ int read_mailmap_blob(struct string_list *map, const char *name)
 
 	if (!name)
 		return 0;
-	if (repo_get_oid(the_repository, name, &oid) < 0)
+	if (repo_get_oid(repo, name, &oid) < 0)
 		return 0;
 
-	buf = odb_read_object(the_repository->objects, &oid, &type, &size);
+	buf = odb_read_object(repo->objects, &oid, &type, &size);
 	if (!buf)
 		return error("unable to read mailmap object at %s", name);
 	if (type != OBJ_BLOB) {
@@ -209,7 +210,7 @@ int read_mailmap_blob(struct string_list *map, const char *name)
 	return 0;
 }
 
-int read_mailmap(struct string_list *map)
+int read_mailmap(struct repository *repo, struct string_list *map)
 {
 	int err = 0;
 
@@ -224,7 +225,7 @@ int read_mailmap(struct string_list *map)
 					 startup_info->have_repository ?
 					 MAILMAP_NOFOLLOW : 0);
 	if (startup_info->have_repository)
-		err |= read_mailmap_blob(map, git_mailmap_blob);
+		err |= read_mailmap_blob(repo, map, git_mailmap_blob);
 	err |= read_mailmap_file(map, git_mailmap_file, 0);
 	return err;
 }
diff --git a/mailmap.h b/mailmap.h
index 908365e1bf..fda329d715 100644
--- a/mailmap.h
+++ b/mailmap.h
@@ -1,6 +1,7 @@
 #ifndef MAILMAP_H
 #define MAILMAP_H
 
+struct repository;
 struct string_list;
 
 extern char *git_mailmap_file;
@@ -11,9 +12,10 @@ extern char *git_mailmap_blob;
 
 int read_mailmap_file(struct string_list *map, const char *filename,
 		      unsigned flags);
-int read_mailmap_blob(struct string_list *map, const char *name);
+int read_mailmap_blob(struct repository *repo, struct string_list *map,
+		      const char *name);
 
-int read_mailmap(struct string_list *map);
+int read_mailmap(struct repository *repo, struct string_list *map);
 void clear_mailmap(struct string_list *map);
 
 int map_user(struct string_list *map,
diff --git a/pretty.c b/pretty.c
index e0646bbc5d..ebf4da4834 100644
--- a/pretty.c
+++ b/pretty.c
@@ -781,7 +781,7 @@ static int mailmap_name(const char **email, size_t *email_len,
 	static struct string_list *mail_map;
 	if (!mail_map) {
 		CALLOC_ARRAY(mail_map, 1);
-		read_mailmap(mail_map);
+		read_mailmap(the_repository, mail_map);
 	}
 	return mail_map->nr && map_user(mail_map, email, email_len, name, name_len);
 }
diff --git a/ref-filter.c b/ref-filter.c
index 3917c4ccd9..d7a23a7b61 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1753,7 +1753,7 @@ static void grab_person(const char *who, struct atom_value *val, int deref, void
 		    (starts_with(name + wholen, "email") &&
 		    (atom->u.email_option.option & EO_MAILMAP))) {
 			if (!mailmap.items)
-				read_mailmap(&mailmap);
+				read_mailmap(the_repository, &mailmap);
 			strbuf_addstr(&mailmap_buf, buf);
 			apply_mailmap_to_header(&mailmap_buf, headers, &mailmap);
 			wholine = find_wholine(who, wholen, mailmap_buf.buf);
-- 
2.52.0
Burak Kaan Karaçay· Feb 20, 2026, 06:04 UTC · re: Burak Kaan Karaçay · lore

[GSOC PATCH v2 2/2] mailmap: drop global config variables

The 'mailmap.file' and 'mailmap.blob' configurations are currently parsed and stored in the global variables 'git_mailmap_file' and 'git_mailmap_blob'. Since these values are typically only needed once when initializing a mailmap, there is no need to keep them as global state throughout the lifetime of the Git process.

To reduce global state, remove these global variables and instead use 'repo_config_get_*' functions to read the configuration on demand.

Signed-off-by: Burak Kaan Karaçay <bkkaracay@gmail.com>
---
 environment.c | 19 -------------------
 mailmap.c     | 21 ++++++++++++++-------
 mailmap.h     |  3 ---
 3 files changed, 14 insertions(+), 29 deletions(-)
Show changes to 3 files +14 −29

environment.c, mailmap.c, mailmap.h

diff --git a/environment.c b/environment.c
index 0026eb2274..2764d8f481 100644
--- a/environment.c
+++ b/environment.c
@@ -647,22 +647,6 @@ static int git_default_push_config(const char *var, const char *value)
 	return 0;
 }
 
-static int git_default_mailmap_config(const char *var, const char *value)
-{
-	if (!strcmp(var, "mailmap.file")) {
-		FREE_AND_NULL(git_mailmap_file);
-		return git_config_pathname(&git_mailmap_file, var, value);
-	}
-
-	if (!strcmp(var, "mailmap.blob")) {
-		FREE_AND_NULL(git_mailmap_blob);
-		return git_config_string(&git_mailmap_blob, var, value);
-	}
-
-	/* Add other config variables here and to Documentation/config.adoc. */
-	return 0;
-}
-
 static int git_default_attr_config(const char *var, const char *value)
 {
 	if (!strcmp(var, "attr.tree")) {
@@ -697,9 +681,6 @@ int git_default_config(const char *var, const char *value,
 	if (starts_with(var, "push."))
 		return git_default_push_config(var, value);
 
-	if (starts_with(var, "mailmap."))
-		return git_default_mailmap_config(var, value);
-
 	if (starts_with(var, "attr."))
 		return git_default_attr_config(var, value);
 
diff --git a/mailmap.c b/mailmap.c
index cf70956675..3b2691781d 100644
--- a/mailmap.c
+++ b/mailmap.c
@@ -7,9 +7,7 @@
 #include "object-name.h"
 #include "odb.h"
 #include "setup.h"
-
-char *git_mailmap_file;
-char *git_mailmap_blob;
+#include "config.h"
 
 struct mailmap_info {
 	char *name;
@@ -213,20 +211,29 @@ int read_mailmap_blob(struct repository *repo, struct string_list *map,
 int read_mailmap(struct repository *repo, struct string_list *map)
 {
 	int err = 0;
+	char *mailmap_file = NULL, *mailmap_blob = NULL;
+
+	repo_config_get_pathname(repo, "mailmap.file", &mailmap_file);
+	repo_config_get_string(repo, "mailmap.blob", &mailmap_blob);
 
 	map->strdup_strings = 1;
 	map->cmp = namemap_cmp;
 
-	if (!git_mailmap_blob && is_bare_repository())
-		git_mailmap_blob = xstrdup("HEAD:.mailmap");
+	if (!mailmap_blob && is_bare_repository())
+		mailmap_blob = xstrdup("HEAD:.mailmap");
 
 	if (!startup_info->have_repository || !is_bare_repository())
 		err |= read_mailmap_file(map, ".mailmap",
 					 startup_info->have_repository ?
 					 MAILMAP_NOFOLLOW : 0);
 	if (startup_info->have_repository)
-		err |= read_mailmap_blob(repo, map, git_mailmap_blob);
-	err |= read_mailmap_file(map, git_mailmap_file, 0);
+		err |= read_mailmap_blob(repo, map, mailmap_blob);
+
+	err |= read_mailmap_file(map, mailmap_file, 0);
+
+	free(mailmap_file);
+	free(mailmap_blob);
+
 	return err;
 }
 
diff --git a/mailmap.h b/mailmap.h
index fda329d715..6866cb6f1d 100644
--- a/mailmap.h
+++ b/mailmap.h
@@ -4,9 +4,6 @@
 struct repository;
 struct string_list;
 
-extern char *git_mailmap_file;
-extern char *git_mailmap_blob;
-
 /* Flags for read_mailmap_file() */
 #define MAILMAP_NOFOLLOW (1<<0)
 
-- 
2.52.0
Junio C Hamano· Feb 20, 2026, 16:16 UTC · re: Burak Kaan Karaçay · lore

Re: [GSOC PATCH v2 0/2] mailmap: reduce global state

Burak Kaan Karaçay <bkkaracay@gmail.com> writes:
Show 14 quoted lines
> This patch series aims to reduce the global variable dependency of the
> mailmap subsystem:
>
>   - Patch 1 eliminates the implicit 'the_repository' dependency in the
>     'read_mailmap' and 'read_mailmap_blob' functions by adding a
>     'struct repository' parameter.
>
>   - Patch 2 removes the 'git_mailmap_file' and 'git_mailmap_blob' global
>     variables, shifting to on-demand configuration reading via the config
>     set helpers and using local variables.
>     
> Changes in v2:
>   - Forward declare 'struct repository' in mailmap.h
>   - Fix whitespace problems
Thanks for a quick reroll.  Looking very good.
Will queue.

← back to recent threads