diff options
author | Athos Ribeiro <athos@redhat.com> | 2020-10-20 14:51:31 +0200 |
---|---|---|
committer | Sebastian Thiel <sebastian.thiel@icloud.com> | 2020-10-22 14:17:36 +0800 |
commit | c96476be7f10616768584a95d06cd1bddfe6d404 (patch) | |
tree | e6a56fea100a066f3dd62fa58ca0f347357840ad | |
parent | 0c6e67013fd22840d6cd6cb1a22fcf52eecab530 (diff) | |
download | gitpython-c96476be7f10616768584a95d06cd1bddfe6d404.tar.gz |
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>
-rw-r--r-- | git/util.py | 16 | ||||
-rw-r--r-- | test/test_util.py | 25 |
2 files changed, 36 insertions, 5 deletions
diff --git a/git/util.py b/git/util.py index 216703cb..44eb0e51 100644 --- a/git/util.py +++ b/git/util.py @@ -582,8 +582,16 @@ class Actor(object): @classmethod def _main_actor(cls, env_name, env_email, config_reader=None): actor = Actor('', '') - default_email = get_user_id() - default_name = default_email.split('@')[0] + user_id = None # We use this to avoid multiple calls to getpass.getuser() + + def default_email(): + nonlocal user_id + if not user_id: + user_id = get_user_id() + return user_id + + def default_name(): + default_email().split('@')[0] for attr, evar, cvar, default in (('name', env_name, cls.conf_name, default_name), ('email', env_email, cls.conf_email, default_email)): @@ -592,10 +600,10 @@ class Actor(object): setattr(actor, attr, val) except KeyError: if config_reader is not None: - setattr(actor, attr, config_reader.get_value('user', cvar, default)) + setattr(actor, attr, config_reader.get_value('user', cvar, default())) # END config-reader handling if not getattr(actor, attr): - setattr(actor, attr, default) + setattr(actor, attr, default()) # END handle name # END for each item to retrieve return actor diff --git a/test/test_util.py b/test/test_util.py index df4e5474..2f946891 100644 --- a/test/test_util.py +++ b/test/test_util.py @@ -4,10 +4,11 @@ # This module is part of GitPython and is released under # the BSD License: http://www.opensource.org/licenses/bsd-license.php +import os import pickle import tempfile import time -from unittest import skipIf +from unittest import mock, skipIf from datetime import datetime import ddt @@ -215,6 +216,28 @@ class TestUtils(TestBase): self.assertIsInstance(Actor.author(cr), Actor) # END assure config reader is handled + @mock.patch("getpass.getuser") + def test_actor_get_uid_laziness_not_called(self, mock_get_uid): + env = { + "GIT_AUTHOR_NAME": "John Doe", + "GIT_AUTHOR_EMAIL": "jdoe@example.com", + "GIT_COMMITTER_NAME": "Jane Doe", + "GIT_COMMITTER_EMAIL": "jane@example.com", + } + os.environ.update(env) + for cr in (None, self.rorepo.config_reader()): + Actor.committer(cr) + Actor.author(cr) + self.assertFalse(mock_get_uid.called) + + @mock.patch("getpass.getuser") + def test_actor_get_uid_laziness_called(self, mock_get_uid): + for cr in (None, self.rorepo.config_reader()): + Actor.committer(cr) + Actor.author(cr) + self.assertTrue(mock_get_uid.called) + self.assertEqual(mock_get_uid.call_count, 4) + def test_actor_from_string(self): self.assertEqual(Actor._from_string("name"), Actor("name", None)) self.assertEqual(Actor._from_string("name <>"), Actor("name", "")) |