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