summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/clash_path_file4
-rw-r--r--tests/conftest.py1
-rw-r--r--tests/main_path_file2
-rw-r--r--tests/mock_group_file4
-rw-r--r--tests/mock_path_file2
-rw-r--r--tests/test_info.py4
-rw-r--r--tests/test_main.py271
-rw-r--r--tests/test_utils.py85
8 files changed, 281 insertions, 92 deletions
diff --git a/tests/clash_path_file b/tests/clash_path_file
index 4abbfca..33eeae2 100644
--- a/tests/clash_path_file
+++ b/tests/clash_path_file
@@ -1,3 +1,3 @@
-/a/bcd/repo1,repo1
-/e/fgh/repo2,repo2
+/a/bcd/repo1,repo1,
+/e/fgh/repo2,repo2,,--haha --pp
/root/x/repo1,repo1
diff --git a/tests/conftest.py b/tests/conftest.py
index b3e59ed..93576d6 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -11,6 +11,7 @@ def fullpath(fname: str):
PATH_FNAME = fullpath('mock_path_file')
PATH_FNAME_EMPTY = fullpath('empty_path_file')
PATH_FNAME_CLASH = fullpath('clash_path_file')
+PATH_FNAME_MAIN = fullpath('main_path_file')
GROUP_FNAME = fullpath('mock_group_file')
def async_mock():
diff --git a/tests/main_path_file b/tests/main_path_file
new file mode 100644
index 0000000..8e87ffb
--- /dev/null
+++ b/tests/main_path_file
@@ -0,0 +1,2 @@
+/path/to/main/,main1,m
+/xxx/xx,xx,
diff --git a/tests/mock_group_file b/tests/mock_group_file
index 32f0a64..1187366 100644
--- a/tests/mock_group_file
+++ b/tests/mock_group_file
@@ -1,2 +1,2 @@
-xx: [a, b]
-yy: [a, c, d]
+xx:a b
+yy:a c d
diff --git a/tests/mock_path_file b/tests/mock_path_file
index 2a5f9f9..81dc9ef 100644
--- a/tests/mock_path_file
+++ b/tests/mock_path_file
@@ -1,4 +1,4 @@
/a/bcd/repo1,repo1
-/a/b/c/repo3,xxx
+/a/b/c/repo3,xxx,,
/e/fgh/repo2,repo2
diff --git a/tests/test_info.py b/tests/test_info.py
index 025aedc..c234d78 100644
--- a/tests/test_info.py
+++ b/tests/test_info.py
@@ -8,9 +8,9 @@ from gita import info
def test_run_quiet_diff(mock_run):
mock_return = MagicMock()
mock_run.return_value = mock_return
- got = info.run_quiet_diff(['my', 'args'])
+ got = info.run_quiet_diff(['--flags'], ['my', 'args'])
mock_run.assert_called_once_with(
- ['git', 'diff', '--quiet', 'my', 'args'],
+ ['git', '--flags', 'diff', '--quiet', 'my', 'args'],
stderr=subprocess.DEVNULL,
)
assert got == mock_return.returncode
diff --git a/tests/test_main.py b/tests/test_main.py
index ad501f7..490f5d2 100644
--- a/tests/test_main.py
+++ b/tests/test_main.py
@@ -1,28 +1,102 @@
+import os
import pytest
-from unittest.mock import patch, mock_open
+from unittest.mock import patch
from pathlib import Path
import argparse
+import asyncio
import shlex
from gita import __main__
-from gita import utils, info
+from gita import utils, info, common
from conftest import (
- PATH_FNAME, PATH_FNAME_EMPTY, PATH_FNAME_CLASH, GROUP_FNAME,
+ PATH_FNAME, PATH_FNAME_EMPTY, PATH_FNAME_CLASH, GROUP_FNAME, PATH_FNAME_MAIN,
async_mock, TEST_DIR,
)
+@patch('gita.utils.get_repos', return_value={'aa'})
+def test_group_name(_):
+ got = __main__._group_name('xx')
+ assert got == 'xx'
+ with pytest.raises(SystemExit):
+ __main__._group_name('aa')
+
+
+class TestAdd:
+
+ @pytest.mark.parametrize('input, expected', [
+ (['add', '.'], ''),
+ (['add', '-m', '.'], 'm'),
+ ])
+ @patch('gita.common.get_config_fname')
+ def test_add(self, mock_path_fname, tmp_path, input, expected):
+ def side_effect(input, _=None):
+ return tmp_path / f'{input}.txt'
+ mock_path_fname.side_effect = side_effect
+ utils.get_repos.cache_clear()
+ __main__.main(input)
+ utils.get_repos.cache_clear()
+ got = utils.get_repos()
+ assert len(got) == 1
+ assert got['gita']['type'] == expected
+
+ @patch('gita.utils.is_git', return_value=True)
+ def test_add_main(self, _, tmp_path, monkeypatch, tmpdir):
+ def side_effect(root=None):
+ if root is None:
+ return os.path.join(tmp_path, "gita")
+ else:
+ return os.path.join(root, ".gita")
+
+ def desc(repos, **_):
+ print(len(repos), repos.keys())
+ assert len(repos) > 0
+ for r, prop in repos.items():
+ if prop['type'] == 'm':
+ assert 'test_add_main' in r
+ break
+ else:
+ assert 0, 'no main repo found'
+ return ''
+
+ monkeypatch.setattr(common, 'get_config_dir', side_effect)
+ monkeypatch.setattr(utils, 'describe', desc)
+
+ utils.get_repos.cache_clear()
+
+ with tmpdir.as_cwd():
+ __main__.main(['add', '-m', '.'])
+ utils.get_repos.cache_clear()
+ __main__.main(['ll'])
+
+
+@pytest.mark.parametrize('path_fname, expected', [
+ (PATH_FNAME, ''),
+ (PATH_FNAME_CLASH, "repo2: ['--haha', '--pp']\n"),
+ ])
+@patch('gita.utils.is_git', return_value=True)
+@patch('gita.utils.get_groups', return_value={})
+@patch('gita.common.get_config_fname')
+def test_flags(mock_path_fname, _, __, path_fname, expected, capfd):
+ mock_path_fname.return_value = path_fname
+ utils.get_repos.cache_clear()
+ __main__.main(['flags'])
+ out, err = capfd.readouterr()
+ assert err == ''
+ assert out == expected
+
+
class TestLsLl:
@patch('gita.common.get_config_fname')
- def testLl(self, mock_path_fname, capfd, tmp_path):
+ def test_ll(self, mock_path_fname, capfd, tmp_path):
"""
functional test
"""
# avoid modifying the local configuration
- def side_effect(input):
+ def side_effect(input, _=None):
return tmp_path / f'{input}.txt'
- #mock_path_fname.return_value = tmp_path / 'path_config.txt'
mock_path_fname.side_effect = side_effect
+ utils.get_repos.cache_clear()
__main__.main(['add', '.'])
out, err = capfd.readouterr()
assert err == ''
@@ -52,11 +126,11 @@ class TestLsLl:
__main__.main(['ls', 'gita'])
out, err = capfd.readouterr()
assert err == ''
- assert out.strip() == utils.get_repos()['gita']
+ assert out.strip() == utils.get_repos()['gita']['path']
- def testLs(self, monkeypatch, capfd):
+ def test_ls(self, monkeypatch, capfd):
monkeypatch.setattr(utils, 'get_repos',
- lambda: {'repo1': '/a/', 'repo2': '/b/'})
+ lambda: {'repo1': {'path': '/a/'}, 'repo2': {'path': '/b/'}})
monkeypatch.setattr(utils, 'describe', lambda x: x)
__main__.main(['ls'])
out, err = capfd.readouterr()
@@ -69,21 +143,24 @@ class TestLsLl:
@pytest.mark.parametrize('path_fname, expected', [
(PATH_FNAME,
- "repo1 cmaster dsu\x1b[0m msg\nrepo2 cmaster dsu\x1b[0m msg\nxxx cmaster dsu\x1b[0m msg\n"),
+ "repo1 cmaster dsu\x1b[0m msg \nrepo2 cmaster dsu\x1b[0m msg \nxxx cmaster dsu\x1b[0m msg \n"),
(PATH_FNAME_EMPTY, ""),
+ (PATH_FNAME_MAIN,
+ '\x1b[4mmain1\x1b[0m cmaster dsu\x1b[0m msg \nxx cmaster dsu\x1b[0m msg \n'),
(PATH_FNAME_CLASH,
- "repo1 cmaster dsu\x1b[0m msg\nrepo2 cmaster dsu\x1b[0m msg\nx/repo1 cmaster dsu\x1b[0m msg\n"
+ "repo1 cmaster dsu\x1b[0m msg \nrepo2 cmaster dsu\x1b[0m msg \n"
),
])
@patch('gita.utils.is_git', return_value=True)
@patch('gita.info.get_head', return_value="master")
@patch('gita.info._get_repo_status', return_value=("d", "s", "u", "c"))
@patch('gita.info.get_commit_msg', return_value="msg")
+ @patch('gita.info.get_commit_time', return_value="")
@patch('gita.common.get_config_fname')
- def testWithPathFiles(self, mock_path_fname, _0, _1, _2, _3, path_fname,
+ def test_with_path_files(self, mock_path_fname, _0, _1, _2, _3, _4, path_fname,
expected, capfd):
- def side_effect(input):
- if input == 'repo_path':
+ def side_effect(input, _=None):
+ if input == 'repos.csv':
return path_fname
return f'/{input}'
mock_path_fname.side_effect = side_effect
@@ -95,25 +172,63 @@ class TestLsLl:
assert out == expected
+@pytest.mark.parametrize('input, expected', [
+ ({'repo1': {'path': '/a/'}, 'repo2': {'path': '/b/'}}, ''),
+ ])
@patch('subprocess.run')
-@patch('gita.utils.get_repos', return_value={'repo1': '/a/', 'repo2': '/b/'})
-def test_freeze(_, mock_run, capfd):
+@patch('gita.utils.get_repos')
+def test_freeze(mock_repos, mock_run, input, expected, capfd):
+ mock_repos.return_value = input
__main__.main(['freeze'])
assert mock_run.call_count == 2
out, err = capfd.readouterr()
assert err == ''
- assert out == ',repo1,/a/\n,repo2,/b/\n'
+ assert out == expected
+
+
+@patch('gita.utils.parse_clone_config', return_value=[
+ ['git@github.com:user/repo.git', 'repo', '/a/repo']])
+@patch('gita.utils.run_async', new=async_mock())
+@patch('subprocess.run')
+def test_clone(*_):
+ asyncio.set_event_loop(asyncio.new_event_loop())
+ args = argparse.Namespace()
+ args.fname = ['freeze_filename']
+ args.preserve_path = None
+ __main__.f_clone(args)
+ mock_run = utils.run_async.mock
+ assert mock_run.call_count == 1
+ cmds = ['git', 'clone', 'git@github.com:user/repo.git']
+ mock_run.assert_called_once_with('repo', Path.cwd(), cmds)
+
+
+@patch('gita.utils.parse_clone_config', return_value=[
+ ['git@github.com:user/repo.git', 'repo', '/a/repo']])
+@patch('gita.utils.run_async', new=async_mock())
+@patch('subprocess.run')
+def test_clone_with_preserve_path(*_):
+ asyncio.set_event_loop(asyncio.new_event_loop())
+ args = argparse.Namespace()
+ args.fname = ['freeze_filename']
+ args.preserve_path = True
+ __main__.f_clone(args)
+ mock_run = utils.run_async.mock
+ assert mock_run.call_count == 1
+ cmds = ['git', 'clone', 'git@github.com:user/repo.git', '/a/repo']
+ mock_run.assert_called_once_with('repo', Path.cwd(), cmds)
@patch('os.path.isfile', return_value=True)
@patch('gita.common.get_config_fname', return_value='some path')
-@patch('gita.utils.get_repos', return_value={'repo1': '/a/', 'repo2': '/b/'})
+@patch('gita.utils.get_repos', return_value={'repo1': {'path': '/a/', 'type': ''},
+ 'repo2': {'path': '/b/', 'type': ''}})
@patch('gita.utils.write_to_repo_file')
def test_rm(mock_write, *_):
args = argparse.Namespace()
args.repo = ['repo1']
__main__.f_rm(args)
- mock_write.assert_called_once_with({'repo2': '/b/'}, 'w')
+ mock_write.assert_called_once_with(
+ {'repo2': {'path': '/b/', 'type': ''}}, 'w')
def test_not_add():
@@ -121,17 +236,19 @@ def test_not_add():
__main__.main(['add', '/home/some/repo/'])
-@patch('gita.utils.get_repos', return_value={'repo2': '/d/efg'})
+@patch('gita.utils.get_repos', return_value={'repo2': {'path': '/d/efg',
+ 'flags': []}})
@patch('subprocess.run')
def test_fetch(mock_run, *_):
+ asyncio.set_event_loop(asyncio.new_event_loop())
__main__.main(['fetch'])
- mock_run.assert_called_once_with(['git', 'fetch'], cwd='/d/efg')
+ mock_run.assert_called_once_with(['git', 'fetch'], cwd='/d/efg', shell=False)
@patch(
'gita.utils.get_repos', return_value={
- 'repo1': '/a/bc',
- 'repo2': '/d/efg'
+ 'repo1': {'path': '/a/bc', 'flags': []},
+ 'repo2': {'path': '/d/efg', 'flags': []}
})
@patch('gita.utils.run_async', new=async_mock())
@patch('subprocess.run')
@@ -149,28 +266,28 @@ def test_async_fetch(*_):
'diff --name-only --staged',
"commit -am 'lala kaka'",
])
-@patch('gita.utils.get_repos', return_value={'repo7': 'path7'})
+@patch('gita.utils.get_repos', return_value={'repo7': {'path': 'path7', 'flags': []}})
@patch('subprocess.run')
def test_superman(mock_run, _, input):
mock_run.reset_mock()
args = ['super', 'repo7'] + shlex.split(input)
__main__.main(args)
expected_cmds = ['git'] + shlex.split(input)
- mock_run.assert_called_once_with(expected_cmds, cwd='path7')
+ mock_run.assert_called_once_with(expected_cmds, cwd='path7', shell=False)
@pytest.mark.parametrize('input', [
'diff --name-only --staged',
"commit -am 'lala kaka'",
])
-@patch('gita.utils.get_repos', return_value={'repo7': 'path7'})
+@patch('gita.utils.get_repos', return_value={'repo7': {'path': 'path7', 'flags': []}})
@patch('subprocess.run')
def test_shell(mock_run, _, input):
mock_run.reset_mock()
- args = ['shell', 'repo7'] + shlex.split(input)
+ args = ['shell', 'repo7', input]
__main__.main(args)
- expected_cmds = shlex.split(input)
- mock_run.assert_called_once_with(expected_cmds, cwd='path7', check=True, stderr=-2, stdout=-1)
+ expected_cmds = input
+ mock_run.assert_called_once_with(expected_cmds, cwd='path7', check=True, shell=True, stderr=-2, stdout=-1)
class TestContext:
@@ -184,21 +301,21 @@ class TestContext:
@patch('gita.utils.get_context', return_value=Path('gname.context'))
@patch('gita.utils.get_groups', return_value={'gname': ['a', 'b']})
- def testDisplayContext(self, _, __, capfd):
+ def test_display_context(self, _, __, capfd):
__main__.main(['context'])
out, err = capfd.readouterr()
assert err == ''
assert 'gname: a b\n' == out
@patch('gita.utils.get_context')
- def testReset(self, mock_ctx):
+ def test_reset(self, mock_ctx):
__main__.main(['context', 'none'])
mock_ctx.return_value.unlink.assert_called()
@patch('gita.utils.get_context', return_value=None)
@patch('gita.common.get_config_dir', return_value=TEST_DIR)
@patch('gita.utils.get_groups', return_value={'lala': ['b'], 'kaka': []})
- def testSetFirstTime(self, *_):
+ def test_set_first_time(self, *_):
ctx = TEST_DIR / 'lala.context'
assert not ctx.is_file()
__main__.main(['context', 'lala'])
@@ -208,7 +325,7 @@ class TestContext:
@patch('gita.common.get_config_dir', return_value=TEST_DIR)
@patch('gita.utils.get_groups', return_value={'lala': ['b'], 'kaka': []})
@patch('gita.utils.get_context')
- def testSetSecondTime(self, mock_ctx, *_):
+ def test_set_second_time(self, mock_ctx, *_):
__main__.main(['context', 'kaka'])
mock_ctx.return_value.rename.assert_called()
@@ -216,7 +333,7 @@ class TestContext:
class TestGroupCmd:
@patch('gita.common.get_config_fname', return_value=GROUP_FNAME)
- def testLs(self, _, capfd):
+ def test_ls(self, _, capfd):
args = argparse.Namespace()
args.to_group = None
args.group_cmd = 'ls'
@@ -227,7 +344,7 @@ class TestGroupCmd:
assert 'xx yy\n' == out
@patch('gita.common.get_config_fname', return_value=GROUP_FNAME)
- def testLl(self, _, capfd):
+ def test_ll(self, _, capfd):
args = argparse.Namespace()
args.to_group = None
args.group_cmd = None
@@ -239,7 +356,7 @@ class TestGroupCmd:
@patch('gita.common.get_config_fname', return_value=GROUP_FNAME)
@patch('gita.utils.write_to_groups_file')
- def testRename(self, mock_write, _):
+ def test_rename(self, mock_write, _):
args = argparse.Namespace()
args.gname = 'xx'
args.new_name = 'zz'
@@ -250,7 +367,7 @@ class TestGroupCmd:
mock_write.assert_called_once_with(expected, 'w')
@patch('gita.common.get_config_fname', return_value=GROUP_FNAME)
- def testRenameError(self, *_):
+ def test_rename_error(self, *_):
args = argparse.Namespace()
args.gname = 'xx'
args.new_name = 'yy'
@@ -266,7 +383,7 @@ class TestGroupCmd:
@patch('gita.utils.get_repos', return_value={'a': '', 'b': '', 'c': '', 'd': ''})
@patch('gita.common.get_config_fname', return_value=GROUP_FNAME)
@patch('gita.utils.write_to_groups_file')
- def testRm(self, mock_write, _, __, input, expected):
+ def test_rm(self, mock_write, _, __, input, expected):
utils.get_groups.cache_clear()
args = ['group', 'rm'] + shlex.split(input)
__main__.main(args)
@@ -275,7 +392,7 @@ class TestGroupCmd:
@patch('gita.utils.get_repos', return_value={'a': '', 'b': '', 'c': '', 'd': ''})
@patch('gita.common.get_config_fname', return_value=GROUP_FNAME)
@patch('gita.utils.write_to_groups_file')
- def testAdd(self, mock_write, *_):
+ def test_add(self, mock_write, *_):
args = argparse.Namespace()
args.to_group = ['a', 'c']
args.group_cmd = 'add'
@@ -287,7 +404,7 @@ class TestGroupCmd:
@patch('gita.utils.get_repos', return_value={'a': '', 'b': '', 'c': '', 'd': ''})
@patch('gita.common.get_config_fname', return_value=GROUP_FNAME)
@patch('gita.utils.write_to_groups_file')
- def testAddToExisting(self, mock_write, *_):
+ def test_add_to_existing(self, mock_write, *_):
args = argparse.Namespace()
args.to_group = ['a', 'c']
args.group_cmd = 'add'
@@ -300,7 +417,7 @@ class TestGroupCmd:
@patch('gita.utils.get_repos', return_value={'a': '', 'b': '', 'c': '', 'd': ''})
@patch('gita.common.get_config_fname', return_value=GROUP_FNAME)
@patch('gita.utils.write_to_groups_file')
- def testRmRepo(self, mock_write, *_):
+ def test_rm_repo(self, mock_write, *_):
args = argparse.Namespace()
args.from_group = ['a', 'c']
args.group_cmd = 'rmrepo'
@@ -310,6 +427,21 @@ class TestGroupCmd:
mock_write.assert_called_once_with(
{'xx': ['b'], 'yy': ['a', 'c', 'd']}, 'w')
+ @patch('gita.common.get_config_fname')
+ def test_integration(self, mock_path_fname, tmp_path, capfd):
+ def side_effect(input, _=None):
+ return tmp_path / f'{input}.csv'
+ mock_path_fname.side_effect = side_effect
+
+ __main__.main('add .'.split())
+ utils.get_repos.cache_clear()
+ __main__.main('group add gita -n test'.split())
+ utils.get_groups.cache_clear()
+ __main__.main('ll test'.split())
+ out, err = capfd.readouterr()
+ assert err == ''
+ assert 'gita' in out
+
@patch('gita.utils.is_git', return_value=True)
@patch('gita.common.get_config_fname', return_value=PATH_FNAME)
@@ -319,44 +451,61 @@ def test_rename(mock_rename, _, __):
args = ['rename', 'repo1', 'abc']
__main__.main(args)
mock_rename.assert_called_once_with(
- {'repo1': '/a/bcd/repo1', 'repo2': '/e/fgh/repo2',
- 'xxx': '/a/b/c/repo3'},
+ {'repo1': {'path': '/a/bcd/repo1', 'type': '', 'flags': []},
+ 'xxx': {'path': '/a/b/c/repo3', 'type': '', 'flags': []},
+ 'repo2': {'path': '/e/fgh/repo2', 'type': '', 'flags': []}},
'repo1', 'abc')
class TestInfo:
@patch('gita.common.get_config_fname', return_value='')
- def testLl(self, _, capfd):
+ def test_ll(self, _, capfd):
args = argparse.Namespace()
args.info_cmd = None
__main__.f_info(args)
out, err = capfd.readouterr()
- assert 'In use: branch,commit_msg\nUnused: path\n' == out
+ assert 'In use: branch,commit_msg,commit_time\nUnused: path\n' == out
assert err == ''
- @patch('gita.common.get_config_fname', return_value='')
- @patch('yaml.dump')
- def testAdd(self, mock_dump, _):
+ @patch('gita.common.get_config_fname')
+ def test_add(self, mock_get_fname, tmpdir):
args = argparse.Namespace()
args.info_cmd = 'add'
args.info_item = 'path'
- with patch('builtins.open', mock_open(), create=True):
+ with tmpdir.as_cwd():
+ csv_config = Path.cwd() / 'info.csv'
+ mock_get_fname.return_value = csv_config
__main__.f_info(args)
- mock_dump.assert_called_once()
- args, kwargs = mock_dump.call_args
- assert args[0] == ['branch', 'commit_msg', 'path']
- assert kwargs == {'default_flow_style': None}
+ items = info.get_info_items()
+ assert items == ['branch', 'commit_msg', 'commit_time', 'path']
- @patch('gita.common.get_config_fname', return_value='')
- @patch('yaml.dump')
- def testRm(self, mock_dump, _):
+ @patch('gita.common.get_config_fname')
+ def test_rm(self, mock_get_fname, tmpdir):
args = argparse.Namespace()
args.info_cmd = 'rm'
args.info_item = 'commit_msg'
- with patch('builtins.open', mock_open(), create=True):
+ with tmpdir.as_cwd():
+ csv_config = Path.cwd() / 'info.csv'
+ mock_get_fname.return_value = csv_config
__main__.f_info(args)
- mock_dump.assert_called_once()
- args, kwargs = mock_dump.call_args
- assert args[0] == ['branch']
- assert kwargs == {'default_flow_style': None}
+ items = info.get_info_items()
+ assert items == ['branch', 'commit_time']
+
+
+@patch('gita.common.get_config_fname')
+def test_set_color(mock_get_fname, tmpdir):
+ args = argparse.Namespace()
+ args.color_cmd = 'set'
+ args.color = 'redrum' # this color doesn't exist
+ args.situation = 'in-sync'
+ with tmpdir.as_cwd():
+ csv_config = Path.cwd() / 'colors.csv'
+ mock_get_fname.return_value = csv_config
+ __main__.f_color(args)
+ info.get_color_encoding.cache_clear() # avoid side effect
+ items = info.get_color_encoding()
+ info.get_color_encoding.cache_clear() # avoid side effect
+ assert items == {'no-remote': 'white', 'in-sync': 'redrum',
+ 'diverged': 'red', 'local-ahead': 'purple',
+ 'remote-ahead': 'yellow'}
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 886ddb9..39430b0 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -1,5 +1,7 @@
import pytest
import asyncio
+import subprocess
+from pathlib import Path
from unittest.mock import patch, mock_open
from gita import utils, info
@@ -8,16 +10,41 @@ from conftest import (
)
+@pytest.mark.parametrize('repo_path, paths, expected', [
+ ('/a/b/c/repo', ['/a/b'], ('b', 'c')),
+ ])
+def test_generate_dir_hash(repo_path, paths, expected):
+ got = utils._generate_dir_hash(repo_path, paths)
+ assert got == expected
+
+
+@pytest.mark.parametrize('repos, paths, expected', [
+ ({'r1': {'path': '/a/b//repo1'}, 'r2': {'path': '/a/b/repo2'}},
+ ['/a/b'], {'b': ['r1', 'r2']}),
+ ({'r1': {'path': '/a/b//repo1'}, 'r2': {'path': '/a/b/c/repo2'}},
+ ['/a/b'], {'b': ['r1', 'r2'], 'b-c': ['r2']}),
+ ({'r1': {'path': '/a/b/c/repo1'}, 'r2': {'path': '/a/b/c/repo2'}},
+ ['/a/b'], {'b-c': ['r1', 'r2'], 'b': ['r1', 'r2']}),
+ ])
+def test_auto_group(repos, paths, expected):
+ got = utils.auto_group(repos, paths)
+ assert got == expected
+
+
@pytest.mark.parametrize('test_input, diff_return, expected', [
- ([{'abc': '/root/repo/'}, False], True, 'abc \x1b[31mrepo *+_ \x1b[0m msg'),
- ([{'abc': '/root/repo/'}, True], True, 'abc repo *+_ msg'),
- ([{'repo': '/root/repo2/'}, False], False, 'repo \x1b[32mrepo _ \x1b[0m msg'),
+ ([{'abc': {'path': '/root/repo/', 'type': '', 'flags': []}}, False],
+ True, 'abc \x1b[31mrepo *+_ \x1b[0m msg xx'),
+ ([{'abc': {'path': '/root/repo/', 'type': '', 'flags': []}}, True],
+ True, 'abc repo *+_ msg xx'),
+ ([{'repo': {'path': '/root/repo2/', 'type': '', 'flags': []}}, False],
+ False, 'repo \x1b[32mrepo _ \x1b[0m msg xx'),
])
def test_describe(test_input, diff_return, expected, monkeypatch):
monkeypatch.setattr(info, 'get_head', lambda x: 'repo')
- monkeypatch.setattr(info, 'run_quiet_diff', lambda _: diff_return)
- monkeypatch.setattr(info, 'get_commit_msg', lambda _: "msg")
- monkeypatch.setattr(info, 'has_untracked', lambda: True)
+ monkeypatch.setattr(info, 'run_quiet_diff', lambda *_: diff_return)
+ monkeypatch.setattr(info, 'get_commit_msg', lambda *_: "msg")
+ monkeypatch.setattr(info, 'get_commit_time', lambda *_: "xx")
+ monkeypatch.setattr(info, 'has_untracked', lambda *_: True)
monkeypatch.setattr('os.chdir', lambda x: None)
print('expected: ', repr(expected))
print('got: ', repr(next(utils.describe(*test_input))))
@@ -26,15 +53,14 @@ def test_describe(test_input, diff_return, expected, monkeypatch):
@pytest.mark.parametrize('path_fname, expected', [
(PATH_FNAME, {
- 'repo1': '/a/bcd/repo1',
- 'repo2': '/e/fgh/repo2',
- 'xxx': '/a/b/c/repo3',
+ 'repo1': {'path': '/a/bcd/repo1', 'type': '', 'flags': []},
+ 'repo2': {'path': '/e/fgh/repo2', 'type': '', 'flags': []},
+ 'xxx': {'path': '/a/b/c/repo3', 'type': '', 'flags': []},
}),
(PATH_FNAME_EMPTY, {}),
(PATH_FNAME_CLASH, {
- 'repo1': '/a/bcd/repo1',
- 'repo2': '/e/fgh/repo2',
- 'x/repo1': '/root/x/repo1'
+ 'repo2': {'path': '/e/fgh/repo2', 'type': '', 'flags': ['--haha', '--pp']},
+ 'repo1': {'path': '/root/x/repo1', 'type': '', 'flags': []}
}),
])
@patch('gita.utils.is_git', return_value=True)
@@ -70,42 +96,46 @@ def test_get_groups(mock_group_fname, group_fname, expected):
@patch('os.path.getsize', return_value=True)
def test_custom_push_cmd(*_):
with patch('builtins.open',
- mock_open(read_data='push:\n cmd: hand\n help: me')):
+ mock_open(read_data='{"push":{"cmd":"hand","help":"me","allow_all":true}}')):
cmds = utils.get_cmds_from_files()
- assert cmds['push'] == {'cmd': 'hand', 'help': 'me'}
+ assert cmds['push'] == {'cmd': 'hand', 'help': 'me', 'allow_all': True}
@pytest.mark.parametrize(
'path_input, expected',
[
- (['/home/some/repo/'], '/home/some/repo,repo\n'), # add one new
+ (['/home/some/repo'], '/home/some/repo,some/repo,,\r\n'), # add one new
(['/home/some/repo1', '/repo2'],
- {'/repo2,repo2\n/home/some/repo1,repo1\n', # add two new
- '/home/some/repo1,repo1\n/repo2,repo2\n'}), # add two new
+ {'/repo2,repo2,,\r\n', # add two new
+ '/home/some/repo1,repo1,,\r\n'}), # add two new
(['/home/some/repo1', '/nos/repo'],
- '/home/some/repo1,repo1\n'), # add one old one new
+ '/home/some/repo1,repo1,,\r\n'), # add one old one new
])
@patch('os.makedirs')
@patch('gita.utils.is_git', return_value=True)
def test_add_repos(_0, _1, path_input, expected, monkeypatch):
monkeypatch.setenv('XDG_CONFIG_HOME', '/config')
with patch('builtins.open', mock_open()) as mock_file:
- utils.add_repos({'repo': '/nos/repo'}, path_input)
- mock_file.assert_called_with('/config/gita/repo_path', 'a+')
+ utils.add_repos({'repo': {'path': '/nos/repo'}}, path_input)
+ mock_file.assert_called_with('/config/gita/repos.csv', 'a+', newline='')
handle = mock_file()
if type(expected) == str:
handle.write.assert_called_once_with(expected)
else:
- handle.write.assert_called_once()
+ # the write order is random
+ assert handle.write.call_count == 2
args, kwargs = handle.write.call_args
assert args[0] in expected
assert not kwargs
+@patch('gita.utils.write_to_groups_file')
@patch('gita.utils.write_to_repo_file')
-def test_rename_repo(mock_write):
- utils.rename_repo({'r1': '/a/b', 'r2': '/c/c'}, 'r2', 'xxx')
- mock_write.assert_called_once_with({'r1': '/a/b', 'xxx': '/c/c'}, 'w')
+def test_rename_repo(mock_write, _):
+ repos = {'r1': {'path': '/a/b', 'type': None},
+ 'r2': {'path': '/c/c', 'type': None}}
+ utils.rename_repo(repos, 'r2', 'xxx')
+ mock_write.assert_called_once_with(repos, 'w')
def test_async_output(capfd):
@@ -124,3 +154,10 @@ def test_async_output(capfd):
out, err = capfd.readouterr()
assert err == ''
assert out == 'myrepo: 0\nmyrepo: 0\n\nmyrepo: 1\nmyrepo: 1\n\nmyrepo: 2\nmyrepo: 2\n\nmyrepo: 3\nmyrepo: 3\n\n'
+
+
+def test_is_git(tmpdir):
+ with tmpdir.as_cwd():
+ subprocess.run('git init --bare .'.split())
+ assert utils.is_git(Path.cwd()) is False
+ assert utils.is_git(Path.cwd(), is_bare=True) is True