summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAli Mohammad Pur <ali.mpfard@gmail.com>2022-01-12 23:07:55 +0330
committerAli Mohammad Pur <Ali.mpfard@gmail.com>2022-01-16 10:32:50 +0330
commitd543db02864aff2d9230147184aa73a112d8ba0b (patch)
tree4e6f179bb22f014cecf8a79de154b2ba6f97995f
parentcdd6d68b2ab56554e5ebcb61f0977534153530f1 (diff)
downloadserenity-d543db02864aff2d9230147184aa73a112d8ba0b.zip
Ports: Add a 'dev' mode that uses git to autogenerate patches for ports
-rwxr-xr-xPorts/.port_include.sh208
1 files changed, 203 insertions, 5 deletions
diff --git a/Ports/.port_include.sh b/Ports/.port_include.sh
index 32574b0b35..2545272c49 100755
--- a/Ports/.port_include.sh
+++ b/Ports/.port_include.sh
@@ -80,6 +80,21 @@ shift
: "${workdir:=$port-$version}"
+cleanup_git() {
+ echo "WARNING: Reverting changes to $workdir as we are in dev mode!"
+ run git clean -xffd >/dev/null 2>&1
+}
+
+# Use the local git target repo as the workdir
+# Make sure to clean it up afterwards
+if [ -n "${IN_SERENITY_PORT_DEV:-}" ]; then
+ echo "WARNING: All changes to the workdir in the current state (inside ./package.sh dev) are temporary!"
+ echo " They will be reverted once the command exits!"
+ nongit_workdir="$workdir"
+ workdir=".$workdir-git"
+ trap "run cleanup_git" EXIT
+fi
+
run_nocd() {
echo "+ $@ (nocd)" >&2
("$@")
@@ -354,7 +369,7 @@ func_defined pre_patch || pre_patch() {
func_defined patch_internal || patch_internal() {
# patch if it was not yet patched (applying patches multiple times doesn't work!)
- if [ -d patches ]; then
+ if [ -z "${IN_SERENITY_PORT_DEV:-}" ] && [ -d patches ]; then
for filepath in patches/*.patch; do
filename=$(basename $filepath)
if [ ! -f "$workdir"/.${filename}_applied ]; then
@@ -386,7 +401,11 @@ func_defined post_install || post_install() {
echo
}
func_defined clean || clean() {
- rm -rf "$workdir" *.out
+ if [ -z "${IN_SERENITY_PORT_DEV:-}" ]; then
+ rm -rf "$workdir" *.out
+ else
+ rm -rf "$nongit_workdir" *.out
+ fi
}
func_defined clean_dist || clean_dist() {
OLDIFS=$IFS
@@ -398,7 +417,11 @@ func_defined clean_dist || clean_dist() {
done
}
func_defined clean_all || clean_all() {
- rm -rf "$workdir" *.out
+ if [ -z "${IN_SERENITY_PORT_DEV:-}" ]; then
+ rm -rf "$workdir" *.out
+ else
+ rm -rf "$nongit_workdir" *.out
+ fi
OLDIFS=$IFS
IFS=$'\n'
for f in $files; do
@@ -551,6 +574,168 @@ do_shell() {
echo "End of package shell. Back to the User shell."
}
+do_generate_patch_readme() {
+ if [ ! -d patches ]; then
+ >&2 echo "Error: Port $port does not have any patches"
+ exit 1
+ fi
+
+ if [ -f patches/ReadMe.md ]; then
+ read -N1 -rp \
+ "A ReadMe.md already exists, overwrite? (N/y) " should_overwrite
+ echo
+ if [ "${should_overwrite,,}" != y ]; then
+ >&2 echo "Not overwriting Ports/$port/patches/ReadMe.md"
+ exit 0
+ fi
+ fi
+
+ rm -fr .patches.tmp
+ mkdir .patches.tmp
+
+ echo "# Patches for $port on SerenityOS" > patches/ReadMe.md
+ echo >> patches/ReadMe.md
+
+ pushd patches
+
+ local tempdir="../.patches.tmp"
+ local count=0
+ for patch in *.patch; do
+ git mailinfo \
+ "$tempdir/$patch.msg" \
+ /dev/null \
+ < "$patch" \
+ > "$tempdir/$patch.info" \
+ 2> "$tempdir/$patch.error" \
+ || {
+ rc=$?
+ >&2 echo "Failed to extract patch info from $patch"
+ >&2 echo "git returned $rc and said:"
+ >&2 cat "$tempdir/$patch.error"
+ exit 1
+ }
+
+ (
+ grep 'Subject: ' "$tempdir/$patch.info" | sed -e 's/Subject: \(.*\)$/\1/'
+ echo
+ cat "$tempdir/$patch.msg"
+ ) > "$tempdir/$patch.desc"
+
+
+ if [ ! -s "$tempdir/$patch.desc" ]; then
+ >&2 echo "WARNING: $patch does not contain a valid git patch or is missing a commit message, and is going to be skipped!"
+ continue
+ fi
+
+ {
+ echo "## \`$patch\`"
+ echo
+ cat "$tempdir/$patch.desc"
+ echo
+ } >> ReadMe.md
+ count=$((count + 1))
+ done
+
+ popd
+
+ >&2 echo "Successfully generated entries for $count patch(es) in patches/ReadMe.md."
+}
+
+launch_user_shell() {
+ env \
+ IN_SERENITY_PORT_DEV="$port" \
+ "${SHELL:-bash}" || \
+ true
+}
+
+prompt_yes_no() {
+ read -N1 -rp \
+ "$1 (N/y) " result
+ 2>&1 echo
+ if [ "${result,,}" == y ]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+do_dev() {
+ if [ -n "${IN_SERENITY_PORT_DEV:-}" ]; then
+ >&2 echo "Error: Already in dev environment for $IN_SERENITY_PORT_DEV"
+ exit 1
+ fi
+
+ git_repo=".$workdir-git"
+ [ -d "$git_repo" ] || (
+ mv "$workdir" "$git_repo"
+ pushd "$git_repo"
+ if [ ! -d "$git_repo/.git" ]; then
+ git init .
+ git add .
+ git commit -a -m 'Initial import'
+ fi
+ # Make it allow pushes from other local checkouts
+ git config receive.denyCurrentBranch ignore
+ # Import patches as commits, or ask the user to commit them
+ # if they're not git patches already.
+ if [ -d ../patches ] && [ -n "$(find ../patches -maxdepth 1 -name '*.patch' -print -quit)" ]; then
+ for patch in ../patches/*.patch; do
+ if [ -f "$workdir/.$(basename $patch).applied" ]; then
+ continue
+ fi
+
+ echo "Importing patch $patch..."
+ git am "$patch" || {
+ git am --abort >/dev/null 2>&1 || true
+ git apply < $patch || {
+ # The patch didn't apply, oh no!
+ # Ask the user to figure it out :shrug:
+ >&2 echo "- This patch does not apply, you'll be dropped into a shell to investigate and fix this, quit the shell when the problem is resolved."
+ launch_user_shell
+ }
+ git add -A
+ if prompt_yes_no "- This patch does not appear to be a git patch, would you like to manually commit its changes?"; then
+ >&2 echo "Apply any changes you want, commit them into the current repo and quit this shell to continue."
+
+ launch_user_shell
+ else
+ git commit --verbose
+ fi
+ }
+ done
+ fi
+ popd
+ )
+
+ [ -d "$git_repo" ] && [ ! -d "$workdir" ] && {
+ git clone "$git_repo" "$workdir"
+ }
+
+ [ -d "$workdir/.git" ] || {
+ >&2 echo "$workdir does not appear to be a git repository, if you did this manually, you're on your own"
+ if prompt_yes_no "Otherwise, press 'y' to remove that directory and clone it again"; then
+ rm -fr "$workdir"
+ git clone "$git_repo" "$workdir"
+ else
+ exit 1
+ fi
+ }
+
+ local first_hash="$(git -C "$git_repo" rev-list --max-parents=0 HEAD)"
+
+ launch_user_shell
+
+ local current_hash="$(git -C "$git_repo" rev-parse HEAD)"
+
+ # If the hashes are the same, we have no patches, otherwise generate patches
+ if [ "$first_hash" != "$current_hash" ]; then
+ >&2 echo "Note: Regenerating patches as there are some commits in the port repo (started at $first_hash, now is $current_hash)"
+ rm -fr patches/*.patch
+ git -C "$git_repo" format-patch "$first_hash" -o "$(realpath patches)"
+ do_generate_patch_readme
+ fi
+}
+
NO_GPG=false
parse_arguments() {
if [ -z "${1:-}" ]; then
@@ -558,7 +743,7 @@ parse_arguments() {
return
fi
case "$1" in
- fetch|patch|shell|configure|build|install|installdepends|clean|clean_dist|clean_all|uninstall|showproperty)
+ fetch|patch|shell|configure|build|install|installdepends|clean|clean_dist|clean_all|uninstall|showproperty|generate_patch_readme)
method=$1
shift
do_${method} "$@"
@@ -575,8 +760,21 @@ parse_arguments() {
export PS1="(serenity):\w$ "
bash --norc
;;
+ dev)
+ shift
+ if [ "${1:-}" != "--no-depends" ]; then
+ do_installdepends
+ fi
+ if [ -d "$workdir" ] && [ ! -d "$workdir/.git" ]; then
+ if prompt_yes_no "- Would you like to clean the working direcory (i.e. ./package.sh clean)?"; then
+ do_clean
+ fi
+ fi
+ do_fetch
+ do_dev
+ ;;
*)
- >&2 echo "I don't understand $1! Supported arguments: fetch, patch, configure, build, install, installdepends, interactive, clean, clean_dist, clean_all, uninstall, showproperty."
+ >&2 echo "I don't understand $1! Supported arguments: fetch, patch, configure, build, install, installdepends, interactive, clean, clean_dist, clean_all, uninstall, showproperty, generate_patch_readme, dev."
exit 1
;;
esac