def main(options, args): # For latest version of each package in the destination distribution, # locate the latest in the source distribution; calculate the base from # the destination if options.package: logger.info("Skipping stats since -p was specified.") return logger.info('Collecting stats...') for target in config.targets(args): stats = {} stats["total"] = 0 stats["local"] = 0 stats["unmodified"] = 0 stats["needs-sync"] = 0 stats["needs-merge"] = 0 stats["repackaged"] = 0 stats["modified"] = 0 for pkg in target.distro.packages(target.dist, target.component): update_info = UpdateInfo(pkg) upstream = update_info.upstream_version base = update_info.base_version our_version = pkg.newestVersion() if our_version.version != update_info.version: logger.debug("Skip %s, no UpdateInfo", pkg.name) continue stats['total'] += 1 logger.debug("%s: %s, upstream: %s", target.distro, our_version, upstream) if upstream is None: logger.debug("%s: locally packaged", pkg) stats["local"] += 1 continue if our_version.version == upstream: logger.debug("%s: unmodified", pkg) stats["unmodified"] += 1 elif base > upstream: logger.debug("%s: locally repackaged", pkg) stats["repackaged"] += 1 elif our_version.version == base: logger.debug("%s: needs sync", pkg) stats["needs-sync"] += 1 elif our_version.version < upstream: logger.debug("%s: needs merge", pkg) stats["needs-merge"] += 1 elif "-0co" in str(our_version.version): logger.debug("%s: locally repackaged", pkg) stats["repackaged"] += 1 else: logger.debug("%s: modified", pkg) stats["modified"] += 1 write_stats(target.name, stats)
def test_noBase(self): th.build_and_import_simple_package('foo', '1.0-1mom1', self.target_repo) target = config.targets()[0] th.update_all_distro_sources() pv = target.distro.findPackage('foo', version='1.0-1mom1')[0] update_sources.handle_package(target, pv.package) update_info = UpdateInfo(pv.package) self.assertIsNone(update_info.base_version)
def test_ourVersionNewer(self): th.build_and_import_simple_package('foo', '2.0', self.target_repo) th.build_and_import_simple_package('foo', '1.0', self.source1_repo) target = config.targets()[0] th.update_all_distro_sources() pv = target.distro.findPackage('foo', version='2.0')[0] update_sources.handle_package(target, pv.package) update_info = UpdateInfo(pv.package) self.assertEqual(update_info.upstream_version, '1.0')
def test_unmodifiedUpgrade(self): testhelper.build_and_import_simple_package('foo', '1.0', self.target_repo) testhelper.build_and_import_simple_package('foo', '2.0', self.source1_repo) target = config.targets()[0] testhelper.update_all_distro_sources() pv = target.distro.findPackage('foo', version='1.0')[0] update_sources.handle_package(target, pv.package) update_info = UpdateInfo(pv.package) self.assertEqual(update_info.upstream_version, '2.0') self.assertEqual(update_info.base_version, '1.0')
def test_baseFromChangelog(self): foo = th.build_and_import_simple_package('foo', '3.0-1', self.source1_repo) foo.changelog_entry('4.0-1mom1') foo.create_orig() foo.build() self.target_repo.importPackage(foo) target = config.targets()[0] th.update_all_distro_sources() pv = target.distro.findPackage('foo', version='4.0-1mom1')[0] update_sources.handle_package(target, pv.package) update_info = UpdateInfo(pv.package) self.assertEqual(update_info.base_version, '3.0-1')
def handle_package(target, package, force=False, specific_upstream=None): # Store our results in a UpdateInfo file and use that to avoid repeating # the work we do below. update_info = UpdateInfo(package) # Find the PackageVersion that we will look to update from upstream, # and download its sources. pv = package.newestVersion() logger.debug('Handling package %s with UpdateInfo %s', pv, update_info) pv.download() # Look at the upstreams and figure out which is the right version to # upgrade to. upstream = find_upstream(target, pv, specific_upstream) if upstream is not None: upstream_version = upstream.version else: upstream_version = None # Make that new version available for the upgrade process if upstream is not None and upstream > pv: upstream.download() # If UpdateInfo is already recorded to upgrade this version to the # detected upstream (or a better version), then nothing has changed since # last time and we do not need to repeat that work. if not force and update_info.version == pv.version \ and ((update_info.upstream_version is not None and upstream_version is not None and update_info.upstream_version >= upstream_version) or update_info.upstream_version == upstream_version): logger.debug('Using existing base info for base=%s upstream=%s', pv, upstream) return update_info.set_version(pv.version) update_info.set_upstream_version(upstream_version) update_info.set_specific_upstream(specific_upstream) # Now we try to figure out which version that our package is based # upon, and we make a strong effort to download that version to # a local pool. base_version = pv.version.base() update_info.set_base_version(base_version) # If our version number is the same as the base then that means # we have taken the package as-is from upstream, so no merging # is necessary. if base_version == pv.version: logger.debug('%s is unmodified from upstream', pv) update_info.save() return # If we already have the base version present in a local pool # then we have nothing else to do. pool_versions = target.getAllPoolVersions(pv.package.name) pool_versions = map(lambda x: x.version, pool_versions) if base_version in pool_versions: logger.info('%s base %s was found in local pool', pv, base_version) update_info.save() return # Look for the base package in one of our standard distros and # download it from there. if find_and_download_package(target, pv.package.name, base_version): update_info.save() return # Fall back on checking snapshot.debian.org debsnap_versions = get_debian_snapshot_versions(pv.package.name) if base_version in debsnap_versions: ret = download_from_debsnap(pv.package.poolPath, pv.package.name, base_version) if ret: update_info.save() return # Fall back on plucking the file from the source distro server ret = download_removed_package(pv.package.poolPath, target, pv.package.name, base_version) if ret: update_info.save() return # We can't find that base version anywhere. Examine our package # changelog and see if we have access to any of the other previous # versions there. They might be close enough to enable a 3-way merge. logging.debug('Checking changelog for older base versions') unpacked_dir = unpack_source(pv) changelog_versions = read_changelog(unpacked_dir + '/debian/changelog') found = None for cl_version, text in changelog_versions: # Only consider versions that correspond to unmodified packages if cl_version.base() != cl_version: continue logger.debug('Considering changelog version %s', cl_version) # Do we have it in the pool? if cl_version in pool_versions: logger.debug('Found %s in pool', cl_version) found = cl_version break # Can we get it from a standard distro? if find_and_download_package(target, pv.package.name, cl_version): found = cl_version break # Can we get it with debsnap? if cl_version in debsnap_versions: ret = download_from_debsnap(pv.package.poolPath, pv.package.name, cl_version) if ret: found = cl_version break cleanup_source(pv) if found: logger.info('Couldn\'t find %s true base %s, using %s instead', pv, base_version, found) update_info.set_base_version(found) update_info.save() return # None of the above approaches worked, so we won't be able to merge. # Record this and move on. logger.info('Failed to find base for %s', pv) update_info.set_base_version(None) update_info.save()