Clone & patch in same local repo

Do not copy the Firefox source repo before patching. Manage everything through git instead.
This commit is contained in:
daijro 2024-07-30 02:51:52 -05:00
parent f8f34bd3f2
commit dc63ec8d3f
5 changed files with 154 additions and 91 deletions

4
.gitignore vendored
View file

@ -1,4 +1,3 @@
/firefox-*
/camoufox-* /camoufox-*
/mozilla-unified /mozilla-unified
/extra-docs /extra-docs
@ -8,4 +7,5 @@ dist/
/bundle/fonts/extra /bundle/fonts/extra
launch launch
launch.exe launch.exe
*.old *.old
__pycache__/

View file

@ -1,14 +1,13 @@
include upstream.sh include upstream.sh
export export
ff_source_dir := firefox-$(version) cf_source_dir := camoufox-$(version)-$(release)
lw_source_dir := camoufox-$(version)-$(release)
debs := python3 python3-dev python3-pip p7zip-full golang-go msitools wget debs := python3 python3-dev python3-pip p7zip-full golang-go msitools wget
rpms := python3 python3-devel p7zip golang msitools wget rpms := python3 python3-devel p7zip golang msitools wget
pacman := python python-pip p7zip go msitools wget pacman := python python-pip p7zip go msitools wget
.PHONY: help fetch clean distclean build package build-launcher check-arch edits run bootstrap mozbootstrap dir package-common package-linux package-macos package-windows .PHONY: help fetch clean distclean build package build-launcher check-arch revert edits run bootstrap mozbootstrap dir package-common package-linux package-macos package-windows
help: help:
@echo "Available targets:" @echo "Available targets:"
@ -16,6 +15,7 @@ help:
@echo " bootstrap - Set up build environment" @echo " bootstrap - Set up build environment"
@echo " mozbootstrap - Sets up mach" @echo " mozbootstrap - Sets up mach"
@echo " dir - Prepare Camoufox source directory" @echo " dir - Prepare Camoufox source directory"
@echo " revert - Kill all working changes"
@echo " edits - Camoufox developer UI" @echo " edits - Camoufox developer UI"
@echo " build-launcher - Build launcher" @echo " build-launcher - Build launcher"
@echo " clean - Remove build artifacts" @echo " clean - Remove build artifacts"
@ -27,35 +27,40 @@ help:
@echo " run - Run Camoufox" @echo " run - Run Camoufox"
fetch: fetch:
git clone --depth 1 --branch $(BASE_BRANCH) --single-branch $(REMOTE_URL) $(ff_source_dir) git clone --depth 1 --branch $(BASE_BRANCH) --single-branch $(REMOTE_URL) $(cf_source_dir)
cd $(ff_source_dir) && git fetch --depth 1 origin $(BASE_REVISION) && git checkout $(BASE_REVISION) cd $(cf_source_dir) && git fetch --depth 1 origin $(BASE_REVISION)
make revert
revert:
cd $(cf_source_dir) && git reset --hard $(BASE_REVISION)
python3 scripts/init-patch.py $(version) $(release)
dir: dir:
@if [ ! -d $(ff_source_dir) ]; then \ @if [ ! -d $(cf_source_dir) ]; then \
make fetch; \ make fetch; \
fi fi
rm -rf $(lw_source_dir) make clean
cp -r $(ff_source_dir) $(lw_source_dir)
python3 scripts/patch.py $(version) $(release) python3 scripts/patch.py $(version) $(release)
mozbootstrap: mozbootstrap:
cd $(ff_source_dir) && MOZBUILD_STATE_PATH=$$HOME/.mozbuild ./mach --no-interactive bootstrap --application-choice=browser cd $(cf_source_dir) && MOZBUILD_STATE_PATH=$$HOME/.mozbuild ./mach --no-interactive bootstrap --application-choice=browser
bootstrap: dir bootstrap: dir
(sudo apt-get -y install $(debs) || sudo dnf -y install $(rpms) || sudo pacman -Sy $(pacman)) (sudo apt-get -y install $(debs) || sudo dnf -y install $(rpms) || sudo pacman -Sy $(pacman))
make mozbootstrap make mozbootstrap
clean: clean:
rm -rf $(lw_source_dir) cd $(cf_source_dir) && git clean -fdx && ./mach clobber
make revert
distclean: clean distclean: clean
rm -rf $(ff_source_dir) rm -rf $(cf_source_dir)
build: build:
@if [ ! -d $(lw_source_dir) ]; then \ @if [ ! -d $(cf_source_dir) ]; then \
make dir; \ make dir; \
fi fi
cd $(lw_source_dir) && ./mach build cd $(cf_source_dir) && ./mach build
edits: edits:
python ./scripts/developer.py python ./scripts/developer.py
@ -70,8 +75,8 @@ build-launcher: check-arch
cd launcher && ./build.sh $(arch) $(os) cd launcher && ./build.sh $(arch) $(os)
package-common: check-arch package-common: check-arch
cd $(lw_source_dir) && cat browser/locales/shipped-locales | xargs ./mach package-multi-locale --locales cd $(cf_source_dir) && cat browser/locales/shipped-locales | xargs ./mach package-multi-locale --locales
cp -v $(lw_source_dir)/obj-*/dist/camoufox-$(version)-$(release).*.* . cp -v $(cf_source_dir)/obj-*/dist/camoufox-$(version)-$(release).*.* .
package-linux: package-common package-linux: package-common
make build-launcher arch=$(arch) os=linux; make build-launcher arch=$(arch) os=linux;
@ -106,4 +111,4 @@ package-windows: package-common
--fonts macos linux --fonts macos linux
run: run:
cd $(lw_source_dir) && rm -rf ~/.camoufox && ./mach run cd $(cf_source_dir) && rm -rf ~/.camoufox && ./mach run

View file

@ -1,37 +1,43 @@
#!/usr/bin/env python3
"""
GUI for managing Camoufox patches.
"""
import os import os
import contextlib
import easygui import easygui
from patch import list_files, patch, run from patch import list_files, patch, run
# Cd to the camoufox-* folder (this is located ..)
os.chdir(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) def into_camoufox_dir():
folders = os.listdir('.') """Find and cd to the camoufox-* folder (this is located ..)"""
for folder in folders: os.chdir(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
if os.path.isdir(folder) and folder.startswith('camoufox-'): folders = os.listdir('.')
os.chdir(folder) for folder in folders:
break if os.path.isdir(folder) and folder.startswith('camoufox-'):
else: os.chdir(folder)
raise Exception('No camoufox-* folder found') break
else:
raise FileNotFoundError('No camoufox-* folder found')
""" @contextlib.contextmanager
GUI Choicebox with the following options: def temp_cd(path):
- Reset: # Temporarily change to a different working directory
`git checkout -- .` _old_cwd = os.getcwd()
then patch *.bootstrap (required) os.chdir(os.path.abspath(path))
- Patch all BUT:
Checklist of *.patch files in ../patches to exclude. The rest gets patched. try:
- Find broken: yield
Resets, runs patches, then finds broken patches. finally:
If all show good error code, show at the top of the message box "All patches applied successfully" os.chdir(_old_cwd)
If any show bad error code, show at the top of the message box "Some patches failed to apply", then the rej output
"""
def reset_camoufox(): def reset_camoufox():
run('git checkout -- .') with temp_cd('..'):
for patch_file in list_files('../patches', suffix='*.bootstrap'): run('make clean')
patch(patch_file)
def run_patches(reverse=False): def run_patches(reverse=False):
@ -58,49 +64,72 @@ choices = [
"Write workspace to patch", "Write workspace to patch",
] ]
choice = easygui.choicebox("Select an option:", "Camoufox Patcher", choices) """
GUI Choicebox with the following options:
- Reset:
`make clean`
- Patch all BUT:
Checklist of *.patch files in ../patches to exclude. The rest gets patched.
- Find broken:
Resets, runs patches, then finds broken patches.
If all show good error code, show at the top of the message box "All patches applied successfully"
If any show bad error code, show at the top of the message box "Some patches failed to apply", then the rej output
"""
if choice == "Reset workspace":
reset_camoufox()
easygui.msgbox("Reset completed and bootstrap patches applied.", "Reset Complete")
elif choice == "Select patches": def handle_choice(choice):
run_patches(reverse=False) match choice:
easygui.msgbox("Patching completed.", "Patching Complete") case "Reset workspace":
reset_camoufox()
easygui.msgbox("Reset completed and bootstrap patches applied.", "Reset Complete")
elif choice == "Reverse patches": case "Select patches":
run_patches(reverse=True) run_patches(reverse=False)
easygui.msgbox("Unpatching completed.", "Unpatching Complete") easygui.msgbox("Patching completed.", "Patching Complete")
elif choice == "Find broken patches": case "Reverse patches":
reset_camoufox() run_patches(reverse=True)
easygui.msgbox("Unpatching completed.", "Unpatching Complete")
broken_patches = [] case "Find broken patches":
for patch_file in list_files('../patches', suffix='*.patch'): reset_camoufox()
cmd = rf'patch -p1 -i "{patch_file}" | tee /dev/stderr | sed -r --quiet \'s/^.*saving rejects to file (.*\.rej)$/\\1/p\''
result = os.popen(cmd).read().strip()
print(result)
if result:
broken_patches.append((patch_file, result))
if not broken_patches: broken_patches = []
easygui.msgbox("All patches applied successfully", "Patching Result") for patch_file in list_files('../patches', suffix='*.patch'):
else: cmd = rf'patch -p1 -i "{patch_file}" | tee /dev/stderr | sed -r --quiet \'s/^.*saving rejects to file (.*\.rej)$/\\1/p\''
message = "Some patches failed to apply:\n\n" result = os.popen(cmd).read().strip()
for patch_file, rejects in broken_patches: print(result)
message += f"Patch: {patch_file}\nRejects: {rejects}\n\n" if result:
easygui.textbox("Patching Result", "Failed Patches", message) broken_patches.append((patch_file, result))
elif choice == "See current workspace": if not broken_patches:
result = os.popen('git diff').read() easygui.msgbox("All patches applied successfully", "Patching Result")
easygui.textbox("Diff", "Diff", result) else:
message = "Some patches failed to apply:\n\n"
for patch_file, rejects in broken_patches:
message += f"Patch: {patch_file}\nRejects: {rejects}\n\n"
easygui.textbox("Patching Result", "Failed Patches", message)
elif choice == "Write workspace to patch": case "See current workspace":
# Open a file dialog to select a file to write the diff to result = os.popen('git diff').read()
file_path = easygui.filesavebox( easygui.textbox("Diff", "Diff", result)
"Select a file to write the diff to", "Write Diff", filetypes="*.patch"
) case "Write workspace to patch":
if not file_path: # Open a file dialog to select a file to write the diff to
exit() file_path = easygui.filesavebox(
run(f'git diff > {file_path}') "Select a file to write the diff to", "Write Diff", filetypes="*.patch"
easygui.msgbox("Diff written to file", "Diff Written") )
if not file_path:
exit()
run(f'git diff > {file_path}')
easygui.msgbox("Diff written to file", "Diff Written")
case _:
print('No choice selected')
if __name__ == "__main__":
into_camoufox_dir()
choice = easygui.choicebox("Select an option:", "Camoufox Dev Tools", choices)
handle_choice(choice)

25
scripts/init-patch.py Normal file
View file

@ -0,0 +1,25 @@
#!/usr/bin/env python3
"""
Simple script to apply *.bootstrap patches
This was separated from the main patch script because its indended to run on docker build.
Run:
python3 scripts/init-patch.py <version> <release>
"""
from patch import list_files, patch, enter_srcdir, leave_srcdir
def apply_bootstrap_patches():
enter_srcdir()
# Apply bootstraps first
for patch_file in list_files('../patches', suffix='*.bootstrap'):
patch(patch_file)
leave_srcdir()
if __name__ == "__main__":
apply_bootstrap_patches()

View file

@ -1,7 +1,12 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
The script that patches the firefox source into the camoufox source. The script that patches the Firefox source into the Camoufox source.
Based on LibreWolf's patch script:
https://gitlab.com/librewolf-community/browser/source/-/blob/main/scripts/librewolf-patches.py
Run:
python3 scripts/init-patch.py <version> <release>
""" """
import fnmatch import fnmatch
@ -69,6 +74,7 @@ def patch(patchfile, reverse=False):
def enter_srcdir(_dir=None): def enter_srcdir(_dir=None):
if _dir is None: if _dir is None:
version, release = extract_args()
dir = f"camoufox-{version}-{release}" dir = f"camoufox-{version}-{release}"
else: else:
dir = _dir dir = _dir
@ -121,9 +127,6 @@ def camoufox_patches():
# Copy the search-config.json file # Copy the search-config.json file
run('cp -v ../assets/search-config.json services/settings/dumps/main/search-config.json') run('cp -v ../assets/search-config.json services/settings/dumps/main/search-config.json')
# Apply bootstraps first
for patch_file in list_files('../patches', suffix='*.bootstrap'):
patch(patch_file)
# Then apply all other patches # Then apply all other patches
for patch_file in list_files('../patches'): for patch_file in list_files('../patches'):
patch(patch_file) patch(patch_file)
@ -210,10 +213,6 @@ def _update_mozconfig():
with open(target_mozconfig, 'r') as f: with open(target_mozconfig, 'r') as f:
content += f.read() content += f.read()
# Add macOS-specific hack
# if target == "macos" and arch == "x86_64":
# content += 'export NASM="$MOZBUILD/nasm/nasm"\n'
# Calculate new hash # Calculate new hash
new_hash = hashlib.sha256(content.encode()).hexdigest() new_hash = hashlib.sha256(content.encode()).hexdigest()
@ -238,12 +237,17 @@ def _update_mozconfig():
Preparation Preparation
""" """
if __name__ == "__main__":
# Extract args def extract_args():
if len(args) != 2: if len(args) != 2:
sys.stderr.write('error: please specify version and release of camoufox source') sys.stderr.write('error: please specify version and release of camoufox source')
sys.exit(1) sys.exit(1)
version, release = args[0], args[1] return args[0], args[1]
if __name__ == "__main__":
# Extract args
version, release = extract_args()
# Get moz_target if passed to BUILD_TARGET environment variable # Get moz_target if passed to BUILD_TARGET environment variable
AVAILABLE_TARGETS = ["linux", "windows", "macos"] AVAILABLE_TARGETS = ["linux", "windows", "macos"]