git_config: add GetInt helper

Change-Id: Ic034ae2fd962299d1b352e597b391b6582ecf44b
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/256052
Tested-by: Mike Frysinger <vapier@google.com>
Reviewed-by: Jonathan Nieder <jrn@google.com>
diff --git a/git_config.py b/git_config.py
index cee33e9..6b1f710 100644
--- a/git_config.py
+++ b/git_config.py
@@ -122,6 +122,43 @@
       return self.defaults.Has(name, include_defaults=True)
     return False
 
+  def GetInt(self, name):
+    """Returns an integer from the configuration file.
+
+    This follows the git config syntax.
+
+    Args:
+      name: The key to lookup.
+
+    Returns:
+      None if the value was not defined, or is not a boolean.
+      Otherwise, the number itself.
+    """
+    v = self.GetString(name)
+    if v is None:
+      return None
+    v = v.strip()
+
+    mult = 1
+    if v.endswith('k'):
+      v = v[:-1]
+      mult = 1024
+    elif v.endswith('m'):
+      v = v[:-1]
+      mult = 1024 * 1024
+    elif v.endswith('g'):
+      v = v[:-1]
+      mult = 1024 * 1024 * 1024
+
+    base = 10
+    if v.startswith('0x'):
+      base = 16
+
+    try:
+      return int(v, base=base) * mult
+    except ValueError:
+      return None
+
   def GetBoolean(self, name):
     """Returns a boolean from the configuration file.
        None : The value was not defined, or is not a boolean.
diff --git a/tests/fixtures/test.gitconfig b/tests/fixtures/test.gitconfig
index 3c573c9..9b3f257 100644
--- a/tests/fixtures/test.gitconfig
+++ b/tests/fixtures/test.gitconfig
@@ -1,3 +1,13 @@
 [section]
 	empty
 	nonempty = true
+	boolinvalid = oops
+	booltrue = true
+	boolfalse = false
+	intinvalid = oops
+	inthex = 0x10
+	inthexk = 0x10k
+	int = 10
+	intk = 10k
+	intm = 10m
+	intg = 10g
diff --git a/tests/test_git_config.py b/tests/test_git_config.py
index 6aa6b38..4541b35 100644
--- a/tests/test_git_config.py
+++ b/tests/test_git_config.py
@@ -71,6 +71,43 @@
     val = config.GetString('empty')
     self.assertEqual(val, None)
 
+  def test_GetBoolean_undefined(self):
+    """Test GetBoolean on key that doesn't exist."""
+    self.assertIsNone(self.config.GetBoolean('section.missing'))
+
+  def test_GetBoolean_invalid(self):
+    """Test GetBoolean on invalid boolean value."""
+    self.assertIsNone(self.config.GetBoolean('section.boolinvalid'))
+
+  def test_GetBoolean_true(self):
+    """Test GetBoolean on valid true boolean."""
+    self.assertTrue(self.config.GetBoolean('section.booltrue'))
+
+  def test_GetBoolean_false(self):
+    """Test GetBoolean on valid false boolean."""
+    self.assertFalse(self.config.GetBoolean('section.boolfalse'))
+
+  def test_GetInt_undefined(self):
+    """Test GetInt on key that doesn't exist."""
+    self.assertIsNone(self.config.GetInt('section.missing'))
+
+  def test_GetInt_invalid(self):
+    """Test GetInt on invalid integer value."""
+    self.assertIsNone(self.config.GetBoolean('section.intinvalid'))
+
+  def test_GetInt_valid(self):
+    """Test GetInt on valid integers."""
+    TESTS = (
+        ('inthex', 16),
+        ('inthexk', 16384),
+        ('int', 10),
+        ('intk', 10240),
+        ('intm', 10485760),
+        ('intg', 10737418240),
+    )
+    for key, value in TESTS:
+      self.assertEqual(value, self.config.GetInt('section.%s' % (key,)))
+
 
 if __name__ == '__main__':
   unittest.main()