view hq/main.py @ 4:44ea39c3e98f

add methods for dealing with the patch repositories
author Jeff Hammel <jhammel@mozilla.com>
date Tue, 25 May 2010 19:02:21 -0700
parents 8bc27dbf0214
children 448c248b3738
line wrap: on
line source

#!/usr/bin/env python
"""
mercurial queue extension front-end policy manager
"""

import os
import subprocess
import sys

from command import CommandParser

def call(command, *args, **kw):
    code = subprocess.call(command, *args, **kw)
    if code:
        if isinstance(command, basestring):
            cmdstr = command
        else:
            cmdstr = ' '.join(command)
        raise SystemExit("Command `%s` exited with code %d" % (cmdstr, code))

class HQ(object):
    """
    mercurial queue extension front-end policy manager
    """

    def __init__(self, parser, options):
        """initialize global options"""
        # TODO: look at hgrc file
        # for [defaults] repository_host

    def clone(self, repo, patch=None, queue=None):
        """
        clone the repository and begin a patch queue
        - path: name of a new patch to initiate
        - queue: name of the remote queue
        """
        directory = repo.rsplit('/', 1)
        call(['hg', 'clone', repo, directory])
        os.chdir(directory)
        call(['hg', 'qinit', '-c'])
        if queue:
            # pull from the given repository
            self._patch_command(*['hg', 'pull', '--update', queue])
        else:
            # (optionally) setup a new repo
            pass # TODO
            
        if patch:
            # create a new patch
            call(['hg', 'qnew', patch])

    def edit(self, patch=None):
        """
        edit a patch
        - patch: the patch to edit
        """

    def commit(self, message):
        """
        commit a patch and push it to the master repository
        """
        call(['hg', 'qrefresh'])
        call(['hg', 'qcommit', '-m', message])
        self._patch_command(*['hg', 'push'])

    def pull(self, repo=None):
        """
        pull from the root repository
        """
        # TODO: commit prior to realignment
        call(['hg', 'qpop', '--all'])
        call(['hg', 'pull'] + repo and [repo] or [])
        call(['hg', 'qpush', '--all'])

    def goto(self, patch):
        """
        goto a specific patch
        """
        # TODO
        process = subprocess.Popen(['hg', 'qapplied'], stdout=subprocess.PIPE)
        stdout, stderr = process.communicate()
        applied = [ i.strip() for i in stdout.splitlines()
                    if i ]
        raise NotImplementedError

    def files(self):
        """
        list the files added by the top patch
        """
        # TODO: should only list top-level directories, otherwise it's silly
        _oldcwd = os.getcwd()
        process = subprocess.Popen("hg qdiff | grep '^+++ ' | sed 's/+++ b\///'", stdout=subprocess.PIPE)
        stdout, stderr = process.communicate()
        return stdout

    def _patch_repo(self):
        """the location of the patch repository"""
        root = subprocess.Popen(['hg', 'root'], stdout=subprocess.PIPE).communicate()[0]
        return os.path.join(root, '.hg', 'patches')

    def _patch_command(self, *command):
        """perform a command in the patch repository"""
        _oldpwd = os.getcwd()
        os.chdir(self._patch_repo())
        call(command)
        os.chdir(_oldpwd)

def main(args=sys.argv[1:]):
    parser = CommandParser(HQ)
    options, args = parser.parse_args(args)
    parser.invoke(args)

if __name__ == '__main__':
    main()