1# Copyright 2014 The Distro Tracker Developers
2# See the COPYRIGHT file at the top-level directory of this distribution and
3# at https://deb.li/DTAuthors
4#
5# This file is part of Distro Tracker. It is subject to the license terms
6# in the LICENSE file found in the top-level directory of this
7# distribution and at https://deb.li/DTLicense. No part of Distro Tracker,
8# including this file, may be copied, modified, propagated, or distributed
9# except according to the terms contained in the LICENSE file.
10"""Helper functions for distro_tracker.derivative."""
12import collections
14from debian.debian_support import BaseVersion, version_compare
16CATEGORIES_VERSION_COMPARISON = {
17 'missing_pkg': 'Packages missing in the derivative',
18 'older_version': 'Packages with older upstream version',
19 'older_revision': 'Packages with older Debian revision',
20 'new_pkg': 'Packages specific to the derivative',
21 'newer_version': 'Packages with newer upstream version',
22 'newer_revision': 'Packages with newer Debian revision'
23}
25CATEGORIES_PRIORITY = {
26 'older_version': 1,
27 'older_revision': 2,
28 'missing_pkg': 3,
29 'new_pkg': 4,
30 'newer_version': 5,
31 'newer_revision': 6
32}
35def categorize_version_comparison(a, b):
36 """Returns an identifier that categorizes the difference
37 between a and b. The identifier can be looked up in
38 CATEGORIES_VERSION_COMPARISON to have a long description."""
39 if a == b:
40 return 'equal'
41 if a is None:
42 return 'missing_pkg'
43 if b is None:
44 return 'new_pkg'
46 deriv_epoch, deriv_upstream, deriv_revision = split_version(a)
47 parent_epoch, parent_upstream, parent_revision = split_version(b)
49 if deriv_epoch == parent_epoch:
50 if deriv_upstream == parent_upstream:
51 if version_compare(deriv_revision, parent_revision) < 0:
52 return 'older_revision'
53 else:
54 return 'newer_revision'
55 elif version_compare(deriv_upstream, parent_upstream) < 0:
56 return 'older_version'
57 else:
58 return 'newer_version'
59 elif version_compare(deriv_epoch, parent_epoch) < 0: 59 ↛ 62line 59 didn't jump to line 62, because the condition on line 59 was never false
60 return 'older_version'
61 else:
62 return 'newer_version'
65def compare_repositories(deriv_repository, parent_repository):
66 """Build a list with results of comparisons for each package."""
67 # create a dict with all source packages and versions
68 all_pkgs = collections.defaultdict(lambda: {})
69 for name, version in deriv_repository.source_entries.values_list(
70 'source_package__source_package_name__name',
71 'source_package__version'):
72 all_pkgs[name]['deriv_version'] = version
73 for name, version in parent_repository.source_entries.values_list(
74 'source_package__source_package_name__name',
75 'source_package__version'):
76 all_pkgs[name]['parent_version'] = version
78 for pkg in all_pkgs:
79 all_pkgs[pkg]['name'] = pkg
80 all_pkgs[pkg]['category'] = categorize_version_comparison(
81 all_pkgs[pkg].get('deriv_version'),
82 all_pkgs[pkg].get('parent_version'))
84 pkglist = [v for v in all_pkgs.values() if v['category'] != 'equal']
86 # Sort by category first, and then by name
87 pkglist.sort(key=lambda x: (CATEGORIES_PRIORITY[x['category']], x['name']))
89 return pkglist
92def split_version(version):
93 """Split the version in its 3 components (epoch, version, revision)."""
94 baseversion = BaseVersion(version)
95 return (baseversion.epoch or '~', baseversion.upstream_version or '~',
96 baseversion.debian_revision or '~')