mercurial/repair.py
author Brendan Cully <brendan@kublai.com>
Wed, 15 Aug 2007 14:38:18 -0700
changeset 5173 7e05bdeee7de
parent 4702 18e91c9def0c
permissions -rw-r--r--
convert: raise Abort instead of NoRepo when CVS pserver auth fails. At this point we know the source is CVS, so we should not go through the rest of the converters.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     1
# repair.py - functions for repository repair for mercurial
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     2
#
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     3
# Copyright 2005, 2006 Chris Mason <mason@suse.com>
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     4
# Copyright 2007 Matt Mackall
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     5
#
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     6
# This software may be used and distributed according to the terms
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     7
# of the GNU General Public License, incorporated herein by reference.
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     8
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     9
import changegroup, revlog, os, commands
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    10
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    11
def strip(ui, repo, rev, backup="all"):
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    12
    def limitheads(chlog, stop):
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    13
        """return the list of all nodes that have no children"""
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    14
        p = {}
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    15
        h = []
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    16
        stoprev = 0
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    17
        if stop in chlog.nodemap:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    18
            stoprev = chlog.rev(stop)
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    19
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    20
        for r in xrange(chlog.count() - 1, -1, -1):
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    21
            n = chlog.node(r)
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    22
            if n not in p:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    23
                h.append(n)
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    24
            if n == stop:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    25
                break
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    26
            if r < stoprev:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    27
                break
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    28
            for pn in chlog.parents(n):
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    29
                p[pn] = 1
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    30
        return h
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    31
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    32
    def bundle(repo, bases, heads, rev, suffix):
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    33
        cg = repo.changegroupsubset(bases, heads, 'strip')
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    34
        backupdir = repo.join("strip-backup")
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    35
        if not os.path.isdir(backupdir):
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    36
            os.mkdir(backupdir)
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    37
        name = os.path.join(backupdir, "%s-%s" % (revlog.short(rev), suffix))
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    38
        ui.warn("saving bundle to %s\n" % name)
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    39
        return changegroup.writebundle(cg, name, "HG10BZ")
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    40
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    41
    def stripall(revnum):
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    42
        mm = repo.changectx(rev).manifest()
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    43
        seen = {}
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    44
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    45
        for x in xrange(revnum, repo.changelog.count()):
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    46
            for f in repo.changectx(x).files():
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    47
                if f in seen:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    48
                    continue
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    49
                seen[f] = 1
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    50
                if f in mm:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    51
                    filerev = mm[f]
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    52
                else:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    53
                    filerev = 0
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    54
                seen[f] = filerev
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    55
        # we go in two steps here so the strip loop happens in a
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    56
        # sensible order.  When stripping many files, this helps keep
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    57
        # our disk access patterns under control.
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    58
        seen_list = seen.keys()
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    59
        seen_list.sort()
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    60
        for f in seen_list:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    61
            ff = repo.file(f)
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    62
            filerev = seen[f]
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    63
            if filerev != 0:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    64
                if filerev in ff.nodemap:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    65
                    filerev = ff.rev(filerev)
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    66
                else:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    67
                    filerev = 0
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    68
            ff.strip(filerev, revnum)
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    69
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    70
    chlog = repo.changelog
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    71
    # TODO delete the undo files, and handle undo of merge sets
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    72
    pp = chlog.parents(rev)
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    73
    revnum = chlog.rev(rev)
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    74
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    75
    # save is a list of all the branches we are truncating away
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    76
    # that we actually want to keep.  changegroup will be used
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    77
    # to preserve them and add them back after the truncate
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    78
    saveheads = []
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    79
    savebases = {}
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    80
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    81
    heads = limitheads(chlog, rev)
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    82
    seen = {}
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    83
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    84
    # search through all the heads, finding those where the revision
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    85
    # we want to strip away is an ancestor.  Also look for merges
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    86
    # that might be turned into new heads by the strip.
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    87
    while heads:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    88
        h = heads.pop()
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    89
        n = h
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    90
        while True:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    91
            seen[n] = 1
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    92
            pp = chlog.parents(n)
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    93
            if pp[1] != revlog.nullid:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    94
                for p in pp:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    95
                    if chlog.rev(p) > revnum and p not in seen:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    96
                        heads.append(p)
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    97
            if pp[0] == revlog.nullid:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    98
                break
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    99
            if chlog.rev(pp[0]) < revnum:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   100
                break
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   101
            n = pp[0]
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   102
            if n == rev:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   103
                break
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   104
        r = chlog.reachable(h, rev)
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   105
        if rev not in r:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   106
            saveheads.append(h)
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   107
            for x in r:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   108
                if chlog.rev(x) > revnum:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   109
                    savebases[x] = 1
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   110
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   111
    # create a changegroup for all the branches we need to keep
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   112
    if backup == "all":
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   113
        bundle(repo, [rev], chlog.heads(), rev, 'backup')
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   114
    if saveheads:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   115
        chgrpfile = bundle(repo, savebases.keys(), saveheads, rev, 'temp')
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   116
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   117
    stripall(revnum)
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   118
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   119
    change = chlog.read(rev)
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   120
    chlog.strip(revnum, revnum)
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   121
    repo.manifest.strip(repo.manifest.rev(change[0]), revnum)
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   122
    if saveheads:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   123
        ui.status("adding branch\n")
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   124
        commands.unbundle(ui, repo, "file:%s" % chgrpfile, update=False)
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   125
        if backup != "strip":
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   126
            os.unlink(chgrpfile)
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   127