1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3# 4# Hardlink only packages used in the build from one directory to another, 5# and updates the RemotePackageRepository file at the same time. 6# 7# Copyright 2017 Augustin Cavalier <waddlesplash> 8# Distributed under the terms of the MIT License. 9 10import sys, os, re, hashlib 11 12if len(sys.argv) < 5: 13 print("usage: hardlink_packages.py [arch] [jam RemotePackageRepository file] " 14 + "[prebuilt packages directory] [destination root directory]") 15 print("note that the [jam RemotePackageRepository file] will be modified.") 16 print("note that [target directory] is assumed to have a 'packages' subdirectory, " 17 + " and a repo.info.template file (using $ARCH$)") 18 sys.exit(1) 19 20args_arch = sys.argv[1] 21args_jamf = sys.argv[2] 22args_src = sys.argv[3] 23args_dst = sys.argv[4] 24 25if not args_dst.endswith('/'): 26 args_dst = args_dst + '/' 27if not args_src.endswith('/'): 28 args_src = args_src + '/' 29 30args_dst_packages = args_dst + 'packages/' 31 32packageVersions = [] 33for filename in os.listdir(args_src): 34 if (not (filename.endswith("-" + args_arch + ".hpkg")) and 35 not (filename.endswith("-any.hpkg"))): 36 continue 37 packageVersions.append(filename) 38 39# Read RemotePackageRepository file and hardlink relevant packages 40pattern = re.compile("^[a-z0-9]") 41newFileForJam = [] 42packageFiles = [] 43filesNotFound = False 44with open(args_jamf) as f: 45 for line in f: 46 pkg = line.strip() 47 if (len(pkg) == 0): 48 continue 49 if not (pattern.match(pkg)): 50 # not a package (probably a Jam directive) 51 newFileForJam.append(line) 52 continue 53 54 try: 55 pkgname = pkg[:pkg.index('-')] 56 except: 57 pkgname = '' 58 if (len(pkgname) == 0): 59 # no version, likely a source/debuginfo listing 60 newFileForJam.append(line) 61 continue 62 63 greatestVersion = None 64 for pkgVersion in packageVersions: 65 if (pkgVersion.startswith(pkgname + '-') and 66 ((greatestVersion == None) or (pkgVersion > greatestVersion))): 67 greatestVersion = pkgVersion 68 if (greatestVersion == None): 69 print("not found: " + pkg) 70 newFileForJam.append(line) 71 filesNotFound = True 72 continue 73 else: 74 # found it, so hardlink it 75 if not (os.path.exists(args_dst_packages + greatestVersion)): 76 os.link(args_src + greatestVersion, args_dst_packages + greatestVersion) 77 if ('packages/' + greatestVersion) not in packageFiles: 78 packageFiles.append('packages/' + greatestVersion) 79 # also hardlink the source package, if one exists 80 srcpkg = greatestVersion.replace("-" + args_arch + ".hpkg", 81 "-source.hpkg").replace('-', '_source-', 1) 82 if os.path.exists(args_src + srcpkg): 83 if not os.path.exists(args_dst_packages + srcpkg): 84 os.link(args_src + srcpkg, args_dst_packages + srcpkg) 85 if ('packages/' + srcpkg) not in packageFiles: 86 packageFiles.append('packages/' + srcpkg) 87 newFileForJam.append("\t" + greatestVersion[:greatestVersion.rfind('-')] + "\n"); 88 89if filesNotFound: 90 sys.exit(1) 91 92finalizedNewFile = "".join(newFileForJam).encode('UTF-8') 93with open(args_jamf, 'wb') as f: 94 f.write(finalizedNewFile) 95 96listhash = hashlib.sha256(finalizedNewFile).hexdigest() 97try: 98 os.mkdir(args_dst + listhash) 99except: 100 print("dir " + listhash + " already exists. No changes?") 101 sys.exit(1) 102 103repodir = args_dst + listhash + '/' 104os.symlink('../packages', repodir + 'packages') 105 106with open(args_dst + 'repo.info.template', 'r') as ritf: 107 repoInfoTemplate = ritf.read() 108 109repoInfoTemplate = repoInfoTemplate.replace("$ARCH$", args_arch) 110with open(repodir + 'repo.info', 'w') as rinf: 111 rinf.write(repoInfoTemplate) 112 113packageFiles.sort() 114with open(repodir + 'package.list', 'w') as pkgl: 115 pkgl.write("\n".join(packageFiles)) 116 117if os.system('cd ' + repodir + ' && package_repo create repo.info ' + " ".join(packageFiles)) != 0: 118 print("failed to create package repo.") 119 sys.exit(1) 120 121if os.system('cd ' + repodir + ' && sha256sum repo >repo.sha256') != 0: 122 print("failed to checksum package repo.") 123 sys.exit(1) 124