ui:util:pager: cleanup pager implementation
[be.git] / libbe / command / commit.py
1 # Copyright (C) 2009-2012 Chris Ball <cjb@laptop.org>
2 #                         Gianluca Montecchi <gian@grys.it>
3 #                         W. Trevor King <wking@tremily.us>
4 #
5 # This file is part of Bugs Everywhere.
6 #
7 # Bugs Everywhere is free software: you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by the Free
9 # Software Foundation, either version 2 of the License, or (at your option) any
10 # later version.
11 #
12 # Bugs Everywhere is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15 # more details.
16 #
17 # You should have received a copy of the GNU General Public License along with
18 # Bugs Everywhere.  If not, see <http://www.gnu.org/licenses/>.
19
20 import sys
21
22 import libbe
23 import libbe.bugdir
24 import libbe.command
25 import libbe.command.util
26 import libbe.storage
27 import libbe.ui.util.editor
28
29
30 class Commit (libbe.command.Command):
31     """Commit the currently pending changes to the repository
32
33     >>> import sys
34     >>> import libbe.bugdir
35     >>> bd = libbe.bugdir.SimpleBugDir(memory=False, versioned=True)
36     >>> io = libbe.command.StringInputOutput()
37     >>> io.stdout = sys.stdout
38     >>> ui = libbe.command.UserInterface(io=io)
39     >>> ui.storage_callbacks.set_storage(bd.storage)
40     >>> cmd = Commit(ui=ui)
41
42     >>> bd.extra_strings = ['hi there']
43     >>> bd.flush_reload()
44     >>> ui.run(cmd, args=['Making a commit']) # doctest: +ELLIPSIS
45     Committed ...
46     >>> ui.cleanup()
47     >>> bd.cleanup()
48     """
49     name = 'commit'
50
51     def __init__(self, *args, **kwargs):
52         libbe.command.Command.__init__(self, *args, **kwargs)
53         self.options.extend([
54                 libbe.command.Option(name='body', short_name='b',
55                     help='Provide the detailed body for the commit message.  In the special case that FILE == "EDITOR", spawn an editor to enter the body text (in which case you cannot use stdin for the summary)',
56                     arg=libbe.command.Argument(name='body', metavar='FILE',
57                         completion_callback=libbe.command.util.complete_path)),
58                 libbe.command.Option(name='allow-empty', short_name='a',
59                                      help='Allow empty commits'),
60                  ])
61         self.args.extend([
62                 libbe.command.Argument(
63                     name='summary', metavar='SUMMARY', default=None,
64                     optional=True),
65                 ])
66
67     def _run(self, **params):
68         if params['summary'] == '-': # read summary from stdin
69             assert params['body'] != 'EDITOR', \
70                 'Cannot spawn and editor when the summary is using stdin.'
71             summary = sys.stdin.readline()
72         else:
73             summary = params['summary']
74             if summary == None and params['body'] == None:
75                 params['body'] = 'EDITOR'
76         storage = self._get_storage()
77         if params['body'] == None:
78             body = None
79         elif params['body'] == 'EDITOR':
80             body = libbe.ui.util.editor.editor_string(
81                 'Please enter your commit message above')
82         else:
83             self._check_restricted_access(storage, params['body'])
84             body = libbe.util.encoding.get_file_contents(
85                 params['body'], decode=True)
86         if summary == None:  # use the first body line as the summary
87             if body == None:
88                 raise libbe.command.UserError(
89                     'cannot commit without a summary')
90             lines = body.splitlines()
91             summary = lines[0]
92             body = '\n'.join(lines[1:]).strip() + '\n'
93         try:
94             revision = storage.commit(summary, body=body,
95                                       allow_empty=params['allow-empty'])
96             print >> self.stdout, 'Committed %s' % revision
97         except libbe.storage.EmptyCommit, e:
98             print >> self.stdout, e
99             return 1
100
101     def _long_help(self):
102         return """
103 Commit the current repository status.
104
105 The summary specified on the commandline is a string (only one line)
106 that describes the commit briefly or "-", in which case the string
107 will be read from stdin.  If no summary is given, the first line from
108 the body message is used instead.  If no summary or body is given, we
109 spawn an editor without needing the special "EDITOR" value for the
110 "--body" option.
111 """