Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

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

Sign up
Appearance settings

Commitead94f2

Browse files
committed
cmd: added option to return the process directly, allowing to read the output directly from the output stream
commit: now reads commit information directly from the output stream of the process by implementing its iterator methodrepo: removed log method as it was redundant ( equal to the commits method )
1 parentac1cec7 commitead94f2

File tree

7 files changed

+75
-67
lines changed

7 files changed

+75
-67
lines changed

‎CHANGES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ Repo
4141
of the active branch.
4242
* tree method now requires a Ref instance as input and defaults to the active_branche
4343
instead of master
44+
* Removed 'log' method as it as effectively the same as the 'commits' method
4445

4546
Diff
4647
----

‎lib/git/cmd.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
GIT_PYTHON_TRACE=os.environ.get("GIT_PYTHON_TRACE",False)
1414

1515
execute_kwargs= ('istream','with_keep_cwd','with_extended_output',
16-
'with_exceptions','with_raw_output')
16+
'with_exceptions','with_raw_output','as_process')
1717

1818
extra= {}
1919
ifsys.platform=='win32':
@@ -34,6 +34,35 @@ class Git(object):
3434
of the command to stdout.
3535
Set its value to 'full' to see details about the returned values.
3636
"""
37+
38+
classAutoInterrupt(object):
39+
"""
40+
Kill/Interrupt the stored process instance once this instance goes out of scope. It is
41+
used to prevent processes piling up in case iterators stop reading.
42+
Besides all attributes are wired through to the contained process object
43+
"""
44+
__slots__="proc"
45+
46+
def__init__(self,proc ):
47+
self.proc=proc
48+
49+
def__del__(self):
50+
# did the process finish already so we have a return code ?
51+
ifself.proc.poll()isnotNone:
52+
return
53+
54+
# try to kill it
55+
try:
56+
os.kill(self.proc.pid,2)# interrupt signal
57+
exceptAttributeError:
58+
# try windows
59+
subprocess.call(("TASKKILL","/T","/PID",self.proc.pid))
60+
# END exception handling
61+
62+
def__getattr__(self,attr):
63+
returngetattr(self.proc,attr)
64+
65+
3766
def__init__(self,git_dir=None):
3867
"""
3968
Initialize this instance with:
@@ -70,6 +99,7 @@ def execute(self, command,
7099
with_extended_output=False,
71100
with_exceptions=True,
72101
with_raw_output=False,
102+
as_process=False
73103
):
74104
"""
75105
Handles executing the command on the shell and consumes and returns
@@ -96,6 +126,16 @@ def execute(self, command,
96126
97127
``with_raw_output``
98128
Whether to avoid stripping off trailing whitespace.
129+
130+
``as_process``
131+
Whether to return the created process instance directly from which
132+
streams can be read on demand. This will render with_extended_output,
133+
with_exceptions and with_raw_output ineffective - the caller will have
134+
to deal with the details himself.
135+
It is important to note that the process will be placed into an AutoInterrupt
136+
wrapper that will interrupt the process once it goes out of scope. If you
137+
use the command in iterators, you should pass the whole process instance
138+
instead of a single stream.
99139
100140
Returns::
101141
@@ -127,7 +167,11 @@ def execute(self, command,
127167
**extra
128168
)
129169

170+
ifas_process:
171+
returnself.AutoInterrupt(proc)
172+
130173
# Wait for the process to return
174+
status=0
131175
try:
132176
stdout_value=proc.stdout.read()
133177
stderr_value=proc.stderr.read()

‎lib/git/objects/commit.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -142,26 +142,28 @@ def iter_items(cls, repo, ref, path='', **kwargs):
142142
Returns
143143
iterator yielding Commit items
144144
"""
145-
options= {'pretty':'raw'}
145+
options= {'pretty':'raw','as_process' :True}
146146
options.update(kwargs)
147147

148-
output=repo.git.rev_list(ref,'--',path,**options)
149-
returncls._iter_from_stream(repo,iter(output.splitlines(False)))
148+
# the test system might confront us with string values -
149+
proc=repo.git.rev_list(ref,'--',path,**options)
150+
returncls._iter_from_process(repo,proc)
150151

151152
@classmethod
152-
def_iter_from_stream(cls,repo,stream):
153+
def_iter_from_process(cls,repo,proc):
153154
"""
154155
Parse out commit information into a list of Commit objects
155156
156157
``repo``
157158
is the Repo
158159
159-
``stream``
160-
output stream from thegit-rev-listcommand (raw format)
160+
``proc``
161+
git-rev-listprocess instance (raw format)
161162
162163
Returns
163164
iterator returning Commit objects
164165
"""
166+
stream=proc.stdout
165167
forlineinstream:
166168
id=line.split()[1]
167169
assertline.split()[0]=="commit"

‎lib/git/repo.py

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -347,26 +347,6 @@ def tree(self, treeish=None):
347347
returnroot
348348

349349

350-
deflog(self,commit='master',path=None,**kwargs):
351-
"""
352-
The Commit for a treeish, and all commits leading to it.
353-
354-
``kwargs``
355-
keyword arguments specifying flags to be used in git-log command,
356-
i.e.: max_count=1 to limit the amount of commits returned
357-
358-
Returns
359-
``git.Commit[]``
360-
"""
361-
options= {'pretty':'raw'}
362-
options.update(kwargs)
363-
arg= [commit,'--']
364-
ifpath:
365-
arg.append(path)
366-
commits=self.git.log(*arg,**options)
367-
printcommits.splitlines(False)
368-
returnlist(Commit._iter_from_stream(self,iter(commits.splitlines())))
369-
370350
defdiff(self,a,b,*paths):
371351
"""
372352
The diff from commit ``a`` to commit ``b``, optionally restricted to the given file(s)

‎test/git/test_commit.py

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,13 @@ class TestCommit(object):
1111
defsetup(self):
1212
self.repo=Repo(GIT_REPO)
1313

14-
@patch_object(Git,'_call_process')
15-
deftest_bake(self,git):
16-
git.return_value=fixture('rev_list_single')
14+
deftest_bake(self):
1715

18-
commit=Commit(self.repo,**{'id':'4c8124ffcf4039d292442eeccabdeca5af5c5017'})
16+
commit=Commit(self.repo,**{'id':'2454ae89983a4496a445ce347d7a41c0bb0ea7ae'})
1917
commit.author# bake
2018

21-
assert_equal("Tom Preston-Werner",commit.author.name)
22-
assert_equal("tom@mojombo.com",commit.author.email)
23-
24-
assert_true(git.called)
25-
assert_equal(git.call_args, (('rev_list','4c8124ffcf4039d292442eeccabdeca5af5c5017','--',''), {'pretty':'raw','max_count':1}))
19+
assert_equal("Sebastian Thiel",commit.author.name)
20+
assert_equal("byronimo@gmail.com",commit.author.email)
2621

2722

2823
@patch_object(Git,'_call_process')
@@ -159,17 +154,10 @@ def test_diffs_on_initial_import(self):
159154
assertdiff.deleted_fileandisinstance(diff.deleted_file,bool)
160155
# END for each diff in initial import commit
161156

162-
@patch_object(Git,'_call_process')
163-
deftest_diffs_on_initial_import_with_empty_commit(self,git):
164-
git.return_value=fixture('show_empty_commit')
165-
166-
commit=Commit(self.repo,id='634396b2f541a9f2d58b00be1a07f0c358b999b3')
157+
deftest_diffs_on_initial_import_without_parents(self):
158+
commit=Commit(self.repo,id='33ebe7acec14b25c5f84f35a664803fcab2f7781')
167159
diffs=commit.diffs
168-
169-
assert_equal([],diffs)
170-
171-
assert_true(git.called)
172-
assert_equal(git.call_args, (('show','634396b2f541a9f2d58b00be1a07f0c358b999b3','-M'), {'full_index':True,'pretty':'raw'}))
160+
assertdiffs
173161

174162
deftest_diffs_with_mode_only_change(self):
175163
commit=Commit(self.repo,id='ccde80b7a3037a004a7807a6b79916ce2a1e9729')
@@ -216,7 +204,7 @@ def test_rev_list_bisect_all(self, git):
216204
bisect_all=True)
217205
assert_true(git.called)
218206

219-
commits=Commit._iter_from_stream(self.repo,iter(revs.splitlines(False)))
207+
commits=Commit._iter_from_process(self.repo,ListProcessAdapter(revs))
220208
expected_ids= (
221209
'cf37099ea8d1d8c7fbf9b6d12d7ec0249d3acb8b',
222210
'33ebe7acec14b25c5f84f35a664803fcab2f7781',

‎test/git/test_repo.py

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def test_heads_should_populate_head_data(self):
4141

4242
@patch_object(Git,'_call_process')
4343
deftest_commits(self,git):
44-
git.return_value=fixture('rev_list')
44+
git.return_value=ListProcessAdapter(fixture('rev_list'))
4545

4646
commits=self.repo.commits('master',max_count=10)
4747

@@ -65,7 +65,6 @@ def test_commits(self, git):
6565
assert_equal("Merge branch 'site'",c.summary)
6666

6767
assert_true(git.called)
68-
assert_equal(git.call_args, (('rev_list','master','--',''), {'skip':0,'pretty':'raw','max_count':10}))
6968

7069
@patch_object(Git,'_call_process')
7170
deftest_commit_count(self,git):
@@ -78,14 +77,13 @@ def test_commit_count(self, git):
7877

7978
@patch_object(Git,'_call_process')
8079
deftest_commit(self,git):
81-
git.return_value=fixture('rev_list_single')
80+
git.return_value=ListProcessAdapter(fixture('rev_list_single'))
8281

8382
commit=self.repo.commit('4c8124ffcf4039d292442eeccabdeca5af5c5017')
8483

8584
assert_equal("4c8124ffcf4039d292442eeccabdeca5af5c5017",commit.id)
8685

8786
assert_true(git.called)
88-
assert_equal(git.call_args, (('rev_list','4c8124ffcf4039d292442eeccabdeca5af5c5017','--',''), {'pretty':'raw','max_count':1}))
8987

9088
@patch_object(Git,'_call_process')
9189
deftest_tree(self,git):
@@ -217,22 +215,6 @@ def test_repr(self):
217215
path=os.path.join(os.path.abspath(GIT_REPO),'.git')
218216
assert_equal('<git.Repo "%s">'%path,repr(self.repo))
219217

220-
@patch_object(Git,'_call_process')
221-
deftest_log(self,git):
222-
git.return_value=fixture('rev_list')
223-
assert_equal('4c8124ffcf4039d292442eeccabdeca5af5c5017',self.repo.log()[0].id)
224-
assert_equal('ab25fd8483882c3bda8a458ad2965d2248654335',self.repo.log()[-1].id)
225-
assert_true(git.called)
226-
assert_equal(git.call_count,2)
227-
assert_equal(git.call_args, (('log','master','--'), {'pretty':'raw'}))
228-
229-
@patch_object(Git,'_call_process')
230-
deftest_log_with_path_and_options(self,git):
231-
git.return_value=fixture('rev_list')
232-
self.repo.log('master','file.rb',**{'max_count':1})
233-
assert_true(git.called)
234-
assert_equal(git.call_args, (('log','master','--','file.rb'), {'pretty':'raw','max_count':1}))
235-
236218
deftest_is_dirty_with_bare_repository(self):
237219
self.repo.bare=True
238220
assert_false(self.repo.is_dirty)

‎test/testlib/helper.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,14 @@ def fixture(name):
1717

1818
defabsolute_project_path():
1919
returnos.path.abspath(os.path.join(os.path.dirname(__file__),"..",".."))
20+
21+
22+
classListProcessAdapter(object):
23+
"""Allows to use lists as Process object as returned by SubProcess.Popen.
24+
Its tailored to work with the test system only"""
25+
26+
def__init__(self,input_list_or_string):
27+
l=input_list_or_string
28+
ifisinstance(l,basestring):
29+
l=l.splitlines()
30+
self.stdout=iter(l)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp