Example #1
0
    def Parse(self, path):
        packages = []

        for pkgdir in os.listdir(os.path.join(path, 'ports')):
            controlpath = os.path.join(path, 'ports', pkgdir, 'CONTROL')
            if not os.path.exists(controlpath):
                continue

            pkg = Package(name=pkgdir)

            with open(controlpath, 'r', encoding='utf-8',
                      errors='ignore') as controlfile:
                for line in controlfile:
                    line = line.strip()
                    if line.startswith('Version:'):
                        version = line[8:].strip()
                        match = re.match(
                            '[0-9]{4}[.-][0-9]{1,2}[.-][0-9]{1,2}', version)
                        if match:
                            pkg.version = version
                            pkg.SetFlag(PackageFlags.ignore)
                        else:
                            pkg.version, pkg.origversion = SanitizeVersion(
                                line[8:].strip())
                    elif line.startswith('Description:'):
                        comment = line[12:].strip()
                        if comment:
                            pkg.comment = comment

            # pretty much a hack to shut a bunch of fake versions up
            portfilepath = os.path.join(path, 'ports', pkgdir,
                                        'portfile.cmake')
            if os.path.exists(portfilepath):
                with open(portfilepath, 'r', encoding='utf-8',
                          errors='ignore') as portfile:
                    for line in portfile:
                        if 'libimobiledevice-win32' in line:
                            print(
                                'WARNING: marking version for {} as untrusted, https://github.com/libimobiledevice-win32 accused of version faking'
                                .format(pkg.name),
                                file=sys.stderr)
                            pkg.SetFlag(PackageFlags.untrusted)
                            break

            if not pkg.version:
                print('WARNING: unable to parse port {}: no version'.format(
                    pkgdir),
                      file=sys.stderr)
                continue

            packages.append(pkg)

        return packages
Example #2
0
    def Parse(self, path):
        result = []

        with open(path, 'r', encoding='utf-8') as jsonfile:
            for package in json.load(jsonfile)['packages']:
                pkg = Package()

                pkg.name = package['name']

                if package['version'] is None:
                    print('no version: {}'.format(pkg.name), file=sys.stderr)
                    continue

                pkg.version, _ = SanitizeVersion(package['version'])
                pkg.origversion = package['full_version']
                pkg.category = package['pkg_section'] or package['section']
                pkg.comment = package['description']
                pkg.maintainers = GetMaintainers(package['committer'])

                if pkg.version == '999':
                    pkg.SetFlag(PackageFlags.ignore)  # XXX: rolling? revisit

                result.append(pkg)

        return result
Example #3
0
    def Parse(self, path):
        result = []

        jsondata = None
        with open(path, 'r', encoding='utf-8') as jsonfile:
            jsondata = json.load(jsonfile)

        for packagedata in SimplifyResult(jsondata):
            entity = packagedata['project'].rsplit(
                '/', 1)[-1]  # this is URL, take only the ID from it

            # use Arch and AUR package names as a name, as they are most non-ambigous
            names = []
            for field in ['arch_packages', 'aur_packages']:
                if packagedata[field]:
                    names = packagedata[field].split(', ')
                    break

            # generate a package for each package name; these will be merged anyway
            for name in set(names):
                # generate a package for each version
                for version in packagedata['versions'].split(', '):
                    version, *flags = version.split('|')

                    is_devel = 'U' in flags
                    is_foreign_os_release = 'O' in flags and 'L' not in flags

                    if is_foreign_os_release:
                        print(
                            'WARNING: {} ({}) version {} skipped as non-linux release'
                            .format(packagedata['projectLabel'], entity,
                                    version),
                            file=sys.stderr)
                        continue

                    pkg = Package()

                    pkg.SetFlag(PackageFlags.devel, is_devel)

                    pkg.name = entity
                    pkg.effname = name
                    pkg.version = version

                    if 'projectDescription' in packagedata:
                        pkg.comment = packagedata['projectDescription']
                    else:
                        pkg.comment = packagedata['projectLabel']

                    if packagedata['licenses']:
                        pkg.licenses = packagedata['licenses'].split(', ')

                    if packagedata['websites']:
                        pkg.homepage = packagedata['websites'].split(', ')[
                            0]  # XXX: use all websites when supported

                    result.append(pkg)

        return result
Example #4
0
    def Parse(self, path):
        result = []

        maintainers = []

        with open(os.path.join(path, 'metadata/about.conf'),
                  'r',
                  encoding='utf-8') as metadata:
            for line in metadata:
                if '=' in line:
                    key, value = map(lambda s: s.strip(), line.split('=', 1))

                    if key == 'owner':
                        maintainers = extract_maintainers(value)

        packages_path = os.path.join(path, 'packages')

        for category in os.listdir(packages_path):
            category_path = os.path.join(packages_path, category)
            if not os.path.isdir(category_path):
                continue
            if category == 'virtual' or category == 'metadata':
                continue

            for package in os.listdir(category_path):
                package_path = os.path.join(category_path, package)
                if not os.path.isdir(package_path):
                    continue

                for exheres in os.listdir(package_path):
                    if not exheres.startswith(package +
                                              '-') and not exheres.endswith(
                                                  '.exheres-0'):
                        continue

                    pkg = Package()

                    pkg.category = category
                    pkg.name = package
                    pkg.version, pkg.origversion = SanitizeVersion(
                        exheres[len(package) + 1:-10])
                    pkg.maintainers = maintainers

                    if pkg.version == 'scm' or pkg.version.endswith('-scm'):
                        pkg.SetFlag(PackageFlags.rolling)

                    result.append(pkg)

        return result
Example #5
0
    def Parse(self, path):
        result = []
        skipped_archs = {}

        for entry in self.ParsePackagesEntriesFromXml(path):
            pkg = Package()

            arch = entry.find('{http://linux.duke.edu/metadata/common}arch').text
            if self.allowed_archs and arch not in self.allowed_archs:
                skipped_archs[arch] = skipped_archs.get(arch, 0) + 1
                continue

            pkg.name = entry.find('{http://linux.duke.edu/metadata/common}name').text
            version = entry.find('{http://linux.duke.edu/metadata/common}version').attrib['ver']
            release = entry.find('{http://linux.duke.edu/metadata/common}version').attrib['rel']

            match = re.match('0\\.[0-9]+\\.((?:alpha|beta|rc)[0-9]+)\\.', release)
            if match:
                # known pre-release schema: https://fedoraproject.org/wiki/Packaging:Versioning#Prerelease_versions
                version += '-' + match.group(1)
            elif release < '1':
                # unknown pre-release schema: https://fedoraproject.org/wiki/Packaging:Versioning#Some_definitions
                # most likely a snapshot
                pkg.SetFlag(PackageFlags.ignore)

            pkg.version, pkg.origversion = SanitizeVersion(version)
            # XXX: append origversion with release

            pkg.comment = entry.find('{http://linux.duke.edu/metadata/common}summary').text
            pkg.homepage = entry.find('{http://linux.duke.edu/metadata/common}url').text
            pkg.category = entry.find('{http://linux.duke.edu/metadata/common}format/'
                                      '{http://linux.duke.edu/metadata/rpm}group').text
            pkg.licenses.append(entry.find('{http://linux.duke.edu/metadata/common}format/'
                                           '{http://linux.duke.edu/metadata/rpm}license').text)

            packager = entry.find('{http://linux.duke.edu/metadata/common}packager').text
            if packager:
                pkg.maintainers = extract_maintainers(packager)

            result.append(pkg)

        for arch, numpackages in sorted(skipped_archs.items()):
            print('WARNING: skipping {} packages(s) with disallowed architecture {}'.format(numpackages, arch), file=sys.stderr)

        return result
Example #6
0
    def Parse(self, path):
        result = []

        root = xml.etree.ElementTree.parse(path)

        for info in root.findall('./info'):
            pkg = Package()

            # derive names and versions from fn field
            fn = info.attrib['fn'].rsplit('-', 2)
            if len(fn) < 3:
                print('WARNING: unable to parse fn: {}'.format(fn),
                      file=sys.stderr)
                continue

            pkg.name = fn[0]
            pkg.origversion = '-'.join(fn[1:])
            pkg.version = fn[1]

            # Rosa packages are named like PKGNAME-PKGVER-ROSAREV
            # where ROSAREV is most commonly in the form of N.src, but
            # may contain other components, such as prerelease stuff
            # like alpha/beta/rc/pre/... and snapshot revisions/dates
            #
            # 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 re.fullmatch('[0-9]+\\.src', fn[2]):
                pkg.SetFlag(PackageFlags.ignore)
                match = re.search('\\b(a|alpha|b|beta|pre|rc)[0-9]+',
                                  fn[2].lower())
                if match:
                    pkg.version += match.group(0)

            # process url and license
            url = info.attrib['url']
            if url:
                pkg.homepage = url

            license_ = info.attrib['license']
            pkg.licenses = [license_]

            result.append(pkg)

        return result
Example #7
0
    def Parse(self, path):
        result = []

        root = xml.etree.ElementTree.parse(path)

        repository = root.find(
            '{http://www.openpkg.org/xml-rdf-index/0.9}Repository')

        for item in repository.findall(
                '{http://www.w3.org/1999/02/22-rdf-syntax-ns#}Description'):
            pkg = Package()

            pkg.name = item.find(
                '{http://www.openpkg.org/xml-rdf-index/0.9}Name').text
            pkg.version = item.find(
                '{http://www.openpkg.org/xml-rdf-index/0.9}Version').text
            pkg.licenses = [
                item.find(
                    '{http://www.openpkg.org/xml-rdf-index/0.9}License').text
            ]
            pkg.comment = item.find(
                '{http://www.openpkg.org/xml-rdf-index/0.9}Summary').text
            pkg.category = item.find(
                '{http://www.openpkg.org/xml-rdf-index/0.9}Group').text
            pkg.homepage = item.find(
                '{http://www.openpkg.org/xml-rdf-index/0.9}URL').text

            for source in item.findall(
                    './{http://www.openpkg.org/xml-rdf-index/0.9}Source/{http://www.w3.org/1999/02/22-rdf-syntax-ns#}bag/{http://www.w3.org/1999/02/22-rdf-syntax-ns#}li'
            ):
                text = source.text
                if (text.startswith('https://') or text.startswith('http://')
                        or text.startswith('ftp://')
                    ) and 'openpkg.org' not in text:
                    pkg.downloads.append(text)

            release = item.find(
                '{http://www.openpkg.org/xml-rdf-index/0.9}Release').text
            if pkg.version.endswith(release):
                pkg.SetFlag(PackageFlags.untrusted)

            result.append(pkg)

        return result
Example #8
0
    def Parse(self, path):
        packages = []

        for pkgdir in os.listdir(os.path.join(path, 'ports')):
            controlpath = os.path.join(path, 'ports', pkgdir, 'CONTROL')
            if not os.path.exists(controlpath):
                continue

            pkg = Package(name=pkgdir)

            with open(controlpath, 'r', encoding='utf-8',
                      errors='ignore') as controlfile:
                for line in controlfile:
                    line = line.strip()
                    if line.startswith('Version:'):
                        version = line[8:].strip()
                        match = re.match(
                            '[0-9]{4}[.-][0-9]{1,2}[.-][0-9]{1,2}', version)
                        if match:
                            pkg.version = version
                            pkg.SetFlag(PackageFlags.ignore)
                        else:
                            pkg.version, pkg.origversion = SanitizeVersion(
                                line[8:].strip())
                    elif line.startswith('Description:'):
                        comment = line[12:].strip()
                        if comment:
                            pkg.comment = comment

            if not pkg.version:
                print('WARNING: unable to parse port {}: no version'.format(
                    pkgdir),
                      file=sys.stderr)
                continue

            packages.append(pkg)

        return packages
Example #9
0
    def Parse(self, path):
        result = []

        for category in os.listdir(path):
            category_path = os.path.join(path, category)
            if not os.path.isdir(category_path):
                continue
            if category == 'virtual' or category == 'metadata':
                continue

            for package in os.listdir(category_path):
                package_path = os.path.join(category_path, package)
                if not os.path.isdir(package_path):
                    continue

                metadata_path = os.path.join(package_path, 'metadata.xml')

                # parse maintainers from metadata.xml
                # these are the same for all ebuilds for current package
                maintainers = []
                if os.path.isfile(metadata_path):
                    with open(metadata_path, 'r',
                              encoding='utf-8') as metafile:
                        meta = xml.etree.ElementTree.parse(metafile)

                        for entry in meta.findall('maintainer'):
                            email_node = entry.find('email')

                            if email_node is not None and email_node.text is not None:
                                maintainers += extract_maintainers(
                                    email_node.text)

                for ebuild in os.listdir(package_path):
                    if not ebuild.endswith('.ebuild'):
                        continue

                    pkg = Package()

                    pkg.name = package
                    pkg.category = category
                    pkg.maintainers = maintainers

                    pkg.version, pkg.origversion = SanitizeVersion(
                        ebuild[len(package) + 1:-7])

                    if pkg.version.endswith('9999'):
                        # ignore versions for snapshots
                        pkg.SetFlag(PackageFlags.rolling)

                    metadata_path = os.path.join(
                        path, 'metadata', 'md5-cache', category,
                        package + '-' +
                        (pkg.origversion if pkg.origversion else pkg.version))
                    if os.path.isfile(metadata_path):
                        with open(metadata_path, 'r',
                                  encoding='utf-8') as metadata_file:
                            for line in metadata_file:
                                line = line.strip()
                                key, value = line.split('=', 1)

                                if key == 'DESCRIPTION':
                                    pkg.comment = value
                                elif key == 'HOMEPAGE':
                                    pkg.homepage = value.split(' ')[
                                        0]  # XXX: save all urls
                                elif key == 'LICENSE':
                                    if '(' in value:
                                        # XXX: conditionals and OR's: need more
                                        # complex parsing and backend support
                                        pkg.licenses.append(value)
                                    else:
                                        pkg.licenses += value.split(' ')
                                elif key == 'SRC_URI':
                                    pkg.downloads += ParseConditionalExpr(
                                        value)

                    result.append(pkg)

        return result
Example #10
0
    def Parse(self, path):
        result = []

        with open(path, 'r', encoding='utf-8') as jsonfile:
            for key, packagedata in sorted(
                    json.load(jsonfile)['packages'].items()):
                # see how Nix parses 'derivative' names in
                # https://github.com/NixOS src/libexpr/names.cc, DrvName::DrvName
                # it just splits on dash followed by non-letter
                #
                # this doesn't work well on 100% cases, it's an upstream problem
                match = re.match('(.+?)-([^a-zA-Z].*)$', packagedata['name'])
                if not match:
                    print('cannot extract version: {}/{}'.format(
                        key, packagedata['name']),
                          file=sys.stderr)
                    continue

                pkg = Package()
                pkg.name = match.group(1)
                pkg.version = match.group(2)

                # some exceptions
                for prefix in ('75dpi', '100dpi'):
                    if pkg.version.startswith(prefix):
                        pkg.name += '-' + prefix
                        pkg.version = pkg.version[len(prefix) + 1:]

                for pkgname in ('liblqr', ):
                    if pkg.name == pkgname:
                        dashpos = pkg.version.find('-')
                        pkg.name = pkg.name + '-' + pkg.version[0:dashpos]
                        pkg.version = pkg.version[dashpos + 1:]

                if pkg.name.endswith('-git'):
                    pkg.name = pkg.name[:-4]
                    pkg.SetFlag(PackageFlags.ignore)

                if re.match('.*20[0-9]{2}-[0-9]{2}-[0-9]{2}', pkg.version):
                    pkg.SetFlag(PackageFlags.ignore)

                if re.match('[0-9a-f]*[a-f][0-9a-f]*$',
                            pkg.version) and len(pkg.version) >= 7:
                    print(
                        'ignoring version which looks like commit hash: {}/{}'.
                        format(key, packagedata['name']),
                        file=sys.stderr)
                    pkg.SetFlag(PackageFlags.ignore)

                meta = packagedata['meta']

                if 'homepage' in meta:
                    pkg.homepage = meta['homepage']
                    if isinstance(
                            pkg.homepage, list
                    ):  # XXX: remove after adding support for homepages array
                        pkg.homepage = pkg.homepage[0]

                if 'description' in meta:
                    pkg.comment = meta['description']

                if 'maintainers' in meta:
                    maintainers = meta['maintainers']
                    if not isinstance(meta['maintainers'], list):
                        print('maintainers is not a list: {}/{}'.format(
                            key, packagedata['name']),
                              file=sys.stderr)
                    else:
                        maintainers = ', '.join(maintainers)
                    pkg.maintainers = GetMaintainers(maintainers)

                if 'license' in meta:
                    pkg.licenses = ExtractLicenses(meta['license'])

                result.append(pkg)

        return result
Example #11
0
 def ignore_action(package: Package,
                   package_context: PackageContext,
                   match_context: MatchContext) -> None:
     package.SetFlag(PackageFlags.ignore, ignore_flag)
Example #12
0
 def generated_action(package: Package,
                      package_context: PackageContext,
                      match_context: MatchContext) -> None:
     # XXX: the same as rolling for now
     package.SetFlag(PackageFlags.rolling, generated_flag)
Example #13
0
 def any_is_patch_action(package: Package,
                         package_context: PackageContext,
                         match_context: MatchContext) -> None:
     package.SetFlag(PackageFlags.any_is_patch, any_is_patch_flag)
Example #14
0
class PackageMaker(PackageMakerBase):
    def __init__(self, logger, ident):
        super(PackageMaker, self).__init__(logger)
        self.package = Package()
        self.ident = ident

    def _get_ident(self):
        return self.package.extrafields.get('origin', None) or self.package.name or self.ident or self.package.effname

    @PackageMakerBase._simple_setter('origin', str, nzs.strip, nzs.forbid_newlines)
    def set_origin(self, origin):
        # XXX: convert to dedicated field
        self.set_extra_field('origin', origin)

    @PackageMakerBase._simple_setter('name', str, nzs.strip, nzs.forbid_newlines)
    def set_effname(self, effname):
        # XXX: this should be refactored
        # It's OK for parsers to set both effname and name, the example case
        # is setting effname to <project> name and <name>s to package names
        # However this erases strict boundary between fields parsed from
        # data and fields calculated based on them. It should be fixed.
        self.package.effname = effname

    @PackageMakerBase._simple_setter('name', str, nzs.strip, nzs.forbid_newlines)
    def set_name(self, name):
        self.package.name = name

    @PackageMakerBase._simple_setter('version', str, nzs.strip, nzs.forbid_newlines)
    def set_version(self, version, version_normalizer=None):
        if version_normalizer is None:
            self.package.version = version
        else:
            normalized_version = version_normalizer(version)

            # XXX: compatibility shim to allow old style SanitizeVesion returning version and origversion
            if isinstance(normalized_version, tuple):
                normalized_version = normalized_version[0]

            if normalized_version == version:
                self.package.version = version
            else:
                self.package.version = normalized_version
                self.package.origversion = version

    @PackageMakerBase._simple_setter('version', str, nzs.strip, nzs.forbid_newlines)
    def set_origversion(self, origversion):
        if origversion != self.package.version:
            self.package.origversion = origversion

    def set_name_and_version(self, namever, version_normalizer=None):
        name, version = namever.rsplit('-', 1)
        self.set_name(name)
        self.set_version(version, version_normalizer)

    @PackageMakerBase._simple_setter('summary', str, nzs.strip)
    def set_summary(self, summary):
        self.package.comment = summary

    @PackageMakerBase._omnivorous_setter('maintainer', str, nzs.strip, nzs.forbid_newlines)
    def add_maintainers(self, *args):
        self.package.maintainers.extend(args)

    @PackageMakerBase._omnivorous_setter('category', str, nzs.strip, nzs.forbid_newlines)
    def add_categories(self, *args):
        # XXX: convert into array
        if not self.package.category:
            self.package.category = args[0]

    @PackageMakerBase._omnivorous_setter('homepage', str, nzs.strip, nzs.require_url, nzs.warn_whitespace, nzs.forbid_newlines)
    def add_homepages(self, *args):
        # XXX: convert into array
        if not self.package.homepage:
            self.package.homepage = args[0]

    @PackageMakerBase._omnivorous_setter('license', str, nzs.strip, nzs.forbid_newlines)
    def add_licenses(self, *args):
        self.package.licenses.extend(args)

    @PackageMakerBase._omnivorous_setter('download', str, nzs.strip, nzs.require_url, nzs.warn_whitespace, nzs.forbid_newlines)
    def add_downloads(self, *args):
        self.package.downloads.extend(args)

    def set_flags(self, mask, is_set=True):
        assert(isinstance(mask, int))
        assert(isinstance(is_set, bool))
        self.package.SetFlag(mask, is_set)

    def set_extra_field(self, key, value):
        assert(isinstance(key, str))
        assert(isinstance(value, str))
        self.package.extrafields[key] = value

    def unwrap(self):
        return self.package

    def clone(self):
        offspring = PackageMaker(self.logger, self.ident)
        offspring.package = deepcopy(self.package)
        return offspring

    def check_sanity(self, verbose=False):
        if not self.package.name:
            if verbose:
                self.log('package with no name', severity=Logger.ERROR)
            return False

        if not self.package.version:
            if verbose:
                self.log('package with no version', severity=Logger.ERROR)
            return False

        return True

    def __getattr__(self, key):
        return getattr(self.package, key)

    # XXX: compatibility shim
    def __setattr__(self, key, value):
        if key in ['package', 'logger', 'ident']:
            return super(PackageMaker, self).__setattr__(key, value)
        return setattr(self.package, key, value)
Example #15
0
 def weak_devel_action(package: Package,
                       package_context: PackageContext,
                       match_context: MatchContext) -> None:
     # XXX: currently sets ignore; change to set non-viral variant of devel (#654)
     package.SetFlag(PackageFlags.ignore, weak_devel_flag)
Example #16
0
 def noscheme_action(package: Package,
                     package_context: PackageContext,
                     match_context: MatchContext) -> None:
     package.SetFlag(PackageFlags.noscheme, noscheme_flag)
Example #17
0
 def untrusted_action(package: Package,
                      package_context: PackageContext,
                      match_context: MatchContext) -> None:
     package.SetFlag(PackageFlags.untrusted, untrusted_flag)
Example #18
0
 def incorrect_action(package: Package,
                      package_context: PackageContext,
                      match_context: MatchContext) -> None:
     package.SetFlag(PackageFlags.incorrect, incorrect_flag)
Example #19
0
 def legacy_action(package: Package,
                   package_context: PackageContext,
                   match_context: MatchContext) -> None:
     package.SetFlag(PackageFlags.legacy, legacy_flag)
Example #20
0
 def outdated_action(package: Package,
                     package_context: PackageContext,
                     match_context: MatchContext) -> None:
     package.SetFlag(PackageFlags.outdated, outdated_flag)
Example #21
0
 def remove_action(package: Package,
                   package_context: PackageContext,
                   match_context: MatchContext) -> None:
     package.SetFlag(PackageFlags.remove, remove_flag)
Example #22
0
class PackageMaker(PackageMakerBase):
    def __init__(self, logger, ident, itemno, skipfailed=False):
        super(PackageMaker, self).__init__(logger)
        self.package = Package()
        self.ident = ident
        self.itemno = itemno
        self.skipfailed = skipfailed

    def _get_ident(self):
        return self.ident or self.package.extrafields.get(
            'origin', None
        ) or self.package.name or self.package.basename or 'item #{}'.format(
            self.itemno)

    @PackageMakerBase._simple_setter('origin', str, nzs.strip,
                                     nzs.forbid_newlines)
    def set_origin(self, origin):
        # XXX: convert to dedicated field
        self.set_extra_field('origin', origin)

    @PackageMakerBase._simple_setter('name', str, nzs.strip,
                                     nzs.forbid_newlines)
    def set_name(self, name):
        self.package.name = name

    @PackageMakerBase._simple_setter('name', str, nzs.strip,
                                     nzs.forbid_newlines)
    def set_basename(self, basename):
        self.package.basename = basename

    def prefix_name(self, prefix):
        self.package.name = prefix + self.package.name

    @PackageMakerBase._simple_setter('version', str, nzs.strip,
                                     nzs.forbid_newlines)
    def set_version(self, version, version_normalizer=None):
        self.package.rawversion = version
        self.package.origversion = version if version_normalizer is None else version_normalizer(
            version)
        self.package.version = self.package.origversion

    @PackageMakerBase._simple_setter('version', str, nzs.strip,
                                     nzs.forbid_newlines)
    def set_rawversion(self, rawversion):
        if rawversion != self.package.version:
            self.package.rawversion = rawversion

    def set_name_and_version(self, namever, version_normalizer=None):
        name, version = namever.rsplit('-', 1)
        self.set_name(name)
        self.set_version(version, version_normalizer)

    @PackageMakerBase._simple_setter('summary', str, nzs.strip)
    def set_summary(self, summary):
        self.package.comment = summary

    @PackageMakerBase._omnivorous_setter('maintainer', str, nzs.strip,
                                         nzs.forbid_newlines, nzs.tolower)
    def add_maintainers(self, *args):
        self.package.maintainers.extend(
            _iter_unique(args, self.package.maintainers))

    @PackageMakerBase._omnivorous_setter('category', str, nzs.strip,
                                         nzs.forbid_newlines)
    def add_categories(self, *args):
        # XXX: convert into array
        if not self.package.category:
            self.package.category = args[0]

    @PackageMakerBase._omnivorous_setter('homepage', str, nzs.strip, nzs.url,
                                         nzs.warn_whitespace,
                                         nzs.forbid_newlines)
    def add_homepages(self, *args):
        # XXX: convert into array
        if not self.package.homepage:
            self.package.homepage = args[0]

    @PackageMakerBase._omnivorous_setter('license', str, nzs.strip,
                                         nzs.forbid_newlines)
    def add_licenses(self, *args):
        self.package.licenses.extend(args)

    @PackageMakerBase._omnivorous_setter('download', str, nzs.strip, nzs.url,
                                         nzs.warn_whitespace,
                                         nzs.forbid_newlines)
    def add_downloads(self, *args):
        self.package.downloads.extend(
            _iter_unique(args, self.package.downloads))

    def set_flags(self, mask, is_set=True):
        assert (isinstance(mask, int))
        assert (isinstance(is_set, bool))
        self.package.SetFlag(mask, is_set)

    def set_extra_field(self, key, value):
        assert (isinstance(key, str))
        assert (isinstance(value, str))
        self.package.extrafields[key] = value

    def unwrap(self):
        return self.package

    def clone(self, ident=None, append_ident=None):
        offspring_ident = self.ident
        if ident is not None:
            offspring_ident = ident
        elif append_ident is not None:
            offspring_ident += append_ident

        offspring = PackageMaker(self.logger, offspring_ident, self.itemno)
        offspring.package = deepcopy(self.package)

        return offspring

    def check_sanity(self,
                     require_name=True,
                     require_version=True,
                     verbose=False):
        if require_name and not self.package.name:
            if verbose:
                self.log('package with no name', severity=Logger.ERROR)
            return False

        if require_version and not self.package.version:
            if verbose:
                self.log('package with no version', severity=Logger.ERROR)
            return False

        return True

    def __getattr__(self, key):
        return getattr(self.package, key)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        if exc_type:
            self.log('parsing failed ({}): {}: {}'.format(
                'skipped' if self.skipfailed else 'fatal', exc_type.__name__,
                exc_value),
                     severity=Logger.ERROR)

            if self.skipfailed:
                return True
Example #23
0
 def successor_action(package: Package,
                      package_context: PackageContext,
                      match_context: MatchContext) -> None:
     # XXX: the same as devel for now
     package.SetFlag(PackageFlags.devel, successor_flag)
Example #24
0
    def iter_parse(self, path):
        with open(path, 'r', encoding='utf-8') as jsonfile:
            for key, packagedata in json.load(jsonfile)['packages'].items():
                # see how Nix parses 'derivative' names in
                # https://github.com/NixOS src/libexpr/names.cc, DrvName::DrvName
                # it just splits on dash followed by non-letter
                #
                # this doesn't work well on 100% cases, it's an upstream problem
                match = re.match('(.+?)-([^a-zA-Z].*)$', packagedata['name'])
                if not match:
                    print('cannot extract version: {}/{}'.format(
                        key, packagedata['name']),
                          file=sys.stderr)
                    continue

                pkg = Package()
                pkg.name = match.group(1)
                pkg.version = match.group(2)

                # some exceptions
                for prefix in ('75dpi', '100dpi'):
                    if pkg.version.startswith(prefix):
                        pkg.name += '-' + prefix
                        pkg.version = pkg.version[len(prefix) + 1:]

                merged = pkg.name + '-' + pkg.version
                for pkgname in [
                        'liblqr-1', 'python2.7-3to2', 'python3.6-3to2'
                ]:
                    if merged.startswith(pkgname):
                        pkg.name = pkgname
                        pkg.version = merged[len(pkgname) + 1:]

                keyparts = key.split('.')
                if len(keyparts) > 1:
                    pkg.category = keyparts[0]

                if pkg.name.endswith('-git'):
                    pkg.name = pkg.name[:-4]
                    pkg.SetFlag(PackageFlags.ignore)

                if re.match('.*20[0-9]{2}-[0-9]{2}-[0-9]{2}', pkg.version):
                    pkg.SetFlag(PackageFlags.ignore)

                if re.match('[0-9a-f]*[a-f][0-9a-f]*$',
                            pkg.version) and len(pkg.version) >= 7:
                    print(
                        'ignoring version which looks like commit hash: {}/{}'.
                        format(key, packagedata['name']),
                        file=sys.stderr)
                    pkg.SetFlag(PackageFlags.ignore)

                meta = packagedata['meta']

                if 'homepage' in meta:
                    pkg.homepage = meta['homepage']
                    if isinstance(
                            pkg.homepage, list
                    ):  # XXX: remove after adding support for homepages array
                        pkg.homepage = pkg.homepage[0]

                if 'description' in meta and meta['description']:
                    pkg.comment = meta['description'].replace('\n',
                                                              ' ').strip()

                if 'maintainers' in meta:
                    if not isinstance(meta['maintainers'], list):
                        print('maintainers is not a list: {}/{}'.format(
                            key, packagedata['name']),
                              file=sys.stderr)
                    else:
                        pkg.maintainers += list(
                            extract_nix_maintainers(meta['maintainers']))

                if 'license' in meta:
                    pkg.licenses = extract_nix_licenses(meta['license'])

                if 'position' in meta:
                    posfile, posline = meta['position'].rsplit(':', 1)
                    pkg.extrafields['posfile'] = posfile
                    pkg.extrafields['posline'] = posline

                yield pkg
Example #25
0
 def debianism_action(package: Package,
                      package_context: PackageContext,
                      match_context: MatchContext) -> None:
     # XXX: the same as devel for now
     package.SetFlag(PackageFlags.devel, debianism_flag)
Example #26
0
 def rolling_action(package: Package,
                    package_context: PackageContext,
                    match_context: MatchContext) -> None:
     package.SetFlag(PackageFlags.rolling, rolling_flag)
Example #27
0
 def devel_action(package: Package, package_context: PackageContext,
                  match_context: MatchContext) -> None:
     package.SetFlag(PackageFlags.devel, devel_flag)
Example #28
0
 def snapshot_action(package: Package,
                     package_context: PackageContext,
                     match_context: MatchContext) -> None:
     # XXX: the same as ignored for now
     package.SetFlag(PackageFlags.ignore, snapshot_flag)
Example #29
0
class PackageMaker(PackageMakerBase):
    _package: Package
    _ident: Optional[str]
    _itemno: int
    _skipfailed: bool

    def __init__(self, logger: Logger, ident: Optional[str], itemno: int, skipfailed: bool = False) -> None:
        super(PackageMaker, self).__init__(logger)
        self._package = Package()
        self._ident = ident
        self._itemno = itemno
        self._skipfailed = skipfailed

    def _get_ident(self) -> str:
        return self._ident or self._package.extrafields.get('origin', None) or self._package.name or self._package.basename or 'item #{}'.format(self._itemno)

    @PackageMakerBase._simple_setter('origin', str, nzs.strip, nzs.forbid_newlines)
    def set_origin(self, origin: str) -> None:
        # XXX: convert to dedicated field
        self.set_extra_field('origin', origin)

    @PackageMakerBase._simple_setter('name', str, nzs.strip, nzs.forbid_newlines)
    def set_name(self, name: str) -> None:
        self._package.name = name

    @PackageMakerBase._simple_setter('basename', str, nzs.strip, nzs.forbid_newlines)
    def set_basename(self, basename: str) -> None:
        self._package.basename = basename

    def prefix_name(self, prefix: str) -> None:
        self._package.name = prefix + self._package.name

    @PackageMakerBase._simple_setter('version', str, nzs.strip, nzs.forbid_newlines)
    def set_version(self, version: str, version_normalizer: Optional[Callable[[str], str]] = None) -> None:
        self._package.rawversion = version
        self._package.origversion = version if version_normalizer is None else version_normalizer(version)
        self._package.version = self._package.origversion

    @PackageMakerBase._simple_setter('version', str, nzs.strip, nzs.forbid_newlines)
    def set_rawversion(self, rawversion: str) -> None:
        if rawversion != self._package.version:
            self._package.rawversion = rawversion

    def set_name_and_version(self, namever: str, version_normalizer: Optional[Callable[[str], str]] = None) -> None:
        name, version = namever.rsplit('-', 1)
        self.set_name(name)
        self.set_version(version, version_normalizer)

    @PackageMakerBase._simple_setter('arch', str, nzs.strip, nzs.forbid_newlines)
    def set_arch(self, arch: str) -> None:
        self._package.arch = arch

    @PackageMakerBase._simple_setter('summary', str, nzs.strip)
    def set_summary(self, summary: str) -> None:
        self._package.comment = summary

    @PackageMakerBase._omnivorous_setter('maintainer', str, nzs.strip, nzs.forbid_newlines, nzs.tolower)
    def add_maintainers(self, *args: Any) -> None:
        self._package.maintainers.extend(_iter_unique(args, self._package.maintainers))

    @PackageMakerBase._omnivorous_setter('category', str, nzs.strip, nzs.forbid_newlines)
    def add_categories(self, *args: Any) -> None:
        # XXX: convert into array
        if not self._package.category:
            self._package.category = args[0]

    @PackageMakerBase._omnivorous_setter('homepage', str, nzs.strip, nzs.url, nzs.warn_whitespace, nzs.forbid_newlines)
    def add_homepages(self, *args: Any) -> None:
        # XXX: convert into array
        if not self._package.homepage:
            self._package.homepage = args[0]

    @PackageMakerBase._omnivorous_setter('license', str, nzs.strip, nzs.forbid_newlines)
    def add_licenses(self, *args: Any) -> None:
        self._package.licenses.extend(args)

    @PackageMakerBase._omnivorous_setter('download', str, nzs.strip, nzs.url, nzs.warn_whitespace, nzs.forbid_newlines)
    def add_downloads(self, *args: Any) -> None:
        self._package.downloads.extend(_iter_unique(args, self._package.downloads))

    def set_flags(self, mask: int, is_set: bool = True) -> None:
        self._package.SetFlag(mask, is_set)

    def set_extra_field(self, key: str, value: str) -> None:
        self._package.extrafields[key] = value

    def unwrap(self) -> Package:
        return self._package

    def clone(self, ident: Optional[str] = None, append_ident: Optional[str] = None) -> 'PackageMaker':
        offspring_ident = self._ident
        if ident is not None:
            offspring_ident = ident
        elif append_ident is not None:
            offspring_ident = (offspring_ident or '') + append_ident

        offspring = PackageMaker(self._logger, offspring_ident, self._itemno)
        offspring._package = deepcopy(self._package)

        return offspring

    def check_sanity(self, require_name: bool = True, require_version: bool = True, verbose: bool = False) -> bool:
        if require_name and not self._package.name:
            if verbose:
                self.log('package with no name', severity=Logger.ERROR)
            return False

        if require_version and not self._package.version:
            if verbose:
                self.log('package with no version', severity=Logger.ERROR)
            return False

        return True

    def __getattr__(self, key: str) -> Any:
        return getattr(self._package, key)

    def __enter__(self) -> 'PackageMaker':
        return self

    def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> Optional[bool]:
        if exc_type:
            self.log('parsing failed ({}): {}: {}'.format(
                'skipped' if self._skipfailed else 'fatal',
                exc_type.__name__,
                exc_value
            ), severity=Logger.ERROR)

            if self._skipfailed:
                return True

        return None