Update install_rtorrent.py

This commit is contained in:
gru
2026-05-15 13:37:43 +02:00
parent d925f207e1
commit 0bbcc0034f

View File

@@ -506,7 +506,23 @@ WantedBy=multi-user.target
run(["systemctl", "daemon-reload"]) run(["systemctl", "daemon-reload"])
def build_rtorrent_config_content(username, scgi_port, torrent_port): def extract_version_tuple(text):
if not text:
return None
match = re.search(r"(?:^|[^0-9])(\d+)\.(\d+)\.(\d+)(?:[^0-9]|$)", str(text))
if not match:
return None
return tuple(int(part) for part in match.groups())
def rtorrent_bind_address_directive(rtorrent_ref, rtorrent_version=None):
version = extract_version_tuple(rtorrent_ref) or extract_version_tuple(rtorrent_version)
if version and version < (0, 16, 0):
return "network.bind_address.set"
return "network.bind_address.ipv4.set"
def build_rtorrent_config_content(username, scgi_port, torrent_port, bind_address_directive):
return f""" return f"""
## https://git.linuxiarz.pl/gru/tools_scripts/_edit/master/install_rtorrent.py ## https://git.linuxiarz.pl/gru/tools_scripts/_edit/master/install_rtorrent.py
# Generated by install_rtorrent.py # Generated by install_rtorrent.py
@@ -518,7 +534,7 @@ encoding.add = UTF-8
network.scgi.open_port = 127.0.0.1:{scgi_port} network.scgi.open_port = 127.0.0.1:{scgi_port}
network.port_range.set = {torrent_port}-{torrent_port} network.port_range.set = {torrent_port}-{torrent_port}
network.port_random.set = no network.port_random.set = no
network.bind_address.ipv4.set = 0.0.0.0 {bind_address_directive} = 0.0.0.0
system.file.allocate.set = 0 system.file.allocate.set = 0
system.umask.set = 0022 system.umask.set = 0022
@@ -543,9 +559,9 @@ network.http.dns_cache_timeout.set = 0
""".lstrip() """.lstrip()
def write_rtorrent_config(user_home, username, scgi_port, torrent_port, *, force_config=False): def write_rtorrent_config(user_home, username, scgi_port, torrent_port, bind_address_directive, *, force_config=False):
config_path = Path(user_home) / ".rtorrent.rc" config_path = Path(user_home) / ".rtorrent.rc"
config_content = build_rtorrent_config_content(username, scgi_port, torrent_port) config_content = build_rtorrent_config_content(username, scgi_port, torrent_port, bind_address_directive)
if config_path.exists() and not force_config: if config_path.exists() and not force_config:
print(f"Config already exists: {config_path}") print(f"Config already exists: {config_path}")
@@ -580,6 +596,47 @@ def print_link_lines(title, lines):
print(line) print(line)
def print_optional_libs_explanation():
print("Optional libraries:")
print(" - c-ares: asynchronous DNS resolver. It helps avoid blocking DNS lookups and can improve tracker/DHT-heavy workloads when curl is built with AsynchDNS support.")
print(" - curl: HTTP/HTTPS transfer library used by libtorrent for tracker/web requests. Building a fresh curl can provide newer TLS/HTTP fixes and c-ares based async DNS.")
print(" - minimal build: builds only xmlrpc-c, libtorrent and rTorrent; it uses the system libraries already available on Debian.")
def resolve_optional_build_mode(args):
requested = [name for name, enabled in [
("--minimal", args.minimal),
("--with-cares", args.with_cares),
("--with-curl", args.with_curl),
("--no-cares", args.no_cares),
("--no-curl", args.no_curl),
] if enabled]
if args.minimal and (args.with_cares or args.with_curl):
raise InstallError("Conflicting options: --minimal cannot be used with --with-cares or --with-curl.")
if args.no_curl and args.with_curl:
raise InstallError("Conflicting options: --no-curl cannot be used with --with-curl.")
if args.no_cares and (args.with_cares or args.with_curl):
raise InstallError("Conflicting options: --no-cares cannot be used with --with-cares or --with-curl.")
if args.minimal or args.no_curl:
return False
if args.with_curl or args.with_cares:
return True
if args.no_cares:
return False
if args.yes:
return False
print_optional_libs_explanation()
return prompt_yes_no(
"Build additional c-ares and newest custom curl?",
default=False,
assume_yes=False,
)
def verify_libtorrent_curl_integration(base_dir, libtorrent_install, curl_install, cares_install, *, debug=False): def verify_libtorrent_curl_integration(base_dir, libtorrent_install, curl_install, cares_install, *, debug=False):
libtorrent_so = next((p for p in sorted((Path(libtorrent_install) / "lib").glob("libtorrent.so*")) if p.is_file() and not p.is_symlink()), None) libtorrent_so = next((p for p in sorted((Path(libtorrent_install) / "lib").glob("libtorrent.so*")) if p.is_file() and not p.is_symlink()), None)
if not libtorrent_so: if not libtorrent_so:
@@ -671,25 +728,31 @@ def build_parser():
parser.add_argument("--torrent-port", type=int, default=DEFAULT_TORRENT_PORT, help=f"Incoming BitTorrent listen port (default: {DEFAULT_TORRENT_PORT})") parser.add_argument("--torrent-port", type=int, default=DEFAULT_TORRENT_PORT, help=f"Incoming BitTorrent listen port (default: {DEFAULT_TORRENT_PORT})")
parser.add_argument("--force-config", action="store_true", help="Overwrite existing ~/.rtorrent.rc. By default, existing config is left unchanged and the proposed changes are printed.") parser.add_argument("--force-config", action="store_true", help="Overwrite existing ~/.rtorrent.rc. By default, existing config is left unchanged and the proposed changes are printed.")
parser.add_argument("--only-build", action="store_true", help="Only build and install libtorrent/rTorrent under /opt. Skip user, config and systemd.") parser.add_argument("--only-build", action="store_true", help="Only build and install libtorrent/rTorrent under /opt. Skip user, config and systemd.")
parser.add_argument("--yes", action="store_true", help="Assume yes for interactive prompts.") parser.add_argument("--yes", action="store_true", help="Assume yes for interactive prompts; optional c-ares/curl remain disabled unless --with-curl or --with-cares is used.")
parser.add_argument("--debug", action="store_true", help="Show full command output during build steps.") parser.add_argument("--debug", action="store_true", help="Show full command output during build steps.")
parser.add_argument("--without-cares", dest="use_cares", action="store_false", help="Skip building c-ares and custom curl.") parser.add_argument("--minimal", "--core-only", action="store_true", help="Build only xmlrpc-c, libtorrent and rTorrent. Do not build c-ares or custom curl.")
parser.set_defaults(use_cares=True) parser.add_argument("--no-cares", "--without-cares", dest="no_cares", action="store_true", help="Do not build c-ares. This also disables custom curl integration.")
parser.add_argument("--no-curl", "--without-curl", dest="no_curl", action="store_true", help="Do not build custom curl. Implies no c-ares integration for libtorrent.")
parser.add_argument("--with-cares", action="store_true", help="Build c-ares and custom curl with asynchronous DNS support.")
parser.add_argument("--with-curl", action="store_true", help="Build newest custom curl; c-ares is enabled unless --no-cares is used.")
return parser return parser
def main(): def main():
parser = build_parser() parser = build_parser()
args = parser.parse_args() args = parser.parse_args()
args.use_cares = resolve_optional_build_mode(args)
require_root() require_root()
detect_debian() detect_debian()
packages = [ packages = [
"build-essential", "pkg-config", "libtool", "autoconf", "automake", "git", "ca-certificates", "build-essential", "pkg-config", "libtool", "autoconf", "automake", "git", "ca-certificates",
"libssl-dev", "libncurses5-dev", "libncursesw5-dev", "libexpat1-dev", "curl", "tar", "cmake", "libssl-dev", "libncurses5-dev", "libncursesw5-dev", "libexpat1-dev", "curl", "tar",
"libpsl-dev", "zlib1g-dev", "libbrotli-dev", "libzstd-dev" "zlib1g-dev"
] ]
if args.use_cares:
packages.extend(["cmake", "libpsl-dev", "libbrotli-dev", "libzstd-dev"])
print("This script will:") print("This script will:")
print(f" - build xmlrpc-c from '{args.xmlrpc_ref}'") print(f" - build xmlrpc-c from '{args.xmlrpc_ref}'")
@@ -698,8 +761,10 @@ def main():
if args.use_cares: if args.use_cares:
print(f" - build c-ares from '{args.cares_ref}'") print(f" - build c-ares from '{args.cares_ref}'")
print(f" - build curl from '{args.curl_ref}' with c-ares") print(f" - build curl from '{args.curl_ref}' with c-ares")
print(" - benefit: async DNS via c-ares and newer curl for HTTP/HTTPS tracker requests")
else: else:
print(" - skip c-ares/custom curl and use system curl") print(" - minimal build: skip c-ares/custom curl")
print(" - build only xmlrpc-c, libtorrent and rTorrent; use Debian system libraries")
print(f" - install everything under '{args.base_dir}'") print(f" - install everything under '{args.base_dir}'")
if args.only_build: if args.only_build:
print(" - skip service user, config and systemd setup") print(" - skip service user, config and systemd setup")
@@ -739,7 +804,9 @@ def main():
if not args.only_build: if not args.only_build:
create_system_user(args.user, args.group, args.home, assume_yes=args.yes, debug=args.debug) create_system_user(args.user, args.group, args.home, assume_yes=args.yes, debug=args.debug)
prepare_user_dirs(args.home, args.user) prepare_user_dirs(args.home, args.user)
write_rtorrent_config(args.home, args.user, args.scgi_port, args.torrent_port, force_config=args.force_config) bind_address_directive = rtorrent_bind_address_directive(args.rtorrent_ref, rtorrent_version)
print(f"Using rTorrent bind address directive: {bind_address_directive}")
write_rtorrent_config(args.home, args.user, args.scgi_port, args.torrent_port, bind_address_directive, force_config=args.force_config)
runtime_lib_dirs = [f"{libtorrent_install}/lib", f"{xmlrpc_install}/lib"] runtime_lib_dirs = [f"{libtorrent_install}/lib", f"{xmlrpc_install}/lib"]
if curl_install: if curl_install:
runtime_lib_dirs.append(f"{curl_install}/lib") runtime_lib_dirs.append(f"{curl_install}/lib")