Warning, /packaging/kdesdk-devenv-dependencies/packages is written in an unsupported language. File is not indexed.
0001 #!/usr/bin/env python3 0002 0003 import argparse 0004 import sys 0005 import shutil 0006 import subprocess 0007 import operator 0008 from enum import Enum 0009 from functools import reduce 0010 import concurrent.futures 0011 import json 0012 import io 0013 0014 # for apt 0015 import urllib.request 0016 0017 neededFiles = [ 0018 "Qt5CoreConfig.cmake", 0019 "Qt5QuickConfig.cmake", 0020 "Qt5WebEngineConfig.cmake", 0021 0022 "ECMConfig.cmake", 0023 "KF5*Config.cmake", 0024 ] 0025 0026 neededBinaries = [ 0027 "gcc", 0028 "g++", 0029 "cmake", 0030 "cmake-gui", 0031 "git", 0032 "gdb", 0033 "clang", 0034 "make", 0035 "ninja", 0036 "msgfmt" #it's needed when including ki18n 0037 #"clazy", 0038 ] 0039 0040 suggestedBinaries = [ 0041 "plasmaengineexplorer", 0042 "plasmawindowed", 0043 "cuttlefish", 0044 "kate", 0045 "kdevelop" 0046 ] 0047 0048 def progressCallback(progress, type, user_data): 0049 pass 0050 #print(' ', type.value_name, 'package:', progress.props.package_id, ':', progress.props.percentage, '%') 0051 0052 class RequirementType(Enum): 0053 Needed = 0 0054 Suggested = 1 0055 0056 class Contents: 0057 class Connection: 0058 def __init__(self, urlBase = 'https://contents.neon.kde.org/v2'): 0059 self.urlBase = urlBase 0060 0061 def getJSON(self, path): 0062 url = "%s/%s" % (self.urlBase, path) 0063 response = urllib.request.urlopen(url) 0064 ret = json.loads(response.read().decode('utf-8')) 0065 return ret 0066 0067 class Archive: 0068 overrides = { 0069 "usr/bin/gcc": "build-essential", 0070 "usr/bin/g++": "build-essential", 0071 "usr/bin/make": "build-essential" 0072 } 0073 0074 def __init__(self, id): 0075 self.id = id 0076 self.connection = Contents.Connection() 0077 0078 def findFile(self, file): 0079 return self.connection.getJSON(('findFirst/%s?q=*%s' % (self.id, file))) 0080 0081 def findPackageForFile(self, file): 0082 try: 0083 return self.overrides[file] 0084 except: 0085 pass 0086 payload = self.findFile(file) 0087 if not payload: 0088 return None 0089 assert len(payload.keys()) == 1 0090 # Nested list since we don't resolve files, simply pick first. 0091 packages = list(payload.values())[0] 0092 assert len(packages) == 1, "Cannot find which package to use for " + file 0093 return packages[0] 0094 0095 def findAllPackages(self, file): 0096 payload = self.findFile(file) 0097 packages = payload.values() 0098 return [item for sublist in packages for item in sublist] #make sure it's just a list, not a list of lists 0099 0100 poolsCache = None 0101 0102 @classmethod 0103 def pools(klass, connection = Connection()): 0104 if not klass.poolsCache: 0105 klass.poolsCache = connection.getJSON('pools') 0106 return klass.poolsCache 0107 0108 class Global: 0109 repositories = None 0110 backend = "debian" 0111 0112 packages = {} 0113 packagesNotFound = [] 0114 0115 def __init__(self): 0116 values = [ (v, RequirementType.Needed, False) for v in neededFiles] 0117 values += [ (v, RequirementType.Needed, True) for v in neededBinaries] 0118 values += [ (v, RequirementType.Suggested, True) for v in suggestedBinaries] 0119 0120 self.process(values) 0121 0122 def addResults(self, fileName, req, pkgs): 0123 if not pkgs: 0124 self.packagesNotFound.append(fileName) 0125 else: 0126 for p in pkgs: 0127 self.packages[p] = (req, fileName) 0128 0129 def printVerbose(self): 0130 if self.packagesNotFound: 0131 print("Could not find packages for", self.packagesNotFound) 0132 print() 0133 0134 print("We suggest the following packages:") 0135 for pkg, props in self.packages.items(): 0136 print("* ", pkg, "<-", props) 0137 0138 def printPackagesJson(self): 0139 ret = { 0140 "required": [], 0141 "suggested": [] 0142 } 0143 for pkg, (required, filename) in self.packages.items(): 0144 if required == RequirementType.Needed: 0145 ret["required"].append(pkg) 0146 else: 0147 ret["suggested"].append(pkg) 0148 ret["required"].sort() 0149 ret["suggested"].sort() 0150 print(json.dumps(ret, sort_keys=True, indent=4, separators=(',', ': '))) 0151 0152 def printPackages(self): 0153 print(" ".join(self.packages.keys())) 0154 0155 def installPackages(self): 0156 subprocess.call(["pkcon", "install"] + list(self.packages.keys())) 0157 0158 def searchFile(fileName, requirement, isExecutable): 0159 packages = None 0160 0161 #ArchLinux 0162 if Global.backend == "archlinux": 0163 cmd = ["pacman", "--machinereadable", "-F", fileName] 0164 output = subprocess.check_output(cmd) 0165 process = output.split(b'\0') 0166 packages = [ process[1].decode("utf-8") ] # only use the first alternative, pacman will sort them by repository precedence 0167 #Debian 0168 elif Global.backend == "debian": 0169 prefix = "usr/bin/" if isExecutable else "/" 0170 packages = [] 0171 for repo in Contents.pools(): 0172 pkg = Contents.Archive(repo).findPackageForFile(prefix + fileName) 0173 if pkg: 0174 packages = [pkg] 0175 break 0176 # print("pac", fileName, package) 0177 0178 return (fileName, requirement, packages) 0179 0180 def searchGlobFiles(fileName, requirement, isExecutable): 0181 packages = None 0182 0183 #ArchLinux 0184 if Global.backend == "archlinux": 0185 fileNamerx = fileName.replace("*", ".*") 0186 cmd = ["pacman", "--machinereadable", "-Fx", fileNamerx] 0187 output = subprocess.check_output(cmd) 0188 lines = output.split(b'\n') 0189 packages = [line.split(b'\0')[1].decode("utf-8") for line in lines if len(line)>0] 0190 #Debian 0191 elif Global.backend == "debian": 0192 prefix = "usr/bin/" if isExecutable else "/" 0193 packages = [] 0194 for repo in Contents.pools(): 0195 packages = Contents.Archive(repo).findAllPackages(prefix + fileName) 0196 if packages: 0197 break 0198 0199 return (fileName, requirement, packages) 0200 0201 def locate(arg): 0202 (fileName, requirement, isExecutable) = arg 0203 ret = None 0204 if '*' in fileName: 0205 ret = Global.searchGlobFiles(fileName, requirement, isExecutable) 0206 else: 0207 ret = Global.searchFile(fileName, requirement, isExecutable) 0208 return ret 0209 0210 def process(self, values): 0211 with concurrent.futures.ProcessPoolExecutor() as executor: 0212 #for fileName, req, packages in map(Global.locate, values): 0213 for fileName, req, packages in executor.map(Global.locate, values): 0214 self.addResults(fileName, req, packages) 0215 0216 def main(): 0217 parser = argparse.ArgumentParser() 0218 parser.add_argument("command", help="[install|packages|packages-json|list]") 0219 parser.add_argument("backend", choices=["debian", "archlinux"]) 0220 parser.add_argument("--verbose", action='store_true', help="increase output verbosity") 0221 args = parser.parse_args() 0222 0223 Global.backend = args.backend 0224 0225 g = Global() 0226 0227 if args.verbose: 0228 g.printVerbose() 0229 0230 if args.command == "install": 0231 g.installPackages() 0232 elif args.command == "packages": 0233 g.printPackages() 0234 elif args.command == "packages-json": 0235 g.printPackagesJson() 0236 else: 0237 correctCommand = args.command=="list" 0238 if not correctCommand: 0239 print("Wrong command '%s'" % args.command) 0240 print() 0241 0242 print(" install: triggers an install of the needed packages.") 0243 print(" packages: lists the suggested packages, for distributors mostly.") 0244 print(" packages-json: lists the suggested packages, for distributors mostly.") 0245 print(" list: this list") 0246 return 0 if correctCommand else 1 0247 0248 return 0 0249 0250 if __name__ == "__main__": 0251 sys.exit(main())