/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to fetch.py

  • Committer: Jelmer Vernooij
  • Date: 2009-03-26 22:51:15 UTC
  • mto: (0.200.299 trunk)
  • mto: This revision was merged to the branch mainline in revision 6960.
  • Revision ID: jelmer@samba.org-20090326225115-2o3nmibxhy5ff1mg
Use inventory deltas internally so fetch is O(changes) rather than O(tree).

Show diffs side-by-side

added added

removed removed

Lines of Context:
39
39
    Inventory,
40
40
    InventoryDirectory,
41
41
    InventoryFile,
42
 
    InventorySymlink,
 
42
    InventoryLink,
43
43
    )
44
44
from bzrlib.repository import (
45
45
    InterRepository,
46
46
    )
 
47
from bzrlib.revision import (
 
48
    NULL_REVISION,
 
49
    )
47
50
from bzrlib.tsort import (
48
51
    topo_sort,
49
52
    )
116
119
    ie.text_size = len(blob.data)
117
120
    ie.text_sha1 = osutils.sha_string(blob.data)
118
121
    ie.executable = executable
119
 
    # See if this is the same revision as one of the parents unchanged
 
122
    # If there were no changes compared to the base inventory, there's no need 
 
123
    # for a delta
 
124
    if (file_id in base_inv and 
 
125
        base_inv[file_id].parent_id == ie.parent_id and
 
126
        base_inv[file_id].text_sha1 == ie.text_sha1 and
 
127
        base_inv[file_id].executable == ie.executable):
 
128
        return []
 
129
    # Check what revision we should store
120
130
    parent_keys = []
121
131
    for pinv in parent_invs:
122
132
        if not file_id in pinv:
123
133
            continue
124
134
        if pinv[file_id].text_sha1 == ie.text_sha1:
 
135
            # found a revision in one of the parents to use
125
136
            ie.revision = pinv[file_id].revision
126
 
            return ie
 
137
            break
127
138
        parent_keys.append((file_id, pinv[file_id].revision))
128
 
    ie.revision = revision_id
129
 
    assert file_id is not None
130
 
    assert ie.revision is not None
131
 
    texts.add_lines((file_id, ie.revision), parent_keys,
132
 
        osutils.split_lines(blob.data))
133
 
    shagitmap.add_entry(blob.sha().hexdigest(), "blob",
134
 
        (ie.file_id, ie.revision))
135
 
    return ie
 
139
    if ie.revision is None:
 
140
        # Need to store a new revision
 
141
        ie.revision = revision_id
 
142
        assert file_id is not None
 
143
        assert ie.revision is not None
 
144
        texts.add_lines((file_id, ie.revision), parent_keys,
 
145
            osutils.split_lines(blob.data))
 
146
        shagitmap.add_entry(blob.sha().hexdigest(), "blob",
 
147
            (ie.file_id, ie.revision))
 
148
    if file_id in base_inv:
 
149
        old_path = base_inv.id2path(file_id)
 
150
    else:
 
151
        old_path = None
 
152
    return [(old_path, path, file_id, ie)]
136
153
 
137
154
 
138
155
def import_git_tree(texts, mapping, path, tree, base_inv, parent_id, 
145
162
    :param base_inv: Base inventory against which to return inventory delta
146
163
    :return: Inventory delta for this subtree
147
164
    """
 
165
    ret = []
148
166
    file_id = mapping.generate_file_id(path)
149
167
    # We just have to hope this is indeed utf-8:
150
 
    ie = InventoryDirectory(file_id, 
151
 
        urlutils.basename(path.decode("utf-8")), parent_id)
152
 
    ie.revision = None
153
 
    parent_keys = []
154
 
    for pinv in parent_invs:
155
 
        if not file_id in pinv:
156
 
            continue
 
168
    ie = InventoryDirectory(file_id, urlutils.basename(path.decode("utf-8")), 
 
169
        parent_id)
 
170
    if not file_id in base_inv:
 
171
        # Newly appeared here
 
172
        ie.revision = revision_id
 
173
        texts.add_lines((file_id, ie.revision), [], [])
 
174
        ret.append((None, path, file_id, ie))
 
175
    else:
 
176
        # See if this has changed at all
157
177
        try:
158
 
            tree_sha = shagitmap.lookup_tree(path, pinv[file_id].revision)
 
178
            base_sha = shagitmap.lookup_tree(path, base_inv.revision_id)
159
179
        except KeyError:
160
180
            pass
161
181
        else:
162
182
            if tree_sha == tree.id:
163
 
                ie.revision = pinv[file_id].revision
164
 
                break
165
 
        parent_keys.append((file_id, pinv[file_id].revision))
166
 
    if ie.revision is None:
167
 
        ie.revision = revision_id
168
 
        texts.add_lines((file_id, ie.revision), parent_keys, [])
169
 
        shagitmap.add_entry(tree.id, "tree", (file_id, ie.revision))
 
183
                # If nothing has changed since the base revision, we're done
 
184
                return []
 
185
    # Remember for next time
 
186
    shagitmap.add_entry(tree.id, "tree", (file_id, revision_id))
 
187
    existing_children = set()
170
188
    for mode, name, hexsha in tree.entries():
171
189
        entry_kind = (mode & 0700000) / 0100000
172
190
        basename = name.decode("utf-8")
 
191
        existing_children.add(basename)
173
192
        if path == "":
174
193
            child_path = name
175
194
        else:
176
195
            child_path = urlutils.join(path, name)
177
196
        obj = lookup_object(hexsha)
178
197
        if entry_kind == 0:
179
 
            import_git_tree(texts, mapping, child_path, obj, base_inv, 
180
 
                parent_id, revision_id, parent_invs, shagitmap, lookup_object)
 
198
            ret.extend(import_git_tree(texts, mapping, child_path, obj, base_inv, 
 
199
                file_id, revision_id, parent_invs, shagitmap, lookup_object))
181
200
        elif entry_kind == 1:
182
201
            fs_mode = mode & 0777
183
 
            import_git_blob(texts, mapping, child_path, obj, base_inv, 
184
 
                parent_id, revision_id, parent_invs, shagitmap, 
185
 
                bool(fs_mode & 0111))
 
202
            ret.extend(import_git_blob(texts, mapping, child_path, obj, base_inv, 
 
203
                file_id, revision_id, parent_invs, shagitmap, 
 
204
                bool(fs_mode & 0111)))
186
205
        else:
187
206
            raise AssertionError("Unknown blob kind, perms=%r." % (mode,))
 
207
    # Remove any children that have disappeared
 
208
    if file_id in base_inv:
 
209
        for x in set(base_inv[file_id].children).difference(existing_children):
 
210
            # TODO: Remove recursively if child is a directory
 
211
            child_file_id = base_inv[file_id].children[x].file_id
 
212
            ret.append((base_inv.id2path(child_file_id), None, child_file_id,
 
213
                        None))
 
214
    return ret
188
215
 
189
216
 
190
217
def import_git_objects(repo, mapping, object_iter, target_git_object_retriever, 
237
264
            return target_git_object_retriever[sha]
238
265
        parent_invs = list(repo.iter_inventories(rev.parent_ids))
239
266
        if parent_invs == []:
240
 
            base_inv = Inventory()
 
267
            base_inv = Inventory(root_id=None)
241
268
        else:
242
269
            base_inv = parent_invs[0]
243
270
        inv_delta = import_git_tree(repo.texts, mapping, "", root_tree, 
247
274
            basis_id = rev.parent_ids[0]
248
275
        except IndexError:
249
276
            basis_id = NULL_REVISION
250
 
        rev.inventory_sha1, inv = self.target.add_inventory_by_delta(basis_id,
 
277
        rev.inventory_sha1, inv = repo.add_inventory_by_delta(basis_id,
251
278
                  inv_delta, rev.revision_id, rev.parent_ids)
252
279
        repo.add_revision(rev.revision_id, rev)
253
280
    target_git_object_retriever._idmap.commit()