##// END OF EJS Templates
mq: create patch header class to abstract header manipulation
Brendan Cully -
r7399:e71bda2d default
parent child Browse files
Show More
@@ -56,6 +56,67 b' class statusentry:'
56 def __str__(self):
56 def __str__(self):
57 return self.rev + ':' + self.name
57 return self.rev + ':' + self.name
58
58
59 class patchheader(object):
60 def __init__(self, message, comments, user, date, haspatch):
61 self.message = message
62 self.comments = comments
63 self.user = user
64 self.date = date
65 self.haspatch = haspatch
66
67 def setuser(self, user):
68 if not self.setheader(['From: ', '# User '], user):
69 try:
70 patchheaderat = self.comments.index('# HG changeset patch')
71 self.comments.insert(patchheaderat + 1,'# User ' + user)
72 except ValueError:
73 self.comments = ['From: ' + user, ''] + self.comments
74 self.user = user
75
76 def setdate(self, date):
77 if self.setheader(['# Date '], date):
78 self.date = date
79
80 def setmessage(self, message):
81 if self.comments:
82 self._delmsg()
83 self.message = [message]
84 self.comments += self.message
85
86 def setheader(self, prefixes, new):
87 '''Update all references to a field in the patch header.
88 If none found, add it email style.'''
89 res = False
90 for prefix in prefixes:
91 for i in xrange(len(self.comments)):
92 if self.comments[i].startswith(prefix):
93 self.comments[i] = prefix + new
94 res = True
95 break
96 return res
97
98 def __str__(self):
99 if not self.comments:
100 return ''
101 return '\n'.join(self.comments) + '\n\n'
102
103 def _delmsg(self):
104 '''Remove existing message, keeping the rest of the comments fields.
105 If comments contains 'subject: ', message will prepend
106 the field and a blank line.'''
107 if self.message:
108 subj = 'subject: ' + self.message[0].lower()
109 for i in xrange(len(self.comments)):
110 if subj == self.comments[i].lower():
111 del self.comments[i]
112 self.message = self.message[2:]
113 break
114 ci = 0
115 for mi in xrange(len(self.message)):
116 while self.message[mi] != self.comments[ci]:
117 ci += 1
118 del self.comments[ci]
119
59 class queue:
120 class queue:
60 def __init__(self, ui, path, patchdir=None):
121 def __init__(self, ui, path, patchdir=None):
61 self.basepath = path
122 self.basepath = path
@@ -307,7 +368,7 b' class queue:'
307 if format and format.startswith("tag") and subject:
368 if format and format.startswith("tag") and subject:
308 message.insert(0, "")
369 message.insert(0, "")
309 message.insert(0, subject)
370 message.insert(0, subject)
310 return (message, comments, user, date, diffstart > 1)
371 return patchheader(message, comments, user, date, diffstart > 1)
311
372
312 def removeundo(self, repo):
373 def removeundo(self, repo):
313 undo = repo.sjoin('undo')
374 undo = repo.sjoin('undo')
@@ -351,13 +412,13 b' class queue:'
351 if n == None:
412 if n == None:
352 raise util.Abort(_("repo commit failed"))
413 raise util.Abort(_("repo commit failed"))
353 try:
414 try:
354 message, comments, user, date, patchfound = mergeq.readheaders(patch)
415 ph = mergeq.readheaders(patch)
355 except:
416 except:
356 raise util.Abort(_("unable to read %s") % patch)
417 raise util.Abort(_("unable to read %s") % patch)
357
418
358 patchf = self.opener(patch, "w")
419 patchf = self.opener(patch, "w")
420 comments = str(ph)
359 if comments:
421 if comments:
360 comments = "\n".join(comments) + '\n\n'
361 patchf.write(comments)
422 patchf.write(comments)
362 self.printdiff(repo, head, n, fp=patchf)
423 self.printdiff(repo, head, n, fp=patchf)
363 patchf.close()
424 patchf.close()
@@ -477,12 +538,13 b' class queue:'
477 pf = os.path.join(patchdir, patchname)
538 pf = os.path.join(patchdir, patchname)
478
539
479 try:
540 try:
480 message, comments, user, date, patchfound = self.readheaders(patchname)
541 ph = self.readheaders(patchname)
481 except:
542 except:
482 self.ui.warn(_("Unable to read %s\n") % patchname)
543 self.ui.warn(_("Unable to read %s\n") % patchname)
483 err = 1
544 err = 1
484 break
545 break
485
546
547 message = ph.message
486 if not message:
548 if not message:
487 message = _("imported patch %s\n") % patchname
549 message = _("imported patch %s\n") % patchname
488 else:
550 else:
@@ -512,7 +574,7 b' class queue:'
512
574
513 files = patch.updatedir(self.ui, repo, files)
575 files = patch.updatedir(self.ui, repo, files)
514 match = cmdutil.matchfiles(repo, files or [])
576 match = cmdutil.matchfiles(repo, files or [])
515 n = repo.commit(files, message, user, date, match=match,
577 n = repo.commit(files, message, ph.user, ph.date, match=match,
516 force=True)
578 force=True)
517
579
518 if n == None:
580 if n == None:
@@ -522,7 +584,7 b' class queue:'
522 self.applied.append(statusentry(revlog.hex(n), patchname))
584 self.applied.append(statusentry(revlog.hex(n), patchname))
523
585
524 if patcherr:
586 if patcherr:
525 if not patchfound:
587 if not ph.haspatch:
526 self.ui.warn(_("patch %s is empty\n") % patchname)
588 self.ui.warn(_("patch %s is empty\n") % patchname)
527 err = 0
589 err = 0
528 else:
590 else:
@@ -1015,6 +1077,8 b' class queue:'
1015 if len(self.applied) == 0:
1077 if len(self.applied) == 0:
1016 self.ui.write(_("No patches applied\n"))
1078 self.ui.write(_("No patches applied\n"))
1017 return 1
1079 return 1
1080 msg = opts.get('msg', '').rstrip()
1081 newuser = opts.get('user')
1018 newdate = opts.get('date')
1082 newdate = opts.get('date')
1019 if newdate:
1083 if newdate:
1020 newdate = '%d %d' % util.parsedate(newdate)
1084 newdate = '%d %d' % util.parsedate(newdate)
@@ -1027,7 +1091,7 b' class queue:'
1027 raise util.Abort(_("cannot refresh a revision with children"))
1091 raise util.Abort(_("cannot refresh a revision with children"))
1028 cparents = repo.changelog.parents(top)
1092 cparents = repo.changelog.parents(top)
1029 patchparent = self.qparents(repo, top)
1093 patchparent = self.qparents(repo, top)
1030 message, comments, user, date, patchfound = self.readheaders(patchfn)
1094 ph = self.readheaders(patchfn)
1031
1095
1032 patchf = self.opener(patchfn, 'r+')
1096 patchf = self.opener(patchfn, 'r+')
1033
1097
@@ -1037,59 +1101,18 b' class queue:'
1037 self.diffopts().git = True
1101 self.diffopts().git = True
1038 break
1102 break
1039
1103
1040 msg = opts.get('msg', '').rstrip()
1104 if msg:
1041 if msg and comments:
1105 ph.setmessage(msg)
1042 # Remove existing message, keeping the rest of the comments
1043 # fields.
1044 # If comments contains 'subject: ', message will prepend
1045 # the field and a blank line.
1046 if message:
1047 subj = 'subject: ' + message[0].lower()
1048 for i in xrange(len(comments)):
1049 if subj == comments[i].lower():
1050 del comments[i]
1051 message = message[2:]
1052 break
1053 ci = 0
1054 for mi in xrange(len(message)):
1055 while message[mi] != comments[ci]:
1056 ci += 1
1057 del comments[ci]
1058
1059 def setheaderfield(comments, prefixes, new):
1060 # Update all references to a field in the patch header.
1061 # If none found, add it email style.
1062 res = False
1063 for prefix in prefixes:
1064 for i in xrange(len(comments)):
1065 if comments[i].startswith(prefix):
1066 comments[i] = prefix + new
1067 res = True
1068 break
1069 return res
1070
1071 newuser = opts.get('user')
1072 if newuser:
1106 if newuser:
1073 if not setheaderfield(comments, ['From: ', '# User '], newuser):
1107 ph.setuser(newuser)
1074 try:
1075 patchheaderat = comments.index('# HG changeset patch')
1076 comments.insert(patchheaderat + 1,'# User ' + newuser)
1077 except ValueError:
1078 comments = ['From: ' + newuser, ''] + comments
1079 user = newuser
1080
1081 if newdate:
1108 if newdate:
1082 if setheaderfield(comments, ['# Date '], newdate):
1109 ph.setdate(newdate)
1083 date = newdate
1084
1085 if msg:
1086 comments.append(msg)
1087
1110
1088 patchf.seek(0)
1111 patchf.seek(0)
1089 patchf.truncate()
1112 patchf.truncate()
1090
1113
1114 comments = str(ph)
1091 if comments:
1115 if comments:
1092 comments = "\n".join(comments) + '\n\n'
1093 patchf.write(comments)
1116 patchf.write(comments)
1094
1117
1095 if opts.get('git'):
1118 if opts.get('git'):
@@ -1204,22 +1227,21 b' class queue:'
1204 repo.dirstate.forget(f)
1227 repo.dirstate.forget(f)
1205
1228
1206 if not msg:
1229 if not msg:
1207 if not message:
1230 if not ph.message:
1208 message = "[mq]: %s\n" % patchfn
1231 message = "[mq]: %s\n" % patchfn
1209 else:
1232 else:
1210 message = "\n".join(message)
1233 message = "\n".join(ph.message)
1211 else:
1234 else:
1212 message = msg
1235 message = msg
1213
1236
1214 if not user:
1237 user = ph.user or changes[1]
1215 user = changes[1]
1216
1238
1217 self.applied.pop()
1239 self.applied.pop()
1218 self.applied_dirty = 1
1240 self.applied_dirty = 1
1219 self.strip(repo, top, update=False,
1241 self.strip(repo, top, update=False,
1220 backup='strip')
1242 backup='strip')
1221 n = repo.commit(match.files(), message, user, date, match=match,
1243 n = repo.commit(match.files(), message, user, ph.date,
1222 force=1)
1244 match=match, force=1)
1223 self.applied.append(statusentry(revlog.hex(n), patchfn))
1245 self.applied.append(statusentry(revlog.hex(n), patchfn))
1224 self.removeundo(repo)
1246 self.removeundo(repo)
1225 else:
1247 else:
@@ -1273,7 +1295,8 b' class queue:'
1273 summary=False):
1295 summary=False):
1274 def displayname(patchname):
1296 def displayname(patchname):
1275 if summary:
1297 if summary:
1276 msg = self.readheaders(patchname)[0]
1298 ph = self.readheaders(patchname)
1299 msg = ph.message
1277 msg = msg and ': ' + msg[0] or ': '
1300 msg = msg and ': ' + msg[0] or ': '
1278 else:
1301 else:
1279 msg = ''
1302 msg = ''
@@ -1828,8 +1851,8 b' def refresh(ui, repo, *pats, **opts):'
1828 if message:
1851 if message:
1829 raise util.Abort(_('option "-e" incompatible with "-m" or "-l"'))
1852 raise util.Abort(_('option "-e" incompatible with "-m" or "-l"'))
1830 patch = q.applied[-1].name
1853 patch = q.applied[-1].name
1831 (message, comment, user, date, hasdiff) = q.readheaders(patch)
1854 ph = q.readheaders(patch)
1832 message = ui.edit('\n'.join(message), user or ui.username())
1855 message = ui.edit('\n'.join(ph.message), ph.user or ui.username())
1833 setupheaderopts(ui, opts)
1856 setupheaderopts(ui, opts)
1834 ret = q.refresh(repo, pats, msg=message, **opts)
1857 ret = q.refresh(repo, pats, msg=message, **opts)
1835 q.save_dirty()
1858 q.save_dirty()
@@ -1887,7 +1910,8 b' def fold(ui, repo, *files, **opts):'
1887
1910
1888 for p in patches:
1911 for p in patches:
1889 if not message:
1912 if not message:
1890 messages.append(q.readheaders(p)[0])
1913 ph = q.readheaders(p)
1914 messages.append(ph.message)
1891 pf = q.join(p)
1915 pf = q.join(p)
1892 (patchsuccess, files, fuzz) = q.patch(repo, pf)
1916 (patchsuccess, files, fuzz) = q.patch(repo, pf)
1893 if not patchsuccess:
1917 if not patchsuccess:
@@ -1895,7 +1919,8 b' def fold(ui, repo, *files, **opts):'
1895 patch.updatedir(ui, repo, files)
1919 patch.updatedir(ui, repo, files)
1896
1920
1897 if not message:
1921 if not message:
1898 message, comments, user = q.readheaders(parent)[0:3]
1922 ph = q.readheaders(parent)
1923 message, user = ph.message, ph.user
1899 for msg in messages:
1924 for msg in messages:
1900 message.append('* * *')
1925 message.append('* * *')
1901 message.extend(msg)
1926 message.extend(msg)
@@ -1978,9 +2003,9 b' def header(ui, repo, patch=None):'
1978 ui.write('No patches applied\n')
2003 ui.write('No patches applied\n')
1979 return 1
2004 return 1
1980 patch = q.lookup('qtip')
2005 patch = q.lookup('qtip')
1981 message = repo.mq.readheaders(patch)[0]
2006 ph = repo.mq.readheaders(patch)
1982
2007
1983 ui.write('\n'.join(message) + '\n')
2008 ui.write('\n'.join(ph.message) + '\n')
1984
2009
1985 def lastsavename(path):
2010 def lastsavename(path):
1986 (directory, base) = os.path.split(path)
2011 (directory, base) = os.path.split(path)
General Comments 0
You need to be logged in to leave comments. Login now