commitmsg: use immediate connections
[git-cola.git] / test / git_test.py
blobce57292fb4884d33b5adc307962de92eb4e8242a
1 """Test the cola.git module"""
2 # pylint: disable=redefined-outer-name
3 from __future__ import absolute_import, division, print_function, unicode_literals
5 from cola import git
6 from cola.git import STDOUT
8 from .helper import patch
11 # 16k+1 bytes to exhaust any output buffers.
12 BUFFER_SIZE = (16 * 1024) + 1
15 @patch('cola.git.is_git_dir')
16 def test_find_git_dir_None(is_git_dir):
17 paths = git.find_git_directory(None)
19 assert not is_git_dir.called
20 assert paths.git_dir is None
21 assert paths.git_file is None
22 assert paths.worktree is None
25 @patch('cola.git.is_git_dir')
26 def test_find_git_dir_empty_string(is_git_dir):
27 paths = git.find_git_directory('')
29 assert not is_git_dir.called
30 assert paths.git_dir is None
31 assert paths.git_file is None
32 assert paths.worktree is None
35 @patch('cola.git.is_git_dir')
36 def test_find_git_dir_never_found(is_git_dir):
37 is_git_dir.return_value = False
39 paths = git.find_git_directory('/does/not/exist')
41 assert is_git_dir.called
42 assert paths.git_dir is None
43 assert paths.git_file is None
44 assert paths.worktree is None
46 expect = 8
47 actual = is_git_dir.call_count
48 assert expect == actual
49 is_git_dir.assert_has_calls(
51 (('/does/not/exist',), {}),
52 (('/does/not/exist/.git',), {}),
53 (('/does/not',), {}),
54 (('/does/not/.git',), {}),
55 (('/does',), {}),
56 (('/does/.git',), {}),
57 (('/',), {}),
58 (('/.git',), {}),
63 @patch('cola.git.is_git_dir')
64 def test_find_git_dir_found_right_away(is_git_dir):
65 git_dir = '/seems/to/exist/.git'
66 worktree = '/seems/to/exist'
67 is_git_dir.return_value = True
69 paths = git.find_git_directory(git_dir)
71 assert is_git_dir.called
72 assert git_dir == paths.git_dir
73 assert paths.git_file is None
74 assert worktree == paths.worktree
77 @patch('cola.git.is_git_dir')
78 def test_find_git_does_discovery(is_git_dir):
79 git_dir = '/the/root/.git'
80 worktree = '/the/root'
81 is_git_dir.side_effect = lambda x: x == git_dir
83 paths = git.find_git_directory('/the/root/sub/dir')
85 assert git_dir == paths.git_dir
86 assert paths.git_file is None
87 assert worktree == paths.worktree
90 @patch('cola.git.read_git_file')
91 @patch('cola.git.is_git_file')
92 @patch('cola.git.is_git_dir')
93 def test_find_git_honors_git_files(is_git_dir, is_git_file, read_git_file):
94 git_file = '/the/root/.git'
95 worktree = '/the/root'
96 git_dir = '/super/module/.git/modules/root'
98 is_git_dir.side_effect = lambda x: x == git_file
99 is_git_file.side_effect = lambda x: x == git_file
100 read_git_file.return_value = git_dir
102 paths = git.find_git_directory('/the/root/sub/dir')
104 assert git_dir == paths.git_dir
105 assert git_file == paths.git_file
106 assert worktree == paths.worktree
108 expect = 6
109 actual = is_git_dir.call_count
110 assert expect == actual
111 is_git_dir.assert_has_calls(
113 (('/the/root/sub/dir',), {}),
114 (('/the/root/sub/dir/.git',), {}),
115 (('/the/root/sub',), {}),
116 (('/the/root/sub/.git',), {}),
117 (('/the/root',), {}),
118 (('/the/root/.git',), {}),
121 read_git_file.assert_called_once_with('/the/root/.git')
124 @patch('cola.core.getenv')
125 @patch('cola.git.is_git_dir')
126 def test_find_git_honors_ceiling_dirs(is_git_dir, getenv):
128 git_dir = '/ceiling/.git'
129 ceiling = '/tmp:/ceiling:/other/ceiling'
130 is_git_dir.side_effect = lambda x: x == git_dir
132 def mock_getenv(k, v=None):
133 if k == 'GIT_CEILING_DIRECTORIES':
134 return ceiling
135 return v
137 getenv.side_effect = mock_getenv
139 paths = git.find_git_directory('/ceiling/sub/dir')
141 assert paths.git_dir is None
142 assert paths.git_file is None
143 assert paths.worktree is None
144 assert is_git_dir.call_count == 4
145 is_git_dir.assert_has_calls(
147 (('/ceiling/sub/dir',), {}),
148 (('/ceiling/sub/dir/.git',), {}),
149 (('/ceiling/sub',), {}),
150 (('/ceiling/sub/.git',), {}),
155 @patch('cola.core.islink')
156 @patch('cola.core.isdir')
157 @patch('cola.core.isfile')
158 def test_is_git_dir_finds_linked_repository(isfile, isdir, islink):
159 dirs = set(
161 '/foo',
162 '/foo/.git',
163 '/foo/.git/refs',
164 '/foo/.git/objects',
165 '/foo/.git/worktrees',
166 '/foo/.git/worktrees/foo',
169 files = set(
171 '/foo/.git/HEAD',
172 '/foo/.git/worktrees/foo/HEAD',
173 '/foo/.git/worktrees/foo/index',
174 '/foo/.git/worktrees/foo/commondir',
175 '/foo/.git/worktrees/foo/gitdir',
178 islink.return_value = False
179 isfile.side_effect = lambda x: x in files
180 isdir.side_effect = lambda x: x in dirs
182 assert git.is_git_dir('/foo/.git/worktrees/foo')
183 assert git.is_git_dir('/foo/.git')
186 @patch('cola.core.getenv')
187 @patch('cola.git.is_git_dir')
188 def test_find_git_worktree_from_GIT_DIR(is_git_dir, getenv):
189 git_dir = '/repo/.git'
190 worktree = '/repo'
191 is_git_dir.return_value = True
192 getenv.side_effect = lambda x: x == 'GIT_DIR' and '/repo/.git' or None
194 paths = git.find_git_directory(git_dir)
195 assert is_git_dir.called
196 assert git_dir == paths.git_dir
197 assert paths.git_file is None
198 assert worktree == paths.worktree
201 @patch('cola.git.is_git_dir')
202 def test_finds_no_worktree_from_bare_repo(is_git_dir):
203 git_dir = '/repos/bare.git'
204 worktree = None
205 is_git_dir.return_value = True
207 paths = git.find_git_directory(git_dir)
208 assert is_git_dir.called
209 assert git_dir == paths.git_dir
210 assert paths.git_file is None
211 assert worktree == paths.worktree
214 @patch('cola.core.getenv')
215 @patch('cola.git.is_git_dir')
216 def test_find_git_directory_uses_GIT_WORK_TREE(is_git_dir, getenv):
217 git_dir = '/repo/worktree/.git'
218 worktree = '/repo/worktree'
220 def is_git_dir_fn(path):
221 return path == git_dir
223 is_git_dir.side_effect = is_git_dir_fn
225 def getenv_fn(name):
226 if name == 'GIT_WORK_TREE':
227 return worktree
228 return None
230 getenv.side_effect = getenv_fn
232 paths = git.find_git_directory(worktree)
233 assert is_git_dir.called
234 assert git_dir == paths.git_dir
235 assert paths.git_file is None
236 assert worktree == paths.worktree
239 @patch('cola.core.getenv')
240 @patch('cola.git.is_git_dir')
241 def test_uses_cwd_for_worktree_with_GIT_DIR(is_git_dir, getenv):
242 git_dir = '/repo/.yadm/repo.git'
243 worktree = '/repo'
245 def getenv_fn(name):
246 if name == 'GIT_DIR':
247 return git_dir
248 return None
250 getenv.side_effect = getenv_fn
252 def is_git_dir_fn(path):
253 return path == git_dir
255 is_git_dir.side_effect = is_git_dir_fn
257 paths = git.find_git_directory(worktree)
258 assert is_git_dir.called
259 assert getenv.called
260 assert git_dir == paths.git_dir
261 assert paths.git_file is None
262 assert worktree == paths.worktree
265 def test_transform_kwargs_empty():
266 expect = []
267 actual = git.transform_kwargs(foo=None, bar=False)
268 assert expect == actual
271 def test_transform_kwargs_single_dash_from_True():
272 """Single dash for one-character True"""
273 expect = ['-a']
274 actual = git.transform_kwargs(a=True)
275 assert expect == actual
278 def test_transform_kwargs_no_single_dash_from_False():
279 """No single-dash for False"""
280 expect = []
281 actual = git.transform_kwargs(a=False)
282 assert expect == actual
285 def test_transform_kwargs_double_dash_from_True():
286 """Double-dash for longer True"""
287 expect = ['--abc']
288 actual = git.transform_kwargs(abc=True)
289 assert expect == actual
292 def test_transform_kwargs_no_double_dash_from_True():
293 """No double-dash for False"""
294 expect = []
295 actual = git.transform_kwargs(abc=False)
296 assert expect == actual
299 def test_transform_kwargs_single_dash_int():
300 expect = ['-a1']
301 actual = git.transform_kwargs(a=1)
302 assert expect == actual
305 def test_transform_kwargs_double_dash_int():
306 expect = ['--abc=1']
307 actual = git.transform_kwargs(abc=1)
308 assert expect == actual
311 def test_transform_kwargs_single_dash_float():
312 expect = ['-a1.5']
313 actual = git.transform_kwargs(a=1.5)
314 assert expect == actual
317 def test_transform_kwargs_double_dash_float():
318 expect = ['--abc=1.5']
319 actual = git.transform_kwargs(abc=1.5)
320 assert expect == actual
323 def test_transform_kwargs_single_dash_string():
324 expect = ['-abc']
325 actual = git.transform_kwargs(a='bc')
326 assert expect == actual
329 def test_transform_double_single_dash_string():
330 expect = ['--abc=def']
331 actual = git.transform_kwargs(abc='def')
332 assert expect == actual
335 def test_version():
336 """Test running 'git version'"""
337 gitcmd = git.Git()
338 version = gitcmd.version()[STDOUT]
339 assert version.startswith('git version')
342 def test_stdout():
343 """Test overflowing the stdout buffer"""
344 # Write to stdout only
345 code = r'import sys; value = "\0" * %d; sys.stdout.write(value);' % BUFFER_SIZE
346 status, out, err = git.Git.execute(['python', '-c', code], _raw=True)
348 assert status == 0
349 expect = BUFFER_SIZE
350 actual = len(out)
351 assert expect == actual
353 expect = 0
354 actual = len(err)
355 assert expect == actual
358 def test_stderr():
359 """Test that stderr is seen"""
360 # Write to stderr and capture it
361 code = (
362 r'import sys;' r'value = "\0" * %d;' r'sys.stderr.write(value);'
363 ) % BUFFER_SIZE
365 status, out, err = git.Git.execute(['python', '-c', code], _raw=True)
367 expect = 0
368 actual = status
369 assert expect == actual
371 expect = 0
372 actual = len(out)
373 assert expect == actual
375 expect = BUFFER_SIZE
376 actual = len(err)
377 assert expect == actual
380 def test_stdout_and_stderr():
381 """Test ignoring stderr when stdout+stderr are provided (v2)"""
382 # Write to stdout and stderr but only capture stdout
383 code = (
384 r'import sys;'
385 r'value = "\0" * %d;'
386 r'sys.stdout.write(value);'
387 r'sys.stderr.write(value);'
388 ) % BUFFER_SIZE
390 status, out, err = git.Git.execute(['python', '-c', code], _raw=True)
392 expect = 0
393 actual = status
394 assert expect == actual
396 expect = BUFFER_SIZE
397 actual = len(out)
398 assert expect == actual
400 actual = len(err)
401 assert expect == actual
404 def test_it_doesnt_deadlock():
405 """Test that we don't deadlock with both stderr and stdout"""
406 code = (
407 r'import sys;'
408 r'value = "\0" * %d;'
409 r'sys.stderr.write(value);'
410 r'sys.stdout.write(value);'
411 ) % BUFFER_SIZE
413 status, out, err = git.Git.execute(['python', '-c', code], _raw=True)
415 expect = 0
416 actual = status
417 assert expect == actual
419 expect = '\0' * BUFFER_SIZE
420 actual = out
421 assert expect == actual
423 actual = err
424 assert expect == actual