66 |
66 |
67 def __str__(self): |
67 def __str__(self): |
68 return self.rev + ':' + self.name |
68 return self.rev + ':' + self.name |
69 |
69 |
70 class patchheader(object): |
70 class patchheader(object): |
71 def __init__(self, pf): |
71 def __init__(self, pf, plainmode=False): |
72 def eatdiff(lines): |
72 def eatdiff(lines): |
73 while lines: |
73 while lines: |
74 l = lines[-1] |
74 l = lines[-1] |
75 if (l.startswith("diff -") or |
75 if (l.startswith("diff -") or |
76 l.startswith("Index:") or |
76 l.startswith("Index:") or |
110 # parse values when importing the result of an hg export |
111 # parse values when importing the result of an hg export |
111 if line.startswith("# User "): |
112 if line.startswith("# User "): |
112 user = line[7:] |
113 user = line[7:] |
113 elif line.startswith("# Date "): |
114 elif line.startswith("# Date "): |
114 date = line[7:] |
115 date = line[7:] |
|
116 elif line.startswith("# Parent "): |
|
117 parent = line[9:] |
115 elif not line.startswith("# ") and line: |
118 elif not line.startswith("# ") and line: |
116 message.append(line) |
119 message.append(line) |
117 format = None |
120 format = None |
118 elif line == '# HG changeset patch': |
121 elif line == '# HG changeset patch': |
119 message = [] |
122 message = [] |
124 format = "tag" |
127 format = "tag" |
125 elif (format != "tagdone" and (line.startswith("From: ") or |
128 elif (format != "tagdone" and (line.startswith("From: ") or |
126 line.startswith("from: "))): |
129 line.startswith("from: "))): |
127 user = line[6:] |
130 user = line[6:] |
128 format = "tag" |
131 format = "tag" |
|
132 elif (format != "tagdone" and (line.startswith("Date: ") or |
|
133 line.startswith("date: "))): |
|
134 date = line[6:] |
|
135 format = "tag" |
129 elif format == "tag" and line == "": |
136 elif format == "tag" and line == "": |
130 # when looking for tags (subject: from: etc) they |
137 # when looking for tags (subject: from: etc) they |
131 # end once you find a blank line in the source |
138 # end once you find a blank line in the source |
132 format = "tagdone" |
139 format = "tagdone" |
133 elif message or line: |
140 elif message or line: |
146 |
153 |
147 self.message = message |
154 self.message = message |
148 self.comments = comments |
155 self.comments = comments |
149 self.user = user |
156 self.user = user |
150 self.date = date |
157 self.date = date |
|
158 self.parent = parent |
151 self.haspatch = diffstart > 1 |
159 self.haspatch = diffstart > 1 |
|
160 self.plainmode = plainmode |
152 |
161 |
153 def setuser(self, user): |
162 def setuser(self, user): |
154 if not self.updateheader(['From: ', '# User '], user): |
163 if not self.updateheader(['From: ', '# User '], user): |
155 try: |
164 try: |
156 patchheaderat = self.comments.index('# HG changeset patch') |
165 patchheaderat = self.comments.index('# HG changeset patch') |
157 self.comments.insert(patchheaderat + 1, '# User ' + user) |
166 self.comments.insert(patchheaderat + 1, '# User ' + user) |
158 except ValueError: |
167 except ValueError: |
159 if self._hasheader(['Date: ']): |
168 if self.plainmode or self._hasheader(['Date: ']): |
160 self.comments = ['From: ' + user] + self.comments |
169 self.comments = ['From: ' + user] + self.comments |
161 else: |
170 else: |
162 tmp = ['# HG changeset patch', '# User ' + user, ''] |
171 tmp = ['# HG changeset patch', '# User ' + user, ''] |
163 self.comments = tmp + self.comments |
172 self.comments = tmp + self.comments |
164 self.user = user |
173 self.user = user |
167 if not self.updateheader(['Date: ', '# Date '], date): |
176 if not self.updateheader(['Date: ', '# Date '], date): |
168 try: |
177 try: |
169 patchheaderat = self.comments.index('# HG changeset patch') |
178 patchheaderat = self.comments.index('# HG changeset patch') |
170 self.comments.insert(patchheaderat + 1, '# Date ' + date) |
179 self.comments.insert(patchheaderat + 1, '# Date ' + date) |
171 except ValueError: |
180 except ValueError: |
172 if self._hasheader(['From: ']): |
181 if self.plainmode or self._hasheader(['From: ']): |
173 self.comments = ['Date: ' + date] + self.comments |
182 self.comments = ['Date: ' + date] + self.comments |
174 else: |
183 else: |
175 tmp = ['# HG changeset patch', '# Date ' + date, ''] |
184 tmp = ['# HG changeset patch', '# Date ' + date, ''] |
176 self.comments = tmp + self.comments |
185 self.comments = tmp + self.comments |
177 self.date = date |
186 self.date = date |
|
187 |
|
188 def setparent(self, parent): |
|
189 if not self.updateheader(['# Parent '], parent): |
|
190 try: |
|
191 patchheaderat = self.comments.index('# HG changeset patch') |
|
192 self.comments.insert(patchheaderat + 1, '# Parent ' + parent) |
|
193 except ValueError: |
|
194 pass |
|
195 self.parent = parent |
178 |
196 |
179 def setmessage(self, message): |
197 def setmessage(self, message): |
180 if self.comments: |
198 if self.comments: |
181 self._delmsg() |
199 self._delmsg() |
182 self.message = [message] |
200 self.message = [message] |
243 if gitmode is None: |
261 if gitmode is None: |
244 raise error.ConfigError() |
262 raise error.ConfigError() |
245 self.gitmode = gitmode and 'yes' or 'no' |
263 self.gitmode = gitmode and 'yes' or 'no' |
246 except error.ConfigError: |
264 except error.ConfigError: |
247 self.gitmode = ui.config('mq', 'git', 'auto').lower() |
265 self.gitmode = ui.config('mq', 'git', 'auto').lower() |
|
266 self.plainmode = ui.configbool('mq', 'plain', False) |
248 |
267 |
249 @util.propertycache |
268 @util.propertycache |
250 def applied(self): |
269 def applied(self): |
251 if os.path.exists(self.join(self.status_path)): |
270 if os.path.exists(self.join(self.status_path)): |
252 lines = self.opener(self.status_path).read().splitlines() |
271 lines = self.opener(self.status_path).read().splitlines() |
507 raise util.Abort(_("update returned %d") % ret) |
526 raise util.Abort(_("update returned %d") % ret) |
508 n = repo.commit(ctx.description(), ctx.user(), force=True) |
527 n = repo.commit(ctx.description(), ctx.user(), force=True) |
509 if n is None: |
528 if n is None: |
510 raise util.Abort(_("repo commit failed")) |
529 raise util.Abort(_("repo commit failed")) |
511 try: |
530 try: |
512 ph = patchheader(mergeq.join(patch)) |
531 ph = patchheader(mergeq.join(patch), self.plainmode) |
513 except: |
532 except: |
514 raise util.Abort(_("unable to read %s") % patch) |
533 raise util.Abort(_("unable to read %s") % patch) |
515 |
534 |
516 diffopts = self.patchopts(diffopts, patch) |
535 diffopts = self.patchopts(diffopts, patch) |
517 patchf = self.opener(patch, "w") |
536 patchf = self.opener(patch, "w") |
637 continue |
656 continue |
638 self.ui.status(_("applying %s\n") % patchname) |
657 self.ui.status(_("applying %s\n") % patchname) |
639 pf = os.path.join(patchdir, patchname) |
658 pf = os.path.join(patchdir, patchname) |
640 |
659 |
641 try: |
660 try: |
642 ph = patchheader(self.join(patchname)) |
661 ph = patchheader(self.join(patchname), self.plainmode) |
643 except: |
662 except: |
644 self.ui.warn(_("unable to read %s\n") % patchname) |
663 self.ui.warn(_("unable to read %s\n") % patchname) |
645 err = 1 |
664 err = 1 |
646 break |
665 break |
647 |
666 |
829 wlock = repo.wlock() |
848 wlock = repo.wlock() |
830 try: |
849 try: |
831 # if patch file write fails, abort early |
850 # if patch file write fails, abort early |
832 p = self.opener(patchfn, "w") |
851 p = self.opener(patchfn, "w") |
833 try: |
852 try: |
834 if date: |
853 if self.plainmode: |
|
854 if user: |
|
855 p.write("From: " + user + "\n") |
|
856 if not date: |
|
857 p.write("\n") |
|
858 if date: |
|
859 p.write("Date: %d %d\n\n" % date) |
|
860 else: |
835 p.write("# HG changeset patch\n") |
861 p.write("# HG changeset patch\n") |
|
862 p.write("# Parent " + hex(repo[None].parents()[0].node()) + "\n") |
836 if user: |
863 if user: |
837 p.write("# User " + user + "\n") |
864 p.write("# User " + user + "\n") |
838 p.write("# Date %d %d\n\n" % date) |
865 if date: |
839 elif user: |
866 p.write("# Date %s %s\n\n" % date) |
840 p.write("From: " + user + "\n\n") |
|
841 |
|
842 if hasattr(msg, '__call__'): |
867 if hasattr(msg, '__call__'): |
843 msg = msg() |
868 msg = msg() |
844 commitmsg = msg and msg or ("[mq]: %s" % patchfn) |
869 commitmsg = msg and msg or ("[mq]: %s" % patchfn) |
845 n = repo.commit(commitmsg, user, date, match=match, force=True) |
870 n = repo.commit(commitmsg, user, date, match=match, force=True) |
846 if n is None: |
871 if n is None: |
1212 if repo.changelog.heads(top) != [top]: |
1237 if repo.changelog.heads(top) != [top]: |
1213 raise util.Abort(_("cannot refresh a revision with children")) |
1238 raise util.Abort(_("cannot refresh a revision with children")) |
1214 |
1239 |
1215 cparents = repo.changelog.parents(top) |
1240 cparents = repo.changelog.parents(top) |
1216 patchparent = self.qparents(repo, top) |
1241 patchparent = self.qparents(repo, top) |
1217 ph = patchheader(self.join(patchfn)) |
1242 ph = patchheader(self.join(patchfn), self.plainmode) |
1218 diffopts = self.diffopts({'git': opts.get('git')}, patchfn) |
1243 diffopts = self.diffopts({'git': opts.get('git')}, patchfn) |
1219 if msg: |
1244 if msg: |
1220 ph.setmessage(msg) |
1245 ph.setmessage(msg) |
1221 if newuser: |
1246 if newuser: |
1222 ph.setuser(newuser) |
1247 ph.setuser(newuser) |
1223 if newdate: |
1248 if newdate: |
1224 ph.setdate(newdate) |
1249 ph.setdate(newdate) |
|
1250 ph.setparent(hex(patchparent)) |
1225 |
1251 |
1226 # only commit new patch when write is complete |
1252 # only commit new patch when write is complete |
1227 patchf = self.opener(patchfn, 'w', atomictemp=True) |
1253 patchf = self.opener(patchfn, 'w', atomictemp=True) |
1228 |
1254 |
1229 comments = str(ph) |
1255 comments = str(ph) |
1404 |
1430 |
1405 def qseries(self, repo, missing=None, start=0, length=None, status=None, |
1431 def qseries(self, repo, missing=None, start=0, length=None, status=None, |
1406 summary=False): |
1432 summary=False): |
1407 def displayname(pfx, patchname): |
1433 def displayname(pfx, patchname): |
1408 if summary: |
1434 if summary: |
1409 ph = patchheader(self.join(patchname)) |
1435 ph = patchheader(self.join(patchname), self.plainmode) |
1410 msg = ph.message and ph.message[0] or '' |
1436 msg = ph.message and ph.message[0] or '' |
1411 if self.ui.interactive(): |
1437 if self.ui.interactive(): |
1412 width = util.termwidth() - len(pfx) - len(patchname) - 2 |
1438 width = util.termwidth() - len(pfx) - len(patchname) - 2 |
1413 if width > 0: |
1439 if width > 0: |
1414 msg = util.ellipsis(msg, width) |
1440 msg = util.ellipsis(msg, width) |
2010 ui.write(_("no patches applied\n")) |
2036 ui.write(_("no patches applied\n")) |
2011 return 1 |
2037 return 1 |
2012 if message: |
2038 if message: |
2013 raise util.Abort(_('option "-e" incompatible with "-m" or "-l"')) |
2039 raise util.Abort(_('option "-e" incompatible with "-m" or "-l"')) |
2014 patch = q.applied[-1].name |
2040 patch = q.applied[-1].name |
2015 ph = patchheader(q.join(patch)) |
2041 ph = patchheader(q.join(patch), q.plainmode) |
2016 message = ui.edit('\n'.join(ph.message), ph.user or ui.username()) |
2042 message = ui.edit('\n'.join(ph.message), ph.user or ui.username()) |
2017 setupheaderopts(ui, opts) |
2043 setupheaderopts(ui, opts) |
2018 ret = q.refresh(repo, pats, msg=message, **opts) |
2044 ret = q.refresh(repo, pats, msg=message, **opts) |
2019 q.save_dirty() |
2045 q.save_dirty() |
2020 return ret |
2046 return ret |
2072 raise util.Abort(_('qfold cannot fold already applied patch %s') % p) |
2098 raise util.Abort(_('qfold cannot fold already applied patch %s') % p) |
2073 patches.append(p) |
2099 patches.append(p) |
2074 |
2100 |
2075 for p in patches: |
2101 for p in patches: |
2076 if not message: |
2102 if not message: |
2077 ph = patchheader(q.join(p)) |
2103 ph = patchheader(q.join(p), q.plainmode) |
2078 if ph.message: |
2104 if ph.message: |
2079 messages.append(ph.message) |
2105 messages.append(ph.message) |
2080 pf = q.join(p) |
2106 pf = q.join(p) |
2081 (patchsuccess, files, fuzz) = q.patch(repo, pf) |
2107 (patchsuccess, files, fuzz) = q.patch(repo, pf) |
2082 if not patchsuccess: |
2108 if not patchsuccess: |
2083 raise util.Abort(_('Error folding patch %s') % p) |
2109 raise util.Abort(_('Error folding patch %s') % p) |
2084 patch.updatedir(ui, repo, files) |
2110 patch.updatedir(ui, repo, files) |
2085 |
2111 |
2086 if not message: |
2112 if not message: |
2087 ph = patchheader(q.join(parent)) |
2113 ph = patchheader(q.join(parent), q.plainmode) |
2088 message, user = ph.message, ph.user |
2114 message, user = ph.message, ph.user |
2089 for msg in messages: |
2115 for msg in messages: |
2090 message.append('* * *') |
2116 message.append('* * *') |
2091 message.extend(msg) |
2117 message.extend(msg) |
2092 message = '\n'.join(message) |
2118 message = '\n'.join(message) |
2165 else: |
2191 else: |
2166 if not q.applied: |
2192 if not q.applied: |
2167 ui.write('no patches applied\n') |
2193 ui.write('no patches applied\n') |
2168 return 1 |
2194 return 1 |
2169 patch = q.lookup('qtip') |
2195 patch = q.lookup('qtip') |
2170 ph = patchheader(repo.mq.join(patch)) |
2196 ph = patchheader(q.join(patch), q.plainmode) |
2171 |
2197 |
2172 ui.write('\n'.join(ph.message) + '\n') |
2198 ui.write('\n'.join(ph.message) + '\n') |
2173 |
2199 |
2174 def lastsavename(path): |
2200 def lastsavename(path): |
2175 (directory, base) = os.path.split(path) |
2201 (directory, base) = os.path.split(path) |