/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.200.252 by Jelmer Vernooij
Clarify history, copyright.
1
# Copyright (C) 2009 Jelmer Vernooij <jelmer@samba.org>
0.200.228 by Jelmer Vernooij
Split out map.
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
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
19
from dulwich.objects import (
20
    Blob,
0.200.784 by Jelmer Vernooij
Use common object generation code in push.
21
    Tree,
0.200.586 by Jelmer Vernooij
Fix issues pointed out by pyflakes.
22
    sha_to_hex,
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
23
    )
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
24
from dulwich.object_store import (
0.200.457 by Jelmer Vernooij
Use BaseObjectStore.
25
    BaseObjectStore,
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
26
    )
0.200.249 by Jelmer Vernooij
Implement Tree.
27
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
28
from bzrlib import (
0.200.440 by Jelmer Vernooij
Remove silly mapping of timezones; dulwich uses offsets now as well.
29
    debug,
0.231.1 by Jelmer Vernooij
Check that regenerated objects have the expected sha1.
30
    errors,
0.200.789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
31
    lru_cache,
0.200.478 by Jelmer Vernooij
Cope with disappeared revisions.
32
    trace,
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
33
    ui,
0.200.773 by Jelmer Vernooij
Implement inventory_to_objects
34
    urlutils,
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
35
    )
0.200.541 by Jelmer Vernooij
Cope with NULL_REVISION.
36
from bzrlib.revision import (
37
    NULL_REVISION,
38
    )
0.200.228 by Jelmer Vernooij
Split out map.
39
0.200.229 by Jelmer Vernooij
More work on converter.
40
from bzrlib.plugins.git.mapping import (
0.200.463 by Jelmer Vernooij
Support remote dpush (except for references).
41
    default_mapping,
0.200.359 by Jelmer Vernooij
Simplify file mode handling, avoid inventory_to_tree_and_blobs as it is expensive if trees/blobs have already been converted.
42
    directory_to_tree,
0.200.548 by Jelmer Vernooij
Extract unusual file modes from revision when reconstructing Trees.
43
    extract_unusual_modes,
0.231.1 by Jelmer Vernooij
Check that regenerated objects have the expected sha1.
44
    mapping_registry,
0.200.229 by Jelmer Vernooij
More work on converter.
45
    )
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
46
from bzrlib.plugins.git.shamap import (
0.200.750 by Jelmer Vernooij
Remove unused tree code, add mechanism for migrating between sha maps.
47
    from_repository as idmap_from_repository,
0.200.231 by Jelmer Vernooij
Partially fix pull.
48
    )
49
0.200.228 by Jelmer Vernooij
Split out map.
50
0.200.452 by Jelmer Vernooij
Rename converter -> object_store, provide utility function for getting ObjectStore's.
51
def get_object_store(repo, mapping=None):
52
    git = getattr(repo, "_git", None)
53
    if git is not None:
54
        return git.object_store
55
    return BazaarObjectStore(repo, mapping)
56
57
0.200.789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
58
MAX_INV_CACHE_SIZE = 50 * 1024 * 1024
59
60
61
class LRUInventoryCache(object):
62
63
    def __init__(self, repository):
64
        def approx_inv_size(inv):
65
            # Very rough estimate, 1k per inventory entry
66
            return len(inv) * 1024
67
        self.repository = repository
68
        self._cache = lru_cache.LRUSizeCache(max_size=MAX_INV_CACHE_SIZE,
69
            after_cleanup_size=None, compute_size=approx_inv_size)
70
71
    def get_inventory(self, revid):            
72
        try:
73
            return self._cache[revid] 
74
        except KeyError:
75
            inv = self.repository.get_inventory(revid)
76
            self._cache.add(revid, inv)
77
            return inv
78
79
    def get_inventories(self, revids):
80
        invs = dict([(k, self._cache.get(k)) for k in revids]) 
81
        for inv in self.repository.iter_inventories([r for r, v in invs.iteritems() if v is None]):
82
            invs[inv.revision_id] = inv
83
            self._cache.add(inv.revision_id, inv)
84
        return [invs[r] for r in revids]
85
86
    def add(self, revid, inv):
87
        self._cache.add(revid, inv)
88
89
0.200.457 by Jelmer Vernooij
Use BaseObjectStore.
90
class BazaarObjectStore(BaseObjectStore):
0.200.320 by Jelmer Vernooij
Handle lightweight checkouts.
91
    """A Git-style object store backed onto a Bazaar repository."""
0.200.228 by Jelmer Vernooij
Split out map.
92
93
    def __init__(self, repository, mapping=None):
94
        self.repository = repository
95
        if mapping is None:
0.200.463 by Jelmer Vernooij
Support remote dpush (except for references).
96
            self.mapping = default_mapping
0.200.228 by Jelmer Vernooij
Split out map.
97
        else:
98
            self.mapping = mapping
0.200.750 by Jelmer Vernooij
Remove unused tree code, add mechanism for migrating between sha maps.
99
        self._idmap = idmap_from_repository(repository)
0.200.735 by Jelmer Vernooij
Use convenience functions for start/stop write groups.
100
        self.start_write_group = self._idmap.start_write_group
101
        self.abort_write_group = self._idmap.abort_write_group
102
        self.commit_write_group = self._idmap.commit_write_group
0.200.789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
103
        self.parent_invs_cache = LRUInventoryCache(self.repository)
0.200.228 by Jelmer Vernooij
Split out map.
104
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
105
    def _update_sha_map(self, stop_revision=None):
0.200.683 by Jelmer Vernooij
Lazier checking of which revisions need to be fetched.
106
        graph = self.repository.get_graph()
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
107
        if stop_revision is None:
0.200.683 by Jelmer Vernooij
Lazier checking of which revisions need to be fetched.
108
            heads = graph.heads(self.repository.all_revision_ids())
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
109
        else:
0.200.683 by Jelmer Vernooij
Lazier checking of which revisions need to be fetched.
110
            heads = set([stop_revision])
0.200.689 by Jelmer Vernooij
Also consider todo heads.
111
        missing_revids = self._idmap.missing_revisions(heads)
0.200.683 by Jelmer Vernooij
Lazier checking of which revisions need to be fetched.
112
        while heads:
113
            parents = graph.get_parent_map(heads)
114
            todo = set()
115
            for p in parents.values():
0.200.684 by Jelmer Vernooij
Properly close write groups.
116
                todo.update([x for x in p if x not in missing_revids])
0.200.683 by Jelmer Vernooij
Lazier checking of which revisions need to be fetched.
117
            heads = self._idmap.missing_revisions(todo)
0.200.684 by Jelmer Vernooij
Properly close write groups.
118
            missing_revids.update(heads)
0.200.694 by Jelmer Vernooij
Avoid processing NULL_REVISION.
119
        if NULL_REVISION in missing_revids:
120
            missing_revids.remove(NULL_REVISION)
0.200.750 by Jelmer Vernooij
Remove unused tree code, add mechanism for migrating between sha maps.
121
        missing_revids = self.repository.has_revisions(missing_revids)
122
        if not missing_revids:
123
            return
0.200.735 by Jelmer Vernooij
Use convenience functions for start/stop write groups.
124
        self.start_write_group()
0.200.231 by Jelmer Vernooij
Partially fix pull.
125
        try:
0.200.733 by Jelmer Vernooij
Use start/stop commit write group.
126
            pb = ui.ui_factory.nested_progress_bar()
127
            try:
128
                for i, revid in enumerate(graph.iter_topo_order(missing_revids)):
0.200.750 by Jelmer Vernooij
Remove unused tree code, add mechanism for migrating between sha maps.
129
                    trace.mutter('processing %r', revid)
0.200.733 by Jelmer Vernooij
Use start/stop commit write group.
130
                    pb.update("updating git map", i, len(missing_revids))
131
                    self._update_sha_map_revision(revid)
132
            finally:
133
                pb.finished()
0.200.735 by Jelmer Vernooij
Use convenience functions for start/stop write groups.
134
        except:
135
            self.abort_write_group()
136
            raise
137
        else:
138
            self.commit_write_group()
0.200.229 by Jelmer Vernooij
More work on converter.
139
0.200.422 by Jelmer Vernooij
'bzr git-object' without arguments now prints the available git objects.
140
    def __iter__(self):
141
        self._update_sha_map()
142
        return iter(self._idmap.sha1s())
143
0.238.7 by Jelmer Vernooij
Cope with ghosts a bit better.
144
    def _revision_to_commit(self, rev, tree_sha):
145
        def parent_lookup(revid):
146
            try:
147
                return self._lookup_revision_sha1(revid)
148
            except errors.NoSuchRevision:
149
                trace.warning("Ignoring ghost parent %s", revid)
150
                return None
0.242.1 by Jelmer Vernooij
Add support for parsing hg-git metadata in the experimental mappings.
151
        return self.mapping.export_commit(rev, tree_sha, parent_lookup)
0.238.7 by Jelmer Vernooij
Cope with ghosts a bit better.
152
0.200.773 by Jelmer Vernooij
Implement inventory_to_objects
153
    def _inventory_to_objects(self, inv, parent_invs, parent_invshamaps,
154
            unusual_modes):
155
        """Iterate over the objects that were introduced in a revision.
156
157
        :param inv: Inventory to process
158
        :param parent_invs: parent inventory SHA maps
159
        :param parent_invshamaps: parent inventory SHA Map
160
        :param unusual_modes: Unusual file modes
161
        :return: Yields (path, object) entries
162
        """
163
        new_trees = {}
164
        shamap = {}
165
        for path, ie in inv.entries():
166
            if ie.kind in ("file", "symlink"):
167
                for (pinv, pinvshamap) in zip(parent_invs, parent_invshamaps):
168
                    try:
169
                        pie = pinv[ie.file_id]
170
                    except errors.NoSuchId:
171
                        pass
172
                    else:
173
                        if pie.kind == ie.kind and pie.revision == ie.revision:
174
                            shamap[ie.file_id] = pinvshamap.lookup_blob(ie.file_id, ie.revision)
175
                            break
176
                else:
0.200.788 by Jelmer Vernooij
Cache inventory.
177
                    obj = self._get_blob(ie.file_id, ie.revision, inv=inv)
0.200.773 by Jelmer Vernooij
Implement inventory_to_objects
178
                    yield path, obj
179
                    shamap[ie.file_id] = obj.id
180
                    new_trees[urlutils.dirname(path)] = ie.parent_id
181
            elif ie.kind == "directory":
182
                for pinv in parent_invs:
183
                    try:
184
                        pie = pinv[ie.file_id]
185
                    except errors.NoSuchId:
186
                        pass
187
                    else:
188
                        if (pie.kind == ie.kind and 
189
                            pie.children.keys() == ie.children.keys()):
0.200.779 by Jelmer Vernooij
Cope with lookup_tree not being implemented by a cache format.
190
                            try:
191
                                shamap[ie.file_id] = pinvshamap.lookup_tree(ie.file_id)
192
                            except NotImplementedError:
193
                                pass
194
                            else:
195
                                break
0.200.773 by Jelmer Vernooij
Implement inventory_to_objects
196
                else:
197
                    new_trees[path] = ie.file_id
198
            else:
199
                raise AssertionError(ie.kind)
200
        for fid in unusual_modes:
201
            new_trees[inv.id2path(fid)] = inv[fid].parent_id
202
        
203
        trees = {}
204
        while new_trees:
205
            items = new_trees.items()
206
            new_trees = {}
207
            for path, file_id in items:
208
                parent_id = inv[file_id].parent_id
209
                if parent_id is not None:
210
                    parent_path = urlutils.dirname(path)
211
                    new_trees[parent_path] = parent_id
212
                trees[path] = file_id
213
214
        for path in sorted(trees.keys(), reverse=True):
215
            ie = inv[trees[path]]
216
            assert ie.kind == "directory"
217
            obj = directory_to_tree(ie, 
218
                    lambda ie: shamap[ie.file_id], unusual_modes)
0.200.776 by Jelmer Vernooij
Remove unnecessary lookups.
219
            if obj is not None:
220
                shamap[ie.file_id] = obj.id
221
                yield path, obj
0.200.762 by Jelmer Vernooij
Add inventory to objects fn.
222
0.200.783 by Jelmer Vernooij
Move object generation into a separate function.
223
    def _revision_to_objects(self, rev, inv):
0.200.548 by Jelmer Vernooij
Extract unusual file modes from revision when reconstructing Trees.
224
        unusual_modes = extract_unusual_modes(rev)
0.200.789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
225
        present_parents = self.repository.has_revisions(rev.parent_ids)
226
        parent_invs = self.parent_invs_cache.get_inventories([p for p in rev.parent_ids if p in present_parents])
227
        parent_invshamaps = [self._idmap.get_inventory_sha_map(r) for r in rev.parent_ids if r in present_parents]
0.200.773 by Jelmer Vernooij
Implement inventory_to_objects
228
        tree_sha = None
229
        for path, obj in self._inventory_to_objects(inv, parent_invs,
230
                parent_invshamaps, unusual_modes):
0.200.783 by Jelmer Vernooij
Move object generation into a separate function.
231
            yield path, obj
0.200.773 by Jelmer Vernooij
Implement inventory_to_objects
232
            if path == "":
233
                tree_sha = obj.id
0.200.784 by Jelmer Vernooij
Use common object generation code in push.
234
        if tree_sha is None:
235
            if not rev.parent_ids:
236
                tree_sha = Tree().id
237
            else:
238
                tree_sha = parent_invshamaps[0][inv.root.file_id]
0.238.7 by Jelmer Vernooij
Cope with ghosts a bit better.
239
        commit_obj = self._revision_to_commit(rev, tree_sha)
0.231.1 by Jelmer Vernooij
Check that regenerated objects have the expected sha1.
240
        try:
0.200.784 by Jelmer Vernooij
Use common object generation code in push.
241
            foreign_revid, mapping = mapping_registry.parse_revision_id(rev.revision_id)
0.231.1 by Jelmer Vernooij
Check that regenerated objects have the expected sha1.
242
        except errors.InvalidRevisionId:
243
            pass
244
        else:
245
            if foreign_revid != commit_obj.id:
0.200.440 by Jelmer Vernooij
Remove silly mapping of timezones; dulwich uses offsets now as well.
246
                if not "fix-shamap" in debug.debug_flags:
247
                    raise AssertionError("recreated git commit had different sha1: expected %s, got %s" % (foreign_revid, commit_obj.id))
0.200.783 by Jelmer Vernooij
Move object generation into a separate function.
248
        yield None, commit_obj
249
250
    def _update_sha_map_revision(self, revid):
251
        rev = self.repository.get_revision(revid)
0.200.789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
252
        inv = self.parent_invs_cache.get_inventory(rev.revision_id)
0.200.783 by Jelmer Vernooij
Move object generation into a separate function.
253
        commit_obj = None
254
        entries = []
255
        for path, obj in self._revision_to_objects(rev, inv):
256
            if obj._type == "commit":
257
                commit_obj = obj
258
            elif obj._type in ("blob", "tree"):
259
                file_id = inv.path2id(path)
260
                ie = inv[file_id]
261
                if obj._type == "blob":
262
                    revision = ie.revision
263
                else:
264
                    revision = revid
265
                entries.append((file_id, obj._type, obj.id, revision))
266
            else:
267
                raise AssertionError
0.200.760 by Jelmer Vernooij
make add_entry private.
268
        self._idmap.add_entries(revid, rev.parent_ids, commit_obj.id, 
0.200.783 by Jelmer Vernooij
Move object generation into a separate function.
269
            commit_obj.tree, entries)
0.200.781 by Jelmer Vernooij
Return commit id after converting a revision.
270
        return commit_obj.id
0.200.229 by Jelmer Vernooij
More work on converter.
271
0.200.353 by Jelmer Vernooij
fileids/revids are plain strings, not unicode
272
    def _check_expected_sha(self, expected_sha, object):
273
        if expected_sha is None:
274
            return
0.200.565 by Jelmer Vernooij
Cope with 'binary' shas.
275
        if len(expected_sha) == 40:
276
            if expected_sha != object.sha().hexdigest():
277
                raise AssertionError("Invalid sha for %r: %s" % (object, expected_sha))
278
        elif len(expected_sha) == 20:
279
            if expected_sha != object.sha().digest():
280
                raise AssertionError("Invalid sha for %r: %s" % (object, sha_to_hex(expected_sha)))
281
        else:
282
            raise AssertionError("Unknown length %d for %r" % (len(expected_sha), expected_sha))
0.200.353 by Jelmer Vernooij
fileids/revids are plain strings, not unicode
283
0.200.664 by Jelmer Vernooij
Support submodules during fetch.
284
    def _get_ie_object(self, entry, inv, unusual_modes):
0.200.364 by Jelmer Vernooij
Reimplement dpush, but more efficient and only writing a single pack file rather than one per revision.
285
        if entry.kind == "directory":
0.200.750 by Jelmer Vernooij
Remove unused tree code, add mechanism for migrating between sha maps.
286
            return self._get_tree(entry.file_id, inv.revision_id, inv,
287
                unusual_modes)
0.244.1 by INADA Naoki
Fix sha1s for symlinks.
288
        elif entry.kind == "symlink":
289
            return self._get_blob_for_symlink(entry.symlink_target)
290
        elif entry.kind == "file":
0.200.698 by Jelmer Vernooij
Merge fixes for SHA1s of symlinks.
291
            return self._get_blob_for_file(entry.file_id, entry.revision)
0.200.664 by Jelmer Vernooij
Support submodules during fetch.
292
        else:
293
            raise AssertionError("unknown entry kind '%s'" % entry.kind)
0.200.364 by Jelmer Vernooij
Reimplement dpush, but more efficient and only writing a single pack file rather than one per revision.
294
0.244.1 by INADA Naoki
Fix sha1s for symlinks.
295
    def _get_blob_for_symlink(self, symlink_target, expected_sha=None):
296
        """Return a Git Blob object for symlink.
297
298
        :param symlink_target: target of symlink.
299
        """
0.200.698 by Jelmer Vernooij
Merge fixes for SHA1s of symlinks.
300
        if type(symlink_target) == unicode:
0.244.1 by INADA Naoki
Fix sha1s for symlinks.
301
            symlink_target = symlink_target.encode('utf-8')
302
        blob = Blob()
303
        blob._text = symlink_target
304
        self._check_expected_sha(expected_sha, blob)
305
        return blob
306
0.200.698 by Jelmer Vernooij
Merge fixes for SHA1s of symlinks.
307
    def _get_blob_for_file(self, fileid, revision, expected_sha=None):
308
        """Return a Git Blob object from a fileid and revision stored in bzr.
309
310
        :param fileid: File id of the text
311
        :param revision: Revision of the text
312
        """
313
        blob = Blob()
314
        chunks = self.repository.iter_files_bytes([(fileid, revision, None)]).next()[1]
315
        blob._text = "".join(chunks)
316
        self._check_expected_sha(expected_sha, blob)
317
        return blob
318
0.200.788 by Jelmer Vernooij
Cache inventory.
319
    def _get_blob(self, fileid, revision, expected_sha=None, inv=None):
0.200.236 by Jelmer Vernooij
require bzr 1.13.
320
        """Return a Git Blob object from a fileid and revision stored in bzr.
0.200.670 by Jelmer Vernooij
Fix symlinks.
321
0.200.236 by Jelmer Vernooij
require bzr 1.13.
322
        :param fileid: File id of the text
323
        :param revision: Revision of the text
324
        """
0.200.788 by Jelmer Vernooij
Cache inventory.
325
        if inv is None:
0.200.789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
326
            inv = self.parent_invs_cache.get_inventory(revision)
0.200.698 by Jelmer Vernooij
Merge fixes for SHA1s of symlinks.
327
        entry = inv[fileid]
0.244.1 by INADA Naoki
Fix sha1s for symlinks.
328
329
        if entry.kind == 'file':
0.200.698 by Jelmer Vernooij
Merge fixes for SHA1s of symlinks.
330
            return self._get_blob_for_file(entry.file_id, entry.revision,
331
                                           expected_sha=expected_sha)
0.244.1 by INADA Naoki
Fix sha1s for symlinks.
332
        elif entry.kind == 'symlink':
0.200.698 by Jelmer Vernooij
Merge fixes for SHA1s of symlinks.
333
            return self._get_blob_for_symlink(entry.symlink_target,
334
                                              expected_sha=expected_sha)
335
        else:
336
            raise AssertionError
0.200.229 by Jelmer Vernooij
More work on converter.
337
0.200.548 by Jelmer Vernooij
Extract unusual file modes from revision when reconstructing Trees.
338
    def _get_tree(self, fileid, revid, inv, unusual_modes, expected_sha=None):
0.200.343 by Jelmer Vernooij
Use file ids consistently in map.
339
        """Return a Git Tree object from a file id and a revision stored in bzr.
0.200.249 by Jelmer Vernooij
Implement Tree.
340
0.200.343 by Jelmer Vernooij
Use file ids consistently in map.
341
        :param fileid: fileid in the tree.
0.200.249 by Jelmer Vernooij
Implement Tree.
342
        :param revision: Revision of the tree.
343
        """
0.200.761 by Jelmer Vernooij
Defer invshamap calls.
344
        invshamap = self._idmap.get_inventory_sha_map(inv.revision_id)
0.200.776 by Jelmer Vernooij
Remove unnecessary lookups.
345
        def get_ie_sha1(entry):
346
            if entry.kind == "directory":
347
                return invshamap.lookup_tree(entry.file_id)
348
            elif entry.kind in ("file", "symlink"):
349
                return invshamap.lookup_blob(entry.file_id, entry.revision)
350
            else:
351
                raise AssertionError("unknown entry kind '%s'" % entry.kind)
352
        tree = directory_to_tree(inv[fileid], get_ie_sha1, unusual_modes)
0.200.353 by Jelmer Vernooij
fileids/revids are plain strings, not unicode
353
        self._check_expected_sha(expected_sha, tree)
0.200.249 by Jelmer Vernooij
Implement Tree.
354
        return tree
0.200.229 by Jelmer Vernooij
More work on converter.
355
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
356
    def get_parents(self, sha):
0.200.454 by Jelmer Vernooij
Use ObjectStore.find_missing_objects in server.
357
        """Retrieve the parents of a Git commit by SHA1.
358
359
        :param sha: SHA1 of the commit
360
        :raises: KeyError, NotCommitError
361
        """
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
362
        return self[sha].parents
363
0.200.364 by Jelmer Vernooij
Reimplement dpush, but more efficient and only writing a single pack file rather than one per revision.
364
    def _lookup_revision_sha1(self, revid):
0.200.449 by Jelmer Vernooij
Use BazaarObjectStore to find matching SHA1s for bzr revisions.
365
        """Return the SHA1 matching a Bazaar revision."""
0.200.541 by Jelmer Vernooij
Cope with NULL_REVISION.
366
        if revid == NULL_REVISION:
367
            return "0" * 40
0.200.364 by Jelmer Vernooij
Reimplement dpush, but more efficient and only writing a single pack file rather than one per revision.
368
        try:
0.200.487 by Jelmer Vernooij
Prevent deep recursion if the shamap is out of date.
369
            return self._idmap.lookup_commit(revid)
0.200.364 by Jelmer Vernooij
Reimplement dpush, but more efficient and only writing a single pack file rather than one per revision.
370
        except KeyError:
0.200.682 by Jelmer Vernooij
Avoid doing a full sha map update if we already know the SHA1.
371
            try:
372
                return mapping_registry.parse_revision_id(revid)[0]
373
            except errors.InvalidRevisionId:
374
                self._update_sha_map(revid)
375
                return self._idmap.lookup_commit(revid)
0.200.364 by Jelmer Vernooij
Reimplement dpush, but more efficient and only writing a single pack file rather than one per revision.
376
0.200.310 by Jelmer Vernooij
Fix pull from remote branches.
377
    def get_raw(self, sha):
0.200.454 by Jelmer Vernooij
Use ObjectStore.find_missing_objects in server.
378
        """Get the raw representation of a Git object by SHA1.
379
380
        :param sha: SHA1 of the git object
381
        """
0.200.566 by Jelmer Vernooij
Fix ObjectStore.get_raw() .
382
        obj = self[sha]
383
        return (obj.type, obj.as_raw_string())
0.200.310 by Jelmer Vernooij
Fix pull from remote branches.
384
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
385
    def __contains__(self, sha):
386
        # See if sha is in map
387
        try:
0.200.568 by Jelmer Vernooij
Properly check that matching bzr objects exist.
388
            (type, type_data) = self._lookup_git_sha(sha)
389
            if type == "commit":
390
                return self.repository.has_revision(type_data[0])
391
            elif type == "blob":
392
                return self.repository.texts.has_version(type_data)
393
            elif type == "tree":
394
                return self.repository.has_revision(type_data[1])
395
            else:
396
                raise AssertionError("Unknown object type '%s'" % type)
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
397
        except KeyError:
398
            return False
399
400
    def _lookup_git_sha(self, sha):
401
        # See if sha is in map
402
        try:
403
            return self._idmap.lookup_git_sha(sha)
0.200.228 by Jelmer Vernooij
Split out map.
404
        except KeyError:
0.200.670 by Jelmer Vernooij
Fix symlinks.
405
            # if not, see if there are any unconverted revisions and add them
0.200.228 by Jelmer Vernooij
Split out map.
406
            # to the map, search for sha in map again
407
            self._update_sha_map()
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
408
            return self._idmap.lookup_git_sha(sha)
409
410
    def __getitem__(self, sha):
411
        (type, type_data) = self._lookup_git_sha(sha)
0.200.228 by Jelmer Vernooij
Split out map.
412
        # convert object to git object
0.200.229 by Jelmer Vernooij
More work on converter.
413
        if type == "commit":
0.200.787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
414
            (revid, tree_sha) = type_data
0.200.478 by Jelmer Vernooij
Cope with disappeared revisions.
415
            try:
0.200.787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
416
                rev = self.repository.get_revision(revid)
0.200.478 by Jelmer Vernooij
Cope with disappeared revisions.
417
            except errors.NoSuchRevision:
418
                trace.mutter('entry for %s %s in shamap: %r, but not found in repository', type, sha, type_data)
419
                raise KeyError(sha)
0.200.787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
420
            commit = self._revision_to_commit(rev, tree_sha)
0.200.785 by Jelmer Vernooij
Eliminate _get_commit.
421
            self._check_expected_sha(sha, commit)
422
            return commit
0.200.229 by Jelmer Vernooij
More work on converter.
423
        elif type == "blob":
0.200.787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
424
            (fileid, revision) = type_data
425
            return self._get_blob(fileid, revision, expected_sha=sha)
0.200.229 by Jelmer Vernooij
More work on converter.
426
        elif type == "tree":
0.200.787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
427
            (fileid, revid) = type_data
0.200.561 by Jelmer Vernooij
Cope with revisions pointed to by trees in the shamap disappearing.
428
            try:
0.200.789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
429
                inv = self.parent_invs_cache.get_inventory(revid)
0.200.787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
430
                rev = self.repository.get_revision(revid)
0.200.561 by Jelmer Vernooij
Cope with revisions pointed to by trees in the shamap disappearing.
431
            except errors.NoSuchRevision:
432
                trace.mutter('entry for %s %s in shamap: %r, but not found in repository', type, sha, type_data)
433
                raise KeyError(sha)
0.200.556 by Jelmer Vernooij
Fix syntax error.
434
            unusual_modes = extract_unusual_modes(rev)
0.200.491 by Jelmer Vernooij
Cope with map for Tree objects becoming invalid.
435
            try:
0.200.787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
436
                return self._get_tree(fileid, revid, inv,
0.200.749 by Jelmer Vernooij
Avoid storing entries for trees in the cache, use blobs instead
437
                    unusual_modes, expected_sha=sha)
0.200.491 by Jelmer Vernooij
Cope with map for Tree objects becoming invalid.
438
            except errors.NoSuchRevision:
439
                raise KeyError(sha)
0.200.228 by Jelmer Vernooij
Split out map.
440
        else:
441
            raise AssertionError("Unknown object type '%s'" % type)
0.200.782 by Jelmer Vernooij
Add custom generate_pack_contents implementation.
442
443
    def generate_pack_contents(self, have, want):
444
        """Iterate over the contents of a pack file.
445
446
        :param have: List of SHA1s of objects that should not be sent
447
        :param want: List of SHA1s of objects that should be sent
448
        """
0.200.787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
449
        processed = set()
450
        for commit_sha in have:
451
            try:
452
                (type, (revid, tree_sha)) = self._lookup_git_sha(commit_sha)
453
            except KeyError:
454
                pass
455
            else:
456
                assert type == "commit"
457
                processed.add(revid)
458
        pending = set()
459
        for commit_sha in want:
460
            if commit_sha in have:
461
                continue
462
            (type, (revid, tree_sha)) = self._lookup_git_sha(commit_sha)
463
            assert type == "commit"
464
            pending.add(revid)
465
        todo = set()
466
        while pending:
467
            processed.update(pending)
468
            next_map = self.repository.get_parent_map(pending)
469
            next_pending = set()
470
            for item in next_map.iteritems():
471
                todo.add(item[0])
472
                next_pending.update(p for p in item[1] if p not in processed)
473
            pending = next_pending
474
        if NULL_REVISION in todo:
475
            todo.remove(NULL_REVISION)
476
        trace.mutter('sending revisions %r', todo)
477
        ret = []
478
        pb = ui.ui_factory.nested_progress_bar()
479
        try:
480
            for i, revid in enumerate(todo):
481
                pb.update("generating git objects", i, len(todo))
482
                rev = self.repository.get_revision(revid)
0.200.789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
483
                inv = self.parent_invs_cache.get_inventory(revid)
0.200.787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
484
                for path, obj in self._revision_to_objects(rev, inv):
485
                    ret.append((obj, path))
486
        finally:
487
            pb.finished()
488
        return ret