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