xref: /haiku/src/tools/hardlink_packages.py (revision 5ac9b506412b11afb993bb52d161efe7666958a5)
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