view gut/main.py @ 4:190ce22e7e83

scour the log and format it like a civilized human being
author Jeff Hammel <jhammel@mozilla.com>
date Fri, 16 Jul 2010 16:18:06 -0700
parents 4d38d14cf1d4
children ef895ddba2d3
line wrap: on
line source

#!/usr/bin/env python
"""
a workflow for git
"""

import os
import subprocess
import sys

from command import CommandParser

def call(command, **kw):
    if isinstance(command, basestring):
        kw['shell'] = True
    output = kw.pop('output', True)
    if output or kw.pop('pipe', False):
        kw['stdout'] = subprocess.PIPE
        kw['stderr'] = subprocess.PIPE
    check = kw.pop('check', True)
    process = subprocess.Popen(command, **kw)
    stdout, stderr = process.communicate()
    code = process.poll()
    if check and code:
        if isinstance(command, basestring):
            cmdstr = command
        else:
            cmdstr = ' '.join(command)
        raise SystemExit("Command `%s` exited with code %d" % (cmdstr, code))
    if output:
        print stdout
        print stderr
    return dict(stdout=stdout, stderr=stderr, code=code)

def fake_call(command, **kw):
    if isinstance(command, basestring):
        print command
    else:
        print ' '.join(command)

class gut(object):
    """
    a workflow for git
    """

    def __init__(self, remote=None, simulate=False):
        """
        - remote: name of the remote repository in .git/config
        - simulate: print what calls will be used but don't run them
        """
        self.remote = remote
        self.simulate = simulate
        if simulate:
            globals()['call'] = fake_call

    def update(self):
        """update the master and the branch you're on"""
        call(['git', 'checkout', 'master'])
        call(['git', 'pull', 'origin', 'master'])
        if self.remote:
            call(['git', 'pull', self.remote, 'master'])

    def feature(self, name):
        """make a new feature branch"""
        call(['git', 'checkout', 'master'])
        call(['git', 'checkout', '-b', name])
        call(['git', 'push', 'origin', name])

    def patch(self, output=None):
        """generate a patch for review"""
        diff = call(['git', 'diff', 'master'], pipe=True, output=False)
        log = call(['git', 'log', 'master..'], pipe=True, output=False)
        if self.simulate:
            return
        if not output:
            output = self.branch() + '.diff'
        diff = diff['stdout']
        log = log['stdout']

        # format the log
        lines = []
        oldline = None
        for line in log.splitlines():
            if not line:
                continue
            if line[0].strip():
                if oldline:
                    lines.append(oldline)
                    oldline = None
                incomment = False
                continue
            line = line.strip()
            if line.startswith('*'):
                if oldline:
                    lines.append(oldline)
                    oldline = None
                lines.append(line[1:].strip())
                continue
            if oldline:
                oldline = oldline + ' ' + line
            else:
                oldline = line
        else:
            if oldline:
                lines.append(oldline)
        log = '\n\n'.join(['* %s' % line for line in lines])
                
        f = file(output, 'w') # write the output to a patch file
        print >> f, diff
        f.close()
        return log

    def branch(self):
        """print what branch you're on"""
        output = call(['git', 'branch'], output=False, pipe=True)
        if self.simulate:
            return
        for line in output['stdout'].splitlines():
            if line.startswith('*'):
                return line[1:].strip()

def main(args=sys.argv[1:]):
    parser = CommandParser(gut)
    parser.invoke(args)

if __name__ == '__main__':
    main()