]> git.wh0rd.org Git - home.git/blob - .bin/r
vcs-url: more updates
[home.git] / .bin / r
1 #!/bin/bash
2 g() { git "$@"; }
3 err() { printf '%b\n' "$*" 1>&2; exit 1; }
4 vr() { echo "$@"; "$@"; }
5
6 case $1 in
7 -x) set -x; shift;;
8 esac
9
10 case $1 in
11 ""|-*) ;;
12 l)
13         cmd=list
14         shift
15         ;;
16 s)
17         cmd=sync
18         shift
19         ;;
20 *)
21         cmd=$1
22         shift
23         acmd=$(git config --get "alias.${cmd}" | sed 's: -.*::')
24         ;;
25 esac
26
27 mj_init() {
28         pipe=$(mktemp)
29         rm -f "${pipe}"
30         mkfifo "${pipe}"
31         exec {ctlfd}<>"${pipe}"
32         rm -f "${pipe}"
33         jobs=0
34         jobs_max=${1:-$(getconf _NPROCESSORS_ONLN)}
35 }
36 _mj_child() { echo ${BASHPID} $? >&${ctlfd} ; }
37 mj_child() {
38         (
39         "$@"
40         _mj_child
41         ) &
42         mj_post_child
43 }
44 mj_post_child() {
45         : $(( ++jobs ))
46         if [[ ${jobs} -eq ${jobs_max} ]] ; then
47                 read -r -u ${ctlfd} pid ret
48                 : $(( --jobs ))
49         fi
50 }
51 mj_finish() {
52         wait
53 }
54
55 repo_root() {
56         local root=${PWD}
57         while [[ ! -d ${root}/.repo && ${root} != "/" ]] ; do
58                 root=${root%/*}
59         done
60         echo "${root}"
61 }
62
63 process_reviewers() {
64         local r arr=()
65         for r in ${*//,/ } ; do
66                 case ${r} in
67                 *OWNERS)
68                         local owners=$(
69                                 awk -F'@' '
70                                         ($2 == "chromium.org" || $2 == "google.com") {list = list "," $1}
71                                         END {print substr(list, 2)}
72                                 ' "${r}"
73                         )
74                         if [[ -z ${owners} ]] ; then
75                                 err "cannot find OWNERS list"
76                         else
77                                 echo "Auto setting reviewers to: ${owners}"
78                         fi
79                         arr+=( ${owners} )
80                         ;;
81                 *)
82                         arr+=( "${r}" )
83                         ;;
84                 esac
85         done
86         reviewers=$(printf '%s,' "${arr[@]}")
87         reviewers=${reviewers%,}
88 }
89
90 case ${acmd:-${cmd}} in
91 rebase)
92         if [[ $1 == "all" ]] ; then
93                 shift
94                 if [[ $# -eq 0 ]] ; then
95                         eval $(bash-colors --env | sed 's:^:export :')
96                         root=$(repo_root)
97                         mj_init
98                         while read -a line ; do
99                                 dir=${line[0]}
100                                 proj=${line[2]}
101                                 if ! cd "${root}/${dir}" ; then
102                                         echo "bad ${proj}"
103                                         continue
104                                 fi
105                                 (
106                                 out=$(env _proj=${proj} r rb all . 2>&1)
107                                 if [[ -n ${out} ]] ; then
108                                         while read line ; do
109                                                 if [[ ${line} == "# "* ]] ; then
110                                                         line="${line#[#] }"
111                                                         printf '%s### %s%-40s%s: %s\n' \
112                                                                 "${BRACKET}" "${GOOD}" "${line%%:*}" "${NORMAL}" "${line#*:}"
113                                                 else
114                                                         printf '%s### %s%-40s%s: ERROR: %s\n' \
115                                                                 "${BRACKET}" "${BAD}" "${dir}" "${NORMAL}" "${line}"
116                                                 fi
117                                         done < <(echo "${out}")
118                                 fi
119                                 _mj_child
120                                 ) &
121                                 mj_post_child
122                         done < <(r l)
123                         mj_finish
124                         exit 0
125                         #exec r forall -p -c 'r rb all .' </dev/null
126                 fi
127
128                 branches=$(g b | awk '
129                         {
130                                 if ($0 ~ "^[*] *[(]no branch[)]") {
131                                         next
132                                 } else if ($0 ~ "^[*] *[(](HEAD )?detached (from|at) ") {
133                                         next
134                                 } else if ($1 == "*") {
135                                         b = $2
136                                 } else {
137                                         list = list $1 " "
138                                 }
139                         }
140                         END { print list b }')
141                 [[ -z ${branches} ]] && exit 0
142
143                 [[ -z ${GOOD} ]] && eval $(bash-colors --env)
144                 #echo "${GOOD}### ${PWD}${NORMAL}"
145                 # Skip if rebase is in progress.
146                 if [[ -e .git/rebase-merge/interactive ]] ; then
147                         echo -e "# ${_proj}: ${WARN}skipping due to active rebase${NORMAL}"
148                         exit 1
149                 fi
150                 for b in ${branches} ; do
151                         #echo " ${HILITE}### $b${NORMAL}"
152                         g co -q $b || exit 1
153                         if ! r rb -q "$@" ; then
154                                 g rb-a
155                         fi
156                 done
157                 exit 0
158         fi
159         ;;
160 clean)
161         root=$(repo_root)
162         cd "${root}" || exit 1
163         mj_init
164         while read -a line ; do
165                 dir=${line[0]}
166                 proj=${line[2]}
167                 cd "${root}/${dir}"
168                 (
169                 out=$(g clean "$@" 2>&1)
170                 if [[ -n ${out} ]] ; then
171                         echo "### ${proj}"
172                         echo "${out}"
173                 fi
174                 _mj_child
175                 ) &
176                 mj_post_child
177         done < <(r l)
178         mj_finish
179         exit
180         ;;
181 sb)
182         sb_cmd=$1
183         case ${sb_cmd} in
184         pull) ;;
185         push) ;;
186         f|fetch) sb_cmd="fetch" ;;
187         *) err "unknown sandbox command: $1"
188         esac
189
190         sync_branch="v"
191
192         root=$(repo_root)
193         cd "${root}" || exit 1
194
195         if [[ ! -e .repo/sandbox-url ]] ; then
196                 err "Please configure remote url base in ${root}/.repo/sandbox-url"
197         fi
198         remote=$(<.repo/sandbox-url) || exit 1
199
200         echo "pushing projects from ${root}"
201
202         # ssh servers do not like it when you hammer them :)
203         #       Received disconnect from 74.125.248.80: 7: Too many concurrent connections
204         #       fatal: The remote end hung up unexpectedly
205         mj_init 16
206
207         rlist=$(r l)
208         tcnt=$(echo "${rlist}" | wc -l)
209         cnt=1
210         while read line ; do
211                 line=( ${line} )
212                 path=${line[0]}
213                 export GIT_DIR=${path}/.git
214                 proj=${line[2]}
215                 printf '### (%*i/%i %3i%%) %s\n' \
216                         ${#tcnt} $((cnt++)) ${tcnt} $(( cnt * 100 / tcnt )) ${proj}
217                 src="${sync_branch}"
218                 case ${sb_cmd} in
219                 push)
220                         g l -1 ${src} >& /dev/null || src=
221                         mj_child g push --force ${remote}/${proj} ${src}:refs/sandbox/${USER}/${sync_branch} >/dev/null
222                         ;;
223                 pull)
224                         ;;
225                 fetch)
226                         mj_child g fetch ${remote}/${proj} refs/sandbox/${USER}/${sync_branch}:refs/remotes/sb/${sync_branch} >/dev/null
227                         ;;
228                 esac
229         done < <(echo "${rlist}")
230         mj_finish
231
232         exit 0
233         ;;
234 g-push)
235         # For the times when repo is being stupid, push directly to gerrit myself.
236         if ! branch=$(g symbolic-ref -q HEAD) ; then
237                 err "could not figure out active branch"
238         fi
239         branch=${branch#refs/heads/}
240         if ! remote_branch=$(g cfg --get "branch.${branch}.merge") ; then
241                 echo "could not figure out remote branch; using ${branch}"
242                 remote_branch=${branch}
243         fi
244         if ! remote=$(g cfg --get "branch.${branch}.remote") ; then
245                 for remote in cros-internal cros origin ; do
246                          g cfg --get "remote.${remote}.url" >/dev/null && break
247                 done
248         fi
249         review=$(g cfg --get "remote.${remote}.review")
250         remote_branch=${remote_branch#refs/heads/}
251
252         git_args=()
253         reviewers=""
254         while [[ $# -gt 0 ]] ; do
255                 case $1 in
256                 --re)
257                         process_reviewers "$2"
258                         shift
259                         ;;
260                 -n|--dry-run|--draft)
261                         git_args+=( $1 )
262                         ;;
263                 *)
264                         err "unknown option: $1"
265                         ;;
266                 esac
267                 shift
268         done
269
270         ref_spec="${branch}:refs/for/${remote_branch}"
271         if [[ -n ${reviewers} ]] ; then
272                 reviewers=( ${reviewers//,/ } )
273                 if [[ ${review} != ssh://* ]] ; then
274                         gob_args=$(printf 'r=%s,' "${reviewers[@]}")
275                         ref_spec+="%${gob_args%,}"
276                 else
277                         git_args+=( "--receive-pack=git receive-pack ${reviewers[*]/#/--reviewer=}" )
278                 fi
279         fi
280
281         vr git push "${git_args[@]}" ${remote} ${ref_spec} && exit
282         err "could not figure out remote to push to"
283         ;;
284 sync)
285         set -- -j16 -c "$@"
286         ;;
287 upload)
288         args=()
289         while [[ $# -gt 0 ]] ; do
290                 case $1 in
291                 --re)
292                         process_reviewers "$2"
293                         args+=( --re "${reviewers}" )
294                         shift 2
295                         continue
296                         ;;
297                 esac
298                 args+=( "$1" )
299                 shift
300         done
301         set -- "${args[@]}"
302         ;;
303 email)
304         email=${1:-${USER}@chromium.org}
305         cmd='forall'
306         set -- -c "git cfg user.email ${email}"
307         ;;
308 esac
309
310 exec python2 $(type -P repo) ${acmd:-${cmd}} "$@"