Updated copyright information
[be.git] / libbe / command / comment.py
1 # Copyright (C) 2005-2010 Aaron Bentley and Panometrics, Inc.
2 #                         Gianluca Montecchi <gian@grys.it>
3 #                         W. Trevor King <wking@drexel.edu>
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 along
16 # with this program; if not, write to the Free Software Foundation, Inc.,
17 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
19 import os
20 import sys
21
22 import libbe
23 import libbe.command
24 import libbe.command.util
25 import libbe.comment
26 import libbe.ui.util.editor
27 import libbe.util.id
28
29
30 class Comment (libbe.command.Command):
31     """Add a comment to a bug
32
33     >>> import time
34     >>> import libbe.bugdir
35     >>> bd = libbe.bugdir.SimpleBugDir(memory=False)
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 = Comment(ui=ui)
41
42     >>> ui._user_id = u'Fran\\xe7ois'
43     >>> ret = ui.run(cmd, args=['/a', 'This is a comment about a'])
44     >>> bd.flush_reload()
45     >>> bug = bd.bug_from_uuid('a')
46     >>> bug.load_comments(load_full=False)
47     >>> comment = bug.comment_root[0]
48     >>> comment.id.storage() == comment.uuid
49     True
50     >>> print comment.body
51     This is a comment about a
52     <BLANKLINE>
53     >>> comment.author
54     u'Fran\\xe7ois'
55     >>> comment.time <= int(time.time())
56     True
57     >>> comment.in_reply_to is None
58     True
59
60     >>> if 'EDITOR' in os.environ:
61     ...     del os.environ['EDITOR']
62     >>> ui._user_id = u'Frank'
63     >>> ret = ui.run(cmd, args=['/b'])
64     Traceback (most recent call last):
65     UserError: No comment supplied, and EDITOR not specified.
66
67     >>> os.environ['EDITOR'] = "echo 'I like cheese' > "
68     >>> ret = ui.run(cmd, args=['/b'])
69     >>> bd.flush_reload()
70     >>> bug = bd.bug_from_uuid('b')
71     >>> bug.load_comments(load_full=False)
72     >>> comment = bug.comment_root[0]
73     >>> print comment.body
74     I like cheese
75     <BLANKLINE>
76     >>> ui.cleanup()
77     >>> bd.cleanup()
78     """
79     name = 'comment'
80
81     def __init__(self, *args, **kwargs):
82         libbe.command.Command.__init__(self, *args, **kwargs)
83         self.options.extend([
84                 libbe.command.Option(name='author', short_name='a',
85                     help='Set the comment author',
86                     arg=libbe.command.Argument(
87                         name='author', metavar='AUTHOR')),
88                 libbe.command.Option(name='alt-id',
89                     help='Set an alternate comment ID',
90                     arg=libbe.command.Argument(
91                         name='alt-id', metavar='ID')),
92                 libbe.command.Option(name='content-type', short_name='c',
93                     help='Set comment content-type (e.g. text/plain)',
94                     arg=libbe.command.Argument(name='content-type',
95                         metavar='MIME')),
96                 ])
97         self.args.extend([
98                 libbe.command.Argument(
99                     name='id', metavar='ID', default=None,
100                     completion_callback=libbe.command.util.complete_bug_comment_id),
101                 libbe.command.Argument(
102                     name='comment', metavar='COMMENT', default=None,
103                     optional=True,
104                     completion_callback=libbe.command.util.complete_assigned),
105                 ])
106
107     def _run(self, **params):
108         bugdir = self._get_bugdir()
109         bug,parent = \
110             libbe.command.util.bug_comment_from_user_id(bugdir, params['id'])
111         if params['comment'] == None:
112             # try to launch an editor for comment-body entry
113             try:
114                 if parent == bug.comment_root:
115                     parent_body = bug.summary+'\n'
116                 else:
117                     parent_body = parent.body
118                 estr = 'Please enter your comment above\n\n> %s\n' \
119                     % ('\n> '.join(parent_body.splitlines()))
120                 body = libbe.ui.util.editor.editor_string(estr)
121             except libbe.ui.util.editor.CantFindEditor, e:
122                 raise libbe.command.UserError(
123                     'No comment supplied, and EDITOR not specified.')
124             if body is None:
125                 raise libbe.command.UserError('No comment entered.')
126         elif params['comment'] == '-': # read body from stdin
127             binary = not (params['content-type'] == None
128                           or params['content-type'].startswith("text/"))
129             if not binary:
130                 body = self.stdin.read()
131                 if not body.endswith('\n'):
132                     body += '\n'
133             else: # read-in without decoding
134                 body = sys.stdin.read()
135         else: # body given on command line
136             body = params['comment']
137             if not body.endswith('\n'):
138                 body+='\n'
139         if params['author'] == None:
140             params['author'] = self._get_user_id()
141
142         new = parent.new_reply(body=body)
143         for key in ['alt-id', 'author', 'content-type']:
144             if params[key] != None:
145                 setattr(new, key, params[key])
146         return 0
147
148     def _long_help(self):
149         return """
150 To add a comment to a bug, use the bug ID as the argument.  To reply
151 to another comment, specify the comment name (as shown in "be show"
152 output).  COMMENT, if specified, should be either the text of your
153 comment or "-", in which case the text will be read from stdin.  If
154 you do not specify a COMMENT, $EDITOR is used to launch an editor.  If
155 COMMENT is unspecified and EDITOR is not set, no comment will be
156 created.
157 """