示例#1
0
    def _add_profile(self, table, show_env, show_dependencies, element_count, profile: Profile, sync: bool, dependencies_iplist: list):
        # Profile header
        table.new_row().new_double_separator(element_count)
        pfname = profile.name
        if profile.is_current:
            pfname += " " + self.tm.PROFILE_CURRENT("[current]")
        header_text = ("{label_theme}Profile:{reset_theme} {profile_name} ({sync_state})").format(
            label_theme=self.tm.LABEL, reset_theme=self.tm.RESET, profile_name=pfname, sync_state="sync" if sync else "not sync"
        )
        table.new_row().new_separator().new_cell(header_text, halign=HAlign.CENTER).new_hspan(element_count - 3).new_separator()

        # Environment
        if show_env:
            env = []
            Environment.build(self.ws_env, profile.build_environment()).print_env(kv_consumer=lambda k, v: env.append("{0}={1}".format(k, v)))
            if len(env) > 0:
                table.new_row().new_separator(element_count)
                table.new_row().new_separator().new_cell(self.tm.LABEL("Environment"), halign=HAlign.CENTER).new_separator().new_cell("\n".join(env)).new_hspan(
                    2
                ).new_separator()

        # Packages header
        if len(profile.packages) > 0:
            table.new_row().new_separator(element_count)
            table.new_row().new_separator().new_cell(self.tm.LABEL("Packages"), halign=HAlign.CENTER).new_separator().new_cell(
                self.tm.LABEL("Identifier"), halign=HAlign.CENTER
            ).new_separator().new_cell(self.tm.LABEL("Description"), halign=HAlign.CENTER).new_separator()

            # Included packages
            included_pkgmap = OrderedDict()
            for pi in profile.packages:
                included_pkgmap[pi] = None
                for ip in dependencies_iplist:
                    if ip.identifier == pi:
                        included_pkgmap[pi] = ip
                        break

            table.new_row().new_separator(element_count)
            self._add_packages_rows(table, "Included", included_pkgmap)

            # Dependencies
            if show_dependencies and len(dependencies_iplist) > 0:
                depends_pkgmap = OrderedDict()
                for ip in dependencies_iplist:
                    if ip not in included_pkgmap.values():
                        depends_pkgmap[ip.identifier] = ip
                if len(depends_pkgmap) > 0:
                    table.new_row().new_separator(element_count)
                    self._add_packages_rows(table, "Dependencies" if len(depends_pkgmap) > 1 else "Dependency", depends_pkgmap)
    def test_conditional_install(self):
        self.pm.install_packages(PackageIdentifier.parse_list(["condition_1.0"]))
        self.check_content(self.pm.list_installed_packages(), ["condition_1.0", "condition-B_1.0", "condition-D_1.0", "condition-F_1.0", "condition-H_1.0"])

        self.pm.install_packages(PackageIdentifier.parse_list(["condition_1.0"]), env=Environment("test", {"FOO": "BAR"}))
        self.check_content(
            self.pm.list_installed_packages(),
            ["condition_1.0", "condition-A_1.0", "condition-B_1.0", "condition-C_1.0", "condition-D_1.0", "condition-F_1.0", "condition-H_1.0"],
        )

        self.pm.update_user_environment(set_map={"FOO2": "BAR2", "HELLO": "WoRld"})

        env = Environment.build(self.pm.build_builtin_environment(), self.pm.build_user_environment(), Environment("test", {"FOO": "BAR"}))
        self.pm.install_packages(PackageIdentifier.parse_list(["condition_1.0"]), env=env)
        self.check_content(
            self.pm.list_installed_packages(),
            [
                "condition_1.0",
                "condition-A_1.0",
                "condition-B_1.0",
                "condition-C_1.0",
                "condition-D_1.0",
                "condition-E_1.0",
                "condition-F_1.0",
                "condition-G_1.0",
                "condition-H_1.0",
            ],
        )

        self.pm.uninstall_packages(PackageIdentifier.parse_list(["condition_1.0"]))
        self.check_content(self.pm.list_installed_packages(), [])
示例#3
0
文件: packages.py 项目: sam974/leaf
 def __execute_steps(self,
                     pi: PackageIdentifier,
                     ipmap: dict,
                     se_func: callable,
                     env: Environment = None):
     # Find the package
     ip = find_manifest(pi, ipmap)
     # The environment
     if env is None:
         env = Environment.build(self.build_builtin_environment(),
                                 self.build_user_environment())
     # build the dependencies
     deps = DependencyUtils.installed([pi],
                                      ipmap,
                                      env=env,
                                      ignore_unknown=True)
     # Update env
     env.append(self.build_packages_environment(deps))
     # Fix PREREQ_ROOT
     env.set_variable("LEAF_PREREQ_ROOT", self.install_folder)
     # The Variable resolver
     vr = VariableResolver(ip, ipmap.values())
     # Execute steps
     se = StepExecutor(self.logger, ip, vr, env=env)
     se_func(se)
示例#4
0
 def test_environment(self):
     pm = PackageManager()
     env = Environment.build(pm.build_builtin_environment(),
                             pm.build_user_environment(),
                             Environment("test", {"FOO": "BAR"}))
     rend = EnvironmentRenderer(env)
     with self.assertStdout(template_out="env.out"):
         self.loggerManager.print_renderer(rend)
    def test_depends_with_custom_env(self):
        env = Environment.build(self.pm.build_builtin_environment(), self.pm.build_user_environment(), Environment("Custom env", {}))
        deps = DependencyUtils.install(
            PackageIdentifier.parse_list(["condition_1.0"]), self.pm.list_available_packages(), self.pm.list_installed_packages(), env=env
        )
        self.__assert_deps(deps, ["condition-B_1.0", "condition-D_1.0", "condition-F_1.0", "condition-H_1.0", "condition_1.0"], AvailablePackage)

        self.pm.update_user_environment(set_map={"FOO": "HELLO"})
        env = Environment.build(self.pm.build_builtin_environment(), self.pm.build_user_environment(), Environment("Custom env", {}))
        deps = DependencyUtils.install(
            PackageIdentifier.parse_list(["condition_1.0"]), self.pm.list_available_packages(), self.pm.list_installed_packages(), env=env
        )
        self.__assert_deps(deps, ["condition-A_1.0", "condition-D_1.0", "condition-F_1.0", "condition-H_1.0", "condition_1.0"], AvailablePackage)

        self.pm.update_user_environment(set_map={"FOO": "HELLO"})
        env = Environment.build(self.pm.build_builtin_environment(), self.pm.build_user_environment(), Environment("Custom env", {"FOO": "BAR"}))
        deps = DependencyUtils.install(
            PackageIdentifier.parse_list(["condition_1.0"]), self.pm.list_available_packages(), self.pm.list_installed_packages(), env=env
        )
        self.__assert_deps(deps, ["condition-A_1.0", "condition-C_1.0", "condition-F_1.0", "condition_1.0"], AvailablePackage)
示例#6
0
    def install_prereq(self,
                       pilist: list,
                       tmp_install_folder: Path,
                       apmap: dict = None,
                       env: Environment = None,
                       raise_on_error: bool = True):
        """
        Install given prereg available package in alternative root folder
        @return: error count
        """
        if apmap is None:
            apmap = self.list_available_packages()

        # Get packages to install
        aplist = [find_manifest(pi, apmap) for pi in pilist]

        errors = 0
        if len(aplist) > 0:
            self.logger.print_verbose(
                "Installing {count} pre-required package(s) in {folder}".
                format(count=len(aplist), folder=tmp_install_folder))
            if env is None:
                env = Environment.build(self.build_builtin_environment(),
                                        self.build_user_environment())
            env.append(
                Environment("Prereq",
                            {"LEAF_PREREQ_ROOT": tmp_install_folder}))
            for prereqap in aplist:
                try:
                    prereqla = self.__download_ap(prereqap)
                    prereqip = self.__extract_artifact(
                        prereqla,
                        env,
                        tmp_install_folder,
                        keep_folder_on_error=True)
                    self.logger.print_verbose(
                        "Prereq package {ip.identifier} is OK".format(
                            ip=prereqip))
                except Exception as e:
                    if raise_on_error:
                        raise e
                    self.logger.print_verbose(
                        "Prereq package {ap.identifier} has error: {error}".
                        format(ap=prereqap, error=e))
                    errors += 1
        return errors
示例#7
0
    def execute(self, args, uargs):
        pm = PackageManager()

        env = Environment.build(pm.build_builtin_environment(),
                                pm.build_user_environment())

        install_list, uninstall_list = DependencyUtils.upgrade(
            None if len(args.packages) == 0 else args.packages,
            pm.list_available_packages(),
            pm.list_installed_packages(),
            env=env)

        pm.logger.print_verbose(
            "{count} package(s) to be upgraded: {text}".format(
                count=len(install_list),
                text=" ".join([str(ap.identifier) for ap in install_list])))
        if args.clean:
            pm.logger.print_verbose(
                "{count} package(s) to be removed: {text}".format(
                    count=len(uninstall_list),
                    text=" ".join(
                        [str(ip.identifier) for ip in uninstall_list])))

        if len(install_list) == 0:
            pm.logger.print_default("No package to upgrade")
        else:
            pm.install_packages(map(IDENTIFIER_GETTER, install_list), env=env)
            if len(uninstall_list) > 0:
                if args.clean:
                    pm.uninstall_packages(
                        map(IDENTIFIER_GETTER, uninstall_list))
                else:
                    pm.logger.print_default(
                        "These packages can be removed:",
                        " ".join([str(ip.identifier)
                                  for ip in uninstall_list]))
示例#8
0
    def install_packages(self,
                         pilist: list,
                         env: Environment = None,
                         keep_folder_on_error: bool = False):
        """
        Compute dependency tree, check compatibility, download from remotes and extract needed packages
        @return: InstalledPackage list
        """
        with self.application_lock.acquire():
            prereq_install_folder = None
            ipmap = self.list_installed_packages()
            apmap = self.list_available_packages()
            out = []

            # Build env to resolve dynamic dependencies
            if env is None:
                env = Environment.build(self.build_builtin_environment(),
                                        self.build_user_environment())

            try:
                ap_to_install = DependencyUtils.install(pilist,
                                                        apmap,
                                                        ipmap,
                                                        env=env)

                # Check leaf min version
                min_version = check_leaf_min_version(ap_to_install)
                if min_version:
                    raise LeafOutOfDateException(
                        "You need to upgrade leaf to v{version} to install {text}"
                        .format(version=min_version,
                                text=", ".join([
                                    str(ap.identifier) for ap in ap_to_install
                                ])))

                # Check nothing to do
                if len(ap_to_install) == 0:
                    self.logger.print_default("All packages are installed")
                else:
                    # Check available size
                    download_totalsize = 0
                    for ap in ap_to_install:
                        if ap.size is not None:
                            download_totalsize += ap.size
                    fs_check_free_space(self.download_cache_folder,
                                        download_totalsize)

                    # Confirm
                    text = ", ".join(
                        [str(ap.identifier) for ap in ap_to_install])
                    self.logger.print_quiet(
                        "Packages to install: {packages}".format(
                            packages=text))
                    if download_totalsize > 0:
                        self.logger.print_default(
                            "Total size:", sizeof_fmt(download_totalsize))
                    self.print_with_confirm(raise_on_decline=True)

                    # Install prereq
                    prereq_to_install = DependencyUtils.prereq(pilist,
                                                               apmap,
                                                               ipmap,
                                                               env=env)

                    if len(prereq_to_install) > 0:
                        self.logger.print_default("Check required packages")
                        prereq_install_folder = mkdir_tmp_leaf_dir()
                        self.install_prereq(
                            [p.identifier for p in prereq_to_install],
                            prereq_install_folder,
                            apmap=apmap,
                            env=env)

                    # Download ap list
                    self.logger.print_default(
                        "Downloading {size} package(s)".format(
                            size=len(ap_to_install)))
                    la_to_install = []
                    for ap in ap_to_install:
                        la_to_install.append(self.__download_ap(ap))

                    # Check the extracted size
                    extracted_totalsize = 0
                    for la in la_to_install:
                        if la.final_size is not None:
                            extracted_totalsize += la.final_size
                        else:
                            extracted_totalsize += la.get_total_size()
                    fs_check_free_space(self.install_folder,
                                        extracted_totalsize)

                    # Extract la list
                    for la in la_to_install:
                        self.logger.print_default(
                            "[{current}/{total}] Installing {la.identifier}".
                            format(current=(len(out) + 1),
                                   total=len(la_to_install),
                                   la=la))
                        ip = self.__extract_artifact(
                            la,
                            env,
                            self.install_folder,
                            ipmap=ipmap,
                            keep_folder_on_error=keep_folder_on_error)
                        out.append(ip)

            finally:
                if not keep_folder_on_error and prereq_install_folder is not None:
                    self.logger.print_verbose(
                        "Remove prereq root folder {folder}".format(
                            folder=prereq_install_folder))
                    rmtree_force(prereq_install_folder)

            return out
示例#9
0
文件: workspace.py 项目: sam974/leaf
 def build_pf_environment(self, profile: Profile):
     return Environment.build(self.build_builtin_environment(),
                              self.build_user_environment(),
                              self.build_ws_environment(),
                              profile.build_environment())
示例#10
0
    def execute(self, args, uargs):
        wm = self.get_workspacemanager(check_initialized=False)

        ipmap = wm.list_installed_packages()
        searching_iplist = None
        env = None

        if args.package is not None:
            # User forces the package
            env = Environment.build(wm.build_builtin_environment(),
                                    wm.build_user_environment())
            searching_iplist = DependencyUtils.installed([args.package],
                                                         ipmap,
                                                         env=env)
            env.append(wm.build_packages_environment(searching_iplist))
        elif wm.is_initialized:
            # We are in a workspace, use the current profile
            pfname = wm.current_profile_name
            profile = wm.get_profile(pfname)
            wm.is_profile_sync(profile, raise_if_not_sync=True)
            searching_iplist = wm.get_profile_dependencies(profile)
            env = wm.build_full_environment(profile)
        else:
            # Use installed packages
            searching_iplist = sorted(ipmap.values(), key=IDENTIFIER_GETTER)

        # Execute
        if args.binary is None:
            # Print mode
            scope = "installed packages"
            if args.package is not None:
                scope = args.package
            elif wm.is_initialized:
                scope = "workspace"
            rend = EntrypointListRenderer(scope)
            rend.extend(searching_iplist)
            wm.print_renderer(rend,
                              verbosity=Verbosity.QUIET
                              if args.oneline else Verbosity.DEFAULT)
        elif args.oneline:
            # User gave BIN and --oneline
            raise LeafException(
                "You must specify a binary or '--oneline', not both",
                hints=[
                    "Run 'leaf run --oneline' to list all binaries",
                    "Run 'leaf run {bin} -- --oneline {uargs}' pass --oneline to the binary"
                    .format(bin=args.binary, uargs=" ".join(uargs)),
                ],
            )
        else:
            # Search entry point
            candidate_ip = None
            for ip in searching_iplist:
                if args.binary in ip.binaries:
                    if candidate_ip is None:
                        candidate_ip = ip
                    elif candidate_ip.name != ip.name:
                        raise LeafException(
                            "Binary {bin} is declared by multiple packages".
                            format(bin=args.binary))
                    elif ip.identifier > candidate_ip.identifier:
                        candidate_ip = ip
            if candidate_ip is None:
                raise LeafException(
                    "Cannot find binary {bin}".format(bin=args.binary))

            if env is None:
                env = Environment.build(wm.build_builtin_environment(),
                                        wm.build_user_environment())
                env.append(
                    wm.build_packages_environment(
                        DependencyUtils.installed([candidate_ip.identifier],
                                                  ipmap=ipmap,
                                                  env=env)))

            ep = candidate_ip.binaries[args.binary]
            vr = VariableResolver(candidate_ip, ipmap.values())
            return execute_command(vr.resolve(ep.command),
                                   *uargs,
                                   print_stdout=True,
                                   env=env)
示例#11
0
    def install_packages(self,
                         items: list,
                         env: Environment = None,
                         keep_folder_on_error: bool = False):
        """
        Compute dependency tree, check compatibility, download from remotes and extract needed packages
        @return: InstalledPackage list
        """
        with self.application_lock.acquire():
            ipmap = self.list_installed_packages()
            apmap = self.list_available_packages()
            pilist = []
            for item in items:
                if isinstance(item, PackageIdentifier):
                    # Package identifier is given
                    pilist.append(item)
                elif PackageIdentifier.is_valid_identifier(item):
                    # Package identifier string given
                    pilist.append(PackageIdentifier.parse(item))
                else:
                    # If leaf artifacts are given, add/replace identifiers of available packages
                    la = LeafArtifact(Path(item))
                    pilist.append(la.identifier)
                    apmap[la.identifier] = la
            out = []

            # Build env to resolve dynamic dependencies
            if env is None:
                env = Environment.build(self.build_builtin_environment(),
                                        self.build_user_environment())

            ap_to_install = DependencyUtils.install(pilist,
                                                    apmap,
                                                    ipmap,
                                                    env=env)

            # Check leaf min version
            min_version = check_leaf_min_version(ap_to_install)
            if min_version:
                raise LeafOutOfDateException(
                    "You need to upgrade leaf to v{version} to install {text}".
                    format(version=min_version,
                           text=", ".join(
                               [str(ap.identifier) for ap in ap_to_install])))

            # Check nothing to do
            if len(ap_to_install) == 0:
                self.logger.print_default("All packages are installed")
            else:
                # Check available size
                download_totalsize = 0
                download_count = 0
                for ap in [
                        ap for ap in ap_to_install
                        if isinstance(ap, AvailablePackage)
                ]:
                    download_count += 1
                    if ap.size is not None:
                        download_totalsize += ap.size
                fs_check_free_space(self.download_cache_folder,
                                    download_totalsize)

                # Confirm
                text = ", ".join([str(ap.identifier) for ap in ap_to_install])
                self.logger.print_quiet(
                    "Packages to install: {packages}".format(packages=text))
                if download_totalsize > 0:
                    self.logger.print_default("Total size:",
                                              sizeof_fmt(download_totalsize))
                self.print_with_confirm(raise_on_decline=True)

                # Install prereq
                prereq_to_install = DependencyUtils.prereq(
                    [ap.identifier for ap in ap_to_install],
                    apmap,
                    ipmap,
                    env=env)

                if len(prereq_to_install) > 0:
                    try:
                        self.__install_prereq(
                            prereq_to_install,
                            ipmap,
                            env=env,
                            keep_folder_on_error=keep_folder_on_error)
                    except BaseException as e:
                        raise PrereqException(e)

                # Download ap list
                self.logger.print_default(
                    "Downloading {size} package(s)".format(
                        size=download_count))
                la_to_install = []
                for mf in ap_to_install:
                    if isinstance(mf, AvailablePackage):
                        la_to_install.append(self.__download_ap(mf))
                    elif isinstance(mf, LeafArtifact):
                        la_to_install.append(mf)

                # Check the extracted size
                extracted_totalsize = 0
                for la in la_to_install:
                    if la.final_size is not None:
                        extracted_totalsize += la.final_size
                    else:
                        extracted_totalsize += la.get_total_size()
                fs_check_free_space(self.install_folder, extracted_totalsize)

                # Extract la list
                for la in la_to_install:
                    self.logger.print_default(
                        "[{current}/{total}] Installing {la.identifier}".
                        format(current=(len(out) + 1),
                               total=len(la_to_install),
                               la=la))
                    ip = self.__extract_artifact(
                        la,
                        env,
                        ipmap,
                        keep_folder_on_error=keep_folder_on_error)
                    out.append(ip)

            return out
示例#12
0
    def execute(self, args, uargs):
        pm = PackageManager()
        env = None
        # If the user specified env values, build a complete env
        if args.custom_envlist is not None:
            env = Environment.build(
                pm.build_builtin_environment(), pm.build_user_environment(),
                Environment("Custom env",
                            env_list_to_map(args.custom_envlist)))

        items = None
        if args.dependency_type == "available":
            items = DependencyUtils.install(PackageIdentifier.parse_list(
                args.packages),
                                            pm.list_available_packages(), {},
                                            env=env)
        elif args.dependency_type == "install":
            items = DependencyUtils.install(PackageIdentifier.parse_list(
                args.packages),
                                            pm.list_available_packages(),
                                            pm.list_installed_packages(),
                                            env=env)
        elif args.dependency_type == "installed":
            items = DependencyUtils.installed(PackageIdentifier.parse_list(
                args.packages),
                                              pm.list_installed_packages(),
                                              env=env,
                                              ignore_unknown=True)
        elif args.dependency_type == "uninstall":
            items = DependencyUtils.uninstall(PackageIdentifier.parse_list(
                args.packages),
                                              pm.list_installed_packages(),
                                              env=env)
        elif args.dependency_type == "prereq":
            items = DependencyUtils.prereq(PackageIdentifier.parse_list(
                args.packages),
                                           pm.list_available_packages(),
                                           pm.list_installed_packages(),
                                           env=env)
        elif args.dependency_type == "upgrade":
            items, _ = DependencyUtils.upgrade(
                None if len(args.packages) == 0 else args.packages,
                pm.list_available_packages(),
                pm.list_installed_packages(),
                env=env)
        elif args.dependency_type == "rdepends":
            mfmap = OrderedDict()
            mfmap.update(
                DependencyUtils.rdepends(PackageIdentifier.parse_list(
                    args.packages),
                                         pm.list_available_packages(),
                                         env=env))
            mfmap.update(
                DependencyUtils.rdepends(PackageIdentifier.parse_list(
                    args.packages),
                                         pm.list_installed_packages(),
                                         env=env))
            items = mfmap.values()
        else:
            raise ValueError()

        rend = ManifestListRenderer()
        rend.extend(items)
        pm.print_renderer(rend)
示例#13
0
    def execute(self, args, uargs):
        wm = self.get_workspacemanager(check_initialized=False)

        ipmap = wm.list_installed_packages()
        searching_iplist = None

        if args.package is not None:
            # User forces the package
            searching_iplist = DependencyUtils.installed(
                [args.package],
                ipmap,
                env=Environment.build(wm.build_builtin_environment(),
                                      wm.build_user_environment()))
        else:
            # Use installed packages
            searching_iplist = keep_latest_mf(ipmap.values())

        topics = self.get_topics(searching_iplist)
        if args.topic is not None:
            topic = self.find_topic(topics, args.topic)
            fmt = args.format
            if fmt is None:
                # No format given
                if LeafSettings.HELP_DEFAULT_FORMAT.value in topic.resources.keys(
                ):
                    # Default format is available
                    fmt = LeafSettings.HELP_DEFAULT_FORMAT.value
                elif len(topic.resources.keys()) == 1:
                    # Only one format available
                    fmt = next(iter(topic.resources.keys()))

            if fmt is None or fmt not in topic.resources.keys():
                # Ensure that this topic is available for needed format
                raise LeafException(
                    "You need to specify a format for topic '{topic}'".format(
                        topic=args.topic),
                    hints=[
                        "For example 'leaf help --format {fmt} {topic}'".
                        format(fmt=fmt, topic=args.topic)
                        for fmt in topic.resources.keys()
                    ],
                )

            # Resolve resource path since it can contain @{} variables
            resource = VariableResolver(topic.installed_package,
                                        ipmap.values()).resolve(
                                            topic.resources[fmt])
            if fmt == "man":
                # If format is 'man', use manpage reader
                command = [
                    "man", "-P", "cat"
                ] if LeafSettings.NON_INTERACTIVE.as_boolean() else ["man"]
                command.append(resource)
                subprocess.check_call(command)
            else:
                # Use default resource handler
                subprocess.check_call(
                    [LeafSettings.HELP_DEFAULT_OPEN.value, resource])
        else:
            # Print mode
            scope = "installed packages"
            if args.package is not None:
                scope = args.package
            rend = HelpTopicListRenderer(scope, filter_format=args.format)
            rend.extend(searching_iplist)
            wm.print_renderer(rend)
示例#14
0
    def execute(self, args, uargs):
        pm = PackageManager()
        wm = self.get_workspacemanager()
        profilename = wm.current_profile_name
        profile = wm.get_profile(profilename)

        env = Environment.build(pm.build_builtin_environment(),
                                pm.build_user_environment())

        install_list, upgraded_list = DependencyUtils.upgrade(
            None if len(args.packages) == 0 else args.packages,
            pm.list_available_packages(),
            pm.list_installed_packages(),
            env=env)

        pm.logger.print_verbose(
            "{count} package(s) to be upgraded: {text}".format(
                count=len(install_list),
                text=" ".join([str(ap.identifier) for ap in install_list])))
        if args.clean:
            pm.logger.print_verbose(
                "{count} package(s) to be removed: {text}".format(
                    count=len(upgraded_list),
                    text=" ".join([str(ip.identifier)
                                   for ip in upgraded_list])))

        if len(install_list) == 0:
            pm.logger.print_default("No package to upgrade")
        else:
            pm.install_packages(map(IDENTIFIER_GETTER, install_list), env=env)
            if len(upgraded_list) > 0:
                if args.clean:
                    pm.uninstall_packages(map(IDENTIFIER_GETTER,
                                              upgraded_list))
                else:
                    pm.logger.print_default(
                        "Packages upgraded:",
                        " ".join([str(ip.identifier) for ip in upgraded_list]))
                    pm.logger.print_default(
                        'Hint: Use "leaf profile config -p {PACKAGENAME}" to add these packages to your workspace profile'
                    )

        update_pilist = install_list
        profile_pkg_map = profile.pkg_map

        installed_packages = group_package_identifiers_by_name(
            wm.list_installed_packages())
        pkg_list = args.packages if args.packages else profile_pkg_map.keys()

        for pkg in pkg_list:
            pi = None
            if pkg in installed_packages.keys():
                # Get latest version
                pi = installed_packages[pkg][-1]

            if pi is not None and pi not in update_pilist:
                # Get PI in profile
                previous_pi = PackageIdentifier(pi.name, profile_pkg_map[
                    pi.name]) if pi.name in profile_pkg_map else None
                if previous_pi is None:
                    # Package is not in profile yet, add it
                    update_pilist.append(pi)
                elif previous_pi != pi:
                    # Package is already in profile with a different version, update it
                    update_pilist.append(pi)
                else:
                    # Package is already in profile with same version, do nothing
                    pass

        if len(update_pilist) == 0:
            pm.logger.print_default(
                "Packages are already in profile with same version")
        else:
            pm.logger.print_default(
                "Packages to be updated in profile:",
                " ".join([str(pi) for pi in update_pilist]))
            profile.add_packages(update_pilist)
            wm.update_profile(profile)