Skip to content
Snippets Groups Projects
dim 64.7 KiB
Newer Older
	tags=$(printf -- "$dim_extract_tags_marker\n%s" "$tags" | escape_quotes)
	FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch -f --msg-filter "cat ; echo \"$tags\"" $range
}

function dim_extract_queued
{
	dim_extract_tags drm-intel-next "$@"
}

function dim_extract_fixes
{
	dim_extract_tags drm-intel-fixes "$@"
}

function dim_extract_next_fixes
{
	dim_extract_tags drm-intel-next-fixes "$@"
}

dim_alias_cp=checkpatch
function dim_checkpatch
{
	range=$(rangeish "${1:-}")

	for commit in $(git rev-list --reverse $range); do
		if ! checkpatch_commit $commit $profile; then
function _restore_head_on_exit
{
	local original_ref
	original_ref="$(git rev-parse --abbrev-ref HEAD)"
	if [ "$original_ref" == "HEAD" ]; then
		original_ref="$(git rev-parse HEAD)"
	fi
	# we want to expand this now
	# shellcheck disable=SC2064
	trap "git checkout -q $original_ref" EXIT
	local range rv sr prev_sr prev_remapped diff_result remap_log commits fast prev_rev
	if [ "$1" == "--fast" ]; then
		fast=1
		shift
	fi

	prev_rev="HEAD~"
	range=$(rangeish "${1:-}")
	remap_log=$DIM_PREFIX/maintainer-tools/remap-log
	if [ ! -e  $remap_log ]; then
		echo "$remap_log is not compailed, please run make in maintainer-tools dir!"
		exit 1
	fi
	echo "Sparse version: $(sparse --version)"

	_restore_head_on_exit
	# make the initial reference build
	commits=( $(git rev-list --reverse $range) )
	git checkout --detach  ${commits[0]}~ > /dev/null 2>&1
	make olddefconfig > /dev/null 2>&1
	make -j8 drivers/gpu/drm/ > /dev/null 2>&1
	if [ "$fast" == 1 ]; then
		prev_rev="${commits[0]}~"
		commits=( "${commits[-1]}" )

		echo "Fast mode used, each commit won't be checked separately."
	fi

	for commit in "${commits[@]}"; do
		touch --no-create $(git diff --name-only $commit~...$commit)
		prev_sr="$(make C=1 -j$(nproc) drivers/gpu/drm/ 2>&1 1>/dev/null)"
		git checkout --detach $commit >/dev/null 2>&1
		make olddefconfig > /dev/null 2>&1
		sr="$(make C=1 -j$(nproc) drivers/gpu/drm/ 2>&1 1>/dev/null)"
		prev_remapped="$(echo "$prev_sr" | $remap_log <(git diff $prev_rev | $remap_log))"
		diff_result="$(diff -u <(echo "$prev_remapped" | sort) <(echo "$sr" | sort) || true)"
		if [ "$fast" != 1 ]; then
			echo "Commit: $(git log -n1 --format='%s' $commit)"
		fi
		if [ -n "$diff_result" ]; then
			echo "$diff_result" | grep -E '^[+-]' | grep -E -v '^[+-]{3}'
		else
			echo "Okay!"
		fi
		echo
		if (echo "$diff_result" | grep -q '^+'); then
			rv=1
		fi
		prev_sr="$sr"
Jani Nikula's avatar
Jani Nikula committed
function dim_checker
{
	rm -f drivers/gpu/drm/i915/*.o drivers/gpu/drm/i915/*.ko
Jani Nikula's avatar
Jani Nikula committed
	make C=1 drivers/gpu/drm/i915/i915.ko
}

function prep_pull_mail_greetings
{
	if [ -r $DIM_TEMPLATE_HELLO ]; then
		cat $DIM_TEMPLATE_HELLO
	fi
}

function prep_pull_mail_signature
{
	if [ -r $DIM_TEMPLATE_SIGNATURE ]; then
		cat $DIM_TEMPLATE_SIGNATURE
	fi
}

# print pull mail overview based on tags in $@, if any
# without tags, print a reminder
function prep_pull_mail_overview
Simona Vetter's avatar
Simona Vetter committed
{
	if [ "$#" = "0" ]; then
		echo "*** PULL REQUEST OVERVIEW HERE ***"
		for tag in "$@"; do
			obj=$(git rev-parse $tag)
			if [[ "$(git cat-file -t $obj)" == "tag" ]] ; then
				git cat-file -p $obj | tail -n+6 | sed -n '/^-----BEGIN PGP SIGNATURE-----$/q;p'
Simona Vetter's avatar
Simona Vetter committed
}

# prepare a pull request mail
# $@: tags, if any, to extract into the pull request overview
Simona Vetter's avatar
Simona Vetter committed
function prep_pull_mail
{
	local file
	file=$1
	shift
	prep_pull_mail_greetings > $file
	$DRY prep_pull_mail_overview "$@" >> $file
	prep_pull_mail_signature >> $file
Simona Vetter's avatar
Simona Vetter committed
}

dim_alias_create_worktree=create-workdir
function dim_create_workdir
	if [[ "$branches" = "all" ]]; then
		branches=$dim_branches
	fi

	for branch in $branches ; do
		if [[ -d $branch ]] ; then
			continue;
		fi

		echo Creating separate workdir for $branch

		cd $DIM_REPO
		$DRY git worktree prune
		$DRY git worktree add $DIM_PREFIX/$branch $branch
		cd $DIM_PREFIX
dim_alias_fw=for-each-workdir
function dim_for_each_workdir
	cd $DIM_PREFIX/$DIM_REPO
	for branch in $dim_branches ; do
		if [[ -d $DIM_PREFIX/$branch ]] ; then
			cd $DIM_PREFIX/$branch
function tag_name
{
	local prefix suffix tag
	prefix=$1
	tag="$prefix-$dim_today"
	while git tag -l $tag | grep -q $tag ; do
		tag="$prefix-$dim_today-$((++suffix))"
	done
	echo "$tag"
}

function tag_summary # branch
{
	local branch tag_template
	branch=$1
	tag_template=$DIM_PREFIX/drm-rerere/tag-templates/${branch//\//-}.txt

	if [ -r $tag_template ]; then
		cat $tag_template
	else
		cat <<-EOF
		UAPI Changes:

		Cross-subsystem Changes:

		Core Changes:

		Driver Changes:

		EOF
	fi
}

function tag_branch
{
Lucas De Marchi's avatar
Lucas De Marchi committed
	local remote tag branch key_arg="" summary_file
	remote=$(branch_to_remote $branch)
	if ! git merge-base --is-ancestor $branch $remote/$branch ; then
		echoerr "Branch contains local commits. Aborting."
		exit 1
	fi

	if [ "$DIM_GPG_KEYID" == "git" ]; then
		key_arg="-s"
	elif [ -n "$DIM_GPG_KEYID" ]; then
		key_arg="-s -u $DIM_GPG_KEYID"
	else
		key_arg="-a"
	fi

Lucas De Marchi's avatar
Lucas De Marchi committed
	summary_file=$(mktemp)
	tag_summary $branch > "$summary_file"
	$DRY git tag -e -F "$summary_file" $key_arg $tag "$branch@{upstream}"
	rm "$summary_file"
	if [ -n "$DRY" ]; then
		tag=$(git rev-parse "$branch@{upstream}"):refs/tags/$tag
	fi
	git_push $remote $tag && echo "$DONE_OR_SKIP"
# $1: commit subject prefix
# $2: file
function dim_update_driver_date
{
	local prefix file driver_date driver_timestamp

	prefix=${1:?$usage}
	file=${2:?$usage}

	driver_date=$(date +%Y%m%d)
	driver_timestamp=$(date +%s)

	$DRY sed -i -e "s/^#define DRIVER_DATE.*\"[0-9]*\"$/#define DRIVER_DATE\t\t\"$driver_date\"/; s/^#define DRIVER_TIMESTAMP.*/#define DRIVER_TIMESTAMP\t$driver_timestamp/" "$file"
	$DRY git add "$file"
	git commit $DRY_RUN -sm "$prefix: Update DRIVER_DATE to $driver_date"
}

function dim_update_i915_driver_date
	dim_update_driver_date "drm/i915" "drivers/gpu/drm/i915/i915_drv.h"
function dim_tag_branch
	local branch upstream remote tag unmerged_tags
	assert_branch $branch
	remote=$(branch_to_remote $branch)
	cd $DIM_PREFIX/$DIM_REPO
	git fetch $remote
	if [ $(git rev-parse $branch) != $(git rev-parse "$branch@{u}") ]; then
		echoerr "ERROR: $branch not up-to-date"
		return 1

	echo "Tagging current $branch"

	if [[ -n "$upstream" ]]; then
		# If there are unmerged tags, show changes since last
		unmerged_tags=$(git_unmerged_tags "$branch" "$upstream")
		if [[ -n "$unmerged_tags" ]]; then
			upstream="${unmerged_tags%% *}"
		fi

		gitk --first-parent "$branch" "^$upstream" &
	fi

	tag=$(tag_name "$branch")
	tag_branch $tag $branch
function dim_pull_request # branch upstream [tag]
	local branch upstream remote repo req_file url_list git_url tag
	branch=${1:?$usage}
	upstream=${2:?$usage}
	remote=$(branch_to_remote $branch)
	req_file=$(mktemp)
Simona Vetter's avatar
Simona Vetter committed
	git_fetch_helper ${upstream%%/*}
	echo "Using $upstream as the upstream"

	checkpatch_commit_push_range 1 "$upstream..${tag:-$branch}"

	if [ -z "$tag" ]; then
		tag=$(tag_name "$branch")
		gitk --first-parent "$branch" ^$upstream &
		tag_branch $tag $branch
	elif ! git ls-remote $remote "refs/tags/$tag"; then
		echoerr "ERROR: $tag does not exist in remote $remote"
		return 1
	fi

	repo=$(branch_to_repo $branch)
	git_url=$(pick_protocol_url https $url_list)
	$DRY git -c diff.algorithm=histogram request-pull \
		$upstream $git_url $tag >> $req_file
Simona Vetter's avatar
Simona Vetter committed
	$DRY $DIM_MUA -s "[PULL] $branch" \
		-i $req_file "${dim_pull_request_recipients[@]}"
function dim_pull_request_next
{
	upstream=${1:-$(branch_to_remote drm-next)/drm-next}
	dim_pull_request drm-intel-next $upstream
}

function dim_pull_request_fixes
{
	upstream=${1:-origin/master}
	dim_pull_request drm-intel-fixes $upstream
}

function dim_pull_request_next_fixes
{
	upstream=${1:-$(branch_to_remote drm-next)/drm-next}
	dim_pull_request drm-intel-next-fixes $upstream
}

# Note: used by bash completion
function dim_list_upstreams
{
	cd $DIM_PREFIX/$DIM_REPO

	echo $(branch_to_remote drm-next)/drm-next
	echo $(branch_to_remote drm-fixes)/drm-fixes
# Note: used by bash completion
function dim_list_branches
{
	echo $dim_branches | sed 's/ /\n/g'
}

dim_alias_ub=update-branches
function dim_update_branches
{
	local repo remote
	cd $DIM_PREFIX/$DIM_REPO

	for branch in $dim_branches ; do
		if ! git_branch_exists $branch ; then
			continue
		fi
		dim_checkout $branch
		repo=$(branch_to_repo $branch)
		remote=$(repo_to_remote $repo)
		if ! $DRY git merge --ff-only $remote/$branch; then
			$DRY git rebase -i
		fi
	done
	cd $DIM_PREFIX/maintainer-tools
	if git_is_current_branch master || git_is_current_branch maintainer-tools; then
		echo "Updating maintainer-tools..."
		git pull --rebase
	fi

	update_rerere_cache
}

Simona Vetter's avatar
Simona Vetter committed
function dim_status
{
	local repo remote patches
	local drm_next_upstream drm_fixes_upstream
	cd $DIM_PREFIX/$DIM_REPO
Simona Vetter's avatar
Simona Vetter committed
	for branch in $dim_branches ; do
		repo=$(branch_to_repo $branch)
		remote=$(repo_to_remote $repo)
		drm_next_upstream=$(branch_to_remote drm-fixes)/drm-fixes
		drm_fixes_upstream=$(branch_to_remote drm-next)/drm-next
		patches=$(git log --oneline $remote/$branch ^origin/master \
			^$drm_next_upstream ^$drm_fixes_upstream | wc -l)
Simona Vetter's avatar
Simona Vetter committed

		if [[ $patches -ne 0 ]] ; then
			echo $repo/$branch: $patches unmerged patches
		fi
	done
}

function bootstrap_drm_rerere
	local name dir remote url_list
	url_list="ssh://git@gitlab.freedesktop.org/drm/tip.git https://gitlab.freedesktop.org/drm/tip.git"
	name="rerere-cache"
	dir="drm-rerere"

	echo "Setting up $dir ..."

	if [ ! -d $dir ]; then
		cd $DIM_PREFIX/$DIM_REPO
		remote=$(url_to_remote $url_list)
		if ! git_branch_exists $name ; then
			git_fetch_helper $remote
			git branch --track $name $remote/$name
		git worktree add $DIM_PREFIX/$dir $name
		remote=$(url_to_remote $url_list)
	if ! git_branch_exists $name ; then
		git checkout -t $remote/$name
	fi
	cd - > /dev/null
function parse_opt_dim_setup # options
{
	local OPTS arg

	OPTS=$(getopt --option y --long yes,reference: -n 'dim setup' -- "$@")

	eval set -- "$OPTS"

	while true; do
		case "$1" in
		-y|--yes)
			ASK_USER_ASSUME_YES=1
			shift
			;;
		--reference)
			DIM_KERNEL_REFERENCE=$2
			shift 2
			;;
		--)
			shift; break ;;
		esac
	done
}

function dim_setup # options
Simona Vetter's avatar
Simona Vetter committed
{
	local remote drm_tip_ssh url_list url cmd_args
	parse_opt_dim_setup "$@"

	url_list=("git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git" "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git")
	if [[ -n "$DIM_PREFERRED_PROTOCOL" ]]; then
		# shellcheck disable=SC2068
		url=$(pick_protocol_url "$DIM_PREFERRED_PROTOCOL" ${url_list[@]})
	else
		url=${url_list[0]}
	fi
	if [[ ! -d "$DIM_PREFIX" ]]; then
		if ask_user "The DIM_PREFIX repository directory '$DIM_PREFIX' doesn't exist. Create?"; then
			mkdir -p "$DIM_PREFIX"
		else
			echoerr "Please set up your DIM_PREFIX repository directory with"
			echoerr "    mkdir -p $DIM_PREFIX"
			echoerr "or update your configuration (see dimrc.sample)."
			exit 1
		fi
	fi

	cd $DIM_PREFIX

	if [[ ! -d "$DIM_REPO" ]]; then
		if ask_user "The DIM_REPO maintainer kernel repository '$DIM_REPO' doesn't exist. Clone upstream?"; then
			cmd_args=()

			if [[ -n "$DIM_KERNEL_REFERENCE" ]]; then
				cmd_args+=("--reference-if-able" "$DIM_KERNEL_REFERENCE" "--dissociate")
			fi

			git clone "${cmd_args[@]}" "$url" "$DIM_REPO"
Simona Vetter's avatar
Simona Vetter committed

	if [[ ! -d "$(git_dir $DIM_REPO)" ]]; then
		echoerr "No kernel git checkout found in '$DIM_REPO'."
		echoerr "Please set up your DIM_REPO maintainer kernel repository at '$DIM_REPO' with:"
		echoerr "    cd $DIM_PREFIX"
		echoerr "    git clone $url $DIM_REPO"
		echoerr "or update your configuration (see dimrc.sample)."
Lucas De Marchi's avatar
Lucas De Marchi committed
	if [[ ! -d "$(git_dir maintainer-tools 2>/dev/null)" ]]; then
		if ask_user "No maintainer-tools git checkout found in 'maintainer-tools'. Clone upstream?"; then
			git clone "$maintainer_tools_https" "maintainer-tools"
		else
			echoerr "No maintainer-tools git checkout found in 'maintainer-tools'."
			echoerr "dim update will not work. Please fix."
		fi
Simona Vetter's avatar
Simona Vetter committed

	bootstrap_drm_rerere
	# now that drm-rerere is setup, read the config again during fetch the
	# additional branches from integration manifest will be read
	echo -n "Reloading $dim_integration_config... "
	read_integration_config
	echo -e "Done.\n"
	echo "Setting up drm-tip ..."
	dim_create_workdir drm-tip
	dim_update_branches

	echo "dim setup successfully completed!"
Simona Vetter's avatar
Simona Vetter committed
}

function assert_branch
	dim_cd $branch
	if git_is_current_branch $branch ; then
		return 0
	else
		echo "You're on the wrong branch, expected $branch in $PWD"
		return 1
	fi
function assert_repo_clean
{
	if [[ -n "$(git status --porcelain --untracked-files=no)" ]]; then
		echo "Working tree $PWD not clean, aborting."
# Note: used by bash completion
function dim_list_commands
{
	declare -F | grep -o " dim_[a-zA-Z0-9_]*" | sed 's/^ dim_//;s/_/-/g'
# Note: used by bash completion
function dim_list_aliases
{
	# use posix mode to omit functions in set output
	( set -o posix; set ) | grep "^dim_alias_[a-zA-Z0-9_]*=" |\
		sed 's/^dim_alias_//;s/=/\t/;s/_/-/g'
# Commands that do not require full setup
function list_developer_commands
{
	local -a developer_commands

	developer_commands=(
		# developer commands
		# these should match the developer section in dim.rst
		"checker"
		"checkpatch"
		"cite"
		"fixes"
		"retip"
		"sparse"
		"tc"
		# help commands
		"help"
		"usage"
		# include setup
		"setup"
	)

	printf "%s\n" "${developer_commands[@]}"
}

function dim_cat_to_fixup # [branch]
	local fixup_file repo branch
	branch=$1

	cd $DIM_PREFIX/drm-tip

	if [ -z "$branch" ]; then
		branch=$(cat .fixup_branch)
	fi

	repo=$(branch_to_repo $branch)
	fixup_file=$(find_fixup_file $repo $branch)

	cat >> $fixup_file
	echo "Applied fixup for $branch"
Jani Nikula's avatar
Jani Nikula committed
function dim_tc
{
	local sha1 tag conf remote_branches
	cd $DIM_PREFIX/$DIM_REPO
	tag=$(git tag --contains $sha1 | grep ^v | sort -V | head -n 1)
Jani Nikula's avatar
Jani Nikula committed
	if [[ -n "$tag" ]]; then
		echo "$tag"
Jani Nikula's avatar
Jani Nikula committed
	fi

	# not in a tagged release, show upstream branches
	remote_branches="origin/master"
	for conf in "${drm_tip_config[@]}"; do
		local repo branch override remote

		read -r repo branch override <<< $conf
		remote=$(repo_to_remote $repo)

		remote_branches="$remote_branches $remote/$branch"
	done

	git branch -r --contains $sha1 $remote_branches | sed 's/^ *//' | sort
function dim_cite
{
	git --git-dir="$DIM_PREFIX/$DIM_REPO/.git" log -1 $sha1 \
	    "--pretty=format:%H (\"%s\")%n" | \
		sed -e 's/\([0-f]\{12\}\)[0-f]*/\1/'
}

Jani Nikula's avatar
Jani Nikula committed
function dim_fixes
{
	cd $DIM_PREFIX/$DIM_REPO
	echo "Fixes: $(dim_cite $sha1)"
	(
		git show --no-patch $sha1 | \
			sed -e 's/\(Reviewed\|Acked\|Reported\|Signed\)[a-zA-Z-]*-by:/Cc:/' | \
			sed -e 's/^    C[Cc]: */Cc: /' | grep '^Cc: '
		git show $sha1 | scripts/get_maintainer.pl  --email --norolestats --pattern-depth 1 | sed -e "s/^/Cc: /"
	) | awk '!x[$0]++'
	tag=$(git tag --contains $sha1 | grep ^v | sort -V | head -n 1)
	if [[ -n "$tag" ]]; then
		if ! echo "$tag" | grep -q -e "-rc"; then
			echo "Cc: <stable@vger.kernel.org> # ${tag}+"
function dim_add_missing_cc
{
	local email name matches

	git show | scripts/get_maintainer.pl --email --norolestats --pattern-depth 1 | while read -r cc; do
		email="$(echo "$cc" | sed -e 's/.*<//' -e 's/>.*//')"
		name=''

		if echo "$cc" | grep -q '<'; then
			name="$(echo ${cc/<*/} | sed -e 's/[[:space:]]*\$//')";
		fi

		# Don't add main mailing lists
		if [[ "$email" = "dri-devel@lists.freedesktop.org" || \
		      "$email" = "linux-kernel@vger.kernel.org}" ]]; then
			continue
		fi

		# Variables from the while loop don't propagate,
		# print out a 1 on success
		matches=$(
			git show -s | grep -i "^    Cc:" | sed 's/^ *[Cc][Cc]: *//' | while read -r testcc; do
				testemail="$(echo "$testcc" | sed -e 's/.*<//' -e 's/>.*//')"

				if [ "$testemail" != "$email" ]; then
					if [ -z "$name" ]; then continue; fi

					testname="$(echo ${testcc/<*/} | sed -e 's/[[:space:]]*\$//' -e 's/^[[:space:]]*//')"

					if [ "$testname" != "$name" ]; then continue; fi
				fi

				echo 1
				break
			done
		)

		if [ -z "$matches" ]; then
			$DRY dim_commit_add_tag "Cc: ${cc}"
		fi
	done
}

Jani Nikula's avatar
Jani Nikula committed
function dim_help
{
	manpage=$DIM_PREFIX/maintainer-tools/dim.rst
	if [ ! -e "$manpage" ]; then
		manpage=$(dirname $(readlink -f $0))/dim.rst
		if [ ! -e "$manpage" ]; then
			echo "Can't find the man page. See https://gitlab.freedesktop.org/drm/maintainer-tools/-/blob/master/dim.rst"
Jani Nikula's avatar
Jani Nikula committed
			exit 1
		fi
	fi

	if hash rst2man 2>/dev/null; then
		renderer="rst2man"
Jani Nikula's avatar
Jani Nikula committed
		pager="man -l -"
	else
		renderer="cat"
Jani Nikula's avatar
Jani Nikula committed
		pager=${PAGER:-cat}
	fi

	$renderer < $manpage | $pager
}

	echo "usage: $dim [OPTIONS] SUBCOMMAND [ARGUMENTS]"
	echo
	echo "The available subcommands are:"
	if hash column 2>/dev/null; then
		dim_list_commands | column -c 72 | sed 's/^/\t/'
	else
		dim_list_commands | sed 's/^/\t/'
	fi
	echo "See '$dim help' for more information."
# Command line options. Global short uppercase variables.
DONE_OR_SKIP="Done."
while getopts hdfils opt; do
	case "$opt" in
		d)
			DRY_RUN=--dry-run
			DRY="echo"
			DONE_OR_SKIP="Skip."
		l)
			if ask_user "This option to ignore missed links should only be used by maintainers on rare situations. Are you sure?"; then
				LINK_MISSING_I_KNOW=1
			fi
			;;
		s)
			# FIXME: transitional, do unconditionally at the top
			# when there are no more errors about unbound variables
			set -u
			;;
		*)
			echoerr "See '$dim help' for more information."
			exit
	esac
done
shift $((OPTIND - 1))

# first positional argument is the subcommand
if [ -n "$HELP" ] || [ "$#" = "0" ]; then
	subcommand="usage"
	subcommand="$1"
	shift
fi

# generic usage to be used for ${1:?$usage} style argument references
usage="Missing arguments(s) for '$dim $subcommand'. See '$dim help' for usage."

# dim subcommand aliases (with bash 4.3+)
if ! declare -n subcmd=dim_alias_${subcommand//-/_} &> /dev/null || \
		test -z "${subcmd:-}"; then
	subcmd="$subcommand"
fi

# look up the function by the subcommand name
subcmd_func=dim_${subcmd//-/_}
if ! declare -f $subcmd_func >/dev/null; then
	echoerr "'$subcommand' is not a dim command."
	dim_usage
	exit 1
fi

#
# Sanity checks.
#

# Make sure we use 'dim_foo' within dim instead of 'dim foo'.
if [[ -n "${__dim_running:-}" ]]; then
	echoerr "INTERNAL ERROR: do not recurse back to dim"
	exit 1
fi
export __dim_running=1

check_dim_config

# Commands useful for developers don't need a full dim setup
if list_developer_commands | grep -qx $subcmd; then
	if [ -r $DIM_PREFIX/drm-rerere/$dim_integration_config ]; then
		read_integration_config
	for d in $DIM_PREFIX $DIM_PREFIX/$DIM_REPO $DIM_PREFIX/drm-rerere $DIM_PREFIX/drm-tip; do
		if [ ! -d $d ]; then
			echoerr "$d is missing, please check your configuration and/or run dim setup"
			exit 1
		fi
	done

	read_integration_config
	check_git_version
# throw away to not confuse list-aliases
unset subcmd