Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
211 lines (179 sloc) 6.54 KB
import subprocess
import os
import click
class Repo(object):
def __init__(self, debug, vc_name='git'):
self.debug = debug
self.vc_name = vc_name
self.FNULL = open(os.devnull, 'w')
def call(self, args, devnull=False):
"""Call other processes.
args - list of command args
devnull - whether to pipe stdout to /dev/null (or equivalent)
"""
if self.debug:
click.echo(subprocess.list2cmdline(args))
click.confirm('Continue?', default=True, abort=True)
try:
kwargs = {}
if devnull:
# Pipe to /dev/null (or equivalent).
kwargs['stderr'] = subprocess.STDOUT
kwargs['stdout'] = self.FNULL
ret_code = subprocess.call(args, **kwargs)
except subprocess.CalledProcessError:
return False
return ret_code
def find_repo_type(self):
"""Check for git or hg repository"""
is_git = self.call(['git', 'rev-parse', '--is-inside-work-tree'],
devnull=True)
if is_git != 0:
if self.debug:
click.echo('not git')
is_hg = self.call(['hg', '-q', 'stat'], devnull=True)
if is_hg != 0:
if self.debug:
click.echo('not hg')
exit(1)
else:
self.vc_name = 'hg'
@click.group()
@click.pass_context
@click.option('--debug', is_flag=True, default=False)
@click.version_option()
def main(context, debug):
context.obj = Repo(debug)
@main.command()
@click.argument('file_names', nargs=-1, type=click.Path())
@click.pass_context
def track(context, file_names):
"""Keep track of each file in list file_names.
Tracking does not create or delete the actual file, it only tells the
version control system whether to maintain versions (to keep track) of
the file.
"""
context.obj.find_repo_type()
for fn in file_names:
context.obj.call([context.obj.vc_name, 'add', fn])
@main.command()
@click.argument('file_names', nargs=-1, type=click.Path())
@click.pass_context
def untrack(context, file_names):
"""Forget about tracking each file in the list file_names
Tracking does not create or delete the actual file, it only tells the
version control system whether to maintain versions (to keep track) of
the file.
"""
context.obj.find_repo_type()
for fn in file_names:
if context.obj.vc_name == 'git':
context.obj.call(['git', 'rm', '--cached', fn])
elif context.obj.vc_name == 'hg':
context.obj.call(['hg', 'forget', fn])
@main.command()
@click.argument('message')
@click.option('--name', default='')
@click.pass_context
def commit(context, message, name):
"""Commit saved changes to the repository.
message - commit message
name - tag name
"""
context.obj.find_repo_type()
if context.obj.vc_name == 'git':
context.obj.call(['git', 'commit', '-a', '-m', message])
elif context.obj.vc_name == 'hg':
context.obj.call(['hg', 'commit', '-m', message])
if name != '' and context.obj.vc_name == 'git':
context.obj.call(['git', 'tag', '-a', name, '-m', message])
elif name != '' and context.obj.vc_name == 'hg':
context.obj.call(['hg', 'tag', '-m', message, name])
@main.command()
@click.argument('message')
@click.option('--name', default='')
@click.pass_context
def ci(context, message, name):
"""alias for commit"""
context.forward(commit)
@main.command()
@click.argument('file_names', nargs=-1, type=click.Path())
@click.pass_context
def revert(context, file_names):
"""Revert each file in the list file_names back to version in repo"""
context.obj.find_repo_type()
if len(file_names) == 0:
click.echo('No file names to checkout specified.')
click.echo('The following have changed since the last check in.')
context.invoke(status)
for fn in file_names:
if context.obj.vc_name == 'git':
context.obj.call(['git', 'checkout', '--', fn])
elif context.obj.vc_name == 'hg':
context.obj.call(['hg', 'revert', '--no-backup', fn])
@main.command()
@click.pass_context
def up(context):
"""(upload) Synchronise local repo to remote repo"""
context.obj.find_repo_type()
if context.obj.vc_name == 'git':
context.obj.call(['git', 'push'])
context.obj.call(['git', 'push', '--tags'])
elif context.obj.vc_name == 'hg':
context.obj.call(['hg', 'push'])
@main.command()
@click.argument('repo_url', nargs=1, default='')
@click.pass_context
def down(context, repo_url):
"""(download) Synchronise remote repo to local repo.
If repo_url is given, then clone from remote URL.
"""
if repo_url == '':
context.obj.find_repo_type()
if context.obj.vc_name == 'git':
context.obj.call(['git', 'pull'])
elif context.obj.vc_name == 'hg':
context.obj.call(['hg', 'pull', '-u'])
else:
context.obj.call([context.obj.vc_name, 'clone', repo_url])
@main.command()
@click.pass_context
def status(context):
"""See which files have changed, checked in, and uploaded"""
context.obj.find_repo_type()
context.obj.call([context.obj.vc_name, 'status'])
@main.command()
@click.pass_context
def log(context):
"""See history"""
context.obj.find_repo_type()
if context.obj.vc_name == 'git':
format = ("--pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset "
"%s %Cgreen(%cr) %C(bold blue)<%an>%Creset'")
context.obj.call(['git', 'log', '--graph', format,
'--abbrev-commit', '--stat'])
elif context.obj.vc_name == 'hg':
template = (
'"changeset: {rev}:{node|short} {tags}\n'
' summary: {desc|firstline|fill68|tabindent|tabindent}"')
context.obj.call(['hg', 'log', '-G', '--template', template])
@main.command()
@click.argument('file_name', default='')
@click.pass_context
def diff(context, file_name):
"""See changes that occured since last check in"""
context.obj.find_repo_type()
if context.obj.vc_name == 'git':
context.obj.call(['git', 'diff', '--color-words',
'--ignore-space-change', file_name])
elif context.obj.vc_name == 'hg':
context.obj.call(['hg', 'diff', file_name])
main.add_command(track)
main.add_command(untrack)
main.add_command(commit)
main.add_command(revert)
main.add_command(up)
main.add_command(down)
main.add_command(status)
main.add_command(log)
main.add_command(diff)
You can’t perform that action at this time.