/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.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
21
    Commit,
0.200.864 by Jelmer Vernooij
Cope with the first commit being pointless.
22
    Tree,
0.200.586 by Jelmer Vernooij
Fix issues pointed out by pyflakes.
23
    sha_to_hex,
0.200.1153 by Jelmer Vernooij
Import ZERO_SHA from dulwich.objects.
24
    ZERO_SHA,
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
25
    )
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
26
from dulwich.object_store import (
0.200.457 by Jelmer Vernooij
Use BaseObjectStore.
27
    BaseObjectStore,
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
28
    )
0.200.249 by Jelmer Vernooij
Implement Tree.
29
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
30
from bzrlib import (
0.231.1 by Jelmer Vernooij
Check that regenerated objects have the expected sha1.
31
    errors,
0.200.789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
32
    lru_cache,
0.200.478 by Jelmer Vernooij
Cope with disappeared revisions.
33
    trace,
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
34
    ui,
0.200.773 by Jelmer Vernooij
Implement inventory_to_objects
35
    urlutils,
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
36
    )
0.200.1212 by Jelmer Vernooij
Support read locking object stores.
37
from bzrlib.lock import LogicalLockResult
0.200.541 by Jelmer Vernooij
Cope with NULL_REVISION.
38
from bzrlib.revision import (
39
    NULL_REVISION,
40
    )
0.200.1023 by Jelmer Vernooij
Set and verify testament.
41
from bzrlib.testament import(
42
    StrictTestament3,
43
    )
0.200.228 by Jelmer Vernooij
Split out map.
44
0.200.229 by Jelmer Vernooij
More work on converter.
45
from bzrlib.plugins.git.mapping import (
0.200.463 by Jelmer Vernooij
Support remote dpush (except for references).
46
    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.
47
    directory_to_tree,
0.200.548 by Jelmer Vernooij
Extract unusual file modes from revision when reconstructing Trees.
48
    extract_unusual_modes,
0.231.1 by Jelmer Vernooij
Check that regenerated objects have the expected sha1.
49
    mapping_registry,
0.200.795 by Jelmer Vernooij
simplify sha extraction for blobs, process multiple blobs at once.
50
    symlink_to_blob,
0.200.229 by Jelmer Vernooij
More work on converter.
51
    )
0.200.938 by Jelmer Vernooij
Rename shamap to cache, as it can also do content caching now.
52
from bzrlib.plugins.git.cache import (
0.200.842 by Jelmer Vernooij
Allow content cache to be provided.
53
    from_repository as cache_from_repository,
0.200.231 by Jelmer Vernooij
Partially fix pull.
54
    )
55
0.200.878 by Jelmer Vernooij
Fix determining of unusual file modes.
56
import posixpath
0.252.23 by Jelmer Vernooij
More work on roundtripping support.
57
import stat
0.200.878 by Jelmer Vernooij
Fix determining of unusual file modes.
58
0.200.228 by Jelmer Vernooij
Split out map.
59
0.200.452 by Jelmer Vernooij
Rename converter -> object_store, provide utility function for getting ObjectStore's.
60
def get_object_store(repo, mapping=None):
61
    git = getattr(repo, "_git", None)
62
    if git is not None:
0.200.1212 by Jelmer Vernooij
Support read locking object stores.
63
        git.object_store.unlock = lambda x: None
64
        git.object_store.lock_read = LogicalLockResult(lambda: None)
65
        git.object_store.lock_write = LogicalLockResult(lambda: None)
0.200.452 by Jelmer Vernooij
Rename converter -> object_store, provide utility function for getting ObjectStore's.
66
        return git.object_store
67
    return BazaarObjectStore(repo, mapping)
68
69
0.200.852 by Jelmer Vernooij
Cache trees rather than inventories.
70
MAX_TREE_CACHE_SIZE = 50 * 1024 * 1024
71
72
73
class LRUTreeCache(object):
0.200.789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
74
75
    def __init__(self, repository):
0.200.852 by Jelmer Vernooij
Cache trees rather than inventories.
76
        def approx_tree_size(tree):
0.200.789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
77
            # Very rough estimate, 1k per inventory entry
0.200.852 by Jelmer Vernooij
Cache trees rather than inventories.
78
            return len(tree.inventory) * 1024
0.200.789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
79
        self.repository = repository
0.200.852 by Jelmer Vernooij
Cache trees rather than inventories.
80
        self._cache = lru_cache.LRUSizeCache(max_size=MAX_TREE_CACHE_SIZE,
81
            after_cleanup_size=None, compute_size=approx_tree_size)
0.200.789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
82
0.200.963 by Jelmer Vernooij
Add some tests for LRUTreeCache.
83
    def revision_tree(self, revid):
0.200.789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
84
        try:
0.200.989 by Jelmer Vernooij
Add asserts.
85
            tree = self._cache[revid]
0.200.789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
86
        except KeyError:
0.200.852 by Jelmer Vernooij
Cache trees rather than inventories.
87
            tree = self.repository.revision_tree(revid)
88
            self.add(tree)
0.200.989 by Jelmer Vernooij
Add asserts.
89
        assert tree.get_revision_id() == tree.inventory.revision_id
90
        return tree
0.200.852 by Jelmer Vernooij
Cache trees rather than inventories.
91
92
    def iter_revision_trees(self, revids):
0.200.989 by Jelmer Vernooij
Add asserts.
93
        trees = {}
94
        todo = []
95
        for revid in revids:
96
            try:
97
                tree = self._cache[revid]
98
            except KeyError:
99
                todo.append(revid)
100
            else:
101
                assert tree.get_revision_id() == revid
102
                trees[revid] = tree
103
        for tree in self.repository.revision_trees(todo):
0.200.852 by Jelmer Vernooij
Cache trees rather than inventories.
104
            trees[tree.get_revision_id()] = tree
105
            self.add(tree)
106
        return (trees[r] for r in revids)
107
108
    def revision_trees(self, revids):
109
        return list(self.iter_revision_trees(revids))
110
111
    def add(self, tree):
112
        self._cache.add(tree.get_revision_id(), tree)
0.200.789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
113
114
0.200.1053 by Jelmer Vernooij
Fix find_missing_bzr_revids.
115
def _find_missing_bzr_revids(graph, want, have):
0.252.5 by Jelmer Vernooij
enable 'bzr push'.
116
    """Find the revisions that have to be pushed.
117
118
    :param get_parent_map: Function that returns the parents for a sequence
119
        of revisions.
120
    :param want: Revisions the target wants
121
    :param have: Revisions the target already has
122
    :return: Set of revisions to fetch
123
    """
0.200.899 by Jelmer Vernooij
Add tests for find_missing_bzr_revids.
124
    todo = set()
0.200.1053 by Jelmer Vernooij
Fix find_missing_bzr_revids.
125
    for rev in want:
126
        todo.update(graph.find_unique_ancestors(rev, have))
0.200.899 by Jelmer Vernooij
Add tests for find_missing_bzr_revids.
127
    if NULL_REVISION in todo:
128
        todo.remove(NULL_REVISION)
129
    return todo
130
131
0.200.793 by Jelmer Vernooij
Make _check_expected_sha a global fn.
132
def _check_expected_sha(expected_sha, object):
0.200.797 by Jelmer Vernooij
Add docstring, fix formatting.
133
    """Check whether an object matches an expected SHA.
134
135
    :param expected_sha: None or expected SHA as either binary or as hex digest
136
    :param object: Object to verify
137
    """
0.200.793 by Jelmer Vernooij
Make _check_expected_sha a global fn.
138
    if expected_sha is None:
139
        return
140
    if len(expected_sha) == 40:
141
        if expected_sha != object.sha().hexdigest():
0.200.797 by Jelmer Vernooij
Add docstring, fix formatting.
142
            raise AssertionError("Invalid sha for %r: %s" % (object,
143
                expected_sha))
0.200.793 by Jelmer Vernooij
Make _check_expected_sha a global fn.
144
    elif len(expected_sha) == 20:
145
        if expected_sha != object.sha().digest():
0.200.797 by Jelmer Vernooij
Add docstring, fix formatting.
146
            raise AssertionError("Invalid sha for %r: %s" % (object,
147
                sha_to_hex(expected_sha)))
0.200.793 by Jelmer Vernooij
Make _check_expected_sha a global fn.
148
    else:
0.200.797 by Jelmer Vernooij
Add docstring, fix formatting.
149
        raise AssertionError("Unknown length %d for %r" % (len(expected_sha),
150
            expected_sha))
0.200.793 by Jelmer Vernooij
Make _check_expected_sha a global fn.
151
152
0.200.931 by Jelmer Vernooij
Update docstring, deal with kind changes appropriately in _tree_to_objects
153
def _tree_to_objects(tree, parent_trees, idmap, unusual_modes,
154
                     dummy_file_name=None):
0.200.798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
155
    """Iterate over the objects that were introduced in a revision.
156
0.200.841 by Jelmer Vernooij
Eliminate InventorySHAMap.
157
    :param idmap: id map
0.200.931 by Jelmer Vernooij
Update docstring, deal with kind changes appropriately in _tree_to_objects
158
    :param parent_trees: Parent revision trees
159
    :param unusual_modes: Unusual file modes dictionary
0.252.30 by Jelmer Vernooij
Support creating dummy files for empty directories.
160
    :param dummy_file_name: File name to use for dummy files
161
        in empty directories. None to skip empty directories
0.200.837 by Jelmer Vernooij
Return inventory entries when creating git objects for a revision.
162
    :return: Yields (path, object, ie) entries
0.200.798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
163
    """
164
    new_trees = {}
165
    new_blobs = []
166
    shamap = {}
0.250.1 by Jelmer Vernooij
Use iter_changes() rather than iterating over all contents of an inventory.
167
    try:
168
        base_tree = parent_trees[0]
169
        other_parent_trees = parent_trees[1:]
170
    except IndexError:
171
        base_tree = tree._repository.revision_tree(NULL_REVISION)
172
        other_parent_trees = []
0.200.868 by Jelmer Vernooij
Cope with no-change merges.
173
    def find_unchanged_parent_ie(ie, parent_trees):
174
        assert ie.kind in ("symlink", "file")
175
        for ptree in parent_trees:
176
            try:
177
                pie = ptree.inventory[ie.file_id]
178
            except errors.NoSuchId:
179
                pass
180
            else:
0.200.1212 by Jelmer Vernooij
Support read locking object stores.
181
                if (pie.text_sha1 == ie.text_sha1 and
0.200.868 by Jelmer Vernooij
Cope with no-change merges.
182
                    pie.kind == ie.kind and
183
                    pie.symlink_target == ie.symlink_target):
184
                    return pie
185
        raise KeyError
0.200.965 by Jelmer Vernooij
Formatting fixes.
186
0.200.931 by Jelmer Vernooij
Update docstring, deal with kind changes appropriately in _tree_to_objects
187
    # Find all the changed blobs
0.250.1 by Jelmer Vernooij
Use iter_changes() rather than iterating over all contents of an inventory.
188
    for (file_id, path, changed_content, versioned, parent, name, kind,
189
         executable) in tree.iter_changes(base_tree):
190
        if kind[1] == "file":
191
            ie = tree.inventory[file_id]
192
            if changed_content:
0.200.868 by Jelmer Vernooij
Cope with no-change merges.
193
                try:
194
                    pie = find_unchanged_parent_ie(ie, other_parent_trees)
195
                except KeyError:
196
                    pass
197
                else:
0.252.40 by Jelmer Vernooij
Checks for roundtripping.
198
                    try:
199
                        shamap[ie.file_id] = idmap.lookup_blob_id(
200
                            pie.file_id, pie.revision)
201
                    except KeyError:
202
                        # no-change merge ?
203
                        blob = Blob()
204
                        blob.data = tree.get_file_text(ie.file_id)
205
                        shamap[ie.file_id] = blob.id
0.250.1 by Jelmer Vernooij
Use iter_changes() rather than iterating over all contents of an inventory.
206
            if not file_id in shamap:
207
                new_blobs.append((path[1], ie))
0.200.878 by Jelmer Vernooij
Fix determining of unusual file modes.
208
            new_trees[posixpath.dirname(path[1])] = parent[1]
0.250.1 by Jelmer Vernooij
Use iter_changes() rather than iterating over all contents of an inventory.
209
        elif kind[1] == "symlink":
210
            ie = tree.inventory[file_id]
211
            if changed_content:
212
                blob = symlink_to_blob(ie)
0.200.868 by Jelmer Vernooij
Cope with no-change merges.
213
                shamap[file_id] = blob.id
214
                try:
215
                    find_unchanged_parent_ie(ie, other_parent_trees)
216
                except KeyError:
217
                    yield path[1], blob, ie
0.200.878 by Jelmer Vernooij
Fix determining of unusual file modes.
218
            new_trees[posixpath.dirname(path[1])] = parent[1]
0.250.3 by Jelmer Vernooij
Simplify..
219
        elif kind[1] not in (None, "directory"):
0.250.1 by Jelmer Vernooij
Use iter_changes() rather than iterating over all contents of an inventory.
220
            raise AssertionError(kind[1])
0.200.1017 by Jelmer Vernooij
Cope with root moving.
221
        if (path[0] not in (None, "") and
222
            parent[0] in tree.inventory and
223
            tree.inventory[parent[0]].kind == "directory"):
0.200.931 by Jelmer Vernooij
Update docstring, deal with kind changes appropriately in _tree_to_objects
224
            # Removal
0.200.878 by Jelmer Vernooij
Fix determining of unusual file modes.
225
            new_trees[posixpath.dirname(path[0])] = parent[0]
0.200.1212 by Jelmer Vernooij
Support read locking object stores.
226
0.200.931 by Jelmer Vernooij
Update docstring, deal with kind changes appropriately in _tree_to_objects
227
    # Fetch contents of the blobs that were changed
0.250.2 by Jelmer Vernooij
Make it work for evolution.
228
    for (path, ie), chunks in tree.iter_files_bytes(
229
        [(ie.file_id, (path, ie)) for (path, ie) in new_blobs]):
0.200.798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
230
        obj = Blob()
0.200.851 by Jelmer Vernooij
Use blob.chunked.
231
        obj.chunked = chunks
0.200.837 by Jelmer Vernooij
Return inventory entries when creating git objects for a revision.
232
        yield path, obj, ie
233
        shamap[ie.file_id] = obj.id
0.200.798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
234
0.200.879 by Jelmer Vernooij
Fix unusual modes.
235
    for path in unusual_modes:
236
        parent_path = posixpath.dirname(path)
237
        new_trees[parent_path] = tree.path2id(parent_path)
0.200.989 by Jelmer Vernooij
Add asserts.
238
0.200.798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
239
    trees = {}
240
    while new_trees:
241
        items = new_trees.items()
242
        new_trees = {}
243
        for path, file_id in items:
0.200.931 by Jelmer Vernooij
Update docstring, deal with kind changes appropriately in _tree_to_objects
244
            parent_id = tree.inventory[file_id].parent_id
0.200.798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
245
            if parent_id is not None:
246
                parent_path = urlutils.dirname(path)
247
                new_trees[parent_path] = parent_id
248
            trees[path] = file_id
249
0.200.808 by Jelmer Vernooij
Avoid recalculating tree shas we already have.
250
    def ie_to_hexsha(ie):
251
        try:
252
            return shamap[ie.file_id]
253
        except KeyError:
0.200.884 by Jelmer Vernooij
Cope with -0000 as timezone in Git commits.
254
            # FIXME: Should be the same as in parent
0.250.1 by Jelmer Vernooij
Use iter_changes() rather than iterating over all contents of an inventory.
255
            if ie.kind in ("file", "symlink"):
0.200.868 by Jelmer Vernooij
Cope with no-change merges.
256
                try:
257
                    return idmap.lookup_blob_id(ie.file_id, ie.revision)
258
                except KeyError:
259
                    # no-change merge ?
260
                    blob = Blob()
261
                    blob.data = tree.get_file_text(ie.file_id)
262
                    return blob.id
0.250.1 by Jelmer Vernooij
Use iter_changes() rather than iterating over all contents of an inventory.
263
            elif ie.kind == "directory":
264
                # Not all cache backends store the tree information, 
265
                # calculate again from scratch
0.252.30 by Jelmer Vernooij
Support creating dummy files for empty directories.
266
                ret = directory_to_tree(ie, ie_to_hexsha, unusual_modes,
267
                    dummy_file_name)
0.250.1 by Jelmer Vernooij
Use iter_changes() rather than iterating over all contents of an inventory.
268
                if ret is None:
269
                    return ret
270
                return ret.id
271
            else:
272
                raise AssertionError
0.200.808 by Jelmer Vernooij
Avoid recalculating tree shas we already have.
273
0.200.798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
274
    for path in sorted(trees.keys(), reverse=True):
0.250.1 by Jelmer Vernooij
Use iter_changes() rather than iterating over all contents of an inventory.
275
        ie = tree.inventory[trees[path]]
0.200.798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
276
        assert ie.kind == "directory"
0.252.30 by Jelmer Vernooij
Support creating dummy files for empty directories.
277
        obj = directory_to_tree(ie, ie_to_hexsha, unusual_modes,
278
            dummy_file_name)
0.200.798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
279
        if obj is not None:
0.200.837 by Jelmer Vernooij
Return inventory entries when creating git objects for a revision.
280
            yield path, obj, ie
0.200.798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
281
            shamap[ie.file_id] = obj.id
282
283
0.200.457 by Jelmer Vernooij
Use BaseObjectStore.
284
class BazaarObjectStore(BaseObjectStore):
0.200.320 by Jelmer Vernooij
Handle lightweight checkouts.
285
    """A Git-style object store backed onto a Bazaar repository."""
0.200.228 by Jelmer Vernooij
Split out map.
286
287
    def __init__(self, repository, mapping=None):
288
        self.repository = repository
0.200.1212 by Jelmer Vernooij
Support read locking object stores.
289
        self._map_updated = False
290
        self._locked = None
0.200.228 by Jelmer Vernooij
Split out map.
291
        if mapping is None:
0.200.463 by Jelmer Vernooij
Support remote dpush (except for references).
292
            self.mapping = default_mapping
0.200.228 by Jelmer Vernooij
Split out map.
293
        else:
294
            self.mapping = mapping
0.200.847 by Jelmer Vernooij
Add BzrGitCache object.
295
        self._cache = cache_from_repository(repository)
0.254.40 by Jelmer Vernooij
Add content cache infrastructure.
296
        self._content_cache_types = ("tree")
0.200.847 by Jelmer Vernooij
Add BzrGitCache object.
297
        self.start_write_group = self._cache.idmap.start_write_group
298
        self.abort_write_group = self._cache.idmap.abort_write_group
299
        self.commit_write_group = self._cache.idmap.commit_write_group
0.200.852 by Jelmer Vernooij
Cache trees rather than inventories.
300
        self.tree_cache = LRUTreeCache(self.repository)
0.200.228 by Jelmer Vernooij
Split out map.
301
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
302
    def _update_sha_map(self, stop_revision=None):
0.200.1212 by Jelmer Vernooij
Support read locking object stores.
303
        if not self.is_locked():
304
            raise AssertionError()
305
        if self._map_updated:
306
            return
0.200.683 by Jelmer Vernooij
Lazier checking of which revisions need to be fetched.
307
        graph = self.repository.get_graph()
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
308
        if stop_revision is None:
0.200.683 by Jelmer Vernooij
Lazier checking of which revisions need to be fetched.
309
            heads = graph.heads(self.repository.all_revision_ids())
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
310
        else:
0.200.683 by Jelmer Vernooij
Lazier checking of which revisions need to be fetched.
311
            heads = set([stop_revision])
0.200.847 by Jelmer Vernooij
Add BzrGitCache object.
312
        missing_revids = self._cache.idmap.missing_revisions(heads)
0.200.683 by Jelmer Vernooij
Lazier checking of which revisions need to be fetched.
313
        while heads:
314
            parents = graph.get_parent_map(heads)
315
            todo = set()
316
            for p in parents.values():
0.200.684 by Jelmer Vernooij
Properly close write groups.
317
                todo.update([x for x in p if x not in missing_revids])
0.200.847 by Jelmer Vernooij
Add BzrGitCache object.
318
            heads = self._cache.idmap.missing_revisions(todo)
0.200.684 by Jelmer Vernooij
Properly close write groups.
319
            missing_revids.update(heads)
0.200.694 by Jelmer Vernooij
Avoid processing NULL_REVISION.
320
        if NULL_REVISION in missing_revids:
321
            missing_revids.remove(NULL_REVISION)
0.254.16 by Jelmer Vernooij
Add optimization preventing recursive index updating.
322
        missing_revids = self.repository.has_revisions(missing_revids)
323
        if not missing_revids:
0.200.1212 by Jelmer Vernooij
Support read locking object stores.
324
            self._map_updated = True
0.254.16 by Jelmer Vernooij
Add optimization preventing recursive index updating.
325
            return
0.200.735 by Jelmer Vernooij
Use convenience functions for start/stop write groups.
326
        self.start_write_group()
0.200.231 by Jelmer Vernooij
Partially fix pull.
327
        try:
0.254.4 by Jelmer Vernooij
Merge trunk.
328
            pb = ui.ui_factory.nested_progress_bar()
329
            try:
330
                for i, revid in enumerate(graph.iter_topo_order(missing_revids)):
0.254.16 by Jelmer Vernooij
Add optimization preventing recursive index updating.
331
                    trace.mutter('processing %r', revid)
0.254.4 by Jelmer Vernooij
Merge trunk.
332
                    pb.update("updating git map", i, len(missing_revids))
333
                    self._update_sha_map_revision(revid)
334
            finally:
335
                pb.finished()
0.200.1212 by Jelmer Vernooij
Support read locking object stores.
336
            self._map_updated = True
0.200.735 by Jelmer Vernooij
Use convenience functions for start/stop write groups.
337
        except:
338
            self.abort_write_group()
339
            raise
340
        else:
341
            self.commit_write_group()
0.200.229 by Jelmer Vernooij
More work on converter.
342
0.200.422 by Jelmer Vernooij
'bzr git-object' without arguments now prints the available git objects.
343
    def __iter__(self):
344
        self._update_sha_map()
0.200.847 by Jelmer Vernooij
Add BzrGitCache object.
345
        return iter(self._cache.idmap.sha1s())
0.200.422 by Jelmer Vernooij
'bzr git-object' without arguments now prints the available git objects.
346
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
347
    def _reconstruct_commit(self, rev, tree_sha, roundtrip, verifiers):
348
        """Reconstruct a Commit object.
349
350
        :param rev: Revision object
351
        :param tree_sha: SHA1 of the root tree object
352
        :param roundtrip: Whether or not to roundtrip bzr metadata
353
        :param verifiers: Verifiers for the commits
354
        :return: Commit object
355
        """
0.238.7 by Jelmer Vernooij
Cope with ghosts a bit better.
356
        def parent_lookup(revid):
357
            try:
358
                return self._lookup_revision_sha1(revid)
359
            except errors.NoSuchRevision:
360
                return None
0.252.4 by Jelmer Vernooij
More work on roundtripping.
361
        return self.mapping.export_commit(rev, tree_sha, parent_lookup,
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
362
            roundtrip, verifiers)
0.238.7 by Jelmer Vernooij
Cope with ghosts a bit better.
363
0.252.49 by Jelmer Vernooij
Avoid trying to set HEAD for remote branches.
364
    def _create_fileid_map_blob(self, inv):
365
        # FIXME: This can probably be a lot more efficient, 
366
        # not all files necessarily have to be processed.
367
        file_ids = {}
368
        for (path, ie) in inv.iter_entries():
369
            if self.mapping.generate_file_id(path) != ie.file_id:
370
                file_ids[path] = ie.file_id
371
        return self.mapping.export_fileid_map(file_ids)
372
0.252.4 by Jelmer Vernooij
More work on roundtripping.
373
    def _revision_to_objects(self, rev, tree, roundtrip):
0.252.23 by Jelmer Vernooij
More work on roundtripping support.
374
        """Convert a revision to a set of git objects.
375
376
        :param rev: Bazaar revision object
377
        :param tree: Bazaar revision tree
378
        :param roundtrip: Whether to roundtrip all Bazaar revision data
379
        """
0.200.548 by Jelmer Vernooij
Extract unusual file modes from revision when reconstructing Trees.
380
        unusual_modes = extract_unusual_modes(rev)
0.200.789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
381
        present_parents = self.repository.has_revisions(rev.parent_ids)
0.200.852 by Jelmer Vernooij
Cache trees rather than inventories.
382
        parent_trees = self.tree_cache.revision_trees(
0.200.797 by Jelmer Vernooij
Add docstring, fix formatting.
383
            [p for p in rev.parent_ids if p in present_parents])
0.252.23 by Jelmer Vernooij
More work on roundtripping support.
384
        root_tree = None
0.200.852 by Jelmer Vernooij
Cache trees rather than inventories.
385
        for path, obj, ie in _tree_to_objects(tree, parent_trees,
0.252.30 by Jelmer Vernooij
Support creating dummy files for empty directories.
386
                self._cache.idmap, unusual_modes, self.mapping.BZR_DUMMY_FILE):
0.200.773 by Jelmer Vernooij
Implement inventory_to_objects
387
            if path == "":
0.252.23 by Jelmer Vernooij
More work on roundtripping support.
388
                root_tree = obj
0.252.34 by Jelmer Vernooij
Yield the proper object for the tree root.
389
                root_ie = ie
390
                # Don't yield just yet
391
            else:
392
                yield path, obj, ie
0.252.23 by Jelmer Vernooij
More work on roundtripping support.
393
        if root_tree is None:
0.250.2 by Jelmer Vernooij
Make it work for evolution.
394
            # Pointless commit - get the tree sha elsewhere
0.200.864 by Jelmer Vernooij
Cope with the first commit being pointless.
395
            if not rev.parent_ids:
0.252.23 by Jelmer Vernooij
More work on roundtripping support.
396
                root_tree = Tree()
0.200.864 by Jelmer Vernooij
Cope with the first commit being pointless.
397
            else:
398
                base_sha1 = self._lookup_revision_sha1(rev.parent_ids[0])
0.252.37 by Jelmer Vernooij
Factor out some common code for finding refs to send.
399
                root_tree = self[self[base_sha1].tree]
0.252.35 by Jelmer Vernooij
Ignore control files in inventories.
400
            root_ie = tree.inventory.root
0.200.915 by Jelmer Vernooij
Cope with the fact that the old format didn't export file ids.
401
        if roundtrip and self.mapping.BZR_FILE_IDS_FILE is not None:
0.252.49 by Jelmer Vernooij
Avoid trying to set HEAD for remote branches.
402
            b = self._create_fileid_map_blob(tree.inventory)
0.252.23 by Jelmer Vernooij
More work on roundtripping support.
403
            if b is not None:
0.200.1212 by Jelmer Vernooij
Support read locking object stores.
404
                root_tree[self.mapping.BZR_FILE_IDS_FILE] = (
405
                    (stat.S_IFREG | 0644), b.id)
0.252.23 by Jelmer Vernooij
More work on roundtripping support.
406
                yield self.mapping.BZR_FILE_IDS_FILE, b, None
0.252.34 by Jelmer Vernooij
Yield the proper object for the tree root.
407
        yield "", root_tree, root_ie
0.200.1023 by Jelmer Vernooij
Set and verify testament.
408
        if roundtrip:
0.200.1195 by Jelmer Vernooij
Cope with new StrictTestament3 arguments.
409
            if getattr(StrictTestament3, "from_revision_tree", None):
410
                testament3 = StrictTestament3(rev, tree)
411
            else: # bzr < 2.4
412
                testament3 = StrictTestament3(rev, tree.inventory)
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
413
            verifiers = { "testament3-sha1": testament3.as_sha1() }
0.200.1023 by Jelmer Vernooij
Set and verify testament.
414
        else:
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
415
            verifiers = {}
0.252.43 by Jelmer Vernooij
Some refactoring, support proper file ids in revision deltas.
416
        commit_obj = self._reconstruct_commit(rev, root_tree.id,
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
417
            roundtrip=roundtrip, verifiers=verifiers)
0.231.1 by Jelmer Vernooij
Check that regenerated objects have the expected sha1.
418
        try:
0.200.841 by Jelmer Vernooij
Eliminate InventorySHAMap.
419
            foreign_revid, mapping = mapping_registry.parse_revision_id(
420
                rev.revision_id)
0.231.1 by Jelmer Vernooij
Check that regenerated objects have the expected sha1.
421
        except errors.InvalidRevisionId:
422
            pass
423
        else:
0.200.794 by Jelmer Vernooij
Use _check_expected_sha rather than custom checks.
424
            _check_expected_sha(foreign_revid, commit_obj)
0.200.837 by Jelmer Vernooij
Return inventory entries when creating git objects for a revision.
425
        yield None, commit_obj, None
0.200.783 by Jelmer Vernooij
Move object generation into a separate function.
426
0.200.838 by Jelmer Vernooij
Add convenience object for updating the object store.
427
    def _get_updater(self, rev):
0.200.849 by Jelmer Vernooij
Allow cache backends to decide when to add entries rather than adding once per commit.
428
        return self._cache.get_updater(rev)
0.200.838 by Jelmer Vernooij
Add convenience object for updating the object store.
429
0.200.783 by Jelmer Vernooij
Move object generation into a separate function.
430
    def _update_sha_map_revision(self, revid):
431
        rev = self.repository.get_revision(revid)
0.200.852 by Jelmer Vernooij
Cache trees rather than inventories.
432
        tree = self.tree_cache.revision_tree(rev.revision_id)
0.200.838 by Jelmer Vernooij
Add convenience object for updating the object store.
433
        updater = self._get_updater(rev)
0.252.4 by Jelmer Vernooij
More work on roundtripping.
434
        for path, obj, ie in self._revision_to_objects(rev, tree,
435
            roundtrip=True):
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
436
            if isinstance(obj, Commit):
0.200.1195 by Jelmer Vernooij
Cope with new StrictTestament3 arguments.
437
                if getattr(StrictTestament3, "from_revision_tree", None):
438
                    testament3 = StrictTestament3(rev, tree)
439
                else: # bzr < 2.4
440
                    testament3 = StrictTestament3(rev, tree.inventory)
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
441
                ie = { "testament3-sha1": testament3.as_sha1() }
0.200.952 by Jelmer Vernooij
Write git pack files rather than loose objects.
442
            updater.add_object(obj, ie, path)
0.200.838 by Jelmer Vernooij
Add convenience object for updating the object store.
443
        commit_obj = updater.finish()
0.200.781 by Jelmer Vernooij
Return commit id after converting a revision.
444
        return commit_obj.id
0.200.229 by Jelmer Vernooij
More work on converter.
445
0.200.855 by Jelmer Vernooij
_get_ -> _reconstruct_.
446
    def _reconstruct_blobs(self, keys):
0.200.698 by Jelmer Vernooij
Merge fixes for SHA1s of symlinks.
447
        """Return a Git Blob object from a fileid and revision stored in bzr.
448
449
        :param fileid: File id of the text
450
        :param revision: Revision of the text
451
        """
0.250.2 by Jelmer Vernooij
Make it work for evolution.
452
        stream = self.repository.iter_files_bytes(
453
            ((key[0], key[1], key) for key in keys))
0.200.856 by Jelmer Vernooij
Support reconstructing multiple blobs at the same time.
454
        for (fileid, revision, expected_sha), chunks in stream:
0.200.854 by Jelmer Vernooij
_get_blob -> _get_blobs.
455
            blob = Blob()
456
            blob.chunked = chunks
0.200.868 by Jelmer Vernooij
Cope with no-change merges.
457
            if blob.id != expected_sha and blob.data == "":
0.200.854 by Jelmer Vernooij
_get_blob -> _get_blobs.
458
                # Perhaps it's a symlink ?
459
                tree = self.tree_cache.revision_tree(revision)
460
                entry = tree.inventory[fileid]
0.200.868 by Jelmer Vernooij
Cope with no-change merges.
461
                if entry.kind == 'symlink':
462
                    blob = symlink_to_blob(entry)
0.200.854 by Jelmer Vernooij
_get_blob -> _get_blobs.
463
            _check_expected_sha(expected_sha, blob)
464
            yield blob
0.200.229 by Jelmer Vernooij
More work on converter.
465
0.200.855 by Jelmer Vernooij
_get_ -> _reconstruct_.
466
    def _reconstruct_tree(self, fileid, revid, inv, unusual_modes,
467
        expected_sha=None):
0.200.343 by Jelmer Vernooij
Use file ids consistently in map.
468
        """Return a Git Tree object from a file id and a revision stored in bzr.
0.200.249 by Jelmer Vernooij
Implement Tree.
469
0.200.343 by Jelmer Vernooij
Use file ids consistently in map.
470
        :param fileid: fileid in the tree.
0.200.249 by Jelmer Vernooij
Implement Tree.
471
        :param revision: Revision of the tree.
472
        """
0.200.776 by Jelmer Vernooij
Remove unnecessary lookups.
473
        def get_ie_sha1(entry):
474
            if entry.kind == "directory":
0.200.808 by Jelmer Vernooij
Avoid recalculating tree shas we already have.
475
                try:
0.200.859 by Jelmer Vernooij
Trivial cleanups.
476
                    return self._cache.idmap.lookup_tree_id(entry.file_id,
477
                        revid)
0.200.812 by Jelmer Vernooij
Catch KeyError from lookup_tree as well - some caches (such as sqlite) don't store all trees, only some.
478
                except (NotImplementedError, KeyError):
0.200.855 by Jelmer Vernooij
_get_ -> _reconstruct_.
479
                    obj = self._reconstruct_tree(entry.file_id, revid, inv,
0.200.808 by Jelmer Vernooij
Avoid recalculating tree shas we already have.
480
                        unusual_modes)
481
                    if obj is None:
482
                        return None
483
                    else:
484
                        return obj.id
0.200.776 by Jelmer Vernooij
Remove unnecessary lookups.
485
            elif entry.kind in ("file", "symlink"):
0.200.868 by Jelmer Vernooij
Cope with no-change merges.
486
                try:
487
                    return self._cache.idmap.lookup_blob_id(entry.file_id,
488
                        entry.revision)
489
                except KeyError:
490
                    # no-change merge?
491
                    return self._reconstruct_blobs(
492
                        [(entry.file_id, entry.revision, None)]).next().id
0.200.776 by Jelmer Vernooij
Remove unnecessary lookups.
493
            else:
494
                raise AssertionError("unknown entry kind '%s'" % entry.kind)
0.252.30 by Jelmer Vernooij
Support creating dummy files for empty directories.
495
        tree = directory_to_tree(inv[fileid], get_ie_sha1, unusual_modes,
496
            self.mapping.BZR_DUMMY_FILE)
0.200.915 by Jelmer Vernooij
Cope with the fact that the old format didn't export file ids.
497
        if (inv.root.file_id == fileid and
498
            self.mapping.BZR_FILE_IDS_FILE is not None):
0.200.1223 by Jelmer Vernooij
Cope with empty directories.
499
            if tree is None:
500
                tree = Tree()
0.252.49 by Jelmer Vernooij
Avoid trying to set HEAD for remote branches.
501
            b = self._create_fileid_map_blob(inv)
502
            # If this is the root tree, add the file ids
0.200.1212 by Jelmer Vernooij
Support read locking object stores.
503
            tree[self.mapping.BZR_FILE_IDS_FILE] = (
504
                (stat.S_IFREG | 0644), b.id)
0.200.1223 by Jelmer Vernooij
Cope with empty directories.
505
        if tree is not None:
506
            _check_expected_sha(expected_sha, tree)
0.200.249 by Jelmer Vernooij
Implement Tree.
507
        return tree
0.200.229 by Jelmer Vernooij
More work on converter.
508
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
509
    def get_parents(self, sha):
0.200.454 by Jelmer Vernooij
Use ObjectStore.find_missing_objects in server.
510
        """Retrieve the parents of a Git commit by SHA1.
511
512
        :param sha: SHA1 of the commit
513
        :raises: KeyError, NotCommitError
514
        """
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
515
        return self[sha].parents
516
0.200.364 by Jelmer Vernooij
Reimplement dpush, but more efficient and only writing a single pack file rather than one per revision.
517
    def _lookup_revision_sha1(self, revid):
0.200.449 by Jelmer Vernooij
Use BazaarObjectStore to find matching SHA1s for bzr revisions.
518
        """Return the SHA1 matching a Bazaar revision."""
0.200.541 by Jelmer Vernooij
Cope with NULL_REVISION.
519
        if revid == NULL_REVISION:
0.200.891 by Jelmer Vernooij
Use ZERO_SHA constant where possible.
520
            return ZERO_SHA
0.200.364 by Jelmer Vernooij
Reimplement dpush, but more efficient and only writing a single pack file rather than one per revision.
521
        try:
0.200.847 by Jelmer Vernooij
Add BzrGitCache object.
522
            return self._cache.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.
523
        except KeyError:
0.200.682 by Jelmer Vernooij
Avoid doing a full sha map update if we already know the SHA1.
524
            try:
525
                return mapping_registry.parse_revision_id(revid)[0]
526
            except errors.InvalidRevisionId:
0.252.47 by Jelmer Vernooij
Fix handling of HEAD refs.
527
                self.repository.lock_read()
528
                try:
529
                    self._update_sha_map(revid)
530
                finally:
531
                    self.repository.unlock()
0.200.847 by Jelmer Vernooij
Add BzrGitCache object.
532
                return self._cache.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.
533
0.200.310 by Jelmer Vernooij
Fix pull from remote branches.
534
    def get_raw(self, sha):
0.200.454 by Jelmer Vernooij
Use ObjectStore.find_missing_objects in server.
535
        """Get the raw representation of a Git object by SHA1.
536
537
        :param sha: SHA1 of the git object
538
        """
0.200.566 by Jelmer Vernooij
Fix ObjectStore.get_raw() .
539
        obj = self[sha]
540
        return (obj.type, obj.as_raw_string())
0.200.310 by Jelmer Vernooij
Fix pull from remote branches.
541
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
542
    def __contains__(self, sha):
543
        # See if sha is in map
544
        try:
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
545
            for (type, type_data) in self.lookup_git_sha(sha):
546
                if type == "commit":
547
                    if self.repository.has_revision(type_data[0]):
548
                        return True
549
                elif type == "blob":
550
                    if self.repository.texts.has_key(type_data):
551
                        return True
552
                elif type == "tree":
553
                    if self.repository.has_revision(type_data[1]):
554
                        return True
555
                else:
556
                    raise AssertionError("Unknown object type '%s'" % type)
0.200.568 by Jelmer Vernooij
Properly check that matching bzr objects exist.
557
            else:
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
558
                return False
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
559
        except KeyError:
560
            return False
561
0.200.1212 by Jelmer Vernooij
Support read locking object stores.
562
    def lock_read(self):
563
        self._locked = 'r'
564
        self._map_updated = False
565
        self.repository.lock_read()
566
        return LogicalLockResult(self.unlock)
567
568
    def lock_write(self):
569
        self._locked = 'r'
570
        self._map_updated = False
571
        self.repository.lock_write()
572
        return LogicalLockResult(self.unlock)
573
574
    def is_locked(self):
575
        return (self._locked is not None)
576
577
    def unlock(self):
578
        self._locked = None
579
        self._map_updated = False
580
        self.repository.unlock()
581
582
    def lookup_git_shas(self, shas):
0.200.898 by Jelmer Vernooij
Optimize finding of git shas.
583
        ret = {}
584
        for sha in shas:
0.200.969 by Jelmer Vernooij
Use tuples with bzr revid and git sha to avoid lookups.
585
            if sha == ZERO_SHA:
0.200.1169 by Jelmer Vernooij
Fix some sha lookups.
586
                ret[sha] = [("commit", (NULL_REVISION, None, {}))]
0.200.969 by Jelmer Vernooij
Use tuples with bzr revid and git sha to avoid lookups.
587
                continue
0.200.898 by Jelmer Vernooij
Optimize finding of git shas.
588
            try:
0.261.3 by Jelmer Vernooij
Fix more tests.
589
                ret[sha] = list(self._cache.idmap.lookup_git_sha(sha))
0.200.898 by Jelmer Vernooij
Optimize finding of git shas.
590
            except KeyError:
0.200.1212 by Jelmer Vernooij
Support read locking object stores.
591
                # if not, see if there are any unconverted revisions and
592
                # add them to the map, search for sha in map again
593
                self._update_sha_map()
594
                try:
595
                    ret[sha] = list(self._cache.idmap.lookup_git_sha(sha))
596
                except KeyError:
597
                    pass
0.200.898 by Jelmer Vernooij
Optimize finding of git shas.
598
        return ret
599
0.200.1212 by Jelmer Vernooij
Support read locking object stores.
600
    def lookup_git_sha(self, sha):
601
        return self.lookup_git_shas([sha])[sha]
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
602
603
    def __getitem__(self, sha):
0.200.849 by Jelmer Vernooij
Allow cache backends to decide when to add entries rather than adding once per commit.
604
        if self._cache.content_cache is not None:
0.200.840 by Jelmer Vernooij
Support using content cache.
605
            try:
0.200.847 by Jelmer Vernooij
Add BzrGitCache object.
606
                return self._cache.content_cache[sha]
0.200.840 by Jelmer Vernooij
Support using content cache.
607
            except KeyError:
608
                pass
0.200.1169 by Jelmer Vernooij
Fix some sha lookups.
609
        for (kind, type_data) in self.lookup_git_sha(sha):
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
610
            # convert object to git object
0.200.1169 by Jelmer Vernooij
Fix some sha lookups.
611
            if kind == "commit":
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
612
                (revid, tree_sha, verifiers) = type_data
613
                try:
614
                    rev = self.repository.get_revision(revid)
615
                except errors.NoSuchRevision:
0.200.1169 by Jelmer Vernooij
Fix some sha lookups.
616
                    trace.mutter('entry for %s %s in shamap: %r, but not '
617
                                 'found in repository', kind, sha, type_data)
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
618
                    raise KeyError(sha)
0.200.1212 by Jelmer Vernooij
Support read locking object stores.
619
                commit = self._reconstruct_commit(rev, tree_sha,
620
                    roundtrip=True, verifiers=verifiers)
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
621
                _check_expected_sha(sha, commit)
622
                return commit
0.200.1169 by Jelmer Vernooij
Fix some sha lookups.
623
            elif kind == "blob":
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
624
                (fileid, revision) = type_data
0.200.1212 by Jelmer Vernooij
Support read locking object stores.
625
                blobs = self._reconstruct_blobs([(fileid, revision, sha)])
626
                return blobs.next()
0.200.1169 by Jelmer Vernooij
Fix some sha lookups.
627
            elif kind == "tree":
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
628
                (fileid, revid) = type_data
629
                try:
630
                    tree = self.tree_cache.revision_tree(revid)
631
                    rev = self.repository.get_revision(revid)
632
                except errors.NoSuchRevision:
0.200.1169 by Jelmer Vernooij
Fix some sha lookups.
633
                    trace.mutter('entry for %s %s in shamap: %r, but not found in repository', kind, sha, type_data)
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
634
                    raise KeyError(sha)
635
                unusual_modes = extract_unusual_modes(rev)
636
                try:
637
                    return self._reconstruct_tree(fileid, revid,
638
                        tree.inventory, unusual_modes, expected_sha=sha)
639
                except errors.NoSuchRevision:
640
                    raise KeyError(sha)
641
            else:
0.200.1169 by Jelmer Vernooij
Fix some sha lookups.
642
                raise AssertionError("Unknown object type '%s'" % kind)
0.200.228 by Jelmer Vernooij
Split out map.
643
        else:
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
644
            raise KeyError(sha)
0.200.782 by Jelmer Vernooij
Add custom generate_pack_contents implementation.
645
0.252.37 by Jelmer Vernooij
Factor out some common code for finding refs to send.
646
    def generate_lossy_pack_contents(self, have, want, progress=None,
647
            get_tagged=None):
648
        return self.generate_pack_contents(have, want, progress, get_tagged,
649
            lossy=True)
650
0.200.899 by Jelmer Vernooij
Add tests for find_missing_bzr_revids.
651
    def generate_pack_contents(self, have, want, progress=None,
0.252.37 by Jelmer Vernooij
Factor out some common code for finding refs to send.
652
            get_tagged=None, lossy=False):
0.200.782 by Jelmer Vernooij
Add custom generate_pack_contents implementation.
653
        """Iterate over the contents of a pack file.
654
655
        :param have: List of SHA1s of objects that should not be sent
656
        :param want: List of SHA1s of objects that should be sent
657
        """
0.200.787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
658
        processed = set()
0.200.898 by Jelmer Vernooij
Optimize finding of git shas.
659
        ret = self.lookup_git_shas(have + want)
0.200.787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
660
        for commit_sha in have:
661
            try:
0.200.1180 by Jelmer Vernooij
Some dpush fixes.
662
                for (type, type_data) in ret[commit_sha]:
663
                    assert type == "commit"
664
                    processed.add(type_data[0])
0.200.787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
665
            except KeyError:
666
                pass
667
        pending = set()
668
        for commit_sha in want:
669
            if commit_sha in have:
670
                continue
0.200.898 by Jelmer Vernooij
Optimize finding of git shas.
671
            try:
0.200.1180 by Jelmer Vernooij
Some dpush fixes.
672
                for (type, type_data) in ret[commit_sha]:
673
                    assert type == "commit"
674
                    pending.add(type_data[0])
0.200.898 by Jelmer Vernooij
Optimize finding of git shas.
675
            except KeyError:
676
                pass
0.200.899 by Jelmer Vernooij
Add tests for find_missing_bzr_revids.
677
0.200.1053 by Jelmer Vernooij
Fix find_missing_bzr_revids.
678
        graph = self.repository.get_graph()
679
        todo = _find_missing_bzr_revids(graph, pending, processed)
0.200.787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
680
        trace.mutter('sending revisions %r', todo)
681
        ret = []
682
        pb = ui.ui_factory.nested_progress_bar()
683
        try:
684
            for i, revid in enumerate(todo):
685
                pb.update("generating git objects", i, len(todo))
0.200.1059 by Jelmer Vernooij
Fix graph tests.
686
                try:
687
                    rev = self.repository.get_revision(revid)
688
                except errors.NoSuchRevision:
689
                    continue
0.200.852 by Jelmer Vernooij
Cache trees rather than inventories.
690
                tree = self.tree_cache.revision_tree(revid)
0.252.37 by Jelmer Vernooij
Factor out some common code for finding refs to send.
691
                for path, obj, ie in self._revision_to_objects(rev, tree,
692
                    roundtrip=not lossy):
0.200.787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
693
                    ret.append((obj, path))
694
        finally:
695
            pb.finished()
696
        return ret
0.251.1 by Jelmer Vernooij
Implement ObjectStore.add_{thin_,}pack.
697
698
    def add_thin_pack(self):
699
        import tempfile
700
        import os
701
        fd, path = tempfile.mkstemp(suffix=".pack")
702
        f = os.fdopen(fd, 'wb')
703
        def commit():
704
            from dulwich.pack import PackData, Pack
705
            from bzrlib.plugins.git.fetch import import_git_objects
706
            os.fsync(fd)
707
            f.close()
708
            if os.path.getsize(path) == 0:
709
                return
710
            pd = PackData(path)
711
            pd.create_index_v2(path[:-5]+".idx", self.object_store.get_raw)
712
713
            p = Pack(path[:-5])
714
            self.repository.lock_write()
715
            try:
716
                self.repository.start_write_group()
717
                try:
718
                    import_git_objects(self.repository, self.mapping, 
719
                        p.iterobjects(get_raw=self.get_raw),
720
                        self.object_store)
721
                except:
722
                    self.repository.abort_write_group()
723
                    raise
724
                else:
725
                    self.repository.commit_write_group()
726
            finally:
727
                self.repository.unlock()
728
        return f, commit
729
730
    # The pack isn't kept around anyway, so no point 
731
    # in treating full packs different from thin packs
732
    add_pack = add_thin_pack