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-2019 Augustin Cavalier <waddlesplash> 8# Distributed under the terms of the MIT License. 9 10import sys, os, subprocess, 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 20if subprocess.run(['package_repo'], None, None, None, 21 subprocess.DEVNULL, subprocess.PIPE).returncode != 1: 22 print("package_repo command does not seem to exist.") 23 sys.exit(1) 24 25args_arch = sys.argv[1] 26args_jamf = sys.argv[2] 27args_src = sys.argv[3] 28args_dst = sys.argv[4] 29 30if not args_dst.endswith('/'): 31 args_dst = args_dst + '/' 32if not args_src.endswith('/'): 33 args_src = args_src + '/' 34 35args_dst_packages = args_dst + 'packages/' 36 37packageVersions = [] 38for filename in os.listdir(args_src): 39 if (not (filename.endswith("-" + args_arch + ".hpkg")) and 40 not (filename.endswith("-any.hpkg"))): 41 continue 42 packageVersions.append(filename) 43 44# Read RemotePackageRepository file and hardlink relevant packages 45pattern = re.compile("^[a-z0-9]") 46newFileForJam = [] 47packageFiles = [] 48filesNotFound = False 49with open(args_jamf) as f: 50 for line in f: 51 pkg = line.strip() 52 if (len(pkg) == 0): 53 continue 54 if not (pattern.match(pkg)): 55 # not a package (probably a Jam directive) 56 newFileForJam.append(line) 57 continue 58 59 try: 60 pkgname = pkg[:pkg.index('-')] 61 except: 62 pkgname = '' 63 if (len(pkgname) == 0): 64 # no version, likely a source/debuginfo listing 65 newFileForJam.append(line) 66 continue 67 68 greatestVersion = None 69 for pkgVersion in packageVersions: 70 if (pkgVersion.startswith(pkgname + '-') and 71 ((greatestVersion == None) or (pkgVersion > greatestVersion))): 72 greatestVersion = pkgVersion 73 if (greatestVersion == None): 74 print("not found: " + pkg) 75 newFileForJam.append(line) 76 filesNotFound = True 77 continue 78 else: 79 # found it, so hardlink it 80 if not (os.path.exists(args_dst_packages + greatestVersion)): 81 os.link(args_src + greatestVersion, args_dst_packages + greatestVersion) 82 if ('packages/' + greatestVersion) not in packageFiles: 83 packageFiles.append('packages/' + greatestVersion) 84 # also hardlink the source package, if one exists 85 srcpkg = greatestVersion.replace("-" + args_arch + ".hpkg", 86 "-source.hpkg").replace('-', '_source-', 1) 87 if os.path.exists(args_src + srcpkg): 88 if not os.path.exists(args_dst_packages + srcpkg): 89 os.link(args_src + srcpkg, args_dst_packages + srcpkg) 90 if ('packages/' + srcpkg) not in packageFiles: 91 packageFiles.append('packages/' + srcpkg) 92 newFileForJam.append("\t" + greatestVersion[:greatestVersion.rfind('-')] + "\n"); 93 94if filesNotFound: 95 sys.exit(1) 96 97finalizedNewFile = "".join(newFileForJam).encode('UTF-8') 98with open(args_jamf, 'wb') as f: 99 f.write(finalizedNewFile) 100 101listhash = hashlib.sha256(finalizedNewFile).hexdigest() 102try: 103 os.mkdir(args_dst + listhash) 104except: 105 print("dir " + listhash + " already exists. No changes?") 106 sys.exit(1) 107 108repodir = args_dst + listhash + '/' 109os.symlink('../packages', repodir + 'packages') 110 111with open(args_dst + 'repo.info.template', 'r') as ritf: 112 repoInfoTemplate = ritf.read() 113 114repoInfoTemplate = repoInfoTemplate.replace("$ARCH$", args_arch) 115with open(repodir + 'repo.info', 'w') as rinf: 116 rinf.write(repoInfoTemplate) 117 118packageFiles.sort() 119with open(repodir + 'package.list', 'w') as pkgl: 120 pkgl.write("\n".join(packageFiles)) 121 122if os.system('cd ' + repodir + ' && package_repo create repo.info ' + " ".join(packageFiles)) != 0: 123 print("failed to create package repo.") 124 sys.exit(1) 125 126if os.system('cd ' + repodir + ' && sha256sum repo >repo.sha256') != 0: 127 print("failed to checksum package repo.") 128 sys.exit(1) 129