diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 83cad0b5..b67fd7cc 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -9,6 +9,9 @@ Changelog version 1.10.0-dev ------------------ ++ Fix ``python -m isal.igzip`` replacing the input file with empty output and + exiting with status 0 when the output file is the input file, as in + ``-f -o data data``. It exits with an error now. + Speed up ``import isal.igzip`` and ``import isal.igzip_threaded`` by not importing ``typing``. + Fix the gzip header that ``igzip_threaded.open`` writes when ``threads`` is diff --git a/src/isal/igzip.py b/src/isal/igzip.py index a7a2d5a5..1c188a7e 100644 --- a/src/isal/igzip.py +++ b/src/isal/igzip.py @@ -349,6 +349,11 @@ def main(): if extension != ".gz" and not args.stdout: sys.exit(f"filename doesn't end in .gz: {args.file!r}. " f"Cannot determine output filename.") + # Opening the output for writing would empty the input before it is read. + if (args.file is not None and out_filepath is not None + and os.path.exists(args.file) and os.path.exists(out_filepath) + and os.path.samefile(args.file, out_filepath)): + sys.exit(f"{args.file!r} and {out_filepath!r} are the same file") if out_filepath is not None and not args.force: if os.path.exists(out_filepath): yes_or_no = input(f"{out_filepath} already exists; " diff --git a/tests/test_igzip.py b/tests/test_igzip.py index 62ca42e2..1c691c2b 100644 --- a/tests/test_igzip.py +++ b/tests/test_igzip.py @@ -355,6 +355,29 @@ def test_compress_infile_out_file_force(monkeypatch, tmp_path, capsysbinary): assert out == b'' +@pytest.mark.parametrize("args", [ + ['-f', '-o', 'test', 'test'], + ['-f', '-o', os.path.join('.', 'test'), 'test'], + ['-o', 'test', 'test'], # Refused before the overwrite prompt. + ['-d', '-f', '-o', 'test.gz', 'test.gz'], +]) +def test_infile_out_file_same_file(monkeypatch, tmp_path, capsysbinary, args): + monkeypatch.chdir(tmp_path) + test = tmp_path / "test" + test.write_bytes(DATA) + test_gz = tmp_path / "test.gz" + test_gz.write_bytes(COMPRESSED_DATA) + monkeypatch.setattr(sys, "argv", ['', *args]) + monkeypatch.setattr(sys, "stdin", io.TextIOWrapper(io.BytesIO(b"y"))) + with pytest.raises(SystemExit) as error: + igzip.main() + assert error.match("are the same file") + assert test.read_bytes() == DATA + assert test_gz.read_bytes() == COMPRESSED_DATA + out, err = capsysbinary.readouterr() + assert out == b'' + + def test_compress_infile_out_file_prompt(monkeypatch, tmp_path, capsysbinary): test = tmp_path / "test" test.write_bytes(DATA)