mercurial/repair.py
author Alexis S. L. Carvalho <alexis@cecm.usp.br>
Sat, 19 Jan 2008 18:01:16 -0200
changeset 5901 16f4129c19ac
parent 5900 1206e3dfc906
child 5902 98f8dec8f437
permissions -rw-r--r--
repair.py: rename chlog to cl
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
5899
d7388ad85511 repair.py: use node.* directly
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5898
diff changeset
     9
import changegroup, os
d7388ad85511 repair.py: use node.* directly
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5898
diff changeset
    10
from node import *
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    11
5900
1206e3dfc906 repair.py: nodes are nodes, revs are revs
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5899
diff changeset
    12
def strip(ui, repo, node, backup="all"):
5901
16f4129c19ac repair.py: rename chlog to cl
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5900
diff changeset
    13
    def limitheads(cl, stop):
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    14
        """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
    15
        p = {}
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    16
        h = []
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    17
        stoprev = 0
5901
16f4129c19ac repair.py: rename chlog to cl
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5900
diff changeset
    18
        if stop in cl.nodemap:
16f4129c19ac repair.py: rename chlog to cl
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5900
diff changeset
    19
            stoprev = cl.rev(stop)
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    20
5901
16f4129c19ac repair.py: rename chlog to cl
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5900
diff changeset
    21
        for r in xrange(cl.count() - 1, -1, -1):
16f4129c19ac repair.py: rename chlog to cl
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5900
diff changeset
    22
            n = cl.node(r)
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    23
            if n not in p:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    24
                h.append(n)
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    25
            if n == stop:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    26
                break
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    27
            if r < stoprev:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    28
                break
5901
16f4129c19ac repair.py: rename chlog to cl
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5900
diff changeset
    29
            for pn in cl.parents(n):
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    30
                p[pn] = 1
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    31
        return h
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    32
5900
1206e3dfc906 repair.py: nodes are nodes, revs are revs
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5899
diff changeset
    33
    def bundle(repo, bases, heads, node, suffix):
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    34
        cg = repo.changegroupsubset(bases, heads, 'strip')
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    35
        backupdir = repo.join("strip-backup")
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    36
        if not os.path.isdir(backupdir):
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    37
            os.mkdir(backupdir)
5900
1206e3dfc906 repair.py: nodes are nodes, revs are revs
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5899
diff changeset
    38
        name = os.path.join(backupdir, "%s-%s" % (short(node), suffix))
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    39
        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
    40
        return changegroup.writebundle(cg, name, "HG10BZ")
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    41
5900
1206e3dfc906 repair.py: nodes are nodes, revs are revs
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5899
diff changeset
    42
    def stripall(striprev):
1206e3dfc906 repair.py: nodes are nodes, revs are revs
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5899
diff changeset
    43
        mm = repo.changectx(node).manifest()
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    44
        seen = {}
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    45
5900
1206e3dfc906 repair.py: nodes are nodes, revs are revs
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5899
diff changeset
    46
        for x in xrange(striprev, repo.changelog.count()):
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    47
            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
    48
                if f in seen:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    49
                    continue
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    50
                seen[f] = 1
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    51
                if f in mm:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    52
                    filerev = mm[f]
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    53
                else:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    54
                    filerev = 0
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    55
                seen[f] = filerev
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    56
        # 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
    57
        # 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
    58
        # our disk access patterns under control.
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    59
        seen_list = seen.keys()
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    60
        seen_list.sort()
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    61
        for f in seen_list:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    62
            ff = repo.file(f)
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    63
            filerev = seen[f]
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    64
            if filerev != 0:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    65
                if filerev in ff.nodemap:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    66
                    filerev = ff.rev(filerev)
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    67
                else:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    68
                    filerev = 0
5900
1206e3dfc906 repair.py: nodes are nodes, revs are revs
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5899
diff changeset
    69
            ff.strip(filerev, striprev)
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    70
5901
16f4129c19ac repair.py: rename chlog to cl
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5900
diff changeset
    71
    cl = repo.changelog
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    72
    # TODO delete the undo files, and handle undo of merge sets
5901
16f4129c19ac repair.py: rename chlog to cl
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5900
diff changeset
    73
    pp = cl.parents(node)
16f4129c19ac repair.py: rename chlog to cl
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5900
diff changeset
    74
    striprev = cl.rev(node)
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    75
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    76
    # 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
    77
    # 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
    78
    # 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
    79
    saveheads = []
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    80
    savebases = {}
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    81
5901
16f4129c19ac repair.py: rename chlog to cl
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5900
diff changeset
    82
    heads = limitheads(cl, node)
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    83
    seen = {}
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    84
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    85
    # 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
    86
    # 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
    87
    # 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
    88
    while heads:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    89
        h = heads.pop()
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    90
        n = h
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    91
        while True:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    92
            seen[n] = 1
5901
16f4129c19ac repair.py: rename chlog to cl
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5900
diff changeset
    93
            pp = cl.parents(n)
5899
d7388ad85511 repair.py: use node.* directly
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5898
diff changeset
    94
            if pp[1] != nullid:
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    95
                for p in pp:
5901
16f4129c19ac repair.py: rename chlog to cl
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5900
diff changeset
    96
                    if cl.rev(p) > striprev and p not in seen:
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    97
                        heads.append(p)
5899
d7388ad85511 repair.py: use node.* directly
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5898
diff changeset
    98
            if pp[0] == nullid:
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    99
                break
5901
16f4129c19ac repair.py: rename chlog to cl
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5900
diff changeset
   100
            if cl.rev(pp[0]) < striprev:
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   101
                break
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   102
            n = pp[0]
5900
1206e3dfc906 repair.py: nodes are nodes, revs are revs
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5899
diff changeset
   103
            if n == node:
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   104
                break
5901
16f4129c19ac repair.py: rename chlog to cl
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5900
diff changeset
   105
        r = cl.reachable(h, node)
5900
1206e3dfc906 repair.py: nodes are nodes, revs are revs
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5899
diff changeset
   106
        if node not in r:
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   107
            saveheads.append(h)
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   108
            for x in r:
5901
16f4129c19ac repair.py: rename chlog to cl
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5900
diff changeset
   109
                if cl.rev(x) > striprev:
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   110
                    savebases[x] = 1
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   111
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   112
    # 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
   113
    if backup == "all":
5901
16f4129c19ac repair.py: rename chlog to cl
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5900
diff changeset
   114
        bundle(repo, [node], cl.heads(), node, 'backup')
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   115
    if saveheads:
5900
1206e3dfc906 repair.py: nodes are nodes, revs are revs
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5899
diff changeset
   116
        chgrpfile = bundle(repo, savebases.keys(), saveheads, node, 'temp')
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   117
5900
1206e3dfc906 repair.py: nodes are nodes, revs are revs
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5899
diff changeset
   118
    stripall(striprev)
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   119
5901
16f4129c19ac repair.py: rename chlog to cl
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5900
diff changeset
   120
    change = cl.read(node)
16f4129c19ac repair.py: rename chlog to cl
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5900
diff changeset
   121
    cl.strip(striprev, striprev)
5900
1206e3dfc906 repair.py: nodes are nodes, revs are revs
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5899
diff changeset
   122
    repo.manifest.strip(repo.manifest.rev(change[0]), striprev)
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   123
    if saveheads:
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   124
        ui.status("adding branch\n")
5898
52cfe86ebe55 repair.py: don't import commands.py
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4702
diff changeset
   125
        f = open(chgrpfile, "rb")
52cfe86ebe55 repair.py: don't import commands.py
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4702
diff changeset
   126
        gen = changegroup.readbundle(f, chgrpfile)
52cfe86ebe55 repair.py: don't import commands.py
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4702
diff changeset
   127
        repo.addchangegroup(gen, 'strip', 'bundle:' + chgrpfile)
52cfe86ebe55 repair.py: don't import commands.py
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4702
diff changeset
   128
        f.close()
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   129
        if backup != "strip":
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   130
            os.unlink(chgrpfile)
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   131