Skip to content

Commit

Permalink
Merge pull request #124 from JrGoodle/repo
Browse files Browse the repository at this point in the history
Add `clowder repo` subcommands
  • Loading branch information
JrGoodle committed Jan 9, 2016
2 parents 312e930 + f9bfdb8 commit f534a9f
Show file tree
Hide file tree
Showing 14 changed files with 291 additions and 83 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ install:
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew install github-release; fi
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get install -y python3-setuptools; fi

before_script: sudo python3 setup.py -q install
before_script: sudo python3 setup.py install

script: scripts/${TARGET}.sh

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ For more example projects, see the [examples directory](https://github.com/JrGoo
$ clowder clean # Discard any changes in projects
$ clowder forall "git status" # Run command in all project directories
$ clowder herd -v 0.1 # Point clowder.yaml symlink to saved version
$ clowder repo 'git status' # Run command in .clowder directory
$ clowder repo run 'git status' # Run command in .clowder directory
$ clowder save 0.1 # Save a version of clowder.yaml with current commit sha's
$ clowder start my_feature # Create new branch 'my_feature' for all projects
$ clowder stash # Stash any changes in projects
Expand Down
61 changes: 55 additions & 6 deletions clowder/clowder_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,16 @@
import emoji
from termcolor import colored
from clowder.utility.git_utilities import (
git_add,
git_branches,
git_create_repo
git_checkout,
git_commit,
git_create_repo,
git_is_dirty,
git_pull,
git_push,
git_reset_head,
git_status
)
from clowder.utility.clowder_utilities import (
force_symlink,
Expand All @@ -22,21 +30,44 @@ def __init__(self, root_directory):
self.root_directory = root_directory
self.clowder_path = os.path.join(self.root_directory, '.clowder')

def add(self, files):
"""Add files in clowder repo to git"""
print(' - Add files in clowder repo')
git_add(self.clowder_path, files)
git_status(self.clowder_path)

def branches(self):
"""Return current local branches"""
return git_branches(self.clowder_path)

def checkout(self, ref):
"""Checkout ref in clowder repo"""
if self.is_dirty():
print(' - Dirty repo. Please stash, commit, or discard your changes')
else:
git_checkout(self.clowder_path, ref)

def clean(self):
"""Discard changes in clowder repo"""
if self.is_dirty():
print(' - Discarding current changes')
git_reset_head(self.clowder_path)
else:
print(' - No changes to discard')

def commit(self, message):
"""Commit current changes in clowder repo"""
git_commit(self.clowder_path, message)

def init(self, url, branch):
"""Clone clowder repo from url"""
repo_branch = 'refs/heads/' + branch
git_create_repo(url, self.clowder_path, 'origin', repo_branch)
self.symlink_yaml()

def run_command(self, command):
"""Run command in clowder repo"""
command_output = colored('$ ' + command, attrs=['bold'])
print(command_output)
subprocess.call(command.split(), cwd=self.clowder_path)
def is_dirty(self):
"""Check if project is dirty"""
return git_is_dirty(self.clowder_path)

def print_status(self):
"""Print clowder repo status"""
Expand All @@ -50,6 +81,24 @@ def print_status(self):
current_ref_output = format_ref_string(repo_path)
print(cat_face + ' ' + project_output + ' ' + current_ref_output)

def pull(self):
"""Pull clowder repo upstream changes"""
git_pull(self.clowder_path)

def push(self):
"""Push clowder repo changes"""
git_push(self.clowder_path)

def run_command(self, command):
"""Run command in clowder repo"""
command_output = colored('$ ' + command, attrs=['bold'])
print(command_output)
subprocess.call(command.split(), cwd=self.clowder_path)

def status(self):
"""Print clowder repo git status"""
git_status(self.clowder_path)

def symlink_yaml(self, version=None):
"""Create symlink pointing to clowder.yaml file"""
if version is None:
Expand Down
94 changes: 87 additions & 7 deletions clowder/cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ def __init__(self):
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):
Expand All @@ -35,7 +34,6 @@ def __init__(self):
self.clowder_repo.symlink_yaml()
self.clowder = ClowderController(self.root_directory)
self.versions = self.clowder.get_saved_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:
Expand Down Expand Up @@ -141,8 +139,64 @@ def repo(self):
"""clowder repo command"""
if self.clowder_repo is not None:
self.clowder_repo.print_status()
print('')
self.clowder_repo.run_command(self.args.cmd)
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()

Expand Down Expand Up @@ -257,9 +311,35 @@ def _configure_subparser_prune(self, subparsers):
def _configure_subparser_repo(self, subparsers):
"""Configure clowder repo subparser and arguments"""
# clowder repo
repo_help = 'Run command in project directories'
parser_repo = subparsers.add_parser('repo', help=repo_help)
parser_repo.add_argument('cmd', help='Command to run in project directories')
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"""
Expand Down
14 changes: 7 additions & 7 deletions clowder/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ def __init__(self, root_directory, project, defaults, sources):
self.forks.append(Fork(fork, full_path, self.source,
self.ref, self.depth))

def clean(self):
"""Discard changes for project"""
if self.is_dirty():
self._print_status()
print(' - Discarding current changes')
git_reset_head(self.full_path())

def exists(self):
"""Check if project exists on disk"""
path = os.path.join(self.full_path(), '.git')
Expand All @@ -85,13 +92,6 @@ def get_yaml(self):
'remote': self.remote_name,
'source': self.source.name}

def clean(self):
"""Discard changes for project"""
if self.is_dirty():
self._print_status()
print(' - Discarding current changes')
git_reset_head(self.full_path())

def herd(self):
"""Clone project or update latest from upstream"""
self._print_status()
Expand Down
90 changes: 62 additions & 28 deletions clowder/utility/git_utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,29 @@
# Disable errors shown by pylint for no specified exception types
# pylint: disable=W0702

def git_add(repo_path, files):
"""Add files to git index"""
repo = _repo(repo_path)
print(repo.git.add(files))

def git_branches(repo_path):
"""Get list of current branches"""
repo = _repo(repo_path)
return repo.branches

def git_checkout(repo_path, ref):
"""Checkout git ref"""
repo = _repo(repo_path)
ref_output = colored('(' + ref + ')', 'magenta')
print(' - Check out ' + ref_output)
print(repo.git.checkout(ref))

def git_commit(repo_path, message):
"""Commit current changes"""
repo = _repo(repo_path)
print(' - Commit current changes')
print(repo.git.commit(message=message))

def git_create_repo(url, repo_path, remote, ref, depth=0):
"""Clone git repo from url at path"""
if not os.path.isdir(os.path.join(repo_path, '.git')):
Expand Down Expand Up @@ -116,6 +134,34 @@ def git_is_dirty(repo_path):
repo = _repo(repo_path)
return repo.is_dirty()

def git_prune(repo_path, branch, default_ref):
"""Start new branch in repository"""
repo = _repo(repo_path)
branch_output = colored('(' + branch + ')', 'magenta')
if branch in repo.heads:
prune_branch = repo.heads[branch]
if repo.head.ref == prune_branch:
truncated_ref = _truncate_ref(default_ref)
ref_output = colored('(' + truncated_ref + ')', 'magenta')
try:
print(' - Checking out ' + ref_output)
repo.git.checkout(truncated_ref)
except:
message = colored(' - Failed to checkout ref', 'red')
print(message + ref_output)
print('')
sys.exit(1)
try:
print(' - Deleting branch ' + branch_output)
repo.delete_head(branch)
except:
message = colored(' - Failed to delete branch', 'red')
print(message + branch_output)
print('')
sys.exit(1)
else:
print(' - Branch ' + branch_output + " doesn't exist")

def git_pull(repo_path):
"""Pull from remote branch"""
repo = _repo(repo_path)
Expand All @@ -127,6 +173,22 @@ def git_pull(repo_path):
cprint(' - Failed to pull latest changes', 'red')
print('')
sys.exit(1)
else:
print(' - HEAD is detached')

def git_push(repo_path):
"""Push to remote branch"""
repo = _repo(repo_path)
if not repo.head.is_detached:
try:
print(' - Pushing local changes')
print(repo.git.push())
except:
cprint(' - Failed to push local changes', 'red')
print('')
sys.exit(1)
else:
print(' - HEAD is detached')

def git_reset_head(repo_path):
"""Reset head of repo, discarding changes"""
Expand Down Expand Up @@ -177,34 +239,6 @@ def git_status(repo_path):
repo = _repo(repo_path)
print(repo.git.status())

def git_prune(repo_path, branch, default_ref):
"""Start new branch in repository"""
repo = _repo(repo_path)
branch_output = colored('(' + branch + ')', 'magenta')
if branch in repo.heads:
prune_branch = repo.heads[branch]
if repo.head.ref == prune_branch:
truncated_ref = _truncate_ref(default_ref)
ref_output = colored('(' + truncated_ref + ')', 'magenta')
try:
print(' - Checking out ' + ref_output)
repo.git.checkout(truncated_ref)
except:
message = colored(' - Failed to checkout ref', 'red')
print(message + ref_output)
print('')
sys.exit(1)
try:
print(' - Deleting branch ' + branch_output)
repo.delete_head(branch)
except:
message = colored(' - Failed to delete branch', 'red')
print(message + branch_output)
print('')
sys.exit(1)
else:
print(' - Branch ' + branch_output + " doesn't exist")

def _checkout_branch(repo_path, branch, remote, depth):
"""Checkout branch, and create if it doesn't exist"""
repo = _repo(repo_path)
Expand Down
Loading

0 comments on commit f534a9f

Please sign in to comment.