def test_release_contains_good_prerelease(suffix: str, expected_suffix: str): assert parse_rpm_version([], '1.2.3', f'0{suffix}') == (f'1.2.3{expected_suffix}', Pf.DEVEL) assert parse_rpm_version([], '1.2.3', f'1{suffix}') == (f'1.2.3{expected_suffix}', Pf.DEVEL)
def test_snapshot_by_rpm_rev(self) -> None: self.assertEqual(parse_rpm_version([], '1.2', '0'), ('1.2', PackageFlags.IGNORE)) self.assertEqual(parse_rpm_version(['foo'], '1.2', '0foo'), ('1.2', PackageFlags.IGNORE)) self.assertEqual(parse_rpm_version(['foo'], '1.2', 'foo0'), ('1.2', PackageFlags.IGNORE))
def test_release_prerelease_without_number(): assert parse_rpm_version([], '1.2.3', '0alpha') == ('1.2.3-alpha', Pf.DEVEL) assert parse_rpm_version([], '1.2.3', '0.alpha') == ('1.2.3-alpha', Pf.DEVEL) assert parse_rpm_version([], '1.2.3', '1alpha') == ('1.2.3-alpha', Pf.DEVEL) assert parse_rpm_version([], '1.2.3', '1.alpha') == ('1.2.3-alpha', Pf.DEVEL)
def test_release_prerelease_dot_longnumber(): assert parse_rpm_version([], '1.2.3', '0.alpha20210101') == ('1.2.3-alpha20210101', Pf.DEVEL) assert parse_rpm_version([], '1.2.3', '0.alpha.20210101') == ('1.2.3-alpha', Pf.DEVEL | Pf.IGNORE) assert parse_rpm_version([], '1.2.3', '1.alpha20210101') == ('1.2.3-alpha20210101', Pf.DEVEL) assert parse_rpm_version([], '1.2.3', '1.alpha.20210101') == ('1.2.3-alpha', Pf.DEVEL | Pf.IGNORE)
def iter_parse(self, path: str, factory: PackageFactory) -> Iterable[PackageMaker]: with open(path) as listfile: for line in listfile: with factory.begin() as pkg: filename = line.strip().split()[-1] name, epoch, version, release, arch = nevra_parse(filename) assert (arch == 'src') pkg.add_name(name, NameType.SRCRPM_NAME) fixed_version, flags = parse_rpm_version( self._vertags, version, release) pkg.set_version(fixed_version) pkg.set_rawversion( nevra_construct(None, epoch, version, release)) pkg.set_flags(flags) pkg.set_arch(arch) pkg.set_extra_field('nevr', filename.rsplit('.', 2)[0]) yield pkg
def iter_parse(self, path: str, factory: PackageFactory) -> Iterable[PackageMaker]: for header in rpm.readHeaderListFromFile(path): with factory.begin() as pkg: assert (header.isSource()) # binary packages not supported yet def sanitize_key(key: Any) -> Any: return rpm.tagnames[key].lower( ) if key in rpm.tagnames else key def sanitize_value(value: Any) -> Any: return value.decode(self._encoding, errors='ignore') if isinstance( value, bytes) else value pkgdata = { sanitize_key(key): sanitize_value(value) for key, value in dict(header).items() } # For Sisyphus (but not PCLinuxOS), there is pkgdata[1000011], which contains # a different name (for instance, for GLEW there is libGLEW-devel) # May use is for some other purposes pkg.add_name(pkgdata['name'], NameType.SRCRPM_NAME) if pkgdata['version'] is None: raise RuntimeError('version not defined') version, flags = parse_rpm_version(self._vertags, pkgdata['version'], pkgdata['release']) pkg.set_version(version) pkg.set_rawversion( nevra_construct(None, header['epoch'], pkgdata['version'], pkgdata['release'])) pkg.set_flags(flags) if 'packager' in pkgdata: pkg.add_maintainers( extract_maintainers(pkgdata['packager']) ) # XXX: may have multiple maintainers pkg.add_categories(pkgdata['group']) try: # e.g. PCLinuxOS summaries may contain surrogate garbage pkgdata['summary'].encode('utf-8') pkg.set_summary(pkgdata['summary']) except: pkg.log('incorrect UTF in summary', Logger.ERROR) pkg.set_arch(pkgdata['arch']) yield pkg
def iter_parse(self, path: str, factory: PackageFactory) -> Iterable[PackageMaker]: for packagedata in iter_json_list(path, ('packages', None)): with factory.begin() as pkg: pkg.add_name(packagedata['name'], NameType.SRCRPM_NAME) pkg.add_binnames(binary['name'] for binary in packagedata['binaries']) version, flags = parse_rpm_version(self._vertags, packagedata['version'], packagedata['release']) pkg.set_version(version) pkg.set_rawversion( nevra_construct(None, packagedata['epoch'], packagedata['version'], packagedata['release'])) pkg.set_flags(flags) pkg.add_categories(packagedata['category']) pkg.set_summary(packagedata['summary']) pkg.add_licenses(packagedata['license']) pkg.add_maintainers(packagedata['packager']) pkg.add_links(LinkType.UPSTREAM_HOMEPAGE, packagedata['url']) pkg.add_links(LinkType.PACKAGE_HOMEPAGE, packagedata['homepage']) pkg.add_links(LinkType.PACKAGE_RECIPE, packagedata['recipe']) pkg.add_links(LinkType.PACKAGE_RECIPE_RAW, packagedata['recipe_raw']) pkg.add_links(LinkType.PACKAGE_ISSUE_TRACKER, packagedata['bugzilla']) # TODO: parse CPE data when available if 'CPE' in packagedata: pass yield pkg
def iter_parse(self, path: str, factory: PackageFactory, transformer: PackageTransformer) -> Iterable[PackageMaker]: root = xml.etree.ElementTree.parse(path) for info in root.findall('./info'): with factory.begin() as pkg: name, epoch, version, release, arch = nevra_parse( info.attrib['fn']) assert (arch == 'src') pkg.add_name(name, NameType.SRCRPM_NAME) fixed_version, flags = parse_rpm_version( self._vertags, version, release) pkg.set_version(fixed_version) pkg.set_rawversion( nevra_construct(None, epoch, version, release)) pkg.set_flags(flags) pkg.set_arch(arch) # What we do here is we try to extract prerelease part # and mark version as ignored with non-trivial ROSAREV, # as it it likely a snapshot and trus cannot be trusted if not version.isdecimal(): pkg.set_flags(PackageFlags.IGNORE) match = re.search('\\b(a|alpha|b|beta|pre|rc)[0-9]+', version.lower()) if match: pkg.set_version(version + match.group(0)) pkg.add_homepages(info.attrib['url']) pkg.add_licenses(info.attrib['license']) yield pkg
def test_release_starts_with_zero(): # Release starts with zero - potentially prerelease or a snapshot assert parse_rpm_version([], '1.2.3', '0') == ('1.2.3', Pf.IGNORE)
def iter_parse(self, path: str, factory: PackageFactory) -> Iterable[PackageMaker]: normalize_version = VersionStripper().strip_right_greedy('+') skipped_archs: dict[str, int] = Counter() if self._arch_from_filename: factory.log('mitigation for incorrect <arch></arch> enabled', severity=Logger.WARNING) for entry in iter_xml_elements_at_level(path, 1, ['{http://linux.duke.edu/metadata/common}package']): if self._arch_from_filename: # XXX: openmandriva 3 hack, to be removed when it EoLs location_elt = entry.find('{http://linux.duke.edu/metadata/common}location') if location_elt is None: raise RuntimeError('Cannot find <location> element') arch = nevra_parse(safe_getattr(location_elt, 'href'))[4] else: arch = safe_findtext(entry, '{http://linux.duke.edu/metadata/common}arch') is_src = arch == 'src' if (is_src and not self._src) or (not is_src and not self._binary): skipped_archs[arch] += 1 continue with factory.begin() as pkg: name = safe_findtext(entry, '{http://linux.duke.edu/metadata/common}name') if '%{' in name: pkg.log('incorrect package name (unexpanded substitution)', severity=Logger.ERROR) continue if is_src: pkg.add_name(name, NameType.SRCRPM_NAME) else: pkg.add_name(name, NameType.BINRPM_NAME) sourcerpm = safe_findtext( entry, '{http://linux.duke.edu/metadata/common}format/' '{http://linux.duke.edu/metadata/rpm}sourcerpm' ) pkg.add_name(nevra_parse(sourcerpm)[0], NameType.BINRPM_SRCNAME) version_elt = entry.find('{http://linux.duke.edu/metadata/common}version') if version_elt is None: raise RuntimeError('Cannot find <version> element') epoch = version_elt.attrib['epoch'] version = version_elt.attrib['ver'] release = version_elt.attrib['rel'] fixed_version, flags = parse_rpm_version(self._vertags, version, release) pkg.set_version(fixed_version, normalize_version) pkg.set_rawversion(nevra_construct(None, epoch, version, release)) pkg.set_flags(flags) pkg.set_summary(entry.findtext('{http://linux.duke.edu/metadata/common}summary')) pkg.add_homepages(entry.findtext('{http://linux.duke.edu/metadata/common}url')) pkg.add_categories(entry.findtext('{http://linux.duke.edu/metadata/common}format/' '{http://linux.duke.edu/metadata/rpm}group')) pkg.add_licenses(entry.findtext('{http://linux.duke.edu/metadata/common}format/' '{http://linux.duke.edu/metadata/rpm}license')) pkg.set_arch(entry.findtext('{http://linux.duke.edu/metadata/common}arch')) packager = entry.findtext('{http://linux.duke.edu/metadata/common}packager') if packager: pkg.add_maintainers(extract_maintainers(packager)) yield pkg for arch, numpackages in sorted(skipped_archs.items()): factory.log('skipped {} packages(s) with disallowed architecture {}'.format(numpackages, arch))
def test_known_prerelease(self) -> None: self.assertEqual(parse_rpm_version([], '1.2', '1.alpha1'), ('1.2-alpha1', 0)) self.assertEqual(parse_rpm_version([], '1.2', '1.beta1'), ('1.2-beta1', 0)) self.assertEqual(parse_rpm_version([], '1.2', '1.rc1'), ('1.2-rc1', 0))
def test_release_tag(): # Release tags, if specified for the repo, are not condidered as # a sing of a snapshot and do not produce IGNORE flag assert parse_rpm_version(['el'], '1.2.3', '1.el6') == ('1.2.3', 0) assert parse_rpm_version(['el'], '1.2.3', '1.6el') == ('1.2.3', 0)
def test_release_multi(): assert parse_rpm_version(['mga'], '1.2.3', '1.mga1.mga2') == ('1.2.3', 0)
def test_snapshot(self) -> None: self.assertEqual(parse_rpm_version([], '1.2', '1.20210102'), ('1.2', PackageFlags.IGNORE)) self.assertEqual(parse_rpm_version([], '1.2', '1.git1a2b3c4'), ('1.2', PackageFlags.IGNORE))
def test_release_suggests_snapshot(): # Release suggests snapshot, even if it doesn't start with zero assert parse_rpm_version([], '1.2.3', '1.20200101') == ('1.2.3', Pf.IGNORE) assert parse_rpm_version([], '1.2.3', '1.garbage') == ('1.2.3', Pf.IGNORE)
def test_plain(self) -> None: self.assertEqual(parse_rpm_version([], '1.2', '1'), ('1.2', 0)) self.assertEqual(parse_rpm_version(['foo'], '1.2', '1foo'), ('1.2', 0)) self.assertEqual(parse_rpm_version(['foo'], '1.2', 'foo1'), ('1.2', 0))
def test_basic(): assert parse_rpm_version([], '1.2.3', '1') == ('1.2.3', 0)
def test_real_world(tags: list[str], version: str, release: str, expected_version: str, expected_flags: int): assert parse_rpm_version(tags, version, release) == (expected_version, expected_flags)
def test_release_tag_glued(): # Removed tags should not corrupt prerelease versions assert parse_rpm_version(['el'], '1.2.3', '1beta3el6') == ('1.2.3-beta3', Pf.DEVEL)