/pyportage.py

https://github.com/meeuw/portage-python
Python | 137 lines | 128 code | 9 blank | 0 comment | 38 complexity | 5bf2db626808605e8051ff2db365e54e MD5 | raw file
  1. import subprocess
  2. import re
  3. import os
  4. import struct
  5. import sys
  6. import glob
  7. import shutil
  8. class XPAK():
  9. def __getitem__(self, index):
  10. self.f.seek(-self.data_len-16 + self.index[index][0],2)
  11. return self.f.read(self.index[index][1])
  12. def __init__(self, f):
  13. self.f = f
  14. self.f.seek(-4, 2)
  15. if self.f.read(4) != 'STOP':
  16. print 'oops'
  17. self.f.seek(-8,2)
  18. xpak_offset = struct.unpack('>I',self.f.read(4))[0]
  19. self.f.seek(-xpak_offset - 8,2)
  20. if self.f.read(8) != 'XPAKPACK':
  21. print 'oops'
  22. self.index_len = struct.unpack('>I',self.f.read(4))[0]
  23. self.data_len = struct.unpack('>I',self.f.read(4))[0]
  24. index_i = 0
  25. self.index = {}
  26. while index_i < self.index_len:
  27. pathname_len = struct.unpack('>I',self.f.read(4))[0]
  28. pathname = self.f.read(pathname_len)
  29. self.index[pathname] = (struct.unpack('>I',self.f.read(4))[0],
  30. struct.unpack('>I',self.f.read(4))[0])
  31. index_i += pathname_len+12
  32. def splitebuildname(d):
  33. ret = {}
  34. if d.startswith('>=') or d.startswith('<='):
  35. ret['operator'] = d[:2]
  36. d = d[2:]
  37. if d.startswith('>') or d.startswith('<') or d.startswith('~'):
  38. ret['operator'] = d[0]
  39. d = d[1:]
  40. if '/' in d:
  41. s = d.split('/')
  42. ret['cat'] = s[0]
  43. d = s[1]
  44. if ':' in d:
  45. s = d.split(':')
  46. ret['slot'] = s[1]
  47. d = s[0]
  48. else:
  49. ret['slot'] = '0'
  50. m = re.match('(.*)-([0-9].*)', d)
  51. if m:
  52. ret['pn'] = m.groups()[0]
  53. ret['pv'] = m.groups()[1]
  54. else:
  55. ret['pn'] = d
  56. ret['pv'] = 0
  57. return ret
  58. def ebuild_digest(ebuild):
  59. devnull = open('/dev/null', 'w')
  60. subprocess.Popen(['ebuild',ebuild,'digest'], stdout=devnull, stderr=devnull).communicate()
  61. def dummyebuild(d):
  62. s = splitebuildname(d)
  63. ebuild = '/usr/portage/%(cat)s/%(pn)s/%(pn)s-%(pv)s.ebuild' % s
  64. ebuild_data = 'SLOT="%s"' % s['slot']
  65. os.makedirs('/usr/portage/%(cat)s/%(pn)s' % s)
  66. f = open(ebuild, 'w').write(ebuild_data)
  67. ebuild_digest(ebuild)
  68. def emerge(args):
  69. fcat = open('/usr/portage/profiles/categories','w')
  70. fcat.write('what-ever\n')
  71. fcat.flush()
  72. while 1:
  73. p = subprocess.Popen(['emerge']+args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  74. stdout, stderr = p.communicate()
  75. if 'has a category that is not listed' in stderr:
  76. for line in stderr.splitlines():
  77. if 'has a category that is not listed' in line:
  78. fcat.write("%s\n" % line.split("'")[1].split('/')[0])
  79. fcat.flush()
  80. elif 'emerge: there are no ebuilds to satisfy' in stdout:
  81. for line in stdout.splitlines():
  82. if line.startswith('emerge: there are no ebuilds to satisfy "'):
  83. d = line.split('"')[1]
  84. dummyebuild(d)
  85. elif 'or don\'t exist:' in stderr:
  86. found = False
  87. for line in stderr.splitlines():
  88. if found:
  89. ds = line.split(' ')
  90. for d in ds: dummyebuild(d)
  91. break
  92. if line.startswith('!!! masked or don\'t exist:'): found = True
  93. else:
  94. return [stdout, stderr]
  95. if __name__ == "__main__":
  96. if sys.argv[1] == 'splitebuildname':
  97. print splitebuildname(sys.argv[2])
  98. elif sys.argv[1] == 'emerge':
  99. stdin, stderr = emerge(sys.argv[2:])
  100. print stdin, stderr
  101. elif sys.argv[1] == 'RDEPEND':
  102. p = sys.argv[3]
  103. ftbz2 = open(p+'.tbz2')
  104. pn = sys.argv[2]
  105. x = XPAK(ftbz2)
  106. for dir in glob.glob('/usr/portage/*-*')+glob.glob('/usr/portage/virtual*'): shutil.rmtree(dir)
  107. try:
  108. os.remove('/usr/portage/profiles/categories')
  109. except:
  110. pass
  111. os.makedirs('/usr/portage/what-ever/'+pn)
  112. ebuild = '/usr/portage/what-ever/'+pn+'/'+p+'.ebuild'
  113. febuild = open(ebuild, 'w')
  114. if 'RDEPEND' in x.index: RDEPEND = x['RDEPEND'][:-1]
  115. else: RDEPEND = ''
  116. febuild.write('''RDEPEND="%s"
  117. SLOT="%s"
  118. EAPI="%s"''' % (RDEPEND, x['SLOT'][:-1], x['EAPI'][:-1]))
  119. febuild.close()
  120. ebuild_digest(ebuild)
  121. for line in emerge(['-op', 'what-ever/'+pn])[1].splitlines():
  122. if line.startswith('[ebuild'):
  123. print splitebuildname(re.split('\[ebuild.*\] ', line)[1][:-1])['pn']
  124. for dir in glob.glob('/usr/portage/*-*')+glob.glob('/usr/portage/virtual'): shutil.rmtree(dir)
  125. try:
  126. os.remove('/usr/portage/profiles/categories')
  127. except:
  128. pass