annotate hgext/patchbomb.py @ 2320:dbdce3b99988

fix parsing of tags. make parse errors useful. add new tag tests. old code read every head of .hgtags. delete and recreate of .hgtags gave new head, but if error in deleted rev, .hgtags had error messages every time it was parsed. this was very hard to fix, because deleted revs hard to get back and update, needed merges too. new code reads .hgtags on every head. advantage is if parse error happens with new code, is possible to fix them by editing .hgtags on a head and committing. NOTE: new code uses binary search of manifest of each head to be fast, but still much slower than old code. best thing would be to have delete record stored in filelog so we never touch manifest. could find live heads directly from filelog. this is more work than i want now. new tests check for parse of tags on different heads, and inaccessible heads created by delete and recreate of .hgtags.
author Vadim Gelfer <vadim.gelfer@gmail.com>
date Thu, 18 May 2006 23:31:12 -0700
parents 903ab41ac7eb
children bd9c39e8f38b
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1669
91d40fc959f0 turn patchbomb script into an extension module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1604
diff changeset
1 # Command for sending a collection of Mercurial changesets as a series
91d40fc959f0 turn patchbomb script into an extension module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1604
diff changeset
2 # of patch emails.
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
3 #
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
4 # The series is started off with a "[PATCH 0 of N]" introduction,
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
5 # which describes the series as a whole.
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
6 #
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
7 # Each patch email has a Subject line of "[PATCH M of N] ...", using
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
8 # the first line of the changeset description as the subject text.
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
9 # The message contains two or three body parts:
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
10 #
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
11 # The remainder of the changeset description.
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
12 #
877
25430c523677 Polish patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents: 876
diff changeset
13 # [Optional] If the diffstat program is installed, the result of
25430c523677 Polish patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents: 876
diff changeset
14 # running diffstat on the patch.
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
15 #
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
16 # The patch itself, as generated by "hg export".
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
17 #
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
18 # Each message refers to all of its predecessors using the In-Reply-To
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
19 # and References headers, so they will show up as a sequence in
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
20 # threaded mail and news readers, and in mail archives.
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
21 #
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
22 # For each changeset, you will be prompted with a diffstat summary and
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
23 # the changeset summary, so you can be sure you are sending the right
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
24 # changes.
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
25 #
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
26 # It is best to run this script with the "-n" (test only) flag before
877
25430c523677 Polish patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents: 876
diff changeset
27 # firing it up "for real", in which case it will use your pager to
25430c523677 Polish patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents: 876
diff changeset
28 # display each of the messages that it would send.
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
29 #
1702
e291d9a30bef add --mbox output to patchbomb
Johannes Stezenbach <js@linuxtv.org>
parents: 1691
diff changeset
30 # The "-m" (mbox) option will create an mbox file instead of sending
e291d9a30bef add --mbox output to patchbomb
Johannes Stezenbach <js@linuxtv.org>
parents: 1691
diff changeset
31 # the messages directly. This can be reviewed e.g. with "mutt -R -f mbox",
e291d9a30bef add --mbox output to patchbomb
Johannes Stezenbach <js@linuxtv.org>
parents: 1691
diff changeset
32 # and finally sent with "formail -s sendmail -bm -t < mbox".
e291d9a30bef add --mbox output to patchbomb
Johannes Stezenbach <js@linuxtv.org>
parents: 1691
diff changeset
33 #
877
25430c523677 Polish patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents: 876
diff changeset
34 # To configure other defaults, add a section like this to your hgrc
25430c523677 Polish patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents: 876
diff changeset
35 # file:
25430c523677 Polish patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents: 876
diff changeset
36 #
2198
564034552f7f rename [patchbomb] section to [email] section in hgrc. old name still ok.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2165
diff changeset
37 # [email]
877
25430c523677 Polish patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents: 876
diff changeset
38 # from = My Name <my@email>
25430c523677 Polish patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents: 876
diff changeset
39 # to = recipient1, recipient2, ...
25430c523677 Polish patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents: 876
diff changeset
40 # cc = cc1, cc2, ...
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
41
1827
26dd4ae77b7b get patchbomb extension to use demandload. speeds up hg startup by 50%.
Vadim Gelfer <vadim.gelger@gmail.com>
parents: 1702
diff changeset
42 from mercurial.demandload import *
26dd4ae77b7b get patchbomb extension to use demandload. speeds up hg startup by 50%.
Vadim Gelfer <vadim.gelger@gmail.com>
parents: 1702
diff changeset
43 demandload(globals(), '''email.MIMEMultipart email.MIMEText email.Utils
26dd4ae77b7b get patchbomb extension to use demandload. speeds up hg startup by 50%.
Vadim Gelfer <vadim.gelger@gmail.com>
parents: 1702
diff changeset
44 mercurial:commands,hg,ui
2200
9f43b6e24232 move mail sending code into core, so extensions can share it.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2198
diff changeset
45 os errno popen2 socket sys tempfile time''')
1671
ba30c17d55f6 forgot to add import statement for _.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1670
diff changeset
46 from mercurial.i18n import gettext as _
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
47
1204
b0f6053df539 patchbomb: continue if we can't import readline.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1154
diff changeset
48 try:
b0f6053df539 patchbomb: continue if we can't import readline.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1154
diff changeset
49 # readline gives raw_input editing capabilities, but is not
b0f6053df539 patchbomb: continue if we can't import readline.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1154
diff changeset
50 # present on windows
b0f6053df539 patchbomb: continue if we can't import readline.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1154
diff changeset
51 import readline
b0f6053df539 patchbomb: continue if we can't import readline.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1154
diff changeset
52 except ImportError: pass
b0f6053df539 patchbomb: continue if we can't import readline.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1154
diff changeset
53
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
54 def diffstat(patch):
2165
d821918e3bee Use better names (hg-{usage}-{random}.{suffix}) for temporary files.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1871
diff changeset
55 fd, name = tempfile.mkstemp(prefix="hg-patchbomb-", suffix=".txt")
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
56 try:
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
57 p = popen2.Popen3('diffstat -p1 -w79 2>/dev/null > ' + name)
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
58 try:
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
59 for line in patch: print >> p.tochild, line
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
60 p.tochild.close()
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
61 if p.wait(): return
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
62 fp = os.fdopen(fd, 'r')
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
63 stat = []
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
64 for line in fp: stat.append(line.lstrip())
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
65 last = stat.pop()
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
66 stat.insert(0, last)
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
67 stat = ''.join(stat)
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
68 if stat.startswith('0 files'): raise ValueError
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
69 return stat
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
70 except: raise
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
71 finally:
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
72 try: os.unlink(name)
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
73 except: pass
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
74
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
75 def patchbomb(ui, repo, *revs, **opts):
1672
07f931af5f40 add documentation for email command.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1670
diff changeset
76 '''send changesets as a series of patch emails
07f931af5f40 add documentation for email command.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1670
diff changeset
77
07f931af5f40 add documentation for email command.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1670
diff changeset
78 The series starts with a "[PATCH 0 of N]" introduction, which
07f931af5f40 add documentation for email command.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1670
diff changeset
79 describes the series as a whole.
07f931af5f40 add documentation for email command.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1670
diff changeset
80
07f931af5f40 add documentation for email command.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1670
diff changeset
81 Each patch email has a Subject line of "[PATCH M of N] ...", using
07f931af5f40 add documentation for email command.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1670
diff changeset
82 the first line of the changeset description as the subject text.
07f931af5f40 add documentation for email command.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1670
diff changeset
83 The message contains two or three body parts. First, the rest of
07f931af5f40 add documentation for email command.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1670
diff changeset
84 the changeset description. Next, (optionally) if the diffstat
07f931af5f40 add documentation for email command.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1670
diff changeset
85 program is installed, the result of running diffstat on the patch.
07f931af5f40 add documentation for email command.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1670
diff changeset
86 Finally, the patch itself, as generated by "hg export".'''
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
87 def prompt(prompt, default = None, rest = ': ', empty_ok = False):
876
14cfaaec2e8e Get patchbomb script to not use MIME attachments.
Bryan O'Sullivan <bos@serpentine.com>
parents: 875
diff changeset
88 if default: prompt += ' [%s]' % default
14cfaaec2e8e Get patchbomb script to not use MIME attachments.
Bryan O'Sullivan <bos@serpentine.com>
parents: 875
diff changeset
89 prompt += rest
14cfaaec2e8e Get patchbomb script to not use MIME attachments.
Bryan O'Sullivan <bos@serpentine.com>
parents: 875
diff changeset
90 while True:
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
91 r = raw_input(prompt)
876
14cfaaec2e8e Get patchbomb script to not use MIME attachments.
Bryan O'Sullivan <bos@serpentine.com>
parents: 875
diff changeset
92 if r: return r
14cfaaec2e8e Get patchbomb script to not use MIME attachments.
Bryan O'Sullivan <bos@serpentine.com>
parents: 875
diff changeset
93 if default is not None: return default
14cfaaec2e8e Get patchbomb script to not use MIME attachments.
Bryan O'Sullivan <bos@serpentine.com>
parents: 875
diff changeset
94 if empty_ok: return r
1670
fe19c54ee403 add _ to several strings
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1669
diff changeset
95 ui.warn(_('Please enter a valid value.\n'))
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
96
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
97 def confirm(s):
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
98 if not prompt(s, default = 'y', rest = '? ').lower().startswith('y'):
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
99 raise ValueError
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
100
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
101 def cdiffstat(summary, patch):
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
102 s = diffstat(patch)
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
103 if s:
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
104 if summary:
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
105 ui.write(summary, '\n')
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
106 ui.write(s, '\n')
1670
fe19c54ee403 add _ to several strings
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1669
diff changeset
107 confirm(_('Does the diffstat above look okay'))
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
108 return s
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
109
876
14cfaaec2e8e Get patchbomb script to not use MIME attachments.
Bryan O'Sullivan <bos@serpentine.com>
parents: 875
diff changeset
110 def makepatch(patch, idx, total):
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
111 desc = []
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
112 node = None
1135
e455d91f6259 Variable 'body' was missing in patchbomb script.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1118
diff changeset
113 body = ''
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
114 for line in patch:
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
115 if line.startswith('#'):
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
116 if line.startswith('# Node ID'): node = line.split()[-1]
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
117 continue
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
118 if line.startswith('diff -r'): break
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
119 desc.append(line)
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
120 if not node: raise ValueError
1118
63b5f68d8167 patchbomb: eliminate silly complete summary message
mpm@selenic.com
parents: 1032
diff changeset
121
63b5f68d8167 patchbomb: eliminate silly complete summary message
mpm@selenic.com
parents: 1032
diff changeset
122 #body = ('\n'.join(desc[1:]).strip() or
63b5f68d8167 patchbomb: eliminate silly complete summary message
mpm@selenic.com
parents: 1032
diff changeset
123 # 'Patch subject is complete summary.')
63b5f68d8167 patchbomb: eliminate silly complete summary message
mpm@selenic.com
parents: 1032
diff changeset
124 #body += '\n\n\n'
63b5f68d8167 patchbomb: eliminate silly complete summary message
mpm@selenic.com
parents: 1032
diff changeset
125
1604
da3f1121721b add --plain option to patchbomb.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1603
diff changeset
126 if opts['plain']:
da3f1121721b add --plain option to patchbomb.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1603
diff changeset
127 while patch and patch[0].startswith('# '): patch.pop(0)
da3f1121721b add --plain option to patchbomb.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1603
diff changeset
128 if patch: patch.pop(0)
da3f1121721b add --plain option to patchbomb.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1603
diff changeset
129 while patch and not patch[0].strip(): patch.pop(0)
877
25430c523677 Polish patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents: 876
diff changeset
130 if opts['diffstat']:
25430c523677 Polish patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents: 876
diff changeset
131 body += cdiffstat('\n'.join(desc), patch) + '\n\n'
876
14cfaaec2e8e Get patchbomb script to not use MIME attachments.
Bryan O'Sullivan <bos@serpentine.com>
parents: 875
diff changeset
132 body += '\n'.join(patch)
1827
26dd4ae77b7b get patchbomb extension to use demandload. speeds up hg startup by 50%.
Vadim Gelfer <vadim.gelger@gmail.com>
parents: 1702
diff changeset
133 msg = email.MIMEText.MIMEText(body)
1846
4d2791f4ef80 only put numbers on patches if > 1 patch.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1845
diff changeset
134 if total == 1:
4d2791f4ef80 only put numbers on patches if > 1 patch.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1845
diff changeset
135 subj = '[PATCH] ' + desc[0].strip()
4d2791f4ef80 only put numbers on patches if > 1 patch.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1845
diff changeset
136 else:
4d2791f4ef80 only put numbers on patches if > 1 patch.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1845
diff changeset
137 subj = '[PATCH %d of %d] %s' % (idx, total, desc[0].strip())
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
138 if subj.endswith('.'): subj = subj[:-1]
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
139 msg['Subject'] = subj
876
14cfaaec2e8e Get patchbomb script to not use MIME attachments.
Bryan O'Sullivan <bos@serpentine.com>
parents: 875
diff changeset
140 msg['X-Mercurial-Node'] = node
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
141 return msg
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
142
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
143 start_time = int(time.time())
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
144
876
14cfaaec2e8e Get patchbomb script to not use MIME attachments.
Bryan O'Sullivan <bos@serpentine.com>
parents: 875
diff changeset
145 def genmsgid(id):
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
146 return '<%s.%s@%s>' % (id[:20], start_time, socket.getfqdn())
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
147
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
148 patches = []
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
149
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
150 class exportee:
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
151 def __init__(self, container):
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
152 self.lines = []
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
153 self.container = container
876
14cfaaec2e8e Get patchbomb script to not use MIME attachments.
Bryan O'Sullivan <bos@serpentine.com>
parents: 875
diff changeset
154 self.name = 'email'
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
155
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
156 def write(self, data):
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
157 self.lines.append(data)
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
158
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
159 def close(self):
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
160 self.container.append(''.join(self.lines).split('\n'))
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
161 self.lines = []
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
162
1669
91d40fc959f0 turn patchbomb script into an extension module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1604
diff changeset
163 commands.export(ui, repo, *revs, **{'output': exportee(patches),
1603
5352a5407dc1 make patchbomb work with recent changes to export
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1226
diff changeset
164 'switch_parent': False,
1032
706c590c9060 Get patchbomb working with tip again.
Bryan O'Sullivan <bos@serpentine.com>
parents: 998
diff changeset
165 'text': None})
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
166
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
167 jumbo = []
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
168 msgs = []
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
169
1670
fe19c54ee403 add _ to several strings
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1669
diff changeset
170 ui.write(_('This patch series consists of %d patches.\n\n') % len(patches))
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
171
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
172 for p, i in zip(patches, range(len(patches))):
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
173 jumbo.extend(p)
876
14cfaaec2e8e Get patchbomb script to not use MIME attachments.
Bryan O'Sullivan <bos@serpentine.com>
parents: 875
diff changeset
174 msgs.append(makepatch(p, i + 1, len(patches)))
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
175
2198
564034552f7f rename [patchbomb] section to [email] section in hgrc. old name still ok.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2165
diff changeset
176 sender = (opts['from'] or ui.config('email', 'from') or
564034552f7f rename [patchbomb] section to [email] section in hgrc. old name still ok.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2165
diff changeset
177 ui.config('patchbomb', 'from') or
877
25430c523677 Polish patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents: 876
diff changeset
178 prompt('From', ui.username()))
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
179
1154
c3cb9f39a91f patchbomb: fix up confusion between strings and lists of strings.
bos@serpentine.internal.keyresearch.com
parents: 1136
diff changeset
180 def getaddrs(opt, prpt, default = None):
2198
564034552f7f rename [patchbomb] section to [email] section in hgrc. old name still ok.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2165
diff changeset
181 addrs = opts[opt] or (ui.config('email', opt) or
564034552f7f rename [patchbomb] section to [email] section in hgrc. old name still ok.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2165
diff changeset
182 ui.config('patchbomb', opt) or
1154
c3cb9f39a91f patchbomb: fix up confusion between strings and lists of strings.
bos@serpentine.internal.keyresearch.com
parents: 1136
diff changeset
183 prompt(prpt, default = default)).split(',')
c3cb9f39a91f patchbomb: fix up confusion between strings and lists of strings.
bos@serpentine.internal.keyresearch.com
parents: 1136
diff changeset
184 return [a.strip() for a in addrs if a.strip()]
c3cb9f39a91f patchbomb: fix up confusion between strings and lists of strings.
bos@serpentine.internal.keyresearch.com
parents: 1136
diff changeset
185 to = getaddrs('to', 'To')
c3cb9f39a91f patchbomb: fix up confusion between strings and lists of strings.
bos@serpentine.internal.keyresearch.com
parents: 1136
diff changeset
186 cc = getaddrs('cc', 'Cc', '')
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
187
1845
cfe689ab3f06 Patchbomb only sends introductory message [0 of N] if there are multiple patches.
Lee Cantey <lcantey@gmail.com>
parents: 1827
diff changeset
188 if len(patches) > 1:
cfe689ab3f06 Patchbomb only sends introductory message [0 of N] if there are multiple patches.
Lee Cantey <lcantey@gmail.com>
parents: 1827
diff changeset
189 ui.write(_('\nWrite the introductory message for the patch series.\n\n'))
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
190
1845
cfe689ab3f06 Patchbomb only sends introductory message [0 of N] if there are multiple patches.
Lee Cantey <lcantey@gmail.com>
parents: 1827
diff changeset
191 msg = email.MIMEMultipart.MIMEMultipart()
cfe689ab3f06 Patchbomb only sends introductory message [0 of N] if there are multiple patches.
Lee Cantey <lcantey@gmail.com>
parents: 1827
diff changeset
192 msg['Subject'] = '[PATCH 0 of %d] %s' % (
cfe689ab3f06 Patchbomb only sends introductory message [0 of N] if there are multiple patches.
Lee Cantey <lcantey@gmail.com>
parents: 1827
diff changeset
193 len(patches),
cfe689ab3f06 Patchbomb only sends introductory message [0 of N] if there are multiple patches.
Lee Cantey <lcantey@gmail.com>
parents: 1827
diff changeset
194 opts['subject'] or
cfe689ab3f06 Patchbomb only sends introductory message [0 of N] if there are multiple patches.
Lee Cantey <lcantey@gmail.com>
parents: 1827
diff changeset
195 prompt('Subject:', rest = ' [PATCH 0 of %d] ' % len(patches)))
cfe689ab3f06 Patchbomb only sends introductory message [0 of N] if there are multiple patches.
Lee Cantey <lcantey@gmail.com>
parents: 1827
diff changeset
196
cfe689ab3f06 Patchbomb only sends introductory message [0 of N] if there are multiple patches.
Lee Cantey <lcantey@gmail.com>
parents: 1827
diff changeset
197 ui.write(_('Finish with ^D or a dot on a line by itself.\n\n'))
cfe689ab3f06 Patchbomb only sends introductory message [0 of N] if there are multiple patches.
Lee Cantey <lcantey@gmail.com>
parents: 1827
diff changeset
198
cfe689ab3f06 Patchbomb only sends introductory message [0 of N] if there are multiple patches.
Lee Cantey <lcantey@gmail.com>
parents: 1827
diff changeset
199 body = []
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
200
1845
cfe689ab3f06 Patchbomb only sends introductory message [0 of N] if there are multiple patches.
Lee Cantey <lcantey@gmail.com>
parents: 1827
diff changeset
201 while True:
cfe689ab3f06 Patchbomb only sends introductory message [0 of N] if there are multiple patches.
Lee Cantey <lcantey@gmail.com>
parents: 1827
diff changeset
202 try: l = raw_input()
cfe689ab3f06 Patchbomb only sends introductory message [0 of N] if there are multiple patches.
Lee Cantey <lcantey@gmail.com>
parents: 1827
diff changeset
203 except EOFError: break
cfe689ab3f06 Patchbomb only sends introductory message [0 of N] if there are multiple patches.
Lee Cantey <lcantey@gmail.com>
parents: 1827
diff changeset
204 if l == '.': break
cfe689ab3f06 Patchbomb only sends introductory message [0 of N] if there are multiple patches.
Lee Cantey <lcantey@gmail.com>
parents: 1827
diff changeset
205 body.append(l)
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
206
1845
cfe689ab3f06 Patchbomb only sends introductory message [0 of N] if there are multiple patches.
Lee Cantey <lcantey@gmail.com>
parents: 1827
diff changeset
207 msg.attach(email.MIMEText.MIMEText('\n'.join(body) + '\n'))
cfe689ab3f06 Patchbomb only sends introductory message [0 of N] if there are multiple patches.
Lee Cantey <lcantey@gmail.com>
parents: 1827
diff changeset
208
cfe689ab3f06 Patchbomb only sends introductory message [0 of N] if there are multiple patches.
Lee Cantey <lcantey@gmail.com>
parents: 1827
diff changeset
209 if opts['diffstat']:
cfe689ab3f06 Patchbomb only sends introductory message [0 of N] if there are multiple patches.
Lee Cantey <lcantey@gmail.com>
parents: 1827
diff changeset
210 d = cdiffstat(_('Final summary:\n'), jumbo)
cfe689ab3f06 Patchbomb only sends introductory message [0 of N] if there are multiple patches.
Lee Cantey <lcantey@gmail.com>
parents: 1827
diff changeset
211 if d: msg.attach(email.MIMEText.MIMEText(d))
cfe689ab3f06 Patchbomb only sends introductory message [0 of N] if there are multiple patches.
Lee Cantey <lcantey@gmail.com>
parents: 1827
diff changeset
212
cfe689ab3f06 Patchbomb only sends introductory message [0 of N] if there are multiple patches.
Lee Cantey <lcantey@gmail.com>
parents: 1827
diff changeset
213 msgs.insert(0, msg)
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
214
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
215 ui.write('\n')
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
216
1702
e291d9a30bef add --mbox output to patchbomb
Johannes Stezenbach <js@linuxtv.org>
parents: 1691
diff changeset
217 if not opts['test'] and not opts['mbox']:
2200
9f43b6e24232 move mail sending code into core, so extensions can share it.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2198
diff changeset
218 mail = ui.sendmail()
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
219 parent = None
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
220 tz = time.strftime('%z')
1827
26dd4ae77b7b get patchbomb extension to use demandload. speeds up hg startup by 50%.
Vadim Gelfer <vadim.gelger@gmail.com>
parents: 1702
diff changeset
221 sender_addr = email.Utils.parseaddr(sender)[1]
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
222 for m in msgs:
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
223 try:
876
14cfaaec2e8e Get patchbomb script to not use MIME attachments.
Bryan O'Sullivan <bos@serpentine.com>
parents: 875
diff changeset
224 m['Message-Id'] = genmsgid(m['X-Mercurial-Node'])
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
225 except TypeError:
876
14cfaaec2e8e Get patchbomb script to not use MIME attachments.
Bryan O'Sullivan <bos@serpentine.com>
parents: 875
diff changeset
226 m['Message-Id'] = genmsgid('patchbomb')
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
227 if parent:
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
228 m['In-Reply-To'] = parent
876
14cfaaec2e8e Get patchbomb script to not use MIME attachments.
Bryan O'Sullivan <bos@serpentine.com>
parents: 875
diff changeset
229 else:
14cfaaec2e8e Get patchbomb script to not use MIME attachments.
Bryan O'Sullivan <bos@serpentine.com>
parents: 875
diff changeset
230 parent = m['Message-Id']
877
25430c523677 Polish patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents: 876
diff changeset
231 m['Date'] = time.strftime('%a, %e %b %Y %T ', time.localtime(start_time)) + tz
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
232 start_time += 1
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
233 m['From'] = sender
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
234 m['To'] = ', '.join(to)
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
235 if cc: m['Cc'] = ', '.join(cc)
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
236 if opts['test']:
1702
e291d9a30bef add --mbox output to patchbomb
Johannes Stezenbach <js@linuxtv.org>
parents: 1691
diff changeset
237 ui.status('Displaying ', m['Subject'], ' ...\n')
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
238 fp = os.popen(os.getenv('PAGER', 'more'), 'w')
1871
258e3a7955b8 patchbomb: ignore exception if pager quits.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1846
diff changeset
239 try:
258e3a7955b8 patchbomb: ignore exception if pager quits.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1846
diff changeset
240 fp.write(m.as_string(0))
258e3a7955b8 patchbomb: ignore exception if pager quits.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1846
diff changeset
241 fp.write('\n')
258e3a7955b8 patchbomb: ignore exception if pager quits.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1846
diff changeset
242 except IOError, inst:
258e3a7955b8 patchbomb: ignore exception if pager quits.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1846
diff changeset
243 if inst.errno != errno.EPIPE:
258e3a7955b8 patchbomb: ignore exception if pager quits.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1846
diff changeset
244 raise
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
245 fp.close()
1702
e291d9a30bef add --mbox output to patchbomb
Johannes Stezenbach <js@linuxtv.org>
parents: 1691
diff changeset
246 elif opts['mbox']:
e291d9a30bef add --mbox output to patchbomb
Johannes Stezenbach <js@linuxtv.org>
parents: 1691
diff changeset
247 ui.status('Writing ', m['Subject'], ' ...\n')
e291d9a30bef add --mbox output to patchbomb
Johannes Stezenbach <js@linuxtv.org>
parents: 1691
diff changeset
248 fp = open(opts['mbox'], m.has_key('In-Reply-To') and 'ab+' or 'wb+')
e291d9a30bef add --mbox output to patchbomb
Johannes Stezenbach <js@linuxtv.org>
parents: 1691
diff changeset
249 date = time.asctime(time.localtime(start_time))
e291d9a30bef add --mbox output to patchbomb
Johannes Stezenbach <js@linuxtv.org>
parents: 1691
diff changeset
250 fp.write('From %s %s\n' % (sender_addr, date))
e291d9a30bef add --mbox output to patchbomb
Johannes Stezenbach <js@linuxtv.org>
parents: 1691
diff changeset
251 fp.write(m.as_string(0))
e291d9a30bef add --mbox output to patchbomb
Johannes Stezenbach <js@linuxtv.org>
parents: 1691
diff changeset
252 fp.write('\n\n')
e291d9a30bef add --mbox output to patchbomb
Johannes Stezenbach <js@linuxtv.org>
parents: 1691
diff changeset
253 fp.close()
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
254 else:
1702
e291d9a30bef add --mbox output to patchbomb
Johannes Stezenbach <js@linuxtv.org>
parents: 1691
diff changeset
255 ui.status('Sending ', m['Subject'], ' ...\n')
2200
9f43b6e24232 move mail sending code into core, so extensions can share it.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2198
diff changeset
256 mail.sendmail(sender, to + cc, m.as_string(0))
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
257
1669
91d40fc959f0 turn patchbomb script into an extension module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1604
diff changeset
258 cmdtable = {
91d40fc959f0 turn patchbomb script into an extension module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1604
diff changeset
259 'email':
91d40fc959f0 turn patchbomb script into an extension module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1604
diff changeset
260 (patchbomb,
91d40fc959f0 turn patchbomb script into an extension module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1604
diff changeset
261 [('c', 'cc', [], 'email addresses of copy recipients'),
91d40fc959f0 turn patchbomb script into an extension module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1604
diff changeset
262 ('d', 'diffstat', None, 'add diffstat output to messages'),
91d40fc959f0 turn patchbomb script into an extension module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1604
diff changeset
263 ('f', 'from', '', 'email address of sender'),
91d40fc959f0 turn patchbomb script into an extension module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1604
diff changeset
264 ('', 'plain', None, 'omit hg patch header'),
91d40fc959f0 turn patchbomb script into an extension module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1604
diff changeset
265 ('n', 'test', None, 'print messages that would be sent'),
1702
e291d9a30bef add --mbox output to patchbomb
Johannes Stezenbach <js@linuxtv.org>
parents: 1691
diff changeset
266 ('m', 'mbox', '', 'write messages to mbox file instead of sending them'),
1669
91d40fc959f0 turn patchbomb script into an extension module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1604
diff changeset
267 ('s', 'subject', '', 'subject of introductory message'),
91d40fc959f0 turn patchbomb script into an extension module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1604
diff changeset
268 ('t', 'to', [], 'email addresses of recipients')],
91d40fc959f0 turn patchbomb script into an extension module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1604
diff changeset
269 "hg email [OPTION]... [REV]...")
91d40fc959f0 turn patchbomb script into an extension module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1604
diff changeset
270 }