/brz/remove-bazaar

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