Skip to content

Commit 1a3ebce

Browse files
committed
Fix gx who: deduplicate authors by email, match You by email
- Merge shortlog entries with the same email address - Keep the longest name as display name (real name over username) - Match current user by email (not just name) for "You" label
1 parent 862d8e1 commit 1a3ebce

1 file changed

Lines changed: 35 additions & 8 deletions

File tree

src/gx/commands/who.py

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def _repo_level(n: int, since: str | None, show_email: bool) -> None:
6565
return
6666

6767
# Parse shortlog output: " 123\tName <email>"
68-
contributors = []
68+
raw_entries = []
6969
for line in output.splitlines():
7070
line = line.strip()
7171
if not line:
@@ -75,26 +75,53 @@ def _repo_level(n: int, since: str | None, show_email: bool) -> None:
7575
continue
7676
commits = int(parts[0].strip())
7777
name_email = parts[1].strip()
78-
# Extract name and email
7978
if "<" in name_email and ">" in name_email:
8079
name = name_email[: name_email.index("<")].strip()
81-
email = name_email[name_email.index("<") + 1 : name_email.index(">")]
80+
email = name_email[name_email.index("<") + 1 : name_email.index(">")].lower()
8281
else:
8382
name = name_email
8483
email = ""
85-
contributors.append({"name": name, "email": email, "commits": commits})
84+
raw_entries.append({"name": name, "email": email, "commits": commits})
85+
86+
# Deduplicate by email: merge entries with the same email,
87+
# keep the name with the most commits as the display name
88+
by_email: dict[str, dict] = {}
89+
for entry in raw_entries:
90+
email = entry["email"]
91+
if not email:
92+
# No email: use name as key
93+
key = f"__name__{entry['name'].lower()}"
94+
else:
95+
key = email
96+
if key in by_email:
97+
by_email[key]["commits"] += entry["commits"]
98+
# Keep the longer name (usually the real one, not a username)
99+
if len(entry["name"]) > len(by_email[key]["name"]):
100+
by_email[key]["name"] = entry["name"]
101+
else:
102+
by_email[key] = dict(entry)
86103

87-
# Get current git user
104+
contributors = sorted(by_email.values(), key=lambda c: c["commits"], reverse=True)
105+
106+
# Get current git user (both name and email for matching)
88107
try:
89-
current_user = run_git(["config", "user.name"])
108+
current_user_name = run_git(["config", "user.name"])
90109
except GitError:
91-
current_user = ""
110+
current_user_name = ""
111+
try:
112+
current_user_email = run_git(["config", "user.email"]).lower()
113+
except GitError:
114+
current_user_email = ""
92115

93116
rows = []
94117
for i, c in enumerate(contributors[:n], 1):
95118
name = str(c["name"])
96119
email_addr = str(c["email"])
97-
display_name = "You" if name == current_user else name
120+
is_you = (
121+
(current_user_email and email_addr == current_user_email)
122+
or (current_user_name and name == current_user_name)
123+
)
124+
display_name = "You" if is_you else name
98125
if show_email and email_addr:
99126
display_name += f" <{email_addr}>"
100127
last_active = _get_author_last_edit(name, ".")

0 commit comments

Comments
 (0)