architecture.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. """architecture matching
  2. @copyright: 2014, Ansgar Burchardt <ansgar@debian.org>
  3. @license: GPL-2+
  4. """
  5. # This program is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation; either version 2 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. import errno
  19. def _load_table(path):
  20. table = []
  21. with open(path, 'r') as fh:
  22. for line in fh:
  23. if not line or line.startswith('#'):
  24. continue
  25. table.append(line.split())
  26. return table
  27. _cached_cputable = None
  28. def _cputable():
  29. global _cached_cputable
  30. if _cached_cputable is None:
  31. _cached_cputable = _load_table('/usr/share/dpkg/cputable')
  32. return _cached_cputable
  33. _cached_arch2tuple = None
  34. _cached_tuple2arch = None
  35. def _tupletable():
  36. global _cached_arch2tuple, _cached_tuple2arch
  37. if _cached_arch2tuple is None or _cached_tuple2arch is None:
  38. try:
  39. tripletable = False
  40. table = _load_table('/usr/share/dpkg/tupletable')
  41. except OSError as e:
  42. if e.errno != errno.ENOENT:
  43. raise
  44. tripletable = True
  45. table = _load_table('/usr/share/dpkg/triplettable')
  46. arch2tuple = {}
  47. tuple2arch = {}
  48. def add_tuple(tuple, arch):
  49. if tripletable:
  50. tuple = "base-{}".format(tuple)
  51. arch2tuple[arch] = tuple
  52. tuple2arch[tuple] = arch
  53. for row in table:
  54. if '<cpu>' in row[0] or '<cpu>' in row[1]:
  55. for cpu in _cputable():
  56. replaced_row = [column.replace('<cpu>', cpu[0]) for column in row]
  57. add_tuple(replaced_row[0], replaced_row[1])
  58. else:
  59. add_tuple(row[0], row[1])
  60. _cached_arch2tuple = arch2tuple
  61. _cached_tuple2arch = tuple2arch
  62. return _cached_tuple2arch, _cached_arch2tuple
  63. class InvalidArchitecture(Exception):
  64. pass
  65. def Debian_arch_to_Debian_tuple(arch: str):
  66. parts = arch.split('-')
  67. # Handle architecture wildcards
  68. if 'any' in parts:
  69. if len(parts) == 4:
  70. return parts
  71. elif len(parts) == 3:
  72. return 'any', parts[0], parts[1], parts[2]
  73. elif len(parts) == 2:
  74. return 'any', 'any', parts[0], parts[1]
  75. else:
  76. return 'any', 'any', 'any', 'any'
  77. if len(parts) == 2 and parts[0] == 'linux':
  78. arch = parts[1]
  79. tuple = _tupletable()[1].get(arch, None)
  80. if tuple is None:
  81. return None
  82. return tuple.split('-', 3)
  83. def match_architecture(arch: str, wildcard: str) -> bool:
  84. # 'all' has no valid tuple
  85. if arch == 'all' or wildcard == 'all':
  86. return arch == wildcard
  87. if wildcard == 'any' or arch == wildcard:
  88. return True
  89. tuple_arch = Debian_arch_to_Debian_tuple(arch)
  90. tuple_wildcard = Debian_arch_to_Debian_tuple(wildcard)
  91. if tuple_arch is None or len(tuple_arch) != 4:
  92. raise InvalidArchitecture('{0} is not a valid architecture name'.format(arch))
  93. if tuple_wildcard is None or len(tuple_wildcard) != 4:
  94. raise InvalidArchitecture('{0} is not a valid architecture name or wildcard'.format(wildcard))
  95. for i in range(0, 4):
  96. if tuple_arch[i] != tuple_wildcard[i] and tuple_wildcard[i] != 'any':
  97. return False
  98. return True