##// END OF EJS Templates
merge.mergestate: add support for persisting a custom merge driver...
Siddharth Agarwal -
r26649:f618b6aa default
parent child Browse files
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