39
by John Arbash Meinel
Update copyright and version information. |
1 |
# Copyright (C) 2005, 2006, 2007 by Canonical Ltd
|
24
by John Arbash Meinel
Add GPL copyright |
2 |
#
|
3 |
# This program is free software; you can redistribute it and/or modify
|
|
4 |
# it under the terms of the GNU General Public License as published by
|
|
5 |
# the Free Software Foundation; either version 2 of the License, or
|
|
6 |
# (at your option) any later version.
|
|
7 |
#
|
|
8 |
# This program is distributed in the hope that it will be useful,
|
|
9 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11 |
# GNU General Public License for more details.
|
|
12 |
#
|
|
13 |
# You should have received a copy of the GNU General Public License
|
|
14 |
# along with this program; if not, write to the Free Software
|
|
15 |
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
2
by John Arbash Meinel
Adding basic work for a test suite. |
16 |
"""Submit an email to a Patch Queue Manager"""
|
17 |
||
18.2.1
by Aaron Bentley
Better diagnostics when out-of-sync |
18 |
from bzrlib import ( |
37.1.3
by James Henstridge
Try and share more configuration from merge directive code: |
19 |
config as _mod_config, |
18.2.1
by Aaron Bentley
Better diagnostics when out-of-sync |
20 |
errors, |
37.1.3
by James Henstridge
Try and share more configuration from merge directive code: |
21 |
gpg, |
22 |
osutils, |
|
23 |
urlutils, |
|
18.2.1
by Aaron Bentley
Better diagnostics when out-of-sync |
24 |
)
|
11
by John Arbash Meinel
[patch] Aaron Bentley: Check the public branch has the expected revision. |
25 |
from bzrlib.branch import Branch |
37.1.2
by James Henstridge
Kill the custom smtplib code, and use bzr's email+smtp infrastructure. |
26 |
from bzrlib.email_message import EmailMessage |
27 |
from bzrlib.smtp_connection import SMTPConnection |
|
37.1.3
by James Henstridge
Try and share more configuration from merge directive code: |
28 |
from bzrlib.trace import note, warning |
2
by John Arbash Meinel
Adding basic work for a test suite. |
29 |
|
30 |
||
34
by Robert Collins
Fix the test_suite method to actually return the correct tests and add a test for commit messages with newlines, fixing bug #110137. (Robert Collins) |
31 |
class BadCommitMessage(errors.BzrError): |
39
by John Arbash Meinel
Update copyright and version information. |
32 |
|
34
by Robert Collins
Fix the test_suite method to actually return the correct tests and add a test for commit messages with newlines, fixing bug #110137. (Robert Collins) |
33 |
_fmt = "The commit message %(msg)r cannot be used by pqm." |
34 |
||
35 |
def __init__(self, message): |
|
36 |
errors.BzrError.__init__(self) |
|
37 |
self.msg = message |
|
38 |
||
39 |
||
37.1.4
by James Henstridge
* Move the PQM submission logic into a PQMSubmission object. |
40 |
class PQMSubmission(object): |
41 |
"""A request to perform a PQM merge into a branch."""
|
|
42 |
||
37.1.5
by James Henstridge
Simplify PQMSubmission object, fixing up locations in the constructor. |
43 |
def __init__(self, source_branch, public_location=None, |
44 |
submit_location=None, message=None): |
|
37.1.4
by James Henstridge
* Move the PQM submission logic into a PQMSubmission object. |
45 |
"""Create a PQMSubmission object.
|
46 |
||
47 |
:param source_branch: the source branch for the merge
|
|
37.1.5
by James Henstridge
Simplify PQMSubmission object, fixing up locations in the constructor. |
48 |
:param public_location: the public location of the source branch
|
49 |
:param submit_location: the location of the target branch
|
|
37.1.4
by James Henstridge
* Move the PQM submission logic into a PQMSubmission object. |
50 |
:param message: The message to use when committing this merge
|
37.1.5
by James Henstridge
Simplify PQMSubmission object, fixing up locations in the constructor. |
51 |
|
52 |
If any of public_location, submit_location or message are
|
|
53 |
omitted, they will be calculated from source_branch.
|
|
37.1.4
by James Henstridge
* Move the PQM submission logic into a PQMSubmission object. |
54 |
"""
|
37.1.5
by James Henstridge
Simplify PQMSubmission object, fixing up locations in the constructor. |
55 |
if source_branch is None: |
56 |
raise errors.NoMergeSource() |
|
37.1.4
by James Henstridge
* Move the PQM submission logic into a PQMSubmission object. |
57 |
self.source_branch = source_branch |
37.1.5
by James Henstridge
Simplify PQMSubmission object, fixing up locations in the constructor. |
58 |
|
59 |
if public_location is None: |
|
60 |
public_location = self.source_branch.get_public_branch() |
|
61 |
# Fall back to the old public_repository hack.
|
|
62 |
if public_location is None: |
|
63 |
src_loc = source_branch.bzrdir.root_transport.local_abspath('.') |
|
64 |
repository = source_branch.repository |
|
65 |
repo_loc = repository.bzrdir.root_transport.local_abspath('.') |
|
66 |
repo_config = _mod_config.LocationConfig(repo_loc) |
|
67 |
public_repo = repo_config.get_user_option("public_repository") |
|
68 |
if public_repo is not None: |
|
69 |
warning("Please use public_branch, not public_repository, " |
|
70 |
"to set the public location of branches.") |
|
71 |
branch_relpath = osutils.relpath(repo_loc, src_loc) |
|
72 |
public_location = urlutils.join(public_repo, branch_relpath) |
|
73 |
||
74 |
if public_location is None: |
|
75 |
raise errors.BzrCommandError( |
|
76 |
'No public branch location given. Please specify with '
|
|
77 |
'--public-location or see "bzr help pqm-submit" to see how '
|
|
78 |
'to set it in ~/.bazaar/locations.conf') |
|
79 |
self.public_location = public_location |
|
80 |
||
81 |
if submit_location is None: |
|
82 |
config = self.source_branch.get_config() |
|
83 |
# First check the deprecated pqm_branch config key:
|
|
84 |
submit_location = config.get_user_option('pqm_branch') |
|
85 |
if submit_location is not None: |
|
86 |
warning("Please use submit_branch, not pqm_branch to set " |
|
87 |
"the PQM merge target branch.") |
|
88 |
else: |
|
89 |
# Otherwise, use the standard config key:
|
|
90 |
submit_location = self.source_branch.get_submit_branch() |
|
91 |
||
92 |
if submit_location is None: |
|
93 |
raise errors.NoSubmitBranch(self.source_branch) |
|
94 |
self.submit_location = submit_location |
|
37.1.4
by James Henstridge
* Move the PQM submission logic into a PQMSubmission object. |
95 |
|
96 |
# Check that the message is okay to pass to PQM
|
|
97 |
if message is None: |
|
98 |
repository = self.source_branch.repository |
|
99 |
rev = repository.get_revision(self.source_branch.last_revision()) |
|
100 |
message = rev.message |
|
101 |
self.message = message.encode('utf8') |
|
102 |
if '\n' in self.message: |
|
103 |
raise BadCommitMessage(self.message) |
|
104 |
||
105 |
def check_public_branch(self): |
|
106 |
"""Check that the public branch is up to date with the local copy."""
|
|
107 |
note('Checking that the public branch is up to date ...') |
|
108 |
local_revision = self.source_branch.last_revision() |
|
37.1.5
by James Henstridge
Simplify PQMSubmission object, fixing up locations in the constructor. |
109 |
public_revision = Branch.open(self.public_location).last_revision() |
37.1.4
by James Henstridge
* Move the PQM submission logic into a PQMSubmission object. |
110 |
if local_revision != public_revision: |
111 |
raise errors.PublicBranchOutOfDate( |
|
37.1.5
by James Henstridge
Simplify PQMSubmission object, fixing up locations in the constructor. |
112 |
self.public_location, local_revision) |
37.1.4
by James Henstridge
* Move the PQM submission logic into a PQMSubmission object. |
113 |
|
114 |
def to_lines(self): |
|
115 |
"""Serialise as a list of lines."""
|
|
37.1.5
by James Henstridge
Simplify PQMSubmission object, fixing up locations in the constructor. |
116 |
return ['star-merge %s %s\n' % (self.public_location, self.submit_location)] |
37.1.4
by James Henstridge
* Move the PQM submission logic into a PQMSubmission object. |
117 |
|
118 |
def to_signed(self): |
|
119 |
"""Serialize as a signed string."""
|
|
120 |
unsigned_text = ''.join(self.to_lines()) |
|
121 |
unsigned_text = unsigned_text.encode('ascii') #URLs should be ascii |
|
122 |
||
123 |
strategy = gpg.GPGStrategy(self.source_branch.get_config()) |
|
124 |
return strategy.sign(unsigned_text) |
|
125 |
||
126 |
def to_email(self, mail_from, mail_to, sign=True): |
|
127 |
"""Serialize as an email message.
|
|
128 |
||
129 |
:param mail_from: The from address for the message
|
|
130 |
:param mail_to: The address to send the message to
|
|
131 |
:param sign: If True, gpg-sign the email
|
|
132 |
:return: an email message
|
|
133 |
"""
|
|
134 |
if sign: |
|
135 |
body = self.to_signed() |
|
136 |
else: |
|
137 |
body = ''.join(self.to_lines()) |
|
138 |
message = EmailMessage(mail_from, mail_to, self.message, body) |
|
139 |
return message |
|
37.1.3
by James Henstridge
Try and share more configuration from merge directive code: |
140 |
|
141 |
||
13
by John Arbash Meinel
Adding a --public-location which lets you force the public location for the pqm. |
142 |
def submit(branch, message, dry_run=False, public_location=None): |
2
by John Arbash Meinel
Adding basic work for a test suite. |
143 |
"""Submit the given branch to the pqm."""
|
19
by John Arbash Meinel
[null-merge] ignore 0.8 compatibility updates |
144 |
config = branch.get_config() |
2
by John Arbash Meinel
Adding basic work for a test suite. |
145 |
|
37.1.4
by James Henstridge
* Move the PQM submission logic into a PQMSubmission object. |
146 |
submission = PQMSubmission( |
37.1.5
by James Henstridge
Simplify PQMSubmission object, fixing up locations in the constructor. |
147 |
source_branch=branch, public_location=public_location, message=message) |
3
by John Arbash Meinel
Everything is hooked up. |
148 |
|
37.1.4
by James Henstridge
* Move the PQM submission logic into a PQMSubmission object. |
149 |
mail_from = config.get_user_option('pqm_user_email') |
150 |
if not mail_from: |
|
151 |
mail_from = config.username() |
|
152 |
mail_from = mail_from.encode('utf8') # Make sure this isn't unicode |
|
153 |
mail_to = config.get_user_option('pqm_email') |
|
154 |
if not mail_to: |
|
32
by John Arbash Meinel
Use 'errors.BzrCommandError' |
155 |
raise errors.BzrCommandError('No PQM submission address specified ' |
156 |
'in configuration') |
|
37.1.4
by James Henstridge
* Move the PQM submission logic into a PQMSubmission object. |
157 |
mail_to = mail_to.encode('utf8') # same here |
158 |
||
159 |
submission.check_public_branch() |
|
160 |
||
161 |
message = submission.to_email(mail_from, mail_to) |
|
3
by John Arbash Meinel
Everything is hooked up. |
162 |
|
10
by John Arbash Meinel
[patch] Aaron Bentley: add --dry-run |
163 |
if dry_run: |
37.1.4
by James Henstridge
* Move the PQM submission logic into a PQMSubmission object. |
164 |
print message.as_string() |
37.1.2
by James Henstridge
Kill the custom smtplib code, and use bzr's email+smtp infrastructure. |
165 |
return
|
166 |
||
37.1.4
by James Henstridge
* Move the PQM submission logic into a PQMSubmission object. |
167 |
SMTPConnection(config).send_email(message) |