diff --git a/README.md b/README.md index 2ab5a41..795c418 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,8 @@ hate_crack **Important:** The tool needs access to `hashcat-utils` and `princeprocessor` subdirectories from the hate_crack repository. The tool will automatically search for these assets in: -- Environment variables: `HATE_CRACK_HOME` or `HATE_CRACK_ASSETS` +- Directory specified by `hcatPath` in `config.json` when it points to the hate_crack checkout that contains the assets +- Ancestors of the installed package directory (e.g., the uv tool root that still contains the original `hashcat-utils`/`princeprocessor` directories) - Current working directory and parent directory - `~/hate_crack`, `~/hate-crack`, or `~/.hate_crack` @@ -122,13 +123,9 @@ cd /path/to/hate_crack hate_crack ``` -**Option 2 - Set environment variable:** -```bash -export HATE_CRACK_HOME=/path/to/hate_crack -hate_crack -``` +If assets live somewhere else, make sure `config.json` uses that directory for `"hcatPath"` before running. -**Note:** The `hcatPath` in config.json is for the hashcat binary location (optional if hashcat is in PATH), not for hate_crack assets. +**Note:** The `hcatPath` in `config.json` is for the hashcat binary location (optional if hashcat is in PATH), not for hate_crack assets. ### Run as a script The script uses a `uv` shebang. Make it executable and run: @@ -162,7 +159,7 @@ This means the tool cannot find the hate_crack repository assets. The `hashcat-u - `hashcat-utils/` and `princeprocessor/` → located in the **hate_crack repository directory** The tool automatically searches for hate_crack assets in these locations: -1. Directory specified by `HATE_CRACK_HOME` or `HATE_CRACK_ASSETS` environment variables +1. Directory specified by `hcatPath` in `config.json` when it points to the hate_crack checkout that contains the assets 2. Current working directory and parent directory 3. `~/hate_crack`, `~/hate-crack`, or `~/.hate_crack` @@ -173,11 +170,7 @@ cd /opt/hate_crack # or wherever you cloned the repository hate_crack ``` -Or set an environment variable: -```bash -export HATE_CRACK_HOME=/opt/hate_crack -hate_crack -``` +If the assets live elsewhere, update `"hcatPath"` in `config.json` to point to the directory that contains `hashcat-utils` and `princeprocessor`. **Example config.json:** ```json diff --git a/hate_crack/main.py b/hate_crack/main.py index 9d4ce7b..1d70744 100755 --- a/hate_crack/main.py +++ b/hate_crack/main.py @@ -81,6 +81,20 @@ def _has_hate_crack_assets(path): ) +def _find_assets_in_ancestors(start_path): + current = os.path.abspath(start_path) + seen = set() + while current not in seen: + if _has_hate_crack_assets(current): + return current + seen.add(current) + parent = os.path.abspath(os.path.join(current, os.pardir)) + if parent == current: + break + current = parent + return None + + def _resolve_hate_path(package_path, config_dict=None): # Try to use hcatPath from config.json if it's set and contains assets if config_dict and config_dict.get('hcatPath'): @@ -88,11 +102,10 @@ def _resolve_hate_path(package_path, config_dict=None): if _has_hate_crack_assets(assets_path): return assets_path - # Check environment variable as fallback - env_override = os.environ.get("HATE_CRACK_HOME") or os.environ.get("HATE_CRACK_ASSETS") - if env_override: - if _has_hate_crack_assets(env_override): - return env_override + # When installed via uv, the assets live above the package directory in the tool root. + ancestor_assets = _find_assets_in_ancestors(package_path) + if ancestor_assets: + return ancestor_assets # Check current working directory and parent (look for repo directory) cwd = os.getcwd() @@ -177,8 +190,8 @@ def ensure_binary(binary_path, build_dir=None, name=None): print('These are part of the hate_crack repository, not hashcat installation.') print('\nPlease run hate_crack from the repository directory:') print(' cd /path/to/hate_crack && hate_crack ') - print('\nOr set the HATE_CRACK_HOME environment variable:') - print(' export HATE_CRACK_HOME=/path/to/hate_crack') + print('\nOr set "hcatPath" in config.json to the hate_crack directory that contains hashcat-utils and princeprocessor:') + print(' "hcatPath": "/path/to/hate_crack"') quit(1) # Binary missing - need to build diff --git a/tests/test_asset_path_separation.py b/tests/test_asset_path_separation.py index 7a20ec2..012c754 100644 --- a/tests/test_asset_path_separation.py +++ b/tests/test_asset_path_separation.py @@ -96,8 +96,25 @@ def test_readme_documents_correct_usage(): readme = f.read() # Check that README mentions the correct relationship - assert 'HATE_CRACK_HOME' in readme + assert 'hcatPath' in readme + assert 'repository directory' in readme assert 'hashcat-utils' in readme # Should NOT suggest putting hashcat-utils in hashcat directory # (This is a documentation test to prevent confusing users) + + +def test_resolve_hate_path_prefers_package_ancestors(tmp_path): + """Ensure package installs discover assets by walking up to the tool root.""" + from hate_crack.main import _resolve_hate_path + + assets_root = tmp_path / "hate_crack_root" + assets_root.mkdir() + (assets_root / "hashcat-utils").mkdir() + (assets_root / "config.json.example").write_text("{}") + + package_path = assets_root / "lib" / "python3.14" / "site-packages" / "hate_crack" + package_path.mkdir(parents=True) + + resolved = _resolve_hate_path(str(package_path), config_dict={}) + assert resolved == str(assets_root) diff --git a/tests/test_e2e_local_install.py b/tests/test_e2e_local_install.py index e4ca4f6..388ca8d 100644 --- a/tests/test_e2e_local_install.py +++ b/tests/test_e2e_local_install.py @@ -24,7 +24,6 @@ def test_local_uv_tool_install_and_help(tmp_path): "HOME": str(home_dir), "PATH": f"{home_dir / '.local' / 'bin'}:{env.get('PATH', '')}", "HATE_CRACK_SKIP_INIT": "1", - "HATE_CRACK_HOME": str(repo_root), "XDG_CACHE_HOME": str(tmp_path / "cache"), "XDG_CONFIG_HOME": str(tmp_path / "config"), "XDG_DATA_HOME": str(tmp_path / "data"), diff --git a/tests/test_invalid_hcatpath.py b/tests/test_invalid_hcatpath.py index e2c1975..6e88f41 100644 --- a/tests/test_invalid_hcatpath.py +++ b/tests/test_invalid_hcatpath.py @@ -27,7 +27,7 @@ def test_ensure_binary_error_message(monkeypatch, capsys): captured = capsys.readouterr() assert "Build directory" in captured.out or "does not exist" in captured.out assert "hate_crack" in captured.out.lower() # Should mention hate_crack assets - assert "HATE_CRACK_HOME" in captured.out or "repository" in captured.out + assert "hcatPath" in captured.out or "repository" in captured.out def test_ensure_binary_with_existing_binary():