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