1 # Copyright (C) 2005-2010 Aaron Bentley and Panometrics, Inc.
2 # Chris Ball <cjb@laptop.org>
3 # Gianluca Montecchi <gian@grys.it>
4 # Marien Zwart <marienz@gentoo.org>
5 # Thomas Gerigk <tgerigk@gmx.de>
6 # W. Trevor King <wking@drexel.edu>
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License along
19 # with this program; if not, write to the Free Software Foundation, Inc.,
20 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 import libbe.command.util
25 import libbe.command.depend
28 class Target (libbe.command.Command):
29 """Assorted bug target manipulations and queries
31 >>> import os, StringIO, sys
32 >>> import libbe.bugdir
33 >>> bd = libbe.bugdir.SimpleBugDir(memory=False)
34 >>> io = libbe.command.StringInputOutput()
35 >>> io.stdout = sys.stdout
36 >>> ui = libbe.command.UserInterface(io=io)
37 >>> ui.storage_callbacks.set_storage(bd.storage)
38 >>> cmd = Target(ui=ui)
40 >>> ret = ui.run(cmd, args=['/a'])
42 >>> ret = ui.run(cmd, args=['/a', 'tomorrow'])
43 >>> ret = ui.run(cmd, args=['/a'])
46 >>> ui.io.stdout = StringIO.StringIO()
47 >>> ret = ui.run(cmd, {'resolve':True}, ['tomorrow'])
48 >>> output = ui.io.get_stdout().strip()
49 >>> target = bd.bug_from_uuid(output)
50 >>> print target.summary
52 >>> print target.severity
55 >>> ui.io.stdout = sys.stdout
56 >>> ret = ui.run(cmd, args=['/a', 'none'])
57 >>> ret = ui.run(cmd, args=['/a'])
64 def __init__(self, *args, **kwargs):
65 libbe.command.Command.__init__(self, *args, **kwargs)
67 libbe.command.Option(name='resolve', short_name='r',
68 help="Print the UUID for the target bug whose summary "
69 "matches TARGET. If TARGET is not given, print the UUID "
70 "of the current bugdir target."),
73 libbe.command.Argument(
74 name='id', metavar='BUG-ID', optional=True,
75 completion_callback=libbe.command.util.complete_bug_id),
76 libbe.command.Argument(
77 name='target', metavar='TARGET', optional=True,
78 completion_callback=complete_target),
81 def _run(self, **params):
82 if params['resolve'] == False:
83 if params['id'] == None:
84 raise libbe.command.UserError('Please specify a bug id.')
86 if params['target'] != None:
87 raise libbe.command.UserError('Too many arguments')
88 params['target'] = params.pop('id')
89 bugdir = self._get_bugdir()
90 if params['resolve'] == True:
91 bug = bug_from_target_summary(bugdir, params['target'])
93 print >> self.stdout, 'No target assigned.'
95 print >> self.stdout, bug.uuid
97 bug,dummy_comment = libbe.command.util.bug_comment_from_user_id(
99 if params['target'] == None:
100 target = bug_target(bugdir, bug)
102 print >> self.stdout, 'No target assigned.'
104 print >> self.stdout, target.summary
106 if params['target'] == 'none':
107 target = remove_target(bugdir, bug)
109 target = add_target(bugdir, bug, params['target'])
113 return 'usage: be %(name)s BUG-ID [TARGET]\nor: be %(name)s --resolve [TARGET]' \
116 def _long_help(self):
118 Assorted bug target manipulations and queries.
120 If no target is specified, the bug's current target is printed. If
121 TARGET is specified, it will be assigned to the bug, creating a new
122 target bug if necessary.
124 Targets are free-form; any text may be specified. They will generally
125 be milestone names or release numbers. The value "none" can be used
128 In the alternative `be target --resolve TARGET` form, print the UUID
129 of the target-bug with summary TARGET. If target is not given, return
130 use the bugdir's current target (see `be set`).
132 If you want to list all bugs blocking the current target, try
133 $ be depend --status -closed,fixed,wontfix --severity -target \
134 $(be target --resolve)
136 If you want to set the current bugdir target by summary (rather than
138 $ be set target $(be target --resolve SUMMARY)
141 def bug_from_target_summary(bugdir, summary=None):
143 if bugdir.target == None:
146 return bugdir.bug_from_uuid(bugdir.target)
148 for uuid in bugdir.uuids():
149 bug = bugdir.bug_from_uuid(uuid)
150 if bug.severity == 'target' and bug.summary == summary:
152 if len(matched) == 0:
155 raise Exception('Several targets with same summary: %s'
156 % '\n '.join([bug.uuid for bug in matched]))
159 def bug_target(bugdir, bug):
160 if bug.severity == 'target':
163 for blocked in libbe.command.depend.get_blocks(bugdir, bug):
164 if blocked.severity == 'target':
165 matched.append(blocked)
166 if len(matched) == 0:
169 raise Exception('This bug (%s) blocks several targets: %s'
171 '\n '.join([b.uuid for b in matched])))
174 def remove_target(bugdir, bug):
175 target = bug_target(bugdir, bug)
176 libbe.command.depend.remove_block(target, bug)
179 def add_target(bugdir, bug, summary):
180 target = bug_from_target_summary(bugdir, summary)
182 target = bugdir.new_bug(summary=summary)
183 target.severity = 'target'
184 libbe.command.depend.add_block(target, bug)
188 bugdir.load_all_bugs()
190 if bug.severity == 'target':
193 def complete_target(command, argument, fragment=None):
195 List possible command completions for fragment.
197 argument argument is not used.
199 return targets(command._get_bugdir())