hgext/fetch.py
author Matt Mackall <mpm@selenic.com>
Wed, 01 Aug 2007 12:33:12 -0500
changeset 5045 f191bc3916f7
parent 4730 eadfaa9ec487
child 4959 97b734fb9c6f
permissions -rw-r--r--
merge: do early copy to deal with issue636 Without copies/renames, merges source names are 1:1 with their targets. Copies and renames introduce the possibility that there will be two merges with the same input but different output. By doing the copy to the destination name before the merge, the actual merge becomes 1:1 again, and no source is the input to two different merges. - add a preliminary scan to applyupdates to do copies - for the merge action, pass the old name (for finding ancestors) and the new name (for input to the merge) to filemerge - eliminate the old post-merge copy - lookup file contents from new name in filemerge - pass new name to external merge helper - report merge failure at new name - add a test
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2795
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
     1
# fetch.py - pull and merge remote changes
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
     2
#
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
     3
# Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
     4
#
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
     6
# of the GNU General Public License, incorporated herein by reference.
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
     7
3893
6b4127c7d52a Simplify i18n imports
Matt Mackall <mpm@selenic.com>
parents: 3886
diff changeset
     8
from mercurial.i18n import _
2795
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
     9
from mercurial.node import *
4549
0c61124ad877 dispatch: move dispatching code to cmdutil
Matt Mackall <mpm@selenic.com>
parents: 3893
diff changeset
    10
from mercurial import commands, cmdutil, hg, node, util
2795
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    11
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    12
def fetch(ui, repo, source='default', **opts):
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    13
    '''Pull changes from a remote repository, merge new changes if needed.
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    14
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    15
    This finds all changes from the repository at the specified path
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    16
    or URL and adds them to the local repository.
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    17
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    18
    If the pulled changes add a new head, the head is automatically
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    19
    merged, and the result of the merge is committed.  Otherwise, the
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    20
    working directory is updated.'''
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    21
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    22
    def postincoming(other, modheads):
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    23
        if modheads == 0:
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    24
            return 0
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    25
        if modheads == 1:
2837
3b21013e7680 fetch: fix test fail
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2830
diff changeset
    26
            return hg.clean(repo, repo.changelog.tip(), wlock=wlock)
2795
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    27
        newheads = repo.heads(parent)
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    28
        newchildren = [n for n in repo.heads(parent) if n != parent]
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    29
        newparent = parent
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    30
        if newchildren:
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    31
            newparent = newchildren[0]
2837
3b21013e7680 fetch: fix test fail
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2830
diff changeset
    32
            hg.clean(repo, newparent, wlock=wlock)
2795
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    33
        newheads = [n for n in repo.heads() if n != newparent]
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    34
        err = False
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    35
        if newheads:
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    36
            ui.status(_('merging with new head %d:%s\n') %
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    37
                      (repo.changelog.rev(newheads[0]), short(newheads[0])))
2830
49988d9f0758 Merge with crew, fix most tests
Matt Mackall <mpm@selenic.com>
parents: 2822 2816
diff changeset
    38
            err = hg.merge(repo, newheads[0], remind=False, wlock=wlock)
2795
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    39
        if not err and len(newheads) > 1:
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    40
            ui.status(_('not merging with %d other new heads '
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    41
                        '(use "hg heads" and "hg merge" to merge them)') %
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    42
                      (len(newheads) - 1))
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    43
        if not err:
2816
2a0c599f7bb0 fetch: hold lock and wlock across all operations
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2814
diff changeset
    44
            mod, add, rem = repo.status(wlock=wlock)[:3]
4549
0c61124ad877 dispatch: move dispatching code to cmdutil
Matt Mackall <mpm@selenic.com>
parents: 3893
diff changeset
    45
            message = (cmdutil.logmessage(opts) or
2795
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    46
                       (_('Automated merge with %s') % other.url()))
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    47
            n = repo.commit(mod + add + rem, message,
2816
2a0c599f7bb0 fetch: hold lock and wlock across all operations
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2814
diff changeset
    48
                            opts['user'], opts['date'], lock=lock, wlock=wlock,
2795
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    49
                            force_editor=opts.get('force_editor'))
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    50
            ui.status(_('new changeset %d:%s merges remote changes '
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    51
                        'with local\n') % (repo.changelog.rev(n),
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    52
                                           short(n)))
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    53
    def pull():
4549
0c61124ad877 dispatch: move dispatching code to cmdutil
Matt Mackall <mpm@selenic.com>
parents: 3893
diff changeset
    54
        cmdutil.setremoteconfig(ui, opts)
2795
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    55
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    56
        other = hg.repository(ui, ui.expandpath(source))
2816
2a0c599f7bb0 fetch: hold lock and wlock across all operations
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2814
diff changeset
    57
        ui.status(_('pulling from %s\n') % ui.expandpath(source))
2795
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    58
        revs = None
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    59
        if opts['rev'] and not other.local():
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    60
            raise util.Abort(_("fetch -r doesn't work for remote repositories yet"))
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    61
        elif opts['rev']:
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    62
            revs = [other.lookup(rev) for rev in opts['rev']]
2814
0496cfb05243 fetch: lock repo across pull and commit
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2813
diff changeset
    63
        modheads = repo.pull(other, heads=revs, lock=lock)
2795
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    64
        return postincoming(other, modheads)
3215
53e843840349 Whitespace/Tab cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 2837
diff changeset
    65
2795
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    66
    parent, p2 = repo.dirstate.parents()
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    67
    if parent != repo.changelog.tip():
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    68
        raise util.Abort(_('working dir not at tip '
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    69
                           '(use "hg update" to check out tip)'))
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    70
    if p2 != nullid:
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    71
        raise util.Abort(_('outstanding uncommitted merge'))
2816
2a0c599f7bb0 fetch: hold lock and wlock across all operations
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2814
diff changeset
    72
    wlock = repo.wlock()
2814
0496cfb05243 fetch: lock repo across pull and commit
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2813
diff changeset
    73
    lock = repo.lock()
0496cfb05243 fetch: lock repo across pull and commit
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2813
diff changeset
    74
    try:
2816
2a0c599f7bb0 fetch: hold lock and wlock across all operations
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2814
diff changeset
    75
        mod, add, rem = repo.status(wlock=wlock)[:3]
2a0c599f7bb0 fetch: hold lock and wlock across all operations
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2814
diff changeset
    76
        if mod or add or rem:
2a0c599f7bb0 fetch: hold lock and wlock across all operations
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2814
diff changeset
    77
            raise util.Abort(_('outstanding uncommitted changes'))
2a0c599f7bb0 fetch: hold lock and wlock across all operations
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2814
diff changeset
    78
        if len(repo.heads()) > 1:
2a0c599f7bb0 fetch: hold lock and wlock across all operations
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2814
diff changeset
    79
            raise util.Abort(_('multiple heads in this repository '
2a0c599f7bb0 fetch: hold lock and wlock across all operations
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2814
diff changeset
    80
                               '(use "hg heads" and "hg merge" to merge)'))
2814
0496cfb05243 fetch: lock repo across pull and commit
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2813
diff changeset
    81
        return pull()
0496cfb05243 fetch: lock repo across pull and commit
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2813
diff changeset
    82
    finally:
0496cfb05243 fetch: lock repo across pull and commit
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2813
diff changeset
    83
        lock.release()
2816
2a0c599f7bb0 fetch: hold lock and wlock across all operations
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2814
diff changeset
    84
        wlock.release()
2795
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    85
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    86
cmdtable = {
135823f37304 new extension: fetch -> combine pull and merge/update
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    87
    'fetch':
4730
eadfaa9ec487 Updated command tables in commands.py and hgext extensions.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4549
diff changeset
    88
        (fetch,
eadfaa9ec487 Updated command tables in commands.py and hgext extensions.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4549
diff changeset
    89
        [('e', 'ssh', '', _('specify ssh command to use')),
eadfaa9ec487 Updated command tables in commands.py and hgext extensions.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4549
diff changeset
    90
         ('m', 'message', '', _('use <text> as commit message')),
eadfaa9ec487 Updated command tables in commands.py and hgext extensions.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4549
diff changeset
    91
         ('l', 'logfile', '', _('read the commit message from <file>')),
eadfaa9ec487 Updated command tables in commands.py and hgext extensions.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4549
diff changeset
    92
         ('d', 'date', '', _('record datecode as commit date')),
eadfaa9ec487 Updated command tables in commands.py and hgext extensions.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4549
diff changeset
    93
         ('u', 'user', '', _('record user as commiter')),
eadfaa9ec487 Updated command tables in commands.py and hgext extensions.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4549
diff changeset
    94
         ('r', 'rev', [], _('a specific revision you would like to pull')),
eadfaa9ec487 Updated command tables in commands.py and hgext extensions.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4549
diff changeset
    95
         ('f', 'force-editor', None, _('edit commit message')),
eadfaa9ec487 Updated command tables in commands.py and hgext extensions.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4549
diff changeset
    96
         ('', 'remotecmd', '', _('hg command to run on the remote side'))],
eadfaa9ec487 Updated command tables in commands.py and hgext extensions.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4549
diff changeset
    97
        _('hg fetch [SOURCE]')),
eadfaa9ec487 Updated command tables in commands.py and hgext extensions.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4549
diff changeset
    98
}