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