mirror of
https://github.com/openSUSE/osc.git
synced 2025-03-03 22:52:10 +01:00
- rewrite configuration handling
- move all configuration code into module osc/conf.py - now, the API server can be configured in .oscrc with apisrv = ... - also, 'scheme' (http/https) is no longer a module variable but can be configured - all config is in DEFAULT - ignore vim swap files - use urllib() convenience wrapper in some functions that used urllib2.urlopen() and had their own error handling. Instead, it seems to make sense -- in the future-- to create our own errors and propagate them up, in cases where the error handling of urlopen() is too generic - rename get_slash_source() to meta_get_project_list() for consistency - show local time in get_buildhistory(), not UTC - rewrite help text of 'rebuildpac' command - allow to run commandline.py from the commandline (without the wrapper) - don't send a space when doing a POST request without body
This commit is contained in:
parent
5f8fc4e340
commit
39779ec9bc
@ -4,8 +4,5 @@
|
|||||||
# python module to be called within the source directory during development
|
# python module to be called within the source directory during development
|
||||||
|
|
||||||
from osc import commandline
|
from osc import commandline
|
||||||
from osc.core import init_basicauth
|
|
||||||
|
|
||||||
init_basicauth()
|
|
||||||
commandline.main()
|
commandline.main()
|
||||||
|
|
||||||
|
147
osc/build.py
147
osc/build.py
@ -9,52 +9,11 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import ConfigParser
|
|
||||||
import cElementTree as ET
|
import cElementTree as ET
|
||||||
from tempfile import NamedTemporaryFile
|
from tempfile import NamedTemporaryFile
|
||||||
from osc.fetch import *
|
from osc.fetch import *
|
||||||
|
import osc.conf
|
||||||
|
|
||||||
APISRV = 'api.opensuse.org'
|
|
||||||
|
|
||||||
DEFAULTS = { 'packagecachedir': '/var/tmp/osbuild-packagecache',
|
|
||||||
'su-wrapper': 'su -c',
|
|
||||||
'build-cmd': '/usr/bin/build',
|
|
||||||
'build-root': '/var/tmp/build-root',
|
|
||||||
|
|
||||||
# default list of download URLs, which will be tried in order
|
|
||||||
'urllist': [
|
|
||||||
# the normal repo server, redirecting to mirrors
|
|
||||||
'http://software.opensuse.org/download/%(project)s/%(repository)s/%(arch)s/%(filename)s',
|
|
||||||
# direct access to "full" tree
|
|
||||||
'http://api.opensuse.org/rpm/%(project)s/%(repository)s/_repository/%(buildarch)s/%(name)s',
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
text_config_incomplete = """
|
|
||||||
|
|
||||||
Your configuration is not complete.
|
|
||||||
Make sure that you have a [general] section in %%s:
|
|
||||||
(You can copy&paste it. Some commented defaults are shown.)
|
|
||||||
|
|
||||||
[general]
|
|
||||||
|
|
||||||
# Downloaded packages are cached here. Must be writable by you.
|
|
||||||
#packagecachedir: %(packagecachedir)s
|
|
||||||
|
|
||||||
# Wrapper to call build as root (sudo, su -, ...)
|
|
||||||
#su-wrapper: %(su-wrapper)s
|
|
||||||
|
|
||||||
# rootdir to setup the chroot environment
|
|
||||||
# can contain %%(repo)s and/or %%(arch)s for replacement
|
|
||||||
#build-root: %(build-root)s
|
|
||||||
|
|
||||||
|
|
||||||
Note:
|
|
||||||
Configuration can be overridden by envvars, e.g.
|
|
||||||
OSC_SU_WRAPPER overrides the setting of su-wrapper.
|
|
||||||
""" % DEFAULTS
|
|
||||||
|
|
||||||
change_personality = {
|
change_personality = {
|
||||||
'i686': 'linux32',
|
'i686': 'linux32',
|
||||||
@ -81,7 +40,14 @@ class Buildinfo:
|
|||||||
|
|
||||||
def __init__(self, filename):
|
def __init__(self, filename):
|
||||||
|
|
||||||
|
print filename
|
||||||
|
try:
|
||||||
tree = ET.parse(filename)
|
tree = ET.parse(filename)
|
||||||
|
except:
|
||||||
|
print 'could not parse the buildconfig:'
|
||||||
|
print open(filename).read()
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
root = tree.getroot()
|
root = tree.getroot()
|
||||||
|
|
||||||
if root.find('error') != None:
|
if root.find('error') != None:
|
||||||
@ -174,82 +140,6 @@ class Pac:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_build_conf():
|
|
||||||
auth_dict = { } # to hold multiple usernames and passwords
|
|
||||||
|
|
||||||
conffile = os.path.expanduser('~/.oscrc')
|
|
||||||
if not os.path.exists(conffile):
|
|
||||||
import netrc
|
|
||||||
|
|
||||||
try:
|
|
||||||
info = netrc.netrc()
|
|
||||||
username, account, password = info.authenticators(APISRV)
|
|
||||||
|
|
||||||
except (IOError, TypeError, netrc.NetrcParseError):
|
|
||||||
print >>sys.stderr, 'Error:'
|
|
||||||
print >>sys.stderr, 'You need to create ~/.oscrc.'
|
|
||||||
print >>sys.stderr, 'Running the osc command will do this for you.'
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
cf = open(conffile, 'w')
|
|
||||||
os.chmod(conffile, 0600)
|
|
||||||
print 'creating', conffile
|
|
||||||
cf.write("""
|
|
||||||
|
|
||||||
[general]
|
|
||||||
|
|
||||||
# Downloaded packages are cached here. Must be writable by you.
|
|
||||||
#packagecachedir: /var/tmp/osbuild-packagecache
|
|
||||||
|
|
||||||
# Wrapper to call build as root (sudo, su -, ...)
|
|
||||||
#su-wrapper: su -c
|
|
||||||
|
|
||||||
# rootdir to setup the chroot environment
|
|
||||||
# can contain %%(repo)s and/or %%(arch)s for replacement
|
|
||||||
#build-root: /var/tmp/build-root
|
|
||||||
|
|
||||||
|
|
||||||
[%s]
|
|
||||||
user: %s
|
|
||||||
pass: %s
|
|
||||||
""" % (APISRV, username, password))
|
|
||||||
cf.close()
|
|
||||||
|
|
||||||
|
|
||||||
config = ConfigParser.ConfigParser(DEFAULTS)
|
|
||||||
config.read(conffile)
|
|
||||||
|
|
||||||
|
|
||||||
if not config.has_section('general'):
|
|
||||||
# FIXME: it might be sufficient to just assume defaults?
|
|
||||||
print >>sys.stderr, text_config_incomplete % conffile
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
for host in [ x for x in config.sections() if x != 'general' ]:
|
|
||||||
auth_dict[host] = dict(config.items(host))
|
|
||||||
|
|
||||||
|
|
||||||
config = dict(config.items('general', raw=1))
|
|
||||||
|
|
||||||
# make it possible to override configuration of the rc file
|
|
||||||
for var in ['OSC_PACKAGECACHEDIR', 'OSC_SU_WRAPPER', 'BUILD_ROOT', 'OSC_BUILD_ROOT']:
|
|
||||||
val = os.getenv(var)
|
|
||||||
if val:
|
|
||||||
if var.startswith('OSC_'): var = var[4:]
|
|
||||||
var = var.lower().replace('_', '-')
|
|
||||||
if config.has_key(var):
|
|
||||||
print 'Overriding config value for %s=\'%s\' with \'%s\'' % (var, config[var], val)
|
|
||||||
config[var] = val
|
|
||||||
|
|
||||||
# transform 'url1, url2, url3' form into a list
|
|
||||||
if type(config['urllist']) == str:
|
|
||||||
config['urllist'] = [ i.strip() for i in config['urllist'].split(',') ]
|
|
||||||
|
|
||||||
return config, auth_dict
|
|
||||||
|
|
||||||
|
|
||||||
def get_built_files(pacdir, pactype):
|
def get_built_files(pacdir, pactype):
|
||||||
if pactype == 'rpm':
|
if pactype == 'rpm':
|
||||||
b_built = os.popen('find %s -name *.rpm' \
|
b_built = os.popen('find %s -name *.rpm' \
|
||||||
@ -265,20 +155,29 @@ def get_built_files(pacdir, pactype):
|
|||||||
|
|
||||||
def main(argv):
|
def main(argv):
|
||||||
|
|
||||||
global config
|
from conf import config
|
||||||
config, auth = get_build_conf()
|
|
||||||
|
|
||||||
repo = argv[1]
|
repo = argv[1]
|
||||||
arch = argv[2]
|
arch = argv[2]
|
||||||
spec = argv[3]
|
spec = argv[3]
|
||||||
buildargs = []
|
buildargs = []
|
||||||
buildargs += argv[4:]
|
buildargs += argv[4:]
|
||||||
|
|
||||||
|
# make it possible to override configuration of the rc file
|
||||||
|
for var in ['OSC_PACKAGECACHEDIR', 'OSC_SU_WRAPPER', 'BUILD_ROOT', 'OSC_BUILD_ROOT']:
|
||||||
|
val = os.getenv(var)
|
||||||
|
if val:
|
||||||
|
if var.startswith('OSC_'): var = var[4:]
|
||||||
|
var = var.lower().replace('_', '-')
|
||||||
|
if config.has_key(var):
|
||||||
|
print 'Overriding config value for %s=\'%s\' with \'%s\'' % (var, config[var], val)
|
||||||
|
config[var] = val
|
||||||
|
|
||||||
|
|
||||||
config['build-root'] = config['build-root'] % {'repo': repo, 'arch': arch}
|
config['build-root'] = config['build-root'] % {'repo': repo, 'arch': arch}
|
||||||
|
|
||||||
if not os.path.exists(spec):
|
if not os.path.exists(spec):
|
||||||
print >>sys.stderr, 'Error: specfile \'%s\' does not exist.' % spec
|
sys.exit('Error: specfile \'%s\' does not exist.' % spec)
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
print 'Getting buildinfo from server'
|
print 'Getting buildinfo from server'
|
||||||
bi_file = NamedTemporaryFile(suffix='.xml', prefix='buildinfo.', dir = '/tmp')
|
bi_file = NamedTemporaryFile(suffix='.xml', prefix='buildinfo.', dir = '/tmp')
|
||||||
@ -292,7 +191,7 @@ def main(argv):
|
|||||||
print 'Updating cache of required packages'
|
print 'Updating cache of required packages'
|
||||||
fetcher = Fetcher(cachedir = config['packagecachedir'],
|
fetcher = Fetcher(cachedir = config['packagecachedir'],
|
||||||
urllist = config['urllist'],
|
urllist = config['urllist'],
|
||||||
auth_dict = auth)
|
auth_dict = config['auth_dict'])
|
||||||
# now update the package cache
|
# now update the package cache
|
||||||
fetcher.run(bi)
|
fetcher.run(bi)
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
|
|
||||||
from core import *
|
from core import *
|
||||||
|
import conf
|
||||||
|
|
||||||
usage_general = """\
|
usage_general = """\
|
||||||
usage: osc <subcommand> [options] [args]
|
usage: osc <subcommand> [options] [args]
|
||||||
@ -45,7 +45,7 @@ usage: osc ls # list projects
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if not args:
|
if not args:
|
||||||
print '\n'.join(get_slash_source())
|
print '\n'.join(meta_get_project_list())
|
||||||
elif len(args) == 1:
|
elif len(args) == 1:
|
||||||
project = args[0]
|
project = args[0]
|
||||||
print '\n'.join(meta_get_packagelist(project))
|
print '\n'.join(meta_get_packagelist(project))
|
||||||
@ -439,10 +439,7 @@ usage: osc ci # current dir
|
|||||||
osc ci file1 file2 ...
|
osc ci file1 file2 ...
|
||||||
"""
|
"""
|
||||||
|
|
||||||
init_basicauth()
|
|
||||||
|
|
||||||
args = parseargs(args)
|
args = parseargs(args)
|
||||||
|
|
||||||
pacs = findpacs(args)
|
pacs = findpacs(args)
|
||||||
|
|
||||||
for p in pacs:
|
for p in pacs:
|
||||||
@ -835,6 +832,12 @@ usage: 1. osc build <platform> <arch> <specfile> [--clean|--noinit]
|
|||||||
|
|
||||||
You may want to configure sudo with option NOPASSWD for /usr/bin/build
|
You may want to configure sudo with option NOPASSWD for /usr/bin/build
|
||||||
and set su-wrapper to 'sudo' in .oscrc.
|
and set su-wrapper to 'sudo' in .oscrc.
|
||||||
|
|
||||||
|
Note:
|
||||||
|
Configuration can be overridden by envvars, e.g.
|
||||||
|
OSC_SU_WRAPPER overrides the setting of su-wrapper.
|
||||||
|
BUILD_DIST or OSC_BUILD_DIST overrides the build target.
|
||||||
|
BUILD_ROOT or OSC_BUILD_ROOT overrides the build-root.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import osc.build
|
import osc.build
|
||||||
@ -895,9 +898,17 @@ usage: osc buildhistory <platform> <arch>
|
|||||||
|
|
||||||
|
|
||||||
def rebuildpac(args):
|
def rebuildpac(args):
|
||||||
"""rebuildpac: Triggers a package rebuild for all repositories/architectures of the package
|
"""rebuildpac: Causes a package to be rebuilt
|
||||||
|
|
||||||
usage: osc rebuildpac <project> <package> [<repo> [<arch>]]
|
usage: osc rebuildpac <project> <package> [<repo> [<arch>]]
|
||||||
|
|
||||||
|
With the optional <repo> and <arch> arguments, the rebuild can be limited
|
||||||
|
to a certain repository or architecture.
|
||||||
|
|
||||||
|
Note that it is normally NOT needed to kick off rebuilds like this, because
|
||||||
|
they principally happen in a fully automatic way, triggered by source
|
||||||
|
check-ins. In particular, the order in which packages are built is handled
|
||||||
|
by the build service.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if args is None or len(args) < 2:
|
if args is None or len(args) < 2:
|
||||||
@ -992,6 +1003,8 @@ cmd_dict = {
|
|||||||
def main():
|
def main():
|
||||||
"""handling of commandline arguments, and dispatching to subcommands"""
|
"""handling of commandline arguments, and dispatching to subcommands"""
|
||||||
|
|
||||||
|
conf.get_config()
|
||||||
|
|
||||||
# which subcommand?
|
# which subcommand?
|
||||||
if len(sys.argv) < 2:
|
if len(sys.argv) < 2:
|
||||||
print "Type 'osc help' for usage."
|
print "Type 'osc help' for usage."
|
||||||
@ -1018,6 +1031,7 @@ def main():
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
init_basicauth()
|
import sys, os.path
|
||||||
|
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
203
osc/conf.py
Normal file
203
osc/conf.py
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
# Copyright (C) 2006 Peter Poeml. 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.
|
||||||
|
|
||||||
|
"""Read osc configuration and store it in a dictionary
|
||||||
|
|
||||||
|
This module reads and parses ~/.oscrc. The resulting configuration is stored
|
||||||
|
for later usage in a dictionary named 'config'.
|
||||||
|
|
||||||
|
In the absence of .oscrc, it tries .netrc.
|
||||||
|
If information is missing, it asks the user questions.
|
||||||
|
|
||||||
|
After reading the config, urllib2 is initialized.
|
||||||
|
|
||||||
|
The configuration dictionary could look like this:
|
||||||
|
|
||||||
|
{'apisrv': 'api.opensuse.org',
|
||||||
|
'scheme': 'http',
|
||||||
|
'user': 'poeml',
|
||||||
|
'pass': 'secret',
|
||||||
|
'auth_dict': {'api.opensuse.org': {'user': 'poeml', 'pass': 'secret'},
|
||||||
|
'apitest.opensuse.org': {'user': 'poeml', 'pass': 'secret'},
|
||||||
|
'foo.opensuse.org': {'user': 'foo', 'pass': 'foo'}},
|
||||||
|
'build-cmd': '/usr/bin/build',
|
||||||
|
'build-root': '/abuild/oscbuild-%(repo)s-%(arch)s',
|
||||||
|
'packagecachedir': '/var/cache/osbuild',
|
||||||
|
'su-wrapper': 'sudo',
|
||||||
|
'urllist': ['http://software.opensuse.org/download/%(project)s/%(repository)s/%(arch)s/%(filename)s',
|
||||||
|
'http://api.opensuse.org/rpm/%(project)s/%(repository)s/_repository/%(buildarch)s/%(name)s'],
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import ConfigParser
|
||||||
|
|
||||||
|
# being global to this module, this dict can be accessed from outside
|
||||||
|
# it will hold the parsed configuration
|
||||||
|
config = { }
|
||||||
|
|
||||||
|
DEFAULTS = { 'apisrv': 'api.opensuse.org',
|
||||||
|
'scheme': 'http',
|
||||||
|
'user': 'your_username',
|
||||||
|
'pass': 'your_password',
|
||||||
|
'packagecachedir': '/var/tmp/osbuild-packagecache',
|
||||||
|
'su-wrapper': 'su -c',
|
||||||
|
'build-cmd': '/usr/bin/build',
|
||||||
|
'build-root': '/var/tmp/build-root',
|
||||||
|
|
||||||
|
# default list of download URLs, which will be tried in order
|
||||||
|
'urllist': [
|
||||||
|
# the normal repo server, redirecting to mirrors
|
||||||
|
'http://software.opensuse.org/download/%(project)s/%(repository)s/%(arch)s/%(filename)s',
|
||||||
|
# direct access to "full" tree
|
||||||
|
'http://api.opensuse.org/rpm/%(project)s/%(repository)s/_repository/%(buildarch)s/%(name)s',
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
new_conf_template = """
|
||||||
|
[general]
|
||||||
|
|
||||||
|
# Downloaded packages are cached here. Must be writable by you.
|
||||||
|
#packagecachedir = %(packagecachedir)s
|
||||||
|
|
||||||
|
# Wrapper to call build as root (sudo, su -, ...)
|
||||||
|
#su-wrapper = %(su-wrapper)s
|
||||||
|
|
||||||
|
# rootdir to setup the chroot environment
|
||||||
|
# can contain %%(repo)s and/or %%(arch)s for replacement
|
||||||
|
#build-root = %(build-root)s
|
||||||
|
|
||||||
|
# use this API server
|
||||||
|
# (it needs a section [%(apisrv)s] with the credentials)
|
||||||
|
#apisrv = %(apisrv)s
|
||||||
|
|
||||||
|
|
||||||
|
[%(apisrv)s]
|
||||||
|
user = %(user)s
|
||||||
|
pass = %(pass)s
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
account_not_configured_text ="""
|
||||||
|
Your user account / password are not configured yet.
|
||||||
|
You will be asked for them below, and they will be stored in
|
||||||
|
%s for future use.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
config_incomplete_text = """
|
||||||
|
|
||||||
|
Your configuration file %s is not complete.
|
||||||
|
Make sure that it has a [general] section.
|
||||||
|
(You can copy&paste the below. Some commented defaults are shown.)
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def init_basicauth(config):
|
||||||
|
"""initialize urllib2 with the credentials for Basic Authentication"""
|
||||||
|
import urllib2
|
||||||
|
from osc.core import __version__
|
||||||
|
|
||||||
|
passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
|
||||||
|
# this creates a password manager
|
||||||
|
passmgr.add_password(None, config['apisrv'], config['user'], config['pass'])
|
||||||
|
# because we have put None at the start it will always
|
||||||
|
# use this username/password combination for urls
|
||||||
|
# for which `apisrv` is a super-url
|
||||||
|
|
||||||
|
authhandler = urllib2.HTTPBasicAuthHandler(passmgr)
|
||||||
|
# create the AuthHandler
|
||||||
|
|
||||||
|
opener = urllib2.build_opener(authhandler)
|
||||||
|
opener.addheaders = [('User-agent', 'osc/%s' % __version__)]
|
||||||
|
|
||||||
|
urllib2.install_opener(opener)
|
||||||
|
# All calls to urllib2.urlopen will now use our handler
|
||||||
|
# Make sure not to include the protocol in with the URL, or
|
||||||
|
# HTTPPasswordMgrWithDefaultRealm will be very confused.
|
||||||
|
# You must (of course) use it when fetching the page though.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_config():
|
||||||
|
"""do the actual work (see module documentation)"""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
global config
|
||||||
|
|
||||||
|
conffile = os.path.expanduser('~/.oscrc')
|
||||||
|
|
||||||
|
if not os.path.exists(conffile):
|
||||||
|
|
||||||
|
# okay, let's create a fresh config file
|
||||||
|
# if credentials are found in .netrc, use those
|
||||||
|
# otherwise ask
|
||||||
|
|
||||||
|
config = DEFAULTS.copy()
|
||||||
|
|
||||||
|
# try .netrc
|
||||||
|
# the needed entry needs to look like this:
|
||||||
|
# machine api.opensuse.org login your_login password your_pass
|
||||||
|
# note that it is not suited for credentials containing spaces
|
||||||
|
import netrc
|
||||||
|
try:
|
||||||
|
config['user'], account, config['pass'] = \
|
||||||
|
netrc.netrc().authenticators(DEFAULTS['apisrv'])
|
||||||
|
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, 'Created osc configuration file %s.\n' % conffile
|
||||||
|
fd = open(conffile, 'w')
|
||||||
|
os.chmod(conffile, 0600)
|
||||||
|
fd.write(new_conf_template % config)
|
||||||
|
fd.close()
|
||||||
|
#print >>sys.stderr, ('Now re-run the command.')
|
||||||
|
#sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
# okay, we made sure that .oscrc exists
|
||||||
|
|
||||||
|
cp = ConfigParser.SafeConfigParser(DEFAULTS)
|
||||||
|
cp.read(conffile)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
# holds multiple usernames and passwords
|
||||||
|
# it is used by urlgrabber's mirror fetcher
|
||||||
|
auth_dict = { }
|
||||||
|
for host in [ x for x in cp.sections() if x != 'general' ]:
|
||||||
|
auth_dict[host] = { 'user': cp.get(host, 'user'),
|
||||||
|
'pass': cp.get(host, 'pass') }
|
||||||
|
|
||||||
|
config = dict(cp.items('general', raw=1))
|
||||||
|
|
||||||
|
# transform 'url1, url2, url3' form into a list
|
||||||
|
if type(config['urllist']) == str:
|
||||||
|
config['urllist'] = [ i.strip() for i in config['urllist'].split(',') ]
|
||||||
|
|
||||||
|
# add the auth data we collected to the config dict
|
||||||
|
config['auth_dict'] = auth_dict
|
||||||
|
|
||||||
|
# for easier access to the api server's credentials, copy them to the "top":
|
||||||
|
config['user'] = config['auth_dict'][config['apisrv']]['user']
|
||||||
|
config['pass'] = config['auth_dict'][config['apisrv']]['pass']
|
||||||
|
|
||||||
|
# finally, initialize urllib2 for to use the credentials for Basic Authentication
|
||||||
|
init_basicauth(config)
|
||||||
|
|
180
osc/core.py
180
osc/core.py
@ -15,14 +15,12 @@ from urlparse import urlunsplit
|
|||||||
import cElementTree as ET
|
import cElementTree as ET
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
import shutil
|
import shutil
|
||||||
|
import conf
|
||||||
|
|
||||||
|
|
||||||
netloc = 'api.opensuse.org'
|
|
||||||
scheme = 'http'
|
|
||||||
|
|
||||||
BUFSIZE = 1024*1024
|
BUFSIZE = 1024*1024
|
||||||
store = '.osc'
|
store = '.osc'
|
||||||
exclude_stuff = [store, '.svn', 'CVS', '.git', '.gitignore', '.pc', '*~']
|
exclude_stuff = [store, '.svn', 'CVS', '.git', '.gitignore', '.pc', '*~', '.*.swp']
|
||||||
|
|
||||||
|
|
||||||
new_project_templ = """\
|
new_project_templ = """\
|
||||||
@ -263,7 +261,7 @@ class Package:
|
|||||||
import othermethods
|
import othermethods
|
||||||
|
|
||||||
u = makeurl(['source', self.prjname, self.name, pathname2url(n)])
|
u = makeurl(['source', self.prjname, self.name, pathname2url(n)])
|
||||||
othermethods.delfile(u, n, username, password)
|
othermethods.delfile(u, n, conf.config['user'], conf.config['pass'])
|
||||||
|
|
||||||
self.delete_localfile(n)
|
self.delete_localfile(n)
|
||||||
|
|
||||||
@ -273,10 +271,11 @@ class Package:
|
|||||||
# escaping '+' in the URL path (note: not in the URL query string) is
|
# escaping '+' in the URL path (note: not in the URL query string) is
|
||||||
# only a workaround for ruby on rails, which swallows it otherwise
|
# only a workaround for ruby on rails, which swallows it otherwise
|
||||||
u = makeurl(['source', self.prjname, self.name, pathname2url(n)])
|
u = makeurl(['source', self.prjname, self.name, pathname2url(n)])
|
||||||
othermethods.putfile(u, username, password, file = os.path.join(self.dir, n))
|
othermethods.putfile(u, conf.config['user'], conf.config['pass'], file = os.path.join(self.dir, n))
|
||||||
|
|
||||||
shutil.copy2(os.path.join(self.dir, n), os.path.join(self.storedir, n))
|
shutil.copy2(os.path.join(self.dir, n), os.path.join(self.storedir, n))
|
||||||
|
|
||||||
|
|
||||||
def write_conflictlist(self):
|
def write_conflictlist(self):
|
||||||
if len(self.in_conflict) == 0:
|
if len(self.in_conflict) == 0:
|
||||||
os.unlink(os.path.join(self.storedir, '_in_conflict'))
|
os.unlink(os.path.join(self.storedir, '_in_conflict'))
|
||||||
@ -454,7 +453,7 @@ rev: %s
|
|||||||
except urllib2.HTTPError, e:
|
except urllib2.HTTPError, e:
|
||||||
if e.code == 404:
|
if e.code == 404:
|
||||||
print 'package does not exist yet... creating it'
|
print 'package does not exist yet... creating it'
|
||||||
m = template % (pac, username)
|
m = template % (pac, conf.config['user'])
|
||||||
else:
|
else:
|
||||||
print 'error getting package meta for project \'%s\' package \'%s\':' % (prj, pac)
|
print 'error getting package meta for project \'%s\' package \'%s\':' % (prj, pac)
|
||||||
print e
|
print e
|
||||||
@ -482,7 +481,7 @@ rev: %s
|
|||||||
if repl == 'y':
|
if repl == 'y':
|
||||||
print 'Sending meta data...',
|
print 'Sending meta data...',
|
||||||
u = makeurl(['source', self.prjname, self.name, '_meta'])
|
u = makeurl(['source', self.prjname, self.name, '_meta'])
|
||||||
othermethods.putfile(u, username, password, file=filename)
|
othermethods.putfile(u, conf.config['user'], conf.config['pass'], file=filename)
|
||||||
print 'Done.'
|
print 'Done.'
|
||||||
else:
|
else:
|
||||||
print 'discarding', filename
|
print 'discarding', filename
|
||||||
@ -598,7 +597,7 @@ def pathjoin(a, *p):
|
|||||||
|
|
||||||
def makeurl(l):
|
def makeurl(l):
|
||||||
"""given a list of path compoments, construct a complete URL"""
|
"""given a list of path compoments, construct a complete URL"""
|
||||||
return urlunsplit((scheme, netloc, '/'.join(l), '', ''))
|
return urlunsplit((conf.config['scheme'], conf.config['apisrv'], '/'.join(l), '', ''))
|
||||||
|
|
||||||
|
|
||||||
def urlopen(url, data=None):
|
def urlopen(url, data=None):
|
||||||
@ -618,100 +617,6 @@ def urlopen(url, data=None):
|
|||||||
return fd
|
return fd
|
||||||
|
|
||||||
|
|
||||||
def readauth():
|
|
||||||
"""look for the credentials. If there aren't any, ask and store them"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# try .netrc first
|
|
||||||
#
|
|
||||||
|
|
||||||
# the needed entry in .netrc looks like this:
|
|
||||||
# machine api.opensuse.org login your_login password your_pass
|
|
||||||
# but it is not able for credentials containing spaces
|
|
||||||
import netrc
|
|
||||||
global username, password
|
|
||||||
|
|
||||||
try:
|
|
||||||
info = netrc.netrc()
|
|
||||||
username, account, password = info.authenticators(netloc)
|
|
||||||
return username, password
|
|
||||||
|
|
||||||
except (IOError, TypeError, netrc.NetrcParseError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
#
|
|
||||||
# try .oscrc next
|
|
||||||
#
|
|
||||||
import ConfigParser
|
|
||||||
conffile = os.path.expanduser('~/.oscrc')
|
|
||||||
if os.path.exists(conffile):
|
|
||||||
config = ConfigParser.ConfigParser()
|
|
||||||
config.read(conffile)
|
|
||||||
username = config.get(netloc, 'user')
|
|
||||||
password = config.get(netloc, 'pass')
|
|
||||||
return username, password
|
|
||||||
|
|
||||||
#
|
|
||||||
# create .oscrc
|
|
||||||
#
|
|
||||||
import getpass
|
|
||||||
print >>sys.stderr, \
|
|
||||||
"""your user account / password are not configured yet.
|
|
||||||
You will be asked for them below, and they will be stored in
|
|
||||||
%s for later use.
|
|
||||||
""" % conffile
|
|
||||||
|
|
||||||
username = raw_input('Username: ')
|
|
||||||
password = getpass.getpass()
|
|
||||||
|
|
||||||
fd = open(conffile, 'w')
|
|
||||||
os.chmod(conffile, 0600)
|
|
||||||
print >>fd, """[general]
|
|
||||||
|
|
||||||
# Downloaded packages are cached here. Must be writable by you.
|
|
||||||
#packagecachedir: /var/tmp/osbuild-packagecache
|
|
||||||
|
|
||||||
# Wrapper to call build as root (sudo, su -, ...)
|
|
||||||
#su-wrapper: su -c
|
|
||||||
|
|
||||||
# rootdir to setup the chroot environment
|
|
||||||
#build-root: /var/tmp/build-root
|
|
||||||
|
|
||||||
|
|
||||||
[%s]
|
|
||||||
user: %s
|
|
||||||
pass: %s
|
|
||||||
""" % (netloc, username, password)
|
|
||||||
fd.close()
|
|
||||||
|
|
||||||
return username, password
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def init_basicauth():
|
|
||||||
|
|
||||||
username, password = readauth()
|
|
||||||
|
|
||||||
passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
|
|
||||||
# this creates a password manager
|
|
||||||
passmgr.add_password(None, netloc, username, password)
|
|
||||||
# because we have put None at the start it will always
|
|
||||||
# use this username/password combination for urls
|
|
||||||
# for which `netloc` is a super-url
|
|
||||||
|
|
||||||
authhandler = urllib2.HTTPBasicAuthHandler(passmgr)
|
|
||||||
# create the AuthHandler
|
|
||||||
|
|
||||||
opener = urllib2.build_opener(authhandler)
|
|
||||||
opener.addheaders = [('User-agent', 'osc/%s' % __version__)]
|
|
||||||
|
|
||||||
urllib2.install_opener(opener)
|
|
||||||
# All calls to urllib2.urlopen will now use our handler
|
|
||||||
# Make sure not to include the protocol in with the URL, or
|
|
||||||
# HTTPPasswordMgrWithDefaultRealm will be very confused.
|
|
||||||
# You must (of course) use it when fetching the page though.
|
|
||||||
|
|
||||||
|
|
||||||
def init_package_dir(project, package, dir):
|
def init_package_dir(project, package, dir):
|
||||||
if not os.path.isdir(store):
|
if not os.path.isdir(store):
|
||||||
os.mkdir(store)
|
os.mkdir(store)
|
||||||
@ -764,64 +669,29 @@ def check_store_version(dir):
|
|||||||
def meta_get_packagelist(prj):
|
def meta_get_packagelist(prj):
|
||||||
|
|
||||||
u = makeurl(['source', prj])
|
u = makeurl(['source', prj])
|
||||||
|
f = urlopen(u)
|
||||||
try:
|
root = ET.parse(f).getroot()
|
||||||
f = urllib2.urlopen(u)
|
|
||||||
except urllib2.HTTPError, e:
|
|
||||||
if e.code == 404:
|
|
||||||
print 'project \'%s\' does not exist' % prj
|
|
||||||
sys.exit(1)
|
|
||||||
else:
|
|
||||||
print e
|
|
||||||
print 'url: \'%s\'' % u
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
tree = ET.parse(f)
|
|
||||||
root = tree.getroot()
|
|
||||||
|
|
||||||
return [ node.get('name') for node in root.findall('entry') ]
|
return [ node.get('name') for node in root.findall('entry') ]
|
||||||
|
|
||||||
|
|
||||||
def meta_get_filelist(prj, package):
|
def meta_get_filelist(prj, package):
|
||||||
|
|
||||||
u = makeurl(['source', prj, package])
|
u = makeurl(['source', prj, package])
|
||||||
|
f = urlopen(u)
|
||||||
try:
|
|
||||||
f = urllib2.urlopen(u)
|
|
||||||
except urllib2.HTTPError, e:
|
|
||||||
print >>sys.stderr, 'error getting filelist for project \'%s\' package \'%s\'' % (prj, package)
|
|
||||||
print >>sys.stderr, e
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
root = ET.parse(f).getroot()
|
root = ET.parse(f).getroot()
|
||||||
|
|
||||||
return [ node.get('name') for node in root ]
|
return [ node.get('name') for node in root ]
|
||||||
|
|
||||||
|
|
||||||
|
def meta_get_project_list():
|
||||||
def get_slash_source():
|
|
||||||
u = makeurl(['source'])
|
u = makeurl(['source'])
|
||||||
try:
|
f = urlopen(u)
|
||||||
root = ET.parse(urllib2.urlopen(u)).getroot()
|
root = ET.parse(f).getroot()
|
||||||
except urllib2.HTTPError, e:
|
|
||||||
print >>sys.stderr, 'error getting /source'
|
|
||||||
print >>sys.stderr, e
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
return sorted([ node.get('name') for node in root ])
|
return sorted([ node.get('name') for node in root ])
|
||||||
|
|
||||||
|
|
||||||
def show_project_meta(prj):
|
def show_project_meta(prj):
|
||||||
try:
|
|
||||||
url = makeurl(['source', prj, '_meta'])
|
url = makeurl(['source', prj, '_meta'])
|
||||||
f = urllib2.urlopen(url)
|
f = urlopen(url)
|
||||||
except urllib2.HTTPError, e:
|
|
||||||
print >>sys.stderr, 'error getting meta for project \'%s\'' % prj
|
|
||||||
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()
|
return f.readlines()
|
||||||
|
|
||||||
|
|
||||||
@ -851,7 +721,7 @@ def edit_meta(prj, pac, template=new_package_templ, change_is_required=True):
|
|||||||
m = urllib2.urlopen(u).readlines()
|
m = urllib2.urlopen(u).readlines()
|
||||||
except urllib2.HTTPError, e:
|
except urllib2.HTTPError, e:
|
||||||
if e.code == 404:
|
if e.code == 404:
|
||||||
m = template % (pac, username)
|
m = template % (pac, conf.config['username'])
|
||||||
else:
|
else:
|
||||||
print 'error getting package meta for project \'%s\' package \'%s\':' % (prj, pac)
|
print 'error getting package meta for project \'%s\' package \'%s\':' % (prj, pac)
|
||||||
print e
|
print e
|
||||||
@ -864,7 +734,7 @@ def edit_meta(prj, pac, template=new_package_templ, change_is_required=True):
|
|||||||
m = urllib2.urlopen(u).readlines()
|
m = urllib2.urlopen(u).readlines()
|
||||||
except urllib2.HTTPError, e:
|
except urllib2.HTTPError, e:
|
||||||
if e.code == 404:
|
if e.code == 404:
|
||||||
m = new_project_templ % (prj, username)
|
m = new_project_templ % (prj, conf.config['username'])
|
||||||
else:
|
else:
|
||||||
print 'error getting package meta for project \'%s\':' % prj
|
print 'error getting package meta for project \'%s\':' % prj
|
||||||
print e
|
print e
|
||||||
@ -885,7 +755,7 @@ def edit_meta(prj, pac, template=new_package_templ, change_is_required=True):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
print 'Sending meta data...',
|
print 'Sending meta data...',
|
||||||
othermethods.putfile(u, username, password, file=filename)
|
othermethods.putfile(u, conf.config['user'], conf.config['pass'], file=filename)
|
||||||
os.unlink(filename)
|
os.unlink(filename)
|
||||||
print 'Done.'
|
print 'Done.'
|
||||||
|
|
||||||
@ -1084,7 +954,7 @@ def link_pac(src_project, src_package, dst_project, dst_package):
|
|||||||
""" % (src_project, src_package)
|
""" % (src_project, src_package)
|
||||||
|
|
||||||
u = makeurl(['source', dst_project, dst_package, '_link'])
|
u = makeurl(['source', dst_project, dst_package, '_link'])
|
||||||
othermethods.putfile(u, username, password, strbuf = link_template)
|
othermethods.putfile(u, conf.config['user'], conf.config['pass'], strbuf = link_template)
|
||||||
print 'Done.'
|
print 'Done.'
|
||||||
|
|
||||||
|
|
||||||
@ -1111,7 +981,7 @@ def copy_pac(src_project, src_package, dst_project, dst_package):
|
|||||||
|
|
||||||
print 'Sending meta data...'
|
print 'Sending meta data...'
|
||||||
u = makeurl(['source', dst_project, dst_package, '_meta'])
|
u = makeurl(['source', dst_project, dst_package, '_meta'])
|
||||||
othermethods.putfile(u, username, password, strbuf=src_meta)
|
othermethods.putfile(u, conf.config['user'], conf.config['pass'], strbuf=src_meta)
|
||||||
|
|
||||||
# copy one file after the other
|
# copy one file after the other
|
||||||
print 'Copying files...'
|
print 'Copying files...'
|
||||||
@ -1121,7 +991,7 @@ def copy_pac(src_project, src_package, dst_project, dst_package):
|
|||||||
print ' ', n
|
print ' ', n
|
||||||
get_source_file(src_project, src_package, n, targetfilename=n)
|
get_source_file(src_project, src_package, n, targetfilename=n)
|
||||||
u = makeurl(['source', dst_project, dst_package, pathname2url(n)])
|
u = makeurl(['source', dst_project, dst_package, pathname2url(n)])
|
||||||
othermethods.putfile(u, username, password, file = n)
|
othermethods.putfile(u, conf.config['user'], conf.config['pass'], file = n)
|
||||||
os.unlink(n)
|
os.unlink(n)
|
||||||
print 'Done.'
|
print 'Done.'
|
||||||
os.rmdir(tmpdir)
|
os.rmdir(tmpdir)
|
||||||
@ -1131,14 +1001,14 @@ def delete_package(prj, pac):
|
|||||||
import othermethods
|
import othermethods
|
||||||
|
|
||||||
u = makeurl(['source', prj, pac])
|
u = makeurl(['source', prj, pac])
|
||||||
othermethods.delfile(u, pac, username, password)
|
othermethods.delfile(u, pac, conf.config['username'], conf.config['pass'])
|
||||||
|
|
||||||
|
|
||||||
def delete_project(prj):
|
def delete_project(prj):
|
||||||
import othermethods
|
import othermethods
|
||||||
|
|
||||||
u = makeurl(['source', prj])
|
u = makeurl(['source', prj])
|
||||||
othermethods.delfile(u, prj, username, password)
|
othermethods.delfile(u, prj, conf.config['username'], conf.config['pass'])
|
||||||
|
|
||||||
|
|
||||||
def get_platforms():
|
def get_platforms():
|
||||||
@ -1208,7 +1078,7 @@ def get_results(prj, package, platform):
|
|||||||
rmap['status'] += ': ' + statusnode.find('summary').text
|
rmap['status'] += ': ' + statusnode.find('summary').text
|
||||||
|
|
||||||
if rmap['status'] == 'failed':
|
if rmap['status'] == 'failed':
|
||||||
rmap['status'] += ': %s://%s' % (scheme, netloc) + \
|
rmap['status'] += ': %s://%s' % (conf.config['scheme'], conf.config['apisrv']) + \
|
||||||
'/result/%(prj)s/%(rep)s/%(pac)s/%(arch)s/log' % rmap
|
'/result/%(prj)s/%(rep)s/%(pac)s/%(arch)s/log' % rmap
|
||||||
|
|
||||||
r.append(result_line_templ % rmap)
|
r.append(result_line_templ % rmap)
|
||||||
@ -1304,7 +1174,7 @@ def get_buildhistory(prj, package, platform, arch):
|
|||||||
srcmd5 = node.get('srcmd5')
|
srcmd5 = node.get('srcmd5')
|
||||||
versrel = node.get('versrel')
|
versrel = node.get('versrel')
|
||||||
bcnt = int(node.get('bcnt'))
|
bcnt = int(node.get('bcnt'))
|
||||||
t = time.gmtime(int(node.get('time')))
|
t = time.localtime(int(node.get('time')))
|
||||||
t = time.strftime('%Y-%m-%d %H:%M:%S', t)
|
t = time.strftime('%Y-%m-%d %H:%M:%S', t)
|
||||||
|
|
||||||
r.append('%s %s %6d %2d %s' % (t, srcmd5, rev, bcnt, versrel))
|
r.append('%s %s %6d %2d %s' % (t, srcmd5, rev, bcnt, versrel))
|
||||||
|
@ -5,7 +5,6 @@ import tempfile
|
|||||||
import os, sys
|
import os, sys
|
||||||
|
|
||||||
from osc import commandline
|
from osc import commandline
|
||||||
from osc.core import init_basicauth
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
@ -17,7 +16,6 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
prof = hotshot.Profile(filename)
|
prof = hotshot.Profile(filename)
|
||||||
|
|
||||||
init_basicauth()
|
|
||||||
prof.runcall(commandline.main)
|
prof.runcall(commandline.main)
|
||||||
print 'run complete. analyzing.'
|
print 'run complete. analyzing.'
|
||||||
prof.close()
|
prof.close()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user