hgext/convert/hg.py
author Brendan Cully <brendan@kublai.com>
Wed, 15 Aug 2007 13:21:23 -0700
changeset 5172 6b4c332f241b
parent 5117 d4fa6bafc43a
child 5192 33015dac5df5
permissions -rw-r--r--
convert: hg: optionally create branches as clones If convert.hg.clonebranches is set, branches will be created as clones of their parent revisions. All clones will be subdirectories of the destination path.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
4534
cc9b79216a76 Split convert extension into common and repository type modules
Brendan Cully <brendan@kublai.com>
parents: 4532
diff changeset
     1
# hg backend for convert extension
3954
fad134931327 convert-repo: add basic CVS import support
Matt Mackall <mpm@selenic.com>
parents: 3948
diff changeset
     2
5013
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
     3
# Note for hg->hg conversion: Old versions of Mercurial didn't trim
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
     4
# the whitespace from the ends of commit messages, but new versions
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
     5
# do.  Changesets created by those older versions, then converted, may
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
     6
# thus have different hashes for changesets that are otherwise
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
     7
# identical.
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
     8
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
     9
4534
cc9b79216a76 Split convert extension into common and repository type modules
Brendan Cully <brendan@kublai.com>
parents: 4532
diff changeset
    10
import os, time
5014
914054ca532e convert: acquire/release locks periodically
Bryan O'Sullivan <bos@serpentine.com>
parents: 5013
diff changeset
    11
from mercurial.i18n import _
5013
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
    12
from mercurial.node import *
5014
914054ca532e convert: acquire/release locks periodically
Bryan O'Sullivan <bos@serpentine.com>
parents: 5013
diff changeset
    13
from mercurial import hg, lock, revlog, util
3954
fad134931327 convert-repo: add basic CVS import support
Matt Mackall <mpm@selenic.com>
parents: 3948
diff changeset
    14
5013
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
    15
from common import NoRepo, commit, converter_source, converter_sink
694
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
    16
5013
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
    17
class mercurial_sink(converter_sink):
4756
8e9d3faec270 convert: split converter into convertsource and convertsink
Brendan Cully <brendan@kublai.com>
parents: 4753
diff changeset
    18
    def __init__(self, ui, path):
316
c48d069163d6 Add new convert-repo script
mpm@selenic.com
parents:
diff changeset
    19
        self.path = path
4513
ac2fe196ac9b Turns convert.py into a real extension
Edouard Gomez <ed.gomez@free.fr>
parents: 4512
diff changeset
    20
        self.ui = ui
5172
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    21
        self.branchnames = ui.configbool('convert', 'hg.usebranchnames', True)
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    22
        self.clonebranches = ui.configbool('convert', 'hg.clonebranches', False)
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    23
        self.lastbranch = None
3947
0fab73b3f453 convert-repo: add some smarts
Matt Mackall <mpm@selenic.com>
parents: 3916
diff changeset
    24
        try:
4513
ac2fe196ac9b Turns convert.py into a real extension
Edouard Gomez <ed.gomez@free.fr>
parents: 4512
diff changeset
    25
            self.repo = hg.repository(self.ui, path)
3947
0fab73b3f453 convert-repo: add some smarts
Matt Mackall <mpm@selenic.com>
parents: 3916
diff changeset
    26
        except:
5013
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
    27
            raise NoRepo("could not open hg repo %s as sink" % path)
5014
914054ca532e convert: acquire/release locks periodically
Bryan O'Sullivan <bos@serpentine.com>
parents: 5013
diff changeset
    28
        self.lock = None
914054ca532e convert: acquire/release locks periodically
Bryan O'Sullivan <bos@serpentine.com>
parents: 5013
diff changeset
    29
        self.wlock = None
914054ca532e convert: acquire/release locks periodically
Bryan O'Sullivan <bos@serpentine.com>
parents: 5013
diff changeset
    30
914054ca532e convert: acquire/release locks periodically
Bryan O'Sullivan <bos@serpentine.com>
parents: 5013
diff changeset
    31
    def before(self):
5052
a11e8a181bd5 convert: fix locking order
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5038
diff changeset
    32
        self.wlock = self.repo.wlock()
5014
914054ca532e convert: acquire/release locks periodically
Bryan O'Sullivan <bos@serpentine.com>
parents: 5013
diff changeset
    33
        self.lock = self.repo.lock()
914054ca532e convert: acquire/release locks periodically
Bryan O'Sullivan <bos@serpentine.com>
parents: 5013
diff changeset
    34
914054ca532e convert: acquire/release locks periodically
Bryan O'Sullivan <bos@serpentine.com>
parents: 5013
diff changeset
    35
    def after(self):
914054ca532e convert: acquire/release locks periodically
Bryan O'Sullivan <bos@serpentine.com>
parents: 5013
diff changeset
    36
        self.lock = None
914054ca532e convert: acquire/release locks periodically
Bryan O'Sullivan <bos@serpentine.com>
parents: 5013
diff changeset
    37
        self.wlock = None
3947
0fab73b3f453 convert-repo: add some smarts
Matt Mackall <mpm@selenic.com>
parents: 3916
diff changeset
    38
5011
89fbb0a5e8e3 convert: rename mapfile to revmapfile, so we can map more than just revs
Bryan O'Sullivan <bos@serpentine.com>
parents: 4965
diff changeset
    39
    def revmapfile(self):
3947
0fab73b3f453 convert-repo: add some smarts
Matt Mackall <mpm@selenic.com>
parents: 3916
diff changeset
    40
        return os.path.join(self.path, ".hg", "shamap")
316
c48d069163d6 Add new convert-repo script
mpm@selenic.com
parents:
diff changeset
    41
4589
451e91ed535e convert extension: Add support for username mapping
Edouard Gomez <ed.gomez@free.fr>
parents: 4534
diff changeset
    42
    def authorfile(self):
451e91ed535e convert extension: Add support for username mapping
Edouard Gomez <ed.gomez@free.fr>
parents: 4534
diff changeset
    43
        return os.path.join(self.path, ".hg", "authormap")
451e91ed535e convert extension: Add support for username mapping
Edouard Gomez <ed.gomez@free.fr>
parents: 4534
diff changeset
    44
316
c48d069163d6 Add new convert-repo script
mpm@selenic.com
parents:
diff changeset
    45
    def getheads(self):
c48d069163d6 Add new convert-repo script
mpm@selenic.com
parents:
diff changeset
    46
        h = self.repo.changelog.heads()
5017
06329efa722d convert: get rid of "hg." prefix where not needed
Bryan O'Sullivan <bos@serpentine.com>
parents: 5016
diff changeset
    47
        return [ hex(x) for x in h ]
692
695dd9a491da convert-repo: deal with packed git and other fixes
mpm@selenic.com
parents: 450
diff changeset
    48
316
c48d069163d6 Add new convert-repo script
mpm@selenic.com
parents:
diff changeset
    49
    def putfile(self, f, e, data):
4082
6b2909e84203 convert-repo converts symlinks from git
Daniel Holth <dholth@fastmail.fm>
parents: 4062
diff changeset
    50
        self.repo.wwrite(f, data, e)
4950
30847b8af7ca dirstate: add __contains__ and make __getitem__ more useful
Matt Mackall <mpm@selenic.com>
parents: 4948
diff changeset
    51
        if f not in self.repo.dirstate:
4948
6fd953d5faea dirstate: break update into separate functions
Matt Mackall <mpm@selenic.com>
parents: 4873
diff changeset
    52
            self.repo.dirstate.add(f)
692
695dd9a491da convert-repo: deal with packed git and other fixes
mpm@selenic.com
parents: 450
diff changeset
    53
4758
b6a1f2c46c6c convert extension: Add SVN converter
Daniel Holth <dholth@fastmail.fm>
parents: 4756
diff changeset
    54
    def copyfile(self, source, dest):
b6a1f2c46c6c convert extension: Add SVN converter
Daniel Holth <dholth@fastmail.fm>
parents: 4756
diff changeset
    55
        self.repo.copy(source, dest)
b6a1f2c46c6c convert extension: Add SVN converter
Daniel Holth <dholth@fastmail.fm>
parents: 4756
diff changeset
    56
316
c48d069163d6 Add new convert-repo script
mpm@selenic.com
parents:
diff changeset
    57
    def delfile(self, f):
c48d069163d6 Add new convert-repo script
mpm@selenic.com
parents:
diff changeset
    58
        try:
c48d069163d6 Add new convert-repo script
mpm@selenic.com
parents:
diff changeset
    59
            os.unlink(self.repo.wjoin(f))
692
695dd9a491da convert-repo: deal with packed git and other fixes
mpm@selenic.com
parents: 450
diff changeset
    60
            #self.repo.remove([f])
316
c48d069163d6 Add new convert-repo script
mpm@selenic.com
parents:
diff changeset
    61
        except:
c48d069163d6 Add new convert-repo script
mpm@selenic.com
parents:
diff changeset
    62
            pass
c48d069163d6 Add new convert-repo script
mpm@selenic.com
parents:
diff changeset
    63
5172
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    64
    def setbranch(self, branch, pbranch, parents):
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    65
        if (not self.clonebranches) or (branch == self.lastbranch):
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    66
            return
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    67
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    68
        self.lastbranch = branch
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    69
        self.after()
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    70
        if not branch:
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    71
            branch = 'default'
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    72
        if not pbranch:
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    73
            pbranch = 'default'
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    74
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    75
        branchpath = os.path.join(self.path, branch)
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    76
        try:
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    77
            self.repo = hg.repository(self.ui, branchpath)
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    78
        except:
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    79
            if not parents:
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    80
                self.repo = hg.repository(self.ui, branchpath, create=True)
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    81
            else:
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    82
                self.ui.note(_('cloning branch %s to %s\n') % (pbranch, branch))
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    83
                hg.clone(self.ui, os.path.join(self.path, pbranch),
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    84
                         branchpath, rev=parents, update=False,
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    85
                         stream=True)
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    86
                self.repo = hg.repository(self.ui, branchpath)
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    87
3955
9af4b853ed4d convert-repo: add CVS branch support
Matt Mackall <mpm@selenic.com>
parents: 3954
diff changeset
    88
    def putcommit(self, files, parents, commit):
5016
4ebc8693ce72 convert: add filename filtering and renaming support
Bryan O'Sullivan <bos@serpentine.com>
parents: 5014
diff changeset
    89
        if not files:
4ebc8693ce72 convert: add filename filtering and renaming support
Bryan O'Sullivan <bos@serpentine.com>
parents: 5014
diff changeset
    90
            return hex(self.repo.changelog.tip())
4ebc8693ce72 convert: add filename filtering and renaming support
Bryan O'Sullivan <bos@serpentine.com>
parents: 5014
diff changeset
    91
4ebc8693ce72 convert: add filename filtering and renaming support
Bryan O'Sullivan <bos@serpentine.com>
parents: 5014
diff changeset
    92
        seen = {hex(nullid): 1}
431
dfc44f3f587c convert-repo fixups
mpm@selenic.com
parents: 316
diff changeset
    93
        pl = []
dfc44f3f587c convert-repo fixups
mpm@selenic.com
parents: 316
diff changeset
    94
        for p in parents:
dfc44f3f587c convert-repo fixups
mpm@selenic.com
parents: 316
diff changeset
    95
            if p not in seen:
dfc44f3f587c convert-repo fixups
mpm@selenic.com
parents: 316
diff changeset
    96
                pl.append(p)
dfc44f3f587c convert-repo fixups
mpm@selenic.com
parents: 316
diff changeset
    97
                seen[p] = 1
dfc44f3f587c convert-repo fixups
mpm@selenic.com
parents: 316
diff changeset
    98
        parents = pl
316
c48d069163d6 Add new convert-repo script
mpm@selenic.com
parents:
diff changeset
    99
692
695dd9a491da convert-repo: deal with packed git and other fixes
mpm@selenic.com
parents: 450
diff changeset
   100
        if len(parents) < 2: parents.append("0" * 40)
695dd9a491da convert-repo: deal with packed git and other fixes
mpm@selenic.com
parents: 450
diff changeset
   101
        if len(parents) < 2: parents.append("0" * 40)
431
dfc44f3f587c convert-repo fixups
mpm@selenic.com
parents: 316
diff changeset
   102
        p2 = parents.pop(0)
692
695dd9a491da convert-repo: deal with packed git and other fixes
mpm@selenic.com
parents: 450
diff changeset
   103
3955
9af4b853ed4d convert-repo: add CVS branch support
Matt Mackall <mpm@selenic.com>
parents: 3954
diff changeset
   104
        text = commit.desc
9af4b853ed4d convert-repo: add CVS branch support
Matt Mackall <mpm@selenic.com>
parents: 3954
diff changeset
   105
        extra = {}
5038
8f157190075e convert: add config option to turn off use of branch names
Bryan O'Sullivan <bos@serpentine.com>
parents: 5017
diff changeset
   106
        if self.branchnames and commit.branch:
4873
28b23b9073a8 convert: record the source revision in the changelog
Brendan Cully <brendan@kublai.com>
parents: 4758
diff changeset
   107
            extra['branch'] = commit.branch
28b23b9073a8 convert: record the source revision in the changelog
Brendan Cully <brendan@kublai.com>
parents: 4758
diff changeset
   108
        if commit.rev:
28b23b9073a8 convert: record the source revision in the changelog
Brendan Cully <brendan@kublai.com>
parents: 4758
diff changeset
   109
            extra['convert_revision'] = commit.rev
4939
cdd33a048289 removed trailing whitespace
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4873
diff changeset
   110
431
dfc44f3f587c convert-repo fixups
mpm@selenic.com
parents: 316
diff changeset
   111
        while parents:
dfc44f3f587c convert-repo fixups
mpm@selenic.com
parents: 316
diff changeset
   112
            p1 = p2
dfc44f3f587c convert-repo fixups
mpm@selenic.com
parents: 316
diff changeset
   113
            p2 = parents.pop(0)
3955
9af4b853ed4d convert-repo: add CVS branch support
Matt Mackall <mpm@selenic.com>
parents: 3954
diff changeset
   114
            a = self.repo.rawcommit(files, text, commit.author, commit.date,
5017
06329efa722d convert: get rid of "hg." prefix where not needed
Bryan O'Sullivan <bos@serpentine.com>
parents: 5016
diff changeset
   115
                                    bin(p1), bin(p2), extra=extra)
5014
914054ca532e convert: acquire/release locks periodically
Bryan O'Sullivan <bos@serpentine.com>
parents: 5013
diff changeset
   116
            self.repo.dirstate.invalidate()
431
dfc44f3f587c convert-repo fixups
mpm@selenic.com
parents: 316
diff changeset
   117
            text = "(octopus merge fixup)\n"
1389
9b3ef6f3cef5 convert-repo: fix up octopus merge conversion
Matt Mackall <mpm@selenic.com>
parents: 1388
diff changeset
   118
            p2 = hg.hex(self.repo.changelog.tip())
431
dfc44f3f587c convert-repo fixups
mpm@selenic.com
parents: 316
diff changeset
   119
1389
9b3ef6f3cef5 convert-repo: fix up octopus merge conversion
Matt Mackall <mpm@selenic.com>
parents: 1388
diff changeset
   120
        return p2
316
c48d069163d6 Add new convert-repo script
mpm@selenic.com
parents:
diff changeset
   121
694
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   122
    def puttags(self, tags):
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   123
        try:
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   124
            old = self.repo.wfile(".hgtags").read()
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   125
            oldlines = old.splitlines(1)
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   126
            oldlines.sort()
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   127
        except:
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   128
            oldlines = []
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   129
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   130
        k = tags.keys()
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   131
        k.sort()
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   132
        newlines = []
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   133
        for tag in k:
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   134
            newlines.append("%s %s\n" % (tags[tag], tag))
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   135
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   136
        newlines.sort()
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   137
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   138
        if newlines != oldlines:
4513
ac2fe196ac9b Turns convert.py into a real extension
Edouard Gomez <ed.gomez@free.fr>
parents: 4512
diff changeset
   139
            self.ui.status("updating tags\n")
694
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   140
            f = self.repo.wfile(".hgtags", "w")
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   141
            f.write("".join(newlines))
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   142
            f.close()
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   143
            if not oldlines: self.repo.add([".hgtags"])
1335
bea6356b8bca git -> hg conversion script
Florian La Roche <laroche@redhat.com>
parents: 1237
diff changeset
   144
            date = "%s 0" % int(time.mktime(time.gmtime()))
694
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   145
            self.repo.rawcommit([".hgtags"], "update tags", "convert-repo",
5017
06329efa722d convert: get rid of "hg." prefix where not needed
Bryan O'Sullivan <bos@serpentine.com>
parents: 5016
diff changeset
   146
                                date, self.repo.changelog.tip(), nullid)
06329efa722d convert: get rid of "hg." prefix where not needed
Bryan O'Sullivan <bos@serpentine.com>
parents: 5016
diff changeset
   147
            return hex(self.repo.changelog.tip())
5013
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   148
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   149
class mercurial_source(converter_source):
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   150
    def __init__(self, ui, path, rev=None):
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   151
        converter_source.__init__(self, ui, path, rev)
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   152
        self.repo = hg.repository(self.ui, path)
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   153
        self.lastrev = None
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   154
        self.lastctx = None
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   155
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   156
    def changectx(self, rev):
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   157
        if self.lastrev != rev:
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   158
            self.lastctx = self.repo.changectx(rev)
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   159
            self.lastrev = rev
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   160
        return self.lastctx
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   161
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   162
    def getheads(self):
5104
2f9edf6bae95 convert: only get history for requested revs when converting hg repo
Bryan O'Sullivan <bos@serpentine.com>
parents: 5076
diff changeset
   163
        if self.rev:
2f9edf6bae95 convert: only get history for requested revs when converting hg repo
Bryan O'Sullivan <bos@serpentine.com>
parents: 5076
diff changeset
   164
            return [hex(self.repo.changectx(self.rev).node())]
2f9edf6bae95 convert: only get history for requested revs when converting hg repo
Bryan O'Sullivan <bos@serpentine.com>
parents: 5076
diff changeset
   165
        else:
2f9edf6bae95 convert: only get history for requested revs when converting hg repo
Bryan O'Sullivan <bos@serpentine.com>
parents: 5076
diff changeset
   166
            return [hex(node) for node in self.repo.heads()]
5013
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   167
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   168
    def getfile(self, name, rev):
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   169
        try:
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   170
            return self.changectx(rev).filectx(name).data()
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   171
        except revlog.LookupError, err:
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   172
            raise IOError(err)
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   173
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   174
    def getmode(self, name, rev):
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   175
        m = self.changectx(rev).manifest()
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   176
        return (m.execf(name) and 'x' or '') + (m.linkf(name) and 'l' or '')
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   177
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   178
    def getchanges(self, rev):
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   179
        ctx = self.changectx(rev)
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   180
        m, a, r = self.repo.status(ctx.parents()[0].node(), ctx.node())[:3]
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   181
        changes = [(name, rev) for name in m + a + r]
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   182
        changes.sort()
5076
ef338e34a906 convert: look up copies in getchanges instead of getcommit
Brendan Cully <brendan@kublai.com>
parents: 5052
diff changeset
   183
        return (changes, self.getcopies(ctx))
5013
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   184
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   185
    def getcopies(self, ctx):
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   186
        added = self.repo.status(ctx.parents()[0].node(), ctx.node())[1]
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   187
        copies = {}
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   188
        for name in added:
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   189
            try:
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   190
                copies[name] = ctx.filectx(name).renamed()[0]
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   191
            except TypeError:
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   192
                pass
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   193
        return copies
5117
d4fa6bafc43a Remove trailing spaces, fix indentation
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5104
diff changeset
   194
5013
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   195
    def getcommit(self, rev):
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   196
        ctx = self.changectx(rev)
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   197
        parents = [hex(p.node()) for p in ctx.parents() if p.node() != nullid]
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   198
        return commit(author=ctx.user(), date=util.datestr(ctx.date()),
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   199
                      desc=ctx.description(), parents=parents,
5076
ef338e34a906 convert: look up copies in getchanges instead of getcommit
Brendan Cully <brendan@kublai.com>
parents: 5052
diff changeset
   200
                      branch=ctx.branch())
5013
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   201
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   202
    def gettags(self):
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   203
        tags = [t for t in self.repo.tagslist() if t[0] != 'tip']
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   204
        return dict([(name, hex(node)) for name, node in tags])