Esempio n. 1
0
def system(cmd, show=False, stage=None, sandbox=None):
    cfg = conf.LPMSConfig()
    if sandbox is None:
        sandbox = True if cfg.sandbox else False
        # override 'sandbox' variable if the user wants to modifiy from cli
        if lpms.getopt('--enable-sandbox'):
            sandbox = True
        elif lpms.getopt('--disable-sandbox'):
            sandbox = False
    if lpms.getopt("--verbose"):
        ret, output, err = run_cmd(cmd, True)
    elif (not cfg.print_output or lpms.getopt("--quiet")) \
            and not show:
        ret, output, err = run_cmd(cmd, show=False, enable_sandbox=sandbox)
    else:
        ret, output, err = run_cmd(cmd, show=True, enable_sandbox=sandbox)

    if ret != 0:
        if not conf.LPMSConfig().print_output or lpms.getopt("--quiet"):
            out.brightred("\n>> error messages:\n")
            out.write(err)
        out.warn("command failed: %s" % out.color(cmd, "red"))
        if stage and output and err:
            return False, output + err
        return False
    return True
Esempio n. 2
0
def system(cmd, show=False, stage=None, sandbox=None):
    cfg = conf.LPMSConfig()
    if sandbox is None:
        sandbox = True if cfg.sandbox else False
        # override 'sandbox' variable if the user wants to modifiy from cli
        if lpms.getopt("--enable-sandbox"):
            sandbox = True
        elif lpms.getopt("--disable-sandbox"):
            sandbox = False
    if lpms.getopt("--verbose"):
        ret, output, err = run_cmd(cmd, True)
    elif (not cfg.print_output or lpms.getopt("--quiet")) and not show:
        ret, output, err = run_cmd(cmd, show=False, enable_sandbox=sandbox)
    else:
        ret, output, err = run_cmd(cmd, show=True, enable_sandbox=sandbox)

    if ret != 0:
        if not conf.LPMSConfig().print_output or lpms.getopt("--quiet"):
            out.brightred("\n>> error messages:\n")
            out.write(err)
        out.warn("command failed: %s" % out.color(cmd, "red"))
        if stage and output and err:
            return False, output + err
        return False
    return True
Esempio n. 3
0
def run_cmd(cmd, show=True, enable_sandbox=True):
    stdout = None
    stderr = None
    if enable_sandbox:
        # FIXME: getopt should not do this.
        # the verbosity of messages, defaults to 1
        # 1 - error
        # 2 - warning
        # 3 - normal
        # 4 - verbose
        # 5 - debug
        # 6 - crazy debug
        log_level = lpms.getopt("--sandbox-log-level", like=True)
        if log_level is None:
            log_level = "1"
        if not log_level in ("1", "2", "3", "4", "5", "6"):
            out.warn("%s is an invalid sandbox log level." % log_level)
        cmd = "%s --config=%s --log-level=%s --log-file=%s -- %s" % (
            cst.sandbox_app,
            cst.sandbox_config,
            log_level,
            cst.sandbox_log,
            cmd,
        )
    if not show:
        stdout = subprocess.PIPE
        stderr = subprocess.PIPE
    result = subprocess.Popen(cmd, shell=True, stdout=stdout, stderr=stderr)
    output, err = result.communicate()
    return result.returncode, output, err
Esempio n. 4
0
    def run(self):
        if lpms.getopt("--help") or len(self.params) == 0:
            self.usage()

        for param in self.params:
            param = param.split("/")
            if len(param) == 3:
                myrepo, mycategory, myname = param
                packages = self.repodb.find_package(
                    package_name=myname, package_repo=myrepo, package_category=mycategory
                )
            elif len(param) == 2:
                mycategory, myname = param
                packages = self.repodb.find_package(package_name=myname, package_category=mycategory)
            elif len(param) == 1:
                packages = self.repodb.find_package(package_name=param[0])
            else:
                out.error("%s seems invalid." % out.color("/".join(param), "brightred"))
                lpms.terminate()
            if not packages:
                out.error("%s not found!" % out.color("/".join(param), "brightred"))
                lpms.terminate()

            # Show time!
            self.show_package(packages)
Esempio n. 5
0
def run_cmd(cmd, show=True, enable_sandbox=True):
    stdout = None
    stderr = None
    if enable_sandbox:
        # FIXME: getopt should not do this.
        # the verbosity of messages, defaults to 1
        # 1 - error
        # 2 - warning
        # 3 - normal
        # 4 - verbose
        # 5 - debug
        # 6 - crazy debug
        log_level = lpms.getopt("--sandbox-log-level", like=True)
        if log_level is None:
            log_level = "1"
        if not log_level in ('1', '2', '3', '4', '5', '6'):
            out.warn("%s is an invalid sandbox log level." % log_level)
        cmd = "%s --config=%s --log-level=%s --log-file=%s -- %s" % (cst.sandbox_app, cst.sandbox_config, \
                log_level, cst.sandbox_log, cmd)
    if not show:
        stdout = subprocess.PIPE
        stderr = subprocess.PIPE
    result = subprocess.Popen(cmd, shell=True, stdout=stdout, stderr=stderr)
    output, err = result.communicate()
    return result.returncode, output, err
Esempio n. 6
0
    def run(self):
        if lpms.getopt("--help") or len(self.params) == 0:
            self.usage()

        for param in self.params:
            param = param.split("/")
            if len(param) == 3:
                myrepo, mycategory, myname = param
                packages = self.repodb.find_package(package_name=myname, \
                        package_repo=myrepo, package_category=mycategory)
            elif len(param) == 2:
                mycategory, myname = param
                packages = self.repodb.find_package(package_name=myname, \
                        package_category=mycategory)
            elif len(param) == 1:
                packages = self.repodb.find_package(package_name=param[0])
            else:
                out.error("%s seems invalid." %
                          out.color("/".join(param), "brightred"))
                lpms.terminate()
            if not packages:
                out.error("%s not found!" %
                          out.color("/".join(param), "brightred"))
                lpms.terminate()

            # Show time!
            self.show_package(packages)
Esempio n. 7
0
 def sync(self):
     if self.git_repo():
         os.chdir(self.repo_path)
         if lpms.getopt("--reset"):
             out.warn("forcing git to overwrite local files")
             shelltools.system("%s reset --hard HEAD" % self.git_binary, sandbox=False)
             shelltools.system("%s clean -f -d" % self.git_binary, sandbox=False)
         shelltools.system("%s pull -f -u origin" % self.git_binary, sandbox=False)
     else:
         os.chdir(os.path.dirname(self.repo_path))
         shelltools.system("%s clone %s %s" % (self.git_binary, self.remote, self.repo), sandbox=False)
Esempio n. 8
0
 def sync(self):
     if self.git_repo():
         os.chdir(self.repo_path)
         if lpms.getopt("--reset"):
             out.warn("forcing git to overwrite local files")
             shelltools.system("%s reset --hard HEAD" % self.git_binary,
                               sandbox=False)
             shelltools.system("%s clean -f -d" % self.git_binary,
                               sandbox=False)
         shelltools.system("%s pull -f -u origin" % self.git_binary,
                           sandbox=False)
     else:
         os.chdir(os.path.dirname(self.repo_path))
         shelltools.system("%s clone %s %s" %
                           (self.git_binary, self.remote, self.repo),
                           sandbox=False)
Esempio n. 9
0
 def update_repository(self, repo_name):
     exceptions = ['scripts', 'licenses', 'news', 'info', 'libraries', '.git', '.svn']
     # fistly, drop the repo
     self.repodb.database.delete_repository(repo_name, commit=True)
     repo_path = os.path.join(cst.repos, repo_name)
     for category in os.listdir(repo_path):
         target_directory = os.path.join(repo_path, category)
         if category in exceptions or not os.path.isdir(target_directory):
             continue
         packages = os.listdir(target_directory)
         try:
             packages.remove("info.xml")
         except ValueError:
             pass
         if lpms.getopt("--verbose"):
             out.notify("%s" % out.color(category, "brightwhite"))
         for my_pkg in packages:
             try:
                 self.update_package(repo_path, category, my_pkg)
             except IntegrityError:
                 continue
Esempio n. 10
0
 def update_repository(self, repo_name):
     exceptions = [
         'scripts', 'licenses', 'news', 'info', 'libraries', '.git', '.svn'
     ]
     # fistly, drop the repo
     self.repodb.database.delete_repository(repo_name, commit=True)
     repo_path = os.path.join(cst.repos, repo_name)
     for category in os.listdir(repo_path):
         target_directory = os.path.join(repo_path, category)
         if category in exceptions or not os.path.isdir(target_directory):
             continue
         packages = os.listdir(target_directory)
         try:
             packages.remove("info.xml")
         except ValueError:
             pass
         if lpms.getopt("--verbose"):
             out.notify("%s" % out.color(category, "brightwhite"))
         for my_pkg in packages:
             try:
                 self.update_package(repo_path, category, my_pkg)
             except IntegrityError:
                 continue
Esempio n. 11
0
def color(msg, cl):
    if lpms.getopt("--no-color") or lpms.getopt(
            "-n") or not conf.LPMSConfig().colorize:
        return msg
    return colors[cl] + msg + colors['default']
Esempio n. 12
0
def color(msg, cl):
    if lpms.getopt("--no-color") or lpms.getopt("-n") or not conf.LPMSConfig().colorize:
        return msg
    return colors[cl] + msg + colors['default']
Esempio n. 13
0
        if not self.is_installed(category, name, version):
            raise NotInstalled("%s/%s-%s is not installed." %
                               (category, name, version))
        filesdb_cursor = self.cursor(category, name, version)
        return filesdb_cursor.content

    def has_path(self, category, name, version, path):
        '''Checks given package for given path'''
        if not self.is_installed(category, name, version):
            raise NotInstalled("%s/%s-%s is not installed." %
                               (category, name, version))
        filesdb_cursor = self.cursor(category, name, version)
        return filesdb_cursor.has_path(path)


if lpms.getopt("--help"):
    print(
        "A script that to migrate old xml based files database to new sql based one"
    )
    lpms.terminate()

installdb = dbapi.InstallDB()
fapi = FilesAPI()
shelltools.remove_file("/var/db/lpms/filesdb.db")
_filesdb = dbapi.FilesDB()

i = 0
for pkg in installdb.get_all_names():
    repo, category, name = pkg
    versions = installdb.get_version(name,
                                     repo_name=repo,
Esempio n. 14
0
    def update_package(self, repo_path, category, my_pkg, my_version = None, update = False):
        dataset = LCollect()
        # Register some variables to use after
        self.env.repo = os.path.basename(repo_path)
        self.env.category = category

        dataset.repo = self.env.repo
        dataset.category = category

        os.chdir(os.path.join(repo_path, category, my_pkg))
        for pkg in glob.glob("*"+cst.spec_suffix):
            script_path = os.path.join(repo_path, category, my_pkg, pkg)

            self.env.name, self.env.version = utils.parse_pkgname(pkg.split(cst.spec_suffix)[0])

            dataset.name = self.env.name
            dataset.version = self.env.version

            # FIXME: We must develop a upper-class or environment to 
            # use that cases to prevent code duplication

            # Begins code duplication
            interphase = re.search(r'-r[0-9][0-9]', self.env.version)
            if not interphase:
                interphase = re.search(r'-r[0-9]', self.env.version)
            self.env.raw_version = self.env.version
            self.env.revision = ""
            # Now, set real values of these variables if package revisioned. 
            if interphase is not None and interphase.group():
                self.env.raw_version = self.env.version.replace(interphase.group(), "")
                self.env.revision = interphase.group()
            # End of code duplication

            self.env.__dict__["fullname"] = self.env.name+"-"+self.env.version

            if not self.import_script(script_path):
                out.error("an error occured while processing the spec: %s" \
                        % out.color(script_path, "red"))
                out.error("please report the above error messages to the package maintainer.")
                continue

            metadata = utils.metadata_parser(self.env.metadata)
            metadata.update({"name": self.env.name, "version": self.env.version})
            # This method checks metadata integrity. 
            # It warn the user and pass the spec if a spec is broken
            self.check_metadata_integrity(metadata)
            # These values are optional
            if not "options" in metadata:
                metadata.update({"options": None})
            if not "slot" in metadata:
                metadata.update({"slot": "0"})
            if not "src_url" in metadata:
                metadata.update({"src_url": None})

            if lpms.getopt("--verbose"):
                out.write("    %s-%s\n" % (self.env.name, self.env.version))
            
            try:
                dataset.summary = metadata['summary']
                dataset.homepage = metadata['homepage']
                dataset.license = metadata['license']
                dataset.src_uri = metadata['src_url']
                if metadata['options'] is None:
                    dataset.options = None
                else:
                    dataset.options = metadata['options'].split(" ")
                dataset.slot = metadata['slot']

            except KeyError as err:
                out.error("%s/%s/%s-%s: invalid metadata" % (repo_name, category, \
                        self.env.name, self.env.version))
                out.warn("repository update was failed and the repository database was removed.")
                out.warn("you can run 'lpms --reload-previous-repodb' command to reload previous db version.")
                lpms.terminate("good luck!")

            if update:
                self.repodb.delete_package(package_repo=dataset.repo, package_category=dataset.category, \
                        package_name=self.env.name, package_version=self.env.version)

            static_depends_runtime = []; static_depends_build = []; static_depends_postmerge = []; static_depends_conflict = []
            if 'depends' in self.env.__dict__.keys():
                deps = utils.depends_parser(self.env.depends)
                if 'runtime' in deps:
                    static_depends_runtime.extend(deps['runtime'])
                if 'build' in deps:
                    static_depends_build.extend(deps['build'])
                if 'common' in deps:
                    static_depends_runtime.extend(deps['common'])
                    static_depends_build.extend(deps['common'])
                if 'postmerge' in deps:
                    static_depends_postmerge.extend(deps['postmerge'])
                if 'conflict' in deps:
                    static_depends_conflict.extend(deps['conflict'])

            optional_depends_runtime = []; optional_depends_build = []; optional_depends_postmerge = []; optional_depends_conflict = []
            for opt in ('opt_common', 'opt_conflict', 'opt_postmerge', 'opt_runtime', 'opt_build'):
                try:
                    deps = utils.parse_opt_deps(getattr(self.env, opt))
                    if opt.split("_")[1] == "runtime":
                        optional_depends_runtime.append(deps)
                    elif opt.split("_")[1] == "build":
                        optional_depends_build.append(deps)
                    elif opt.split("_")[1] == "common":
                        optional_depends_build.append(deps)
                        optional_depends_runtime.append(deps)
                    elif opt.split("_")[1] == "postmerge":
                        optional_depends_postmerge.append(deps)
                    elif opt.split("_")[1] == "conflict":
                        optional_depends_conflict.append(deps)
                    del deps
                except AttributeError:
                    continue

            dataset.optional_depends_runtime = optional_depends_runtime
            dataset.optional_depends_build = optional_depends_build
            dataset.optional_depends_postmerge = optional_depends_postmerge
            dataset.optional_depends_conflict = optional_depends_conflict

            dataset.static_depends_runtime = static_depends_runtime
            dataset.static_depends_build = static_depends_build
            dataset.static_depends_postmerge = static_depends_postmerge
            dataset.static_depends_conflict = static_depends_conflict

            if metadata['arch'] is not None:
                arches = metadata['arch'].split(" ")
                for arch in arches:
                    dataset.arch = arch
                    self.repodb.insert_package(dataset)
            else:
                dataset.arch = None
                self.repodb.insert_package(dataset)

            # remove optional keys
            for key in ('depends', 'options', 'opt_runtime', 'opt_build', \
                    'opt_conflict', 'opt_common', 'opt_postmerge'):
                try:
                    del self.env.__dict__[key]
                except KeyError:
                    pass
            self.packages_num += 1
Esempio n. 15
0
def remove_package(pkgnames, instruction):
    '''Triggers remove operation for given packages'''
    if instruction.like:
        # handle shortened package names
        database = dbapi.InstallDB()
        for item in instruction.like:
            query = database.db.cursor.execute("SELECT name FROM package where name LIKE ?", (item,))
            results = query.fetchall()
            if results:
                for result in results:
                    pkgnames.append(result[0])
        del database
    file_relationsdb = dbapi.FileRelationsDB()
    #try:
    packages = [GetPackage(pkgname, installdb=True).select() for pkgname in pkgnames]
    #except PackageNotFound as package_name:
    #    out.error("%s seems not installed." % package_name)
    #    lpms.terminate()

    instruction.count = len(packages); index = 0;
    # FIXME: I must create a new reverse dependency handler implementation

    #if instruct["show-reverse-depends"]:
    #    instruct["ask"] = True
    #    # WARNING: the mechanism only shows directly reverse dependencies
    #    # supposing that if A is a reverse dependency of B and C is depends on A.
    #    # when the user removes B, A and C will be broken. But lpms will warn the user about A.
    #    broken_packages = []
    #    reversedb = dbapi.ReverseDependsDB()
    #    out.normal("resolving primary reverse dependencies...\n")
    #    for package in packages:
    #        category, name, version = package[1:]
    #        if lpms.getopt("--use-file-relations"):
    #            broken_packages.extend(file_relations.get_packages(category, name, version))
    #        else:
    #            broken_packages.extend(reversedb.get_reverse_depends(category, name))

    #    if broken_packages:
    #        out.warn("the following packages will be broken:\n")
    #        for broken_package in broken_packages:
    #            broken_repo, broken_category, broken_name, broken_version = broken_package
    #            out.write(" %s %s/%s/%s-%s\n" % (out.color(">", "brightred"), broken_repo, broken_category, \
    #                    broken_name, broken_version))
    #    else:
    #        out.warn("no reverse dependency found.")

    if instruction.ask:
        out.write("\n")
        for package in packages:
            out.write(" %s %s/%s/%s-%s\n" % (out.color(">", "brightgreen"), out.color(package.repo, "green"), 
                out.color(package.category, "green"), out.color(package.name, "green"), 
                out.color(package.version, "green")))
        utils.xterm_title("lpms: confirmation request")
        out.write("\nTotal %s package will be removed.\n\n" % out.color(str(instruction.count), "green"))
        if not utils.confirm("Would you like to continue?"):
            out.write("quitting...\n")
            utils.xterm_title_reset()
            lpms.terminate()

    realroot = instruction.new_root if instruction.new_root else cst.root
    config = conf.LPMSConfig()
    for package in packages:
        fdb = file_collisions.CollisionProtect(package.category, package.name, \
                package.slot, version=package.version, real_root=realroot)
        fdb.handle_collisions()
        if fdb.collisions:
            out.write(out.color(" > ", "brightyellow")+"file collisions detected while removing %s/%s/%s-%s\n\n" \
                    % (package.repo, package.category, package.name, package.version))
        for (c_package, c_path) in fdb.collisions:
            c_category, c_name, c_slot, c_version = c_package
            out.write(out.color(" -- ", "red")+c_category+"/"+c_name+"-"\
                    +c_version+":"+c_slot+" -> "+c_path+"\n")
            if fdb.collisions and config.collision_protect and not \
                    lpms.getopt('--force-file-collision'):
                        out.write("\nquitting... use '--force-file-collision' to continue.\n")
                        lpms.terminate()
        index += 1;
        instruction.index = index
        if not initpreter.InitializeInterpreter(package, instruction, ['remove'], remove=True).initialize():
            out.warn("an error occured during remove operation: %s/%s/%s-%s" % (package.repo, package.category, \
                    package.name, package.version))
        else:
            file_relationsdb.delete_item_by_pkgdata(package.category, package.name, package.version, commit=True)
Esempio n. 16
0
    def search(self):
        if not list(self.keyword) and lpms.getopt("--only-installed"):
            total = 0
            for package in self.instdb.get_all_names():
                repo, category, name = package
                version_data = self.instdb.get_version(name, repo_name=repo, \
                        pkg_category=category)
                total += 1
                for slot in version_data:
                    out.notify("%s/%s/%s [slot:%s] -> %s" % (repo, category, name, \
                            slot, ", ".join(version_data[slot])))
            out.write("\npackage count: %d\n" % total)
            lpms.terminate()

        if lpms.getopt("--help") or len(self.keyword) == 0:
            self.usage()

        available = True
        results = []
        if not lpms.getopt("--in-summary") and not lpms.getopt("--in-name"):
            self.cursor.execute(
                '''SELECT repo, category, name, version, summary, slot FROM \
                    package WHERE name LIKE (?) OR summary LIKE (?)''',
                ("%" + self.keyword + "%", "%" + self.keyword + "%"))
            results.extend(self.cursor.fetchall())
        elif lpms.getopt("--in-summary"):
            self.cursor.execute(
                '''SELECT repo, category, name, version, summary, slot FROM \
                    package WHERE summary LIKE (?)''',
                ("%" + self.keyword + "%", ))
            results.extend(self.cursor.fetchall())
        else:
            self.cursor.execute(
                '''SELECT repo, category, name, version, summary, slot FROM \
                    package WHERE name LIKE (?)''',
                ("%" + self.keyword + "%", ))
            results.extend(self.cursor.fetchall())

        if not results:
            # if no result, search given keyword in installed packages database
            connection = sqlite3.connect(cst.installdb_path)
            cursor = connection.cursor()
            cursor.execute(
                '''SELECT repo, category, name, version, summary, slot FROM \
                    package WHERE name LIKE (?) OR summary LIKE (?)''',
                ("%" + self.keyword + "%", "%" + self.keyword + "%"))
            results.extend(cursor.fetchall())
            if results:
                out.notify(
                    "these packages are installed but no longer available.")
                available = False

        packages = self.classificate_packages(results)

        for index, package in enumerate(packages, 1):
            category, name = package
            if lpms.getopt("--interactive"):
                out.write("[" + str(index) + "] " +
                          out.color(category, "green") + "/" +
                          out.color(name, "green") + " - ")
            else:
                out.write(
                    out.color(category, "green") + "/" +
                    out.color(name, "green") + " - ")
            items = {}
            for item in packages[package]:
                if item[0] in items:
                    items[item[0]].append(item[3])
                else:
                    items[item[0]] = [item[3]]
            for item in items:
                out.write(
                    out.color(item, "yellow") + "(" + ", ".join(items[item]) +
                    ") ")
            out.write("\n")
            out.write("    " + packages[package][0][4] + "\n")

        # shows a dialogue, selects the packages and triggers api's build function
        if results and lpms.getopt("--interactive"):
            my_packages = []

            def ask():
                out.write("\ngive number(s):\n")
                out.write(
                    "in order to select more than one package, use space between numbers:\n"
                )
                out.write("to exit, press Q or q.\n")

            while True:
                ask()
                answers = sys.stdin.readline().strip()
                if answers == "Q" or answers == "q":
                    lpms.terminate()
                else:
                    targets = set()
                    for answer in answers.split(" "):
                        if not answer.isdigit():
                            out.warn("%s is invalid. please give a number!" %
                                     out.color(answer, "red"))
                            continue
                        else:
                            targets.add(answer)
                try:
                    my_items = packages.keys()
                    for target in targets:
                        my_packages.append("/".join(my_items[int(target) - 1]))
                    break
                except (IndexError, ValueError):
                    out.warn("invalid command.")
                    continue

            if my_packages:
                api.pkgbuild(my_packages, self.instruct)
Esempio n. 17
0
    def update_package(self,
                       repo_path,
                       category,
                       my_pkg,
                       my_version=None,
                       update=False):
        dataset = LCollect()
        # Register some variables to use after
        self.env.repo = os.path.basename(repo_path)
        self.env.category = category

        dataset.repo = self.env.repo
        dataset.category = category

        os.chdir(os.path.join(repo_path, category, my_pkg))
        for pkg in glob.glob("*" + cst.spec_suffix):
            script_path = os.path.join(repo_path, category, my_pkg, pkg)

            self.env.name, self.env.version = utils.parse_pkgname(
                pkg.split(cst.spec_suffix)[0])

            dataset.name = self.env.name
            dataset.version = self.env.version

            # FIXME: We must develop a upper-class or environment to
            # use that cases to prevent code duplication

            # Begins code duplication
            interphase = re.search(r'-r[0-9][0-9]', self.env.version)
            if not interphase:
                interphase = re.search(r'-r[0-9]', self.env.version)
            self.env.raw_version = self.env.version
            self.env.revision = ""
            # Now, set real values of these variables if package revisioned.
            if interphase is not None and interphase.group():
                self.env.raw_version = self.env.version.replace(
                    interphase.group(), "")
                self.env.revision = interphase.group()
            # End of code duplication

            self.env.__dict__[
                "fullname"] = self.env.name + "-" + self.env.version

            if not self.import_script(script_path):
                out.error("an error occured while processing the spec: %s" \
                        % out.color(script_path, "red"))
                out.error(
                    "please report the above error messages to the package maintainer."
                )
                continue

            metadata = utils.metadata_parser(self.env.metadata)
            metadata.update({
                "name": self.env.name,
                "version": self.env.version
            })
            # This method checks metadata integrity.
            # It warn the user and pass the spec if a spec is broken
            self.check_metadata_integrity(metadata)
            # These values are optional
            if not "options" in metadata:
                metadata.update({"options": None})
            if not "slot" in metadata:
                metadata.update({"slot": "0"})
            if not "src_url" in metadata:
                metadata.update({"src_url": None})

            if lpms.getopt("--verbose"):
                out.write("    %s-%s\n" % (self.env.name, self.env.version))

            try:
                dataset.summary = metadata['summary']
                dataset.homepage = metadata['homepage']
                dataset.license = metadata['license']
                dataset.src_uri = metadata['src_url']
                if metadata['options'] is None:
                    dataset.options = None
                else:
                    dataset.options = metadata['options'].split(" ")
                dataset.slot = metadata['slot']

            except KeyError as err:
                out.error("%s/%s/%s-%s: invalid metadata" % (repo_name, category, \
                        self.env.name, self.env.version))
                out.warn(
                    "repository update was failed and the repository database was removed."
                )
                out.warn(
                    "you can run 'lpms --reload-previous-repodb' command to reload previous db version."
                )
                lpms.terminate("good luck!")

            if update:
                self.repodb.delete_package(package_repo=dataset.repo, package_category=dataset.category, \
                        package_name=self.env.name, package_version=self.env.version)

            static_depends_runtime = []
            static_depends_build = []
            static_depends_postmerge = []
            static_depends_conflict = []
            if 'depends' in self.env.__dict__.keys():
                deps = utils.depends_parser(self.env.depends)
                if 'runtime' in deps:
                    static_depends_runtime.extend(deps['runtime'])
                if 'build' in deps:
                    static_depends_build.extend(deps['build'])
                if 'common' in deps:
                    static_depends_runtime.extend(deps['common'])
                    static_depends_build.extend(deps['common'])
                if 'postmerge' in deps:
                    static_depends_postmerge.extend(deps['postmerge'])
                if 'conflict' in deps:
                    static_depends_conflict.extend(deps['conflict'])

            optional_depends_runtime = []
            optional_depends_build = []
            optional_depends_postmerge = []
            optional_depends_conflict = []
            for opt in ('opt_common', 'opt_conflict', 'opt_postmerge',
                        'opt_runtime', 'opt_build'):
                try:
                    deps = utils.parse_opt_deps(getattr(self.env, opt))
                    if opt.split("_")[1] == "runtime":
                        optional_depends_runtime.append(deps)
                    elif opt.split("_")[1] == "build":
                        optional_depends_build.append(deps)
                    elif opt.split("_")[1] == "common":
                        optional_depends_build.append(deps)
                        optional_depends_runtime.append(deps)
                    elif opt.split("_")[1] == "postmerge":
                        optional_depends_postmerge.append(deps)
                    elif opt.split("_")[1] == "conflict":
                        optional_depends_conflict.append(deps)
                    del deps
                except AttributeError:
                    continue

            dataset.optional_depends_runtime = optional_depends_runtime
            dataset.optional_depends_build = optional_depends_build
            dataset.optional_depends_postmerge = optional_depends_postmerge
            dataset.optional_depends_conflict = optional_depends_conflict

            dataset.static_depends_runtime = static_depends_runtime
            dataset.static_depends_build = static_depends_build
            dataset.static_depends_postmerge = static_depends_postmerge
            dataset.static_depends_conflict = static_depends_conflict

            if metadata['arch'] is not None:
                arches = metadata['arch'].split(" ")
                for arch in arches:
                    dataset.arch = arch
                    self.repodb.insert_package(dataset)
            else:
                dataset.arch = None
                self.repodb.insert_package(dataset)

            # remove optional keys
            for key in ('depends', 'options', 'opt_runtime', 'opt_build', \
                    'opt_conflict', 'opt_common', 'opt_postmerge'):
                try:
                    del self.env.__dict__[key]
                except KeyError:
                    pass
            self.packages_num += 1
Esempio n. 18
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
Esempio n. 19
0
def remove_package(pkgnames, instruction):
    '''Triggers remove operation for given packages'''
    if instruction.like:
        # handle shortened package names
        database = dbapi.InstallDB()
        for item in instruction.like:
            query = database.db.cursor.execute(
                "SELECT name FROM package where name LIKE ?", (item, ))
            results = query.fetchall()
            if results:
                for result in results:
                    pkgnames.append(result[0])
        del database
    file_relationsdb = dbapi.FileRelationsDB()
    #try:
    packages = [
        GetPackage(pkgname, installdb=True).select() for pkgname in pkgnames
    ]
    #except PackageNotFound as package_name:
    #    out.error("%s seems not installed." % package_name)
    #    lpms.terminate()

    instruction.count = len(packages)
    index = 0
    # FIXME: I must create a new reverse dependency handler implementation

    #if instruct["show-reverse-depends"]:
    #    instruct["ask"] = True
    #    # WARNING: the mechanism only shows directly reverse dependencies
    #    # supposing that if A is a reverse dependency of B and C is depends on A.
    #    # when the user removes B, A and C will be broken. But lpms will warn the user about A.
    #    broken_packages = []
    #    reversedb = dbapi.ReverseDependsDB()
    #    out.normal("resolving primary reverse dependencies...\n")
    #    for package in packages:
    #        category, name, version = package[1:]
    #        if lpms.getopt("--use-file-relations"):
    #            broken_packages.extend(file_relations.get_packages(category, name, version))
    #        else:
    #            broken_packages.extend(reversedb.get_reverse_depends(category, name))

    #    if broken_packages:
    #        out.warn("the following packages will be broken:\n")
    #        for broken_package in broken_packages:
    #            broken_repo, broken_category, broken_name, broken_version = broken_package
    #            out.write(" %s %s/%s/%s-%s\n" % (out.color(">", "brightred"), broken_repo, broken_category, \
    #                    broken_name, broken_version))
    #    else:
    #        out.warn("no reverse dependency found.")

    if instruction.ask:
        out.write("\n")
        for package in packages:
            out.write(
                " %s %s/%s/%s-%s\n" % (out.color(
                    ">", "brightgreen"), out.color(package.repo, "green"),
                                       out.color(package.category, "green"),
                                       out.color(package.name, "green"),
                                       out.color(package.version, "green")))
        utils.xterm_title("lpms: confirmation request")
        out.write("\nTotal %s package will be removed.\n\n" %
                  out.color(str(instruction.count), "green"))
        if not utils.confirm("Would you like to continue?"):
            out.write("quitting...\n")
            utils.xterm_title_reset()
            lpms.terminate()

    realroot = instruction.new_root if instruction.new_root else cst.root
    config = conf.LPMSConfig()
    for package in packages:
        fdb = file_collisions.CollisionProtect(package.category, package.name, \
                package.slot, version=package.version, real_root=realroot)
        fdb.handle_collisions()
        if fdb.collisions:
            out.write(out.color(" > ", "brightyellow")+"file collisions detected while removing %s/%s/%s-%s\n\n" \
                    % (package.repo, package.category, package.name, package.version))
        for (c_package, c_path) in fdb.collisions:
            c_category, c_name, c_slot, c_version = c_package
            out.write(out.color(" -- ", "red")+c_category+"/"+c_name+"-"\
                    +c_version+":"+c_slot+" -> "+c_path+"\n")
            if fdb.collisions and config.collision_protect and not \
                    lpms.getopt('--force-file-collision'):
                out.write(
                    "\nquitting... use '--force-file-collision' to continue.\n"
                )
                lpms.terminate()
        index += 1
        instruction.index = index
        if not initpreter.InitializeInterpreter(
                package, instruction, ['remove'], remove=True).initialize():
            out.warn("an error occured during remove operation: %s/%s/%s-%s" % (package.repo, package.category, \
                    package.name, package.version))
        else:
            file_relationsdb.delete_item_by_pkgdata(package.category,
                                                    package.name,
                                                    package.version,
                                                    commit=True)