Changeset 1241 in tailor for vcpx/repository/darcs/source.py
- Timestamp:
- 08/15/06 00:11:26 (7 years ago)
- Hash name:
- 20060814221126-97f81-d54d76cb84ff96793c96fa5b09a762fd389cdc18
- File:
-
- 1 edited
-
vcpx/repository/darcs/source.py (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
vcpx/repository/darcs/source.py
r1222 r1241 14 14 import re 15 15 16 from vcpx.changes import ChangesetEntry, Changeset 16 17 from vcpx.shwrap import ExternalCommand, PIPE, STDOUT 17 18 from vcpx.source import UpdatableSourceWorkingDir, ChangesetApplicationFailure, \ … … 21 22 22 23 24 class DarcsChangeset(Changeset): 25 """ 26 Fixup darcs idiosyncrasies: 27 28 - collapse "add A; rename A B" into "add B" 29 - collapse "rename A B; remove B" into "remove A" 30 """ 31 32 def __init__(self, revision, date, author, log, entries=None, **other): 33 """ 34 Initialize a new DarcsChangeset. 35 """ 36 37 super(DarcsChangeset, self).__init__(revision, date, author, log, entries=None, **other) 38 if entries is not None: 39 for e in entries: 40 self.addEntry(e, revision) 41 42 def addEntry(self, entry, revision): 43 """ 44 Fixup darcs idiosyncrasies: 45 46 - collapse "add A; rename A B" into "add B" 47 - collapse "rename A B; remove B" into "remove A" 48 """ 49 50 # This should not happen, since the parser feeds us an already built 51 # list of ChangesetEntries, anyway... 52 if not isinstance(entry, ChangesetEntry): 53 return super(DarcsChangeset, self).addEntry(entry, revision) 54 55 # Ok, before adding this entry, check it against already 56 # known: if this is an add, and there's a rename (such as "add 57 # A; rename A B; ") then... 58 59 if entry.action_kind == entry.ADDED: 60 # ... we have to check existings, because of a bug in 61 # darcs: `changes --xml` (as of 1.0.7) emits the changes 62 # in the wrong order, that is, it prefers to start with 63 # renames, *always*, even when they obviously follows the 64 # add of the same entry (even, it should apply this "fix" 65 # by its own). 66 # 67 # So, if there's a rename of this entry there, change that 68 # to an addition instead, and don't insert any other entry 69 70 dirname = entry.name+'/' # darcs hopefully use forward slashes also under win 71 72 for i,e in enumerate(self.entries): 73 if e.action_kind == e.RENAMED and e.old_name == entry.name: 74 # Luckily enough (since removes are the first entries 75 # in the list, that is) by anticipating the add we 76 # cure also the case below, when addition follows 77 # edit. 78 e.action_kind = e.ADDED 79 e.old_name = None 80 return e 81 82 # Assert also that add_dir events must preceeds any 83 # add_file and ren_file that have that dir as target, 84 # and that add_file preceeds any edit. 85 86 if ((e.name == entry.name or e.name.startswith(dirname)) 87 or (e.action_kind == e.RENAMED and e.old_name.startswith(dirname))): 88 self.entries.insert(i, entry) 89 return entry 90 91 # Likewise, if this is a deletion, and there is a rename of this 92 # entry (such as "rename A B; remove B") then ... 93 94 elif entry.action_kind == entry.DELETED: 95 # turn the existing rename into a deletion instead 96 97 for i,e in enumerate(self.entries): 98 if e.action_kind == e.RENAMED and e.name == entry.name: 99 e.action_kind = e.DELETED 100 e.name = e.old_name 101 e.old_name = None 102 return e 103 104 # Ok, it must be either an edit or a rename: the former goes 105 # obviously to the end, and since the latter, as said, come 106 # in very early, appending is just good. 107 self.entries.append(entry) 108 return entry 109 110 23 111 def changesets_from_darcschanges(changes, unidiff=False, repodir=None, 24 112 chunksize=2**15): … … 55 143 from xml.sax.handler import ContentHandler, ErrorHandler 56 144 from datetime import datetime 57 from vcpx.changes import ChangesetEntry, Changeset58 145 59 146 class DarcsXMLChangesHandler(ContentHandler): … … 97 184 def endElement(self, name): 98 185 if name == 'patch': 99 entries = [] 100 todo = self.current['entries'] 101 # Darcs allows "rename A B; remove B": collapse those 102 # into "remove A" 103 while todo: 104 e = todo.pop(0) 105 if e.action_kind == e.RENAMED: 106 lookfor = e.name 107 forget = [] 108 for i,n in enumerate(todo): 109 if n.action_kind == n.DELETED and n.name == lookfor: 110 e.action_kind = e.DELETED 111 e.name = e.old_name 112 e.old_name = None 113 entries.append(e) 114 forget.append(i) 115 forget.reverse() 116 for i in forget: 117 del todo[i] 118 break 119 elif n.action_kind == n.RENAMED and n.old_name == lookfor: 120 forget.append(i) 121 lookfor = n.name 122 if not forget: 123 entries.append(e) 124 else: 125 entries.append(e) 126 127 # Darcs changes --xml (as of 1.0.7) emits bad ordered hunks: it 128 # begins with file moves, apparently for no good reason. Do as 129 # little reordering as needed to adjust the meaning, ie moving all 130 # add_dirs before add_file and ren_file that have that dir as 131 # target 132 133 sorted = False 134 while not sorted: 135 sorted = True 136 for i,e in enumerate(entries): 137 if e.action_kind == e.RENAMED: 138 for j,n in enumerate(entries[i+1:]): 139 if ((e.name.startswith(n.name+'/') or e.old_name==n.name) and 140 (n.action_kind == n.ADDED or n.action_kind == n.RENAMED)): 141 m = entries.pop(i+1+j) 142 entries.insert(i, m) 143 sorted = False 144 145 cset = Changeset(self.current['name'], 146 self.current['date'], 147 self.current['author'], 148 self.current['comment'], 149 entries, 150 tags=self.current.get('tags',[])) 186 cset = DarcsChangeset(self.current['name'], 187 self.current['date'], 188 self.current['author'], 189 self.current['comment'], 190 self.current['entries'], 191 tags=self.current.get('tags',[])) 151 192 cset.darcs_hash = self.current['hash'] 152 193 if self.darcsdiff:
Note: See TracChangeset
for help on using the changeset viewer.
