84 Each patch email has a Subject line of "[PATCH M of N] ...", using |
84 Each patch email has a Subject line of "[PATCH M of N] ...", using |
85 the first line of the changeset description as the subject text. |
85 the first line of the changeset description as the subject text. |
86 The message contains two or three body parts. First, the rest of |
86 The message contains two or three body parts. First, the rest of |
87 the changeset description. Next, (optionally) if the diffstat |
87 the changeset description. Next, (optionally) if the diffstat |
88 program is installed, the result of running diffstat on the patch. |
88 program is installed, the result of running diffstat on the patch. |
89 Finally, the patch itself, as generated by "hg export".''' |
89 Finally, the patch itself, as generated by "hg export". |
|
90 |
|
91 With --outgoing, emails will be generated for patches not |
|
92 found in the target repository (or only those which are |
|
93 ancestors of the specified revisions if any are provided) |
|
94 ''' |
|
95 |
90 def prompt(prompt, default = None, rest = ': ', empty_ok = False): |
96 def prompt(prompt, default = None, rest = ': ', empty_ok = False): |
91 if default: prompt += ' [%s]' % default |
97 if default: prompt += ' [%s]' % default |
92 prompt += rest |
98 prompt += rest |
93 while True: |
99 while True: |
94 r = raw_input(prompt) |
100 r = raw_input(prompt) |
163 subj = '[PATCH %0*d of %d] %s' % (tlen, idx, total, subj) |
169 subj = '[PATCH %0*d of %d] %s' % (tlen, idx, total, subj) |
164 msg['Subject'] = subj |
170 msg['Subject'] = subj |
165 msg['X-Mercurial-Node'] = node |
171 msg['X-Mercurial-Node'] = node |
166 return msg |
172 return msg |
167 |
173 |
|
174 def outgoing(dest, revs): |
|
175 '''Return the revisions present locally but not in dest''' |
|
176 dest = ui.expandpath(dest or 'default-push', dest or 'default') |
|
177 revs = [repo.lookup(rev) for rev in revs] |
|
178 other = hg.repository(ui, dest) |
|
179 ui.status(_('comparing with %s\n') % dest) |
|
180 o = repo.findoutgoing(other) |
|
181 if not o: |
|
182 ui.status(_("no changes found\n")) |
|
183 return [] |
|
184 o = repo.changelog.nodesbetween(o, revs or None)[0] |
|
185 return [str(repo.changelog.rev(r)) for r in o] |
|
186 |
|
187 # option handling |
|
188 commands.setremoteconfig(ui, opts) |
|
189 if opts.get('outgoing'): |
|
190 if len(revs) > 1: |
|
191 raise util.Abort(_("too many destinations")) |
|
192 dest = revs and revs[0] or None |
|
193 revs = [] |
|
194 |
|
195 if opts.get('rev'): |
|
196 if revs: |
|
197 raise util.Abort(_('use only one form to specify the revision')) |
|
198 revs = opts.get('rev') |
|
199 |
|
200 if opts.get('outgoing'): |
|
201 revs = outgoing(dest, opts.get('rev')) |
|
202 |
|
203 # start |
168 start_time = util.makedate() |
204 start_time = util.makedate() |
169 |
205 |
170 def genmsgid(id): |
206 def genmsgid(id): |
171 return '<%s.%s@%s>' % (id[:20], int(start_time[0]), socket.getfqdn()) |
207 return '<%s.%s@%s>' % (id[:20], int(start_time[0]), socket.getfqdn()) |
172 |
208 |
297 ('g', 'git', None, _('use git extended diff format')), |
333 ('g', 'git', None, _('use git extended diff format')), |
298 ('f', 'from', '', 'email address of sender'), |
334 ('f', 'from', '', 'email address of sender'), |
299 ('', 'plain', None, 'omit hg patch header'), |
335 ('', 'plain', None, 'omit hg patch header'), |
300 ('n', 'test', None, 'print messages that would be sent'), |
336 ('n', 'test', None, 'print messages that would be sent'), |
301 ('m', 'mbox', '', 'write messages to mbox file instead of sending them'), |
337 ('m', 'mbox', '', 'write messages to mbox file instead of sending them'), |
|
338 ('o', 'outgoing', None, _('send changes not found in the target repository')), |
|
339 ('r', 'rev', [], _('a revision to send')), |
302 ('s', 'subject', '', 'subject of first message (intro or single patch)'), |
340 ('s', 'subject', '', 'subject of first message (intro or single patch)'), |
303 ('t', 'to', [], 'email addresses of recipients')], |
341 ('t', 'to', [], 'email addresses of recipients')] + commands.remoteopts, |
304 "hg email [OPTION]... [REV]...") |
342 "hg email [OPTION]... [DEST]...") |
305 } |
343 } |