Repository: lutris/lutris

Issue:
Lutris fails to open .tar.gz with "not a gzip file" if file is a tar file
Lutris fails to open archive where 7z doesn't. If I rename the file to `TTRLinux-v1.2.3.tar` Lutris can open and extract it. `format: tar` doesn't work here.

```
files:
- client: https://download.toontownrewritten.com/launcher/linux/TTRLinux-v1.2.3.tar.gz
game:
  exe: Launcher
installer:
- extract:
    file: client
    format: tar
```

```
2019-04-04 16:53:40,809: Downloading file 1 of 1
2019-04-04 16:53:40,811: Downloading [client]: https://download.toontownrewritten.com/launcher/linux/TTRLinux-v1.2.3.tar.gz to /home/cxf/.cache/lutris/installer/toontown-rewritten/client/TTRLinux-v1.2.3.tar.gz
2019-04-04 16:53:40,814: Downloading https://download.toontownrewritten.com/launcher/linux/TTRLinux-v1.2.3.tar.gz to /home/cxf/.cache/lutris/installer/toontown-rewritten/client/TTRLinux-v1.2.3.tar.gz
2019-04-04 16:53:40,816: Starting download of:
 https://download.toontownrewritten.com/launcher/linux/TTRLinux-v1.2.3.tar.gz
2019-04-04 16:53:44,410: Finished downloading https://download.toontownrewritten.com/launcher/linux/TTRLinux-v1.2.3.tar.gz
2019-04-04 16:53:44,822: Installer command: {'extract': {'format': 'tar', 'file': 'client'}}
2019-04-04 16:53:44,823: Extracting TTRLinux-v1.2.3.tar.gz
2019-04-04 16:53:44,824: extracting file /home/cxf/.cache/lutris/installer/toontown-rewritten/client/TTRLinux-v1.2.3.tar.gz to /home/cxf/Games/toontown-rewritten
2019-04-04 16:53:44,831: Extracting /home/cxf/.cache/lutris/installer/toontown-rewritten/client/TTRLinux-v1.2.3.tar.gz to /home/cxf/Games/toontown-rewritten
2019-04-04 16:53:44,832: Extraction failed: not a gzip file
Traceback (most recent call last):
  File "/usr/lib/python3.6/tarfile.py", line 1643, in gzopen
    t = cls.taropen(name, mode, fileobj, **kwargs)
  File "/usr/lib/python3.6/tarfile.py", line 1619, in taropen
    return cls(name, mode, fileobj, **kwargs)
  File "/usr/lib/python3.6/tarfile.py", line 1482, in __init__
    self.firstmember = self.next()
  File "/usr/lib/python3.6/tarfile.py", line 2297, in next
    tarinfo = self.tarinfo.fromtarfile(self)
  File "/usr/lib/python3.6/tarfile.py", line 1092, in fromtarfile
    buf = tarfile.fileobj.read(BLOCKSIZE)
  File "/usr/lib/python3.6/gzip.py", line 276, in read
    return self._buffer.read(size)
  File "/usr/lib/python3.6/_compression.py", line 68, in readinto
    data = self.read(len(byte_view))
  File "/usr/lib/python3.6/gzip.py", line 463, in read
    if not self._read_gzip_header():
  File "/usr/lib/python3.6/gzip.py", line 411, in _read_gzip_header
    raise OSError('Not a gzipped file (%r)' % magic)
OSError: Not a gzipped file (b'To')

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/cxf/.lutris/lutris/util/extract.py", line 90, in extract_archive
    _do_extract(path, temp_path, opener, mode, extractor)
  File "/home/cxf/.lutris/lutris/util/extract.py", line 134, in _do_extract
    handler = opener(archive, mode)
  File "/usr/lib/python3.6/tarfile.py", line 1589, in open
    return func(name, filemode, fileobj, **kwargs)
  File "/usr/lib/python3.6/tarfile.py", line 1647, in gzopen
    raise ReadError("not a gzip file")
tarfile.ReadError: not a gzip file
2019-04-04 16:53:44,835: Error while completing task <bound method CommandsMixin.extract of <lutris.installer.interpreter.ScriptInterpreter object at 0x7f0507748c88>>: not a gzip file
<class 'lutris.util.extract.ExtractFailure'> not a gzip file
  File "/home/cxf/.lutris/lutris/util/jobs.py", line 30, in target
    result = self.function(*args, **kwargs)
  File "/home/cxf/.lutris/lutris/installer/commands.py", line 180, in extract
    extract.extract_archive, filename, dest_path, merge_single, extractor
  File "/home/cxf/.lutris/lutris/installer/commands.py", line 527, in _killable_process
    result = result_obj.get()  # Wait process end & reraise exceptions
  File "/usr/lib/python3.6/multiprocessing/pool.py", line 670, in get
    raise self._value
2019-04-04 16:53:49,289: Install cancelled
```

```
cxf@PC:~/Downloads$ 7z e TTRLinux-v1.2.3.tar.gz 

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,4 CPUs Intel(R) Core(TM) i5-4460  CPU @ 3.20GHz (306C3),ASM,AES-NI)

Scanning the drive for archives:
1 file, 37233152 bytes (36 MiB)

Extracting archive: TTRLinux-v1.2.3.tar.gz
WARNING:
TTRLinux-v1.2.3.tar.gz
Can not open the file as [gzip] archive
The file is open as [tar] archive

--
Path = TTRLinux-v1.2.3.tar.gz
Open WARNING: Can not open the file as [gzip] archive
Type = tar
Physical Size = 37233152
Headers Size = 2048
Code Page = UTF-8

Everything is Ok

Archives with Warnings: 1
Folders: 1
Files: 1
Size:       37231062
Compressed: 37233152
```



Discussion:

Resolving patch:
diff --git a/lutris/util/extract.py b/lutris/util/extract.py
--- a/lutris/util/extract.py
+++ b/lutris/util/extract.py
@@ -67,23 +67,42 @@ def extract_archive(path, to_directory=".", merge_single=True, extractor=None):
     mode = None
     logger.debug("Extracting %s to %s", path, to_directory)
 
-    if path.endswith(".tar.gz") or path.endswith(".tgz") or extractor == "tgz":
+    if extractor is None:
+        if path.endswith(".tar.gz") or path.endswith(".tgz"):
+            extractor = "tgz"
+        elif path.endswith(".tar.xz") or path.endswith(".txz"):
+            extractor = "txz"
+        elif path.endswith(".tar"):
+            extractor = "tar"
+        elif path.endswith(".tar.bz2") or path.endswith(".tbz"):
+            extractor = "bz2"
+        elif path.endswith(".gz"):
+            extractor = "gzip"
+        elif is_7zip_supported(path, None):
+            extractor = None
+        else:
+            raise RuntimeError(
+                "Could not extract `%s` - no appropriate extractor found" % path
+            )
+
+    if extractor == "tgz":
         opener, mode = tarfile.open, "r:gz"
-    elif path.endswith(".tar.xz") or path.endswith(".txz") or extractor == "txz":
+    elif extractor == "txz":
         opener, mode = tarfile.open, "r:xz"
-    elif path.endswith(".tar") or extractor == "tar":
+    elif extractor == "tar":
         opener, mode = tarfile.open, "r:"
-    elif path.endswith(".gz") or extractor == "gzip":
+    elif extractor == "bz2":
+        opener, mode = tarfile.open, "r:bz2"
+    elif extractor == "gzip":
         decompress_gz(path, to_directory)
         return
-    elif path.endswith(".tar.bz2") or path.endswith(".tbz") or extractor == "bz2":
-        opener, mode = tarfile.open, "r:bz2"
-    elif is_7zip_supported(path, extractor):
+    elif extractor is None or is_7zip_supported(path, extractor):
         opener = "7zip"
     else:
         raise RuntimeError(
-            "Could not extract `%s` as no appropriate extractor is found" % path
+            "Could not extract `%s` - unknown format specified" % path
         )
+
     temp_name = ".extract-" + str(uuid.uuid4())[:8]
     temp_path = temp_dir = os.path.join(to_directory, temp_name)
     try:


Test patch: