Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit e583a9e

Browse filesBrowse files
committed
Added version_info property to git command. Its cached and efficient, including test
1 parent e11f12a commit e583a9e
Copy full SHA for e583a9e

File tree

2 files changed

+106
-71
lines changed
Filter options

2 files changed

+106
-71
lines changed

‎git/cmd.py

Copy file name to clipboardExpand all lines: git/cmd.py
+24-5Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
66

77
import os, sys
8-
from util import *
8+
from util import (
9+
LazyMixin,
10+
stream_copy
11+
)
912
from exc import GitCommandError
1013

1114
from subprocess import (
@@ -26,7 +29,7 @@
2629
def dashify(string):
2730
return string.replace('_', '-')
2831

29-
class Git(object):
32+
class Git(LazyMixin):
3033
"""
3134
The Git class manages communication with the Git binary.
3235
@@ -41,7 +44,7 @@ class Git(object):
4144
of the command to stdout.
4245
Set its value to 'full' to see details about the returned values.
4346
"""
44-
__slots__ = ("_working_dir", "cat_file_all", "cat_file_header")
47+
__slots__ = ("_working_dir", "cat_file_all", "cat_file_header", "_version_info")
4548

4649
# CONFIGURATION
4750
# The size in bytes read from stdout when copying git's output to another stream
@@ -214,14 +217,30 @@ def __getattr__(self, name):
214217
"""A convenience method as it allows to call the command as if it was
215218
an object.
216219
:return: Callable object that will execute call _call_process with your arguments."""
217-
if name[:1] == '_':
218-
raise AttributeError(name)
220+
if name[0] == '_':
221+
return LazyMixin.__getattr__(self, name)
219222
return lambda *args, **kwargs: self._call_process(name, *args, **kwargs)
220223

224+
def _set_cache_(self, attr):
225+
if attr == '_version_info':
226+
version_numbers = self._call_process('version').rpartition(' ')[2]
227+
self._version_info = tuple(int(n) for n in version_numbers.split('.'))
228+
else:
229+
super(Git, self)._set_cache_(attr)
230+
#END handle version info
231+
232+
221233
@property
222234
def working_dir(self):
223235
""":return: Git directory we are working on"""
224236
return self._working_dir
237+
238+
@property
239+
def version_info(self):
240+
""":return: tuple(int, ...) tuple with integers representing the major, minor
241+
and additional version numbers as parsed from git version.
242+
This value is generated on demand and is cached"""
243+
return self._version_info
225244

226245
def execute(self, command,
227246
istream=None,

‎git/test/test_git.py

Copy file name to clipboardExpand all lines: git/test/test_git.py
+82-66Lines changed: 82 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -5,80 +5,96 @@
55
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
66

77
import os, sys
8-
from git.test.lib import *
8+
from git.test.lib import (
9+
TestBase,
10+
patch_object,
11+
raises,
12+
assert_equal,
13+
assert_true,
14+
assert_match,
15+
fixture_path
16+
)
917
from git import Git, GitCommandError
1018

11-
class TestGit(TestCase):
12-
13-
@classmethod
14-
def setUpAll(cls):
15-
cls.git = Git(GIT_REPO)
19+
class TestGit(TestBase):
20+
21+
@classmethod
22+
def setUpAll(cls):
23+
super(TestGit, cls).setUpAll()
24+
cls.git = Git(cls.rorepo.working_dir)
1625

17-
@patch_object(Git, 'execute')
18-
def test_call_process_calls_execute(self, git):
19-
git.return_value = ''
20-
self.git.version()
21-
assert_true(git.called)
22-
assert_equal(git.call_args, ((['git', 'version'],), {}))
26+
@patch_object(Git, 'execute')
27+
def test_call_process_calls_execute(self, git):
28+
git.return_value = ''
29+
self.git.version()
30+
assert_true(git.called)
31+
assert_equal(git.call_args, ((['git', 'version'],), {}))
2332

24-
@raises(GitCommandError)
25-
def test_it_raises_errors(self):
26-
self.git.this_does_not_exist()
33+
@raises(GitCommandError)
34+
def test_it_raises_errors(self):
35+
self.git.this_does_not_exist()
2736

2837

29-
def test_it_transforms_kwargs_into_git_command_arguments(self):
30-
assert_equal(["-s"], self.git.transform_kwargs(**{'s': True}))
31-
assert_equal(["-s5"], self.git.transform_kwargs(**{'s': 5}))
38+
def test_it_transforms_kwargs_into_git_command_arguments(self):
39+
assert_equal(["-s"], self.git.transform_kwargs(**{'s': True}))
40+
assert_equal(["-s5"], self.git.transform_kwargs(**{'s': 5}))
3241

33-
assert_equal(["--max-count"], self.git.transform_kwargs(**{'max_count': True}))
34-
assert_equal(["--max-count=5"], self.git.transform_kwargs(**{'max_count': 5}))
42+
assert_equal(["--max-count"], self.git.transform_kwargs(**{'max_count': True}))
43+
assert_equal(["--max-count=5"], self.git.transform_kwargs(**{'max_count': 5}))
3544

36-
assert_equal(["-s", "-t"], self.git.transform_kwargs(**{'s': True, 't': True}))
45+
assert_equal(["-s", "-t"], self.git.transform_kwargs(**{'s': True, 't': True}))
3746

38-
def test_it_executes_git_to_shell_and_returns_result(self):
39-
assert_match('^git version [\d\.]{2}.*$', self.git.execute(["git","version"]))
47+
def test_it_executes_git_to_shell_and_returns_result(self):
48+
assert_match('^git version [\d\.]{2}.*$', self.git.execute(["git","version"]))
4049

41-
def test_it_accepts_stdin(self):
42-
filename = fixture_path("cat_file_blob")
43-
fh = open(filename, 'r')
44-
assert_equal("70c379b63ffa0795fdbfbc128e5a2818397b7ef8",
45-
self.git.hash_object(istream=fh, stdin=True))
46-
fh.close()
50+
def test_it_accepts_stdin(self):
51+
filename = fixture_path("cat_file_blob")
52+
fh = open(filename, 'r')
53+
assert_equal("70c379b63ffa0795fdbfbc128e5a2818397b7ef8",
54+
self.git.hash_object(istream=fh, stdin=True))
55+
fh.close()
4756

48-
@patch_object(Git, 'execute')
49-
def test_it_ignores_false_kwargs(self, git):
50-
# this_should_not_be_ignored=False implies it *should* be ignored
51-
output = self.git.version(pass_this_kwarg=False)
52-
assert_true("pass_this_kwarg" not in git.call_args[1])
53-
54-
def test_persistent_cat_file_command(self):
55-
# read header only
56-
import subprocess as sp
57-
hexsha = "b2339455342180c7cc1e9bba3e9f181f7baa5167"
58-
g = self.git.cat_file(batch_check=True, istream=sp.PIPE,as_process=True)
59-
g.stdin.write("b2339455342180c7cc1e9bba3e9f181f7baa5167\n")
60-
g.stdin.flush()
61-
obj_info = g.stdout.readline()
62-
63-
# read header + data
64-
g = self.git.cat_file(batch=True, istream=sp.PIPE,as_process=True)
65-
g.stdin.write("b2339455342180c7cc1e9bba3e9f181f7baa5167\n")
66-
g.stdin.flush()
67-
obj_info_two = g.stdout.readline()
68-
assert obj_info == obj_info_two
69-
70-
# read data - have to read it in one large chunk
71-
size = int(obj_info.split()[2])
72-
data = g.stdout.read(size)
73-
terminating_newline = g.stdout.read(1)
74-
75-
# now we should be able to read a new object
76-
g.stdin.write("b2339455342180c7cc1e9bba3e9f181f7baa5167\n")
77-
g.stdin.flush()
78-
assert g.stdout.readline() == obj_info
79-
80-
81-
# same can be achived using the respective command functions
82-
hexsha, typename, size = self.git.get_object_header(hexsha)
83-
hexsha, typename_two, size_two, data = self.git.get_object_data(hexsha)
84-
assert typename == typename_two and size == size_two
57+
@patch_object(Git, 'execute')
58+
def test_it_ignores_false_kwargs(self, git):
59+
# this_should_not_be_ignored=False implies it *should* be ignored
60+
output = self.git.version(pass_this_kwarg=False)
61+
assert_true("pass_this_kwarg" not in git.call_args[1])
62+
63+
def test_persistent_cat_file_command(self):
64+
# read header only
65+
import subprocess as sp
66+
hexsha = "b2339455342180c7cc1e9bba3e9f181f7baa5167"
67+
g = self.git.cat_file(batch_check=True, istream=sp.PIPE,as_process=True)
68+
g.stdin.write("b2339455342180c7cc1e9bba3e9f181f7baa5167\n")
69+
g.stdin.flush()
70+
obj_info = g.stdout.readline()
71+
72+
# read header + data
73+
g = self.git.cat_file(batch=True, istream=sp.PIPE,as_process=True)
74+
g.stdin.write("b2339455342180c7cc1e9bba3e9f181f7baa5167\n")
75+
g.stdin.flush()
76+
obj_info_two = g.stdout.readline()
77+
assert obj_info == obj_info_two
78+
79+
# read data - have to read it in one large chunk
80+
size = int(obj_info.split()[2])
81+
data = g.stdout.read(size)
82+
terminating_newline = g.stdout.read(1)
83+
84+
# now we should be able to read a new object
85+
g.stdin.write("b2339455342180c7cc1e9bba3e9f181f7baa5167\n")
86+
g.stdin.flush()
87+
assert g.stdout.readline() == obj_info
88+
89+
90+
# same can be achived using the respective command functions
91+
hexsha, typename, size = self.git.get_object_header(hexsha)
92+
hexsha, typename_two, size_two, data = self.git.get_object_data(hexsha)
93+
assert typename == typename_two and size == size_two
94+
95+
def test_version(self):
96+
v = self.git.version_info
97+
assert isinstance(v, tuple)
98+
for n in v:
99+
assert isinstance(n, int)
100+
#END verify number types

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.