On 2025-02-20 08:49:33, Darrick J. Wong wrote: > From: Darrick J. Wong <djwong@xxxxxxxxxx> > > Currently, libxfs-apply handles merge conflicts in the auto-backported > patches in a somewhat unfriendly way -- either it applies completely > cleanly, or the user has to ^Z, find the raw diff file in /tmp, apply it > by hand, resume the process, and then tell it to skip the patch. > > This is annoying, and I've long worked around that by using my handy > stg-force-import script that imports the patch with --reject, undoes the > partially-complete diff, uses patch(1) to import as much of the diff as > possible, and then starts an editor so the caller can clean up the rest. > > When patches are fuzzy, patch(1) is /much/ less strict about applying > changes than stg-import. Since Carlos sent in his own workaround for > guilt, I figured I might as well port stg-force-import into libxfs-apply > and contribute that. > > Signed-off-by: "Darrick J. Wong" <djwong@xxxxxxxxxx> > --- > per maintainer request > --- > tools/libxfs-apply | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++-- > 1 file changed, 62 insertions(+), 2 deletions(-) > > diff --git a/tools/libxfs-apply b/tools/libxfs-apply > index 097a695f942bb8..9fb31f74d5c9af 100755 > --- a/tools/libxfs-apply > +++ b/tools/libxfs-apply > @@ -297,6 +297,64 @@ fixup_header_format() > > } > > +editor() { > + if [ -n "${EDITOR}" ]; then > + ${EDITOR} "$@" > + elif [ -n "${VISUAL}" ]; then > + ${VISUAL} "$@" > + elif command -v editor &>/dev/null; then > + editor "$@" > + elif command -v nano &>/dev/null; then > + nano "$@" > + else > + echo "No editor available, aborting messily." > + exit 1 > + fi > +} > + > +stg_force_import() > +{ > + local patch_name="$1" > + local patch="$2" > + > + # Import patch to get the metadata even though the diff application > + # might fail due to stg import being very picky. If the patch applies > + # cleanly, we're done. > + stg import --reject -n "${patch_name}" "${patch}" && return 0 > + > + local tmpfile="${patch}.stgit" > + rm -f "${tmpfile}" > + > + # Erase whatever stgit managed to apply, then use patch(1)'s more > + # flexible heuristics. Capture the output for later use. > + stg diff | patch -p1 -R > + patch -p1 < "${patch}" &> "${tmpfile}" > + cat "${tmpfile}" > + > + # Attach any new files created by the patch > + grep 'create mode' "${patch}" | sed -e 's/^.* mode [0-7]* //g' | while read -r f; do > + git add "$f" > + done > + > + # Remove any existing files deleted by the patch > + grep 'delete mode' "${patch}" | sed -e 's/^.* mode [0-7]* //g' | while read -r f; do > + git rm "$f" > + done > + > + # Open an editor so the user can clean up the rejects. Use readarray > + # instead of "<<<" because the latter picks up empty output as a single > + # line and does variable expansion... stupid bash. > + readarray -t rej_files < <(grep 'saving rejects to' "${tmpfile}" | \ > + sed -e 's/^.*saving rejects to file //g') > + rm -f "${tmpfile}" > + if [ "${#rej_files[@]}" -gt 0 ]; then > + echo "Opening editor to deal with rejects. Changes commit when you close the editor." > + editor "${rej_files[@]}" > + fi > + > + stg refresh > +} > + > apply_patch() > { > local _patch=$1 > @@ -385,11 +443,13 @@ apply_patch() > stg import -n $_patch_name $_new_patch.2 > if [ $? -ne 0 ]; then > echo "stgit push failed!" > - read -r -p "Skip or Fail [s|F]? " response > - if [ -z "$response" -o "$response" != "s" ]; then > + read -r -p "Skip, force Apply, or Fail [s|a|F]? " response > + if [ -z "$response" -o "$response" = "F" -o "$response" = "f" ]; then > echo "Force push patch, fix and refresh." > echo "Restart from commit $_current_commit" > fail "Manual cleanup required!" > + elif [ "$response" = "a" -o "$response" = "A" ]; then > + stg_force_import "$_patch_name" "$_new_patch.2" > else > echo "Skipping. Manual series file cleanup needed!" > fi > Thanks! Works great, lgtm Reviewed-by: Andrey Albershteyn <aalbersh@xxxxxxxxxx> Sending fix for stgit detection in reply to this patch -- - Andrey