#!/bin/bash # # Commit patches from --spec file to git (in the curret working directory). # # Example: # # 1) clone upstrem reporitory # git clone git://git.kernel.org/pub/scm/utils/util-linux/util-linux.git # # 2) create a branch based on the same version as tarball version in your .spec file # git checkout -f -b rhel v2.23.2 # # 3) create tag to remember the start point # git tag rhel-7-start # # 4) apply patches from 7.0 # spec2git --spec /path/to/rhel/dist-git/util-linux.spec --from 0 --to 22 # # 5) add tag to remember 7.0 (7.1, 7.2, ...) # git tag rhel-7.0 # # n) repeat 4) and 5) for each version, don't forget to update --from and --to according your spec file # # Notes: # # * spec2git expects these lines in your spec file: # # # 123456 - description of the bug # Patch0: filename.patch # # it means comment with relevant information before Patch: # TEMP=$(getopt -o f:t:p:s:e: --long patch:,spec:,from:,to:,extra: -n 'spec2git' -- "$@") BASE="" PATCH_NUM="" PATCH_FROM="" PATCH_TO="" SPEC_FILE="" FORCE_EDIT="" n_patches=0 declare -a PATCHES declare -a COMMENTS bold=$(tput setaf 3) normal=$(tput sgr0) function die() { echo "$1" exit 0 } function add_to_array() { local -n a=$1 local idx=$2 a[$idx]=$3 } function patch_get_filename() { local -n a=PATCHES echo "${a[$1]}" } function patch_get_comment() { local -n a=COMMENTS echo "${a[$1]}" | sed 's/^# [0-9]*[[:blank:]]*-[[:blank:]]*//' } function patch_get_bz() { local -n a=COMMENTS echo "${a[$1]}" | sed 's/# \([0-9]*\).*/\1/' } function filename_to_commit_subject() { local name="$1" echo $name | sed 's/\.patch$//; s/-/ /g; s/^[0-9\. ]*//; s/ /\: /' } function bz_to_url() { echo "Addresses: http://bugzilla.redhat.com/show_bug.cgi?id=$1" } function cmd_git_commit() { local i=$1 local bz=$(patch_get_bz $i) local file="$(patch_get_filename $i)" local comm="$(patch_get_comment $i)" local subj="$(filename_to_commit_subject $file)" local url="$(bz_to_url $bz)" for x in $(get_new_files); do echo "*** Add new file: $x" git add $x done git commit -a -m "$subj" -m "$comm" -m "$url" ${GIT_COMMIT_EXTRA} } function get_patch_desc() { local num="$1" local patch local comment while read line; do case "$line" in --) ;; # ignore, empty line \#*) comment="$line" ;; Patch*) patch="$(echo "$line" | sed 's/Patch[0-9]*\://; s/[[:blank:]]//g')" ;; esac done < <(grep -B 1 -E "^Patch$num\: .*\.patch" ${SPEC_FILE}) if [ -n "$patch" ]; then add_to_array PATCHES $n_patches "$patch" add_to_array COMMENTS $n_patches "$comment" n_patches=$(($n_patches + 1)) fi } function apply_patch() { local file=$(patch_get_filename $1) patch -p1 < ${BASE}/$file } function get_new_files() { git ls-files -o } # # main() # eval set -- "$TEMP" while true ; do case "$1" in -p|--patch) PATCH_NUM="$2" ; shift 2 ;; -s|--spec) SPEC_FILE="$2" ; shift 2 ;; -f|--from) PATCH_FROM="$2" ; shift 2 ;; -e|--extra) GIT_COMMIT_EXTRA="$2"; shift 2 ;; -t|--to) PATCH_TO="$2" ; shift 2 ;; --) shift ; break ;; *) echo "Internal error!" ; exit 1 ;; esac done [ -z "$SPEC_FILE" ] && die "No spec file specified (use --spec )." BASE="$(dirname $SPEC_FILE)" NFILES=$(get_new_files) [ -n "$NFILES" ] && die "Current working direcory is dirty, use 'git clean -xdf'" if [ -n "$PATCH_NUM" ]; then get_patch_desc $PATCH_NUM elif [ -n "$PATCH_FROM" -o -n "$PATCH_TO" ]; then [ -z "$PATCH_TO" ] && die "use --from together with --to" [ -z "$PATCH_FROM" ] && die "use --to together with --from" for n in $(seq $PATCH_FROM $PATCH_TO); do get_patch_desc $n done fi [ $n_patches -eq 0 ] && die "Not found patches." for i in $(seq 0 $(($n_patches - 1))); do echo "${bold}$(patch_get_filename $i)${normal}" apply_patch $i cmd_git_commit $i echo done