diff --git a/docs/en/usage.md b/docs/en/usage.md index 6975e87..a553528 100644 --- a/docs/en/usage.md +++ b/docs/en/usage.md @@ -106,6 +106,10 @@ When you host a flyer, the **"Download Source Code"** button on the landing page - Installation and setup scripts for all platforms. - Complete documentation and templates. +To keep the mirrored download practical for low-bandwidth redistribution, the +source archive does not ship pre-downloaded Tor binaries. Normal installer and +release builds still fetch or bundle those artifacts separately. + This allows anyone who scans your flyer to become a new distributor of the VoxVera tool. ## Export & Backup diff --git a/docs/he/usage.md b/docs/he/usage.md index 058210a..4223ae2 100644 --- a/docs/he/usage.md +++ b/docs/he/usage.md @@ -106,6 +106,10 @@ When you host a flyer, the **"הורד כלי וקוד מקור"** button on the - Installation and setup scripts for all platforms. - Complete documentation and templates. +To keep the mirrored download practical for low-bandwidth redistribution, the +source archive does not ship pre-downloaded Tor binaries. Normal installer and +release builds still fetch or bundle those artifacts separately. + This allows anyone who scans your flyer to become a new distributor of the VoxVera tool. ## Export & Backup diff --git a/docs/templates/usage.md b/docs/templates/usage.md index e80012b..54e573e 100644 --- a/docs/templates/usage.md +++ b/docs/templates/usage.md @@ -106,6 +106,10 @@ When you host a flyer, the **"{{t('web.download_button')}}"** button on the land - Installation and setup scripts for all platforms. - Complete documentation and templates. +To keep the mirrored download practical for low-bandwidth redistribution, the +source archive does not ship pre-downloaded Tor binaries. Normal installer and +release builds still fetch or bundle those artifacts separately. + This allows anyone who scans your flyer to become a new distributor of the VoxVera tool. ## Export & Backup diff --git a/pyproject.toml b/pyproject.toml index d881de1..4d8bdd0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,7 +14,7 @@ voxvera = ["templates/**", "src/**", "resources/**", "locales/**", "resources/bi [project] name = "voxvera" -version = "0.3.10" +version = "0.3.11" description = "VoxVera CLI utilities" readme = "README.md" authors = [{name = "VoxVera"}] diff --git a/site/download/voxvera-source.zip b/site/download/voxvera-source.zip index e854097..1db4e79 100644 Binary files a/site/download/voxvera-source.zip and b/site/download/voxvera-source.zip differ diff --git a/tests/test_integrity.py b/tests/test_integrity.py index a7a35ca..b1944f4 100644 --- a/tests/test_integrity.py +++ b/tests/test_integrity.py @@ -230,3 +230,28 @@ def test_portable_bundle_integrity(tmp_path, monkeypatch): # Verify root scripts assert "voxvera-run.sh" in names + + +def test_portable_bundle_excludes_prebuilt_tor_binaries(tmp_path, monkeypatch): + project_root = tmp_path + voxvera_dir = project_root / "voxvera" + voxvera_dir.mkdir() + + shutil.copytree(REPO_ROOT / "voxvera" / "src", voxvera_dir / "src") + shutil.copytree(REPO_ROOT / "voxvera" / "locales", voxvera_dir / "locales") + shutil.copytree(REPO_ROOT / "voxvera" / "resources", voxvera_dir / "resources") + os.makedirs(voxvera_dir / "vendor", exist_ok=True) + (voxvera_dir / "vendor" / "anchor.txt").write_text("anchor") + + for script in ["voxvera-run.sh", "uninstall.sh", "uninstall.ps1", "install.sh", "install.ps1", "setup.sh"]: + if (REPO_ROOT / script).exists(): + shutil.copy(REPO_ROOT / script, project_root / script) + + monkeypatch.setattr(cli, "ROOT", voxvera_dir) + + bundle_zip = project_root / "voxvera-portable.zip" + cli.bundle_portable(bundle_zip) + + with zipfile.ZipFile(bundle_zip, "r") as zf: + names = zf.namelist() + assert not any(name.startswith("voxvera/resources/tor/") for name in names) diff --git a/voxvera/__init__.py b/voxvera/__init__.py index 404c34b..41ce391 100644 --- a/voxvera/__init__.py +++ b/voxvera/__init__.py @@ -1,7 +1,7 @@ import sys from pathlib import Path -__version__ = "0.3.10" +__version__ = "0.3.11" # Add the vendor directory to sys.path ONLY for PyInstaller (frozen) builds. # For pip/pipx installs the system/venv packages are correct and the vendored diff --git a/voxvera/cli.py b/voxvera/cli.py index a2f01f3..002bc8b 100644 --- a/voxvera/cli.py +++ b/voxvera/cli.py @@ -693,12 +693,26 @@ def copy_template(name: str) -> str: def bundle_source(dest_zip: Path): - """Bundle the VoxVera source code, dependencies (vendor), and root scripts.""" + """Bundle the VoxVera source tree and install scripts for viral mirroring. + + We intentionally exclude pre-downloaded Tor binaries from the mirrored source + archive. They dominate the zip size and are regenerated by the normal + packaging/build flows, while the mirrored source bundle is meant to stay + small enough for practical redistribution from flyer sites. + """ with zipfile.ZipFile(dest_zip, 'w', zipfile.ZIP_DEFLATED) as zipf: - # 1. Include the voxvera/ source directory (excluding host, bin, pycache) - # We DO include vendor here so the source zip is fully functional offline. + # 1. Include the voxvera/ source directory (excluding host, bin, + # bundled Tor artifacts, and pycache). We still include vendor so the + # source zip remains portable without re-resolving Python deps. for root, dirs, files in os.walk(ROOT): - if "__pycache__" in root or "host" in root or "resources/bin" in root: + root_path = Path(root) + if ( + "__pycache__" in root + or "host" in root + or "resources/bin" in root + or root_path == ROOT / "resources" / "tor" + or (ROOT / "resources" / "tor") in root_path.parents + ): continue for file in files: file_path = Path(root) / file