diff --git a/osc/build.py b/osc/build.py index 395ad123..10fc79e0 100644 --- a/osc/build.py +++ b/osc/build.py @@ -33,6 +33,11 @@ except ImportError: from .conf import config, cookiejar +try: + from .meter import TextMeter +except: + TextMeter = None + change_personality = { 'i686': 'linux32', 'i586': 'linux32', @@ -161,6 +166,11 @@ class Buildinfo: self.noinstall_list = [ dep.name for dep in self.deps if dep.noinstall ] self.installonly_list = [ dep.name for dep in self.deps if dep.installonly ] + if root.find('preinstallimage') != None: + self.preinstallimage = root.find('preinstallimage') + else: + self.preinstallimage = None + def has_dep(self, name): for i in self.deps: @@ -262,6 +272,55 @@ class Pac: return "%s" % self.name +def get_preinstall_image(apiurl, arch, cache_dir, img_info): + """ + Searches preinstall image according to build info and downloads it to cache. + Returns preinstall image path, source and list of image binaries, which can + be used to create rpmlist. + NOTE: preinstall image can be used only for new build roots! + """ + imagefile = '' + imagesource = '' + img_bins = [] + for bin in img_info.findall('binary'): + img_bins.append(bin.text) + + img_project = img_info.get('project') + img_repository = img_info.get('repository') + img_arch = arch + img_pkg = img_info.get('package') + img_file = img_info.get('filename') + img_hdrmd5 = img_info.get('hdrmd5') + cache_path = '%s/%s/%s/%s' % (cache_dir, img_project, img_repository, img_arch) + ifile_path = '%s/%s' % (cache_path, img_file) + ifile_path_part = '%s.part' % ifile_path + + imagefile = ifile_path + imagesource = "%s/%s/%s [%s]" % (img_project, img_repository, img_pkg, img_hdrmd5) + + if not os.path.exists(ifile_path): + url = "%s/build/%s/%s/%s/%s/%s" % (apiurl, img_project, img_repository, img_arch, img_pkg, img_file) + print("downloading preinstall image %s" % imagesource) + if not os.path.exists(cache_path): + try: + os.makedirs(cache_path, mode=0o755) + except OSError as e: + print('packagecachedir is not writable for you?', file=sys.stderr) + print(e, file=sys.stderr) + sys.exit(1) + if sys.stdout.isatty() and TextMeter: + progress_obj = TextMeter(fo=sys.stdout) + else: + progress_obj = None + gr = OscFileGrabber(progress_obj=progress_obj) + try: + gr.urlgrab(url, filename=ifile_path_part, text='fetching image') + except URLGrabError as e: + print("Failed to download! ecode:%i errno:%i" % (e.code, e.errno)) + return ('', '', []) + # download ok, rename partial file to final file name + os.rename(ifile_path_part, ifile_path) + return (imagefile, imagesource, img_bins) def get_built_files(pacdir, buildtype): if buildtype == 'spec': @@ -781,6 +840,21 @@ def main(apiurl, opts, argv): # implicitly trust the project we are building for check_trusted_projects(apiurl, [ i for i in bi.projects.keys() if not i == prj ]) + imagefile = '' + imagesource = '' + imagebins = [] + if (not config['no_preinstallimage'] and not opts.nopreinstallimage and + bi.preinstallimage and + not opts.noinit and not opts.offline and + (opts.clean or (not os.path.exists(build_root + "/installed-pkg") and + not os.path.exists(build_root + "/.build/init_buildsystem.data")))): + (imagefile, imagesource, imagebins) = get_preinstall_image(apiurl, arch, cache_dir, bi.preinstallimage) + if imagefile: + # remove binaries from build deps which are included in preinstall image + for i in bi.deps: + if i.name in imagebins: + bi.remove_dep(i.name) + # now update the package cache fetcher.run(bi) @@ -981,8 +1055,15 @@ def main(apiurl, opts, argv): rpmlist = [ '%s %s\n' % (i.name, i.fullfilename) for i in bi.deps if not i.noinstall ] else: rpmlist = [ '%s %s\n' % (i.name, i.fullfilename) for i in bi.deps ] + for i in imagebins: + rpmlist.append('%s preinstallimage\n' % i) rpmlist += [ '%s %s\n' % (i[0], i[1]) for i in rpmlist_prefers ] + if imagefile: + rpmlist.append('preinstallimage: %s\n' % imagefile) + if imagesource: + rpmlist.append('preinstallimagesource: %s\n' % imagesource) + rpmlist.append('preinstall: ' + ' '.join(bi.preinstall_list) + '\n') rpmlist.append('vminstall: ' + ' '.join(bi.vminstall_list) + '\n') rpmlist.append('runscripts: ' + ' '.join(bi.runscripts_list) + '\n') diff --git a/osc/commandline.py b/osc/commandline.py index 12afbffd..ba9b4272 100644 --- a/osc/commandline.py +++ b/osc/commandline.py @@ -5810,6 +5810,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. help='perform the build on a remote server - user@server:~/remote/directory') @cmdln.option('--trust-all-projects', action='store_true', help='trust packages from all projects') + @cmdln.option('--nopreinstallimage', '--no-preinstallimage', action='store_true', + help='Do not use preinstall images for creating the build root.') def do_build(self, subcmd, opts, *args): """${cmd_name}: Build a package on your local machine @@ -5903,6 +5905,9 @@ Please submit there instead, or use --nodevelproject to force direct submission. if opts.offline and opts.preload: raise oscerr.WrongOptions('--offline and --preload are mutually exclusive') + if opts.preload: + opts.nopreinstallimage = True + print('Building %s for %s/%s' % (args[2], args[0], args[1])) if not opts.host: return osc.build.main(self.get_api_url(), opts, args) diff --git a/osc/conf.py b/osc/conf.py index 100259aa..523b3652 100644 --- a/osc/conf.py +++ b/osc/conf.py @@ -128,6 +128,7 @@ DEFAULTS = {'apiurl': 'https://api.opensuse.org', 'http_full_debug': '0', 'http_retries': '3', 'verbose': '1', + 'no_preinstallimage': '0', 'traceback': '0', 'post_mortem': '0', 'use_keyring': '0', @@ -188,7 +189,7 @@ config = DEFAULTS.copy() boolean_opts = ['debug', 'do_package_tracking', 'http_debug', 'post_mortem', 'traceback', 'check_filelist', 'plaintext_passwd', 'checkout_no_colon', 'checkout_rooted', 'check_for_request_on_action', 'linkcontrol', 'show_download_progress', 'request_show_interactive', 'request_show_source_buildstatus', 'review_inherit_group', 'use_keyring', 'gnome_keyring', 'no_verify', 'builtin_signature_check', - 'http_full_debug', 'include_request_from_project', 'local_service_run', 'buildlog_strip_time'] + 'http_full_debug', 'include_request_from_project', 'local_service_run', 'buildlog_strip_time', 'no_preinstallimage'] api_host_options = ['user', 'pass', 'passx', 'aliases', 'http_headers', 'email', 'sslcertck', 'cafile', 'capath', 'trusted_prj']