#!/bin/bash # update_git.sh: script to manage package maintenance using a git-based # workflow. Commands are as follows: # git2pkg (update package spec file and patches from git) # pkg2git (update git (frombundle branch) from the package "bundleofbundles") # refresh (refresh spec file from spec file template and "bundlofbundles") # # (default is git2pkg) set -e source ./config.sh declare -A COMMIT_IDS_BY_SUBMODULE_PATH # Get version info from the packages' tarball - decode and do some checks BASE_RE="qemu-[[:digit:]]+(\.[[:digit:]]+){2}(-rc[[:digit:]])?" EXTRA_RE="\+git\.[[:digit:]]+\.([[:xdigit:]]+)" SUFFIX_RE="\.tar\.xz" SIG_SUFFIX_RE="\.tar\.xz\.sig" QEMU_TARBALL=($(find -maxdepth 1 -type f -regextype posix-extended -regex \ "\./$BASE_RE($EXTRA_RE)?$SUFFIX_RE" -printf "%f ")) QEMU_TARBALL_SIG=($(find -maxdepth 1 -type f -regextype posix-extended -regex \ "\./$BASE_RE($EXTRA_RE)?$SIG_SUFFIX_RE" -printf "%f ")) if [ ${#QEMU_TARBALL[@]} -gt 1 ]; then echo "Multiple qemu tarballs detected. Please clean up" exit fi if [ ${#QEMU_TARBALL_SIG[@]} -gt 1 ]; then echo "Multiple qemu tarballs signature files detected. Please clean up" exit fi OLD_SOURCE_VERSION_AND_EXTRA=$(echo $QEMU_TARBALL 2>/dev/null | head --bytes=-8\ | cut --bytes=6-) VERSION_EXTRA=$(echo $OLD_SOURCE_VERSION_AND_EXTRA|awk -F+ '{if ($2) print \ "+"$2}') if [ "$OLD_SOURCE_VERSION_AND_EXTRA" = "" ]; then echo "ERROR: No tarball found!" exit fi #============================================================================== TEMP_CHECK() { # TEMPORARY! FOR NOW WE REQUIRE THESE LOCALLY TO DO WORK ON PACKAGE REQUIRED_LOCAL_REPO_MAP=( ~/git/qemu-opensuse ~/git/qemu-seabios ~/git/qemu-ipxe ~/git/qemu-sgabios ~/git/qemu-skiboot ~/git/qemu-keycodemapdb ) # Validate that all the local repos that we currently have patches in are available # TEMPORARY REQUIREMENT! for entry in ${REQUIRED_LOCAL_REPO_MAP[@]}; do if [[ -e $(readlink -f ${entry}) ]]; then if $(git -C $entry branch| grep -F "$GIT_BRANCH" >/dev/null); then : else echo "Didn't find the $GIT_BRANCH branch in repo at $entry" exit fi else echo "ERROR! For now, you need to have these local git repos available:" echo ${REQUIRED_LOCAL_REPO_MAP[@]} exit fi done } #============================================================================== initbundle() { # The bundle tarball has git bundles stored in a directory structure which mimics the # submodule locations in the containing git repo. Also at that same dir level # is a file named repo which contains the one line git repo url (with git:// or # http(s) prefix). The bundles are named as follows: # "{path/}{git_sha}.{bundle}", where {path/} isn't present for # the top (qemu) bundle (ie it's for submodules). SUBMODULE_COMMIT_IDS=($(git -C ${LOCAL_REPO_MAP[0]} submodule status --recursive|awk '{print $1}')) SUBMODULE_DIRS=($(git -C ${LOCAL_REPO_MAP[0]} submodule status --recursive|awk '{print $2}')) SUBMODULE_COUNT=${#SUBMODULE_COMMIT_IDS[@]} # TODO: do this with simply math - ie: use (( ... )) if [[ "$REPO_COUNT" != "$(expr $SUBMODULE_COUNT + 1)" ]]; then echo "ERROR: submodule count doesn't match the REPO_COUNT variable in config.sh file!" exit fi rm -rf $GIT_DIR rm -rf $BUNDLE_DIR mkdir -p $BUNDLE_DIR for (( i=0; i <$SUBMODULE_COUNT; i++ )); do mkdir -p $BUNDLE_DIR/${SUBMODULE_DIRS[$i]} # what should this file be? for now use an extension of id touch $BUNDLE_DIR/${SUBMODULE_DIRS[$i]}/${SUBMODULE_COMMIT_IDS[$i]}.id done if [ "$GIT_UPSTREAM_COMMIT_ISH" = "LATEST" ]; then GIT_UPSTREAM_COMMIT=$NEW_COMMIT_ISH_FULL else # TODO: make this smarter, or change something - works for tag, but not normal commit? GIT_UPSTREAM_COMMIT=$(git -C ${LOCAL_REPO_MAP[0]} show-ref -d $GIT_UPSTREAM_COMMIT_ISH|grep -F "^{}"|awk '{print $1}') fi touch $BUNDLE_DIR/$GIT_UPSTREAM_COMMIT.id # Now go through all the submodule local repos that are present and create a bundle file for the patches found there for (( i=0; i <$REPO_COUNT; i++ )); do if [[ -e $(readlink -f ${LOCAL_REPO_MAP[$i]}) ]]; then SUBDIR=${PATCH_PATH_MAP[$i]} GITREPO_COMMIT_ISH=($BUNDLE_DIR/$SUBDIR*.id) if [[ $GITREPO_COMMIT_ISH =~ .*(.{40})[.]id ]]; then GITREPO_COMMIT_ISH=${BASH_REMATCH[1]} echo "Using $GITREPO_COMMIT_ISH" PATCH_RANGE_INDEX=$i mkdir -p $GIT_DIR/$SUBDIR git -C $GIT_DIR/$SUBDIR init git -C $GIT_DIR/$SUBDIR remote add origin file://$(readlink -f \ ${LOCAL_REPO_MAP[$PATCH_RANGE_INDEX]}) git -C $(readlink -f ${LOCAL_REPO_MAP[$PATCH_RANGE_INDEX]}) remote get-url origin >$BUNDLE_DIR/$SUBDIR/repo if [[ $(git -C $GIT_DIR/$SUBDIR ls-remote --heads origin $GIT_BRANCH) ]]; then git -C $GIT_DIR/$SUBDIR fetch origin $GIT_BRANCH if [[ $(git -C $GIT_DIR/$SUBDIR rev-list $GITREPO_COMMIT_ISH..FETCH_HEAD) ]]; then git -C $GIT_DIR/$SUBDIR bundle create $BUNDLE_DIR/$SUBDIR$GITREPO_COMMIT_ISH.bundle $GITREPO_COMMIT_ISH..FETCH_HEAD fi fi fi fi done # keep diffs to a minimum - touch bundle files to "something common" TODO: decide if there's something better find $BUNDLE_DIR -exec touch -r qemu-$SOURCE_VERSION$VERSION_EXTRA.tar.xz {} \; tar --format gnu --xz -cf bundles.tar.xz -C $BUNDLE_DIR . rm -rf $BUNDLE_DIR rm -rf $GIT_DIR } #============================================================================== bundle2local() { rm -rf $BUNDLE_DIR mkdir -p $BUNDLE_DIR tar xJf bundles.tar.xz -C $BUNDLE_DIR BUNDLE_FILES=$(find $BUNDLE_DIR -printf "%P\n"|grep "bundle$") for entry in ${BUNDLE_FILES[@]}; do if [[ $entry =~ ^(.*)[/]*([a-f0-9]{40})[.]bundle$ ]]; then SUBDIR=${BASH_REMATCH[1]} GITREPO_COMMIT_ISH=${BASH_REMATCH[2]} else echo "ERROR! BAD BUNDLE CONTENT!" exit fi for (( i=0; i <$REPO_COUNT; i++ )); do if [[ "$SUBDIR" = "${PATCH_PATH_MAP[$i]}" ]]; then PATCH_RANGE_INDEX=$i break fi done LOCAL_REPO=$(readlink -f ${LOCAL_REPO_MAP[$PATCH_RANGE_INDEX]}) if [ -e $LOCAL_REPO ]; then git -C $LOCAL_REPO remote remove bundlerepo || true # git won't let you delete a branch we're on - so get onto master temporarily (TODO: is there a better approach?) git -C $LOCAL_REPO checkout master -f git -C $LOCAL_REPO branch -D frombundle || true git -C $LOCAL_REPO remote add bundlerepo $BUNDLE_DIR/$entry git -C $LOCAL_REPO fetch bundlerepo FETCH_HEAD git -C $LOCAL_REPO branch frombundle FETCH_HEAD git -C $LOCAL_REPO remote remove bundlerepo else echo "No local repo $LOCAL_REPO corresponding to archived git bundle!" exit fi done rm -rf $BUNDLE_DIR } #============================================================================== redo_tarball_and_rebase_patches() { rm -rf $GIT_DIR #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # CREATE TARBALL, USING FRESH REPO - WE COULD RELY MORE ON LOCAL IF WE WERE MORE CAREFUL #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # TODO: WHAT IS THIS NEXT LINE EVEN DOING FOR US?? (OK, it's initing a repo, what do we rely on there?) git clone -ls ${LOCAL_REPO_MAP[0]} $GIT_DIR -b master --single-branch &>/dev/null echo "Please wait..." (cd $GIT_DIR && git remote add upstream \ git://git.qemu-project.org/qemu.git &>/dev/null) (cd $GIT_DIR && git remote update upstream &>/dev/null) (cd $GIT_DIR && git checkout $NEW_COMMIT_ISH &>/dev/null) # As an alternative, we could add a --recurse-submodules to the checkout instead here as well, right? #UPSTREAM DOESNT DO THIS (time takes 17 minutes!): # (cd $GIT_DIR && git submodule update --init --recursive &>/dev/null) #INSTEAD THESE NEXT TWO LINES ARE WHAT IS DONE (these take 9 minutes and 3 minutes respectively): (cd $GIT_DIR && git submodule update --init &>/dev/null) (cd $GIT_DIR/roms/edk2 && git submodule update --init &>/dev/null) VERSION_EXTRA=+git.$NOW_SECONDS.$NEW_COMMIT_ISH if (cd ${LOCAL_REPO_MAP[0]} && git describe --exact-match $NEW_COMMIT_ISH \ &>/dev/null); then if [ "$X" = "50" ]; then echo "Ignoring non-standard tag" else # there is no VERSION_EXTRA VERSION_EXTRA= fi fi (cd $GIT_DIR/roms/seabios && git describe --tags --long --dirty > \ .version) (cd $GIT_DIR/roms/skiboot && ./make_version.sh > .version) echo "Almost there..." tar --exclude=.git --transform "s,$GIT_DIR,qemu-$SOURCE_VERSION," \ -Pcf qemu-$SOURCE_VERSION$VERSION_EXTRA.tar $GIT_DIR osc rm --force qemu-$OLD_SOURCE_VERSION_AND_EXTRA.tar.xz &>/dev/null ||\ true osc rm --force qemu-$OLD_SOURCE_VERSION_AND_EXTRA.tar.xz.sig \ &>/dev/null || true unset QEMU_TARBALL_SIG xz -T 0 qemu-$SOURCE_VERSION$VERSION_EXTRA.tar osc add qemu-$SOURCE_VERSION$VERSION_EXTRA.tar.xz #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # GET THE SUBMODULE COMMIT ID'S FROM THIS NEWLY MINTED QEMU CHECKOUT. WE'LL USE THAT WHEN WE REBASE OUR PATCHES #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # !! We (perhaps temporarily) do MORE recursive submodules, since we are tracking ALL in these scripts, while upstream doesn't include all in tarball currently (cd $GIT_DIR && git submodule update --init --recursive &>/dev/null) SUBMODULE_COMMIT_IDS=($(git -C $GIT_DIR submodule status --recursive|awk '{print $1}')) SUBMODULE_DIRS=($(git -C $GIT_DIR submodule status --recursive|awk '{print $2}')) SUBMODULE_COUNT=${#SUBMODULE_COMMIT_IDS[@]} # TODO: do this with simply math - ie: use (( ... )) if [[ "$REPO_COUNT" != "$(expr $SUBMODULE_COUNT + 1)" ]]; then echo "ERROR: submodule count doesn't match the REPO_COUNT variable in config.sh file!" exit fi # We have the submodule commits, but not in the PATCH ORDER which our config.sh has (see $PATCH_PATH_MAP) for (( i=0; i <$REPO_COUNT-1; i++ )); do COMMIT_IDS_BY_SUBMODULE_PATH[${SUBMODULE_DIRS[$i]}/]=${SUBMODULE_COMMIT_IDS[$i]} done COMMIT_IDS_BY_SUBMODULE_PATH[SUPERPROJECT]=$NEW_COMMIT_ISH_FULL #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # MOVE BUNDLE COMMITS OVER TO LOCAL frombundle BRANCH #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! bundle2local #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # REBASE frombundle patches USING COMMIT_IDS_BY_SUBMODULE, ALSO USING OLD ID'S STORED IN OLD BUNDLE #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! mkdir -p $BUNDLE_DIR tar xJf bundles.tar.xz -C $BUNDLE_DIR # Now go through all the submodule local repos that are present and create a bundle file for the patches found there for (( i=0; i <$REPO_COUNT; i++ )); do if [[ -e $(readlink -f ${LOCAL_REPO_MAP[$i]}) ]]; then if $(git -C ${LOCAL_REPO_MAP[$i]} branch | grep -F "frombundle" >/dev/null); then SUBDIR=${PATCH_PATH_MAP[$i]} GITREPO_COMMIT_ISH=($BUNDLE_DIR/$SUBDIR*.id) if [[ $GITREPO_COMMIT_ISH =~ .*(.{40})[.]id ]]; then GITREPO_COMMIT_ISH=${BASH_REMATCH[1]} fi git -C ${LOCAL_REPO_MAP[$i]} checkout frombundle -f git -C ${LOCAL_REPO_MAP[$i]} branch -D $GIT_BRANCH git -C ${LOCAL_REPO_MAP[$i]} checkout -b $GIT_BRANCH if [[ "$SUBDIR" = "" ]]; then SUBDIR=SUPERPROJECT fi if ! $(git -C ${LOCAL_REPO_MAP[$i]} rebase --onto ${COMMIT_IDS_BY_SUBMODULE_PATH[$SUBDIR]} $GITREPO_COMMIT_ISH >/dev/null); then # TODO: record that this one needs manual help! echo "Rebase of ${LOCAL_REPO_MAP[$i]}, branch $GIT_BRANCH needs manual help" REBASE_FAILS="${LOCAL_REPO_MAP[$i]} $REBASE_FAILS" fi fi fi done } #============================================================================== bundle2spec() { rm -f checkpatch.log rm -f checkthese rm -rf checkdir rm -rf $GIT_DIR rm -rf $CMP_DIR rm -rf $BUNDLE_DIR mkdir -p $BUNDLE_DIR #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # NOW PROCESS BUNDLES INTO COMMITS AND FILL SPEC FILE #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! tar xJf bundles.tar.xz -C $BUNDLE_DIR BUNDLE_FILES=$(find $BUNDLE_DIR -printf "%P\n"|grep "bundle$") for entry in ${BUNDLE_FILES[@]}; do if [[ $entry =~ ^(.*)[/]*([a-f0-9]{40})[.]bundle$ ]]; then SUBDIR=${BASH_REMATCH[1]} GITREPO_COMMIT_ISH=${BASH_REMATCH[2]} else echo "ERROR! BAD BUNDLE CONTENT!" exit fi for (( i=0; i <$REPO_COUNT; i++ )); do if [[ "$SUBDIR" = "${PATCH_PATH_MAP[$i]}" ]]; then PATCH_RANGE_INDEX=$i break fi done mkdir -p $GIT_DIR/$SUBDIR git -C $GIT_DIR/$SUBDIR init git -C $GIT_DIR/$SUBDIR remote add origin file://$(readlink -f \ ${LOCAL_REPO_MAP[$PATCH_RANGE_INDEX]}) git -C $GIT_DIR/$SUBDIR fetch origin $GIT_BRANCH git -C $GIT_DIR/$SUBDIR reset --hard $GITREPO_COMMIT_ISH git -C $GIT_DIR/$SUBDIR remote add bundle $BUNDLE_DIR/$entry git -C $GIT_DIR/$SUBDIR fetch bundle FETCH_HEAD git -C $GIT_DIR/$SUBDIR format-patch -N --suffix= --no-renames -o $CMP_DIR -k --stat=72 \ --indent-heuristic --zero-commit --no-signature --full-index \ --src-prefix=a/$SUBDIR --dst-prefix=b/$SUBDIR \ --start-number=$(expr $PATCH_RANGE_INDEX \* $PATCH_RANGE) \ $GITREPO_COMMIT_ISH..FETCH_HEAD > /dev/null done rm -rf $GIT_DIR rm -rf $BUNDLE_DIR ( CHANGED_COUNT=0 UNCHANGED_COUNT=0 DELETED_COUNT=0 ADDED_COUNT=0 TOTAL_COUNT=0 shopt -s nullglob for i in $CMP_DIR/*; do # index line isn't consistent, so cut full index to normal line length sed -E -i 's/(^index [a-f0-9]{28})[a-f0-9]{12}([.][.][a-f0-9]{28})[a-f0-9]{12}( [0-9]{6}$)/\1\2\3/' $i BASENAME=$(basename $i) if [ "$FIVE_DIGIT_POTENTIAL" = "1" ]; then if [[ $BASENAME =~ [[:digit:]]{5}.* ]]; then : else BASENAME=0$BASENAME fi fi if [[ "$NUMBERED_PATCHES" = "0" ]]; then KEEP_COUNT=40+4+$FIVE_DIGIT_POTENTIAL+1 else KEEP_COUNT=40 fi tail -n +2 $i > $CMP_DIR/${BASENAME:0:$KEEP_COUNT}.patch rm $i done if [[ "$NUMBERED_PATCHES" = "0" ]]; then for i in [0-9]*.patch; do osc rm --force $i done # make sure that w/out the numbered prefixes, the patchnames are all unique mkdir checkdir for i in $CMP_DIR/*; do BASENAME=$(basename $i) FINALNAME=${BASENAME:4+$FIVE_DIGIT_POTENTIAL+1:40+1+5} if [[ -e checkdir/$FINALNAME ]]; then echo "ERROR! Patch name $FINALNAME is not unique! Please modify patch subject to achieve uniqueness" exit 1 fi cp $i checkdir/$FINALNAME done CHECK_DIR=checkdir cp $CMP_DIR/*.patch . else CHECK_DIR=$CMP_DIR fi if [ "$FIVE_DIGIT_POTENTIAL" = "0" ]; then CHECK_PREFIX="0" else CHECK_PREFIX="00" fi for i in $CHECK_DIR/*; do BASENAME=$(basename $i) if [ -e $BASENAME ]; then if cmp -s $i $BASENAME; then touch --reference=$BASENAME $i rm $BASENAME let UNCHANGED_COUNT+=1 else if [ "${BASENAME:0:1+$FIVE_DIGIT_POTENTIAL}" = "$CHECK_PREFIX" ]; then echo "$BASENAME" >> checkthese fi rm $BASENAME let CHANGED_COUNT+=1 let TOTAL_COUNT+=1 fi else echo " $BASENAME" >> qemu.changes.added if [ "${BASENAME:0:1+$FIVE_DIGIT_POTENTIAL}" = "$CHECK_PREFIX" ]; then echo "$BASENAME" >> checkthese fi let ADDED_COUNT+=1 let TOTAL_COUNT+=1 fi done if [ "$FIVE_DIGIT_POTENTIAL" = "0" ]; then NUMBERED_PATCH_RE="^[[:digit:]]{4}-.*[.]patch$" else NUMBERED_PATCH_RE="^[[:digit:]]{5}-.*[.]patch$" fi for i in *.patch; do if [[ $i =~ $NUMBERED_PATCH_RE ]]; then if [[ "$NUMBERED_PATCHES" = "1" ]]; then osc rm --force $i echo " $i" >> qemu.changes.deleted let DELETED_COUNT+=1 let TOTAL_COUNT+=1 fi else osc rm --force $i echo " $i" >> qemu.changes.deleted let DELETED_COUNT+=1 let TOTAL_COUNT+=1 fi done mv $CHECK_DIR/* . if [ -e qemu.changes.added ]; then xargs osc add < qemu.changes.added fi if [[ -e checkthese ]]; then tar Jxf qemu-$SOURCE_VERSION$VERSION_EXTRA.tar.xz \ qemu-$SOURCE_VERSION/scripts/checkpatch.pl --strip-components=2 for i in $(cat checkthese); do ./checkpatch.pl --no-tree --terse --no-summary --summary-file \ --patch $i >> checkpatch.log || true done fi rm -f checkthese rm -f checkpatch.pl if [ -s checkpatch.log ]; then echo "WARNING: Issues reported by qemu patch checker. Please handle" \ "ERROR items now:" cat checkpatch.log fi rm -f checkpatch.log if [ "$TOTAL_COUNT" != "0" -a "$VERSION_EXTRA" != "" -a "$OLD_COMMIT_ISH" =\ "$NEW_COMMIT_ISH" ]; then # Only patches changed: update the version using current timestamp VERSION_EXTRA=+git.$NOW_SECONDS.$OLD_COMMIT_ISH osc mv qemu-$OLD_SOURCE_VERSION_AND_EXTRA.tar.xz \ qemu-$SOURCE_VERSION$VERSION_EXTRA.tar.xz osc add qemu-$SOURCE_VERSION$VERSION_EXTRA.tar.xz fi echo "QEMU version file: $QEMU_VERSION" echo "QEMU source version: $SOURCE_VERSION" echo "QEMU version extra: $VERSION_EXTRA" SEABIOS_VERSION=$(tar JxfO qemu-$SOURCE_VERSION$VERSION_EXTRA.tar.xz \ qemu-$SOURCE_VERSION/roms/seabios/.version | cut -d '-' -f 2) for package in qemu; do while IFS= read -r line; do if [ "$line" = "PATCH_FILES" ]; then for i in [0-9]*-*.patch; do NUM=${i%%-*} DIV=$((10#$NUM/$PATCH_RANGE)) REM=$((10#$NUM%$PATCH_RANGE)) if [[ "$REM" = "0" ]]; then if [[ "$DIV" = "0" ]]; then echo "# Patches applied in base project:" else echo "# Patches applied in ${PATCH_PATH_MAP[$DIV]}:" fi fi if [[ "$FIVE_DIGIT_POTENTIAL" != "0" ]]; then if [[ "$NUMBERED_PATCHES" = "0" ]]; then PATCH_NUMBER=${i%%-*} echo -e "Patch$NUM: ${i:${#PATCH_NUMBER}+1:40+1+5}" else echo -e "Patch$NUM: $i" fi else if [[ "$NUMBERED_PATCHES" = "0" ]]; then PATCH_NUMBER=${i%%-*} echo -e "Patch$NUM: ${i:${#PATCH_NUMBER}+1:40+1+5}" else echo -e "Patch$NUM: $i" fi fi done elif [ "$line" = "PATCH_EXEC" ]; then for i in [0-9]*-*.patch; do S=$(grep "^Include-If: " $i) || true NUM=${i%%-*} if [ "$S" != "" ]; then echo "${S:12}" echo "%patch$NUM -p1" echo "%endif" else echo "%patch$NUM -p1" fi done elif [ "$line" = "QEMU_VERSION" ]; then echo "%define qemuver $QEMU_VERSION$VERSION_EXTRA" echo "%define srcver $SOURCE_VERSION$VERSION_EXTRA" echo "Version: %qemuver" elif [[ "$line" =~ ^Source: ]]; then echo "$line" if [ ${#QEMU_TARBALL_SIG[@]} -eq 1 ]; then # We assume the signature file corresponds - just add .sig echo "$line.sig"|sed 's/^Source: /Source99:/' fi elif [ "$line" = "SEABIOS_VERSION" ]; then echo "Version: $SEABIOS_VERSION" else echo "$line" fi done < $package.spec.in > $CMP_DIR/$package.spec if cmp -s $package.spec $CMP_DIR/$package.spec; then echo "$package.spec unchanged" else mv $CMP_DIR/$package.spec $package.spec echo "$package.spec regenerated" let PACKAGE_CHANGED_COUNT+=1 fi if [ "$WRITE_LOG" = "1" ]; then # Factory requires all deleted and added patches to be mentioned if [ -e qemu.changes.deleted ] || [ -e qemu.changes.added ]; then echo "Patch queue updated from ${GIT_TREE} ${GIT_BRANCH}" > \ $package.changes.proposed fi if [ -e qemu.changes.deleted ]; then echo "* Patches dropped:" >> $package.changes.proposed cat qemu.changes.deleted >> $package.changes.proposed fi if [ -e qemu.changes.added ]; then echo "* Patches added:" >> $package.changes.proposed cat qemu.changes.added >> $package.changes.proposed fi if [ -e $package.changes.proposed ]; then osc vc --file=$package.changes.proposed $package rm -f $package.changes.proposed fi fi done if [[ "$NUMBERED_PATCHES" = "0" ]]; then rm -f [0-9]*-*.patch fi if [ -e qemu.changes.deleted ]; then rm -f qemu.changes.deleted fi if [ -e qemu.changes.added ]; then rm -f qemu.changes.added fi if [[ "0" = "$(expr $CHANGED_COUNT + $DELETED_COUNT + $ADDED_COUNT)" ]]; then osc revert bundles.tar.xz fi echo "git patch summary" echo " unchanged: $UNCHANGED_COUNT" echo " changed: $CHANGED_COUNT" echo " deleted: $DELETED_COUNT" echo " added: $ADDED_COUNT" ) rm -rf $CMP_DIR rm -rf checkdir osc service localrun format_spec_file } #============================================================================== usage() { echo "Usage:" echo "bash ./git_update.sh " echo "description: package maintenance using a git-based workflow. Commands:" echo " git2pkg (update package spec file and patches from git. Is default)" echo " pkg2git (update git (frombundle branch) from the package "bundleofbundles")" echo " refresh (refresh spec file from spec file template and "bundlofbundles")" echo "(See script for details on doing 'LATEST' workflow)" } #============================================================================== echo "WARNING: Script using local git repos. Some operations may be time consuming..." #TODO: Most of these checks are not necessary for (( i=0; i <$REPO_COUNT; i++ )); do if [[ -e $(readlink -f ${LOCAL_REPO_MAP[$i]}) ]]; then if [[ -d ${LOCAL_REPO_MAP[$i]}/.git/rebase-merge || \ -d ${LOCAL_REPO_MAP[$i]}/.git/rebase-apply ]]; then echo "ERROR! Rebase appears to be in progress in ${LOCAL_REPO_MAP[$i]}. Please resolve" exit fi if ! git -C ${LOCAL_REPO_MAP[$i]} submodule update --init --recursive &> /dev/null; then echo "Please clean up state of local repo ${LOCAL_REPO_MAP[$i]} before using script" echo "(ensure git submodule update --init --recursive is successful)" exit fi if [ "$(git -C ${LOCAL_REPO_MAP[$i]} status --porcelain)" ]; then echo "Please clean up state of local repo ${LOCAL_REPO_MAP[$i]} before using script" echo "(ensure git status --porcelain produces no output)" exit fi if ! git -C ${LOCAL_REPO_MAP[$i]} checkout master --recurse-submodules -f &> /dev/null; then echo "Please clean up state of local repo ${LOCAL_REPO_MAP[$i]} before using script" echo "(cannot check out master, incl. it's submodules)" exit fi if ! git -C ${LOCAL_REPO_MAP[$i]} submodule update --init --recursive &> /dev/null; then echo "Please clean up state of local repo ${LOCAL_REPO_MAP[$i]} before using script" echo "(cannot init and update master submodules)" exit fi if [ "$(git -C ${LOCAL_REPO_MAP[$i]} status --porcelain)" ]; then echo "Please clean up state of local repo ${LOCAL_REPO_MAP[$i]} before using script" echo "(ensure git status --porcelain produces no output)" exit fi fi done if [ "$GIT_UPSTREAM_COMMIT_ISH" = "LATEST" ]; then if [ "$1" = "continue" ]; then CONTINUE_AFTER_REBASE=1 else if [ "$1" = "pause" ]; then PAUSE_BEFORE_BUNDLE_CREATION=1 else if [ "$1" ]; then echo "ERROR: unrecognized option '$1'. Script in LATEST mode only recognizes 'pause' and 'continue' options" exit fi fi fi for (( i=0; i <$REPO_COUNT; i++ )); do if [[ -e $(readlink -f ${LOCAL_REPO_MAP[$i]}) ]]; then git -C ${LOCAL_REPO_MAP[$i]} remote update upstream &> /dev/null fi done NEW_COMMIT_ISH_FULL=$(cd ${LOCAL_REPO_MAP[0]} && git rev-parse upstream/master) NEW_COMMIT_ISH=${NEW_COMMIT_ISH_FULL:0:8} git -C ${LOCAL_REPO_MAP[0]} checkout $NEW_COMMIT_ISH_FULL --recurse-submodules -f &> /dev/null QEMU_VERSION=$(git -C ${LOCAL_REPO_MAP[0]} show upstream/master:VERSION) MAJOR_VERSION=$(echo $QEMU_VERSION|awk -F. '{print $1}') MINOR_VERSION=$(echo $QEMU_VERSION|awk -F. '{print $2}') X=$(echo $QEMU_VERSION|awk -F. '{print $3}') # 0 = release, 50 = development cycle, 90..99 equate to release candidates if [ "$X" != "0" -a "$X" != "50" ]; then if [ "$NEXT_RELEASE_IS_MAJOR" = "0" ]; then SOURCE_VERSION=$MAJOR_VERSION.$[$MINOR_VERSION+1].0-rc$[X-90] GIT_BRANCH=opensuse-$MAJOR_VERSION.$[$MINOR_VERSION+1] else SOURCE_VERSION=$[$MAJOR_VERSION+1].0.0-rc$[X-90] GIT_BRANCH=opensuse-$[$MAJOR_VERSION+1].0 fi else SOURCE_VERSION=$MAJOR_VERSION.$MINOR_VERSION.$X GIT_BRANCH=opensuse-$MAJOR_VERSION.$[$MINOR_VERSION+1] fi WRITE_LOG=0 echo "Processing LATEST upstream changes" echo "(If SUCCESS is not printed upon completion, see /tmp/latest.log for issues)" TEMP_CHECK if [[ $QEMU_TARBALL =~ $BASE_RE$EXTRA_RE$SUFFIX_RE ]]; then OLD_COMMIT_ISH=${BASH_REMATCH[3]} else #Assume release (or release candidate) tarball with equivalent tag: OLD_COMMIT_ISH=$(cd ${LOCAL_REPO_MAP[0]} && git rev-list --abbrev-commit \ --abbrev=9 -1 v$OLD_SOURCE_VERSION_AND_EXTRA) fi if [ ${#QEMU_TARBALL_SIG[@]} -ne 0 ]; then echo "INFO: Ignoring signature file: $QEMU_TARBALL_SIG" QEMU_TARBALL_SIG= fi NOW_SECONDS=$(date +%s) if [ "$OLD_COMMIT_ISH" != "$NEW_COMMIT_ISH" ]; then if [ "$CONTINUE_AFTER_REBASE" = "1" ]; then echo "continue after rebase selected but tarball is out of date. Continuing not possible." echo "If desired, save your rebase work (eg, branch $GIT_BRANCH), because otherwise it will" echo "be lost. Then run script again without the continue option" exit fi redo_tarball_and_rebase_patches &> /tmp/latest.log if [[ "$REBASE_FAILS" ]]; then echo "ERROR! Rebase of the $GIT_BRANCH branch failed in the following local git repos:" echo $REBASE_FAILS echo "Manually resolve all these rebases, then finish the workflow by passing 'continue' to script" if [[ "$PAUSE_BEFORE_BUNDLE_CREATION" = "1" ]]; then echo "Feel free to also do the work now occasioned by the selected 'pause' option" fi exit fi CONTINUE_AFTER_REBASE=1 fi if [[ "$PAUSE_BEFORE_BUNDLE_CREATION" = "1" ]]; then echo "As requested, pausing before re-creating bundle of bundles for additional patch or specfile work" echo "(using current 'ready to go' $GIT_BRANCH branch of local repos to produce patches.)" echo "When changes are complete, finish the workflow by passing 'continue' to script" exit fi if [ "$CONTINUE_AFTER_REBASE" = "1" ]; then initbundle &>> /tmp/latest.log fi bundle2spec &>> /tmp/latest.log echo "SUCCESS" tail -9 /tmp/latest.log else # not LATEST git -C ${LOCAL_REPO_MAP[0]} checkout $GIT_UPSTREAM_COMMIT_ISH --recurse-submodules -f &> /dev/null NEW_COMMIT_ISH= SOURCE_VERSION=$OLD_SOURCE_VERSION_AND_EXTRA QEMU_VERSION=$(tar JxfO qemu-$SOURCE_VERSION$VERSION_EXTRA.tar.xz qemu-$SOURCE_VERSION/VERSION) MAJOR_VERSION=$(echo $QEMU_VERSION|awk -F. '{print $1}') MINOR_VERSION=$(echo $QEMU_VERSION|awk -F. '{print $2}') GIT_BRANCH=opensuse-$MAJOR_VERSION.$MINOR_VERSION WRITE_LOG=1 if [ "$1" = "" ]; then set -- git2pkg fi case $1 in initbundle ) initbundle ;; git2pkg ) echo "Updating the package using the $GIT_BRANCH branch of the local repos." echo "(If SUCCESS is not printed upon completion, see /tmp/git2pkg.log for issues)" TEMP_CHECK initbundle &> /tmp/git2pkg.log bundle2spec &>> /tmp/git2pkg.log echo "SUCCESS" tail -9 /tmp/git2pkg.log ;; pkg2git ) echo "Exporting the package's git bundles to the local repo's frombundle branches..." echo "(If SUCCESS is not printed upon completion, see /tmp/pkg2git.log for issues)" TEMP_CHECK bundle2local &> /tmp/pkg2git.log echo "SUCCESS" echo "To modify package patches, use the frombundle branch as the basis for updating" echo "the $GIT_BRANCH branch with the new patch queue." echo "Then export the changes back to the package using update_git.sh git2pkg" ;; refresh ) echo "Updating the spec file and patches from the spec file template and the bundle" echo "of bundles (bundles.tar.xz)" echo "(If SUCCESS is not printed upon completion, see /tmp/refresh.log for issues)" TEMP_CHECK bundle2spec &> /tmp/refresh.log echo "SUCCESS" tail -9 /tmp/refresh.log ;; * ) echo "Unknown command" usage ;; help ) usage ;; esac fi exit