X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=.bin%2Fr;h=a969597655a52ff8dec24afdd286d64a705cbfab;hb=a5f629de0d2669846d3b30fe8a38dfca79d92aae;hp=6771348c705bcf90d1fb944f63b467d7282dbe02;hpb=17ff99a03c3487b471d9b519872e76602a61ee0b;p=home.git diff --git a/.bin/r b/.bin/r index 6771348..a969597 100755 --- a/.bin/r +++ b/.bin/r @@ -1,6 +1,11 @@ #!/bin/bash g() { git "$@"; } err() { printf '%b\n' "$*" 1>&2; exit 1; } +vr() { echo "$@"; "$@"; } + +case $1 in +-x) set -x; shift;; +esac case $1 in ""|-*) ;; @@ -8,53 +13,232 @@ l) cmd=list shift ;; +s) + cmd=sync + shift + ;; +rb-all) + cmd=rebase + shift + set -- all "$@" + ;; *) 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}" +} + +process_reviewers() { + local r arr=() + for r in ${*//,/ } ; do + case ${r} in + OWNERS*|*/OWNERS*) + local owners=$( + awk -F'@' ' + ($2 == "chromium.org" || $2 == "google.com") {list = list "," $1} + END {print substr(list, 2)} + ' "${r}" + ) + if [[ -z ${owners} ]] ; then + err "cannot find OWNERS list" + else + echo "Auto setting reviewers to: ${owners}" + fi + arr+=( ${owners} ) + ;; + *) + arr+=( "${r}" ) + ;; + esac + done + reviewers=$(printf '%s,' "${arr[@]}") + reviewers=${reviewers%,} +} + +find_repo() { + # Diff projects have diff versions of repo. Find a compatible one. + local root=$(repo_root) + + # Use the manifest repo URL. + local manifest_dir="${root}/.repo/manifests.git" + local d + + # Default to the local repo if it's there. + local search=( + "${root}/.repo/repo" + ) + + case $(g --git-dir="${manifest_dir}" config remote.origin.url) in + *android*) + search+=( + /usr/local/src/repo + ~/src/repo + ) + ;; + *chromium*|*chrome*) + search+=( + ~/depot_tools + ~/chromiumos/depot_tools + /usr/local/src/depot_tools + ~/src/depot_tools + ) + ;; + esac + for d in "${search[@]}" ; do + if [[ -x ${d}/repo ]] ; then + echo "${d}"/repo + return + fi + done + + # Fallback: use $PATH. + type -P repo +} + case ${acmd:-${cmd}} in rebase) if [[ $1 == "all" ]] ; then shift if [[ $# -eq 0 ]] ; then - exec r forall -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]} + if ! cd "${root}/${dir}" ; then + echo "bad ${proj}" + continue + fi + ( + out=$(env _proj=${proj} r rb all . 2>&1) + if [[ -n ${out} ]] ; then + while read line ; do + case ${line} in + "Fast-forwarded "*) ;; + "# "*) + line="${line#[#] }" + printf '%s### %s%-40s%s: %s\n' \ + "${BRACKET}" "${GOOD}" "${line%%:*}" "${NORMAL}" "${line#*:}" + ;; + *) + printf '%s### %s%-40s%s: ERROR: %s\n' \ + "${BRACKET}" "${BAD}" "${dir}" "${NORMAL}" "${line}" + ;; + esac + done < <(echo "${out}") + fi + _mj_child + ) & + mj_post_child + done < <(r l) + mj_finish + exit 0 + #exec r forall -p -c 'r rb all .' &1) + if [[ -n ${out} ]] ; then + echo "### ${proj}" + echo "${out}" + fi + _mj_child + ) & + mj_post_child + done < <(r l) + mj_finish + exit + ;; +sb) + sb_cmd=$1 + case ${sb_cmd} in + pull) ;; + push) ;; + f|fetch) sb_cmd="fetch" ;; + *) err "unknown sandbox command: $1" + esac + 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,8 +248,12 @@ sb-push) echo "pushing projects from ${root}" - pids=() - rlist=$(r list) + # 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 l) tcnt=$(echo "${rlist}" | wc -l) cnt=1 while read line ; do @@ -76,47 +264,84 @@ sb-push) printf '### (%*i/%i %3i%%) %s\n' \ ${#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 ) & - - # 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 - pids+=( $! ) - if [[ ${#pids[@]} -eq 20 ]] ; then - wait ${pids[@]:0:3} - pids=( ${pids[@]:3} ) - fi - done <<<"$(r list)" - wait + case ${sb_cmd} in + push) + g l -1 ${src} >& /dev/null || src= + mj_child g push --force ${remote}/${proj} ${src}:refs/sandbox/${USER}/${sync_branch} >/dev/null + ;; + pull) + ;; + fetch) + mj_child g fetch ${remote}/${proj} refs/sandbox/${USER}/${sync_branch}:refs/remotes/sb/${sync_branch} >/dev/null + ;; + esac + 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 " - exit 1 + if ! branch=$(g symbolic-ref -q HEAD) ; then + err "could not figure out active branch" + fi + 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) + process_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 - exec g push cros-internal HEAD:refs/for/master + + vr git push "${git_args[@]}" ${remote} ${ref_spec} && exit + err "could not figure out remote to push to" + ;; +sync) + set -- -j16 -c "$@" ;; upload) args=() while [[ $# -gt 0 ]] ; do case $1 in --re) - if [[ $2 == *"OWNERS" ]] ; then - owners=$(awk -F'@' '{list = list "," $1} END {print substr(list, 2)}' "$2") - if [[ -z ${owners} ]] ; then - err "cannot find OWNERS list" - else - echo "Auto setting reviewers to: ${owners}" - fi - args+=( --re "${owners}" ) - shift 2 - continue - fi + process_reviewers "$2" + args+=( --re "${reviewers}" ) + shift 2 + continue ;; esac args+=( "$1" ) @@ -124,6 +349,16 @@ upload) done set -- "${args[@]}" ;; +email) + email=${1:-${USER}@chromium.org} + + root=$(repo_root) + git --git-dir="${root}/.repo/manifests.git" cfg user.email "${email}" + git --git-dir="${root}/.repo/repo/.git" cfg user.email "${email}" + + cmd='forall' + set -- -c "git cfg user.email '${email}'" + ;; esac -exec repo ${acmd:-${cmd}} "$@" +exec python2 $(find_repo) ${acmd:-${cmd}} "$@"