Skip to content

Commit c96476b

Browse files
Athos RibeiroByron
Athos Ribeiro
authored andcommitted
Get system user id in a lazy manner
Calling getpass.getuser may lead to breakage in environments where there is no entries in the /etc/passwd file for the current user. Setting the environment variables for the git user configurations should prevents GitPython from using values from /etc/passwd. However, doing so will not prevent reading /etc/passwd and looking for an entry with the current user UID. This patch changes the behavior described above so GitPython will perform a lazy evaluation of /etc/passwd, only doing so when the environment variables for the git user configuration are not available. Signed-off-by: Athos Ribeiro <athos@redhat.com>
1 parent 0c6e670 commit c96476b

File tree

2 files changed

+36
-5
lines changed

2 files changed

+36
-5
lines changed

git/util.py

+12-4
Original file line numberDiff line numberDiff line change
@@ -582,8 +582,16 @@ def _from_string(cls, string):
582582
@classmethod
583583
def _main_actor(cls, env_name, env_email, config_reader=None):
584584
actor = Actor('', '')
585-
default_email = get_user_id()
586-
default_name = default_email.split('@')[0]
585+
user_id = None # We use this to avoid multiple calls to getpass.getuser()
586+
587+
def default_email():
588+
nonlocal user_id
589+
if not user_id:
590+
user_id = get_user_id()
591+
return user_id
592+
593+
def default_name():
594+
default_email().split('@')[0]
587595

588596
for attr, evar, cvar, default in (('name', env_name, cls.conf_name, default_name),
589597
('email', env_email, cls.conf_email, default_email)):
@@ -592,10 +600,10 @@ def _main_actor(cls, env_name, env_email, config_reader=None):
592600
setattr(actor, attr, val)
593601
except KeyError:
594602
if config_reader is not None:
595-
setattr(actor, attr, config_reader.get_value('user', cvar, default))
603+
setattr(actor, attr, config_reader.get_value('user', cvar, default()))
596604
# END config-reader handling
597605
if not getattr(actor, attr):
598-
setattr(actor, attr, default)
606+
setattr(actor, attr, default())
599607
# END handle name
600608
# END for each item to retrieve
601609
return actor

test/test_util.py

+24-1
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44
# This module is part of GitPython and is released under
55
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
66

7+
import os
78
import pickle
89
import tempfile
910
import time
10-
from unittest import skipIf
11+
from unittest import mock, skipIf
1112
from datetime import datetime
1213

1314
import ddt
@@ -215,6 +216,28 @@ def test_actor(self):
215216
self.assertIsInstance(Actor.author(cr), Actor)
216217
# END assure config reader is handled
217218

219+
@mock.patch("getpass.getuser")
220+
def test_actor_get_uid_laziness_not_called(self, mock_get_uid):
221+
env = {
222+
"GIT_AUTHOR_NAME": "John Doe",
223+
"GIT_AUTHOR_EMAIL": "jdoe@example.com",
224+
"GIT_COMMITTER_NAME": "Jane Doe",
225+
"GIT_COMMITTER_EMAIL": "jane@example.com",
226+
}
227+
os.environ.update(env)
228+
for cr in (None, self.rorepo.config_reader()):
229+
Actor.committer(cr)
230+
Actor.author(cr)
231+
self.assertFalse(mock_get_uid.called)
232+
233+
@mock.patch("getpass.getuser")
234+
def test_actor_get_uid_laziness_called(self, mock_get_uid):
235+
for cr in (None, self.rorepo.config_reader()):
236+
Actor.committer(cr)
237+
Actor.author(cr)
238+
self.assertTrue(mock_get_uid.called)
239+
self.assertEqual(mock_get_uid.call_count, 4)
240+
218241
def test_actor_from_string(self):
219242
self.assertEqual(Actor._from_string("name"), Actor("name", None))
220243
self.assertEqual(Actor._from_string("name <>"), Actor("name", ""))

0 commit comments

Comments
 (0)