2 # A contrib plugin for osc
4 # This tool makes maintenance of openSUSE:Factory:Contrib more easier than an
5 # universal osc commands.
7 # Copyright: (c) 2009 Michal Vyskocil <mvyskocil@suse.cz>
12 @cmdln.option('-m', '--message', metavar
='MESSAGE',
13 help='the request message (optional)')
14 @cmdln.option('-i', '--id', metavar
='REQUEST_ID',
15 help='The concrete request id. Usefull whe multiple requests exists.')
16 @cmdln.option('-l', '--last-request', action
='store_true', default
=False,
17 help='Use a last request (default False)')
18 @cmdln.option('-s', '--state', metavar
='STATE',
19 help='Show a requests with a specified state.')
20 @cmdln.option('-f', '--full-view', action
='store_true', default
=False,
21 help='Make a full view for show command (default False)')
23 def do_contrib(self
, subcmd
, opts
, *args
):
24 """${cmd_name}: Handling a requests for Contrib
26 osc subcommand for maintenance of openSUSE Contrib repository. This command
27 tries to make the maintenance process easier than common osc commands. These
28 commands are derived from existing ones, but have a different arguments.
30 osc contrib show [PACKAGE]
31 Show all new requests towards Contrib. The optional argument package will
32 filter only a requests to it.
35 -s, --state filter the state (type 'any' for all)
36 -f, --full-view a full view of requests
38 osc contrib new [DEST_PACKAGE]
39 osc contrib new PROJECT PACKAGE [DEST_PACKAGE]
40 A request for adding a new package to Contrib. When requesting from package dir
41 all necessary informations are readed from osc metadata. Only a DEST_PACKAGE
42 should be givven, if you want to have another name of your package in Contrib.
44 If you are in common dir, then you have to specify the PROJECT and PACKAGE
45 manually and DEST_PACKAGE is also optional.
47 osc contrib checkout PACKAGE
48 Checkout the requested package to the current dir.
51 -i, --id id of request (if multiple exists)
52 -l, --last use a last request (if multiple exists)
55 osc contrib [accept|decline|revoke] PACKAGE
56 Change the state of package to <state>
59 -i, --id id of request (if multiple exists)
60 -l, --last use a last request (if multiple exists)
61 -m, --message the submit message (optional for accept)
65 cmds
= [cmd
[12:] for cmd
in dir(self
) if cmd
[0:12] == '_do_contrib_' and type(getattr(self
, cmd
)) == types
.MethodType
]
66 if not args
or args
[0] not in cmds
:
67 raise oscerr
.WrongArgs("Unknown contrib action. Choose one of %s." \
72 self
.project
= 'openSUSE:Factory:Contrib'
73 #self.project = 'home:mvyskocil'
74 self
.apiurl
= conf
.config
['apiurl']
77 getattr(self
, "_do_contrib_%s" % (command
))(opts
, args
[1:])
79 def _sr_from_package(self
, package
, reqid
=None, use_last
=False, req_state
=''):
80 requests
= get_submit_request_list(self
.apiurl
, self
.project
, package
, req_state
=req_state
)
81 if len(requests
) == 0:
82 raise oscerr
.WrongArgs("No request for package %s found" % (package
))
83 elif len(requests
) > 1:
85 requests
= requests
[-1:]
87 raise oscerr
.WrongArgs(
88 "There are multiple requests (%s) towards package %s. Specify one by -i/--id, or use -l/--last-request argument!" %
89 (", ".join([str(r
.reqid
) for r
in requests
]), package
))
91 ret
= [req
for req
in requests
if req
.reqid
== int(reqid
)]
93 raise oscerr
.WrongArgs("The package %s and request id %s doesn't match! \
94 Use one of these (%s)" % (package
, reqid
, ", ".join([str(r
.reqid
) for r
in requests
])))
99 def _do_contrib_show(self
, opts
, args
):
105 state
= opts
.state
or 'new'
109 srs
= get_submit_request_list(self
.apiurl
, self
.project
, package
, req_state
=state
)
115 print(sr
.list_view())
117 def _do_contrib_new(self
, opts
, args
):
118 if is_package_dir(os
.getcwdu()):
119 src_project
= store_read_project(os
.getcwdu())
120 src_package
= store_read_package(os
.getcwdu())
121 dest_package
= src_package
123 dest_package
= args
[0]
126 raise oscerr
.WrongArgs("The source project and package names are mandatory!!")
127 src_project
, src_package
= args
[0], args
[1]
128 if not src_package
in meta_get_packagelist(self
.apiurl
, src_project
):
129 raise oscerr
.WrongArgs("Package '%s' don't exists in project '%s'" % (src_package
, src_project
))
130 dest_package
= src_package
132 dest_package
= args
[2]
134 message
= opts
.message
or "please add a '%s' to Contrib" % (dest_package
)
135 id = create_submit_request(self
.apiurl
, src_project
, src_package
, self
.project
, dest_package
, message
)
136 print("Request id %s created" % (id))
138 def _do_contrib_accept(self
, opts
, args
):
140 return self
._contrib
_sr
_change
(opts
, args
, "accepted",
141 "Reviewed and checked OK.")
143 def _do_contrib_decline(self
, opts
, args
):
146 raise oscerr
.WrongArgs('A message is mandatory for decline')
148 return self
._contrib
_sr
_change
(opts
, args
, "declined",
151 def _do_contrib_revoke(self
, opts
, args
):
154 raise oscerr
.WrongArgs('A message is mandatory for decline')
156 return self
._contrib
_sr
_change
(opts
, args
, "revoked",
160 def _do_contrib_co(self
, opts
, args
):
161 return self
._do
_contrib
_checkout
(opts
, args
)
163 def _do_contrib_checkout(self
, opts
, args
):
166 raise oscerr
.WrongArgs("The package names are mandatory!!")
168 request
= self
._sr
_from
_package
(package
, opts
.id, opts
.last_request
)
170 checkout_package(self
.apiurl
,
171 request
.src_project
, package
,
174 # the original API is *very* ugly!!
175 # return the meta in an xml form first
176 def _get_meta_xml(self
, package
):
177 path
= quote_plus(self
.project
),
180 path
= path
+ (quote_plus(package
),)
182 data
= meta_exists(metatype
=kind
,
187 return ET
.fromstring(''.join(data
))
188 raise oscerr
.PackageError('Meta data for package %s missing' % (package
))
190 # return all persons from meta
191 def _get_persons_from_meta(self
, meta
):
192 return meta
.getiterator('person')
194 def _get_roles_from_meta(self
, meta
, role
):
195 assert(role
in ['maintainer', 'bugowner'])
196 return [p
for p
in self
._get
_persons
_from
_meta
(meta
) if p
.get('role') == role
]
198 def _has_user_role(self
, meta
, role
, user
):
199 assert(role
in ['maintainer', 'bugowner'])
200 if not get_user_meta(self
.apiurl
, user
):
201 raise oscerr
.WrongArgs("The user %s doesn't exists" % (user
))
203 return user
in [p
.get('userid') for p
in self
._get
_roles
_from
_meta
(meta
, role
)]
205 # from osc.core, FIXME, this is broken
206 # look at the svn, or send a patch to obs
207 def _addBugowner(self
, apiurl
, prj
, pac
, user
):
208 """ add a new bugowner to a package or project """
209 path
= quote_plus(prj
),
212 path
= path
+ (quote_plus(pac
),)
214 data
= meta_exists(metatype
=kind
,
219 if data
and get_user_meta(apiurl
, user
) != None:
220 tree
= ET
.fromstring(''.join(data
))
222 for person
in tree
.getiterator('person'):
223 if person
.get('userid') == user
and person
.get('role') == 'bugowner':
225 print "user already exists"
228 # the xml has a fixed structure
229 tree
.insert(2, ET
.Element('person', role
='bugowner', userid
=user
))
230 print 'user \'%s\' added to \'%s\'' % (user
, pac
or prj
)
231 edit_meta(metatype
=kind
,
233 data
=ET
.tostring(tree
))
235 print "osc: an error occured"
237 def _contrib_sr_change(self
, opts
, args
, action
, message
):
240 raise oscerr
.WrongArgs('The package name is mandatory for %s' % (action
))
243 request
= self
._sr
_from
_package
(package
, opts
.id, opts
.last_request
)
245 id = str(request
.reqid
)
247 # check the current state
248 sr
= get_submit_request(self
.apiurl
, id)
250 if sr
.state
.name
!= 'new':
251 print "The state of %s request was changed to '%s' by '%s'" % (package
, sr
.state
.name
, sr
.state
.who
)
252 res
= raw_input("Do you want to change it to '%s'? [y/N] " % (action
))
253 if res
!= 'y' and res
!= 'Y':
256 # check before change of commit request
257 is_new_package
= not package
in meta_get_packagelist(self
.apiurl
, self
.project
)
258 if action
== 'accepted' and is_new_package
:
259 essage
= "You are now a maintainer of %s in openSUSE:Factory:Contrib" % (package
)
261 # change to the state action
262 response
= change_submit_request_state(self
.apiurl
, id, action
, message
)
264 # change the state for a new packages
265 if action
== 'accepted' and is_new_package
:
266 # fix the maintainer and a bugowner
267 meta
= self
._get
_meta
_xml
(package
)
268 who
= sr
.statehistory
[0].who
269 if not self
._has
_user
_role
(meta
, 'maintainer', who
):
270 delMaintainer(self
.apiurl
, self
.project
, package
, sr
.state
.who
)
271 addMaintainer(self
.apiurl
, self
.project
, package
, who
)
272 if not self
._has
_user
_role
(meta
, 'bugowner', who
):
273 self
._addBugowner
(self
.apiurl
, self
.project
, package
, who
)