Repository: kdeldycke/meta-package-manager (language: python)

Issue:
pacman (Arch based distros) support
Is pacman a possible package manager to add? This would mean this would be useful on Arch based distros of linux as well. 
Another piece might be an AUR helper like [paru](https://github.com/morganamilo/paru) to help build packages.


Discussion / hints:

Fix patch:
diff --git a/.github/labels-extra.json b/.github/labels-extra.json
index 53ee9ff0f..b55f11c62 100644
--- a/.github/labels-extra.json
+++ b/.github/labels-extra.json
@@ -59,6 +59,11 @@
     "color": "#bfdadc",
     "description": "npm, yarn"
   },
+  {
+    "name": "📦 manager: pacman",
+    "color": "#bfdadc",
+    "description": "pacman"
+  },
   {
     "name": "📦 manager: pip",
     "color": "#bfdadc",
diff --git a/changelog.md b/changelog.md
index 778da72fd..2da12858d 100644
--- a/changelog.md
+++ b/changelog.md
@@ -7,6 +7,7 @@ This version is not released yet and is under active development.
 ```
 
 - \[mpm\] Add `--xbar-plugin-path` option.
+- \[pacman\] Add support for `pacman`. Closes {issue}`416`
 
 ## {gh}`4.12.1 (2022-04-05) <compare/v4.12.0...v4.12.1>`
 
diff --git a/meta_package_manager/managers/pacman.py b/meta_package_manager/managers/pacman.py
new file mode 100644
index 000000000..d44453908
--- /dev/null
+++ b/meta_package_manager/managers/pacman.py
@@ -0,0 +1,177 @@
+# Copyright Kevin Deldycke <kevin@deldycke.com> and contributors.
+# All Rights Reserved.
+#
+# 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.
+
+import re
+
+from click_extra.platform import LINUX
+
+from ..base import PackageManager
+from ..version import TokenizedString, parse_version
+
+class Pacman(PackageManager):
+
+    platforms = frozenset({LINUX})
+
+    requirement = "5.0.0"
+
+    pre_args = ("--noconfirm",)
+
+    version_regex = r".*Pacman\s+v(?P<version>\S+)"
+    """
+    .. code-block:: shell-session
+        ► pacman --version
+
+         .--.                  Pacman v6.0.1 - libalpm v13.0.1
+        / _.-' .-.  .-.  .-.   Copyright (C) 2006-2021 Pacman Development Team
+        \  '-. '-'  '-'  '-'   Copyright (C) 2002-2006 Judd Vinet
+         '--'
+                            This program may be freely redistributed under
+                            the terms of the GNU General Public License.
+
+    """
+
+    @property
+    def installed(self):
+        """Fetch installed packages from ``pacman --query`` output.
+
+        Raw CLI output sample:
+
+        .. code-block:: shell-session
+
+            ► pacman --query
+            a52dec 0.7.4-11
+            aalib 1.4rc5-14
+            abseil-cpp 20211102.0-2
+            accountsservice 22.08.8-2
+            acl 2.3.1-2
+            acme.sh 3.0.2-1
+            acpi 1.7-3
+            acpid 2.0.33-1
+        """
+        installed = {}
+
+        output = self.run_cli("--query")
+
+        regexp = re.compile(r"(\S+) (\S+)")
+        for package in output.splitlines():
+            match = regexp.match(package)
+            if match:
+                package_id, installed_version = match.groups()
+                installed[package_id] = {
+                    "id": package_id,
+                    "name": package_id,
+                    "installed_version": parse_version(installed_version)
+                }
+
+        return installed
+
+    @property
+    def outdated(self):
+        """Fetch outdated packages from ``pacman -Qu`` output.
+
+        Raw CLI output samples:
+
+        .. code-block:: shell-session
+
+            ► pacman -Qu
+            linux 4.19.1.arch1-1 -> 4.19.2.arch1-1 
+            linux-headers 4.19.1.arch1-1 -> 4.19.2.arch1-1
+        """
+        outdated = {}
+
+        output = self.run_cli("-Qu")
+
+        regexp = re.compile(r"(\S+) (\S+) -> (\S+)")
+        for package in output.splitlines():
+            match = regexp.match(package)
+            if match:
+                package_id, installed_version, latest_version = match.groups()
+                outdated[package_id] = {
+                    "id": package_id,
+                    "name": package_id,
+                    "latest_version": parse_version(latest_version),
+                    "installed_version": parse_version(installed_version),
+                }
+        return outdated
+
+    def install(self, package_id):
+        """Install one package.
+
+        .. code-block:: shell-session
+
+            ► pacman -S firefox
+        """
+        super().install(package_id)
+        return self.run_cli("-S", package_id)
+
+    def upgrade_cli(self, package_id=None):
+        """Upgrade one package.
+
+        .. code-block:: shell-session
+
+            ► pacman -S firefox
+        """
+        return self.build_cli("-S", package_id)
+    
+    def sync(self):
+        super().sync()
+        self.run_cli("-Sy")
+
+    def cleanup(self):
+        super().cleanup()
+        self.run_cli("-Scc")
+
+    def upgrade_all_cli(self):
+        return self.build_cli("-Syu")
+
+    def search(self, query, extended, exact):
+        """
+        code-block:: shell-session
+
+            ► pacman -Ss fire
+            extra/dump_syms 0.0.7-1
+                Symbol dumper for Firefox
+            extra/firefox 99.0-1
+                Standalone web browser from mozilla.org
+            extra/firefox-i18n-ach 99.0-1
+                Acholi language pack for Firefox
+            extra/firefox-i18n-af 99.0-1
+                Afrikaans language pack for Firefox
+            extra/firefox-i18n-an 99.0-1
+                Aragonese language pack for Firefox
+            extra/firefox-i18n-ar 99.0-1
+                Arabic language pack for Firefox
+            extra/firefox-i18n-ast 99.0-1
+                Asturian language pack for Firefox
+        """
+        matches = {}
+
+        if exact:
+            query = f"^{query}$"
+
+        output = self.run_cli("-Ss", query)
+
+        regexp = re.compile(r"(?P<package_id>\S+)\s+(?P<version>\S+).*\n\s+(?P<description>.+)", re.MULTILINE | re.VERBOSE)
+
+        for package_id, version, description in regexp.findall(output):
+            matches[package_id] = {
+                "id": package_id,
+                "name": package_id,
+                "latest_version": parse_version(version),
+            }
+
+        return matches
diff --git a/pyproject.toml b/pyproject.toml
index c1b513c8f..88b4ce58a 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -31,6 +31,7 @@ keywords = [
     'npm',
     'opkg',
     'package',
+    'pacman',
     'php composer',
     'pip',
     'plugin',
diff --git a/readme.md b/readme.md
index 4ff2b75fa..d17e2c17c 100644
--- a/readme.md
+++ b/readme.md
@@ -66,6 +66,7 @@ ______________________________________________________________________
 | [`mas`](https://github.com/argon/mas)                                     | 1.6.1        |   ✓   |       |         |        |      ✓      |                                   ✓                                   |     ✓     |     ✓      |     ✓     |           |
 | [`npm`](https://www.npmjs.com)                                            | 4.0.0        |   ✓   |   ✓   |    ✓    |        |      ✓      |                                   ✓                                   |     ✓     |     ✓      |     ✓     |           |
 | [`opkg`](https://git.yoctoproject.org/cgit/cgit.cgi/opkg/)                | 0.2.0        |       |   ✓   |         |   ✓    |      ✓      |                                   ✓                                   |     ✓     |     ✓      |     ✓     |           |
+| [`pacman`](https://wiki.archlinux.org/title/pacman)                       | 5.0.0        |        |   ✓   |         |   ✓    |      ✓      |                                   ✓                                   |     ✓     |     ✓      |     ✓     |     ✓     |
 | [`pip`](https://pypi.org)                                                 | 10.0.0       |   ✓   |   ✓   |    ✓    |        |      ✓      | [✘\*](https://github.com/pypa/pip/issues/5216#issuecomment-744605466) |     ✓     |     ✓      |     ✓     |           |
 | [`snap`](https://snapcraft.io)                                            | 2.0.0        |       |   ✓   |         |        |      ✓      |                                   ✓                                   |     ✓     |            |     ✓     |           |
 | [`vscode`](https://code.visualstudio.com)                                 | 1.60.0       |   ✓   |   ✓   |    ✓    |        |      ✓      |                                   ✓                                   |     ✓     |            |     ✓     |           |


Test patch:
diff --git a/meta_package_manager/tests/test_cli_install.py b/meta_package_manager/tests/test_cli_install.py
index 5a72d6597..09a80fb3f 100644
--- a/meta_package_manager/tests/test_cli_install.py
+++ b/meta_package_manager/tests/test_cli_install.py
@@ -55,6 +55,7 @@ def test_no_package_id(self, invoke):
         "mas": "747648890",  # Telegram
         "npm": "raven",
         "opkg": "enigma2-hotplug",
+        "pacman": "manjaro-hello",
         "pip": "arrow",
         "snap": "standard-notes",
         "vscode": "tamasfe.even-better-toml",