hgext/convert/hg.py
author Maxim Dounin <mdounin@mdounin.ru>
Sat, 27 Oct 2007 16:27:55 +0400
changeset 5483 0c43f87baba3
parent 5437 71e7c86adcb7
permissions -rw-r--r--
Fix file-changed-to-dir and dir-to-file commits (issue660). Allow adding to dirstate files that clash with previously existing but marked for removal. Protect from reintroducing clashes by revert. This change doesn't address related issues with update. Current workaround is to do "clean" update by manually removing conflicting files/dirs from working directory.
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):
5436
b4ae8535f834 convert: add default constructor for converter_sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5435
diff changeset
    19
        converter_sink.__init__(self, ui, path)
5172
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    20
        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
    21
        self.clonebranches = ui.configbool('convert', 'hg.clonebranches', False)
5256
be4835ad9a85 convert: new config variable hg.tagsbranch controls which branch tags are committed to
Brendan Cully <brendan@kublai.com>
parents: 5192
diff changeset
    22
        self.tagsbranch = ui.config('convert', 'hg.tagsbranch', 'default')
5172
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    23
        self.lastbranch = None
5437
71e7c86adcb7 convert: refactor sink initialisation, to remove hardcoding of hg
Bryan O'Sullivan <bos@serpentine.com>
parents: 5436
diff changeset
    24
        if os.path.isdir(path) and len(os.listdir(path)) > 0:
71e7c86adcb7 convert: refactor sink initialisation, to remove hardcoding of hg
Bryan O'Sullivan <bos@serpentine.com>
parents: 5436
diff changeset
    25
            try:
71e7c86adcb7 convert: refactor sink initialisation, to remove hardcoding of hg
Bryan O'Sullivan <bos@serpentine.com>
parents: 5436
diff changeset
    26
                self.repo = hg.repository(self.ui, path)
71e7c86adcb7 convert: refactor sink initialisation, to remove hardcoding of hg
Bryan O'Sullivan <bos@serpentine.com>
parents: 5436
diff changeset
    27
                ui.status(_('destination %s is a Mercurial repository\n') %
71e7c86adcb7 convert: refactor sink initialisation, to remove hardcoding of hg
Bryan O'Sullivan <bos@serpentine.com>
parents: 5436
diff changeset
    28
                          path)
71e7c86adcb7 convert: refactor sink initialisation, to remove hardcoding of hg
Bryan O'Sullivan <bos@serpentine.com>
parents: 5436
diff changeset
    29
            except hg.RepoError, err:
71e7c86adcb7 convert: refactor sink initialisation, to remove hardcoding of hg
Bryan O'Sullivan <bos@serpentine.com>
parents: 5436
diff changeset
    30
                ui.print_exc()
71e7c86adcb7 convert: refactor sink initialisation, to remove hardcoding of hg
Bryan O'Sullivan <bos@serpentine.com>
parents: 5436
diff changeset
    31
                raise NoRepo(err.args[0])
71e7c86adcb7 convert: refactor sink initialisation, to remove hardcoding of hg
Bryan O'Sullivan <bos@serpentine.com>
parents: 5436
diff changeset
    32
        else:
71e7c86adcb7 convert: refactor sink initialisation, to remove hardcoding of hg
Bryan O'Sullivan <bos@serpentine.com>
parents: 5436
diff changeset
    33
            try:
71e7c86adcb7 convert: refactor sink initialisation, to remove hardcoding of hg
Bryan O'Sullivan <bos@serpentine.com>
parents: 5436
diff changeset
    34
                ui.status(_('initializing destination %s repository\n') % path)
71e7c86adcb7 convert: refactor sink initialisation, to remove hardcoding of hg
Bryan O'Sullivan <bos@serpentine.com>
parents: 5436
diff changeset
    35
                self.repo = hg.repository(self.ui, path, create=True)
71e7c86adcb7 convert: refactor sink initialisation, to remove hardcoding of hg
Bryan O'Sullivan <bos@serpentine.com>
parents: 5436
diff changeset
    36
                self.created.append(path)
71e7c86adcb7 convert: refactor sink initialisation, to remove hardcoding of hg
Bryan O'Sullivan <bos@serpentine.com>
parents: 5436
diff changeset
    37
            except hg.RepoError, err:
71e7c86adcb7 convert: refactor sink initialisation, to remove hardcoding of hg
Bryan O'Sullivan <bos@serpentine.com>
parents: 5436
diff changeset
    38
                ui.print_exc()
71e7c86adcb7 convert: refactor sink initialisation, to remove hardcoding of hg
Bryan O'Sullivan <bos@serpentine.com>
parents: 5436
diff changeset
    39
                raise NoRepo("could not create hg repo %s as sink" % path)
5014
914054ca532e convert: acquire/release locks periodically
Bryan O'Sullivan <bos@serpentine.com>
parents: 5013
diff changeset
    40
        self.lock = None
914054ca532e convert: acquire/release locks periodically
Bryan O'Sullivan <bos@serpentine.com>
parents: 5013
diff changeset
    41
        self.wlock = None
5378
8a2915f57dfc convert: add a mode where mercurial_sink skips empty revisions.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5356
diff changeset
    42
        self.filemapmode = False
5014
914054ca532e convert: acquire/release locks periodically
Bryan O'Sullivan <bos@serpentine.com>
parents: 5013
diff changeset
    43
914054ca532e convert: acquire/release locks periodically
Bryan O'Sullivan <bos@serpentine.com>
parents: 5013
diff changeset
    44
    def before(self):
5052
a11e8a181bd5 convert: fix locking order
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5038
diff changeset
    45
        self.wlock = self.repo.wlock()
5014
914054ca532e convert: acquire/release locks periodically
Bryan O'Sullivan <bos@serpentine.com>
parents: 5013
diff changeset
    46
        self.lock = self.repo.lock()
5279
2dbd750b3ddd convert: clear the dirstate before a conversion, invalidate it afterwards
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5278
diff changeset
    47
        self.repo.dirstate.clear()
5014
914054ca532e convert: acquire/release locks periodically
Bryan O'Sullivan <bos@serpentine.com>
parents: 5013
diff changeset
    48
914054ca532e convert: acquire/release locks periodically
Bryan O'Sullivan <bos@serpentine.com>
parents: 5013
diff changeset
    49
    def after(self):
5279
2dbd750b3ddd convert: clear the dirstate before a conversion, invalidate it afterwards
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5278
diff changeset
    50
        self.repo.dirstate.invalidate()
5014
914054ca532e convert: acquire/release locks periodically
Bryan O'Sullivan <bos@serpentine.com>
parents: 5013
diff changeset
    51
        self.lock = None
914054ca532e convert: acquire/release locks periodically
Bryan O'Sullivan <bos@serpentine.com>
parents: 5013
diff changeset
    52
        self.wlock = None
3947
0fab73b3f453 convert-repo: add some smarts
Matt Mackall <mpm@selenic.com>
parents: 3916
diff changeset
    53
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
    54
    def revmapfile(self):
3947
0fab73b3f453 convert-repo: add some smarts
Matt Mackall <mpm@selenic.com>
parents: 3916
diff changeset
    55
        return os.path.join(self.path, ".hg", "shamap")
316
c48d069163d6 Add new convert-repo script
mpm@selenic.com
parents:
diff changeset
    56
4589
451e91ed535e convert extension: Add support for username mapping
Edouard Gomez <ed.gomez@free.fr>
parents: 4534
diff changeset
    57
    def authorfile(self):
451e91ed535e convert extension: Add support for username mapping
Edouard Gomez <ed.gomez@free.fr>
parents: 4534
diff changeset
    58
        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
    59
316
c48d069163d6 Add new convert-repo script
mpm@selenic.com
parents:
diff changeset
    60
    def getheads(self):
c48d069163d6 Add new convert-repo script
mpm@selenic.com
parents:
diff changeset
    61
        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
    62
        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
    63
316
c48d069163d6 Add new convert-repo script
mpm@selenic.com
parents:
diff changeset
    64
    def putfile(self, f, e, data):
4082
6b2909e84203 convert-repo converts symlinks from git
Daniel Holth <dholth@fastmail.fm>
parents: 4062
diff changeset
    65
        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
    66
        if f not in self.repo.dirstate:
5278
70e9a527cc61 convert: avoid dirstate checks; add a test
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5256
diff changeset
    67
            self.repo.dirstate.normallookup(f)
692
695dd9a491da convert-repo: deal with packed git and other fixes
mpm@selenic.com
parents: 450
diff changeset
    68
4758
b6a1f2c46c6c convert extension: Add SVN converter
Daniel Holth <dholth@fastmail.fm>
parents: 4756
diff changeset
    69
    def copyfile(self, source, dest):
b6a1f2c46c6c convert extension: Add SVN converter
Daniel Holth <dholth@fastmail.fm>
parents: 4756
diff changeset
    70
        self.repo.copy(source, dest)
b6a1f2c46c6c convert extension: Add SVN converter
Daniel Holth <dholth@fastmail.fm>
parents: 4756
diff changeset
    71
316
c48d069163d6 Add new convert-repo script
mpm@selenic.com
parents:
diff changeset
    72
    def delfile(self, f):
c48d069163d6 Add new convert-repo script
mpm@selenic.com
parents:
diff changeset
    73
        try:
5343
26692d08c2f9 convert: delete empty directories if deleting a file (bug 754)
Bryan O'Sullivan <bos@serpentine.com>
parents: 4589
diff changeset
    74
            util.unlink(self.repo.wjoin(f))
692
695dd9a491da convert-repo: deal with packed git and other fixes
mpm@selenic.com
parents: 450
diff changeset
    75
            #self.repo.remove([f])
5345
002fe2f364f5 convert: fix missing import
Patrick Mezard <pmezard@gmail.com>
parents: 5343
diff changeset
    76
        except OSError:
316
c48d069163d6 Add new convert-repo script
mpm@selenic.com
parents:
diff changeset
    77
            pass
c48d069163d6 Add new convert-repo script
mpm@selenic.com
parents:
diff changeset
    78
5172
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    79
    def setbranch(self, branch, pbranch, parents):
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    80
        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
    81
            return
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    82
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    83
        self.lastbranch = branch
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    84
        self.after()
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    85
        if not branch:
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    86
            branch = 'default'
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    87
        if not pbranch:
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    88
            pbranch = 'default'
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    89
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    90
        branchpath = os.path.join(self.path, branch)
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    91
        try:
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    92
            self.repo = hg.repository(self.ui, branchpath)
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    93
        except:
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    94
            if not parents:
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    95
                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
    96
            else:
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
    97
                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
    98
                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
    99
                         branchpath, rev=parents, update=False,
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
   100
                         stream=True)
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
   101
                self.repo = hg.repository(self.ui, branchpath)
5402
ad0b580cad35 mercurial_sink: regrab locks in setbranch
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5379
diff changeset
   102
        self.before()
5172
6b4c332f241b convert: hg: optionally create branches as clones
Brendan Cully <brendan@kublai.com>
parents: 5117
diff changeset
   103
3955
9af4b853ed4d convert-repo: add CVS branch support
Matt Mackall <mpm@selenic.com>
parents: 3954
diff changeset
   104
    def putcommit(self, files, parents, commit):
5192
33015dac5df5 convert: fix mercurial_sink.putcommit
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5172
diff changeset
   105
        seen = {}
431
dfc44f3f587c convert-repo fixups
mpm@selenic.com
parents: 316
diff changeset
   106
        pl = []
dfc44f3f587c convert-repo fixups
mpm@selenic.com
parents: 316
diff changeset
   107
        for p in parents:
dfc44f3f587c convert-repo fixups
mpm@selenic.com
parents: 316
diff changeset
   108
            if p not in seen:
dfc44f3f587c convert-repo fixups
mpm@selenic.com
parents: 316
diff changeset
   109
                pl.append(p)
dfc44f3f587c convert-repo fixups
mpm@selenic.com
parents: 316
diff changeset
   110
                seen[p] = 1
dfc44f3f587c convert-repo fixups
mpm@selenic.com
parents: 316
diff changeset
   111
        parents = pl
5378
8a2915f57dfc convert: add a mode where mercurial_sink skips empty revisions.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5356
diff changeset
   112
        nparents = len(parents)
8a2915f57dfc convert: add a mode where mercurial_sink skips empty revisions.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5356
diff changeset
   113
        if self.filemapmode and nparents == 1:
8a2915f57dfc convert: add a mode where mercurial_sink skips empty revisions.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5356
diff changeset
   114
            m1node = self.repo.changelog.read(bin(parents[0]))[0]
8a2915f57dfc convert: add a mode where mercurial_sink skips empty revisions.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5356
diff changeset
   115
            parent = parents[0]
316
c48d069163d6 Add new convert-repo script
mpm@selenic.com
parents:
diff changeset
   116
692
695dd9a491da convert-repo: deal with packed git and other fixes
mpm@selenic.com
parents: 450
diff changeset
   117
        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
   118
        if len(parents) < 2: parents.append("0" * 40)
431
dfc44f3f587c convert-repo fixups
mpm@selenic.com
parents: 316
diff changeset
   119
        p2 = parents.pop(0)
692
695dd9a491da convert-repo: deal with packed git and other fixes
mpm@selenic.com
parents: 450
diff changeset
   120
3955
9af4b853ed4d convert-repo: add CVS branch support
Matt Mackall <mpm@selenic.com>
parents: 3954
diff changeset
   121
        text = commit.desc
5435
d0c67b52ac01 convert: make contents of "extra" dict available from sources, for sinks.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5433
diff changeset
   122
        extra = commit.extra.copy()
5038
8f157190075e convert: add config option to turn off use of branch names
Bryan O'Sullivan <bos@serpentine.com>
parents: 5017
diff changeset
   123
        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
   124
            extra['branch'] = commit.branch
28b23b9073a8 convert: record the source revision in the changelog
Brendan Cully <brendan@kublai.com>
parents: 4758
diff changeset
   125
        if commit.rev:
28b23b9073a8 convert: record the source revision in the changelog
Brendan Cully <brendan@kublai.com>
parents: 4758
diff changeset
   126
            extra['convert_revision'] = commit.rev
4939
cdd33a048289 removed trailing whitespace
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4873
diff changeset
   127
431
dfc44f3f587c convert-repo fixups
mpm@selenic.com
parents: 316
diff changeset
   128
        while parents:
dfc44f3f587c convert-repo fixups
mpm@selenic.com
parents: 316
diff changeset
   129
            p1 = p2
dfc44f3f587c convert-repo fixups
mpm@selenic.com
parents: 316
diff changeset
   130
            p2 = parents.pop(0)
3955
9af4b853ed4d convert-repo: add CVS branch support
Matt Mackall <mpm@selenic.com>
parents: 3954
diff changeset
   131
            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
   132
                                    bin(p1), bin(p2), extra=extra)
5278
70e9a527cc61 convert: avoid dirstate checks; add a test
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5256
diff changeset
   133
            self.repo.dirstate.clear()
431
dfc44f3f587c convert-repo fixups
mpm@selenic.com
parents: 316
diff changeset
   134
            text = "(octopus merge fixup)\n"
1389
9b3ef6f3cef5 convert-repo: fix up octopus merge conversion
Matt Mackall <mpm@selenic.com>
parents: 1388
diff changeset
   135
            p2 = hg.hex(self.repo.changelog.tip())
431
dfc44f3f587c convert-repo fixups
mpm@selenic.com
parents: 316
diff changeset
   136
5378
8a2915f57dfc convert: add a mode where mercurial_sink skips empty revisions.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5356
diff changeset
   137
        if self.filemapmode and nparents == 1:
8a2915f57dfc convert: add a mode where mercurial_sink skips empty revisions.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5356
diff changeset
   138
            man = self.repo.manifest
8a2915f57dfc convert: add a mode where mercurial_sink skips empty revisions.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5356
diff changeset
   139
            mnode = self.repo.changelog.read(bin(p2))[0]
8a2915f57dfc convert: add a mode where mercurial_sink skips empty revisions.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5356
diff changeset
   140
            if not man.cmp(m1node, man.revision(mnode)):
8a2915f57dfc convert: add a mode where mercurial_sink skips empty revisions.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5356
diff changeset
   141
                self.repo.rollback()
8a2915f57dfc convert: add a mode where mercurial_sink skips empty revisions.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5356
diff changeset
   142
                self.repo.dirstate.clear()
8a2915f57dfc convert: add a mode where mercurial_sink skips empty revisions.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5356
diff changeset
   143
                return parent
1389
9b3ef6f3cef5 convert-repo: fix up octopus merge conversion
Matt Mackall <mpm@selenic.com>
parents: 1388
diff changeset
   144
        return p2
316
c48d069163d6 Add new convert-repo script
mpm@selenic.com
parents:
diff changeset
   145
694
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   146
    def puttags(self, tags):
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   147
        try:
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   148
            old = self.repo.wfile(".hgtags").read()
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   149
            oldlines = old.splitlines(1)
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   150
            oldlines.sort()
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   151
        except:
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   152
            oldlines = []
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   153
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   154
        k = tags.keys()
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   155
        k.sort()
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   156
        newlines = []
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   157
        for tag in k:
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   158
            newlines.append("%s %s\n" % (tags[tag], tag))
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   159
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   160
        newlines.sort()
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   161
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   162
        if newlines != oldlines:
4513
ac2fe196ac9b Turns convert.py into a real extension
Edouard Gomez <ed.gomez@free.fr>
parents: 4512
diff changeset
   163
            self.ui.status("updating tags\n")
694
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   164
            f = self.repo.wfile(".hgtags", "w")
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   165
            f.write("".join(newlines))
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   166
            f.close()
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   167
            if not oldlines: self.repo.add([".hgtags"])
1335
bea6356b8bca git -> hg conversion script
Florian La Roche <laroche@redhat.com>
parents: 1237
diff changeset
   168
            date = "%s 0" % int(time.mktime(time.gmtime()))
5256
be4835ad9a85 convert: new config variable hg.tagsbranch controls which branch tags are committed to
Brendan Cully <brendan@kublai.com>
parents: 5192
diff changeset
   169
            extra = {}
be4835ad9a85 convert: new config variable hg.tagsbranch controls which branch tags are committed to
Brendan Cully <brendan@kublai.com>
parents: 5192
diff changeset
   170
            if self.tagsbranch != 'default':
be4835ad9a85 convert: new config variable hg.tagsbranch controls which branch tags are committed to
Brendan Cully <brendan@kublai.com>
parents: 5192
diff changeset
   171
                extra['branch'] = self.tagsbranch
be4835ad9a85 convert: new config variable hg.tagsbranch controls which branch tags are committed to
Brendan Cully <brendan@kublai.com>
parents: 5192
diff changeset
   172
            try:
be4835ad9a85 convert: new config variable hg.tagsbranch controls which branch tags are committed to
Brendan Cully <brendan@kublai.com>
parents: 5192
diff changeset
   173
                tagparent = self.repo.changectx(self.tagsbranch).node()
be4835ad9a85 convert: new config variable hg.tagsbranch controls which branch tags are committed to
Brendan Cully <brendan@kublai.com>
parents: 5192
diff changeset
   174
            except hg.RepoError, inst:
be4835ad9a85 convert: new config variable hg.tagsbranch controls which branch tags are committed to
Brendan Cully <brendan@kublai.com>
parents: 5192
diff changeset
   175
                tagparent = nullid
694
51eb248d3348 Teach convert-repo about tags
mpm@selenic.com
parents: 692
diff changeset
   176
            self.repo.rawcommit([".hgtags"], "update tags", "convert-repo",
5256
be4835ad9a85 convert: new config variable hg.tagsbranch controls which branch tags are committed to
Brendan Cully <brendan@kublai.com>
parents: 5192
diff changeset
   177
                                date, tagparent, nullid)
5017
06329efa722d convert: get rid of "hg." prefix where not needed
Bryan O'Sullivan <bos@serpentine.com>
parents: 5016
diff changeset
   178
            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
   179
5378
8a2915f57dfc convert: add a mode where mercurial_sink skips empty revisions.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5356
diff changeset
   180
    def setfilemapmode(self, active):
8a2915f57dfc convert: add a mode where mercurial_sink skips empty revisions.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5356
diff changeset
   181
        self.filemapmode = active
8a2915f57dfc convert: add a mode where mercurial_sink skips empty revisions.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5356
diff changeset
   182
5013
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   183
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
   184
    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
   185
        converter_source.__init__(self, ui, path, rev)
5354
4fbd27bf04b1 convert: fail properly if we can't read a source hg repository
Bryan O'Sullivan <bos@serpentine.com>
parents: 5344
diff changeset
   186
        try:
4fbd27bf04b1 convert: fail properly if we can't read a source hg repository
Bryan O'Sullivan <bos@serpentine.com>
parents: 5344
diff changeset
   187
            self.repo = hg.repository(self.ui, path)
5433
4d34f8b12a9e convert: report errors more meaningfully if run with --traceback
Bryan O'Sullivan <bos@serpentine.com>
parents: 5402
diff changeset
   188
            # try to provoke an exception if this isn't really a hg
4d34f8b12a9e convert: report errors more meaningfully if run with --traceback
Bryan O'Sullivan <bos@serpentine.com>
parents: 5402
diff changeset
   189
            # repo, but some other bogus compatible-looking url
4d34f8b12a9e convert: report errors more meaningfully if run with --traceback
Bryan O'Sullivan <bos@serpentine.com>
parents: 5402
diff changeset
   190
            self.repo.heads()
4d34f8b12a9e convert: report errors more meaningfully if run with --traceback
Bryan O'Sullivan <bos@serpentine.com>
parents: 5402
diff changeset
   191
        except hg.RepoError:
4d34f8b12a9e convert: report errors more meaningfully if run with --traceback
Bryan O'Sullivan <bos@serpentine.com>
parents: 5402
diff changeset
   192
            ui.print_exc()
5354
4fbd27bf04b1 convert: fail properly if we can't read a source hg repository
Bryan O'Sullivan <bos@serpentine.com>
parents: 5344
diff changeset
   193
            raise NoRepo("could not open hg repo %s as source" % path)
5013
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   194
        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
   195
        self.lastctx = None
5379
d3e51dc804f8 mercurial_source: add --filemap support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5378
diff changeset
   196
        self._changescache = None
5013
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   197
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   198
    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
   199
        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
   200
            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
   201
            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
   202
        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
   203
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   204
    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
   205
        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
   206
            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
   207
        else:
2f9edf6bae95 convert: only get history for requested revs when converting hg repo
Bryan O'Sullivan <bos@serpentine.com>
parents: 5076
diff changeset
   208
            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
   209
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   210
    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
   211
        try:
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   212
            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
   213
        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
   214
            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
   215
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   216
    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
   217
        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
   218
        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
   219
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   220
    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
   221
        ctx = self.changectx(rev)
5379
d3e51dc804f8 mercurial_source: add --filemap support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5378
diff changeset
   222
        if self._changescache and self._changescache[0] == rev:
d3e51dc804f8 mercurial_source: add --filemap support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5378
diff changeset
   223
            m, a, r = self._changescache[1]
d3e51dc804f8 mercurial_source: add --filemap support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5378
diff changeset
   224
        else:
d3e51dc804f8 mercurial_source: add --filemap support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5378
diff changeset
   225
            m, a, r = self.repo.status(ctx.parents()[0].node(), ctx.node())[:3]
5013
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   226
        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
   227
        changes.sort()
5280
11e1e574da02 convert: mercurial_source: also search for copies in modified files
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5279
diff changeset
   228
        return (changes, self.getcopies(ctx, m + a))
5013
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   229
5280
11e1e574da02 convert: mercurial_source: also search for copies in modified files
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5279
diff changeset
   230
    def getcopies(self, ctx, files):
5013
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   231
        copies = {}
5280
11e1e574da02 convert: mercurial_source: also search for copies in modified files
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5279
diff changeset
   232
        for name in files:
5013
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   233
            try:
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   234
                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
   235
            except TypeError:
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   236
                pass
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   237
        return copies
5117
d4fa6bafc43a Remove trailing spaces, fix indentation
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5104
diff changeset
   238
5013
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   239
    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
   240
        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
   241
        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
   242
        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
   243
                      desc=ctx.description(), parents=parents,
5435
d0c67b52ac01 convert: make contents of "extra" dict available from sources, for sinks.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5433
diff changeset
   244
                      branch=ctx.branch(), extra=ctx.extra())
5013
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   245
6c1029aacc9a convert: Support Mercurial as a source, as well as a sink
Bryan O'Sullivan <bos@serpentine.com>
parents: 5011
diff changeset
   246
    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
   247
        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
   248
        return dict([(name, hex(node)) for name, node in tags])
5379
d3e51dc804f8 mercurial_source: add --filemap support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5378
diff changeset
   249
d3e51dc804f8 mercurial_source: add --filemap support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5378
diff changeset
   250
    def getchangedfiles(self, rev, i):
d3e51dc804f8 mercurial_source: add --filemap support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5378
diff changeset
   251
        ctx = self.changectx(rev)
d3e51dc804f8 mercurial_source: add --filemap support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5378
diff changeset
   252
        i = i or 0
d3e51dc804f8 mercurial_source: add --filemap support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5378
diff changeset
   253
        changes = self.repo.status(ctx.parents()[i].node(), ctx.node())[:3]
d3e51dc804f8 mercurial_source: add --filemap support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5378
diff changeset
   254
d3e51dc804f8 mercurial_source: add --filemap support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5378
diff changeset
   255
        if i == 0:
d3e51dc804f8 mercurial_source: add --filemap support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5378
diff changeset
   256
            self._changescache = (rev, changes)
d3e51dc804f8 mercurial_source: add --filemap support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5378
diff changeset
   257
d3e51dc804f8 mercurial_source: add --filemap support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5378
diff changeset
   258
        return changes[0] + changes[1] + changes[2]
d3e51dc804f8 mercurial_source: add --filemap support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5378
diff changeset
   259