~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/inventory.py

  • Committer: Martin Pool
  • Date: 2005-10-06 04:09:55 UTC
  • mfrom: (1413)
  • mto: (1185.13.3)
  • mto: This revision was merged to the branch mainline in revision 1417.
  • Revision ID: mbp@sourcefrog.net-20051006040955-36f27e5a8d5c977b
[merge] from robert

Show diffs side-by-side

added added

removed removed

Lines of Context:
146
146
             output_to, reverse=False):
147
147
        """Perform a diff between two entries of the same kind."""
148
148
 
 
149
    def find_previous_heads(self, previous_inventories, entry_weave):
 
150
        """Return the revisions and entries that directly preceed this.
 
151
 
 
152
        Returned as a map from revision to inventory entry.
 
153
 
 
154
        This is a map containing the file revisions in all parents
 
155
        for which the file exists, and its revision is not a parent of
 
156
        any other. If the file is new, the set will be empty.
 
157
        """
 
158
        def get_ancestors(weave, entry):
 
159
            return set(map(weave.idx_to_name,
 
160
                           weave.inclusions([weave.lookup(entry.revision)])))
 
161
        heads = {}
 
162
        head_ancestors = {}
 
163
        for inv in previous_inventories:
 
164
            if self.file_id in inv:
 
165
                ie = inv[self.file_id]
 
166
                assert ie.file_id == self.file_id
 
167
                if ie.revision in heads:
 
168
                    assert heads[ie.revision] == ie
 
169
                else:
 
170
                    # may want to add it.
 
171
                    # may already be covered:
 
172
                    already_present = 0 != len(
 
173
                        [head for head in heads 
 
174
                         if ie.revision in head_ancestors[head]])
 
175
                    if already_present:
 
176
                        # an ancestor of a known head.
 
177
                        continue
 
178
                    # definately a head:
 
179
                    ancestors = get_ancestors(entry_weave, ie)
 
180
                    # may knock something else out:
 
181
                    check_heads = list(heads.keys())
 
182
                    for head in check_heads:
 
183
                        if head in ancestors:
 
184
                            # this head is not really a head
 
185
                            heads.pop(head)
 
186
                    head_ancestors[ie.revision] = ancestors
 
187
                    heads[ie.revision] = ie
 
188
        return heads
 
189
 
149
190
    def get_tar_item(self, root, dp, now, tree):
150
191
        """Get a tarfile item and a file stream for its content."""
151
192
        item = tarfile.TarInfo(os.path.join(root, dp))
159
200
        """Return true if the object this entry represents has textual data.
160
201
 
161
202
        Note that textual data includes binary content.
 
203
 
 
204
        Also note that all entries get weave files created for them.
 
205
        This attribute is primarily used when upgrading from old trees that
 
206
        did not have the weave index for all inventory entries.
162
207
        """
163
208
        return False
164
209
 
264
309
                   self.name,
265
310
                   self.parent_id))
266
311
 
267
 
    def snapshot(self, revision, path, previous_entries, work_tree, 
268
 
                 weave_store):
 
312
    def snapshot(self, revision, path, previous_entries,
 
313
                 work_tree, weave_store):
269
314
        """Make a snapshot of this entry which may or may not have changed.
270
315
        
271
316
        This means that all its fields are populated, that it has its
276
321
        if len(previous_entries) == 1:
277
322
            # cannot be unchanged unless there is only one parent file rev.
278
323
            parent_ie = previous_entries.values()[0]
279
 
            if self._unchanged(path, parent_ie, work_tree):
 
324
            if self._unchanged(parent_ie):
280
325
                mutter("found unchanged entry")
281
326
                self.revision = parent_ie.revision
282
327
                return "unchanged"
289
334
        mutter('new revision for {%s}', self.file_id)
290
335
        self.revision = revision
291
336
        change = self._get_snapshot_change(previous_entries)
 
337
        self._snapshot_text(previous_entries, work_tree, weave_store)
292
338
        return change
293
339
 
294
340
    def _snapshot_text(self, file_parents, work_tree, weave_store): 
 
341
        """Record the 'text' of this entry, whatever form that takes.
 
342
        
 
343
        This default implementation simply adds an empty text.
 
344
        """
295
345
        mutter('storing file {%s} in revision {%s}',
296
346
               self.file_id, self.revision)
297
 
        # special case to avoid diffing on renames or 
298
 
        # reparenting
299
 
        if (len(file_parents) == 1
300
 
            and self.text_sha1 == file_parents.values()[0].text_sha1
301
 
            and self.text_size == file_parents.values()[0].text_size):
302
 
            previous_ie = file_parents.values()[0]
303
 
            weave_store.add_identical_text(
304
 
                self.file_id, previous_ie.revision, 
305
 
                self.revision, file_parents)
306
 
        else:
307
 
            new_lines = work_tree.get_file(self.file_id).readlines()
308
 
            self._add_text_to_weave(new_lines, file_parents, weave_store)
309
 
            self.text_sha1 = sha_strings(new_lines)
310
 
            self.text_size = sum(map(len, new_lines))
 
347
        self._add_text_to_weave([], file_parents, weave_store)
311
348
 
312
349
    def __eq__(self, other):
313
350
        if not isinstance(other, InventoryEntry):
331
368
    def __hash__(self):
332
369
        raise ValueError('not hashable')
333
370
 
334
 
    def _unchanged(self, path, previous_ie, work_tree):
 
371
    def _unchanged(self, previous_ie):
335
372
        """Has this entry changed relative to previous_ie.
336
373
 
337
374
        This method should be overriden in child classes.
502
539
        self.text_sha1 = work_tree.get_file_sha1(self.file_id)
503
540
        self.executable = work_tree.is_executable(self.file_id)
504
541
 
505
 
    def snapshot_revision(self, revision, previous_entries, work_tree,
506
 
                          weave_store):
507
 
        """See InventoryEntry.snapshot_revision."""
508
 
        change = super(InventoryFile, self).snapshot_revision(revision, 
509
 
            previous_entries, work_tree, weave_store)
510
 
        self._snapshot_text(previous_entries, work_tree, weave_store)
511
 
        return change
512
 
 
513
 
    def _unchanged(self, path, previous_ie, work_tree):
 
542
    def _snapshot_text(self, file_parents, work_tree, weave_store): 
 
543
        """See InventoryEntry._snapshot_text."""
 
544
        mutter('storing file {%s} in revision {%s}',
 
545
               self.file_id, self.revision)
 
546
        # special case to avoid diffing on renames or 
 
547
        # reparenting
 
548
        if (len(file_parents) == 1
 
549
            and self.text_sha1 == file_parents.values()[0].text_sha1
 
550
            and self.text_size == file_parents.values()[0].text_size):
 
551
            previous_ie = file_parents.values()[0]
 
552
            weave_store.add_identical_text(
 
553
                self.file_id, previous_ie.revision, 
 
554
                self.revision, file_parents)
 
555
        else:
 
556
            new_lines = work_tree.get_file(self.file_id).readlines()
 
557
            self._add_text_to_weave(new_lines, file_parents, weave_store)
 
558
            self.text_sha1 = sha_strings(new_lines)
 
559
            self.text_size = sum(map(len, new_lines))
 
560
 
 
561
 
 
562
    def _unchanged(self, previous_ie):
514
563
        """See InventoryEntry._unchanged."""
515
 
        compatible = super(InventoryFile, self)._unchanged(path, previous_ie, 
516
 
            work_tree)
 
564
        compatible = super(InventoryFile, self)._unchanged(previous_ie)
517
565
        if self.text_sha1 != previous_ie.text_sha1:
518
566
            compatible = False
519
567
        else:
597
645
        """See InventoryEntry._read_tree_state."""
598
646
        self.symlink_target = work_tree.get_symlink_target(self.file_id)
599
647
 
600
 
    def _unchanged(self, path, previous_ie, work_tree):
 
648
    def _unchanged(self, previous_ie):
601
649
        """See InventoryEntry._unchanged."""
602
 
        compatible = super(InventoryLink, self)._unchanged(path, previous_ie, 
603
 
            work_tree)
 
650
        compatible = super(InventoryLink, self)._unchanged(previous_ie)
604
651
        if self.symlink_target != previous_ie.symlink_target:
605
652
            compatible = False
606
653
        return compatible