mirror of
https://github.com/openSUSE/osc.git
synced 2025-01-26 22:56:15 +01:00
import new request handling from branch:
- New generic "request" command: - new "delete" request - new "change_devel" request - Multiple actions in one request is not yet supported by osc
This commit is contained in:
parent
0158d5e377
commit
46d726133c
5
NEWS
5
NEWS
@ -1,4 +1,9 @@
|
||||
0.118:
|
||||
- Obsolete "submitreq" command
|
||||
- New generic "request" command:
|
||||
- new "delete" request
|
||||
- new "change_devel" request
|
||||
- Multiple actions in one request is not yet supported by osc
|
||||
- support of added .changes in commit message template
|
||||
- make submit request listing fast by server side filtering
|
||||
- allow pulling of conflicting changes via "osc repairlink"
|
||||
|
74
TODO
74
TODO
@ -58,85 +58,11 @@ MINOR:
|
||||
|
||||
|
||||
|
||||
[1]
|
||||
|
||||
http://api.opensuse.org/result/Apache/SUSE_Linux_10.0/apache2/result
|
||||
15:06 <darix> kurz zeit ueber 1-2 osc feature request zu reden die ich grade bekommen habe?
|
||||
15:06 <DuDE_> ja
|
||||
15:06 <darix> ok
|
||||
15:06 <darix> das 1. ist
|
||||
15:06 <darix> osc listpackages [<project>]
|
||||
15:06 <DuDE_> als Alias?
|
||||
15:07 <darix> osc listpackages [<project>] [<package>]
|
||||
15:07 <darix> es soll die gebauten sachen listen
|
||||
15:07 <DuDE_> ach so, rpms
|
||||
15:07 <darix> quasi alle rpms/debs die da sind
|
||||
15:07 <darix> und dann
|
||||
15:07 <DuDE_> mit Pfad/URL?
|
||||
15:07 <DuDE_> also praktisch den Link auf software.opesuse.org?
|
||||
15:07 <darix> osc getpackage [<project>] [<package>] [<rpm>]+
|
||||
15:07 <darix> nein
|
||||
15:07 <darix> im zweifel ueber API saugen
|
||||
15:08 <DuDE_> hm, waere noetig, falls ein Projekt noch nicht durchgebaut hat
|
||||
15:08 <darix> jau
|
||||
15:08 <darix> richi wuerde sich wirklich drueber freuen
|
||||
15:08 <darix> ich weiss dass es ueber die api vom backend geht
|
||||
15:09 <darix> ich weiss nur nicht ob api alles durchreicht
|
||||
15:09 <darix> und leider hab ich schon ein paar sachen im api code gefunden
|
||||
15:09 <darix> der falsch mit dem backend spricht :/
|
||||
15:09 <DuDE_> ja, macht osc build auch so, eigentlich, allerdings weiss es dann die noetigen Datein aus dem buildinfo (version, release)
|
||||
15:09 <darix> man kann auf dem backend alle rpms listen lassen
|
||||
|
||||
|
||||
|
||||
[3]
|
||||
|
||||
19:08 < Beineri> DuDE: can you add an option to "up" which moves instead overwriting a file if it has changed in the repository?
|
||||
19:08 < darix> Beineri: moves?
|
||||
19:08 < darix> oO
|
||||
19:08 < darix> Beineri: use case?
|
||||
19:09 < Beineri> darix: I want to see what changed when updating (we miss notification and history if you didn't notice). so I want to run "diff foo.myversion foo"
|
||||
19:09 < darix> Beineri: we have a history?
|
||||
19:09 < darix> Beineri: you should rtfm the api docs before claiming stuff!:p
|
||||
19:10 < Beineri> darix: trying to turn around my words?
|
||||
19:10 < darix> Beineri: no
|
||||
19:10 < darix> just correcting wrong statements.
|
||||
19:10 < DuDE> Beineri: doesn't sound too useful
|
||||
19:10 < Beineri> darix: what's wrong with "we miss history"?
|
||||
19:10 < DuDE> it's deviating too much from the normal usecase
|
||||
19:10 < DuDE> which is, merging upstream changes in
|
||||
19:10 < DuDE> Beineri: but I have a better idea, I think
|
||||
19:11 < DuDE> Beineri: something that I miss in svn very much
|
||||
19:11 < Beineri> DuDE: it still shall merge, but make a copy of my version before :-)
|
||||
19:11 < darix> GET http://api.opensuse.org/source/<project>/<package>/<filename>
|
||||
19:11 < DuDE> Beineri: you mean, keep a fool.mine file in any case?
|
||||
19:11 < darix> GET http://api.opensuse.org/source/<project>/<package>/<filename>?rev=1234
|
||||
19:11 < DuDE> Beineri: what I miss badly, is a command to see upstream changes
|
||||
19:11 < DuDE> Beineri: such as the good old cvs status
|
||||
19:12 < DuDE> Beineri: which showed the status of the files on the server
|
||||
19:12 < Beineri> DuDE: status is not enough, I want to see what changed :-)
|
||||
19:12 < DuDE> Beineri: I mostly want to know what I have to expect, before up'ping and merging
|
||||
19:12 < DuDE> Beineri: yes, I also want to see that
|
||||
19:12 < DuDE> Beineri: some kind of osc updiff
|
||||
19:13 < DuDE> Beineri: would that help?
|
||||
19:13 < darix> .oO( i smell nice race conditions^^ )o
|
||||
19:13 < DuDE> Beineri: sorry, I just recognize that you asked for an option
|
||||
19:13 < DuDE> Beineri: that's of course always an option
|
||||
19:14 < DuDE> Beineri: surely
|
||||
19:14 < Beineri> DuDE: that would help, yes. "my" stuff I could for now do with a wrapper :-)
|
||||
19:15 < Beineri> darix: and that's how useful without osc/web-frontend support?
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
15:16 < DuDE> mt: Projekte anlegen geht nur, wenn es ein Subprojekt ist von einem Projekt wo Du Schreibrechte hast
|
||||
15:16 < mt> DuDE: wofür?
|
||||
15:16 < DuDE> mt: dass jeder einfach so top-level-Projekte anlegen kann, war einmal. Chaos-Reduzierung
|
||||
15:17 < DuDE> mt: ueblich ist heutzutage ein Request auf opensuse-buildservice@
|
||||
15:18 < DuDE> mt: kannst Du das gleiche mal eben mit osc -H probieren? Mich wuerde mal interessieren, ob da eine sinnvollere Meldung im Body mitkommt
|
||||
15:19 < DuDE> mt: mit -H muesste osc den Response-Body anzeigen. Meist ist der unerwuenscht, weil er typischerweise dank iChain hauptsaechlich Javascript-Schlonz enthaelt.
|
||||
15:19 < mt> DuDE: reply: 'HTTP/1.1 403 Forbidden\r\n'
|
||||
15:20 < DuDE> mt: das ist gut, dann sollte osc kein "try again" anbieten, sondern die Meldung rueberbringen
|
||||
|
||||
|
@ -486,58 +486,25 @@ class Osc(cmdln.Cmdln):
|
||||
help='only show requests created by yourself')
|
||||
@cmdln.alias("sr")
|
||||
@cmdln.alias("submitrequest")
|
||||
@cmdln.hide(1)
|
||||
def do_submitreq(self, subcmd, opts, *args):
|
||||
"""${cmd_name}: Handle requests to submit a package into another project
|
||||
|
||||
[See http://en.opensuse.org/Build_Service/Collaboration for information
|
||||
on this topic.]
|
||||
|
||||
For "create", there are two ways to use it. Either with a working copy
|
||||
or without. If called with no arguments, osc will guess what to submit
|
||||
where. If you don't have a working copy, you can give the respective
|
||||
arguments on the command line (see below for an example).
|
||||
Then, the DESTPAC name is optional; the source packages' name will be
|
||||
used if DESTPAC is omitted.
|
||||
With --message, a message can be attached.
|
||||
With --revision, a revision MD5 of a package can be specified which is
|
||||
to be submitted. The default is to request submission of the currently
|
||||
checked in revision.
|
||||
|
||||
"list" lists open requests attached to a project or package.
|
||||
|
||||
"log" will show the history of the given ID
|
||||
|
||||
"show" will show the request itself, and generate a diff for review, if
|
||||
used with the --diff option.
|
||||
|
||||
"decline" will change the request state to "declined" and append a
|
||||
message that you specify with the --message option.
|
||||
|
||||
"delete" will permanently delete a request and append a
|
||||
message that you specify with the --message option.
|
||||
|
||||
"revoke" will set the request state to "revoked" and append a
|
||||
message that you specify with the --message option.
|
||||
|
||||
"accept" will change the request state to "accepted" and will trigger
|
||||
the actual submit process. That would normally be a server-side copy of
|
||||
the source package to the target package.
|
||||
|
||||
|
||||
usage:
|
||||
osc submitreq create [-m TEXT]
|
||||
osc submitreq create [-m TEXT] DESTPRJ [DESTPKG]
|
||||
osc submitreq create [-m TEXT] SOURCEPRJ SOURCEPKG DESTPRJ [DESTPKG]
|
||||
osc submitreq list [-M] [PRJ [PKG]]
|
||||
osc submitreq log ID
|
||||
osc submitreq show [-d] [-b] ID
|
||||
osc submitreq accept [-m TEXT] ID
|
||||
osc submitreq decline [-m TEXT] ID
|
||||
osc submitreq delete [-m TEXT] ID
|
||||
osc submitreq revoke [-m TEXT] ID
|
||||
${cmd_option_list}
|
||||
*************************************************************************
|
||||
WARNING: the "submitreq" command is about to become obsolete. Please use
|
||||
the "request" command instead !
|
||||
*************************************************************************
|
||||
"""
|
||||
|
||||
print """
|
||||
*************************************************************************
|
||||
WARNING: the "submitreq" command is about to become obsolete. Please use
|
||||
the "request" command instead !
|
||||
*************************************************************************
|
||||
"""
|
||||
args = slash_split(args)
|
||||
|
||||
cmds = ['create', 'list', 'log', 'show', 'decline', 'accept', 'delete', 'revoke']
|
||||
@ -639,23 +606,25 @@ of the package %s primarily takes place.
|
||||
Please submit there instead, or use --nodevelproject to force direct submission.""" \
|
||||
% (devloc, dst_package)
|
||||
sys.exit(1)
|
||||
reqs = get_submit_request_list(apiurl, dst_project, dst_package)
|
||||
reqs = get_request_list(apiurl, dst_project, dst_package)
|
||||
user = conf.get_apiurl_usr(apiurl)
|
||||
myreqs = [ i for i in reqs if i.state.who == user ]
|
||||
repl = ''
|
||||
if len(myreqs) > 0:
|
||||
print 'You already created the following submitrequests: %s.' % \
|
||||
print 'You already created the following requests: %s.' % \
|
||||
', '.join([str(i.reqid) for i in myreqs ])
|
||||
repl = raw_input('Revoke the old requests? (y/N) ')
|
||||
|
||||
# since we have no support in the cli to specify different action types yet
|
||||
# the default is a submit action
|
||||
result = create_submit_request(apiurl,
|
||||
src_project, src_package,
|
||||
dst_project, dst_package,
|
||||
opts.message, orev=opts.revision)
|
||||
src_project, src_package,
|
||||
dst_project, dst_package,
|
||||
opts.message, orev=opts.revision)
|
||||
if repl == 'y':
|
||||
for req in myreqs:
|
||||
change_submit_request_state(apiurl, str(req.reqid), 'revoked',
|
||||
'superseded by %s' % result)
|
||||
change_request_state(apiurl, str(req.reqid), 'revoked',
|
||||
'superseded by %s' % result)
|
||||
|
||||
print 'created request id', result
|
||||
|
||||
@ -667,8 +636,8 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
||||
if opts.mine:
|
||||
who = conf.get_apiurl_usr(apiurl)
|
||||
|
||||
results = get_submit_request_list(apiurl,
|
||||
project, package, who, state_list)
|
||||
results = get_request_list(apiurl,
|
||||
project, package, who, state_list)
|
||||
|
||||
results.sort(reverse=True)
|
||||
|
||||
@ -676,13 +645,13 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
||||
print result.list_view()
|
||||
|
||||
elif cmd == 'log':
|
||||
for l in get_submit_request_log(conf.config['apiurl'], reqid):
|
||||
for l in get_request_log(conf.config['apiurl'], reqid):
|
||||
print l
|
||||
|
||||
|
||||
# show
|
||||
elif cmd == 'show':
|
||||
r = get_submit_request(conf.config['apiurl'], reqid)
|
||||
r = get_request(conf.config['apiurl'], reqid)
|
||||
if opts.brief:
|
||||
print r.list_view()
|
||||
else:
|
||||
@ -691,8 +660,8 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
||||
if opts.diff:
|
||||
try:
|
||||
print server_diff(conf.config['apiurl'],
|
||||
r.dst_project, r.dst_package, None,
|
||||
r.src_project, r.src_package, r.src_rev, opts.unified)
|
||||
r.actions[0].dst_project, r.actions[0].dst_package, None,
|
||||
r.actions[0].src_project, r.actions[0].src_package, r.actions[0].src_rev, opts.unified)
|
||||
except urllib2.HTTPError, e:
|
||||
e.osc_msg = 'Diff not possible'
|
||||
raise
|
||||
@ -700,23 +669,300 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
||||
|
||||
# decline
|
||||
elif cmd == 'decline':
|
||||
r = change_submit_request_state(conf.config['apiurl'],
|
||||
r = change_request_state(conf.config['apiurl'],
|
||||
reqid, 'declined', opts.message or '')
|
||||
print r
|
||||
|
||||
# accept
|
||||
elif cmd == 'accept':
|
||||
r = change_submit_request_state(conf.config['apiurl'],
|
||||
r = change_request_state(conf.config['apiurl'],
|
||||
reqid, 'accepted', opts.message or '')
|
||||
print r
|
||||
# delete
|
||||
elif cmd == 'delete':
|
||||
r = change_submit_request_state(conf.config['apiurl'],
|
||||
r = change_request_state(conf.config['apiurl'],
|
||||
reqid, 'deleted', opts.message or '')
|
||||
print r
|
||||
# revoke
|
||||
elif cmd == 'revoke':
|
||||
r = change_submit_request_state(conf.config['apiurl'],
|
||||
r = change_request_state(conf.config['apiurl'],
|
||||
reqid, 'revoked', opts.message or '')
|
||||
print r
|
||||
|
||||
|
||||
@cmdln.option('-d', '--diff', action='store_true',
|
||||
help='generate a diff')
|
||||
@cmdln.option('-u', '--unified', action='store_true',
|
||||
help='output the diff in the unified diff format')
|
||||
@cmdln.option('-m', '--message', metavar='TEXT',
|
||||
help='specify message TEXT')
|
||||
@cmdln.option('-r', '--revision', metavar='REV',
|
||||
help='for "create", specify a certain source revision ID (the md5 sum)')
|
||||
@cmdln.option('--nodevelproject', action='store_true',
|
||||
help='do not follow a defined devel project ' \
|
||||
'(primary project where a package is developed)')
|
||||
@cmdln.option('-s', '--state', default='new',
|
||||
help='only list requests in one of the comma separated given states [default=new]')
|
||||
@cmdln.option('-b', '--brief', action='store_true', default=False,
|
||||
help='print output in list view as list subcommand')
|
||||
@cmdln.option('-M', '--mine', action='store_true',
|
||||
help='only show requests created by yourself')
|
||||
@cmdln.alias("rq")
|
||||
def do_request(self, subcmd, opts, *args):
|
||||
"""${cmd_name}: Handle requests to another project
|
||||
|
||||
[See http://en.opensuse.org/Build_Service/Collaboration for information
|
||||
on this topic.]
|
||||
|
||||
For "submit", there are two ways to use it. Either with a working copy
|
||||
or without. If called with no arguments, osc will guess what to submit
|
||||
where. If you don't have a working copy, you can give the respective
|
||||
arguments on the command line (see below for an example).
|
||||
Then, the DESTPAC name is optional; the source packages' name will be
|
||||
used if DESTPAC is omitted.
|
||||
With --message, a message can be attached.
|
||||
With --revision, a revision MD5 of a package can be specified which is
|
||||
to be submitted. The default is to request submission of the currently
|
||||
checked in revision.
|
||||
|
||||
"list" lists open requests attached to a project or package.
|
||||
|
||||
"log" will show the history of the given ID
|
||||
|
||||
"show" will show the request itself, and generate a diff for review, if
|
||||
used with the --diff option.
|
||||
|
||||
"decline" will change the request state to "declined" and append a
|
||||
message that you specify with the --message option.
|
||||
|
||||
"delete" will permanently delete a request and append a
|
||||
message that you specify with the --message option.
|
||||
|
||||
"revoke" will set the request state to "revoked" and append a
|
||||
message that you specify with the --message option.
|
||||
|
||||
"accept" will change the request state to "accepted" and will trigger
|
||||
the actual submit process. That would normally be a server-side copy of
|
||||
the source package to the target package.
|
||||
|
||||
|
||||
usage:
|
||||
osc request submit [-m TEXT]
|
||||
osc request submit [-m TEXT] DESTPRJ [DESTPKG]
|
||||
osc request submit [-m TEXT] SOURCEPRJ SOURCEPKG DESTPRJ [DESTPKG]
|
||||
osc request list [-M] [PRJ [PKG]]
|
||||
osc request log ID
|
||||
osc request show [-d] [-b] ID
|
||||
osc request accept [-m TEXT] ID
|
||||
osc request decline [-m TEXT] ID
|
||||
osc request revoke [-m TEXT] ID
|
||||
osc request delete [-m TEXT] DESTPRJ [DESTPKG]
|
||||
osc request change_devel [-m TEXT] PROJECT PACKAGE DEVEL_PROJECT [DEVEL_PACKAGE]
|
||||
${cmd_option_list}
|
||||
"""
|
||||
|
||||
args = slash_split(args)
|
||||
|
||||
cmds = ['submit', 'list', 'log', 'show', 'decline', 'accept', 'delete', 'revoke', 'change_devel']
|
||||
if not args or args[0] not in cmds:
|
||||
raise oscerr.WrongArgs('Unknown request action. Choose one of %s.' \
|
||||
% ', '.join(cmds))
|
||||
|
||||
cmd = args[0]
|
||||
del args[0]
|
||||
|
||||
if cmd in ['submit']:
|
||||
min_args, max_args = 0, 4
|
||||
elif cmd in ['delete']:
|
||||
min_args, max_args = 1, 2
|
||||
elif cmd in ['change_devel']:
|
||||
min_args, max_args = 3, 4
|
||||
elif cmd in ['list']:
|
||||
min_args, max_args = 0, 2
|
||||
else:
|
||||
min_args, max_args = 1, 1
|
||||
if len(args) < min_args:
|
||||
raise oscerr.WrongArgs('Too few arguments.')
|
||||
if len(args) > max_args:
|
||||
raise oscerr.WrongArgs('Too many arguments.')
|
||||
|
||||
apiurl = conf.config['apiurl']
|
||||
|
||||
# collect specific arguments
|
||||
if cmd == 'submit':
|
||||
if len(args) <= 2:
|
||||
# try using the working copy at hand
|
||||
p = findpacs(os.curdir)[0]
|
||||
src_project = p.prjname
|
||||
src_package = p.name
|
||||
if len(args) == 0 and p.islink():
|
||||
dst_project = p.linkinfo.project
|
||||
dst_package = p.linkinfo.package
|
||||
apiurl = p.apiurl
|
||||
elif len(args) > 0:
|
||||
dst_project = args[0]
|
||||
if len(args) == 2:
|
||||
dst_package = args[1]
|
||||
else:
|
||||
dst_package = src_package
|
||||
else:
|
||||
sys.exit('Package \'%s\' is not a source link, so I cannot guess the submit target.\n'
|
||||
'Please provide it the target via commandline arguments.' % p.name)
|
||||
|
||||
modified = [i for i in p.filenamelist if p.status(i) != ' ' and p.status(i) != '?']
|
||||
if len(modified) > 0:
|
||||
print 'Your working copy has local modifications.'
|
||||
repl = raw_input('Proceed without committing the local changes? (y|N) ')
|
||||
if repl != 'y':
|
||||
sys.exit(1)
|
||||
elif len(args) >= 3:
|
||||
# get the arguments from the commandline
|
||||
src_project, src_package, dst_project = args[0:3]
|
||||
if len(args) == 4:
|
||||
dst_package = args[3]
|
||||
else:
|
||||
dst_package = src_package
|
||||
else:
|
||||
raise oscerr.WrongArgs('Incorrect number of arguments.\n\n' \
|
||||
+ self.get_cmd_help('request'))
|
||||
|
||||
elif cmd == 'list':
|
||||
package = None
|
||||
project = None
|
||||
if len(args) > 0:
|
||||
project = args[0]
|
||||
elif not opts.mine:
|
||||
project = store_read_project(os.curdir)
|
||||
apiurl = store_read_apiurl(os.curdir)
|
||||
try:
|
||||
package = store_read_package(os.curdir)
|
||||
except oscerr.NoWorkingCopy:
|
||||
pass
|
||||
|
||||
if len(args) > 1:
|
||||
package = args[1]
|
||||
elif cmd in ['log', 'show', 'decline', 'accept', 'delete', 'revoke']:
|
||||
reqid = args[0]
|
||||
|
||||
|
||||
# create submit request
|
||||
if cmd == 'submit':
|
||||
if not opts.nodevelproject:
|
||||
devloc = None
|
||||
try:
|
||||
devloc = show_develproject(apiurl, dst_project, dst_package)
|
||||
except urllib2.HTTPError:
|
||||
print >>sys.stderr, """\
|
||||
Warning: failed to fetch meta data for '%s' package '%s' (new package?) """ \
|
||||
% (dst_project, dst_package)
|
||||
pass
|
||||
|
||||
if devloc \
|
||||
and dst_project != devloc \
|
||||
and src_project != devloc:
|
||||
print """\
|
||||
Sorry, but a different project, %s, is defined as the place where development
|
||||
of the package %s primarily takes place.
|
||||
Please submit there instead, or use --nodevelproject to force direct submission.""" \
|
||||
% (devloc, dst_package)
|
||||
sys.exit(1)
|
||||
reqs = get_request_list(apiurl, dst_project, dst_package)
|
||||
user = conf.get_apiurl_usr(apiurl)
|
||||
myreqs = [ i for i in reqs if i.state.who == user ]
|
||||
repl = ''
|
||||
if len(myreqs) > 0:
|
||||
print 'You already created the following submit request: %s.' % \
|
||||
', '.join([str(i.reqid) for i in myreqs ])
|
||||
repl = raw_input('Revoke the old requests? (y/N) ')
|
||||
|
||||
# since we have no support in the cli to specify different action types yet
|
||||
# the default is a submit action
|
||||
result = create_submit_request(apiurl,
|
||||
src_project, src_package,
|
||||
dst_project, dst_package,
|
||||
opts.message, orev=opts.revision)
|
||||
if repl == 'y':
|
||||
for req in myreqs:
|
||||
change_request_state(apiurl, str(req.reqid), 'revoked',
|
||||
'superseded by %s' % result)
|
||||
|
||||
print 'created request id', result
|
||||
|
||||
# create delete request
|
||||
elif cmd == 'delete':
|
||||
project = args[0]
|
||||
package = None
|
||||
if len(args) > 1:
|
||||
package = args[1]
|
||||
result = create_delete_request(apiurl, project, package, opts.message)
|
||||
print result
|
||||
|
||||
# request to change devel project
|
||||
elif cmd == 'change_devel':
|
||||
devel_project = args[2]
|
||||
project = args[0]
|
||||
package = args[1]
|
||||
devel_package = package
|
||||
if len(args) > 3:
|
||||
devel_package = args[3]
|
||||
result = create_change_devel_request(apiurl,
|
||||
devel_project, devel_package,
|
||||
project, package,
|
||||
opts.message)
|
||||
print result
|
||||
|
||||
# list
|
||||
elif cmd == 'list':
|
||||
state_list = opts.state.split(',')
|
||||
who = ''
|
||||
if opts.mine:
|
||||
who = conf.get_apiurl_usr(apiurl)
|
||||
|
||||
results = get_request_list(apiurl,
|
||||
project, package, who, state_list)
|
||||
|
||||
results.sort(reverse=True)
|
||||
|
||||
for result in results:
|
||||
print result.list_view()
|
||||
|
||||
elif cmd == 'log':
|
||||
for l in get_request_log(conf.config['apiurl'], reqid):
|
||||
print l
|
||||
|
||||
|
||||
# show
|
||||
elif cmd == 'show':
|
||||
r = get_request(conf.config['apiurl'], reqid)
|
||||
if opts.brief:
|
||||
print r.list_view()
|
||||
else:
|
||||
print r
|
||||
# fixme: will inevitably fail if the given target doesn't exist
|
||||
if opts.diff:
|
||||
try:
|
||||
print server_diff(conf.config['apiurl'],
|
||||
r.actions[0].dst_project, r.actions[0].dst_package, None,
|
||||
r.actions[0].src_project, r.actions[0].src_package, r.actions[0].src_rev, opts.unified)
|
||||
except urllib2.HTTPError, e:
|
||||
e.osc_msg = 'Diff not possible'
|
||||
raise
|
||||
|
||||
|
||||
# decline
|
||||
elif cmd == 'decline':
|
||||
r = change_request_state(conf.config['apiurl'],
|
||||
reqid, 'declined', opts.message or '')
|
||||
print r
|
||||
|
||||
# accept
|
||||
elif cmd == 'accept':
|
||||
r = change_request_state(conf.config['apiurl'],
|
||||
reqid, 'accepted', opts.message or '')
|
||||
print r
|
||||
# revoke
|
||||
elif cmd == 'revoke':
|
||||
r = change_request_state(conf.config['apiurl'],
|
||||
reqid, 'revoked', opts.message or '')
|
||||
print r
|
||||
|
||||
@ -727,6 +973,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
||||
@cmdln.alias("createpac")
|
||||
@cmdln.alias("edituser")
|
||||
@cmdln.alias("usermeta")
|
||||
@cmdln.hide(1)
|
||||
def do_editmeta(self, subcmd, opts, *args):
|
||||
"""${cmd_name}:
|
||||
|
||||
|
213
osc/core.py
213
osc/core.py
@ -1231,9 +1231,18 @@ class RequestState:
|
||||
self.when = when
|
||||
self.comment = comment
|
||||
|
||||
class Action:
|
||||
"""represents an action"""
|
||||
def __init__(self, type, src_project, src_package, src_rev, dst_project, dst_package):
|
||||
self.type = type
|
||||
self.src_project = src_project
|
||||
self.src_package = src_package
|
||||
self.src_rev = src_rev
|
||||
self.dst_project = dst_project
|
||||
self.dst_package = dst_package
|
||||
|
||||
class SubmitReq:
|
||||
"""represent a submit request and holds its metadata
|
||||
class Request:
|
||||
"""represent a request and holds its metadata
|
||||
it has methods to read in metadata from xml,
|
||||
different views, ..."""
|
||||
def __init__(self):
|
||||
@ -1242,26 +1251,30 @@ class SubmitReq:
|
||||
self.who = None
|
||||
self.when = None
|
||||
self.last_author = None
|
||||
self.src_project = None
|
||||
self.src_package = None
|
||||
self.src_rev = None
|
||||
self.dst_project = None
|
||||
self.dst_package = None
|
||||
self.descr = None
|
||||
self.actions = []
|
||||
self.statehistory = []
|
||||
|
||||
def read(self, root):
|
||||
self.reqid = int(root.get('id'))
|
||||
actions = root.findall('action')
|
||||
if len(actions) == 0:
|
||||
actions = [ root.find('submit') ] # for old style requests
|
||||
|
||||
n = root.find('submit').find('source')
|
||||
self.src_project = n.get('project')
|
||||
self.src_package = n.get('package')
|
||||
try: self.src_rev = n.get('rev')
|
||||
except: pass
|
||||
|
||||
n = root.find('submit').find('target')
|
||||
self.dst_project = n.get('project')
|
||||
self.dst_package = n.get('package')
|
||||
for action in actions:
|
||||
type = action.get('type', 'submit')
|
||||
try:
|
||||
n = action.find('source')
|
||||
src_prj = n.get('project')
|
||||
src_pkg = n.get('package')
|
||||
src_rev = n.get('rev', None)
|
||||
n = action.find('target')
|
||||
dst_prj = n.get('project')
|
||||
dst_pkg = n.get('package')
|
||||
self.add_action(type, src_prj, src_pkg, src_rev, dst_prj, dst_pkg)
|
||||
except:
|
||||
msg = 'invalid request format:\n%s' % ET.tostring(root)
|
||||
raise oscerr.APIError(msg)
|
||||
|
||||
# read the state
|
||||
n = root.find('state')
|
||||
@ -1292,11 +1305,15 @@ class SubmitReq:
|
||||
except:
|
||||
pass
|
||||
|
||||
def add_action(self, type, src_prj, src_pkg, src_rev, dst_prj, dst_pkg):
|
||||
self.actions.append(Action(type, src_prj, src_pkg, src_rev,
|
||||
dst_prj, dst_pkg)
|
||||
)
|
||||
|
||||
def list_view(self):
|
||||
dst = "%s/%s" % (self.dst_project, self.dst_package)
|
||||
if self.src_package == self.dst_package:
|
||||
dst = self.dst_project
|
||||
dst = "%s/%s" % (self.actions[0].dst_project, self.actions[0].dst_package)
|
||||
if self.actions[0].src_package == self.actions[0].dst_package:
|
||||
dst = self.actions[0].dst_project
|
||||
|
||||
desc = ""
|
||||
if self.descr:
|
||||
@ -1305,15 +1322,16 @@ class SubmitReq:
|
||||
return '%6d %-7s %-12s %-50s -> %-20s %s' % \
|
||||
(self.reqid,
|
||||
self.state.name, "(%s)" % self.state.who,
|
||||
"%s/%s" % (self.src_project, self.src_package),
|
||||
"%s/%s" % (self.actions[0].src_project, self.actions[0].src_package),
|
||||
dst, desc)
|
||||
|
||||
def __cmp__(self, other):
|
||||
return cmp(self.reqid, other.reqid)
|
||||
|
||||
def __str__(self):
|
||||
# XXX: only prints out the first action element
|
||||
s = """\
|
||||
Request to submit (sri%d):
|
||||
Request to %s (sri%s):
|
||||
|
||||
%s/%s -> %s/%s
|
||||
|
||||
@ -1325,12 +1343,13 @@ Message:
|
||||
|
||||
State: %-10s %s %s
|
||||
Comment: %s
|
||||
""" % (self.reqid,
|
||||
self.src_project,
|
||||
self.src_package,
|
||||
self.dst_project,
|
||||
self.dst_package,
|
||||
self.src_rev or 'not given',
|
||||
""" % (self.actions[0].type,
|
||||
self.reqid,
|
||||
self.actions[0].src_project,
|
||||
self.actions[0].src_package,
|
||||
self.actions[0].dst_project,
|
||||
self.actions[0].dst_package,
|
||||
self.actions[0].src_rev or 'not given',
|
||||
self.descr,
|
||||
self.state.name,
|
||||
self.state.when, self.state.who, self.state.comment)
|
||||
@ -2022,21 +2041,68 @@ def edit_message(footer='', template=''):
|
||||
pass
|
||||
|
||||
|
||||
def create_delete_request(apiurl, project, package, message):
|
||||
|
||||
import cgi
|
||||
|
||||
if package:
|
||||
package = """package="%s" """ % (package)
|
||||
else:
|
||||
package = ""
|
||||
|
||||
xml = """\
|
||||
<request>
|
||||
<action type="delete">
|
||||
<target project="%s" %s/>
|
||||
</action>
|
||||
<state name="new"/>
|
||||
<description>%s</description>
|
||||
</request>
|
||||
""" % (project, package,
|
||||
cgi.escape(message or ''))
|
||||
|
||||
u = makeurl(apiurl, ['request'], query='cmd=create')
|
||||
f = http_POST(u, data=xml)
|
||||
|
||||
root = ET.parse(f).getroot()
|
||||
return root.get('id')
|
||||
|
||||
|
||||
def create_change_devel_request(apiurl,
|
||||
devel_project, devel_package,
|
||||
project, package,
|
||||
message):
|
||||
|
||||
import cgi
|
||||
xml = """\
|
||||
<request>
|
||||
<action type="change_devel">
|
||||
<source project="%s" package="%s" />
|
||||
<target project="%s" package="%s" />
|
||||
</action>
|
||||
<state name="new"/>
|
||||
<description>%s</description>
|
||||
</request>
|
||||
""" % (devel_project,
|
||||
devel_package,
|
||||
project,
|
||||
package,
|
||||
cgi.escape(message or ''))
|
||||
|
||||
u = makeurl(apiurl, ['request'], query='cmd=create')
|
||||
f = http_POST(u, data=xml)
|
||||
|
||||
root = ET.parse(f).getroot()
|
||||
return root.get('id')
|
||||
|
||||
|
||||
def create_submit_request(apiurl,
|
||||
src_project, src_package,
|
||||
dst_project, dst_package,
|
||||
message, orev=None):
|
||||
|
||||
import cgi
|
||||
|
||||
r = SubmitReq()
|
||||
r.src_project = src_project
|
||||
r.src_package = src_package
|
||||
r.src_rev = orev or show_upstream_rev(apiurl, src_project, src_package)
|
||||
r.dst_project = dst_project
|
||||
r.dst_package = dst_package
|
||||
r.descr = cgi.escape(message or '')
|
||||
|
||||
# XXX: keep the old template for now in order to work with old obs instances
|
||||
xml = """\
|
||||
<request type="submit">
|
||||
<submit>
|
||||
@ -2046,12 +2112,12 @@ def create_submit_request(apiurl,
|
||||
<state name="new"/>
|
||||
<description>%s</description>
|
||||
</request>
|
||||
""" % (r.src_project,
|
||||
r.src_package,
|
||||
r.src_rev,
|
||||
r.dst_project,
|
||||
r.dst_package,
|
||||
r.descr)
|
||||
""" % (src_project,
|
||||
src_package,
|
||||
orev or show_upstream_rev(apiurl, src_project, src_package),
|
||||
dst_project,
|
||||
dst_package,
|
||||
cgi.escape(message or ''))
|
||||
|
||||
u = makeurl(apiurl, ['request'], query='cmd=create')
|
||||
f = http_POST(u, data=xml)
|
||||
@ -2060,17 +2126,17 @@ def create_submit_request(apiurl,
|
||||
return root.get('id')
|
||||
|
||||
|
||||
def get_submit_request(apiurl, reqid):
|
||||
def get_request(apiurl, reqid):
|
||||
u = makeurl(apiurl, ['request', reqid])
|
||||
f = http_GET(u)
|
||||
root = ET.parse(f).getroot()
|
||||
|
||||
r = SubmitReq()
|
||||
r = Request()
|
||||
r.read(root)
|
||||
return r
|
||||
|
||||
|
||||
def change_submit_request_state(apiurl, reqid, newstate, message=''):
|
||||
def change_request_state(apiurl, reqid, newstate, message=''):
|
||||
u = makeurl(apiurl,
|
||||
['request', reqid],
|
||||
query={'cmd': 'changestate', 'newstate': newstate})
|
||||
@ -2078,40 +2144,43 @@ def change_submit_request_state(apiurl, reqid, newstate, message=''):
|
||||
return f.read()
|
||||
|
||||
|
||||
def get_submit_request_list(apiurl, project, package, req_who='', req_state=('new',) ):
|
||||
match = ''
|
||||
if project:
|
||||
if len(match): match += '%20and%20'
|
||||
match += 'submit/target/@project=\'%s\'' % quote_plus(project)
|
||||
if package:
|
||||
if len(match): match += '%20and%20'
|
||||
match += 'submit/target/@package=\'%s\'' % quote_plus(package)
|
||||
for state in req_state:
|
||||
if len(match): match += '%20and%20'
|
||||
match += 'state/@name=\'%s\'' % quote_plus(state)
|
||||
if req_who:
|
||||
if len(match): match += '%20and%20'
|
||||
match += 'state/@who=\'%s\'' % quote_plus(req_who)
|
||||
|
||||
u = makeurl(apiurl, ['search', 'request'], ['match=%s' % match])
|
||||
f = http_GET(u)
|
||||
collection = ET.parse(f).getroot()
|
||||
|
||||
def get_request_list(apiurl, project, package, req_who='', req_state=('new',) ):
|
||||
requests = []
|
||||
for root in collection.findall('request'):
|
||||
r = SubmitReq()
|
||||
r.read(root)
|
||||
if (r.state.name in req_state) or not len(req_state):
|
||||
requests.append(r)
|
||||
# XXX: we cannot use the '|' in the xpath expression because it is not supported
|
||||
# in the backend
|
||||
for what in ['action', 'submit']:
|
||||
match = ''
|
||||
if project:
|
||||
if len(match): match += '%20and%20'
|
||||
match += '%s/target/@project=\'%s\'' % (what, quote_plus(project))
|
||||
if package:
|
||||
if len(match): match += '%20and%20'
|
||||
match += '%s/target/@package=\'%s\'' % (what, quote_plus(package))
|
||||
for state in req_state:
|
||||
if len(match): match += '%20and%20'
|
||||
match += 'state/@name=\'%s\'' % quote_plus(state)
|
||||
if req_who:
|
||||
if len(match): match += '%20and%20'
|
||||
match += 'state/@who=\'%s\'' % quote_plus(req_who)
|
||||
|
||||
u = makeurl(apiurl, ['search', 'request'], ['match=%s' % match])
|
||||
f = http_GET(u)
|
||||
collection = ET.parse(f).getroot()
|
||||
|
||||
for root in collection.findall('request'):
|
||||
r = Request()
|
||||
r.read(root)
|
||||
if (r.state.name in req_state) or not len(req_state):
|
||||
requests.append(r)
|
||||
|
||||
return requests
|
||||
|
||||
|
||||
def get_submit_request_log(apiurl, reqid):
|
||||
r = get_submit_request(conf.config['apiurl'], reqid)
|
||||
def get_request_log(apiurl, reqid):
|
||||
r = get_request(conf.config['apiurl'], reqid)
|
||||
data = []
|
||||
frmt = '-' * 76 + '\n%s | %s | %s\n\n%s'
|
||||
# the description of the submitrequest is used for the initial log entry
|
||||
# the description of the request is used for the initial log entry
|
||||
# otherwise its comment attribute would contain None
|
||||
if len(r.statehistory) >= 1:
|
||||
r.statehistory[-1].comment = r.descr
|
||||
|
Loading…
Reference in New Issue
Block a user