blob: e3bb845b9222086f38a2a17bb48a292947cd85a9 [file] [log] [blame]
Philipp Schrader0e19c602018-03-07 21:07:22 -08001#!/usr/bin/env python3
2
3import sys
4import os
5import re
6import subprocess
7import tempfile
8import argparse
9import hashlib
10
11def get_deps(package):
Brian Silverman4c7235a2021-11-17 19:04:37 -080012 env = dict(os.environ)
13 del env['LD_LIBRARY_PATH']
14 out = subprocess.check_output(["apt-rdepends", package], env=env)
Philipp Schrader0e19c602018-03-07 21:07:22 -080015 deps = out.splitlines()
16 return set([dep for dep in deps if not dep.startswith(b" ")])
17
18def get_all_deps(packages):
19 deps = set()
Philipp Schraderaedfc5c2018-03-10 19:32:30 -080020 for package in packages or ():
Philipp Schrader0e19c602018-03-07 21:07:22 -080021 deps.update(get_deps(package))
22 return deps
23
Brian Silverman6470f442018-08-05 12:08:16 -070024def map_virtual_packages(packages):
25 '''Maps known virtual packages to the preferred concrete packages which
26 provide them.'''
27 for package in packages:
28 if package == b'python-numpy-abi9':
29 yield b'python-numpy'
30 continue
31 if package == b'python3-numpy-abi9':
32 yield b'python3-numpy'
33 continue
Tyler Chatow60671d32020-02-26 19:49:30 -080034 if package == b'libjack-0.125':
35 yield b'libjack-jackd2-0'
36 continue
37 if package == b'fonts-freefont':
38 yield b'fonts-freefont-ttf'
39 continue
40 if package == b'gsettings-backend':
41 yield b'dconf-gsettings-backend'
42 continue
43 if package == b'gdal-abi-2-4-0':
44 yield b'libgdal20'
45 continue
46 if package == b'libglu1':
47 yield b'libglu1-mesa'
48 continue
49 if package == b'liblapack.so.3':
50 yield b'liblapack3'
51 continue
52 if package == b'libopencl1':
53 yield b'ocl-icd-libopencl1'
54 continue
Brian Silverman4c7235a2021-11-17 19:04:37 -080055 if package == b'libgcc1':
56 yield b'libgcc-s1'
57 continue
58 if package == b'libopencl-1.2-1':
59 yield b'ocl-icd-libopencl1'
60 continue
Tyler Chatow60671d32020-02-26 19:49:30 -080061 if package == b'libblas.so.3':
62 yield b'libblas3'
63 continue
Brian Silverman6470f442018-08-05 12:08:16 -070064 yield package
65
Philipp Schraderaedfc5c2018-03-10 19:32:30 -080066def download_deps(packages, excludes, force_includes):
Philipp Schrader0e19c602018-03-07 21:07:22 -080067 deps = get_all_deps(packages)
68 exclude_deps = get_all_deps(excludes)
69 deps -= exclude_deps
Philipp Schraderaedfc5c2018-03-10 19:32:30 -080070 force_include_deps = get_all_deps(force_includes)
71 deps |= force_include_deps
Brian Silverman4c7235a2021-11-17 19:04:37 -080072 env = dict(os.environ)
73 del env['LD_LIBRARY_PATH']
74 subprocess.check_call([b"apt-get", b"download"] + list(map_virtual_packages(deps)), env=env)
Philipp Schrader0e19c602018-03-07 21:07:22 -080075
76def fixup_files():
77 # Gotta remove those pesky epoch numbers in the file names. Bazel doesn't
78 # like them.
79 regex = re.compile(".%3a")
80 contents = os.listdir(os.getcwd())
81 for deb in contents:
82 new_name = regex.sub("", deb)
83 if new_name != deb:
84 os.rename(deb, new_name)
85
86def sha256_checksum(filename, block_size=65536):
87 sha256 = hashlib.sha256()
88 with open(filename, 'rb') as f:
89 for block in iter(lambda: f.read(block_size), b''):
90 sha256.update(block)
91 return sha256.hexdigest()
92
93def print_file_list():
94 contents = os.listdir(os.getcwd())
95 contents.sort()
96 print("_files = {")
97 for deb in contents:
98 print(' "%s": "%s",' % (deb, sha256_checksum(deb)))
99 print("}")
100
Philipp Schraderaedfc5c2018-03-10 19:32:30 -0800101_ALWAYS_EXCLUDE = [
Tyler Chatow60671d32020-02-26 19:49:30 -0800102 "dbus-session-bus",
Philipp Schraderaedfc5c2018-03-10 19:32:30 -0800103 "debconf",
104 "debconf-2.0",
Tyler Chatow60671d32020-02-26 19:49:30 -0800105 "default-dbus-session-bus",
Philipp Schraderaedfc5c2018-03-10 19:32:30 -0800106 "dpkg",
107 "install-info",
108 "libc-dev",
109 "libc6",
110 "libc6-dev",
111]
112
Philipp Schrader0e19c602018-03-07 21:07:22 -0800113def main(argv):
114 parser = argparse.ArgumentParser()
115 parser.add_argument("--exclude", "-e", type=str, action="append", help="A package to exclude from the list")
Philipp Schraderaedfc5c2018-03-10 19:32:30 -0800116 parser.add_argument("--force-include", type=str, action="append", help="Force include this and its dependencies. Even if listed in excludes.")
Philipp Schrader0e19c602018-03-07 21:07:22 -0800117 parser.add_argument("package", nargs="+", help="The packages to download.")
118 args = parser.parse_args(argv[1:])
119 folder = tempfile.mkdtemp()
120 os.chdir(folder)
121 excludes = args.exclude or []
122 # Exclude common packages that don't make sense to include in everything all
123 # the time.
Philipp Schraderaedfc5c2018-03-10 19:32:30 -0800124 excludes += _ALWAYS_EXCLUDE
125 download_deps(args.package, excludes, args.force_include)
Philipp Schrader0e19c602018-03-07 21:07:22 -0800126 fixup_files()
127 print_file_list()
128 print("Your packages are all in %s" % folder)
129
130if __name__ == "__main__":
131 sys.exit(main(sys.argv))