⛏️ index : haiku.git

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Hardlink only packages used in the build from one directory to another,
# and updates the RemotePackageRepository file at the same time.
#
# Copyright 2017-2020 Augustin Cavalier <waddlesplash>
# Distributed under the terms of the MIT License.

import sys, os, subprocess, re, hashlib
from pkg_resources import parse_version

# Detect architecture from provided jam remote package repo file
def probe_architecture(jamf):
	text = ""
	with open(jamf) as f:
		for readline in f:
			line_strip = readline.strip()
			text += line_strip
	return text.split(":")[1].strip()

if len(sys.argv) != 4:
	print("usage: hardlink_packages.py [jam RemotePackageRepository file] "
		+ "[prebuilt packages directory] [destination root directory]")
	print("  note that the [jam RemotePackageRepository file] will be modified.")
	print("  note that [target directory] is assumed to have a 'packages' subdirectory, "
		+ "and a repo.info.template file (using $ARCH$)")
	sys.exit(1)

if subprocess.run(['package_repo'], None, None, None,
		subprocess.DEVNULL, subprocess.PIPE).returncode != 1:
	print("package_repo command does not seem to exist.")
	sys.exit(1)

args_jamf = sys.argv[1]
args_src = sys.argv[2]
args_dst = sys.argv[3]
arch = probe_architecture(args_jamf)

print("Detected Architecture: " + arch)

if not args_dst.endswith('/'):
	args_dst = args_dst + '/'
if not args_src.endswith('/'):
	args_src = args_src + '/'

args_dst_packages = args_dst + 'packages/'

packageVersions = []
for filename in os.listdir(args_src):
	if (not (filename.endswith("-" + arch + ".hpkg")) and
			not (filename.endswith("-any.hpkg"))):
		continue
	packageVersions.append(filename)

# Read RemotePackageRepository file and hardlink relevant packages
pattern = re.compile("^[a-z0-9]")
newFileForJam = []
packageFiles = []
filesNotFound = False
with open(args_jamf) as f:
	for line in f:
		pkg = line.strip()
		if (len(pkg) == 0):
			continue
		if not (pattern.match(pkg)):
			# not a package (probably a Jam directive)
			newFileForJam.append(line)
			continue

		try:
			pkgname = pkg[:pkg.index('-')]
		except:
			pkgname = ''
		if (len(pkgname) == 0):
			# no version, likely a source/debuginfo listing
			newFileForJam.append(line)
			continue

		greatestVersion = None
		for pkgVersion in packageVersions:
			if (pkgVersion.startswith(pkgname + '-')):
				if ((greatestVersion == None) or parse_version(pkgVersion) > parse_version(greatestVersion)):
					greatestVersion = pkgVersion
		if (greatestVersion == None):
			print("not found: " + pkg)
			newFileForJam.append(line)
			filesNotFound = True
			continue
		else:
			# found it, so hardlink it
			if not (os.path.exists(args_dst_packages + greatestVersion)):
				os.link(args_src + greatestVersion, args_dst_packages + greatestVersion)
			if ('packages/' + greatestVersion) not in packageFiles:
				packageFiles.append('packages/' + greatestVersion)
			# also hardlink the source package, if one exists
			srcpkg = greatestVersion.replace("-" + arch + ".hpkg",
				"-source.hpkg").replace('-', '_source-', 1)
			if os.path.exists(args_src + srcpkg):
				if not os.path.exists(args_dst_packages + srcpkg):
					os.link(args_src + srcpkg, args_dst_packages + srcpkg)
				if ('packages/' + srcpkg) not in packageFiles:
					packageFiles.append('packages/' + srcpkg)
		newFileForJam.append("\t" + greatestVersion[:greatestVersion.rfind('-')] + "\n");

if filesNotFound:
	sys.exit(1)

finalizedNewFile = "".join(newFileForJam).encode('UTF-8')
with open(args_jamf, 'wb') as f:
	f.write(finalizedNewFile)

listhash = hashlib.sha256(finalizedNewFile).hexdigest()
try:
	os.mkdir(args_dst + listhash)
except:
	print("dir " + listhash + " already exists. No changes?")
	sys.exit(1)

repodir = args_dst + listhash + '/'
os.symlink('../packages', repodir + 'packages')

with open(args_dst + 'repo.info.template', 'r') as ritf:
	repoInfoTemplate = ritf.read()

repoInfoTemplate = repoInfoTemplate.replace("$ARCH$", arch)
with open(repodir + 'repo.info', 'w') as rinf:
	rinf.write(repoInfoTemplate)

packageFiles.sort()
with open(repodir + 'package.list', 'w') as pkgl:
	pkgl.write("\n".join(packageFiles))

if os.system('cd ' + repodir + ' && package_repo create repo.info ' + " ".join(packageFiles)) != 0:
	print("failed to create package repo.")
	sys.exit(1)

if os.system('cd ' + repodir + ' && sha256sum repo >repo.sha256') != 0:
	print("failed to checksum package repo.")
	sys.exit(1)