From 2f73289737780ef00f8cd3e83beb02eaff77da1f Mon Sep 17 00:00:00 2001 From: Justin Bollinger Date: Wed, 8 Apr 2026 12:58:05 -0400 Subject: [PATCH] fix: remove symlink/copy from _ensure_hashfile_in_cwd Output files now land next to the original hashfile. resolve_path() already resolves relative paths against HATE_CRACK_ORIG_CWD, so relocating the hashfile into CWD was unnecessary and created confusing symlinks in the working directory. Co-Authored-By: Claude Opus 4.6 (1M context) --- hate_crack/main.py | 28 ++++++----------------- tests/test_hashview.py | 12 ++-------- tests/test_main_utils.py | 49 +++++++++++++++++----------------------- 3 files changed, 30 insertions(+), 59 deletions(-) diff --git a/hate_crack/main.py b/hate_crack/main.py index 4e8110e..9e299e1 100755 --- a/hate_crack/main.py +++ b/hate_crack/main.py @@ -196,27 +196,13 @@ def _resolve_config_destination(): def _ensure_hashfile_in_cwd(hashfile_path): - """Ensure hashfile path points to cwd to keep output files in execution dir.""" - if not hashfile_path: - return hashfile_path - cwd = orig_cwd() - if not os.path.isabs(hashfile_path): - return hashfile_path - if os.path.dirname(hashfile_path) == cwd: - return hashfile_path - basename = os.path.basename(hashfile_path) - local_path = os.path.join(cwd, basename) - if os.path.exists(local_path): - return local_path - try: - os.symlink(hashfile_path, local_path) - return local_path - except Exception: - try: - shutil.copy2(hashfile_path, local_path) - return local_path - except Exception: - return hashfile_path + """Return hashfile path as-is. + + Output files (.out, .nt, etc.) are written next to the hashfile. + ``resolve_path()`` already resolves relative paths against + ``HATE_CRACK_ORIG_CWD`` so no relocation is needed. + """ + return hashfile_path # hate_path is where hate_crack assets live (hashcat-utils, princeprocessor, etc.) diff --git a/tests/test_hashview.py b/tests/test_hashview.py index b93a3dd..ed01f2a 100644 --- a/tests/test_hashview.py +++ b/tests/test_hashview.py @@ -775,7 +775,7 @@ class TestHashviewAPI: assert content == b"hash1\nhash2\n" def test_hashfile_orig_path_preservation(self, tmp_path, monkeypatch): - """Test that original hashfile path is preserved before _ensure_hashfile_in_cwd""" + """Test that _ensure_hashfile_in_cwd is a pass-through returning the input path.""" from hate_crack.main import _ensure_hashfile_in_cwd # Create a test hashfile in a different directory @@ -792,16 +792,8 @@ class TestHashviewAPI: # Call _ensure_hashfile_in_cwd result_path = _ensure_hashfile_in_cwd(original_path) - # The result should be different from original (in cwd now) - # But original_path should still exist and be unchanged + assert result_path == original_path, "Pass-through should return the input path" assert os.path.exists(original_path), "Original file should still exist" - assert os.path.exists(result_path), "Result file should exist" - - # If they're different, result should be in cwd - if result_path != original_path: - assert os.path.dirname(result_path) == str(tmp_path), ( - "Result should be in cwd" - ) if __name__ == "__main__": diff --git a/tests/test_main_utils.py b/tests/test_main_utils.py index 2569f44..7808149 100644 --- a/tests/test_main_utils.py +++ b/tests/test_main_utils.py @@ -100,25 +100,8 @@ class TestEnsureHashfileInCwd: result = main_module._ensure_hashfile_in_cwd(str(target)) assert result == str(target) - def test_different_dir_existing_file_in_cwd(self, main_module, tmp_path, monkeypatch): - # File exists in a different directory - other_dir = tmp_path / "other" - other_dir.mkdir() - source_file = other_dir / "hashes.txt" - source_file.write_text("hashes") - - # A file with the same name already exists in cwd - cwd_dir = tmp_path / "cwd" - cwd_dir.mkdir() - cwd_copy = cwd_dir / "hashes.txt" - cwd_copy.write_text("cwd version") - - monkeypatch.setenv("HATE_CRACK_ORIG_CWD", str(cwd_dir)) - result = main_module._ensure_hashfile_in_cwd(str(source_file)) - assert result == str(cwd_copy) - - def test_different_dir_creates_symlink(self, main_module, tmp_path, monkeypatch): - # Source file in a different directory, nothing in cwd + def test_different_dir_returns_original_path(self, main_module, tmp_path, monkeypatch): + """File in different dir is returned as-is (no symlink/copy).""" other_dir = tmp_path / "other" other_dir.mkdir() source_file = other_dir / "hashes.txt" @@ -129,14 +112,25 @@ class TestEnsureHashfileInCwd: monkeypatch.setenv("HATE_CRACK_ORIG_CWD", str(cwd_dir)) result = main_module._ensure_hashfile_in_cwd(str(source_file)) + assert result == str(source_file) - expected = str(cwd_dir / "hashes.txt") - assert result == expected - assert os.path.exists(expected) + def test_different_dir_no_symlink(self, main_module, tmp_path, monkeypatch): + """File in different dir does NOT create a symlink in cwd.""" + other_dir = tmp_path / "other" + other_dir.mkdir() + source_file = other_dir / "hashes.txt" + source_file.write_text("hashes") + + cwd_dir = tmp_path / "cwd" + cwd_dir.mkdir() + + monkeypatch.setenv("HATE_CRACK_ORIG_CWD", str(cwd_dir)) + result = main_module._ensure_hashfile_in_cwd(str(source_file)) + assert result == str(source_file) + assert not (cwd_dir / "hashes.txt").exists() def test_uses_orig_cwd_not_process_cwd(self, main_module, tmp_path, monkeypatch): - """Output files go to HATE_CRACK_ORIG_CWD, not the process CWD.""" - # Simulate: process CWD is the install dir, orig CWD is the user's dir + """Returns original path as-is; no files created in any cwd.""" install_dir = tmp_path / "install" install_dir.mkdir() user_dir = tmp_path / "user" @@ -150,10 +144,9 @@ class TestEnsureHashfileInCwd: monkeypatch.setenv("HATE_CRACK_ORIG_CWD", str(user_dir)) result = main_module._ensure_hashfile_in_cwd(str(source_file)) - # Should land in user_dir, NOT install_dir - assert result == str(user_dir / "hashes.txt") - assert os.path.exists(user_dir / "hashes.txt") - assert not os.path.exists(install_dir / "hashes.txt") + assert result == str(source_file) + assert not (user_dir / "hashes.txt").exists() + assert not (install_dir / "hashes.txt").exists() class TestRunHashcatShow: