]> git.wh0rd.org - home.git/blob - .bin/r
r: handle updated branch output
[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 repo ${acmd:-${cmd}} "$@"