mirror of
https://github.com/openSUSE/osc.git
synced 2024-12-25 01:16:14 +01:00
Merge branch 'master' of gitorious.org:opensuse/osc
This commit is contained in:
commit
1685ff801b
1
NEWS
1
NEWS
@ -17,6 +17,7 @@
|
|||||||
- support for new source service modes: disabled, trylocal and localonly
|
- support for new source service modes: disabled, trylocal and localonly
|
||||||
- support project wide source services
|
- support project wide source services
|
||||||
- support for armv7hl architecuture. used to denote armv7 + hardfloat binaries
|
- support for armv7hl architecuture. used to denote armv7 + hardfloat binaries
|
||||||
|
- add force option to accept requests in review state.
|
||||||
|
|
||||||
0.130
|
0.130
|
||||||
- new "revert" command to restore the original working copy file (without
|
- new "revert" command to restore the original working copy file (without
|
||||||
|
@ -9,6 +9,7 @@ import cmdln
|
|||||||
import conf
|
import conf
|
||||||
import oscerr
|
import oscerr
|
||||||
import sys
|
import sys
|
||||||
|
from util import safewriter
|
||||||
from optparse import SUPPRESS_HELP
|
from optparse import SUPPRESS_HELP
|
||||||
|
|
||||||
MAN_HEADER = r""".TH %(ucname)s "1" "%(date)s" "%(name)s %(version)s" "User Commands"
|
MAN_HEADER = r""".TH %(ucname)s "1" "%(date)s" "%(name)s %(version)s" "User Commands"
|
||||||
@ -63,6 +64,8 @@ class Osc(cmdln.Cmdln):
|
|||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
cmdln.Cmdln.__init__(self, *args, **kwargs)
|
cmdln.Cmdln.__init__(self, *args, **kwargs)
|
||||||
cmdln.Cmdln.do_help.aliases.append('h')
|
cmdln.Cmdln.do_help.aliases.append('h')
|
||||||
|
sys.stderr = safewriter.SafeWriter(sys.stderr)
|
||||||
|
sys.stdout = safewriter.SafeWriter(sys.stdout)
|
||||||
|
|
||||||
def get_version(self):
|
def get_version(self):
|
||||||
return get_osc_version()
|
return get_osc_version()
|
||||||
@ -349,10 +352,7 @@ class Osc(cmdln.Cmdln):
|
|||||||
elif not opts.binaries:
|
elif not opts.binaries:
|
||||||
if not args:
|
if not args:
|
||||||
for prj in meta_get_project_list(apiurl, opts.deleted):
|
for prj in meta_get_project_list(apiurl, opts.deleted):
|
||||||
try:
|
print prj
|
||||||
print prj
|
|
||||||
except UnicodeEncodeError:
|
|
||||||
print prj.encode('unicode_escape')
|
|
||||||
|
|
||||||
elif len(args) == 1:
|
elif len(args) == 1:
|
||||||
if opts.verbose:
|
if opts.verbose:
|
||||||
@ -361,10 +361,7 @@ class Osc(cmdln.Cmdln):
|
|||||||
if opts.expand:
|
if opts.expand:
|
||||||
raise oscerr.WrongOptions('Sorry, the --expand option is not implemented for projects.')
|
raise oscerr.WrongOptions('Sorry, the --expand option is not implemented for projects.')
|
||||||
for pkg in meta_get_packagelist(apiurl, project, opts.deleted):
|
for pkg in meta_get_packagelist(apiurl, project, opts.deleted):
|
||||||
try:
|
print pkg
|
||||||
print pkg
|
|
||||||
except UnicodeEncodeError:
|
|
||||||
print pkg.encode('unicode_escape')
|
|
||||||
|
|
||||||
elif len(args) == 2 or len(args) == 3:
|
elif len(args) == 2 or len(args) == 3:
|
||||||
link_seen = False
|
link_seen = False
|
||||||
@ -1014,7 +1011,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
|||||||
'superseded by %s' % result, result)
|
'superseded by %s' % result, result)
|
||||||
|
|
||||||
if opts.supersede:
|
if opts.supersede:
|
||||||
change_request_state(apiurl, opts.supersede, 'superseded',
|
change_request_state(apiurl, opts.supersede, 'superseded',
|
||||||
opts.message or '', result)
|
opts.message or '', result)
|
||||||
|
|
||||||
print 'created request id', result
|
print 'created request id', result
|
||||||
@ -1198,7 +1195,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
|||||||
'superseded by %s' % result, result)
|
'superseded by %s' % result, result)
|
||||||
|
|
||||||
if opts.supersede:
|
if opts.supersede:
|
||||||
change_request_state(apiurl, opts.supersede, 'superseded', '', result)
|
change_request_state(apiurl, opts.supersede, 'superseded', '', result)
|
||||||
|
|
||||||
#print 'created request id', result
|
#print 'created request id', result
|
||||||
return actionxml
|
return actionxml
|
||||||
@ -1605,6 +1602,8 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
|||||||
help='limit to requests which contain a given action type (submit/delete/change_devel)')
|
help='limit to requests which contain a given action type (submit/delete/change_devel)')
|
||||||
@cmdln.option('-a', '--all', action='store_true',
|
@cmdln.option('-a', '--all', action='store_true',
|
||||||
help='all states. Same as\'-s all\'')
|
help='all states. Same as\'-s all\'')
|
||||||
|
@cmdln.option('-f', '--force', action='store_true',
|
||||||
|
help='enforce state change, can be used to ignore open reviews')
|
||||||
@cmdln.option('-s', '--state', default='', # default is 'all' if no args given, 'new' otherwise
|
@cmdln.option('-s', '--state', default='', # default is 'all' if no args given, 'new' otherwise
|
||||||
help='only list requests in one of the comma separated given states (new/accepted/revoked/declined) or "all" [default=new, or all, if no args given]')
|
help='only list requests in one of the comma separated given states (new/accepted/revoked/declined) or "all" [default=new, or all, if no args given]')
|
||||||
@cmdln.option('-D', '--days', metavar='DAYS',
|
@cmdln.option('-D', '--days', metavar='DAYS',
|
||||||
@ -1873,7 +1872,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
|||||||
for result in results:
|
for result in results:
|
||||||
print result.reqid, ": ",
|
print result.reqid, ": ",
|
||||||
r = change_request_state(apiurl,
|
r = change_request_state(apiurl,
|
||||||
result.reqid, 'accepted', opts.message or '')
|
result.reqid, 'accepted', opts.message or '', force=opts.force)
|
||||||
print 'Result of change request state: %s' % r
|
print 'Result of change request state: %s' % r
|
||||||
else:
|
else:
|
||||||
print >>sys.stderr, 'Aborted...'
|
print >>sys.stderr, 'Aborted...'
|
||||||
@ -1955,7 +1954,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
|||||||
tmpl = change_request_state_template(rq, state_map[cmd])
|
tmpl = change_request_state_template(rq, state_map[cmd])
|
||||||
opts.message = edit_message(template=tmpl)
|
opts.message = edit_message(template=tmpl)
|
||||||
r = change_request_state(apiurl,
|
r = change_request_state(apiurl,
|
||||||
reqid, state_map[cmd], opts.message or '')
|
reqid, state_map[cmd], opts.message or '', force=opts.force)
|
||||||
print 'Result of change request state: %s' % r
|
print 'Result of change request state: %s' % r
|
||||||
|
|
||||||
# editmeta and its aliases are all depracated
|
# editmeta and its aliases are all depracated
|
||||||
@ -2407,11 +2406,6 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
|||||||
if len(args) >= 4:
|
if len(args) >= 4:
|
||||||
tpackage = args[3]
|
tpackage = args[3]
|
||||||
|
|
||||||
if not opts.message:
|
|
||||||
footer='please specify the purpose of your branch'
|
|
||||||
template='This package was branched from %s in order to ...\n' % args[0]
|
|
||||||
opts.message = edit_message(footer, template)
|
|
||||||
|
|
||||||
exists, targetprj, targetpkg, srcprj, srcpkg = \
|
exists, targetprj, targetpkg, srcprj, srcpkg = \
|
||||||
branch_pkg(apiurl, args[0], args[1],
|
branch_pkg(apiurl, args[0], args[1],
|
||||||
nodevelproject=opts.nodevelproject, rev=opts.revision,
|
nodevelproject=opts.nodevelproject, rev=opts.revision,
|
||||||
@ -2422,18 +2416,23 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
|||||||
print >>sys.stderr, 'Using existing branch project: %s' % targetprj
|
print >>sys.stderr, 'Using existing branch project: %s' % targetprj
|
||||||
|
|
||||||
devloc = None
|
devloc = None
|
||||||
if not exists and (srcprj is not None and srcprj != args[0] or \
|
if not exists and (srcprj != args[0] or srcpkg != args[1]):
|
||||||
srcprj is None and targetprj != expected):
|
try:
|
||||||
devloc = srcprj or targetprj
|
root = ET.fromstring(''.join(show_attribute_meta(apiurl, args[0], None, None,
|
||||||
if not srcprj and 'branches:' in targetprj:
|
conf.config['maintained_update_project_attribute'], False, False)))
|
||||||
devloc = targetprj.split('branches:')[1]
|
# this might raise an AttributeError
|
||||||
print '\nNote: The branch has been created of a different project,\n' \
|
uproject = root.find('attribute').find('value').text
|
||||||
' %s,\n' \
|
print '\nNote: The branch has been created from the configured update project: %s' \
|
||||||
' which is the primary location of where development for\n' \
|
% uproject
|
||||||
' that package takes place.\n' \
|
except (AttributeError, urllib2.HTTPError), e:
|
||||||
' That\'s also where you would normally make changes against.\n' \
|
devloc = srcprj
|
||||||
' A direct branch of the specified package can be forced\n' \
|
print '\nNote: The branch has been created of a different project,\n' \
|
||||||
' with the --nodevelproject option.\n' % devloc
|
' %s,\n' \
|
||||||
|
' which is the primary location of where development for\n' \
|
||||||
|
' that package takes place.\n' \
|
||||||
|
' That\'s also where you would normally make changes against.\n' \
|
||||||
|
' A direct branch of the specified package can be forced\n' \
|
||||||
|
' with the --nodevelproject option.\n' % devloc
|
||||||
|
|
||||||
package = tpackage or args[1]
|
package = tpackage or args[1]
|
||||||
if opts.checkout:
|
if opts.checkout:
|
||||||
@ -2450,7 +2449,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
|||||||
% (apiopt, targetprj, package)
|
% (apiopt, targetprj, package)
|
||||||
print_request_list(apiurl, args[0], args[1])
|
print_request_list(apiurl, args[0], args[1])
|
||||||
if devloc:
|
if devloc:
|
||||||
print_request_list(apiurl, devloc, args[1])
|
print_request_list(apiurl, devloc, srcpkg)
|
||||||
|
|
||||||
|
|
||||||
def do_undelete(self, subcmd, opts, *args):
|
def do_undelete(self, subcmd, opts, *args):
|
||||||
@ -5042,7 +5041,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
|||||||
what = {'project': ''}
|
what = {'project': ''}
|
||||||
elif type in args_sr:
|
elif type in args_sr:
|
||||||
requests = get_request_list(apiurl, req_who=user, exclude_target_projects=exclude_projects)
|
requests = get_request_list(apiurl, req_who=user, exclude_target_projects=exclude_projects)
|
||||||
for r in requests:
|
for r in sorted(requests):
|
||||||
print r.list_view(), '\n'
|
print r.list_view(), '\n'
|
||||||
return
|
return
|
||||||
elif not type in args_pkg:
|
elif not type in args_pkg:
|
||||||
@ -5061,19 +5060,25 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
|||||||
if list_requests:
|
if list_requests:
|
||||||
# try api side search as supported since OBS 2.2
|
# try api side search as supported since OBS 2.2
|
||||||
try:
|
try:
|
||||||
u = makeurl(apiurl, ['request'], ['view=collection&user=%s' % quote_plus(user)])
|
u = makeurl(apiurl, ['request'], {
|
||||||
res = http_GET(u)
|
'view' : 'collection',
|
||||||
requests = []
|
'state': 'pending',
|
||||||
for root in res['request'].findall('request'):
|
'user' : user,
|
||||||
r = Request()
|
})
|
||||||
r.read(root)
|
f = http_GET(u)
|
||||||
requests.append(r)
|
root = ET.parse(f).getroot()
|
||||||
for r in requests:
|
requests = []
|
||||||
print r.list_view(), '\n'
|
for node in root.findall('request'):
|
||||||
return
|
r = Request()
|
||||||
except:
|
r.read(node)
|
||||||
# skip it ... try again with old style below
|
requests.append(r)
|
||||||
pass
|
for r in sorted(requests):
|
||||||
|
print r.list_view(), '\n'
|
||||||
|
return
|
||||||
|
except urllib2.HTTPError, e:
|
||||||
|
if e.code == 400:
|
||||||
|
# skip it ... try again with old style below
|
||||||
|
pass
|
||||||
|
|
||||||
res = get_user_projpkgs(apiurl, user, role_filter, exclude_projects,
|
res = get_user_projpkgs(apiurl, user, role_filter, exclude_projects,
|
||||||
what.has_key('project'), what.has_key('package'),
|
what.has_key('project'), what.has_key('package'),
|
||||||
@ -5100,7 +5105,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
|||||||
if list_requests:
|
if list_requests:
|
||||||
# old style, only for OBS 2.1 and before. Should not be used, since it is slow and incomplete
|
# old style, only for OBS 2.1 and before. Should not be used, since it is slow and incomplete
|
||||||
requests = get_user_projpkgs_request_list(apiurl, user, projpkgs=request_todo)
|
requests = get_user_projpkgs_request_list(apiurl, user, projpkgs=request_todo)
|
||||||
for r in requests:
|
for r in sorted(requests):
|
||||||
print r.list_view(), '\n'
|
print r.list_view(), '\n'
|
||||||
else:
|
else:
|
||||||
for i in sorted(roles.keys()):
|
for i in sorted(roles.keys()):
|
||||||
|
57
osc/conf.py
57
osc/conf.py
@ -108,9 +108,7 @@ DEFAULTS = { 'apiurl': 'https://api.opensuse.org',
|
|||||||
'checkout_rooted': '0',
|
'checkout_rooted': '0',
|
||||||
# local files to ignore with status, addremove, ....
|
# local files to ignore with status, addremove, ....
|
||||||
'exclude_glob': '.osc CVS .svn .* _linkerror *~ #*# *.orig *.bak *.changes.vctmp.*',
|
'exclude_glob': '.osc CVS .svn .* _linkerror *~ #*# *.orig *.bak *.changes.vctmp.*',
|
||||||
# keep passwords in plaintext. If you see this comment, your osc
|
# whether to keep passwords in plaintext.
|
||||||
# already uses the encrypted password, and only keeps them in plain text
|
|
||||||
# for backwards compatibility. Default will change to 0 in future releases.
|
|
||||||
'plaintext_passwd': '1',
|
'plaintext_passwd': '1',
|
||||||
# limit the age of requests shown with 'osc req list'.
|
# limit the age of requests shown with 'osc req list'.
|
||||||
# this is a default only, can be overridden by 'osc req list -D NNN'
|
# this is a default only, can be overridden by 'osc req list -D NNN'
|
||||||
@ -224,11 +222,10 @@ apiurl = %(apiurl)s
|
|||||||
# local files to ignore with status, addremove, ....
|
# local files to ignore with status, addremove, ....
|
||||||
#exclude_glob = %(exclude_glob)s
|
#exclude_glob = %(exclude_glob)s
|
||||||
|
|
||||||
# keep passwords in plaintext. If you see this comment, your osc
|
# keep passwords in plaintext.
|
||||||
# already uses the encrypted password, and only keeps them in plain text
|
# Set to 0 to obfuscate passwords. It's no real security, just
|
||||||
# for backwards compatibility. Default will change to 0 in future releases.
|
# prevents most people from remembering your password if they watch
|
||||||
# You can remove the plaintext password without harm, if you do not need
|
# you editing this file.
|
||||||
# backwards compatibility.
|
|
||||||
#plaintext_passwd = %(plaintext_passwd)s
|
#plaintext_passwd = %(plaintext_passwd)s
|
||||||
|
|
||||||
# limit the age of requests shown with 'osc req list'.
|
# limit the age of requests shown with 'osc req list'.
|
||||||
@ -285,7 +282,7 @@ apiurl = %(apiurl)s
|
|||||||
|
|
||||||
[%(apiurl)s]
|
[%(apiurl)s]
|
||||||
user = %(user)s
|
user = %(user)s
|
||||||
passx = %(passx)s
|
pass = %(pass)s
|
||||||
# set aliases for this apiurl
|
# set aliases for this apiurl
|
||||||
# aliases = foo, bar
|
# aliases = foo, bar
|
||||||
# email used in .changes, unless the one from osc meta prj <user> will be used
|
# email used in .changes, unless the one from osc meta prj <user> will be used
|
||||||
@ -601,7 +598,6 @@ def write_initial_config(conffile, entries, custom_template = ''):
|
|||||||
conf_template = custom_template or new_conf_template
|
conf_template = custom_template or new_conf_template
|
||||||
config = DEFAULTS.copy()
|
config = DEFAULTS.copy()
|
||||||
config.update(entries)
|
config.update(entries)
|
||||||
config['passx'] = base64.b64encode(config['pass'].encode('bz2'))
|
|
||||||
# at this point use_keyring and gnome_keyring are str objects
|
# at this point use_keyring and gnome_keyring are str objects
|
||||||
if config['use_keyring'] == '1' and GENERIC_KEYRING:
|
if config['use_keyring'] == '1' and GENERIC_KEYRING:
|
||||||
protocol, host = \
|
protocol, host = \
|
||||||
@ -622,6 +618,9 @@ def write_initial_config(conffile, entries, custom_template = ''):
|
|||||||
config['passx'] = ''
|
config['passx'] = ''
|
||||||
if not config['plaintext_passwd']:
|
if not config['plaintext_passwd']:
|
||||||
config['pass'] = ''
|
config['pass'] = ''
|
||||||
|
else:
|
||||||
|
config['passx'] = base64.b64encode(config['pass'].encode('bz2'))
|
||||||
|
|
||||||
sio = StringIO.StringIO(conf_template.strip() % config)
|
sio = StringIO.StringIO(conf_template.strip() % config)
|
||||||
cp = OscConfigParser.OscConfigParser(DEFAULTS)
|
cp = OscConfigParser.OscConfigParser(DEFAULTS)
|
||||||
cp.readfp(sio)
|
cp.readfp(sio)
|
||||||
@ -675,7 +674,11 @@ def add_section(filename, url, user, passwd):
|
|||||||
cp.set(url, 'user', user)
|
cp.set(url, 'user', user)
|
||||||
if not config['plaintext_passwd']:
|
if not config['plaintext_passwd']:
|
||||||
cp.remove_option(url, 'pass')
|
cp.remove_option(url, 'pass')
|
||||||
cp.set(url, 'passx', base64.b64encode(passwd.encode('bz2')))
|
cp.set(url, 'passx', base64.b64encode(passwd.encode('bz2')))
|
||||||
|
else:
|
||||||
|
cp.remove_option(url, 'passx')
|
||||||
|
cp.set(url, 'pass', passwd)
|
||||||
|
|
||||||
file = open(filename, 'w')
|
file = open(filename, 'w')
|
||||||
cp.write(file, True)
|
cp.write(file, True)
|
||||||
if file: file.close()
|
if file: file.close()
|
||||||
@ -786,23 +789,29 @@ def get_config(override_conffile = None,
|
|||||||
#from the general section.
|
#from the general section.
|
||||||
user = cp.get(url, 'user', raw=True) # need to set raw to prevent '%' expansion
|
user = cp.get(url, 'user', raw=True) # need to set raw to prevent '%' expansion
|
||||||
password = cp.get(url, 'pass', raw=True) # especially on password!
|
password = cp.get(url, 'pass', raw=True) # especially on password!
|
||||||
passwordx = cp.get(url, 'passx', raw=True) # especially on password!
|
try:
|
||||||
|
passwordx = cp.get(url, 'passx', raw=True).decode('base64').decode('bz2') # especially on password!
|
||||||
|
except:
|
||||||
|
passwordx = ''
|
||||||
|
|
||||||
|
if password == None or password == 'your_password':
|
||||||
|
password = ''
|
||||||
|
|
||||||
if user is None or user == '':
|
if user is None or user == '':
|
||||||
raise oscerr.ConfigError('user is blank for %s' % apiurl, config['conffile'])
|
raise oscerr.ConfigError('user is blank for %s' % apiurl, config['conffile'])
|
||||||
|
|
||||||
if password is None or password == 'your_password':
|
if config['plaintext_passwd'] and passwordx or not config['plaintext_passwd'] and password:
|
||||||
try:
|
if not config['plaintext_passwd']:
|
||||||
password = passwordx.decode('base64').decode('bz2')
|
if password != passwordx:
|
||||||
except:
|
print >>sys.stderr, '%s: rewriting from plain pass to encoded pass' % url
|
||||||
print >>sys.stderr, "%s: no credentials known" % url
|
add_section(conffile, url, user, password)
|
||||||
password = 'your_password'
|
|
||||||
elif password != passwordx.decode('base64').decode('bz2'):
|
|
||||||
if not passwordx:
|
|
||||||
# passx not present
|
|
||||||
print >>sys.stderr, '%s: rewriting from plain pass to encoded pass\n' % url
|
|
||||||
else:
|
else:
|
||||||
print >>sys.stderr, '%s: pass and passx mismatch (rewriting from plain pass to encoded pass)\n' % url
|
if password != passwordx:
|
||||||
add_section(conffile, url, user, password)
|
print >>sys.stderr, '%s: rewriting from encoded pass to plain pass' % url
|
||||||
|
add_section(conffile, url, user, passwordx)
|
||||||
|
|
||||||
|
if not config['plaintext_passwd']:
|
||||||
|
password = passwordx
|
||||||
|
|
||||||
if cp.has_option(url, 'http_headers'):
|
if cp.has_option(url, 'http_headers'):
|
||||||
http_headers = cp.get(url, 'http_headers')
|
http_headers = cp.get(url, 'http_headers')
|
||||||
|
38
osc/core.py
38
osc/core.py
@ -2500,7 +2500,7 @@ class Request:
|
|||||||
|
|
||||||
def list_view(self):
|
def list_view(self):
|
||||||
"""return "list view" format"""
|
"""return "list view" format"""
|
||||||
import textwrap, locale
|
import textwrap
|
||||||
lines = ['%6s State:%-10s By:%-12s When:%-19s' % (self.reqid, self.state.name, self.state.who, self.state.when)]
|
lines = ['%6s State:%-10s By:%-12s When:%-19s' % (self.reqid, self.state.name, self.state.who, self.state.when)]
|
||||||
tmpl = ' %(type)-16s %(source)-50s %(target)s'
|
tmpl = ' %(type)-16s %(source)-50s %(target)s'
|
||||||
for action in self.actions:
|
for action in self.actions:
|
||||||
@ -2512,14 +2512,12 @@ class Request:
|
|||||||
if history:
|
if history:
|
||||||
lines.append(' From: %s' % ' -> '.join(history))
|
lines.append(' From: %s' % ' -> '.join(history))
|
||||||
if self.description:
|
if self.description:
|
||||||
descr = self.description.encode(locale.getpreferredencoding(), 'replace')
|
lines.append(textwrap.fill(self.description, width=80, initial_indent=' Descr: ',
|
||||||
lines.append(textwrap.fill(descr, width=80, initial_indent=' Descr: ',
|
|
||||||
subsequent_indent=' '))
|
subsequent_indent=' '))
|
||||||
return '\n'.join(lines)
|
return '\n'.join(lines)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""return "detailed" format"""
|
"""return "detailed" format"""
|
||||||
import locale
|
|
||||||
lines = ['Request: #%s\n' % self.reqid]
|
lines = ['Request: #%s\n' % self.reqid]
|
||||||
for action in self.actions:
|
for action in self.actions:
|
||||||
tmpl = ' %(type)-13s %(source)s %(target)s'
|
tmpl = ' %(type)-13s %(source)s %(target)s'
|
||||||
@ -2529,7 +2527,7 @@ class Request:
|
|||||||
lines.append(tmpl % Request.format_action(action, show_srcupdate=True))
|
lines.append(tmpl % Request.format_action(action, show_srcupdate=True))
|
||||||
lines.append('\n\nMessage:')
|
lines.append('\n\nMessage:')
|
||||||
if self.description:
|
if self.description:
|
||||||
lines.append(self.description.encode(locale.getpreferredencoding(), 'replace'))
|
lines.append(self.description)
|
||||||
else:
|
else:
|
||||||
lines.append('<no message>')
|
lines.append('<no message>')
|
||||||
if self.state:
|
if self.state:
|
||||||
@ -2568,7 +2566,7 @@ class Request:
|
|||||||
return '\n'.join(lines)
|
return '\n'.join(lines)
|
||||||
|
|
||||||
def __cmp__(self, other):
|
def __cmp__(self, other):
|
||||||
return cmp(self.reqid, other.reqid)
|
return cmp(int(self.reqid), int(other.reqid))
|
||||||
|
|
||||||
def create(self, apiurl):
|
def create(self, apiurl):
|
||||||
"""create a new request"""
|
"""create a new request"""
|
||||||
@ -3522,10 +3520,12 @@ def change_review_state(apiurl, reqid, newstate, by_user='', by_group='', by_pro
|
|||||||
root = ET.parse(f).getroot()
|
root = ET.parse(f).getroot()
|
||||||
return root.attrib['code']
|
return root.attrib['code']
|
||||||
|
|
||||||
def change_request_state(apiurl, reqid, newstate, message='', supersed=None):
|
def change_request_state(apiurl, reqid, newstate, message='', supersed=None, force=False):
|
||||||
query={'cmd': 'changestate', 'newstate': newstate }
|
query={'cmd': 'changestate', 'newstate': newstate }
|
||||||
if supersed:
|
if supersed:
|
||||||
query['superseded_by'] = supersed
|
query['superseded_by'] = supersed
|
||||||
|
if force:
|
||||||
|
query['force'] = "1"
|
||||||
u = makeurl(apiurl,
|
u = makeurl(apiurl,
|
||||||
['request', reqid], query=query)
|
['request', reqid], query=query)
|
||||||
f = http_POST(u, data=message)
|
f = http_POST(u, data=message)
|
||||||
@ -3595,7 +3595,7 @@ def get_review_list(apiurl, project='', package='', byuser='', bygroup='', bypro
|
|||||||
requests.append(r)
|
requests.append(r)
|
||||||
return requests
|
return requests
|
||||||
|
|
||||||
def get_request_list(apiurl, project='', package='', req_who='', req_state=('new',), req_type=None, exclude_target_projects=[]):
|
def get_request_list(apiurl, project='', package='', req_who='', req_state=('new','review',), req_type=None, exclude_target_projects=[]):
|
||||||
xpath = ''
|
xpath = ''
|
||||||
if not 'all' in req_state:
|
if not 'all' in req_state:
|
||||||
for state in req_state:
|
for state in req_state:
|
||||||
@ -3633,7 +3633,7 @@ def get_request_list(apiurl, project='', package='', req_who='', req_state=('new
|
|||||||
return requests
|
return requests
|
||||||
|
|
||||||
# old style search, this is to be removed
|
# old style search, this is to be removed
|
||||||
def get_user_projpkgs_request_list(apiurl, user, req_state=('new',), req_type=None, exclude_projects=[], projpkgs={}):
|
def get_user_projpkgs_request_list(apiurl, user, req_state=('new','review',), req_type=None, exclude_projects=[], projpkgs={}):
|
||||||
"""OBSOLETE: user involved request search is supported by OBS 2.2 server side in a better way
|
"""OBSOLETE: user involved request search is supported by OBS 2.2 server side in a better way
|
||||||
Return all running requests for all projects/packages where is user is involved"""
|
Return all running requests for all projects/packages where is user is involved"""
|
||||||
if not projpkgs:
|
if not projpkgs:
|
||||||
@ -4330,12 +4330,13 @@ def branch_pkg(apiurl, src_project, src_package, nodevelproject=False, rev=None,
|
|||||||
except urllib2.HTTPError, e:
|
except urllib2.HTTPError, e:
|
||||||
if not return_existing:
|
if not return_existing:
|
||||||
raise
|
raise
|
||||||
msg = ''.join(e.readlines())
|
root = ET.fromstring(e.read())
|
||||||
msg = msg.split('<summary>')[1]
|
summary = root.find('summary')
|
||||||
msg = msg.split('</summary>')[0]
|
if summary is None:
|
||||||
m = re.match(r"branch target package already exists: (\S+)/(\S+)", msg)
|
raise oscerr.APIError('unexpected response:\n%s' % ET.tostring(root))
|
||||||
|
m = re.match(r"branch target package already exists: (\S+)/(\S+)", summary.text)
|
||||||
if not m:
|
if not m:
|
||||||
e.msg += '\n' + msg
|
e.msg += '\n' + summary.text
|
||||||
raise
|
raise
|
||||||
return (True, m.group(1), m.group(2), None, None)
|
return (True, m.group(1), m.group(2), None, None)
|
||||||
|
|
||||||
@ -5889,13 +5890,8 @@ def request_interactive_review(apiurl, request, initial_cmd=''):
|
|||||||
tmpfile = None
|
tmpfile = None
|
||||||
|
|
||||||
def print_request(request):
|
def print_request(request):
|
||||||
try:
|
print request
|
||||||
# FIXME: print can fail with unicode chars in the string.
|
|
||||||
# Here we fix the symptoms, not the cause.
|
|
||||||
# UnicodeEncodeError: 'ascii' codec can't encode character u'\u2002' in position 309: ordinal not in range(128)
|
|
||||||
print request
|
|
||||||
except:
|
|
||||||
print request.__str__().encode('ascii', 'xmlcharrefreplace')
|
|
||||||
print_request(request)
|
print_request(request)
|
||||||
try:
|
try:
|
||||||
prompt = '(a)ccept/(d)ecline/(r)evoke/c(l)one/(s)kip/(c)ancel > '
|
prompt = '(a)ccept/(d)ecline/(r)evoke/c(l)one/(s)kip/(c)ancel > '
|
||||||
|
@ -1 +1 @@
|
|||||||
__all__ = ['ar', 'cpio', 'debquery', 'packagequery', 'rpmquery']
|
__all__ = ['ar', 'cpio', 'debquery', 'packagequery', 'rpmquery', 'safewriter']
|
||||||
|
29
osc/util/safewriter.py
Normal file
29
osc/util/safewriter.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# be careful when debugging this code:
|
||||||
|
# don't add print statements when setting sys.stdout = SafeWriter(sys.stdout)...
|
||||||
|
class SafeWriter:
|
||||||
|
"""
|
||||||
|
Safely write an (unicode) str. In case of an "UnicodeEncodeError" the
|
||||||
|
the str is encoded with the "encoding" encoding.
|
||||||
|
All getattr, setattr calls are passed through to the "writer" instance.
|
||||||
|
"""
|
||||||
|
def __init__(self, writer, encoding='unicode_escape'):
|
||||||
|
self.__dict__['writer'] = writer
|
||||||
|
self.__dict__['encoding'] = encoding
|
||||||
|
|
||||||
|
def __get_writer(self):
|
||||||
|
return self.__dict__['writer']
|
||||||
|
|
||||||
|
def __get_encoding(self):
|
||||||
|
return self.__dict__['encoding']
|
||||||
|
|
||||||
|
def write(self, s):
|
||||||
|
try:
|
||||||
|
self.__get_writer().write(s)
|
||||||
|
except UnicodeEncodeError, e:
|
||||||
|
self.__get_writer().write(s.encode(self.__get_encoding()))
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
return getattr(self.__get_writer(), name)
|
||||||
|
|
||||||
|
def __setattr__(self, name, value):
|
||||||
|
setattr(self.__get_writer(), name, value)
|
@ -90,9 +90,8 @@ apiurl = http://localhost
|
|||||||
#source_validator_directory = /usr/lib/osc/source_validators
|
#source_validator_directory = /usr/lib/osc/source_validators
|
||||||
|
|
||||||
[http://localhost]
|
[http://localhost]
|
||||||
user = Admin
|
user=Admin
|
||||||
pass = opensuse
|
pass=opensuse
|
||||||
passx = QlpoOTFBWSZTWeTSblkAAAGBgAIBygAgADDACGNEHxaYXckU4UJDk0m5ZA==
|
|
||||||
# set aliases for this apiurl
|
# set aliases for this apiurl
|
||||||
# aliases = foo, bar
|
# aliases = foo, bar
|
||||||
# email used in .changes, unless the one from osc meta prj <user> will be used
|
# email used in .changes, unless the one from osc meta prj <user> will be used
|
||||||
|
@ -90,9 +90,8 @@ apiurl = http://localhost
|
|||||||
#source_validator_directory = /usr/lib/osc/source_validators
|
#source_validator_directory = /usr/lib/osc/source_validators
|
||||||
|
|
||||||
[http://localhost]
|
[http://localhost]
|
||||||
user = Admin
|
user=Admin
|
||||||
pass = opensuse
|
pass=opensuse
|
||||||
passx = QlpoOTFBWSZTWeTSblkAAAGBgAIBygAgADDACGNEHxaYXckU4UJDk0m5ZA==
|
|
||||||
# set aliases for this apiurl
|
# set aliases for this apiurl
|
||||||
# aliases = foo, bar
|
# aliases = foo, bar
|
||||||
# email used in .changes, unless the one from osc meta prj <user> will be used
|
# email used in .changes, unless the one from osc meta prj <user> will be used
|
||||||
|
@ -90,9 +90,8 @@ apiurl = http://localhost
|
|||||||
#source_validator_directory = /usr/lib/osc/source_validators
|
#source_validator_directory = /usr/lib/osc/source_validators
|
||||||
|
|
||||||
[http://localhost]
|
[http://localhost]
|
||||||
user = Admin
|
user=Admin
|
||||||
pass = opensuse
|
pass=opensuse
|
||||||
passx = QlpoOTFBWSZTWeTSblkAAAGBgAIBygAgADDACGNEHxaYXckU4UJDk0m5ZA==
|
|
||||||
# set aliases for this apiurl
|
# set aliases for this apiurl
|
||||||
# aliases = foo, bar
|
# aliases = foo, bar
|
||||||
# email used in .changes, unless the one from osc meta prj <user> will be used
|
# email used in .changes, unless the one from osc meta prj <user> will be used
|
||||||
|
@ -90,9 +90,8 @@ apiurl = http://localhost
|
|||||||
#source_validator_directory = /usr/lib/osc/source_validators
|
#source_validator_directory = /usr/lib/osc/source_validators
|
||||||
|
|
||||||
[http://localhost]
|
[http://localhost]
|
||||||
user = Admin
|
user=Admin
|
||||||
pass = opensuse
|
pass=opensuse
|
||||||
passx = QlpoOTFBWSZTWeTSblkAAAGBgAIBygAgADDACGNEHxaYXckU4UJDk0m5ZA==
|
|
||||||
# set aliases for this apiurl
|
# set aliases for this apiurl
|
||||||
# aliases = foo, bar
|
# aliases = foo, bar
|
||||||
# email used in .changes, unless the one from osc meta prj <user> will be used
|
# email used in .changes, unless the one from osc meta prj <user> will be used
|
||||||
|
@ -90,9 +90,8 @@ apiurl = http://localhost
|
|||||||
#source_validator_directory = /usr/lib/osc/source_validators
|
#source_validator_directory = /usr/lib/osc/source_validators
|
||||||
|
|
||||||
[http://localhost]
|
[http://localhost]
|
||||||
user = Admin
|
user=Admin
|
||||||
pass = opensuse
|
pass=opensuse
|
||||||
passx = QlpoOTFBWSZTWeTSblkAAAGBgAIBygAgADDACGNEHxaYXckU4UJDk0m5ZA==
|
|
||||||
# set aliases for this apiurl
|
# set aliases for this apiurl
|
||||||
# aliases = foo, bar
|
# aliases = foo, bar
|
||||||
# email used in .changes, unless the one from osc meta prj <user> will be used
|
# email used in .changes, unless the one from osc meta prj <user> will be used
|
||||||
|
@ -90,9 +90,8 @@ apiurl = http://localhost
|
|||||||
#source_validator_directory = /usr/lib/osc/source_validators
|
#source_validator_directory = /usr/lib/osc/source_validators
|
||||||
|
|
||||||
[http://localhost]
|
[http://localhost]
|
||||||
user = Admin
|
user=Admin
|
||||||
pass = opensuse
|
pass=opensuse
|
||||||
passx = QlpoOTFBWSZTWeTSblkAAAGBgAIBygAgADDACGNEHxaYXckU4UJDk0m5ZA==
|
|
||||||
# set aliases for this apiurl
|
# set aliases for this apiurl
|
||||||
# aliases = foo, bar
|
# aliases = foo, bar
|
||||||
# email used in .changes, unless the one from osc meta prj <user> will be used
|
# email used in .changes, unless the one from osc meta prj <user> will be used
|
||||||
|
@ -90,9 +90,8 @@ apiurl = http://localhost
|
|||||||
#source_validator_directory = /usr/lib/osc/source_validators
|
#source_validator_directory = /usr/lib/osc/source_validators
|
||||||
|
|
||||||
[http://localhost]
|
[http://localhost]
|
||||||
user = Admin
|
user=Admin
|
||||||
pass = opensuse
|
pass=opensuse
|
||||||
passx = QlpoOTFBWSZTWeTSblkAAAGBgAIBygAgADDACGNEHxaYXckU4UJDk0m5ZA==
|
|
||||||
# set aliases for this apiurl
|
# set aliases for this apiurl
|
||||||
# aliases = foo, bar
|
# aliases = foo, bar
|
||||||
# email used in .changes, unless the one from osc meta prj <user> will be used
|
# email used in .changes, unless the one from osc meta prj <user> will be used
|
||||||
|
@ -90,9 +90,8 @@ apiurl = http://localhost
|
|||||||
#source_validator_directory = /usr/lib/osc/source_validators
|
#source_validator_directory = /usr/lib/osc/source_validators
|
||||||
|
|
||||||
[http://localhost]
|
[http://localhost]
|
||||||
user = Admin
|
user=Admin
|
||||||
pass = opensuse
|
pass=opensuse
|
||||||
passx = QlpoOTFBWSZTWeTSblkAAAGBgAIBygAgADDACGNEHxaYXckU4UJDk0m5ZA==
|
|
||||||
# set aliases for this apiurl
|
# set aliases for this apiurl
|
||||||
# aliases = foo, bar
|
# aliases = foo, bar
|
||||||
# email used in .changes, unless the one from osc meta prj <user> will be used
|
# email used in .changes, unless the one from osc meta prj <user> will be used
|
||||||
|
@ -90,9 +90,8 @@ apiurl = http://localhost
|
|||||||
#source_validator_directory = /usr/lib/osc/source_validators
|
#source_validator_directory = /usr/lib/osc/source_validators
|
||||||
|
|
||||||
[http://localhost]
|
[http://localhost]
|
||||||
user = Admin
|
user=Admin
|
||||||
pass = opensuse
|
pass=opensuse
|
||||||
passx = QlpoOTFBWSZTWeTSblkAAAGBgAIBygAgADDACGNEHxaYXckU4UJDk0m5ZA==
|
|
||||||
# set aliases for this apiurl
|
# set aliases for this apiurl
|
||||||
# aliases = foo, bar
|
# aliases = foo, bar
|
||||||
# email used in .changes, unless the one from osc meta prj <user> will be used
|
# email used in .changes, unless the one from osc meta prj <user> will be used
|
||||||
|
@ -90,9 +90,8 @@ apiurl = http://localhost
|
|||||||
#source_validator_directory = /usr/lib/osc/source_validators
|
#source_validator_directory = /usr/lib/osc/source_validators
|
||||||
|
|
||||||
[http://localhost]
|
[http://localhost]
|
||||||
user = Admin
|
user=Admin
|
||||||
pass = opensuse
|
pass=opensuse
|
||||||
passx = QlpoOTFBWSZTWeTSblkAAAGBgAIBygAgADDACGNEHxaYXckU4UJDk0m5ZA==
|
|
||||||
# set aliases for this apiurl
|
# set aliases for this apiurl
|
||||||
# aliases = foo, bar
|
# aliases = foo, bar
|
||||||
# email used in .changes, unless the one from osc meta prj <user> will be used
|
# email used in .changes, unless the one from osc meta prj <user> will be used
|
||||||
|
@ -90,9 +90,8 @@ apiurl = http://localhost
|
|||||||
#source_validator_directory = /usr/lib/osc/source_validators
|
#source_validator_directory = /usr/lib/osc/source_validators
|
||||||
|
|
||||||
[http://localhost]
|
[http://localhost]
|
||||||
user = Admin
|
user=Admin
|
||||||
pass = opensuse
|
pass=opensuse
|
||||||
passx = QlpoOTFBWSZTWeTSblkAAAGBgAIBygAgADDACGNEHxaYXckU4UJDk0m5ZA==
|
|
||||||
# set aliases for this apiurl
|
# set aliases for this apiurl
|
||||||
# aliases = foo, bar
|
# aliases = foo, bar
|
||||||
# email used in .changes, unless the one from osc meta prj <user> will be used
|
# email used in .changes, unless the one from osc meta prj <user> will be used
|
||||||
|
Loading…
Reference in New Issue
Block a user