gitcfg: remove unused `*paths` argument in GitConfig.hooks()
[git-cola.git] / test / git_test.py
blob858a60c54a8f99cc493d7859d9c9cc457fc92e11
1 #!/usr/bin/env python
2 """Tests various operations using the cola.git module
3 """
4 from __future__ import absolute_import, division, unicode_literals
5 import unittest
7 try:
8 from unittest.mock import patch
9 except ImportError:
10 from mock import patch
12 from cola import git
13 from cola.git import STDOUT
16 class GitModuleTestCase(unittest.TestCase):
17 @patch('cola.git.is_git_dir')
18 def test_find_git_dir_None(self, is_git_dir):
20 paths = git.find_git_directory(None)
22 self.assertFalse(is_git_dir.called)
23 self.assertEqual(None, paths.git_dir)
24 self.assertEqual(None, paths.git_file)
25 self.assertEqual(None, paths.worktree)
27 @patch('cola.git.is_git_dir')
28 def test_find_git_dir_empty_string(self, is_git_dir):
30 paths = git.find_git_directory('')
32 self.assertFalse(is_git_dir.called)
33 self.assertEqual(None, paths.git_dir)
34 self.assertEqual(None, paths.git_file)
35 self.assertEqual(None, paths.worktree)
37 @patch('cola.git.is_git_dir')
38 def test_find_git_dir_never_found(self, is_git_dir):
39 is_git_dir.return_value = False
41 paths = git.find_git_directory('/does/not/exist')
43 self.assertTrue(is_git_dir.called)
44 self.assertEqual(None, paths.git_dir)
45 self.assertEqual(None, paths.git_file)
46 self.assertEqual(None, paths.worktree)
48 self.assertEqual(8, is_git_dir.call_count)
49 kwargs = {}
50 is_git_dir.assert_has_calls(
52 (('/does/not/exist',), kwargs),
53 (('/does/not/exist/.git',), kwargs),
54 (('/does/not',), kwargs),
55 (('/does/not/.git',), kwargs),
56 (('/does',), kwargs),
57 (('/does/.git',), kwargs),
58 (('/',), kwargs),
59 (('/.git',), kwargs),
63 @patch('cola.git.is_git_dir')
64 def test_find_git_dir_found_right_away(self, 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 self.assertTrue(is_git_dir.called)
72 self.assertEqual(git_dir, paths.git_dir)
73 self.assertEqual(None, paths.git_file)
74 self.assertEqual(worktree, paths.worktree)
76 @patch('cola.git.is_git_dir')
77 def test_find_git_does_discovery(self, is_git_dir):
78 git_dir = '/the/root/.git'
79 worktree = '/the/root'
80 is_git_dir.side_effect = lambda x: x == git_dir
82 paths = git.find_git_directory('/the/root/sub/dir')
84 self.assertEqual(git_dir, paths.git_dir)
85 self.assertEqual(None, paths.git_file)
86 self.assertEqual(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(self, is_git_dir, is_git_file, read_git_file):
92 git_file = '/the/root/.git'
93 worktree = '/the/root'
94 git_dir = '/super/module/.git/modules/root'
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('/the/root/sub/dir')
102 self.assertEqual(git_dir, paths.git_dir)
103 self.assertEqual(git_file, paths.git_file)
104 self.assertEqual(worktree, paths.worktree)
106 kwargs = {}
107 self.assertEqual(6, is_git_dir.call_count)
108 is_git_dir.assert_has_calls(
110 (('/the/root/sub/dir',), kwargs),
111 (('/the/root/sub/dir/.git',), kwargs),
112 (('/the/root/sub',), kwargs),
113 (('/the/root/sub/.git',), kwargs),
114 (('/the/root',), kwargs),
115 (('/the/root/.git',), kwargs),
118 read_git_file.assert_called_once_with('/the/root/.git')
120 @patch('cola.core.getenv')
121 @patch('cola.git.is_git_dir')
122 def test_find_git_honors_ceiling_dirs(self, is_git_dir, getenv):
124 git_dir = '/ceiling/.git'
125 ceiling = '/tmp:/ceiling:/other/ceiling'
126 is_git_dir.side_effect = lambda x: x == git_dir
128 def mock_getenv(k, v=None):
129 if k == 'GIT_CEILING_DIRECTORIES':
130 return ceiling
131 return v
133 getenv.side_effect = mock_getenv
135 paths = git.find_git_directory('/ceiling/sub/dir')
137 self.assertEqual(None, paths.git_dir)
138 self.assertEqual(None, paths.git_file)
139 self.assertEqual(None, paths.worktree)
141 self.assertEqual(4, is_git_dir.call_count)
142 kwargs = {}
143 is_git_dir.assert_has_calls(
145 (('/ceiling/sub/dir',), kwargs),
146 (('/ceiling/sub/dir/.git',), kwargs),
147 (('/ceiling/sub',), kwargs),
148 (('/ceiling/sub/.git',), kwargs),
152 @patch('cola.core.islink')
153 @patch('cola.core.isdir')
154 @patch('cola.core.isfile')
155 def test_is_git_dir_finds_linked_repository(self, isfile, isdir, islink):
156 dirs = set(
158 '/foo',
159 '/foo/.git',
160 '/foo/.git/refs',
161 '/foo/.git/objects',
162 '/foo/.git/worktrees',
163 '/foo/.git/worktrees/foo',
166 files = set(
168 '/foo/.git/HEAD',
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 self.assertTrue(git.is_git_dir('/foo/.git/worktrees/foo'))
180 self.assertTrue(git.is_git_dir('/foo/.git'))
182 @patch('cola.core.getenv')
183 @patch('cola.git.is_git_dir')
184 def test_find_git_worktree_from_GIT_DIR(self, is_git_dir, getenv):
185 git_dir = '/repo/.git'
186 worktree = '/repo'
187 is_git_dir.return_value = True
188 getenv.side_effect = lambda x: x == 'GIT_DIR' and '/repo/.git' or None
190 paths = git.find_git_directory(git_dir)
191 self.assertTrue(is_git_dir.called)
192 self.assertEqual(git_dir, paths.git_dir)
193 self.assertEqual(None, paths.git_file)
194 self.assertEqual(worktree, paths.worktree)
196 @patch('cola.git.is_git_dir')
197 def test_finds_no_worktree_from_bare_repo(self, is_git_dir):
198 git_dir = '/repos/bare.git'
199 worktree = None
200 is_git_dir.return_value = True
202 paths = git.find_git_directory(git_dir)
203 self.assertTrue(is_git_dir.called)
204 self.assertEqual(git_dir, paths.git_dir)
205 self.assertEqual(None, paths.git_file)
206 self.assertEqual(worktree, paths.worktree)
208 @patch('cola.core.getenv')
209 @patch('cola.git.is_git_dir')
210 def test_find_git_directory_uses_GIT_WORK_TREE(self, is_git_dir, getenv):
211 git_dir = '/repo/worktree/.git'
212 worktree = '/repo/worktree'
214 def is_git_dir_fn(path):
215 return path == git_dir
217 is_git_dir.side_effect = is_git_dir_fn
219 def getenv_fn(name):
220 if name == 'GIT_WORK_TREE':
221 return worktree
222 return None
224 getenv.side_effect = getenv_fn
226 paths = git.find_git_directory(worktree)
227 self.assertTrue(is_git_dir.called)
228 self.assertEqual(git_dir, paths.git_dir)
229 self.assertEqual(None, paths.git_file)
230 self.assertEqual(worktree, paths.worktree)
232 @patch('cola.core.getenv')
233 @patch('cola.git.is_git_dir')
234 def test_uses_cwd_for_worktree_with_GIT_DIR(self, is_git_dir, getenv):
235 git_dir = '/repo/.yadm/repo.git'
236 worktree = '/repo'
238 def getenv_fn(name):
239 if name == 'GIT_DIR':
240 return git_dir
241 return None
243 getenv.side_effect = getenv_fn
245 def is_git_dir_fn(path):
246 return path == git_dir
248 is_git_dir.side_effect = is_git_dir_fn
250 paths = git.find_git_directory(worktree)
251 self.assertTrue(is_git_dir.called)
252 self.assertTrue(getenv.called)
253 self.assertEqual(git_dir, paths.git_dir)
254 self.assertEqual(None, paths.git_file)
255 self.assertEqual(worktree, paths.worktree)
258 class GitCommandTest(unittest.TestCase):
259 """Runs tests using a git.Git instance"""
261 def setUp(self):
262 """Creates a git.Git instance for later use"""
263 self.git = git.Git()
265 def test_transform_kwargs_empty(self):
266 expect = []
267 actual = git.transform_kwargs(foo=None, bar=False)
268 self.assertEqual(expect, actual)
270 def test_transform_kwargs_single_dash_from_True(self):
271 """Single dash for one-character True"""
272 expect = ['-a']
273 actual = git.transform_kwargs(a=True)
274 self.assertEqual(expect, actual)
276 def test_transform_kwargs_no_single_dash_from_False(self):
277 """No single-dash for False"""
278 expect = []
279 actual = git.transform_kwargs(a=False)
280 self.assertEqual(expect, actual)
282 def test_transform_kwargs_double_dash_from_True(self):
283 """Double-dash for longer True"""
284 expect = ['--abc']
285 actual = git.transform_kwargs(abc=True)
286 self.assertEqual(expect, actual)
288 def test_transform_kwargs_no_double_dash_from_True(self):
289 """No double-dash for False"""
290 expect = []
291 actual = git.transform_kwargs(abc=False)
292 self.assertEqual(expect, actual)
294 def test_transform_kwargs_single_dash_int(self):
295 expect = ['-a1']
296 actual = git.transform_kwargs(a=1)
297 self.assertEqual(expect, actual)
299 def test_transform_kwargs_double_dash_int(self):
300 expect = ['--abc=1']
301 actual = git.transform_kwargs(abc=1)
302 self.assertEqual(expect, actual)
304 def test_transform_kwargs_single_dash_float(self):
305 expect = ['-a1.5']
306 actual = git.transform_kwargs(a=1.5)
307 self.assertEqual(expect, actual)
309 def test_transform_kwargs_double_dash_float(self):
310 expect = ['--abc=1.5']
311 actual = git.transform_kwargs(abc=1.5)
312 self.assertEqual(expect, actual)
314 def test_transform_kwargs_single_dash_string(self):
315 expect = ['-abc']
316 actual = git.transform_kwargs(a='bc')
317 self.assertEqual(expect, actual)
319 def test_transform_double_single_dash_string(self):
320 expect = ['--abc=def']
321 actual = git.transform_kwargs(abc='def')
322 self.assertEqual(expect, actual)
324 def test_version(self):
325 """Test running 'git version'"""
326 version = self.git.version()[STDOUT]
327 self.assertTrue(version.startswith('git version'))
329 def test_stdout(self):
330 """Test overflowing the stdout buffer"""
331 # Write to stdout only
332 code = r'import sys; s = "\0" * (1024 * 16 + 1); sys.stdout.write(s);'
333 status, out, err = git.Git.execute(['python', '-c', code], _raw=True)
334 self.assertEqual(status, 0)
335 self.assertEqual(len(out), 1024 * 16 + 1)
336 self.assertEqual(len(err), 0)
338 def test_stderr(self):
339 """Test that stderr is seen"""
340 # Write to stderr and capture it
341 code = r'import sys; s = "\0" * (1024 * 16 + 1); sys.stderr.write(s);'
342 status, out, err = git.Git.execute(['python', '-c', code], _raw=True)
343 self.assertEqual(status, 0)
344 self.assertEqual(len(out), 0)
345 self.assertEqual(len(err), 1024 * 16 + 1)
347 def test_stdout_and_stderr(self):
348 """Test ignoring stderr when stdout+stderr are provided (v2)"""
349 # Write to stdout and stderr but only capture stdout
350 code = (
351 'import sys;'
352 's = "\\0" * (1024 * 16 + 1);'
353 'sys.stdout.write(s);'
354 'sys.stderr.write(s);'
356 status, out, err = git.Git.execute(['python', '-c', code], _raw=True)
357 self.assertEqual(status, 0)
358 self.assertEqual(len(out), 1024 * 16 + 1)
359 self.assertEqual(len(err), 1024 * 16 + 1)
361 def test_it_doesnt_deadlock(self):
362 """Test that we don't deadlock with both stderr and stdout"""
363 # 16k+1 bytes to exhaust any output buffers
364 code = (
365 'import sys;'
366 's = "\\0" * (1024 * 16 + 1);'
367 'sys.stderr.write(s);'
368 'sys.stdout.write(s);'
370 status, out, err = git.Git.execute(['python', '-c', code], _raw=True)
371 self.assertEqual(status, 0)
372 self.assertEqual(out, '\0' * (1024 * 16 + 1))
373 self.assertEqual(err, '\0' * (1024 * 16 + 1))
376 if __name__ == '__main__':
377 unittest.main()