/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to converter.py

Fix tests.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2009 Jelmer Vernooij <jelmer@samba.org>
 
2
#
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
14
# along with this program; if not, write to the Free Software
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
16
 
 
17
"""Map from Git sha's to Bazaar objects."""
 
18
 
 
19
import stat
 
20
 
 
21
import bzrlib
 
22
from bzrlib import ui
 
23
from bzrlib.errors import NoSuchRevision
 
24
 
 
25
from bzrlib.plugins.git.mapping import (
 
26
    inventory_to_tree_and_blobs,
 
27
    revision_to_commit,
 
28
    )
 
29
from bzrlib.plugins.git.shamap import GitShaMap
 
30
 
 
31
from dulwich.objects import (
 
32
    Blob,
 
33
    Tree,
 
34
    )
 
35
 
 
36
 
 
37
class GitObjectConverter(object):
 
38
 
 
39
    def __init__(self, repository, mapping=None):
 
40
        self.repository = repository
 
41
        if mapping is None:
 
42
            self.mapping = self.repository.get_mapping()
 
43
        else:
 
44
            self.mapping = mapping
 
45
        self._idmap = GitShaMap(self.repository._transport)
 
46
 
 
47
    def _update_sha_map(self):
 
48
        all_revids = self.repository.all_revision_ids()
 
49
        graph = self.repository.get_graph()
 
50
        present_revids = set(self._idmap.revids())
 
51
        pb = ui.ui_factory.nested_progress_bar()
 
52
        try:
 
53
            for i, revid in enumerate(graph.iter_topo_order(all_revids)):
 
54
                if revid in present_revids:
 
55
                    continue
 
56
                pb.update("updating git map", i, len(all_revids))
 
57
                self._update_sha_map_revision(revid)
 
58
        finally:
 
59
            self._idmap.commit()
 
60
            pb.finished()
 
61
 
 
62
    def _update_sha_map_revision(self, revid):
 
63
        inv = self.repository.get_inventory(revid)
 
64
        objects = inventory_to_tree_and_blobs(self.repository, self.mapping, revid)
 
65
        for sha, o, path in objects:
 
66
            if path == "":
 
67
                tree_sha = sha
 
68
            ie = inv[inv.path2id(path)]
 
69
            if ie.kind in ("file", "symlink"):
 
70
                self._idmap.add_entry(sha, "blob", (ie.file_id, ie.revision))
 
71
            elif ie.kind == "directory":
 
72
                self._idmap.add_entry(sha, "tree", (path, ie.revision))
 
73
            else:
 
74
                raise AssertionError()
 
75
        rev = self.repository.get_revision(revid)
 
76
        commit_obj = revision_to_commit(rev, tree_sha, self._idmap._parent_lookup)
 
77
        self._idmap.add_entry(commit_obj.sha().hexdigest(), "commit", (revid, tree_sha))
 
78
 
 
79
    def _get_blob(self, fileid, revision):
 
80
        """Return a Git Blob object from a fileid and revision stored in bzr.
 
81
        
 
82
        :param fileid: File id of the text
 
83
        :param revision: Revision of the text
 
84
        """
 
85
        text = self.repository.texts.get_record_stream([(fileid, revision)], "unordered", True).next().get_bytes_as("fulltext")
 
86
        blob = Blob()
 
87
        blob._text = text
 
88
        return blob
 
89
 
 
90
    def _get_tree(self, path, revid, inv=None):
 
91
        """Return a Git Tree object from a path and a revision stored in bzr.
 
92
 
 
93
        :param path: path in the tree.
 
94
        :param revision: Revision of the tree.
 
95
        """
 
96
        if inv is None:
 
97
            inv = self.repository.get_inventory(revid)
 
98
        tree = Tree()
 
99
        fileid = inv.path2id(path)
 
100
        for name, ie in inv[fileid].children.iteritems():
 
101
            if ie.kind == "directory":
 
102
                subtree = self._get_tree(inv.id2path(ie.file_id), revid, inv)
 
103
                tree.add(stat.S_IFDIR, name.encode('UTF-8'), subtree.sha().hexdigest())
 
104
            elif ie.kind == "file":
 
105
                blob = self._get_blob(inv.path2id(ie.file_id), revid)
 
106
                mode = stat.S_IFREG | 0644
 
107
                if ie.executable:
 
108
                    mode |= 0111
 
109
                tree.add(mode, name.encode('UTF-8'), blob.sha().hexdigest())
 
110
            elif ie.kind == "symlink":
 
111
                raise AssertionError("Symlinks not yet supported")
 
112
        tree.serialize()
 
113
        return tree
 
114
 
 
115
    def _get_commit(self, revid, tree_sha):
 
116
        rev = self.repository.get_revision(revid)
 
117
        return revision_to_commit(rev, tree_sha, self._idmap._parent_lookup)
 
118
 
 
119
    def __getitem__(self, sha):
 
120
        # See if sha is in map
 
121
        try:
 
122
            (type, type_data) = self._idmap.lookup_git_sha(sha)
 
123
        except KeyError:
 
124
            # if not, see if there are any unconverted revisions and add them 
 
125
            # to the map, search for sha in map again
 
126
            self._update_sha_map()
 
127
            (type, type_data) = self._idmap.lookup_git_sha(sha)
 
128
        # convert object to git object
 
129
        if type == "commit":
 
130
            return self._get_commit(*type_data)
 
131
        elif type == "blob":
 
132
            return self._get_blob(*type_data)
 
133
        elif type == "tree":
 
134
            return self._get_tree(*type_data)
 
135
        else:
 
136
            raise AssertionError("Unknown object type '%s'" % type)