Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/merge.py @ 26768:ac68769a5985
merge.mergestate: only check for merge driver when property is accessed
Otherwise 'hg update --clean', 'hg rebase --abort' etc wouldn't work.
author | Siddharth Agarwal <sid0@fb.com> |
---|---|
date | Thu, 15 Oct 2015 01:04:46 -0700 |
parents | a83110faece1 |
children | 5b00ec4c05cb |
comparison
equal
deleted
inserted
replaced
26767:69a121c378ef | 26768:ac68769a5985 |
---|---|
88 del self.otherctx | 88 del self.otherctx |
89 if node: | 89 if node: |
90 self._local = node | 90 self._local = node |
91 self._other = other | 91 self._other = other |
92 self._mdstate = 'u' | 92 self._mdstate = 'u' |
93 self._readmergedriver = None | |
93 shutil.rmtree(self._repo.join('merge'), True) | 94 shutil.rmtree(self._repo.join('merge'), True) |
94 self._dirty = False | 95 self._dirty = False |
95 | 96 |
96 def _read(self): | 97 def _read(self): |
97 """Analyse each record content to restore a serialized state from disk | 98 """Analyse each record content to restore a serialized state from disk |
103 self._local = None | 104 self._local = None |
104 self._other = None | 105 self._other = None |
105 self._mdstate = 'u' | 106 self._mdstate = 'u' |
106 if 'otherctx' in vars(self): | 107 if 'otherctx' in vars(self): |
107 del self.otherctx | 108 del self.otherctx |
109 self._readmergedriver = None | |
108 records = self._readrecords() | 110 records = self._readrecords() |
109 for rtype, record in records: | 111 for rtype, record in records: |
110 if rtype == 'L': | 112 if rtype == 'L': |
111 self._local = bin(record) | 113 self._local = bin(record) |
112 elif rtype == 'O': | 114 elif rtype == 'O': |
116 mdstate = bits[1] | 118 mdstate = bits[1] |
117 if len(mdstate) != 1 or mdstate not in 'ums': | 119 if len(mdstate) != 1 or mdstate not in 'ums': |
118 # the merge driver should be idempotent, so just rerun it | 120 # the merge driver should be idempotent, so just rerun it |
119 mdstate = 'u' | 121 mdstate = 'u' |
120 | 122 |
121 # protect against the following: | 123 self._readmergedriver = bits[0] |
122 # - A configures a malicious merge driver in their hgrc, then | |
123 # pauses the merge | |
124 # - A edits their hgrc to remove references to the merge driver | |
125 # - A gives a copy of their entire repo, including .hg, to B | |
126 # - B inspects .hgrc and finds it to be clean | |
127 # - B then continues the merge and the malicious merge driver | |
128 # gets invoked | |
129 if self.mergedriver != bits[0]: | |
130 raise error.ConfigError( | |
131 _("merge driver changed since merge started"), | |
132 hint=_("revert merge driver change or abort merge")) | |
133 self._mdstate = mdstate | 124 self._mdstate = mdstate |
134 elif rtype in 'FD': | 125 elif rtype in 'FD': |
135 bits = record.split('\0') | 126 bits = record.split('\0') |
136 self._state[bits[0]] = bits[1:] | 127 self._state[bits[0]] = bits[1:] |
137 elif not rtype.islower(): | 128 elif not rtype.islower(): |
234 raise | 225 raise |
235 return records | 226 return records |
236 | 227 |
237 @util.propertycache | 228 @util.propertycache |
238 def mergedriver(self): | 229 def mergedriver(self): |
239 return self._repo.ui.config('experimental', 'mergedriver') | 230 # protect against the following: |
231 # - A configures a malicious merge driver in their hgrc, then | |
232 # pauses the merge | |
233 # - A edits their hgrc to remove references to the merge driver | |
234 # - A gives a copy of their entire repo, including .hg, to B | |
235 # - B inspects .hgrc and finds it to be clean | |
236 # - B then continues the merge and the malicious merge driver | |
237 # gets invoked | |
238 configmergedriver = self._repo.ui.config('experimental', 'mergedriver') | |
239 if (self._readmergedriver is not None | |
240 and self._readmergedriver != configmergedriver): | |
241 raise error.ConfigError( | |
242 _("merge driver changed since merge started"), | |
243 hint=_("revert merge driver change or abort merge")) | |
244 | |
245 return configmergedriver | |
246 | |
240 @util.propertycache | 247 @util.propertycache |
241 def otherctx(self): | 248 def otherctx(self): |
242 return self._repo[self._other] | 249 return self._repo[self._other] |
243 | 250 |
244 def active(self): | 251 def active(self): |