hgext/patchbomb.py
author Boris Feld <boris.feld@octobus.net>
Tue, 16 Oct 2018 15:48:00 +0200
changeset 41798 8c42b4a3d447
parent 40346 943248e47864
child 43076 2372284d9457
permissions -rw-r--r--
strip: introduce a soft strip option This is the first user-accessible way to use the archived phase introduced in 4.8. This implements a feature discussed during the Stockholm sprint, using the archived phase for hiding changesets. The archived phase behaves exactly as stripping: changesets are no longer visible, but pulling/unbundling them will make then reappear. The only notable difference is that unlike hard stripping, soft stripping does not affect obsmarkers. The next changeset will make use of the archived phase for history rewriting command. However, having a way to manually trigger the feature first seems a necessary step before exposing users to this phase; there is a way to un-archived changesets (unbundling), so there must be a way to archive them again. Adding a flag to strip is a good way to provide access to the feature without taking a too big risk on the final UI we want. The flag is experimental so it won't be exposed by default. Using the archived phase is faster and less traumatic for the repository than actually stripping changesets.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
8252
9674d64b6416 patchbomb: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 8208
diff changeset
     1
# patchbomb.py - sending Mercurial changesets as patch emails
9674d64b6416 patchbomb: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 8208
diff changeset
     2
#
9674d64b6416 patchbomb: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 8208
diff changeset
     3
#  Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
9674d64b6416 patchbomb: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 8208
diff changeset
     4
#
9674d64b6416 patchbomb: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 8208
diff changeset
     5
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 10022
diff changeset
     6
# GNU General Public License version 2 or any later version.
8252
9674d64b6416 patchbomb: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 8208
diff changeset
     7
8935
f4f0e902b750 extensions: change descriptions for hook-providing extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8934
diff changeset
     8
'''command to send changesets as (a series of) patch emails
6666
53465a7464e2 convert comments to docstrings in a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6548
diff changeset
     9
7997
8eb9f495e150 patchbomb: word-wrap help texts at 70 characters
Martin Geisler <mg@daimi.au.dk>
parents: 7983
diff changeset
    10
The series is started off with a "[PATCH 0 of N]" introduction, which
8eb9f495e150 patchbomb: word-wrap help texts at 70 characters
Martin Geisler <mg@daimi.au.dk>
parents: 7983
diff changeset
    11
describes the series as a whole.
6666
53465a7464e2 convert comments to docstrings in a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6548
diff changeset
    12
9269
1d6499adf211 patchbomb: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9214
diff changeset
    13
Each patch email has a Subject line of "[PATCH M of N] ...", using the
1d6499adf211 patchbomb: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9214
diff changeset
    14
first line of the changeset description as the subject text. The
1d6499adf211 patchbomb: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9214
diff changeset
    15
message contains two or three body parts:
6666
53465a7464e2 convert comments to docstrings in a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6548
diff changeset
    16
9300
ad95ea1c975a patchbomb: use a list instead of indented paragraphs
Martin Geisler <mg@lazybytes.net>
parents: 9289
diff changeset
    17
- The changeset description.
ad95ea1c975a patchbomb: use a list instead of indented paragraphs
Martin Geisler <mg@lazybytes.net>
parents: 9289
diff changeset
    18
- [Optional] The result of running diffstat on the patch.
10973
49a07f441496 Use hg role in help strings
Martin Geisler <mg@aragost.com>
parents: 10734
diff changeset
    19
- The patch itself, as generated by :hg:`export`.
6666
53465a7464e2 convert comments to docstrings in a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6548
diff changeset
    20
9269
1d6499adf211 patchbomb: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9214
diff changeset
    21
Each message refers to the first in the series using the In-Reply-To
1d6499adf211 patchbomb: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9214
diff changeset
    22
and References headers, so they will show up as a sequence in threaded
1d6499adf211 patchbomb: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9214
diff changeset
    23
mail and news readers, and in mail archives.
6666
53465a7464e2 convert comments to docstrings in a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6548
diff changeset
    24
13838
c5709dfa5c1e patchbomb, help/hgweb: do not refer to config files as hgrc files
Martin Geisler <mg@aragost.com>
parents: 13400
diff changeset
    25
To configure other defaults, add a section like this to your
c5709dfa5c1e patchbomb, help/hgweb: do not refer to config files as hgrc files
Martin Geisler <mg@aragost.com>
parents: 13400
diff changeset
    26
configuration file::
6666
53465a7464e2 convert comments to docstrings in a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6548
diff changeset
    27
53465a7464e2 convert comments to docstrings in a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6548
diff changeset
    28
  [email]
53465a7464e2 convert comments to docstrings in a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6548
diff changeset
    29
  from = My Name <my@email>
53465a7464e2 convert comments to docstrings in a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6548
diff changeset
    30
  to = recipient1, recipient2, ...
53465a7464e2 convert comments to docstrings in a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6548
diff changeset
    31
  cc = cc1, cc2, ...
53465a7464e2 convert comments to docstrings in a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6548
diff changeset
    32
  bcc = bcc1, bcc2, ...
11150
f66ca4431eb9 patchbomb: Reply-To support
Cédric Duval <cedricduval@free.fr>
parents: 10973
diff changeset
    33
  reply-to = address1, address2, ...
6666
53465a7464e2 convert comments to docstrings in a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6548
diff changeset
    34
10284
b08ffd27dfc8 patchbomb: document [patchbomb] config section for addresses
Christian Ebert <blacktrash@gmx.net>
parents: 10263
diff changeset
    35
Use ``[patchbomb]`` as configuration section name if you need to
b08ffd27dfc8 patchbomb: document [patchbomb] config section for addresses
Christian Ebert <blacktrash@gmx.net>
parents: 10263
diff changeset
    36
override global ``[email]`` address settings.
b08ffd27dfc8 patchbomb: document [patchbomb] config section for addresses
Christian Ebert <blacktrash@gmx.net>
parents: 10263
diff changeset
    37
10973
49a07f441496 Use hg role in help strings
Martin Geisler <mg@aragost.com>
parents: 10734
diff changeset
    38
Then you can use the :hg:`email` command to mail a series of
49a07f441496 Use hg role in help strings
Martin Geisler <mg@aragost.com>
parents: 10734
diff changeset
    39
changesets as a patchbomb.
6666
53465a7464e2 convert comments to docstrings in a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6548
diff changeset
    40
9269
1d6499adf211 patchbomb: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9214
diff changeset
    41
You can also either configure the method option in the email section
1d6499adf211 patchbomb: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9214
diff changeset
    42
to be a sendmail compatible mailer or fill out the [smtp] section so
1d6499adf211 patchbomb: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9214
diff changeset
    43
that the patchbomb extension can automatically send patchbombs
1d6499adf211 patchbomb: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9214
diff changeset
    44
directly from the commandline. See the [email] and [smtp] sections in
1d6499adf211 patchbomb: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9214
diff changeset
    45
hgrc(5) for details.
23487
c14af817ab76 patchbomb: add a 'patchbomb.intro' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23486
diff changeset
    46
27697
0ce0cfee497f patchbomb: treat empty address list as no addresses
Bryan O'Sullivan <bos@serpentine.com>
parents: 27150
diff changeset
    47
By default, :hg:`email` will prompt for a ``To`` or ``CC`` header if
0ce0cfee497f patchbomb: treat empty address list as no addresses
Bryan O'Sullivan <bos@serpentine.com>
parents: 27150
diff changeset
    48
you do not supply one via configuration or the command line.  You can
0ce0cfee497f patchbomb: treat empty address list as no addresses
Bryan O'Sullivan <bos@serpentine.com>
parents: 27150
diff changeset
    49
override this to never prompt by configuring an empty value::
0ce0cfee497f patchbomb: treat empty address list as no addresses
Bryan O'Sullivan <bos@serpentine.com>
parents: 27150
diff changeset
    50
0ce0cfee497f patchbomb: treat empty address list as no addresses
Bryan O'Sullivan <bos@serpentine.com>
parents: 27150
diff changeset
    51
  [email]
0ce0cfee497f patchbomb: treat empty address list as no addresses
Bryan O'Sullivan <bos@serpentine.com>
parents: 27150
diff changeset
    52
  cc =
0ce0cfee497f patchbomb: treat empty address list as no addresses
Bryan O'Sullivan <bos@serpentine.com>
parents: 27150
diff changeset
    53
23487
c14af817ab76 patchbomb: add a 'patchbomb.intro' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23486
diff changeset
    54
You can control the default inclusion of an introduction message with the
c14af817ab76 patchbomb: add a 'patchbomb.intro' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23486
diff changeset
    55
``patchbomb.intro`` configuration option. The configuration is always
c14af817ab76 patchbomb: add a 'patchbomb.intro' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23486
diff changeset
    56
overwritten by command line flags like --intro and --desc::
c14af817ab76 patchbomb: add a 'patchbomb.intro' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23486
diff changeset
    57
c14af817ab76 patchbomb: add a 'patchbomb.intro' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23486
diff changeset
    58
  [patchbomb]
c14af817ab76 patchbomb: add a 'patchbomb.intro' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23486
diff changeset
    59
  intro=auto   # include introduction message if more than 1 patch (default)
c14af817ab76 patchbomb: add a 'patchbomb.intro' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23486
diff changeset
    60
  intro=never  # never include an introduction message
c14af817ab76 patchbomb: add a 'patchbomb.intro' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23486
diff changeset
    61
  intro=always # always include an introduction message
23488
11b215731e74 patchbomb: introduce a 'patchbomb.confirm' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23487
diff changeset
    62
31187
6b8e1a08ef1d patchbomb: add config knob to generate flags by template (issue5354)
Yuya Nishihara <yuya@tcha.org>
parents: 31186
diff changeset
    63
You can specify a template for flags to be added in subject prefixes. Flags
6b8e1a08ef1d patchbomb: add config knob to generate flags by template (issue5354)
Yuya Nishihara <yuya@tcha.org>
parents: 31186
diff changeset
    64
specified by --flag option are exported as ``{flags}`` keyword::
6b8e1a08ef1d patchbomb: add config knob to generate flags by template (issue5354)
Yuya Nishihara <yuya@tcha.org>
parents: 31186
diff changeset
    65
6b8e1a08ef1d patchbomb: add config knob to generate flags by template (issue5354)
Yuya Nishihara <yuya@tcha.org>
parents: 31186
diff changeset
    66
  [patchbomb]
6b8e1a08ef1d patchbomb: add config knob to generate flags by template (issue5354)
Yuya Nishihara <yuya@tcha.org>
parents: 31186
diff changeset
    67
  flagtemplate = "{separate(' ',
6b8e1a08ef1d patchbomb: add config knob to generate flags by template (issue5354)
Yuya Nishihara <yuya@tcha.org>
parents: 31186
diff changeset
    68
                            ifeq(branch, 'default', '', branch|upper),
6b8e1a08ef1d patchbomb: add config knob to generate flags by template (issue5354)
Yuya Nishihara <yuya@tcha.org>
parents: 31186
diff changeset
    69
                            flags)}"
6b8e1a08ef1d patchbomb: add config knob to generate flags by template (issue5354)
Yuya Nishihara <yuya@tcha.org>
parents: 31186
diff changeset
    70
23488
11b215731e74 patchbomb: introduce a 'patchbomb.confirm' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23487
diff changeset
    71
You can set patchbomb to always ask for confirmation by setting
11b215731e74 patchbomb: introduce a 'patchbomb.confirm' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23487
diff changeset
    72
``patchbomb.confirm`` to true.
9071
141e3ef20d84 patchbomb: wrapped docstrings at 78 characters
Martin Geisler <mg@lazybytes.net>
parents: 9047
diff changeset
    73
'''
28415
21524ae331b7 patchbomb: use absolute_import
timeless <timeless@mozdev.org>
parents: 27767
diff changeset
    74
from __future__ import absolute_import
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    75
39032
8979626089bb patchbomb: use email.encoders instead of email.Encoders
Augie Fackler <augie@google.com>
parents: 39027
diff changeset
    76
import email.encoders as emailencoders
36435
f449138a52df py3: use email.generator module instead of email.Generator
Pulkit Goyal <7895pulkit@gmail.com>
parents: 36410
diff changeset
    77
import email.generator as emailgen
38472
d17d1ee1d602 patchbomb: use email.mime.base instead of email.MIMEBase
Pulkit Goyal <7895pulkit@gmail.com>
parents: 38471
diff changeset
    78
import email.mime.base as emimebase
38471
91228d9ae7c8 patchbomb: use email.mime.multipart instead of email.MIMEMultipart
Pulkit Goyal <7895pulkit@gmail.com>
parents: 38403
diff changeset
    79
import email.mime.multipart as emimemultipart
36448
39c9f339b692 py3: use email.utils module instead of email.Utils
Pulkit Goyal <7895pulkit@gmail.com>
parents: 36446
diff changeset
    80
import email.utils as eutil
28415
21524ae331b7 patchbomb: use absolute_import
timeless <timeless@mozdev.org>
parents: 27767
diff changeset
    81
import errno
21524ae331b7 patchbomb: use absolute_import
timeless <timeless@mozdev.org>
parents: 27767
diff changeset
    82
import os
21524ae331b7 patchbomb: use absolute_import
timeless <timeless@mozdev.org>
parents: 27767
diff changeset
    83
import socket
19810
c80feeb715d1 python2.4: fix imports of sub-packages of the email package
Augie Fackler <raf@durin42.com>
parents: 19791
diff changeset
    84
29205
a0939666b836 py3: move up symbol imports to enforce import-checker rules
Yuya Nishihara <yuya@tcha.org>
parents: 28981
diff changeset
    85
from mercurial.i18n import _
28415
21524ae331b7 patchbomb: use absolute_import
timeless <timeless@mozdev.org>
parents: 27767
diff changeset
    86
from mercurial import (
21524ae331b7 patchbomb: use absolute_import
timeless <timeless@mozdev.org>
parents: 27767
diff changeset
    87
    cmdutil,
21524ae331b7 patchbomb: use absolute_import
timeless <timeless@mozdev.org>
parents: 27767
diff changeset
    88
    commands,
36449
a918c996a881 py3: use encoding.strtolocal() to convert str to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 36448
diff changeset
    89
    encoding,
28415
21524ae331b7 patchbomb: use absolute_import
timeless <timeless@mozdev.org>
parents: 27767
diff changeset
    90
    error,
31187
6b8e1a08ef1d patchbomb: add config knob to generate flags by template (issue5354)
Yuya Nishihara <yuya@tcha.org>
parents: 31186
diff changeset
    91
    formatter,
28415
21524ae331b7 patchbomb: use absolute_import
timeless <timeless@mozdev.org>
parents: 27767
diff changeset
    92
    hg,
21524ae331b7 patchbomb: use absolute_import
timeless <timeless@mozdev.org>
parents: 27767
diff changeset
    93
    mail,
21524ae331b7 patchbomb: use absolute_import
timeless <timeless@mozdev.org>
parents: 27767
diff changeset
    94
    node as nodemod,
21524ae331b7 patchbomb: use absolute_import
timeless <timeless@mozdev.org>
parents: 27767
diff changeset
    95
    patch,
35044
71e63fe6b1ab py3: handle keyword arguments correctly in hgext/patchbomb.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34911
diff changeset
    96
    pycompat,
32337
46ba2cdda476 registrar: move cmdutil.command to registrar module (API)
Yuya Nishihara <yuya@tcha.org>
parents: 31490
diff changeset
    97
    registrar,
28415
21524ae331b7 patchbomb: use absolute_import
timeless <timeless@mozdev.org>
parents: 27767
diff changeset
    98
    scmutil,
31187
6b8e1a08ef1d patchbomb: add config knob to generate flags by template (issue5354)
Yuya Nishihara <yuya@tcha.org>
parents: 31186
diff changeset
    99
    templater,
28415
21524ae331b7 patchbomb: use absolute_import
timeless <timeless@mozdev.org>
parents: 27767
diff changeset
   100
    util,
21524ae331b7 patchbomb: use absolute_import
timeless <timeless@mozdev.org>
parents: 27767
diff changeset
   101
)
36607
c6061cadb400 util: extract all date-related utils in utils/dateutil module
Boris Feld <boris.feld@octobus.net>
parents: 36450
diff changeset
   102
from mercurial.utils import dateutil
28861
86db5cb55d46 pycompat: switch to util.stringio for py3 compat
timeless <timeless@mozdev.org>
parents: 28474
diff changeset
   103
stringio = util.stringio
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   104
14309
37e80214badf patchbomb: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 14290
diff changeset
   105
cmdtable = {}
32337
46ba2cdda476 registrar: move cmdutil.command to registrar module (API)
Yuya Nishihara <yuya@tcha.org>
parents: 31490
diff changeset
   106
command = registrar.command(cmdtable)
34111
798b679680aa configitems: register the 'patchbomb.bundletype' config
Boris Feld <boris.feld@octobus.net>
parents: 34029
diff changeset
   107
798b679680aa configitems: register the 'patchbomb.bundletype' config
Boris Feld <boris.feld@octobus.net>
parents: 34029
diff changeset
   108
configtable = {}
798b679680aa configitems: register the 'patchbomb.bundletype' config
Boris Feld <boris.feld@octobus.net>
parents: 34029
diff changeset
   109
configitem = registrar.configitem(configtable)
798b679680aa configitems: register the 'patchbomb.bundletype' config
Boris Feld <boris.feld@octobus.net>
parents: 34029
diff changeset
   110
798b679680aa configitems: register the 'patchbomb.bundletype' config
Boris Feld <boris.feld@octobus.net>
parents: 34029
diff changeset
   111
configitem('patchbomb', 'bundletype',
798b679680aa configitems: register the 'patchbomb.bundletype' config
Boris Feld <boris.feld@octobus.net>
parents: 34029
diff changeset
   112
    default=None,
798b679680aa configitems: register the 'patchbomb.bundletype' config
Boris Feld <boris.feld@octobus.net>
parents: 34029
diff changeset
   113
)
34760
3819809198c6 configitems: register the 'patchbomb.bcc' config
Boris Feld <boris.feld@octobus.net>
parents: 34116
diff changeset
   114
configitem('patchbomb', 'bcc',
3819809198c6 configitems: register the 'patchbomb.bcc' config
Boris Feld <boris.feld@octobus.net>
parents: 34116
diff changeset
   115
    default=None,
3819809198c6 configitems: register the 'patchbomb.bcc' config
Boris Feld <boris.feld@octobus.net>
parents: 34116
diff changeset
   116
)
34761
cb1ea7ef773d configitems: register the 'patchbomb.cc' config
Boris Feld <boris.feld@octobus.net>
parents: 34760
diff changeset
   117
configitem('patchbomb', 'cc',
cb1ea7ef773d configitems: register the 'patchbomb.cc' config
Boris Feld <boris.feld@octobus.net>
parents: 34760
diff changeset
   118
    default=None,
cb1ea7ef773d configitems: register the 'patchbomb.cc' config
Boris Feld <boris.feld@octobus.net>
parents: 34760
diff changeset
   119
)
34112
4ec0029b76e8 configitems: register the 'patchbomb.confirm' config
Boris Feld <boris.feld@octobus.net>
parents: 34111
diff changeset
   120
configitem('patchbomb', 'confirm',
4ec0029b76e8 configitems: register the 'patchbomb.confirm' config
Boris Feld <boris.feld@octobus.net>
parents: 34111
diff changeset
   121
    default=False,
4ec0029b76e8 configitems: register the 'patchbomb.confirm' config
Boris Feld <boris.feld@octobus.net>
parents: 34111
diff changeset
   122
)
34113
a6fa5af781a4 configitems: register the 'patchbomb.flagtemplate' config
Boris Feld <boris.feld@octobus.net>
parents: 34112
diff changeset
   123
configitem('patchbomb', 'flagtemplate',
a6fa5af781a4 configitems: register the 'patchbomb.flagtemplate' config
Boris Feld <boris.feld@octobus.net>
parents: 34112
diff changeset
   124
    default=None,
a6fa5af781a4 configitems: register the 'patchbomb.flagtemplate' config
Boris Feld <boris.feld@octobus.net>
parents: 34112
diff changeset
   125
)
34114
7e2adac3dd60 configitems: register the 'patchbomb.from' config
Boris Feld <boris.feld@octobus.net>
parents: 34113
diff changeset
   126
configitem('patchbomb', 'from',
7e2adac3dd60 configitems: register the 'patchbomb.from' config
Boris Feld <boris.feld@octobus.net>
parents: 34113
diff changeset
   127
    default=None,
7e2adac3dd60 configitems: register the 'patchbomb.from' config
Boris Feld <boris.feld@octobus.net>
parents: 34113
diff changeset
   128
)
34115
97a3bb5aff25 configitems: register the 'patchbomb.intro' config
Boris Feld <boris.feld@octobus.net>
parents: 34114
diff changeset
   129
configitem('patchbomb', 'intro',
97a3bb5aff25 configitems: register the 'patchbomb.intro' config
Boris Feld <boris.feld@octobus.net>
parents: 34114
diff changeset
   130
    default='auto',
97a3bb5aff25 configitems: register the 'patchbomb.intro' config
Boris Feld <boris.feld@octobus.net>
parents: 34114
diff changeset
   131
)
34116
aeb956e7729f configitems: register the 'patchbomb.publicurl' config
Boris Feld <boris.feld@octobus.net>
parents: 34115
diff changeset
   132
configitem('patchbomb', 'publicurl',
aeb956e7729f configitems: register the 'patchbomb.publicurl' config
Boris Feld <boris.feld@octobus.net>
parents: 34115
diff changeset
   133
    default=None,
aeb956e7729f configitems: register the 'patchbomb.publicurl' config
Boris Feld <boris.feld@octobus.net>
parents: 34115
diff changeset
   134
)
34762
9223a437fdb6 configitems: register the 'patchbomb.reply-to' config
Boris Feld <boris.feld@octobus.net>
parents: 34761
diff changeset
   135
configitem('patchbomb', 'reply-to',
9223a437fdb6 configitems: register the 'patchbomb.reply-to' config
Boris Feld <boris.feld@octobus.net>
parents: 34761
diff changeset
   136
    default=None,
9223a437fdb6 configitems: register the 'patchbomb.reply-to' config
Boris Feld <boris.feld@octobus.net>
parents: 34761
diff changeset
   137
)
34911
645b6684cf5b configitems: register 'email.to' and 'patchbomb.to'
Yuya Nishihara <yuya@tcha.org>
parents: 34762
diff changeset
   138
configitem('patchbomb', 'to',
645b6684cf5b configitems: register 'email.to' and 'patchbomb.to'
Yuya Nishihara <yuya@tcha.org>
parents: 34762
diff changeset
   139
    default=None,
645b6684cf5b configitems: register 'email.to' and 'patchbomb.to'
Yuya Nishihara <yuya@tcha.org>
parents: 34762
diff changeset
   140
)
34111
798b679680aa configitems: register the 'patchbomb.bundletype' config
Boris Feld <boris.feld@octobus.net>
parents: 34029
diff changeset
   141
39022
b95538a21613 patchbomb: work around email module really wanting to write unicode data
Augie Fackler <augie@google.com>
parents: 38776
diff changeset
   142
if pycompat.ispy3:
b95538a21613 patchbomb: work around email module really wanting to write unicode data
Augie Fackler <augie@google.com>
parents: 38776
diff changeset
   143
    _bytesgenerator = emailgen.BytesGenerator
b95538a21613 patchbomb: work around email module really wanting to write unicode data
Augie Fackler <augie@google.com>
parents: 38776
diff changeset
   144
else:
39104
2e578eced958 patchbomb: really use BytesGenerator API
Yuya Nishihara <yuya@tcha.org>
parents: 39038
diff changeset
   145
    _bytesgenerator = emailgen.Generator
39022
b95538a21613 patchbomb: work around email module really wanting to write unicode data
Augie Fackler <augie@google.com>
parents: 38776
diff changeset
   146
29841
d5883fd055c6 extensions: change magic "shipped with hg" string
Augie Fackler <augie@google.com>
parents: 29285
diff changeset
   147
# Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
25186
80c5b2666a96 extensions: document that `testedwith = 'internal'` is special
Augie Fackler <augie@google.com>
parents: 24568
diff changeset
   148
# extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
80c5b2666a96 extensions: document that `testedwith = 'internal'` is special
Augie Fackler <augie@google.com>
parents: 24568
diff changeset
   149
# be specifying the version(s) of Mercurial they are tested with, or
80c5b2666a96 extensions: document that `testedwith = 'internal'` is special
Augie Fackler <augie@google.com>
parents: 24568
diff changeset
   150
# leave the attribute unspecified.
29841
d5883fd055c6 extensions: change magic "shipped with hg" string
Augie Fackler <augie@google.com>
parents: 29285
diff changeset
   151
testedwith = 'ships-with-hg-core'
14309
37e80214badf patchbomb: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 14290
diff changeset
   152
26546
500386e65759 patchbomb: add experimental config of a "pullurl" and export it
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25826
diff changeset
   153
def _addpullheader(seq, ctx):
500386e65759 patchbomb: add experimental config of a "pullurl" and export it
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25826
diff changeset
   154
    """Add a header pointing to a public URL where the changeset is available
500386e65759 patchbomb: add experimental config of a "pullurl" and export it
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25826
diff changeset
   155
    """
500386e65759 patchbomb: add experimental config of a "pullurl" and export it
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25826
diff changeset
   156
    repo = ctx.repo()
500386e65759 patchbomb: add experimental config of a "pullurl" and export it
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25826
diff changeset
   157
    # experimental config: patchbomb.publicurl
500386e65759 patchbomb: add experimental config of a "pullurl" and export it
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25826
diff changeset
   158
    # waiting for some logic that check that the changeset are available on the
500386e65759 patchbomb: add experimental config of a "pullurl" and export it
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25826
diff changeset
   159
    # destination before patchbombing anything.
32824
d3b2d4587e73 patchbomb: make variable name for publicurl always be publicurl
Augie Fackler <augie@google.com>
parents: 32695
diff changeset
   160
    publicurl = repo.ui.config('patchbomb', 'publicurl')
32825
16ff5c6066a6 patchbomb: look for non-empty publicurl, not a non-None one
Augie Fackler <augie@google.com>
parents: 32824
diff changeset
   161
    if publicurl:
26546
500386e65759 patchbomb: add experimental config of a "pullurl" and export it
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25826
diff changeset
   162
        return ('Available At %s\n'
32824
d3b2d4587e73 patchbomb: make variable name for publicurl always be publicurl
Augie Fackler <augie@google.com>
parents: 32695
diff changeset
   163
                '#              hg pull %s -r %s' % (publicurl, publicurl, ctx))
26546
500386e65759 patchbomb: add experimental config of a "pullurl" and export it
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25826
diff changeset
   164
    return None
500386e65759 patchbomb: add experimental config of a "pullurl" and export it
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25826
diff changeset
   165
500386e65759 patchbomb: add experimental config of a "pullurl" and export it
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25826
diff changeset
   166
def uisetup(ui):
500386e65759 patchbomb: add experimental config of a "pullurl" and export it
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25826
diff changeset
   167
    cmdutil.extraexport.append('pullurl')
500386e65759 patchbomb: add experimental config of a "pullurl" and export it
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25826
diff changeset
   168
    cmdutil.extraexportmap['pullurl'] = _addpullheader
500386e65759 patchbomb: add experimental config of a "pullurl" and export it
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25826
diff changeset
   169
33436
9bb4decd43b0 repovfs: add a ward to check if locks are properly taken
Boris Feld <boris.feld@octobus.net>
parents: 32826
diff changeset
   170
def reposetup(ui, repo):
9bb4decd43b0 repovfs: add a ward to check if locks are properly taken
Boris Feld <boris.feld@octobus.net>
parents: 32826
diff changeset
   171
    if not repo.local():
9bb4decd43b0 repovfs: add a ward to check if locks are properly taken
Boris Feld <boris.feld@octobus.net>
parents: 32826
diff changeset
   172
        return
9bb4decd43b0 repovfs: add a ward to check if locks are properly taken
Boris Feld <boris.feld@octobus.net>
parents: 32826
diff changeset
   173
    repo._wlockfreeprefix.add('last-email.txt')
26546
500386e65759 patchbomb: add experimental config of a "pullurl" and export it
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25826
diff changeset
   174
9648
6064de41b7e4 patchbomb: accept default if it is empty string
Alexander Solovyov <piranha@piranha.org.ua>
parents: 9647
diff changeset
   175
def prompt(ui, prompt, default=None, rest=':'):
7354
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   176
    if default:
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   177
        prompt += ' [%s]' % default
15166
9ec9dd8d1b24 patchbomb: drop loop in prompt
Matt Mackall <mpm@selenic.com>
parents: 15165
diff changeset
   178
    return ui.prompt(prompt + rest, default)
7354
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   179
23487
c14af817ab76 patchbomb: add a 'patchbomb.intro' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23486
diff changeset
   180
def introwanted(ui, opts, number):
15164
7bddec632821 patchbomb: make it easy for the user to decline sending an intro message.
Greg Ward <greg@gerg.ca>
parents: 15162
diff changeset
   181
    '''is an introductory message apparently wanted?'''
34115
97a3bb5aff25 configitems: register the 'patchbomb.intro' config
Boris Feld <boris.feld@octobus.net>
parents: 34114
diff changeset
   182
    introconfig = ui.config('patchbomb', 'intro')
23487
c14af817ab76 patchbomb: add a 'patchbomb.intro' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23486
diff changeset
   183
    if opts.get('intro') or opts.get('desc'):
c14af817ab76 patchbomb: add a 'patchbomb.intro' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23486
diff changeset
   184
        intro = True
c14af817ab76 patchbomb: add a 'patchbomb.intro' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23486
diff changeset
   185
    elif introconfig == 'always':
c14af817ab76 patchbomb: add a 'patchbomb.intro' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23486
diff changeset
   186
        intro = True
c14af817ab76 patchbomb: add a 'patchbomb.intro' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23486
diff changeset
   187
    elif introconfig == 'never':
c14af817ab76 patchbomb: add a 'patchbomb.intro' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23486
diff changeset
   188
        intro = False
c14af817ab76 patchbomb: add a 'patchbomb.intro' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23486
diff changeset
   189
    elif introconfig == 'auto':
40029
e2697acd9381 cleanup: some Yoda conditions, this patch removes
Martin von Zweigbergk <martinvonz@google.com>
parents: 39118
diff changeset
   190
        intro = number > 1
23487
c14af817ab76 patchbomb: add a 'patchbomb.intro' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23486
diff changeset
   191
    else:
c14af817ab76 patchbomb: add a 'patchbomb.intro' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23486
diff changeset
   192
        ui.write_err(_('warning: invalid patchbomb.intro value "%s"\n')
c14af817ab76 patchbomb: add a 'patchbomb.intro' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23486
diff changeset
   193
                     % introconfig)
c14af817ab76 patchbomb: add a 'patchbomb.intro' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23486
diff changeset
   194
        ui.write_err(_('(should be one of always, never, auto)\n'))
40029
e2697acd9381 cleanup: some Yoda conditions, this patch removes
Martin von Zweigbergk <martinvonz@google.com>
parents: 39118
diff changeset
   195
        intro = number > 1
23487
c14af817ab76 patchbomb: add a 'patchbomb.intro' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23486
diff changeset
   196
    return intro
10734
7a0502a6f9a1 patchbomb: --desc implies --intro
Cédric Duval <cedricduval@free.fr>
parents: 10611
diff changeset
   197
31187
6b8e1a08ef1d patchbomb: add config knob to generate flags by template (issue5354)
Yuya Nishihara <yuya@tcha.org>
parents: 31186
diff changeset
   198
def _formatflags(ui, repo, rev, flags):
6b8e1a08ef1d patchbomb: add config knob to generate flags by template (issue5354)
Yuya Nishihara <yuya@tcha.org>
parents: 31186
diff changeset
   199
    """build flag string optionally by template"""
6b8e1a08ef1d patchbomb: add config knob to generate flags by template (issue5354)
Yuya Nishihara <yuya@tcha.org>
parents: 31186
diff changeset
   200
    tmpl = ui.config('patchbomb', 'flagtemplate')
6b8e1a08ef1d patchbomb: add config knob to generate flags by template (issue5354)
Yuya Nishihara <yuya@tcha.org>
parents: 31186
diff changeset
   201
    if not tmpl:
6b8e1a08ef1d patchbomb: add config knob to generate flags by template (issue5354)
Yuya Nishihara <yuya@tcha.org>
parents: 31186
diff changeset
   202
        return ' '.join(flags)
6b8e1a08ef1d patchbomb: add config knob to generate flags by template (issue5354)
Yuya Nishihara <yuya@tcha.org>
parents: 31186
diff changeset
   203
    out = util.stringio()
6b8e1a08ef1d patchbomb: add config knob to generate flags by template (issue5354)
Yuya Nishihara <yuya@tcha.org>
parents: 31186
diff changeset
   204
    opts = {'template': templater.unquotestring(tmpl)}
6b8e1a08ef1d patchbomb: add config knob to generate flags by template (issue5354)
Yuya Nishihara <yuya@tcha.org>
parents: 31186
diff changeset
   205
    with formatter.templateformatter(ui, out, 'patchbombflag', opts) as fm:
6b8e1a08ef1d patchbomb: add config knob to generate flags by template (issue5354)
Yuya Nishihara <yuya@tcha.org>
parents: 31186
diff changeset
   206
        fm.startitem()
6b8e1a08ef1d patchbomb: add config knob to generate flags by template (issue5354)
Yuya Nishihara <yuya@tcha.org>
parents: 31186
diff changeset
   207
        fm.context(ctx=repo[rev])
6b8e1a08ef1d patchbomb: add config knob to generate flags by template (issue5354)
Yuya Nishihara <yuya@tcha.org>
parents: 31186
diff changeset
   208
        fm.write('flags', '%s', fm.formatlist(flags, name='flag'))
6b8e1a08ef1d patchbomb: add config knob to generate flags by template (issue5354)
Yuya Nishihara <yuya@tcha.org>
parents: 31186
diff changeset
   209
    return out.getvalue()
6b8e1a08ef1d patchbomb: add config knob to generate flags by template (issue5354)
Yuya Nishihara <yuya@tcha.org>
parents: 31186
diff changeset
   210
31186
83fa357edbd5 patchbomb: pass around ui and revs that are needed for flag template
Yuya Nishihara <yuya@tcha.org>
parents: 31185
diff changeset
   211
def _formatprefix(ui, repo, rev, flags, idx, total, numbered):
31183
8018b90f8307 patchbomb: factor out function that builds a prefix string to patch subject
Yuya Nishihara <yuya@tcha.org>
parents: 30848
diff changeset
   212
    """build prefix to patch subject"""
31187
6b8e1a08ef1d patchbomb: add config knob to generate flags by template (issue5354)
Yuya Nishihara <yuya@tcha.org>
parents: 31186
diff changeset
   213
    flag = _formatflags(ui, repo, rev, flags)
31183
8018b90f8307 patchbomb: factor out function that builds a prefix string to patch subject
Yuya Nishihara <yuya@tcha.org>
parents: 30848
diff changeset
   214
    if flag:
8018b90f8307 patchbomb: factor out function that builds a prefix string to patch subject
Yuya Nishihara <yuya@tcha.org>
parents: 30848
diff changeset
   215
        flag = ' ' + flag
8018b90f8307 patchbomb: factor out function that builds a prefix string to patch subject
Yuya Nishihara <yuya@tcha.org>
parents: 30848
diff changeset
   216
8018b90f8307 patchbomb: factor out function that builds a prefix string to patch subject
Yuya Nishihara <yuya@tcha.org>
parents: 30848
diff changeset
   217
    if not numbered:
8018b90f8307 patchbomb: factor out function that builds a prefix string to patch subject
Yuya Nishihara <yuya@tcha.org>
parents: 30848
diff changeset
   218
        return '[PATCH%s]' % flag
8018b90f8307 patchbomb: factor out function that builds a prefix string to patch subject
Yuya Nishihara <yuya@tcha.org>
parents: 30848
diff changeset
   219
    else:
36668
e77cee5de1c7 py3: use b"%d" to covert integer to bytes instead of str
Pulkit Goyal <7895pulkit@gmail.com>
parents: 36607
diff changeset
   220
        tlen = len("%d" % total)
31183
8018b90f8307 patchbomb: factor out function that builds a prefix string to patch subject
Yuya Nishihara <yuya@tcha.org>
parents: 30848
diff changeset
   221
        return '[PATCH %0*d of %d%s]' % (tlen, idx, total, flag)
8018b90f8307 patchbomb: factor out function that builds a prefix string to patch subject
Yuya Nishihara <yuya@tcha.org>
parents: 30848
diff changeset
   222
31186
83fa357edbd5 patchbomb: pass around ui and revs that are needed for flag template
Yuya Nishihara <yuya@tcha.org>
parents: 31185
diff changeset
   223
def makepatch(ui, repo, rev, patchlines, opts, _charsets, idx, total, numbered,
12199
17d604e522b4 patchbomb: rename argument to avoid shadowing patch module
Martin Geisler <mg@lazybytes.net>
parents: 12197
diff changeset
   224
              patchname=None):
7354
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   225
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   226
    desc = []
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   227
    node = None
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   228
    body = ''
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   229
12199
17d604e522b4 patchbomb: rename argument to avoid shadowing patch module
Martin Geisler <mg@lazybytes.net>
parents: 12197
diff changeset
   230
    for line in patchlines:
7354
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   231
        if line.startswith('#'):
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   232
            if line.startswith('# Node ID'):
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   233
                node = line.split()[-1]
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   234
            continue
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   235
        if line.startswith('diff -r') or line.startswith('diff --git'):
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   236
            break
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   237
        desc.append(line)
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   238
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   239
    if not patchname and not node:
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   240
        raise ValueError
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   241
16307
17a9a1f5cee2 patchbomb: add --body flag to send patches as inline message body text
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 16233
diff changeset
   242
    if opts.get('attach') and not opts.get('body'):
7354
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   243
        body = ('\n'.join(desc[1:]).strip() or
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   244
                'Patch subject is complete summary.')
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   245
        body += '\n\n\n'
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   246
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   247
    if opts.get('plain'):
12199
17d604e522b4 patchbomb: rename argument to avoid shadowing patch module
Martin Geisler <mg@lazybytes.net>
parents: 12197
diff changeset
   248
        while patchlines and patchlines[0].startswith('# '):
17d604e522b4 patchbomb: rename argument to avoid shadowing patch module
Martin Geisler <mg@lazybytes.net>
parents: 12197
diff changeset
   249
            patchlines.pop(0)
17d604e522b4 patchbomb: rename argument to avoid shadowing patch module
Martin Geisler <mg@lazybytes.net>
parents: 12197
diff changeset
   250
        if patchlines:
17d604e522b4 patchbomb: rename argument to avoid shadowing patch module
Martin Geisler <mg@lazybytes.net>
parents: 12197
diff changeset
   251
            patchlines.pop(0)
17d604e522b4 patchbomb: rename argument to avoid shadowing patch module
Martin Geisler <mg@lazybytes.net>
parents: 12197
diff changeset
   252
        while patchlines and not patchlines[0].strip():
17d604e522b4 patchbomb: rename argument to avoid shadowing patch module
Martin Geisler <mg@lazybytes.net>
parents: 12197
diff changeset
   253
            patchlines.pop(0)
7354
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   254
30407
e1677cc29da6 patch: remove unused git parameter from patch.diffstat()
Henning Schild <henning@hennsch.de>
parents: 29841
diff changeset
   255
    ds = patch.diffstat(patchlines)
7354
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   256
    if opts.get('diffstat'):
12200
aebb39d45500 patchbomb: let diffstat prompt only once with complete summary
Christian Ebert <blacktrash@gmx.net>
parents: 12199
diff changeset
   257
        body += ds + '\n\n'
7354
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   258
16307
17a9a1f5cee2 patchbomb: add --body flag to send patches as inline message body text
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 16233
diff changeset
   259
    addattachment = opts.get('attach') or opts.get('inline')
17a9a1f5cee2 patchbomb: add --body flag to send patches as inline message body text
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 16233
diff changeset
   260
    if not addattachment or opts.get('body'):
17a9a1f5cee2 patchbomb: add --body flag to send patches as inline message body text
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 16233
diff changeset
   261
        body += '\n'.join(patchlines)
17a9a1f5cee2 patchbomb: add --body flag to send patches as inline message body text
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 16233
diff changeset
   262
17a9a1f5cee2 patchbomb: add --body flag to send patches as inline message body text
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 16233
diff changeset
   263
    if addattachment:
38471
91228d9ae7c8 patchbomb: use email.mime.multipart instead of email.MIMEMultipart
Pulkit Goyal <7895pulkit@gmail.com>
parents: 38403
diff changeset
   264
        msg = emimemultipart.MIMEMultipart()
7354
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   265
        if body:
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   266
            msg.attach(mail.mimeencode(ui, body, _charsets, opts.get('test')))
16683
525fdb738975 cleanup: eradicate long lines
Brodie Rao <brodie@sf.io>
parents: 16307
diff changeset
   267
        p = mail.mimetextpatch('\n'.join(patchlines), 'x-patch',
525fdb738975 cleanup: eradicate long lines
Brodie Rao <brodie@sf.io>
parents: 16307
diff changeset
   268
                               opts.get('test'))
28415
21524ae331b7 patchbomb: use absolute_import
timeless <timeless@mozdev.org>
parents: 27767
diff changeset
   269
        binnode = nodemod.bin(node)
8761
0289f384e1e5 Generally replace "file name" with "filename" in help and comments.
timeless <timeless@gmail.com>
parents: 8520
diff changeset
   270
        # if node is mq patch, it will have the patch file's name as a tag
7354
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   271
        if not patchname:
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   272
            patchtags = [t for t in repo.nodetags(binnode)
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   273
                         if t.endswith('.patch') or t.endswith('.diff')]
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   274
            if patchtags:
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   275
                patchname = patchtags[0]
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   276
            elif total > 1:
36204
33ed8b511185 cmdutil: pass ctx to makefilename() in place of repo/node pair (API)
Yuya Nishihara <yuya@tcha.org>
parents: 35674
diff changeset
   277
                patchname = cmdutil.makefilename(repo[node], '%b-%n.patch',
33ed8b511185 cmdutil: pass ctx to makefilename() in place of repo/node pair (API)
Yuya Nishihara <yuya@tcha.org>
parents: 35674
diff changeset
   278
                                                 seqno=idx, total=total)
7354
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   279
            else:
36204
33ed8b511185 cmdutil: pass ctx to makefilename() in place of repo/node pair (API)
Yuya Nishihara <yuya@tcha.org>
parents: 35674
diff changeset
   280
                patchname = cmdutil.makefilename(repo[node], '%b.patch')
39038
2161faf0d24b patchbomb: use native strings when determining attachment disposition
Augie Fackler <augie@google.com>
parents: 39035
diff changeset
   281
        disposition = r'inline'
7354
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   282
        if opts.get('attach'):
39038
2161faf0d24b patchbomb: use native strings when determining attachment disposition
Augie Fackler <augie@google.com>
parents: 39035
diff changeset
   283
            disposition = r'attachment'
2161faf0d24b patchbomb: use native strings when determining attachment disposition
Augie Fackler <augie@google.com>
parents: 39035
diff changeset
   284
        p[r'Content-Disposition'] = (
2161faf0d24b patchbomb: use native strings when determining attachment disposition
Augie Fackler <augie@google.com>
parents: 39035
diff changeset
   285
            disposition + r'; filename=' + encoding.strfromlocal(patchname))
7354
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   286
        msg.attach(p)
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   287
    else:
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   288
        msg = mail.mimetextpatch(body, display=opts.get('test'))
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   289
31186
83fa357edbd5 patchbomb: pass around ui and revs that are needed for flag template
Yuya Nishihara <yuya@tcha.org>
parents: 31185
diff changeset
   290
    prefix = _formatprefix(ui, repo, rev, opts.get('flag'), idx, total,
83fa357edbd5 patchbomb: pass around ui and revs that are needed for flag template
Yuya Nishihara <yuya@tcha.org>
parents: 31185
diff changeset
   291
                           numbered)
7354
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   292
    subj = desc[0].strip().rstrip('. ')
15164
7bddec632821 patchbomb: make it easy for the user to decline sending an intro message.
Greg Ward <greg@gerg.ca>
parents: 15162
diff changeset
   293
    if not numbered:
31183
8018b90f8307 patchbomb: factor out function that builds a prefix string to patch subject
Yuya Nishihara <yuya@tcha.org>
parents: 30848
diff changeset
   294
        subj = ' '.join([prefix, opts.get('subject') or subj])
7354
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   295
    else:
31183
8018b90f8307 patchbomb: factor out function that builds a prefix string to patch subject
Yuya Nishihara <yuya@tcha.org>
parents: 30848
diff changeset
   296
        subj = ' '.join([prefix, subj])
7354
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   297
    msg['Subject'] = mail.headencode(ui, subj, _charsets, opts.get('test'))
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   298
    msg['X-Mercurial-Node'] = node
21282
697fba94dec9 patchbomb: includes series information in the header
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 21055
diff changeset
   299
    msg['X-Mercurial-Series-Index'] = '%i' % idx
697fba94dec9 patchbomb: includes series information in the header
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 21055
diff changeset
   300
    msg['X-Mercurial-Series-Total'] = '%i' % total
12200
aebb39d45500 patchbomb: let diffstat prompt only once with complete summary
Christian Ebert <blacktrash@gmx.net>
parents: 12199
diff changeset
   301
    return msg, subj, ds
7354
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   302
23210
79f7444520bf patchbomb: extract 'getpatches' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23173
diff changeset
   303
def _getpatches(repo, revs, **opts):
79f7444520bf patchbomb: extract 'getpatches' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23173
diff changeset
   304
    """return a list of patches for a list of revisions
79f7444520bf patchbomb: extract 'getpatches' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23173
diff changeset
   305
79f7444520bf patchbomb: extract 'getpatches' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23173
diff changeset
   306
    Each patch in the list is itself a list of lines.
79f7444520bf patchbomb: extract 'getpatches' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23173
diff changeset
   307
    """
79f7444520bf patchbomb: extract 'getpatches' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23173
diff changeset
   308
    ui = repo.ui
79f7444520bf patchbomb: extract 'getpatches' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23173
diff changeset
   309
    prev = repo['.'].rev()
24568
2e5f6cdf01f6 patchbomb: factor out scmutil.revrange() calls
Yuya Nishihara <yuya@tcha.org>
parents: 24567
diff changeset
   310
    for r in revs:
23210
79f7444520bf patchbomb: extract 'getpatches' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23173
diff changeset
   311
        if r == prev and (repo[None].files() or repo[None].deleted()):
79f7444520bf patchbomb: extract 'getpatches' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23173
diff changeset
   312
            ui.warn(_('warning: working directory has '
79f7444520bf patchbomb: extract 'getpatches' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23173
diff changeset
   313
                      'uncommitted changes\n'))
28861
86db5cb55d46 pycompat: switch to util.stringio for py3 compat
timeless <timeless@mozdev.org>
parents: 28474
diff changeset
   314
        output = stringio()
37603
678d760c71ff export: extract function to write patch to file object (API)
Yuya Nishihara <yuya@tcha.org>
parents: 36668
diff changeset
   315
        cmdutil.exportfile(repo, [r], output,
678d760c71ff export: extract function to write patch to file object (API)
Yuya Nishihara <yuya@tcha.org>
parents: 36668
diff changeset
   316
                           opts=patch.difffeatureopts(ui, opts, git=True))
23210
79f7444520bf patchbomb: extract 'getpatches' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23173
diff changeset
   317
        yield output.getvalue().split('\n')
23211
6993282e5362 patchbomb: extract 'getbundle' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23210
diff changeset
   318
def _getbundle(repo, dest, **opts):
6993282e5362 patchbomb: extract 'getbundle' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23210
diff changeset
   319
    """return a bundle containing changesets missing in "dest"
6993282e5362 patchbomb: extract 'getbundle' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23210
diff changeset
   320
6993282e5362 patchbomb: extract 'getbundle' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23210
diff changeset
   321
    The `opts` keyword-arguments are the same as the one accepted by the
6993282e5362 patchbomb: extract 'getbundle' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23210
diff changeset
   322
    `bundle` command.
6993282e5362 patchbomb: extract 'getbundle' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23210
diff changeset
   323
6993282e5362 patchbomb: extract 'getbundle' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23210
diff changeset
   324
    The bundle is a returned as a single in-memory binary blob.
6993282e5362 patchbomb: extract 'getbundle' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23210
diff changeset
   325
    """
6993282e5362 patchbomb: extract 'getbundle' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23210
diff changeset
   326
    ui = repo.ui
38165
2ce60954b1b7 py3: wrap tempfile.mkdtemp() to use bytes path
Yuya Nishihara <yuya@tcha.org>
parents: 38131
diff changeset
   327
    tmpdir = pycompat.mkdtemp(prefix='hg-email-bundle-')
23211
6993282e5362 patchbomb: extract 'getbundle' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23210
diff changeset
   328
    tmpfn = os.path.join(tmpdir, 'bundle')
26563
d4a1bfe1de63 patchbomb: add a 'bundletype' config under 'patchbomb'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26546
diff changeset
   329
    btype = ui.config('patchbomb', 'bundletype')
d4a1bfe1de63 patchbomb: add a 'bundletype' config under 'patchbomb'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26546
diff changeset
   330
    if btype:
35044
71e63fe6b1ab py3: handle keyword arguments correctly in hgext/patchbomb.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34911
diff changeset
   331
        opts[r'type'] = btype
23211
6993282e5362 patchbomb: extract 'getbundle' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23210
diff changeset
   332
    try:
6993282e5362 patchbomb: extract 'getbundle' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23210
diff changeset
   333
        commands.bundle(ui, repo, tmpfn, dest, **opts)
27767
ddfb8887212d patchbomb: replace file I/O with util.readfile
Bryan O'Sullivan <bryano@fb.com>
parents: 27697
diff changeset
   334
        return util.readfile(tmpfn)
23211
6993282e5362 patchbomb: extract 'getbundle' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23210
diff changeset
   335
    finally:
6993282e5362 patchbomb: extract 'getbundle' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23210
diff changeset
   336
        try:
6993282e5362 patchbomb: extract 'getbundle' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23210
diff changeset
   337
            os.unlink(tmpfn)
6993282e5362 patchbomb: extract 'getbundle' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23210
diff changeset
   338
        except OSError:
6993282e5362 patchbomb: extract 'getbundle' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23210
diff changeset
   339
            pass
6993282e5362 patchbomb: extract 'getbundle' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23210
diff changeset
   340
        os.rmdir(tmpdir)
6993282e5362 patchbomb: extract 'getbundle' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23210
diff changeset
   341
23212
4b4eae00f9dd patchbomb: extract 'getdescription' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23211
diff changeset
   342
def _getdescription(repo, defaultbody, sender, **opts):
4b4eae00f9dd patchbomb: extract 'getdescription' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23211
diff changeset
   343
    """obtain the body of the introduction message and return it
4b4eae00f9dd patchbomb: extract 'getdescription' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23211
diff changeset
   344
4b4eae00f9dd patchbomb: extract 'getdescription' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23211
diff changeset
   345
    This is also used for the body of email with an attached bundle.
4b4eae00f9dd patchbomb: extract 'getdescription' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23211
diff changeset
   346
4b4eae00f9dd patchbomb: extract 'getdescription' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23211
diff changeset
   347
    The body can be obtained either from the command line option or entered by
4b4eae00f9dd patchbomb: extract 'getdescription' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23211
diff changeset
   348
    the user through the editor.
4b4eae00f9dd patchbomb: extract 'getdescription' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23211
diff changeset
   349
    """
4b4eae00f9dd patchbomb: extract 'getdescription' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23211
diff changeset
   350
    ui = repo.ui
35044
71e63fe6b1ab py3: handle keyword arguments correctly in hgext/patchbomb.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34911
diff changeset
   351
    if opts.get(r'desc'):
71e63fe6b1ab py3: handle keyword arguments correctly in hgext/patchbomb.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34911
diff changeset
   352
        body = open(opts.get(r'desc')).read()
23212
4b4eae00f9dd patchbomb: extract 'getdescription' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23211
diff changeset
   353
    else:
4b4eae00f9dd patchbomb: extract 'getdescription' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23211
diff changeset
   354
        ui.write(_('\nWrite the introductory message for the '
4b4eae00f9dd patchbomb: extract 'getdescription' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23211
diff changeset
   355
                   'patch series.\n\n'))
34029
6e6452bc441d editor: use an unambiguous path suffix for editor files
Michael Bolin <mbolin@fb.com>
parents: 33436
diff changeset
   356
        body = ui.edit(defaultbody, sender, repopath=repo.path,
6e6452bc441d editor: use an unambiguous path suffix for editor files
Michael Bolin <mbolin@fb.com>
parents: 33436
diff changeset
   357
                       action='patchbombbody')
23212
4b4eae00f9dd patchbomb: extract 'getdescription' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23211
diff changeset
   358
        # Save series description in case sendmail fails
23877
7cc77030c557 localrepo: remove all external users of localrepo.opener
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 23488
diff changeset
   359
        msgfile = repo.vfs('last-email.txt', 'wb')
23212
4b4eae00f9dd patchbomb: extract 'getdescription' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23211
diff changeset
   360
        msgfile.write(body)
4b4eae00f9dd patchbomb: extract 'getdescription' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23211
diff changeset
   361
        msgfile.close()
4b4eae00f9dd patchbomb: extract 'getdescription' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23211
diff changeset
   362
    return body
23211
6993282e5362 patchbomb: extract 'getbundle' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23210
diff changeset
   363
23213
23a78662b6dd patchbomb: extract 'getbundlemsgs' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23212
diff changeset
   364
def _getbundlemsgs(repo, sender, bundle, **opts):
23a78662b6dd patchbomb: extract 'getbundlemsgs' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23212
diff changeset
   365
    """Get the full email for sending a given bundle
23a78662b6dd patchbomb: extract 'getbundlemsgs' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23212
diff changeset
   366
23a78662b6dd patchbomb: extract 'getbundlemsgs' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23212
diff changeset
   367
    This function returns a list of "email" tuples (subject, content, None).
23a78662b6dd patchbomb: extract 'getbundlemsgs' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23212
diff changeset
   368
    The list is always one message long in that case.
23a78662b6dd patchbomb: extract 'getbundlemsgs' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23212
diff changeset
   369
    """
23a78662b6dd patchbomb: extract 'getbundlemsgs' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23212
diff changeset
   370
    ui = repo.ui
23a78662b6dd patchbomb: extract 'getbundlemsgs' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23212
diff changeset
   371
    _charsets = mail._charsets(ui)
35044
71e63fe6b1ab py3: handle keyword arguments correctly in hgext/patchbomb.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34911
diff changeset
   372
    subj = (opts.get(r'subject')
23213
23a78662b6dd patchbomb: extract 'getbundlemsgs' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23212
diff changeset
   373
            or prompt(ui, 'Subject:', 'A bundle for your repository'))
23a78662b6dd patchbomb: extract 'getbundlemsgs' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23212
diff changeset
   374
23a78662b6dd patchbomb: extract 'getbundlemsgs' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23212
diff changeset
   375
    body = _getdescription(repo, '', sender, **opts)
38471
91228d9ae7c8 patchbomb: use email.mime.multipart instead of email.MIMEMultipart
Pulkit Goyal <7895pulkit@gmail.com>
parents: 38403
diff changeset
   376
    msg = emimemultipart.MIMEMultipart()
23213
23a78662b6dd patchbomb: extract 'getbundlemsgs' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23212
diff changeset
   377
    if body:
35044
71e63fe6b1ab py3: handle keyword arguments correctly in hgext/patchbomb.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34911
diff changeset
   378
        msg.attach(mail.mimeencode(ui, body, _charsets, opts.get(r'test')))
39034
751caa6a2936 patchbomb: use sysstrs when describing content-type
Augie Fackler <augie@google.com>
parents: 39033
diff changeset
   379
    datapart = emimebase.MIMEBase(r'application', r'x-mercurial-bundle')
23213
23a78662b6dd patchbomb: extract 'getbundlemsgs' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23212
diff changeset
   380
    datapart.set_payload(bundle)
35044
71e63fe6b1ab py3: handle keyword arguments correctly in hgext/patchbomb.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34911
diff changeset
   381
    bundlename = '%s.hg' % opts.get(r'bundlename', 'bundle')
39033
ed9537bd2d1a patchbomb: use native strs for email header keys and values
Augie Fackler <augie@google.com>
parents: 39032
diff changeset
   382
    datapart.add_header(r'Content-Disposition', r'attachment',
ed9537bd2d1a patchbomb: use native strs for email header keys and values
Augie Fackler <augie@google.com>
parents: 39032
diff changeset
   383
                        filename=encoding.strfromlocal(bundlename))
39032
8979626089bb patchbomb: use email.encoders instead of email.Encoders
Augie Fackler <augie@google.com>
parents: 39027
diff changeset
   384
    emailencoders.encode_base64(datapart)
23213
23a78662b6dd patchbomb: extract 'getbundlemsgs' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23212
diff changeset
   385
    msg.attach(datapart)
35044
71e63fe6b1ab py3: handle keyword arguments correctly in hgext/patchbomb.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34911
diff changeset
   386
    msg['Subject'] = mail.headencode(ui, subj, _charsets, opts.get(r'test'))
23213
23a78662b6dd patchbomb: extract 'getbundlemsgs' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23212
diff changeset
   387
    return [(msg, subj, None)]
23a78662b6dd patchbomb: extract 'getbundlemsgs' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23212
diff changeset
   388
31186
83fa357edbd5 patchbomb: pass around ui and revs that are needed for flag template
Yuya Nishihara <yuya@tcha.org>
parents: 31185
diff changeset
   389
def _makeintro(repo, sender, revs, patches, **opts):
23214
563d33fc4b3d patchbomb: extract 'makeintro' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23213
diff changeset
   390
    """make an introduction email, asking the user for content if needed
563d33fc4b3d patchbomb: extract 'makeintro' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23213
diff changeset
   391
563d33fc4b3d patchbomb: extract 'makeintro' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23213
diff changeset
   392
    email is returned as (subject, body, cumulative-diffstat)"""
563d33fc4b3d patchbomb: extract 'makeintro' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23213
diff changeset
   393
    ui = repo.ui
563d33fc4b3d patchbomb: extract 'makeintro' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23213
diff changeset
   394
    _charsets = mail._charsets(ui)
563d33fc4b3d patchbomb: extract 'makeintro' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23213
diff changeset
   395
31186
83fa357edbd5 patchbomb: pass around ui and revs that are needed for flag template
Yuya Nishihara <yuya@tcha.org>
parents: 31185
diff changeset
   396
    # use the last revision which is likely to be a bookmarked head
35044
71e63fe6b1ab py3: handle keyword arguments correctly in hgext/patchbomb.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34911
diff changeset
   397
    prefix = _formatprefix(ui, repo, revs.last(), opts.get(r'flag'),
31186
83fa357edbd5 patchbomb: pass around ui and revs that are needed for flag template
Yuya Nishihara <yuya@tcha.org>
parents: 31185
diff changeset
   398
                           0, len(patches), numbered=True)
35044
71e63fe6b1ab py3: handle keyword arguments correctly in hgext/patchbomb.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34911
diff changeset
   399
    subj = (opts.get(r'subject') or
23214
563d33fc4b3d patchbomb: extract 'makeintro' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23213
diff changeset
   400
            prompt(ui, '(optional) Subject: ', rest=prefix, default=''))
563d33fc4b3d patchbomb: extract 'makeintro' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23213
diff changeset
   401
    if not subj:
563d33fc4b3d patchbomb: extract 'makeintro' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23213
diff changeset
   402
        return None         # skip intro if the user doesn't bother
563d33fc4b3d patchbomb: extract 'makeintro' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23213
diff changeset
   403
563d33fc4b3d patchbomb: extract 'makeintro' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23213
diff changeset
   404
    subj = prefix + ' ' + subj
563d33fc4b3d patchbomb: extract 'makeintro' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23213
diff changeset
   405
563d33fc4b3d patchbomb: extract 'makeintro' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23213
diff changeset
   406
    body = ''
35044
71e63fe6b1ab py3: handle keyword arguments correctly in hgext/patchbomb.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34911
diff changeset
   407
    if opts.get(r'diffstat'):
23214
563d33fc4b3d patchbomb: extract 'makeintro' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23213
diff changeset
   408
        # generate a cumulative diffstat of the whole patch series
563d33fc4b3d patchbomb: extract 'makeintro' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23213
diff changeset
   409
        diffstat = patch.diffstat(sum(patches, []))
563d33fc4b3d patchbomb: extract 'makeintro' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23213
diff changeset
   410
        body = '\n' + diffstat
563d33fc4b3d patchbomb: extract 'makeintro' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23213
diff changeset
   411
    else:
563d33fc4b3d patchbomb: extract 'makeintro' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23213
diff changeset
   412
        diffstat = None
563d33fc4b3d patchbomb: extract 'makeintro' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23213
diff changeset
   413
563d33fc4b3d patchbomb: extract 'makeintro' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23213
diff changeset
   414
    body = _getdescription(repo, body, sender, **opts)
35044
71e63fe6b1ab py3: handle keyword arguments correctly in hgext/patchbomb.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34911
diff changeset
   415
    msg = mail.mimeencode(ui, body, _charsets, opts.get(r'test'))
23214
563d33fc4b3d patchbomb: extract 'makeintro' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23213
diff changeset
   416
    msg['Subject'] = mail.headencode(ui, subj, _charsets,
35044
71e63fe6b1ab py3: handle keyword arguments correctly in hgext/patchbomb.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34911
diff changeset
   417
                                     opts.get(r'test'))
23214
563d33fc4b3d patchbomb: extract 'makeintro' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23213
diff changeset
   418
    return (msg, subj, diffstat)
563d33fc4b3d patchbomb: extract 'makeintro' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23213
diff changeset
   419
31185
bbb5d2aa0bf0 patchbomb: build patch texts by _getpatchmsgs()
Yuya Nishihara <yuya@tcha.org>
parents: 31184
diff changeset
   420
def _getpatchmsgs(repo, sender, revs, patchnames=None, **opts):
23215
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   421
    """return a list of emails from a list of patches
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   422
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   423
    This involves introduction message creation if necessary.
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   424
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   425
    This function returns a list of "email" tuples (subject, content, None).
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   426
    """
35044
71e63fe6b1ab py3: handle keyword arguments correctly in hgext/patchbomb.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34911
diff changeset
   427
    bytesopts = pycompat.byteskwargs(opts)
23215
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   428
    ui = repo.ui
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   429
    _charsets = mail._charsets(ui)
31185
bbb5d2aa0bf0 patchbomb: build patch texts by _getpatchmsgs()
Yuya Nishihara <yuya@tcha.org>
parents: 31184
diff changeset
   430
    patches = list(_getpatches(repo, revs, **opts))
23215
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   431
    msgs = []
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   432
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   433
    ui.write(_('this patch series consists of %d patches.\n\n')
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   434
             % len(patches))
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   435
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   436
    # build the intro message, or skip it if the user declines
35044
71e63fe6b1ab py3: handle keyword arguments correctly in hgext/patchbomb.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34911
diff changeset
   437
    if introwanted(ui, bytesopts, len(patches)):
31186
83fa357edbd5 patchbomb: pass around ui and revs that are needed for flag template
Yuya Nishihara <yuya@tcha.org>
parents: 31185
diff changeset
   438
        msg = _makeintro(repo, sender, revs, patches, **opts)
23215
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   439
        if msg:
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   440
            msgs.append(msg)
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   441
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   442
    # are we going to send more than one message?
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   443
    numbered = len(msgs) + len(patches) > 1
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   444
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   445
    # now generate the actual patch messages
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   446
    name = None
31186
83fa357edbd5 patchbomb: pass around ui and revs that are needed for flag template
Yuya Nishihara <yuya@tcha.org>
parents: 31185
diff changeset
   447
    assert len(revs) == len(patches)
83fa357edbd5 patchbomb: pass around ui and revs that are needed for flag template
Yuya Nishihara <yuya@tcha.org>
parents: 31185
diff changeset
   448
    for i, (r, p) in enumerate(zip(revs, patches)):
23215
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   449
        if patchnames:
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   450
            name = patchnames[i]
35044
71e63fe6b1ab py3: handle keyword arguments correctly in hgext/patchbomb.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34911
diff changeset
   451
        msg = makepatch(ui, repo, r, p, bytesopts, _charsets,
71e63fe6b1ab py3: handle keyword arguments correctly in hgext/patchbomb.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34911
diff changeset
   452
                        i + 1, len(patches), numbered, name)
23215
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   453
        msgs.append(msg)
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   454
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   455
    return msgs
83a191031f94 patchbomb: extract 'getpatchmsgs' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23214
diff changeset
   456
23486
1de214837f5e patchbomb: extract 'getoutgoing' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23450
diff changeset
   457
def _getoutgoing(repo, dest, revs):
1de214837f5e patchbomb: extract 'getoutgoing' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23450
diff changeset
   458
    '''Return the revisions present locally but not in dest'''
1de214837f5e patchbomb: extract 'getoutgoing' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23450
diff changeset
   459
    ui = repo.ui
1de214837f5e patchbomb: extract 'getoutgoing' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23450
diff changeset
   460
    url = ui.expandpath(dest or 'default-push', dest or 'default')
1de214837f5e patchbomb: extract 'getoutgoing' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23450
diff changeset
   461
    url = hg.parseurl(url)[0]
1de214837f5e patchbomb: extract 'getoutgoing' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23450
diff changeset
   462
    ui.status(_('comparing with %s\n') % util.hidepassword(url))
1de214837f5e patchbomb: extract 'getoutgoing' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23450
diff changeset
   463
24568
2e5f6cdf01f6 patchbomb: factor out scmutil.revrange() calls
Yuya Nishihara <yuya@tcha.org>
parents: 24567
diff changeset
   464
    revs = [r for r in revs if r >= 0]
23486
1de214837f5e patchbomb: extract 'getoutgoing' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23450
diff changeset
   465
    if not revs:
35674
e711906aa42c patchbomb: use 'tiprev' when appropriate
Boris Feld <boris.feld@octobus.net>
parents: 35466
diff changeset
   466
        revs = [repo.changelog.tiprev()]
23486
1de214837f5e patchbomb: extract 'getoutgoing' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23450
diff changeset
   467
    revs = repo.revs('outgoing(%s) and ::%ld', dest or '', revs)
1de214837f5e patchbomb: extract 'getoutgoing' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23450
diff changeset
   468
    if not revs:
1de214837f5e patchbomb: extract 'getoutgoing' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23450
diff changeset
   469
        ui.status(_("no changes found\n"))
24567
13f0af2a5a4c patchbomb: return outgoing revs as a smartset
Yuya Nishihara <yuya@tcha.org>
parents: 24306
diff changeset
   470
    return revs
23486
1de214837f5e patchbomb: extract 'getoutgoing' closure into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23450
diff changeset
   471
39117
4899c6d22dff patchbomb: extract function for generating message-id
Augie Fackler <raf@durin42.com>
parents: 39104
diff changeset
   472
def _msgid(node, timestamp):
39118
1415b78869eb patchbomb: allow using HGHOSTNAME to force a hostname
Augie Fackler <raf@durin42.com>
parents: 39117
diff changeset
   473
    hostname = encoding.strtolocal(socket.getfqdn())
1415b78869eb patchbomb: allow using HGHOSTNAME to force a hostname
Augie Fackler <raf@durin42.com>
parents: 39117
diff changeset
   474
    hostname = encoding.environ.get('HGHOSTNAME', hostname)
1415b78869eb patchbomb: allow using HGHOSTNAME to force a hostname
Augie Fackler <raf@durin42.com>
parents: 39117
diff changeset
   475
    return '<%s.%d@%s>' % (node, timestamp, hostname)
39117
4899c6d22dff patchbomb: extract function for generating message-id
Augie Fackler <raf@durin42.com>
parents: 39104
diff changeset
   476
14309
37e80214badf patchbomb: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 14290
diff changeset
   477
emailopts = [
16307
17a9a1f5cee2 patchbomb: add --body flag to send patches as inline message body text
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 16233
diff changeset
   478
    ('', 'body', None, _('send patches as inline message text (default)')),
14309
37e80214badf patchbomb: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 14290
diff changeset
   479
    ('a', 'attach', None, _('send patches as attachments')),
37e80214badf patchbomb: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 14290
diff changeset
   480
    ('i', 'inline', None, _('send patches as inline attachments')),
40346
943248e47864 commands: adjust metavariables as appropriate
Anton Shestakov <av6@dwimlabs.net>
parents: 40293
diff changeset
   481
    ('', 'bcc', [],
943248e47864 commands: adjust metavariables as appropriate
Anton Shestakov <av6@dwimlabs.net>
parents: 40293
diff changeset
   482
     _('email addresses of blind carbon copy recipients'), _('EMAIL')),
943248e47864 commands: adjust metavariables as appropriate
Anton Shestakov <av6@dwimlabs.net>
parents: 40293
diff changeset
   483
    ('c', 'cc', [], _('email addresses of copy recipients'), _('EMAIL')),
14309
37e80214badf patchbomb: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 14290
diff changeset
   484
    ('', 'confirm', None, _('ask for confirmation before sending')),
37e80214badf patchbomb: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 14290
diff changeset
   485
    ('d', 'diffstat', None, _('add diffstat output to messages')),
40346
943248e47864 commands: adjust metavariables as appropriate
Anton Shestakov <av6@dwimlabs.net>
parents: 40293
diff changeset
   486
    ('', 'date', '', _('use the given date as the sending date'), _('DATE')),
943248e47864 commands: adjust metavariables as appropriate
Anton Shestakov <av6@dwimlabs.net>
parents: 40293
diff changeset
   487
    ('', 'desc', '',
943248e47864 commands: adjust metavariables as appropriate
Anton Shestakov <av6@dwimlabs.net>
parents: 40293
diff changeset
   488
     _('use the given file as the series description'), _('FILE')),
943248e47864 commands: adjust metavariables as appropriate
Anton Shestakov <av6@dwimlabs.net>
parents: 40293
diff changeset
   489
    ('f', 'from', '', _('email address of sender'), _('EMAIL')),
14309
37e80214badf patchbomb: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 14290
diff changeset
   490
    ('n', 'test', None, _('print messages that would be sent')),
40346
943248e47864 commands: adjust metavariables as appropriate
Anton Shestakov <av6@dwimlabs.net>
parents: 40293
diff changeset
   491
    ('m', 'mbox', '',
943248e47864 commands: adjust metavariables as appropriate
Anton Shestakov <av6@dwimlabs.net>
parents: 40293
diff changeset
   492
     _('write messages to mbox file instead of sending them'), _('FILE')),
943248e47864 commands: adjust metavariables as appropriate
Anton Shestakov <av6@dwimlabs.net>
parents: 40293
diff changeset
   493
    ('', 'reply-to', [],
943248e47864 commands: adjust metavariables as appropriate
Anton Shestakov <av6@dwimlabs.net>
parents: 40293
diff changeset
   494
     _('email addresses replies should be sent to'), _('EMAIL')),
943248e47864 commands: adjust metavariables as appropriate
Anton Shestakov <av6@dwimlabs.net>
parents: 40293
diff changeset
   495
    ('s', 'subject', '',
943248e47864 commands: adjust metavariables as appropriate
Anton Shestakov <av6@dwimlabs.net>
parents: 40293
diff changeset
   496
     _('subject of first message (intro or single patch)'), _('TEXT')),
943248e47864 commands: adjust metavariables as appropriate
Anton Shestakov <av6@dwimlabs.net>
parents: 40293
diff changeset
   497
    ('', 'in-reply-to', '', _('message identifier to reply to'), _('MSGID')),
943248e47864 commands: adjust metavariables as appropriate
Anton Shestakov <av6@dwimlabs.net>
parents: 40293
diff changeset
   498
    ('', 'flag', [], _('flags to add in subject prefixes'), _('FLAG')),
943248e47864 commands: adjust metavariables as appropriate
Anton Shestakov <av6@dwimlabs.net>
parents: 40293
diff changeset
   499
    ('t', 'to', [], _('email addresses of recipients'), _('EMAIL'))]
14309
37e80214badf patchbomb: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 14290
diff changeset
   500
37e80214badf patchbomb: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 14290
diff changeset
   501
@command('email',
37e80214badf patchbomb: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 14290
diff changeset
   502
    [('g', 'git', None, _('use git extended diff format')),
37e80214badf patchbomb: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 14290
diff changeset
   503
    ('', 'plain', None, _('omit hg patch header')),
37e80214badf patchbomb: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 14290
diff changeset
   504
    ('o', 'outgoing', None,
37e80214badf patchbomb: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 14290
diff changeset
   505
     _('send changes not found in the target repository')),
37e80214badf patchbomb: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 14290
diff changeset
   506
    ('b', 'bundle', None, _('send changes not in target as a binary bundle')),
40346
943248e47864 commands: adjust metavariables as appropriate
Anton Shestakov <av6@dwimlabs.net>
parents: 40293
diff changeset
   507
    ('B', 'bookmark', '',
943248e47864 commands: adjust metavariables as appropriate
Anton Shestakov <av6@dwimlabs.net>
parents: 40293
diff changeset
   508
     _('send changes only reachable by given bookmark'), _('BOOKMARK')),
14309
37e80214badf patchbomb: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 14290
diff changeset
   509
    ('', 'bundlename', 'bundle',
37e80214badf patchbomb: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 14290
diff changeset
   510
     _('name of the bundle attachment file'), _('NAME')),
37e80214badf patchbomb: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 14290
diff changeset
   511
    ('r', 'rev', [], _('a revision to send'), _('REV')),
37e80214badf patchbomb: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 14290
diff changeset
   512
    ('', 'force', None, _('run even when remote repository is unrelated '
37e80214badf patchbomb: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 14290
diff changeset
   513
       '(with -b/--bundle)')),
37e80214badf patchbomb: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 14290
diff changeset
   514
    ('', 'base', [], _('a base changeset to specify instead of a destination '
37e80214badf patchbomb: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 14290
diff changeset
   515
       '(with -b/--bundle)'), _('REV')),
37e80214badf patchbomb: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 14290
diff changeset
   516
    ('', 'intro', None, _('send an introduction email for a single patch')),
32375
04baab18d60a commands: move templates of common command options to cmdutil (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32337
diff changeset
   517
    ] + emailopts + cmdutil.remoteopts,
40293
c303d65d2e34 help: assigning categories to existing commands
rdamazio@google.com
parents: 40029
diff changeset
   518
    _('hg email [OPTION]... [DEST]...'),
c303d65d2e34 help: assigning categories to existing commands
rdamazio@google.com
parents: 40029
diff changeset
   519
    helpcategory=command.CATEGORY_IMPORT_EXPORT)
27150
88aaddb1af88 patchbomb: rename email function
timeless <timeless@mozdev.org>
parents: 26626
diff changeset
   520
def email(ui, repo, *revs, **opts):
4283
8625504f507c Slight refining to help text in patchbomb.py
John Goerzen <jgoerzen@complete.org>
parents: 4280
diff changeset
   521
    '''send changesets by email
1204
b0f6053df539 patchbomb: continue if we can't import readline.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1154
diff changeset
   522
11193
687c7d395f20 Use our custom hg reStructuredText role some more
Martin Geisler <mg@aragost.com>
parents: 11183
diff changeset
   523
    By default, diffs are sent in the format generated by
687c7d395f20 Use our custom hg reStructuredText role some more
Martin Geisler <mg@aragost.com>
parents: 11183
diff changeset
   524
    :hg:`export`, one per message. The series starts with a "[PATCH 0
687c7d395f20 Use our custom hg reStructuredText role some more
Martin Geisler <mg@aragost.com>
parents: 11183
diff changeset
   525
    of N]" introduction, which describes the series as a whole.
1672
07f931af5f40 add documentation for email command.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1670
diff changeset
   526
9269
1d6499adf211 patchbomb: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9214
diff changeset
   527
    Each patch email has a Subject line of "[PATCH M of N] ...", using
1d6499adf211 patchbomb: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9214
diff changeset
   528
    the first line of the changeset description as the subject text.
1d6499adf211 patchbomb: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9214
diff changeset
   529
    The message contains two or three parts. First, the changeset
12749
338b4b615d33 patchbomb: move command option help from the extension (patchbomb) to the command (email)
timeless <timeless@gmail.com>
parents: 12265
diff changeset
   530
    description.
338b4b615d33 patchbomb: move command option help from the extension (patchbomb) to the command (email)
timeless <timeless@gmail.com>
parents: 12265
diff changeset
   531
338b4b615d33 patchbomb: move command option help from the extension (patchbomb) to the command (email)
timeless <timeless@gmail.com>
parents: 12265
diff changeset
   532
    With the -d/--diffstat option, if the diffstat program is
338b4b615d33 patchbomb: move command option help from the extension (patchbomb) to the command (email)
timeless <timeless@gmail.com>
parents: 12265
diff changeset
   533
    installed, the result of running diffstat on the patch is inserted.
338b4b615d33 patchbomb: move command option help from the extension (patchbomb) to the command (email)
timeless <timeless@gmail.com>
parents: 12265
diff changeset
   534
338b4b615d33 patchbomb: move command option help from the extension (patchbomb) to the command (email)
timeless <timeless@gmail.com>
parents: 12265
diff changeset
   535
    Finally, the patch itself, as generated by :hg:`export`.
338b4b615d33 patchbomb: move command option help from the extension (patchbomb) to the command (email)
timeless <timeless@gmail.com>
parents: 12265
diff changeset
   536
17880
9f6044119166 patchbomb: -c is not an alias for the --confirm option
Julian Cowley <julian@lava.net>
parents: 17859
diff changeset
   537
    With the -d/--diffstat or --confirm options, you will be presented
12749
338b4b615d33 patchbomb: move command option help from the extension (patchbomb) to the command (email)
timeless <timeless@gmail.com>
parents: 12265
diff changeset
   538
    with a final summary of all messages and asked for confirmation before
338b4b615d33 patchbomb: move command option help from the extension (patchbomb) to the command (email)
timeless <timeless@gmail.com>
parents: 12265
diff changeset
   539
    the messages are sent.
4262
f51317e24114 Add --outgoing option to patchbomb
Brendan Cully <brendan@kublai.com>
parents: 4144
diff changeset
   540
9269
1d6499adf211 patchbomb: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9214
diff changeset
   541
    By default the patch is included as text in the email body for
1d6499adf211 patchbomb: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9214
diff changeset
   542
    easy reviewing. Using the -a/--attach option will instead create
1d6499adf211 patchbomb: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9214
diff changeset
   543
    an attachment for the patch. With -i/--inline an inline attachment
16307
17a9a1f5cee2 patchbomb: add --body flag to send patches as inline message body text
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 16233
diff changeset
   544
    will be created. You can include a patch both as text in the email
17a9a1f5cee2 patchbomb: add --body flag to send patches as inline message body text
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 16233
diff changeset
   545
    body and as a regular or an inline attachment by combining the
17a9a1f5cee2 patchbomb: add --body flag to send patches as inline message body text
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 16233
diff changeset
   546
    -a/--attach or -i/--inline with the --body option.
8472
223363bb6d66 patchbomb: describe --attach and --inline options in help
Martin Geisler <mg@lazybytes.net>
parents: 8471
diff changeset
   547
32639
c2fe2b00db53 patchbomb: add -B option to select a bookmark
David Demelier <demelier.david@gmail.com>
parents: 32375
diff changeset
   548
    With -B/--bookmark changesets reachable by the given bookmark are
c2fe2b00db53 patchbomb: add -B option to select a bookmark
David Demelier <demelier.david@gmail.com>
parents: 32375
diff changeset
   549
    selected.
c2fe2b00db53 patchbomb: add -B option to select a bookmark
David Demelier <demelier.david@gmail.com>
parents: 32375
diff changeset
   550
9269
1d6499adf211 patchbomb: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9214
diff changeset
   551
    With -o/--outgoing, emails will be generated for patches not found
1d6499adf211 patchbomb: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9214
diff changeset
   552
    in the destination repository (or only those which are ancestors
1d6499adf211 patchbomb: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9214
diff changeset
   553
    of the specified revisions if any are provided)
4280
a9336520a4ee Improve documentation for patchbomb and email
John Goerzen <jgoerzen@complete.org>
parents: 4279
diff changeset
   554
9269
1d6499adf211 patchbomb: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9214
diff changeset
   555
    With -b/--bundle, changesets are selected as for --outgoing, but a
1d6499adf211 patchbomb: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9214
diff changeset
   556
    single email containing a binary Mercurial bundle as an attachment
26563
d4a1bfe1de63 patchbomb: add a 'bundletype' config under 'patchbomb'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26546
diff changeset
   557
    will be sent. Use the ``patchbomb.bundletype`` config option to
d4a1bfe1de63 patchbomb: add a 'bundletype' config under 'patchbomb'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26546
diff changeset
   558
    control the bundle type as with :hg:`bundle --type`.
4280
a9336520a4ee Improve documentation for patchbomb and email
John Goerzen <jgoerzen@complete.org>
parents: 4279
diff changeset
   559
12749
338b4b615d33 patchbomb: move command option help from the extension (patchbomb) to the command (email)
timeless <timeless@gmail.com>
parents: 12265
diff changeset
   560
    With -m/--mbox, instead of previewing each patchbomb message in a
338b4b615d33 patchbomb: move command option help from the extension (patchbomb) to the command (email)
timeless <timeless@gmail.com>
parents: 12265
diff changeset
   561
    pager or sending the messages directly, it will create a UNIX
338b4b615d33 patchbomb: move command option help from the extension (patchbomb) to the command (email)
timeless <timeless@gmail.com>
parents: 12265
diff changeset
   562
    mailbox file with the patch emails. This mailbox file can be
338b4b615d33 patchbomb: move command option help from the extension (patchbomb) to the command (email)
timeless <timeless@gmail.com>
parents: 12265
diff changeset
   563
    previewed with any mail user agent which supports UNIX mbox
338b4b615d33 patchbomb: move command option help from the extension (patchbomb) to the command (email)
timeless <timeless@gmail.com>
parents: 12265
diff changeset
   564
    files.
338b4b615d33 patchbomb: move command option help from the extension (patchbomb) to the command (email)
timeless <timeless@gmail.com>
parents: 12265
diff changeset
   565
338b4b615d33 patchbomb: move command option help from the extension (patchbomb) to the command (email)
timeless <timeless@gmail.com>
parents: 12265
diff changeset
   566
    With -n/--test, all steps will run, but mail will not be sent.
338b4b615d33 patchbomb: move command option help from the extension (patchbomb) to the command (email)
timeless <timeless@gmail.com>
parents: 12265
diff changeset
   567
    You will be prompted for an email recipient address, a subject and
338b4b615d33 patchbomb: move command option help from the extension (patchbomb) to the command (email)
timeless <timeless@gmail.com>
parents: 12265
diff changeset
   568
    an introductory message describing the patches of your patchbomb.
31489
5b2e1689b24d patchbomb: use modern pager to display -n/--test result (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 31187
diff changeset
   569
    Then when all is done, patchbomb messages are displayed.
12749
338b4b615d33 patchbomb: move command option help from the extension (patchbomb) to the command (email)
timeless <timeless@gmail.com>
parents: 12265
diff changeset
   570
13198
e71b2aa74ce3 patchbomb: save introductory message in .hg/last-email.txt
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 12839
diff changeset
   571
    In case email sending fails, you will find a backup of your series
23488
11b215731e74 patchbomb: introduce a 'patchbomb.confirm' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23487
diff changeset
   572
    introductory message in ``.hg/last-email.txt``.
11b215731e74 patchbomb: introduce a 'patchbomb.confirm' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23487
diff changeset
   573
11b215731e74 patchbomb: introduce a 'patchbomb.confirm' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23487
diff changeset
   574
    The default behavior of this command can be customized through
11b215731e74 patchbomb: introduce a 'patchbomb.confirm' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23487
diff changeset
   575
    configuration. (See :hg:`help patchbomb` for details)
13198
e71b2aa74ce3 patchbomb: save introductory message in .hg/last-email.txt
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 12839
diff changeset
   576
9289
45aaf27f95b8 patchbomb: reST syntax for literal blocks in help text
Christian Ebert <blacktrash@gmx.net>
parents: 9286
diff changeset
   577
    Examples::
4280
a9336520a4ee Improve documentation for patchbomb and email
John Goerzen <jgoerzen@complete.org>
parents: 4279
diff changeset
   578
9289
45aaf27f95b8 patchbomb: reST syntax for literal blocks in help text
Christian Ebert <blacktrash@gmx.net>
parents: 9286
diff changeset
   579
      hg email -r 3000          # send patch 3000 only
45aaf27f95b8 patchbomb: reST syntax for literal blocks in help text
Christian Ebert <blacktrash@gmx.net>
parents: 9286
diff changeset
   580
      hg email -r 3000 -r 3001  # send patches 3000 and 3001
45aaf27f95b8 patchbomb: reST syntax for literal blocks in help text
Christian Ebert <blacktrash@gmx.net>
parents: 9286
diff changeset
   581
      hg email -r 3000:3005     # send patches 3000 through 3005
45aaf27f95b8 patchbomb: reST syntax for literal blocks in help text
Christian Ebert <blacktrash@gmx.net>
parents: 9286
diff changeset
   582
      hg email 3000             # send patch 3000 (deprecated)
4280
a9336520a4ee Improve documentation for patchbomb and email
John Goerzen <jgoerzen@complete.org>
parents: 4279
diff changeset
   583
9289
45aaf27f95b8 patchbomb: reST syntax for literal blocks in help text
Christian Ebert <blacktrash@gmx.net>
parents: 9286
diff changeset
   584
      hg email -o               # send all patches not in default
45aaf27f95b8 patchbomb: reST syntax for literal blocks in help text
Christian Ebert <blacktrash@gmx.net>
parents: 9286
diff changeset
   585
      hg email -o DEST          # send all patches not in DEST
45aaf27f95b8 patchbomb: reST syntax for literal blocks in help text
Christian Ebert <blacktrash@gmx.net>
parents: 9286
diff changeset
   586
      hg email -o -r 3000       # send all ancestors of 3000 not in default
45aaf27f95b8 patchbomb: reST syntax for literal blocks in help text
Christian Ebert <blacktrash@gmx.net>
parents: 9286
diff changeset
   587
      hg email -o -r 3000 DEST  # send all ancestors of 3000 not in DEST
4280
a9336520a4ee Improve documentation for patchbomb and email
John Goerzen <jgoerzen@complete.org>
parents: 4279
diff changeset
   588
32639
c2fe2b00db53 patchbomb: add -B option to select a bookmark
David Demelier <demelier.david@gmail.com>
parents: 32375
diff changeset
   589
      hg email -B feature       # send all ancestors of feature bookmark
c2fe2b00db53 patchbomb: add -B option to select a bookmark
David Demelier <demelier.david@gmail.com>
parents: 32375
diff changeset
   590
9289
45aaf27f95b8 patchbomb: reST syntax for literal blocks in help text
Christian Ebert <blacktrash@gmx.net>
parents: 9286
diff changeset
   591
      hg email -b               # send bundle of all patches not in default
45aaf27f95b8 patchbomb: reST syntax for literal blocks in help text
Christian Ebert <blacktrash@gmx.net>
parents: 9286
diff changeset
   592
      hg email -b DEST          # send bundle of all patches not in DEST
45aaf27f95b8 patchbomb: reST syntax for literal blocks in help text
Christian Ebert <blacktrash@gmx.net>
parents: 9286
diff changeset
   593
      hg email -b -r 3000       # bundle of all ancestors of 3000 not in default
45aaf27f95b8 patchbomb: reST syntax for literal blocks in help text
Christian Ebert <blacktrash@gmx.net>
parents: 9286
diff changeset
   594
      hg email -b -r 3000 DEST  # bundle of all ancestors of 3000 not in DEST
4280
a9336520a4ee Improve documentation for patchbomb and email
John Goerzen <jgoerzen@complete.org>
parents: 4279
diff changeset
   595
12749
338b4b615d33 patchbomb: move command option help from the extension (patchbomb) to the command (email)
timeless <timeless@gmail.com>
parents: 12265
diff changeset
   596
      hg email -o -m mbox &&    # generate an mbox file...
338b4b615d33 patchbomb: move command option help from the extension (patchbomb) to the command (email)
timeless <timeless@gmail.com>
parents: 12265
diff changeset
   597
        mutt -R -f mbox         # ... and view it with mutt
338b4b615d33 patchbomb: move command option help from the extension (patchbomb) to the command (email)
timeless <timeless@gmail.com>
parents: 12265
diff changeset
   598
      hg email -o -m mbox &&    # generate an mbox file ...
12839
d85e30889f26 patchbomb: fix stray backslash in docstring
Martin Geisler <mg@lazybytes.net>
parents: 12794
diff changeset
   599
        formail -s sendmail \\   # ... and use formail to send from the mbox
12749
338b4b615d33 patchbomb: move command option help from the extension (patchbomb) to the command (email)
timeless <timeless@gmail.com>
parents: 12265
diff changeset
   600
          -bm -t < mbox         # ... using sendmail
338b4b615d33 patchbomb: move command option help from the extension (patchbomb) to the command (email)
timeless <timeless@gmail.com>
parents: 12265
diff changeset
   601
9269
1d6499adf211 patchbomb: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9214
diff changeset
   602
    Before using this command, you will need to enable email in your
1d6499adf211 patchbomb: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9214
diff changeset
   603
    hgrc. See the [email] section in hgrc(5) for details.
4262
f51317e24114 Add --outgoing option to patchbomb
Brendan Cully <brendan@kublai.com>
parents: 4144
diff changeset
   604
    '''
35044
71e63fe6b1ab py3: handle keyword arguments correctly in hgext/patchbomb.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34911
diff changeset
   605
    opts = pycompat.byteskwargs(opts)
4262
f51317e24114 Add --outgoing option to patchbomb
Brendan Cully <brendan@kublai.com>
parents: 4144
diff changeset
   606
7115
c5c2d43b01da patchbomb: mime-encode headers and parts not containing patches
Christian Ebert <blacktrash@gmx.net>
parents: 7095
diff changeset
   607
    _charsets = mail._charsets(ui)
c5c2d43b01da patchbomb: mime-encode headers and parts not containing patches
Christian Ebert <blacktrash@gmx.net>
parents: 7095
diff changeset
   608
11413
4c1fe996838c patchbomb: reduce number of opts.get calls
Christian Ebert <blacktrash@gmx.net>
parents: 11321
diff changeset
   609
    bundle = opts.get('bundle')
4c1fe996838c patchbomb: reduce number of opts.get calls
Christian Ebert <blacktrash@gmx.net>
parents: 11321
diff changeset
   610
    date = opts.get('date')
4c1fe996838c patchbomb: reduce number of opts.get calls
Christian Ebert <blacktrash@gmx.net>
parents: 11321
diff changeset
   611
    mbox = opts.get('mbox')
4c1fe996838c patchbomb: reduce number of opts.get calls
Christian Ebert <blacktrash@gmx.net>
parents: 11321
diff changeset
   612
    outgoing = opts.get('outgoing')
4c1fe996838c patchbomb: reduce number of opts.get calls
Christian Ebert <blacktrash@gmx.net>
parents: 11321
diff changeset
   613
    rev = opts.get('rev')
32639
c2fe2b00db53 patchbomb: add -B option to select a bookmark
David Demelier <demelier.david@gmail.com>
parents: 32375
diff changeset
   614
    bookmark = opts.get('bookmark')
11413
4c1fe996838c patchbomb: reduce number of opts.get calls
Christian Ebert <blacktrash@gmx.net>
parents: 11321
diff changeset
   615
4c1fe996838c patchbomb: reduce number of opts.get calls
Christian Ebert <blacktrash@gmx.net>
parents: 11321
diff changeset
   616
    if not (opts.get('test') or mbox):
5472
23889160905a Catch smtp exceptions
Christian Ebert <blacktrash@gmx.net>
parents: 4887
diff changeset
   617
        # really sending
4489
a11e13d50645 patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4486
diff changeset
   618
        mail.validateconfig(ui)
a11e13d50645 patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4486
diff changeset
   619
32639
c2fe2b00db53 patchbomb: add -B option to select a bookmark
David Demelier <demelier.david@gmail.com>
parents: 32375
diff changeset
   620
    if not (revs or rev or outgoing or bundle or bookmark):
c2fe2b00db53 patchbomb: add -B option to select a bookmark
David Demelier <demelier.david@gmail.com>
parents: 32375
diff changeset
   621
        raise error.Abort(_('specify at least one changeset with -B, -r or -o'))
4493
ead2fa544cbf patchbomb: Fail early if no revs given to email
Bryan O'Sullivan <bos@serpentine.com>
parents: 4492
diff changeset
   622
11413
4c1fe996838c patchbomb: reduce number of opts.get calls
Christian Ebert <blacktrash@gmx.net>
parents: 11321
diff changeset
   623
    if outgoing and bundle:
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26563
diff changeset
   624
        raise error.Abort(_("--outgoing mode always on with --bundle;"
5746
d3ef7e86bc3b patchbomb: break lines > 80 chars (coding style)
Christian Ebert <blacktrash@gmx.net>
parents: 5677
diff changeset
   625
                           " do not re-specify --outgoing"))
32695
0841382d114a patchbomb: avoid -r and -B options at the same time
David Demelier <demelier.david@gmail.com>
parents: 32639
diff changeset
   626
    if rev and bookmark:
0841382d114a patchbomb: avoid -r and -B options at the same time
David Demelier <demelier.david@gmail.com>
parents: 32639
diff changeset
   627
        raise error.Abort(_("-r and -B are mutually exclusive"))
4278
cfe886c14ddf Add ability to send bundles to patchbomb extension
John Goerzen <jgoerzen@complete.org>
parents: 4262
diff changeset
   628
11413
4c1fe996838c patchbomb: reduce number of opts.get calls
Christian Ebert <blacktrash@gmx.net>
parents: 11321
diff changeset
   629
    if outgoing or bundle:
4262
f51317e24114 Add --outgoing option to patchbomb
Brendan Cully <brendan@kublai.com>
parents: 4144
diff changeset
   630
        if len(revs) > 1:
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26563
diff changeset
   631
            raise error.Abort(_("too many destinations"))
24306
6ddc86eedc3b style: kill ersatz if-else ternary operators
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23877
diff changeset
   632
        if revs:
6ddc86eedc3b style: kill ersatz if-else ternary operators
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23877
diff changeset
   633
            dest = revs[0]
6ddc86eedc3b style: kill ersatz if-else ternary operators
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23877
diff changeset
   634
        else:
6ddc86eedc3b style: kill ersatz if-else ternary operators
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 23877
diff changeset
   635
            dest = None
4262
f51317e24114 Add --outgoing option to patchbomb
Brendan Cully <brendan@kublai.com>
parents: 4144
diff changeset
   636
        revs = []
f51317e24114 Add --outgoing option to patchbomb
Brendan Cully <brendan@kublai.com>
parents: 4144
diff changeset
   637
11413
4c1fe996838c patchbomb: reduce number of opts.get calls
Christian Ebert <blacktrash@gmx.net>
parents: 11321
diff changeset
   638
    if rev:
4262
f51317e24114 Add --outgoing option to patchbomb
Brendan Cully <brendan@kublai.com>
parents: 4144
diff changeset
   639
        if revs:
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26563
diff changeset
   640
            raise error.Abort(_('use only one form to specify the revision'))
11413
4c1fe996838c patchbomb: reduce number of opts.get calls
Christian Ebert <blacktrash@gmx.net>
parents: 11321
diff changeset
   641
        revs = rev
32639
c2fe2b00db53 patchbomb: add -B option to select a bookmark
David Demelier <demelier.david@gmail.com>
parents: 32375
diff changeset
   642
    elif bookmark:
c2fe2b00db53 patchbomb: add -B option to select a bookmark
David Demelier <demelier.david@gmail.com>
parents: 32375
diff changeset
   643
        if bookmark not in repo._bookmarks:
c2fe2b00db53 patchbomb: add -B option to select a bookmark
David Demelier <demelier.david@gmail.com>
parents: 32375
diff changeset
   644
            raise error.Abort(_("bookmark '%s' not found") % bookmark)
38131
46c2b19a1263 scmutil: move repair.stripbmrevset as scmutil.bookmarkrevs (API)
David Demelier <markand@malikania.fr>
parents: 37603
diff changeset
   645
        revs = scmutil.bookmarkrevs(repo, bookmark)
4262
f51317e24114 Add --outgoing option to patchbomb
Brendan Cully <brendan@kublai.com>
parents: 4144
diff changeset
   646
24568
2e5f6cdf01f6 patchbomb: factor out scmutil.revrange() calls
Yuya Nishihara <yuya@tcha.org>
parents: 24567
diff changeset
   647
    revs = scmutil.revrange(repo, revs)
11413
4c1fe996838c patchbomb: reduce number of opts.get calls
Christian Ebert <blacktrash@gmx.net>
parents: 11321
diff changeset
   648
    if outgoing:
24568
2e5f6cdf01f6 patchbomb: factor out scmutil.revrange() calls
Yuya Nishihara <yuya@tcha.org>
parents: 24567
diff changeset
   649
        revs = _getoutgoing(repo, dest, revs)
11413
4c1fe996838c patchbomb: reduce number of opts.get calls
Christian Ebert <blacktrash@gmx.net>
parents: 11321
diff changeset
   650
    if bundle:
36668
e77cee5de1c7 py3: use b"%d" to covert integer to bytes instead of str
Pulkit Goyal <7895pulkit@gmail.com>
parents: 36607
diff changeset
   651
        opts['revs'] = ["%d" % r for r in revs]
4262
f51317e24114 Add --outgoing option to patchbomb
Brendan Cully <brendan@kublai.com>
parents: 4144
diff changeset
   652
26626
dca161728dc9 patchbomb: check that targets exist at the publicurl
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
   653
    # check if revision exist on the public destination
dca161728dc9 patchbomb: check that targets exist at the publicurl
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
   654
    publicurl = repo.ui.config('patchbomb', 'publicurl')
32825
16ff5c6066a6 patchbomb: look for non-empty publicurl, not a non-None one
Augie Fackler <augie@google.com>
parents: 32824
diff changeset
   655
    if publicurl:
35466
7906354cbc68 debug: add newlines at the end of three locations that appear to need it
Kyle Lippincott <spectral@google.com>
parents: 35044
diff changeset
   656
        repo.ui.debug('checking that revision exist in the public repo\n')
26626
dca161728dc9 patchbomb: check that targets exist at the publicurl
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
   657
        try:
dca161728dc9 patchbomb: check that targets exist at the publicurl
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
   658
            publicpeer = hg.peer(repo, {}, publicurl)
dca161728dc9 patchbomb: check that targets exist at the publicurl
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
   659
        except error.RepoError:
dca161728dc9 patchbomb: check that targets exist at the publicurl
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
   660
            repo.ui.write_err(_('unable to access public repo: %s\n')
dca161728dc9 patchbomb: check that targets exist at the publicurl
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
   661
                              % publicurl)
dca161728dc9 patchbomb: check that targets exist at the publicurl
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
   662
            raise
dca161728dc9 patchbomb: check that targets exist at the publicurl
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
   663
        if not publicpeer.capable('known'):
35466
7906354cbc68 debug: add newlines at the end of three locations that appear to need it
Kyle Lippincott <spectral@google.com>
parents: 35044
diff changeset
   664
            repo.ui.debug('skipping existence checks: public repo too old\n')
26626
dca161728dc9 patchbomb: check that targets exist at the publicurl
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
   665
        else:
dca161728dc9 patchbomb: check that targets exist at the publicurl
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
   666
            out = [repo[r] for r in revs]
dca161728dc9 patchbomb: check that targets exist at the publicurl
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
   667
            known = publicpeer.known(h.node() for h in out)
dca161728dc9 patchbomb: check that targets exist at the publicurl
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
   668
            missing = []
dca161728dc9 patchbomb: check that targets exist at the publicurl
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
   669
            for idx, h in enumerate(out):
dca161728dc9 patchbomb: check that targets exist at the publicurl
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
   670
                if not known[idx]:
dca161728dc9 patchbomb: check that targets exist at the publicurl
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
   671
                    missing.append(h)
dca161728dc9 patchbomb: check that targets exist at the publicurl
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
   672
            if missing:
40029
e2697acd9381 cleanup: some Yoda conditions, this patch removes
Martin von Zweigbergk <martinvonz@google.com>
parents: 39118
diff changeset
   673
                if len(missing) > 1:
26626
dca161728dc9 patchbomb: check that targets exist at the publicurl
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
   674
                    msg = _('public "%s" is missing %s and %i others')
dca161728dc9 patchbomb: check that targets exist at the publicurl
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
   675
                    msg %= (publicurl, missing[0], len(missing) - 1)
dca161728dc9 patchbomb: check that targets exist at the publicurl
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
   676
                else:
dca161728dc9 patchbomb: check that targets exist at the publicurl
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
   677
                    msg = _('public url %s is missing %s')
dca161728dc9 patchbomb: check that targets exist at the publicurl
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
   678
                    msg %= (publicurl, missing[0])
36410
67ec4ad815e6 patchbomb: resolve revs before evaluating %ld revset
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36204
diff changeset
   679
                missingrevs = [ctx.rev() for ctx in missing]
28907
66e647312d30 patchbomb: fix public-is-missing hint
timeless <timeless@mozdev.org>
parents: 28861
diff changeset
   680
                revhint = ' '.join('-r %s' % h
36410
67ec4ad815e6 patchbomb: resolve revs before evaluating %ld revset
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36204
diff changeset
   681
                                   for h in repo.set('heads(%ld)', missingrevs))
28981
7b188bc23942 patchbomb: use single quotes around command hint
timeless <timeless@mozdev.org>
parents: 28907
diff changeset
   682
                hint = _("use 'hg push %s %s'") % (publicurl, revhint)
26626
dca161728dc9 patchbomb: check that targets exist at the publicurl
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
   683
                raise error.Abort(msg, hint=hint)
dca161728dc9 patchbomb: check that targets exist at the publicurl
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26587
diff changeset
   684
4262
f51317e24114 Add --outgoing option to patchbomb
Brendan Cully <brendan@kublai.com>
parents: 4144
diff changeset
   685
    # start
11413
4c1fe996838c patchbomb: reduce number of opts.get calls
Christian Ebert <blacktrash@gmx.net>
parents: 11321
diff changeset
   686
    if date:
36607
c6061cadb400 util: extract all date-related utils in utils/dateutil module
Boris Feld <boris.feld@octobus.net>
parents: 36450
diff changeset
   687
        start_time = dateutil.parsedate(date)
4566
087b3ae4f08a patchbomb: add --date option
Bryan O'Sullivan <bos@serpentine.com>
parents: 4565
diff changeset
   688
    else:
36607
c6061cadb400 util: extract all date-related utils in utils/dateutil module
Boris Feld <boris.feld@octobus.net>
parents: 36450
diff changeset
   689
        start_time = dateutil.makedate()
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   690
876
14cfaaec2e8e Get patchbomb script to not use MIME attachments.
Bryan O'Sullivan <bos@serpentine.com>
parents: 875
diff changeset
   691
    def genmsgid(id):
39117
4899c6d22dff patchbomb: extract function for generating message-id
Augie Fackler <raf@durin42.com>
parents: 39104
diff changeset
   692
        return _msgid(id[:20], int(start_time[0]))
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   693
25825
577b050caada patchbomb: mark ancient option deprecated
Matt Mackall <mpm@selenic.com>
parents: 25660
diff changeset
   694
    # deprecated config: patchbomb.from
5818
77775ae8d5d9 patchbomb: consistently use opts.get
Christian Ebert <blacktrash@gmx.net>
parents: 5817
diff changeset
   695
    sender = (opts.get('from') or ui.config('email', 'from') or
2198
564034552f7f rename [patchbomb] section to [email] section in hgrc. old name still ok.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2165
diff changeset
   696
              ui.config('patchbomb', 'from') or
7354
cad454f295b0 patchbomb: extract a bunch of nested functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7353
diff changeset
   697
              prompt(ui, 'From', ui.username()))
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   698
31184
e3ab7c717129 patchbomb: drop internal option for pbranch extension (API)
Yuya Nishihara <yuya@tcha.org>
parents: 31183
diff changeset
   699
    if bundle:
35044
71e63fe6b1ab py3: handle keyword arguments correctly in hgext/patchbomb.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34911
diff changeset
   700
        stropts = pycompat.strkwargs(opts)
71e63fe6b1ab py3: handle keyword arguments correctly in hgext/patchbomb.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34911
diff changeset
   701
        bundledata = _getbundle(repo, dest, **stropts)
71e63fe6b1ab py3: handle keyword arguments correctly in hgext/patchbomb.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34911
diff changeset
   702
        bundleopts = stropts.copy()
71e63fe6b1ab py3: handle keyword arguments correctly in hgext/patchbomb.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34911
diff changeset
   703
        bundleopts.pop(r'bundle', None)  # already processed
23213
23a78662b6dd patchbomb: extract 'getbundlemsgs' closure in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23212
diff changeset
   704
        msgs = _getbundlemsgs(repo, sender, bundledata, **bundleopts)
4278
cfe886c14ddf Add ability to send bundles to patchbomb extension
John Goerzen <jgoerzen@complete.org>
parents: 4262
diff changeset
   705
    else:
35044
71e63fe6b1ab py3: handle keyword arguments correctly in hgext/patchbomb.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34911
diff changeset
   706
        msgs = _getpatchmsgs(repo, sender, revs, **pycompat.strkwargs(opts))
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   707
12200
aebb39d45500 patchbomb: let diffstat prompt only once with complete summary
Christian Ebert <blacktrash@gmx.net>
parents: 12199
diff changeset
   708
    showaddrs = []
aebb39d45500 patchbomb: let diffstat prompt only once with complete summary
Christian Ebert <blacktrash@gmx.net>
parents: 12199
diff changeset
   709
15162
d67a15b2e608 patchbomb: simplify some contorted logic and odd variable names.
Greg Ward <greg@gerg.ca>
parents: 14556
diff changeset
   710
    def getaddrs(header, ask=False, default=None):
d67a15b2e608 patchbomb: simplify some contorted logic and odd variable names.
Greg Ward <greg@gerg.ca>
parents: 14556
diff changeset
   711
        configkey = header.lower()
d67a15b2e608 patchbomb: simplify some contorted logic and odd variable names.
Greg Ward <greg@gerg.ca>
parents: 14556
diff changeset
   712
        opt = header.replace('-', '_').lower()
d67a15b2e608 patchbomb: simplify some contorted logic and odd variable names.
Greg Ward <greg@gerg.ca>
parents: 14556
diff changeset
   713
        addrs = opts.get(opt)
11150
f66ca4431eb9 patchbomb: Reply-To support
Cédric Duval <cedricduval@free.fr>
parents: 10973
diff changeset
   714
        if addrs:
15162
d67a15b2e608 patchbomb: simplify some contorted logic and odd variable names.
Greg Ward <greg@gerg.ca>
parents: 14556
diff changeset
   715
            showaddrs.append('%s: %s' % (header, ', '.join(addrs)))
12264
b8146231c3de patchbomb: consistent code style in getaddrs()
Christian Ebert <blacktrash@gmx.net>
parents: 12201
diff changeset
   716
            return mail.addrlistencode(ui, addrs, _charsets, opts.get('test'))
9947
4600e6222efb patchbomb: fix parsing of multiple addresses, allow multiple addrs in --to/cc/bcc
Marti Raudsepp <marti@juffo.org>
parents: 9818
diff changeset
   717
15162
d67a15b2e608 patchbomb: simplify some contorted logic and odd variable names.
Greg Ward <greg@gerg.ca>
parents: 14556
diff changeset
   718
        # not on the command line: fallback to config and then maybe ask
d67a15b2e608 patchbomb: simplify some contorted logic and odd variable names.
Greg Ward <greg@gerg.ca>
parents: 14556
diff changeset
   719
        addr = (ui.config('email', configkey) or
27697
0ce0cfee497f patchbomb: treat empty address list as no addresses
Bryan O'Sullivan <bos@serpentine.com>
parents: 27150
diff changeset
   720
                ui.config('patchbomb', configkey))
0ce0cfee497f patchbomb: treat empty address list as no addresses
Bryan O'Sullivan <bos@serpentine.com>
parents: 27150
diff changeset
   721
        if not addr:
0ce0cfee497f patchbomb: treat empty address list as no addresses
Bryan O'Sullivan <bos@serpentine.com>
parents: 27150
diff changeset
   722
            specified = (ui.hasconfig('email', configkey) or
0ce0cfee497f patchbomb: treat empty address list as no addresses
Bryan O'Sullivan <bos@serpentine.com>
parents: 27150
diff changeset
   723
                         ui.hasconfig('patchbomb', configkey))
0ce0cfee497f patchbomb: treat empty address list as no addresses
Bryan O'Sullivan <bos@serpentine.com>
parents: 27150
diff changeset
   724
            if not specified and ask:
0ce0cfee497f patchbomb: treat empty address list as no addresses
Bryan O'Sullivan <bos@serpentine.com>
parents: 27150
diff changeset
   725
                addr = prompt(ui, header, default=default)
15162
d67a15b2e608 patchbomb: simplify some contorted logic and odd variable names.
Greg Ward <greg@gerg.ca>
parents: 14556
diff changeset
   726
        if addr:
d67a15b2e608 patchbomb: simplify some contorted logic and odd variable names.
Greg Ward <greg@gerg.ca>
parents: 14556
diff changeset
   727
            showaddrs.append('%s: %s' % (header, addr))
15164
7bddec632821 patchbomb: make it easy for the user to decline sending an intro message.
Greg Ward <greg@gerg.ca>
parents: 15162
diff changeset
   728
            return mail.addrlistencode(ui, [addr], _charsets, opts.get('test'))
32826
3abba5bc3454 patchbomb: make getaddrs function easier to work with
Augie Fackler <augie@google.com>
parents: 32825
diff changeset
   729
        elif default:
3abba5bc3454 patchbomb: make getaddrs function easier to work with
Augie Fackler <augie@google.com>
parents: 32825
diff changeset
   730
            return mail.addrlistencode(
3abba5bc3454 patchbomb: make getaddrs function easier to work with
Augie Fackler <augie@google.com>
parents: 32825
diff changeset
   731
                ui, [default], _charsets, opts.get('test'))
3abba5bc3454 patchbomb: make getaddrs function easier to work with
Augie Fackler <augie@google.com>
parents: 32825
diff changeset
   732
        return []
9947
4600e6222efb patchbomb: fix parsing of multiple addresses, allow multiple addrs in --to/cc/bcc
Marti Raudsepp <marti@juffo.org>
parents: 9818
diff changeset
   733
15162
d67a15b2e608 patchbomb: simplify some contorted logic and odd variable names.
Greg Ward <greg@gerg.ca>
parents: 14556
diff changeset
   734
    to = getaddrs('To', ask=True)
15164
7bddec632821 patchbomb: make it easy for the user to decline sending an intro message.
Greg Ward <greg@gerg.ca>
parents: 15162
diff changeset
   735
    if not to:
7bddec632821 patchbomb: make it easy for the user to decline sending an intro message.
Greg Ward <greg@gerg.ca>
parents: 15162
diff changeset
   736
        # we can get here in non-interactive mode
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26563
diff changeset
   737
        raise error.Abort(_('no recipient addresses provided'))
32826
3abba5bc3454 patchbomb: make getaddrs function easier to work with
Augie Fackler <augie@google.com>
parents: 32825
diff changeset
   738
    cc = getaddrs('Cc', ask=True, default='')
3abba5bc3454 patchbomb: make getaddrs function easier to work with
Augie Fackler <augie@google.com>
parents: 32825
diff changeset
   739
    bcc = getaddrs('Bcc')
15162
d67a15b2e608 patchbomb: simplify some contorted logic and odd variable names.
Greg Ward <greg@gerg.ca>
parents: 14556
diff changeset
   740
    replyto = getaddrs('Reply-To')
2679
f1de91be1d87 optionally send blind carbon copies
Christian Ebert <blacktrash@gmx.net>
parents: 2443
diff changeset
   741
23488
11b215731e74 patchbomb: introduce a 'patchbomb.confirm' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23487
diff changeset
   742
    confirm = ui.configbool('patchbomb', 'confirm')
11b215731e74 patchbomb: introduce a 'patchbomb.confirm' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23487
diff changeset
   743
    confirm |= bool(opts.get('diffstat') or opts.get('confirm'))
11b215731e74 patchbomb: introduce a 'patchbomb.confirm' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23487
diff changeset
   744
11b215731e74 patchbomb: introduce a 'patchbomb.confirm' option
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23487
diff changeset
   745
    if confirm:
23173
122f5c3f3308 patchbomb: add label and color to the confirm output
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 21727
diff changeset
   746
        ui.write(_('\nFinal summary:\n\n'), label='patchbomb.finalsummary')
122f5c3f3308 patchbomb: add label and color to the confirm output
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 21727
diff changeset
   747
        ui.write(('From: %s\n' % sender), label='patchbomb.from')
12200
aebb39d45500 patchbomb: let diffstat prompt only once with complete summary
Christian Ebert <blacktrash@gmx.net>
parents: 12199
diff changeset
   748
        for addr in showaddrs:
23173
122f5c3f3308 patchbomb: add label and color to the confirm output
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 21727
diff changeset
   749
            ui.write('%s\n' % addr, label='patchbomb.to')
12200
aebb39d45500 patchbomb: let diffstat prompt only once with complete summary
Christian Ebert <blacktrash@gmx.net>
parents: 12199
diff changeset
   750
        for m, subj, ds in msgs:
23173
122f5c3f3308 patchbomb: add label and color to the confirm output
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 21727
diff changeset
   751
            ui.write(('Subject: %s\n' % subj), label='patchbomb.subject')
12200
aebb39d45500 patchbomb: let diffstat prompt only once with complete summary
Christian Ebert <blacktrash@gmx.net>
parents: 12199
diff changeset
   752
            if ds:
23173
122f5c3f3308 patchbomb: add label and color to the confirm output
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 21727
diff changeset
   753
                ui.write(ds, label='patchbomb.diffstats')
12200
aebb39d45500 patchbomb: let diffstat prompt only once with complete summary
Christian Ebert <blacktrash@gmx.net>
parents: 12199
diff changeset
   754
        ui.write('\n')
19226
c58b6ab4c26f ui: merge prompt text components into a singe string
Matt Mackall <mpm@selenic.com>
parents: 18888
diff changeset
   755
        if ui.promptchoice(_('are you sure you want to send (yn)?'
c58b6ab4c26f ui: merge prompt text components into a singe string
Matt Mackall <mpm@selenic.com>
parents: 18888
diff changeset
   756
                             '$$ &Yes $$ &No')):
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26563
diff changeset
   757
            raise error.Abort(_('patchbomb canceled'))
12200
aebb39d45500 patchbomb: let diffstat prompt only once with complete summary
Christian Ebert <blacktrash@gmx.net>
parents: 12199
diff changeset
   758
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   759
    ui.write('\n')
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   760
8025
1280934dd2dd patchbomb: Support initial in-reply-to header
Henrik Stuart <henrik.stuart at edlund.dk>
parents: 7997
diff changeset
   761
    parent = opts.get('in_reply_to') or None
8826
2aff285b902f patchbomb: do not assume the presence of angle brackets around msg-id
Cédric Duval <cedricduval@free.fr>
parents: 8761
diff changeset
   762
    # angle brackets may be omitted, they're not semantically part of the msg-id
2aff285b902f patchbomb: do not assume the presence of angle brackets around msg-id
Cédric Duval <cedricduval@free.fr>
parents: 8761
diff changeset
   763
    if parent is not None:
2aff285b902f patchbomb: do not assume the presence of angle brackets around msg-id
Cédric Duval <cedricduval@free.fr>
parents: 8761
diff changeset
   764
        if not parent.startswith('<'):
2aff285b902f patchbomb: do not assume the presence of angle brackets around msg-id
Cédric Duval <cedricduval@free.fr>
parents: 8761
diff changeset
   765
            parent = '<' + parent
2aff285b902f patchbomb: do not assume the presence of angle brackets around msg-id
Cédric Duval <cedricduval@free.fr>
parents: 8761
diff changeset
   766
        if not parent.endswith('>'):
2aff285b902f patchbomb: do not assume the presence of angle brackets around msg-id
Cédric Duval <cedricduval@free.fr>
parents: 8761
diff changeset
   767
            parent += '>'
2aff285b902f patchbomb: do not assume the presence of angle brackets around msg-id
Cédric Duval <cedricduval@free.fr>
parents: 8761
diff changeset
   768
36450
d478c8cd89d1 py3: convert bytes to str using encoding.strfromlocal
Pulkit Goyal <7895pulkit@gmail.com>
parents: 36449
diff changeset
   769
    sender_addr = eutil.parseaddr(encoding.strfromlocal(sender))[1]
7115
c5c2d43b01da patchbomb: mime-encode headers and parts not containing patches
Christian Ebert <blacktrash@gmx.net>
parents: 7095
diff changeset
   770
    sender = mail.addressencode(ui, sender, _charsets, opts.get('test'))
5973
ea77f6f77514 patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents: 5948
diff changeset
   771
    sendmail = None
21726
fae032549ca2 patchbomb: always use message-id of first patch for series-id
Augie Fackler <raf@durin42.com>
parents: 21724
diff changeset
   772
    firstpatch = None
38403
8ce3f91d5f6f patchbomb: use progress helper
Martin von Zweigbergk <martinvonz@google.com>
parents: 38402
diff changeset
   773
    progress = ui.makeprogress(_('sending'), unit=_('emails'), total=len(msgs))
12265
1ed2dc9d4368 patchbomb: show progress when sending emails or writing mbox
Yuya Nishihara <yuya@tcha.org>
parents: 12264
diff changeset
   774
    for i, (m, subj, ds) in enumerate(msgs):
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   775
        try:
876
14cfaaec2e8e Get patchbomb script to not use MIME attachments.
Bryan O'Sullivan <bos@serpentine.com>
parents: 875
diff changeset
   776
            m['Message-Id'] = genmsgid(m['X-Mercurial-Node'])
21726
fae032549ca2 patchbomb: always use message-id of first patch for series-id
Augie Fackler <raf@durin42.com>
parents: 21724
diff changeset
   777
            if not firstpatch:
fae032549ca2 patchbomb: always use message-id of first patch for series-id
Augie Fackler <raf@durin42.com>
parents: 21724
diff changeset
   778
                firstpatch = m['Message-Id']
21727
5f98ad8fb8d9 patchbomb: reorder header insertions to clarify code
Augie Fackler <raf@durin42.com>
parents: 21726
diff changeset
   779
            m['X-Mercurial-Series-Id'] = firstpatch
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   780
        except TypeError:
876
14cfaaec2e8e Get patchbomb script to not use MIME attachments.
Bryan O'Sullivan <bos@serpentine.com>
parents: 875
diff changeset
   781
            m['Message-Id'] = genmsgid('patchbomb')
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   782
        if parent:
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   783
            m['In-Reply-To'] = parent
7413
0b6428da1f22 email: add References field in the header
Benoit Allard <benoit@aeteurope.nl>
parents: 7360
diff changeset
   784
            m['References'] = parent
17859
d38d90ad5bbf patchbomb: respect --in-reply-to for all mails if no intro message is sent
Thomas Arendsen Hein <thomas@intevation.de>
parents: 17178
diff changeset
   785
        if not parent or 'X-Mercurial-Node' not in m:
876
14cfaaec2e8e Get patchbomb script to not use MIME attachments.
Bryan O'Sullivan <bos@serpentine.com>
parents: 875
diff changeset
   786
            parent = m['Message-Id']
8514
252232621165 patchbomb: with --in-reply-to, still thread message under first in series
Cédric Duval <cedricduval@free.fr>
parents: 8512
diff changeset
   787
8160
094e0d982c8a patchbomb: add user agent header to mails
Henrik Stuart <hg@hstuart.dk>
parents: 8076
diff changeset
   788
        m['User-Agent'] = 'Mercurial-patchbomb/%s' % util.version()
36448
39c9f339b692 py3: use email.utils module instead of email.Utils
Pulkit Goyal <7895pulkit@gmail.com>
parents: 36446
diff changeset
   789
        m['Date'] = eutil.formatdate(start_time[0], localtime=True)
2443
bd9c39e8f38b patchbomb does not handle email time stamp plattform independent
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 2292
diff changeset
   790
4027
2601ac9c54f0 patchbomb: fix timezone offset in message date header
Christian Ebert <blacktrash@gmx.net>
parents: 3473
diff changeset
   791
        start_time = (start_time[0] + 1, start_time[1])
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   792
        m['From'] = sender
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   793
        m['To'] = ', '.join(to)
5785
38cd1ce8650d patchbomb: add linebreaks after colons (coding style)
Christian Ebert <blacktrash@gmx.net>
parents: 5758
diff changeset
   794
        if cc:
38cd1ce8650d patchbomb: add linebreaks after colons (coding style)
Christian Ebert <blacktrash@gmx.net>
parents: 5758
diff changeset
   795
            m['Cc']  = ', '.join(cc)
38cd1ce8650d patchbomb: add linebreaks after colons (coding style)
Christian Ebert <blacktrash@gmx.net>
parents: 5758
diff changeset
   796
        if bcc:
38cd1ce8650d patchbomb: add linebreaks after colons (coding style)
Christian Ebert <blacktrash@gmx.net>
parents: 5758
diff changeset
   797
            m['Bcc'] = ', '.join(bcc)
11150
f66ca4431eb9 patchbomb: Reply-To support
Cédric Duval <cedricduval@free.fr>
parents: 10973
diff changeset
   798
        if replyto:
f66ca4431eb9 patchbomb: Reply-To support
Cédric Duval <cedricduval@free.fr>
parents: 10973
diff changeset
   799
            m['Reply-To'] = ', '.join(replyto)
38776
65ed2fcb9032 patchbomb: ensure all headers and values given to email mod are native strings
Augie Fackler <augie@google.com>
parents: 38472
diff changeset
   800
        # Fix up all headers to be native strings.
65ed2fcb9032 patchbomb: ensure all headers and values given to email mod are native strings
Augie Fackler <augie@google.com>
parents: 38472
diff changeset
   801
        # TODO(durin42): this should probably be cleaned up above in the future.
65ed2fcb9032 patchbomb: ensure all headers and values given to email mod are native strings
Augie Fackler <augie@google.com>
parents: 38472
diff changeset
   802
        if pycompat.ispy3:
65ed2fcb9032 patchbomb: ensure all headers and values given to email mod are native strings
Augie Fackler <augie@google.com>
parents: 38472
diff changeset
   803
            for hdr, val in list(m.items()):
39035
cecb05c371f7 patchbomb: don't unintentionally duplicate headers
Augie Fackler <augie@google.com>
parents: 39034
diff changeset
   804
                change = False
38776
65ed2fcb9032 patchbomb: ensure all headers and values given to email mod are native strings
Augie Fackler <augie@google.com>
parents: 38472
diff changeset
   805
                if isinstance(hdr, bytes):
65ed2fcb9032 patchbomb: ensure all headers and values given to email mod are native strings
Augie Fackler <augie@google.com>
parents: 38472
diff changeset
   806
                    del m[hdr]
65ed2fcb9032 patchbomb: ensure all headers and values given to email mod are native strings
Augie Fackler <augie@google.com>
parents: 38472
diff changeset
   807
                    hdr = pycompat.strurl(hdr)
39035
cecb05c371f7 patchbomb: don't unintentionally duplicate headers
Augie Fackler <augie@google.com>
parents: 39034
diff changeset
   808
                    change = True
38776
65ed2fcb9032 patchbomb: ensure all headers and values given to email mod are native strings
Augie Fackler <augie@google.com>
parents: 38472
diff changeset
   809
                if isinstance(val, bytes):
65ed2fcb9032 patchbomb: ensure all headers and values given to email mod are native strings
Augie Fackler <augie@google.com>
parents: 38472
diff changeset
   810
                    val = pycompat.strurl(val)
39035
cecb05c371f7 patchbomb: don't unintentionally duplicate headers
Augie Fackler <augie@google.com>
parents: 39034
diff changeset
   811
                    if not change:
cecb05c371f7 patchbomb: don't unintentionally duplicate headers
Augie Fackler <augie@google.com>
parents: 39034
diff changeset
   812
                        # prevent duplicate headers
cecb05c371f7 patchbomb: don't unintentionally duplicate headers
Augie Fackler <augie@google.com>
parents: 39034
diff changeset
   813
                        del m[hdr]
cecb05c371f7 patchbomb: don't unintentionally duplicate headers
Augie Fackler <augie@google.com>
parents: 39034
diff changeset
   814
                    change = True
cecb05c371f7 patchbomb: don't unintentionally duplicate headers
Augie Fackler <augie@google.com>
parents: 39034
diff changeset
   815
                if change:
cecb05c371f7 patchbomb: don't unintentionally duplicate headers
Augie Fackler <augie@google.com>
parents: 39034
diff changeset
   816
                    m[hdr] = val
5818
77775ae8d5d9 patchbomb: consistently use opts.get
Christian Ebert <blacktrash@gmx.net>
parents: 5817
diff changeset
   817
        if opts.get('test'):
16931
ee388b0a6f67 patchbomb: lowercase status messages
Martin Geisler <mg@aragost.com>
parents: 16743
diff changeset
   818
            ui.status(_('displaying '), subj, ' ...\n')
31489
5b2e1689b24d patchbomb: use modern pager to display -n/--test result (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 31187
diff changeset
   819
            ui.pager('email')
39104
2e578eced958 patchbomb: really use BytesGenerator API
Yuya Nishihara <yuya@tcha.org>
parents: 39038
diff changeset
   820
            generator = _bytesgenerator(ui, mangle_from_=False)
1871
258e3a7955b8 patchbomb: ignore exception if pager quits.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1846
diff changeset
   821
            try:
6447
9d2ce19bdacd patchbomb: Fix mangling of lines beginning with From
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6229
diff changeset
   822
                generator.flatten(m, 0)
31489
5b2e1689b24d patchbomb: use modern pager to display -n/--test result (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 31187
diff changeset
   823
                ui.write('\n')
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25202
diff changeset
   824
            except IOError as inst:
1871
258e3a7955b8 patchbomb: ignore exception if pager quits.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1846
diff changeset
   825
                if inst.errno != errno.EPIPE:
258e3a7955b8 patchbomb: ignore exception if pager quits.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1846
diff changeset
   826
                    raise
15560
cc58c228503e mail: mbox handling as a part of mail handling, refactored from patchbomb
Mads Kiilerich <mads@kiilerich.com>
parents: 15559
diff changeset
   827
        else:
cc58c228503e mail: mbox handling as a part of mail handling, refactored from patchbomb
Mads Kiilerich <mads@kiilerich.com>
parents: 15559
diff changeset
   828
            if not sendmail:
29285
63a3749147af mail: unsupport smtp.verifycert (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29205
diff changeset
   829
                sendmail = mail.connect(ui, mbox=mbox)
16931
ee388b0a6f67 patchbomb: lowercase status messages
Martin Geisler <mg@aragost.com>
parents: 16743
diff changeset
   830
            ui.status(_('sending '), subj, ' ...\n')
38403
8ce3f91d5f6f patchbomb: use progress helper
Martin von Zweigbergk <martinvonz@google.com>
parents: 38402
diff changeset
   831
            progress.update(i, item=subj)
15560
cc58c228503e mail: mbox handling as a part of mail handling, refactored from patchbomb
Mads Kiilerich <mads@kiilerich.com>
parents: 15559
diff changeset
   832
            if not mbox:
cc58c228503e mail: mbox handling as a part of mail handling, refactored from patchbomb
Mads Kiilerich <mads@kiilerich.com>
parents: 15559
diff changeset
   833
                # Exim does not remove the Bcc field
cc58c228503e mail: mbox handling as a part of mail handling, refactored from patchbomb
Mads Kiilerich <mads@kiilerich.com>
parents: 15559
diff changeset
   834
                del m['Bcc']
28861
86db5cb55d46 pycompat: switch to util.stringio for py3 compat
timeless <timeless@mozdev.org>
parents: 28474
diff changeset
   835
            fp = stringio()
39104
2e578eced958 patchbomb: really use BytesGenerator API
Yuya Nishihara <yuya@tcha.org>
parents: 39038
diff changeset
   836
            generator = _bytesgenerator(fp, mangle_from_=False)
6447
9d2ce19bdacd patchbomb: Fix mangling of lines beginning with From
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6229
diff changeset
   837
            generator.flatten(m, 0)
39027
8919cc4f63b4 patchbomb: python 3 really wants those email addresses in unicode
Augie Fackler <augie@google.com>
parents: 39022
diff changeset
   838
            alldests = to + bcc + cc
8919cc4f63b4 patchbomb: python 3 really wants those email addresses in unicode
Augie Fackler <augie@google.com>
parents: 39022
diff changeset
   839
            alldests = [encoding.strfromlocal(d) for d in alldests]
8919cc4f63b4 patchbomb: python 3 really wants those email addresses in unicode
Augie Fackler <augie@google.com>
parents: 39022
diff changeset
   840
            sendmail(sender_addr, alldests, fp.getvalue())
875
d3f836bf6cc1 Add patchbomb script.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   841
38403
8ce3f91d5f6f patchbomb: use progress helper
Martin von Zweigbergk <martinvonz@google.com>
parents: 38402
diff changeset
   842
    progress.complete()