| #!/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://[email protected]/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://[email protected]/$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 |