Source code for meta_package_manager.managers.macports

# Copyright Kevin Deldycke <kevin@deldycke.com> and contributors.
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

from __future__ import annotations

import re

from extra_platforms import MACOS

from ..base import PackageManager
from ..capabilities import search_capabilities, version_not_implemented

TYPE_CHECKING = False
if TYPE_CHECKING:
    from collections.abc import Iterator

    from ..base import Package


[docs] class MacPorts(PackageManager): """MacPorts package manager for macOS. .. note:: MacPorts installs into ``/opt/local`` by default and requires root privileges for mutating operations. The ``port`` binary is located at ``/opt/local/bin/port``. """ homepage_url = "https://www.macports.org" platforms = MACOS requirement = ">=2.0.0" cli_names = ("port",) cli_search_path = ("/opt/local/bin",) _INSTALLED_REGEXP = re.compile( r"^\s+(?P<package_id>\S+)\s+@(?P<version>[^+\s]+)\S*\s+\(active\)", re.MULTILINE, ) _OUTDATED_REGEXP = re.compile( r"^(?P<package_id>\S+)\s+(?P<installed_version>\S+)\s+<\s+(?P<latest_version>\S+)", re.MULTILINE, ) _SEARCH_REGEXP = re.compile( r"^(?P<package_id>[^\t]+)\t(?P<version>[^\t]+)\t[^\t]+\t(?P<description>.+)$", re.MULTILINE, ) version_cli_options = ("version",) version_regexes = (r"Version:\s+(?P<version>\S+)",) """ .. code-block:: shell-session $ port version Version: 2.12.4 """ @property def installed(self) -> Iterator[Package]: """Fetch installed packages. Only active ports are returned. Inactive ports (old versions kept by MacPorts) are skipped. .. code-block:: shell-session $ port -q installed curl @8.7.1_0 (active) python312 @3.12.3_0+lzma+optimizations (active) vim @9.1.0_0 (active) """ output = self.run_cli("-q", "installed") for package_id, version in self._INSTALLED_REGEXP.findall(output): yield self.package(id=package_id, installed_version=version) @property def outdated(self) -> Iterator[Package]: """Fetch outdated packages. .. code-block:: shell-session $ port -q outdated curl 8.7.1_0 < 8.8.0_0 python312 3.12.3_0 < 3.12.4_0 """ output = self.run_cli("-q", "outdated") for ( package_id, installed_version, latest_version, ) in self._OUTDATED_REGEXP.findall(output): yield self.package( id=package_id, installed_version=installed_version, latest_version=latest_version, )
[docs] @search_capabilities(extended_support=True, exact_support=True) def search(self, query: str, extended: bool, exact: bool) -> Iterator[Package]: """Fetch matching packages. .. code-block:: shell-session $ port search --name --line vim MacVim 9.1.1092 aqua MacVim - VIM for macOS vim 9.1.1092 editors Vi IMproved """ args: list[str] = ["search", "--name"] if extended: args.append("--description") if exact: args.append("--exact") args.extend(("--line", query)) output = self.run_cli(*args) for package_id, version, description in self._SEARCH_REGEXP.findall(output): yield self.package( id=package_id, description=description, latest_version=version, )
[docs] @version_not_implemented def install(self, package_id: str, version: str | None = None) -> str: """Install one package. .. code-block:: shell-session $ port install vim """ return self.run_cli("install", package_id)
[docs] def upgrade_all_cli(self) -> tuple[str, ...]: """Generates the CLI to upgrade all packages. .. code-block:: shell-session $ port upgrade outdated """ return self.build_cli("upgrade", "outdated")
[docs] @version_not_implemented def upgrade_one_cli( self, package_id: str, version: str | None = None, ) -> tuple[str, ...]: """Generates the CLI to upgrade one package. .. code-block:: shell-session $ port upgrade vim """ return self.build_cli("upgrade", package_id)
[docs] def remove(self, package_id: str) -> str: """Remove one package. .. code-block:: shell-session $ port uninstall vim """ return self.run_cli("uninstall", package_id)
[docs] def sync(self) -> None: """Sync the local ports tree with remote repositories. .. code-block:: shell-session $ port sync """ self.run_cli("sync")
[docs] def cleanup(self) -> None: """Remove work directories, distfiles, and logs for installed ports. .. code-block:: shell-session $ port clean --all installed """ self.run_cli("clean", "--all", "installed")