blob: 64f7741bd3ab87927bae9887b0cbae6494877f20 [file] [log] [blame]
Clare Bayleyafa63422014-12-15 11:48:10 -08001#!/usr/bin/env bash
2
3##############################################################################
4##
5## GitHub Upload+Update Script (V2, combined) for DevPlat Samples
6##
7##############################################################################
8
9update=true
10upload=true
11deleteTemp=true
12useAllSamples=true
13allSamples=()
14token=
15
16## Generates a random 32 character alphaneumeric string to use as a post script
17## for the temporary code folder (folder will be deleted at end)
18folderPS=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)
19
20#utility function to print to stderr
21echoerr() { echo "$@" 1>&2; }
22
23display_usage() {
24echo -e "\e[90mUsage:
25
26 -t | --token [github_auth_token]
27 Input an auth token to access the googlesamples GitHub org
28 (if this is not present, you will be prompted for one later)
29
30 -s | --samples [sample1 sample2 sample3 ... sampleN]
31 If you don't want to check the entire samples folder,
32 you can specify which samples to use with this option.
33
34 --upload-only
35 Only uploads new samples - samples with existing
36 repos will be ignored
37
38 --update-only
39 Only updates samples with existing repos - new
40 samples will be ignored
41
42 --keep-temp-files
43 Will not delete the temporary directory used to pull/push
44 to Github. (normally deleted upon exit) Preserves logs.
45
46 This script can be run with no options - it will check the entire
47 ./prebuilts/gradle folder and prompt for an auth token when needed.\e[0m\n"
48}
49
50##############################################################################
51## Make sure we delete the temporary folder (if it gets created) before exiting
52finish() {
53 if $deleteTemp; then
54 if [ -d "../github-temp$folderPS" ]; then
55 cd ..
56 rm -rf ./github-temp$folderPS
57 elif [ -d "github-temp$folderPS" ]; then
58 rm -rf ./github-temp$folderPS
59 fi
60 fi
61}
62# this ensures finish() will always be called no matter how the script ends
63trap finish EXIT
64
65
66##############################################################################
67## Process input parameters. (see above for usage)
68
69## How this works:
70## $# is the number of parameters passed in
71## $1 is the first parameter, $2 the second, and so on. (space delimited)
72## shift basically left shifts the params array - $1 goes away, $2 becomes $1, etc
73## Thus, this while loop iterates through all command line parameters
74while [[ $# > 0 ]]; do
75case "$1" in
76
77 -t|--token)
78 if [[ $2 != -* ]] && [[ $2 ]]; then
79 token="$2"; shift
80 else
81 echoerr -e "Option $1 requires an argument. Cancelling script.\nUse --help to display usage."
82 exit 1
83 fi;;
84
85 --update-only) upload=false;;
86
87 --upload-only) update=false;;
88
89 --keep-temp-files) deleteTemp=false;;
90
91 -s|--samples)
92 useAllSamples=false
93 while [[ $2 != -* ]] && [[ $2 ]]; do
94 #if true; then ##for testing
95 if [ -d "./prebuilts/gradle/$2" ]; then
96 allSamples+=("$2")
97 shift
98 else
99 echoerr -e "Sample \"$2\" does not exist in ./prebuilts/gradle. Cancelling script.\n"
100 exit 1
101 fi
102 done;;
103
104 -h|--help)
105 display_usage
106 exit 1;;
107
108 *)
109 echoerr -e "Unknown Option: $1\nUse --help to display usage."
110 exit 1;;
111
112esac
113shift
114done #ends options while loop
115
116if ! $upload && ! $update; then
117 echoerr -e "Do not use both --update-only and --upload-only, no samples will be processed.
118 If you want to do both updates and uploads, no flags are needed.
119 Use --help to display usage."
120 exit 1
121fi
122
123##############################################################################
124## Get all folders in prebuilts and stick 'em in an array
125
126if $useAllSamples; then
127 allSamples=($(ls ./prebuilts/gradle))
128fi
129
130# [@] returns all items in an array, ${#...} counts them
131numSamples=${#allSamples[@]}
132echo "Running script for $numSamples samples"
133
134##############################################################################
135## Iterate through all the samples and see if there's
136## a repo for them on GitHub already - save results so we only do it once
137
138toUpdate=()
139toUpload=()
140problemSamples=()
141curSample=0
142
143echo -ne "Checking for existence of repos... ($curSample/$numSamples)\r"
144for i in ${allSamples[@]};
145do
146 #echo "$i"
147 URL=https://github.com/googlesamples/android-$i
148 result=$(curl -o /dev/null --silent --head --write-out '%{http_code}' "$URL")
149 #echo "$result $URL"
150 if [ "$result" -eq "404" ]; then
151 toUpload+=("$i")
152 elif [ "$result" -eq "200" ]; then
153 toUpdate+=("$i")
154 else
155 problemSamples+=("$i")
156 fi
157 curSample=$(($curSample+1))
158 echo -ne "Checking for existence of repos... ($curSample/$numSamples)\r"
159done #close for loop for existence check
160echo ""
161
162
163##############################################################################
164## For every sample that has a repo already, clone it and diff it against
165## the sample code in our git to see if it needs updating.
166
167if $update; then
168
169needsUpdate=()
170curSample=0
171numUpdates=${#toUpdate[@]}
172
173##make temporary dir to pull code into - will be deleted upon exit.
174mkdir github-temp$folderPS
175cd github-temp$folderPS
176
177echo -ne "Checking for out-of-date repos... ($curSample/$numUpdates)\r"
178for i in ${toUpdate[@]};
179do
180 URL=https://github.com/googlesamples/android-$i
181 git clone $URL.git &> /dev/null
182 if [ -d "android-$i" ]; then
183 diffResult=$(diff -r --exclude '*.git' ../prebuilts/gradle/$i/ ./android-$i/)
184 #for testing (will show diff in every repo)
185 #diffResult=$(diff -r ../prebuilts/gradle/$i/ ./android-$i/)`
186 #echo $diffResult
187 if [ -n "$diffResult" ]; then
188 needsUpdate+=("$i")
189 fi
190 else
191 echoerr "Something went wrong when cloning $i - result directory does not exist.
192 Leaving temp files in place for further examination."
193 deleteTemp=false;
194 fi
195 curSample=$(($curSample+1))
196 echo -ne "Checking for out-of-date repos... ($curSample/$numUpdates)\r"
197done #end of for loop when checking which repos actually need updating
198echo ""
199fi
200
201echo ""
202
203##############################################################################
204## Display the detected changes to be made and get user confirmation
205
206if $upload; then
207 if [ ${#toUpload[@]} -ne 0 ]; then
208 echo -e "\n\e[1mNew samples that will be uploaded:\e[0m"
209 for i in ${toUpload[@]}; do
210 echo -e "\e[32m$i\e[0m"
211 done
212 else
213 upload=false
214 echo "Nothing new to upload."
215 fi
216else
217 echo "No uploads - check skipped on user request"
218fi
219
220if $update; then
221 if [ ${#needsUpdate[@]} -ne 0 ]; then
222 echo -e "\n\e[1mSamples that will be updated:\e[0m"
223 for i in ${needsUpdate[@]}; do
224 echo -e "\e[34m$i\e[0m"
225 done
226 else
227 update=false
228 echo "Nothing to update."
229 fi
230else
231 echo "No updates - check skipped on user request"
232fi
233
234if [ ${#problemSamples[@]} -ne 0 ]; then
235 echoerr "
236These repos returned something other than a 404 or 200 result code:"
237 for i in ${problemSamples[@]};
238 do
239 echoerr "$i"
240 done
241fi
242
243if ! $upload && ! $update; then
244 echo -e "\e[1mLooks like everything's up-to-date.\e[0m\n"
245else
246
247read -p "
248Do you want to continue? [y/n]: " -n 1 -r
249echo
250# if they type anything but an upper or lower case y, don't proceed.
251if [[ $REPLY =~ ^[Yy]$ ]]
252then
253 #echo "Commencing Github updates"
254
255##############################################################################
256## If the user hasn't supplied a token via parameter, ask now
257
258if ! [ -n "$token" ]
259then
260 read -p "
261Input a valid googlesamples GitHub access token to continue: " -r
262 token=$REPLY
263fi
264
265##############################################################################
266## Test that token
267
268tokenTest=$(curl -o /dev/null --silent \
269 -H "Authorization: token $token" \
270 --write-out '%{http_code}' "https://api.github.com/orgs/googlesamples/repos")
271
272if [ "$tokenTest" -eq "200" ]; then
273
274
275##############################################################################
276## If there's something to update, do the updates
277if [ ${#needsUpdate[@]} -ne 0 ] && $update; then
278 for i in ${needsUpdate[@]}; do
279 echo -e "\nUpdating $i"
280 if [ -d "android-$i" ]; then
281 rsync -az --delete --exclude '*.git' ../prebuilts/gradle/$i/ ./android-$i/
282
283 cd ./android-$i/
284
285 git config user.name "google-automerger"
286 git config user.email automerger@google.com
287
288 git add .
289 git status
290 git commit -m "Auto-update"
291
292 git remote set-url origin "https://$token@github.com/googlesamples/android-$i.git"
293 git push origin master
294
295 #overwrite remote url to not contain auth token
296 git remote set-url origin "http://github.com/googlesamples/android-$i.git"
297
298 cd ..
299 else
300 echoerr "Something went wrong when cloning $i - result directory does not exist.
301Leaving temp files in place for further examination."
302 deleteTemp=false;
303 fi
304 done
305fi
306
307#moves out of the temp folder, if we're in it.
308if [ -d "../github-temp$folderPS" ]; then
309 cd ..
310fi
311
312##############################################################################
313## If there's something new to upload, do the uploads
314if [ ${#toUpload[@]} -ne 0 ] && $upload; then
315 for i in ${toUpload[@]}; do
316 echo -e "\nUploading $i"
317
318 repoName="googlesamples/android-$i"
319
320 CREATE="curl -H 'Authorization: token '$TOKEN \
321 -d '{\"name\":\"android-'$i'\", \"team_id\":889859}' \
322 https://api.github.com/orgs/googlesamples/repos"
323 eval $CREATE
324
325 #add secondary team permissions (robots)
326 ADDTEAM="curl -X PUT \
327 -H 'Authorization: token '$TOKEN \
328 -H 'Content-Length: 0' \
329 https://api.github.com/teams/889856/repos/$repoName"
330
331 eval $ADDTEAM
332
333 URL="https://$token@github.com/$repoName"
334
335 cd $i
336 git init
337 #overrides .gitconfig just for this project - does not alter your global settings.
338 git config user.name "google-automerger"
339 git config user.email automerger@google.com
340 git add .
341 git commit -m "Initial Commit"
342 git remote add origin $URL
343 git push origin master
344 cd ..
345
346
347 done
348fi
349
350else
351 echoerr "That token doesn't work. A test returned the code: $tokenTest"
352fi
353
354else
355 echo "User cancelled Github update."
356fi
357
358fi #end of "is there something to do?" if statement