/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
1167 by Martin Pool
- split commit message editor functions out into own file
1
# Bazaar-NG -- distributed version control
2
3
# Copyright (C) 2005 by Canonical Ltd
4
5
# This program is free software; you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 2 of the License, or
8
# (at your option) any later version.
9
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
# GNU General Public License for more details.
14
15
# You should have received a copy of the GNU General Public License
16
# along with this program; if not, write to the Free Software
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
19
20
"""Commit message editor support."""
21
1185.85.2 by John Arbash Meinel
[patch] from Ivan Vilata i Balaguer: infotext should be encoded from unicode to flat strings
22
import codecs
1167 by Martin Pool
- split commit message editor functions out into own file
23
import os
1185.85.14 by John Arbash Meinel
Change exception handling for msgeditor.py to only catch specific exceptions.
24
import errno
1185.1.2 by Martin Pool
- merge various windows and other fixes from Ollie Rutherfurd
25
from subprocess import call
1442.1.3 by Robert Collins
move editor into the config file too
26
1185.85.2 by John Arbash Meinel
[patch] from Ivan Vilata i Balaguer: infotext should be encoded from unicode to flat strings
27
import bzrlib
1442.1.3 by Robert Collins
move editor into the config file too
28
import bzrlib.config as config
1167 by Martin Pool
- split commit message editor functions out into own file
29
from bzrlib.errors import BzrError
30
31
def _get_editor():
32
    """Return a sequence of possible editor binaries for the current platform"""
1185.1.30 by Robert Collins
Accept and tweak David Clymers BZREDITOR support patch
33
    try:
34
        yield os.environ["BZR_EDITOR"]
35
    except KeyError:
36
        pass
37
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
38
    e = config.GlobalConfig().get_editor()
1167 by Martin Pool
- split commit message editor functions out into own file
39
    if e is not None:
40
        yield e
41
        
1185.1.2 by Martin Pool
- merge various windows and other fixes from Ollie Rutherfurd
42
    try:
43
        yield os.environ["EDITOR"]
44
    except KeyError:
1185.1.30 by Robert Collins
Accept and tweak David Clymers BZREDITOR support patch
45
        pass
46
47
    if os.name == "nt":
48
        yield "notepad.exe"
49
    elif os.name == "posix":
50
        yield "/usr/bin/vi"
1167 by Martin Pool
- split commit message editor functions out into own file
51
52
53
def _run_editor(filename):
1168 by Martin Pool
- work properly when $EDITOR contains multiple words
54
    """Try to execute an editor to edit the commit message."""
1167 by Martin Pool
- split commit message editor functions out into own file
55
    for e in _get_editor():
1168 by Martin Pool
- work properly when $EDITOR contains multiple words
56
        edargs = e.split(' ')
1185.62.19 by John Arbash Meinel
Fix error when we can't find an editor
57
        try:
58
            x = call(edargs + [filename])
59
        except OSError, e:
60
           # ENOENT means no such editor
61
           if e.errno == errno.ENOENT:
62
               continue
63
           raise
1167 by Martin Pool
- split commit message editor functions out into own file
64
        if x == 0:
65
            return True
66
        elif x == 127:
67
            continue
68
        else:
69
            break
1168 by Martin Pool
- work properly when $EDITOR contains multiple words
70
    raise BzrError("Could not start any editor. "
71
                   "Please specify $EDITOR or use ~/.bzr.conf/editor")
1553.4.9 by Michael Ellerman
Make the "ignore line" in the commit message editor the "right" width, so
72
73
74
DEFAULT_IGNORE_LINE = "%(bar)s %(msg)s %(bar)s" % \
75
    { 'bar' : '-' * 14, 'msg' : 'This line and the following will be ignored' }
76
77
78
def edit_commit_message(infotext, ignoreline=DEFAULT_IGNORE_LINE):
1167 by Martin Pool
- split commit message editor functions out into own file
79
    """Let the user edit a commit message in a temp file.
80
81
    This is run if they don't give a message or
82
    message-containing file on the command line.
83
84
    infotext:
85
        Text to be displayed at bottom of message for
86
        the user's reference; currently similar to
87
        'bzr status'.
88
    """
89
    import tempfile
1553.4.9 by Michael Ellerman
Make the "ignore line" in the commit message editor the "right" width, so
90
1167 by Martin Pool
- split commit message editor functions out into own file
91
    try:
1185.33.66 by Martin Pool
[patch] use unicode literals for all hardcoded paths (Alexander Belchenko)
92
        tmp_fileno, msgfilename = tempfile.mkstemp(prefix='bzr_log.', dir=u'.')
1167 by Martin Pool
- split commit message editor functions out into own file
93
        msgfile = os.close(tmp_fileno)
94
        if infotext is not None and infotext != "":
95
            hasinfo = True
96
            msgfile = file(msgfilename, "w")
1185.85.2 by John Arbash Meinel
[patch] from Ivan Vilata i Balaguer: infotext should be encoded from unicode to flat strings
97
            msgfile.write("\n\n%s\n\n%s" % (ignoreline,
1185.85.9 by John Arbash Meinel
[patch] Alexander Belchenko: test spawning a msg editor
98
                infotext.encode(bzrlib.user_encoding, 'replace')))
1167 by Martin Pool
- split commit message editor functions out into own file
99
            msgfile.close()
100
        else:
101
            hasinfo = False
102
103
        if not _run_editor(msgfilename):
104
            return None
105
        
106
        started = False
107
        msg = []
108
        lastline, nlines = 0, 0
1185.85.2 by John Arbash Meinel
[patch] from Ivan Vilata i Balaguer: infotext should be encoded from unicode to flat strings
109
        for line in codecs.open(msgfilename, 'r', bzrlib.user_encoding):
1167 by Martin Pool
- split commit message editor functions out into own file
110
            stripped_line = line.strip()
111
            # strip empty line before the log message starts
112
            if not started:
113
                if stripped_line != "":
114
                    started = True
115
                else:
116
                    continue
117
            # check for the ignore line only if there
118
            # is additional information at the end
119
            if hasinfo and stripped_line == ignoreline:
120
                break
121
            nlines += 1
122
            # keep track of the last line that had some content
123
            if stripped_line != "":
124
                lastline = nlines
125
            msg.append(line)
126
            
1393.3.3 by Jelmer Vernooij
Add test for empty commit messages.
127
        if len(msg) == 0:
1393.3.2 by Jelmer Vernooij
Fix error message when an empty commit message was specified (when using an editor). Previously bzr warned that it wanted either --message or --file.
128
            return ""
1167 by Martin Pool
- split commit message editor functions out into own file
129
        # delete empty lines at the end
130
        del msg[lastline:]
131
        # add a newline at the end, if needed
132
        if not msg[-1].endswith("\n"):
133
            return "%s%s" % ("".join(msg), "\n")
134
        else:
135
            return "".join(msg)
136
    finally:
137
        # delete the msg file in any case
138
        try: os.unlink(msgfilename)
1185.85.14 by John Arbash Meinel
Change exception handling for msgeditor.py to only catch specific exceptions.
139
        except (IOError, OSError), e:
140
            if (not hasattr(e, 'errno')
1185.85.45 by John Arbash Meinel
[patch] Alexander Belchenko: win32 'Permission denied' is errno.EACCES
141
                or e.errno not in (errno.ENOENT, errno.ENOTDIR,
142
                                   errno.EPERM, errno.EACCES)):
1185.85.14 by John Arbash Meinel
Change exception handling for msgeditor.py to only catch specific exceptions.
143
                raise
1167 by Martin Pool
- split commit message editor functions out into own file
144
1185.33.72 by Martin Pool
Fix commit message template for non-ascii files, and add test for handling of
145
146
def make_commit_message_template(working_tree, specific_files):
147
    """Prepare a template file for a commit into a branch.
148
149
    Returns a unicode string containing the template.
150
    """
151
    # TODO: Should probably be given the WorkingTree not the branch
152
    #
153
    # TODO: make provision for this to be overridden or modified by a hook
154
    #
155
    # TODO: Rather than running the status command, should prepare a draft of
156
    # the revision to be committed, then pause and ask the user to
157
    # confirm/write a message.
158
    from StringIO import StringIO       # must be unicode-safe
1551.2.9 by Aaron Bentley
Fix status to work with checkouts
159
    from bzrlib.status import show_tree_status
1185.33.72 by Martin Pool
Fix commit message template for non-ascii files, and add test for handling of
160
    status_tmp = StringIO()
1551.2.9 by Aaron Bentley
Fix status to work with checkouts
161
    show_tree_status(working_tree, specific_files=specific_files, 
162
                     to_file=status_tmp)
1185.33.72 by Martin Pool
Fix commit message template for non-ascii files, and add test for handling of
163
    return status_tmp.getvalue()