1 """Test the cola.git module"""
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(str(pathlib
.Path('/does/not/exist').resolve()))
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
47 actual
= is_git_dir
.call_count
48 assert expect
== actual
49 is_git_dir
.assert_has_calls([
50 ((str(pathlib
.Path('/does/not/exist').resolve()),), {}),
51 ((str(pathlib
.Path('/does/not/exist/.git').resolve()),), {}),
52 ((str(pathlib
.Path('/does/not').resolve()),), {}),
53 ((str(pathlib
.Path('/does/not/.git').resolve()),), {}),
54 ((str(pathlib
.Path('/does').resolve()),), {}),
55 ((str(pathlib
.Path('/does/.git').resolve()),), {}),
56 ((str(pathlib
.Path('/').resolve()),), {}),
57 ((str(pathlib
.Path('/.git').resolve()),), {}),
61 @patch('cola.git.is_git_dir')
62 def test_find_git_dir_found_right_away(is_git_dir
):
63 git_dir
= str(pathlib
.Path('/seems/to/exist/.git').resolve())
64 worktree
= str(pathlib
.Path('/seems/to/exist').resolve())
65 is_git_dir
.return_value
= True
67 paths
= git
.find_git_directory(git_dir
)
69 assert is_git_dir
.called
70 assert git_dir
== paths
.git_dir
71 assert paths
.git_file
is None
72 assert worktree
== paths
.worktree
75 @patch('cola.git.is_git_dir')
76 def test_find_git_does_discovery(is_git_dir
):
77 git_dir
= str(pathlib
.Path('/the/root/.git').resolve())
78 worktree
= str(pathlib
.Path('/the/root').resolve())
79 is_git_dir
.side_effect
= lambda x
: x
== git_dir
81 paths
= git
.find_git_directory('/the/root/sub/dir')
83 assert git_dir
== paths
.git_dir
84 assert paths
.git_file
is None
85 assert worktree
== paths
.worktree
88 @patch('cola.git.read_git_file')
89 @patch('cola.git.is_git_file')
90 @patch('cola.git.is_git_dir')
91 def test_find_git_honors_git_files(is_git_dir
, is_git_file
, read_git_file
):
92 git_file
= str(pathlib
.Path('/the/root/.git').resolve())
93 worktree
= str(pathlib
.Path('/the/root').resolve())
94 git_dir
= str(pathlib
.Path('/super/module/.git/modules/root').resolve())
96 is_git_dir
.side_effect
= lambda x
: x
== git_file
97 is_git_file
.side_effect
= lambda x
: x
== git_file
98 read_git_file
.return_value
= git_dir
100 paths
= git
.find_git_directory(str(pathlib
.Path('/the/root/sub/dir').resolve()))
102 assert git_dir
== paths
.git_dir
103 assert git_file
== paths
.git_file
104 assert worktree
== paths
.worktree
107 actual
= is_git_dir
.call_count
108 assert expect
== actual
109 is_git_dir
.assert_has_calls([
110 ((str(pathlib
.Path('/the/root/sub/dir').resolve()),), {}),
111 ((str(pathlib
.Path('/the/root/sub/dir/.git').resolve()),), {}),
112 ((str(pathlib
.Path('/the/root/sub').resolve()),), {}),
113 ((str(pathlib
.Path('/the/root/sub/.git').resolve()),), {}),
114 ((str(pathlib
.Path('/the/root').resolve()),), {}),
115 ((str(pathlib
.Path('/the/root/.git').resolve()),), {}),
117 read_git_file
.assert_called_once_with(git_file
)
120 @patch('cola.core.getenv')
121 @patch('cola.git.is_git_dir')
122 def test_find_git_honors_ceiling_dirs(is_git_dir
, getenv
):
123 git_dir
= str(pathlib
.Path('/ceiling/.git').resolve())
124 ceiling
= os
.pathsep
.join(
125 str(pathlib
.Path(path
).resolve())
126 for path
in ('/tmp', '/ceiling', '/other/ceiling')
128 is_git_dir
.side_effect
= lambda x
: x
== git_dir
130 def mock_getenv(k
, v
=None):
131 if k
== 'GIT_CEILING_DIRECTORIES':
135 getenv
.side_effect
= mock_getenv
136 paths
= git
.find_git_directory(str(pathlib
.Path('/ceiling/sub/dir').resolve()))
138 assert paths
.git_dir
is None
139 assert paths
.git_file
is None
140 assert paths
.worktree
is None
141 assert is_git_dir
.call_count
== 4
142 is_git_dir
.assert_has_calls([
143 ((str(pathlib
.Path('/ceiling/sub/dir').resolve()),), {}),
144 ((str(pathlib
.Path('/ceiling/sub/dir/.git').resolve()),), {}),
145 ((str(pathlib
.Path('/ceiling/sub').resolve()),), {}),
146 ((str(pathlib
.Path('/ceiling/sub/.git').resolve()),), {}),
150 @patch('cola.core.islink')
151 @patch('cola.core.isdir')
152 @patch('cola.core.isfile')
153 def test_is_git_dir_finds_linked_repository(isfile
, isdir
, islink
):
155 str(pathlib
.Path(directory
).resolve())
161 '/foo/.git/worktrees',
162 '/foo/.git/worktrees/foo',
166 str(pathlib
.Path(file).resolve())
169 '/foo/.git/worktrees/foo/HEAD',
170 '/foo/.git/worktrees/foo/index',
171 '/foo/.git/worktrees/foo/commondir',
172 '/foo/.git/worktrees/foo/gitdir',
175 islink
.return_value
= False
176 isfile
.side_effect
= lambda x
: x
in files
177 isdir
.side_effect
= lambda x
: x
in dirs
179 assert git
.is_git_dir(str(pathlib
.Path('/foo/.git/worktrees/foo').resolve()))
180 assert git
.is_git_dir(str(pathlib
.Path('/foo/.git').resolve()))
183 @patch('cola.core.getenv')
184 @patch('cola.git.is_git_dir')
185 def test_find_git_worktree_from_GIT_DIR(is_git_dir
, getenv
):
186 git_dir
= str(pathlib
.Path('/repo/.git').resolve())
187 worktree
= str(pathlib
.Path('/repo').resolve())
188 is_git_dir
.return_value
= True
189 getenv
.side_effect
= lambda x
: x
== 'GIT_DIR' and git_dir
or None
191 paths
= git
.find_git_directory(git_dir
)
192 assert is_git_dir
.called
193 assert git_dir
== paths
.git_dir
194 assert paths
.git_file
is None
195 assert worktree
== paths
.worktree
198 @patch('cola.git.is_git_dir')
199 def test_finds_no_worktree_from_bare_repo(is_git_dir
):
200 git_dir
= str(pathlib
.Path('/repos/bare.git').resolve())
202 is_git_dir
.return_value
= True
204 paths
= git
.find_git_directory(git_dir
)
205 assert is_git_dir
.called
206 assert git_dir
== paths
.git_dir
207 assert paths
.git_file
is None
208 assert worktree
== paths
.worktree
211 @patch('cola.core.getenv')
212 @patch('cola.git.is_git_dir')
213 def test_find_git_directory_uses_GIT_WORK_TREE(is_git_dir
, getenv
):
214 git_dir
= str(pathlib
.Path('/repo/worktree/.git').resolve())
215 worktree
= str(pathlib
.Path('/repo/worktree').resolve())
217 def is_git_dir_func(path
):
218 return path
== git_dir
220 is_git_dir
.side_effect
= is_git_dir_func
222 def getenv_func(name
):
223 if name
== 'GIT_WORK_TREE':
227 getenv
.side_effect
= getenv_func
229 paths
= git
.find_git_directory(worktree
)
230 assert is_git_dir
.called
231 assert git_dir
== paths
.git_dir
232 assert paths
.git_file
is None
233 assert worktree
== paths
.worktree
236 @patch('cola.core.getenv')
237 @patch('cola.git.is_git_dir')
238 def test_uses_cwd_for_worktree_with_GIT_DIR(is_git_dir
, getenv
):
239 git_dir
= str(pathlib
.Path('/repo/.yadm/repo.git').resolve())
240 worktree
= str(pathlib
.Path('/repo').resolve())
242 def getenv_func(name
):
243 if name
== 'GIT_DIR':
247 getenv
.side_effect
= getenv_func
249 def is_git_dir_func(path
):
250 return path
== git_dir
252 is_git_dir
.side_effect
= is_git_dir_func
254 paths
= git
.find_git_directory(worktree
)
255 assert is_git_dir
.called
257 assert git_dir
== paths
.git_dir
258 assert paths
.git_file
is None
259 assert worktree
== paths
.worktree
262 def test_transform_kwargs_empty():
264 actual
= git
.transform_kwargs(foo
=None, bar
=False)
265 assert expect
== actual
268 def test_transform_kwargs_single_dash_from_True():
269 """Single dash for one-character True"""
271 actual
= git
.transform_kwargs(a
=True)
272 assert expect
== actual
275 def test_transform_kwargs_no_single_dash_from_False():
276 """No single-dash for False"""
278 actual
= git
.transform_kwargs(a
=False)
279 assert expect
== actual
282 def test_transform_kwargs_double_dash_from_True():
283 """Double-dash for longer True"""
285 actual
= git
.transform_kwargs(abc
=True)
286 assert expect
== actual
289 def test_transform_kwargs_no_double_dash_from_True():
290 """No double-dash for False"""
292 actual
= git
.transform_kwargs(abc
=False)
293 assert expect
== actual
296 def test_transform_kwargs_single_dash_int():
298 actual
= git
.transform_kwargs(a
=1)
299 assert expect
== actual
302 def test_transform_kwargs_double_dash_int():
304 actual
= git
.transform_kwargs(abc
=1)
305 assert expect
== actual
308 def test_transform_kwargs_single_dash_float():
310 actual
= git
.transform_kwargs(a
=1.5)
311 assert expect
== actual
314 def test_transform_kwargs_double_dash_float():
315 expect
= ['--abc=1.5']
316 actual
= git
.transform_kwargs(abc
=1.5)
317 assert expect
== actual
320 def test_transform_kwargs_single_dash_string():
322 actual
= git
.transform_kwargs(a
='bc')
323 assert expect
== actual
326 def test_transform_double_single_dash_string():
327 expect
= ['--abc=def']
328 actual
= git
.transform_kwargs(abc
='def')
329 assert expect
== actual
333 """Test running 'git version'"""
335 version
= gitcmd
.version()[STDOUT
]
336 assert version
.startswith('git version')
340 """Test overflowing the stdout buffer"""
341 # Write to stdout only
342 code
= r
'import sys; value = "\0" * %d; sys.stdout.write(value);' % BUFFER_SIZE
343 status
, out
, err
= git
.Git
.execute(['python', '-c', code
], _raw
=True)
348 assert expect
== actual
352 assert expect
== actual
356 """Test that stderr is seen"""
357 # Write to stderr and capture it
359 r
'import sys;' r
'value = "\0" * %d;' r
'sys.stderr.write(value);'
362 status
, out
, err
= git
.Git
.execute(['python', '-c', code
], _raw
=True)
366 assert expect
== actual
370 assert expect
== actual
374 assert expect
== actual
377 def test_stdout_and_stderr():
378 """Test ignoring stderr when stdout+stderr are provided (v2)"""
379 # Write to stdout and stderr but only capture stdout
382 r
'value = "\0" * %d;'
383 r
'sys.stdout.write(value);'
384 r
'sys.stderr.write(value);'
387 status
, out
, err
= git
.Git
.execute(['python', '-c', code
], _raw
=True)
391 assert expect
== actual
395 assert expect
== actual
398 assert expect
== actual
401 def test_it_doesnt_deadlock():
402 """Test that we don't deadlock with both stderr and stdout"""
405 r
'value = "\0" * %d;'
406 r
'sys.stderr.write(value);'
407 r
'sys.stdout.write(value);'
410 status
, out
, err
= git
.Git
.execute(['python', '-c', code
], _raw
=True)
414 assert expect
== actual
416 expect
= '\0' * BUFFER_SIZE
418 assert expect
== actual
421 assert expect
== actual