diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-10-14 22:20:15 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-10-14 22:20:15 +0200 |
| commit | 422647e7898b8df67cd11f8fb060aec23dec84aa (patch) | |
| tree | 7ecca0e8df1bc8a7d26cf4b471bd44906dd9cfd1 /packaging/win/meshbay-node.spec | |
| parent | 28c88908b88c58cba4de08710f6bb268ede02d57 (diff) | |
| download | meshbay-422647e7898b8df67cd11f8fb060aec23dec84aa.tar.gz | |
feat(cli): meshbay-cli, a command-line client for members
Signs in to the hub, lists the account's groups and their folders, and
downloads and uploads files directly with each group's node, end-to-end
encrypted. With no argument it opens a two-pane interactive mode (Textual).
Session and device keys are kept encrypted under the system's key storage,
or a 0600 key file where there is none; node keys are pinned at first
contact; a new machine links as a device.
Packaged on its own on Linux (deb and rpm, on meshbay-common's venv, with a
man page generated from the parser) and frozen next to meshbay-node in the
full Windows installer, not the light one, with a self-test the build runs.
client/keys.py ports keyderive.js and is LGPL like it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packaging/win/meshbay-node.spec')
| -rw-r--r-- | packaging/win/meshbay-node.spec | 127 |
1 files changed, 110 insertions, 17 deletions
diff --git a/packaging/win/meshbay-node.spec b/packaging/win/meshbay-node.spec index a1173a2..8a6e384 100644 --- a/packaging/win/meshbay-node.spec +++ b/packaging/win/meshbay-node.spec @@ -1,6 +1,8 @@ -# PyInstaller spec for the bundled Windows node daemon. +# PyInstaller spec for the bundled Windows node daemon, and the command-line +# client beside it. # -# Output: dist/meshbay-node/meshbay-node.exe (--onedir, relocatable) +# Output: dist/meshbay-node/meshbay-node.exe, meshbay-nodew.exe and +# meshbay-cli.exe (--onedir, relocatable, one _internal\ for the three) # Consumed by: packaging/win/build-node-runtime.ps1, which moves the tree to # packages/meshbay-client/node-runtime/ for electron-builder to carry as an # extraResource. @@ -35,21 +37,27 @@ _vtuple = tuple( int(p) for p in (_ver.split("+")[0].split(".") + ["0", "0", "0", "0"])[:4] ) -_version_info = VSVersionInfo( - ffi=FixedFileInfo(filevers=_vtuple, prodvers=_vtuple), - kids=[ - StringFileInfo([StringTable("040904B0", [ - StringStruct("CompanyName", "MeshBay"), - StringStruct("FileDescription", "MeshBay Node"), - StringStruct("FileVersion", _ver), - StringStruct("InternalName", "meshbay-node"), - StringStruct("OriginalFilename", "meshbay-node.exe"), - StringStruct("ProductName", "MeshBay Node"), - StringStruct("ProductVersion", _ver), - ])]), - VarFileInfo([VarStruct("Translation", [0x0409, 1200])]), - ], -) + + +def _version_resource(name: str, description: str) -> VSVersionInfo: + return VSVersionInfo( + ffi=FixedFileInfo(filevers=_vtuple, prodvers=_vtuple), + kids=[ + StringFileInfo([StringTable("040904B0", [ + StringStruct("CompanyName", "MeshBay"), + StringStruct("FileDescription", description), + StringStruct("FileVersion", _ver), + StringStruct("InternalName", name), + StringStruct("OriginalFilename", f"{name}.exe"), + StringStruct("ProductName", description), + StringStruct("ProductVersion", _ver), + ])]), + VarFileInfo([VarStruct("Translation", [0x0409, 1200])]), + ], + ) + + +_version_info = _version_resource("meshbay-node", "MeshBay Node") # Packages taken in full: data files + shared libs + every submodule. COLLECT_ALL = [ @@ -177,11 +185,96 @@ exe_windowless = EXE( icon="../../packages/meshbay-client/build/icon.ico", version=_version_info, ) + +# --- The command-line client --------------------------------------------------- +# Its own analysis: another entry point, and packages the daemon does not use +# (Textual loads its widgets lazily, Rich its Unicode tables by version, +# Pygments its lexers by name, keyring its backends through entry points — +# hence keyring's metadata). What both import (aiortc, av, cryptography, ...) +# lands once in _internal\: COLLECT keeps one copy of a file the two share. +CLI_COLLECT_ALL = [ + "meshbay_cli", + "meshbay_common", + "aiortc", + "aioice", + "av", + "cryptography", + "pylibsrtp", + "pyee", + "google_crc32c", + "httpx", + "httpcore", + "h11", + "anyio", + "dns", + "argon2", + "_argon2_cffi_bindings", + "keyring", + "win32ctypes", + "textual", + "rich", + "pygments", + "markdown_it", + "mdit_py_plugins", + "linkify_it", + "platformdirs", + "blake3", + "msgpack", + "jwt", + "tzdata", +] +CLI_COPY_META = ["meshbay-cli", "meshbay-common", "keyring", "textual"] + +cli_datas, cli_binaries, cli_hidden = [], [], [] +for pkg in CLI_COLLECT_ALL: + d, b, h = collect_all(pkg) + cli_datas += d + cli_binaries += b + cli_hidden += h +for dist in CLI_COPY_META: + cli_datas += copy_metadata(dist) + +cli_a = Analysis( + ["cli-entry.py"], + pathex=[], + binaries=cli_binaries, + datas=cli_datas, + hiddenimports=cli_hidden, + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=["tkinter", "pytest", "ruff", "IPython", "meshbay_node", "meshbay_hub"], + noarchive=False, +) +cli_pyz = PYZ(cli_a.pure) +exe_cli = EXE( + cli_pyz, + cli_a.scripts, + [], + exclude_binaries=True, + name="meshbay-cli", + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=False, + console=True, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, + icon="../../packages/meshbay-client/build/icon.ico", + version=_version_resource("meshbay-cli", "MeshBay command-line client"), +) + coll = COLLECT( exe, exe_windowless, + exe_cli, a.binaries, a.datas, + cli_a.binaries, + cli_a.datas, strip=False, upx=False, upx_exclude=[], |