/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 bzrlib/changeset.py

  • Committer: Aaron Bentley
  • Date: 2005-10-13 21:10:11 UTC
  • mto: (1185.25.1)
  • mto: This revision was merged to the branch mainline in revision 1460.
  • Revision ID: abentley@panoramicfeedback.com-20051013211011-7aeccd5c452e31ee
Replaced FileCreate with TreeFileCreate, fixed revert with empty parents

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
import patch
19
19
import stat
20
20
from bzrlib.trace import mutter
21
 
from bzrlib.osutils import rename
 
21
from bzrlib.osutils import rename, sha_file
22
22
import bzrlib
 
23
from itertools import izip
23
24
 
24
25
# XXX: mbp: I'm not totally convinced that we should handle conflicts
25
26
# as part of changeset application, rather than only in the merge
230
231
 
231
232
                    
232
233
 
 
234
class TreeFileCreate(object):
 
235
    """Create or delete a file (for use with ReplaceContents)"""
 
236
    def __init__(self, tree, file_id):
 
237
        """Constructor
 
238
 
 
239
        :param contents: The contents of the file to write
 
240
        :type contents: str
 
241
        """
 
242
        self.tree = tree
 
243
        self.file_id = file_id
 
244
 
 
245
    def __repr__(self):
 
246
        return "TreeFileCreate(%i)" % self.id
 
247
 
 
248
    def __eq__(self, other):
 
249
        if not isinstance(other, TreeFileCreate):
 
250
            return False
 
251
        return self.tree.get_file_sha1(self.file_id) == \
 
252
            other.tree.get_file_sha1(other.file_id)
 
253
 
 
254
    def __ne__(self, other):
 
255
        return not (self == other)
 
256
 
 
257
    def write_file(self, filename):
 
258
        outfile = file(filename, "wb")
 
259
        for line in self.tree.get_file(self.file_id):
 
260
            outfile.write(line)
 
261
 
 
262
    def same_text(self, filename):
 
263
        in_file = file(filename, "rb")
 
264
        return sha_file(in_file) == self.tree.get_file_sha1(self.file_id)
 
265
 
 
266
    def __call__(self, filename, conflict_handler, reverse):
 
267
        """Create or delete a file
 
268
 
 
269
        :param filename: The name of the file to create
 
270
        :type filename: str
 
271
        :param reverse: Delete the file instead of creating it
 
272
        :type reverse: bool
 
273
        """
 
274
        if not reverse:
 
275
            try:
 
276
                self.write_file(filename)
 
277
            except IOError, e:
 
278
                if e.errno == errno.ENOENT:
 
279
                    if conflict_handler.missing_parent(filename)=="continue":
 
280
                        self.write_file(filename)
 
281
                else:
 
282
                    raise
 
283
 
 
284
        else:
 
285
            try:
 
286
                if not self.same_text(filename):
 
287
                    direction = conflict_handler.wrong_old_contents(filename,
 
288
                        self.tree.get_file(self.file_id).read())
 
289
                    if  direction != "continue":
 
290
                        return
 
291
                os.unlink(filename)
 
292
            except IOError, e:
 
293
                if e.errno != errno.ENOENT:
 
294
                    raise
 
295
                if conflict_handler.missing_for_rm(filename, undo) == "skip":
 
296
                    return
 
297
 
 
298
                    
 
299
 
233
300
def reversed(sequence):
234
301
    max = len(sequence) - 1
235
302
    for i in range(len(sequence)):
302
369
            if mode is not None:
303
370
                os.chmod(filename, mode)
304
371
 
 
372
    def is_creation(self):
 
373
        return self.new_contents is not None and self.old_contents is None
 
374
 
 
375
    def is_deletion(self):
 
376
        return self.old_contents is not None and self.new_contents is None
 
377
 
305
378
class ApplySequence(object):
306
379
    def __init__(self, changes=None):
307
380
        self.changes = []
338
411
        self.base = base
339
412
        self.other = other
340
413
 
 
414
    def is_creation(self):
 
415
        return False
 
416
 
 
417
    def is_deletion(self):
 
418
        return False
 
419
 
341
420
    def __eq__(self, other):
342
421
        if not isinstance(other, Diff3Merge):
343
422
            return False
411
490
    """
412
491
    return ReplaceContents(FileCreate(contents), None)
413
492
 
414
 
def ReplaceFileContents(old_contents, new_contents):
 
493
def ReplaceFileContents(old_tree, new_tree, file_id):
415
494
    """Convenience fucntion to replace the contents of a file.
416
495
    
417
496
    :param old_contents: The contents of the file to replace 
421
500
    :return: A ReplaceContents that will replace the contents of a file a file 
422
501
    :rtype: `ReplaceContents`
423
502
    """
424
 
    return ReplaceContents(FileCreate(old_contents), FileCreate(new_contents))
 
503
    return ReplaceContents(TreeFileCreate(old_tree, file_id), 
 
504
                           TreeFileCreate(new_tree, file_id))
425
505
 
426
506
def CreateSymlink(target):
427
507
    """Convenience fucntion to create a symlink.
590
670
        :param reverse: if true, the changeset is being applied in reverse
591
671
        :rtype: bool
592
672
        """
593
 
        return ((self.new_parent is None and not reverse) or 
594
 
                (self.parent is None and reverse))
 
673
        return self.is_creation(not reverse)
595
674
 
596
675
    def is_creation(self, reverse):
597
676
        """Return true if applying the entry would create a file/directory.
599
678
        :param reverse: if true, the changeset is being applied in reverse
600
679
        :rtype: bool
601
680
        """
602
 
        return ((self.parent is None and not reverse) or 
603
 
                (self.new_parent is None and reverse))
 
681
        if self.contents_change is None:
 
682
            return False
 
683
        if reverse:
 
684
            return self.contents_change.is_deletion()
 
685
        else:
 
686
            return self.contents_change.is_creation()
604
687
 
605
688
    def is_creation_or_deletion(self):
606
689
        """Return true if applying the entry would create or delete a 
608
691
 
609
692
        :rtype: bool
610
693
        """
611
 
        return self.parent is None or self.new_parent is None
 
694
        return self.is_creation(False) or self.is_deletion(False)
612
695
 
613
696
    def get_cset_path(self, mod=False):
614
697
        """Determine the path of the entry according to the changeset.
786
869
    :rtype: (List, List)
787
870
    """
788
871
    source_entries = [x for x in changeset.entries.itervalues() 
789
 
                      if x.needs_rename()]
 
872
                      if x.needs_rename() or x.is_creation_or_deletion()]
790
873
    # these are done from longest path to shortest, to avoid deleting a
791
874
    # parent before its children are deleted/renamed 
792
875
    def longest_to_shortest(entry):
833
916
            entry.apply(path, conflict_handler, reverse)
834
917
            temp_name[entry.id] = None
835
918
 
836
 
        else:
 
919
        elif entry.needs_rename():
837
920
            to_name = os.path.join(temp_dir, str(i))
838
921
            src_path = inventory.get(entry.id)
839
922
            if src_path is not None:
878
961
        if entry.is_creation(reverse):
879
962
            entry.apply(new_path, conflict_handler, reverse)
880
963
            changed_inventory[entry.id] = new_tree_path
881
 
        else:
 
964
        elif entry.needs_rename():
882
965
            if old_path is None:
883
966
                continue
884
967
            try:
1088
1171
    
1089
1172
    #apply changes that don't affect filenames
1090
1173
    for entry in changeset.entries.itervalues():
1091
 
        if not entry.is_creation_or_deletion():
 
1174
        if not entry.is_creation_or_deletion() and not entry.is_boring():
1092
1175
            path = os.path.join(dir, inventory[entry.id])
1093
1176
            entry.apply(path, conflict_handler, reverse)
1094
1177
 
1413
1496
        return None
1414
1497
    kind = tree.kind(file_id)
1415
1498
    if kind == "file":
1416
 
        return FileCreate(tree.get_file(file_id).read())
 
1499
        return TreeFileCreate(tree, file_id)
1417
1500
    elif kind in ("directory", "root_directory"):
1418
1501
        return dir_create
1419
1502
    elif kind == "symlink":