#!/bin/bash # Copyright © 2012-2014 Intel Corporation # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice (including the next # paragraph) shall be included in all copies or substantial portions of the # Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. # # Authors: # Daniel Vetter <daniel.vetter@ffwll.ch> # drm-intel-next maintainer script # TODO # - Add functions to setup/update all the branches/trees # - Improve docs/workflow for topic branches # - extract the integration tree logic and make it generally useful, maybe for a # drm-integration tree ... # fail on any goof-up set -e # # User configuration. Set in environment or configuration file. See # dimrc.sample for an example. # # dim configuration file DIM_CONFIG=${DIM_CONFIG:-$HOME/.dimrc} if [ -r $DIM_CONFIG ]; then . $DIM_CONFIG fi # prefix for repo directories DIM_PREFIX=${DIM_PREFIX:-$HOME/linux} # main maintainer repo under $DIM_PREFIX DIM_DRM_INTEL=${DIM_DRM_INTEL:-src} # name of the $drm_intel_git remote within $DIM_DRM_INTEL DIM_DRM_INTEL_REMOTE=${DIM_DRM_INTEL_REMOTE:-danvet} # name of the $drm_upstream_git remote within $DIM_DRM_INTEL DIM_DRM_UPSTREAM_REMOTE=${DIM_DRM_UPSTREAM_REMOTE:-airlied} # mail user agent. must support a subset of mutt(1) command line options: # usage: $DIM_MUA [-s subject] [-i file] [-c cc-addr] to-addr [...] DIM_MUA=${DIM_MUA:-mutt} # # Internal configuration. # today=`date +%Y-%m-%d` nightly_branches="origin/drm-intel-next-queued origin/drm-intel-fixes" nightly_branches="$nightly_branches drm-upstream/drm-next drm-upstream/drm-fixes" nightly_branches="$nightly_branches origin/topic/core-stuff" drm_intel_git=ssh://git.freedesktop.org/git/drm-intel drm_upstream_git=git://people.freedesktop.org/~airlied/linux linux_upstream_git=git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git # email aliases addr_drm_maintainer="Dave Airlie <airlied@gmail.com>" addr_intel_gfx_maintainer1="Daniel Vetter <daniel.vetter@ffwll.ch>" addr_intel_gfx_maintainer2="Jani Nikula <jani.nikula@linux.intel.com>" addr_intel_gfx="intel-gfx@lists.freedesktop.org" addr_dri_devel="dri-devel@lists.freedesktop.org" addr_intel_qa="Terence Yang <guang.a.yang@intel.com>" # # Command line options. # DRY_RUN= DRY= while getopts d opt; do case "$opt" in d) DRY_RUN=--dry-run DRY=echo ;; *) exit esac done shift `expr $OPTIND - 1` # first positional argument is the subcommand subcommand="$1" shift function update_linux_next { cd $DIM_PREFIX/$DIM_DRM_INTEL if git grep "EXTRAVERSION.*=" origin/master Makefile | grep rc > /dev/null ; then echo linux-next: -rc phase if [[ $1 == queued ]] ; then echo Updating for-linux-next to -queued and updating for-linux-next-fixes git push $DRY_RUN $DIM_DRM_INTEL_REMOTE +drm-intel-next-queued:for-linux-next >& /dev/null git push $DRY_RUN $DIM_DRM_INTEL_REMOTE +drm-intel-fixes:for-linux-next-fixes >& /dev/null fi if [[ $1 == fixes ]] ; then echo Updating for-linux-next-fixes git push $DRY_RUN $DIM_DRM_INTEL_REMOTE +drm-intel-fixes:for-linux-next-fixes >& /dev/null fi else echo linux-next: merge window if [[ $1 == fixes ]] ; then echo Updating for-linux-next to -fixes git push $DRY_RUN $DIM_DRM_INTEL_REMOTE +drm-intel-fixes:for-linux-next >& /dev/null fi fi } function check_conflicts { if git diff | grep '<<<<<<<' ; then echo conflict found exit 1 fi if git diff | grep '=======' ; then echo conflict found exit 1 fi if git diff | grep '>>>>>>>' ; then echo conflict found exit 1 fi if git diff | grep '|||||||' ; then echo conflict found exit 1 fi true } function update_nightly { local integration_branch=drm-intel-nightly local specfile=`mktemp` local time=`date +%Yy-%mm-%dd-%Hh-%Mm-%Ss` local first=1 cd $DIM_PREFIX/$integration_branch # git fetch returns 128 if there's nothing to be fetched git fetch origin >& /dev/null || true # don't auto-fetch drm-upstream to avoid including -rc1 too early #git fetch drm-upstream >& /dev/null || true # merge -fixes for branch in $nightly_branches; do local name=${branch##*/} if [ $first == 1 ] ; then git reset --hard $branch >& /dev/null first=0 else git merge --rerere-autoupdate --no-commit $branch >& /dev/null || true if [ -f ../$integration_branch-$name-fixup.patch ] ; then echo applying manual fixup patch for $integration_branch merge ... git apply --index ../$integration_branch-$name-fixup.patch fi check_conflicts git add -u git commit --no-edit || true fi echo $branch `git rev-parse $branch` >> $specfile done mv $specfile integration-manifest git add integration-manifest git commit -m "$integration_branch: $time integration manifest" git push $DRY_RUN origin +HEAD >& /dev/null && echo "$integration_branch branch successfully updated" cd $DIM_PREFIX/drm-intel-rerere/ if git branch | grep rerere-cache | grep '\*' >& /dev/null ; then git pull >& /dev/null git rm *.patch >& /dev/null || true cp $DIM_PREFIX/$integration_branch/.git/rr-cache/* rr-cache -r cp ../$integration_branch*fixup.patch . >& /dev/null || true git add *.patch >& /dev/null || true git add rr-cache/* > /dev/null if git commit -m "$time: $integration_branch rerere cache update" >& /dev/null; then git push $DRY_RUN origin HEAD >& /dev/null && echo "rerere cache successfully updated" else echo "nothing changed in the rerere cache" fi else echo "Branch setup for the rerere-cache is borked" fi } function check_repo_clean { cd $1 if ! git diff-index --quiet HEAD ; then echo $2 repo not clean, aborting exit 1 fi } function dim_checkpatch # $1 is the git sha1 to check { git show $1 --pretty=email | scripts/checkpatch.pl --strict - || true git show $1 | grep '^\+.*\WBUG' > /dev/null && echo -e "\n\nWARNING: New BUG macro added\n" || true git show $1 | grep '^\+.*drm_i915_private_t' > /dev/null && echo -e "\n\nWARNING: New drm_i915_private_t added\n" || true } function prep_pull_mail_tags { cat > ~/tmp/dim-pull-request <<-HERE Hi Dave, HERE for tag in $@ ; do local obj=`git rev-parse $tag` if [[ `git cat-file -t $obj` == "tag" ]] ; then echo $tag: >> ~/tmp/dim-pull-request git cat-file -p $obj | tail -n+6 >> ~/tmp/dim-pull-request fi done cat >> ~/tmp/dim-pull-request <<-HERE Cheers, Daniel HERE } function prep_pull_mail { cat > ~/tmp/dim-pull-request <<-HERE Hi Dave, <insert pull request overview here> Cheers, Daniel HERE } function setup_dim { cd $DIM_PREFIX if [ ! -d $DIM_DRM_INTEL ]; then echo "please set up $DIM_PREFIX/$DIM_DRM_INTEL (or update config)" exit 1 fi cd $DIM_DRM_INTEL if ! git remote -v | grep "^origin[[:space:]]" | grep $linux_upstream_git > /dev/null; then echo "please set up remote origin for $linux_upstream_git" exit 1 fi if ! git remote -v | grep "^$DIM_DRM_INTEL_REMOTE[[:space:]]" | grep $drm_intel_git > /dev/null; then echo "please set up remote $DIM_DRM_INTEL_REMOTE for $drm_intel_git (or update config)" exit 1 fi if ! git remote -v | grep "^$DIM_DRM_UPSTREAM_REMOTE[[:space:]]" | grep $drm_upstream_git > /dev/null; then echo "please set up remote $DIM_DRM_UPSTREAM_REMOTE for $drm_upstream_git (or update config)" exit 1 fi cd .. if [ ! -d maintainer-tools ]; then git clone $drm_intel_git maintainer-tools fi cd maintainer-tools git config remote.origin.url $drm_intel_git if ! git branch | grep maintainer-tools > /dev/null ; then git checkout -t origin/maintainer-tools fi cd .. if [ ! -d drm-intel-rerere ]; then git clone $drm_intel_git drm-intel-rerere fi cd drm-intel-rerere git config remote.origin.url $drm_intel_git if ! git branch | grep rerere-cache > /dev/null ; then git checkout -t origin/rerere-cache fi cd .. if [ ! -d drm-intel-nightly ]; then git clone $drm_intel_git drm-intel-nightly fi cd drm-intel-nightly mkdir -p .git/rr-cache git config remote.origin.url $drm_intel_git if git remote | grep drm-upstream > /dev/null ; then git config remote.drm-upstream.url $drm_upstream_git else git remote add drm-upstream $drm_upstream_git fi } cd $DIM_PREFIX/$DIM_DRM_INTEL case "$subcommand" in setup) setup_dim ;; upload-docs) # cd back cd - make htmldocs $DRY scp -r Documentation/DocBook/drm annarchy.freedesktop.org:~/public_html ;; nightly-forget) cd $DIM_PREFIX/drm-intel-nightly git fetch origin >& /dev/null git reset --hard origin/drm-intel-next-queued >& /dev/null git merge origin/drm-intel-fixes git rerere forget ;; update-branches|ub) git fetch $DIM_DRM_INTEL_REMOTE check_repo_clean $DIM_PREFIX/$DIM_DRM_INTEL Kernel dim co git rebase -i $DIM_DRM_INTEL_REMOTE/drm-intel-next-queued dim cof git rebase -i $DIM_DRM_INTEL_REMOTE/drm-intel-fixes git checkout drm-intel-next git reset --hard $DIM_DRM_INTEL_REMOTE/drm-intel-next # TODO: Restore -nightly merge state from the rerere-cache # branch cd $DIM_PREFIX/drm-intel-rerere/ git fetch origin cp rr-cache/* $DIM_PREFIX/drm-intel-nightly/.git/rr-cache/ -r rm $DIM_PREFIX/*fixup.patch &> /dev/null || true cp *.patch $DIM_PREFIX &> /dev/null || true ;; rebuild-nightly) update_nightly ;; push-queued|pq) if git branch | grep drm-intel-next-queued | grep '\*' ; then git push $DRY_RUN $DIM_DRM_INTEL_REMOTE drm-intel-next-queued $@ update_nightly update_linux_next queued else echo "You're on the wrong branch." fi ;; push-fixes|pf) if git branch | grep drm-intel-fixes | grep '\*' ; then git push $DRY_RUN $DIM_DRM_INTEL_REMOTE drm-intel-fixes $@ update_nightly update_linux_next fixes else echo "You're on the wrong branch." fi ;; co) git checkout drm-intel-next-queued ;; cof) git checkout drm-intel-fixes ;; apply-branch|ab) branch=$1 shift if git branch | grep $branch | grep '\*' ; then git am -3 $@ dim_checkpatch HEAD git commit --amend & else echo "You're on the wrong branch." fi ;; apply-queued|aq) dim apply-branch drm-intel-next-queued $@ ;; apply-fixes|af) dim apply-branch drm-intel-fixes $@ ;; apply-resolved|ar) make -j 20 && git add -u && git am --resolved dim_checkpatch HEAD git commit --amend & ;; apply-igt|ai) cd ~/xorg/intel-gpu-tools/ git am -3 -s ;; magic-patch|mp) conflict_files=`patch -p1 | grep "saving rejects" | sed -e "s/.*saving rejects to file \(.*\)/\1/"` if [[ $conflict_files != "" ]] ; then echo conflicts found! fi for file in $conflict_files ; do echo wiggling in ${file%.rej}: #cat $file rm -f ${file%.rej}.porig wiggle -r ${file%.rej} $file || true done ;; magic-rebase-resolve|mrr) git diff HEAD | patch -p1 -R cat .git/rebase-merge/patch | dim mp make -j 20 git add -u git rebase --continue ;; tc) git tag --contains $2 | grep ^v | sort -V | head -n 1 ;; check-patch|cp) if [ "x$2" == "x" ] ; then dim_checkpatch HEAD else dim_checkpatch $2 fi ;; pull-request) upstream=$DIM_DRM_UPSTREAM_REMOTE/drm-next if [[ "x$2" != "x" ]] ; then upstream=$2 fi echo Using $upstream as the upstream # generate tag list drm_intel_next_tags=`git log drm-intel-next ^$upstream --decorate | grep "(.*tag: drm-intel-next-" | sed -e "s/^.*(.*tag:.*\(drm-intel-next-[^ ,]*\).*)$/\1/"` prep_pull_mail_tags $drm_intel_next_tags git request-pull $upstream $drm_intel_git $DIM_DRM_INTEL_REMOTE/drm-intel-next >> ~/tmp/dim-pull-request $DIM_MUA -s "[PULL] drm-intel-next" \ -i ~/tmp/dim-pull-request \ -c "$addr_intel_gfx" \ -c "$addr_dri_devel" \ -c "$addr_intel_gfx_maintainer1" \ -c "$addr_intel_gfx_maintainer2" \ "$addr_drm_maintainer" ;; pull-request-fixes) upstream=origin/master if [[ "x$2" != "x" ]] ; then upstream=$2 fi echo Using $upstream as the upstream $DRY git tag -f drm-intel-fixes-$today $DIM_DRM_INTEL_REMOTE/drm-intel-fixes $DRY git push -f $DIM_DRM_INTEL_REMOTE drm-intel-fixes-$today prep_pull_mail git request-pull $upstream $drm_intel_git $DIM_DRM_INTEL_REMOTE/drm-intel-fixes >> ~/tmp/dim-pull-request $DIM_MUA -s "[PULL] drm-intel-fixes" \ -i ~/tmp/dim-pull-request \ -c "$addr_intel_gfx" \ -c "$addr_dri_devel" \ -c "$addr_intel_gfx_maintainer1" \ -c "$addr_intel_gfx_maintainer2" \ "$addr_drm_maintainer" ;; pull-request-topic) if [[ "x$3" != "x" ]] ; then branch=$2 else no branch given fi if [[ "x$2" != "x" ]] ; then upstream=$3 else no upstream given fi prep_pull_mail git request-pull $upstream $drm_intel_git $DIM_DRM_INTEL_REMOTE/$branch >> ~/tmp/dim-pull-request $DIM_MUA -s "[PULL] topic" \ -i ~/tmp/dim-pull-request \ -c "$addr_intel_gfx" \ -c "$addr_dri_devel" \ -c "$addr_intel_gfx_maintainer1" \ -c "$addr_intel_gfx_maintainer2" \ "$addr_drm_maintainer" ;; update-next) cd $DIM_PREFIX/$DIM_DRM_INTEL git fetch $DIM_DRM_INTEL_REMOTE if ! git branch --merged $DIM_DRM_INTEL_REMOTE/drm-intel-nightly | grep drm-intel-fixes &> /dev/null ; then echo "drm-intel-fixes not merged into -nigthly, please update!" exit 2 fi if ! git branch --merged $DIM_DRM_INTEL_REMOTE/drm-intel-nightly | grep drm-intel-next-queued &> /dev/null ; then echo "drm-intel-next-queued not merged into -nigthly, please update!" exit 2 fi gitk drm-intel-next-queued ^$DIM_DRM_UPSTREAM_REMOTE/drm-next & git push $DRY_RUN $DIM_DRM_INTEL_REMOTE drm-intel-next-queued:drm-intel-next tag=drm-intel-next-$today $DRY git tag -f -a $tag $DIM_DRM_INTEL_REMOTE/drm-intel-next git push $DRY_RUN -f $DIM_DRM_INTEL_REMOTE $tag echo "Updating -testing to latest -nightly" git push $DRY_RUN $DIM_DRM_INTEL_REMOTE +$DIM_DRM_INTEL_REMOTE/drm-intel-nightly:drm-intel-testing cat > ~/tmp/test-request <<-HERE Hi all, New -testing cycle with cool stuff: HERE obj=`git rev-parse $tag` if [[ `git cat-file -t $obj` == "tag" ]] ; then git cat-file -p $obj | tail -n+6 >> ~/tmp/test-request else echo "<tag doesn't contain a changelog overview, fix this>" >> ~/tmp/test-request fi cat >> ~/tmp/test-request <<-HERE Happy testing! Cheers, Daniel HERE $DIM_MUA -s "Updated drm-intel-testing" \ -i ~/tmp/test-request \ -c "$addr_intel_gfx" \ -c "$addr_intel_gfx_maintainer1" \ -c "$addr_intel_gfx_maintainer2" \ "$addr_intel_qa" ;; checker) rm drivers/gpu/drm/i915/*.o &> /dev/null || true rm drivers/gpu/drm/i915/*.ko &> /dev/null || true make C=1 drivers/gpu/drm/i915/i915.ko ;; *) exec ${PAGER:-cat} <<-HERE dim drm-intel maintainer script =============================== setup prefix Setup git maintainer branches in the given prefix. nightly-forget Forget git rerere solutions for nightly merges in case they contain a bogus merge resolution. update-branches Updates all maintainer branches. rebuild-nightly Rebuilds the nightly branch. Useful when ad-hoc trees are included in -nightly. push-queued|pq [git push arguments] push-fixes|pf [git push arguments] Updates the drm-intel-fixes or the drm-intel-next-queued branch respectively. Complains if that's not the current branch, assuming that patches got merged to the wrong branch. co cof Checks out the drm-intel-fixes branch or dinq respectively for merging patches. apply-branch|ab branch [git am arguments] Applys a patch to the given branch, complaining if it is not checked out yet. apply-queued|aq [git am arguments] apply-fixes|af [git am arguments] Applies a patch to fixes or queued respectively, complains if it's not the right branch. Additional arguments are passed to git am. magic-patch|mp Apply a patch using patch and then wiggle in any conflicts. magic-rebase-resolve|mrr Tries to resolve a rebase conflict by first resetting the tree and the using the magic patch tool. Then builds the tree, adds any changes with git add -u and continues the rebase. apply-resolved|ar Compile-test the current tree and if successfully resolve a confilicted git am. Also runs the patch checker afterwards. apply-igt|ai Apply a patch to the i-g-t repository. tc <commit-ish> Prints the linux kernel tag which contains the supplied commit-ish check-patch|cp [commit-ish] Runs a commit through the check tools like when applying a patch. Git commit-ish can be passed in, defaults to HEAD pull-request [upstream] pull-request-fixes [upstream] Create a tag for the -fixes, but no tag is created for -next since that's already been done by update-next. Then prepares a pull request in ~/tmp/dim-pull-request. The upstream for -fixes defaults to origin/master, the upstream for -next defaults to airlied/drm-next Since the tag for -fixes is based only on the day (and not the exact time) and there's not tag being pushed for -next the pull request can be regenerated with the same commands if the upstream was wrong. Then fires up mutt with the pre-generated email with subject and recipients already set. pull-request-topic branch upstream Generates a pull request for the given topic-branch/upstream combo and fires up mutt with the pre-generated email. update-next Pushes out the latest dinq to drm-intel-next and tags it. Also pushes out the latest nightly to drm-intel-testing. For an overview a gitk view of the currently unmerged feature pile is opened. Also checks that the drm-intel-fixes|-next-queued are fully merged into -nightly to avoid operator error. upload-docs Generate html kernel docs and upload the drm DocBook to the private fdo space. Note that this always uses the kernel sources in the current directory. checker Run sparse on the kernel. HERE ;; esac