mirror of
https://github.com/openSUSE/osc.git
synced 2025-03-03 14:42:11 +01:00
Merged revisions 3774-3775,3779,3781-3782,3787,3789-3793,3798,3802,3805,3817-3822,3827,3829-3830,3837-3839,3841-3842,3848-3850 via svnmerge from
https://forgesvn1.novell.com/svn/opensuse/branches/buildservice/osc-exception-handling ........ r3774 | poeml | 2008-04-22 17:39:45 +0200 (Tue, 22 Apr 2008) | 3 lines A first draft on implement systematic exception handling: Add errors.py with some exceptions defined, and babysitter.py to handle them ........ r3775 | poeml | 2008-04-22 22:34:12 +0200 (Tue, 22 Apr 2008) | 9 lines - new global options: --debugger jump into the debugger before executing anything --post-mortem jump into the debugger in case of errors -t, --traceback print call trace in case of errors - traceback and post_mortem can also be set in .oscrc. - catch more errors (HTTPError). - make config accessible from outside of the Osc instance, by making it a class attribute ........ r3779 | poeml | 2008-04-23 00:55:49 +0200 (Wed, 23 Apr 2008) | 5 lines - new global option: -d, --debug print info useful for debugging - catch some more errors (HTTPError), with OscHTTPError which isn't very advanced yet. ........ r3781 | Marcus_H | 2008-04-23 01:02:00 +0200 (Wed, 23 Apr 2008) | 2 lines - added OscConfigError class (just for testing). - small change in the signature of the OscBaseError constructor (actually we should get rid of the 'args' tuple because it will be deprecated sooner or later ........ r3782 | Marcus_H | 2008-04-23 02:02:13 +0200 (Wed, 23 Apr 2008) | 2 lines - access the prg.conf.config dict in a save way - this way we avoid AttributeErrors if the prg.conf.config dict doesn't exist - in case of an configparser error we have to use the prg.options object directly (this was removed in r3781 by accident) ........ r3787 | poeml | 2008-04-23 09:23:56 +0200 (Wed, 23 Apr 2008) | 4 lines - remove local exception handling from do_req - for HTTPError, print details (headers and response) when in debug mode - catch AttributeError ........ r3789 | poeml | 2008-04-23 16:23:14 +0200 (Wed, 23 Apr 2008) | 4 lines - errors: add two new classes named OscWrongOptionsError and OscWrongArgsError - commandline: raise instances of the new errors in a number of places - commandline: add get_cmd_help() to Osc instance which returns the formatted help of a subcommand ........ r3790 | Marcus_H | 2008-04-23 16:48:28 +0200 (Wed, 23 Apr 2008) | 4 lines - added 2 new exception classes: OscNoConfigfileError and OscIOError - added new method write_config() to the conf.py module: This method writes osc's configuration file - minor cleanups in the conf module ........ r3791 | poeml | 2008-04-23 17:11:07 +0200 (Wed, 23 Apr 2008) | 3 lines small compatibility fix for r3790: try-except-finally isn't supported in python-2.4.2, thus do the same as try-except inside a try-finally. ........ r3792 | poeml | 2008-04-23 17:37:53 +0200 (Wed, 23 Apr 2008) | 2 lines fix up the remaining places regarding handling of errors related to commandline parsing ........ r3793 | poeml | 2008-04-23 17:40:34 +0200 (Wed, 23 Apr 2008) | 3 lines raise a NoWorkingCopyError in osc.core.store_read_project() in case of an IOError ........ r3798 | Marcus_H | 2008-04-23 23:55:24 +0200 (Wed, 23 Apr 2008) | 1 line ported -r3797 from trunk ........ r3802 | Marcus_H | 2008-04-24 11:00:55 +0200 (Thu, 24 Apr 2008) | 1 line ported -r3801 from trunk ........ r3805 | poeml | 2008-04-24 12:52:30 +0200 (Thu, 24 Apr 2008) | 2 lines raise OscHTTPError in show_pattern_meta(), replacing local error handling ........ r3817 | poeml | 2008-04-24 20:21:32 +0200 (Thu, 24 Apr 2008) | 9 lines - remove errors.OscHTTPError again. it seems simpler to use urllib2.HTTPError instead (and just add a specific error text message where appropriate, and re-raise) - for 404s, check out _which_ part was not found it is very ugly, but may be considered Good for pragmatic reasons - removed local exception handling and workaround for returned 500's from delete_package() and delete_project(), thereby getting rid of 4 possible exit points. ........ r3818 | Marcus_H | 2008-04-24 22:36:17 +0200 (Thu, 24 Apr 2008) | 1 line - this check is superfluous because every HTTPError instance has a code attribute ........ r3819 | poeml | 2008-04-25 00:39:39 +0200 (Fri, 25 Apr 2008) | 1 line remove a forgotten debug line from core.delete_project() ........ r3820 | poeml | 2008-04-25 10:07:58 +0200 (Fri, 25 Apr 2008) | 2 lines - ditch local error handling from wipebinaries(), rebuild(), and abortbuild() ........ r3821 | poeml | 2008-04-25 10:56:38 +0200 (Fri, 25 Apr 2008) | 2 lines It is never needed to import the exception module. ........ r3822 | poeml | 2008-04-25 11:13:39 +0200 (Fri, 25 Apr 2008) | 4 lines - when going into the debugger with --post-mortem, always print a traceback before (thus implying -t) - do not jump into the debugger if not on a TTY, or working in interactive mode ........ r3827 | poeml | 2008-04-25 13:07:46 +0200 (Fri, 25 Apr 2008) | 9 lines - add errors.OscWorkingCopyOutdated, which takes a tuple with three args: path to working copy, current rev, expected rev - add handler for urllib2.URLError errors to the babysitter - simplify the OscWrongArgsError and OscWrongOptionsError handlers, by removing the extra line "Sorry, wrong ..." that was printed before the messages given when the error was raised. - remove one more errors.OscHTTPError which was still there, and raise urllib2.HTTPError instead (show_package_meta()) ........ r3829 | poeml | 2008-04-25 14:19:10 +0200 (Fri, 25 Apr 2008) | 11 lines - comment some methods in osc.core which are used by nearly all do_* methods in osc.commandline - improve "is not a package/project dir" error messages, by printing the absolute path tried, instead of '.' for the cwd - make core.store_read_package() raise a proper NoWorkingCopyError instead of terminating - give attribution to things in babysitter.py copied from mercurial - prefix HTTPError exceptions with 'Server returned an error:' - remove obsolete local error handling from do_prjresults(), do_importsrcpkg(), do_repos() ........ r3830 | poeml | 2008-04-25 14:29:35 +0200 (Fri, 25 Apr 2008) | 1 line catch IOError exceptions in the babysitter ........ r3837 | poeml | 2008-04-25 17:27:36 +0200 (Fri, 25 Apr 2008) | 5 lines - do_remotebuildlog: raise errors for wrong arguments, remove exits - raise AttributeError in make_meta_url() instead of exiting - delete unused method core.delete_server_files() - replace exit call inside make_meta_url() with an AttributeError ........ r3838 | poeml | 2008-04-25 17:49:18 +0200 (Fri, 25 Apr 2008) | 1 line simplify the check in do_checkout if a project exists, by using show_project_meta() instead of meta_exists ........ r3839 | poeml | 2008-04-25 18:31:26 +0200 (Fri, 25 Apr 2008) | 6 lines - commandline do_checkout(): change the order of the two checks, first do the (cheaper) check for existing directory - core.core checkout_package(): simplify the check in if the package exists, by using show_package_meta() instead of meta_exists Let it throw an exception, instead of using sys.exit(). ........ r3841 | Marcus_H | 2008-04-27 15:48:06 +0200 (Sun, 27 Apr 2008) | 5 lines - added 2 new exception classes: PackageError() and PackageExistsError. The PackageError() class is meant to be the base class for all subsequent package exceptions. - get rid of 2 sys.exit(1) calls - make the update() method of the Project() class safer: in any case we have to write the _packages file otherwise the package tracking will be screwed up. - minor fix in delPackage(): use getTransActPath() when printing out the filename ........ r3842 | Marcus_H | 2008-04-27 16:52:55 +0200 (Sun, 27 Apr 2008) | 3 lines - make the commit() method safe: in any case we have to write the _packages file otherwise the package tracking will be screwed up. - removed another sys.exit(1): raise an exception if a package is missing when doing a commit. For now we use the PackageExistsError() exception but this might change in the future (updated description of PackageExistsError() according to this change) ........ r3848 | poeml | 2008-04-28 12:46:45 +0200 (Mon, 28 Apr 2008) | 3 lines rename several error classes, dropping the "Osc" prefix, and "Error" suffix in cases where they don't really make sense. ........ r3849 | poeml | 2008-04-28 12:57:32 +0200 (Mon, 28 Apr 2008) | 3 lines - rename osc.errors module to osc.oscerr, to make it easier to import it from other programs and have a crystal clear namespace ........ r3850 | poeml | 2008-04-28 13:26:12 +0200 (Mon, 28 Apr 2008) | 2 lines split PackageExists exception class into PackageExists and PackageMissing ........
This commit is contained in:
parent
f8b35ba80a
commit
3018460596
@ -5,8 +5,12 @@
|
||||
|
||||
import sys
|
||||
from osc import commandline
|
||||
from osc import babysitter
|
||||
|
||||
osccli = commandline.Osc()
|
||||
|
||||
r = babysitter.run(osccli)
|
||||
sys.exit(r)
|
||||
|
||||
osc = commandline.Osc()
|
||||
sys.exit( osc.main() )
|
||||
|
||||
|
||||
|
@ -1 +1 @@
|
||||
__all__ = ['core', 'commandline', 'othermethods', 'build', 'fetch', 'meter']
|
||||
__all__ = ['babysitter', 'core', 'commandline', 'oscerr', 'othermethods', 'build', 'fetch', 'meter']
|
||||
|
145
osc/babysitter.py
Normal file
145
osc/babysitter.py
Normal file
@ -0,0 +1,145 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright (C) 2008 Peter Poeml / Novell Inc. All rights reserved.
|
||||
# This program is free software; it may be used, copied, modified
|
||||
# and distributed under the terms of the GNU General Public Licence,
|
||||
# either version 2, or (at your option) any later version.
|
||||
|
||||
import sys
|
||||
import signal
|
||||
from osc import oscerr
|
||||
from urllib2 import URLError, HTTPError
|
||||
|
||||
# the good things are stolen from Matt Mackall's mercurial
|
||||
|
||||
def catchterm(*args):
|
||||
raise oscerr.SignalInterrupt
|
||||
|
||||
for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
|
||||
num = getattr(signal, name, None)
|
||||
if num: signal.signal(num, catchterm)
|
||||
|
||||
|
||||
def run(prg):
|
||||
|
||||
try:
|
||||
|
||||
try:
|
||||
if '--debugger' in sys.argv:
|
||||
import pdb
|
||||
pdb.set_trace()
|
||||
|
||||
# here we actually run the program:
|
||||
return prg.main()
|
||||
|
||||
except:
|
||||
# look for an option in the prg.options object and in the config dict
|
||||
# print stack trace, if desired
|
||||
if getattr(prg.options, 'traceback', None) or getattr(prg.conf, 'config', {}).get('traceback', None) or \
|
||||
getattr(prg.options, 'post_mortem', None) or getattr(prg.conf, 'config', {}).get('post_mortem', None):
|
||||
import traceback
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
# we could use http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52215
|
||||
|
||||
# enter the debugger, if desired
|
||||
if getattr(prg.options, 'post_mortem', None) or getattr(prg.conf, 'config', {}).get('post_mortem', None):
|
||||
if sys.stdout.isatty() and not hasattr(sys, 'ps1'):
|
||||
import pdb
|
||||
pdb.post_mortem(sys.exc_info()[2])
|
||||
else:
|
||||
print >>sys.stderr, 'sys.stdout is not a tty. Not jumping into pdb.'
|
||||
raise
|
||||
|
||||
except oscerr.SignalInterrupt:
|
||||
print >>sys.stderr, 'killed!'
|
||||
return 1
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print >>sys.stderr, 'interrupted!'
|
||||
return 1
|
||||
|
||||
except oscerr.UnreadableFile, e:
|
||||
print >>sys.stderr, e.msg
|
||||
return 1
|
||||
|
||||
except (oscerr.NoWorkingCopy, oscerr.WorkingCopyWrongVersion), e:
|
||||
print >>sys.stderr, e
|
||||
return 1
|
||||
|
||||
except HTTPError, e:
|
||||
print >>sys.stderr, 'Server returned an error:', e
|
||||
if hasattr(e, 'osc_msg'):
|
||||
print >>sys.stderr, e.osc_msg
|
||||
|
||||
if getattr(prg.options, 'debug', None) or \
|
||||
getattr(prg.conf, 'config', {}).get('debug', None):
|
||||
print >>sys.stderr, e.hdrs
|
||||
print >>sys.stderr, e.read()
|
||||
|
||||
# For 404s, check out _which_ part was not found
|
||||
#
|
||||
# It is very ugly, but may be Good for pragmatic reasons
|
||||
#
|
||||
# FIXME this can be obsoleted when the api returns a more specific error code
|
||||
# like "project not found" right away
|
||||
if e.code == 404:
|
||||
import urlparse
|
||||
scheme, netloc, path = urlparse.urlsplit(e.url)[0:3]
|
||||
parts = path.split('/')
|
||||
# we know how to do this for /source URLs. I don't know for others right now...
|
||||
if len(parts) > 1 and parts[1] == 'source':
|
||||
if len(parts) == 3:
|
||||
# it was a request on /source/project
|
||||
print >>sys.stderr, 'A project named \'%s\' does not exist.' % parts[2]
|
||||
if len(parts) == 4:
|
||||
# it was a request on /source/project/package
|
||||
prjurl = urlparse.urlunsplit((scheme, netloc, '/'.join(parts[:3]), None, None))
|
||||
import osc.core
|
||||
try:
|
||||
osc.core.http_GET(prjurl)
|
||||
except:
|
||||
print >>sys.stderr, 'A project named \'%s\' does not exist.' % parts[2]
|
||||
else:
|
||||
print >>sys.stderr, \
|
||||
'A package named \'%s\' does not exist in project \'%s\'.' \
|
||||
% (parts[3], parts[2])
|
||||
else:
|
||||
# not handled...
|
||||
pass
|
||||
|
||||
return 1
|
||||
|
||||
except URLError, e:
|
||||
print >>sys.stderr, 'Failed to reach a server:', e.reason
|
||||
return 1
|
||||
|
||||
except (oscerr.ConfigError, oscerr.NoConfigfile), e:
|
||||
print >>sys.stderr, e.msg
|
||||
return 1
|
||||
|
||||
except oscerr.OscIOError, e:
|
||||
print >>sys.stderr, e.msg
|
||||
if getattr(prg.options, 'debug', None) or \
|
||||
getattr(prg.conf, 'config', {}).get('debug', None):
|
||||
print >>sys.stderr, e.e
|
||||
return 1
|
||||
|
||||
except (oscerr.WrongOptions, oscerr.WrongArgs), e:
|
||||
print >>sys.stderr, e
|
||||
return 2
|
||||
|
||||
except oscerr.WorkingCopyOutdated, e:
|
||||
print >>sys.stderr, e
|
||||
return 1
|
||||
|
||||
except (oscerr.PackageExists, oscerr.PackageMissing), e:
|
||||
print >>sys.stderr, e.msg
|
||||
return 1
|
||||
|
||||
except IOError, e:
|
||||
print >>sys.stderr, e
|
||||
return 1
|
||||
|
||||
except AttributeError, e:
|
||||
print >>sys.stderr, e
|
||||
return 1
|
@ -9,6 +9,7 @@
|
||||
from core import *
|
||||
import cmdln
|
||||
import conf
|
||||
import oscerr
|
||||
|
||||
|
||||
class Osc(cmdln.Cmdln):
|
||||
@ -26,6 +27,7 @@ class Osc(cmdln.Cmdln):
|
||||
* http://www.opensuse.org/Build_Service/CLI
|
||||
"""
|
||||
name = 'osc'
|
||||
conf = None
|
||||
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@ -37,8 +39,16 @@ class Osc(cmdln.Cmdln):
|
||||
"""this is the parser for "global" options (not specific to subcommand)"""
|
||||
|
||||
optparser = cmdln.CmdlnOptionParser(self, version=get_osc_version())
|
||||
optparser.add_option('--debugger', action='store_true',
|
||||
help='jump into the debugger before executing anything')
|
||||
optparser.add_option('--post-mortem', action='store_true',
|
||||
help='jump into the debugger in case of errors')
|
||||
optparser.add_option('-t', '--traceback', action='store_true',
|
||||
help='print call trace in case of errors')
|
||||
optparser.add_option('-H', '--http-debug', action='store_true',
|
||||
help='debug HTTP traffic')
|
||||
optparser.add_option('-d', '--debug', action='store_true',
|
||||
help='print info useful for debugging')
|
||||
optparser.add_option('-A', '--apisrv', dest='apisrv',
|
||||
metavar='URL',
|
||||
help='specify URL to access API server at')
|
||||
@ -50,10 +60,41 @@ class Osc(cmdln.Cmdln):
|
||||
|
||||
def postoptparse(self):
|
||||
"""merge commandline options into the config"""
|
||||
|
||||
try:
|
||||
conf.get_config(override_conffile = self.options.conffile,
|
||||
override_apisrv = self.options.apisrv,
|
||||
override_debug = self.options.debug,
|
||||
override_http_debug = self.options.http_debug,
|
||||
override_apisrv = self.options.apisrv)
|
||||
override_traceback = self.options.traceback,
|
||||
override_post_mortem = self.options.post_mortem)
|
||||
except oscerr.NoConfigfile, e:
|
||||
print >>sys.stderr, e.msg
|
||||
print >>sys.stderr, 'Creating osc configuration file %s ...' % e.file
|
||||
import getpass
|
||||
config = {}
|
||||
config['user'] = raw_input('Username: ')
|
||||
config['pass'] = getpass.getpass()
|
||||
|
||||
if conf.write_config(e.file, config):
|
||||
print >>sys.stderr, 'done'
|
||||
conf.get_config(override_conffile = self.options.conffile,
|
||||
override_apisrv = self.options.apisrv,
|
||||
override_debug = self.options.debug,
|
||||
override_http_debug = self.options.http_debug,
|
||||
override_traceback = self.options.traceback,
|
||||
override_post_mortem = self.options.post_mortem)
|
||||
else:
|
||||
raise NoConfigfile(e.file, 'Unable to create osc\'s configuration file \
|
||||
\'%s\'' % e.file)
|
||||
self.conf = conf
|
||||
|
||||
|
||||
def get_cmd_help(self, cmdname):
|
||||
doc = self._get_cmd_handler(cmdname).__doc__
|
||||
doc = self._help_reindent(doc)
|
||||
doc = self._help_preprocess(doc, cmdname)
|
||||
doc = doc.rstrip() + '\n' # trim down trailing space
|
||||
return self._str(doc)
|
||||
|
||||
|
||||
def do_init(self, subcmd, opts, project, package):
|
||||
@ -117,15 +158,13 @@ class Osc(cmdln.Cmdln):
|
||||
package = args[1]
|
||||
|
||||
if opts.binaries and (not opts.repo or not opts.arch):
|
||||
sys.exit('missing options:\n'
|
||||
'-r <repo> -a <arch>\n'
|
||||
'list repositories with:\n'
|
||||
'\'osc platforms %s\'' %project)
|
||||
raise oscerr.WrongOptions('Sorry, -r <repo> -a <arch> missing\n'
|
||||
'You can list repositories with: \'osc platforms <project>\'')
|
||||
|
||||
# list binaries
|
||||
if opts.binaries:
|
||||
if not args:
|
||||
sys.exit('there are no binaries to list above project level.')
|
||||
raise oscerr.WrongArgs('There are no binaries to list above project level.')
|
||||
|
||||
elif len(args) == 1:
|
||||
#if opts.verbose:
|
||||
@ -144,7 +183,7 @@ class Osc(cmdln.Cmdln):
|
||||
|
||||
elif len(args) == 1:
|
||||
if opts.verbose:
|
||||
sys.exit('The verbose option is not implemented for projects.')
|
||||
raise oscerr.WrongOptions('Sorry, the --verbose option is not implemented for projects.')
|
||||
|
||||
print '\n'.join(meta_get_packagelist(conf.config['apiurl'], project))
|
||||
|
||||
@ -211,8 +250,8 @@ class Osc(cmdln.Cmdln):
|
||||
args = slash_split(args)
|
||||
|
||||
if not args or args[0] not in metatypes.keys():
|
||||
print >>sys.stderr, 'Unknown meta type. Choose one of %s.' % ', '.join(metatypes)
|
||||
return 2
|
||||
raise oscerr.WrongArgs('Unknown meta type. Choose one of %s.' \
|
||||
% ', '.join(metatypes))
|
||||
|
||||
cmd = args[0]
|
||||
del args[0]
|
||||
@ -224,11 +263,9 @@ class Osc(cmdln.Cmdln):
|
||||
else:
|
||||
min_args, max_args = 1, 1
|
||||
if len(args) < min_args:
|
||||
print >>sys.stderr, 'Too few arguments.'
|
||||
return 2
|
||||
raise oscerr.WrongArgs('Too few arguments.')
|
||||
if len(args) > max_args:
|
||||
print >>sys.stderr, 'Too many arguments.'
|
||||
return 2
|
||||
raise oscerr.WrongArgs('Too many arguments.')
|
||||
|
||||
# specific arguments
|
||||
if cmd == 'prj':
|
||||
@ -247,7 +284,7 @@ class Osc(cmdln.Cmdln):
|
||||
pattern = None
|
||||
# enforce pattern argument if needed
|
||||
if opts.edit or opts.file:
|
||||
sys.exit('a pattern file argument is required.')
|
||||
raise oscerr.WrongArgs('A pattern file argument is required.')
|
||||
|
||||
# show
|
||||
if not opts.edit and not opts.file and not opts.delete:
|
||||
@ -395,8 +432,8 @@ class Osc(cmdln.Cmdln):
|
||||
|
||||
cmds = ['create', 'list', 'show', 'decline', 'accept']
|
||||
if not args or args[0] not in cmds:
|
||||
print >>sys.stderr, 'Unknown submitreq action. Choose one of %s.' % ', '.join(cmds)
|
||||
return 2
|
||||
raise oscerr.WrongArgs('Unknown submitreq action. Choose one of %s.' \
|
||||
% ', '.join(cmds))
|
||||
|
||||
cmd = args[0]
|
||||
del args[0]
|
||||
@ -408,11 +445,9 @@ class Osc(cmdln.Cmdln):
|
||||
else:
|
||||
min_args, max_args = 1, 1
|
||||
if len(args) < min_args:
|
||||
print >>sys.stderr, 'Too few arguments.'
|
||||
return 2
|
||||
raise oscerr.WrongArgs('Too few arguments.')
|
||||
if len(args) > max_args:
|
||||
print >>sys.stderr, 'Too many arguments.'
|
||||
return 2
|
||||
raise oscerr.WrongArgs('Too many arguments.')
|
||||
|
||||
# collect specific arguments
|
||||
if cmd == 'create':
|
||||
@ -459,7 +494,8 @@ class Osc(cmdln.Cmdln):
|
||||
r.dst_project, r.dst_package, None,
|
||||
r.src_project, r.src_package, r.src_md5)
|
||||
except urllib2.HTTPError, e:
|
||||
print >>sys.stderr, 'Diff not possible:', e
|
||||
e.osc_msg = 'Diff not possible'
|
||||
raise
|
||||
|
||||
|
||||
# decline
|
||||
@ -521,9 +557,8 @@ class Osc(cmdln.Cmdln):
|
||||
args = slash_split(args)
|
||||
|
||||
if not args or len(args) < 3:
|
||||
print >>sys.stderr, 'Incorrect number of argument.'
|
||||
self.do_help([None, 'linkpac'])
|
||||
return 2
|
||||
raise oscerr.WrongArgs('Incorrect number of arguments.\n\n' \
|
||||
+ self.get_cmd_help('linkpac'))
|
||||
|
||||
src_project = args[0]
|
||||
src_package = args[1]
|
||||
@ -552,9 +587,8 @@ class Osc(cmdln.Cmdln):
|
||||
args = slash_split(args)
|
||||
|
||||
if not args or len(args) < 3:
|
||||
print >>sys.stderr, 'Incorrect number of argument.'
|
||||
self.do_help([None, 'aggregatepac'])
|
||||
return 2
|
||||
raise oscerr.WrongArgs('Incorrect number of arguments.\n\n' \
|
||||
+ self.get_cmd_help('aggregatepac'))
|
||||
|
||||
src_project = args[0]
|
||||
src_package = args[1]
|
||||
@ -595,9 +629,8 @@ class Osc(cmdln.Cmdln):
|
||||
args = slash_split(args)
|
||||
|
||||
if not args or len(args) < 3:
|
||||
print >>sys.stderr, 'Incorrect number of argument.'
|
||||
self.do_help([None, 'copypac'])
|
||||
return 2
|
||||
raise oscerr.WrongArgs('Incorrect number of arguments.\n\n' \
|
||||
+ self.get_cmd_help('copypac'))
|
||||
|
||||
src_project = args[0]
|
||||
src_package = args[1]
|
||||
@ -616,8 +649,7 @@ class Osc(cmdln.Cmdln):
|
||||
if src_project == dst_project and \
|
||||
src_package == dst_package and \
|
||||
src_apiurl == dst_apiurl:
|
||||
print >>sys.stderr, 'Error: source and destination are the same.'
|
||||
return 1
|
||||
raise oscerr.WrongArgs('Source and destination are the same.')
|
||||
|
||||
if src_apiurl != dst_apiurl:
|
||||
opts.client_side_copy = True
|
||||
@ -679,7 +711,6 @@ class Osc(cmdln.Cmdln):
|
||||
specfile = None
|
||||
pacs = findpacs(args)
|
||||
for p in pacs:
|
||||
|
||||
p.read_meta_from_spec(specfile)
|
||||
p.update_package_meta()
|
||||
|
||||
@ -823,24 +854,22 @@ class Osc(cmdln.Cmdln):
|
||||
rev, expand_link=opts.expand_link, prj_dir=project)
|
||||
|
||||
elif project:
|
||||
if not os.path.exists(project):
|
||||
if meta_exists(metatype='prj', path_args=quote_plus(project), create_new=False):
|
||||
if os.path.exists(project):
|
||||
sys.exit('osc: project \'%s\' already exists' % project)
|
||||
|
||||
# check if the project does exist (show_project_meta will throw an exception)
|
||||
show_project_meta(conf.config['apiurl'], project)
|
||||
|
||||
init_project_dir(conf.config['apiurl'], project, project)
|
||||
print statfrmt('A', project)
|
||||
else:
|
||||
print >>sys.stderr, 'osc: project \'%s\' does not exist on the server' % project
|
||||
sys.exit(1)
|
||||
else:
|
||||
print >>sys.stderr, 'osc: project \'%s\' already exists' % project
|
||||
sys.exit(1)
|
||||
|
||||
# all packages
|
||||
for package in meta_get_packagelist(conf.config['apiurl'], project):
|
||||
checkout_package(conf.config['apiurl'], project, package,
|
||||
expand_link=opts.expand_link, prj_dir=project)
|
||||
else:
|
||||
print >>sys.stderr, 'Missing argument.'
|
||||
self.do_help([None, 'checkout'])
|
||||
return 2
|
||||
raise oscerr.WrongArgs('Missing argument.\n\n' \
|
||||
+ self.get_cmd_help('checkout'))
|
||||
|
||||
|
||||
@cmdln.option('-v', '--verbose', action='store_true',
|
||||
@ -897,8 +926,8 @@ class Osc(cmdln.Cmdln):
|
||||
elif os.path.isfile(arg):
|
||||
pacpaths.append(arg)
|
||||
else:
|
||||
print >>sys.stderr, 'osc: error: \'%s\' is neither a project or a package directory' % arg
|
||||
return 1
|
||||
msg = '\'%s\' is neither a project or a package directory' % arg
|
||||
raise oscerr.NoWorkingCopy, msg
|
||||
lines = []
|
||||
# process single packages
|
||||
lines = getStatus(findpacs(pacpaths), None, opts.verbose)
|
||||
@ -917,9 +946,8 @@ class Osc(cmdln.Cmdln):
|
||||
${cmd_option_list}
|
||||
"""
|
||||
if not args:
|
||||
print >>sys.stderr, 'Missing argument.'
|
||||
self.do_help([None, 'add'])
|
||||
return 2
|
||||
raise oscerr.WrongArgs('Missing argument.\n\n' \
|
||||
+ self.get_cmd_help('add'))
|
||||
|
||||
filenames = parseargs(args)
|
||||
#print filenames
|
||||
@ -938,8 +966,8 @@ class Osc(cmdln.Cmdln):
|
||||
sys.exit(1)
|
||||
|
||||
if len(args) != 1:
|
||||
print >>sys.stderr, 'wrong number of arguments!'
|
||||
sys.exit(1)
|
||||
raise oscerr.WrongArgs('Wrong number of arguments.')
|
||||
|
||||
createPackageDir(args[0])
|
||||
|
||||
|
||||
@ -1098,8 +1126,8 @@ class Osc(cmdln.Cmdln):
|
||||
if (opts.expand_link and opts.unexpand_link) \
|
||||
or (opts.expand_link and opts.revision) \
|
||||
or (opts.unexpand_link and opts.revision):
|
||||
sys.exit('The options --expand-link, --unexpand-link and '
|
||||
'--revision are mutually exclusive')
|
||||
raise oscerr.WrongOptions('Sorry, the options --expand-link, --unexpand-link and '
|
||||
'--revision are mutually exclusive.')
|
||||
|
||||
if opts.revision and ( len(args) == 1):
|
||||
rev, dummy = parseRevisionOption(opts.revision)
|
||||
@ -1140,9 +1168,8 @@ class Osc(cmdln.Cmdln):
|
||||
"""
|
||||
|
||||
if not args:
|
||||
print >>sys.stderr, 'Missing argument.'
|
||||
self.do_help([None, 'delete'])
|
||||
return 2
|
||||
raise oscerr.WrongArgs('Missing argument.\n\n' \
|
||||
+ self.get_cmd_help('delete'))
|
||||
|
||||
args = parseargs(args)
|
||||
# check if args contains a package which was removed by
|
||||
@ -1199,9 +1226,8 @@ class Osc(cmdln.Cmdln):
|
||||
"""
|
||||
|
||||
if not args:
|
||||
print >>sys.stderr, 'Missing argument.'
|
||||
self.do_help([None, 'resolved'])
|
||||
return 2
|
||||
raise oscerr.WrongArgs('Missing argument.\n\n' \
|
||||
+ self.get_cmd_help('resolved'))
|
||||
|
||||
args = parseargs(args)
|
||||
pacs = findpacs(args)
|
||||
@ -1296,12 +1322,8 @@ class Osc(cmdln.Cmdln):
|
||||
else:
|
||||
wd = os.curdir
|
||||
|
||||
try:
|
||||
project = store_read_project(wd)
|
||||
apiurl = store_read_apiurl(wd)
|
||||
except:
|
||||
print >>sys.stderr, '\'%s\' is neither an osc project or package directory' % wd
|
||||
return 1
|
||||
|
||||
print '\n'.join(get_prj_results(apiurl, project, show_legend=opts.legend, csv=opts.csv))
|
||||
|
||||
@ -1344,11 +1366,9 @@ class Osc(cmdln.Cmdln):
|
||||
"""
|
||||
args = slash_split(args)
|
||||
if len(args) < 4:
|
||||
print >>sys.stderr, "too few arguments"
|
||||
sys.exit(1)
|
||||
raise oscerr.WrongArgs('Too few arguments.')
|
||||
elif len(args) > 4:
|
||||
print >>sys.stderr, "too many arguments"
|
||||
sys.exit(1)
|
||||
raise oscerr.WrongArgs('Too many arguments.')
|
||||
|
||||
print_buildlog(conf.config['apiurl'], *args)
|
||||
|
||||
@ -1385,12 +1405,11 @@ class Osc(cmdln.Cmdln):
|
||||
apiurl = store_read_apiurl(wd)
|
||||
|
||||
if args is None or len(args) < 2:
|
||||
print >>sys.stderr, 'Missing argument.'
|
||||
print 'Valid arguments for this package are:'
|
||||
print
|
||||
self.do_repos(None, None)
|
||||
print
|
||||
return 2
|
||||
raise oscerr.WrongArgs('Missing argument')
|
||||
|
||||
platform = args[0]
|
||||
arch = args[1]
|
||||
@ -1450,10 +1469,6 @@ class Osc(cmdln.Cmdln):
|
||||
"""
|
||||
|
||||
args = parseargs(args)
|
||||
for arg in args:
|
||||
if not is_project_dir(arg) and not is_package_dir(arg):
|
||||
print >>sys.stderr, '\'%s\' is neither a package dir nor a project dir' % arg
|
||||
args.remove(arg)
|
||||
|
||||
for arg in args:
|
||||
for platform in get_repos_of_project(store_read_apiurl(arg), store_read_project(arg)):
|
||||
@ -1532,25 +1547,22 @@ class Osc(cmdln.Cmdln):
|
||||
return 1
|
||||
|
||||
if len(args) == 2:
|
||||
print >>sys.stderr, 'Missing argument: build description (spec of dsc file)'
|
||||
return 2
|
||||
raise oscerr.WrongArgs('Missing argument: build description (spec of dsc file)')
|
||||
|
||||
elif len(args) < 2:
|
||||
print
|
||||
print >>sys.stderr, 'Missing argument.'
|
||||
print 'Valid arguments are:'
|
||||
print 'you have to choose a repo to build on'
|
||||
print 'possible repositories on this machine are:'
|
||||
print
|
||||
# we are going to raise an error for this, but first look up some helpful details:
|
||||
msg= ['You have to choose a repo to build on.']
|
||||
msg.append('Possible repositories on this machine are:\n')
|
||||
for platform in get_repos_of_project(store_read_apiurl(os.curdir),
|
||||
store_read_project(os.curdir)):
|
||||
arch = platform.split()[1] # arch
|
||||
if arch == osc.build.hostarch or \
|
||||
arch in osc.build.can_also_build.get(osc.build.hostarch, []):
|
||||
print platform.strip()
|
||||
return 2
|
||||
msg.append(platform.strip())
|
||||
raise oscerr.WrongArgs('Missing argument.\n\n' + '\n'.join(msg))
|
||||
|
||||
elif len(args) > 3:
|
||||
print >>sys.stderr, 'too many arguments'
|
||||
return 2
|
||||
raise oscerr.WrongArgs('Too many arguments')
|
||||
|
||||
if opts.prefer_pkgs:
|
||||
for d in opts.prefer_pkgs:
|
||||
@ -1634,9 +1646,7 @@ class Osc(cmdln.Cmdln):
|
||||
args = slash_split(args)
|
||||
|
||||
if len(args) < 1:
|
||||
print >>sys.stderr, 'Missing argument.'
|
||||
#self.do_help([None, 'rebuildpac'])
|
||||
return 2
|
||||
raise oscerr.WrongArgs('Missing argument.')
|
||||
|
||||
package = repo = arch = code = None
|
||||
project = args[0]
|
||||
@ -1687,8 +1697,7 @@ class Osc(cmdln.Cmdln):
|
||||
"""
|
||||
|
||||
if len(args) < 1:
|
||||
print >>sys.stderr, 'Missing <project> argument'
|
||||
return 2
|
||||
raise oscerr.WrongArgs('Missing <project> argument.')
|
||||
|
||||
if len(args) == 2:
|
||||
package = args[1]
|
||||
@ -1722,8 +1731,7 @@ class Osc(cmdln.Cmdln):
|
||||
args = slash_split(args)
|
||||
|
||||
if len(args) < 1:
|
||||
print >>sys.stderr, 'Missing <project> argument'
|
||||
return 2
|
||||
raise oscerr.WrongArgs('Missing <project> argument.')
|
||||
|
||||
if len(args) == 2:
|
||||
package = args[1]
|
||||
@ -1773,11 +1781,9 @@ class Osc(cmdln.Cmdln):
|
||||
"""
|
||||
|
||||
if len(args) > 1:
|
||||
print >>sys.stderr, 'too many arguments'
|
||||
sys.exit(1)
|
||||
raise oscerr.WrongArgs('Too many arguments.')
|
||||
elif len(args) < 1:
|
||||
print >>sys.stderr, 'too few arguments'
|
||||
sys.exit(1)
|
||||
raise oscerr.WrongArgs('Too few arguments.')
|
||||
|
||||
search_list = []
|
||||
search_for = []
|
||||
@ -1872,10 +1878,6 @@ class Osc(cmdln.Cmdln):
|
||||
else:
|
||||
project_dir = os.curdir
|
||||
|
||||
if not is_project_dir(project_dir):
|
||||
print >>sys.stderr, 'project dir \'%s\' does not exist' % project_dir
|
||||
sys.exit(1)
|
||||
else:
|
||||
if conf.config['do_package_tracking']:
|
||||
project = Project(project_dir)
|
||||
else:
|
||||
@ -1999,34 +2001,13 @@ class Osc(cmdln.Cmdln):
|
||||
if opts.headers:
|
||||
opts.headers = dict(opts.headers)
|
||||
|
||||
try:
|
||||
r = http_request(opts.method,
|
||||
url,
|
||||
data=opts.data,
|
||||
file=opts.file,
|
||||
headers=opts.headers)
|
||||
|
||||
except urllib2.HTTPError, e:
|
||||
if e.code in [400, 404]:
|
||||
print >>sys.stderr, e
|
||||
print >>sys.stderr, e.read()
|
||||
sys.exit(1)
|
||||
elif e.code == 500:
|
||||
print >>sys.stderr, e
|
||||
# this may be unhelpful... because it may just print a big blob of uninteresting
|
||||
# ichain html and javascript... however it could potentially be useful if the orign
|
||||
# server returns an information body
|
||||
if conf.config['http_debug']:
|
||||
print >>sys.stderr, e.read()
|
||||
sys.exit(1)
|
||||
else:
|
||||
sys.exit('unexpected error')
|
||||
|
||||
try:
|
||||
out = r.read()
|
||||
except:
|
||||
sys.exit('failed to read from file object')
|
||||
|
||||
sys.stdout.write(out)
|
||||
|
||||
|
||||
@ -2060,7 +2041,7 @@ class Osc(cmdln.Cmdln):
|
||||
prj = args[0]
|
||||
pac = args[1]
|
||||
else:
|
||||
sys.exit('wrong argument count')
|
||||
raise oscerr.WrongArgs('I need at least one argument.')
|
||||
|
||||
maintainers = []
|
||||
|
||||
@ -2107,8 +2088,7 @@ class Osc(cmdln.Cmdln):
|
||||
|
||||
args = slash_split(args)
|
||||
if len(args) != 3:
|
||||
print >>sys.stderr, 'error - incorrect number of arguments'
|
||||
sys.exit(1)
|
||||
raise oscerr.WrongArgs('Wrong number of arguments.')
|
||||
rev, dummy = parseRevisionOption(opts.revision)
|
||||
|
||||
import tempfile
|
||||
|
83
osc/conf.py
83
osc/conf.py
@ -33,6 +33,7 @@ The configuration dictionary could look like this:
|
||||
"""
|
||||
|
||||
import ConfigParser
|
||||
from osc import oscerr
|
||||
|
||||
# being global to this module, this dict can be accessed from outside
|
||||
# it will hold the parsed configuration
|
||||
@ -55,12 +56,15 @@ DEFAULTS = { 'apisrv': 'https://api.opensuse.org/',
|
||||
'%(scheme)s://%(apisrv)s/build/%(project)s/%(repository)s/%(buildarch)s/_repository/%(name)s',
|
||||
],
|
||||
|
||||
'debug': '0',
|
||||
'http_debug': '0',
|
||||
'traceback': '0',
|
||||
'post_mortem': '0',
|
||||
'cookiejar': '~/.osc_cookiejar',
|
||||
# disable project tracking by default
|
||||
'do_package_tracking': '0',
|
||||
}
|
||||
boolean_opts = ['http_debug', 'do_package_tracking']
|
||||
boolean_opts = ['debug', 'do_package_tracking', 'http_debug', 'post_mortem', 'traceback']
|
||||
|
||||
new_conf_template = """
|
||||
[general]
|
||||
@ -80,9 +84,18 @@ new_conf_template = """
|
||||
# /srv/oscbuild/%%(repo)s-%%(arch)s
|
||||
#build-root = %(build-root)s
|
||||
|
||||
# show info useful for debugging
|
||||
#debug = 1
|
||||
|
||||
# show HTTP traffic useful for debugging
|
||||
#http_debug = 1
|
||||
|
||||
# jump into the debugger in case of errors
|
||||
#post_mortem = 1
|
||||
|
||||
# print call traces in case of errors
|
||||
#traceback = 1
|
||||
|
||||
[%(apisrv)s]
|
||||
user = %(user)s
|
||||
pass = %(pass)s
|
||||
@ -192,9 +205,42 @@ def get_configParser(conffile=None, force_read=False):
|
||||
return get_configParser.cp
|
||||
|
||||
|
||||
def write_config(conffile, entries, custom_template = None, force = False):
|
||||
"""
|
||||
write osc's configuration file. entries is a dict which contains values
|
||||
for the config file (e.g. { 'user' : 'username', 'pass' : 'password' } ).
|
||||
custom_template is an optional configuration template. Use force=True if you
|
||||
want to overwrite an existing configuration file.
|
||||
"""
|
||||
import os
|
||||
conf_template = custom_template or new_conf_template
|
||||
config = DEFAULTS.copy()
|
||||
config.update(entries)
|
||||
if force or not os.path.exists(conffile):
|
||||
file = None
|
||||
try:
|
||||
file = open(conffile, 'w')
|
||||
except IOError, e:
|
||||
raise oscerr.OscIOError(e, 'cannot open configfile \'%s\'' % conffile)
|
||||
try:
|
||||
try:
|
||||
os.chmod(conffile, 0600)
|
||||
file.write(conf_template % config)
|
||||
except IOError, e:
|
||||
raise oscerr.OscIOError(e, 'cannot write configfile \'s\'' % conffile)
|
||||
finally:
|
||||
if file: file.close()
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def get_config(override_conffile = None,
|
||||
override_apisrv = None,
|
||||
override_debug = None,
|
||||
override_http_debug = None,
|
||||
override_apisrv = None):
|
||||
override_traceback = None,
|
||||
override_post_mortem = None):
|
||||
"""do the actual work (see module documentation)"""
|
||||
import os
|
||||
import sys
|
||||
@ -223,23 +269,8 @@ def get_config(override_conffile = None,
|
||||
netrc.netrc().authenticators(netrc_host)
|
||||
print >>sys.stderr, 'Read credentials from %s.' % os.path.expanduser('~/.netrc')
|
||||
except (IOError, TypeError, netrc.NetrcParseError):
|
||||
#
|
||||
# last resort... ask the user
|
||||
#
|
||||
import getpass
|
||||
print >>sys.stderr, account_not_configured_text % conffile
|
||||
config['user'] = raw_input('Username: ')
|
||||
config['pass'] = getpass.getpass()
|
||||
|
||||
print >>sys.stderr, 'Creating osc configuration file %s ...' % conffile
|
||||
fd = open(conffile, 'w')
|
||||
os.chmod(conffile, 0600)
|
||||
fd.write(new_conf_template % config)
|
||||
fd.close()
|
||||
print >>sys.stderr, 'done.'
|
||||
#print >>sys.stderr, ('Now re-run the command.')
|
||||
#sys.exit(0)
|
||||
|
||||
raise oscerr.NoConfigfile(conffile, \
|
||||
account_not_configured_text % conffile)
|
||||
|
||||
# okay, we made sure that .oscrc exists
|
||||
|
||||
@ -247,9 +278,9 @@ def get_config(override_conffile = None,
|
||||
|
||||
if not cp.has_section('general'):
|
||||
# FIXME: it might be sufficient to just assume defaults?
|
||||
print >>sys.stderr, config_incomplete_text % conffile
|
||||
print >>sys.stderr, new_conf_template % DEFAULTS
|
||||
sys.exit(1)
|
||||
msg = config_incomplete_text % conffile
|
||||
msg += new_conf_template % DEFAULTS
|
||||
raise oscerr.ConfigError(msg)
|
||||
|
||||
config = dict(cp.items('general', raw=1))
|
||||
|
||||
@ -263,7 +294,7 @@ def get_config(override_conffile = None,
|
||||
else:
|
||||
config[i] = False
|
||||
except:
|
||||
sys.exit('option %s requires an integer value' % i)
|
||||
raise oscerr.ConfigError('option %s requires an integer value' % i)
|
||||
|
||||
packagecachedir = os.path.expanduser(config['packagecachedir'])
|
||||
|
||||
@ -283,8 +314,14 @@ def get_config(override_conffile = None,
|
||||
config['auth_dict'] = auth_dict
|
||||
|
||||
# override values which we were called with
|
||||
if override_debug:
|
||||
config['debug'] = override_debug
|
||||
if override_http_debug:
|
||||
config['http_debug'] = override_http_debug
|
||||
if override_traceback:
|
||||
config['traceback'] = override_traceback
|
||||
if override_post_mortem:
|
||||
config['post_mortem'] = override_post_mortem
|
||||
if override_apisrv:
|
||||
config['scheme'], config['apisrv'] = \
|
||||
parse_apisrv_url(config['scheme'], override_apisrv)
|
||||
|
178
osc/core.py
178
osc/core.py
@ -14,6 +14,7 @@ from urllib import pathname2url, quote_plus, urlencode
|
||||
from urlparse import urlsplit, urlunsplit
|
||||
from cStringIO import StringIO
|
||||
import shutil
|
||||
import oscerr
|
||||
import conf
|
||||
try:
|
||||
from xml.etree import cElementTree as ET
|
||||
@ -252,8 +253,8 @@ class Project:
|
||||
|
||||
if conf.config['do_package_tracking'] and pac in self.pacs_unvers:
|
||||
# pac is not under version control but a local file/dir exists
|
||||
print 'can\'t add package \'%s\': Object already exists' % pac
|
||||
sys.exit(1)
|
||||
msg = 'can\'t add package \'%s\': Object already exists' % pac
|
||||
raise oscerr.PackageExists(self.name, pac, msg)
|
||||
else:
|
||||
print 'checking out new package %s' % pac
|
||||
checkout_package(self.apiurl, self.name, pac, \
|
||||
@ -318,7 +319,7 @@ class Project:
|
||||
self.new_package_entry(pac, 'A')
|
||||
self.write_packages()
|
||||
# sometimes the new pac doesn't exist in the list because
|
||||
# it would take too much time to update all data structs regulary
|
||||
# it would take too much time to update all data structs regularly
|
||||
if pac in self.pacs_unvers:
|
||||
self.pacs_unvers.remove(pac)
|
||||
return True
|
||||
@ -345,9 +346,7 @@ class Project:
|
||||
pac.delete_storefile(file)
|
||||
# this is not really necessary
|
||||
pac.put_on_deletelist(file)
|
||||
print statfrmt('D', os.path.join(pac.dir, file))
|
||||
#print os.path.dirname(pac.dir)
|
||||
# some black path vodoo
|
||||
print statfrmt('D', getTransActPath(os.path.join(pac.dir, file)))
|
||||
print statfrmt('D', getTransActPath(os.path.join(pac.dir, os.pardir, pac.name)))
|
||||
pac.write_deletelist()
|
||||
self.set_state(pac.name, 'D')
|
||||
@ -372,6 +371,9 @@ class Project:
|
||||
for pac in pacs:
|
||||
Package(os.path.join(self.dir, pac)).update()
|
||||
else:
|
||||
# we need to make sure that the _packages file will be written (even if an exception
|
||||
# occurs)
|
||||
try:
|
||||
# update complete project
|
||||
# packages which no longer exists upstream
|
||||
upstream_del = [ pac for pac in self.pacs_have if not pac in self.pacs_available and self.get_state(pac) != 'A']
|
||||
@ -416,8 +418,8 @@ class Project:
|
||||
Package(os.path.join(self.dir, pac)).update()
|
||||
elif state == 'A' and pac in self.pacs_available:
|
||||
# file/dir called pac already exists and is under version control
|
||||
print 'can\'t add package \'%s\': Object already exists' % pac
|
||||
sys.exit(1)
|
||||
msg = 'can\'t add package \'%s\': Object already exists' % pac
|
||||
raise oscerr.PackageExists(self.name, pac, msg)
|
||||
elif state == 'A':
|
||||
# do nothing
|
||||
pass
|
||||
@ -425,10 +427,12 @@ class Project:
|
||||
print 'unexpected state.. package \'%s\'' % pac
|
||||
|
||||
self.checkout_missing_pacs()
|
||||
finally:
|
||||
self.write_packages()
|
||||
|
||||
def commit(self, pacs = (), msg = '', files = {}):
|
||||
if len(pacs):
|
||||
try:
|
||||
for pac in pacs:
|
||||
todo = []
|
||||
if files.has_key(pac):
|
||||
@ -452,24 +456,25 @@ class Project:
|
||||
print 'osc: \'%s\' package not found' % pac
|
||||
elif state == None:
|
||||
self.commitExtPackage(pac, msg, todo)
|
||||
finally:
|
||||
self.write_packages()
|
||||
else:
|
||||
# if we have packages marked as '!' we cannot commit
|
||||
for pac in self.pacs_broken:
|
||||
if self.get_state(pac) != 'D':
|
||||
print 'commit failed: package \'%s\' is missing' % pac
|
||||
sys.exit(1)
|
||||
msg = 'commit failed: package \'%s\' is missing' % pac
|
||||
raise oscerr.PackageMissing(self.name, pac, msg)
|
||||
try:
|
||||
for pac in self.pacs_have:
|
||||
state = self.get_state(pac)
|
||||
if state == ' ':
|
||||
# do a simple commit
|
||||
try:
|
||||
Package(os.path.join(self.dir, pac)).commit(msg)
|
||||
except SystemExit:
|
||||
pass
|
||||
elif state == 'D':
|
||||
self.commitDelPackage(pac)
|
||||
elif state == 'A':
|
||||
self.commitNewPackage(pac, msg)
|
||||
finally:
|
||||
self.write_packages()
|
||||
|
||||
def commitNewPackage(self, pac, msg = '', files = []):
|
||||
@ -677,10 +682,7 @@ class Package:
|
||||
else:
|
||||
upstream_rev = show_upstream_rev(self.apiurl, self.prjname, self.name)
|
||||
if self.rev != upstream_rev:
|
||||
print >>sys.stderr, 'Working copy \'%s\' is out of date (rev %s vs rev %s).' \
|
||||
% (self.absdir, self.rev, upstream_rev)
|
||||
print >>sys.stderr, 'Looks as if you need to update it first.'
|
||||
sys.exit(1)
|
||||
raise oscerr.WorkingCopyOutdated((self.absdir, self.rev, upstream_rev))
|
||||
|
||||
if not self.todo:
|
||||
self.todo = self.filenamelist_unvers + self.filenamelist
|
||||
@ -1247,6 +1249,8 @@ def slash_split(l):
|
||||
|
||||
|
||||
def findpacs(files):
|
||||
"""collect Package objects belonging to the given files
|
||||
and make sure each Package is returned only once"""
|
||||
pacs = []
|
||||
for f in files:
|
||||
p = filedir_to_pac(f)
|
||||
@ -1287,13 +1291,21 @@ def read_inconflict(dir):
|
||||
|
||||
|
||||
def parseargs(list_of_args):
|
||||
"""Convenience method osc's commandline argument parsing.
|
||||
|
||||
If called with an empty tuple (or list), return a list containing the current directory.
|
||||
Otherwise, return a list of the arguments."""
|
||||
if list_of_args:
|
||||
return list(list_of_args)
|
||||
else:
|
||||
return [ os.curdir ]
|
||||
return [os.curdir]
|
||||
|
||||
|
||||
def filedir_to_pac(f):
|
||||
"""Takes a working copy path, or a path to a file inside a working copy,
|
||||
and returns a Package object instance
|
||||
|
||||
If the argument was a filename, add it onto the "todo" list of the Package """
|
||||
|
||||
if os.path.isdir(f):
|
||||
wd = f
|
||||
@ -1385,6 +1397,8 @@ def http_request(method, url, headers={}, data=None, file=None):
|
||||
else:
|
||||
raise
|
||||
|
||||
if conf.config['debug']: print method, url
|
||||
|
||||
try:
|
||||
fd = urllib2.urlopen(req, data=data)
|
||||
|
||||
@ -1453,8 +1467,8 @@ def check_store_version(dir):
|
||||
v = ''
|
||||
|
||||
if v == '':
|
||||
print >>sys.stderr, 'error: "%s" is not an osc working copy' % dir
|
||||
sys.exit(1)
|
||||
msg = 'Error: "%s" is not an osc working copy.' % os.path.abspath(dir)
|
||||
raise oscerr.NoWorkingCopy(msg)
|
||||
|
||||
if v != __version__:
|
||||
if v in ['0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '0.95', '0.96', '0.97', '0.98']:
|
||||
@ -1463,12 +1477,10 @@ def check_store_version(dir):
|
||||
f.write(__version__ + '\n')
|
||||
f.close()
|
||||
return
|
||||
print >>sys.stderr
|
||||
print >>sys.stderr, 'the osc metadata of your working copy "%s"' % dir
|
||||
print >>sys.stderr, 'has the wrong version (%s), should be %s' % (v, __version__)
|
||||
print >>sys.stderr, 'please do a fresh checkout'
|
||||
print >>sys.stderr
|
||||
sys.exit(1)
|
||||
msg = 'The osc metadata of your working copy "%s"' % dir
|
||||
msg += '\nhas the wrong version (%s), should be %s' % (v, __version__)
|
||||
msg += '\nPlease do a fresh checkout'
|
||||
raise oscerr.WorkingCopyWrongVersion, msg
|
||||
|
||||
|
||||
def meta_get_packagelist(apiurl, prj):
|
||||
@ -1523,22 +1535,23 @@ def show_project_conf(apiurl, prj):
|
||||
|
||||
|
||||
def show_package_meta(apiurl, prj, pac):
|
||||
try:
|
||||
url = makeurl(apiurl, ['source', prj, pac, '_meta'])
|
||||
try:
|
||||
f = http_GET(url)
|
||||
except urllib2.HTTPError, e:
|
||||
print >>sys.stderr, 'error getting meta for project \'%s\' package \'%s\'' % (prj, pac)
|
||||
print >>sys.stderr, e
|
||||
if e.code == 500:
|
||||
print >>sys.stderr, '\nDebugging output follows.\nurl:\n%s\nresponse:\n%s' % (url, e.read())
|
||||
sys.exit(1)
|
||||
return f.readlines()
|
||||
except urllib2.HTTPError, e:
|
||||
e.osc_msg = 'Error getting meta for project \'%s\' package \'%s\'' % (prj, pac)
|
||||
raise
|
||||
|
||||
|
||||
def show_pattern_metalist(apiurl, prj):
|
||||
url = makeurl(apiurl, ['source', prj, '_pattern'])
|
||||
try:
|
||||
f = http_GET(url)
|
||||
tree = ET.parse(f)
|
||||
except urllib2.HTTPError, e:
|
||||
e.osc_msg = 'show_pattern_metalist: Error getting pattern list for project \'%s\'' % prj
|
||||
raise
|
||||
r = [ node.get('name') for node in tree.getroot() ]
|
||||
r.sort()
|
||||
return r
|
||||
@ -1548,11 +1561,10 @@ def show_pattern_meta(apiurl, prj, pattern):
|
||||
url = makeurl(apiurl, ['source', prj, '_pattern', pattern])
|
||||
try:
|
||||
f = http_GET(url)
|
||||
except urllib2.HTTPError, e:
|
||||
print >>sys.stderr, 'error getting pattern \'%s\' for project \'%s\'' % (pattern, prj)
|
||||
print >>sys.stderr, e
|
||||
sys.exit(1)
|
||||
return f.readlines()
|
||||
except urllib2.HTTPError, e:
|
||||
e.osc_msg = 'show_pattern_meta: Error getting pattern \'%s\' for project \'%s\'' % (pattern, prj)
|
||||
raise
|
||||
|
||||
|
||||
class metafile:
|
||||
@ -1650,7 +1662,7 @@ def make_meta_url(metatype, path_args=None, apiurl=None):
|
||||
if not apiurl:
|
||||
apiurl = conf.config['apiurl']
|
||||
if metatype not in metatypes.keys():
|
||||
sys.exit('unknown metatype %s' % metatype)
|
||||
raise AttributeError('make_meta_url(): Unknown meta type \'%s\'' % metatype)
|
||||
path = metatypes[metatype]['path']
|
||||
|
||||
if path_args:
|
||||
@ -1742,8 +1754,8 @@ def read_meta_from_spec(specfile, *args):
|
||||
"""
|
||||
|
||||
if not os.path.isfile(specfile):
|
||||
print 'file \'%s\' is not a readable file' % specfile
|
||||
sys.exit(1)
|
||||
msg = 'File \'%s\' is not a readable file' % specfile
|
||||
raise oscerr.UnreadableFile, msg
|
||||
|
||||
try:
|
||||
lines = codecs.open(specfile, 'r', locale.getpreferredencoding()).readlines()
|
||||
@ -2192,10 +2204,9 @@ def checkout_package(apiurl, project, package,
|
||||
if not pathname:
|
||||
pathname = getTransActPath(os.path.join(prj_dir, package))
|
||||
|
||||
path = (quote_plus(project), quote_plus(package))
|
||||
if meta_exists(metatype='pkg', path_args=path, create_new=False, apiurl=apiurl) == None:
|
||||
print >>sys.stderr, 'error 404 - project or package does not exist'
|
||||
sys.exit(1)
|
||||
# before we create directories and stuff, check if the package actually
|
||||
# exists
|
||||
show_package_meta(apiurl, project, package)
|
||||
|
||||
if expand_link:
|
||||
# try to read from the linkinfo
|
||||
@ -2348,30 +2359,12 @@ def copy_pac(src_apiurl, src_project, src_package,
|
||||
|
||||
def delete_package(apiurl, prj, pac):
|
||||
u = makeurl(apiurl, ['source', prj, pac])
|
||||
try:
|
||||
http_DELETE(u)
|
||||
except urllib2.HTTPError, e:
|
||||
if e.code == 404:
|
||||
print >>sys.stderr, 'Package \'%s\' does not exist' % pac
|
||||
sys.exit(1)
|
||||
else:
|
||||
print >>sys.stderr, 'an unexpected error occured while deleting ' \
|
||||
'\'%s\'' % pac
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def delete_project(apiurl, prj):
|
||||
u = makeurl(apiurl, ['source', prj])
|
||||
try:
|
||||
http_DELETE(u)
|
||||
except urllib2.HTTPError, e:
|
||||
if e.code == 404:
|
||||
print >>sys.stderr, 'Package \'%s\' does not exist' % pac
|
||||
sys.exit(1)
|
||||
else:
|
||||
print >>sys.stderr, 'an unexpected error occured while deleting ' \
|
||||
'\'%s\'' % pac
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def get_platforms(apiurl):
|
||||
@ -2660,10 +2653,8 @@ def rebuild(apiurl, prj, package, repo, arch, code=None):
|
||||
try:
|
||||
f = http_POST(u)
|
||||
except urllib2.HTTPError, e:
|
||||
print >>sys.stderr, 'could not trigger rebuild for project \'%s\' package \'%s\'' % (prj, package)
|
||||
print >>sys.stderr, u
|
||||
print >>sys.stderr, e
|
||||
sys.exit(1)
|
||||
e.osc_msg = 'could not trigger rebuild for project \'%s\' package \'%s\'' % (prj, package)
|
||||
raise
|
||||
|
||||
root = ET.parse(f).getroot()
|
||||
return root.get('code')
|
||||
@ -2673,9 +2664,8 @@ def store_read_project(dir):
|
||||
try:
|
||||
p = open(os.path.join(dir, store, '_project')).readlines()[0].strip()
|
||||
except IOError:
|
||||
print >>sys.stderr, 'error: \'%s\' is not an osc project dir ' \
|
||||
'or working copy' % dir
|
||||
sys.exit(1)
|
||||
raise oscerr.NoWorkingCopy('Error: \'%s\' is not an osc project dir ' \
|
||||
'or working copy.' % os.path.abspath(dir))
|
||||
return p
|
||||
|
||||
|
||||
@ -2683,8 +2673,8 @@ def store_read_package(dir):
|
||||
try:
|
||||
p = open(os.path.join(dir, store, '_package')).readlines()[0].strip()
|
||||
except IOError:
|
||||
print >>sys.stderr, 'error: \'%s\' is not an osc working copy' % dir
|
||||
sys.exit(1)
|
||||
raise oscerr.NoWorkingCopy('error: \'%s\' is not an osc working copy' \
|
||||
% os.path.abspath(dir))
|
||||
return p
|
||||
|
||||
def store_read_apiurl(dir):
|
||||
@ -2727,17 +2717,15 @@ def abortbuild(apiurl, project, package=None, arch=None, repo=None):
|
||||
try:
|
||||
f = http_POST(u)
|
||||
except urllib2.HTTPError, e:
|
||||
err_str = 'abortion failed for project %s' % project
|
||||
e.osc_msg = 'abortion failed for project %s' % project
|
||||
if package:
|
||||
err_str += ' package %s' % package
|
||||
e.osc_msg += ' package %s' % package
|
||||
if arch:
|
||||
err_str += ' arch %s' % arch
|
||||
e.osc_msg += ' arch %s' % arch
|
||||
if repo:
|
||||
err_str += ' repo %s' % repo
|
||||
print >> sys.stderr, err_str
|
||||
print >> sys.stderr, u
|
||||
print >> sys.stderr, e
|
||||
sys.exit(1)
|
||||
e.osc_msg += ' repo %s' % repo
|
||||
raise
|
||||
|
||||
root = ET.parse(f).getroot()
|
||||
return root.get('code')
|
||||
|
||||
@ -2757,19 +2745,17 @@ def wipebinaries(apiurl, project, package=None, arch=None, repo=None, code=None)
|
||||
try:
|
||||
f = http_POST(u)
|
||||
except urllib2.HTTPError, e:
|
||||
err_str = 'wipe binary rpms failed for project %s' % project
|
||||
e.osc_msg = 'wipe binary rpms failed for project %s' % project
|
||||
if package:
|
||||
err_str += ' package %s' % package
|
||||
e.osc_msg += ' package %s' % package
|
||||
if arch:
|
||||
err_str += ' arch %s' % arch
|
||||
e.osc_msg += ' arch %s' % arch
|
||||
if repo:
|
||||
err_str += ' repository %s' % repo
|
||||
e.osc_msg += ' repository %s' % repo
|
||||
if code:
|
||||
err_str += ' code=%s' % code
|
||||
print >> sys.stderr, err_str
|
||||
print >> sys.stderr, u
|
||||
print >> sys.stderr, e
|
||||
sys.exit(1)
|
||||
e.osc_msg += ' code=%s' % code
|
||||
raise
|
||||
|
||||
root = ET.parse(f).getroot()
|
||||
return root.get('code')
|
||||
|
||||
@ -3061,22 +3047,6 @@ def is_srcrpm(f):
|
||||
else:
|
||||
return False
|
||||
|
||||
def delete_server_files(apiurl, prj, pac, files):
|
||||
"""
|
||||
This method deletes the given filelist on the
|
||||
server. No local data will be touched.
|
||||
"""
|
||||
|
||||
for file in files:
|
||||
try:
|
||||
u = makeurl(apiurl, ['source', prj, pac, file])
|
||||
http_DELETE(u)
|
||||
except:
|
||||
# we do not handle all exceptions here - we need another solution
|
||||
# see bug #280034
|
||||
print >>sys.stderr, 'error while deleting file \'%s\'' % file
|
||||
sys.exit(1)
|
||||
|
||||
def addMaintainer(apiurl, prj, pac, user):
|
||||
""" add a new maintainer to a package or project """
|
||||
path = quote_plus(prj),
|
||||
|
91
osc/oscerr.py
Normal file
91
osc/oscerr.py
Normal file
@ -0,0 +1,91 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright (C) 2008 Peter Poeml / Novell Inc. All rights reserved.
|
||||
# This program is free software; it may be used, copied, modified
|
||||
# and distributed under the terms of the GNU General Public Licence,
|
||||
# either version 2, or (at your option) any later version.
|
||||
|
||||
|
||||
|
||||
class OscBaseError(Exception):
|
||||
def __init__(self, args=()):
|
||||
Exception.__init__(self)
|
||||
self.args = args
|
||||
|
||||
class ConfigError(OscBaseError):
|
||||
"""Exception raised when there is an error in the config file"""
|
||||
def __init__(self, msg):
|
||||
OscBaseError.__init__(self)
|
||||
self.msg = msg
|
||||
|
||||
class NoConfigfile(OscBaseError):
|
||||
"""Exception raised when osc's configfile cannot be found"""
|
||||
def __init__(self, fname, msg):
|
||||
OscBaseError.__init__(self)
|
||||
self.file = fname
|
||||
self.msg = msg
|
||||
|
||||
class WrongArgs(OscBaseError):
|
||||
"""Exception raised by the cli for wrong arguments usage"""
|
||||
|
||||
class WrongOptions(OscBaseError):
|
||||
"""Exception raised by the cli for wrong option usage"""
|
||||
#def __str__(self):
|
||||
# s = 'Sorry, wrong options.'
|
||||
# if self.args:
|
||||
# s += '\n' + self.args
|
||||
# return s
|
||||
|
||||
class NoWorkingCopy(OscBaseError):
|
||||
"""Exception raised when directory is neither a project dir nor a package dir"""
|
||||
|
||||
class WorkingCopyWrongVersion(OscBaseError):
|
||||
"""Exception raised when working copy's .osc/_osclib_version doesn't match"""
|
||||
|
||||
class WorkingCopyOutdated(OscBaseError):
|
||||
"""Exception raised when the working copy is outdated.
|
||||
It takes a tuple with three arguments: path to wc,
|
||||
revision that it has, revision that it should have.
|
||||
"""
|
||||
def __str__(self):
|
||||
return ('Working copy \'%s\' is out of date (rev %s vs rev %s).\n'
|
||||
'Looks as if you need to update it first.' \
|
||||
% (self[0], self[1], self[2]))
|
||||
|
||||
|
||||
class UnreadableFile(OscBaseError):
|
||||
def __init__(self, msg):
|
||||
OscBaseError.__init__(self)
|
||||
self.msg = msg
|
||||
|
||||
class OscIOError(OscBaseError):
|
||||
def __init__(self, e, msg):
|
||||
OscBaseError.__init__(self)
|
||||
self.e = e
|
||||
self.msg = msg
|
||||
|
||||
class SignalInterrupt(Exception):
|
||||
"""Exception raised on SIGTERM and SIGHUP."""
|
||||
|
||||
class PackageError(OscBaseError):
|
||||
"""Base class for all Package related exceptions"""
|
||||
def __init__(self, prj, pac):
|
||||
OscBaseError.__init__(self)
|
||||
self.prj = prj
|
||||
self.pac = pac
|
||||
|
||||
class PackageExists(PackageError):
|
||||
"""
|
||||
Exception raised when a local object already exists
|
||||
"""
|
||||
def __init__(self, prj, pac, msg):
|
||||
PackageError.__init__(self, prj, pac)
|
||||
self.msg = msg
|
||||
|
||||
class PackageMissing(PackageError):
|
||||
"""
|
||||
Exception raised when a local object doesn't exist
|
||||
"""
|
||||
def __init__(self, prj, pac, msg):
|
||||
PackageError.__init__(self, prj, pac)
|
||||
self.msg = msg
|
Loading…
x
Reference in New Issue
Block a user