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.""" 

11 

12import collections 

13 

14from debian.debian_support import BaseVersion, version_compare 

15 

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} 

24 

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} 

33 

34 

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' 

45 

46 deriv_epoch, deriv_upstream, deriv_revision = split_version(a) 

47 parent_epoch, parent_upstream, parent_revision = split_version(b) 

48 

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' 

63 

64 

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 

77 

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')) 

83 

84 pkglist = [v for v in all_pkgs.values() if v['category'] != 'equal'] 

85 

86 # Sort by category first, and then by name 

87 pkglist.sort(key=lambda x: (CATEGORIES_PRIORITY[x['category']], x['name'])) 

88 

89 return pkglist 

90 

91 

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 '~')