| #!/usr/bin/env bash | 
 |  | 
 | ############################################################################## | 
 | ## | 
 | ##  GitHub Upload+Update Script (V2, combined) for DevPlat Samples | 
 | ## | 
 | ############################################################################## | 
 |  | 
 | update=true | 
 | upload=true | 
 | deleteTemp=true | 
 | useAllSamples=true | 
 | allSamples=() | 
 | token= | 
 |  | 
 | ## Generates a random 32 character alphaneumeric string to use as a post script  | 
 | ##   for the temporary code folder (folder will be deleted at end) | 
 | folderPS=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1) | 
 |  | 
 | #utility function to print to stderr | 
 | echoerr() { echo "$@" 1>&2; } | 
 |  | 
 | display_usage() { | 
 | echo -e "\e[90mUsage: | 
 |  | 
 |       -t | --token [github_auth_token] | 
 |          Input an auth token to access the googlesamples GitHub org | 
 |          (if this is not present, you will be prompted for one later) | 
 |  | 
 |       -s | --samples [sample1 sample2 sample3 ... sampleN] | 
 |          If you don't want to check the entire samples folder, | 
 |          you can specify which samples to use with this option. | 
 |  | 
 |       --upload-only | 
 |           Only uploads new samples - samples with existing | 
 |           repos will be ignored | 
 |  | 
 |       --update-only | 
 |           Only updates samples with existing repos - new | 
 |           samples will be ignored | 
 |  | 
 |       --keep-temp-files | 
 |           Will not delete the temporary directory used to pull/push | 
 |           to Github. (normally deleted upon exit) Preserves logs. | 
 |  | 
 |   This script can be run with no options - it will check the entire | 
 |   ./prebuilts/gradle folder and prompt for an auth token when needed.\e[0m\n" | 
 | } | 
 |  | 
 | ############################################################################## | 
 | ##  Make sure we delete the temporary folder (if it gets created) before exiting | 
 | finish() { | 
 |   if $deleteTemp; then | 
 |     if [ -d "../github-temp$folderPS" ]; then | 
 |      cd .. | 
 |      rm -rf ./github-temp$folderPS | 
 |     elif [ -d "github-temp$folderPS" ]; then | 
 |      rm -rf ./github-temp$folderPS | 
 |     fi | 
 |   fi | 
 | } | 
 | # this ensures finish() will always be called no matter how the script ends | 
 | trap finish EXIT | 
 |  | 
 |  | 
 | ############################################################################## | 
 | ##  Process input parameters. (see above for usage) | 
 |  | 
 | ## How this works: | 
 | ##  $# is the number of parameters passed in | 
 | ##  $1 is the first parameter, $2 the second, and so on. (space delimited) | 
 | ##  shift basically left shifts the params array - $1 goes away, $2 becomes $1, etc | 
 | ##  Thus, this while loop iterates through all command line parameters | 
 | while [[ $# > 0 ]]; do | 
 | case "$1" in | 
 |  | 
 |   -t|--token) | 
 |     if [[ $2 != -* ]] && [[ $2 ]]; then | 
 |       token="$2"; shift | 
 |     else | 
 |       echoerr -e "Option $1 requires an argument. Cancelling script.\nUse --help to display usage." | 
 |       exit 1 | 
 |     fi;; | 
 |  | 
 |   --update-only) upload=false;; | 
 |  | 
 |   --upload-only) update=false;; | 
 |  | 
 |   --keep-temp-files) deleteTemp=false;; | 
 |  | 
 |   -s|--samples) | 
 |     useAllSamples=false | 
 |     while [[ $2 != -* ]] && [[ $2 ]]; do | 
 |       #if true; then ##for testing | 
 |       if [ -d "./prebuilts/gradle/$2" ]; then | 
 |         allSamples+=("$2") | 
 |         shift | 
 |       else | 
 |         echoerr -e "Sample \"$2\" does not exist in ./prebuilts/gradle. Cancelling script.\n" | 
 |         exit 1 | 
 |       fi | 
 |     done;; | 
 |  | 
 |   -h|--help) | 
 |       display_usage | 
 |       exit 1;; | 
 |  | 
 |   *) | 
 |     echoerr -e "Unknown Option: $1\nUse --help to display usage." | 
 |     exit 1;; | 
 |  | 
 | esac | 
 | shift | 
 | done #ends options while loop | 
 |  | 
 | if ! $upload && ! $update; then | 
 |   echoerr -e "Do not use both --update-only and --upload-only, no samples will be processed. | 
 |   If you want to do both updates and uploads, no flags are needed. | 
 |   Use --help to display usage." | 
 |   exit 1 | 
 | fi | 
 |  | 
 | ############################################################################## | 
 | ##  Get all folders in prebuilts and stick 'em in an array | 
 |  | 
 | if $useAllSamples; then | 
 |   allSamples=($(ls ./prebuilts/gradle)) | 
 | fi | 
 |  | 
 | # [@] returns all items in an array, ${#...} counts them | 
 | numSamples=${#allSamples[@]} | 
 | echo "Running script for $numSamples samples" | 
 |  | 
 | ############################################################################## | 
 | ##  Iterate through all the samples and see if there's | 
 | ##  a repo for them on GitHub already - save results so we only do it once | 
 |  | 
 | toUpdate=() | 
 | toUpload=() | 
 | problemSamples=() | 
 | curSample=0 | 
 |  | 
 | echo -ne "Checking for existence of repos... ($curSample/$numSamples)\r" | 
 | for i in ${allSamples[@]}; | 
 | do | 
 |  #echo "$i" | 
 |  URL=https://github.com/googlesamples/android-$i | 
 |  result=$(curl -o /dev/null --silent --head --write-out '%{http_code}' "$URL") | 
 |  #echo "$result $URL" | 
 |  if [ "$result" -eq "404" ]; then | 
 |    toUpload+=("$i") | 
 |  elif [ "$result" -eq "200" ]; then | 
 |    toUpdate+=("$i") | 
 |  else | 
 |    problemSamples+=("$i") | 
 |  fi | 
 |  curSample=$(($curSample+1)) | 
 |  echo -ne "Checking for existence of repos... ($curSample/$numSamples)\r" | 
 | done #close for loop for existence check | 
 | echo "" | 
 |  | 
 |  | 
 | ############################################################################## | 
 | ##  For every sample that has a repo already, clone it and diff it against | 
 | ##  the sample code in our git to see if it needs updating. | 
 |  | 
 | if $update; then | 
 |  | 
 | needsUpdate=() | 
 | curSample=0 | 
 | numUpdates=${#toUpdate[@]} | 
 |  | 
 | ##make temporary dir to pull code into - will be deleted upon exit. | 
 | mkdir github-temp$folderPS | 
 | cd github-temp$folderPS | 
 |  | 
 | echo -ne "Checking for out-of-date repos... ($curSample/$numUpdates)\r" | 
 | for i in ${toUpdate[@]}; | 
 | do | 
 |  URL=https://github.com/googlesamples/android-$i | 
 |  git clone $URL.git &> /dev/null | 
 |  if [ -d "android-$i" ]; then | 
 |    diffResult=$(diff -r --exclude '*.git' ../prebuilts/gradle/$i/ ./android-$i/) | 
 |    #for testing (will show diff in every repo) | 
 |    #diffResult=$(diff -r ../prebuilts/gradle/$i/ ./android-$i/)` | 
 |    #echo $diffResult | 
 |    if [ -n "$diffResult" ]; then | 
 |      needsUpdate+=("$i") | 
 |    fi | 
 |  else | 
 |    echoerr "Something went wrong when cloning $i - result directory does not exist. | 
 |    Leaving temp files in place for further examination." | 
 |    deleteTemp=false; | 
 |  fi | 
 |  curSample=$(($curSample+1)) | 
 |  echo -ne "Checking for out-of-date repos... ($curSample/$numUpdates)\r" | 
 | done #end of for loop when checking which repos actually need updating | 
 | echo "" | 
 | fi | 
 |  | 
 | echo "" | 
 |  | 
 | ############################################################################## | 
 | ##  Display the detected changes to be made and get user confirmation | 
 |  | 
 | if $upload; then | 
 |   if [ ${#toUpload[@]} -ne 0 ]; then | 
 |     echo -e "\n\e[1mNew samples that will be uploaded:\e[0m" | 
 |     for i in ${toUpload[@]}; do | 
 |      echo -e "\e[32m$i\e[0m" | 
 |     done | 
 |   else | 
 |     upload=false | 
 |     echo "Nothing new to upload." | 
 |   fi | 
 | else | 
 |   echo "No uploads - check skipped on user request" | 
 | fi | 
 |  | 
 | if $update; then | 
 |   if [ ${#needsUpdate[@]} -ne 0 ]; then | 
 |     echo -e "\n\e[1mSamples that will be updated:\e[0m" | 
 |     for i in ${needsUpdate[@]}; do | 
 |       echo -e "\e[34m$i\e[0m" | 
 |     done | 
 |   else | 
 |     update=false | 
 |     echo "Nothing to update." | 
 |   fi | 
 | else | 
 |   echo "No updates - check skipped on user request" | 
 | fi | 
 |  | 
 | if [ ${#problemSamples[@]} -ne 0 ]; then | 
 |  echoerr " | 
 | These repos returned something other than a 404 or 200 result code:" | 
 |  for i in ${problemSamples[@]}; | 
 |  do | 
 |   echoerr "$i" | 
 |  done | 
 | fi | 
 |  | 
 | if ! $upload && ! $update; then | 
 |  echo -e "\e[1mLooks like everything's up-to-date.\e[0m\n" | 
 | else | 
 |  | 
 | read -p " | 
 | Do you want to continue? [y/n]: " -n 1 -r | 
 | echo | 
 | # if they type anything but an upper or lower case y, don't proceed. | 
 | if [[ $REPLY =~ ^[Yy]$ ]] | 
 | then | 
 |    #echo "Commencing Github updates" | 
 |  | 
 | ############################################################################## | 
 | ##  If the user hasn't supplied a token via parameter, ask now | 
 |  | 
 | if ! [ -n "$token" ] | 
 | then | 
 |  read -p " | 
 | Input a valid googlesamples GitHub access token to continue: " -r | 
 |  token=$REPLY | 
 | fi | 
 |  | 
 | ############################################################################## | 
 | ##  Test that token | 
 |  | 
 | tokenTest=$(curl -o /dev/null --silent \ | 
 |   -H "Authorization: token $token" \ | 
 |   --write-out '%{http_code}' "https://api.github.com/orgs/googlesamples/repos") | 
 |  | 
 | if [ "$tokenTest" -eq "200" ]; then | 
 |  | 
 |  | 
 | ############################################################################## | 
 | ##  If there's something to update, do the updates | 
 | if [ ${#needsUpdate[@]} -ne 0 ] && $update; then | 
 |  for i in ${needsUpdate[@]}; do | 
 |    echo -e "\nUpdating $i" | 
 |    if [ -d "android-$i" ]; then | 
 |      rsync -az --delete --exclude '*.git' ../prebuilts/gradle/$i/ ./android-$i/ | 
 |  | 
 |      cd ./android-$i/ | 
 |  | 
 |      git config user.name "google-automerger" | 
 |      git config user.email automerger@google.com | 
 |  | 
 |      git add . | 
 |      git status | 
 |      git commit -m "Auto-update" | 
 |  | 
 |      git remote set-url origin "https://$token@github.com/googlesamples/android-$i.git" | 
 |      git push origin master | 
 |  | 
 |      #overwrite remote url to not contain auth token | 
 |      git remote set-url origin "http://github.com/googlesamples/android-$i.git" | 
 |  | 
 |      cd .. | 
 |    else | 
 |      echoerr "Something went wrong when cloning $i - result directory does not exist. | 
 | Leaving temp files in place for further examination." | 
 |    deleteTemp=false; | 
 |   fi | 
 |  done | 
 | fi | 
 |  | 
 | #moves out of the temp folder, if we're in it. | 
 | if [ -d "../github-temp$folderPS" ]; then | 
 |    cd .. | 
 | fi | 
 |  | 
 | ############################################################################## | 
 | ##  If there's something new to upload, do the uploads | 
 | if [ ${#toUpload[@]} -ne 0 ] && $upload; then | 
 |  for i in ${toUpload[@]}; do | 
 |    echo -e "\nUploading $i" | 
 |  | 
 |    repoName="googlesamples/android-$i" | 
 |  | 
 |    CREATE="curl -H 'Authorization: token '$TOKEN \ | 
 |      -d '{\"name\":\"android-'$i'\", \"team_id\":889859}' \ | 
 |      https://api.github.com/orgs/googlesamples/repos" | 
 |    eval $CREATE | 
 |  | 
 |    #add secondary team permissions (robots) | 
 |    ADDTEAM="curl -X PUT \ | 
 |      -H 'Authorization: token '$TOKEN \ | 
 |      -H 'Content-Length: 0' \ | 
 |      https://api.github.com/teams/889856/repos/$repoName" | 
 |  | 
 |    eval $ADDTEAM | 
 |  | 
 |    URL="https://$token@github.com/$repoName" | 
 |  | 
 |    cd $i | 
 |    git init | 
 |     #overrides .gitconfig just for this project - does not alter your global settings. | 
 |    git config user.name "google-automerger" | 
 |    git config user.email automerger@google.com | 
 |    git add . | 
 |    git commit -m "Initial Commit" | 
 |    git remote add origin $URL | 
 |    git push origin master | 
 |    cd .. | 
 |  | 
 |  | 
 |  done | 
 | fi | 
 |  | 
 | else | 
 |   echoerr "That token doesn't work. A test returned the code: $tokenTest" | 
 | fi | 
 |  | 
 | else | 
 |    echo "User cancelled Github update." | 
 | fi | 
 |  | 
 | fi #end of "is there something to do?" if statement |