Loading build/moz.configure/torbrowser-resources.configure +157 −2 Changes for build/moz.configure/torbrowser-resources.configure: 157 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ option( nargs=1, default=None, help="Path to location of tor-expert-bundle directory.", when=is_desktop_build, ) Loading @@ -12,8 +13,11 @@ option( mozbuild_state_path, bootstrap_path( "tor-expert-bundle", when=depends("--with-tor-expert-bundle")(lambda x: not x) & is_desktop_build, when=depends("--with-tor-expert-bundle", when=is_desktop_build)( lambda x: not x ), ), when=is_desktop_build, ) @checking("for tor-expert-bundle") @imports(_from="pathlib", _import="Path") Loading @@ -34,4 +38,155 @@ def tor_expert_bundle(value, mozbuild_state_path, _bootstrapped): return None set_config("TOR_EXPERT_BUNDLE", tor_expert_bundle) set_config("TOR_EXPERT_BUNDLE", tor_expert_bundle, when=is_desktop_build) # Android # ------------------------------------------------- @depends(build_project) def is_android_build(build_project): return build_project == "mobile/android" @imports(_from="pathlib", _import="Path") def maven_local_default(): return str(Path.home() / ".m2/repository") option( "--with-maven-local", nargs=1, default=maven_local_default(), help="Path the maven local directory. Defaults to $HOME/.m2/repository", ) @depends("--with-maven-local") def maven_local(value): if value: return value[0] option( "--with-tor-expert-bundle-aar", env="TOR_EXPERT_BUNDLE_AAR", nargs=1, default=None, help="Path to location of tor-expert-bundle.aar archive.", when=is_android_build, ) @depends( "--with-tor-expert-bundle-aar", mozbuild_state_path, bootstrap_path( "tor-expert-bundle-aar", no_unpack=True, when=depends("--with-tor-expert-bundle-aar", when=is_android_build)( lambda x: not x ), ), when=is_android_build, ) @checking("for tor-expert-bundle.aar") @imports(_from="pathlib", _import="Path") def tor_expert_bundle_aar(value, mozbuild_state_path, _bootstrapped): if value: path = Path(value[0]) if path.suffix.lower() == ".aar": return value[0] else: die("--with-tor-expert-bundle-aar must point to a AAR archive.") bootstrapped_location = Path(mozbuild_state_path) / "tor-expert-bundle.aar" if bootstrapped_location.is_file(): return str(bootstrapped_location) die( "tor-expert-bundle-aar not found. Either enable bootstrap, or provide a path with --with-tor-expert-bundle-aar." ) set_config("TOR_EXPERT_BUNDLE_AAR", tor_expert_bundle_aar) option( "--with-application-services", env="APPLICATION_SERVICES", nargs=1, default=None, help="Path to location of application-services gradle lib.", when=is_android_build, ) @depends( maven_local, "--with-application-services", mozbuild_state_path, bootstrap_path( "application-services", when=depends("--with-application-services", when=is_android_build)( lambda x: not x ), ), when=is_android_build, ) @checking("for application-services") @imports(_from="pathlib", _import="Path") @imports("mozbuild.tbbutils") def application_services(maven_local, value, mozbuild_state_path, _bootstrapped): as_location = None if value: path = Path(value[0]) if path.is_dir(): as_location = path else: die("--with-application-services must point to a directory.") else: bootstrapped_location = Path(mozbuild_state_path) / "application-services/maven" if bootstrapped_location.is_dir(): as_location = bootstrapped_location if not as_location: # application-services is not required for building. die( "application-services not found. Either enable bootstrap, or provide a path with --with-application-services." ) # Symlink a-s in the maven local repository. # Note that this _overwrites_ whatever is already in there. mozbuild.tbbutils.symlink_tree(as_location, maven_local) return as_location option( "--with-nimbus-fml", env="NIMBUS_FML", nargs=1, default=None, help="Path to location of nimbus-fml executable.", when=is_android_build, ) @depends("--with-nimbus-fml", when=is_android_build) @checking("for nimbus-fml") @imports(_from="pathlib", _import="Path") def nimbus_fml(value): if value: path = Path(value[0]) if path.is_file(): return value[0] else: die("--with-nimbus-fml must point to an existing file.") # a-s nimbus-gradle-plugin will download nimbus-fml itself if not provided. return None set_config("NIMBUS_FML", nimbus_fml) python/mozbuild/mozbuild/backend/base.py +27 −0 Changes for python/mozbuild/mozbuild/backend/base.py: 27 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -258,8 +258,35 @@ class BuildBackend(LoggingMixin): os.remove(dst) os.symlink(src, dst) else: self.log( logging.ERROR, "_setup_tor_browser_environment", {}, "Error creating symlink.", ) return if app == "mobile/android": # Set up NoScript extension # We put it in the srcdir... It will be moved to the APK in the gradle build. if noscript_location: noscript_target = ( Path(config.topsrcdir) / "mobile/android/fenix/app/src/main/assets/extensions" / noscript_target_filename ) self.log( logging.INFO, "_setup_tor_browser_environment", { "noscript_location": noscript_location, "noscript_target": str(noscript_target), }, "Creating symlink for NoScript from {noscript_location} to {noscript_target}", ) _infallible_symlink(noscript_location, noscript_target) if app == "browser": tbdir = Path(config.topobjdir) / "dist" / "bin" Loading python/mozbuild/mozbuild/tbbutils.py +35 −1 Changes for python/mozbuild/mozbuild/tbbutils.py: 35 added lines, 1 removed line. Original line number Diff line number Diff line import os import re from pathlib import Path from urllib.request import Request, urlopen def symlink_tree(src_dir, target_dir): """ Recursively mirror the directory tree from `src_dir` into `target_dir` using symbolic links. Equivalent to: `cp -rs src_dir/* target_dir` Notes: - If a file or symlink already exists in the destination, it overwritten. - The symlinks created here use absolute paths i.e. not relocatable. """ src = Path(src_dir) target = Path(target_dir) target.mkdir(parents=True, exist_ok=True) for root, _, files in os.walk(src): target_path = target / Path(root).relative_to(src) target_path.mkdir(parents=True, exist_ok=True) for file in files: src_file = Path(root) / file target_file = target_path / file if target_file.exists() or target_file.is_symlink(): target_file.unlink() os.symlink(src_file, target_file) def list_files_http(url): try: req = Request(url, method="GET") Loading @@ -17,7 +47,9 @@ def list_files_http(url): if href == "../": continue if "tor-expert-bundle" in href: if "tor-expert-bundle-aar" in href: href = f"{href.rstrip('/')}/tor-expert-bundle.aar" elif "tor-expert-bundle" in href: href = f"{href.rstrip('/')}/tor-expert-bundle.tar.gz" links.append(href) Loading @@ -30,6 +62,8 @@ TOR_BROWSER_BUILD_ARTIFACTS = [ "noscript", "fonts", "tor-expert-bundle", "tor-expert-bundle-aar", "application-services", ] # Mapping of artifacts from taskcluster to tor-browser-build. Loading python/mozbuild/mozbuild/test/test_tbbutils.py +91 −1 Changes for python/mozbuild/mozbuild/test/test_tbbutils.py: 91 added lines, 1 removed line. Original line number Diff line number Diff line import os import shutil import tempfile import unittest from pathlib import Path from types import SimpleNamespace from unittest.mock import MagicMock, patch import mozunit from mozbuild.tbbutils import get_artifact_index, get_artifact_path, list_files_http from mozbuild.tbbutils import ( get_artifact_index, get_artifact_path, list_files_http, symlink_tree, ) class TestSymlinkTree(unittest.TestCase): def _create_sample_tree(self, base: Path): (base / "subdir").mkdir() (base / "file1.txt").write_text("content1") (base / "subdir" / "file2.txt").write_text("content2") def setUp(self): self.tmpdir = tempfile.mkdtemp() self.src = Path(self.tmpdir) / "src" self.dst = Path(self.tmpdir) / "dst" self.src.mkdir() self.dst.mkdir() def tearDown(self): shutil.rmtree(self.tmpdir) def test_symlinks_created_correctly(self): self._create_sample_tree(self.src) symlink_tree(self.src, self.dst) self.assertTrue((self.dst / "file1.txt").is_symlink()) self.assertTrue((self.dst / "subdir" / "file2.txt").is_symlink()) self.assertEqual( os.readlink(self.dst / "file1.txt"), str(self.src / "file1.txt"), ) self.assertEqual( os.readlink(self.dst / "subdir" / "file2.txt"), str(self.src / "subdir" / "file2.txt"), ) def test_overwrites_existing_files(self): self._create_sample_tree(self.src) # Create a conflicting file in destination (self.dst / "file1.txt").write_text("old") symlink_tree(self.src, self.dst) self.assertTrue((self.dst / "file1.txt").is_symlink()) self.assertEqual( os.readlink(self.dst / "file1.txt"), str(self.src / "file1.txt"), ) def test_nested_directories_are_mirrored(self): (self.src / "a" / "b" / "c").mkdir(parents=True) (self.src / "a" / "b" / "c" / "deep.txt").write_text("deep content") symlink_tree(self.src, self.dst) deep_link = self.dst / "a" / "b" / "c" / "deep.txt" self.assertTrue(deep_link.is_symlink()) self.assertEqual( os.readlink(deep_link), str(self.src / "a" / "b" / "c" / "deep.txt"), ) def test_idempotence(self): self._create_sample_tree(self.src) symlink_tree(self.src, self.dst) symlink_tree(self.src, self.dst) # Run again self.assertTrue((self.dst / "file1.txt").is_symlink()) self.assertTrue((self.dst / "subdir" / "file2.txt").is_symlink()) def test_symlinks_use_absolute_paths(self): (self.src / "file.txt").write_text("absolute") symlink_tree(self.src, self.dst) link_target = os.readlink(self.dst / "file.txt") self.assertTrue(Path(link_target).is_absolute()) self.assertEqual(Path(link_target), self.src / "file.txt") class TestGetArtifactName(unittest.TestCase): Loading Loading @@ -152,6 +240,7 @@ class TestListFilesHttp(unittest.TestCase): def test_tor_expert_bundle_rewrites(self, mock_urlopen): html = """ <a href="tor-expert-bundle">bundle</a> <a href="tor-expert-bundle-aar">bundle</a> """ mock_resp = MagicMock() mock_resp.status = 200 Loading @@ -163,6 +252,7 @@ class TestListFilesHttp(unittest.TestCase): result, [ "tor-expert-bundle/tor-expert-bundle.tar.gz", "tor-expert-bundle-aar/tor-expert-bundle.aar", ], ) Loading Loading
build/moz.configure/torbrowser-resources.configure +157 −2 Changes for build/moz.configure/torbrowser-resources.configure: 157 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ option( nargs=1, default=None, help="Path to location of tor-expert-bundle directory.", when=is_desktop_build, ) Loading @@ -12,8 +13,11 @@ option( mozbuild_state_path, bootstrap_path( "tor-expert-bundle", when=depends("--with-tor-expert-bundle")(lambda x: not x) & is_desktop_build, when=depends("--with-tor-expert-bundle", when=is_desktop_build)( lambda x: not x ), ), when=is_desktop_build, ) @checking("for tor-expert-bundle") @imports(_from="pathlib", _import="Path") Loading @@ -34,4 +38,155 @@ def tor_expert_bundle(value, mozbuild_state_path, _bootstrapped): return None set_config("TOR_EXPERT_BUNDLE", tor_expert_bundle) set_config("TOR_EXPERT_BUNDLE", tor_expert_bundle, when=is_desktop_build) # Android # ------------------------------------------------- @depends(build_project) def is_android_build(build_project): return build_project == "mobile/android" @imports(_from="pathlib", _import="Path") def maven_local_default(): return str(Path.home() / ".m2/repository") option( "--with-maven-local", nargs=1, default=maven_local_default(), help="Path the maven local directory. Defaults to $HOME/.m2/repository", ) @depends("--with-maven-local") def maven_local(value): if value: return value[0] option( "--with-tor-expert-bundle-aar", env="TOR_EXPERT_BUNDLE_AAR", nargs=1, default=None, help="Path to location of tor-expert-bundle.aar archive.", when=is_android_build, ) @depends( "--with-tor-expert-bundle-aar", mozbuild_state_path, bootstrap_path( "tor-expert-bundle-aar", no_unpack=True, when=depends("--with-tor-expert-bundle-aar", when=is_android_build)( lambda x: not x ), ), when=is_android_build, ) @checking("for tor-expert-bundle.aar") @imports(_from="pathlib", _import="Path") def tor_expert_bundle_aar(value, mozbuild_state_path, _bootstrapped): if value: path = Path(value[0]) if path.suffix.lower() == ".aar": return value[0] else: die("--with-tor-expert-bundle-aar must point to a AAR archive.") bootstrapped_location = Path(mozbuild_state_path) / "tor-expert-bundle.aar" if bootstrapped_location.is_file(): return str(bootstrapped_location) die( "tor-expert-bundle-aar not found. Either enable bootstrap, or provide a path with --with-tor-expert-bundle-aar." ) set_config("TOR_EXPERT_BUNDLE_AAR", tor_expert_bundle_aar) option( "--with-application-services", env="APPLICATION_SERVICES", nargs=1, default=None, help="Path to location of application-services gradle lib.", when=is_android_build, ) @depends( maven_local, "--with-application-services", mozbuild_state_path, bootstrap_path( "application-services", when=depends("--with-application-services", when=is_android_build)( lambda x: not x ), ), when=is_android_build, ) @checking("for application-services") @imports(_from="pathlib", _import="Path") @imports("mozbuild.tbbutils") def application_services(maven_local, value, mozbuild_state_path, _bootstrapped): as_location = None if value: path = Path(value[0]) if path.is_dir(): as_location = path else: die("--with-application-services must point to a directory.") else: bootstrapped_location = Path(mozbuild_state_path) / "application-services/maven" if bootstrapped_location.is_dir(): as_location = bootstrapped_location if not as_location: # application-services is not required for building. die( "application-services not found. Either enable bootstrap, or provide a path with --with-application-services." ) # Symlink a-s in the maven local repository. # Note that this _overwrites_ whatever is already in there. mozbuild.tbbutils.symlink_tree(as_location, maven_local) return as_location option( "--with-nimbus-fml", env="NIMBUS_FML", nargs=1, default=None, help="Path to location of nimbus-fml executable.", when=is_android_build, ) @depends("--with-nimbus-fml", when=is_android_build) @checking("for nimbus-fml") @imports(_from="pathlib", _import="Path") def nimbus_fml(value): if value: path = Path(value[0]) if path.is_file(): return value[0] else: die("--with-nimbus-fml must point to an existing file.") # a-s nimbus-gradle-plugin will download nimbus-fml itself if not provided. return None set_config("NIMBUS_FML", nimbus_fml)
python/mozbuild/mozbuild/backend/base.py +27 −0 Changes for python/mozbuild/mozbuild/backend/base.py: 27 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -258,8 +258,35 @@ class BuildBackend(LoggingMixin): os.remove(dst) os.symlink(src, dst) else: self.log( logging.ERROR, "_setup_tor_browser_environment", {}, "Error creating symlink.", ) return if app == "mobile/android": # Set up NoScript extension # We put it in the srcdir... It will be moved to the APK in the gradle build. if noscript_location: noscript_target = ( Path(config.topsrcdir) / "mobile/android/fenix/app/src/main/assets/extensions" / noscript_target_filename ) self.log( logging.INFO, "_setup_tor_browser_environment", { "noscript_location": noscript_location, "noscript_target": str(noscript_target), }, "Creating symlink for NoScript from {noscript_location} to {noscript_target}", ) _infallible_symlink(noscript_location, noscript_target) if app == "browser": tbdir = Path(config.topobjdir) / "dist" / "bin" Loading
python/mozbuild/mozbuild/tbbutils.py +35 −1 Changes for python/mozbuild/mozbuild/tbbutils.py: 35 added lines, 1 removed line. Original line number Diff line number Diff line import os import re from pathlib import Path from urllib.request import Request, urlopen def symlink_tree(src_dir, target_dir): """ Recursively mirror the directory tree from `src_dir` into `target_dir` using symbolic links. Equivalent to: `cp -rs src_dir/* target_dir` Notes: - If a file or symlink already exists in the destination, it overwritten. - The symlinks created here use absolute paths i.e. not relocatable. """ src = Path(src_dir) target = Path(target_dir) target.mkdir(parents=True, exist_ok=True) for root, _, files in os.walk(src): target_path = target / Path(root).relative_to(src) target_path.mkdir(parents=True, exist_ok=True) for file in files: src_file = Path(root) / file target_file = target_path / file if target_file.exists() or target_file.is_symlink(): target_file.unlink() os.symlink(src_file, target_file) def list_files_http(url): try: req = Request(url, method="GET") Loading @@ -17,7 +47,9 @@ def list_files_http(url): if href == "../": continue if "tor-expert-bundle" in href: if "tor-expert-bundle-aar" in href: href = f"{href.rstrip('/')}/tor-expert-bundle.aar" elif "tor-expert-bundle" in href: href = f"{href.rstrip('/')}/tor-expert-bundle.tar.gz" links.append(href) Loading @@ -30,6 +62,8 @@ TOR_BROWSER_BUILD_ARTIFACTS = [ "noscript", "fonts", "tor-expert-bundle", "tor-expert-bundle-aar", "application-services", ] # Mapping of artifacts from taskcluster to tor-browser-build. Loading
python/mozbuild/mozbuild/test/test_tbbutils.py +91 −1 Changes for python/mozbuild/mozbuild/test/test_tbbutils.py: 91 added lines, 1 removed line. Original line number Diff line number Diff line import os import shutil import tempfile import unittest from pathlib import Path from types import SimpleNamespace from unittest.mock import MagicMock, patch import mozunit from mozbuild.tbbutils import get_artifact_index, get_artifact_path, list_files_http from mozbuild.tbbutils import ( get_artifact_index, get_artifact_path, list_files_http, symlink_tree, ) class TestSymlinkTree(unittest.TestCase): def _create_sample_tree(self, base: Path): (base / "subdir").mkdir() (base / "file1.txt").write_text("content1") (base / "subdir" / "file2.txt").write_text("content2") def setUp(self): self.tmpdir = tempfile.mkdtemp() self.src = Path(self.tmpdir) / "src" self.dst = Path(self.tmpdir) / "dst" self.src.mkdir() self.dst.mkdir() def tearDown(self): shutil.rmtree(self.tmpdir) def test_symlinks_created_correctly(self): self._create_sample_tree(self.src) symlink_tree(self.src, self.dst) self.assertTrue((self.dst / "file1.txt").is_symlink()) self.assertTrue((self.dst / "subdir" / "file2.txt").is_symlink()) self.assertEqual( os.readlink(self.dst / "file1.txt"), str(self.src / "file1.txt"), ) self.assertEqual( os.readlink(self.dst / "subdir" / "file2.txt"), str(self.src / "subdir" / "file2.txt"), ) def test_overwrites_existing_files(self): self._create_sample_tree(self.src) # Create a conflicting file in destination (self.dst / "file1.txt").write_text("old") symlink_tree(self.src, self.dst) self.assertTrue((self.dst / "file1.txt").is_symlink()) self.assertEqual( os.readlink(self.dst / "file1.txt"), str(self.src / "file1.txt"), ) def test_nested_directories_are_mirrored(self): (self.src / "a" / "b" / "c").mkdir(parents=True) (self.src / "a" / "b" / "c" / "deep.txt").write_text("deep content") symlink_tree(self.src, self.dst) deep_link = self.dst / "a" / "b" / "c" / "deep.txt" self.assertTrue(deep_link.is_symlink()) self.assertEqual( os.readlink(deep_link), str(self.src / "a" / "b" / "c" / "deep.txt"), ) def test_idempotence(self): self._create_sample_tree(self.src) symlink_tree(self.src, self.dst) symlink_tree(self.src, self.dst) # Run again self.assertTrue((self.dst / "file1.txt").is_symlink()) self.assertTrue((self.dst / "subdir" / "file2.txt").is_symlink()) def test_symlinks_use_absolute_paths(self): (self.src / "file.txt").write_text("absolute") symlink_tree(self.src, self.dst) link_target = os.readlink(self.dst / "file.txt") self.assertTrue(Path(link_target).is_absolute()) self.assertEqual(Path(link_target), self.src / "file.txt") class TestGetArtifactName(unittest.TestCase): Loading Loading @@ -152,6 +240,7 @@ class TestListFilesHttp(unittest.TestCase): def test_tor_expert_bundle_rewrites(self, mock_urlopen): html = """ <a href="tor-expert-bundle">bundle</a> <a href="tor-expert-bundle-aar">bundle</a> """ mock_resp = MagicMock() mock_resp.status = 200 Loading @@ -163,6 +252,7 @@ class TestListFilesHttp(unittest.TestCase): result, [ "tor-expert-bundle/tor-expert-bundle.tar.gz", "tor-expert-bundle-aar/tor-expert-bundle.aar", ], ) Loading