~wgrant/bzr-git/dulwich-0.9.6

1613 by Jelmer Vernooij
Handle encoding better in working tree iter changes.
1
# Copyright (C) 2009-2012 Jelmer Vernooij <jelmer@samba.org>
2
# Copyright (C) 2012 Canonical Ltd
228 by Jelmer Vernooij
Split out map.
3
#
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
18
"""Map from Git sha's to Bazaar objects."""
19
1594 by Jelmer Vernooij
Use absolute_import everywhere.
20
from __future__ import absolute_import
21
260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
22
from dulwich.objects import (
23
    Blob,
1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
24
    Commit,
864 by Jelmer Vernooij
Cope with the first commit being pointless.
25
    Tree,
586 by Jelmer Vernooij
Fix issues pointed out by pyflakes.
26
    sha_to_hex,
1153 by Jelmer Vernooij
Import ZERO_SHA from dulwich.objects.
27
    ZERO_SHA,
260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
28
    )
437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
29
from dulwich.object_store import (
457 by Jelmer Vernooij
Use BaseObjectStore.
30
    BaseObjectStore,
437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
31
    )
249 by Jelmer Vernooij
Implement Tree.
32
260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
33
from bzrlib import (
324.1.1 by Jelmer Vernooij
Check that regenerated objects have the expected sha1.
34
    errors,
789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
35
    lru_cache,
478 by Jelmer Vernooij
Cope with disappeared revisions.
36
    trace,
260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
37
    ui,
773 by Jelmer Vernooij
Implement inventory_to_objects
38
    urlutils,
260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
39
    )
1212 by Jelmer Vernooij
Support read locking object stores.
40
from bzrlib.lock import LogicalLockResult
541 by Jelmer Vernooij
Cope with NULL_REVISION.
41
from bzrlib.revision import (
42
    NULL_REVISION,
43
    )
1023 by Jelmer Vernooij
Set and verify testament.
44
from bzrlib.testament import(
45
    StrictTestament3,
46
    )
228 by Jelmer Vernooij
Split out map.
47
1292 by Jelmer Vernooij
Fix repeeling objects when determining what to send.
48
from bzrlib.plugins.git.cache import (
49
    from_repository as cache_from_repository,
50
    )
229 by Jelmer Vernooij
More work on converter.
51
from bzrlib.plugins.git.mapping import (
463 by Jelmer Vernooij
Support remote dpush (except for references).
52
    default_mapping,
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.
53
    directory_to_tree,
548 by Jelmer Vernooij
Extract unusual file modes from revision when reconstructing Trees.
54
    extract_unusual_modes,
324.1.1 by Jelmer Vernooij
Check that regenerated objects have the expected sha1.
55
    mapping_registry,
795 by Jelmer Vernooij
simplify sha extraction for blobs, process multiple blobs at once.
56
    symlink_to_blob,
229 by Jelmer Vernooij
More work on converter.
57
    )
1292 by Jelmer Vernooij
Fix repeeling objects when determining what to send.
58
from bzrlib.plugins.git.unpeel_map import (
59
    UnpeelMap,
231 by Jelmer Vernooij
Partially fix pull.
60
    )
61
878 by Jelmer Vernooij
Fix determining of unusual file modes.
62
import posixpath
900.1.23 by Jelmer Vernooij
More work on roundtripping support.
63
import stat
878 by Jelmer Vernooij
Fix determining of unusual file modes.
64
228 by Jelmer Vernooij
Split out map.
65
452 by Jelmer Vernooij
Rename converter -> object_store, provide utility function for getting ObjectStore's.
66
def get_object_store(repo, mapping=None):
67
    git = getattr(repo, "_git", None)
68
    if git is not None:
1303 by Jelmer Vernooij
Fix locking.
69
        git.object_store.unlock = lambda: None
70
        git.object_store.lock_read = lambda: LogicalLockResult(lambda: None)
71
        git.object_store.lock_write = lambda: LogicalLockResult(lambda: None)
452 by Jelmer Vernooij
Rename converter -> object_store, provide utility function for getting ObjectStore's.
72
        return git.object_store
73
    return BazaarObjectStore(repo, mapping)
74
75
852 by Jelmer Vernooij
Cache trees rather than inventories.
76
MAX_TREE_CACHE_SIZE = 50 * 1024 * 1024
77
78
79
class LRUTreeCache(object):
789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
80
81
    def __init__(self, repository):
852 by Jelmer Vernooij
Cache trees rather than inventories.
82
        def approx_tree_size(tree):
1569.1.1 by Jelmer Vernooij
Use root_inventory.
83
            # Very rough estimate, 250 per inventory entry
1569.1.5 by Jelmer Vernooij
Cope with root_inventory and inventory.
84
            try:
85
                inv = tree.root_inventory
86
            except AttributeError:
87
                inv = tree.inventory
88
            return len(inv) * 250
789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
89
        self.repository = repository
852 by Jelmer Vernooij
Cache trees rather than inventories.
90
        self._cache = lru_cache.LRUSizeCache(max_size=MAX_TREE_CACHE_SIZE,
91
            after_cleanup_size=None, compute_size=approx_tree_size)
789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
92
963 by Jelmer Vernooij
Add some tests for LRUTreeCache.
93
    def revision_tree(self, revid):
789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
94
        try:
989 by Jelmer Vernooij
Add asserts.
95
            tree = self._cache[revid]
789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
96
        except KeyError:
852 by Jelmer Vernooij
Cache trees rather than inventories.
97
            tree = self.repository.revision_tree(revid)
98
            self.add(tree)
989 by Jelmer Vernooij
Add asserts.
99
        return tree
852 by Jelmer Vernooij
Cache trees rather than inventories.
100
101
    def iter_revision_trees(self, revids):
989 by Jelmer Vernooij
Add asserts.
102
        trees = {}
103
        todo = []
104
        for revid in revids:
105
            try:
106
                tree = self._cache[revid]
107
            except KeyError:
108
                todo.append(revid)
109
            else:
110
                assert tree.get_revision_id() == revid
111
                trees[revid] = tree
112
        for tree in self.repository.revision_trees(todo):
852 by Jelmer Vernooij
Cache trees rather than inventories.
113
            trees[tree.get_revision_id()] = tree
114
            self.add(tree)
115
        return (trees[r] for r in revids)
116
117
    def revision_trees(self, revids):
118
        return list(self.iter_revision_trees(revids))
119
120
    def add(self, tree):
1418.1.1 by Martin
Avoid the deprecated LRUSizeCache.add method
121
        self._cache[tree.get_revision_id()] = tree
789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
122
123
1053 by Jelmer Vernooij
Fix find_missing_bzr_revids.
124
def _find_missing_bzr_revids(graph, want, have):
900.1.5 by Jelmer Vernooij
enable 'bzr push'.
125
    """Find the revisions that have to be pushed.
126
127
    :param get_parent_map: Function that returns the parents for a sequence
128
        of revisions.
129
    :param want: Revisions the target wants
130
    :param have: Revisions the target already has
131
    :return: Set of revisions to fetch
132
    """
1292 by Jelmer Vernooij
Fix repeeling objects when determining what to send.
133
    handled = set(have)
899 by Jelmer Vernooij
Add tests for find_missing_bzr_revids.
134
    todo = set()
1053 by Jelmer Vernooij
Fix find_missing_bzr_revids.
135
    for rev in want:
1292 by Jelmer Vernooij
Fix repeeling objects when determining what to send.
136
        extra_todo = graph.find_unique_ancestors(rev, handled)
137
        todo.update(extra_todo)
138
        handled.update(extra_todo)
899 by Jelmer Vernooij
Add tests for find_missing_bzr_revids.
139
    if NULL_REVISION in todo:
140
        todo.remove(NULL_REVISION)
141
    return todo
142
143
793 by Jelmer Vernooij
Make _check_expected_sha a global fn.
144
def _check_expected_sha(expected_sha, object):
797 by Jelmer Vernooij
Add docstring, fix formatting.
145
    """Check whether an object matches an expected SHA.
146
147
    :param expected_sha: None or expected SHA as either binary or as hex digest
148
    :param object: Object to verify
149
    """
793 by Jelmer Vernooij
Make _check_expected_sha a global fn.
150
    if expected_sha is None:
151
        return
152
    if len(expected_sha) == 40:
153
        if expected_sha != object.sha().hexdigest():
797 by Jelmer Vernooij
Add docstring, fix formatting.
154
            raise AssertionError("Invalid sha for %r: %s" % (object,
155
                expected_sha))
793 by Jelmer Vernooij
Make _check_expected_sha a global fn.
156
    elif len(expected_sha) == 20:
157
        if expected_sha != object.sha().digest():
797 by Jelmer Vernooij
Add docstring, fix formatting.
158
            raise AssertionError("Invalid sha for %r: %s" % (object,
159
                sha_to_hex(expected_sha)))
793 by Jelmer Vernooij
Make _check_expected_sha a global fn.
160
    else:
797 by Jelmer Vernooij
Add docstring, fix formatting.
161
        raise AssertionError("Unknown length %d for %r" % (len(expected_sha),
162
            expected_sha))
793 by Jelmer Vernooij
Make _check_expected_sha a global fn.
163
164
931 by Jelmer Vernooij
Update docstring, deal with kind changes appropriately in _tree_to_objects
165
def _tree_to_objects(tree, parent_trees, idmap, unusual_modes,
166
                     dummy_file_name=None):
798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
167
    """Iterate over the objects that were introduced in a revision.
168
841 by Jelmer Vernooij
Eliminate InventorySHAMap.
169
    :param idmap: id map
931 by Jelmer Vernooij
Update docstring, deal with kind changes appropriately in _tree_to_objects
170
    :param parent_trees: Parent revision trees
171
    :param unusual_modes: Unusual file modes dictionary
900.1.30 by Jelmer Vernooij
Support creating dummy files for empty directories.
172
    :param dummy_file_name: File name to use for dummy files
173
        in empty directories. None to skip empty directories
837 by Jelmer Vernooij
Return inventory entries when creating git objects for a revision.
174
    :return: Yields (path, object, ie) entries
798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
175
    """
176
    new_trees = {}
177
    new_blobs = []
178
    shamap = {}
859.1.1 by Jelmer Vernooij
Use iter_changes() rather than iterating over all contents of an inventory.
179
    try:
180
        base_tree = parent_trees[0]
181
        other_parent_trees = parent_trees[1:]
182
    except IndexError:
183
        base_tree = tree._repository.revision_tree(NULL_REVISION)
184
        other_parent_trees = []
1569.1.1 by Jelmer Vernooij
Use root_inventory.
185
    def find_unchanged_parent_ie(file_id, kind, other, parent_trees):
868 by Jelmer Vernooij
Cope with no-change merges.
186
        for ptree in parent_trees:
187
            try:
1569.1.1 by Jelmer Vernooij
Use root_inventory.
188
                pkind = ptree.kind(file_id)
868 by Jelmer Vernooij
Cope with no-change merges.
189
            except errors.NoSuchId:
190
                pass
191
            else:
1569.1.1 by Jelmer Vernooij
Use root_inventory.
192
                if kind == "file":
193
                    if (pkind == "file" and 
194
                        ptree.get_file_sha1(file_id) == other):
1575 by Jelmer Vernooij
Fix name error.
195
                        return (file_id, ptree.get_file_revision(file_id))
1569.1.1 by Jelmer Vernooij
Use root_inventory.
196
                if kind == "symlink":
197
                    if (pkind == "symlink" and
198
                        ptree.get_symlink_target(file_id) == other):
1575 by Jelmer Vernooij
Fix name error.
199
                        return (file_id, ptree.get_file_revision(file_id))
868 by Jelmer Vernooij
Cope with no-change merges.
200
        raise KeyError
965 by Jelmer Vernooij
Formatting fixes.
201
931 by Jelmer Vernooij
Update docstring, deal with kind changes appropriately in _tree_to_objects
202
    # Find all the changed blobs
859.1.1 by Jelmer Vernooij
Use iter_changes() rather than iterating over all contents of an inventory.
203
    for (file_id, path, changed_content, versioned, parent, name, kind,
204
         executable) in tree.iter_changes(base_tree):
205
        if kind[1] == "file":
206
            if changed_content:
868 by Jelmer Vernooij
Cope with no-change merges.
207
                try:
1575 by Jelmer Vernooij
Fix name error.
208
                    (pfile_id, prevision) = find_unchanged_parent_ie(file_id, kind[1], tree.get_file_sha1(file_id), other_parent_trees)
868 by Jelmer Vernooij
Cope with no-change merges.
209
                except KeyError:
210
                    pass
211
                else:
900.1.40 by Jelmer Vernooij
Checks for roundtripping.
212
                    try:
1569.1.1 by Jelmer Vernooij
Use root_inventory.
213
                        shamap[file_id] = idmap.lookup_blob_id(
1575 by Jelmer Vernooij
Fix name error.
214
                            pfile_id, prevision)
900.1.40 by Jelmer Vernooij
Checks for roundtripping.
215
                    except KeyError:
216
                        # no-change merge ?
217
                        blob = Blob()
1569.1.1 by Jelmer Vernooij
Use root_inventory.
218
                        blob.data = tree.get_file_text(file_id)
219
                        shamap[file_id] = blob.id
859.1.1 by Jelmer Vernooij
Use iter_changes() rather than iterating over all contents of an inventory.
220
            if not file_id in shamap:
1569.1.1 by Jelmer Vernooij
Use root_inventory.
221
                new_blobs.append((path[1], file_id))
878 by Jelmer Vernooij
Fix determining of unusual file modes.
222
            new_trees[posixpath.dirname(path[1])] = parent[1]
859.1.1 by Jelmer Vernooij
Use iter_changes() rather than iterating over all contents of an inventory.
223
        elif kind[1] == "symlink":
224
            if changed_content:
1569.1.1 by Jelmer Vernooij
Use root_inventory.
225
                target = tree.get_symlink_target(file_id)
226
                blob = symlink_to_blob(target)
868 by Jelmer Vernooij
Cope with no-change merges.
227
                shamap[file_id] = blob.id
228
                try:
1569.1.1 by Jelmer Vernooij
Use root_inventory.
229
                    find_unchanged_parent_ie(file_id, kind[1], target, other_parent_trees)
868 by Jelmer Vernooij
Cope with no-change merges.
230
                except KeyError:
1569.1.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
231
                    yield path[1], blob, (file_id, tree.get_file_revision(file_id, path[1]))
878 by Jelmer Vernooij
Fix determining of unusual file modes.
232
            new_trees[posixpath.dirname(path[1])] = parent[1]
859.1.3 by Jelmer Vernooij
Simplify..
233
        elif kind[1] not in (None, "directory"):
859.1.1 by Jelmer Vernooij
Use iter_changes() rather than iterating over all contents of an inventory.
234
            raise AssertionError(kind[1])
1017 by Jelmer Vernooij
Cope with root moving.
235
        if (path[0] not in (None, "") and
1375 by Jelmer Vernooij
Avoid using deprecated Inventory.__contains.
236
            tree.has_id(parent[0]) and
1569.1.3 by Jelmer Vernooij
Avoid inventories in a few more places.
237
            tree.kind(parent[0]) == "directory"):
931 by Jelmer Vernooij
Update docstring, deal with kind changes appropriately in _tree_to_objects
238
            # Removal
878 by Jelmer Vernooij
Fix determining of unusual file modes.
239
            new_trees[posixpath.dirname(path[0])] = parent[0]
1212 by Jelmer Vernooij
Support read locking object stores.
240
931 by Jelmer Vernooij
Update docstring, deal with kind changes appropriately in _tree_to_objects
241
    # Fetch contents of the blobs that were changed
1569.1.1 by Jelmer Vernooij
Use root_inventory.
242
    for (path, file_id), chunks in tree.iter_files_bytes(
243
        [(file_id, (path, file_id)) for (path, file_id) in new_blobs]):
798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
244
        obj = Blob()
851 by Jelmer Vernooij
Use blob.chunked.
245
        obj.chunked = chunks
1569.1.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
246
        yield path, obj, (file_id, tree.get_file_revision(file_id, path))
1569.1.1 by Jelmer Vernooij
Use root_inventory.
247
        shamap[file_id] = obj.id
798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
248
879 by Jelmer Vernooij
Fix unusual modes.
249
    for path in unusual_modes:
250
        parent_path = posixpath.dirname(path)
1577 by Jelmer Vernooij
Add assertion.
251
        file_id = tree.path2id(parent_path)
252
        assert file_id is not None, "Unable to find file id for %r" % parent_path
253
        new_trees[parent_path] = file_id
989 by Jelmer Vernooij
Add asserts.
254
798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
255
    trees = {}
256
    while new_trees:
257
        items = new_trees.items()
258
        new_trees = {}
259
        for path, file_id in items:
1569.1.5 by Jelmer Vernooij
Cope with root_inventory and inventory.
260
            if path != "":
798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
261
                parent_path = urlutils.dirname(path)
1569.1.5 by Jelmer Vernooij
Cope with root_inventory and inventory.
262
                parent_id = tree.path2id(parent_path)
798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
263
                new_trees[parent_path] = parent_id
264
            trees[path] = file_id
265
808 by Jelmer Vernooij
Avoid recalculating tree shas we already have.
266
    def ie_to_hexsha(ie):
267
        try:
268
            return shamap[ie.file_id]
269
        except KeyError:
884 by Jelmer Vernooij
Cope with -0000 as timezone in Git commits.
270
            # FIXME: Should be the same as in parent
859.1.1 by Jelmer Vernooij
Use iter_changes() rather than iterating over all contents of an inventory.
271
            if ie.kind in ("file", "symlink"):
868 by Jelmer Vernooij
Cope with no-change merges.
272
                try:
273
                    return idmap.lookup_blob_id(ie.file_id, ie.revision)
274
                except KeyError:
275
                    # no-change merge ?
276
                    blob = Blob()
277
                    blob.data = tree.get_file_text(ie.file_id)
278
                    return blob.id
859.1.1 by Jelmer Vernooij
Use iter_changes() rather than iterating over all contents of an inventory.
279
            elif ie.kind == "directory":
280
                # Not all cache backends store the tree information, 
281
                # calculate again from scratch
1569.1.4 by Jelmer Vernooij
Pass children list to directory_to_tree .
282
                ret = directory_to_tree(ie.children, ie_to_hexsha,
1573 by Jelmer Vernooij
Fix regression in allowing empty directory check.
283
                    unusual_modes, dummy_file_name, ie.parent_id is None)
859.1.1 by Jelmer Vernooij
Use iter_changes() rather than iterating over all contents of an inventory.
284
                if ret is None:
285
                    return ret
286
                return ret.id
287
            else:
288
                raise AssertionError
808 by Jelmer Vernooij
Avoid recalculating tree shas we already have.
289
1569.1.5 by Jelmer Vernooij
Cope with root_inventory and inventory.
290
    try:
291
        inv = tree.root_inventory
292
    except AttributeError:
293
        inv = tree.inventory
294
798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
295
    for path in sorted(trees.keys(), reverse=True):
1569.1.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
296
        file_id = trees[path]
1569.1.4 by Jelmer Vernooij
Pass children list to directory_to_tree .
297
        assert tree.kind(file_id) == 'directory'
1569.1.5 by Jelmer Vernooij
Cope with root_inventory and inventory.
298
        ie = inv[file_id]
1569.1.4 by Jelmer Vernooij
Pass children list to directory_to_tree .
299
        obj = directory_to_tree(ie.children, ie_to_hexsha, unusual_modes,
300
            dummy_file_name, path == "")
798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
301
        if obj is not None:
1569.1.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
302
            yield path, obj, (file_id, )
303
            shamap[file_id] = obj.id
798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
304
305
1290 by Jelmer Vernooij
Avoid storing all objects to push in memory.
306
class PackTupleIterable(object):
307
308
    def __init__(self, store):
309
        self.store = store
1432 by Jelmer Vernooij
Make sure object store is locked/unlocked.
310
        self.store.lock_read()
1290 by Jelmer Vernooij
Avoid storing all objects to push in memory.
311
        self.objects = {}
312
1432 by Jelmer Vernooij
Make sure object store is locked/unlocked.
313
    def __del__(self):
314
        self.store.unlock()
315
1290 by Jelmer Vernooij
Avoid storing all objects to push in memory.
316
    def add(self, sha, path):
317
        self.objects[sha] = path
318
319
    def __len__(self):
320
        return len(self.objects)
321
322
    def __iter__(self):
323
        return ((self.store[object_id], path) for (object_id, path) in
324
                self.objects.iteritems())
325
326
457 by Jelmer Vernooij
Use BaseObjectStore.
327
class BazaarObjectStore(BaseObjectStore):
320 by Jelmer Vernooij
Handle lightweight checkouts.
328
    """A Git-style object store backed onto a Bazaar repository."""
228 by Jelmer Vernooij
Split out map.
329
330
    def __init__(self, repository, mapping=None):
331
        self.repository = repository
1212 by Jelmer Vernooij
Support read locking object stores.
332
        self._map_updated = False
333
        self._locked = None
228 by Jelmer Vernooij
Split out map.
334
        if mapping is None:
463 by Jelmer Vernooij
Support remote dpush (except for references).
335
            self.mapping = default_mapping
228 by Jelmer Vernooij
Split out map.
336
        else:
337
            self.mapping = mapping
847 by Jelmer Vernooij
Add BzrGitCache object.
338
        self._cache = cache_from_repository(repository)
1291 by Jelmer Vernooij
add hook for updating to local git cache.
339
        self._content_cache_types = ("tree",)
847 by Jelmer Vernooij
Add BzrGitCache object.
340
        self.start_write_group = self._cache.idmap.start_write_group
341
        self.abort_write_group = self._cache.idmap.abort_write_group
342
        self.commit_write_group = self._cache.idmap.commit_write_group
852 by Jelmer Vernooij
Cache trees rather than inventories.
343
        self.tree_cache = LRUTreeCache(self.repository)
1292 by Jelmer Vernooij
Fix repeeling objects when determining what to send.
344
        self.unpeel_map = UnpeelMap.from_repository(self.repository)
228 by Jelmer Vernooij
Split out map.
345
1319 by Jelmer Vernooij
Only update git cache during post-commit if parents are already in the cache.
346
    def _missing_revisions(self, revisions):
347
        return self._cache.idmap.missing_revisions(revisions)
348
437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
349
    def _update_sha_map(self, stop_revision=None):
1212 by Jelmer Vernooij
Support read locking object stores.
350
        if not self.is_locked():
351
            raise AssertionError()
352
        if self._map_updated:
353
            return
1264 by Jelmer Vernooij
Fix updating cache for single revision - don't consider it an update of the full cache.
354
        if (stop_revision is not None and
1319 by Jelmer Vernooij
Only update git cache during post-commit if parents are already in the cache.
355
            not self._missing_revisions([stop_revision])):
1264 by Jelmer Vernooij
Fix updating cache for single revision - don't consider it an update of the full cache.
356
            return
683 by Jelmer Vernooij
Lazier checking of which revisions need to be fetched.
357
        graph = self.repository.get_graph()
437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
358
        if stop_revision is None:
1301 by Jelmer Vernooij
Avoid expensive get_parent_map call.
359
            all_revids = self.repository.all_revision_ids()
1319 by Jelmer Vernooij
Only update git cache during post-commit if parents are already in the cache.
360
            missing_revids = self._missing_revisions(all_revids)
437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
361
        else:
683 by Jelmer Vernooij
Lazier checking of which revisions need to be fetched.
362
            heads = set([stop_revision])
1319 by Jelmer Vernooij
Only update git cache during post-commit if parents are already in the cache.
363
            missing_revids = self._missing_revisions(heads)
1301 by Jelmer Vernooij
Avoid expensive get_parent_map call.
364
            while heads:
365
                parents = graph.get_parent_map(heads)
366
                todo = set()
367
                for p in parents.values():
368
                    todo.update([x for x in p if x not in missing_revids])
1319 by Jelmer Vernooij
Only update git cache during post-commit if parents are already in the cache.
369
                heads = self._missing_revisions(todo)
1301 by Jelmer Vernooij
Avoid expensive get_parent_map call.
370
                missing_revids.update(heads)
694 by Jelmer Vernooij
Avoid processing NULL_REVISION.
371
        if NULL_REVISION in missing_revids:
372
            missing_revids.remove(NULL_REVISION)
677.1.16 by Jelmer Vernooij
Add optimization preventing recursive index updating.
373
        missing_revids = self.repository.has_revisions(missing_revids)
374
        if not missing_revids:
1264 by Jelmer Vernooij
Fix updating cache for single revision - don't consider it an update of the full cache.
375
            if stop_revision is None:
376
                self._map_updated = True
677.1.16 by Jelmer Vernooij
Add optimization preventing recursive index updating.
377
            return
735 by Jelmer Vernooij
Use convenience functions for start/stop write groups.
378
        self.start_write_group()
231 by Jelmer Vernooij
Partially fix pull.
379
        try:
677.1.4 by Jelmer Vernooij
Merge trunk.
380
            pb = ui.ui_factory.nested_progress_bar()
381
            try:
382
                for i, revid in enumerate(graph.iter_topo_order(missing_revids)):
677.1.16 by Jelmer Vernooij
Add optimization preventing recursive index updating.
383
                    trace.mutter('processing %r', revid)
677.1.4 by Jelmer Vernooij
Merge trunk.
384
                    pb.update("updating git map", i, len(missing_revids))
385
                    self._update_sha_map_revision(revid)
386
            finally:
387
                pb.finished()
1264 by Jelmer Vernooij
Fix updating cache for single revision - don't consider it an update of the full cache.
388
            if stop_revision is None:
389
                self._map_updated = True
735 by Jelmer Vernooij
Use convenience functions for start/stop write groups.
390
        except:
391
            self.abort_write_group()
392
            raise
393
        else:
394
            self.commit_write_group()
229 by Jelmer Vernooij
More work on converter.
395
422 by Jelmer Vernooij
'bzr git-object' without arguments now prints the available git objects.
396
    def __iter__(self):
397
        self._update_sha_map()
847 by Jelmer Vernooij
Add BzrGitCache object.
398
        return iter(self._cache.idmap.sha1s())
422 by Jelmer Vernooij
'bzr git-object' without arguments now prints the available git objects.
399
1509 by Jelmer Vernooij
Properly raise exception when pulling from git into bzr without experimental mappings.
400
    def _reconstruct_commit(self, rev, tree_sha, lossy, verifiers):
1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
401
        """Reconstruct a Commit object.
402
403
        :param rev: Revision object
404
        :param tree_sha: SHA1 of the root tree object
1509 by Jelmer Vernooij
Properly raise exception when pulling from git into bzr without experimental mappings.
405
        :param lossy: Whether or not to roundtrip bzr metadata
1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
406
        :param verifiers: Verifiers for the commits
407
        :return: Commit object
408
        """
527.1.7 by Jelmer Vernooij
Cope with ghosts a bit better.
409
        def parent_lookup(revid):
410
            try:
411
                return self._lookup_revision_sha1(revid)
412
            except errors.NoSuchRevision:
413
                return None
900.1.4 by Jelmer Vernooij
More work on roundtripping.
414
        return self.mapping.export_commit(rev, tree_sha, parent_lookup,
1509 by Jelmer Vernooij
Properly raise exception when pulling from git into bzr without experimental mappings.
415
            lossy, verifiers)
527.1.7 by Jelmer Vernooij
Cope with ghosts a bit better.
416
1386.1.2 by Jelmer Vernooij
use tree objects rather than inventories
417
    def _create_fileid_map_blob(self, tree):
900.1.49 by Jelmer Vernooij
Avoid trying to set HEAD for remote branches.
418
        # FIXME: This can probably be a lot more efficient, 
419
        # not all files necessarily have to be processed.
420
        file_ids = {}
1386.1.2 by Jelmer Vernooij
use tree objects rather than inventories
421
        for (path, ie) in tree.inventory.iter_entries():
900.1.49 by Jelmer Vernooij
Avoid trying to set HEAD for remote branches.
422
            if self.mapping.generate_file_id(path) != ie.file_id:
423
                file_ids[path] = ie.file_id
424
        return self.mapping.export_fileid_map(file_ids)
425
1509 by Jelmer Vernooij
Properly raise exception when pulling from git into bzr without experimental mappings.
426
    def _revision_to_objects(self, rev, tree, lossy):
900.1.23 by Jelmer Vernooij
More work on roundtripping support.
427
        """Convert a revision to a set of git objects.
428
429
        :param rev: Bazaar revision object
430
        :param tree: Bazaar revision tree
1509 by Jelmer Vernooij
Properly raise exception when pulling from git into bzr without experimental mappings.
431
        :param lossy: Whether to not roundtrip all Bazaar revision data
900.1.23 by Jelmer Vernooij
More work on roundtripping support.
432
        """
548 by Jelmer Vernooij
Extract unusual file modes from revision when reconstructing Trees.
433
        unusual_modes = extract_unusual_modes(rev)
789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
434
        present_parents = self.repository.has_revisions(rev.parent_ids)
852 by Jelmer Vernooij
Cache trees rather than inventories.
435
        parent_trees = self.tree_cache.revision_trees(
797 by Jelmer Vernooij
Add docstring, fix formatting.
436
            [p for p in rev.parent_ids if p in present_parents])
900.1.23 by Jelmer Vernooij
More work on roundtripping support.
437
        root_tree = None
1569.1.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
438
        for path, obj, bzr_key_data in _tree_to_objects(tree, parent_trees,
900.1.30 by Jelmer Vernooij
Support creating dummy files for empty directories.
439
                self._cache.idmap, unusual_modes, self.mapping.BZR_DUMMY_FILE):
773 by Jelmer Vernooij
Implement inventory_to_objects
440
            if path == "":
900.1.23 by Jelmer Vernooij
More work on roundtripping support.
441
                root_tree = obj
1569.1.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
442
                root_key_data = bzr_key_data
900.1.34 by Jelmer Vernooij
Yield the proper object for the tree root.
443
                # Don't yield just yet
444
            else:
1569.1.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
445
                yield path, obj, bzr_key_data
900.1.23 by Jelmer Vernooij
More work on roundtripping support.
446
        if root_tree is None:
859.1.2 by Jelmer Vernooij
Make it work for evolution.
447
            # Pointless commit - get the tree sha elsewhere
864 by Jelmer Vernooij
Cope with the first commit being pointless.
448
            if not rev.parent_ids:
900.1.23 by Jelmer Vernooij
More work on roundtripping support.
449
                root_tree = Tree()
864 by Jelmer Vernooij
Cope with the first commit being pointless.
450
            else:
451
                base_sha1 = self._lookup_revision_sha1(rev.parent_ids[0])
900.1.37 by Jelmer Vernooij
Factor out some common code for finding refs to send.
452
                root_tree = self[self[base_sha1].tree]
1569.1.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
453
            root_key_data = (tree.get_root_id(), )
1509 by Jelmer Vernooij
Properly raise exception when pulling from git into bzr without experimental mappings.
454
        if not lossy and self.mapping.BZR_FILE_IDS_FILE is not None:
1386.1.2 by Jelmer Vernooij
use tree objects rather than inventories
455
            b = self._create_fileid_map_blob(tree)
900.1.23 by Jelmer Vernooij
More work on roundtripping support.
456
            if b is not None:
1212 by Jelmer Vernooij
Support read locking object stores.
457
                root_tree[self.mapping.BZR_FILE_IDS_FILE] = (
458
                    (stat.S_IFREG | 0644), b.id)
900.1.23 by Jelmer Vernooij
More work on roundtripping support.
459
                yield self.mapping.BZR_FILE_IDS_FILE, b, None
1569.1.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
460
        yield "", root_tree, root_key_data
1509 by Jelmer Vernooij
Properly raise exception when pulling from git into bzr without experimental mappings.
461
        if not lossy:
1559 by Jelmer Vernooij
Fix compatibility with bzr 2.5.
462
            testament3 = StrictTestament3(rev, tree)
1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
463
            verifiers = { "testament3-sha1": testament3.as_sha1() }
1023 by Jelmer Vernooij
Set and verify testament.
464
        else:
1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
465
            verifiers = {}
900.1.43 by Jelmer Vernooij
Some refactoring, support proper file ids in revision deltas.
466
        commit_obj = self._reconstruct_commit(rev, root_tree.id,
1509 by Jelmer Vernooij
Properly raise exception when pulling from git into bzr without experimental mappings.
467
            lossy=lossy, verifiers=verifiers)
324.1.1 by Jelmer Vernooij
Check that regenerated objects have the expected sha1.
468
        try:
841 by Jelmer Vernooij
Eliminate InventorySHAMap.
469
            foreign_revid, mapping = mapping_registry.parse_revision_id(
470
                rev.revision_id)
324.1.1 by Jelmer Vernooij
Check that regenerated objects have the expected sha1.
471
        except errors.InvalidRevisionId:
472
            pass
473
        else:
794 by Jelmer Vernooij
Use _check_expected_sha rather than custom checks.
474
            _check_expected_sha(foreign_revid, commit_obj)
837 by Jelmer Vernooij
Return inventory entries when creating git objects for a revision.
475
        yield None, commit_obj, None
783 by Jelmer Vernooij
Move object generation into a separate function.
476
838 by Jelmer Vernooij
Add convenience object for updating the object store.
477
    def _get_updater(self, rev):
849 by Jelmer Vernooij
Allow cache backends to decide when to add entries rather than adding once per commit.
478
        return self._cache.get_updater(rev)
838 by Jelmer Vernooij
Add convenience object for updating the object store.
479
783 by Jelmer Vernooij
Move object generation into a separate function.
480
    def _update_sha_map_revision(self, revid):
481
        rev = self.repository.get_revision(revid)
852 by Jelmer Vernooij
Cache trees rather than inventories.
482
        tree = self.tree_cache.revision_tree(rev.revision_id)
838 by Jelmer Vernooij
Add convenience object for updating the object store.
483
        updater = self._get_updater(rev)
1510 by Jelmer Vernooij
Fix tests.
484
        # FIXME JRV 2011-12-15: Shouldn't we try both values for lossy ?
485
        for path, obj, ie in self._revision_to_objects(rev, tree, lossy=(not self.mapping.roundtripping)):
1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
486
            if isinstance(obj, Commit):
1559 by Jelmer Vernooij
Fix compatibility with bzr 2.5.
487
                testament3 = StrictTestament3(rev, tree)
1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
488
                ie = { "testament3-sha1": testament3.as_sha1() }
952 by Jelmer Vernooij
Write git pack files rather than loose objects.
489
            updater.add_object(obj, ie, path)
838 by Jelmer Vernooij
Add convenience object for updating the object store.
490
        commit_obj = updater.finish()
781 by Jelmer Vernooij
Return commit id after converting a revision.
491
        return commit_obj.id
229 by Jelmer Vernooij
More work on converter.
492
855 by Jelmer Vernooij
_get_ -> _reconstruct_.
493
    def _reconstruct_blobs(self, keys):
698 by Jelmer Vernooij
Merge fixes for SHA1s of symlinks.
494
        """Return a Git Blob object from a fileid and revision stored in bzr.
495
496
        :param fileid: File id of the text
497
        :param revision: Revision of the text
498
        """
859.1.2 by Jelmer Vernooij
Make it work for evolution.
499
        stream = self.repository.iter_files_bytes(
500
            ((key[0], key[1], key) for key in keys))
856 by Jelmer Vernooij
Support reconstructing multiple blobs at the same time.
501
        for (fileid, revision, expected_sha), chunks in stream:
854 by Jelmer Vernooij
_get_blob -> _get_blobs.
502
            blob = Blob()
503
            blob.chunked = chunks
868 by Jelmer Vernooij
Cope with no-change merges.
504
            if blob.id != expected_sha and blob.data == "":
854 by Jelmer Vernooij
_get_blob -> _get_blobs.
505
                # Perhaps it's a symlink ?
506
                tree = self.tree_cache.revision_tree(revision)
1586 by Jelmer Vernooij
Fixes duplicate tag warnings in 'git-remote-bzr' helper.
507
                if tree.kind(fileid) == 'symlink':
508
                    blob = symlink_to_blob(tree.get_symlink_target(fileid))
854 by Jelmer Vernooij
_get_blob -> _get_blobs.
509
            _check_expected_sha(expected_sha, blob)
510
            yield blob
229 by Jelmer Vernooij
More work on converter.
511
1386.1.2 by Jelmer Vernooij
use tree objects rather than inventories
512
    def _reconstruct_tree(self, fileid, revid, bzr_tree, unusual_modes,
855 by Jelmer Vernooij
_get_ -> _reconstruct_.
513
        expected_sha=None):
343 by Jelmer Vernooij
Use file ids consistently in map.
514
        """Return a Git Tree object from a file id and a revision stored in bzr.
249 by Jelmer Vernooij
Implement Tree.
515
343 by Jelmer Vernooij
Use file ids consistently in map.
516
        :param fileid: fileid in the tree.
249 by Jelmer Vernooij
Implement Tree.
517
        :param revision: Revision of the tree.
518
        """
776 by Jelmer Vernooij
Remove unnecessary lookups.
519
        def get_ie_sha1(entry):
520
            if entry.kind == "directory":
808 by Jelmer Vernooij
Avoid recalculating tree shas we already have.
521
                try:
859 by Jelmer Vernooij
Trivial cleanups.
522
                    return self._cache.idmap.lookup_tree_id(entry.file_id,
523
                        revid)
812 by Jelmer Vernooij
Catch KeyError from lookup_tree as well - some caches (such as sqlite) don't store all trees, only some.
524
                except (NotImplementedError, KeyError):
1386.1.2 by Jelmer Vernooij
use tree objects rather than inventories
525
                    obj = self._reconstruct_tree(entry.file_id, revid, bzr_tree,
808 by Jelmer Vernooij
Avoid recalculating tree shas we already have.
526
                        unusual_modes)
527
                    if obj is None:
528
                        return None
529
                    else:
530
                        return obj.id
776 by Jelmer Vernooij
Remove unnecessary lookups.
531
            elif entry.kind in ("file", "symlink"):
868 by Jelmer Vernooij
Cope with no-change merges.
532
                try:
533
                    return self._cache.idmap.lookup_blob_id(entry.file_id,
534
                        entry.revision)
535
                except KeyError:
536
                    # no-change merge?
537
                    return self._reconstruct_blobs(
538
                        [(entry.file_id, entry.revision, None)]).next().id
1551 by Jelmer Vernooij
Support nested trees in reconstruction code.
539
            elif entry.kind == 'tree-reference':
540
                # FIXME: Make sure the file id is the root id
541
                return self._lookup_revision_sha1(entry.reference_revision)
776 by Jelmer Vernooij
Remove unnecessary lookups.
542
            else:
543
                raise AssertionError("unknown entry kind '%s'" % entry.kind)
1569.1.5 by Jelmer Vernooij
Cope with root_inventory and inventory.
544
        try:
545
            inv = bzr_tree.root_inventory
546
        except AttributeError:
547
            inv = bzr_tree.inventory
548
        tree = directory_to_tree(inv[fileid].children,
1569.1.4 by Jelmer Vernooij
Pass children list to directory_to_tree .
549
                get_ie_sha1, unusual_modes, self.mapping.BZR_DUMMY_FILE,
550
                bzr_tree.get_root_id() == fileid)
1386.1.2 by Jelmer Vernooij
use tree objects rather than inventories
551
        if (bzr_tree.get_root_id() == fileid and
915 by Jelmer Vernooij
Cope with the fact that the old format didn't export file ids.
552
            self.mapping.BZR_FILE_IDS_FILE is not None):
1223 by Jelmer Vernooij
Cope with empty directories.
553
            if tree is None:
554
                tree = Tree()
1386.1.2 by Jelmer Vernooij
use tree objects rather than inventories
555
            b = self._create_fileid_map_blob(bzr_tree)
900.1.49 by Jelmer Vernooij
Avoid trying to set HEAD for remote branches.
556
            # If this is the root tree, add the file ids
1212 by Jelmer Vernooij
Support read locking object stores.
557
            tree[self.mapping.BZR_FILE_IDS_FILE] = (
558
                (stat.S_IFREG | 0644), b.id)
1223 by Jelmer Vernooij
Cope with empty directories.
559
        if tree is not None:
560
            _check_expected_sha(expected_sha, tree)
249 by Jelmer Vernooij
Implement Tree.
561
        return tree
229 by Jelmer Vernooij
More work on converter.
562
437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
563
    def get_parents(self, sha):
454 by Jelmer Vernooij
Use ObjectStore.find_missing_objects in server.
564
        """Retrieve the parents of a Git commit by SHA1.
565
566
        :param sha: SHA1 of the commit
567
        :raises: KeyError, NotCommitError
568
        """
437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
569
        return self[sha].parents
570
364 by Jelmer Vernooij
Reimplement dpush, but more efficient and only writing a single pack file rather than one per revision.
571
    def _lookup_revision_sha1(self, revid):
449 by Jelmer Vernooij
Use BazaarObjectStore to find matching SHA1s for bzr revisions.
572
        """Return the SHA1 matching a Bazaar revision."""
541 by Jelmer Vernooij
Cope with NULL_REVISION.
573
        if revid == NULL_REVISION:
891 by Jelmer Vernooij
Use ZERO_SHA constant where possible.
574
            return ZERO_SHA
364 by Jelmer Vernooij
Reimplement dpush, but more efficient and only writing a single pack file rather than one per revision.
575
        try:
847 by Jelmer Vernooij
Add BzrGitCache object.
576
            return self._cache.idmap.lookup_commit(revid)
364 by Jelmer Vernooij
Reimplement dpush, but more efficient and only writing a single pack file rather than one per revision.
577
        except KeyError:
682 by Jelmer Vernooij
Avoid doing a full sha map update if we already know the SHA1.
578
            try:
579
                return mapping_registry.parse_revision_id(revid)[0]
580
            except errors.InvalidRevisionId:
1264 by Jelmer Vernooij
Fix updating cache for single revision - don't consider it an update of the full cache.
581
                self._update_sha_map(revid)
847 by Jelmer Vernooij
Add BzrGitCache object.
582
                return self._cache.idmap.lookup_commit(revid)
364 by Jelmer Vernooij
Reimplement dpush, but more efficient and only writing a single pack file rather than one per revision.
583
310 by Jelmer Vernooij
Fix pull from remote branches.
584
    def get_raw(self, sha):
454 by Jelmer Vernooij
Use ObjectStore.find_missing_objects in server.
585
        """Get the raw representation of a Git object by SHA1.
586
587
        :param sha: SHA1 of the git object
588
        """
1622 by William Grant
BazaarObjectStore.get_raw now copes with non-hex-encoded SHA-1s, as some ref delta resolution in dulwich apparently requires.
589
        if len(sha) == 20:
590
            sha = sha_to_hex(sha)
566 by Jelmer Vernooij
Fix ObjectStore.get_raw() .
591
        obj = self[sha]
592
        return (obj.type, obj.as_raw_string())
310 by Jelmer Vernooij
Fix pull from remote branches.
593
437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
594
    def __contains__(self, sha):
595
        # See if sha is in map
596
        try:
1162.1.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
597
            for (type, type_data) in self.lookup_git_sha(sha):
598
                if type == "commit":
599
                    if self.repository.has_revision(type_data[0]):
600
                        return True
601
                elif type == "blob":
602
                    if self.repository.texts.has_key(type_data):
603
                        return True
604
                elif type == "tree":
605
                    if self.repository.has_revision(type_data[1]):
606
                        return True
607
                else:
608
                    raise AssertionError("Unknown object type '%s'" % type)
568 by Jelmer Vernooij
Properly check that matching bzr objects exist.
609
            else:
1162.1.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
610
                return False
437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
611
        except KeyError:
612
            return False
613
1212 by Jelmer Vernooij
Support read locking object stores.
614
    def lock_read(self):
615
        self._locked = 'r'
616
        self._map_updated = False
617
        self.repository.lock_read()
618
        return LogicalLockResult(self.unlock)
619
620
    def lock_write(self):
621
        self._locked = 'r'
622
        self._map_updated = False
623
        self.repository.lock_write()
624
        return LogicalLockResult(self.unlock)
625
626
    def is_locked(self):
627
        return (self._locked is not None)
628
629
    def unlock(self):
630
        self._locked = None
631
        self._map_updated = False
632
        self.repository.unlock()
633
634
    def lookup_git_shas(self, shas):
898 by Jelmer Vernooij
Optimize finding of git shas.
635
        ret = {}
636
        for sha in shas:
969 by Jelmer Vernooij
Use tuples with bzr revid and git sha to avoid lookups.
637
            if sha == ZERO_SHA:
1169 by Jelmer Vernooij
Fix some sha lookups.
638
                ret[sha] = [("commit", (NULL_REVISION, None, {}))]
969 by Jelmer Vernooij
Use tuples with bzr revid and git sha to avoid lookups.
639
                continue
898 by Jelmer Vernooij
Optimize finding of git shas.
640
            try:
1162.1.3 by Jelmer Vernooij
Fix more tests.
641
                ret[sha] = list(self._cache.idmap.lookup_git_sha(sha))
898 by Jelmer Vernooij
Optimize finding of git shas.
642
            except KeyError:
1212 by Jelmer Vernooij
Support read locking object stores.
643
                # if not, see if there are any unconverted revisions and
644
                # add them to the map, search for sha in map again
645
                self._update_sha_map()
646
                try:
647
                    ret[sha] = list(self._cache.idmap.lookup_git_sha(sha))
648
                except KeyError:
649
                    pass
898 by Jelmer Vernooij
Optimize finding of git shas.
650
        return ret
651
1212 by Jelmer Vernooij
Support read locking object stores.
652
    def lookup_git_sha(self, sha):
653
        return self.lookup_git_shas([sha])[sha]
437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
654
655
    def __getitem__(self, sha):
849 by Jelmer Vernooij
Allow cache backends to decide when to add entries rather than adding once per commit.
656
        if self._cache.content_cache is not None:
840 by Jelmer Vernooij
Support using content cache.
657
            try:
847 by Jelmer Vernooij
Add BzrGitCache object.
658
                return self._cache.content_cache[sha]
840 by Jelmer Vernooij
Support using content cache.
659
            except KeyError:
660
                pass
1169 by Jelmer Vernooij
Fix some sha lookups.
661
        for (kind, type_data) in self.lookup_git_sha(sha):
1162.1.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
662
            # convert object to git object
1169 by Jelmer Vernooij
Fix some sha lookups.
663
            if kind == "commit":
1162.1.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
664
                (revid, tree_sha, verifiers) = type_data
665
                try:
666
                    rev = self.repository.get_revision(revid)
667
                except errors.NoSuchRevision:
1341 by Jelmer Vernooij
Add check that callers don't try to look up NULL_REVISION.
668
                    if revid == NULL_REVISION:
669
                        raise AssertionError(
670
                            "should not try to look up NULL_REVISION")
1169 by Jelmer Vernooij
Fix some sha lookups.
671
                    trace.mutter('entry for %s %s in shamap: %r, but not '
672
                                 'found in repository', kind, sha, type_data)
1162.1.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
673
                    raise KeyError(sha)
1510 by Jelmer Vernooij
Fix tests.
674
                # FIXME: the type data should say whether conversion was lossless
1212 by Jelmer Vernooij
Support read locking object stores.
675
                commit = self._reconstruct_commit(rev, tree_sha,
1510 by Jelmer Vernooij
Fix tests.
676
                    lossy=(not self.mapping.roundtripping), verifiers=verifiers)
1162.1.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
677
                _check_expected_sha(sha, commit)
678
                return commit
1169 by Jelmer Vernooij
Fix some sha lookups.
679
            elif kind == "blob":
1162.1.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
680
                (fileid, revision) = type_data
1212 by Jelmer Vernooij
Support read locking object stores.
681
                blobs = self._reconstruct_blobs([(fileid, revision, sha)])
682
                return blobs.next()
1169 by Jelmer Vernooij
Fix some sha lookups.
683
            elif kind == "tree":
1162.1.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
684
                (fileid, revid) = type_data
685
                try:
686
                    tree = self.tree_cache.revision_tree(revid)
687
                    rev = self.repository.get_revision(revid)
688
                except errors.NoSuchRevision:
1319 by Jelmer Vernooij
Only update git cache during post-commit if parents are already in the cache.
689
                    trace.mutter('entry for %s %s in shamap: %r, but not found in '
690
                        'repository', kind, sha, type_data)
1162.1.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
691
                    raise KeyError(sha)
692
                unusual_modes = extract_unusual_modes(rev)
693
                try:
694
                    return self._reconstruct_tree(fileid, revid,
1386.1.2 by Jelmer Vernooij
use tree objects rather than inventories
695
                        tree, unusual_modes, expected_sha=sha)
1162.1.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
696
                except errors.NoSuchRevision:
697
                    raise KeyError(sha)
698
            else:
1169 by Jelmer Vernooij
Fix some sha lookups.
699
                raise AssertionError("Unknown object type '%s'" % kind)
228 by Jelmer Vernooij
Split out map.
700
        else:
1162.1.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
701
            raise KeyError(sha)
782 by Jelmer Vernooij
Add custom generate_pack_contents implementation.
702
900.1.37 by Jelmer Vernooij
Factor out some common code for finding refs to send.
703
    def generate_lossy_pack_contents(self, have, want, progress=None,
704
            get_tagged=None):
705
        return self.generate_pack_contents(have, want, progress, get_tagged,
706
            lossy=True)
707
899 by Jelmer Vernooij
Add tests for find_missing_bzr_revids.
708
    def generate_pack_contents(self, have, want, progress=None,
900.1.37 by Jelmer Vernooij
Factor out some common code for finding refs to send.
709
            get_tagged=None, lossy=False):
782 by Jelmer Vernooij
Add custom generate_pack_contents implementation.
710
        """Iterate over the contents of a pack file.
711
712
        :param have: List of SHA1s of objects that should not be sent
713
        :param want: List of SHA1s of objects that should be sent
714
        """
787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
715
        processed = set()
898 by Jelmer Vernooij
Optimize finding of git shas.
716
        ret = self.lookup_git_shas(have + want)
787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
717
        for commit_sha in have:
1292 by Jelmer Vernooij
Fix repeeling objects when determining what to send.
718
            commit_sha = self.unpeel_map.peel_tag(commit_sha, commit_sha)
787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
719
            try:
1180 by Jelmer Vernooij
Some dpush fixes.
720
                for (type, type_data) in ret[commit_sha]:
721
                    assert type == "commit"
722
                    processed.add(type_data[0])
787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
723
            except KeyError:
1292 by Jelmer Vernooij
Fix repeeling objects when determining what to send.
724
                trace.mutter("unable to find remote ref %s", commit_sha)
787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
725
        pending = set()
726
        for commit_sha in want:
727
            if commit_sha in have:
728
                continue
898 by Jelmer Vernooij
Optimize finding of git shas.
729
            try:
1180 by Jelmer Vernooij
Some dpush fixes.
730
                for (type, type_data) in ret[commit_sha]:
731
                    assert type == "commit"
732
                    pending.add(type_data[0])
898 by Jelmer Vernooij
Optimize finding of git shas.
733
            except KeyError:
734
                pass
899 by Jelmer Vernooij
Add tests for find_missing_bzr_revids.
735
1053 by Jelmer Vernooij
Fix find_missing_bzr_revids.
736
        graph = self.repository.get_graph()
737
        todo = _find_missing_bzr_revids(graph, pending, processed)
1290 by Jelmer Vernooij
Avoid storing all objects to push in memory.
738
        ret = PackTupleIterable(self)
787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
739
        pb = ui.ui_factory.nested_progress_bar()
740
        try:
741
            for i, revid in enumerate(todo):
742
                pb.update("generating git objects", i, len(todo))
1059 by Jelmer Vernooij
Fix graph tests.
743
                try:
744
                    rev = self.repository.get_revision(revid)
745
                except errors.NoSuchRevision:
746
                    continue
852 by Jelmer Vernooij
Cache trees rather than inventories.
747
                tree = self.tree_cache.revision_tree(revid)
1509 by Jelmer Vernooij
Properly raise exception when pulling from git into bzr without experimental mappings.
748
                for path, obj, ie in self._revision_to_objects(rev, tree, lossy=lossy):
1290 by Jelmer Vernooij
Avoid storing all objects to push in memory.
749
                    ret.add(obj.id, path)
1298 by Jelmer Vernooij
Fix compatibility with newer versions of dulwich.
750
            return ret
787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
751
        finally:
752
            pb.finished()
865.1.1 by Jelmer Vernooij
Implement ObjectStore.add_{thin_,}pack.
753
754
    def add_thin_pack(self):
755
        import tempfile
756
        import os
757
        fd, path = tempfile.mkstemp(suffix=".pack")
758
        f = os.fdopen(fd, 'wb')
759
        def commit():
760
            from dulwich.pack import PackData, Pack
761
            from bzrlib.plugins.git.fetch import import_git_objects
762
            os.fsync(fd)
763
            f.close()
764
            if os.path.getsize(path) == 0:
765
                return
766
            pd = PackData(path)
767
            pd.create_index_v2(path[:-5]+".idx", self.object_store.get_raw)
768
769
            p = Pack(path[:-5])
770
            self.repository.lock_write()
771
            try:
772
                self.repository.start_write_group()
773
                try:
1289 by Jelmer Vernooij
Switch to dulwich 0.8.0.
774
                    import_git_objects(self.repository, self.mapping,
865.1.1 by Jelmer Vernooij
Implement ObjectStore.add_{thin_,}pack.
775
                        p.iterobjects(get_raw=self.get_raw),
776
                        self.object_store)
777
                except:
778
                    self.repository.abort_write_group()
779
                    raise
780
                else:
781
                    self.repository.commit_write_group()
782
            finally:
783
                self.repository.unlock()
784
        return f, commit
785
786
    # The pack isn't kept around anyway, so no point 
787
    # in treating full packs different from thin packs
788
    add_pack = add_thin_pack