From 4005cd05ea1f4bc6a8fcbcb0f793f57bd20af0be Mon Sep 17 00:00:00 2001 From: Florian Staudacher Date: Mon, 8 Apr 2013 17:28:42 +0200 Subject: [PATCH 1/9] refactor install script the script is now split up in parts that will be fetched from github on demand. fixes #4047 --- Changelog.md | 1 + script/install.sh | 491 +++---------------------------- script/install/defaults | 51 ++++ script/install/functions | 272 +++++++++++++++++ script/install/path_sanitizer | 40 +++ script/install/remote_var_reader | 13 + script/install/setup | 177 +++++++++++ 7 files changed, 590 insertions(+), 455 deletions(-) create mode 100644 script/install/defaults create mode 100644 script/install/functions create mode 100644 script/install/path_sanitizer create mode 100644 script/install/remote_var_reader create mode 100644 script/install/setup diff --git a/Changelog.md b/Changelog.md index b0d4eeb1c..9f7cc0974 100644 --- a/Changelog.md +++ b/Changelog.md @@ -106,6 +106,7 @@ everything is set up. * Delete unnecessary javascript views. [#4059](https://github.com/diaspora/diaspora/pull/4059) * Cleanup of script/server * Attempt to stabilize federation of attached photos (fix [#3033](https://github.com/diaspora/diaspora/issues/3033) [#3940](https://github.com/diaspora/diaspora/pull/3940) +* Refactor develop install script [#4111](https://github.com/diaspora/diaspora/pull/4111) ## Bug fixes diff --git a/script/install.sh b/script/install.sh index fd0870e26..1c5a9497b 100755 --- a/script/install.sh +++ b/script/install.sh @@ -1,210 +1,49 @@ #!/usr/bin/env bash -### -# MAKE ME BETTER -### - -: ' -see https://github.com/jamiew/git-friendly for more ideas - -maybe this should be two files -one which includes cloning diaspora/diaspora, and one that assumes you already cloned it yourself -maybe one script just calls another? - - -other ideas what we could do - - 1. check that you have ruby installed, if not, point to wiki page and exit - 2. check to see if we need sudo (generally, if it is a system ruby you need sudo, which you can check - if which ruby is /usr/bin/ruby, or does not have rvm in the path) - 3. check if you have bundle installed and install it, and install with/without sudo if you need it - - check if you have mysql and/or postgres installed, point to wiki page if neither is found. - (maybe even switch database.yml if this is the case?) - - make it work if you have just cloned diapsora and want a quick setup, or - support magic install, like this http://docs.meteor.com/#quickstart -' - #### #### # # -# DEFAULT VARS # +# minimal required functions to load the rest... # # # #### #### -# required programs -declare -A BINARIES -BINARIES["git"]="git" -BINARIES["ruby"]="ruby" -BINARIES["rubygems"]="gem" -BINARIES["bundler"]="bundle" -BINARIES["sed"]="sed" -BINARIES["mktemp"]="mktemp" -D_GIT_CLONE_PATH="/srv/diaspora" # path for diaspora +# ... let's hope nobody hijacks githubs DNS while this runs :P +D_REMOTE_BASE_URL="https://raw.github.com/diaspora/diaspora/develop/" -D_REMOTE_REPO_URL="https://github.com/diaspora/diaspora.git" +# ruby environment +D_REMOTE_ENV_PATH="script/env/ruby_env" -D_INSTALL_SCRIPT_URL="https://raw.github.com/diaspora/diaspora/master/script/install.sh" +# installer files +D_INSTALL_SCRIPT="script/install.sh" +D_INSTALL_DEFAULTS_PATH="script/install/defaults" +D_INSTALL_REMOTE_VAR_READER_PATH="script/install/remote_var_reader" +D_INSTALL_PATH_SANITIZER_PATH="script/install/path_sanitizer" +D_INSTALL_FUNCTIONS_PATH="script/install/functions" +D_INSTALL_SETUP_PATH="script/install/setup" -D_WIKI_URL="https://github.com/diaspora/diaspora/wiki" +# fetch a remote script containing functions and eval them into the local env +include_remote() { + _remote_include=$1 + __TMP=$(curl -L $_remote_include) + eval "$__TMP" +} -D_IRC_URL="irc://freenode.net/diaspora" -D_DB="mysql" +include_remote "$D_REMOTE_BASE_URL$D_INSTALL_DEFAULTS_PATH" +include_remote "$D_REMOTE_BASE_URL$D_INSTALL_REMOTE_VAR_READER_PATH" +include_remote "$D_REMOTE_BASE_URL$D_INSTALL_PATH_SANITIZER_PATH" +include_remote "$D_REMOTE_BASE_URL$D_INSTALL_FUNCTIONS_PATH" +include_remote "$D_REMOTE_BASE_URL$D_INSTALL_SETUP_PATH" -D_DB_CONFIG_FILE="config/database.yml" +read_var_remote "ruby_version" "D_RUBY_VERSION" -D_DB_HOST="localhost" - -D_DB_USER="diaspora" - -D_DB_PASS="diaspora" - -# TODO: read this from ./script/env/ruby_env -D_RUBY_VERSION="1.9.3-p194" - -#### INTERNAL VARS #### - -RVM_DETECTED=false -JS_RUNTIME_DETECTED=false -ONE_UP="\e[1A" #### #### # # -# FUNCTIONS, etc. # +# define some overly long message strings here... # # # #### #### -#... could be put in a separate file and sourced here - -# heredoc for variables - very readable, http://stackoverflow.com/a/8088167 -# use like this: -# define VAR <<'EOF' -# somecontent -# EOF -define(){ IFS='\n' read -r -d '' ${1}; } - -# add padding to the left of a given string to -# fill to a given amount of characters with a -# given char or space -# example: -# lpad 7 "test" "-" -lpad() { - LEN=$1 - TXT=$2 - CHR=$3 - PAD="" - - L_PAD=$(($LEN - ${#TXT})) - if [ $L_PAD -ne 0 ] ; then - PAD=$(printf "%*s" ${L_PAD} " ") - fi - if [ ${#CHR} -ne 0 ] ; then - PAD=$(printf "$PAD" | tr " " "$CHR") - fi - PAD="${PAD}${TXT}" - - printf "%s" "$PAD" -} - -# log function -# prints a given message with the given log level to STDOUT -logf() { - MSG=$1 - LVL=$2 - L_LEN=7 - - if [ ${#LVL} -ne 0 ] ; then - LVL="[$(lpad $(($L_LEN-2)) $LVL " ")]" - else - LVL=$(lpad $L_LEN "" "-") - fi - - printf "%s -- %s\\n" "$LVL" "$MSG" -} - -# short functions for various log levels -log_err() { - logf "$1" "error" -} - -log_wrn() { - logf "$1" "warn" -} - -log_dbg() { - logf "$1" "debug" -} - -log_inf() { - logf "$1" "info" -} - -# run a command or print the error -run_or_error() { - eval "$1" - if [ $? -ne 0 ]; then - error "executing '$1' failed." - fi -} - -# nicely output error messages and quit -error() { - log_err "$1" - logf "have a look at our wiki: $D_WIKI_URL" - logf "or join us on IRC: $D_IRC_URL" - exit 1 -} - -# check for functions -fn_exists() { - type -t $1 | grep -q 'function' -} - -# shell interactive or not -interactive_check() { - fd=0 #stdin - if [[ -t "$fd" || -p /dev/stdin ]]; then - # all is well - printf "\n" - else - # non-interactive - TMPFILE=`mktemp` - curl -s -o "$TMPFILE" "$D_INSTALL_SCRIPT_URL" - chmod +x "$TMPFILE" - exec 0< /dev/tty - bash -i "$TMPFILE" - rm "$TMPFILE" - exit 0 - fi -} - -# check if this script is run as root -root_check() { - if [ `id -u` -eq 0 ] ; then - error "don't run this script as root!" - fi -} - -# check if all necessary binaries are available -binaries_check() { - for exe in "${!BINARIES[@]}"; do - LOG_MSG="checking for $exe... " - log_inf "$LOG_MSG" - - EXE_PATH=$(which "${BINARIES[$exe]}") - if [ $? -ne 0 ]; then - error "you are missing the '${BINARIES[$exe]}' command, please install '$exe'"; - else - printf "$ONE_UP" - log_inf "$LOG_MSG found" - fi - done - printf "\n" -} - -# check for rvm define RVM_MSG <<'EOT' RVM was not found on your system (or it isn't working properly). It is higly recommended to use it, since it's making it extremely easy @@ -212,98 +51,8 @@ to install, manage and work with multiple ruby environments. For more details check out https://rvm.io// EOT -rvm_check() { - LOG_MSG="checking for rvm... " - log_inf "$LOG_MSG" - fn_exists rvm - if [ $? -eq 0 ] ; then - RVM_DETECTED=true - # seems we don't have it loaded, try to do so - elif [ -s "$HOME/.rvm/scripts/rvm" ] ; then - source "$HOME/.rvm/scripts/rvm" >/dev/null 2>&1 - RVM_DETECTED=true - elif [ -s "/usr/local/rvm/scripts/rvm" ] ; then - source "/usr/local/rvm/scripts/rvm" >/dev/null 2>&1 - RVM_DETECTED=true - fi - - if $RVM_DETECTED ; then - printf "$ONE_UP" - log_inf "$LOG_MSG found" - else - log_wrn "not found" - logf "$RVM_MSG" - read -p "Press [Enter] to continue without RVM or abort this script and install RVM..." - fi - printf "\n" -} - -# prepare ruby with rvm -install_or_use_ruby() { - if ! $RVM_DETECTED ; then - return - fi - - # make sure we have the correct ruby version available - LOG_MSG="checking your ruby version... " - log_inf "$LOG_MSG" - - rvm use $D_RUBY_VERSION >/dev/null 2>&1 - if [ $? -ne 0 ] ; then - log_wrn "not ok" - rvm --force install $D_RUBY_VERSION - else - printf "$ONE_UP" - log_inf "$LOG_MSG ok" - fi - - printf "\n" -} - -# trust and load rvmrc -# do this in a directory that has a .rvmrc, only :) -load_rvmrc() { - if ! $RVM_DETECTED || [[ ! -s ".rvmrc" ]] ; then - return - fi - - # trust rvmrc - rvm rvmrc is_trusted - if [ $? -ne 0 ] ; then - rvm rvmrc trust - fi - - # load .rvmrc - LOG_MSG="loading .rvmrc ... " - log_inf "$LOG_MSG" - - . ".rvmrc" - #rvm rvmrc load - if [ $? -eq 0 ] ; then - printf "$ONE_UP" - log_inf "$LOG_MSG ok" - else - log_wrn "not ok" - fi - printf "\n" -} - -# rvm doesn't need sudo, otherwise we do have to use it :( -rvm_or_sudo() { - if $RVM_DETECTED ; then - run_or_error "$1" - else - eval "$1" - if [ $? -ne 0 ] ; then - log_wrn "running '$1' didn't succeed, trying again with sudo..." - run_or_error "sudo $1" - fi - fi -} - -# we need a valid js runtime... define JS_RT_MSG <<'EOT' This script was unable to find a JavaScript runtime compatible to ExecJS on your system. We recommend you install either Node.js or TheRubyRacer, since @@ -315,154 +64,16 @@ TheRubyRacer -- https://github.com/cowboyd/therubyracer For more information on ExecJS, visit -- https://github.com/sstephenson/execjs EOT -js_runtime_check() { - LOG_MSG="checking for a JavaScript runtime... " - log_inf "$LOG_MSG" - # Node.js - which node >/dev/null 2>&1 - if [ $? -eq 0 ] ; then - JS_RUNTIME_DETECTED=true - fi - - # TheRubyRacer - (printf "require 'v8'" | ruby) >/dev/null 2>&1 - if [ $? -eq 0 ] ; then - JS_RUNTIME_DETECTED=true - fi - - ## - # add a check for your favourite js runtime here... - ## - - if $JS_RUNTIME_DETECTED ; then - printf "$ONE_UP" - log_inf "$LOG_MSG found" - else - log_err "not ok" - printf "$JS_RT_MSG" - error "can't continue without a JS runtime" - fi - printf "\n" -} - -# make ourselves comfy -prepare_install_env() { - install_or_use_ruby - load_rvmrc - js_runtime_check - - log_inf "making sure the 'bundler' gem is installed" - rvm_or_sudo "gem install bundler" -} - -# do some sanity checking -sane_environment_check() { - binaries_check - rvm_check -} - -# find or set up a working git environment -git_stuff_check() { - printf "Where would you like to put the git clone, or, where is your existing git clone?\n" - printf "(please use a full path, not '~' or '.')\n" - read -e -p "-> " D_GIT_CLONE_PATH - printf "\n" - - test -d "$D_GIT_CLONE_PATH" \ - && cd "$D_GIT_CLONE_PATH" \ - && git status # folder exists? go there. is a good git clone? - if [ $? -ne 0 ]; then - # not a git repo, create it? - printf "the folder you specified does not exist or doesn't contain a git repo\n" - read -p "Press [Enter] to create it and continue... " - run_or_error "mkdir -p -v \"$D_GIT_CLONE_PATH\"" # only if it doesn't exist - run_or_error "git clone \"$D_REMOTE_REPO_URL\" \"$D_GIT_CLONE_PATH\"" - else - run_or_error "git checkout master" - run_or_error "git pull" - fi - printf "\n" -} - -# handle database decision -database_question() { - printf "Which database type are you using? [1|2]\n" - select choice in "MySQL" "PgSQL"; do - case $choice in - MySQL ) - D_DB="mysql" - # we're done, mysql is default - break - ;; - PgSQL ) - D_DB="postgres" - # replace default with postgres - run_or_error "sed -i'' -e 's/\(<<: \*mysql\)/#\1/g' \"$D_DB_CONFIG_FILE\"" - run_or_error "sed -i'' -e 's/\(#\(<<: \*postgres\)\)/\2/g' \"$D_DB_CONFIG_FILE\"" - break - ;; - esac - done - - printf "\n" -} - -# ask for database credentials -database_credentials() { - printf "Please specify the database credentials\n(the user must be existent and allowed to create new databases)\n" - read -e -p "hostname: " D_DB_HOST - read -e -p "username: " D_DB_USER - read -e -p "password: " D_DB_PASS - - run_or_error "sed -i'' -e \"s/\(host:\)[^\n]*/\1 $D_DB_HOST/g\" \"$D_DB_CONFIG_FILE\"" - run_or_error "sed -i'' -e \"s/\(username:\)[^\n]*/\1 $D_DB_USER/g\" \"$D_DB_CONFIG_FILE\"" - run_or_error "sed -i'' -e \"s/\(password:\)[^\n]*/\1 $D_DB_PASS/g\" \"$D_DB_CONFIG_FILE\"" - - printf "\n" -} - -# setup database -# (assume we are in the Diaspora directory) define DATABASE_CHK_MSG << 'EOT' -you can now check the generated database config file in './config/database.yml' +You can now check the generated database config file in './config/database.yml' and see if the specified values are correct. +Please make sure the database server is started and the credentials you +specified are working. This script will populate the database in a later step. + EOT -database_setup() { - log_inf "Database setup" - run_or_error "cp config/database.yml.example \"$D_DB_CONFIG_FILE\"" - printf "\n" - database_question - database_credentials - - printf "$DATABASE_CHK_MSG" - read -p "Press [Enter] to continue... " - - printf "\n" -} - -# install all the gems with bundler -# (assume we are in the Diaspora directory) -prepare_gem_bundle() { - log_inf "installing all required gems..." - rvm_or_sudo "bundle install" - printf "\n" -} - - -#### #### -# # -# START # -# # -#### #### - -#interactive_check -root_check - - -# display a nice welcome message define WELCOME_MSG <<'EOT' ##################################################################### @@ -480,40 +91,6 @@ Follow the guide in our wiki, instead: ##################################################################### EOT -printf "$WELCOME_MSG" -read -p "Press [Enter] to continue... " - - -# check if we have everything we need -sane_environment_check - - -# check git stuff and pull if necessary -git_stuff_check - - -# goto working directory -run_or_error "cd \"$D_GIT_CLONE_PATH\"" -prepare_install_env - - -# configure database setup -database_setup - - -# diaspora config -log_inf "copying diaspora.yml.example to diaspora.yml" -run_or_error "cp config/diaspora.yml.example config/diaspora.yml" -printf "\n" - - -# bundle gems -prepare_gem_bundle - - -log_inf "creating the default database specified in config/database.yml. please wait..." -run_or_error "bundle exec rake db:schema:load_if_ruby --trace" -printf "\n" define GOODBYE_MSG </dev/null 2>&1 + RVM_DETECTED=true + elif [ -s "/usr/local/rvm/scripts/rvm" ] ; then + source "/usr/local/rvm/scripts/rvm" >/dev/null 2>&1 + RVM_DETECTED=true + fi + + if $RVM_DETECTED ; then + printf "$ONE_UP" + log_inf "$LOG_MSG found" + else + log_wrn "not found" + logf "$RVM_MSG" + read -p "Press [Enter] to continue without RVM or abort this script and install RVM..." + fi + printf "\n" +} + + +# prepare ruby with rvm +install_or_use_ruby() { + if ! $RVM_DETECTED ; then + return + fi + + # make sure we have the correct ruby version available + LOG_MSG="checking your ruby version... " + log_inf "$LOG_MSG" + + rvm use $D_RUBY_VERSION >/dev/null 2>&1 + if [ $? -ne 0 ] ; then + log_wrn "not ok" + rvm --force install $D_RUBY_VERSION + else + printf "$ONE_UP" + log_inf "$LOG_MSG ok" + fi + + printf "\n" +} + + +# trust and load rvmrc +# do this in a directory that has a .rvmrc, only :) +load_rvmrc() { + if ! $RVM_DETECTED || [[ ! -s ".rvmrc" ]] ; then + return + fi + + # trust rvmrc + rvm rvmrc is_trusted + if [ $? -ne 0 ] ; then + rvm rvmrc trust + fi + + # load .rvmrc + LOG_MSG="loading .rvmrc ... " + log_inf "$LOG_MSG" + + . ".rvmrc" + #rvm rvmrc load + if [ $? -eq 0 ] ; then + printf "$ONE_UP" + log_inf "$LOG_MSG ok" + else + log_wrn "not ok" + fi + printf "\n" +} + + +# rvm doesn't need sudo, otherwise we do have to use it :( +rvm_or_sudo() { + if $RVM_DETECTED ; then + run_or_error "$1" + else + eval "$1" + if [ $? -ne 0 ] ; then + log_wrn "running '$1' didn't succeed, trying again with sudo..." + run_or_error "sudo $1" + fi + fi +} + + +# we need a valid js runtime... +js_runtime_check() { + LOG_MSG="checking for a JavaScript runtime... " + log_inf "$LOG_MSG" + + # Node.js + which node >/dev/null 2>&1 + if [ $? -eq 0 ] ; then + JS_RUNTIME_DETECTED=true + fi + + # TheRubyRacer + (printf "require 'v8'" | ruby) >/dev/null 2>&1 + if [ $? -eq 0 ] ; then + JS_RUNTIME_DETECTED=true + fi + + ## + # add a check for your favourite js runtime here... + ## + + if $JS_RUNTIME_DETECTED ; then + printf "$ONE_UP" + log_inf "$LOG_MSG found" + else + log_err "not ok" + printf "$JS_RT_MSG" + error "can't continue without a JS runtime" + fi + printf "\n" +} diff --git a/script/install/path_sanitizer b/script/install/path_sanitizer new file mode 100644 index 000000000..e847b1680 --- /dev/null +++ b/script/install/path_sanitizer @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +# to be included by install.sh + +# Deconstruct a given path string, applies bash expansion and remove all +# remaining relative fragments (e.g. "." or ".."). +# Writes the result in the two given variable names, first is the portion +# with the existing path and the second contains the structure relative to the +# existing path, that'd have to be created. +# usage: +# sanitize_path "~/some/path/string" "EXISTING_VAR_NAME" "REL_NEW_PATH_NAME" +sanitize_path() { + # apply bash expansion + eval _path=$1 + + _existing_path_var=$2 + _rel_new_segment_var=$3 + + _new_segment="" + _chk=1 + _test_cmd='test -d "$_path" -a -n "$_path"' + + $(eval $_test_cmd) && _chk=0 + + while [ $_chk -ne 0 ] ; do + # path doesn't exist, split it up + _segment="$(basename $_path)/$_segment" + _path="$(dirname $_path)" + + $(eval $_test_cmd) && _chk=0 + done + + # remove relative fragments + _path="$(realpath $_path)/" + + log_dbg "pt1 - existing path: $_path" + log_dbg "pt2 - new path: $_segment" + + eval "$_existing_path_var=\"$_path\"" + eval "$_rel_new_segment_var=\"$_segment\"" +} diff --git a/script/install/remote_var_reader b/script/install/remote_var_reader new file mode 100644 index 000000000..76e1226a9 --- /dev/null +++ b/script/install/remote_var_reader @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +# to be included by install.sh + +# read a variable defined in the remote repository +# usage: +# read_remote_var "name_in_remote_script" "name_we_want_locally" +read_var_remote() { + _remote_name=$1 + _local_name=$2 + _remote_source="$D_REMOTE_BASE_URL$D_REMOTE_ENV_PATH" + + eval "$_local_name=\"$(include_remote $_remote_source; echo ${!_remote_name})\"" +} diff --git a/script/install/setup b/script/install/setup new file mode 100644 index 000000000..503538740 --- /dev/null +++ b/script/install/setup @@ -0,0 +1,177 @@ +#!/usr/bin/env bash +# to be included by install.sh + + +#### #### +# # +# DIASPORA* development setup # +# # +#### #### + + +# make ourselves comfy +prepare_install_env() { + install_or_use_ruby + load_rvmrc + js_runtime_check + + log_inf "making sure the 'bundler' gem is installed" + rvm_or_sudo "gem install bundler" +} + + +# do some sanity checking +sane_environment_check() { + binaries_check + rvm_check +} + + +# find or set up a working git environment +git_stuff_check() { + printf "Where would you like to put the git clone, or, where is your existing git clone?\n" + #printf "(please use a full path, not '~' or '.')\n" + read -e -p "-> " D_GIT_CLONE_PATH + printf "\n" + + sanitize_path "$D_GIT_CLONE_PATH" "_D_GCLONE_PATH_EXISTING" "_D_GCLONE_PATH_NEW" + D_GIT_CLONE_PATH="$_D_GCLONE_PATH_EXISTING$_D_GCLONE_PATH_NEW" + + if [ -n "$_D_GCLONE_PATH_NEW" ] ; then + # the path obviously doesn't exist yet + printf "the folder you specified does not exist.\n" + printf "create '$D_GIT_CLONE_PATH'?\n" + read -p "Press [Enter] to create it and continue... " + + log_inf "creating '$D_GIT_CLONE_PATH' and cloning the git repo..." + run_or_error "mkdir -p -v \"$D_GIT_CLONE_PATH\"" + _git_clone_diaspora_repo + + elif ! (cd "$D_GIT_CLONE_PATH" && git status) ; then + # the path doesn't appear to contain a git clone + printf "the folder you specified does not contain a git repo\n" + read -p "Press [Enter] to create it and continue... " + + log_inf "cloning the git repo..." + _git_clone_diaspora_repo + + else + cd "$D_GIT_CLONE_PATH" + + log_inf "setting your git clone to '$D_GIT_BRANCH' branch..." + run_or_error "git stash" + run_or_error "git checkout \"$D_GIT_BRANCH\"" + run_or_error "git pull" + fi + printf "\n" +} + +_git_clone_diaspora_repo() { + run_or_error "git clone \"$D_REMOTE_REPO_URL\" -b \"$D_GIT_BRANCH\" \"$D_GIT_CLONE_PATH\"" +} + + +# handle database decision +database_question() { + printf "Which database type are you using? [1|2]\n" + select choice in "MySQL" "PgSQL"; do + case $choice in + MySQL ) + D_DB="mysql" + # we're done, mysql is default + break + ;; + PgSQL ) + D_DB="postgres" + # replace default with postgres + run_or_error "sed -i'' -e 's/\(<<: \*mysql\)/#\1/g' \"$D_DB_CONFIG_FILE\"" + run_or_error "sed -i'' -e 's/\(#\(<<: \*postgres\)\)/\2/g' \"$D_DB_CONFIG_FILE\"" + break + ;; + esac + done + + printf "\n" +} + + +# ask for database credentials +database_credentials() { + printf "Please specify the database credentials\n(the user must be existent and allowed to create new databases)\n" + read -e -p "hostname: " D_DB_HOST + read -e -p "username: " D_DB_USER + read -e -p "password: " D_DB_PASS + + run_or_error "sed -i'' -e \"s/\(host:\)[^\n]*/\1 $D_DB_HOST/g\" \"$D_DB_CONFIG_FILE\"" + run_or_error "sed -i'' -e \"s/\(username:\)[^\n]*/\1 $D_DB_USER/g\" \"$D_DB_CONFIG_FILE\"" + run_or_error "sed -i'' -e \"s/\(password:\)[^\n]*/\1 $D_DB_PASS/g\" \"$D_DB_CONFIG_FILE\"" + + printf "\n" +} + + +# setup database +# (assume we are in the Diaspora directory) +database_setup() { + log_inf "Database setup" + run_or_error "cp config/database.yml.example \"$D_DB_CONFIG_FILE\"" + printf "\n" + + database_question + database_credentials + + printf "$DATABASE_CHK_MSG" + read -p "Press [Enter] to continue... " + + printf "\n" +} + + +# install all the gems with bundler +# (assume we are in the Diaspora directory) +prepare_gem_bundle() { + log_inf "installing all required gems..." + rvm_or_sudo "bundle install" + printf "\n" +} + + +# main setup function, entry point +# all other functions will be called from here +diaspora_setup() { + #interactive_check + root_check + + # display a nice welcome message + printf "$WELCOME_MSG" + read -p "Press [Enter] to continue... " + + # check if we have everything we need + sane_environment_check + + # check git stuff and pull if necessary + git_stuff_check + + # goto working directory + run_or_error "cd \"$D_GIT_CLONE_PATH\"" + prepare_install_env + + # configure database setup + database_setup + + # diaspora config + log_inf "copying diaspora.yml.example to diaspora.yml" + run_or_error "cp config/diaspora.yml.example config/diaspora.yml" + printf "\n" + + # bundle gems + prepare_gem_bundle + + log_inf "creating the default database specified in config/database.yml. please wait..." + run_or_error "bundle exec rake db:schema:load_if_ruby --trace" + printf "\n" + + printf "$GOODBYE_MSG" + + exit 0 +} From 19d22a8928cc71586eeaf9df1fb39be6ee97fdd5 Mon Sep 17 00:00:00 2001 From: movilla Date: Wed, 1 May 2013 19:22:53 +0200 Subject: [PATCH 2/9] fix missing translation back to top --- Changelog.md | 1 + app/views/streams/main_stream.html.haml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index b0d4eeb1c..e239b20f5 100644 --- a/Changelog.md +++ b/Changelog.md @@ -133,6 +133,7 @@ everything is set up. * My Activity mobile doesn't show second page when clicking "more". [#4109](https://github.com/diaspora/diaspora/issues/4109) * Remove unnecessary navigation bar to access mobile site and re-add flash warning to mobile registrations. [#4085](https://github.com/diaspora/diaspora/pull/4085) * Fix broken reactions link on mobile page [#4125](https://github.com/diaspora/diaspora/pull/4125) +* Missing translation "Back to top". [#4138](https://github.com/diaspora/diaspora/pull/4138) ## Features diff --git a/app/views/streams/main_stream.html.haml b/app/views/streams/main_stream.html.haml index 7deb0934b..3429fff75 100644 --- a/app/views/streams/main_stream.html.haml +++ b/app/views/streams/main_stream.html.haml @@ -61,5 +61,5 @@ = render 'shared/right_sections' - %a{:id=>"back-to-top", :title=>"#{t('.back_to_top')}", :href=>"#"} + %a{:id=>"back-to-top", :title=>"#{t('layouts.application.back_to_top')}", :href=>"#"} ⇧ From 00a33320133cfebe87ec3ffc15d68d2fe13d346e Mon Sep 17 00:00:00 2001 From: Braulio Martinez Date: Wed, 1 May 2013 20:13:31 -0300 Subject: [PATCH 3/9] Remove unnecessary ruby187 hacks --- Changelog.md | 1 + app/controllers/photos_controller.rb | 11 ++--------- app/models/acts_as_taggable_on/tag.rb | 4 ++-- config/application.rb | 6 ------ config/initializers/monkey_patch_to_xs.rb | 12 ------------ spec/models/photo_spec.rb | 11 ++++------- 6 files changed, 9 insertions(+), 36 deletions(-) delete mode 100644 config/initializers/monkey_patch_to_xs.rb diff --git a/Changelog.md b/Changelog.md index dbfa4a9cb..b056425f6 100644 --- a/Changelog.md +++ b/Changelog.md @@ -107,6 +107,7 @@ everything is set up. * Cleanup of script/server * Attempt to stabilize federation of attached photos (fix [#3033](https://github.com/diaspora/diaspora/issues/3033) [#3940](https://github.com/diaspora/diaspora/pull/3940) * Refactor develop install script [#4111](https://github.com/diaspora/diaspora/pull/4111) +* Remove special hacks for supporting Ruby 1.8 [#4113] (https://github.com/diaspora/diaspora/pull/4139) ## Bug fixes diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb index 186b96435..f28b8cc9a 100644 --- a/app/controllers/photos_controller.rb +++ b/app/controllers/photos_controller.rb @@ -141,16 +141,9 @@ class PhotosController < ApplicationController # get file content type att_content_type = (request.content_type.to_s == "") ? "application/octet-stream" : request.content_type.to_s # create tempora##l file - begin - file = Tempfile.new(file_name, {:encoding => 'BINARY'}) - file.print request.raw_post.force_encoding('BINARY') - rescue RuntimeError => e - raise e unless e.message.include?('cannot generate tempfile') - file = Tempfile.new(file_name) # Ruby 1.8 compatibility - file.binmode - file.print request.raw_post - end + file = Tempfile.new(file_name, {:encoding => 'BINARY'}) # put data into this file from raw post request + file.print request.raw_post.force_encoding('BINARY') # create several required methods for this temporal file Tempfile.send(:define_method, "content_type") {return att_content_type} diff --git a/app/models/acts_as_taggable_on/tag.rb b/app/models/acts_as_taggable_on/tag.rb index 70b77f69b..4e652ee4d 100644 --- a/app/models/acts_as_taggable_on/tag.rb +++ b/app/models/acts_as_taggable_on/tag.rb @@ -1,13 +1,13 @@ class ActsAsTaggableOn::Tag self.include_root_in_json = false - + def followed_count @followed_count ||= TagFollowing.where(:tag_id => self.id).count end def self.tag_text_regexp - @@tag_text_regexp ||= (RUBY_VERSION.include?('1.9') ? "[[:alnum:]]_-" : "\\w-") + @@tag_text_regexp ||= "[[:alnum:]]_-" end def self.autocomplete(name) diff --git a/config/application.rb b/config/application.rb index 8e1d13759..2f14c8c41 100644 --- a/config/application.rb +++ b/config/application.rb @@ -5,13 +5,7 @@ require 'pathname' require Pathname.new(__FILE__).expand_path.dirname.join('boot') -# Needed for versions of ruby 1.9.2 that were compiled with libyaml. -# They use psych by default which doesn't handle having a default set of parameters. -# See bug #1120. require 'yaml' -if RUBY_VERSION.include? '1.9' - YAML::ENGINE.yamler= 'syck' -end require 'rails/all' diff --git a/config/initializers/monkey_patch_to_xs.rb b/config/initializers/monkey_patch_to_xs.rb deleted file mode 100644 index cae9570f8..000000000 --- a/config/initializers/monkey_patch_to_xs.rb +++ /dev/null @@ -1,12 +0,0 @@ -#see https://github.com/hpricot/hpricot/issues/53 -if RUBY_VERSION < "1.9" - module Builder - class XmlBase - unless ::String.method_defined?(:encode) - def _escape(text) - text.to_xs - end - end - end - end -end \ No newline at end of file diff --git a/spec/models/photo_spec.rb b/spec/models/photo_spec.rb index b168e10c0..f9e8d2036 100644 --- a/spec/models/photo_spec.rb +++ b/spec/models/photo_spec.rb @@ -120,13 +120,10 @@ describe Photo do it 'should save a photo' do @photo.unprocessed_image.store! File.open(@fixture_name) @photo.save.should == true - begin - binary = @photo.unprocessed_image.read.force_encoding('BINARY') - fixture_binary = File.open(@fixture_name).read.force_encoding('BINARY') - rescue NoMethodError # Ruby 1.8 doesn't have force_encoding - binary = @photo.unprocessed_image.read - fixture_binary = File.open(@fixture_name).read - end + + binary = @photo.unprocessed_image.read.force_encoding('BINARY') + fixture_binary = File.read(@fixture_name).force_encoding('BINARY') + binary.should == fixture_binary end From 4aab8762fa1a8b37cec8ca553f1ac6c186c6614d Mon Sep 17 00:00:00 2001 From: Marco Gallardo Date: Thu, 29 Mar 2012 13:02:08 -0600 Subject: [PATCH 4/9] Locator feature added marker image for publisher, showing div for address, and added functionality to close it when clicking 'X' image showing marker image in publisher renamed map-marker to locator fixed style for map marker image in publisher added locator.js to get user's location loading google maps api removed unecessary append and showing location next to publisher moved location address inside div and added image to close location styled div location address an image to close location removing location when clicking close image cleaned code cleaned code showing loader while location is being obtained, translated normal js to backbone structure, created locations db stuff, and removing location div when clicking 'share' refactored code; started to move code to backbone refactored js code; moving functionality to backbone structure created address function to make accessible address variable value refactored locator.js showing and removing location div from dom created location; it belongs_to status_message added location model and created association with status_message added hidden field for location address and added respective code on js files to retrieve it on ajax call saving location for status_message (post) removing location when sharing renamed locator backbone view to location, added template, showing location, and saving lat and lng prepared and added template to show location added location to post model in order to have it accessible in backbone retrieving location to show it in template removed console.log XD fixes when removing location cleanind location_address hidden field when location is removed more fixes; showing location when sharing saving location just when it exists created method to retrieve location address just when location was created fixed issue about showing 'Near from' message when there was not any location added style for location cleaned code renamed locator view retrieving lat and lng from locator.js saving lat and lng in location_coords saving lat and lng added style for input location_address removed location_address hidden field; the value will be taken directly from input with the location replaced div with location for input; the user will be able to edit the place avoiding submitting the form when pressing Enter key on new input for location added missed spec file for location model refactored location_view code refactored location_view code cleaned code added sinon library for testing added describes for new publisher's view functions created test for destroyLocation function added test for showLocation publisher view function created test for avoidEnter publisher view function removed unnecessary div Created first test for locations view, added more specs, added Sinon.js, and fixed issue with assets loading locator.js for tests moved location stuff to app/assets moved locator.js and sinon.js to app/assets fixed route for images included locator.js to assets fixed issue when post object is different than StatusMessage; also fixed issue with lat and lng loading Sinon for specs refactoring locator errorGettingposition and start replacing google maps stuff with OSM added OpenLayers JS, osmlocator, and added them into the main js changing the locator from Google to OSM instance changing lat and lng value in the backbone view removing google javascript tag in application layout adding jasmine to locator test and removed locator.js adding jasmine to locator test using OSM adding Jasmine test to OSM locator removed locator.js removed require locator and updated schema fixed js response; added location since we are using OSM Locator we don't need locator-spec test fixed spec for location view; we are not using google maps anymore changed description of osmlocator-spec fixed issue with status-message-location template fixed style for location_address textbox fixed tests for locator moved split function to model created test for location model removed puts added effect for location marker added translations for locator removed conflicting-unnecessary lines that were loading files for specs removed sinon library; using sinon-rails gem removed useless code removed puts; added Rails.logger.error added sinon.js file added specific version of sinon-rails gem improving validations sintax using openlayers-rails gem removed 'google API' text using sinon gem isolating LocationStream view refactored validation getting location when post is a Reshare refactored code fixed aligment for elements under location message improved styling for location message refactored begin-rescue block getting absolute root instead of just the root added address method to retrive address of location removed code from Post model; also added descriptinon why it was removed removed validation when retrieving address; with latest refactorizations we dont need them any more interpolated location; using file in locales fixed width for div of location moved Sinon gem into development and test group fixed method's description added missed indexes updated schema with locations table removed openlayers-rails gem preventing location to be saved if there are not coordinates fixed spec; wrong closing tag --- Gemfile | 3 +- Gemfile.lock | 7 +- app/assets/images/icons/marker.png | Bin 0 -> 969 bytes .../javascripts/app/views/content_view.js | 11 +++- .../javascripts/app/views/location_stream.js | 3 + .../javascripts/app/views/location_view.js | 25 +++++++ .../javascripts/app/views/publisher_view.js | 33 +++++++++- .../app/views/stream_post_views.js | 7 +- app/assets/javascripts/jasmine-load-all.js | 3 +- app/assets/javascripts/main.js | 1 + app/assets/javascripts/osmlocator.js | 23 +++++++ app/assets/stylesheets/application.css.sass | 60 +++++++++++++++++ .../status-message-location_tpl.jst.hbs | 5 ++ .../templates/stream-element_tpl.jst.hbs | 1 + app/controllers/status_messages_controller.rb | 1 + app/models/location.rb | 12 ++++ app/models/post.rb | 4 ++ app/models/reshare.rb | 4 ++ app/models/status_message.rb | 6 ++ app/presenters/post_presenter.rb | 1 + app/views/shared/_publisher.html.haml | 8 ++- config/locales/diaspora/en.yml | 1 + config/locales/javascript/javascript.en.yml | 1 + db/migrate/20120405170105_create_locations.rb | 12 ++++ db/schema.rb | 9 +++ .../app/views/location_view_spec.js | 17 +++++ .../app/views/publisher_view_spec.js | 62 ++++++++++++++++++ spec/javascripts/osmlocator-spec.js | 24 +++++++ spec/models/location_spec.rb | 15 +++++ 29 files changed, 347 insertions(+), 12 deletions(-) create mode 100644 app/assets/images/icons/marker.png create mode 100644 app/assets/javascripts/app/views/location_stream.js create mode 100644 app/assets/javascripts/app/views/location_view.js create mode 100644 app/assets/javascripts/osmlocator.js create mode 100644 app/assets/templates/status-message-location_tpl.jst.hbs create mode 100644 app/models/location.rb create mode 100644 db/migrate/20120405170105_create_locations.rb create mode 100644 spec/javascripts/app/views/location_view_spec.js create mode 100644 spec/javascripts/osmlocator-spec.js create mode 100644 spec/models/location_spec.rb diff --git a/Gemfile b/Gemfile index 4a3de515a..9c3cc781d 100644 --- a/Gemfile +++ b/Gemfile @@ -160,7 +160,7 @@ group :development do gem 'guard-rspec', '2.5.3' gem 'rb-fsevent', '0.9.3', :require => false gem 'rb-inotify', '0.9.0', :require => false - + # Preloading environment gem 'guard-spork', '1.5.0' @@ -197,4 +197,5 @@ group :development, :test do # Jasmine (client side application tests (JS)) gem 'jasmine', '1.3.2' + gem 'sinon-rails', '1.4.2.1' end diff --git a/Gemfile.lock b/Gemfile.lock index 4922904e8..952c5910c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -211,7 +211,6 @@ GEM rails multi_json (1.7.2) multipart-post (1.2.0) - mysql2 (0.3.11) nested_form (0.3.2) net-scp (1.1.0) net-ssh (>= 2.6.5) @@ -241,6 +240,7 @@ GEM multi_json (~> 1.3) omniauth-oauth (~> 1.0) orm_adapter (0.4.0) + pg (0.15.1) polyglot (0.3.3) pry (0.9.12) coderay (~> 1.0.5) @@ -357,6 +357,8 @@ GEM rack (~> 1.3, >= 1.3.6) rack-protection (~> 1.2) tilt (~> 1.3, >= 1.3.3) + sinon-rails (1.4.2.1) + railties (>= 3.1) slim (1.3.8) temple (~> 0.6.3) tilt (~> 1.3.3) @@ -441,12 +443,12 @@ DEPENDENCIES messagebus_ruby_api (= 1.0.3) mini_magick (= 3.5) mobile-fu (= 1.1.1) - mysql2 (= 0.3.11) nokogiri (= 1.5.9) omniauth (= 1.1.4) omniauth-facebook (= 1.4.1) omniauth-tumblr (= 1.1) omniauth-twitter (= 0.0.16) + pg (= 0.15.1) rack-cors (= 0.2.7) rack-google-analytics (= 0.11.0) rack-piwik (= 0.2.2) @@ -470,6 +472,7 @@ DEPENDENCIES selenium-webdriver (= 2.32.1) sidekiq (= 2.11.1) sinatra (= 1.3.3) + sinon-rails (= 1.4.2.1) slim (= 1.3.8) spork (= 1.0.0rc3) timecop (= 0.6.1) diff --git a/app/assets/images/icons/marker.png b/app/assets/images/icons/marker.png new file mode 100644 index 0000000000000000000000000000000000000000..99286532988158449b24cb190629e4f49e29d29c GIT binary patch literal 969 zcmV;)12+7LP){Q70008+X+uL$Nkc;* zP;zf(X>4Tx0C)j~RL^S@K@|QrZmG~B2wH0nvUrdpNm;9CMbtL^5n^i$+aIn^?(HA4aZWV5ov6ELTdbo0FI&wK{O>*+w4vx20?>!`FrQsdJlnHR>OPy zcd~b_n$otK2Za4V;76L-DzNVtaSB-y0*E}{p()372;bw_^6ZZ}PI-92wGS&j#91PI zKs7DSe@(bk%_Y-7gGe}(^>I=@oY#w#*Bu9GZf3^F5WP>3rn}7Ut74&?PWBFvy`A)a zPP5)V!Xd&78LdA?xQ(9mjMYElVd13a#D+Z_7&Y|xU=_C-srWU*6kiZcC!$nw*)9$7 zn6CX+@=AhmkT}X@VSsa5NKe;HZuq)~1$`#h6R+ZTR#D-3j}vF!)ZOnz+5)dI4jl{{ z44Mr{P!L4~VVJN`K!!XTF*LGrKO?IK8z<8w`3e3jI8lUGNUta*C8 zn(P`s>{pjD=7Kek#B;Fw@hxAK%$F&Q6vg9J^Xf~4by_hu-=A!MJ3Znq&n~srbFGPs zH&&aMXZ>nO`|hf|ljc?VPhR!${AbO?W8x_>CU%PFA&Hm8F7cAsOREdwU~R_;ot1_u z(ruCYB-LPGn!NQdT|ZlRy+(fw^-+`=%+gee_kY4FWHg<*4sZI8+sFJD270UUORdLHO0nA4V) z%{fwsET5CQ>B?eK%uw4yQc~9?*JVo2}ze(;aRcp*ceL#HUJSllrgm5wQKR zQu+C;QrUh^8rFfA`ftFz{YAidi-`aL010qNS#tmY3ljhU3ljkVnw%H_004nWL_t&- z8GVmI4uBvG1Y6_3_=m6cBYM=c7vjZW7g<3dHfbo`X<0OcAit3SXV7j58o60I4nw3+ zpU}kr0A7;_up2|So0|c^n(s}uNOF3bR2%frlwVO*01Ru#?LrSQJ5ep`as%KCkWFJC r1~;HtK0#f^w|a`Xx;MaKz-QA96AnSENnNl&00000NkvXXu0mjf&$+@B literal 0 HcmV?d00001 diff --git a/app/assets/javascripts/app/views/content_view.js b/app/assets/javascripts/app/views/content_view.js index 68f5f26c8..c869707b7 100644 --- a/app/assets/javascripts/app/views/content_view.js +++ b/app/assets/javascripts/app/views/content_view.js @@ -7,7 +7,8 @@ app.views.Content = app.views.Base.extend({ return _.extend(this.defaultPresenter(), { text : app.helpers.textFormatter(this.model.get("text"), this.model), largePhoto : this.largePhoto(), - smallPhotos : this.smallPhotos() + smallPhotos : this.smallPhotos(), + location: this.location() }); }, @@ -34,12 +35,16 @@ app.views.Content = app.views.Base.extend({ $(evt.currentTarget).hide(); }, + location: function(){ + var address = this.model.get('address')? this.model.get('address') : ''; + return address; + }, + collapseOversized : function() { var collHeight = 200 , elem = this.$(".collapsible") , oembed = elem.find(".oembed") , addHeight = 0; - if($.trim(oembed.html()) != "") { addHeight = oembed.height(); } @@ -100,4 +105,4 @@ app.views.OEmbed = app.views.Base.extend({ insertHTML.attr("src", insertHTML.attr("src") + paramSeparator + "autoplay=1"); this.$el.html(insertHTML); } -}) \ No newline at end of file +}); diff --git a/app/assets/javascripts/app/views/location_stream.js b/app/assets/javascripts/app/views/location_stream.js new file mode 100644 index 000000000..fbf60f580 --- /dev/null +++ b/app/assets/javascripts/app/views/location_stream.js @@ -0,0 +1,3 @@ +app.views.LocationStream = app.views.Content.extend({ + templateName: "status-message-location" +}); diff --git a/app/assets/javascripts/app/views/location_view.js b/app/assets/javascripts/app/views/location_view.js new file mode 100644 index 000000000..a01f2709d --- /dev/null +++ b/app/assets/javascripts/app/views/location_view.js @@ -0,0 +1,25 @@ +app.views.Location = Backbone.View.extend({ + + el: "#location", + + initialize: function(){ + this.render(); + this.getLocation(); + }, + + render: function(){ + $(this.el).append('delete location'); + }, + + getLocation: function(e){ + element = this.el; + + locator = new OSM.Locator(); + locator.getAddress(function(address, latlng){ + $(element).html(''); + $('#location_coords').val(latlng.latitude + "," + latlng.longitude); + $(element).append('delete location'); + }); + }, +}); + diff --git a/app/assets/javascripts/app/views/publisher_view.js b/app/assets/javascripts/app/views/publisher_view.js index 56cd35f91..137bbe381 100644 --- a/app/assets/javascripts/app/views/publisher_view.js +++ b/app/assets/javascripts/app/views/publisher_view.js @@ -23,7 +23,10 @@ app.views.Publisher = Backbone.View.extend(_.extend( "click .post_preview_button" : "createPostPreview", "click .service_icon": "toggleService", "textchange #status_message_fake_text": "handleTextchange", - "click .dropdown .dropdown_list li": "toggleAspect" + "click .dropdown .dropdown_list li": "toggleAspect", + "click #locator" : "showLocation", + "click #hide_location" : "destroyLocation", + "keypress #location_address" : "avoidEnter" }, tooltipSelector: ".service_icon", @@ -79,7 +82,9 @@ app.views.Publisher = Backbone.View.extend(_.extend( }, "aspect_ids" : serializedForm["aspect_ids[]"], "photos" : serializedForm["photos[]"], - "services" : serializedForm["services[]"] + "services" : serializedForm["services[]"], + "location_address" : $("#location_address").val(), + "location_coords" : serializedForm["location[coords]"] }, { url : "/status_messages", success : function() { @@ -94,6 +99,30 @@ app.views.Publisher = Backbone.View.extend(_.extend( // clear state this.clear(); + + // clear location + this.destroyLocation(); + }, + + // creates the location + showLocation: function(){ + if($('#location').length == 0){ + $('#publisher_textarea_wrapper').after('
'); + app.views.location = new app.views.Location(); + } + }, + + // destroys the location + destroyLocation: function(){ + if(app.views.location){ + app.views.location.remove(); + } + }, + + // avoid submitting form when pressing Enter key + avoidEnter: function(evt){ + if(evt.keyCode == 13) + return false; }, createPostPreview : function(evt) { diff --git a/app/assets/javascripts/app/views/stream_post_views.js b/app/assets/javascripts/app/views/stream_post_views.js index 89ddf9927..a8a3d8c52 100644 --- a/app/assets/javascripts/app/views/stream_post_views.js +++ b/app/assets/javascripts/app/views/stream_post_views.js @@ -7,7 +7,8 @@ app.views.StreamPost = app.views.Post.extend({ ".likes" : "likesInfoView", ".comments" : "commentStreamView", ".post-content" : "postContentView", - ".oembed" : "oEmbedView" + ".oembed" : "oEmbedView", + ".status-message-location" : "postLocationStreamView" }, events: { @@ -47,6 +48,10 @@ app.views.StreamPost = app.views.Post.extend({ return new postClass({ model : this.model }) }, + postLocationStreamView : function(){ + return new app.views.LocationStream({ model : this.model}); + }, + removeNsfwShield: function(evt){ if(evt){ evt.preventDefault(); } this.model.set({nsfw : false}) diff --git a/app/assets/javascripts/jasmine-load-all.js b/app/assets/javascripts/jasmine-load-all.js index f7ca3afb4..755afb9a7 100644 --- a/app/assets/javascripts/jasmine-load-all.js +++ b/app/assets/javascripts/jasmine-load-all.js @@ -9,4 +9,5 @@ //= require mobile //= require profile //= require people -//= require photos \ No newline at end of file +//= require photos +//= require sinon diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js index 5562329d4..2df7a3a00 100644 --- a/app/assets/javascripts/main.js +++ b/app/assets/javascripts/main.js @@ -42,3 +42,4 @@ //= require bootstrap-popover //= require bootstrap-dropdown //= require bootstrap-scrollspy-custom +//= require osmlocator diff --git a/app/assets/javascripts/osmlocator.js b/app/assets/javascripts/osmlocator.js new file mode 100644 index 000000000..1ff766294 --- /dev/null +++ b/app/assets/javascripts/osmlocator.js @@ -0,0 +1,23 @@ +OSM = {}; + +OSM.Locator = function(){ + + var geolocalize = function(callback){ + navigator.geolocation.getCurrentPosition(function(position) { + lat=position.coords.latitude; + lon=position.coords.longitude; + var display_name =$.getJSON("http://nominatim.openstreetmap.org/reverse?format=json&lat="+lat+"&lon="+lon+"&addressdetails=3", function(data){ + return callback(data.display_name, position.coords); + }); + },errorGettingPosition); + }; + + function errorGettingPosition(err) { + $("#location").remove(); + }; + + return { + getAddress: geolocalize + } + +} diff --git a/app/assets/stylesheets/application.css.sass b/app/assets/stylesheets/application.css.sass index c0f9c516a..bda28d483 100644 --- a/app/assets/stylesheets/application.css.sass +++ b/app/assets/stylesheets/application.css.sass @@ -573,9 +573,22 @@ ul.as-selections & > .likes, & > .comments :margin-right 15px +.status-message-location + .near-from + :font-size smaller + :color #aaa + :width 100% + :float left + .address + :font-size 11px + :color #bbb + .stream_element .post-content .reshare :border-left 2px solid #ddd +.stream_element.loaded .media .bd .feedback + :clear both + form.new_comment input :display none @@ -697,6 +710,8 @@ form p.checkbox_select :height 100% :width 100% :cursor pointer + img + :margin-right 20px #publisher :z-index 1 @@ -876,6 +891,8 @@ form p.checkbox_select :position absolute :bottom 0 :right 35px + :width 430px + :left 5px :padding 0 li @@ -3120,3 +3137,46 @@ body :bottom 3px solid #3f8fba !important :background :color #e8f7ff + +#publisher-images + #locator + :bottom 1px !important + :display inline-block + :margin 0 + :position absolute !important + :right 30px + :cursor pointer + img + :padding-top 2px + @include opacity(0.4) + &:hover + :color #666 + :cursor pointer + img + @include opacity(0.8) + .btn + :height 19px + :width 19px + +#location + :border 1px solid #999 + :height 20px + #location_address + :border none + :color #aaa + :height 10px + :width 430px + :float left + a#hide_location + :position absolute + :right 22px + :filter alpha(opacity=30) + :-moz-opacity 0.3 + :-khtml-opacity 0.3 + :opacity 0.3 + :z-index 5 + a#hide_location:hover + @include opacity(0) + :-khtml-opacity 1 + :opacity 1 + :cursor pointer diff --git a/app/assets/templates/status-message-location_tpl.jst.hbs b/app/assets/templates/status-message-location_tpl.jst.hbs new file mode 100644 index 000000000..c6c7ea7ec --- /dev/null +++ b/app/assets/templates/status-message-location_tpl.jst.hbs @@ -0,0 +1,5 @@ +{{#if location}} +
+ {{ t "publisher.near_from" location=location}} +
+{{/if}} diff --git a/app/assets/templates/stream-element_tpl.jst.hbs b/app/assets/templates/stream-element_tpl.jst.hbs index 5a4df8288..be0587f72 100644 --- a/app/assets/templates/stream-element_tpl.jst.hbs +++ b/app/assets/templates/stream-element_tpl.jst.hbs @@ -55,6 +55,7 @@ {{/if}}
+
diff --git a/app/controllers/status_messages_controller.rb b/app/controllers/status_messages_controller.rb index 3b8a4d120..119442805 100644 --- a/app/controllers/status_messages_controller.rb +++ b/app/controllers/status_messages_controller.rb @@ -46,6 +46,7 @@ class StatusMessagesController < ApplicationController services = [*params[:services]].compact @status_message = current_user.build_post(:status_message, params[:status_message]) + @status_message.build_location(:address => params[:location_address], :coordinates => params[:location_coords]) if params[:location_address].present? @status_message.attach_photos_by_ids(params[:photos]) if @status_message.save diff --git a/app/models/location.rb b/app/models/location.rb new file mode 100644 index 000000000..b3896c32e --- /dev/null +++ b/app/models/location.rb @@ -0,0 +1,12 @@ +class Location < ActiveRecord::Base + + before_validation :split_coords, :on => :create + + attr_accessor :coordinates + + belongs_to :status_message + + def split_coords + coordinates.present? ? (self.lat, self.lng = coordinates.split(',')) : false + end +end diff --git a/app/models/post.rb b/app/models/post.rb index 847f7ddda..3926a0abf 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -66,6 +66,10 @@ class Post < ActiveRecord::Base def mentioned_people; []; end def photos; []; end + #prevents error when trying to access @post.address in a post different than Reshare and StatusMessage types; + #check PostPresenter + def address + end def self.excluding_blocks(user) people = user.blocks.map{|b| b.person_id} diff --git a/app/models/reshare.rb b/app/models/reshare.rb index e5bdba9b9..1815badb4 100644 --- a/app/models/reshare.rb +++ b/app/models/reshare.rb @@ -79,6 +79,10 @@ class Reshare < Post current end + def address + absolute_root.location.try(:address) + end + private def after_parse diff --git a/app/models/status_message.rb b/app/models/status_message.rb index 949db615e..c46c3e3d3 100644 --- a/app/models/status_message.rb +++ b/app/models/status_message.rb @@ -18,6 +18,8 @@ class StatusMessage < Post has_many :photos, :dependent => :destroy, :foreign_key => :status_message_guid, :primary_key => :guid + has_one :location + # a StatusMessage is federated before its photos are so presence_of_content() fails erroneously if no text is present # therefore, we put the validation in a before_destory callback instead of a validation before_destroy :presence_of_content @@ -164,6 +166,10 @@ class StatusMessage < Post self.oembed_url = urls.find{ |url| !TRUSTED_OEMBED_PROVIDERS.find(url).nil? } end + def address + location.try(:address) + end + protected def presence_of_content unless text_and_photos_blank? diff --git a/app/presenters/post_presenter.rb b/app/presenters/post_presenter.rb index 895ff9a4f..03d05f559 100644 --- a/app/presenters/post_presenter.rb +++ b/app/presenters/post_presenter.rb @@ -33,6 +33,7 @@ class PostPresenter :title => title, :next_post => next_post_path, :previous_post => previous_post_path, + :address => @post.address, :interactions => { :likes => [user_like].compact, diff --git a/app/views/shared/_publisher.html.haml b/app/views/shared/_publisher.html.haml index f2150dfca..f892b4e44 100644 --- a/app/views/shared/_publisher.html.haml +++ b/app/views/shared/_publisher.html.haml @@ -26,8 +26,12 @@ = status.text_area :fake_text, :rows => 2, :value => h(publisher_formatted_text), :tabindex => 1, :placeholder => "#{t('contacts.index.start_a_conversation')}..." = status.hidden_field :text, :value => h(publisher_hidden_text), :class => 'clear_on_submit' - #file-upload{:title => t('.upload_photos')} - = image_tag 'icons/camera.png', :alt => t('.upload_photos').titleize + #publisher-images + #locator.btn{:title => t('.get_location')} + = image_tag 'icons/marker.png', :alt => t('.get_location').titleize, :class => 'publisher_image' + #file-upload.btn{:title => t('.upload_photos')} + = image_tag 'icons/camera.png', :alt => t('.upload_photos').titleize, :class => 'publisher_image' + = hidden_field :location, :coords - if publisher_public = hidden_field_tag 'aspect_ids[]', "public" diff --git a/config/locales/diaspora/en.yml b/config/locales/diaspora/en.yml index 92984d995..6b98b10b2 100644 --- a/config/locales/diaspora/en.yml +++ b/config/locales/diaspora/en.yml @@ -794,6 +794,7 @@ en: make_public: "make public" all: "all" upload_photos: "Upload photos" + get_location: "Get your location" all_contacts: "all contacts" share_with: "share with" whats_on_your_mind: "What's on your mind?" diff --git a/config/locales/javascript/javascript.en.yml b/config/locales/javascript/javascript.en.yml index 44e6f0e42..4c2507c2f 100644 --- a/config/locales/javascript/javascript.en.yml +++ b/config/locales/javascript/javascript.en.yml @@ -41,6 +41,7 @@ en: at_least_one_aspect: "You must publish to at least one aspect" limited: "Limited - your post will only be seen by people you are sharing with" public: "Public - your post will be visible to everyone and found by search engines" + near_from: "Near from: <%= location %>" infinite_scroll: no_more: "No more posts." no_more_contacts: "No more contacts." diff --git a/db/migrate/20120405170105_create_locations.rb b/db/migrate/20120405170105_create_locations.rb new file mode 100644 index 000000000..f46d76860 --- /dev/null +++ b/db/migrate/20120405170105_create_locations.rb @@ -0,0 +1,12 @@ +class CreateLocations < ActiveRecord::Migration + def change + create_table :locations do |t| + t.string :address + t.string :lat + t.string :lng + t.integer :status_message_id + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 9b1ff820f..79e696a65 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -151,6 +151,15 @@ ActiveRecord::Schema.define(:version => 20130404211624) do add_index "likes", ["target_id", "author_id", "target_type"], :name => "index_likes_on_target_id_and_author_id_and_target_type", :unique => true add_index "likes", ["target_id"], :name => "index_likes_on_post_id" + create_table "locations", :force => true do |t| + t.string "address" + t.string "lat" + t.string "lng" + t.integer "status_message_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + create_table "mentions", :force => true do |t| t.integer "post_id", :null => false t.integer "person_id", :null => false diff --git a/spec/javascripts/app/views/location_view_spec.js b/spec/javascripts/app/views/location_view_spec.js new file mode 100644 index 000000000..68e5ac59b --- /dev/null +++ b/spec/javascripts/app/views/location_view_spec.js @@ -0,0 +1,17 @@ +describe("app.views.Location", function(){ + beforeEach(function(){ + OSM = {}; + OSM.Locator = function(){return { getAddress:function(){}}}; + + this.view = new app.views.Location(); + }); + + describe("When it gets instantiated", function(){ + it("creates #location_address", function(){ + + expect($("#location_address")).toBeTruthy(); + expect($("#location_coords")).toBeTruthy(); + expect($("#hide_location")).toBeTruthy(); + }) + }); +}); diff --git a/spec/javascripts/app/views/publisher_view_spec.js b/spec/javascripts/app/views/publisher_view_spec.js index e40c66466..5c9b0866a 100644 --- a/spec/javascripts/app/views/publisher_view_spec.js +++ b/spec/javascripts/app/views/publisher_view_spec.js @@ -292,4 +292,66 @@ describe("app.views.Publisher", function() { }); }); }); + + context("locator", function() { + beforeEach(function() { + // should be jasmine helper + loginAs({name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}}); + + spec.loadFixture("aspects_index"); + this.view = new app.views.Publisher(); + }); + + describe('#showLocation', function(){ + it("Show location", function(){ + + // inserts location to the DOM; it is the location's view element + setFixtures('
'); + + // creates a fake Locator + OSM = {}; + OSM.Locator = function(){return { getAddress:function(){}}}; + + // validates there is not location + expect($("#location").length).toBe(0); + + // this should create a new location + this.view.showLocation(); + + // validates there is one location created + expect($("#location").length).toBe(1); + }) + }); + + describe('#destroyLocation', function(){ + it("Destroy location if exists", function(){ + + // inserts location to the DOM; it is the location's view element + setFixtures('
'); + + // creates a new Location view with the #location element + app.views.Location = new Backbone.View({el:"#location"}); + + // creates the mock + app.views.location = sinon.mock(app.views.Location).object; + + // calls the destroy function and test the expected result + this.view.destroyLocation(); + expect($("#location").length).toBe(0); + }) + }); + + describe('#avoidEnter', function(){ + it("Avoid submitting the form when pressing enter", function(){ + // simulates the event object + evt = {}; + evt.keyCode = 13; + + // should return false in order to avoid the form submition + expect(this.view.avoidEnter(evt)).toBeFalsy(); + }) + }); + }); + }); + diff --git a/spec/javascripts/osmlocator-spec.js b/spec/javascripts/osmlocator-spec.js new file mode 100644 index 000000000..5cd22fa69 --- /dev/null +++ b/spec/javascripts/osmlocator-spec.js @@ -0,0 +1,24 @@ +describe("Locator", function(){ + navigator.geolocation['getCurrentPosition'] = function(myCallback){ + lat = 1; + lon = 2; + position = { coords: { latitude: lat, longitude: lon} } + return myCallback(position); + }; + + $.getJSON = function(url, myCallback){ + if(url == "http://nominatim.openstreetmap.org/reverse?format=json&lat=1&lon=2&addressdetails=3") + { + return myCallback({ display_name: 'locator address' }) + } + } + + var osmlocator = new OSM.Locator(); + + it("should return address, latitude, and longitude using getAddress method", function(){ + osmlocator.getAddress(function(display_name, coordinates){ + expect(display_name, 'locator address') + expect(coordinates, { latitude: 1, longitude: 2 }) + }) + }); +}); diff --git a/spec/models/location_spec.rb b/spec/models/location_spec.rb new file mode 100644 index 000000000..f3c45d654 --- /dev/null +++ b/spec/models/location_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +describe Location do + describe 'before validation' do + it 'should create new location when it has coordinates' do + location = Location.new(coordinates:'1,2') + location.save.should be true + end + + it 'should not create new location when it does not have coordinates' do + location = Location.new() + location.save.should be false + end + end +end From e70c2593ffdf7f7154e77c7d003cfbd7ee98164e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonne=20Ha=C3=9F?= Date: Fri, 3 May 2013 12:07:50 +0200 Subject: [PATCH 5/9] bump configurate --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 4a3de515a..3afef9259 100644 --- a/Gemfile +++ b/Gemfile @@ -23,7 +23,7 @@ gem 'slim', '1.3.8' # Configuration -gem 'configurate', '0.0.6' +gem 'configurate', '0.0.7' # Cross-origin resource sharing diff --git a/Gemfile.lock b/Gemfile.lock index 4922904e8..c36c1ff30 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -75,7 +75,7 @@ GEM sass (~> 3.1) compass-rails (1.0.3) compass (>= 0.12.2, < 0.14) - configurate (0.0.6) + configurate (0.0.7) connection_pool (1.0.0) crack (0.3.2) cucumber (1.2.5) @@ -414,7 +414,7 @@ DEPENDENCIES carrierwave (= 0.8.0) client_side_validations (= 3.2.5) compass-rails (= 1.0.3) - configurate (= 0.0.6) + configurate (= 0.0.7) cucumber-rails (= 1.3.1) database_cleaner (= 0.9.1) devise (= 2.1.3) From fdff9c8b8a77aab84e4354d92bc2be168244feb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonne=20Ha=C3=9F?= Date: Sun, 5 May 2013 10:53:35 +0200 Subject: [PATCH 6/9] drop another capistrano leftover --- config/cap_colors.rb | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 config/cap_colors.rb diff --git a/config/cap_colors.rb b/config/cap_colors.rb deleted file mode 100644 index e5ca5516f..000000000 --- a/config/cap_colors.rb +++ /dev/null @@ -1,11 +0,0 @@ -require 'capistrano_colors' - -capistrano_color_matchers = [ - # Full docs at https://github.com/stjernstrom/capistrano_colors/ - # Any priority above 0 will override capistrano_colors' defaults if needed - { :match => /^Deploying branch/, :color => :yellow, :prio => 20 }, -] - -capistrano_color_matchers.each do |matcher| - Capistrano::Logger::add_color_matcher( matcher ) -end From c41db6634ccd66fb8d123969cb21072cb64aae5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonne=20Ha=C3=9F?= Date: Sun, 5 May 2013 16:12:22 +0200 Subject: [PATCH 7/9] Fix reading of redis namespace from config Changed default to nil to not screw users running develop already --- config/defaults.yml | 2 +- lib/configuration_methods.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/defaults.yml b/config/defaults.yml index 4f3b96796..d4b0ecde9 100644 --- a/config/defaults.yml +++ b/config/defaults.yml @@ -13,7 +13,7 @@ defaults: require_ssl: true single_process_mode: false sidekiq: - namespace: "diaspora" + namespace: concurrency: 5 retry: 10 backtrace: 15 diff --git a/lib/configuration_methods.rb b/lib/configuration_methods.rb index 1dc2b2b19..d41ee81e5 100644 --- a/lib/configuration_methods.rb +++ b/lib/configuration_methods.rb @@ -93,7 +93,7 @@ module Configuration redis_options[:url] = redis_url end - redis_options[:namespace] = AppConfig.environment.sidekiq_namespace.get + redis_options[:namespace] = AppConfig.environment.sidekiq.namespace.get redis_options end From eb5bc379d13b6833b52d768d3bbede4a3b6210bd Mon Sep 17 00:00:00 2001 From: eloydegen Date: Mon, 6 May 2013 16:27:40 +0300 Subject: [PATCH 8/9] Update _header.html.haml Change blog url, now there is no 301 required :) --- app/views/layouts/_header.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/layouts/_header.html.haml b/app/views/layouts/_header.html.haml index 85456cc11..0ec83a54c 100644 --- a/app/views/layouts/_header.html.haml +++ b/app/views/layouts/_header.html.haml @@ -10,5 +10,5 @@ %ul#landing_nav %li= link_to '@joindiaspora', "http://twitter.com/joindiaspora" %li= link_to 'github', "https://github.com/diaspora/diaspora" - %li= link_to t('.blog'), 'http://blog.joindiaspora.com/' + %li= link_to t('.blog'), 'http://blog.diasporafoundation.org/' %li= link_to t('.login'), new_user_session_path, :class => 'login' From e462b95316e225ff4d63472e1d166c7c51f18ab1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonne=20Ha=C3=9F?= Date: Mon, 6 May 2013 17:34:55 +0200 Subject: [PATCH 9/9] add changelog entry for locator [ci skip] --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index b056425f6..bc4d2a5f3 100644 --- a/Changelog.md +++ b/Changelog.md @@ -150,6 +150,7 @@ everything is set up. * Add a preview for posts in the stream [#4099](https://github.com/diaspora/diaspora/issues/4099) * Add shortcut key Shift to submit comments and publish posts. [#4096](https://github.com/diaspora/diaspora/pull/4096) * Show the service username in a tooltip next to the publisher icons [#4126](https://github.com/diaspora/diaspora/pull/4126) +* Ability to add location when creating a post [#3803](https://github.com/diaspora/diaspora/pull/3803) # 0.0.3.4