/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to brzlib/msgeditor.py

  • Committer: Jelmer Vernooij
  • Date: 2017-05-21 12:41:27 UTC
  • mto: This revision was merged to the branch mainline in revision 6623.
  • Revision ID: jelmer@jelmer.uk-20170521124127-iv8etg0vwymyai6y
s/bzr/brz/ in apport config.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
"""Commit message editor support."""
18
18
 
 
19
from __future__ import absolute_import
 
20
 
19
21
import codecs
20
 
from io import (
21
 
    BytesIO,
22
 
    StringIO,
23
 
    )
24
22
import os
25
23
from subprocess import call
26
24
import sys
27
25
 
28
 
from . import (
29
 
    bedding,
 
26
from brzlib import (
30
27
    cmdline,
31
28
    config,
32
29
    osutils,
34
31
    transport,
35
32
    ui,
36
33
    )
37
 
from .errors import BzrError
38
 
from .hooks import Hooks
39
 
 
40
 
 
41
 
class BadCommitMessageEncoding(BzrError):
42
 
 
43
 
    _fmt = 'The specified commit message contains characters unsupported by '\
44
 
        'the current encoding.'
 
34
from brzlib.errors import BzrError, BadCommitMessageEncoding
 
35
from brzlib.hooks import Hooks
45
36
 
46
37
 
47
38
def _get_editor():
48
 
    """Return sequence of possible editor binaries for the current platform"""
 
39
    """Return a sequence of possible editor binaries for the current platform"""
49
40
    try:
50
 
        yield os.environ["BRZ_EDITOR"], '$BRZ_EDITOR'
 
41
        yield os.environ["BZR_EDITOR"], '$BZR_EDITOR'
51
42
    except KeyError:
52
43
        pass
53
44
 
54
45
    e = config.GlobalStack().get('editor')
55
46
    if e is not None:
56
 
        yield e, bedding.config_path()
 
47
        yield e, config.config_filename()
57
48
 
58
49
    for varname in 'VISUAL', 'EDITOR':
59
50
        if varname in os.environ:
72
63
    for candidate, candidate_source in _get_editor():
73
64
        edargs = cmdline.split(candidate)
74
65
        try:
 
66
            ## mutter("trying editor: %r", (edargs +[filename]))
75
67
            x = call(edargs + [filename])
76
 
        except OSError as e:
 
68
        except OSError, e:
77
69
            if candidate_source is not None:
78
70
                # We tried this editor because some user configuration (an
79
71
                # environment variable or config file) said to try it.  Let
90
82
        else:
91
83
            break
92
84
    raise BzrError("Could not start any editor.\nPlease specify one with:\n"
93
 
                   " - $BRZ_EDITOR\n - editor=/some/path in %s\n"
94
 
                   " - $VISUAL\n - $EDITOR" %
95
 
                   bedding.config_path())
 
85
                   " - $BZR_EDITOR\n - editor=/some/path in %s\n"
 
86
                   " - $VISUAL\n - $EDITOR" % \
 
87
                    config.config_filename())
96
88
 
97
89
 
98
90
DEFAULT_IGNORE_LINE = "%(bar)s %(msg)s %(bar)s" % \
99
 
    {'bar': '-' * 14, 'msg': 'This line and the following will be ignored'}
 
91
    { 'bar' : '-' * 14, 'msg' : 'This line and the following will be ignored' }
100
92
 
101
93
 
102
94
def edit_commit_message(infotext, ignoreline=DEFAULT_IGNORE_LINE,
119
111
    :return:    commit message or None.
120
112
    """
121
113
 
122
 
    if start_message is not None:
 
114
    if not start_message is None:
123
115
        start_message = start_message.encode(osutils.get_user_encoding())
124
116
    infotext = infotext.encode(osutils.get_user_encoding(), 'replace')
125
117
    return edit_commit_message_encoded(infotext, ignoreline, start_message)
149
141
    msgfilename = None
150
142
    try:
151
143
        msgfilename, hasinfo = _create_temp_file_with_commit_template(
152
 
            infotext, ignoreline, start_message)
 
144
                                    infotext, ignoreline, start_message)
153
145
        if not msgfilename:
154
146
            return None
155
147
        basename = osutils.basename(msgfilename)
156
 
        msg_transport = transport.get_transport_from_path(
157
 
            osutils.dirname(msgfilename))
 
148
        msg_transport = transport.get_transport_from_path(osutils.dirname(msgfilename))
158
149
        reference_content = msg_transport.get_bytes(basename)
159
150
        if not _run_editor(msgfilename):
160
151
            return None
162
153
        if edited_content == reference_content:
163
154
            if not ui.ui_factory.confirm_action(
164
155
                u"Commit message was not edited, use anyway",
165
 
                "breezy.msgeditor.unchanged",
166
 
                    {}):
 
156
                "brzlib.msgeditor.unchanged",
 
157
                {}):
167
158
                # Returning "" makes cmd_commit raise 'empty commit message
168
159
                # specified' which is a reasonable error, given the user has
169
160
                # rejected using the unedited template.
171
162
        started = False
172
163
        msg = []
173
164
        lastline, nlines = 0, 0
174
 
        with codecs.open(msgfilename, mode='rb', encoding=osutils.get_user_encoding()) as f:
 
165
        # codecs.open() ALWAYS opens file in binary mode but we need text mode
 
166
        # 'rU' mode useful when bzr.exe used on Cygwin (bialix 20070430)
 
167
        f = file(msgfilename, 'rU')
 
168
        try:
175
169
            try:
176
 
                for line in f:
 
170
                for line in codecs.getreader(osutils.get_user_encoding())(f):
177
171
                    stripped_line = line.strip()
178
172
                    # strip empty line before the log message starts
179
173
                    if not started:
192
186
                    msg.append(line)
193
187
            except UnicodeDecodeError:
194
188
                raise BadCommitMessageEncoding()
 
189
        finally:
 
190
            f.close()
195
191
 
196
192
        if len(msg) == 0:
197
193
            return ""
207
203
        if msgfilename is not None:
208
204
            try:
209
205
                os.unlink(msgfilename)
210
 
            except IOError as e:
 
206
            except IOError, e:
211
207
                trace.warning(
212
208
                    "failed to unlink %s: %s; ignored", msgfilename, e)
213
209
 
233
229
    import tempfile
234
230
    tmp_fileno, msgfilename = tempfile.mkstemp(prefix='bzr_log.',
235
231
                                               dir=tmpdir, text=True)
236
 
    with os.fdopen(tmp_fileno, 'wb') as msgfile:
 
232
    msgfile = os.fdopen(tmp_fileno, 'w')
 
233
    try:
237
234
        if start_message is not None:
238
 
            msgfile.write(b"%s\n" % start_message)
 
235
            msgfile.write("%s\n" % start_message)
239
236
 
240
237
        if infotext is not None and infotext != "":
241
238
            hasinfo = True
242
 
            trailer = b"\n\n%s\n\n%s" % (
243
 
                ignoreline.encode(osutils.get_user_encoding()), infotext)
244
 
            msgfile.write(trailer)
 
239
            msgfile.write("\n\n%s\n\n%s" %(ignoreline, infotext))
245
240
        else:
246
241
            hasinfo = False
 
242
    finally:
 
243
        msgfile.close()
247
244
 
248
245
    return (msgfilename, hasinfo)
249
246
 
258
255
    # TODO: Rather than running the status command, should prepare a draft of
259
256
    # the revision to be committed, then pause and ask the user to
260
257
    # confirm/write a message.
261
 
    from .status import show_tree_status
 
258
    from StringIO import StringIO       # must be unicode-safe
 
259
    from brzlib.status import show_tree_status
262
260
    status_tmp = StringIO()
263
261
    show_tree_status(working_tree, specific_files=specific_files,
264
262
                     to_file=status_tmp, verbose=True)
276
274
    # TODO: Rather than running the status command, should prepare a draft of
277
275
    # the revision to be committed, then pause and ask the user to
278
276
    # confirm/write a message.
279
 
    from .diff import show_diff_trees
 
277
    from StringIO import StringIO       # must be unicode-safe
 
278
    from brzlib.diff import show_diff_trees
280
279
 
281
280
    template = make_commit_message_template(working_tree, specific_files)
282
281
    template = template.encode(output_encoding, "replace")
283
282
 
284
283
    if diff:
285
 
        stream = BytesIO()
 
284
        stream = StringIO()
286
285
        show_diff_trees(working_tree.basis_tree(),
287
286
                        working_tree, stream, specific_files,
288
287
                        path_encoding=output_encoding)
289
 
        template = template + b'\n' + stream.getvalue()
 
288
        template = template + '\n' + stream.getvalue()
290
289
 
291
290
    return template
292
291
 
304
303
 
305
304
        These are all empty initially.
306
305
        """
307
 
        Hooks.__init__(self, "breezy.msgeditor", "hooks")
308
 
        self.add_hook(
309
 
            'set_commit_message',
 
306
        Hooks.__init__(self, "brzlib.msgeditor", "hooks")
 
307
        self.add_hook('set_commit_message',
310
308
            "Set a fixed commit message. "
311
309
            "set_commit_message is called with the "
312
 
            "breezy.commit.Commit object (so you can also change e.g. "
313
 
            "revision properties by editing commit.builder._revprops) and the "
314
 
            "message so far. set_commit_message must return the message to "
315
 
            "use or None if it should use the message editor as normal.",
316
 
            (2, 4))
317
 
        self.add_hook(
318
 
            'commit_message_template',
 
310
            "brzlib.commit.Commit object (so you can also change e.g. revision "
 
311
            "properties by editing commit.builder._revprops) and the message "
 
312
            "so far. set_commit_message must return the message to use or None"
 
313
            " if it should use the message editor as normal.", (2, 4))
 
314
        self.add_hook('commit_message_template',
319
315
            "Called when a commit message is being generated. "
320
 
            "commit_message_template is called with the breezy.commit.Commit "
 
316
            "commit_message_template is called with the brzlib.commit.Commit "
321
317
            "object and the message that is known so far. "
322
318
            "commit_message_template must return a new message to use (which "
323
319
            "could be the same as it was given). When there are multiple "