/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.200.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
0.200.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
0.200.1594 by Jelmer Vernooij
Use absolute_import everywhere.
20
from __future__ import absolute_import
21
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
22
from dulwich.objects import (
23
    Blob,
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
24
    Commit,
0.200.864 by Jelmer Vernooij
Cope with the first commit being pointless.
25
    Tree,
0.200.586 by Jelmer Vernooij
Fix issues pointed out by pyflakes.
26
    sha_to_hex,
0.200.1153 by Jelmer Vernooij
Import ZERO_SHA from dulwich.objects.
27
    ZERO_SHA,
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
28
    )
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
29
from dulwich.object_store import (
0.200.457 by Jelmer Vernooij
Use BaseObjectStore.
30
    BaseObjectStore,
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
31
    )
0.200.249 by Jelmer Vernooij
Implement Tree.
32
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
33
from ... import (
0.231.1 by Jelmer Vernooij
Check that regenerated objects have the expected sha1.
34
    errors,
0.200.789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
35
    lru_cache,
0.200.478 by Jelmer Vernooij
Cope with disappeared revisions.
36
    trace,
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
37
    ui,
0.200.773 by Jelmer Vernooij
Implement inventory_to_objects
38
    urlutils,
0.200.260 by Jelmer Vernooij
Add DictGitShaMap, useful for testing.
39
    )
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
40
from ...lock import LogicalLockResult
41
from ...revision import (
0.200.541 by Jelmer Vernooij
Cope with NULL_REVISION.
42
    NULL_REVISION,
43
    )
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
44
from ...testament import(
0.200.1023 by Jelmer Vernooij
Set and verify testament.
45
    StrictTestament3,
46
    )
0.200.228 by Jelmer Vernooij
Split out map.
47
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
48
from .cache import (
0.200.1292 by Jelmer Vernooij
Fix repeeling objects when determining what to send.
49
    from_repository as cache_from_repository,
50
    )
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
51
from .mapping import (
0.200.463 by Jelmer Vernooij
Support remote dpush (except for references).
52
    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.
53
    directory_to_tree,
0.200.548 by Jelmer Vernooij
Extract unusual file modes from revision when reconstructing Trees.
54
    extract_unusual_modes,
0.231.1 by Jelmer Vernooij
Check that regenerated objects have the expected sha1.
55
    mapping_registry,
0.200.795 by Jelmer Vernooij
simplify sha extraction for blobs, process multiple blobs at once.
56
    symlink_to_blob,
0.200.229 by Jelmer Vernooij
More work on converter.
57
    )
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
58
from .unpeel_map import (
0.200.1292 by Jelmer Vernooij
Fix repeeling objects when determining what to send.
59
    UnpeelMap,
0.200.231 by Jelmer Vernooij
Partially fix pull.
60
    )
61
0.200.878 by Jelmer Vernooij
Fix determining of unusual file modes.
62
import posixpath
0.252.23 by Jelmer Vernooij
More work on roundtripping support.
63
import stat
0.200.878 by Jelmer Vernooij
Fix determining of unusual file modes.
64
0.200.228 by Jelmer Vernooij
Split out map.
65
0.200.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:
0.200.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)
0.200.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
0.200.852 by Jelmer Vernooij
Cache trees rather than inventories.
76
MAX_TREE_CACHE_SIZE = 50 * 1024 * 1024
77
78
79
class LRUTreeCache(object):
0.200.789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
80
81
    def __init__(self, repository):
0.200.852 by Jelmer Vernooij
Cache trees rather than inventories.
82
        def approx_tree_size(tree):
0.275.1 by Jelmer Vernooij
Use root_inventory.
83
            # Very rough estimate, 250 per inventory entry
0.275.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
0.200.789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
89
        self.repository = repository
0.200.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)
0.200.789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
92
0.200.963 by Jelmer Vernooij
Add some tests for LRUTreeCache.
93
    def revision_tree(self, revid):
0.200.789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
94
        try:
0.200.989 by Jelmer Vernooij
Add asserts.
95
            tree = self._cache[revid]
0.200.789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
96
        except KeyError:
0.200.852 by Jelmer Vernooij
Cache trees rather than inventories.
97
            tree = self.repository.revision_tree(revid)
98
            self.add(tree)
0.200.989 by Jelmer Vernooij
Add asserts.
99
        return tree
0.200.852 by Jelmer Vernooij
Cache trees rather than inventories.
100
101
    def iter_revision_trees(self, revids):
0.200.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):
0.200.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):
0.270.1 by Martin
Avoid the deprecated LRUSizeCache.add method
121
        self._cache[tree.get_revision_id()] = tree
0.200.789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
122
123
0.200.1053 by Jelmer Vernooij
Fix find_missing_bzr_revids.
124
def _find_missing_bzr_revids(graph, want, have):
0.252.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
    """
0.200.1292 by Jelmer Vernooij
Fix repeeling objects when determining what to send.
133
    handled = set(have)
0.200.899 by Jelmer Vernooij
Add tests for find_missing_bzr_revids.
134
    todo = set()
0.200.1053 by Jelmer Vernooij
Fix find_missing_bzr_revids.
135
    for rev in want:
0.200.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)
0.200.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
0.200.793 by Jelmer Vernooij
Make _check_expected_sha a global fn.
144
def _check_expected_sha(expected_sha, object):
0.200.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
    """
0.200.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():
0.200.797 by Jelmer Vernooij
Add docstring, fix formatting.
154
            raise AssertionError("Invalid sha for %r: %s" % (object,
155
                expected_sha))
0.200.793 by Jelmer Vernooij
Make _check_expected_sha a global fn.
156
    elif len(expected_sha) == 20:
157
        if expected_sha != object.sha().digest():
0.200.797 by Jelmer Vernooij
Add docstring, fix formatting.
158
            raise AssertionError("Invalid sha for %r: %s" % (object,
159
                sha_to_hex(expected_sha)))
0.200.793 by Jelmer Vernooij
Make _check_expected_sha a global fn.
160
    else:
0.200.797 by Jelmer Vernooij
Add docstring, fix formatting.
161
        raise AssertionError("Unknown length %d for %r" % (len(expected_sha),
162
            expected_sha))
0.200.793 by Jelmer Vernooij
Make _check_expected_sha a global fn.
163
164
0.200.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):
0.200.798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
167
    """Iterate over the objects that were introduced in a revision.
168
0.200.841 by Jelmer Vernooij
Eliminate InventorySHAMap.
169
    :param idmap: id map
0.200.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
0.252.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
0.200.837 by Jelmer Vernooij
Return inventory entries when creating git objects for a revision.
174
    :return: Yields (path, object, ie) entries
0.200.798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
175
    """
0.282.1 by William Grant
Rework _tree_to_objects to work out parents by ID, not path. Fixes weirdness with various directory renames.
176
    dirty_dirs = set()
0.200.798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
177
    new_blobs = []
178
    shamap = {}
0.250.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 = []
0.275.1 by Jelmer Vernooij
Use root_inventory.
185
    def find_unchanged_parent_ie(file_id, kind, other, parent_trees):
0.200.868 by Jelmer Vernooij
Cope with no-change merges.
186
        for ptree in parent_trees:
187
            try:
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
188
                ppath = ptree.id2path(file_id)
0.200.868 by Jelmer Vernooij
Cope with no-change merges.
189
            except errors.NoSuchId:
190
                pass
191
            else:
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
192
                pkind = ptree.kind(ppath, file_id)
0.275.1 by Jelmer Vernooij
Use root_inventory.
193
                if kind == "file":
0.200.1636 by Jelmer Vernooij
Some formatting fixes.
194
                    if (pkind == "file" and
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
195
                        ptree.get_file_sha1(ppath, file_id) == other):
196
                        return (file_id, ptree.get_file_revision(ppath, file_id))
0.275.1 by Jelmer Vernooij
Use root_inventory.
197
                if kind == "symlink":
198
                    if (pkind == "symlink" and
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
199
                        ptree.get_symlink_target(ppath, file_id) == other):
200
                        return (file_id, ptree.get_file_revision(ppath, file_id))
0.200.868 by Jelmer Vernooij
Cope with no-change merges.
201
        raise KeyError
0.200.965 by Jelmer Vernooij
Formatting fixes.
202
0.200.931 by Jelmer Vernooij
Update docstring, deal with kind changes appropriately in _tree_to_objects
203
    # Find all the changed blobs
0.250.1 by Jelmer Vernooij
Use iter_changes() rather than iterating over all contents of an inventory.
204
    for (file_id, path, changed_content, versioned, parent, name, kind,
205
         executable) in tree.iter_changes(base_tree):
206
        if kind[1] == "file":
207
            if changed_content:
0.200.868 by Jelmer Vernooij
Cope with no-change merges.
208
                try:
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
209
                    (pfile_id, prevision) = find_unchanged_parent_ie(file_id, kind[1], tree.get_file_sha1(path[1], file_id), other_parent_trees)
0.200.868 by Jelmer Vernooij
Cope with no-change merges.
210
                except KeyError:
211
                    pass
212
                else:
0.252.40 by Jelmer Vernooij
Checks for roundtripping.
213
                    try:
0.275.1 by Jelmer Vernooij
Use root_inventory.
214
                        shamap[file_id] = idmap.lookup_blob_id(
0.200.1575 by Jelmer Vernooij
Fix name error.
215
                            pfile_id, prevision)
0.252.40 by Jelmer Vernooij
Checks for roundtripping.
216
                    except KeyError:
217
                        # no-change merge ?
218
                        blob = Blob()
0.275.1 by Jelmer Vernooij
Use root_inventory.
219
                        blob.data = tree.get_file_text(file_id)
220
                        shamap[file_id] = blob.id
0.250.1 by Jelmer Vernooij
Use iter_changes() rather than iterating over all contents of an inventory.
221
            if not file_id in shamap:
0.275.1 by Jelmer Vernooij
Use root_inventory.
222
                new_blobs.append((path[1], file_id))
0.250.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:
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
225
                target = tree.get_symlink_target(path[1], file_id)
0.275.1 by Jelmer Vernooij
Use root_inventory.
226
                blob = symlink_to_blob(target)
0.200.868 by Jelmer Vernooij
Cope with no-change merges.
227
                shamap[file_id] = blob.id
228
                try:
0.275.1 by Jelmer Vernooij
Use root_inventory.
229
                    find_unchanged_parent_ie(file_id, kind[1], target, other_parent_trees)
0.200.868 by Jelmer Vernooij
Cope with no-change merges.
230
                except KeyError:
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
231
                    yield path[1], blob, (file_id, tree.get_file_revision(path[1], file_id))
0.250.3 by Jelmer Vernooij
Simplify..
232
        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.
233
            raise AssertionError(kind[1])
0.282.2 by William Grant
Always dirty both parents, fixing weird directory rename cases.
234
        for p in parent:
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
235
            if p and tree.has_id(p) and tree.kind(tree.id2path(p)) == "directory":
0.282.2 by William Grant
Always dirty both parents, fixing weird directory rename cases.
236
                dirty_dirs.add(p)
0.200.1212 by Jelmer Vernooij
Support read locking object stores.
237
0.200.931 by Jelmer Vernooij
Update docstring, deal with kind changes appropriately in _tree_to_objects
238
    # Fetch contents of the blobs that were changed
0.275.1 by Jelmer Vernooij
Use root_inventory.
239
    for (path, file_id), chunks in tree.iter_files_bytes(
240
        [(file_id, (path, file_id)) for (path, file_id) in new_blobs]):
0.200.798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
241
        obj = Blob()
0.200.851 by Jelmer Vernooij
Use blob.chunked.
242
        obj.chunked = chunks
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
243
        yield path, obj, (file_id, tree.get_file_revision(path, file_id))
0.275.1 by Jelmer Vernooij
Use root_inventory.
244
        shamap[file_id] = obj.id
0.200.798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
245
0.200.879 by Jelmer Vernooij
Fix unusual modes.
246
    for path in unusual_modes:
247
        parent_path = posixpath.dirname(path)
0.200.1577 by Jelmer Vernooij
Add assertion.
248
        file_id = tree.path2id(parent_path)
249
        assert file_id is not None, "Unable to find file id for %r" % parent_path
0.282.1 by William Grant
Rework _tree_to_objects to work out parents by ID, not path. Fixes weirdness with various directory renames.
250
        dirty_dirs.add(file_id)
251
252
    try:
253
        inv = tree.root_inventory
254
    except AttributeError:
255
        inv = tree.inventory
0.200.989 by Jelmer Vernooij
Add asserts.
256
0.200.798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
257
    trees = {}
0.282.1 by William Grant
Rework _tree_to_objects to work out parents by ID, not path. Fixes weirdness with various directory renames.
258
    while dirty_dirs:
259
        new_dirs = set()
260
        for file_id in dirty_dirs:
261
            if file_id is None or not inv.has_id(file_id):
262
                continue
263
            trees[inv.id2path(file_id)] = file_id
264
            ie = inv[file_id]
265
            if ie.parent_id is not None:
266
                new_dirs.add(ie.parent_id)
267
        dirty_dirs = new_dirs
0.200.798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
268
0.200.808 by Jelmer Vernooij
Avoid recalculating tree shas we already have.
269
    def ie_to_hexsha(ie):
270
        try:
271
            return shamap[ie.file_id]
272
        except KeyError:
0.200.884 by Jelmer Vernooij
Cope with -0000 as timezone in Git commits.
273
            # 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.
274
            if ie.kind in ("file", "symlink"):
0.200.868 by Jelmer Vernooij
Cope with no-change merges.
275
                try:
276
                    return idmap.lookup_blob_id(ie.file_id, ie.revision)
277
                except KeyError:
278
                    # no-change merge ?
279
                    blob = Blob()
0.200.1725 by Jelmer Vernooij
Use path in argument to get_file_text.
280
                    path = tree.id2path(ie.file_id)
281
                    blob.data = tree.get_file_text(path, ie.file_id)
0.200.868 by Jelmer Vernooij
Cope with no-change merges.
282
                    return blob.id
0.250.1 by Jelmer Vernooij
Use iter_changes() rather than iterating over all contents of an inventory.
283
            elif ie.kind == "directory":
0.200.1636 by Jelmer Vernooij
Some formatting fixes.
284
                # Not all cache backends store the tree information,
0.250.1 by Jelmer Vernooij
Use iter_changes() rather than iterating over all contents of an inventory.
285
                # calculate again from scratch
0.275.4 by Jelmer Vernooij
Pass children list to directory_to_tree .
286
                ret = directory_to_tree(ie.children, ie_to_hexsha,
0.200.1573 by Jelmer Vernooij
Fix regression in allowing empty directory check.
287
                    unusual_modes, dummy_file_name, ie.parent_id is None)
0.250.1 by Jelmer Vernooij
Use iter_changes() rather than iterating over all contents of an inventory.
288
                if ret is None:
289
                    return ret
290
                return ret.id
291
            else:
292
                raise AssertionError
0.200.808 by Jelmer Vernooij
Avoid recalculating tree shas we already have.
293
0.200.798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
294
    for path in sorted(trees.keys(), reverse=True):
0.275.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
295
        file_id = trees[path]
0.285.1 by Jelmer Vernooij
Swap arguments for tree methods.
296
        assert tree.kind(path, file_id) == 'directory'
0.275.5 by Jelmer Vernooij
Cope with root_inventory and inventory.
297
        ie = inv[file_id]
0.275.4 by Jelmer Vernooij
Pass children list to directory_to_tree .
298
        obj = directory_to_tree(ie.children, ie_to_hexsha, unusual_modes,
299
            dummy_file_name, path == "")
0.200.798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
300
        if obj is not None:
0.275.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
301
            yield path, obj, (file_id, )
302
            shamap[file_id] = obj.id
0.200.798 by Jelmer Vernooij
Split out _inventory_to_objects into a function.
303
304
0.200.1290 by Jelmer Vernooij
Avoid storing all objects to push in memory.
305
class PackTupleIterable(object):
306
307
    def __init__(self, store):
308
        self.store = store
0.200.1432 by Jelmer Vernooij
Make sure object store is locked/unlocked.
309
        self.store.lock_read()
0.200.1290 by Jelmer Vernooij
Avoid storing all objects to push in memory.
310
        self.objects = {}
311
0.200.1432 by Jelmer Vernooij
Make sure object store is locked/unlocked.
312
    def __del__(self):
313
        self.store.unlock()
314
0.200.1290 by Jelmer Vernooij
Avoid storing all objects to push in memory.
315
    def add(self, sha, path):
316
        self.objects[sha] = path
317
318
    def __len__(self):
319
        return len(self.objects)
320
321
    def __iter__(self):
322
        return ((self.store[object_id], path) for (object_id, path) in
323
                self.objects.iteritems())
324
325
0.200.457 by Jelmer Vernooij
Use BaseObjectStore.
326
class BazaarObjectStore(BaseObjectStore):
0.200.320 by Jelmer Vernooij
Handle lightweight checkouts.
327
    """A Git-style object store backed onto a Bazaar repository."""
0.200.228 by Jelmer Vernooij
Split out map.
328
329
    def __init__(self, repository, mapping=None):
330
        self.repository = repository
0.200.1212 by Jelmer Vernooij
Support read locking object stores.
331
        self._map_updated = False
332
        self._locked = None
0.200.228 by Jelmer Vernooij
Split out map.
333
        if mapping is None:
0.200.463 by Jelmer Vernooij
Support remote dpush (except for references).
334
            self.mapping = default_mapping
0.200.228 by Jelmer Vernooij
Split out map.
335
        else:
336
            self.mapping = mapping
0.200.847 by Jelmer Vernooij
Add BzrGitCache object.
337
        self._cache = cache_from_repository(repository)
0.200.1291 by Jelmer Vernooij
add hook for updating to local git cache.
338
        self._content_cache_types = ("tree",)
0.200.847 by Jelmer Vernooij
Add BzrGitCache object.
339
        self.start_write_group = self._cache.idmap.start_write_group
340
        self.abort_write_group = self._cache.idmap.abort_write_group
341
        self.commit_write_group = self._cache.idmap.commit_write_group
0.200.852 by Jelmer Vernooij
Cache trees rather than inventories.
342
        self.tree_cache = LRUTreeCache(self.repository)
0.200.1292 by Jelmer Vernooij
Fix repeeling objects when determining what to send.
343
        self.unpeel_map = UnpeelMap.from_repository(self.repository)
0.200.228 by Jelmer Vernooij
Split out map.
344
0.200.1319 by Jelmer Vernooij
Only update git cache during post-commit if parents are already in the cache.
345
    def _missing_revisions(self, revisions):
346
        return self._cache.idmap.missing_revisions(revisions)
347
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
348
    def _update_sha_map(self, stop_revision=None):
0.200.1212 by Jelmer Vernooij
Support read locking object stores.
349
        if not self.is_locked():
350
            raise AssertionError()
351
        if self._map_updated:
352
            return
0.200.1264 by Jelmer Vernooij
Fix updating cache for single revision - don't consider it an update of the full cache.
353
        if (stop_revision is not None and
0.200.1319 by Jelmer Vernooij
Only update git cache during post-commit if parents are already in the cache.
354
            not self._missing_revisions([stop_revision])):
0.200.1264 by Jelmer Vernooij
Fix updating cache for single revision - don't consider it an update of the full cache.
355
            return
0.200.683 by Jelmer Vernooij
Lazier checking of which revisions need to be fetched.
356
        graph = self.repository.get_graph()
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
357
        if stop_revision is None:
0.200.1301 by Jelmer Vernooij
Avoid expensive get_parent_map call.
358
            all_revids = self.repository.all_revision_ids()
0.200.1319 by Jelmer Vernooij
Only update git cache during post-commit if parents are already in the cache.
359
            missing_revids = self._missing_revisions(all_revids)
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
360
        else:
0.200.683 by Jelmer Vernooij
Lazier checking of which revisions need to be fetched.
361
            heads = set([stop_revision])
0.200.1319 by Jelmer Vernooij
Only update git cache during post-commit if parents are already in the cache.
362
            missing_revids = self._missing_revisions(heads)
0.200.1301 by Jelmer Vernooij
Avoid expensive get_parent_map call.
363
            while heads:
364
                parents = graph.get_parent_map(heads)
365
                todo = set()
366
                for p in parents.values():
367
                    todo.update([x for x in p if x not in missing_revids])
0.200.1319 by Jelmer Vernooij
Only update git cache during post-commit if parents are already in the cache.
368
                heads = self._missing_revisions(todo)
0.200.1301 by Jelmer Vernooij
Avoid expensive get_parent_map call.
369
                missing_revids.update(heads)
0.200.694 by Jelmer Vernooij
Avoid processing NULL_REVISION.
370
        if NULL_REVISION in missing_revids:
371
            missing_revids.remove(NULL_REVISION)
0.254.16 by Jelmer Vernooij
Add optimization preventing recursive index updating.
372
        missing_revids = self.repository.has_revisions(missing_revids)
373
        if not missing_revids:
0.200.1264 by Jelmer Vernooij
Fix updating cache for single revision - don't consider it an update of the full cache.
374
            if stop_revision is None:
375
                self._map_updated = True
0.254.16 by Jelmer Vernooij
Add optimization preventing recursive index updating.
376
            return
0.200.735 by Jelmer Vernooij
Use convenience functions for start/stop write groups.
377
        self.start_write_group()
0.200.231 by Jelmer Vernooij
Partially fix pull.
378
        try:
0.254.4 by Jelmer Vernooij
Merge trunk.
379
            pb = ui.ui_factory.nested_progress_bar()
380
            try:
381
                for i, revid in enumerate(graph.iter_topo_order(missing_revids)):
0.254.16 by Jelmer Vernooij
Add optimization preventing recursive index updating.
382
                    trace.mutter('processing %r', revid)
0.254.4 by Jelmer Vernooij
Merge trunk.
383
                    pb.update("updating git map", i, len(missing_revids))
384
                    self._update_sha_map_revision(revid)
385
            finally:
386
                pb.finished()
0.200.1264 by Jelmer Vernooij
Fix updating cache for single revision - don't consider it an update of the full cache.
387
            if stop_revision is None:
388
                self._map_updated = True
0.200.735 by Jelmer Vernooij
Use convenience functions for start/stop write groups.
389
        except:
390
            self.abort_write_group()
391
            raise
392
        else:
393
            self.commit_write_group()
0.200.229 by Jelmer Vernooij
More work on converter.
394
0.200.422 by Jelmer Vernooij
'bzr git-object' without arguments now prints the available git objects.
395
    def __iter__(self):
396
        self._update_sha_map()
0.200.847 by Jelmer Vernooij
Add BzrGitCache object.
397
        return iter(self._cache.idmap.sha1s())
0.200.422 by Jelmer Vernooij
'bzr git-object' without arguments now prints the available git objects.
398
0.200.1509 by Jelmer Vernooij
Properly raise exception when pulling from git into bzr without experimental mappings.
399
    def _reconstruct_commit(self, rev, tree_sha, lossy, verifiers):
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
400
        """Reconstruct a Commit object.
401
402
        :param rev: Revision object
403
        :param tree_sha: SHA1 of the root tree object
0.200.1509 by Jelmer Vernooij
Properly raise exception when pulling from git into bzr without experimental mappings.
404
        :param lossy: Whether or not to roundtrip bzr metadata
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
405
        :param verifiers: Verifiers for the commits
406
        :return: Commit object
407
        """
0.238.7 by Jelmer Vernooij
Cope with ghosts a bit better.
408
        def parent_lookup(revid):
409
            try:
410
                return self._lookup_revision_sha1(revid)
411
            except errors.NoSuchRevision:
412
                return None
0.252.4 by Jelmer Vernooij
More work on roundtripping.
413
        return self.mapping.export_commit(rev, tree_sha, parent_lookup,
0.200.1509 by Jelmer Vernooij
Properly raise exception when pulling from git into bzr without experimental mappings.
414
            lossy, verifiers)
0.238.7 by Jelmer Vernooij
Cope with ghosts a bit better.
415
0.273.2 by Jelmer Vernooij
use tree objects rather than inventories
416
    def _create_fileid_map_blob(self, tree):
0.200.1636 by Jelmer Vernooij
Some formatting fixes.
417
        # FIXME: This can probably be a lot more efficient,
0.252.49 by Jelmer Vernooij
Avoid trying to set HEAD for remote branches.
418
        # not all files necessarily have to be processed.
419
        file_ids = {}
0.273.2 by Jelmer Vernooij
use tree objects rather than inventories
420
        for (path, ie) in tree.inventory.iter_entries():
0.252.49 by Jelmer Vernooij
Avoid trying to set HEAD for remote branches.
421
            if self.mapping.generate_file_id(path) != ie.file_id:
422
                file_ids[path] = ie.file_id
423
        return self.mapping.export_fileid_map(file_ids)
424
0.200.1509 by Jelmer Vernooij
Properly raise exception when pulling from git into bzr without experimental mappings.
425
    def _revision_to_objects(self, rev, tree, lossy):
0.252.23 by Jelmer Vernooij
More work on roundtripping support.
426
        """Convert a revision to a set of git objects.
427
428
        :param rev: Bazaar revision object
429
        :param tree: Bazaar revision tree
0.200.1509 by Jelmer Vernooij
Properly raise exception when pulling from git into bzr without experimental mappings.
430
        :param lossy: Whether to not roundtrip all Bazaar revision data
0.252.23 by Jelmer Vernooij
More work on roundtripping support.
431
        """
0.200.548 by Jelmer Vernooij
Extract unusual file modes from revision when reconstructing Trees.
432
        unusual_modes = extract_unusual_modes(rev)
0.200.789 by Jelmer Vernooij
Cope with ghosts, cache inventories.
433
        present_parents = self.repository.has_revisions(rev.parent_ids)
0.200.852 by Jelmer Vernooij
Cache trees rather than inventories.
434
        parent_trees = self.tree_cache.revision_trees(
0.200.797 by Jelmer Vernooij
Add docstring, fix formatting.
435
            [p for p in rev.parent_ids if p in present_parents])
0.252.23 by Jelmer Vernooij
More work on roundtripping support.
436
        root_tree = None
0.275.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
437
        for path, obj, bzr_key_data in _tree_to_objects(tree, parent_trees,
0.252.30 by Jelmer Vernooij
Support creating dummy files for empty directories.
438
                self._cache.idmap, unusual_modes, self.mapping.BZR_DUMMY_FILE):
0.200.773 by Jelmer Vernooij
Implement inventory_to_objects
439
            if path == "":
0.252.23 by Jelmer Vernooij
More work on roundtripping support.
440
                root_tree = obj
0.275.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
441
                root_key_data = bzr_key_data
0.252.34 by Jelmer Vernooij
Yield the proper object for the tree root.
442
                # Don't yield just yet
443
            else:
0.275.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
444
                yield path, obj, bzr_key_data
0.252.23 by Jelmer Vernooij
More work on roundtripping support.
445
        if root_tree is None:
0.250.2 by Jelmer Vernooij
Make it work for evolution.
446
            # Pointless commit - get the tree sha elsewhere
0.200.864 by Jelmer Vernooij
Cope with the first commit being pointless.
447
            if not rev.parent_ids:
0.252.23 by Jelmer Vernooij
More work on roundtripping support.
448
                root_tree = Tree()
0.200.864 by Jelmer Vernooij
Cope with the first commit being pointless.
449
            else:
450
                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.
451
                root_tree = self[self[base_sha1].tree]
0.275.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
452
            root_key_data = (tree.get_root_id(), )
0.200.1509 by Jelmer Vernooij
Properly raise exception when pulling from git into bzr without experimental mappings.
453
        if not lossy and self.mapping.BZR_FILE_IDS_FILE is not None:
0.273.2 by Jelmer Vernooij
use tree objects rather than inventories
454
            b = self._create_fileid_map_blob(tree)
0.252.23 by Jelmer Vernooij
More work on roundtripping support.
455
            if b is not None:
0.200.1212 by Jelmer Vernooij
Support read locking object stores.
456
                root_tree[self.mapping.BZR_FILE_IDS_FILE] = (
457
                    (stat.S_IFREG | 0644), b.id)
0.252.23 by Jelmer Vernooij
More work on roundtripping support.
458
                yield self.mapping.BZR_FILE_IDS_FILE, b, None
0.275.2 by Jelmer Vernooij
Pass tuples around for cache entries, rather than inventory entries.
459
        yield "", root_tree, root_key_data
0.200.1509 by Jelmer Vernooij
Properly raise exception when pulling from git into bzr without experimental mappings.
460
        if not lossy:
0.200.1559 by Jelmer Vernooij
Fix compatibility with bzr 2.5.
461
            testament3 = StrictTestament3(rev, tree)
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
462
            verifiers = { "testament3-sha1": testament3.as_sha1() }
0.200.1023 by Jelmer Vernooij
Set and verify testament.
463
        else:
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
464
            verifiers = {}
0.252.43 by Jelmer Vernooij
Some refactoring, support proper file ids in revision deltas.
465
        commit_obj = self._reconstruct_commit(rev, root_tree.id,
0.200.1509 by Jelmer Vernooij
Properly raise exception when pulling from git into bzr without experimental mappings.
466
            lossy=lossy, verifiers=verifiers)
0.231.1 by Jelmer Vernooij
Check that regenerated objects have the expected sha1.
467
        try:
0.200.841 by Jelmer Vernooij
Eliminate InventorySHAMap.
468
            foreign_revid, mapping = mapping_registry.parse_revision_id(
469
                rev.revision_id)
0.231.1 by Jelmer Vernooij
Check that regenerated objects have the expected sha1.
470
        except errors.InvalidRevisionId:
471
            pass
472
        else:
0.200.794 by Jelmer Vernooij
Use _check_expected_sha rather than custom checks.
473
            _check_expected_sha(foreign_revid, commit_obj)
0.200.837 by Jelmer Vernooij
Return inventory entries when creating git objects for a revision.
474
        yield None, commit_obj, None
0.200.783 by Jelmer Vernooij
Move object generation into a separate function.
475
0.200.838 by Jelmer Vernooij
Add convenience object for updating the object store.
476
    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.
477
        return self._cache.get_updater(rev)
0.200.838 by Jelmer Vernooij
Add convenience object for updating the object store.
478
0.200.783 by Jelmer Vernooij
Move object generation into a separate function.
479
    def _update_sha_map_revision(self, revid):
480
        rev = self.repository.get_revision(revid)
0.200.852 by Jelmer Vernooij
Cache trees rather than inventories.
481
        tree = self.tree_cache.revision_tree(rev.revision_id)
0.200.838 by Jelmer Vernooij
Add convenience object for updating the object store.
482
        updater = self._get_updater(rev)
0.200.1510 by Jelmer Vernooij
Fix tests.
483
        # FIXME JRV 2011-12-15: Shouldn't we try both values for lossy ?
484
        for path, obj, ie in self._revision_to_objects(rev, tree, lossy=(not self.mapping.roundtripping)):
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
485
            if isinstance(obj, Commit):
0.200.1559 by Jelmer Vernooij
Fix compatibility with bzr 2.5.
486
                testament3 = StrictTestament3(rev, tree)
0.200.1029 by Jelmer Vernooij
Use dictionary with verifiers rather than requiring testament3-sha1 everywhere.
487
                ie = { "testament3-sha1": testament3.as_sha1() }
0.200.952 by Jelmer Vernooij
Write git pack files rather than loose objects.
488
            updater.add_object(obj, ie, path)
0.200.838 by Jelmer Vernooij
Add convenience object for updating the object store.
489
        commit_obj = updater.finish()
0.200.781 by Jelmer Vernooij
Return commit id after converting a revision.
490
        return commit_obj.id
0.200.229 by Jelmer Vernooij
More work on converter.
491
0.200.855 by Jelmer Vernooij
_get_ -> _reconstruct_.
492
    def _reconstruct_blobs(self, keys):
0.200.698 by Jelmer Vernooij
Merge fixes for SHA1s of symlinks.
493
        """Return a Git Blob object from a fileid and revision stored in bzr.
494
495
        :param fileid: File id of the text
496
        :param revision: Revision of the text
497
        """
0.250.2 by Jelmer Vernooij
Make it work for evolution.
498
        stream = self.repository.iter_files_bytes(
499
            ((key[0], key[1], key) for key in keys))
0.200.856 by Jelmer Vernooij
Support reconstructing multiple blobs at the same time.
500
        for (fileid, revision, expected_sha), chunks in stream:
0.200.854 by Jelmer Vernooij
_get_blob -> _get_blobs.
501
            blob = Blob()
502
            blob.chunked = chunks
0.200.868 by Jelmer Vernooij
Cope with no-change merges.
503
            if blob.id != expected_sha and blob.data == "":
0.200.854 by Jelmer Vernooij
_get_blob -> _get_blobs.
504
                # Perhaps it's a symlink ?
505
                tree = self.tree_cache.revision_tree(revision)
0.200.1586 by Jelmer Vernooij
Fixes duplicate tag warnings in 'git-remote-bzr' helper.
506
                if tree.kind(fileid) == 'symlink':
507
                    blob = symlink_to_blob(tree.get_symlink_target(fileid))
0.200.854 by Jelmer Vernooij
_get_blob -> _get_blobs.
508
            _check_expected_sha(expected_sha, blob)
509
            yield blob
0.200.229 by Jelmer Vernooij
More work on converter.
510
0.273.2 by Jelmer Vernooij
use tree objects rather than inventories
511
    def _reconstruct_tree(self, fileid, revid, bzr_tree, unusual_modes,
0.200.855 by Jelmer Vernooij
_get_ -> _reconstruct_.
512
        expected_sha=None):
0.200.343 by Jelmer Vernooij
Use file ids consistently in map.
513
        """Return a Git Tree object from a file id and a revision stored in bzr.
0.200.249 by Jelmer Vernooij
Implement Tree.
514
0.200.343 by Jelmer Vernooij
Use file ids consistently in map.
515
        :param fileid: fileid in the tree.
0.200.249 by Jelmer Vernooij
Implement Tree.
516
        :param revision: Revision of the tree.
517
        """
0.200.776 by Jelmer Vernooij
Remove unnecessary lookups.
518
        def get_ie_sha1(entry):
519
            if entry.kind == "directory":
0.200.808 by Jelmer Vernooij
Avoid recalculating tree shas we already have.
520
                try:
0.200.859 by Jelmer Vernooij
Trivial cleanups.
521
                    return self._cache.idmap.lookup_tree_id(entry.file_id,
522
                        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.
523
                except (NotImplementedError, KeyError):
0.273.2 by Jelmer Vernooij
use tree objects rather than inventories
524
                    obj = self._reconstruct_tree(entry.file_id, revid, bzr_tree,
0.200.808 by Jelmer Vernooij
Avoid recalculating tree shas we already have.
525
                        unusual_modes)
526
                    if obj is None:
527
                        return None
528
                    else:
529
                        return obj.id
0.200.776 by Jelmer Vernooij
Remove unnecessary lookups.
530
            elif entry.kind in ("file", "symlink"):
0.200.868 by Jelmer Vernooij
Cope with no-change merges.
531
                try:
532
                    return self._cache.idmap.lookup_blob_id(entry.file_id,
533
                        entry.revision)
534
                except KeyError:
535
                    # no-change merge?
536
                    return self._reconstruct_blobs(
537
                        [(entry.file_id, entry.revision, None)]).next().id
0.200.1551 by Jelmer Vernooij
Support nested trees in reconstruction code.
538
            elif entry.kind == 'tree-reference':
539
                # FIXME: Make sure the file id is the root id
540
                return self._lookup_revision_sha1(entry.reference_revision)
0.200.776 by Jelmer Vernooij
Remove unnecessary lookups.
541
            else:
542
                raise AssertionError("unknown entry kind '%s'" % entry.kind)
0.275.5 by Jelmer Vernooij
Cope with root_inventory and inventory.
543
        try:
544
            inv = bzr_tree.root_inventory
545
        except AttributeError:
546
            inv = bzr_tree.inventory
547
        tree = directory_to_tree(inv[fileid].children,
0.275.4 by Jelmer Vernooij
Pass children list to directory_to_tree .
548
                get_ie_sha1, unusual_modes, self.mapping.BZR_DUMMY_FILE,
549
                bzr_tree.get_root_id() == fileid)
0.273.2 by Jelmer Vernooij
use tree objects rather than inventories
550
        if (bzr_tree.get_root_id() == fileid and
0.200.915 by Jelmer Vernooij
Cope with the fact that the old format didn't export file ids.
551
            self.mapping.BZR_FILE_IDS_FILE is not None):
0.200.1223 by Jelmer Vernooij
Cope with empty directories.
552
            if tree is None:
553
                tree = Tree()
0.273.2 by Jelmer Vernooij
use tree objects rather than inventories
554
            b = self._create_fileid_map_blob(bzr_tree)
0.252.49 by Jelmer Vernooij
Avoid trying to set HEAD for remote branches.
555
            # If this is the root tree, add the file ids
0.200.1212 by Jelmer Vernooij
Support read locking object stores.
556
            tree[self.mapping.BZR_FILE_IDS_FILE] = (
557
                (stat.S_IFREG | 0644), b.id)
0.200.1223 by Jelmer Vernooij
Cope with empty directories.
558
        if tree is not None:
559
            _check_expected_sha(expected_sha, tree)
0.200.249 by Jelmer Vernooij
Implement Tree.
560
        return tree
0.200.229 by Jelmer Vernooij
More work on converter.
561
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
562
    def get_parents(self, sha):
0.200.454 by Jelmer Vernooij
Use ObjectStore.find_missing_objects in server.
563
        """Retrieve the parents of a Git commit by SHA1.
564
565
        :param sha: SHA1 of the commit
566
        :raises: KeyError, NotCommitError
567
        """
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
568
        return self[sha].parents
569
0.200.364 by Jelmer Vernooij
Reimplement dpush, but more efficient and only writing a single pack file rather than one per revision.
570
    def _lookup_revision_sha1(self, revid):
0.200.449 by Jelmer Vernooij
Use BazaarObjectStore to find matching SHA1s for bzr revisions.
571
        """Return the SHA1 matching a Bazaar revision."""
0.200.541 by Jelmer Vernooij
Cope with NULL_REVISION.
572
        if revid == NULL_REVISION:
0.200.891 by Jelmer Vernooij
Use ZERO_SHA constant where possible.
573
            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.
574
        try:
0.200.847 by Jelmer Vernooij
Add BzrGitCache object.
575
            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.
576
        except KeyError:
0.200.682 by Jelmer Vernooij
Avoid doing a full sha map update if we already know the SHA1.
577
            try:
578
                return mapping_registry.parse_revision_id(revid)[0]
579
            except errors.InvalidRevisionId:
0.200.1264 by Jelmer Vernooij
Fix updating cache for single revision - don't consider it an update of the full cache.
580
                self._update_sha_map(revid)
0.200.847 by Jelmer Vernooij
Add BzrGitCache object.
581
                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.
582
0.200.310 by Jelmer Vernooij
Fix pull from remote branches.
583
    def get_raw(self, sha):
0.200.454 by Jelmer Vernooij
Use ObjectStore.find_missing_objects in server.
584
        """Get the raw representation of a Git object by SHA1.
585
586
        :param sha: SHA1 of the git object
587
        """
0.200.1622 by William Grant
BazaarObjectStore.get_raw now copes with non-hex-encoded SHA-1s, as some ref delta resolution in dulwich apparently requires.
588
        if len(sha) == 20:
589
            sha = sha_to_hex(sha)
0.200.566 by Jelmer Vernooij
Fix ObjectStore.get_raw() .
590
        obj = self[sha]
591
        return (obj.type, obj.as_raw_string())
0.200.310 by Jelmer Vernooij
Fix pull from remote branches.
592
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
593
    def __contains__(self, sha):
594
        # See if sha is in map
595
        try:
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
596
            for (type, type_data) in self.lookup_git_sha(sha):
597
                if type == "commit":
598
                    if self.repository.has_revision(type_data[0]):
599
                        return True
600
                elif type == "blob":
0.200.1648 by Jelmer Vernooij
Fix compatibility with newer versions of breezy.
601
                    if type_data in self.repository.texts:
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
602
                        return True
603
                elif type == "tree":
604
                    if self.repository.has_revision(type_data[1]):
605
                        return True
606
                else:
607
                    raise AssertionError("Unknown object type '%s'" % type)
0.200.568 by Jelmer Vernooij
Properly check that matching bzr objects exist.
608
            else:
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
609
                return False
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
610
        except KeyError:
611
            return False
612
0.200.1212 by Jelmer Vernooij
Support read locking object stores.
613
    def lock_read(self):
614
        self._locked = 'r'
615
        self._map_updated = False
616
        self.repository.lock_read()
617
        return LogicalLockResult(self.unlock)
618
619
    def lock_write(self):
620
        self._locked = 'r'
621
        self._map_updated = False
622
        self.repository.lock_write()
623
        return LogicalLockResult(self.unlock)
624
625
    def is_locked(self):
626
        return (self._locked is not None)
627
628
    def unlock(self):
629
        self._locked = None
630
        self._map_updated = False
631
        self.repository.unlock()
632
633
    def lookup_git_shas(self, shas):
0.200.898 by Jelmer Vernooij
Optimize finding of git shas.
634
        ret = {}
635
        for sha in shas:
0.200.969 by Jelmer Vernooij
Use tuples with bzr revid and git sha to avoid lookups.
636
            if sha == ZERO_SHA:
0.200.1169 by Jelmer Vernooij
Fix some sha lookups.
637
                ret[sha] = [("commit", (NULL_REVISION, None, {}))]
0.200.969 by Jelmer Vernooij
Use tuples with bzr revid and git sha to avoid lookups.
638
                continue
0.200.898 by Jelmer Vernooij
Optimize finding of git shas.
639
            try:
0.261.3 by Jelmer Vernooij
Fix more tests.
640
                ret[sha] = list(self._cache.idmap.lookup_git_sha(sha))
0.200.898 by Jelmer Vernooij
Optimize finding of git shas.
641
            except KeyError:
0.200.1212 by Jelmer Vernooij
Support read locking object stores.
642
                # if not, see if there are any unconverted revisions and
643
                # add them to the map, search for sha in map again
644
                self._update_sha_map()
645
                try:
646
                    ret[sha] = list(self._cache.idmap.lookup_git_sha(sha))
647
                except KeyError:
648
                    pass
0.200.898 by Jelmer Vernooij
Optimize finding of git shas.
649
        return ret
650
0.200.1212 by Jelmer Vernooij
Support read locking object stores.
651
    def lookup_git_sha(self, sha):
652
        return self.lookup_git_shas([sha])[sha]
0.200.437 by Jelmer Vernooij
Implement BazaarObjectStore.__contains__, BazaarObjectStore.iter_shas, BazaarObjectStore.get_parents.
653
654
    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.
655
        if self._cache.content_cache is not None:
0.200.840 by Jelmer Vernooij
Support using content cache.
656
            try:
0.200.847 by Jelmer Vernooij
Add BzrGitCache object.
657
                return self._cache.content_cache[sha]
0.200.840 by Jelmer Vernooij
Support using content cache.
658
            except KeyError:
659
                pass
0.200.1169 by Jelmer Vernooij
Fix some sha lookups.
660
        for (kind, type_data) in self.lookup_git_sha(sha):
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
661
            # convert object to git object
0.200.1169 by Jelmer Vernooij
Fix some sha lookups.
662
            if kind == "commit":
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
663
                (revid, tree_sha, verifiers) = type_data
664
                try:
665
                    rev = self.repository.get_revision(revid)
666
                except errors.NoSuchRevision:
0.200.1341 by Jelmer Vernooij
Add check that callers don't try to look up NULL_REVISION.
667
                    if revid == NULL_REVISION:
668
                        raise AssertionError(
669
                            "should not try to look up NULL_REVISION")
0.200.1169 by Jelmer Vernooij
Fix some sha lookups.
670
                    trace.mutter('entry for %s %s in shamap: %r, but not '
671
                                 'found in repository', kind, sha, type_data)
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
672
                    raise KeyError(sha)
0.200.1510 by Jelmer Vernooij
Fix tests.
673
                # FIXME: the type data should say whether conversion was lossless
0.200.1212 by Jelmer Vernooij
Support read locking object stores.
674
                commit = self._reconstruct_commit(rev, tree_sha,
0.200.1510 by Jelmer Vernooij
Fix tests.
675
                    lossy=(not self.mapping.roundtripping), verifiers=verifiers)
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
676
                _check_expected_sha(sha, commit)
677
                return commit
0.200.1169 by Jelmer Vernooij
Fix some sha lookups.
678
            elif kind == "blob":
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
679
                (fileid, revision) = type_data
0.200.1212 by Jelmer Vernooij
Support read locking object stores.
680
                blobs = self._reconstruct_blobs([(fileid, revision, sha)])
681
                return blobs.next()
0.200.1169 by Jelmer Vernooij
Fix some sha lookups.
682
            elif kind == "tree":
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
683
                (fileid, revid) = type_data
684
                try:
685
                    tree = self.tree_cache.revision_tree(revid)
686
                    rev = self.repository.get_revision(revid)
687
                except errors.NoSuchRevision:
0.200.1319 by Jelmer Vernooij
Only update git cache during post-commit if parents are already in the cache.
688
                    trace.mutter('entry for %s %s in shamap: %r, but not found in '
689
                        'repository', kind, sha, type_data)
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
690
                    raise KeyError(sha)
691
                unusual_modes = extract_unusual_modes(rev)
692
                try:
693
                    return self._reconstruct_tree(fileid, revid,
0.273.2 by Jelmer Vernooij
use tree objects rather than inventories
694
                        tree, unusual_modes, expected_sha=sha)
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
695
                except errors.NoSuchRevision:
696
                    raise KeyError(sha)
697
            else:
0.200.1169 by Jelmer Vernooij
Fix some sha lookups.
698
                raise AssertionError("Unknown object type '%s'" % kind)
0.200.228 by Jelmer Vernooij
Split out map.
699
        else:
0.261.1 by Jelmer Vernooij
Initial work on supporting multiple results for git shas.
700
            raise KeyError(sha)
0.200.782 by Jelmer Vernooij
Add custom generate_pack_contents implementation.
701
0.252.37 by Jelmer Vernooij
Factor out some common code for finding refs to send.
702
    def generate_lossy_pack_contents(self, have, want, progress=None,
703
            get_tagged=None):
704
        return self.generate_pack_contents(have, want, progress, get_tagged,
705
            lossy=True)
706
0.200.899 by Jelmer Vernooij
Add tests for find_missing_bzr_revids.
707
    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.
708
            get_tagged=None, lossy=False):
0.200.782 by Jelmer Vernooij
Add custom generate_pack_contents implementation.
709
        """Iterate over the contents of a pack file.
710
711
        :param have: List of SHA1s of objects that should not be sent
712
        :param want: List of SHA1s of objects that should be sent
713
        """
0.200.787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
714
        processed = set()
0.200.898 by Jelmer Vernooij
Optimize finding of git shas.
715
        ret = self.lookup_git_shas(have + want)
0.200.787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
716
        for commit_sha in have:
0.200.1292 by Jelmer Vernooij
Fix repeeling objects when determining what to send.
717
            commit_sha = self.unpeel_map.peel_tag(commit_sha, commit_sha)
0.200.787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
718
            try:
0.200.1180 by Jelmer Vernooij
Some dpush fixes.
719
                for (type, type_data) in ret[commit_sha]:
720
                    assert type == "commit"
721
                    processed.add(type_data[0])
0.200.787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
722
            except KeyError:
0.200.1292 by Jelmer Vernooij
Fix repeeling objects when determining what to send.
723
                trace.mutter("unable to find remote ref %s", commit_sha)
0.200.787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
724
        pending = set()
725
        for commit_sha in want:
726
            if commit_sha in have:
727
                continue
0.200.898 by Jelmer Vernooij
Optimize finding of git shas.
728
            try:
0.200.1180 by Jelmer Vernooij
Some dpush fixes.
729
                for (type, type_data) in ret[commit_sha]:
730
                    assert type == "commit"
731
                    pending.add(type_data[0])
0.200.898 by Jelmer Vernooij
Optimize finding of git shas.
732
            except KeyError:
733
                pass
0.200.899 by Jelmer Vernooij
Add tests for find_missing_bzr_revids.
734
0.200.1053 by Jelmer Vernooij
Fix find_missing_bzr_revids.
735
        graph = self.repository.get_graph()
736
        todo = _find_missing_bzr_revids(graph, pending, processed)
0.200.1290 by Jelmer Vernooij
Avoid storing all objects to push in memory.
737
        ret = PackTupleIterable(self)
0.200.787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
738
        pb = ui.ui_factory.nested_progress_bar()
739
        try:
740
            for i, revid in enumerate(todo):
741
                pb.update("generating git objects", i, len(todo))
0.200.1059 by Jelmer Vernooij
Fix graph tests.
742
                try:
743
                    rev = self.repository.get_revision(revid)
744
                except errors.NoSuchRevision:
745
                    continue
0.200.852 by Jelmer Vernooij
Cache trees rather than inventories.
746
                tree = self.tree_cache.revision_tree(revid)
0.200.1509 by Jelmer Vernooij
Properly raise exception when pulling from git into bzr without experimental mappings.
747
                for path, obj, ie in self._revision_to_objects(rev, tree, lossy=lossy):
0.200.1290 by Jelmer Vernooij
Avoid storing all objects to push in memory.
748
                    ret.add(obj.id, path)
0.200.1298 by Jelmer Vernooij
Fix compatibility with newer versions of dulwich.
749
            return ret
0.200.787 by Jelmer Vernooij
Implement custom ObjectWalker.generate_pack_contents.
750
        finally:
751
            pb.finished()
0.251.1 by Jelmer Vernooij
Implement ObjectStore.add_{thin_,}pack.
752
753
    def add_thin_pack(self):
754
        import tempfile
755
        import os
756
        fd, path = tempfile.mkstemp(suffix=".pack")
757
        f = os.fdopen(fd, 'wb')
758
        def commit():
759
            from dulwich.pack import PackData, Pack
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
760
            from .fetch import import_git_objects
0.251.1 by Jelmer Vernooij
Implement ObjectStore.add_{thin_,}pack.
761
            os.fsync(fd)
762
            f.close()
763
            if os.path.getsize(path) == 0:
764
                return
765
            pd = PackData(path)
766
            pd.create_index_v2(path[:-5]+".idx", self.object_store.get_raw)
767
768
            p = Pack(path[:-5])
769
            self.repository.lock_write()
770
            try:
771
                self.repository.start_write_group()
772
                try:
0.200.1289 by Jelmer Vernooij
Switch to dulwich 0.8.0.
773
                    import_git_objects(self.repository, self.mapping,
0.251.1 by Jelmer Vernooij
Implement ObjectStore.add_{thin_,}pack.
774
                        p.iterobjects(get_raw=self.get_raw),
775
                        self.object_store)
776
                except:
777
                    self.repository.abort_write_group()
778
                    raise
779
                else:
780
                    self.repository.commit_write_group()
781
            finally:
782
                self.repository.unlock()
783
        return f, commit
784
0.200.1636 by Jelmer Vernooij
Some formatting fixes.
785
    # The pack isn't kept around anyway, so no point
0.251.1 by Jelmer Vernooij
Implement ObjectStore.add_{thin_,}pack.
786
    # in treating full packs different from thin packs
787
    add_pack = add_thin_pack