Source

mercurial/extensions/rdiff / rdiff.py

# rdiff.py: diff against remote repositories
#
# Copyright 2007 Brendan Cully <brendan@kublai.com>
#
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.

'''diff against remote repositories

When this extension is loaded, if the first argument to the diff command
is a remote repository URL, the diff will be performed against that
URL. If revision arguments are given, the first revision is the revision
in the source repository, and the second revision is looked up in the
destination.
'''

from mercurial.i18n import _
from mercurial import bundlerepo, changegroup, cmdutil, commands, hg, patch
from mercurial import util

import os

def rdiff(ui, repo, url, lrev=None, rrev=None, *pats, **opts):
    other = hg.repository(ui, url)
    cmdutil.setremoteconfig(ui, opts)
    ui.status(_('comparing with %s\n') % url)

    if rrev:
        if 'lookup' in other.capabilities:
            rrev = other.lookup(rrev)
        else:
            error = _("Other repository doesn't support revision lookup, so a rev cannot be specified.")
            raise util.Abort(error)

    incoming = repo.findincoming(other, heads=rrev and [rrev] or [])
    if not incoming:
        # remote is a subset of local
        if not rrev:
            if 'lookup' in other.capabilities:
                rrev = other.lookup('tip')
            else:
                raise util.Abort(_('cannot determine remote tip'))
        other = repo

    bundle = None
    try:
        if incoming:
            # create a bundle (uncompressed if other repo is not local)
            if not rrev:
                cg = other.changegroup(incoming, "incoming")
            else:
                if 'changegroupsubset' not in other.capabilities:
                    raise util.Abort(_("Partial incoming cannot be done because other repository doesn't support changegroupsubset."))
                cg = other.changegroupsubset(incoming, rrev, 'incoming')
            bundle = changegroup.writebundle(cg, '', 'HG10UN')
            other = hg.repository(ui, bundle)

        if lrev:
            lrev = repo.changectx(lrev).node()
        rrev = other.changectx(rrev or 'tip').node()
        if opts['reverse']:
            lrev, rrev = rrev, lrev
        try:
            m = cmdutil.match(repo, pats, opts)
            patch.diff(other, lrev, rrev, match=m,
                       opts=patch.diffopts(ui, opts))
        except AttributeError:
            # 1.0 compatibility
            fns, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
            patch.diff(other, lrev, rrev, fns, match=matchfn,
                       opts=patch.diffopts(ui, opts))
            
    finally:
        if hasattr(other, 'close'):
            other.close()
        if bundle:
            os.unlink(bundle)

def diff(orig, ui, repo, *pats, **opts):
    url = None
    rrev = None
    if pats:
        path = ui.expandpath(pats[0])
        if hasattr(hg, 'parseurl'):
            # parseurl changed from returning two args to three
            args = hg.parseurl(ui.expandpath(pats[0]), [])
            path, rrev = args[0], args[-1]
        if '://' in path or os.path.isdir(os.path.join(path, '.hg')):
            url = path
            pats = pats[1:]

    if url:
        lrev = None
        if len(opts['rev']) > 2 or rrev and len(opts['rev']) > 1:
            raise util.Abort(_('too many revisions'))
        if opts['rev']:
            lrev = opts['rev'][0]
        if len(opts['rev']) > 1:
            rrev = opts['rev'][1]
        return rdiff(ui, repo, url, lrev, rrev, *pats, **opts)
    else:
        return orig(ui, repo, *pats, **opts)

def wrapcommand(table, command, wrapper):
    aliases, entry = cmdutil.findcmd(command, table)
    for alias, e in table.iteritems():
        if e is entry:
            key = alias
            break

    origfn = entry[0]
    def wrap(*args, **kwargs):
        return wrapper(origfn, *args, **kwargs)

    wrap.__doc__ = getattr(origfn, '__doc__')
    if wrapper.__doc__:
        if wrapper.__doc__.startswith('\n'):
            wrap.__doc__ += wrapper.__doc__
        else:
            wrap.__doc__ = wrapper.__doc__

    newentry = list(entry)
    newentry[0] = wrap
    table[key] = tuple(newentry)
    return entry

def uisetup(ui):
    rdiffopts = [('', 'reverse', None, _('reverse patch direction'))] + \
        commands.remoteopts

    entry = wrapcommand(commands.table, 'diff', diff)
    entry[1].extend(rdiffopts)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.