Show More
@@ -61,6 +61,14 b' class mergestate(object):' | |||||
61 | L: the node of the "local" part of the merge (hexified version) |
|
61 | L: the node of the "local" part of the merge (hexified version) | |
62 | O: the node of the "other" part of the merge (hexified version) |
|
62 | O: the node of the "other" part of the merge (hexified version) | |
63 | F: a file to be merged entry |
|
63 | F: a file to be merged entry | |
|
64 | m: the external merge driver defined for this merge plus its run state | |||
|
65 | (experimental) | |||
|
66 | ||||
|
67 | Merge driver run states (experimental): | |||
|
68 | u: driver-resolved files unmarked -- needs to be run next time we're about | |||
|
69 | to resolve or commit | |||
|
70 | m: driver-resolved files marked -- only needs to be run before commit | |||
|
71 | s: success/skipped -- does not need to be run any more | |||
64 | ''' |
|
72 | ''' | |
65 | statepathv1 = 'merge/state' |
|
73 | statepathv1 = 'merge/state' | |
66 | statepathv2 = 'merge/state2' |
|
74 | statepathv2 = 'merge/state2' | |
@@ -77,6 +85,7 b' class mergestate(object):' | |||||
77 | if node: |
|
85 | if node: | |
78 | self._local = node |
|
86 | self._local = node | |
79 | self._other = other |
|
87 | self._other = other | |
|
88 | self._mdstate = 'u' | |||
80 | shutil.rmtree(self._repo.join('merge'), True) |
|
89 | shutil.rmtree(self._repo.join('merge'), True) | |
81 | self._dirty = False |
|
90 | self._dirty = False | |
82 |
|
91 | |||
@@ -89,12 +98,33 b' class mergestate(object):' | |||||
89 | self._state = {} |
|
98 | self._state = {} | |
90 | self._local = None |
|
99 | self._local = None | |
91 | self._other = None |
|
100 | self._other = None | |
|
101 | self._mdstate = 'u' | |||
92 | records = self._readrecords() |
|
102 | records = self._readrecords() | |
93 | for rtype, record in records: |
|
103 | for rtype, record in records: | |
94 | if rtype == 'L': |
|
104 | if rtype == 'L': | |
95 | self._local = bin(record) |
|
105 | self._local = bin(record) | |
96 | elif rtype == 'O': |
|
106 | elif rtype == 'O': | |
97 | self._other = bin(record) |
|
107 | self._other = bin(record) | |
|
108 | elif rtype == 'm': | |||
|
109 | bits = record.split('\0', 1) | |||
|
110 | mdstate = bits[1] | |||
|
111 | if len(mdstate) != 1 or mdstate not in 'ums': | |||
|
112 | # the merge driver should be idempotent, so just rerun it | |||
|
113 | mdstate = 'u' | |||
|
114 | ||||
|
115 | # protect against the following: | |||
|
116 | # - A configures a malicious merge driver in their hgrc, then | |||
|
117 | # pauses the merge | |||
|
118 | # - A edits their hgrc to remove references to the merge driver | |||
|
119 | # - A gives a copy of their entire repo, including .hg, to B | |||
|
120 | # - B inspects .hgrc and finds it to be clean | |||
|
121 | # - B then continues the merge and the malicious merge driver | |||
|
122 | # gets invoked | |||
|
123 | if self.mergedriver != bits[0]: | |||
|
124 | raise error.ConfigError( | |||
|
125 | _("merge driver changed since merge started"), | |||
|
126 | hint=_("revert merge driver change or abort merge")) | |||
|
127 | self._mdstate = mdstate | |||
98 | elif rtype == 'F': |
|
128 | elif rtype == 'F': | |
99 | bits = record.split('\0') |
|
129 | bits = record.split('\0') | |
100 | self._state[bits[0]] = bits[1:] |
|
130 | self._state[bits[0]] = bits[1:] | |
@@ -198,6 +228,10 b' class mergestate(object):' | |||||
198 | raise |
|
228 | raise | |
199 | return records |
|
229 | return records | |
200 |
|
230 | |||
|
231 | @util.propertycache | |||
|
232 | def mergedriver(self): | |||
|
233 | return self._repo.ui.config('experimental', 'mergedriver') | |||
|
234 | ||||
201 | def active(self): |
|
235 | def active(self): | |
202 | """Whether mergestate is active. |
|
236 | """Whether mergestate is active. | |
203 |
|
237 | |||
@@ -216,6 +250,9 b' class mergestate(object):' | |||||
216 | records = [] |
|
250 | records = [] | |
217 | records.append(('L', hex(self._local))) |
|
251 | records.append(('L', hex(self._local))) | |
218 | records.append(('O', hex(self._other))) |
|
252 | records.append(('O', hex(self._other))) | |
|
253 | if self.mergedriver: | |||
|
254 | records.append(('m', '\0'.join([ | |||
|
255 | self.mergedriver, self._mdstate]))) | |||
219 | for d, v in self._state.iteritems(): |
|
256 | for d, v in self._state.iteritems(): | |
220 | records.append(('F', '\0'.join([d] + v))) |
|
257 | records.append(('F', '\0'.join([d] + v))) | |
221 | self._writerecords(records) |
|
258 | self._writerecords(records) |
General Comments 0
You need to be logged in to leave comments.
Login now