@@ -0,0 +1,86 @@
2+# Write the MultiGram stack as numbered patches (git format-patch forkgram..multigram) into
3+# a folder, with APPLY.txt saying how to apply them onto a plain Forkgram checkout.
5+# scripts/export-patches.sh [--base REF] [--head REF] [--force] [FOLDER]
7+# --base REF the snapshot branch (default: forkgram)
8+# --head REF the app branch (default: multigram)
9+# --force replace the patches of an earlier export in FOLDER
10+# FOLDER where to write them (default: multigram-patches)
12+# For branches you have not checked out locally, pass --base origin/forkgram
13+# --head origin/multigram after a git fetch.
16+die() { printf 'export-patches: %s\n' "$*" >&2; exit 1; }
18+base=forkgram head=multigram force=no dir=multigram-patches
19+while [ $# -gt 0 ]; do
21+ --base) base=${2:?--base needs a ref}; shift 2 ;;
22+ --head) head=${2:?--head needs a ref}; shift 2 ;;
23+ --force) force=yes; shift ;;
24+ -h | --help) sed -n '2,/^set -euo/p' "$0" | sed '$d; s/^# \{0,1\}//'; exit 0 ;;
25+ -*) die "unknown option: $1 (see --help)" ;;
30+git rev-parse --git-dir >/dev/null 2>&1 || die "run this inside a clone of the MultiGram repository"
31+base_c=$(git rev-parse -q --verify "$base^{commit}") || die "no such ref: $base"
32+head_c=$(git rev-parse -q --verify "$head^{commit}") || die "no such ref: $head"
33+count=$(git rev-list --count "$base_c..$head_c")
34+[ "$count" -gt 0 ] || die "$head has no commits on top of $base"
35+[ -z "$(git rev-list --merges "$base_c..$head_c")" ] ||
36+ die "$head has merge commits on top of $base; git format-patch cannot export them"
38+# The snapshot the stack sits on, and the Forkgram commit it was made from.
39+snap=$(git merge-base "$base_c" "$head_c") || die "$head shares no history with $base"
40+msg=$(git log -1 --format=%B "$snap")
41+fg_commit=$(printf '%s\n' "$msg" | sed -n 's/^Forkgram-Commit:[[:space:]]*\([0-9a-f]\{40\}\).*/\1/p' | tail -n 1)
42+fg_version=$(printf '%s\n' "$msg" | sed -n 's/^Forkgram-Version:[[:space:]]*\([0-9A-Za-z._+-]*\).*/\1/p' | tail -n 1)
43+[ -n "$fg_commit" ] || die "$(git rev-parse --short "$snap") (where $head meets $base) is not a Forkgram snapshot"
44+[ -n "$fg_version" ] || fg_version=unknown
45+if [ "$snap" != "$base_c" ]; then
46+ printf 'export-patches: note: %s is based on an older snapshot than %s; the patches are for Forkgram %s\n' \
47+ "$head" "$base" "$fg_version" >&2
51+if [ -n "$(ls -A "$dir")" ]; then
52+ [ "$force" = yes ] || die "$dir is not empty (use --force to replace an earlier export)"
53+ find "$dir" -mindepth 1 -maxdepth 1 \( -name '[0-9][0-9][0-9][0-9]-*.patch' -o -name APPLY.txt \) -exec rm -f {} +
54+ [ -z "$(ls -A "$dir")" ] || die "$dir holds files this script did not write; pick another folder"
57+git format-patch --quiet --full-index --binary -o "$dir" "$base_c..$head_c"
58+abs=$(cd "$dir" && pwd)
60+cat >"$dir/APPLY.txt" <<EOF
64+$count patch(es): the MultiGram commits of $head ($(git rev-parse --short "$head_c")), made on the
65+forkgram snapshot $(git rev-parse --short "$snap"), which is Forkgram $fg_version with the .github folder removed:
67+ Forkgram commit $fg_commit
69+Apply them onto a plain Forkgram checkout of that commit. Forkgram tags its releases
70+<version>.0 (so $fg_version.0 here); if the tag is missing, fetch the commit instead.
72+ git clone --depth 1 --branch $fg_version.0 https://github.com/forkgram/TelegramAndroid.git
74+ git rev-parse HEAD # should print $fg_commit
75+ git switch -c multigram
76+ git am -3 $abs/*.patch
78+-3 lets git fall back to a three-way merge when a patch does not apply as it is.
79+If git am still stops, it names the patch and the files: fix them, "git add" them and
80+run "git am --continue" (or "git am --skip" to leave that patch out, "git am --abort"
81+to go back). The same commands work on a newer Forkgram release (expect more stops);
82+clone without --depth 1 then, so -3 can find the older versions of the files.
85+printf '%s\n' "Wrote $count patch(es) and APPLY.txt to $abs"
86+sed -n '/^ git clone/,/^ git am/p' "$dir/APPLY.txt"