Skip to content
install-deps.sh 17.5 KiB
Newer Older
#!/usr/bin/env bash

function run_installer()
{
	####### Init vars

	HOMEBREW_PREFIX=/usr/local
	HOMEBREW_CACHE=/Library/Caches/Homebrew
	HOMEBREW_REPO=https://github.com/Homebrew/homebrew
	OSX_REQUIERED_VERSION="10.7.0"


	declare OS_TYPE
	declare OSX_VERSION
	declare GIT_PATH
	declare RUBY_PATH
	declare BREW_PATH
	declare INSTALL_FILES=""

	errorMessages=""
	isOsVersion=false
	isGit=false
	isRuby=false
	isBrew=false
	canContinue=true
	depCount=0
	depFound=0



	####### Setup colors

	red=`tput setaf 1`
	green=`tput setaf 2`
	yellow=`tput setaf 3`
	blue=`tput setaf 4`
	magenta=`tput setaf 5`
	cyan=`tput setaf 6`
	white=`tput setaf 7`
	b=`tput bold`
	u=`tput sgr 0 1`
	ul=`tput smul`
	xl=`tput rmul`
	stou=`tput smso`
	xtou=`tput rmso`
	dim=`tput dim`
	reverse=`tput rev`
	reset=`tput sgr0`
Gav Wood's avatar
Gav Wood committed
	n=$'\n'


	function head() {
		echo "${blue}${b}==>${white} $1${reset}"
	}

	function info() {
		echo "${blue}${b}==>${reset} $1"
	}

	function successHeading() {
		echo "${green}${b}==> $1${reset}"
	}

	function success() {
		echo "${green}${b}==>${reset}${green} $1${reset}"
	}

	function error() {
		echo "${red}==> ${u}${b}${red}$1${reset}"
	}

	function smallError() {
		echo "${red}==>${reset} $1"
	}

	function green() {
		echo "${green}$1${reset}"
	}

	function red() {
		echo "${red}$1${reset}"
	}

	function check() {
		echo "${green}${bold}${reset}  $1${reset}"
	}

	function uncheck() {
		echo "${red}${bold}${reset}  $1${reset}"
	}



	####### Setup methods

	function wait_for_user() {
Gav Wood's avatar
Gav Wood committed
		if [[ $( ask_user "$1" ) == false ]]; then
			abort_install "${red}==>${reset} Process stopped by user. To resume the install run the one-liner command again."
		fi
	}

	function ask_user() {
		while :
		do
			read -p "${blue}==>${reset} $1 [Y/n] " imp
			case $imp in
Gav Wood's avatar
Gav Wood committed
				[yY] ) echo true; break ;;
				'' ) echo true; break ;;
				[nN] ) echo false; break ;;
				* ) echo "Unrecognized option provided. Please provide either 'Y' or 'N'";
			esac
		done
	}

	function prompt_for_input() {
		while :
		do
			read -p "$1 " imp
			echo $imp
			return
		done
	}

	function exe() {
		echo "\$ $@"; "$@"
	}

	function sudo() {
		if $isSudo; then
			`which sudo` "$@"
		else
			"$@"
		fi
	}

Gav Wood's avatar
Gav Wood committed
	function detect_os() {
		if [[ "$OSTYPE" == "linux-gnu" ]]
		then
			OS_TYPE="linux"
			get_linux_dependencies
		elif [[ "$OSTYPE" == "darwin"* ]]
		then
			OS_TYPE="osx"
			get_osx_dependencies
		else
			OS_TYPE="win"
Gav Wood's avatar
Gav Wood committed
			abort_install "${red}==>${reset} ${b}OS not supported:${reset} Parity one-liner currently support OS X and Linux.${n}For instructions on installing parity on other platforms please visit ${u}${blue}http://ethcore.io/${reset}"
		fi

		echo

		if [[ $depCount == $depFound ]]
		then
			green "Found all dependencies ($depFound/$depCount)"
		else
			if [[ $canContinue == true ]]
			then
				red "Some dependencies are missing ($depFound/$depCount)"
			elif [[ $canContinue == false && $depFound == 0 ]]
			then
				red "All dependencies are missing and cannot be auto-installed ($depFound/$depCount)"
Gav Wood's avatar
Gav Wood committed
				abort_install "$errorMessages";
			elif [[ $canContinue == false ]]
			then
				red "Some dependencies which cannot be auto-installed are missing ($depFound/$depCount)"
Gav Wood's avatar
Gav Wood committed
				abort_install "$errorMessages";
			fi
		fi
	}

	function get_osx_dependencies()
	{
		macos_version
		find_git
		find_ruby
		find_brew
	}

	function macos_version()
	{
		declare -a reqVersion
		declare -a localVersion

		depCount=$((depCount+1))
		OSX_VERSION=`/usr/bin/sw_vers -productVersion 2>/dev/null`

		if [ -z "$OSX_VERSION" ]
		then
			uncheck "OS X version not supported 🔥"
			isOsVersion=false
			canContinue=false
		else
			IFS='.' read -a localVersion <<< "$OSX_VERSION"
			IFS='.' read -a reqVersion <<< "$OSX_REQUIERED_VERSION"

			if (( ${reqVersion[0]} <= ${localVersion[0]} )) && (( ${reqVersion[1]} <= ${localVersion[1]} ))
			then
				check "OS X Version ${OSX_VERSION}"
				isOsVersion=true
				depFound=$((depFound+1))
				return
			else
				uncheck "OS X version not supported"
				isOsVersion=false
				canContinue=false
			fi
		fi

Gav Wood's avatar
Gav Wood committed
		errorMessages+="${red}==>${reset} ${b}Mac OS version too old:${reset} eth requires OS X version ${red}$OSX_REQUIERED_VERSION${reset} at least in order to run.${n}"
		errorMessages+="    Please update the OS and reload the install process.${n}"
	}

	function find_eth()
	{
		ETH_PATH=`which eth 2>/dev/null`

		if [[ -f $ETH_PATH ]]
		then
			check "Found eth: $ETH_PATH"
			echo "$($ETH_PATH -V)"
			isEth=true
		else
			uncheck "Eth is missing"
			isEth=false
		fi
	}

	function find_git()
	{
		depCount=$((depCount+1))

		GIT_PATH=`which git 2>/dev/null`

		if [[ -f $GIT_PATH ]]
		then
			check "$($GIT_PATH --version)"
			isGit=true
			depFound=$((depFound+1))
		else
			uncheck "Git is missing"
			isGit=false
		fi
	}

	function find_ruby()
	{
		depCount=$((depCount+1))

		RUBY_PATH=`which ruby 2>/dev/null`

		if [[ -f $RUBY_PATH ]]
		then
			RUBY_VERSION=`ruby -e "print RUBY_VERSION"`
			check "Ruby ${RUBY_VERSION}"
			isRuby=true
			depFound=$((depFound+1))
		else
			uncheck "Ruby is missing 🔥"
			isRuby=false
			canContinue=false
Gav Wood's avatar
Gav Wood committed
			errorMessages+="${red}==>${reset} ${b}Couldn't find Ruby:${reset} Brew requires Ruby which could not be found.${n}"
			errorMessages+="    Please install Ruby using these instructions ${u}${blue}https://www.ruby-lang.org/en/documentation/installation/${reset}.${n}"
		fi
	}

	function find_brew()
	{
		BREW_PATH=`which brew 2>/dev/null`

		if [[ -f $BREW_PATH ]]
		then
			check "$($BREW_PATH -v)"
			isBrew=true
			depFound=$((depFound+1))
		else
			uncheck "Homebrew is missing"
			isBrew=false

Gav Wood's avatar
Gav Wood committed
			INSTALL_FILES+="${blue}${dim}==> Homebrew:${reset}${n}"
			INSTALL_FILES+=" ${blue}${dim}${reset}  $HOMEBREW_PREFIX/bin/brew${n}"
			INSTALL_FILES+=" ${blue}${dim}${reset}  $HOMEBREW_PREFIX/Library${n}"
			INSTALL_FILES+=" ${blue}${dim}${reset}  $HOMEBREW_PREFIX/share/man/man1/brew.1${n}"
		fi

		depCount=$((depCount+1))
	}

	function install_brew()
	{
		if [[ $isBrew == false ]]
		then
			head "Installing Homebrew"

			if [[ $isRuby == true ]]
			then
				ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
			else
				cd /usr

				if [[ ! -d $HOMEBREW_PREFIX ]]
				then
					sudo mkdir $HOMEBREW_PREFIX
					sudo chmod g+rwx $HOMEBREW_PREFIX
				fi

				if [[ ! -d $HOMEBREW_CACHE ]]
				then
					sudo mkdir $HOMEBREW_CACHE
					sudo chmod g+rwx $HOMEBREW_CACHE
				fi

				DEVELOPER_DIR=`/usr/bin/xcode-select -print-path 2>/dev/null`

				if [[ ! $(ls -A $DEVELOPER_DIR) || ! -f $DEVELOPER_DIR/usr/bin/git ]]
				then
					info "Installing the Command Line Tools (expect a GUI popup):"
					sudo /usr/bin/xcode-select --install

					echo "Press any key when the installation has completed"
				fi

				cd $HOMEBREW_PREFIX

				bash -o pipefail -c "curl -fsSL ${HOMEBREW_REPO}/tarball/master | tar xz -m --strip 1"
			fi

			find_brew
			echo

			if [[ $isBrew == false ]]
			then
Gav Wood's avatar
Gav Wood committed
				abort_install "Couldn't install brew"
			fi
		fi
	}

	function osx_installer()
	{
		osx_dependency_installer

		info "Updating brew"
		exe brew update
		echo

		info "Installing rocksdb"
		exe brew install rocksdb
		info "Installing multirust"
		exe brew install multirust
		sudo multirust update nightly
		sudo multirust default nightly
		echo
	}

	function osx_dependency_installer()
	{
		if [[ $isGit == false ]];
		then
			echo "Installing Git"
		fi

		if [[ $isRuby == false ]];
		then
			echo "Installing Ruby"
		fi

		if [[ $isBrew == false ]];
		then
			install_brew
		fi
	}

	function linux_version()
	{
		source /etc/lsb-release
		
		if [[ $DISTRIB_ID == "Ubuntu" ]]; then
			if [[ $DISTRIB_RELEASE == "14.04" || $DISTRIB_RELEASE == "15.04" || $DISTRIB_RELEASE == "15.10" ]]; then
				check "Ubuntu"
				isUbuntu=true
				check "Ubuntu, but version not supported"
				isUbuntu=false
			isUbuntu=false
	function get_linux_dependencies()
	{
Gav Wood's avatar
Gav Wood committed
		find_curl
Gav Wood's avatar
Gav Wood committed
		find_git
		find_make
		find_gcc

		find_apt
	function find_rocksdb()
	{
		depCount=$((depCount+1))
		if [[ $(ldconfig -v 2>/dev/null | grep rocksdb | wc -l) == 1 ]]; then
			depFound=$((depFound+1))
			check "apt-get"
			isRocksDB=true
Gav Wood's avatar
Gav Wood committed
			INSTALL_FILES+="${blue}${dim}==> librocksdb:${reset}$n"
		else
			uncheck "librocksdb is missing"
			isRocksDB=false
Gav Wood's avatar
Gav Wood committed
			INSTALL_FILES+="${blue}${dim}==> librocksdb:${reset}$n"
		fi
	}

	function find_multirust()
	{
		depCount=$((depCount+2))
		MULTIRUST_PATH=`which multirust 2>/dev/null`
		if [[ -f $MULTIRUST_PATH ]]; then
			depFound=$((depFound+1))
			check "multirust"
			isMultirust=true
			if [[ $(multirust show-default 2>/dev/null | grep nightly | wc -l) == 4 ]]; then
				depFound=$((depFound+1))
				check "rust nightly"
				isMultirustNightly=true
			else
				uncheck "rust is not nightly"
				isMultirustNightly=false
Gav Wood's avatar
Gav Wood committed
				INSTALL_FILES+="${blue}${dim}==> multirust -> rust nightly:${reset}${n}"
			fi
		else
			uncheck "multirust is missing"
			uncheck "rust nightly is missing"
			isMultirust=false
			isMultirustNightly=false
Gav Wood's avatar
Gav Wood committed
			INSTALL_FILES+="${blue}${dim}==> multirust:${reset}${n}"
	function find_apt()
	{
Gav Wood's avatar
Gav Wood committed
		depCount=$((depCount+1))

		APT_PATH=`which apt-get 2>/dev/null`

		if [[ -f $APT_PATH ]]
		then
Gav Wood's avatar
Gav Wood committed
			depFound=$((depFound+1))
			check "apt-get"
			isApt=true
		else
			uncheck "apt-get is missing"
			isApt=false
Gav Wood's avatar
Gav Wood committed
			if [[ $isGCC == false || $isGit == false || $isMake == false || $isCurl == false ]]; then
Gav Wood's avatar
Gav Wood committed
				canContinue=false
Gav Wood's avatar
Gav Wood committed
				errorMessages+="${red}==>${reset} ${b}Couldn't find apt-get:${reset} We can only use apt-get in order to grab our dependencies.${n}"
				errorMessages+="    Please switch to a distribution such as Debian or Ubuntu or manually install the missing packages.${n}"
Gav Wood's avatar
Gav Wood committed
			fi
		fi
	}

	function find_gcc()
	{
		depCount=$((depCount+1))
		GCC_PATH=`which g++ 2>/dev/null`

		if [[ -f $GCC_PATH ]]
		then
			depFound=$((depFound+1))
			check "g++"
			isGCC=true
		else
			uncheck "g++ is missing"
			isGCC=false
Gav Wood's avatar
Gav Wood committed
			INSTALL_FILES+="${blue}${dim}==> g++:${reset}${n}"
	function find_sudo()
	{
		depCount=$((depCount+1))
		SUDO_PATH=`which sudo 2>/dev/null`

		if [[ -f $SUDO_PATH ]]
		then
			depFound=$((depFound+1))
			check "sudo"
			isSudo=true
			uncheck "sudo is missing"
			if [[ `whoami` == "root" ]]; then
				if [[ $isApt == false && $isMultirust == false ]]; then
					canContinue=false
Gav Wood's avatar
Gav Wood committed
					errorMessages+="${red}==>${reset} ${b}Couldn't find sudo:${reset} Sudo is needed for the installation of multirust.${n}"
					errorMessages+="    Please ensure you have sudo installed or alternatively install multirust manually.${n}"
			else
				canContinue=false
Gav Wood's avatar
Gav Wood committed
				errorMessages+="${red}==>${reset} ${b}Couldn't find sudo:${reset} Root access is needed for parts of this installation.${n}"
				errorMessages+="    Please ensure you have sudo installed or alternatively run this script as root.${n}"
Gav Wood's avatar
Gav Wood committed
	function find_git()
	{
		depCount=$((depCount+1))
		GIT_PATH=`which git 2>/dev/null`

		if [[ -f $GIT_PATH ]]
		then
			depFound=$((depFound+1))
			check "git"
			isGit=true
		else
			uncheck "git is missing"
			isGit=false
Gav Wood's avatar
Gav Wood committed
			INSTALL_FILES+="${blue}${dim}==> git:${reset}${n}"
Gav Wood's avatar
Gav Wood committed
		fi
	}

	function find_make()
	{
		depCount=$((depCount+1))
		MAKE_PATH=`which make 2>/dev/null`

		if [[ -f $MAKE_PATH ]]
		then
			depFound=$((depFound+1))
			check "make"
			isMake=true
		else
			uncheck "make is missing"
			isMake=false
Gav Wood's avatar
Gav Wood committed
			INSTALL_FILES+="${blue}${dim}==> make:${reset}${n}"
Gav Wood's avatar
Gav Wood committed
	function find_curl()
	{
		depCount=$((depCount+1))
		CURL_PATH=`which curl 2>/dev/null`
Gav Wood's avatar
Gav Wood committed

		if [[ -f $CURL_PATH ]]
		then
			depFound=$((depFound+1))
			check "curl"
			isCurl=true
		else
			uncheck "curl is missing"
			isCurl=false
Gav Wood's avatar
Gav Wood committed
			INSTALL_FILES+="${blue}${dim}==> curl:${reset}${n}"
	function ubuntu_rocksdb_installer()
		sudo apt-get update -qq
		sudo apt-get install -qq -y software-properties-common
		sudo apt-add-repository -y ppa:ethcore/ethcore
		sudo apt-get -f -y install
		sudo apt-get update -qq
Gav Wood's avatar
Gav Wood committed
		sudo apt-get install -qq -y librocksdb-dev librocksdb
	function linux_rocksdb_installer()
	{
		if [[ $isUbuntu == true ]]; then
			ubuntu_rocksdb_installer
KKudryavtsev's avatar
KKudryavtsev committed
			exe git clone --branch v4.2 --depth=1 https://github.com/facebook/rocksdb.git
			cd rocksdb
			exe make shared_lib
			sudo cp -a librocksdb.so* /usr/lib
			sudo ldconfig
			cd /tmp
			rm -rf /tmp/rocksdb
			cd $oldpwd
		fi
	}

	function linux_installer()
	{
Gav Wood's avatar
Gav Wood committed
		if [[ $isGCC == false || $isGit == false || $isMake == false || $isCurl == false ]]; then
Gav Wood's avatar
Gav Wood committed
			info "Installing build dependencies..."
Gav Wood's avatar
Gav Wood committed
			if [[ $isGit == false ]]; then
				sudo apt-get install -q -y git
			fi
			if [[ $isGCC == false ]]; then
				sudo apt-get install -q -y g++ gcc
			fi
			if [[ $isMake == false ]]; then
				sudo apt-get install -q -y make
			fi
Gav Wood's avatar
Gav Wood committed
			if [[ $isCurl == false ]]; then
				sudo apt-get install -q -y curl
			fi
Gav Wood's avatar
Gav Wood committed
			echo
		fi
		if [[ $isRocksDB == false ]]; then
			info "Installing rocksdb..."
			linux_rocksdb_installer
			echo
		fi
		if [[ $isMultirust == false ]]; then
			info "Installing multirust..."
			if [[ $isSudo == false ]]; then
				apt-get install -q -y sudo
			fi
			curl -sf https://raw.githubusercontent.com/brson/multirust/master/blastoff.sh | sudo sh -s -- --yes
			echo
		fi

		if [[ $isMultirustNightly == false ]]; then
			info "Installing rust nightly..."
Gav Wood's avatar
Gav Wood committed
			multirust update nightly
			multirust default nightly
	}

	function install()
	{
		echo
		head "Installing Parity build dependencies"

		if [[ $OS_TYPE == "osx" ]]
		then
			osx_installer
		elif [[ $OS_TYPE == "linux" ]]
		then
			linux_installer
		fi
	}

	function verify_installation()
	{
		info "Verifying installation"

		if [[ $OS_TYPE == "linux" ]]; then
			find_curl
			find_git
			find_make
			find_gcc
			find_rocksdb
			find_multirust

			if [[ $isCurl == false || $isGit == false || $isMake == false || $isGCC == false || $isRocksDB == false || $isMultirustNightly == false ]]; then
Gav Wood's avatar
Gav Wood committed
				abort_install
	function build_parity()
	{
		info "Downloading Parity..."
Gav Wood's avatar
Gav Wood committed
		git clone https://github.com/ethcore/parity
Gav Wood's avatar
Gav Wood committed
		git submodule init
		git submodule update
		info "Building..."
		cargo build --release
		cd ..
Gav Wood's avatar
Gav Wood committed
		successHeading "Parity is built!"
		info "Parity source code is in ${b}$(pwd)/parity${reset}. From there, you can:"
		info "- Run a client & sync the chain with:"
		info "    ${b}cargo run --release${reset}"
		info "- Run a JSONRPC-capable client (for use with netstats) with:"
		info "    ${b}cargo run --release -- -j --jsonrpc-url 127.0.0.1:8545${reset}"
		info "- Run tests with:"
		info "    ${b}cargo test --release --features ethcore/json-tests -p ethcore${reset}"
		info "- Install the client with:"
Gav Wood's avatar
Gav Wood committed
		info "    ${b}sudo cp parity/target/release/parity${reset}"
	}

	function install_netstats()
	{
		echo "Installing netstats"

		secret=$(prompt_for_input "Please enter the netstats secret:")
		instance_name=$(prompt_for_input "Please enter your instance name:")
		contact_details=$(prompt_for_input "Please enter your contact details (optional):")
		
		# install ethereum & install dependencies
		sudo apt-get install -y -qq build-essential git unzip wget nodejs npm ntp cloud-utils

		# add node symlink if it doesn't exist
		[[ ! -f /usr/bin/node ]] && sudo ln -s /usr/bin/nodejs /usr/bin/node

		# set up time update cronjob
		sudo bash -c "cat > /etc/cron.hourly/ntpdate << EOF
		#!/bin/sh
		pm2 flush
		sudo service ntp stop
		sudo ntpdate -s ntp.ubuntu.com
		sudo service ntp start
		EOF"

		sudo chmod 755 /etc/cron.hourly/ntpdate

		[ ! -d "www" ] && git clone https://github.com/cubedro/eth-net-intelligence-api netstats
		cd netstats
		git pull
		git checkout 95d595258239a0fdf56b97dedcfb2be62f6170e6

		sudo npm install
		sudo npm install pm2 -g

		cat > app.json << EOL
[
	{
		"name"							: "node-app",
		"script"						: "app.js",
		"log_date_format"		: "YYYY-MM-DD HH:mm Z",
		"merge_logs"				: false,
		"watch"							: false,
		"max_restarts"			: 10,
		"exec_interpreter"	: "node",
		"exec_mode"					: "fork_mode",
		"env":
		{
			"NODE_ENV"				: "production",
			"RPC_HOST"				: "localhost",
			"RPC_PORT"				: "8545",
			"LISTENING_PORT"	: "30303",
			"INSTANCE_NAME"		: "${instance_name}",
			"CONTACT_DETAILS" : "${contact_details}",
			"WS_SERVER"				: "wss://rpc.ethstats.net",
			"WS_SECRET"				: "${secret}",
			"VERBOSITY"				: 2
		
		}
	}
]
EOL

		pm2 start app.json
		cd ..
Gav Wood's avatar
Gav Wood committed
	function abort_install()
Gav Wood's avatar
Gav Wood committed
		error "Installation aborted"
		echo -e "$1"
		echo
		exit 0
	}

	function finish()
	{
		echo
		successHeading "Installation successful!"
		echo

	####### Run the script
	tput clear
	echo
	echo
	echo " ${blue}${b}${green} WELCOME TO PARITY ${reset} ${blue}${reset}"
	echo
	echo

	# Check dependencies
	head "Checking OS dependencies"
Gav Wood's avatar
Gav Wood committed
	detect_os
Gav Wood's avatar
Gav Wood committed
	if [[ $INSTALL_FILES != "" ]]; then
		echo
		head "In addition to the Parity build dependencies, this script will install:"
Gav Wood's avatar
Gav Wood committed
		echo "$INSTALL_FILES"
		echo
	fi

	# Prompt user to continue or abort
Gav Wood's avatar
Gav Wood committed
	wait_for_user "${b}Last chance!${reset} Sure you want to install this software?"

	# Install dependencies and eth
	install

	# Check installation
	verify_installation

	if [[ ! -e parity ]]; then
		# Maybe install parity
Gav Wood's avatar
Gav Wood committed
		if [[ $(ask_user "${b}Parity${reset} Would you like to download and build parity?") == true ]]; then
			# Do get parity.
			build_parity
		fi
	fi

	if [[ $OS_TYPE == "linux" && $DISTRIB_ID == "Ubuntu" ]]; then
Gav Wood's avatar
Gav Wood committed
		if [[ $(ask_user "${b}Netstats${reset} Would you like to download, install and configure a Netstats client?${n}${b}${red}WARNING: ${reset}${red}This will need a secret and reconfigure any existing node/NPM installation you have.${reset} ") == true ]]; then
	# Display goodby message
	finish
}

Gav Wood's avatar
Gav Wood committed
run_installer