From f61fdde670bd549969486280dc5aec722a32fbe6 Mon Sep 17 00:00:00 2001 From: Paul Landes Date: Sun, 2 Jul 2023 15:36:25 -0500 Subject: [PATCH] add more repo utility --- src/bin/repoutil.py | 42 ++++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/src/bin/repoutil.py b/src/bin/repoutil.py index 8f8e8fe..a2b8ffb 100755 --- a/src/bin/repoutil.py +++ b/src/bin/repoutil.py @@ -8,12 +8,13 @@ """ __author__ = 'Paul Landes' -from typing import Iterable, Callable +from typing import Iterable, Callable, Tuple, Dict from dataclasses import dataclass, field import sys import logging from pathlib import Path import plac +import git from zensols.cli import CliHarness from zensols.grsync import ( RepoSpec, Discoverer, DistManager, ApplicationFactory, InfoApplication @@ -68,10 +69,25 @@ def _execute(self, cmd: str, exist_path_fn: Callable = None): def dirty(self): """Print dirty repos, which are those that need committing.""" + rs: RepoSpec for rs in filter(lambda rs: rs.repo.is_dirty(), self.repo_specs): print(rs.path) - print(f'untracked: {rs.repo.untracked_files}') - print(f'difs: {rs.repo.index.diff(None)}') + + def uncommitted(self, remote: str = 'origin', branch: str = 'master'): + """Print repos that have commits that haven't been pushed yet.""" + def has_commits(rs: RepoSpec) -> bool: + commits: Tuple[git.Commit] = () + try: + spec: str = f'{remote}/{branch}..{branch}' + # only the given remote and branch is supported for now + commits = tuple(rs.repo.iter_commits(spec)) + except git.GitCommandError: + pass + return len(commits) > 0 + + rs: RepoSpec + for rs in filter(has_commits, self.repo_specs): + print(rs.path) def clean(self): """Do a make clean on all repo paths.""" @@ -90,21 +106,27 @@ def pull(self): def list(self): """Print a list of actions for this script""" - print('\n'.join('dirty clean status pull list'.split())) + print('\n'.join('dirty uncommitted clean status pull list'.split())) @plac.annotations( - action=('Action: ()', + action=('Action: ()', 'positional', None, str), - dryrun=('Don\'t actually move the file.', 'flag', 'd')) -def main(action, dryrun=False): + dryrun=('don\'t do anything, just act like it', 'flag', 'd'), + remote=('repo remote', 'option', 'r'), + branch=('repo branch', 'option', 'b')) +def main(action: str, dryrun: bool = False, + remote: str = 'origin', branch: str = 'master'): logging.basicConfig(level=logging.WARNING, format='%(message)s') logger.setLevel(level=logging.INFO) ru = RepoUtil(dry_run=dryrun) + params: Dict[str, str] = {} + if action == 'uncommitted': + params.update({'remote': remote, 'branch': branch}) try: - getattr(ru, action)() - except AttributeError: - print(f'no such action: {action}', file=sys.stderr) + getattr(ru, action)(**params) + except AttributeError as e: + print(f'no such action: {action}: {e}', file=sys.stderr) sys.exit(1)