def test_parse_end_to_end(self): test_dir = self.extract_test_tar('debian/end-to-end.tgz') test_info_dir = os.path.join(test_dir, 'end-to-end') test_file = os.path.join(test_info_dir, 'status') packages = list(debian.parse_status_file(test_file, distro='ubuntu')) assert 1 == len(packages) test_package = packages[0] expected = [ models.PackageFile('/lib/x86_64-linux-gnu/libncurses.so.5.9', md5='23c8a935fa4fc7290d55cc5df3ef56b1'), models.PackageFile('/usr/lib/x86_64-linux-gnu/libform.so.5.9', md5='98b70f283324e89db5787a018a54adf4'), models.PackageFile('/usr/lib/x86_64-linux-gnu/libmenu.so.5.9', md5='e3a0f5154928da2da234920343ac14b2'), models.PackageFile('/usr/lib/x86_64-linux-gnu/libpanel.so.5.9', md5='a927e7d76753bb85f5a784b653d337d2') ] resources = test_package.get_list_of_installed_files(test_info_dir) assert 4 == len(resources) assert expected == resources
def dirname_handler(value, current_file, **kwargs): """ Update the current_file by adding the correct dir and basename along with the md5 value. Add to installed_files """ installed_files = [] for file in current_file: dirindexes, md5, basename = file dirname = value[int(dirindexes)] # TODO: review this. Empty filename does not make sense, unless these # are directories that we might ignore OK. # There is case where entry of basename is "</string>" which will # cause error as None type cannot be used for join. # Therefore, we need to convert the None type to empty string # in order to make the join works. if basename == None: basename = '' rpm_file = models.PackageFile( path=posixpath.join(dirname, basename), md5=md5, ) installed_files.append(rpm_file) return {'installed_files': installed_files}
def test_multi_arch_is_missing(self): test_info_dir = self.get_test_loc('debian/missing-multi-arch') test_pkg = debian.DebianPackage( name='mokutil', qualifiers={'arch':'amd64'} ) expected = [ models.PackageFile('/usr/bin/mokutil', md5='7a1a2629613d260e43dabc793bebdf19'), models.PackageFile('/usr/share/bash-completion/completions/mokutil', md5='9086049384eaf0360dca4371ca50acbf'), models.PackageFile('/usr/share/doc/mokutil/changelog.Debian.gz', md5='b3f4bb874bd61e4609823993857b9c17'), models.PackageFile('/usr/share/doc/mokutil/copyright', md5='24dd593b630976a785b4c5ed097bbd96'), models.PackageFile('/usr/share/man/man1/mokutil.1.gz', md5='b608675058a943d834129b6972b8509a'), ] results = test_pkg.get_list_of_installed_files(test_info_dir) assert len(results) == 5 assert results == expected
def R_filename_handler(value, current_dir, installed_files=None, **kwargs): """ Return a new current_file PackageFile in current_dir. Add to installed_files """ # operate on a copy for safety and create an empty list on first use installed_files = installed_files[:] if installed_files else [] current_file = models.PackageFile(path=posixpath.join(current_dir, value)) installed_files.append(current_file) return {'current_file': current_file, 'installed_files': installed_files}
def test_multi_arch_is_same(self): test_dir = self.extract_test_tar('debian/same-multi-arch.tgz') test_info_dir = os.path.join(test_dir, 'same-multi-arch') test_pkg = debian.DebianPackage(name='libatk-adaptor', multi_arch='same', qualifiers={'arch': 'amd64'}) expected = [ models.PackageFile( '/usr/lib/gnome-settings-daemon-3.0/gtk-modules/at-spi2-atk.desktop', md5='34900bd11562f427776ed2c05ba6002d'), models.PackageFile( '/usr/lib/unity-settings-daemon-1.0/gtk-modules/at-spi2-atk.desktop', md5='34900bd11562f427776ed2c05ba6002d'), models.PackageFile( '/usr/lib/x86_64-linux-gnu/gtk-2.0/modules/libatk-bridge.so', md5='6ddbc10b64afe708945c3b1497714aaa'), models.PackageFile('/usr/share/doc/libatk-adaptor/NEWS.gz', md5='3a24add33624132b6b3b4c2ed08a4394'), models.PackageFile('/usr/share/doc/libatk-adaptor/README', md5='452c2e9db46c9ac92a10e700d116b120'), models.PackageFile('/usr/share/doc/libatk-adaptor/copyright', md5='971e4b2093741db8c51d263cd5c3ee48'), ] results = test_pkg.get_list_of_installed_files(test_info_dir) assert 6 == len(results) assert expected == results
def populate_installed_files(self, root_dir, root_prefix=''): install_location = self.extra_data.get('install_location') if not install_location: return if root_prefix: # The rootfs location of a Docker image layer can be in a # subdirectory of the layer directory (where `root_dir` is the path # to the layer directory), so we append `root_prefix` (where prefix # is relative to the file paths within the Docker image layer's # rootfs files) to `root_dir` root_dir = os.path.join(root_dir, root_prefix) absolute_install_location = create_absolute_installed_file_path( root_dir=root_dir, file_path=install_location) if not os.path.exists(absolute_install_location): return installed_files = [] for root, _, files in os.walk(absolute_install_location): for file in files: installed_file_location = os.path.join(root, file) relative_installed_file_path = create_relative_file_path( file_path=installed_file_location, root_dir=root_dir, root_prefix=root_prefix) installed_files.append(relative_installed_file_path) known_program_files = self.extra_data.get('known_program_files', []) for known_program_file_path in known_program_files: known_program_file_location = create_absolute_installed_file_path( root_dir=root_dir, file_path=known_program_file_path, ) relative_known_file_path = create_relative_file_path( file_path=known_program_file_location, root_dir=root_dir, root_prefix=root_prefix) if (not os.path.exists(known_program_file_location) or relative_known_file_path in installed_files): continue installed_files.append(relative_known_file_path) self.installed_files = [ models.PackageFile(path=path) for path in sorted(installed_files) ]
def get_list_of_installed_files(self, var_lib_dpkg_info_dir): """ Return a list of InstalledFile given a `var_lib_dpkg_info_dir` path to a Debian /var/lib/dpkg/info directory where <package>.list and/or <package>.md5sums files can be found for a package name. We first use the .md5sums file and switch to the .list file otherwise. The .list files also contains directories. """ # Multi-Arch can be: foreign, same, allowed or empty # We only need to adjust the md5sum path in the case of `same` if self.multi_arch == 'same': arch = ':{}'.format(self.qualifiers.get('arch')) else: arch = '' package_md5sum = '{}{}.md5sums'.format(self.name, arch) md5sum_file = os.path.join(var_lib_dpkg_info_dir, package_md5sum) package_list = '{}{}.list'.format(self.name, arch) list_file = os.path.join(var_lib_dpkg_info_dir, package_list) has_md5 = os.path.exists(md5sum_file) has_list = os.path.exists(list_file) if not (has_md5 or has_list): return [] installed_files = [] directories = set() if has_md5: with open(md5sum_file) as info_file: for line in info_file: line = line.strip() if not line: continue md5sum, _, path = line.partition(' ') md5sum = md5sum.strip() path = path.strip() if not path.startswith('/'): path = '/' + path # we ignore dirs in general, and we ignore these that would # be created a plain dir when we can if path in ignored_root_dirs: continue installed_file = models.PackageFile(path=path, md5=md5sum) installed_files.append(installed_file) directories.add(os.path.dirname(path)) elif has_list: with open(list_file) as info_file: for line in info_file: line = line.strip() if not line: continue md5sum = None path = line path = path.strip() if not path.startswith('/'): path = '/' + path # we ignore dirs in general, and we ignore these that would # be created a plain dir when we can if path in ignored_root_dirs: continue installed_file = models.PackageFile(path=path, md5=md5sum) if installed_file not in installed_files: installed_files.append(installed_file) directories.add(os.path.dirname(path)) # skip directories when possible installed_files = [ f for f in installed_files if f.path not in directories ] return installed_files
def test_multi_arch_is_foreign(self): test_info_dir = self.get_test_loc('debian/foreign-multi-arch') test_pkg = debian.DebianPackage( name='fonts-sil-abyssinica', multi_arch='foreign', qualifiers={'arch':'amd64'} ) expected = [ models.PackageFile('/usr/share/bug/fonts-sil-abyssinica/presubj', md5='7faf213b3c06e818b9976cc2ae5af51a'), models.PackageFile('/usr/share/bug/fonts-sil-abyssinica/script', md5='672370efca8bffa183e2828907e0365d'), models.PackageFile('/usr/share/doc/fonts-sil-abyssinica/OFL-FAQ.txt.gz', md5='ea72ae1d2ba5471ef54b132c79b1a03b'), models.PackageFile('/usr/share/doc/fonts-sil-abyssinica/README.Debian', md5='f497d6bfc7ca4d423d703fabb7ff2e4c'), models.PackageFile('/usr/share/doc/fonts-sil-abyssinica/changelog.Debian.gz', md5='7f81bc6ed7506b95af01b5eef76662bb'), models.PackageFile('/usr/share/doc/fonts-sil-abyssinica/copyright', md5='13d9a840b6db71f7060670be0aafa953'), models.PackageFile('/usr/share/doc/fonts-sil-abyssinica/documentation/AbyssinicaSILGraphiteFontFeatures.odt', md5='0e4a5ad6839067740e81a3e1244b0b16'), models.PackageFile('/usr/share/doc/fonts-sil-abyssinica/documentation/AbyssinicaSILGraphiteFontFeatures.pdf.gz', md5='8fee9c92ecd425c71217418b8370c5ae'), models.PackageFile('/usr/share/doc/fonts-sil-abyssinica/documentation/AbyssinicaSILOpenTypeFontFeatures.pdf.gz', md5='2cc8cbe21730258dd03a465e045066cc'), models.PackageFile('/usr/share/doc/fonts-sil-abyssinica/documentation/AbyssinicaSILTypeSample.pdf.gz', md5='40948ce7d8e4b1ba1c7043ec8926edf9'), models.PackageFile('/usr/share/doc/fonts-sil-abyssinica/documentation/AbyssinicaSILTypeTunerGuide.pdf.gz', md5='36ca1d62ca7365216e8bda952d2461e6'), models.PackageFile('/usr/share/doc/fonts-sil-abyssinica/documentation/DOCUMENTATION.txt', md5='491295c116dbcb74bcad2d78a56aedbe'), models.PackageFile('/usr/share/doc/fonts-sil-abyssinica/documentation/SILEthiopicPrivateUseAreaBlock.pdf.gz', md5='bea5aeeb76a15c2c1b8189d1b2437b31'), models.PackageFile('/usr/share/fonts/truetype/abyssinica/AbyssinicaSIL-R.ttf', md5='9e3d4310af3892a739ba7b1189c44dca'), ] results = test_pkg.get_list_of_installed_files(test_info_dir) assert len(results) == 14 assert results == expected