1#!/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