1 # Copyright (C) 2006-2009 Novell Inc. All rights reserved.
2 # This program is free software; it may be used, copied, modified
3 # and distributed under the terms of the GNU General Public Licence,
4 # either version 2, or version 3 (at your option).
6 """Read osc configuration and store it in a dictionary
8 This module reads and parses ~/.oscrc. The resulting configuration is stored
9 for later usage in a dictionary named 'config'.
10 The .oscrc is kept mode 0600, so that it is not publically readable.
11 This gives no real security for storing passwords.
12 If in doubt, use your favourite keyring.
13 Password is stored on ~/.oscrc as bz2 compressed and base64 encoded, so that is fairly
14 large and not to be recognized or remembered easily by an occasional spectator.
16 If information is missing, it asks the user questions.
18 After reading the config, urllib2 is initialized.
20 The configuration dictionary could look like this:
22 {'apisrv': 'https://api.opensuse.org/',
24 'api_host_options': {'api.opensuse.org': {'user': 'joe', 'pass': 'secret'},
25 'apitest.opensuse.org': {'user': 'joe', 'pass': 'secret',
26 'http_headers':(('Host','api.suse.de'),
28 'foo.opensuse.org': {'user': 'foo', 'pass': 'foo'}},
29 'build-cmd': '/usr/bin/build',
30 'build-root': '/abuild/oscbuild-%(repo)s-%(arch)s',
31 'packagecachedir': '/var/cache/osbuild',
37 import OscConfigParser
38 from osc import oscerr
39 from oscsslexcp import NoSecureSSLError
42 GENERIC_KEYRING = False
47 GENERIC_KEYRING = True
52 gobject.set_application_name('osc')
54 if os.environ['GNOME_DESKTOP_SESSION_ID']:
55 # otherwise gnome keyring bindings spit out errors, when you have
56 # it installed, but you are not under gnome
57 # (even though hundreds of gnome-keyring daemons got started in parallel)
58 # another option would be to support kwallet here
59 GNOME_KEYRING = gnomekeyring.is_available()
63 DEFAULTS = { 'apiurl': 'https://api.opensuse.org',
64 'user': 'your_username',
65 'pass': 'your_password',
67 'packagecachedir': '/var/tmp/osbuild-packagecache',
68 'su-wrapper': 'su -c',
71 'build-cmd': '/usr/bin/build',
72 'build-type': '', # may be empty for chroot, kvm or xen
73 'build-root': '/var/tmp/build-root',
74 'build-uid': '', # use the default provided by build
75 'build-device': '', # required for VM builds
76 'build-memory': '',# required for VM builds
77 'build-swap': '', # optional for VM builds
78 'build-vmdisk-rootsize': '', # optional for VM builds
79 'build-vmdisk-swapsize': '', # optional for VM builds
81 'build-jobs': os.sysconf('SC_NPROCESSORS_ONLN'), # compile with N jobs
91 'cookiejar': '~/.osc_cookiejar',
92 # enable project tracking by default
93 'do_package_tracking': '1',
94 # default for osc build
97 'build_repository': 'openSUSE_Factory',
98 # default project for branch or bco
99 'getpac_default_project': 'openSUSE:Factory',
100 # alternate filesystem layout: have multiple subdirs, where colons were.
101 'checkout_no_colon': '0',
102 # local files to ignore with status, addremove, ....
103 # local files to ignore with status, addremove, ....
104 'exclude_glob': '.osc CVS .svn .* _linkerror *~ #*# *.orig *.bak *.changes.*',
105 # keep passwords in plaintext. If you see this comment, your osc
106 # already uses the encrypted password, and only keeps them in plain text
107 # for backwards compatibility. Default will change to 0 in future releases.
108 'plaintext_passwd': '1',
109 # limit the age of requests shown with 'osc req list'.
110 # this is a default only, can be overridden by 'osc req list -D NNN'
111 # Use 0 for unlimted.
112 'request_list_days': 30,
113 # check for unversioned/removed files before commit
114 'check_filelist': '1',
115 # External scripts to validate sources, esp before commit. This is a directory
116 'source_validator_directory': '/usr/lib/osc/source_validators',
117 # check for pending requests after executing an action (e.g. checkout, update, commit)
118 'check_for_request_on_action': '0',
119 # what to do with the source package if the submitrequest has been accepted
120 'submitrequest_on_accept_action': '',
121 'request_show_interactive': '0',
124 # Maintenance defaults to OBS instance defaults
125 'maintained_attribute': 'OBS:Maintained',
126 'maintained_update_project_attribute': 'OBS:UpdateProject',
127 'show_download_progress': '0',
130 # being global to this module, this dict can be accessed from outside
131 # it will hold the parsed configuration
132 config = DEFAULTS.copy()
134 boolean_opts = ['debug', 'do_package_tracking', 'http_debug', 'post_mortem', 'traceback', 'check_filelist', 'plaintext_passwd',
135 'checkout_no_colon', 'check_for_request_on_action', 'linkcontrol', 'show_download_progress', 'request_show_interactive',
136 'use_keyring', 'gnome_keyring']
138 api_host_options = ['user', 'pass', 'passx', 'aliases', 'http_headers', 'email', 'sslcertck', 'cafile', 'capath', 'trusted_prj']
140 new_conf_template = """
143 # URL to access API server, e.g. %(apiurl)s
144 # you also need a section [%(apiurl)s] with the credentials
147 # Downloaded packages are cached here. Must be writable by you.
148 #packagecachedir = %(packagecachedir)s
150 # Wrapper to call build as root (sudo, su -, ...)
151 #su-wrapper = %(su-wrapper)s
153 # rootdir to setup the chroot environment
154 # can contain %%(repo)s, %%(arch)s, %%(project)s and %%(package)s for replacement, e.g.
155 # /srv/oscbuild/%%(repo)s-%%(arch)s or
156 # /srv/oscbuild/%%(repo)s-%%(arch)s-%%(project)s-%%(package)s
157 #build-root = %(build-root)s
159 # compile with N jobs (default: "getconf _NPROCESSORS_ONLN")
162 # build-type to use - values can be (depending on the capabilities of the 'build' script)
163 # empty - chroot build
164 # kvm - kvm VM build (needs build-device, build-swap, build-memory)
165 # xen - xen VM build (needs build-device, build-swap, build-memory)
167 # qemu - qemu VM build
171 # build-device is the disk-image file to use as root for VM builds
172 # e.g. /var/tmp/FILE.root
173 #build-device = /var/tmp/FILE.root
175 # build-swap is the disk-image to use as swap for VM builds
176 # e.g. /var/tmp/FILE.swap
177 #build-swap = /var/tmp/FILE.swap
179 # build-memory is the amount of memory used in the VM
180 # value in MB - e.g. 512
183 # build-vmdisk-rootsize is the size of the disk-image used as root in a VM build
184 # values in MB - e.g. 4096
185 #build-vmdisk-rootsize = 4096
187 # build-vmdisk-swapsize is the size of the disk-image used as swap in a VM build
188 # values in MB - e.g. 1024
189 #build-vmdisk-swapsize = 1024
191 # Numeric uid:gid to assign to the "abuild" user in the build-root
192 # or "caller" to use the current users uid:gid
193 # This is convenient when sharing the buildroot with ordinary userids
195 # This should not be 0
198 # extra packages to install when building packages locally (osc build)
199 # this corresponds to osc build's -x option and can be overridden with that
200 # -x '' can also be given on the command line to override this setting, or
201 # you can have an empty setting here.
202 #extra-pkgs = vim gdb strace
204 # build platform is used if the platform argument is omitted to osc build
205 #build_repository = %(build_repository)s
207 # default project for getpac or bco
208 #getpac_default_project = %(getpac_default_project)s
210 # alternate filesystem layout: have multiple subdirs, where colons were.
211 #checkout_no_colon = %(checkout_no_colon)s
213 # local files to ignore with status, addremove, ....
214 #exclude_glob = %(exclude_glob)s
216 # keep passwords in plaintext. If you see this comment, your osc
217 # already uses the encrypted password, and only keeps them in plain text
218 # for backwards compatibility. Default will change to 0 in future releases.
219 # You can remove the plaintext password without harm, if you do not need
220 # backwards compatibility.
221 #plaintext_passwd = %(plaintext_passwd)s
223 # limit the age of requests shown with 'osc req list'.
224 # this is a default only, can be overridden by 'osc req list -D NNN'
225 # Use 0 for unlimted.
226 #request_list_days = %(request_list_days)s
228 # show info useful for debugging
231 # show HTTP traffic useful for debugging
234 # jump into the debugger in case of errors
237 # print call traces in case of errors
240 # use KDE/Gnome/MacOS/Windows keyring for credentials if available
243 # check for unversioned/removed files before commit
246 # check for pending requests after executing an action (e.g. checkout, update, commit)
247 #check_for_request_on_action = 0
249 # what to do with the source package if the submitrequest has been accepted. If
250 # nothing is specified the API default is used
251 #submitrequest_on_accept_action = cleanup|update|noupdate
253 #review requests interactively (default: off)
254 #request_show_review = 1
256 # Directory with executables to validate sources, esp before committing
257 #source_validator_directory = /usr/lib/osc/source_validators
263 # set aliases for this apiurl
265 # email used in .changes, unless the one from osc meta prj <user> will be used
267 # additional headers to pass to a request, e.g. for special authentication
268 #http_headers = Host: foofoobar,
270 # Force using of keyring for this API
275 account_not_configured_text ="""
276 Your user account / password are not configured yet.
277 You will be asked for them below, and they will be stored in
281 config_incomplete_text = """
283 Your configuration file %s is not complete.
284 Make sure that it has a [general] section.
285 (You can copy&paste the below. Some commented defaults are shown.)
289 config_missing_apiurl_text = """
290 the apiurl \'%s\' does not exist in the config file. Please enter
291 your credentials for this apiurl.
296 def parse_apisrv_url(scheme, apisrv):
298 if apisrv.startswith('http://') or apisrv.startswith('https://'):
299 return urlparse.urlsplit(apisrv)[0:2]
301 # the split/join is needed to get a proper url (e.g. without a trailing slash)
302 return urlparse.urlsplit(urljoin(scheme, apisrv))[0:2]
304 from urllib2 import URLError
305 msg = 'invalid apiurl \'%s\' (specify the protocol (http:// or https://))' % apisrv
308 def urljoin(scheme, apisrv):
309 return '://'.join([scheme, apisrv])
311 def get_apiurl_api_host_options(apiurl):
313 Returns all apihost specific options for the given apiurl, None if
314 no such specific optiosn exist.
316 # FIXME: in A Better World (tm) there was a config object which
317 # knows this instead of having to extract it from a url where it
318 # had been mingled into before. But this works fine for now.
320 apiurl = urljoin(*parse_apisrv_url(None, apiurl))
322 return config['api_host_options'][apiurl]
324 raise oscerr.ConfigMissingApiurl('missing credentials for apiurl: \'%s\'' % apiurl,
327 def get_apiurl_usr(apiurl):
329 returns the user for this host - if this host does not exist in the
330 internal api_host_options the default user is returned.
332 # FIXME: maybe there should be defaults not just for the user but
333 # for all apihost specific options. The ConfigParser class
334 # actually even does this but for some reason we don't use it
339 return get_apiurl_api_host_options(apiurl)['user']
341 print >>sys.stderr, 'no specific section found in config file for host of [\'%s\'] - using default user: \'%s\'' \
342 % (apiurl, config['user'])
343 return config['user']
347 def init_basicauth(config):
348 """initialize urllib2 with the credentials for Basic Authentication"""
350 from osc.core import __version__
353 if config['api_host_options'][config['apiurl']]['sslcertck']:
356 from M2Crypto import m2urllib2
357 except ImportError, e:
359 raise NoSecureSSLError("M2Crypto is needed to access %s in a secure way.\nPlease install python-m2crypto." % config['apiurl'])
367 if sys.version_info < (2, 6):
368 # HTTPS proxy is not supported in old urllib2. It only leads to an error
369 # or, at best, a warning.
370 if 'https_proxy' in os.environ:
371 del os.environ['https_proxy']
372 if 'HTTPS_PROXY' in os.environ:
373 del os.environ['HTTPS_PROXY']
375 if config['http_debug']:
377 def urllib2_debug_init(self, debuglevel=0):
379 urllib2.AbstractHTTPHandler.__init__ = urllib2_debug_init
381 authhandler = urllib2.HTTPBasicAuthHandler( \
382 urllib2.HTTPPasswordMgrWithDefaultRealm())
384 cookie_file = os.path.expanduser(config['cookiejar'])
385 cookiejar = cookielib.LWPCookieJar(cookie_file)
387 cookiejar.load(ignore_discard=True)
390 open(cookie_file, 'w').close()
391 os.chmod(cookie_file, 0600)
393 #print 'Unable to create cookiejar file: \'%s\'. Using RAM-based cookies.' % cookie_file
394 cookiejar = cookielib.CookieJar()
397 if config['api_host_options'][config['apiurl']]['sslcertck']:
398 cafile = capath = None
399 if 'capath' in config['api_host_options'][config['apiurl']]:
400 capath = config['api_host_options'][config['apiurl']]['capath']
401 if 'cafile' in config['api_host_options'][config['apiurl']]:
402 cafile = config['api_host_options'][config['apiurl']]['cafile']
403 if not cafile and not capath:
404 for i in ['/etc/pki/tls/cert.pem', '/etc/ssl/certs' ]:
405 if os.path.isfile(i):
408 elif os.path.isdir(i):
411 ctx = oscssl.mySSLContext()
412 if ctx.load_verify_locations(capath=capath, cafile=cafile) != 1: raise Exception('No CA certificates found')
413 opener = m2urllib2.build_opener(ctx, oscssl.myHTTPSHandler(ssl_context = ctx, appname = 'osc'), urllib2.HTTPCookieProcessor(cookiejar), authhandler)
416 print >>sys.stderr, "WARNING: SSL certificate checks disabled. Connection is insecure!\n"
417 opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookiejar), authhandler)
419 urllib2.install_opener(opener)
421 opener.addheaders = [('User-agent', 'osc/%s' % __version__)]
423 # with None as first argument, it will always use this username/password
424 # combination for urls for which arg2 (apisrv) is a super-url
425 for host, auth in config['api_host_options'].iteritems():
426 authhandler.add_password(None, host, auth['user'], auth['pass'])
429 def get_configParser(conffile=None, force_read=False):
431 Returns an ConfigParser() object. After its first invocation the
432 ConfigParser object is stored in a method attribute and this attribute
433 is returned unless you pass force_read=True.
435 conffile = conffile or os.environ.get('OSC_CONFIG', '~/.oscrc')
436 conffile = os.path.expanduser(conffile)
437 if not get_configParser.__dict__.has_key('conffile'):
438 get_configParser.conffile = conffile
439 if force_read or not get_configParser.__dict__.has_key('cp') or conffile != get_configParser.conffile:
440 get_configParser.cp = OscConfigParser.OscConfigParser(DEFAULTS)
441 get_configParser.cp.read(conffile)
442 get_configParser.conffile = conffile
443 return get_configParser.cp
445 def config_set_option(section, opt, val=None, delete=False, update=True, **kwargs):
447 Sets a config option. If val is not specified the current/default value is
448 returned. If val is specified, opt is set to val and the new value is returned.
449 If an option was modified get_config is called with **kwargs unless update is set
450 to False (override_conffile defaults to config['conffile']).
451 If val is not specified and delete is True then the option is removed from the
452 config/reset to the default value.
454 def write_config(fname, cp):
455 """write new configfile in a safe way"""
457 f = open(fname + '.new', 'w')
458 cp.write(f, comments=True)
460 os.rename(fname + '.new', fname)
462 if os.path.exists(fname + '.new'):
463 os.unlink(fname + '.new')
466 cp = get_configParser(config['conffile'])
467 # don't allow "internal" options
468 general_opts = [i for i in DEFAULTS.keys() if not i in ['user', 'pass', 'passx']]
469 if section != 'general':
470 section = config['apiurl_aliases'].get(section, section)
472 parse_apisrv_url(config.get('scheme', 'https'), section)
473 section = urljoin(scheme, host)
476 for url in cp.sections():
481 parse_apisrv_url(config.get('scheme', 'https'), url)
482 apiurl = urljoin(scheme, host)
483 sections[apiurl] = url
485 section = sections.get(section.rstrip('/'), section)
486 if not section in cp.sections():
487 raise oscerr.ConfigError('unknown section \'%s\'' % section, config['conffile'])
488 if section == 'general' and not opt in general_opts or \
489 section != 'general' and not opt in api_host_options:
490 raise oscerr.ConfigError('unknown config option \'%s\'' % opt, config['conffile'])
493 cp.set(section, opt, val)
494 write_config(config['conffile'], cp)
496 elif delete and cp.has_option(section, opt):
497 cp.remove_option(section, opt)
498 write_config(config['conffile'], cp)
501 kw = {'override_conffile': config['conffile']}
504 if cp.has_option(section, opt):
505 return (opt, cp.get(section, opt, raw=True))
508 def write_initial_config(conffile, entries, custom_template = ''):
510 write osc's intial configuration file. entries is a dict which contains values
511 for the config file (e.g. { 'user' : 'username', 'pass' : 'password' } ).
512 custom_template is an optional configuration template.
514 import StringIO, sys, base64
515 conf_template = custom_template or new_conf_template
516 config = DEFAULTS.copy()
517 config.update(entries)
518 config['passx'] = base64.b64encode(config['pass'].encode('bz2'))
519 # at this point use_keyring and gnome_keyring are str objects
520 if config['use_keyring'] == '1' and GENERIC_KEYRING:
522 parse_apisrv_url(None, config['apiurl'])
523 keyring.set_password(host, config['user'], config['pass'])
526 elif config['gnome_keyring'] == '1' and GNOME_KEYRING:
528 parse_apisrv_url(None, config['apiurl'])
529 gnomekeyring.set_network_password_sync(
530 user = config['user'],
531 password = config['pass'],
537 if not config['plaintext_passwd']:
539 sio = StringIO.StringIO(conf_template.strip() % config)
540 cp = OscConfigParser.OscConfigParser(DEFAULTS)
545 file = open(conffile, 'w')
547 raise oscerr.OscIOError(e, 'cannot open configfile \'%s\'' % conffile)
550 os.chmod(conffile, 0600)
553 raise oscerr.OscIOError(e, 'cannot write configfile \'s\'' % conffile)
555 if file: file.close()
557 def add_section(filename, url, user, passwd):
559 Add a section to config file for new api url.
563 cp = get_configParser(filename)
566 except OscConfigParser.ConfigParser.DuplicateSectionError:
567 # Section might have existed, but was empty
569 if config['use_keyring'] and GENERIC_KEYRING:
571 parse_apisrv_url(None, url)
572 keyring.set_password(host, user, passwd)
573 cp.set(url, 'keyring', '1')
574 cp.set(url, 'user', user)
575 cp.remove_option(url, 'pass')
576 cp.remove_option(url, 'passx')
577 elif config['gnome_keyring'] and GNOME_KEYRING:
579 parse_apisrv_url(None, url)
580 gnomekeyring.set_network_password_sync(
585 cp.set(url, 'keyring', '1')
586 cp.remove_option(url, 'pass')
587 cp.remove_option(url, 'passx')
589 cp.set(url, 'user', user)
590 if not config['plaintext_passwd']:
591 cp.remove_option(url, 'pass')
592 cp.set(url, 'passx', base64.b64encode(passwd.encode('bz2')))
593 file = open(filename, 'w')
595 if file: file.close()
598 def get_config(override_conffile = None,
599 override_apiurl = None,
600 override_debug = None,
601 override_http_debug = None,
602 override_traceback = None,
603 override_post_mortem = None,
604 override_no_keyring = None,
605 override_no_gnome_keyring = None,
606 override_verbose = None):
607 """do the actual work (see module documentation)"""
612 conffile = override_conffile or os.environ.get('OSC_CONFIG', '~/.oscrc')
613 conffile = os.path.expanduser(conffile)
615 if not os.path.exists(conffile):
616 raise oscerr.NoConfigfile(conffile, \
617 account_not_configured_text % conffile)
619 # okay, we made sure that .oscrc exists
621 # make sure it is not world readable, it may contain a password.
622 os.chmod(conffile, 0600)
624 cp = get_configParser(conffile)
626 if not cp.has_section('general'):
627 # FIXME: it might be sufficient to just assume defaults?
628 msg = config_incomplete_text % conffile
629 msg += new_conf_template % DEFAULTS
630 raise oscerr.ConfigError(msg, conffile)
632 config = dict(cp.items('general', raw=1))
633 config['conffile'] = conffile
635 for i in boolean_opts:
637 config[i] = cp.getboolean('general', i)
638 except ValueError, e:
639 raise oscerr.ConfigError('cannot parse \'%s\' setting: ' % i + str(e), conffile)
641 config['packagecachedir'] = os.path.expanduser(config['packagecachedir'])
642 config['exclude_glob'] = config['exclude_glob'].split()
644 re_clist = re.compile('[, ]+')
645 config['extra-pkgs'] = [ i.strip() for i in re_clist.split(config['extra-pkgs'].strip()) if i ]
647 # collect the usernames, passwords and additional options for each api host
648 api_host_options = {}
650 # Regexp to split extra http headers into a dictionary
651 # the text to be matched looks essentially looks this:
652 # "Attribute1: value1, Attribute2: value2, ..."
653 # there may be arbitray leading and intermitting whitespace.
654 # the following regexp does _not_ support quoted commas within the value.
655 http_header_regexp = re.compile(r"\s*(.*?)\s*:\s*(.*?)\s*(?:,\s*|\Z)")
657 # override values which we were called with
658 # This needs to be done before processing API sections as it might be already used there
659 if override_no_keyring:
660 config['use_keyring'] = False
661 if override_no_gnome_keyring:
662 config['gnome_keyring'] = False
665 for url in [ x for x in cp.sections() if x != 'general' ]:
666 # backward compatiblity
668 parse_apisrv_url(config.get('scheme', 'https'), url)
669 apiurl = urljoin(scheme, host)
671 if config['use_keyring'] and GENERIC_KEYRING:
673 # Read from keyring lib if available
674 user = cp.get(url, 'user', raw=True)
675 password = keyring.get_password(host, user)
677 # Fallback to file based auth.
679 elif config['gnome_keyring'] and GNOME_KEYRING:
680 # Read from gnome keyring if available
682 gk_data = gnomekeyring.find_network_password_sync(
685 password = gk_data[0]['password']
686 user = gk_data[0]['user']
687 except gnomekeyring.NoMatchError:
688 # Fallback to file based auth.
690 # Read credentials from config
692 #FIXME: this could actually be the ideal spot to take defaults
693 #from the general section.
694 user = cp.get(url, 'user', raw=True) # need to set raw to prevent '%' expansion
695 password = cp.get(url, 'pass', raw=True) # especially on password!
696 passwordx = cp.get(url, 'passx', raw=True) # especially on password!
697 if password is None or password == 'your_password':
699 password = passwordx.decode('base64').decode('bz2')
701 print "%s: no credentials known" % url
702 password = 'your_password'
705 print "%s: rewriting from plain pass to encoded pass\n" % url
706 add_section(conffile, url, user, password)
708 if cp.has_option(url, 'http_headers'):
709 http_headers = cp.get(url, 'http_headers')
710 http_headers = http_header_regexp.findall(http_headers)
713 if cp.has_option(url, 'aliases'):
714 for i in cp.get(url, 'aliases').split(','):
718 if aliases.has_key(key):
719 msg = 'duplicate alias entry: \'%s\' is already used for another apiurl' % key
720 raise oscerr.ConfigError(msg, conffile)
723 api_host_options[apiurl] = { 'user': user,
725 'http_headers': http_headers}
727 optional = ('email', 'sslcertck', 'cafile', 'capath')
729 if cp.has_option(url, key):
730 if key == 'sslcertck':
731 api_host_options[apiurl][key] = cp.getboolean(url, key)
733 api_host_options[apiurl][key] = cp.get(url, key)
735 if not 'sslcertck' in api_host_options[apiurl]:
736 api_host_options[apiurl]['sslcertck'] = True
738 if cp.has_option(url, 'trusted_prj'):
739 api_host_options[apiurl]['trusted_prj'] = cp.get(url, key).split(' ')
741 api_host_options[apiurl]['trusted_prj'] = []
743 # add the auth data we collected to the config dict
744 config['api_host_options'] = api_host_options
745 config['apiurl_aliases'] = aliases
747 apiurl = aliases.get(config['apiurl'], config['apiurl'])
748 config['apiurl'] = urljoin(*parse_apisrv_url(None, apiurl))
749 # backward compatibility
750 if config.has_key('apisrv'):
751 apisrv = config['apisrv'].lstrip('http://')
752 apisrv = apisrv.lstrip('https://')
753 scheme = config.get('scheme', 'https')
754 config['apiurl'] = urljoin(scheme, apisrv)
755 if config.has_key('apisrv') or config.has_key('scheme'):
756 print >>sys.stderr, 'Warning: Use of the \'scheme\' or \'apisrv\' in ~/.oscrc is deprecated!\n' \
757 'Warning: See README for migration details.'
758 if config.has_key('build_platform'):
759 print >>sys.stderr, 'Warning: Use of \'build_platform\' config option is deprecated! (use \'build_repository\' instead)'
760 config['build_repository'] = config['build_platform']
762 config['verbose'] = int(config['verbose'])
763 # override values which we were called with
765 config['verbose'] = override_verbose + 1
768 config['debug'] = override_debug
769 if override_http_debug:
770 config['http_debug'] = override_http_debug
771 if override_traceback:
772 config['traceback'] = override_traceback
773 if override_post_mortem:
774 config['post_mortem'] = override_post_mortem
776 apiurl = aliases.get(override_apiurl, override_apiurl)
777 # check if apiurl is a valid url
778 config['apiurl'] = urljoin(*parse_apisrv_url(None, apiurl))
780 # XXX unless config['user'] goes away (and is replaced with a handy function, or
781 # config becomes an object, even better), set the global 'user' here as well,
782 # provided that there _are_ credentials for the chosen apiurl:
784 config['user'] = get_apiurl_usr(config['apiurl'])
785 except oscerr.ConfigMissingApiurl, e:
786 e.msg = config_missing_apiurl_text % config['apiurl']
790 # finally, initialize urllib2 for to use the credentials for Basic Authentication
791 init_basicauth(config)