diff --git a/Changelog.md b/Changelog.md index b0d4eeb1c..bc4d2a5f3 100644 --- a/Changelog.md +++ b/Changelog.md @@ -106,6 +106,8 @@ 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) +* Remove special hacks for supporting Ruby 1.8 [#4113] (https://github.com/diaspora/diaspora/pull/4139) ## Bug fixes @@ -133,6 +135,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 @@ -147,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 diff --git a/Gemfile b/Gemfile index 4a3de515a..ba814e704 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 @@ -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..ba77b24a8 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) @@ -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) @@ -414,7 +416,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) @@ -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 000000000..992865329 Binary files /dev/null and b/app/assets/images/icons/marker.png differ 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/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/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/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/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/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' 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/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=>"#"} ⇧ 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/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 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/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/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/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 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 +} 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 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