summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAthos Ribeiro <athos@redhat.com>2020-10-20 14:51:31 +0200
committerSebastian Thiel <sebastian.thiel@icloud.com>2020-10-22 14:17:36 +0800
commitc96476be7f10616768584a95d06cd1bddfe6d404 (patch)
treee6a56fea100a066f3dd62fa58ca0f347357840ad
parent0c6e67013fd22840d6cd6cb1a22fcf52eecab530 (diff)
downloadgitpython-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.py16
-rw-r--r--test/test_util.py25
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", ""))