Mercurial > gub
changeset 3353:1cd50c9b33ea
Refactor gub building into smaller functions. Add bit smarter
conflict resolution.
author | Jan Nieuwenhuizen <janneke@gnu.org> |
---|---|
date | Sun, 29 Apr 2007 10:25:48 +0200 |
parents | 1dd83f9be9a4 |
children | 82b667bc3d7a |
files | bin/gub lib/gub.py lib/gup.py |
diffstat | 3 files changed, 137 insertions(+), 96 deletions(-) [+] |
line wrap: on
line diff
--- a/bin/gub Sat Apr 28 11:17:48 2007 +0200 +++ b/bin/gub Sun Apr 29 10:25:48 2007 +0200 @@ -122,34 +122,38 @@ return p -def checksums_valid (manager, specname, specs): - import pickle - spec = specs[specname] +# FIXME: put all these functions that take manager, settings, specs, deps +# into a 'builder' class? +def pkg_checksum_valid (manager, spec, pkg): + name = pkg.name () + pkg_dict = manager.package_dict (name) - valid = True - for package in spec.get_packages (): - name = package.name() - package_dict = manager.package_dict (name) - - valid = (spec.spec_checksum == package_dict['spec_checksum'] - and spec.source_checksum () == package_dict['source_checksum']) + valid = (spec.spec_checksum == pkg_dict['spec_checksum'] + and spec.source_checksum () == pkg_dict['source_checksum']) - hdr = package.expand ('%(split_hdr)s') - valid = valid and os.path.exists (hdr) - if valid: - hdr_dict = pickle.load (open (hdr)) - hdr_sum = hdr_dict['spec_checksum'] - valid = valid and hdr_sum == spec.spec_checksum - valid = valid and spec.source_checksum () == hdr_dict['source_checksum'] + hdr = pkg.expand ('%(split_hdr)s') + valid = valid and os.path.exists (hdr) + if valid: + import pickle + hdr_dict = pickle.load (open (hdr)) + hdr_sum = hdr_dict['spec_checksum'] + valid = valid and hdr_sum == spec.spec_checksum + valid = valid and spec.source_checksum () == hdr_dict['source_checksum'] - ## let's be lenient for cross packages. + ## let's be lenient for cross pkgs. ## spec.cross_checksum == manager.package_dict(name)['cross_checksum']) + return valid + +def spec_checksums_valid (manager, spec): + valid = True + for pkg in spec.get_packages (): + valid = valid and pkg_checksum_valid (manager, spec, pkg) return valid -def run_one_builder (options, spec_obj): +def run_one_builder (options, spec): import inspect - available = dict (inspect.getmembers (spec_obj, callable)) + available = dict (inspect.getmembers (spec, callable)) if options.stage: (available[options.stage]) () return @@ -169,15 +173,15 @@ if (not available.has_key (stage)): continue - if spec_obj.is_done (stage, stages.index (stage)): + if spec.is_done (stage, stages.index (stage)): tainted = True continue - spec_obj.os_interface.log_command (' *** Stage: %s (%s)\n' - % (stage, spec_obj.name ())) + spec.os_interface.log_command (' *** Stage: %s (%s)\n' + % (stage, spec.name ())) if stage == 'package' and tainted and not options.force_package: - msg = spec_obj.expand ('''Compile was continued from previous run. + msg = spec.expand ('''Compile was continued from previous run. Will not package. Use @@ -189,13 +193,13 @@ to skip this check. ''') - spec_obj.os_interface.log_command (msg) + spec.os_interface.log_command (msg) raise 'abort' if (stage == 'clean' and options.keep_build): - os.unlink (spec_obj.get_stamp_file ()) + os.unlink (spec.get_stamp_file ()) continue try: @@ -204,15 +208,104 @@ ## failed patch will leave system in unpredictable state. if stage == 'patch': - spec_obj.system ('rm %(stamp_file)s') + spec.system ('rm %(stamp_file)s') raise if stage != 'clean': - spec_obj.set_done (stage, stages.index (stage)) + spec.set_done (stage, stages.index (stage)) + +def spec_conflict_resolution (manager, spec, pkg): + pkg_name = pkg.name () + install_candidate = pkg + subname = '' + if spec.name () != pkg_name: + subname = pkg_name.split ('-')[-1] + if spec.get_conflict_dict ().has_key (subname): + for c in spec.get_conflict_dict ()[subname]: + if manager.is_installed (c): + print '%(c)s conflicts with %(pkg_name)s' % locals () + conflict_source = manager.source_name (c) + # FIXME: implicit provides: foo-* provides foo-core, + # should implement explicit provides + if conflict_source + '-core' == pkg_name: + print (' non-core %(conflict_source)s already installed' + % locals ()) + print (' skipping request to install %(pkg_name)s' + % locals ()) + install_candidate = None + continue + manager.uninstall_package (c) + return install_candidate + +def pkg_install (manager, spec, pkg): + if not manager.is_installed (pkg.name ()): + install_candidate = spec_conflict_resolution (manager, spec, pkg) + if install_candidate: + manager.unregister_package_dict (install_candidate.name ()) + manager.register_package_dict (install_candidate.dict ()) + manager.install_package (install_candidate.name ()) + +def spec_install (manager, spec): + for pkg in spec.get_packages (): + pkg_install (manager, spec, pkg) + +def spec_build (settings, manager, specs, spec_name): + spec = specs[spec_name] + all_installed = True + for p in spec.get_packages (): + all_installed = all_installed and manager.is_installed (p.name ()) + if all_installed: + return -# What a mess, what happens here? -def run_builder (options, settings, manager, names, specs): + # ugh, dupe + checksum_ok = (settings.options.lax_checksums + or spec_checksums_valid (manager, specs[spec_name])) + + is_installable = misc.forall (manager.is_installable (p.name ()) + for p in spec.get_packages ()) + + if (settings.options.stage + or not is_installable + or not checksum_ok): + settings.os_interface.log_command ('building package: %s\n' % spec_name) + run_one_builder (settings.options, spec) + + # FIXME, spec_install should be stage? + if settings.options.stage: # and options.stage != spec_install: + return + + # FIXME, spec_install should be stage? + spec_install (manager, spec) + +def uninstall_outdated_specs (settings, manager, specs, deps): + def reverse (lst): + list.reverse (lst) + return lst + for spec_name in reverse (deps[:]): + spec = specs[spec_name] + # ugh, dupe + checksum_ok = (settings.options.lax_checksums + or spec_checksums_valid (manager, specs[spec_name])) + for pkg in spec.get_packages (): + if (manager.is_installed (pkg.name ()) + and (not manager.is_installable (pkg.name ()) + or not checksum_ok)): + manager.uninstall_package (pkg.name ()) + +def build_source_packages (settings, specs, names): + try: + manager = gup.get_target_manager (settings) + + ## Todo: have a readonly lock for local platform + except locker.LockedError: + print 'another build in progress. Skipping.' + if settings.options.skip_if_locked: + sys.exit (0) + raise + + deps = filter (specs.has_key, names) + PATH = os.environ['PATH'] ## cross_prefix is also necessary for building cross packages, such as GCC os.environ['PATH'] = settings.expand ('%(cross_prefix)s/bin:' + PATH, @@ -226,62 +319,14 @@ extra_build_deps = [p.name () for p in sdk_pkgs + cross_pkgs] gup.add_packages_to_manager (manager, settings, specs) - if not options.stage: - reved = names[:] - reved.reverse () - for spec_name in reved: - spec = specs[spec_name] - checksum_ok = (options.lax_checksums - or checksums_valid (manager, spec_name, - specs)) - for p in spec.get_packages (): - if (manager.is_installed (p.name ()) and - (not manager.is_installable (p.name ()) - or not checksum_ok)): - manager.uninstall_package (p.name ()) - - for spec_name in names: - spec = specs[spec_name] - all_installed = True - for p in spec.get_packages (): - all_installed = all_installed and manager.is_installed (p.name ()) - if all_installed: - continue - - # ugh, dupe - checksum_ok = (options.lax_checksums - or checksums_valid (manager, spec_name, specs)) - is_installable = misc.forall (manager.is_installable (p.name ()) - for p in spec.get_packages ()) - - if (options.stage - or not is_installable - or not checksum_ok): - settings.os_interface.log_command ('building package: %s\n' - % spec_name) - run_one_builder (options, spec) - - # FIXME, pkg_install should be stage? - if options.stage: # and options.stage != pkg_install: - continue + # FIXME: what happens here, move to descriptive function? + if not settings.options.stage: + uninstall_outdated_specs (settings, manager, specs, deps) - # FIXME, pkg_install should be stage? - for p in spec.get_packages (): - name = p.name () - if not manager.is_installed (name): - subname = '' - if spec.name () != p.name (): - subname = name.split ('-')[-1] - if spec.get_conflict_dict ().has_key (subname): - for c in spec.get_conflict_dict ()[subname]: - if manager.is_installed (c): - print '%(c)s conflicts with %(name)s' % locals () - manager.uninstall_package (c) - manager.unregister_package_dict (p.name ()) - manager.register_package_dict (p.dict ()) - manager.install_package (p.name ()) - + for spec_name in deps: + spec_build (settings, manager, specs, spec_name) + def get_settings (options): # FIXME, move (all these get_setting*) to constructors settings = settings_mod.get_settings (options.platform) @@ -315,6 +360,7 @@ deps = [gup.get_base_package_name (d) for d in deps] return deps + # FIXME: why do we only use deps for download, not for build? deps = gup.topologically_sorted (files, {}, get_all_deps, None) if settings.options.verbose: print 'deps:' + `deps` @@ -332,18 +378,7 @@ specs[i].download () sys.exit (0) - try: - pm = gup.get_target_manager (settings) - - ## Todo: have a readonly lock for local platform - except locker.LockedError: - print 'another build in progress. Skipping.' - if settings.options.skip_if_locked: - sys.exit (0) - raise - - deps = filter (specs.has_key, names) - run_builder (settings.options, settings, pm, deps, specs) + build_source_packages (settings, specs, names) def main (): cli_parser = get_cli_parser ()
--- a/lib/gub.py Sat Apr 28 11:17:48 2007 +0200 +++ b/lib/gub.py Sun Apr 29 10:25:48 2007 +0200 @@ -31,6 +31,9 @@ self._dict['split_hdr'] = ('%(gub_uploads)s/%(split_name)s%(vc_branch_suffix)s.%(platform)s.hdr') % self._dict self._dict['conflicts_string'] = ';'.join (self._conflicts) self._dict['dependencies_string'] = ';'.join (self._dependencies) + self._dict['source_name'] = self.name () + if sub_name: + self._dict['source_name'] = self.name ()[:-len (sub_name)] def expand (self, s): return s % self._dict
--- a/lib/gup.py Sat Apr 28 11:17:48 2007 +0200 +++ b/lib/gup.py Sun Apr 29 10:25:48 2007 +0200 @@ -309,6 +309,9 @@ FileManager.uninstall_package (self, name) del self._package_dict_db[name] + def source_name (self, name): + return self._packages [name]['source_name'] + def is_string (x): return type (x) == type ('')