~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/changeset.py

Whitespace cleanups.

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
 
36
36
__docformat__ = "restructuredtext"
37
37
 
 
38
 
38
39
NULL_ID = "!NULL"
39
40
 
 
41
 
40
42
class OldFailedTreeOp(Exception):
41
43
    def __init__(self):
42
44
        Exception.__init__(self, "bzr-tree-change contains files from a"
43
45
                           " previous failed merge operation.")
 
46
 
 
47
 
44
48
def invert_dict(dict):
45
49
    newdict = {}
46
50
    for (key,value) in dict.iteritems():
174
178
    def __ne__(self, other):
175
179
        return not (self == other)
176
180
 
 
181
 
177
182
class FileCreate(object):
178
183
    """Create or delete a file (for use with ReplaceContents)"""
179
184
    def __init__(self, contents):
230
235
                if conflict_handler.missing_for_rm(filename, undo) == "skip":
231
236
                    return
232
237
 
 
238
 
233
239
class TreeFileCreate(object):
234
240
    """Create or delete a file (for use with ReplaceContents)"""
235
241
    def __init__(self, tree, file_id):
294
300
                if conflict_handler.missing_for_rm(filename, undo) == "skip":
295
301
                    return
296
302
 
 
303
 
297
304
class ReplaceContents(object):
298
305
    """A contents-replacement framework.  It allows a file/directory/symlink to
299
306
    be created, deleted, or replaced with another file/directory/symlink.
429
436
    """
430
437
    return ReplaceContents(None, dir_create)
431
438
 
 
439
 
432
440
def DeleteDir():
433
441
    """Convenience function to delete a directory.
434
442
 
437
445
    """
438
446
    return ReplaceContents(dir_create, None)
439
447
 
 
448
 
440
449
def CreateFile(contents):
441
450
    """Convenience fucntion to create a file.
442
451
    
447
456
    """
448
457
    return ReplaceContents(None, FileCreate(contents))
449
458
 
 
459
 
450
460
def DeleteFile(contents):
451
461
    """Convenience fucntion to delete a file.
452
462
    
457
467
    """
458
468
    return ReplaceContents(FileCreate(contents), None)
459
469
 
 
470
 
460
471
def ReplaceFileContents(old_tree, new_tree, file_id):
461
472
    """Convenience fucntion to replace the contents of a file.
462
473
    
470
481
    return ReplaceContents(TreeFileCreate(old_tree, file_id), 
471
482
                           TreeFileCreate(new_tree, file_id))
472
483
 
 
484
 
473
485
def CreateSymlink(target):
474
486
    """Convenience fucntion to create a symlink.
475
487
    
480
492
    """
481
493
    return ReplaceContents(None, SymlinkCreate(target))
482
494
 
 
495
 
483
496
def DeleteSymlink(target):
484
497
    """Convenience fucntion to delete a symlink.
485
498
    
490
503
    """
491
504
    return ReplaceContents(SymlinkCreate(target), None)
492
505
 
 
506
 
493
507
def ChangeTarget(old_target, new_target):
494
508
    """Convenience fucntion to change the target of a symlink.
495
509
    
533
547
        msg = 'Child of !NULL is named "%s", not "./.".' % name
534
548
        InvalidEntry.__init__(self, entry, msg)
535
549
 
 
550
 
536
551
class NullIDAssigned(InvalidEntry):
537
552
    """The id !NULL was assigned to a real entry"""
538
553
    def __init__(self, entry):
544
559
        msg = '"!NULL" id assigned to a file "%s".' % entry.path
545
560
        InvalidEntry.__init__(self, entry, msg)
546
561
 
 
562
 
547
563
class ParentIDIsSelf(InvalidEntry):
548
564
    """An entry is marked as its own parent"""
549
565
    def __init__(self, entry):
556
572
            (entry.path, entry.id)
557
573
        InvalidEntry.__init__(self, entry, msg)
558
574
 
 
575
 
559
576
class ChangesetEntry(object):
560
577
    """An entry the changeset"""
561
578
    def __init__(self, id, parent, path):
704
721
        else:
705
722
            return "%s => %s" % (orig_path, mod_path)
706
723
 
707
 
 
708
724
    def get_new_path(self, id_map, changeset):
709
725
        """Determine the full pathname to rename to
710
726
 
772
788
        if not self.is_deletion() and self.metadata_change is not None:
773
789
            self.metadata_change.apply(filename, conflict_handler)
774
790
 
 
791
 
775
792
class IDPresent(Exception):
776
793
    def __init__(self, id):
777
794
        msg = "Cannot add entry because that id has already been used:\n%s" %\
779
796
        Exception.__init__(self, msg)
780
797
        self.id = id
781
798
 
 
799
 
782
800
class Changeset(object):
783
801
    """A set of changes to apply"""
784
802
    def __init__(self):
790
808
            raise IDPresent(entry.id)
791
809
        self.entries[entry.id] = entry
792
810
 
 
811
 
793
812
def get_rename_entries(changeset, inventory):
794
813
    """Return a list of entries that will be renamed.  Entries are sorted from
795
814
    longest to shortest source path and from shortest to longest target path.
825
844
    target_entries.sort(None, shortest_to_longest)
826
845
    return (source_entries, target_entries)
827
846
 
 
847
 
828
848
def rename_to_temp_delete(source_entries, inventory, dir, temp_dir, 
829
849
                          conflict_handler):
830
850
    """Delete and rename entries as appropriate.  Entries are renamed to temp
906
926
                raise BzrCheckError('failed to rename %s to %s for changeset entry %s: %s'
907
927
                        % (old_path, new_path, entry, e))
908
928
 
 
929
 
909
930
class TargetExists(Exception):
910
931
    def __init__(self, entry, target):
911
932
        msg = "The path %s already exists" % target
913
934
        self.entry = entry
914
935
        self.target = target
915
936
 
 
937
 
916
938
class RenameConflict(Exception):
917
939
    def __init__(self, id, this_name, base_name, other_name):
918
940
        msg = """Trees all have different names for a file
925
947
        self.base_name = base_name
926
948
        self_other_name = other_name
927
949
 
 
950
 
928
951
class MoveConflict(Exception):
929
952
    def __init__(self, id, this_parent, base_parent, other_parent):
930
953
        msg = """The file is in different directories in every tree
937
960
        self.base_parent = base_parent
938
961
        self_other_parent = other_parent
939
962
 
 
963
 
940
964
class MergeConflict(Exception):
941
965
    def __init__(self, this_path):
942
966
        Exception.__init__(self, "Conflict applying changes to %s" % this_path)
943
967
        self.this_path = this_path
944
968
 
 
969
 
945
970
class WrongOldContents(Exception):
946
971
    def __init__(self, filename):
947
972
        msg = "Contents mismatch deleting %s" % filename
948
973
        self.filename = filename
949
974
        Exception.__init__(self, msg)
950
975
 
 
976
 
951
977
class WrongOldExecFlag(Exception):
952
978
    def __init__(self, filename, old_exec_flag, new_exec_flag):
953
979
        msg = "Executable flag missmatch on %s:\n" \
955
981
        self.filename = filename
956
982
        Exception.__init__(self, msg)
957
983
 
 
984
 
958
985
class RemoveContentsConflict(Exception):
959
986
    def __init__(self, filename):
960
987
        msg = "Conflict deleting %s, which has different contents in BASE"\
962
989
        self.filename = filename
963
990
        Exception.__init__(self, msg)
964
991
 
 
992
 
965
993
class DeletingNonEmptyDirectory(Exception):
966
994
    def __init__(self, filename):
967
995
        msg = "Trying to remove dir %s while it still had files" % filename
975
1003
        Exception.__init__(self, msg)
976
1004
        self.filename = filename
977
1005
 
 
1006
 
978
1007
class MissingForSetExec(Exception):
979
1008
    def __init__(self, filename):
980
1009
        msg = "Attempt to change permissions on  %s, which does not exist" %\
982
1011
        Exception.__init__(self, msg)
983
1012
        self.filename = filename
984
1013
 
 
1014
 
985
1015
class MissingForRm(Exception):
986
1016
    def __init__(self, filename):
987
1017
        msg = "Attempt to remove missing path %s" % filename
995
1025
        Exception.__init__(self, msg)
996
1026
        self.filename = filename
997
1027
 
 
1028
 
998
1029
class NewContentsConflict(Exception):
999
1030
    def __init__(self, filename):
1000
1031
        msg = "Conflicting contents for new file %s" % (filename)
1001
1032
        Exception.__init__(self, msg)
1002
1033
 
 
1034
 
1003
1035
class WeaveMergeConflict(Exception):
1004
1036
    def __init__(self, filename):
1005
1037
        msg = "Conflicting contents for file %s" % (filename)
1006
1038
        Exception.__init__(self, msg)
1007
1039
 
 
1040
 
1008
1041
class ThreewayContentsConflict(Exception):
1009
1042
    def __init__(self, filename):
1010
1043
        msg = "Conflicting contents for file %s" % (filename)
1091
1124
    def finalize(self):
1092
1125
        pass
1093
1126
 
 
1127
 
1094
1128
def apply_changeset(changeset, inventory, dir, conflict_handler=None):
1095
1129
    """Apply a changeset to a directory.
1096
1130
 
1179
1213
        print entry.id
1180
1214
        print entry.summarize_name(cset)
1181
1215
 
 
1216
 
1182
1217
class UnsupportedFiletype(Exception):
1183
1218
    def __init__(self, kind, full_path):
1184
1219
        msg = "The file \"%s\" is a %s, which is not a supported filetype." \
1187
1222
        self.full_path = full_path
1188
1223
        self.kind = kind
1189
1224
 
 
1225
 
1190
1226
def generate_changeset(tree_a, tree_b, interesting_ids=None):
1191
1227
    return ChangesetGenerator(tree_a, tree_b, interesting_ids)()
1192
1228
 
1281
1317
            return self.make_entry(id, only_interesting=False)
1282
1318
        else:
1283
1319
            return cs_entry
1284
 
        
1285
1320
 
1286
1321
    def make_entry(self, id, only_interesting=True):
1287
1322
        cs_entry = self.make_basic_entry(id, only_interesting)
1338
1373
def full_path(entry, tree):
1339
1374
    return pathjoin(tree.basedir, entry.path)
1340
1375
 
 
1376
 
1341
1377
def new_delete_entry(entry, tree, inventory, delete):
1342
1378
    if entry.path == "":
1343
1379
        parent = NULL_ID
1354
1390
    status = os.lstat(full_path)
1355
1391
    if stat.S_ISDIR(file_stat.st_mode):
1356
1392
        action = dir_create
1357
 
    
1358
 
 
1359
 
 
1360
 
        
 
1393
 
 
1394
 
1361
1395
# XXX: Can't we unify this with the regular inventory object
1362
1396
class Inventory(object):
1363
1397
    def __init__(self, inventory):
1396
1430
        if directory is None:
1397
1431
            return NULL_ID
1398
1432
        return self.get_rinventory().get(directory)
 
1433
 
 
1434