Exemple #1
0
def error_from_dose3_report(report):
    def fixup_relation(rel):
        for o in rel:
            for d in o:
                if d['version']:
                    try:
                        newoperator = {'<': '<<', '>': '>>'}[d['version'][0]]
                    except KeyError:
                        pass
                    else:
                        d['version'] = (newoperator, d['version'][1])

    packages = [entry["package"] for entry in report]
    assert packages == ["sbuild-build-depends-main-dummy"]
    if report[0]["status"] != "broken":
        return None
    missing = []
    conflict = []
    for reason in report[0]["reasons"]:
        if "missing" in reason:
            relation = PkgRelation.parse_relations(
                reason["missing"]["pkg"]["unsat-dependency"])
            fixup_relation(relation)
            missing.extend(relation)
        if "conflict" in reason:
            relation = PkgRelation.parse_relations(
                reason["conflict"]["pkg1"]["unsat-conflict"])
            fixup_relation(relation)
            conflict.extend(relation)
    if missing:
        return UnsatisfiedAptDependencies(missing)
    if conflict:
        return UnsatisfiedAptConflicts(conflict)
 def update_deps(control, field, package, min_version, epoch=None):
     bdi = PkgRelation.parse_relations(control[field])
     if epoch is not None:
         epoch = "%d:" % epoch
     else:
         epoch = ""
     update_relation(bdi, package, ">=", epoch + "%d.%d.%d~" % min_version)
     control[field] = PkgRelation.str(bdi)
 def update_deps(control, field, package, min_version, epoch=None):
     bdi = PkgRelation.parse_relations(control[field])
     if epoch is not None:
         epoch = "%d:" % epoch
     else:
         epoch = ""
     update_relation(bdi, package, ">=", epoch + "%d.%d.%d~" % min_version)
     control[field] = PkgRelation.str(bdi)
def relationship_builder(relationship_line, getter):
    """Parse relationship_line into a IPackageRelationshipSet.

    'relationship_line' is parsed via PkgRelation.parse_relations.
    It also looks up the corresponding URL via the given 'getter'.
    Return empty list if no line is given.
    """
    relationship_set = PackageRelationshipSet()

    if not relationship_line:
        return relationship_set

    parsed_relationships = [
        token[0] for token in PkgRelation.parse_relations(relationship_line)
    ]

    for rel in parsed_relationships:
        name = rel['name']
        target_object = getter(name)
        if target_object is not None:
            url = canonical_url(target_object)
        else:
            url = None
        if rel['version'] is None:
            operator = u''
            version = u''
        else:
            operator, version = rel['version']
        relationship_set.add(name, operator, version, url)

    return relationship_set
Exemple #5
0
 def install(self, requirements):
     missing = []
     for req in requirements:
         try:
             if not req.met(self.apt.session):
                 missing.append(req)
         except NotImplementedError:
             missing.append(req)
     if not missing:
         return
     still_missing = []
     apt_requirements = []
     for m in missing:
         apt_req = self.resolve(m)
         if apt_req is None:
             still_missing.append(m)
         else:
             apt_requirements.append(apt_req)
     if apt_requirements:
         self.apt.satisfy([
             PkgRelation.str(chain(*[r.relations
                                     for r in apt_requirements]))
         ])
     if still_missing:
         raise UnsatisfiedRequirements(still_missing)
Exemple #6
0
def add_build_dependency(context, requirement: AptRequirement):
    if not isinstance(requirement, AptRequirement):
        raise TypeError(requirement)

    control_path = context.abspath("debian/control")
    try:
        with ControlEditor(path=control_path) as updater:
            for binary in updater.binaries:
                if requirement.touches_package(binary["Package"]):
                    raise CircularDependency(binary["Package"])
            for rel in requirement.relations:
                updater.source["Build-Depends"] = ensure_relation(
                    updater.source.get("Build-Depends", ""),
                    PkgRelation.str([rel]))
    except FormattingUnpreservable as e:
        logging.info("Unable to edit %s in a way that preserves formatting.",
                     e.path)
        return False

    desc = requirement.pkg_relation_str()

    if not updater.changed:
        logging.info("Giving up; dependency %s was already present.", desc)
        return False

    logging.info("Adding build dependency: %s", desc)
    return context.commit("Add missing build dependency on %s." % desc)
Exemple #7
0
def add_test_dependency(context, testname, requirement):
    if not isinstance(requirement, AptRequirement):
        raise TypeError(requirement)

    tests_control_path = context.abspath("debian/tests/control")

    # TODO(jelmer): If requirement is for one of our binary packages
    # but "@" is already present then don't do anything.

    try:
        with Deb822Editor(path=tests_control_path) as updater:
            command_counter = 1
            for control in updater.paragraphs:
                try:
                    name = control["Tests"]
                except KeyError:
                    name = "command%d" % command_counter
                    command_counter += 1
                if name != testname:
                    continue
                for rel in requirement.relations:
                    control["Depends"] = ensure_relation(
                        control.get("Depends", ""), PkgRelation.str([rel]))
    except FormattingUnpreservable as e:
        logging.info("Unable to edit %s in a way that preserves formatting.",
                     e.path)
        return False
    if not updater.changed:
        return False

    desc = requirement.pkg_relation_str()

    logging.info("Adding dependency to test %s: %s", testname, desc)
    return context.commit(
        "Add missing dependency for test %s on %s." % (testname, desc), )
Exemple #8
0
 def binary_pkg_matches(entry, binary):
     # TODO(jelmer): check versions
     if entry['name'] == binary['Package']:
         return True
     for provides_top in PkgRelation.parse_relations(
             binary.get('Provides', '')):
         for provides in provides_top:
             if entry['name'] == provides['name']:
                 return True
     return False
Exemple #9
0
def validate_relations(value):
    """
    Package Lists
    """
    relations = PkgRelation.parse_relations(value)
    for relation in relations:
        for rel in relation:
            if len(rel) == 3:
                raise ValidationError(
                    _("Cannot parse package relationship \"%s\"") %
                    rel.get("name", "untitled"))
 def rep_dbgsym_migration(m):
     rep = m.group(2).strip(b'"').strip(b"'").decode()
     if '$' in rep:
         # too complicated
         return m.group(0)
     rep = PkgRelation.parse_relations(rep)
     if migration_done(rep):
         issue = LintianIssue(
             'source', 'debug-symbol-migration-possibly-complete',
             '%s (line XX)' % (m.group(0).decode().strip()))
         if issue.should_fix():
             issue.report_fixed()
             return b''
     return m.group(0)
Exemple #11
0
 def explain(self, requirements):
     apt_requirements = []
     for r in requirements:
         apt_req = self.resolve(r)
         if apt_req is not None:
             apt_requirements.append((r, apt_req))
     if apt_requirements:
         yield (
             self.apt.satisfy_command([
                 PkgRelation.str(
                     chain(*[r.relations for o, r in apt_requirements]))
             ]),
             [o for o, r in apt_requirements],
         )
Exemple #12
0
def targeted_python_versions(tree: Tree, subpath: str) -> List[str]:
    with tree.get_file(os.path.join(subpath, "debian/control")) as f:
        control = Deb822(f)
    build_depends = PkgRelation.parse_relations(
        control.get("Build-Depends", ""))
    all_build_deps: Set[str] = set()
    for or_deps in build_depends:
        all_build_deps.update(or_dep["name"] for or_dep in or_deps)
    targeted = []
    if any(x.startswith("python3-") for x in all_build_deps):
        targeted.append("python3")
    if any(x.startswith("pypy") for x in all_build_deps):
        targeted.append("pypy")
    if any(x.startswith("python-") for x in all_build_deps):
        targeted.append("python")
    return targeted
Exemple #13
0
 def update_deps(control, field, package, min_version):
     bdi = PkgRelation.parse_relations(control[field])
     update_relation(bdi, package, ">=", "%d.%d.%d~" % min_version)
     control[field] = PkgRelation.str(bdi)
Exemple #14
0
 def __str__(self):
     return "Unsatisfied APT dependencies: %s" % PkgRelation.str(
         self.relations)
def generate_debian_package(args, config):
    debfile = Deb822(
        open("debian/control"),
        fields=["Build-Depends", "Build-Depends-Indep"])

    rel_str = debfile.get("Build-Depends")
    if debfile.has_key("Build-Depends-Indep"):
        rel_str = rel_str + "," + debfile.get("Build-Depends-Indep")

    relations = PkgRelation.parse_relations(rel_str)

    cache = Cache()

    # Check if all required packages are installed
    for dep in relations:
        if not check_deb_dependency_installed(cache, dep):
            # Install not found dependencies
            print("Dependency not matched: " + str(dep))
            if not install_dependency(cache, dep):
                print("Dependency cannot be installed: " + PkgRelation.str([dep
                                                                            ]))
                exit(1)

    changelog = Changelog(open("debian/changelog"))
    old_changelog = Changelog(open("debian/changelog"))

    dist = os.popen("lsb_release -c").read()
    dist = dist[dist.rfind(":") + 1::].replace("\n", "").replace(
        "\t", "").replace(" ", "")

    new_version = get_debian_version(args, dist)

    changelog.new_block(version=new_version,
                        package=changelog.package,
                        distributions="testing",
                        changes=["\n  Generating new package version\n"],
                        author=changelog.author,
                        date=strftime("%a, %d %b %Y %H:%M:%S %z"),
                        urgency=changelog.urgency)

    changelog.write_to_open_file(open("debian/changelog", 'w'))

    # Execute commands defined in config:
    if config.has_key("prebuild-command"):
        print("Executing prebuild-command: " + str(config["prebuild-command"]))
        if os.system(config["prebuild-command"]) != 0:
            print("Failed to execute prebuild command")
            exit(1)

    if os.system("dpkg-buildpackage -uc -us") != 0:
        print("Error generating package")
        exit(1)

    if os.system("sudo dpkg -i ../*" + new_version + "_*.deb") != 0:
        print("Packages are not installable")
        exit(1)

    files = glob.glob("../*" + new_version + "_*.deb")
    if args.command == "upload":
        for f in files:
            if f is files[-1]:
                is_last = True
            else:
                is_last = False
            if new_version.find("~") == -1:
                upload_package(args, config, dist, f)
            upload_package(args, config, dist + "-dev", f, publish=is_last)

    if args.clean:
        files = glob.glob("../*" + new_version + "*")
        for f in files:
            os.remove(f)

    # Write old changelog to let everything as it was
    old_changelog.write_to_open_file(open("debian/changelog", 'w'))
Exemple #16
0
    def verify(self):
        """Verify the uploaded .dsc file.

        This method is an error generator, i.e, it returns an iterator over
        all exceptions that are generated while processing DSC file checks.
        """

        for error in SourceUploadFile.verify(self):
            yield error

        # Check size and checksum of the DSC file itself
        try:
            self.checkSizeAndCheckSum()
        except UploadError as error:
            yield error

        try:
            raw_files = parse_and_merge_file_lists(self._dict, changes=False)
        except UploadError as e:
            yield e
            return

        files = []
        for attr in raw_files:
            filename, hashes, size = attr
            if not re_issource.match(filename):
                # DSC files only really hold on references to source
                # files; they are essentially a description of a source
                # package. Anything else is crack.
                yield UploadError("%s: File %s does not look sourceful." %
                                  (self.filename, filename))
                continue
            filepath = os.path.join(self.dirname, filename)
            try:
                file_instance = DSCUploadedFile(filepath, hashes, size,
                                                self.policy, self.logger)
            except UploadError as error:
                yield error
            else:
                files.append(file_instance)
        self.files = files

        if not re_valid_pkg_name.match(self.source):
            yield UploadError("%s: invalid source name %s" %
                              (self.filename, self.source))
        if not re_valid_version.match(self.dsc_version):
            yield UploadError("%s: invalid version %s" %
                              (self.filename, self.dsc_version))

        if not self.policy.distroseries.isSourcePackageFormatPermitted(
                self.format):
            yield UploadError(
                "%s: format '%s' is not permitted in %s." %
                (self.filename, self.format, self.policy.distroseries.name))

        # Validate the build dependencies
        for field_name in ['Build-Depends', 'Build-Depends-Indep']:
            field = self._dict.get(field_name, None)
            if field is not None:
                if field.startswith("ARRAY"):
                    yield UploadError(
                        "%s: invalid %s field produced by a broken version "
                        "of dpkg-dev (1.10.11)" % (self.filename, field_name))
                try:
                    with warnings.catch_warnings():
                        warnings.simplefilter("error")
                        PkgRelation.parse_relations(field)
                except Warning as error:
                    yield UploadError(
                        "%s: invalid %s field; cannot be parsed by deb822: %s"
                        % (self.filename, field_name, error))

        # Verify if version declared in changesfile is the same than that
        # in DSC (including epochs).
        if self.dsc_version != self.version:
            yield UploadError(
                "%s: version ('%s') in .dsc does not match version "
                "('%s') in .changes." %
                (self.filename, self.dsc_version, self.version))

        for error in self.checkFiles():
            yield error
Exemple #17
0
 def from_str(cls, text):
     return cls(PkgRelation.parse_relations(text))
Exemple #18
0
 def pkg_relation_str(self):
     return PkgRelation.str(self.relations)
Exemple #19
0
 def __repr__(self):
     return "%s.from_str(%r)" % (
         type(self).__name__,
         PkgRelation.str(self.relations),
     )
Exemple #20
0
 def __str__(self):
     return "Unsatisfied APT conflicts: %s" % PkgRelation.str(
         self.relations)