Beispiel #1
0
 def handle_condition_conflict(self, decision_point, final_plan, primary_key, \
         condition_set, result_set):
     conflict_condition, decision_condition = condition_set
     result = final_plan.check_pk(primary_key)
     if isinstance(result, int):
         conflict_id = final_plan[result].id
         if conflict_id not in self.conditional_packages:
             final_plan[result] = package
             return False
         for conflict_point in self.conditional_packages[conflict_id]:
             if conflict_point["type"].startswith(conflict_condition):
                 if decision_point["type"].startswith(decision_condition):
                     compare_result = utils.vercmp(decision_point["version"], \
                             conflict_point["version"])
                     if compare_result in result_set:
                         self.conflict_point = conflict_point
                         raise ConditionConflict(conflict_point)
Beispiel #2
0
    def select_pkgs(self):
        for pkg in self.instdb.get_all_packages():
            self.repo, self.category, self.name, self.version, self.slot = pkg
            # catch packages which are from the outside
            if not self.repodb.find_package(package_name=self.name, \
                    package_category=self.category):
                if not (self.category, self.name) in self.notfound_pkg:
                    self.notfound_pkg.append((self.category, self.name))

            # get version data from repository database
            repository_items = self.repodb.find_package(package_name=self.name, \
                    package_category=self.category)
            if not repository_items:
                # if the installed package could not found in the repository database
                # add the item to not-founds list
                self.notfound_pkg.append((self.category, self.name))
                continue

            # collect available package version by slot value
            available_versions = {}
            for item in repository_items:
                if item.slot in available_versions:
                    available_versions[item.slot].append(item.version)
                else:
                    available_versions[item.slot] = [item.version]

            # comparise versions
            for item in repository_items:
                if item.slot == self.slot:
                    best_version = utils.best_version(
                        available_versions[item.slot])
                    result = utils.vercmp(best_version, self.version)
                    if result != 0:
                        self.packages.append(
                            os.path.join(self.category, self.name) + ":" +
                            self.slot)
                        break

        if self.notfound_pkg:
            out.write(
                "%s: the following packages were installed but they could not be found in the database:\n\n"
                % out.color("WARNING", "brightyellow"))
            for no_category, no_name, in self.notfound_pkg:
                out.notify("%s/%s" % (no_category, no_name))
            out.write("\n")
Beispiel #3
0
    def select_pkgs(self):
        for pkg in self.instdb.get_all_packages():
            self.repo, self.category, self.name, self.version, self.slot = pkg
            # catch packages which are from the outside
            if not self.repodb.find_package(package_name=self.name, \
                    package_category=self.category):
                if not (self.category, self.name) in self.notfound_pkg:
                    self.notfound_pkg.append((self.category, self.name))

            # get version data from repository database
            repository_items = self.repodb.find_package(package_name=self.name, \
                    package_category=self.category)
            if not repository_items:
                # if the installed package could not found in the repository database
                # add the item to not-founds list
                self.notfound_pkg.append((self.category, self.name))
                continue

            # collect available package version by slot value
            available_versions = {}
            for item in repository_items:
                if item.slot in available_versions:
                    available_versions[item.slot].append(item.version)
                else:
                    available_versions[item.slot] = [item.version]

            # comparise versions
            for item in repository_items:
                if item.slot == self.slot:
                    best_version = utils.best_version(available_versions[item.slot])
                    result = utils.vercmp(best_version, self.version)
                    if result != 0:
                        self.packages.append(os.path.join(self.category, self.name)+":"+self.slot)
                        break

        if self.notfound_pkg:
            out.write("%s: the following packages were installed but they could not be found in the database:\n\n" 
                    % out.color("WARNING", "brightyellow"))
            for no_category, no_name, in self.notfound_pkg:
                out.notify("%s/%s" % (no_category, no_name))
            out.write("\n")
Beispiel #4
0
    def create_operation_plan(self):
        '''Resolve dependencies and prepares a convenient operation plan'''
        single_packages = PackageItem()
        for package in self.packages:
            self.parent_package = package
            self.current_package = None
            self.package_heap[package.id] = package
            dependencies = []
            package_dependencies = self.collect_dependencies(package)
            if not package_dependencies:
                single_packages.add(package)
                continue
            # Create a list that consists of parent and child items
            for dependency in package_dependencies:
                dependency.parent = package.category+"/"+package.name+"/"+package.slot
                dependencies.append((package.id, dependency))
            while True:
                buff = []
                for parent, dependency in dependencies:
                    self.current_package = dependency
                    self.parent_package = None
                    self.package_query.append((dependency.id, parent))
                    if dependency.id in self.processed:
                        if self.processed[dependency.id] == self.package_options.get(dependency.id, None):
                            # This package was processed and it has no option changes
                            continue

                    # Keep the package options to prevent extra transaction
                    self.processed[dependency.id] = self.package_options.get(dependency.id, None)

                    # Keep the package information for the next operations.
                    # We don't want to create a new transaction for it.
                    self.package_heap[dependency.id] = dependency

                    # Get its dependencies
                    package_collection = self.collect_dependencies(dependency)
                    if not package_collection:
                        # The item has no dependency
                        continue
                    # Create a list that consists of parent and child items
                    for item in package_collection:
                        item.parent = package.category+"/"+package.name+"/"+package.slot
                        buff.append((dependency.id, item))
                if not buff:
                    # End of the node
                    break
                dependencies = buff

        try:
            # Sort packages for building operation
            plan = sorter.topsort(self.package_query)
        except sorter.CycleError as err:
            answer, num_parents, children = err
            out.brightred("Circular dependency detected:\n")
            for items in sorter.find_cycles(parent_children=children):
                for item in items:
                    package = self.repodb.find_package(package_id=item).get(0)
                    out.write(package.repo+"/"+package.category+"/"+package.name+"-"\
                            +package.version+":"+package.slot+"  ")
            out.write("\n")
            raise DependencyError

        # This part detects inline option conflicts
        removed = {}
        option_conflict = set()
        for package_id in self.inline_option_targets:
            for target in self.inline_option_targets[package_id]:
                for option in self.inline_option_targets[package_id][target]:
                    if option.startswith("-"):
                        if option in removed:
                            removed[option].add((package_id, target))
                        else:
                            removed[option] = set([(package_id, target)])
                    else:
                        if "-"+option in removed:
                            for (my_pkg_id, my_target)  in removed["-"+option]:
                                if my_target == target:
                                    option_conflict.add((my_target, \
                                            self.package_heap[package_id], \
                                            self.package_heap[my_pkg_id],\
                                            option))
        if option_conflict:
            out.error("option conflict detected:\n")
            for (pkg, add, remove, option)in option_conflict:
                out.error(out.color(option, "red")+" option on "+pkg+"\n")
                out.warn("%s/%s/%s/%s adds the option." % (add.repo, add.category, \
                        add.name, add.version))
                out.warn("%s/%s/%s/%s removes the option." % (remove.repo, remove.category, \
                        remove.name, remove.version))
            lpms.terminate()

        self.conditional_versions = {}
        for (key, values) in self.conditional_packages.items():
            for value in values:
                target_package = self.package_heap[key]
                my_item = {
                            "type": value["type"],
                            "version": value["version"],
                            "target": target_package.category+"/"+target_package.name+\
                                    "/"+target_package.slot,
                }
                if not value["owner_id"] in self.conditional_versions:
                    self.conditional_versions[value["owner_id"]] = [my_item]
                else:
                    self.conditional_versions[value["owner_id"]].append(my_item)

        # TODO: I think I must use most professional way for ignore-depends feature.
        if lpms.getopt("--ignore-deps"):
            result = LCollect()
            result.packages = self.packages
            result.dependencies = self.package_dependencies
            result.options = self.package_options
            result.inline_option_targets = self.inline_option_targets
            result.conditional_versions = self.conditional_versions
            result.conflicts = self.conflicts
            return result

        # Workaround for postmerge dependencies
        for (id_dependency, id_package) in self.postmerge_dependencies:
            plan.remove(id_dependency)
            plan.insert(plan.index(id_package)+1, id_dependency)

        final_plan = PackageItem()
        required_package_ids = [package.id for package in self.packages]
        for package_id in plan:
            package = self.package_heap[package_id]
            continue_conditional = False
            # If a package has a conditional decision point,
            # we should consider the condition
            if package.id not in self.conditional_packages:
                for c_package_id in self.conditional_packages:
                    c_package = self.package_heap[c_package_id]
                    if package.pk == c_package.pk:
                        continue_conditional = True
                        if package_id in required_package_ids:
                            final_plan.add_by_pk(c_package)
                            break
                if package_id in required_package_ids:
                    if continue_conditional is False:
                        final_plan.add_by_pk(package)
            if continue_conditional:
                continue
            installed_package = self.instdb.find_package(
                    package_category=package.category,
                    package_name=package.name,
                    package_slot=package.slot
            )
            if installed_package:
                if package.id in self.inline_options:
                    if installed_package.get(0).applied_options is None:
                        final_plan.add_by_pk(package)
                        continue
                    continue_inline = False
                    for inline_option in self.inline_options[package.id]:
                        if not inline_option in installed_package.get(0).applied_options:
                            final_plan.add_by_pk(package)
                            continue_inline = True
                            break
                    if continue_inline:
                        continue
                try:
                    conditional_versions_query = self.instdb.find_conditional_versions(
                            target=package.category+"/"+package.name+"/"+package.slot)
                    if conditional_versions_query:
                        for item in conditional_versions_query:
                            item.decision_point["package_id"]=item.package_id
                            if package.id in self.conditional_packages:
                                if not item.decision_point in self.conditional_packages[package.id]:
                                    self.conditional_packages[package.id].append(item.decision_point)
                            else:
                                self.conditional_packages[package.id] = [item.decision_point]
                    if package.id in self.conditional_packages:
                        decision_points = self.conditional_packages[package.id]
                        for decision_point in decision_points:
                            comparison = utils.vercmp(installed_package.get(0).version, \
                                        decision_point["version"])
                            if decision_point["type"] == ">=":
                                if self.handle_condition_conflict(decision_point, final_plan, \
                                        package.pk, ("<", ">"), (0, 1)) is False:
                                    continue
                                if not comparison in (1, 0) or package.id in required_package_ids:
                                    final_plan.add_by_pk(package)
                            elif decision_point["type"] == "<":
                                if self.handle_condition_conflict(decision_point, final_plan, \
                                        package.pk, (">", "<"), (0, -1)) is False:
                                    continue
                                if comparison != -1:
                                    final_plan.add_by_pk(package)
                            elif decision_point["type"] == ">":
                                if self.handle_condition_conflict(decision_point, final_plan, \
                                        package.pk, ("<", ">"), (0, 1)) is False:
                                    continue
                                if comparison != 1 or package.id in required_package_ids:
                                    final_plan.add_by_pk(package)
                            elif decision_point["type"] == "<=":
                                if self.handle_condition_conflict(decision_point, final_plan, \
                                        package.pk, (">", "<"), (0, -1)) is False:
                                    continue
                                if not comparison in (-1, 0) or package.id in required_package_ids:
                                    final_plan.add_by_pk(package)
                            elif decision_point["type"] == "==":
                                if comparison != 0 or package.id in required_package_ids:
                                    final_plan.add_by_pk(package)
                except ConditionConflict:
                    if not "owner_package" in decision_point:
                        conflict_package = self.instdb.find_package(package_id=\
                                decision_point["package_id"]).get(0)
                        decision_point["owner_package"] = conflict_package.repo+"/"+ \
                        conflict_package.category+"/"+ \
                        conflict_package.name+"/"+ \
                        conflict_package.version

                    out.error("while selecting a convenient version of %s, a conflict detected:\n" % \
                            out.color(package.pk, "red"))
                    out.notify(decision_point["owner_package"]+" wants "+\
                            decision_point["type"]+decision_point["version"])
                    out.notify(self.conflict_point["owner_package"]+" wants "+\
                            self.conflict_point["type"]+self.conflict_point["version"])
                    lpms.terminate("\nplease contact the package maintainers.")

                # Use new options if the package is effected
                if self.use_new_options and not package in final_plan:
                    if package.id in self.package_options:
                        for option in self.package_options[package.id]:
                            if not option in installed_package.get(0).applied_options:
                                final_plan.add_by_pk(package)
                                break
            else:
                final_plan.add_by_pk(package)

        # Oh my god! Some packages have no dependency.
        if single_packages:
            for single_package in single_packages:
                for item_id in plan:
                    if self.package_heap[item_id].pk == single_package.pk:
                        single_packages.remove(single_package)
                        break
            for single_package in single_packages:
                final_plan.insert_into(0, single_package)

        # Create LCollect object to manage package dependency data
        operation_plan = LCollect()
        operation_plan.packages = final_plan
        operation_plan.dependencies = self.package_dependencies
        operation_plan.options = self.package_options
        operation_plan.inline_option_targets = self.inline_option_targets
        operation_plan.conditional_versions = self.conditional_versions
        operation_plan.conflicts = self.conflicts
        return operation_plan
Beispiel #5
0
    def get_convenient_package(self, package, instdb=False):
        def inline_options_management(inline_options):
            # TODO: inline_options variable must be a set
            # Check inline options, if an option is not available for the package, warn the user
            for inline_option in inline_options:
                if not inline_option in package.options:
                    out.warn("%s option is not available for %s/%s/%s-%s. So that the option is removing..." % (
                        inline_option,
                        package.repo,
                        package.category,
                        package.name,
                        package.version
                    ))
                    inline_options.remove(inline_option)

            if inline_options:
                target = self.current_package.id if self.current_package is not \
                        None else self.parent_package.id
                my_package = package.category+"/"+package.name+"/"+package.slot
                if target in self.inline_option_targets:
                    if my_package in self.inline_option_targets[target]:
                        for option in inline_options:
                            self.inline_option_targets[target][my_package].add(option)
                    else:
                        self.inline_option_targets[target][my_package] = set(inline_options)
                else:
                    self.inline_option_targets[target] = {my_package: set(inline_options)}
                
                if package.id in self.inline_options:
                    if not package.id in self.package_options:
                        self.package_options[package.id] = set()
                    for option in inline_options:
                        if not option in self.inline_options[package.id]:
                            self.inline_options[package.id].append(option)
                            if package.id in self.package_options:
                                self.package_options[package.id].add(option)
                else:
                    self.inline_options[package.id] = inline_options
                    if package.id in self.package_options:
                        for inline_option in inline_options:
                            self.package_options[package.id].add(inline_option)
                    else:
                        self.package_options[package.id] = set(inline_options)

        convenient_arches = utils.get_convenient_arches(self.conf.arch)
        current_package = self.parent_package if self.parent_package is not \
                None else self.current_package
        result = LCollect()
        database = self.repodb if instdb is False else self.instdb
        slot = None
        gte, lte, lt, gt, et = False, False, False, False, False
        slot_parsed = package.split(":")

        if len(slot_parsed) == 2:
            data, slot = slot_parsed
        elif len(slot_parsed) > 2:
            out.error("%s invalid dependency in %s.py" % (data, self.current_package))
            # Use and exception
            raise DependencyError
        else:
            data = package

        if ">=" == data[:2]:
            gte = True
            pkgname = data[2:]
        elif "<=" == data[:2]:
            lte = True
            pkgname = data[2:]
        elif "<" == data[:1]:
            lt = True
            pkgname = data[1:]
        elif ">" == data[:1]:
            gt = True
            pkgname = data[1:]
        elif "==" == data[:2]:
            et = True
            pkgname = data[2:]
        else:
            category, name = data.split("/")
            inline_options = self.parse_inline_options(name)
            if inline_options:
                name = name[:name.index("[")]
            if (category, name) in self.repository_cache:
                results = self.repository_cache[(category, name)]
            else:
                results = database.find_package(package_name=name, package_category=category)
                self.repository_cache[(category, name)] = results
            slot = self.get_convenient_slot(results, slot)
            if not results:
                if instdb:
                    return
                current_package = current_package.repo+"/"+current_package.category+\
                        "/"+current_package.name+"-"+current_package.version+":"+current_package.slot
                out.error("unmet dependency: %s depends on %s" % (out.color(current_package, \
                        "red"), out.color(package, "red")))
                raise DependencyError
            try:
                package = utils.get_convenient_package(
                        results, 
                        self.locked_packages,
                        self.custom_arch_requests, 
                        convenient_arches, 
                        self.instdb, 
                        slot
                )
            except UnavailablePackage:
                for result in results:
                    out.error("%s/%s/%s-%s:%s {%s} is unavailable for your arch(%s)." % (result.repo, result.category, \
                            result.name, result.version, result.slot, result.arch, self.conf.arch))
                out.write("\n")
                out.write("%s %s/%s/%s-%s:%s {%s}\n" % (out.color("->", "brightyellow"), current_package.repo, \
                        current_package.category, current_package.name, current_package.version, \
                        current_package.slot, current_package.arch))
                out.write(" %s %s/%s/%s-%s:%s {%s}\n" % (out.color("->", "brightyellow"), current_package.repo, \
                        current_package.category, current_package.name, current_package.version, \
                        current_package.slot, current_package.arch))
                raise DependencyError
            except LockedPackage:
                out.error("these package(s) is/are locked by the system administrator:")
                for result in results:
                    out.error_notify("%s/%s/%s-%s:%s {%s}" % (result.repo, result.category, \
                            result.name, result.version, result.slot, result.arch))
                out.write("\n")
                out.write("%s %s/%s/%s-%s:%s {%s}\n" % (out.color("->", "brightyellow"), current_package.repo, \
                        current_package.category, current_package.name, current_package.version, \
                        current_package.slot, current_package.arch))
                out.write(" %s %s/%s/%s-%s:%s {%s}\n" % (out.color("->", "brightyellow"), current_package.repo, \
                        current_package.category, current_package.name, current_package.version, \
                        current_package.slot, current_package.arch))
                raise DependencyError

            # Set some variables to manage inline options
            inline_options_management(inline_options)

            return package

        category, name = pkgname.split("/")
        inline_options = self.parse_inline_options(name)
        if inline_options:
            name = name[:name.index("[")]
        name, version = utils.parse_pkgname(name)
        if (category, name) in self.repository_cache:
            results = self.repository_cache[(category, name)]
        else:
            results = database.find_package(package_name=name, package_category=category)
            self.repository_cache[(category, name)] = results
        slot = self.get_convenient_slot(results, slot)
        packages = []
        decision_point = {}
        owner_package = current_package.repo+"/"+current_package.category+\
                "/"+current_package.name+"-"+current_package.version
        if gte:
            decision_point = {"type": ">=", "version": version, \
                    "owner_package": owner_package, "owner_id": current_package.id}
            for result in results:
                comparison = utils.vercmp(result.version, version)
                if comparison == 1 or comparison == 0:
                    packages.append(result)
        elif lte:
            decision_point = {"type": "<=", "version": version, \
                    "owner_package": owner_package, "owner_id": current_package.id}
            for result in results:
                comparison = utils.vercmp(result.version, version)
                if comparison == -1 or comparison == 0:
                    packages.append(result)
        elif lt:
            decision_point = {"type": "<", "version": version, \
                    "owner_package": owner_package, "owner_id": current_package.id}
            for result in results:
                comparison = utils.vercmp(result.version, version)
                if comparison == -1:
                    packages.append(result)
        elif gt:
            decision_point = {"type": ">", "version": version, \
                    "owner_package": owner_package, "owner_id": current_package.id}
            for result in results:
                comparison = utils.vercmp(result.version, version)
                if comparison == 1:
                    packages.append(result)
        elif et:
            decision_point = {"type": "==", "version": version, \
                    "owner_package": owner_package, "owner_id": current_package.id}
            for result in results:
                comparison = utils.vercmp(result.version, version)
                if comparison == 0:
                    packages.append(result)

        if not packages:
            out.error("unmet dependency: %s/%s/%s-%s:%s {%s} depends on %s" % \
                    (current_package.repo, \
                    current_package.category, \
                    current_package.name, \
                    current_package.version, \
                    current_package.slot, \
                    current_package.arch, \
                    out.color(package, "red")))
            raise DependencyError

        try:
            package = utils.get_convenient_package(
                    results if not packages else packages,
                    self.locked_packages,
                    self.custom_arch_requests,
                    convenient_arches,
                    self.instdb,
                    slot
                    )
        except UnavailablePackage:
            for result in results:
                out.error("%s/%s/%s-%s:%s {%s}is unavailable for your arch(%s)." % (result.repo, result.category, \
                        result.name, result.version, result.slot, result.arch, self.conf.arch))
            out.write("\n")
            out.write("%s %s/%s/%s-%s:%s {%s}\n" % (out.color("->", "brightyellow"), current_package.repo, \
                    current_package.category, current_package.name, current_package.version, \
                    current_package.slot, current_package.arch))
            out.write(" %s %s/%s/%s-%s:%s {%s}\n" % (out.color("->", "brightyellow"), current_package.repo, \
                    current_package.category, current_package.name, current_package.version, \
                    current_package.slot, current_package.arch))
            raise DependencyError
        except LockedPackage:
            out.error("these package(s) is/are locked by the system administrator:")
            for result in results:
                out.error_notify("%s/%s/%s-%s:%s {%s}" % (result.repo, result.category, \
                        result.name, result.version, result.slot, result.arch))
            out.write("\n")
            out.write("%s %s/%s/%s-%s:%s {%s}\n" % (out.color("->", "brightyellow"), current_package.repo, \
                    current_package.category, current_package.name, current_package.version, \
                    current_package.slot, current_package.arch))
            out.write(" %s %s/%s/%s-%s:%s {%s}\n" % (out.color("->", "brightyellow"), current_package.repo, \
                    current_package.category, current_package.name, current_package.version, \
                    current_package.slot, current_package.arch))
            raise DependencyError

        # Set some variables to manage inline options
        inline_options_management(inline_options)

        if package.id in self.conditional_packages:
            self.conditional_packages[package.id].append(decision_point)
        else:
            self.conditional_packages[package.id] = [decision_point]

        return package
Beispiel #6
0
def show(packages, conflicts, options, installdb):
    '''Shows operation summary to the user'''
    # TODO: This can be splitted as a module
    for package in packages:
        status_bar = [' ', '  ']
        other_version = ""
        installed_packages = installdb.find_package(
                package_name=package.name, \
                package_category=package.category)
        if not installed_packages:
            installed_package = None
            status_bar[0] = out.color("N", "brightgreen")
        else:
            if not [installed_package for installed_package in installed_packages \
                    if package.slot == installed_package.slot]:
                status_bar[1] = out.color("NS", "brightgreen")
            else:
                for installed_package in installed_packages:
                    if installed_package.slot == package.slot:
                        if package.version != installed_package.version:
                            compare = utils.vercmp(package.version, \
                                    installed_package.version)
                            if compare == -1:
                                status_bar[0] = out.color("D", "brightred")
                                other_version = "[%s]" % out.color(\
                                        installed_package.version, "brightred")
                            elif compare == 1:
                                status_bar[0] = out.color("U", "brightgreen")
                                other_version = "[%s]" % out.color(\
                                        installed_package.version, "green")
                        elif package.version == installed_package.version:
                            status_bar[0] = out.color("R", "brightyellow")

        class FormattedOptions(list):
            def __init__(self, data):
                super(FormattedOptions, self).extend(data)

            def append(self, item, color=None):
                self.remove(item)
                if color is not None:
                    super(FormattedOptions, self).insert(0, out.color("*"+item, color))
                else:
                    super(FormattedOptions, self).insert(0, item)

        formatted_options = []
        if package.options is not None:
            installed_package = None
            for item in installed_packages:
                if item.slot == package.slot:
                    installed_package = item
            formatted_options = FormattedOptions(package.options)
            if package.id in options:
                if not status_bar[0].strip() or not status_bar[1].strip():
                    for applied_option in options[package.id]:
                        if installed_package:
                            if installed_package.applied_options is not None and not \
                                    applied_option in installed_package.applied_options:
                                formatted_options.append(applied_option, "brightgreen")
                                continue
                            elif installed_package.applied_options is None:
                                formatted_options.append(applied_option, "brightgreen")
                                continue
                        formatted_options.append(applied_option, "red")
                    if installed_package and installed_package.applied_options is not None:
                        for applied_option in installed_package.applied_options:
                            if not applied_option in options[package.id]:
                                formatted_options.append(applied_option, "brightyellow")
            else:
                for option in package.options:
                    if installed_package and installed_package.applied_options is not None and \
                            option in installed_package.applied_options:
                        formatted_options.append(option, "brightyellow")
                    else:
                        formatted_options.append(option)
        else:
            if hasattr(installed_package, "applied_options") and installed_package.applied_options is not None:
                formatted_options = [out.color("%"+applied_option, "brightyellow") \
                        for applied_option in installed_package.applied_options]

        out.write("  [%s] %s/%s/%s {%s:%s} {%s} %s%s\n" % (
                " ".join(status_bar), \
                package.repo, \
                package.category, \
                package.name, \
                out.color(package.slot, "yellow"),\
                out.color(package.version, "green"),\
                package.arch, \
                other_version, \
                " ("+", ".join(formatted_options)+")" if formatted_options else ""
                )
        )
        
        if package.id in conflicts:
            for conflict in conflicts[package.id]:
                category, name, slot = conflict.split("/")
                conflict = installdb.find_package(package_name=name, \
                        package_category=category, \
                        package_slot = slot).get(0)
                out.write("\t %s %s/%s/%s-%s" % (out.color(">> conflict:", "green"), \
                conflict.repo,\
                        conflict.category, \
                            conflict.name, \
                            conflict.version
                    ))