class Command(object): """Command class for parsing commandline options""" def __init__(self): self.root_directory = os.getcwd() self.clowder = None self.clowder_repo = None self.versions = None self.group_names = '' self.project_names = '' self.branches = '' # Load current clowder.yml config if it exists clowder_path = os.path.join(self.root_directory, 'clowder') if os.path.isdir(clowder_path): self.clowder_repo = ClowderRepo(self.root_directory) self.clowder = ClowderController(self.root_directory) self.versions = self.clowder.get_fixed_version_names() self.branches = self.clowder_repo.branches() if self.clowder.get_all_group_names() is not None: self.group_names = self.clowder.get_all_group_names() if self.clowder.get_all_project_names() is not None: self.project_names = self.clowder.get_all_project_names() # clowder argparse setup command_description = 'Utility for managing multiple git repositories' parser = argparse.ArgumentParser(description=command_description) subparsers = parser.add_subparsers(dest='command') self._configure_subparsers(subparsers) # Argcomplete and arguments parsing argcomplete.autocomplete(parser) self.args = parser.parse_args() print('') if not hasattr(self, self.args.command): exit_unrecognized_command(parser) # use dispatch pattern to invoke method with same name getattr(self, self.args.command)() print('') def breed(self): """clowder breed command""" if self.clowder_repo is None: cprint('Breed from %s\n' % self.args.url, 'yellow') clowder_repo = ClowderRepo(self.root_directory) clowder_repo.breed(self.args.url) else: cprint('Clowder already bred in this directory, exiting...\n', 'red') sys.exit() def fix(self): """clowder fix command""" if self.clowder_repo is not None: cprint('Fix...\n', 'yellow') self.clowder.fix_version(self.args.version) else: exit_clowder_not_found() def forall(self): """clowder forall command""" if self.clowder_repo is not None: cprint('Forall...\n', 'yellow') self.clowder_repo.print_status() print('') if self.args.projects is None: self.clowder.forall_groups(self.args.cmd, self.args.groups) else: self.clowder.forall_projects(self.args.cmd, self.args.projects) else: exit_clowder_not_found() def groom(self): """clowder groom command""" if self.clowder_repo is not None: cprint('Groom...\n', 'yellow') self.clowder_repo.print_status() print('') if self.args.projects is None: self.clowder.groom_groups(self.args.groups) else: self.clowder.groom_projects(self.args.projects) else: exit_clowder_not_found() def herd(self): """clowder herd command""" if self.clowder_repo is not None: cprint('Herd...\n', 'yellow') self.clowder_repo.print_status() self.clowder_repo.symlink_yaml(self.args.version) print('') clowder = ClowderController(self.root_directory) if self.args.projects is None: clowder.herd_groups(self.args.groups) else: clowder.herd_projects(self.args.projects) else: exit_clowder_not_found() def meow(self): """clowder meow command""" if self.clowder_repo is not None: cprint('Meow...\n', 'yellow') self.clowder_repo.print_status() print('') if self.args.verbose: self.clowder.meow_verbose(self.args.groups) else: self.clowder.meow(self.args.groups) else: exit_clowder_not_found() def stash(self): """clowder stash command""" if self.clowder_repo is not None: cprint('Stash...\n', 'yellow') self.clowder_repo.print_status() print('') if self.args.projects is None: self.clowder.stash_groups(self.args.groups) else: self.clowder.stash_projects(self.args.projects) else: exit_clowder_not_found() def sync(self): """clowder sync command""" if self.clowder_repo is not None: cprint('Sync...\n', 'yellow') if self.args.branch is None: self.clowder_repo.sync() else: self.clowder_repo.sync_branch(self.args.branch) else: exit_clowder_not_found() # Disable errors shown by pylint for unused arguments # pylint: disable=R0914 def _configure_subparsers(self, subparsers): """Configure all clowder command subparsers and arguments""" # clowder breed breed_help = 'Clone repository to clowder directory and create clowder.yaml symlink' parser_breed = subparsers.add_parser('breed', help=breed_help) parser_breed.add_argument('url', help='URL of repo containing clowder.yaml') # clowder herd herd_help = 'Clone and sync latest changes for projects' parser_herd = subparsers.add_parser('herd', help=herd_help) group_herd = parser_herd.add_mutually_exclusive_group() group_herd.add_argument('--version', '-v', choices=self.versions, help='Version name to herd') group_herd.add_argument('--groups', '-g', choices=self.group_names, default=self.group_names, nargs='+', help='Groups to herd') group_herd.add_argument('--projects', '-p', choices=self.project_names, nargs='+', help='Projects to herd') # clowder forall forall_help = 'Run command in project directories' parser_forall = subparsers.add_parser('forall', help=forall_help) parser_forall.add_argument('cmd', help='Command to run in project directories') group_forall = parser_forall.add_mutually_exclusive_group() group_forall.add_argument('--groups', '-g', choices=self.group_names, default=self.group_names, nargs='+', help='Groups to run command for') group_forall.add_argument('--projects', '-p', choices=self.project_names, nargs='+', help='Projects to run command for') # clowder meow parser_meow = subparsers.add_parser('meow', help='Print status for projects') parser_meow.add_argument('--verbose', '-v', action='store_true', help='Print detailed diff status') parser_meow.add_argument('--groups', '-g', choices=self.group_names, default=self.group_names, nargs='+', help='Groups to print status for') # clowder fix fix_help = 'Create version of clowder.yaml for current repos' parser_fix = subparsers.add_parser('fix', help=fix_help) parser_fix.add_argument('version', help='Version name to fix') # clowder groom groom_help = 'Discard current changes in all projects' parser_groom = subparsers.add_parser('groom', help=groom_help) group_groom = parser_groom.add_mutually_exclusive_group() group_groom.add_argument('--groups', '-g', choices=self.group_names, default=self.group_names, nargs='+', help='Groups to groom') group_groom.add_argument('--projects', '-p', choices=self.project_names, nargs='+', help='Projects to groom') # clowder stash parser_stash = subparsers.add_parser('stash', help='Stash current changes in all projects') group_stash = parser_stash.add_mutually_exclusive_group() group_stash.add_argument('--groups', '-g', choices=self.group_names, default=self.group_names, nargs='+', help='Groups to stash') group_stash.add_argument('--projects', '-p', choices=self.project_names, nargs='+', help='Projects to stash') # clowder sync parser_sync = subparsers.add_parser('sync', add_help=False, help='Sync clowder repo') parser_sync.add_argument('--branch', '-b', choices=self.branches, help='Groups to print status for')
class Command(object): """Command class for parsing commandline options""" def __init__(self): self.root_directory = os.getcwd() self.clowder = None self.clowder_repo = None self.versions = None self.group_names = '' self.project_names = '' # Load current clowder.yml config if it exists clowder_path = os.path.join(self.root_directory, '.clowder') if os.path.isdir(clowder_path): clowder_symlink = os.path.join(self.root_directory, 'clowder.yaml') self.clowder_repo = ClowderRepo(self.root_directory) if not os.path.islink(clowder_symlink): print('') clowder_output = colored('.clowder', 'green') print(clowder_output) self.clowder_repo.link() self.clowder = ClowderController(self.root_directory) self.versions = self.clowder.get_saved_version_names() if self.clowder.get_all_group_names() is not None: self.group_names = self.clowder.get_all_group_names() if self.clowder.get_all_project_names() is not None: self.project_names = self.clowder.get_all_project_names() # clowder argparse setup command_description = 'Utility for managing multiple git repositories' parser = argparse.ArgumentParser(description=command_description) parser.add_argument('--version', '-v', action='store_true', dest='clowder_version', help='Print clowder version') subparsers = parser.add_subparsers(dest='command') self._configure_subparser_clean(subparsers) self._configure_subparser_forall(subparsers) self._configure_subparser_herd(subparsers) self._configure_subparser_init(subparsers) self._configure_subparser_link(subparsers) self._configure_subparser_prune(subparsers) self._configure_subparser_repo(subparsers) self._configure_subparser_save(subparsers) self._configure_subparser_start(subparsers) self._configure_subparser_stash(subparsers) self._configure_subparser_status(subparsers) # Argcomplete and arguments parsing argcomplete.autocomplete(parser) self.args = parser.parse_args() if self.args.clowder_version: print('clowder version 1.1.2') sys.exit(0) print('') if self.args.command is None or not hasattr(self, self.args.command): exit_unrecognized_command(parser) # use dispatch pattern to invoke method with same name getattr(self, self.args.command)() print('') def clean(self): """clowder clean command""" if self.clowder_repo is not None: self.clowder_repo.print_status() print('') if self.args.projects is None: self.clowder.clean_groups(self.args.groups) else: self.clowder.clean_projects(self.args.projects) else: exit_clowder_not_found() def forall(self): """clowder forall command""" if self.clowder_repo is not None: self.clowder_repo.print_status() print('') if self.args.projects is None: if self.args.cmd is not None: self.clowder.forall_groups_command(self.args.cmd[0], self.args.groups) else: self.clowder.forall_groups_file(self.args.file[0], self.args.groups) else: if self.args.cmd is not None: self.clowder.forall_projects_command(self.args.cmd[0], self.args.projects) else: self.clowder.forall_projects_file(self.args.file[0], self.args.projects) else: exit_clowder_not_found() def herd(self): """clowder herd command""" if self.clowder_repo is not None: self.clowder_repo.print_status() print('') if self.args.branch is None: ref = None else: ref = self.args.branch[0] if self.args.depth is None: depth = None else: depth = self.args.depth[0] if self.args.projects is None: if self.args.groups is None: self.clowder.herd_groups(self.clowder.get_all_group_names(), ref, depth) else: self.clowder.herd_groups(self.args.groups, ref, depth) else: self.clowder.herd_projects(self.args.projects, ref, depth) else: exit_clowder_not_found() def init(self): """clowder init command""" if self.clowder_repo is None: url_output = colored(self.args.url, 'green') print('Create clowder repo from ' + url_output) print('') clowder_repo = ClowderRepo(self.root_directory) clowder_repo.init(self.args.url, self.args.branch) else: cprint('Clowder already initialized in this directory', 'red') print('') sys.exit() def link(self): """clowder link command""" self.clowder_repo.print_status() if self.clowder_repo is not None: if self.args.version is None: version = None else: version = self.args.version[0] self.clowder_repo.link(version) else: exit_clowder_not_found() def prune(self): """clowder prune command""" if self.clowder_repo is not None: self.clowder_repo.print_status() print('') if self.args.projects is None: self.clowder.prune_groups(self.args.groups, self.args.branch, self.args.remote) else: self.clowder.prune_projects(self.args.projects, self.args.branch, self.args.remote) else: exit_clowder_not_found() def repo(self): """clowder repo command""" if self.clowder_repo is not None: self.clowder_repo.print_status() repo_command = 'repo_' + self.args.repo_command getattr(self, repo_command)() else: exit_clowder_not_found() def repo_add(self): """clowder repo add command""" if self.clowder_repo is not None: self.clowder_repo.add(self.args.files) else: exit_clowder_not_found() def repo_checkout(self): """clowder repo checkout command""" if self.clowder_repo is not None: self.clowder_repo.checkout(self.args.ref[0]) else: exit_clowder_not_found() def repo_clean(self): """clowder repo clean command""" if self.clowder_repo is not None: self.clowder_repo.clean() else: exit_clowder_not_found() def repo_commit(self): """clowder repo commit command""" if self.clowder_repo is not None: self.clowder_repo.commit(self.args.message[0]) else: exit_clowder_not_found() def repo_pull(self): """clowder repo pull command""" if self.clowder_repo is not None: self.clowder_repo.pull() else: exit_clowder_not_found() def repo_push(self): """clowder repo push command""" if self.clowder_repo is not None: self.clowder_repo.push() else: exit_clowder_not_found() def repo_run(self): """clowder repo run command""" if self.clowder_repo is not None: self.clowder_repo.run_command(self.args.cmd[0]) else: exit_clowder_not_found() def repo_status(self): """clowder repo status command""" if self.clowder_repo is not None: self.clowder_repo.status() else: exit_clowder_not_found() def save(self): """clowder save command""" if self.clowder_repo is not None: self.clowder.save_version(self.args.version) else: exit_clowder_not_found() def start(self): """clowder start command""" if self.clowder_repo is not None: self.clowder_repo.print_status() print('') if self.args.projects is None: self.clowder.start_groups(self.args.groups, self.args.branch) else: self.clowder.start_projects(self.args.projects, self.args.branch) else: exit_clowder_not_found() def stash(self): """clowder stash command""" if self.clowder_repo is not None: self.clowder_repo.print_status() print('') if self.args.projects is None: self.clowder.stash_groups(self.args.groups) else: self.clowder.stash_projects(self.args.projects) else: exit_clowder_not_found() def status(self): """clowder status command""" if self.clowder_repo is not None: self.clowder_repo.print_status() print('') if self.args.fetch: print(' - Fetching upstream changes for projects', end="", flush=True) timer = RepeatedTimer(1, self._print_progress) if self.args.projects is None: self.clowder.fetch_groups(self.args.groups) else: self.clowder.fetch_projects(self.args.projects) timer.stop() print('\n') if self.args.projects is None: self.clowder.status_groups(self.args.groups, self.args.verbose) else: self.clowder.status_projects(self.args.projects, self.args.verbose) else: exit_clowder_not_found() # Disable errors shown by pylint for too many local variables # pylint: disable=R0201 def _configure_subparser_clean(self, subparsers): """Configure clowder clean subparser and arguments""" # clowder clean clean_help = 'Discard current changes in all projects' parser_clean = subparsers.add_parser('clean', help=clean_help) group_clean = parser_clean.add_mutually_exclusive_group() group_clean.add_argument('--groups', '-g', choices=self.group_names, default=self.group_names, nargs='+', help='Groups to clean') group_clean.add_argument('--projects', '-p', choices=self.project_names, nargs='+', help='Projects to clean') def _configure_subparser_forall(self, subparsers): """Configure clowder forall subparser and arguments""" # clowder forall forall_help = 'Run command in project directories' parser_forall = subparsers.add_parser('forall', help=forall_help) group_forall_command = parser_forall.add_mutually_exclusive_group() group_forall_command.add_argument('--cmd', '-c', nargs=1, help='Command to run in project directories') group_forall_command.add_argument('--file', '-f', nargs=1, help='Script to run') group_forall_targets = parser_forall.add_mutually_exclusive_group() group_forall_targets.add_argument('--groups', '-g', choices=self.group_names, default=self.group_names, nargs='+', help='Groups to run command for') group_forall_targets.add_argument('--projects', '-p', choices=self.project_names, nargs='+', help='Projects to run command for') def _configure_subparser_herd(self, subparsers): """Configure clowder herd subparser and arguments""" # clowder herd herd_help = 'Clone and sync latest changes for projects' parser_herd = subparsers.add_parser('herd', help=herd_help) parser_herd.add_argument('--depth', '-d', default=None, type=int, nargs=1, help='Depth to herd') parser_herd.add_argument('--branch', '-b', nargs=1, default=None, help='Branch to herd') group_herd = parser_herd.add_mutually_exclusive_group() group_herd.add_argument('--groups', '-g', choices=self.group_names, default=self.group_names, nargs='+', help='Groups to herd') group_herd.add_argument('--projects', '-p', choices=self.project_names, nargs='+', help='Projects to herd') def _configure_subparser_init(self, subparsers): """Configure clowder init subparser and arguments""" # clowder init init_help = 'Clone repository to clowder directory and create clowder.yaml symlink' parser_init = subparsers.add_parser('init', help=init_help) parser_init.add_argument('url', help='URL of repo containing clowder.yaml') parser_init.add_argument('--branch', '-b', default='master', nargs='?', help='Branch of repo containing clowder.yaml') def _configure_subparser_link(self, subparsers): """Configure clowder link subparser and arguments""" # clowder link parser_link = subparsers.add_parser('link', help='Symlink clowder.yaml version') parser_link.add_argument('--version', '-v', choices=self.versions, nargs=1, default=None, help='Version name to symlink') def _configure_subparser_prune(self, subparsers): """Configure clowder prune subparser and arguments""" # clowder prune parser_prune = subparsers.add_parser('prune', help='Prune old branch') parser_prune.add_argument('branch', help='Name of branch to remove') parser_prune.add_argument('--remote', '-r', action='store_true', help='Prune remote branches') group_prune = parser_prune.add_mutually_exclusive_group() group_prune.add_argument('--groups', '-g', choices=self.group_names, default=self.group_names, nargs='+', help='Groups to prune branch for') group_prune.add_argument('--projects', '-p', choices=self.project_names, nargs='+', help='Projects to prune branch for') def _configure_subparser_repo(self, subparsers): """Configure clowder repo subparser and arguments""" # clowder repo parser_repo = subparsers.add_parser('repo', help='Manage clowder repo') repo_subparsers = parser_repo.add_subparsers(dest='repo_command') # clowder repo add repo_add_help = 'Add files in clowder repo' parser_repo_add = repo_subparsers.add_parser('add', help=repo_add_help) parser_repo_add.add_argument('files', nargs='+', help='Files to add') # clowder repo checkout repo_checkout_help = 'Checkout ref in clowder repo' parser_repo_checkout = repo_subparsers.add_parser('checkout', help=repo_checkout_help) parser_repo_checkout.add_argument('ref', nargs=1, help='Git ref to checkout') # clowder repo clean repo_clean_help = 'Discard changes in clowder repo' repo_subparsers.add_parser('clean', help=repo_clean_help) # clowder repo commit repo_commit_help = 'Commit current changes in clowder repo yaml files' parser_repo_commit = repo_subparsers.add_parser('commit', help=repo_commit_help) parser_repo_commit.add_argument('message', nargs=1, help='Commit message') # clowder repo run repo_run_help = 'Run command in clowder repo' parser_repo_run = repo_subparsers.add_parser('run', help=repo_run_help) repo_run_command_help = 'Command to run in clowder repo directory' parser_repo_run.add_argument('cmd', nargs=1, help=repo_run_command_help) # clowder repo pull repo_pull_help = 'Pull upstream changes in clowder repo' repo_subparsers.add_parser('pull', help=repo_pull_help) # clowder repo push repo_subparsers.add_parser('push', help='Push changes in clowder repo') # clowder repo status repo_subparsers.add_parser('status', help='Print clowder repo git status') def _configure_subparser_save(self, subparsers): """Configure clowder save subparser and arguments""" # clowder save save_help = 'Create version of clowder.yaml for current repos' parser_save = subparsers.add_parser('save', help=save_help) parser_save.add_argument('version', help='Version name to save') def _configure_subparser_start(self, subparsers): """Configure clowder start subparser and arguments""" # clowder start parser_start = subparsers.add_parser('start', help='Start a new feature') parser_start.add_argument('branch', help='Name of branch to create') group_start = parser_start.add_mutually_exclusive_group() group_start.add_argument('--groups', '-g', choices=self.group_names, default=self.group_names, nargs='+', help='Groups to start feature for') group_start.add_argument('--projects', '-p', choices=self.project_names, nargs='+', help='Projects to start feature for') def _configure_subparser_stash(self, subparsers): """Configure clowder stash subparser and arguments""" # clowder stash parser_stash = subparsers.add_parser('stash', help='Stash current changes') group_stash = parser_stash.add_mutually_exclusive_group() group_stash.add_argument('--groups', '-g', choices=self.group_names, default=self.group_names, nargs='+', help='Groups to stash') group_stash.add_argument('--projects', '-p', choices=self.project_names, nargs='+', help='Projects to stash') def _configure_subparser_status(self, subparsers): """Configure clowder status subparser and arguments""" # clowder status parser_status = subparsers.add_parser('status', help='Print project status') parser_status.add_argument('--fetch', '-f', action='store_true', help='Fetch projects before printing status') parser_status.add_argument('--verbose', '-v', action='store_true', help='Print detailed diff status') group_status = parser_status.add_mutually_exclusive_group() group_status.add_argument('--groups', '-g', choices=self.group_names, default=self.group_names, nargs='+', help='Groups to print status for') group_status.add_argument('--projects', '-p', choices=self.project_names, nargs='+', help='Projects to print status for') def _print_progress(self): print('.', end="", flush=True)