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