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