ASR_BASE

Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/scripts/autopick.sh b/scripts/autopick.sh
new file mode 100755
index 0000000..dc1cf4e
--- /dev/null
+++ b/scripts/autopick.sh
@@ -0,0 +1,107 @@
+#!/bin/bash
+set -e
+get_patch_id_commit_id_pairs() {
+	git log "$@" --pretty=tformat:'COMMITm@g1c %H %al %as %f%n%B' | awk 'function p(){if(h){print(d?d:c?c:g?g:(a":"t":"s)),h}};$1=="COMMITm@g1c"{p();h=$2;a=$3;t=$4;s=$5;c=d=g="";next};$1=="Differential"&&$2=="Revision:"{d=$3;sub("http.*/","",d);next};$1=="Change-Id:"{c=$1$2;next};$1=="git-svn-id:"{g=$2;next};END{p()}'
+}
+
+if [ -z "$1" ]; then
+	echo "Usage: `basename "$0"` branch_to_auto_pick_from"
+	exit
+fi
+FROM_BRANCH="$1"
+TO_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
+if [ -z "$TO_BRANCH" ]; then
+	echo "Please git checkout to a branch first"
+	exit 1
+fi
+
+echo "Computing merge base from $FROM_BRANCH to $TO_BRANCH ..."
+MERGE_BASE="$(git merge-base --all "$FROM_BRANCH" "$TO_BRANCH")"
+if [ -z "$MERGE_BASE" ]; then
+	echo "Failed to get merge base"
+	exit 1
+elif [ $(wc -l <<< "$MERGE_BASE") -gt 1 ]; then
+	echo "Git tree with cross merge not supported"
+	exit 1
+fi
+echo "Merge base is $(get_patch_id_commit_id_pairs $MERGE_BASE^..$MERGE_BASE)"
+
+echo -n "Getting patch list on $FROM_BRANCH ... "
+declare -A MAP_FROM_PATCHES
+REV_LIST_FROM_PATCHES=
+while read c d; do
+	if [ -n "$(exec 2>/dev/null; echo ${MAP_FROM_PATCHES[$c]})" ]; then
+		echo "Duplicate patch name found for $c $d ${MAP_FROM_PATCHES[$c]}"
+		d="$d ${MAP_FROM_PATCHES[$c]}"
+	fi
+	MAP_FROM_PATCHES[$c]="$d"
+	REV_LIST_FROM_PATCHES="$c
+$REV_LIST_FROM_PATCHES"
+done < <(get_patch_id_commit_id_pairs "$MERGE_BASE..$FROM_BRANCH")
+echo "${#MAP_FROM_PATCHES[@]} patches"
+
+echo -n "Getting patch list on $TO_BRANCH ... "
+declare -A MAP_TO_PATCHES
+declare -A MAP_TO_PATCHES_DUP
+while read c d; do
+	if [ -n "$(exec 2>/dev/null; echo ${MAP_TO_PATCHES[$c]})" ]; then
+		echo "Duplicate patch name found for $c $d ${MAP_TO_PATCHES[$c]}"
+		d="$d ${MAP_TO_PATCHES[$c]}"
+		MAP_TO_PATCHES_DUP[$c]="$d"
+	fi
+	MAP_TO_PATCHES[$c]="$d"
+done < <(get_patch_id_commit_id_pairs "$MERGE_BASE..$TO_BRANCH")
+echo "${#MAP_TO_PATCHES[@]} patches"
+for d in ${MAP_TO_PATCHES_DUP[@]}; do
+	HASH="$(git diff --binary $d^..$d | sha1sum | cut -d ' ' -f 1)"
+	eval "HAS_$HASH=true"
+done
+
+echo "Computing patches to cherry-pick ..."
+PATCHES_TO_PICK=
+while read c; do
+	if [ -z "$c" ]; then
+		continue
+	fi
+	if [ -z "$(exec 2>/dev/null; echo ${MAP_TO_PATCHES[$c]})" ] || [ ${#MAP_FROM_PATCHES[$c]} -ne ${#MAP_TO_PATCHES[$c]} ]; then
+		echo -ne "$c\t"
+		if [[ "${MAP_FROM_PATCHES[$c]}" == *" "* ]]; then
+			if [ -z "$(exec 2>/dev/null; echo ${MAP_TO_PATCHES_DUP[$c]})" ]; then
+				for d in ${MAP_TO_PATCHES[$c]}; do
+					HASH="$(git diff --binary $d^..$d | sha1sum | cut -d ' ' -f 1)"
+					eval "HAS_$HASH=true"
+				done
+			fi
+			for d in ${MAP_FROM_PATCHES[$c]}; do
+				if [ -z "$(eval echo "\${VISITED_$d}")" ]; then
+					break
+				fi
+			done
+			if [ -n "$(eval echo "\${VISITED_$d}")" ]; then
+				echo "All patches visited for $c: ${MAP_FROM_PATCHES[$c]}"
+				exit 1
+			fi
+			eval "VISITED_$d=true"
+			HASH="$(git diff --binary $d^..$d | sha1sum | cut -d ' ' -f 1)"
+			if [ -n "$(eval echo "\${HAS_$HASH}")" ]; then
+				echo "$d skipped"
+				continue
+			fi
+			c="$c-$HASH"
+			MAP_FROM_PATCHES[$c]="$d"
+		fi
+		echo "${MAP_FROM_PATCHES[$c]}"
+		PATCHES_TO_PICK="$PATCHES_TO_PICK
+$c"
+	fi
+done <<< "$REV_LIST_FROM_PATCHES"
+while read c; do
+	if [ -z "$c" ]; then
+		continue
+	fi
+	d="${MAP_FROM_PATCHES[$c]}"
+	echo "Cherry-picking $d for $c ..."
+	git cherry-pick "$d"
+done <<< "$PATCHES_TO_PICK"
+
+echo "Done"