]> git.wh0rd.org - home.git/blobdiff - .bin/r
r: support --re with GoB
[home.git] / .bin / r
diff --git a/.bin/r b/.bin/r
index d204eb1186964c89a57f577cc7c1a5dccc1ce76a..6a86466c38ecdedb3e53527b7699c15e4699ac62 100755 (executable)
--- a/.bin/r
+++ b/.bin/r
@@ -1,6 +1,7 @@
 #!/bin/bash
 g() { git "$@"; }
 err() { printf '%b\n' "$*" 1>&2; exit 1; }
+vr() { echo "$@"; "$@"; }
 
 case $1 in
 ""|-*) ;;
@@ -8,53 +9,144 @@ l)
        cmd=list
        shift
        ;;
+s)
+       cmd=sync
+       shift
+       ;;
 *)
        cmd=$1
        shift
-       acmd=$(git config --get "alias.${cmd}")
+       acmd=$(git config --get "alias.${cmd}" | sed 's: -.*::')
        ;;
 esac
 
+mj_init() {
+       pipe=$(mktemp)
+       rm -f "${pipe}"
+       mkfifo "${pipe}"
+       exec {ctlfd}<>"${pipe}"
+       rm -f "${pipe}"
+       jobs=0
+       jobs_max=${1:-$(getconf _NPROCESSORS_ONLN)}
+}
+_mj_child() { echo ${BASHPID} $? >&${ctlfd} ; }
+mj_child() {
+       (
+       "$@"
+       _mj_child
+       ) &
+       mj_post_child
+}
+mj_post_child() {
+       : $(( ++jobs ))
+       if [[ ${jobs} -eq ${jobs_max} ]] ; then
+               read -r -u ${ctlfd} pid ret
+               : $(( --jobs ))
+       fi
+}
+mj_finish() {
+       wait
+}
+
+repo_root() {
+       local root=${PWD}
+       while [[ ! -d ${root}/.repo && ${root} != "/" ]] ; do
+               root=${root%/*}
+       done
+       echo "${root}"
+}
+
 case ${acmd:-${cmd}} in
 rebase)
        if [[ $1 == "all" ]] ; then
                shift
                if [[ $# -eq 0 ]] ; then
-                       exec r forall -p -c 'r rb all .'
+                       eval $(bash-colors --env | sed 's:^:export :')
+                       root=$(repo_root)
+                       mj_init
+                       while read -a line ; do
+                               dir=${line[0]}
+                               proj=${line[2]}
+                               cd "${root}/${dir}"
+                               (
+                               out=$(env _proj=${proj} r rb all . 2>&1)
+                               if [[ -n ${out} ]] ; then
+                                       while read line ; do
+                                               if [[ ${line} == "# "* ]] ; then
+                                                       line="${line#[#] }"
+                                                       printf '%s### %s%-40s%s: %s\n' \
+                                                               "${BRACKET}" "${GOOD}" "${line%%:*}" "${NORMAL}" "${line#*:}"
+                                               else
+                                                       echo "${line}"
+                                               fi
+                                       done < <(echo "${out}")
+                               fi
+                               _mj_child
+                               ) &
+                               mj_post_child
+                       done < <(r l)
+                       mj_finish
+                       exit 0
+                       #exec r forall -p -c 'r rb all .' </dev/null
                fi
 
                branches=$(g b | awk '
                        {
                                if ($0 ~ "^[*] *[(]no branch[)]") {
                                        next
+                               } else if ($0 ~ "^[*] *[(]detached from ") {
+                                       next
                                } else if ($1 == "*") {
-                                       b = $NF
+                                       b = $2
                                } else {
-                                       list = list $NF " "
+                                       list = list $1 " "
                                }
                        }
                        END { print list b }')
                [[ -z ${branches} ]] && exit 0
 
-               eval $(bash-colors --env)
+               [[ -z ${GOOD} ]] && eval $(bash-colors --env)
                #echo "${GOOD}### ${PWD}${NORMAL}"
+               # Skip if rebase is in progress.
+               if [[ -e .git/rebase-merge/interactive ]] ; then
+                       echo -e "# ${_proj}: ${WARN}skipping due to active rebase${NORMAL}"
+                       exit 1
+               fi
                for b in ${branches} ; do
-                       echo " ${HILITE}### $b${NORMAL}"
+                       #echo " ${HILITE}### $b${NORMAL}"
                        g co -q $b || exit 1
-                       if ! r rb "$@" ; then
+                       if ! r rb -q "$@" ; then
                                g rb-a
                        fi
                done
                exit 0
        fi
        ;;
+clean)
+       root=$(repo_root)
+       cd "${root}" || exit 1
+       mj_init
+       while read -a line ; do
+               dir=${line[0]}
+               proj=${line[2]}
+               cd "${root}/${dir}"
+               (
+               out=$(g clean "$@" 2>&1)
+               if [[ -n ${out} ]] ; then
+                       echo "### ${proj}"
+                       echo "${out}"
+               fi
+               _mj_child
+               ) &
+               mj_post_child
+       done < <(r l)
+       mj_finish
+       exit
+       ;;
 sb-push)
        sync_branch="v"
 
-       root=${PWD}
-       while [[ ! -d ${root}/.repo && ${root} != "/" ]] ; do
-               root=${root%/*}
-       done
+       root=$(repo_root)
        cd "${root}" || exit 1
 
        if [[ ! -e .repo/sandbox-url ]] ; then
@@ -64,14 +156,12 @@ sb-push)
 
        echo "pushing projects from ${root}"
 
-       pipe=$(mktemp)
-       rm -f "${pipe}"
-       mkfifo "${pipe}"
-       exec {ctlfd}<>"${pipe}"
-       rm -f "${pipe}"
-       jobs=0
+       # ssh servers do not like it when you hammer them :)
+       #       Received disconnect from 74.125.248.80: 7: Too many concurrent connections
+       #       fatal: The remote end hung up unexpectedly
+       mj_init 16
 
-       rlist=$(r list)
+       rlist=$(r l)
        tcnt=$(echo "${rlist}" | wc -l)
        cnt=1
        while read line ; do
@@ -83,32 +173,64 @@ sb-push)
                        ${#tcnt} $((cnt++)) ${tcnt} $(( cnt * 100 / tcnt )) ${proj}
                src="${sync_branch}"
                g l -1 ${src} >& /dev/null || src=
-               (
-               g push --force ${remote}/${proj} ${src}:refs/sandbox/${USER}/${sync_branch} >/dev/null
-               echo ${BASHPID} $? >&${ctlfd}
-               ) &
-
-               # ssh servers do not like it when you hammer them :)
-               #       Received disconnect from 74.125.248.80: 7: Too many concurrent connections
-               #       fatal: The remote end hung up unexpectedly
-               : $(( ++jobs ))
-               if [[ ${jobs} -eq 16 ]] ; then
-                       read -r -u ${ctlfd} pid ret
-                       : $(( --jobs ))
-               fi
-       done < <(r list)
-       wait
+               mj_child g push --force ${remote}/${proj} ${src}:refs/sandbox/${USER}/${sync_branch} >/dev/null
+       done < <(echo "${rlist}")
+       mj_finish
 
        exit 0
        ;;
 g-push)
        # For the times when repo is being stupid, push directly to gerrit myself.
-       shift
-       if [[ $# -ne 1 ]] ; then
-               echo "Usage: r g-push <branch>"
-               exit 1
+       if ! branch=$(g symbolic-ref -q HEAD) ; then
+               err "could not figure out active branch"
        fi
-       exec g push cros-internal HEAD:refs/for/master
+       branch=${branch#refs/heads/}
+       if ! remote_branch=$(g cfg --get "branch.${branch}.merge") ; then
+               echo "could not figure out remote branch; using ${branch}"
+               remote_branch=${branch}
+       fi
+       if ! remote=$(g cfg --get "branch.${branch}.remote") ; then
+               for remote in cros-internal cros origin ; do
+                        g cfg --get "remote.${remote}.url" >/dev/null && break
+               done
+       fi
+       review=$(g cfg --get "remote.${remote}.review")
+       remote_branch=${remote_branch#refs/heads/}
+
+       git_args=()
+       reviewers=""
+       while [[ $# -gt 0 ]] ; do
+               case $1 in
+               --re)
+                       reviewers=$2
+                       shift
+                       ;;
+               -n|--dry-run|--draft)
+                       git_args+=( $1 )
+                       ;;
+               *)
+                       err "unknown option: $1"
+                       ;;
+               esac
+               shift
+       done
+
+       ref_spec="${branch}:refs/for/${remote_branch}"
+       if [[ -n ${reviewers} ]] ; then
+               reviewers=( ${reviewers//,/ } )
+               if [[ ${review} != ssh://* ]] ; then
+                       gob_args=$(printf 'r=%s,' "${reviewers[@]}")
+                       ref_spec+="%${gob_args%,}"
+               else
+                       git_args+=( "--receive-pack=git receive-pack ${reviewers[*]/#/--reviewer=}" )
+               fi
+       fi
+
+       vr git push "${git_args[@]}" ${remote} ${ref_spec} && exit
+       err "could not figure out remote to push to"
+       ;;
+sync)
+       set -- -j16 -c "$@"
        ;;
 upload)
        args=()
@@ -133,6 +255,11 @@ upload)
        done
        set -- "${args[@]}"
        ;;
+email)
+       email=${1:-${USER}@chromium.org}
+       cmd='forall'
+       set -- -c "git cfg user.email ${email}"
+       ;;
 esac
 
 exec repo ${acmd:-${cmd}} "$@"