Many changes, bump to v128.0.3-1

- Heavy changes to Makefile. Now uses aria2c to download the Firefox release tarball
- New features in developer UI to make patch editing much easier
- Modified Playwright's Juggler patches to run on Firefox release v128.0.3
- Bump Playwright Juggler module to June 2th patches
- Fix viewport-hijacker and xmas-modified patches for new Firefox release
This commit is contained in:
daijro 2024-08-01 04:41:03 -05:00
parent 7ecdd14d4a
commit bd12f3c46e
19 changed files with 676 additions and 21927 deletions

2
.gitignore vendored
View file

@ -1,4 +1,5 @@
/camoufox-*
/firefox-*
/mozilla-unified
/extra-docs
/.vscode
@ -10,3 +11,4 @@ launch.exe
*.old
__pycache__/
*.pyc
wget-log

View file

@ -7,15 +7,15 @@ COPY . /app
# Install necessary packages
RUN apt-get update && apt-get install -y \
# Makefile utils
build-essential make git msitools wget unzip \
# Mach build tools
build-essential make msitools wget unzip \
# Python
python3 python3-dev python3-pip \
# Camoufox build system utils
p7zip-full golang-go
# Camoufox build system tools
git p7zip-full golang-go aria2c
# Fetch Firefox & apply initial patches
RUN make fetch && \
RUN make setup-minimal && \
make mozbootstrap && \
mkdir /app/dist

View file

@ -2,19 +2,21 @@ include upstream.sh
export
cf_source_dir := camoufox-$(version)-$(release)
ff_source_tarball := firefox-$(version).source.tar.xz
debs := python3 python3-dev python3-pip p7zip-full golang-go msitools wget
rpms := python3 python3-devel p7zip golang msitools wget
pacman := python python-pip p7zip go msitools wget
debs := python3 python3-dev python3-pip p7zip-full golang-go msitools wget aria2c
rpms := python3 python3-devel p7zip golang msitools wget aria2c
pacman := python python-pip p7zip go msitools wget aria2c
.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
.PHONY: help fetch setup setup-minimal clean distclean build package build-launcher check-arch revert edits run bootstrap mozbootstrap dir package-common package-linux package-macos package-windows
help:
@echo "Available targets:"
@echo " fetch - Clone Firefox source code"
@echo " fetch - Fetch the Firefox source code"
@echo " setup - Setup Camoufox & local git repo for development"
@echo " bootstrap - Set up build environment"
@echo " mozbootstrap - Sets up mach"
@echo " dir - Prepare Camoufox source directory"
@echo " dir - Prepare Camoufox source directory with BUILD_TARGET"
@echo " revert - Kill all working changes"
@echo " edits - Camoufox developer UI"
@echo " build-launcher - Build launcher"
@ -27,17 +29,35 @@ help:
@echo " run - Run Camoufox"
fetch:
git clone --depth 1 --branch $(BASE_BRANCH) --single-branch $(REMOTE_URL) $(cf_source_dir)
cd $(cf_source_dir) && git fetch --depth 1 origin $(BASE_REVISION)
make revert
aria2c -x16 -s16 -k1M -o $(ff_source_tarball) "https://archive.mozilla.org/pub/firefox/releases/$(version)/source/firefox-$(version).source.tar.xz"; \
setup-minimal:
# Note: Only docker containers are intended to run this directly.
# Run this before `make dir` or `make build` to avoid setting up a local git repo.
if [ ! -f $(ff_source_tarball) ]; then \
make fetch; \
fi
# Create new cf_source_dir
rm -rf $(cf_source_dir)
mkdir -p $(cf_source_dir)
tar -xJf $(ff_source_tarball) -C $(cf_source_dir) --strip-components=1
# Copy settings & additions
cd $(cf_source_dir) && bash ../scripts/copy-additions.sh $(version) $(release)
setup: setup-minimal
# Initialize local git repo for development
cd $(cf_source_dir) && \
git init -b main && \
git add -f -A && \
git commit -m "Initial commit" && \
git tag -a unpatched -m "Initial commit"
revert:
cd $(cf_source_dir) && git reset --hard $(BASE_REVISION)
python3 scripts/init-patch.py $(version) $(release)
cd $(cf_source_dir) && git reset --hard unpatched
dir:
@if [ ! -d $(cf_source_dir) ]; then \
make fetch; \
make setup; \
fi
make clean
python3 scripts/patch.py $(version) $(release)
@ -61,7 +81,7 @@ clean:
make revert
distclean:
rm -rf $(cf_source_dir)
rm -rf $(cf_source_dir) $(ff_source_tarball)
build:
@if [ ! -f $(cf_source_dir)/_READY ]; then \

View file

@ -217,7 +217,7 @@ Miscellaneous (WebGl spoofing, battery status, etc)
#### Playwright support
- Added Playwright's Juggler patches
- A more updated version of Playwright's Juggler for the latest Firefox, maintained by me
- Various config patches to evade bot detection
#### Debloat/Optimizations
@ -386,9 +386,7 @@ Build artifacts will now appear written under the `dist/` folder.
---
## Development Notes
### How to make a patch
## Development Tools
This repo comes with a developer UI under scripts/developer.py:
@ -396,26 +394,20 @@ This repo comes with a developer UI under scripts/developer.py:
make edits
```
Patches can be added, removed, and new patches can be added through here.
Patches can be edited, created, removed, and managed through here.
<img src="https://i.imgur.com/cLEn2Yr.png">
<img src="https://i.imgur.com/BYAN5J0.png">
To use, select "Reset workspace", make changes in the camoufox-\*/ folder, then select "Write workspace to patch".
### How to make a patch
1. In the developer UI, click **Reset workspace**.
2. Make changes in the `camoufox-*/` folder as needed. You can test your changes with `make build` and `make run`.
3. After you're done making changes, click **Write workspace to patch** and save the patch file.
### How to work on an existing patch
1. In the developer UI, reset your workspace.
2. Then, click "Select patches", and select all **but** the one you want to edit.
3. Create a checkpoint. This will commit the current workspace to the local repo:
```bash
make checkpoint
```
4. In the developer UI, click "Select patches", and _apply_ the patch you would like to edit.
Make your changes. Test builds can be made with `make build` and `make run`.
5. After you're done editing, hit "Write workspace to patch", and overwrite the existing patch.
1. In the developer UI, click **Edit a patch**.
2. Select the patch you'd like to edit. Your workspace will be reset to the state of the selected patch.
3. After you're done making changes, hit **Write workspace to patch** and overwrite the existing patch file.
---

View file

@ -368,7 +368,7 @@ class PageTarget {
onLocationChange: (aWebProgress, aRequest, aLocation) => this._onNavigated(aLocation),
};
this._eventListeners = [
helper.addObserver(this._updateModalDialogs.bind(this), 'tabmodal-dialog-loaded'),
helper.addObserver(this._updateModalDialogs.bind(this), 'common-dialog-loaded'),
helper.addProgressListener(tab.linkedBrowser, navigationListener, Ci.nsIWebProgress.NOTIFY_LOCATION),
helper.addEventListener(this._linkedBrowser, 'DOMModalDialogClosed', event => this._updateModalDialogs()),
helper.addEventListener(this._linkedBrowser, 'WillChangeBrowserRemoteness', event => this._willChangeBrowserRemoteness()),
@ -499,7 +499,7 @@ class PageTarget {
}
_updateModalDialogs() {
const prompts = new Set(this._linkedBrowser.tabModalPromptBox ? this._linkedBrowser.tabModalPromptBox.listPrompts() : []);
const prompts = new Set(this._linkedBrowser.tabDialogBox.getContentDialogManager().dialogs.map(dialog => dialog.frameContentWindow.Dialog));
for (const dialog of this._dialogs.values()) {
if (!prompts.has(dialog.prompt())) {
this._dialogs.delete(dialog.id());

View file

@ -8,6 +8,8 @@ const helper = new Helper();
let sameProcessInstanceNumber = 0;
const topBrowingContextToAgents = new Map();
class JugglerFrameChild extends JSWindowActorChild {
constructor() {
super();
@ -16,46 +18,66 @@ class JugglerFrameChild extends JSWindowActorChild {
}
handleEvent(aEvent) {
if (this._agents && aEvent.type === 'DOMWillOpenModalDialog') {
this._agents.channel.pause();
const agents = this._agents();
if (!agents)
return;
if (aEvent.type === 'DOMWillOpenModalDialog') {
agents.channel.pause();
return;
}
if (this._agents && aEvent.type === 'DOMModalDialogClosed') {
this._agents.channel.resumeSoon();
if (aEvent.type === 'DOMModalDialogClosed') {
agents.channel.resumeSoon();
return;
}
if (this._agents && aEvent.target === this.document)
this._agents.pageAgent.onWindowEvent(aEvent);
if (this._agents && aEvent.target === this.document)
this._agents.frameTree.onWindowEvent(aEvent);
if (aEvent.target === this.document) {
agents.pageAgent.onWindowEvent(aEvent);
agents.frameTree.onWindowEvent(aEvent);
}
}
_agents() {
return topBrowingContextToAgents.get(this.browsingContext.top);
}
actorCreated() {
this.actorName = `content::${this.browsingContext.browserId}/${this.browsingContext.id}/${++sameProcessInstanceNumber}`;
this._eventListeners.push(helper.addEventListener(this.contentWindow, 'load', event => {
this._agents?.pageAgent.onWindowEvent(event);
this._agents()?.pageAgent.onWindowEvent(event);
}));
if (this.document.documentURI.startsWith('moz-extension://'))
return;
this._agents = initialize(this.browsingContext, this.docShell, this);
// Child frame events will be forwarded to related top-level agents.
if (this.browsingContext.parent)
return;
let agents = topBrowingContextToAgents.get(this.browsingContext);
if (!agents) {
agents = initialize(this.browsingContext, this.docShell);
topBrowingContextToAgents.set(this.browsingContext, agents);
}
_dispose() {
helper.removeListeners(this._eventListeners);
// We do not cleanup since agents are shared for all frames in the process.
// TODO: restore the cleanup.
// Reset transport so that all messages will be pending and will not throw any errors.
// this._channel.resetTransport();
// this._agents.pageAgent.dispose();
// this._agents.frameTree.dispose();
// this._agents = undefined;
agents.channel.bindToActor(this);
agents.actor = this;
}
didDestroy() {
this._dispose();
helper.removeListeners(this._eventListeners);
if (this.browsingContext.parent)
return;
const agents = topBrowingContextToAgents.get(this.browsingContext);
// The agents are already re-bound to a new actor.
if (agents.actor !== this)
return;
topBrowingContextToAgents.delete(this.browsingContext);
agents.channel.resetTransport();
agents.pageAgent.dispose();
agents.frameTree.dispose();
}
receiveMessage() { }

View file

@ -370,7 +370,12 @@ class PageAgent {
const unsafeObject = frame.unsafeObject(objectId);
if (!unsafeObject)
throw new Error('Object is not input!');
const nsFiles = await Promise.all(files.map(filePath => File.createFromFileName(filePath)));
let nsFiles;
if (unsafeObject.webkitdirectory) {
nsFiles = await new Directory(files[0]).getFiles(true);
} else {
nsFiles = await Promise.all(files.map(filePath => File.createFromFileName(filePath)));
}
unsafeObject.mozSetFileArray(nsFiles);
const events = [
new (frame.domWindow().Event)('input', { bubbles: true, cancelable: true, composed: true }),

View file

@ -7,24 +7,10 @@ const {FrameTree} = ChromeUtils.import('chrome://juggler/content/content/FrameTr
const {SimpleChannel} = ChromeUtils.import('chrome://juggler/content/SimpleChannel.js');
const {PageAgent} = ChromeUtils.import('chrome://juggler/content/content/PageAgent.js');
const browsingContextToAgents = new Map();
const helper = new Helper();
function initialize(browsingContext, docShell, actor) {
if (browsingContext.parent) {
// For child frames, return agents from the main frame.
return browsingContextToAgents.get(browsingContext.top);
}
let data = browsingContextToAgents.get(browsingContext);
if (data) {
// Rebind from one main frame actor to another one.
data.channel.bindToActor(actor);
return data;
}
data = { channel: undefined, pageAgent: undefined, frameTree: undefined, failedToOverrideTimezone: false };
browsingContextToAgents.set(browsingContext, data);
function initialize(browsingContext, docShell) {
const data = { channel: undefined, pageAgent: undefined, frameTree: undefined, failedToOverrideTimezone: false };
const applySetting = {
geolocation: (geolocation) => {
@ -84,7 +70,6 @@ function initialize(browsingContext, docShell, actor) {
data.frameTree.addBinding(worldName, name, script);
data.frameTree.setInitScripts([...contextCrossProcessCookie.initScripts, ...pageCrossProcessCookie.initScripts]);
data.channel = new SimpleChannel('', 'process-' + Services.appinfo.processID);
data.channel.bindToActor(actor);
data.pageAgent = new PageAgent(data.channel, data.frameTree);
docShell.fileInputInterceptionEnabled = !!pageCrossProcessCookie.interceptFileChooserDialog;

File diff suppressed because one or more lines are too long

View file

@ -1,7 +1,7 @@
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
diff --git a/browser/base/content/browser-init.js b/browser/base/content/browser-init.js
index cc62392ab0..0c68a0e991 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
--- a/browser/base/content/browser-init.js
+++ b/browser/base/content/browser-init.js
@@ -1568,7 +1568,7 @@ var gBrowserInit = {
updateBookmarkToolbarVisibility();

View file

@ -1,21 +1,21 @@
diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in
index a638dbe8e2..f0d4310cfa 100644
index bb0f71dd60..3ad3d84b82 100644
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -253,6 +253,11 @@
@RESPATH@/browser/defaults/settings/main
@RESPATH@/browser/defaults/settings/security-state
@@ -244,6 +244,11 @@
#endif
#endif
+; Camoufox specific files
+@RESPATH@/defaults/pref/local-settings.js
+@RESPATH@/distribution/policies.json
+@RESPATH@/camoufox.cfg
+
; Warning: changing the path to channel-prefs.js can cause bugs (Bug 756325)
; Technically this is an app pref file, but we are keeping it in the original
; gre location for now.
; [Default Preferences]
; All the pref files must be part of base to prevent migration bugs
@RESPATH@/browser/@PREF_DIR@/firefox.js
diff --git a/lw/moz.build b/lw/moz.build
index e69de29..8589aac 100644
index e69de29bb2..208184547e 100644
--- a/lw/moz.build
+++ b/lw/moz.build
@@ -0,0 +1,13 @@
@ -33,10 +33,10 @@ index e69de29..8589aac 100644
+ "local-settings.js",
+]
diff --git a/moz.build b/moz.build
index 5af3642165..01f5a7e45b 100644
index 9db27fd056..e1ec1dc872 100644
--- a/moz.build
+++ b/moz.build
@@ -218,3 +218,5 @@ SPHINX_TREES["mots"] = "docs/mots"
@@ -220,3 +220,5 @@ SPHINX_TREES["mots"] = "docs/mots"
SPHINX_TREES["update-infrastructure"] = "docs/update-infrastructure"
include("build/templates.mozbuild")

View file

@ -15,10 +15,7 @@ import sys
major, minor = sys.version_info[:2]
if (major < 3) or (major == 3 and minor < 8):
print(
"Bootstrap currently only runs on Python 3.8+."
"Please try re-running with python3.8+."
)
print("Bootstrap currently only runs on Python 3.8+." "Please try re-running with python3.8+.")
sys.exit(1)
import ctypes
@ -147,9 +144,7 @@ def hg_clone_firefox(hg: Path, dest: Path, head_repo, head_rev):
[str(hg), "pull", "https://hg.mozilla.org/mozilla-unified"], cwd=str(dest)
)
if not res and head_repo:
res = subprocess.call(
[str(hg), "pull", head_repo, "-r", head_rev], cwd=str(dest)
)
res = subprocess.call([str(hg), "pull", head_repo, "-r", head_rev], cwd=str(dest))
print("")
if res:
print(CLONE_MERCURIAL_PULL_FAIL % dest)
@ -159,10 +154,7 @@ def hg_clone_firefox(hg: Path, dest: Path, head_repo, head_rev):
print(f'updating to "{head_rev}" - the development head of Gecko and Firefox')
res = subprocess.call([str(hg), "update", "-r", head_rev], cwd=str(dest))
if res:
print(
f"error updating; you will need to `cd {dest} && hg update -r central` "
"manually"
)
print(f"error updating; you will need to `cd {dest} && hg update -r central` " "manually")
return dest
@ -182,9 +174,7 @@ def git_clone_firefox(git: Path, dest: Path, watchman: Path, head_repo, head_rev
# tiny bootstrapping script.
tempdir = Path(tempfile.mkdtemp())
with open(tempdir / "download.py", "wb") as fh:
shutil.copyfileobj(
urlopen(f"{cinnabar_url}/raw/master/download.py"), fh
)
shutil.copyfileobj(urlopen(f"{cinnabar_url}/raw/master/download.py"), fh)
subprocess.check_call(
[sys.executable, str(tempdir / "download.py")],
@ -213,12 +203,8 @@ def git_clone_firefox(git: Path, dest: Path, watchman: Path, head_repo, head_rev
],
env=env,
)
subprocess.check_call(
[str(git), "config", "fetch.prune", "true"], cwd=str(dest), env=env
)
subprocess.check_call(
[str(git), "config", "pull.ff", "only"], cwd=str(dest), env=env
)
subprocess.check_call([str(git), "config", "fetch.prune", "true"], cwd=str(dest), env=env)
subprocess.check_call([str(git), "config", "pull.ff", "only"], cwd=str(dest), env=env)
if head_repo:
subprocess.check_call(
@ -278,9 +264,7 @@ def add_microsoft_defender_antivirus_exclusions(dest, no_system_changes):
return
def print_attempt_exclusion(path):
print(
f"Attempting to add exclusion path to Microsoft Defender Antivirus for: {path}"
)
print(f"Attempting to add exclusion path to Microsoft Defender Antivirus for: {path}")
powershell_exe = str(powershell_exe)
paths = []

54
scripts/copy-additions.sh Normal file
View file

@ -0,0 +1,54 @@
#!/bin/bash
# Simple bash script that copies the additions from the repository into the source directory
# Must be ran from within the source directory
# Check if correct number of arguments are provided
if [ "$#" -ne 2 ]; then
echo "Usage: $0 <version> <release>"
exit 1
fi
# Assign command-line arguments to variables
version="$1"
release="$2"
# Function to run commands and exit on failure
run() {
echo "$ $1"
eval "$1"
if [ $? -ne 0 ]; then
echo "Command failed: $1"
exit 1
fi
}
# Copy the search-config.json file
run 'cp -v ../assets/search-config.json services/settings/dumps/main/search-config.json'
# vs_pack.py issue... should be temporary
run 'cp -v ../patches/librewolf/pack_vs.py build/vs/'
# Apply most recent `settings` repository files
run 'mkdir -p lw'
pushd lw > /dev/null
run 'cp -v ../../settings/camoufox.cfg .'
run 'cp -v ../../settings/distribution/policies.json .'
run 'cp -v ../../settings/defaults/pref/local-settings.js .'
run 'cp -v ../../settings/chrome.css .'
run 'touch moz.build'
popd > /dev/null
# Copy ALL new files/folders from ../additions to .
run 'cp -r ../additions/* .'
# Provide a script that fetches and bootstraps Nightly and some mozconfigs
run 'cp -v ../scripts/mozfetch.sh lw/'
# Override the firefox version
for file in "browser/config/version.txt" "browser/config/version_display.txt"; do
echo "${version}-${release}" > "$file"
done
# Generate locales
run "bash ../scripts/generate-locales.sh"

View file

@ -4,11 +4,12 @@
GUI for managing Camoufox patches.
"""
import os
import contextlib
import os
import re
import easygui
from patch import list_files, patch, run
from patch import list_patches, patch, run
def into_camoufox_dir():
@ -41,7 +42,7 @@ def reset_camoufox():
def run_patches(reverse=False):
patch_files = list(list_files('../patches', suffix='*.patch'))
patch_files = list_patches()
if reverse:
title = "Unpatch files"
else:
@ -54,16 +55,116 @@ def run_patches(reverse=False):
patch(patch_file, reverse=reverse)
def open_patch_workspace(selected_patch, stop_at_patch=False):
"""
Resets a workspace for editing a patch.
Process:
1. Resets Camoufox
2. Patches all except the selected patch
3. Sets checkpoint
4. Reruns the selected patch, but reads rejects similar to "Find broken patches"
"""
# Prepare UI
patch_files = list_patches()
# Reset workspace
reset_camoufox()
skipped_patches = []
applied_patches = []
# Patch all except the selected patch
for patch_file in patch_files:
if patch_file == selected_patch:
if stop_at_patch:
break
continue
if is_broken(patch_file):
print(f'Skipping broken patch: {patch_file}')
skipped_patches.append(patch_file)
continue
patch(patch_file, silent=True)
applied_patches.append(patch_file)
# Set checkpoint
if applied_patches:
with temp_cd('..'):
run('make checkpoint')
# Set message for patch result
patch_broken = is_broken(selected_patch)
if patch_broken:
message = "Broken patch has been applied to the workspace.\n\nPLEASE FIX THE FOLLOWING:\n"
else:
message = "Successfully applied patch to the workspace.\n"
# Run the selected patch
patch_result = os.popen(f'patch -p1 -i "{selected_patch}"').read()
# Find any line containing a file .rej
if patch_broken:
for line in patch_result.splitlines():
if file := re.search(r'[^\s]+\.rej', line):
message += f'> {file[0]}' + '\n'
def msg_format_paths(file_list):
message = ''
for patch_file in file_list:
message += '> ' + patch_file[len('../patches/') :] + '\n'
return message
# Show which patches were applied if not all patches were allowed
if stop_at_patch and applied_patches:
message += f'\n{"-" * 22} Applied patches {"-" * 22}\n'
message += msg_format_paths(applied_patches)
if skipped_patches:
message += f'\n{"-" * 17} Skipped patches (broken!) {"-" * 17}\n'
message += msg_format_paths(skipped_patches)
message += f'\n{"-" * 24} Full output {"-" * 24}\n{patch_result}'
easygui.textbox("Patch Result", "Patch Result", message)
def check_patch(patch_file):
"""
Checks if the patch can be applied or can be reversed
Returns (can_apply, can_reverse, is_broken)
"""
can_apply = not bool(
os.system(f'patch -p1 --dry-run --force -i "{patch_file}" > /dev/null 2>&1')
)
can_reverse = not bool(
os.system(f'patch -p1 -R --dry-run --force -i "{patch_file}" > /dev/null 2>&1')
)
return can_apply, can_reverse, not (can_apply or can_reverse)
def is_broken(patch_file):
_, _, is_broken = check_patch(patch_file)
return is_broken
def get_rejects(patch_file):
# Returns a broken patch's rejects
cmd = f'patch -p1 -i "{patch_file}" | tee /dev/stderr | sed -n -E \'s/^.*saving rejects to file (.*\\.rej)$/\\1/p\''
result = os.popen(cmd).read().strip()
return result.split('\n') if result else []
# GUI Choicebox with options
choices = [
"Reset workspace",
"Check patches",
"Set checkpoint",
"Edit a patch",
"\u2014" * 44,
"List patches currently applied",
"Select patches",
"Reverse patches",
"Find broken patches",
"Find broken patches (resets workspace)",
"\u2014" * 44,
"See current workspace",
"Write workspace to patch",
"Set checkpoint",
]
"""
@ -75,23 +176,34 @@ def handle_choice(choice):
match choice:
case "Reset workspace":
reset_camoufox()
easygui.msgbox("Reset completed and bootstrap patches applied.", "Reset Complete")
easygui.msgbox(
"Reset. All patches & changes have been removed.",
"Reset Complete",
)
case "Check patches":
case "List patches currently applied":
# Produces a list of patches that are applied
apply_dict = {}
for patch_file in list_files('../patches', suffix='*.patch'):
result = os.system(f'git apply --check "{patch_file}" > /dev/null 2>&1')
if result == 0:
for patch_file in list_patches():
print(f'FILE: {patch_file}')
can_apply, can_reverse, broken = check_patch(patch_file)
if broken:
apply_dict[patch_file] = 'BROKEN'
elif can_reverse:
apply_dict[patch_file] = 'APPLIED'
elif can_apply:
apply_dict[patch_file] = 'NOT APPLIED'
else:
apply_dict[patch_file] = 'APPLIED'
apply_dict[patch_file] = 'UNKNOWN (broken .patch?)'
easygui.textbox(
"Patching Result",
"Patching Result",
'\n'.join(
sorted(
(f'{v}\t{os.path.basename(k)[:-6]}' for k, v in apply_dict.items()),
(
f'{v}\t{k[len("../patches/"):-len('.patch')]}'
for k, v in apply_dict.items()
),
reverse=True,
key=lambda x: x[0],
)
@ -111,38 +223,76 @@ def handle_choice(choice):
run_patches(reverse=True)
easygui.msgbox("Unpatching completed.", "Unpatching Complete")
case "Find broken patches":
case "Find broken patches (resets workspace)":
reset_camoufox()
broken_patches = []
for patch_file in list_files('../patches', suffix='*.patch'):
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))
for patch_file in list_patches():
if reject_files := get_rejects(patch_file):
broken_patches.append((patch_file, reject_files))
if not broken_patches:
easygui.msgbox("All patches applied successfully", "Patching Result")
else:
return
# Display message
message = "Some patches failed to apply:\n\n"
for patch_file, rejects in broken_patches:
message += f"Patch: {patch_file}\nRejects: {rejects}\n\n"
message += '> ' + patch_file[len('../patches/') :] + '\n'
message += '\n\n\n'
# Show file contents
for patch_file, rejects in broken_patches:
message += f"Patch: {patch_file[len('../patches/'):]}\nRejects:\n"
for reject in rejects:
message += f"{reject}\n"
with open(reject, 'r') as f:
message += f.read()
message += "-" * 62 + "\n"
message += '\n'
easygui.textbox("Patching Result", "Failed Patches", message)
case "Edit a patch":
patch_files = list_patches()
ui_choices = [
(
f'{n+1}. {"BOOTSTRAP:" if os.path.basename(file_name).startswith("0-") else ""} '
f'{file_name[len("../patches/") :]}'
)
for n, file_name in enumerate(patch_files)
]
selected_patch = easygui.choicebox(
"Select patch to open in workspace",
"Patches",
ui_choices,
)
# Return if user cancelled
if not selected_patch:
return
# Get file path of selected patch
selected_patch = patch_files[ui_choices.index(selected_patch)]
open_patch_workspace(
selected_patch,
# Patches starting with 0- rely on being ran first.
stop_at_patch=os.path.basename(selected_patch).startswith('0-'),
)
case "See current workspace":
result = os.popen('git diff').read()
easygui.textbox("Diff", "Diff", result)
case "Write workspace to patch":
# Open a file dialog to select a file to write the diff to
with temp_cd('../patches'):
file_path = easygui.filesavebox(
"Select a file to write the diff to", "Write Diff", filetypes="*.patch"
"Select a file to write the patch to",
"Write Patch",
filetypes="*.patch",
)
if not file_path:
exit()
run(f'git diff > {file_path}')
easygui.msgbox("Diff written to file", "Diff Written")
easygui.msgbox(f"Patch has been written to {file_path}.", "Patch Written")
case _:
print('No choice selected')

View file

@ -1,25 +0,0 @@
#!/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

@ -139,7 +139,7 @@ def main():
includes=args.includes,
fonts=args.fonts,
new_file=new_name,
os==args.os,
os=args.os,
)
print(f"Packaging complete for {args.os}")

View file

@ -56,11 +56,14 @@ def run(cmd, exit_on_fail=True, do_print=True):
return retval
def patch(patchfile, reverse=False):
def patch(patchfile, reverse=False, silent=False):
if reverse:
cmd = f"patch -p1 -R -i {patchfile}"
else:
cmd = f"patch -p1 -i {patchfile}"
if silent:
cmd += ' > /dev/null'
else:
print(f"\n*** -> {cmd}")
sys.stdout.flush()
if options.no_execute:
@ -97,7 +100,7 @@ def leave_srcdir():
os.chdir("..")
def list_files(root_dir, suffix='*.patch'):
def list_files(root_dir, suffix):
for root, _, files in os.walk(root_dir):
for file in fnmatch.filter(files, suffix):
full_path = os.path.join(root, file)
@ -105,6 +108,10 @@ def list_files(root_dir, suffix='*.patch'):
yield os.path.join('..', 'patches', relative_path).replace('\\', '/')
def list_patches(root_dir='../patches', suffix='*.patch'):
return sorted(list_files(root_dir, suffix), key=lambda f: os.path.basename(f))
def add_rustup(*targets):
for rust_target in targets:
os.system(f'~/.cargo/bin/rustup target add "{rust_target}"')
@ -124,42 +131,10 @@ def camoufox_patches():
print(f'Using target: {moz_target}')
_update_mozconfig()
# Copy the search-config.json file
run('cp -v ../assets/search-config.json services/settings/dumps/main/search-config.json')
# Then apply all other patches
for patch_file in list_files('../patches'):
for patch_file in list_patches():
patch(patch_file)
# vs_pack.py issue... should be temporary
run('cp -v ../patches/librewolf/pack_vs.py build/vs/')
"""
Apply most recent `settings` repository files.
"""
run('mkdir -p lw', exit_on_fail=False)
enter_srcdir('lw')
run('cp -v ../../settings/camoufox.cfg .')
run('cp -v ../../settings/distribution/policies.json .')
run('cp -v ../../settings/defaults/pref/local-settings.js .')
run('cp -v ../../settings/chrome.css .')
leave_srcdir()
# Copy ALL new files/folders from ../additions to .
run('cp -r ../additions/* .')
# Provide a script that fetches and bootstraps Nightly and some mozconfigs
run('cp -v ../scripts/mozfetch.sh lw/')
# Override the firefox version
for file in ["browser/config/version.txt", "browser/config/version_display.txt"]:
with open(file, "w") as f:
f.write(f"{version}-{release}")
# Generate locales
run("bash ../scripts/generate-locales.sh")
leave_srcdir()

View file

@ -1,6 +1,2 @@
REMOTE_URL=https://github.com/mozilla/gecko-dev
BASE_BRANCH=release
BASE_REVISION=bd7e0ac24a6fb1cddde3e45ea191b7abcc90cf56
version=128.0
version=128.0.3
release=1