Repository: ansible/ansible
Pull request: fix pacman package state detection
##### SUMMARY
Fixes #51265 

##### ISSUE TYPE
- Bugfix Pull Request

##### COMPONENT NAME
pacman

##### ADDITIONAL INFORMATION
This is a fix to correctly detect a package's installation status as being absent when it is not installed but another package provides it.

Problem statement:
pacman module `state: absent` verification failure when package name is provided by another
On ansible 2.7.6 I've done:
```
- name: remove test
  pacman:
    name: linux-gpib
    state: absent
```
the linux-gpib package is not installed on the system, however linux-gpib-dkms is installed which provides linux-gpib
```
fatal: [127.0.0.1]: FAILED! => {"changed": false, "msg": "failed to remove linux-gpib"}
```
I expect no errors because the the package is indeed absent on the system.

Hints from issue discussion:
@greyltc: Greetings! Thanks for taking the time to open this issue. In order for the community to handle your issue effectively, we need a bit more information.

Here are the items we could not find in your description:
- issue type
- ansible version
- component name

Please set the description of this issue with this template:
https://raw.githubusercontent.com/ansible/ansible/devel/.github/ISSUE_TEMPLATE.md

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: issue_missing_data --->
My PR #51311 should fix this

Commit message: fix pep8 issues

Patch to review:
diff --git a/lib/ansible/modules/packaging/os/pacman.py b/lib/ansible/modules/packaging/os/pacman.py
index 7dd6db74d6e856..7526b98cc9e726 100644
--- a/lib/ansible/modules/packaging/os/pacman.py
+++ b/lib/ansible/modules/packaging/os/pacman.py
@@ -176,6 +176,15 @@ def get_version(pacman_output):
     return None
 
 
+def get_name(pacman_output):
+    """Take pacman -Qi or pacman -Si output and get the package name"""
+    lines = pacman_output.split('\n')
+    for line in lines:
+        if 'Name' in line:
+            return line.split(':')[1].strip()
+    return None
+
+
 def query_package(module, pacman_path, name, state="present"):
     """Query the package status in both the local system and the repository. Returns a boolean to indicate if the package is installed, a second
     boolean to indicate if the package is up-to-date and a third boolean to indicate whether online information were available
@@ -186,6 +195,12 @@ def query_package(module, pacman_path, name, state="present"):
         if lrc != 0:
             # package is not installed locally
             return False, False, False
+        else:
+            # a non-zero exit code doesn't always mean the package is installed
+            # for example, if the package name queried is "provided" by another package
+            installed_name = get_name(lstdout)
+            if installed_name != name:
+                return False, False, False
 
         # get the version installed locally (if any)
         lversion = get_version(lstdout)


Code review comments:
diff_hunk: @@ -176,6 +176,15 @@ def get_version(pacman_output):
     return None
 
 
+def get_name(pacman_output):
+    """Take pacman -Qi or pacman -Si output and get the package name"""
+    lines = pacman_output.split('\n')
+    for line in lines:
+        if 'Name' in line:
path: lib/ansible/modules/packaging/os/pacman.py
text: @user1:
```suggestion
        if line.startswith('Name '):
```

@author:
Yes, much better. Should be in the version getting function too. I'll add it there.

diff_hunk: @@ -176,6 +176,15 @@ def get_version(pacman_output):
     return None
 
 
+def get_name(pacman_output):
+    """Take pacman -Qi or pacman -Si output and get the package name"""
+    lines = pacman_output.split('\n')
+    for line in lines:
+        if 'Name' in line:
+            return line.split(':')[1].strip()
+    return None
path: lib/ansible/modules/packaging/os/pacman.py
text: @user1:
```suggestion
    module.fail_json(msg="get_name: fail to retrieve package name from pacman output")
```