Skip to content

Commit

Permalink
clean up shell and super parsing (#196)
Browse files Browse the repository at this point in the history
  • Loading branch information
nosarthur authored Sep 13, 2021
1 parent bdb046a commit 9f9d725
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 47 deletions.
65 changes: 18 additions & 47 deletions gita/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,20 +303,11 @@ def f_git_cmd(args: argparse.Namespace):
Delegate git command/alias defined in `args.cmd`. Asynchronous execution is
disabled for commands in the `args.async_blacklist`.
"""
repos = utils.get_repos()
groups = utils.get_groups()
ctx = utils.get_context()
if not args.repo and ctx:
args.repo = [ctx.stem]
if args.repo: # with user specified repo(s) or group(s)
chosen = {}
for k in args.repo:
if k in repos:
chosen[k] = repos[k]
if k in groups:
for r in groups[k]['repos']:
chosen[r] = repos[r]
repos = chosen
if '_parsed_repos' in args:
repos = args._parsed_repos
else:
repos, _ = utils.parse_repos_and_rest(args.repo)

per_repo_cmds = []
for prop in repos.values():
cmds = args.cmd.copy()
Expand Down Expand Up @@ -351,29 +342,12 @@ def f_shell(args):
Delegate shell command defined in `args.man`, which may or may not
contain repo names.
"""
names = []
repos = utils.get_repos()
groups = utils.get_groups()
ctx = utils.get_context()
for i, word in enumerate(args.man):
if word in repos or word in groups:
names.append(word)
else:
break
args.repo = names
# TODO: redundant with f_git_cmd
if not args.repo and ctx:
args.repo = [ctx.stem]
if args.repo: # with user specified repo(s) or group(s)
chosen = {}
for k in args.repo:
if k in repos:
chosen[k] = repos[k]
if k in groups:
for r in groups[k]['repos']:
chosen[r] = repos[r]
repos = chosen
cmds = ' '.join(args.man[i:]) # join the shell command into a single string
repos, cmds = utils.parse_repos_and_rest(args.man)
if not cmds:
print('Missing commands')
sys.exit(2)

cmds = ' '.join(cmds) # join the shell command into a single string
for name, prop in repos.items():
# TODO: pull this out as a function
got = subprocess.run(cmds, cwd=prop['path'], shell=True,
Expand All @@ -387,16 +361,13 @@ def f_super(args):
Delegate git command/alias defined in `args.man`, which may or may not
contain repo names.
"""
names = []
repos = utils.get_repos()
groups = utils.get_groups()
for i, word in enumerate(args.man):
if word in repos or word in groups:
names.append(word)
else:
break
args.cmd = ['git'] + args.man[i:]
args.repo = names
repos, cmds = utils.parse_repos_and_rest(args.man)
if not cmds:
print('Missing commands')
sys.exit(2)

args.cmd = ['git'] + cmds
args._parsed_repos = repos
args.shell = False
f_git_cmd(args)

Expand Down
35 changes: 35 additions & 0 deletions gita/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -479,3 +479,38 @@ def get_cmds_from_files() -> Dict[str, Dict[str, str]]:
# custom commands shadow default ones
cmds.update(custom_cmds)
return cmds


def parse_repos_and_rest(input: List[str]
) -> Tuple[Dict[str, Dict[str, str]], List[str]]:
"""
Parse gita input arguments
@return: repos and the rest (e.g., gita shell and super commands)
"""
i = None
names = []
repos = get_repos()
groups = get_groups()
ctx = get_context()
for i, word in enumerate(input):
if word in repos or word in groups:
names.append(word)
else:
break
else: # all input is repos and groups, shift the index once more
if i is not None:
i += 1
if not names and ctx:
names = [ctx.stem]
if names:
chosen = {}
for k in names:
if k in repos:
chosen[k] = repos[k]
if k in groups:
for r in groups[k]['repos']:
chosen[r] = repos[r]
# if not set here, all repos are chosen
repos = chosen
return repos, input[i:]
13 changes: 13 additions & 0 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@
)


@pytest.mark.parametrize('input, expected', [
([], ({'repo1': {'path': '/a/bcd/repo1', 'type': '', 'flags': []}, 'xxx': {'path': '/a/b/c/repo3', 'type': '', 'flags': []}, 'repo2': {'path': '/e/fgh/repo2', 'type': '', 'flags': []}}, [])),
(['st'], ({'repo1': {'path': '/a/bcd/repo1', 'type': '', 'flags': []}, 'xxx': {'path': '/a/b/c/repo3', 'type': '', 'flags': []}, 'repo2': {'path': '/e/fgh/repo2', 'type': '', 'flags': []}}, ['st'])),
(['repo1', 'st'], ({'repo1': {'flags': [], 'path': '/a/bcd/repo1', 'type': ''}}, ['st'])),
(['repo1'], ({'repo1': {'flags': [], 'path': '/a/bcd/repo1', 'type': ''}}, [])),
])
@patch('gita.utils.is_git', return_value=True)
@patch('gita.common.get_config_fname', return_value=PATH_FNAME)
def test_parse_repos_and_rest(mock_path_fname, _, input, expected):
got = utils.parse_repos_and_rest(input)
assert got == expected


@pytest.mark.parametrize('repo_path, paths, expected', [
('/a/b/c/repo', ['/a/b'], (('b', 'c'), '/a')),
])
Expand Down

0 comments on commit 9f9d725

Please sign in to comment.