# advanced_patch # # parameters: # : u-boot, kernel, atf # : u-boot: u-boot, u-boot-neo; kernel: sun4i-default, sunxi-next, ... # : cubieboard, cubieboard2, cubietruck, ... # : optional subdirectory # : additional description text # # priority: # $USERPATCHES_PATH///target_ # $USERPATCHES_PATH///board_ # $USERPATCHES_PATH///branch_ # $USERPATCHES_PATH// # $SRC/patch///target_ # $SRC/patch///board_ # $SRC/patch///branch_ # $SRC/patch// # advanced_patch() { local dest=$1 local family=$2 local board=$3 local target=$4 local branch=$5 local description=$6 display_alert "Started patching process for" "$dest $description" "info" display_alert "Looking for user patches in" "userpatches/$dest/$family" "info" local names=() local dirs=( "$USERPATCHES_PATH/$dest/$family/target_${target}:[\e[33mu\e[0m][\e[34mt\e[0m]" "$USERPATCHES_PATH/$dest/$family/board_${board}:[\e[33mu\e[0m][\e[35mb\e[0m]" "$USERPATCHES_PATH/$dest/$family/branch_${branch}:[\e[33mu\e[0m][\e[33mb\e[0m]" "$USERPATCHES_PATH/$dest/$family:[\e[33mu\e[0m][\e[32mc\e[0m]" "$SRC/patch/$dest/$family/target_${target}:[\e[32ml\e[0m][\e[34mt\e[0m]" "$SRC/patch/$dest/$family/board_${board}:[\e[32ml\e[0m][\e[35mb\e[0m]" "$SRC/patch/$dest/$family/branch_${branch}:[\e[32ml\e[0m][\e[33mb\e[0m]" "$SRC/patch/$dest/$family:[\e[32ml\e[0m][\e[32mc\e[0m]" ) local links=() # required for "for" command shopt -s nullglob dotglob # get patch file names for dir in "${dirs[@]}"; do for patch in ${dir%%:*}/*.patch; do names+=($(basename "${patch}")) done # add linked patch directories if [[ -d ${dir%%:*} ]]; then local findlinks findlinks=$(find "${dir%%:*}" -maxdepth 1 -type l -print0 2>&1 | xargs -0) [[ -n $findlinks ]] && readarray -d '' links < <(find "${findlinks}" -maxdepth 1 -type f -follow -print -iname "*.patch" -print | grep "\.patch$" | sed "s|${dir%%:*}/||g" 2>&1) fi done # merge static and linked names=("${names[@]}" "${links[@]}") # remove duplicates local names_s=($(echo "${names[@]}" | tr ' ' '\n' | LC_ALL=C sort -u | tr '\n' ' ')) # apply patches for name in "${names_s[@]}"; do for dir in "${dirs[@]}"; do if [[ -f ${dir%%:*}/$name ]]; then if [[ -s ${dir%%:*}/$name ]]; then process_patch_file "${dir%%:*}/$name" "${dir##*:}" else display_alert "* ${dir##*:} $name" "skipped" fi break # next name fi done done } # process_patch_file # # parameters: # : path to patch file # : additional status text # process_patch_file() { local patch=$1 local status=$2 # detect and remove files which patch will create lsdiff -s --strip=1 "${patch}" | grep '^+' | awk '{print $2}' | xargs -I % sh -c 'rm -f %' echo "Processing file $patch" >> "${DEST}"/${LOG_SUBPATH}/patching.log patch --batch --silent -p1 -N < "${patch}" >> "${DEST}"/${LOG_SUBPATH}/patching.log 2>&1 if [[ $? -ne 0 ]]; then display_alert "* $status $(basename "${patch}")" "failed" "wrn" [[ $EXIT_PATCHING_ERROR == yes ]] && exit_with_error "Aborting due to" "EXIT_PATCHING_ERROR" else display_alert "* $status $(basename "${patch}")" "" "info" fi echo >> "${DEST}"/${LOG_SUBPATH}/patching.log } # apply_patch_series apply_patch_series() { local t_dir="${1}" local series="${2}" local bzdir="$(dirname $series)" local flag local err_pt=$(mktemp /tmp/apply_patch_series_XXXXX) list=$(awk '$0 !~ /^#.*|^-.*|^$/' "${series}") skiplist=$(awk '$0 ~ /^-.*/{print $NF}' "${series}") display_alert "apply a series of " "[$(echo $list | wc -w)] patches" display_alert "skip [$(echo $skiplist | wc -w)] patches" cd "${t_dir}" || exit 1 for p in $list; do # Detect and remove files as '*.patch' which patch will create. # So we need to delete the file before applying the patch if it exists. lsdiff -s --strip=1 "$bzdir/$p" | awk '$0 ~ /^+.*patch$/{print $2}' | xargs -I % sh -c 'rm -f %' patch --batch --silent --no-backup-if-mismatch -p1 -N < $bzdir/"$p" >> $err_pt 2>&1 flag=$? case $flag in 0) printf "[\033[32m done \033[0m] %s\n" "${p}" printf "[ done ] %s\n" "${p}" >> "${DEST}"/debug/patching.log ;; 1) printf "[\033[33m FAILED \033[0m] %s\n" "${p}" echo -e "[ FAILED ] For ${p} \t\tprocess exit [ $flag ]" >> "${DEST}"/debug/patching.log cat $err_pt >> "${DEST}"/debug/patching.log ;; 2) printf "[\033[31m Patch wrong \033[0m] %s\n" "${p}" echo -e "Patch wrong ${p}\t\tprocess exit [ $flag ]" >> "${DEST}"/debug/patching.log cat $err_pt >> "${DEST}"/debug/patching.log ;; esac echo "" > $err_pt done echo "" >> "${DEST}"/debug/patching.log rm $err_pt } userpatch_create() { # create commit to start from clean source git add . git -c user.name='Armbian User' -c user.email='user@example.org' commit -q -m "Cleaning working copy" local patch="$DEST/patch/$1-$LINUXFAMILY-$BRANCH.patch" # apply previous user debug mode created patches if [[ -f $patch ]]; then display_alert "Applying existing $1 patch" "$patch" "wrn" && patch --batch --silent -p1 -N < "${patch}" # read title of a patch in case Git is configured if [[ -n $(git config user.email) ]]; then COMMIT_MESSAGE=$(cat "${patch}" | grep Subject | sed -n -e '0,/PATCH/s/.*PATCH]//p' | xargs) display_alert "Patch name extracted" "$COMMIT_MESSAGE" "wrn" fi fi # prompt to alter source display_alert "Make your changes in this directory:" "$(pwd)" "wrn" display_alert "Press after you are done" "waiting" "wrn" read -r < /dev/tty tput cuu1 git add . # create patch out of changes if ! git diff-index --quiet --cached HEAD; then # If Git is configured, create proper patch and ask for a name if [[ -n $(git config user.email) ]]; then display_alert "Add / change patch name" "$COMMIT_MESSAGE" "wrn" read -e -p "Patch description: " -i "$COMMIT_MESSAGE" COMMIT_MESSAGE [[ -z "$COMMIT_MESSAGE" ]] && COMMIT_MESSAGE="Patching something" git commit -s -m "$COMMIT_MESSAGE" git format-patch -1 HEAD --stdout --signature="Created with Armbian build tools $GITHUB_SOURCE/armbian/build" > "${patch}" PATCHFILE=$(git format-patch -1 HEAD) rm $PATCHFILE # delete the actual file # create a symlink to have a nice name ready find $DEST/patch/ -type l -delete # delete any existing ln -sf $patch $DEST/patch/$PATCHFILE else git diff --staged > "${patch}" fi display_alert "You will find your patch here:" "$patch" "info" else display_alert "No changes found, skipping patch creation" "" "wrn" fi git reset --soft HEAD~ for i in {3..1..1}; do echo -n "$i." && sleep 1; done }