From 1b78f18bf483047e1ab1d29bb9ef42d11c79efa0 Mon Sep 17 00:00:00 2001
From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com>
Date: Thu, 20 Oct 2022 20:45:27 +0200
Subject: [PATCH] Do not crash when lzma is not around. (#5393) (#5397)

(cherry picked from commit 5aa1e587496c906f5985d8c294ab23c2d9a4c818)

Co-authored-by: Felix Fontein <felix@fontein.de>
---
 changelogs/fragments/5393-archive.yml         |  2 +
 plugins/modules/files/archive.py              |  7 +++-
 .../targets/archive/tasks/main.yml            | 40 ++++++++++++++-----
 3 files changed, 39 insertions(+), 10 deletions(-)
 create mode 100644 changelogs/fragments/5393-archive.yml

diff --git a/changelogs/fragments/5393-archive.yml b/changelogs/fragments/5393-archive.yml
new file mode 100644
index 0000000000..a589c935ec
--- /dev/null
+++ b/changelogs/fragments/5393-archive.yml
@@ -0,0 +1,2 @@
+bugfixes:
+  - "archive - avoid crash when ``lzma`` is not present and ``format`` is not ``xz`` (https://github.com/ansible-collections/community.general/pull/5393)."
diff --git a/plugins/modules/files/archive.py b/plugins/modules/files/archive.py
index 91dc6e5112..b7a05a0b2a 100644
--- a/plugins/modules/files/archive.py
+++ b/plugins/modules/files/archive.py
@@ -581,6 +581,11 @@ class TarArchive(Archive):
             self.file.add(path, archive_name, recursive=False, exclude=py26_filter)
 
     def _get_checksums(self, path):
+        if HAS_LZMA:
+            LZMAError = lzma.LZMAError
+        else:
+            # Just picking another exception that's also listed below
+            LZMAError = tarfile.ReadError
         try:
             if self.format == 'xz':
                 with lzma.open(_to_native_ascii(path), 'r') as f:
@@ -591,7 +596,7 @@ class TarArchive(Archive):
                 archive = tarfile.open(_to_native_ascii(path), 'r|' + self.format)
                 checksums = set((info.name, info.chksum) for info in archive.getmembers())
                 archive.close()
-        except (lzma.LZMAError, tarfile.ReadError, tarfile.CompressionError):
+        except (LZMAError, tarfile.ReadError, tarfile.CompressionError):
             try:
                 # The python implementations of gzip, bz2, and lzma do not support restoring compressed files
                 # to their original names so only file checksum is returned
diff --git a/tests/integration/targets/archive/tasks/main.yml b/tests/integration/targets/archive/tasks/main.yml
index e7b6c44175..88f2878afa 100644
--- a/tests/integration/targets/archive/tasks/main.yml
+++ b/tests/integration/targets/archive/tasks/main.yml
@@ -23,6 +23,37 @@
 # Make sure we start fresh
 
 # Test setup
+- name: prep our files
+  copy: src={{ item }} dest={{remote_tmp_dir}}/{{ item }}
+  with_items:
+    - foo.txt
+    - bar.txt
+    - empty.txt
+    - sub
+    - sub/subfile.txt
+
+# Run twice without lzma backport installed, to make sure it does not crash
+- name: Archive - pre-test - first run
+  archive:
+    path: "{{ remote_tmp_dir }}/*.txt"
+    dest: "{{ remote_tmp_dir }}/archive_pretest_1.tar"
+    format: "tar"
+  register: pretest_1
+
+- name: Archive - pre-test - second run
+  archive:
+    path: "{{ remote_tmp_dir }}/*.txt"
+    dest: "{{ remote_tmp_dir }}/archive_pretest_1.tar"
+    format: "tar"
+  register: pretest_2
+
+- name: Archive - validate pre-test
+  assert:
+    that:
+      - pretest_1 is changed
+      - pretest_2 is not changed
+
+# Install dependencies
 - name: Ensure zip is present to create test archive (yum)
   yum: name=zip state=latest
   when: ansible_facts.pkg_mgr == 'yum'
@@ -74,15 +105,6 @@
   when: ansible_python_version.split('.')[0] == '2'
   register: backports_lzma_pip
 
-- name: prep our files
-  copy: src={{ item }} dest={{remote_tmp_dir}}/{{ item }}
-  with_items:
-    - foo.txt
-    - bar.txt
-    - empty.txt
-    - sub
-    - sub/subfile.txt
-
 - name: Define formats to test
   set_fact:
     formats: