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