[MERGE] Add mail-mode GNU Emacs mail package as a mail_client option.
Xavier Maillard
xma at gnu.org
Tue Mar 25 01:00:11 GMT 2008
Hello,
As designed by Bojan earlier today, here is my modified version
of it.
The differences are quite small and simple:
1. we use mail-mode instead of the non default message-mode
2. I renamed the python class name
3. I added tests
Credits go to Bojan Nikolic for the original code and idea.
As this is my first /hack/ in Python, do not expect something
polished from me :)
By the way, all tests test_mail_client passed.
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: xma at gnu.org-20080324221201-o29kclhm0kbpx6iq
# target_branch: file:///home/xma/usr/src/BZRed/bzr/bzr.dev/
# testament_sha1: 344f620da994c637eee14a2b2f9a6710b34b306e
# timestamp: 2008-03-24 23:20:31 +0100
# base_revision_id: pqm at pqm.ubuntu.com-20080323231145-nh7pyfd19alqp471
#
# Begin patch
=== modified file 'bzrlib/config.py'
--- bzrlib/config.py 2007-12-02 18:59:28 +0000
+++ bzrlib/config.py 2008-03-24 22:12:01 +0000
@@ -37,7 +37,7 @@
[/home/robertc/source]
recurse=False|True(default)
email= as above
-check_signatures= as above
+check_signatures= as above
create_signatures= as above.
explanation of options
@@ -45,9 +45,9 @@
editor - this option sets the pop up editor to use during commits.
email - this option sets the user id bzr will use when committing.
check_signatures - this option controls whether bzr will require good gpg
- signatures, ignore them, or check them if they are
+ signatures, ignore them, or check them if they are
present.
-create_signatures - this option controls whether bzr will always create
+create_signatures - this option controls whether bzr will always create
gpg signatures, never create them, or create them if the
branch is configured to require them.
log_format - this option sets the default log format. Possible values are
@@ -159,6 +159,7 @@
'default': mail_client.DefaultMail,
'editor': mail_client.Editor,
'mapi': mail_client.MAPIClient,
+ 'emacsclient': mail_client.EmacsClient,
'xdg-email': mail_client.XDGEmail,
}[selected_client]
except KeyError:
@@ -221,16 +222,16 @@
def username(self):
"""Return email-style username.
-
+
Something similar to 'Martin Pool <mbp at sourcefrog.net>'
-
+
$BZR_EMAIL can be set to override this (as well as the
deprecated $BZREMAIL), then
the concrete policy type is checked, and finally
$EMAIL is examined.
If none is found, a reasonable default is (hopefully)
created.
-
+
TODO: Check it's reasonably well-formed.
"""
v = os.environ.get('BZR_EMAIL')
@@ -390,7 +391,7 @@
super(IniBasedConfig, self).__init__()
self._get_filename = get_filename
self._parser = None
-
+
def _post_commit(self):
"""See Config.post_commit."""
return self._get_user_option('post_commit')
@@ -419,7 +420,7 @@
def _get_alias(self, value):
try:
- return self._get_parser().get_value("ALIASES",
+ return self._get_parser().get_value("ALIASES",
value)
except KeyError:
pass
@@ -622,7 +623,7 @@
def _get_safe_value(self, option_name):
"""This variant of get_best_value never returns untrusted values.
-
+
It does not return values from the branch data, because the branch may
not be controlled by the user.
@@ -637,18 +638,18 @@
def _get_user_id(self):
"""Return the full user id for the branch.
-
+
e.g. "John Hacker <jhacker at foo.org>"
This is looked up in the email controlfile for the branch.
"""
try:
- return (self.branch.control_files.get_utf8("email")
+ return (self.branch.control_files.get_utf8("email")
.read()
.decode(bzrlib.user_encoding)
.rstrip("\r\n"))
except errors.NoSuchFile, e:
pass
-
+
return self._get_best_value('_get_user_id')
def _get_signature_checking(self):
@@ -694,14 +695,14 @@
def _gpg_signing_command(self):
"""See Config.gpg_signing_command."""
return self._get_safe_value('_gpg_signing_command')
-
+
def __init__(self, branch):
super(BranchConfig, self).__init__()
self._location_config = None
self._branch_data_config = None
self._global_config = None
self.branch = branch
- self.option_sources = (self._get_location_config,
+ self.option_sources = (self._get_location_config,
self._get_branch_data_config,
self._get_global_config)
@@ -749,7 +750,7 @@
"""Return per-user configuration directory.
By default this is ~/.bazaar/
-
+
TODO: Global option --config-dir to override this.
"""
base = os.environ.get('BZR_HOME', None)
@@ -874,7 +875,7 @@
def extract_email_address(e):
"""Return just the address part of an email string.
- That is just the user at domain part, nothing else.
+ That is just the user at domain part, nothing else.
This part is required to contain only ascii characters.
If it can't be extracted, raises an error.
=== modified file 'bzrlib/mail_client.py'
--- bzrlib/mail_client.py 2008-03-16 14:41:10 +0000
+++ bzrlib/mail_client.py 2008-03-24 22:12:01 +0000
@@ -305,6 +305,34 @@
self._encode_path(attach_path, 'attachment')])
return commandline
+class EmacsClient (ExternalMailClient):
+ """Call emacsclient in mail-mode. This only work for emacs >= 22.1"""
+ _client_commands = ['emacsclient']
+ def _get_compose_commandline (self, to, subject, attach_path):
+ commandline = ["--eval"]
+ """Ensure we can at least have an empty mail-mode buffer"""
+ _to = "nil"
+ _subject = "nil"
+
+ if to is not None:
+ _to = ("\"%s\"" % self._encode_safe(to))
+ if subject is not None:
+ _subject = ("\"%s\"" % self._encode_safe(subject))
+ mmform = "(mail nil %s %s)" %(_to ,_subject)
+
+ """call mail-mode, move the point to body and insert a new blank line"""
+ """we *must* force this point movement for the case when To is not passed"""
+ """with --mail-to. Without this, the patch could be inserted at the wrong place"""
+ commandline.append(mmform)
+ commandline.append("(mail-text)")
+ commandline.append("(newline)")
+
+ """... and insert the patch as an inline content"""
+ if attach_path is not None:
+ ifform = "(insert-file-contents \"%s\")" % self._encode_path(attach_path,'attachment')
+ commandline.append(ifform)
+ return commandline
+
class MAPIClient(ExternalMailClient):
"""Default Windows mail client launched using MAPI."""
=== modified file 'bzrlib/tests/test_mail_client.py'
--- bzrlib/tests/test_mail_client.py 2008-03-19 20:13:06 +0000
+++ bzrlib/tests/test_mail_client.py 2008-03-24 22:12:01 +0000
@@ -70,6 +70,30 @@
self.assertFalse(isinstance(item, unicode),
'Command-line item %r is unicode!' % item)
+class TestEmacsClient(tests.TestCase):
+
+ def test_commandline(self):
+ eclient = mail_client.EmacsClient(None)
+ commandline = eclient._get_compose_commandline(None, None, 'file%')
+ self.assertEqual(['--eval', '(mail nil nil nil)', \
+ '(mail-text)' , '(newline)', \
+ '(insert-file-contents "file%")'], commandline)
+
+ commandline = eclient._get_compose_commandline('jrandom at example.org',
+ 'Hi there!', None)
+ self.assertEqual(['--eval', '(mail nil "jrandom at example.org" "Hi there!")', \
+ '(mail-text)' , '(newline)'], commandline)
+
+ def test_commandline_is_8bit(self):
+ eclient = mail_client.EmacsClient(None)
+ commandline = eclient._get_compose_commandline(u'jrandom at example.org',
+ u'Hi there!', u'file%')
+ self.assertEqual(['--eval', '(mail nil "jrandom at example.org" "Hi there!")', \
+ '(mail-text)' , '(newline)', \
+ '(insert-file-contents "file%")'], commandline)
+ for item in commandline:
+ self.assertFalse(isinstance(item, unicode),
+ 'Command-line item %r is unicode!' % item)
class TestXDGEmail(tests.TestCase):
# Begin bundle
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
ZeCpDMqwR0oqT/F3JFOFCQO4eA0A
Xavier
--
http://www.gnu.org
http://www.april.org
http://www.lolica.org
More information about the bazaar
mailing list