diff --git a/.gitignore b/.gitignore
index 760487ca9b31244fc0c16d7602822e08376ed712..d22760e778069498ed0e86a4bccbcb06f870a28a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,4 +22,4 @@ config/unicorn.rb
 db/data.yml
 .idea
 .DS_Store
-
+.chef
diff --git a/.travis.yml b/.travis.yml
index da67e37dbd0842e72c788ff66e410806969aa999..bb4c4a7924562609b3368277976be16dc729ffdb 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,6 +9,8 @@ branches:
     - 'master'
 rvm:
   - 1.9.3
+services:
+  - mysql
 before_script:
   - "cp config/database.yml.$DB config/database.yml"
   - "cp config/gitlab.yml.example config/gitlab.yml"
diff --git a/CHANGELOG b/CHANGELOG
index 6868c07ba52dbde6ce02e6cab7641f13861badbd..99641ad3a95b49db58b4183171b9b2d831a914d8 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,19 @@
+v 2.9.0
+  - fixed inline notes bugs
+  - refactored rspecs
+  - refactored gitolite backend
+  - added factory_girl
+  - restyled projects list on dashboard
+  - ssh keys validation to prevent gitolite crash
+  - send notifications if changed premission in project
+  - scss refactoring. gitlab_bootstrap/ dir 
+  - fix git push http body bigger than 112k problem
+  - list of labels  page under issues tab
+  - API for milestones, keys
+  - restyled buttons
+  - OAuth
+  - Comment order changed
+
 v 2.8.1
   - ability to disable gravatars
   - improved MR diff logic
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000000000000000000000000000000000000..9041530d98006cd8fec496c6e549946a4fe9a042
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,30 @@
+## Contribute to GitLab 
+
+If you want to contribute to GitLab, follow this process:
+
+1. Fork the project
+2. Create a feature branch
+3. Code
+4. Create a pull request
+
+We only accept pull requests if: 
+
+* Your code has proper tests and all tests pass
+* Your code can be merged w/o problems 
+* It wont broke existing functionality
+* Its a quality code
+* We like it :)
+
+## [You may need a developer VM](https://github.com/gitlabhq/developer-vm)
+
+## Running tests
+
+To run the specs for GitLab, you need to run seeds for test db.
+
+    cd gitlabhq
+    rake db:seed_fu RAILS_ENV=test
+
+Then you can run the test suite with rake:
+
+    rake gitlab:test
+
diff --git a/Gemfile b/Gemfile
index 045baa36974f5518c3d4e2971722ddb182b52e39..8e569c5b2e525b07ba78e552352717004371a76a 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,5 +1,13 @@
 source "http://rubygems.org"
 
+def darwin_only(require_as)
+  RUBY_PLATFORM.include?('darwin') && require_as
+end
+
+def linux_only(require_as)
+  RUBY_PLATFORM.include?('linux') && require_as
+end
+
 gem "rails", "3.2.8"
 
 # Supported DBs
@@ -8,6 +16,10 @@ gem "mysql2"
 
 # Auth
 gem "devise", "~> 2.1.0"
+gem 'omniauth'
+gem 'omniauth-google-oauth2'
+gem 'omniauth-twitter'
+gem 'omniauth-github'
 
 # GITLAB patched libs
 gem "grit",          :git => "https://github.com/gitlabhq/grit.git",            :ref => "7f35cb98ff17d534a07e3ce6ec3d580f67402837"
@@ -44,7 +56,8 @@ gem "ffaker"
 gem "seed-fu"
 
 # Markdown to HTML
-gem "redcarpet", "~> 2.1.1"
+gem "redcarpet",     "~> 2.1.1"
+gem "github-markup", "~> 0.7.4"
 
 # Servers
 gem "thin"
@@ -97,20 +110,28 @@ group :development do
 end
 
 group :development, :test do
+  gem 'spinach-rails'
   gem "rspec-rails"
   gem "capybara"
   gem "capybara-webkit"
   gem "headless"
-  gem "autotest"
-  gem "autotest-rails"
   gem "pry"
   gem "awesome_print"
   gem "database_cleaner"
   gem "launchy"
+  gem 'factory_girl_rails'
+
+  # Guard
+  gem 'guard-rspec'
+  gem 'guard-spinach'
+
+  # Notification
+  gem 'rb-fsevent', :require => darwin_only('rb-fsevent')
+  gem 'growl',      :require => darwin_only('growl')
+  gem 'rb-inotify', :require => linux_only('rb-inotify')
 end
 
 group :test do
-  gem 'cucumber-rails', :require => false
   gem "simplecov", :require => false
   gem "shoulda-matchers"
   gem 'email_spec'
@@ -119,5 +140,5 @@ group :test do
 end
 
 group :production do
-  gem "gitlab_meta", '2.8'
+  gem "gitlab_meta", '2.9'
 end
diff --git a/Gemfile.lock b/Gemfile.lock
index 656bede47661b5de65bf9b2abec5c57880f17913..3d27d3fbe816fcf5af41114e741d6f9ddb5c7068 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -68,7 +68,6 @@ GIT
 GEM
   remote: http://rubygems.org/
   specs:
-    ZenTest (4.8.1)
     actionmailer (3.2.8)
       actionpack (= 3.2.8)
       mail (~> 2.4.4)
@@ -100,15 +99,11 @@ GEM
       rails (~> 3.0)
     addressable (2.2.8)
     arel (3.0.2)
-    autotest (4.4.6)
-      ZenTest (>= 4.4.1)
-    autotest-rails (4.1.2)
-      ZenTest (~> 4.5)
     awesome_print (1.0.2)
     bcrypt-ruby (3.0.1)
     blankslate (2.1.2.4)
     bootstrap-sass (2.0.4.0)
-    builder (3.0.0)
+    builder (3.0.2)
     capybara (1.1.2)
       mime-types (>= 1.16)
       nokogiri (>= 1.3.3)
@@ -125,7 +120,7 @@ GEM
     charlock_holmes (0.6.8)
     childprocess (0.3.2)
       ffi (~> 1.0.6)
-    chosen-rails (0.9.8)
+    chosen-rails (0.9.8.3)
       railties (~> 3.0)
       thor (~> 0.14)
     coderay (1.0.6)
@@ -137,16 +132,8 @@ GEM
       execjs
     coffee-script-source (1.3.3)
     colored (1.2)
+    colorize (0.5.8)
     crack (0.3.1)
-    cucumber (1.2.1)
-      builder (>= 2.1.2)
-      diff-lcs (>= 1.1.3)
-      gherkin (~> 2.11.0)
-      json (>= 1.4.6)
-    cucumber-rails (1.3.0)
-      capybara (>= 1.1.2)
-      cucumber (>= 1.1.8)
-      nokogiri (>= 1.5.0)
     daemons (1.1.8)
     database_cleaner (0.8.0)
     devise (2.1.2)
@@ -166,20 +153,36 @@ GEM
     eventmachine (0.12.10)
     execjs (1.4.0)
       multi_json (~> 1.0)
+    factory_girl (4.0.0)
+      activesupport (>= 3.0.0)
+    factory_girl_rails (4.0.0)
+      factory_girl (~> 4.0.0)
+      railties (>= 3.0.0)
+    faraday (0.8.4)
+      multipart-post (~> 1.1)
     ffaker (1.14.0)
     ffi (1.0.11)
     foreman (0.47.0)
       thor (>= 0.13.6)
-    gherkin (2.11.0)
-      json (>= 1.4.6)
+    gherkin-ruby (0.2.1)
     git (1.2.5)
-    gitlab_meta (2.8)
+    github-markup (0.7.4)
+    gitlab_meta (2.9)
     grape (0.2.1)
       hashie (~> 1.2)
       multi_json
       multi_xml
       rack
       rack-mount
+    growl (1.0.3)
+    guard (1.3.2)
+      listen (>= 0.4.2)
+      thor (>= 0.14.6)
+    guard-rspec (1.2.1)
+      guard (>= 1.1)
+    guard-spinach (0.0.2)
+      guard (>= 1.1)
+      spinach
     haml (3.1.6)
     haml-rails (0.3.4)
       actionpack (~> 3.0)
@@ -193,7 +196,8 @@ GEM
     httparty (0.8.3)
       multi_json (~> 1.0)
       multi_xml
-    i18n (0.6.0)
+    httpauth (0.1)
+    i18n (0.6.1)
     journey (1.0.4)
     jquery-rails (2.0.2)
       railties (>= 3.2.0, < 5.0)
@@ -201,11 +205,12 @@ GEM
     jquery-ui-rails (0.5.0)
       jquery-rails
       railties (>= 3.1.0)
-    json (1.7.4)
-    kaminari (0.13.0)
+    json (1.7.5)
+    jwt (0.1.5)
+      multi_json (>= 1.0)
+    kaminari (0.14.0)
       actionpack (>= 3.0.0)
       activesupport (>= 3.0.0)
-      railties (>= 3.0.0)
     kgio (2.7.4)
     launchy (2.1.0)
       addressable (~> 2.2.6)
@@ -214,6 +219,7 @@ GEM
     libv8 (3.3.10.4)
     libwebsocket (0.1.3)
       addressable
+    listen (0.5.0)
     mail (2.4.4)
       i18n (>= 0.4.0)
       mime-types (~> 1.16)
@@ -224,12 +230,35 @@ GEM
       sprockets (~> 2.0)
     multi_json (1.3.6)
     multi_xml (0.5.1)
+    multipart-post (1.1.5)
     mysql2 (0.3.11)
     net-ldap (0.2.2)
     nokogiri (1.5.3)
+    oauth (0.4.7)
+    oauth2 (0.8.0)
+      faraday (~> 0.8)
+      httpauth (~> 0.1)
+      jwt (~> 0.1.4)
+      multi_json (~> 1.0)
+      rack (~> 1.2)
     omniauth (1.1.0)
       hashie (~> 1.2)
       rack
+    omniauth-github (1.0.3)
+      omniauth (~> 1.0)
+      omniauth-oauth2 (~> 1.1)
+    omniauth-google-oauth2 (0.1.13)
+      omniauth (~> 1.0)
+      omniauth-oauth2
+    omniauth-oauth (1.0.1)
+      oauth
+      omniauth (~> 1.0)
+    omniauth-oauth2 (1.1.0)
+      oauth2 (~> 0.8.0)
+      omniauth (~> 1.0)
+    omniauth-twitter (0.0.13)
+      multi_json (~> 1.3)
+      omniauth-oauth (~> 1.0)
     orm_adapter (0.3.0)
     polyglot (0.3.3)
     posix-spawn (0.3.6)
@@ -269,6 +298,9 @@ GEM
     raindrops (0.9.0)
     rake (0.9.2.2)
     raphael-rails (1.5.2)
+    rb-fsevent (0.9.1)
+    rb-inotify (0.8.8)
+      ffi (>= 0.5.0)
     rdoc (3.12)
       json (~> 1.4)
     redcarpet (2.1.1)
@@ -319,7 +351,7 @@ GEM
       multi_json (~> 1.0)
       rubyzip
     settingslogic (2.0.8)
-    shoulda-matchers (1.1.0)
+    shoulda-matchers (1.3.0)
       activesupport (>= 3.0.0)
     simplecov (0.6.4)
       multi_json (~> 1.0)
@@ -331,6 +363,13 @@ GEM
       tilt (~> 1.3, >= 1.3.3)
     six (0.2.0)
     slop (2.4.4)
+    spinach (0.5.2)
+      colorize
+      gherkin-ruby (~> 0.2.0)
+    spinach-rails (0.1.8)
+      capybara (~> 1)
+      railties (>= 3)
+      spinach (>= 0.4)
     sprockets (2.1.3)
       hike (~> 1.2)
       rack (~> 1.0)
@@ -343,7 +382,7 @@ GEM
       daemons (>= 1.0.9)
       eventmachine (>= 0.12.6)
       rack (>= 1.0.0)
-    thor (0.15.4)
+    thor (0.16.0)
     tilt (1.3.3)
     treetop (1.4.10)
       polyglot
@@ -372,8 +411,6 @@ PLATFORMS
 DEPENDENCIES
   acts-as-taggable-on (= 2.3.1)
   annotate!
-  autotest
-  autotest-rails
   awesome_print
   bootstrap-sass (= 2.0.4)
   capybara
@@ -383,19 +420,23 @@ DEPENDENCIES
   chosen-rails
   coffee-rails (= 3.2.2)
   colored
-  cucumber-rails
   database_cleaner
   devise (~> 2.1.0)
   draper
   email_spec
+  factory_girl_rails
   ffaker
   foreman
   git
-  gitlab_meta (= 2.8)
+  github-markup (~> 0.7.4)
+  gitlab_meta (= 2.9)
   gitolite!
   grack!
   grape (~> 0.2.1)
   grit!
+  growl
+  guard-rspec
+  guard-spinach
   haml-rails
   headless
   httparty
@@ -407,12 +448,18 @@ DEPENDENCIES
   linguist (~> 1.0.0)!
   modernizr (= 2.5.3)
   mysql2
+  omniauth
+  omniauth-github
+  omniauth-google-oauth2
   omniauth-ldap!
+  omniauth-twitter
   pry
   pygments.rb!
   rack-mini-profiler
   rails (= 3.2.8)
   raphael-rails (= 1.5.2)
+  rb-fsevent
+  rb-inotify
   redcarpet (~> 2.1.1)
   resque (~> 1.20.0)
   resque_mailer
@@ -424,6 +471,7 @@ DEPENDENCIES
   shoulda-matchers
   simplecov
   six
+  spinach-rails
   sqlite3
   stamp
   therubyracer
diff --git a/Guardfile b/Guardfile
new file mode 100644
index 0000000000000000000000000000000000000000..e682f0b6cf1fb6faa1b3035d20052f5d53396815
--- /dev/null
+++ b/Guardfile
@@ -0,0 +1,27 @@
+# A sample Guardfile
+# More info at https://github.com/guard/guard#readme
+
+guard 'rspec', :version => 2, :all_on_start => false, :all_after_pass => false do
+  watch(%r{^spec/.+_spec\.rb$})
+  watch(%r{^lib/(.+)\.rb$})     { |m| "spec/lib/#{m[1]}_spec.rb" }
+  watch(%r{^lib/api/(.+)\.rb$})     { |m| "spec/requests/api/#{m[1]}_spec.rb" }
+  watch('spec/spec_helper.rb')  { "spec" }
+
+  # Rails example
+  watch(%r{^app/(.+)\.rb$})                           { |m| "spec/#{m[1]}_spec.rb" }
+  watch(%r{^app/(.*)(\.erb|\.haml)$})                 { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
+  watch(%r{^app/controllers/(.+)_(controller)\.rb$})  { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
+  watch(%r{^spec/support/(.+)\.rb$})                  { "spec" }
+  watch('config/routes.rb')                           { "spec/routing" }
+  watch('app/controllers/application_controller.rb')  { "spec/controllers" }
+
+  # Capybara request specs
+  watch(%r{^app/views/(.+)/.*\.(erb|haml)$})          { |m| "spec/requests/#{m[1]}_spec.rb" }
+end
+
+guard 'spinach' do
+  watch(%r|^features/(.*)\.feature|)
+  watch(%r|^features/steps/(.*)([^/]+)\.rb|) do |m|
+    "features/#{m[1]}#{m[2]}.feature"
+  end
+end
diff --git a/README.md b/README.md
index 26ed209ef8799915455cfaafc9f9f070c0aef7ff..122cd984b4a7020dd05d1c91a4a92fdd93c9d9aa 100644
--- a/README.md
+++ b/README.md
@@ -39,5 +39,6 @@ Email
 
 ## Contribute
 
+[Development Tips](https://github.com/gitlabhq/gitlabhq/blob/master/doc/development.md)
 Want to help - send a pull request.
 We'll accept good pull requests.
diff --git a/VERSION b/VERSION
index 1817afea416c4a8e4814d22f5f4b2dcf4b0807e6..c8e38b614057b7e417c63fde44726a4143de9da0 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.8.2
+2.9.0
diff --git a/app/assets/images/emoji/+1.png b/app/assets/images/emoji/+1.png
new file mode 100755
index 0000000000000000000000000000000000000000..3a43ecae29590cb314aeeea6e1b0fc4b065df671
Binary files /dev/null and b/app/assets/images/emoji/+1.png differ
diff --git a/app/assets/images/emoji/-1.png b/app/assets/images/emoji/-1.png
new file mode 100755
index 0000000000000000000000000000000000000000..41c6b825d6a6abf736a1b882c951c1eb942afabf
Binary files /dev/null and b/app/assets/images/emoji/-1.png differ
diff --git a/app/assets/images/emoji/100.png b/app/assets/images/emoji/100.png
new file mode 100755
index 0000000000000000000000000000000000000000..bce9ab14f59d1c8dc298279ed1931292f613fdcd
Binary files /dev/null and b/app/assets/images/emoji/100.png differ
diff --git a/app/assets/images/emoji/109.png b/app/assets/images/emoji/109.png
new file mode 100755
index 0000000000000000000000000000000000000000..74b9d5d38cdce2f1dee8cc7c1ff2fa8619851aed
Binary files /dev/null and b/app/assets/images/emoji/109.png differ
diff --git a/app/assets/images/emoji/1234.png b/app/assets/images/emoji/1234.png
new file mode 100755
index 0000000000000000000000000000000000000000..c47c2e1f9f0d0e86bc78e3a9ee96e643b83a57f1
Binary files /dev/null and b/app/assets/images/emoji/1234.png differ
diff --git a/app/assets/images/emoji/8ball.png b/app/assets/images/emoji/8ball.png
new file mode 100755
index 0000000000000000000000000000000000000000..c2c710d45019ca3110a50771ef41d19da878e708
Binary files /dev/null and b/app/assets/images/emoji/8ball.png differ
diff --git a/app/assets/images/emoji/a.png b/app/assets/images/emoji/a.png
new file mode 100755
index 0000000000000000000000000000000000000000..09ff6d6f184399df9750220cd697392017b85170
Binary files /dev/null and b/app/assets/images/emoji/a.png differ
diff --git a/app/assets/images/emoji/ab.png b/app/assets/images/emoji/ab.png
new file mode 100755
index 0000000000000000000000000000000000000000..2a522204767b0aafef8129675cb7042f3d01b975
Binary files /dev/null and b/app/assets/images/emoji/ab.png differ
diff --git a/app/assets/images/emoji/abc.png b/app/assets/images/emoji/abc.png
new file mode 100755
index 0000000000000000000000000000000000000000..505d40a15572fcaf3b9455d5db41986513360ba4
Binary files /dev/null and b/app/assets/images/emoji/abc.png differ
diff --git a/app/assets/images/emoji/abcd.png b/app/assets/images/emoji/abcd.png
new file mode 100755
index 0000000000000000000000000000000000000000..5218470b63c93b4074c814b879f5c7c542c3b855
Binary files /dev/null and b/app/assets/images/emoji/abcd.png differ
diff --git a/app/assets/images/emoji/accept.png b/app/assets/images/emoji/accept.png
new file mode 100755
index 0000000000000000000000000000000000000000..2d200903188ccc0c59156798e3a939c2dc88ab7e
Binary files /dev/null and b/app/assets/images/emoji/accept.png differ
diff --git a/app/assets/images/emoji/aerial_tramway.png b/app/assets/images/emoji/aerial_tramway.png
new file mode 100755
index 0000000000000000000000000000000000000000..38f6dfe2334f4f48136eec16f5fbf4a507af5306
Binary files /dev/null and b/app/assets/images/emoji/aerial_tramway.png differ
diff --git a/app/assets/images/emoji/airplane.png b/app/assets/images/emoji/airplane.png
new file mode 100755
index 0000000000000000000000000000000000000000..8407cb6757565f0561b470f63a0d2a101fcb50f4
Binary files /dev/null and b/app/assets/images/emoji/airplane.png differ
diff --git a/app/assets/images/emoji/alarm_clock.png b/app/assets/images/emoji/alarm_clock.png
new file mode 100755
index 0000000000000000000000000000000000000000..86ca8c8ed450d0b249c5820f15d43b0504dd413d
Binary files /dev/null and b/app/assets/images/emoji/alarm_clock.png differ
diff --git a/app/assets/images/emoji/alien.png b/app/assets/images/emoji/alien.png
new file mode 100755
index 0000000000000000000000000000000000000000..416de47be465f67782f65262c32c4c10a353b7f2
Binary files /dev/null and b/app/assets/images/emoji/alien.png differ
diff --git a/app/assets/images/emoji/ambulance.png b/app/assets/images/emoji/ambulance.png
new file mode 100755
index 0000000000000000000000000000000000000000..b740f45dba20daf0e9e917feed179467640e232d
Binary files /dev/null and b/app/assets/images/emoji/ambulance.png differ
diff --git a/app/assets/images/emoji/anchor.png b/app/assets/images/emoji/anchor.png
new file mode 100755
index 0000000000000000000000000000000000000000..0c5192e64739dce90d59415bf5c3301db224ef61
Binary files /dev/null and b/app/assets/images/emoji/anchor.png differ
diff --git a/app/assets/images/emoji/angel.png b/app/assets/images/emoji/angel.png
new file mode 100755
index 0000000000000000000000000000000000000000..da52c310c64fd4b2b745df3c44b58aa1c9cdbf6c
Binary files /dev/null and b/app/assets/images/emoji/angel.png differ
diff --git a/app/assets/images/emoji/anger.png b/app/assets/images/emoji/anger.png
new file mode 100755
index 0000000000000000000000000000000000000000..6fb4dca1854fdc7585ba22a7a953f35b42d1b935
Binary files /dev/null and b/app/assets/images/emoji/anger.png differ
diff --git a/app/assets/images/emoji/angry.png b/app/assets/images/emoji/angry.png
new file mode 100755
index 0000000000000000000000000000000000000000..f95bfa897ed9a5bf105a66a3e962eb11d6ccd1a4
Binary files /dev/null and b/app/assets/images/emoji/angry.png differ
diff --git a/app/assets/images/emoji/ant.png b/app/assets/images/emoji/ant.png
new file mode 100755
index 0000000000000000000000000000000000000000..b92d1cc14bde3bd6bb43ba03416719cec806d803
Binary files /dev/null and b/app/assets/images/emoji/ant.png differ
diff --git a/app/assets/images/emoji/apple.png b/app/assets/images/emoji/apple.png
new file mode 100755
index 0000000000000000000000000000000000000000..08aa17b95137ef962f1957a447485dfef8a69339
Binary files /dev/null and b/app/assets/images/emoji/apple.png differ
diff --git a/app/assets/images/emoji/aquarius.png b/app/assets/images/emoji/aquarius.png
new file mode 100755
index 0000000000000000000000000000000000000000..cbff66edcf3c5308ad51cd25a8168158934747ce
Binary files /dev/null and b/app/assets/images/emoji/aquarius.png differ
diff --git a/app/assets/images/emoji/aries.png b/app/assets/images/emoji/aries.png
new file mode 100755
index 0000000000000000000000000000000000000000..899902237c974fb00d51b113e405e3747987c32a
Binary files /dev/null and b/app/assets/images/emoji/aries.png differ
diff --git a/app/assets/images/emoji/arrow_backward.png b/app/assets/images/emoji/arrow_backward.png
new file mode 100755
index 0000000000000000000000000000000000000000..088621834f79d886414b5bce8038f51848600d2f
Binary files /dev/null and b/app/assets/images/emoji/arrow_backward.png differ
diff --git a/app/assets/images/emoji/arrow_double_down.png b/app/assets/images/emoji/arrow_double_down.png
new file mode 100755
index 0000000000000000000000000000000000000000..2ecbebcda13081ebc7167ad60c915c76af94d3a8
Binary files /dev/null and b/app/assets/images/emoji/arrow_double_down.png differ
diff --git a/app/assets/images/emoji/arrow_double_up.png b/app/assets/images/emoji/arrow_double_up.png
new file mode 100755
index 0000000000000000000000000000000000000000..d42979d4bf6adc6b1ea911bd0625beefad84ece1
Binary files /dev/null and b/app/assets/images/emoji/arrow_double_up.png differ
diff --git a/app/assets/images/emoji/arrow_down.png b/app/assets/images/emoji/arrow_down.png
new file mode 100755
index 0000000000000000000000000000000000000000..e6702f02baeebbf7d31c6da3a59e52002a574935
Binary files /dev/null and b/app/assets/images/emoji/arrow_down.png differ
diff --git a/app/assets/images/emoji/arrow_down_small.png b/app/assets/images/emoji/arrow_down_small.png
new file mode 100755
index 0000000000000000000000000000000000000000..f7f2d510137230ea3126018c3b790fda7aee42f9
Binary files /dev/null and b/app/assets/images/emoji/arrow_down_small.png differ
diff --git a/app/assets/images/emoji/arrow_forward.png b/app/assets/images/emoji/arrow_forward.png
new file mode 100755
index 0000000000000000000000000000000000000000..fbfe711b64debda17e7a38e48ef0e3d0f05f85c3
Binary files /dev/null and b/app/assets/images/emoji/arrow_forward.png differ
diff --git a/app/assets/images/emoji/arrow_heading_down.png b/app/assets/images/emoji/arrow_heading_down.png
new file mode 100755
index 0000000000000000000000000000000000000000..56dd3b9d3c82b414776df4825c2cffe22a191695
Binary files /dev/null and b/app/assets/images/emoji/arrow_heading_down.png differ
diff --git a/app/assets/images/emoji/arrow_heading_up.png b/app/assets/images/emoji/arrow_heading_up.png
new file mode 100755
index 0000000000000000000000000000000000000000..c8f670a1ef0d6507b478c10aef33805db936a958
Binary files /dev/null and b/app/assets/images/emoji/arrow_heading_up.png differ
diff --git a/app/assets/images/emoji/arrow_left.png b/app/assets/images/emoji/arrow_left.png
new file mode 100755
index 0000000000000000000000000000000000000000..d64ac619c9d23bfd68d8cbd3bde58419f57d9719
Binary files /dev/null and b/app/assets/images/emoji/arrow_left.png differ
diff --git a/app/assets/images/emoji/arrow_lower_left.png b/app/assets/images/emoji/arrow_lower_left.png
new file mode 100755
index 0000000000000000000000000000000000000000..55fb03c412185cd5f976dfad3c0ea0e2161e45dd
Binary files /dev/null and b/app/assets/images/emoji/arrow_lower_left.png differ
diff --git a/app/assets/images/emoji/arrow_lower_right.png b/app/assets/images/emoji/arrow_lower_right.png
new file mode 100755
index 0000000000000000000000000000000000000000..da8fb8294d91d46426752555c1b32e9543f6f4f1
Binary files /dev/null and b/app/assets/images/emoji/arrow_lower_right.png differ
diff --git a/app/assets/images/emoji/arrow_right.png b/app/assets/images/emoji/arrow_right.png
new file mode 100755
index 0000000000000000000000000000000000000000..6d483b5144f38155564201bb77b7de0921c23de7
Binary files /dev/null and b/app/assets/images/emoji/arrow_right.png differ
diff --git a/app/assets/images/emoji/arrow_right_hook.png b/app/assets/images/emoji/arrow_right_hook.png
new file mode 100755
index 0000000000000000000000000000000000000000..8b4ea6e1720e19534d9bdcddb67d4a3a7a4c72a0
Binary files /dev/null and b/app/assets/images/emoji/arrow_right_hook.png differ
diff --git a/app/assets/images/emoji/arrow_up.png b/app/assets/images/emoji/arrow_up.png
new file mode 100755
index 0000000000000000000000000000000000000000..b5b0688d3c60baa9174e99c9d427c32afe6b43c2
Binary files /dev/null and b/app/assets/images/emoji/arrow_up.png differ
diff --git a/app/assets/images/emoji/arrow_up_down.png b/app/assets/images/emoji/arrow_up_down.png
new file mode 100755
index 0000000000000000000000000000000000000000..b718c21458293f890b495deef5d48acf989d6c29
Binary files /dev/null and b/app/assets/images/emoji/arrow_up_down.png differ
diff --git a/app/assets/images/emoji/arrow_up_small.png b/app/assets/images/emoji/arrow_up_small.png
new file mode 100755
index 0000000000000000000000000000000000000000..1217331977284472dd35685ae89c4102b5db4e0d
Binary files /dev/null and b/app/assets/images/emoji/arrow_up_small.png differ
diff --git a/app/assets/images/emoji/arrow_upper_left.png b/app/assets/images/emoji/arrow_upper_left.png
new file mode 100755
index 0000000000000000000000000000000000000000..e895fd7b628ee110eaa92196e43aad48f96f9121
Binary files /dev/null and b/app/assets/images/emoji/arrow_upper_left.png differ
diff --git a/app/assets/images/emoji/arrow_upper_right.png b/app/assets/images/emoji/arrow_upper_right.png
new file mode 100755
index 0000000000000000000000000000000000000000..e23790ba18d5c2cf1efad64293af7c131b2ff7c1
Binary files /dev/null and b/app/assets/images/emoji/arrow_upper_right.png differ
diff --git a/app/assets/images/emoji/arrows_clockwise.png b/app/assets/images/emoji/arrows_clockwise.png
new file mode 100755
index 0000000000000000000000000000000000000000..5f84d7e72b79e1ada173447a15f44444dcc1b5e8
Binary files /dev/null and b/app/assets/images/emoji/arrows_clockwise.png differ
diff --git a/app/assets/images/emoji/arrows_counterclockwise.png b/app/assets/images/emoji/arrows_counterclockwise.png
new file mode 100755
index 0000000000000000000000000000000000000000..1933ae18b90f830fbff6954eb926f1adacf9bcbf
Binary files /dev/null and b/app/assets/images/emoji/arrows_counterclockwise.png differ
diff --git a/app/assets/images/emoji/art.png b/app/assets/images/emoji/art.png
new file mode 100755
index 0000000000000000000000000000000000000000..d45212b0340418f08b4c2dc74bbcc9a837af917f
Binary files /dev/null and b/app/assets/images/emoji/art.png differ
diff --git a/app/assets/images/emoji/articulated_lorry.png b/app/assets/images/emoji/articulated_lorry.png
new file mode 100755
index 0000000000000000000000000000000000000000..81ec1f917411f42a24c21a66e249e0c2a89a8972
Binary files /dev/null and b/app/assets/images/emoji/articulated_lorry.png differ
diff --git a/app/assets/images/emoji/astonished.png b/app/assets/images/emoji/astonished.png
new file mode 100755
index 0000000000000000000000000000000000000000..858a83484a8d7dcacf867dff9f7513f4b4a668af
Binary files /dev/null and b/app/assets/images/emoji/astonished.png differ
diff --git a/app/assets/images/emoji/atm.png b/app/assets/images/emoji/atm.png
new file mode 100755
index 0000000000000000000000000000000000000000..c2846e792183b0957c0821eb27ae38c4dedf4c66
Binary files /dev/null and b/app/assets/images/emoji/atm.png differ
diff --git a/app/assets/images/emoji/b.png b/app/assets/images/emoji/b.png
new file mode 100755
index 0000000000000000000000000000000000000000..8742b3d2e3ebc335f654f4279519d5413badb699
Binary files /dev/null and b/app/assets/images/emoji/b.png differ
diff --git a/app/assets/images/emoji/baby.png b/app/assets/images/emoji/baby.png
new file mode 100755
index 0000000000000000000000000000000000000000..3b29da40b602d1fc659acd93d9f02ab60e9a5bed
Binary files /dev/null and b/app/assets/images/emoji/baby.png differ
diff --git a/app/assets/images/emoji/baby_bottle.png b/app/assets/images/emoji/baby_bottle.png
new file mode 100755
index 0000000000000000000000000000000000000000..1b2cfe5e30142e5d17119050a1ea452a33130e7a
Binary files /dev/null and b/app/assets/images/emoji/baby_bottle.png differ
diff --git a/app/assets/images/emoji/baby_chick.png b/app/assets/images/emoji/baby_chick.png
new file mode 100755
index 0000000000000000000000000000000000000000..9be8d2930062b1e0c798fa553fb8818aa6615465
Binary files /dev/null and b/app/assets/images/emoji/baby_chick.png differ
diff --git a/app/assets/images/emoji/baby_symbol.png b/app/assets/images/emoji/baby_symbol.png
new file mode 100755
index 0000000000000000000000000000000000000000..2e58725cf56563837391f3e9e0f2203582095a1c
Binary files /dev/null and b/app/assets/images/emoji/baby_symbol.png differ
diff --git a/app/assets/images/emoji/baggage_claim.png b/app/assets/images/emoji/baggage_claim.png
new file mode 100755
index 0000000000000000000000000000000000000000..59ae044a45e8849549f93a241794c0d3daf5540d
Binary files /dev/null and b/app/assets/images/emoji/baggage_claim.png differ
diff --git a/app/assets/images/emoji/balloon.png b/app/assets/images/emoji/balloon.png
new file mode 100755
index 0000000000000000000000000000000000000000..0344897025624a967bb3efcf1d2abfa469eb6f7a
Binary files /dev/null and b/app/assets/images/emoji/balloon.png differ
diff --git a/app/assets/images/emoji/ballot_box_with_check.png b/app/assets/images/emoji/ballot_box_with_check.png
new file mode 100755
index 0000000000000000000000000000000000000000..f07a466c77847298d320668d6d2911377cc51139
Binary files /dev/null and b/app/assets/images/emoji/ballot_box_with_check.png differ
diff --git a/app/assets/images/emoji/bamboo.png b/app/assets/images/emoji/bamboo.png
new file mode 100755
index 0000000000000000000000000000000000000000..fc858d0fc2c2431826a012572b7c565585fe4ade
Binary files /dev/null and b/app/assets/images/emoji/bamboo.png differ
diff --git a/app/assets/images/emoji/banana.png b/app/assets/images/emoji/banana.png
new file mode 100755
index 0000000000000000000000000000000000000000..a0563afb9584524209bf7616ddfa7ecf751feb96
Binary files /dev/null and b/app/assets/images/emoji/banana.png differ
diff --git a/app/assets/images/emoji/bangbang.png b/app/assets/images/emoji/bangbang.png
new file mode 100755
index 0000000000000000000000000000000000000000..7270f0afe6e66920a0cc4059ef29d04e50dc1eb5
Binary files /dev/null and b/app/assets/images/emoji/bangbang.png differ
diff --git a/app/assets/images/emoji/bank.png b/app/assets/images/emoji/bank.png
new file mode 100755
index 0000000000000000000000000000000000000000..1faa8777e42a17dcf75fe2e702638c83e9d0fcbb
Binary files /dev/null and b/app/assets/images/emoji/bank.png differ
diff --git a/app/assets/images/emoji/bar_chart.png b/app/assets/images/emoji/bar_chart.png
new file mode 100755
index 0000000000000000000000000000000000000000..7871cc6032333f84b09e33a88694a19b4f514bb0
Binary files /dev/null and b/app/assets/images/emoji/bar_chart.png differ
diff --git a/app/assets/images/emoji/barber.png b/app/assets/images/emoji/barber.png
new file mode 100755
index 0000000000000000000000000000000000000000..a10cb232286d1b1fa0a5f0d6b77cbcc468311e9b
Binary files /dev/null and b/app/assets/images/emoji/barber.png differ
diff --git a/app/assets/images/emoji/baseball.png b/app/assets/images/emoji/baseball.png
new file mode 100755
index 0000000000000000000000000000000000000000..da004e2ead04f570b01aa9c0723a27117b182838
Binary files /dev/null and b/app/assets/images/emoji/baseball.png differ
diff --git a/app/assets/images/emoji/basketball.png b/app/assets/images/emoji/basketball.png
new file mode 100755
index 0000000000000000000000000000000000000000..ef694bec4c92aa8837c12eae7fe3c51dfc8d7cca
Binary files /dev/null and b/app/assets/images/emoji/basketball.png differ
diff --git a/app/assets/images/emoji/bath.png b/app/assets/images/emoji/bath.png
new file mode 100755
index 0000000000000000000000000000000000000000..8f75d1d2499e46ef31b25c735c76eae87f01c2ee
Binary files /dev/null and b/app/assets/images/emoji/bath.png differ
diff --git a/app/assets/images/emoji/bathtub.png b/app/assets/images/emoji/bathtub.png
new file mode 100755
index 0000000000000000000000000000000000000000..1c3f844ab262b2ad6c00b61bcafeea1cc13ab861
Binary files /dev/null and b/app/assets/images/emoji/bathtub.png differ
diff --git a/app/assets/images/emoji/battery.png b/app/assets/images/emoji/battery.png
new file mode 100755
index 0000000000000000000000000000000000000000..aa7eedce4bbcb3e2d4c7f4a6fcfd321e7e5ecafa
Binary files /dev/null and b/app/assets/images/emoji/battery.png differ
diff --git a/app/assets/images/emoji/bear.png b/app/assets/images/emoji/bear.png
new file mode 100755
index 0000000000000000000000000000000000000000..f5afe920e8e23c2f033d9cb9476a303a6e520d01
Binary files /dev/null and b/app/assets/images/emoji/bear.png differ
diff --git a/app/assets/images/emoji/beer.png b/app/assets/images/emoji/beer.png
new file mode 100755
index 0000000000000000000000000000000000000000..cd78bed7440fee98515a0748851cceddb4efae1b
Binary files /dev/null and b/app/assets/images/emoji/beer.png differ
diff --git a/app/assets/images/emoji/beers.png b/app/assets/images/emoji/beers.png
new file mode 100755
index 0000000000000000000000000000000000000000..cc5e4ab5aa968151058aa335f14b1c458f34f57f
Binary files /dev/null and b/app/assets/images/emoji/beers.png differ
diff --git a/app/assets/images/emoji/beetle.png b/app/assets/images/emoji/beetle.png
new file mode 100755
index 0000000000000000000000000000000000000000..222577ca7ea582012b50223a28095511ae143146
Binary files /dev/null and b/app/assets/images/emoji/beetle.png differ
diff --git a/app/assets/images/emoji/beginner.png b/app/assets/images/emoji/beginner.png
new file mode 100755
index 0000000000000000000000000000000000000000..1f022d175dac777aacc371be6ea0b56ffd398ba8
Binary files /dev/null and b/app/assets/images/emoji/beginner.png differ
diff --git a/app/assets/images/emoji/bell.png b/app/assets/images/emoji/bell.png
new file mode 100755
index 0000000000000000000000000000000000000000..69acceb286ef2a3ede896e8ea2427e25062bb962
Binary files /dev/null and b/app/assets/images/emoji/bell.png differ
diff --git a/app/assets/images/emoji/bento.png b/app/assets/images/emoji/bento.png
new file mode 100755
index 0000000000000000000000000000000000000000..c6d99e89b674f124154f8e3ad748a624bc16afdc
Binary files /dev/null and b/app/assets/images/emoji/bento.png differ
diff --git a/app/assets/images/emoji/bicyclist.png b/app/assets/images/emoji/bicyclist.png
new file mode 100755
index 0000000000000000000000000000000000000000..4e3e0549c21daaeba2ff6ce1a7e181954492475e
Binary files /dev/null and b/app/assets/images/emoji/bicyclist.png differ
diff --git a/app/assets/images/emoji/bike.png b/app/assets/images/emoji/bike.png
new file mode 100755
index 0000000000000000000000000000000000000000..65738602722677c81440b37a42db23c11624312a
Binary files /dev/null and b/app/assets/images/emoji/bike.png differ
diff --git a/app/assets/images/emoji/bikini.png b/app/assets/images/emoji/bikini.png
new file mode 100755
index 0000000000000000000000000000000000000000..4ff63b40f8868b49a803bfcc642c229622f17f39
Binary files /dev/null and b/app/assets/images/emoji/bikini.png differ
diff --git a/app/assets/images/emoji/bird.png b/app/assets/images/emoji/bird.png
new file mode 100755
index 0000000000000000000000000000000000000000..e6be8c027866f2ccdaee2d6389da50c0cea5c227
Binary files /dev/null and b/app/assets/images/emoji/bird.png differ
diff --git a/app/assets/images/emoji/birthday.png b/app/assets/images/emoji/birthday.png
new file mode 100755
index 0000000000000000000000000000000000000000..36e8edcbec4e8a21b060753be80e4ff4ba36d8e3
Binary files /dev/null and b/app/assets/images/emoji/birthday.png differ
diff --git a/app/assets/images/emoji/black_circle.png b/app/assets/images/emoji/black_circle.png
new file mode 100755
index 0000000000000000000000000000000000000000..e46f9df615f92e1c1f00e9a45f010a0a9138c13b
Binary files /dev/null and b/app/assets/images/emoji/black_circle.png differ
diff --git a/app/assets/images/emoji/black_joker.png b/app/assets/images/emoji/black_joker.png
new file mode 100755
index 0000000000000000000000000000000000000000..4c78f3614d798dd3fd8a1c0331c2c340b85785e8
Binary files /dev/null and b/app/assets/images/emoji/black_joker.png differ
diff --git a/app/assets/images/emoji/black_nib.png b/app/assets/images/emoji/black_nib.png
new file mode 100755
index 0000000000000000000000000000000000000000..29f6994c11a79dcdf0ec9790fc33e79a0d24adbe
Binary files /dev/null and b/app/assets/images/emoji/black_nib.png differ
diff --git a/app/assets/images/emoji/black_square.png b/app/assets/images/emoji/black_square.png
new file mode 100755
index 0000000000000000000000000000000000000000..71da10de81ced24b98b721a771147c9b2e91242d
Binary files /dev/null and b/app/assets/images/emoji/black_square.png differ
diff --git a/app/assets/images/emoji/blossom.png b/app/assets/images/emoji/blossom.png
new file mode 100755
index 0000000000000000000000000000000000000000..55a97353b474ba5faebf8322a235f7f98a318c53
Binary files /dev/null and b/app/assets/images/emoji/blossom.png differ
diff --git a/app/assets/images/emoji/blowfish.png b/app/assets/images/emoji/blowfish.png
new file mode 100755
index 0000000000000000000000000000000000000000..a1d47cb7e69b807a442ddc7ecebdfc54104fed51
Binary files /dev/null and b/app/assets/images/emoji/blowfish.png differ
diff --git a/app/assets/images/emoji/blue_book.png b/app/assets/images/emoji/blue_book.png
new file mode 100755
index 0000000000000000000000000000000000000000..e2b9e8c797ab05460602c8ce06abb2702412eadb
Binary files /dev/null and b/app/assets/images/emoji/blue_book.png differ
diff --git a/app/assets/images/emoji/blue_car.png b/app/assets/images/emoji/blue_car.png
new file mode 100755
index 0000000000000000000000000000000000000000..978291e087d6f61a717757fd8c9be70bde621f30
Binary files /dev/null and b/app/assets/images/emoji/blue_car.png differ
diff --git a/app/assets/images/emoji/blue_heart.png b/app/assets/images/emoji/blue_heart.png
new file mode 100755
index 0000000000000000000000000000000000000000..baa29b31bcde24931dcbd256976695ff01c08f74
Binary files /dev/null and b/app/assets/images/emoji/blue_heart.png differ
diff --git a/app/assets/images/emoji/blush.png b/app/assets/images/emoji/blush.png
new file mode 100755
index 0000000000000000000000000000000000000000..3a95eb61a3af84e6de44eaf5b4e165fdf1d1d90d
Binary files /dev/null and b/app/assets/images/emoji/blush.png differ
diff --git a/app/assets/images/emoji/boar.png b/app/assets/images/emoji/boar.png
new file mode 100755
index 0000000000000000000000000000000000000000..8196ad4a14b97d1b79d3e19c257f94396360022d
Binary files /dev/null and b/app/assets/images/emoji/boar.png differ
diff --git a/app/assets/images/emoji/boat.png b/app/assets/images/emoji/boat.png
new file mode 100755
index 0000000000000000000000000000000000000000..ff656dc62bb78682ba3a1775eb4100459ac95bf5
Binary files /dev/null and b/app/assets/images/emoji/boat.png differ
diff --git a/app/assets/images/emoji/bomb.png b/app/assets/images/emoji/bomb.png
new file mode 100755
index 0000000000000000000000000000000000000000..3289787dcf9d5ce7aeabbcd377a2523e893de33d
Binary files /dev/null and b/app/assets/images/emoji/bomb.png differ
diff --git a/app/assets/images/emoji/book.png b/app/assets/images/emoji/book.png
new file mode 100755
index 0000000000000000000000000000000000000000..8b698415c3df31dfe15d7ccf13b158404557e024
Binary files /dev/null and b/app/assets/images/emoji/book.png differ
diff --git a/app/assets/images/emoji/bookmark.png b/app/assets/images/emoji/bookmark.png
new file mode 100755
index 0000000000000000000000000000000000000000..dbee45c605b08bbe6d92075ae245b023db95c7d7
Binary files /dev/null and b/app/assets/images/emoji/bookmark.png differ
diff --git a/app/assets/images/emoji/bookmark_tabs.png b/app/assets/images/emoji/bookmark_tabs.png
new file mode 100755
index 0000000000000000000000000000000000000000..0c4e3bf17df928c5d90fe63dc789dd30fd42c371
Binary files /dev/null and b/app/assets/images/emoji/bookmark_tabs.png differ
diff --git a/app/assets/images/emoji/books.png b/app/assets/images/emoji/books.png
new file mode 100755
index 0000000000000000000000000000000000000000..dca06a1ad99323ebebd02ee97a07c8e12a07e307
Binary files /dev/null and b/app/assets/images/emoji/books.png differ
diff --git a/app/assets/images/emoji/boot.png b/app/assets/images/emoji/boot.png
new file mode 100755
index 0000000000000000000000000000000000000000..58d0fdbcd0cf81be6e14ec0ae8e65edf8317c91e
Binary files /dev/null and b/app/assets/images/emoji/boot.png differ
diff --git a/app/assets/images/emoji/bouquet.png b/app/assets/images/emoji/bouquet.png
new file mode 100755
index 0000000000000000000000000000000000000000..ce637832e17e2e2abea71a72367ad5f9e0c176c3
Binary files /dev/null and b/app/assets/images/emoji/bouquet.png differ
diff --git a/app/assets/images/emoji/bow.png b/app/assets/images/emoji/bow.png
new file mode 100755
index 0000000000000000000000000000000000000000..024cb610492b005e11d41c368fdf0519c0ecba1c
Binary files /dev/null and b/app/assets/images/emoji/bow.png differ
diff --git a/app/assets/images/emoji/bowling.png b/app/assets/images/emoji/bowling.png
new file mode 100755
index 0000000000000000000000000000000000000000..13d8ece2ee5489a81434c7988f2264eed327d8d0
Binary files /dev/null and b/app/assets/images/emoji/bowling.png differ
diff --git a/app/assets/images/emoji/bowtie.png b/app/assets/images/emoji/bowtie.png
new file mode 100755
index 0000000000000000000000000000000000000000..28ff0c787d533e2322317778b67baee8f5c441d6
Binary files /dev/null and b/app/assets/images/emoji/bowtie.png differ
diff --git a/app/assets/images/emoji/boy.png b/app/assets/images/emoji/boy.png
new file mode 100755
index 0000000000000000000000000000000000000000..f79f1f29807f76432586afa2304b475ee3abdb6e
Binary files /dev/null and b/app/assets/images/emoji/boy.png differ
diff --git a/app/assets/images/emoji/bread.png b/app/assets/images/emoji/bread.png
new file mode 100755
index 0000000000000000000000000000000000000000..7e7c63753d3b1f8b94a4a96569339ec15c487e88
Binary files /dev/null and b/app/assets/images/emoji/bread.png differ
diff --git a/app/assets/images/emoji/bride_with_veil.png b/app/assets/images/emoji/bride_with_veil.png
new file mode 100755
index 0000000000000000000000000000000000000000..dd0b0cfdad1ca4d627d0ecbff9aaaec706e08a54
Binary files /dev/null and b/app/assets/images/emoji/bride_with_veil.png differ
diff --git a/app/assets/images/emoji/bridge_at_night.png b/app/assets/images/emoji/bridge_at_night.png
new file mode 100755
index 0000000000000000000000000000000000000000..495b06c3dfe7cb55791cf54a934d1453acf54da1
Binary files /dev/null and b/app/assets/images/emoji/bridge_at_night.png differ
diff --git a/app/assets/images/emoji/briefcase.png b/app/assets/images/emoji/briefcase.png
new file mode 100755
index 0000000000000000000000000000000000000000..46e82b0010c7d7056986d6651f6f26871e38117a
Binary files /dev/null and b/app/assets/images/emoji/briefcase.png differ
diff --git a/app/assets/images/emoji/broken_heart.png b/app/assets/images/emoji/broken_heart.png
new file mode 100755
index 0000000000000000000000000000000000000000..a1bc850ecb4cfcdf75f8668bd0c668537a764223
Binary files /dev/null and b/app/assets/images/emoji/broken_heart.png differ
diff --git a/app/assets/images/emoji/bug.png b/app/assets/images/emoji/bug.png
new file mode 100755
index 0000000000000000000000000000000000000000..c2eaf7a708d8d66baa0203174ce825aa52906f25
Binary files /dev/null and b/app/assets/images/emoji/bug.png differ
diff --git a/app/assets/images/emoji/bulb.png b/app/assets/images/emoji/bulb.png
new file mode 100755
index 0000000000000000000000000000000000000000..23afca1c73f07aab1a20a73c41d67114ec031970
Binary files /dev/null and b/app/assets/images/emoji/bulb.png differ
diff --git a/app/assets/images/emoji/bullettrain_front.png b/app/assets/images/emoji/bullettrain_front.png
new file mode 100755
index 0000000000000000000000000000000000000000..16651acff8ebb8c7359f15db2e1eb9654ceb37be
Binary files /dev/null and b/app/assets/images/emoji/bullettrain_front.png differ
diff --git a/app/assets/images/emoji/bullettrain_side.png b/app/assets/images/emoji/bullettrain_side.png
new file mode 100755
index 0000000000000000000000000000000000000000..8eca368458a3847fa2da6c92e0ad4c1a127bbb49
Binary files /dev/null and b/app/assets/images/emoji/bullettrain_side.png differ
diff --git a/app/assets/images/emoji/bus.png b/app/assets/images/emoji/bus.png
new file mode 100755
index 0000000000000000000000000000000000000000..823aa39e49d233729f3f3f1572f982c5c53fe36c
Binary files /dev/null and b/app/assets/images/emoji/bus.png differ
diff --git a/app/assets/images/emoji/busstop.png b/app/assets/images/emoji/busstop.png
new file mode 100755
index 0000000000000000000000000000000000000000..94894847b54350bae3d3d7d53b4464c2af563d53
Binary files /dev/null and b/app/assets/images/emoji/busstop.png differ
diff --git a/app/assets/images/emoji/bust_in_silhouette.png b/app/assets/images/emoji/bust_in_silhouette.png
new file mode 100755
index 0000000000000000000000000000000000000000..d13139869257fc6b7336d2af23b8ce339b3bcf01
Binary files /dev/null and b/app/assets/images/emoji/bust_in_silhouette.png differ
diff --git a/app/assets/images/emoji/busts_in_silhouette.png b/app/assets/images/emoji/busts_in_silhouette.png
new file mode 100755
index 0000000000000000000000000000000000000000..1f3aabcff60a29ea1da4a0816c282c25817d31d5
Binary files /dev/null and b/app/assets/images/emoji/busts_in_silhouette.png differ
diff --git a/app/assets/images/emoji/cactus.png b/app/assets/images/emoji/cactus.png
new file mode 100755
index 0000000000000000000000000000000000000000..5a2c3cc725e393a3a9836280a8efd8fe414906a6
Binary files /dev/null and b/app/assets/images/emoji/cactus.png differ
diff --git a/app/assets/images/emoji/cake.png b/app/assets/images/emoji/cake.png
new file mode 100755
index 0000000000000000000000000000000000000000..efeb9b4b2145398db357367573993a03da9c30e3
Binary files /dev/null and b/app/assets/images/emoji/cake.png differ
diff --git a/app/assets/images/emoji/calendar.png b/app/assets/images/emoji/calendar.png
new file mode 100755
index 0000000000000000000000000000000000000000..900b868bb9435bb3d410ef3ae5ee04f680c79bd9
Binary files /dev/null and b/app/assets/images/emoji/calendar.png differ
diff --git a/app/assets/images/emoji/calling.png b/app/assets/images/emoji/calling.png
new file mode 100755
index 0000000000000000000000000000000000000000..837897f261b2f2a2e9fb3d040b4cec6f501b81de
Binary files /dev/null and b/app/assets/images/emoji/calling.png differ
diff --git a/app/assets/images/emoji/camel.png b/app/assets/images/emoji/camel.png
new file mode 100755
index 0000000000000000000000000000000000000000..496c186ae6cec08ebd74dd6c2778e5ffea0a6a5e
Binary files /dev/null and b/app/assets/images/emoji/camel.png differ
diff --git a/app/assets/images/emoji/camera.png b/app/assets/images/emoji/camera.png
new file mode 100755
index 0000000000000000000000000000000000000000..397d03b39351adf90023aa3ed00cee36a4ff1d61
Binary files /dev/null and b/app/assets/images/emoji/camera.png differ
diff --git a/app/assets/images/emoji/cancer.png b/app/assets/images/emoji/cancer.png
new file mode 100755
index 0000000000000000000000000000000000000000..ea43a4a2a048ab575c02240833133f1456652898
Binary files /dev/null and b/app/assets/images/emoji/cancer.png differ
diff --git a/app/assets/images/emoji/candy.png b/app/assets/images/emoji/candy.png
new file mode 100755
index 0000000000000000000000000000000000000000..33722f236e96f848610a7ad2536a79adb4ca8f9b
Binary files /dev/null and b/app/assets/images/emoji/candy.png differ
diff --git a/app/assets/images/emoji/capital_abcd.png b/app/assets/images/emoji/capital_abcd.png
new file mode 100755
index 0000000000000000000000000000000000000000..ffc0cba4b4362c1c3a11affb2d6534cb211525bb
Binary files /dev/null and b/app/assets/images/emoji/capital_abcd.png differ
diff --git a/app/assets/images/emoji/capricorn.png b/app/assets/images/emoji/capricorn.png
new file mode 100755
index 0000000000000000000000000000000000000000..f2044e78935a95143d9139503ca5efff1927603b
Binary files /dev/null and b/app/assets/images/emoji/capricorn.png differ
diff --git a/app/assets/images/emoji/car.png b/app/assets/images/emoji/car.png
new file mode 100755
index 0000000000000000000000000000000000000000..d70a2f06263fa99a8553765a6bfbb8a9a86a5597
Binary files /dev/null and b/app/assets/images/emoji/car.png differ
diff --git a/app/assets/images/emoji/card_index.png b/app/assets/images/emoji/card_index.png
new file mode 100755
index 0000000000000000000000000000000000000000..374e94e9e8466c0891b05f22af3929a016960034
Binary files /dev/null and b/app/assets/images/emoji/card_index.png differ
diff --git a/app/assets/images/emoji/carousel_horse.png b/app/assets/images/emoji/carousel_horse.png
new file mode 100755
index 0000000000000000000000000000000000000000..765d2c0a8bd2d11c61e9ba4f71e71d3aa42c744e
Binary files /dev/null and b/app/assets/images/emoji/carousel_horse.png differ
diff --git a/app/assets/images/emoji/cat.png b/app/assets/images/emoji/cat.png
new file mode 100755
index 0000000000000000000000000000000000000000..09b9ef79a7d1aad4e9dd8fa8163b3ef5e9567b11
Binary files /dev/null and b/app/assets/images/emoji/cat.png differ
diff --git a/app/assets/images/emoji/cat2.png b/app/assets/images/emoji/cat2.png
new file mode 100755
index 0000000000000000000000000000000000000000..977c992c526b0516e9e721fc1245701e3bcd9c05
Binary files /dev/null and b/app/assets/images/emoji/cat2.png differ
diff --git a/app/assets/images/emoji/cd.png b/app/assets/images/emoji/cd.png
new file mode 100755
index 0000000000000000000000000000000000000000..baff835c489475511ac4e189a8d25ec52687735a
Binary files /dev/null and b/app/assets/images/emoji/cd.png differ
diff --git a/app/assets/images/emoji/chart.png b/app/assets/images/emoji/chart.png
new file mode 100755
index 0000000000000000000000000000000000000000..ac2c4bb093e395db35ce002e96aebf82ea362a0b
Binary files /dev/null and b/app/assets/images/emoji/chart.png differ
diff --git a/app/assets/images/emoji/chart_with_downwards_trend.png b/app/assets/images/emoji/chart_with_downwards_trend.png
new file mode 100755
index 0000000000000000000000000000000000000000..65b82f04413831335404787f55d68ca342b67543
Binary files /dev/null and b/app/assets/images/emoji/chart_with_downwards_trend.png differ
diff --git a/app/assets/images/emoji/chart_with_upwards_trend.png b/app/assets/images/emoji/chart_with_upwards_trend.png
new file mode 100755
index 0000000000000000000000000000000000000000..de3e9ba7b576a9867391421c378f8882c8e01f37
Binary files /dev/null and b/app/assets/images/emoji/chart_with_upwards_trend.png differ
diff --git a/app/assets/images/emoji/checkered_flag.png b/app/assets/images/emoji/checkered_flag.png
new file mode 100755
index 0000000000000000000000000000000000000000..ead4a68dd37d2d8d817e8452f2430e85b9ab6211
Binary files /dev/null and b/app/assets/images/emoji/checkered_flag.png differ
diff --git a/app/assets/images/emoji/cherries.png b/app/assets/images/emoji/cherries.png
new file mode 100755
index 0000000000000000000000000000000000000000..8d3e044f2f57a83f1d1a86c6607bd5eb871b7a29
Binary files /dev/null and b/app/assets/images/emoji/cherries.png differ
diff --git a/app/assets/images/emoji/cherry_blossom.png b/app/assets/images/emoji/cherry_blossom.png
new file mode 100755
index 0000000000000000000000000000000000000000..e03155499902f52b0d728ba83559c07f554d9dc9
Binary files /dev/null and b/app/assets/images/emoji/cherry_blossom.png differ
diff --git a/app/assets/images/emoji/chestnut.png b/app/assets/images/emoji/chestnut.png
new file mode 100755
index 0000000000000000000000000000000000000000..066fb6bf6df4880c20715dc3809f1c367ff9a4d3
Binary files /dev/null and b/app/assets/images/emoji/chestnut.png differ
diff --git a/app/assets/images/emoji/chicken.png b/app/assets/images/emoji/chicken.png
new file mode 100755
index 0000000000000000000000000000000000000000..6d25c0ef4ad549d92e1e5da3bdf14c19cde2d268
Binary files /dev/null and b/app/assets/images/emoji/chicken.png differ
diff --git a/app/assets/images/emoji/children_crossing.png b/app/assets/images/emoji/children_crossing.png
new file mode 100755
index 0000000000000000000000000000000000000000..b0302ae625866bf2cb5f9b9e3637e9d6b6a05cba
Binary files /dev/null and b/app/assets/images/emoji/children_crossing.png differ
diff --git a/app/assets/images/emoji/chocolate_bar.png b/app/assets/images/emoji/chocolate_bar.png
new file mode 100755
index 0000000000000000000000000000000000000000..c7ec19d07965810f020c25ed0ecf2160dc3c0360
Binary files /dev/null and b/app/assets/images/emoji/chocolate_bar.png differ
diff --git a/app/assets/images/emoji/christmas_tree.png b/app/assets/images/emoji/christmas_tree.png
new file mode 100755
index 0000000000000000000000000000000000000000..d813b9593dc12881db3146fcbace5ee62538ce82
Binary files /dev/null and b/app/assets/images/emoji/christmas_tree.png differ
diff --git a/app/assets/images/emoji/church.png b/app/assets/images/emoji/church.png
new file mode 100755
index 0000000000000000000000000000000000000000..4c07c6b9ea5beb5b036c498ef4516bc4de7dacbc
Binary files /dev/null and b/app/assets/images/emoji/church.png differ
diff --git a/app/assets/images/emoji/cinema.png b/app/assets/images/emoji/cinema.png
new file mode 100755
index 0000000000000000000000000000000000000000..a990ccf99c25023f9850ca214a7ab7f081e93985
Binary files /dev/null and b/app/assets/images/emoji/cinema.png differ
diff --git a/app/assets/images/emoji/circus_tent.png b/app/assets/images/emoji/circus_tent.png
new file mode 100755
index 0000000000000000000000000000000000000000..4af8719aa0313843fa3393e5f224d980efa9fb99
Binary files /dev/null and b/app/assets/images/emoji/circus_tent.png differ
diff --git a/app/assets/images/emoji/city_sunrise.png b/app/assets/images/emoji/city_sunrise.png
new file mode 100755
index 0000000000000000000000000000000000000000..91ca2a40b69fa81434a2f48447eb193bec5a1637
Binary files /dev/null and b/app/assets/images/emoji/city_sunrise.png differ
diff --git a/app/assets/images/emoji/city_sunset.png b/app/assets/images/emoji/city_sunset.png
new file mode 100755
index 0000000000000000000000000000000000000000..7cb178a2cc6686f8282cf53ab972e86fb1d5440a
Binary files /dev/null and b/app/assets/images/emoji/city_sunset.png differ
diff --git a/app/assets/images/emoji/cl.png b/app/assets/images/emoji/cl.png
new file mode 100755
index 0000000000000000000000000000000000000000..15ac67525aad1469e911760a403654cde6c5f840
Binary files /dev/null and b/app/assets/images/emoji/cl.png differ
diff --git a/app/assets/images/emoji/clap.png b/app/assets/images/emoji/clap.png
new file mode 100755
index 0000000000000000000000000000000000000000..d01c982a75acf2968d07cbaccd4d601e9660eadb
Binary files /dev/null and b/app/assets/images/emoji/clap.png differ
diff --git a/app/assets/images/emoji/clapper.png b/app/assets/images/emoji/clapper.png
new file mode 100755
index 0000000000000000000000000000000000000000..4e1dc111d76018cfd2c1986f039d930bf3a7818a
Binary files /dev/null and b/app/assets/images/emoji/clapper.png differ
diff --git a/app/assets/images/emoji/clipboard.png b/app/assets/images/emoji/clipboard.png
new file mode 100755
index 0000000000000000000000000000000000000000..e2c74e6df82322b4b0aa361c48d390a29635a234
Binary files /dev/null and b/app/assets/images/emoji/clipboard.png differ
diff --git a/app/assets/images/emoji/clock1.png b/app/assets/images/emoji/clock1.png
new file mode 100755
index 0000000000000000000000000000000000000000..9174d4e0bc027c423e65853819207b256b63a334
Binary files /dev/null and b/app/assets/images/emoji/clock1.png differ
diff --git a/app/assets/images/emoji/clock10.png b/app/assets/images/emoji/clock10.png
new file mode 100755
index 0000000000000000000000000000000000000000..39f590d69458d276f2132d95c23fd7b231636d6e
Binary files /dev/null and b/app/assets/images/emoji/clock10.png differ
diff --git a/app/assets/images/emoji/clock1030.png b/app/assets/images/emoji/clock1030.png
new file mode 100755
index 0000000000000000000000000000000000000000..84a3bc8fbd02c3b5232d350f240766e7b8fa2896
Binary files /dev/null and b/app/assets/images/emoji/clock1030.png differ
diff --git a/app/assets/images/emoji/clock11.png b/app/assets/images/emoji/clock11.png
new file mode 100755
index 0000000000000000000000000000000000000000..ddb53fadad64f8a8b578331b843686028593fb80
Binary files /dev/null and b/app/assets/images/emoji/clock11.png differ
diff --git a/app/assets/images/emoji/clock1130.png b/app/assets/images/emoji/clock1130.png
new file mode 100755
index 0000000000000000000000000000000000000000..415999ec838cd611aa6d68a71f53684a3ffba11c
Binary files /dev/null and b/app/assets/images/emoji/clock1130.png differ
diff --git a/app/assets/images/emoji/clock12.png b/app/assets/images/emoji/clock12.png
new file mode 100755
index 0000000000000000000000000000000000000000..87b132878b701dfe1bc24596fce80766f8dbda9a
Binary files /dev/null and b/app/assets/images/emoji/clock12.png differ
diff --git a/app/assets/images/emoji/clock1230.png b/app/assets/images/emoji/clock1230.png
new file mode 100755
index 0000000000000000000000000000000000000000..a6527154d1f40f0f4dadbbf0b568e8ba3bb49cd9
Binary files /dev/null and b/app/assets/images/emoji/clock1230.png differ
diff --git a/app/assets/images/emoji/clock130.png b/app/assets/images/emoji/clock130.png
new file mode 100755
index 0000000000000000000000000000000000000000..df939201900046dad0404d17487d32d067707c3f
Binary files /dev/null and b/app/assets/images/emoji/clock130.png differ
diff --git a/app/assets/images/emoji/clock2.png b/app/assets/images/emoji/clock2.png
new file mode 100755
index 0000000000000000000000000000000000000000..65b3b3af0e1a2833dde63772070f1f26438374c2
Binary files /dev/null and b/app/assets/images/emoji/clock2.png differ
diff --git a/app/assets/images/emoji/clock230.png b/app/assets/images/emoji/clock230.png
new file mode 100755
index 0000000000000000000000000000000000000000..f12c6912af7f530416329acf7e3022ff31ecf4ce
Binary files /dev/null and b/app/assets/images/emoji/clock230.png differ
diff --git a/app/assets/images/emoji/clock3.png b/app/assets/images/emoji/clock3.png
new file mode 100755
index 0000000000000000000000000000000000000000..3e44d64e2fb5698c8d8459643d77c517d807372d
Binary files /dev/null and b/app/assets/images/emoji/clock3.png differ
diff --git a/app/assets/images/emoji/clock330.png b/app/assets/images/emoji/clock330.png
new file mode 100755
index 0000000000000000000000000000000000000000..1dc9628ea2426bf2ac5cda1607e51ea571053ead
Binary files /dev/null and b/app/assets/images/emoji/clock330.png differ
diff --git a/app/assets/images/emoji/clock4.png b/app/assets/images/emoji/clock4.png
new file mode 100755
index 0000000000000000000000000000000000000000..948ed1a380cc8523f6cdbd6ae16d5b58f9198c9a
Binary files /dev/null and b/app/assets/images/emoji/clock4.png differ
diff --git a/app/assets/images/emoji/clock430.png b/app/assets/images/emoji/clock430.png
new file mode 100755
index 0000000000000000000000000000000000000000..7726aaea1bc7bd44cf7b6c9c029a2026e6d7e12c
Binary files /dev/null and b/app/assets/images/emoji/clock430.png differ
diff --git a/app/assets/images/emoji/clock5.png b/app/assets/images/emoji/clock5.png
new file mode 100755
index 0000000000000000000000000000000000000000..b010b4f8aaf6fd55b0cd1099812bf35897f76cae
Binary files /dev/null and b/app/assets/images/emoji/clock5.png differ
diff --git a/app/assets/images/emoji/clock530.png b/app/assets/images/emoji/clock530.png
new file mode 100755
index 0000000000000000000000000000000000000000..e08d4ad2bac10aa88703e8c08424dbf012975f40
Binary files /dev/null and b/app/assets/images/emoji/clock530.png differ
diff --git a/app/assets/images/emoji/clock6.png b/app/assets/images/emoji/clock6.png
new file mode 100755
index 0000000000000000000000000000000000000000..76bf8cf1854be600717d388ce7307b3f5180ae0a
Binary files /dev/null and b/app/assets/images/emoji/clock6.png differ
diff --git a/app/assets/images/emoji/clock630.png b/app/assets/images/emoji/clock630.png
new file mode 100755
index 0000000000000000000000000000000000000000..46f0681f1c48f269e97898bb57f1fb7e8c64cdd9
Binary files /dev/null and b/app/assets/images/emoji/clock630.png differ
diff --git a/app/assets/images/emoji/clock7.png b/app/assets/images/emoji/clock7.png
new file mode 100755
index 0000000000000000000000000000000000000000..d48f645d8350f54f0e83dc24184599c363df32b6
Binary files /dev/null and b/app/assets/images/emoji/clock7.png differ
diff --git a/app/assets/images/emoji/clock730.png b/app/assets/images/emoji/clock730.png
new file mode 100755
index 0000000000000000000000000000000000000000..18aab22fd8ca24e0ef9e7743aad298c90f930ac9
Binary files /dev/null and b/app/assets/images/emoji/clock730.png differ
diff --git a/app/assets/images/emoji/clock8.png b/app/assets/images/emoji/clock8.png
new file mode 100755
index 0000000000000000000000000000000000000000..74c770d891c5434631f6c00f289636ad8d501fae
Binary files /dev/null and b/app/assets/images/emoji/clock8.png differ
diff --git a/app/assets/images/emoji/clock830.png b/app/assets/images/emoji/clock830.png
new file mode 100755
index 0000000000000000000000000000000000000000..ec3e382dd4c421a1ff56dd65aff742ce04539501
Binary files /dev/null and b/app/assets/images/emoji/clock830.png differ
diff --git a/app/assets/images/emoji/clock9.png b/app/assets/images/emoji/clock9.png
new file mode 100755
index 0000000000000000000000000000000000000000..f009d14ac114dba4a03ea41dc6b0b9539a7620ac
Binary files /dev/null and b/app/assets/images/emoji/clock9.png differ
diff --git a/app/assets/images/emoji/clock930.png b/app/assets/images/emoji/clock930.png
new file mode 100755
index 0000000000000000000000000000000000000000..fd35221428f989a438afbf433275d118ae79cc16
Binary files /dev/null and b/app/assets/images/emoji/clock930.png differ
diff --git a/app/assets/images/emoji/closed_book.png b/app/assets/images/emoji/closed_book.png
new file mode 100755
index 0000000000000000000000000000000000000000..484029c5ebcfa44e922172b5d908631fc469cde4
Binary files /dev/null and b/app/assets/images/emoji/closed_book.png differ
diff --git a/app/assets/images/emoji/closed_lock_with_key.png b/app/assets/images/emoji/closed_lock_with_key.png
new file mode 100755
index 0000000000000000000000000000000000000000..e6fdf6cb2040e18f7faf326d6211c23753485422
Binary files /dev/null and b/app/assets/images/emoji/closed_lock_with_key.png differ
diff --git a/app/assets/images/emoji/closed_umbrella.png b/app/assets/images/emoji/closed_umbrella.png
new file mode 100755
index 0000000000000000000000000000000000000000..0b719f086b152fd4d7f619038bf47ec404cc66ac
Binary files /dev/null and b/app/assets/images/emoji/closed_umbrella.png differ
diff --git a/app/assets/images/emoji/cloud.png b/app/assets/images/emoji/cloud.png
new file mode 100755
index 0000000000000000000000000000000000000000..b31c08c0b883444326948789ca5bd9ddb2fcbe97
Binary files /dev/null and b/app/assets/images/emoji/cloud.png differ
diff --git a/app/assets/images/emoji/clubs.png b/app/assets/images/emoji/clubs.png
new file mode 100755
index 0000000000000000000000000000000000000000..bfab5365695d72bd44f75802700818e8a76b4c4a
Binary files /dev/null and b/app/assets/images/emoji/clubs.png differ
diff --git a/app/assets/images/emoji/cn.png b/app/assets/images/emoji/cn.png
new file mode 100755
index 0000000000000000000000000000000000000000..b30dcc53df9fc194f69e1e058b079ce69e08ccdc
Binary files /dev/null and b/app/assets/images/emoji/cn.png differ
diff --git a/app/assets/images/emoji/cocktail.png b/app/assets/images/emoji/cocktail.png
new file mode 100755
index 0000000000000000000000000000000000000000..28b45ea51455841835cae67032bfbfa687739190
Binary files /dev/null and b/app/assets/images/emoji/cocktail.png differ
diff --git a/app/assets/images/emoji/coffee.png b/app/assets/images/emoji/coffee.png
new file mode 100755
index 0000000000000000000000000000000000000000..57e1adcb04ac2d22d05664a54aebb718b83801a9
Binary files /dev/null and b/app/assets/images/emoji/coffee.png differ
diff --git a/app/assets/images/emoji/cold_sweat.png b/app/assets/images/emoji/cold_sweat.png
new file mode 100755
index 0000000000000000000000000000000000000000..b9e39bc60fb0324d4bba4551ba2be497344dc2b5
Binary files /dev/null and b/app/assets/images/emoji/cold_sweat.png differ
diff --git a/app/assets/images/emoji/collision.png b/app/assets/images/emoji/collision.png
new file mode 100755
index 0000000000000000000000000000000000000000..bddeb8f49f8f6a1f43de8fb5b9e1a9189e84d13c
Binary files /dev/null and b/app/assets/images/emoji/collision.png differ
diff --git a/app/assets/images/emoji/computer.png b/app/assets/images/emoji/computer.png
new file mode 100755
index 0000000000000000000000000000000000000000..d4d2687627e06cfbf8aaf405ccd239d397053106
Binary files /dev/null and b/app/assets/images/emoji/computer.png differ
diff --git a/app/assets/images/emoji/confetti_ball.png b/app/assets/images/emoji/confetti_ball.png
new file mode 100755
index 0000000000000000000000000000000000000000..bd293e3d8746d7e7536f04c85cf4c29a93921c1c
Binary files /dev/null and b/app/assets/images/emoji/confetti_ball.png differ
diff --git a/app/assets/images/emoji/confounded.png b/app/assets/images/emoji/confounded.png
new file mode 100755
index 0000000000000000000000000000000000000000..762c3766abc2276eed29f9a3727b5ba9813f36c4
Binary files /dev/null and b/app/assets/images/emoji/confounded.png differ
diff --git a/app/assets/images/emoji/congratulations.png b/app/assets/images/emoji/congratulations.png
new file mode 100755
index 0000000000000000000000000000000000000000..dcbb1d229ed4f80e4a60d9228e81f3f3a5c7b647
Binary files /dev/null and b/app/assets/images/emoji/congratulations.png differ
diff --git a/app/assets/images/emoji/construction.png b/app/assets/images/emoji/construction.png
new file mode 100755
index 0000000000000000000000000000000000000000..523e9f10bf6cfdb64715cea6e6044e0affde5ed2
Binary files /dev/null and b/app/assets/images/emoji/construction.png differ
diff --git a/app/assets/images/emoji/construction_worker.png b/app/assets/images/emoji/construction_worker.png
new file mode 100755
index 0000000000000000000000000000000000000000..4d6486047864e90e06df51f298ba06094ed6e0c6
Binary files /dev/null and b/app/assets/images/emoji/construction_worker.png differ
diff --git a/app/assets/images/emoji/convenience_store.png b/app/assets/images/emoji/convenience_store.png
new file mode 100755
index 0000000000000000000000000000000000000000..671696c2dfdbd8970c72696f49a35bbc178ee3a9
Binary files /dev/null and b/app/assets/images/emoji/convenience_store.png differ
diff --git a/app/assets/images/emoji/cookie.png b/app/assets/images/emoji/cookie.png
new file mode 100755
index 0000000000000000000000000000000000000000..653edb258c62caa52e7f05b199b0974099e14eec
Binary files /dev/null and b/app/assets/images/emoji/cookie.png differ
diff --git a/app/assets/images/emoji/cool.png b/app/assets/images/emoji/cool.png
new file mode 100755
index 0000000000000000000000000000000000000000..937dcd792105b847e41b6f8a1146d73d31ea3236
Binary files /dev/null and b/app/assets/images/emoji/cool.png differ
diff --git a/app/assets/images/emoji/cop.png b/app/assets/images/emoji/cop.png
new file mode 100755
index 0000000000000000000000000000000000000000..43a5a84f821473f9a2b3eb5700e2a503a080d339
Binary files /dev/null and b/app/assets/images/emoji/cop.png differ
diff --git a/app/assets/images/emoji/copyright.png b/app/assets/images/emoji/copyright.png
new file mode 100755
index 0000000000000000000000000000000000000000..38493c33fcaf95787fffd6d6f1630c93513f5a71
Binary files /dev/null and b/app/assets/images/emoji/copyright.png differ
diff --git a/app/assets/images/emoji/corn.png b/app/assets/images/emoji/corn.png
new file mode 100755
index 0000000000000000000000000000000000000000..fe5d8b1287e27fc852b48262327547aa0a951d74
Binary files /dev/null and b/app/assets/images/emoji/corn.png differ
diff --git a/app/assets/images/emoji/couple.png b/app/assets/images/emoji/couple.png
new file mode 100755
index 0000000000000000000000000000000000000000..9e51f40e16ecfaa96b25c2fa4854d6e9935fb1b8
Binary files /dev/null and b/app/assets/images/emoji/couple.png differ
diff --git a/app/assets/images/emoji/couple_with_heart.png b/app/assets/images/emoji/couple_with_heart.png
new file mode 100755
index 0000000000000000000000000000000000000000..c503f40a931aa79cad2f9f5f72d768fe2ed53561
Binary files /dev/null and b/app/assets/images/emoji/couple_with_heart.png differ
diff --git a/app/assets/images/emoji/couplekiss.png b/app/assets/images/emoji/couplekiss.png
new file mode 100755
index 0000000000000000000000000000000000000000..d02790822ea0c8ac8903eb525364778e95debbb4
Binary files /dev/null and b/app/assets/images/emoji/couplekiss.png differ
diff --git a/app/assets/images/emoji/cow.png b/app/assets/images/emoji/cow.png
new file mode 100755
index 0000000000000000000000000000000000000000..12e1ab6c0bd8d6923b028e2a5336ac388b977d60
Binary files /dev/null and b/app/assets/images/emoji/cow.png differ
diff --git a/app/assets/images/emoji/cow2.png b/app/assets/images/emoji/cow2.png
new file mode 100755
index 0000000000000000000000000000000000000000..594c92155bc52116674fb8dbd94738fd2e0a32b1
Binary files /dev/null and b/app/assets/images/emoji/cow2.png differ
diff --git a/app/assets/images/emoji/credit_card.png b/app/assets/images/emoji/credit_card.png
new file mode 100755
index 0000000000000000000000000000000000000000..be1c1dd3063120ab9b0844346731b7e2cdf88671
Binary files /dev/null and b/app/assets/images/emoji/credit_card.png differ
diff --git a/app/assets/images/emoji/crocodile.png b/app/assets/images/emoji/crocodile.png
new file mode 100755
index 0000000000000000000000000000000000000000..7435d5ab3c485879624a025d8b46185e5b28dbb3
Binary files /dev/null and b/app/assets/images/emoji/crocodile.png differ
diff --git a/app/assets/images/emoji/crossed_flags.png b/app/assets/images/emoji/crossed_flags.png
new file mode 100755
index 0000000000000000000000000000000000000000..2397bcd0fc9892531b3c714cd34d65a58dfa3d89
Binary files /dev/null and b/app/assets/images/emoji/crossed_flags.png differ
diff --git a/app/assets/images/emoji/crown.png b/app/assets/images/emoji/crown.png
new file mode 100755
index 0000000000000000000000000000000000000000..39da1d52873ed8694b5285f2baf5b413bdc067c5
Binary files /dev/null and b/app/assets/images/emoji/crown.png differ
diff --git a/app/assets/images/emoji/cry.png b/app/assets/images/emoji/cry.png
new file mode 100755
index 0000000000000000000000000000000000000000..6d0d9afd284b9a22107defc3979c9384c192af74
Binary files /dev/null and b/app/assets/images/emoji/cry.png differ
diff --git a/app/assets/images/emoji/crying_cat_face.png b/app/assets/images/emoji/crying_cat_face.png
new file mode 100755
index 0000000000000000000000000000000000000000..42d4c27cabfaafc0c17b92483050aeaeeecbed25
Binary files /dev/null and b/app/assets/images/emoji/crying_cat_face.png differ
diff --git a/app/assets/images/emoji/crystal_ball.png b/app/assets/images/emoji/crystal_ball.png
new file mode 100755
index 0000000000000000000000000000000000000000..6d2c6c42d448ff1e77ef23906f4048649ccbbf1d
Binary files /dev/null and b/app/assets/images/emoji/crystal_ball.png differ
diff --git a/app/assets/images/emoji/cupid.png b/app/assets/images/emoji/cupid.png
new file mode 100755
index 0000000000000000000000000000000000000000..4987284767c6d850e249f1af95d80a11b73e736b
Binary files /dev/null and b/app/assets/images/emoji/cupid.png differ
diff --git a/app/assets/images/emoji/curly_loop.png b/app/assets/images/emoji/curly_loop.png
new file mode 100755
index 0000000000000000000000000000000000000000..8f051aca43e5c12bc059db4bd7d156b825f14e68
Binary files /dev/null and b/app/assets/images/emoji/curly_loop.png differ
diff --git a/app/assets/images/emoji/currency_exchange.png b/app/assets/images/emoji/currency_exchange.png
new file mode 100755
index 0000000000000000000000000000000000000000..6ebebe70afb01c3f179258d04eb9a8a22ff5b543
Binary files /dev/null and b/app/assets/images/emoji/currency_exchange.png differ
diff --git a/app/assets/images/emoji/curry.png b/app/assets/images/emoji/curry.png
new file mode 100755
index 0000000000000000000000000000000000000000..7983c706a40ebd81c1d6431c52dc7fdbd75d6ba1
Binary files /dev/null and b/app/assets/images/emoji/curry.png differ
diff --git a/app/assets/images/emoji/custard.png b/app/assets/images/emoji/custard.png
new file mode 100755
index 0000000000000000000000000000000000000000..9f843b4c13016805cb3f8a64cc02b83706528dec
Binary files /dev/null and b/app/assets/images/emoji/custard.png differ
diff --git a/app/assets/images/emoji/customs.png b/app/assets/images/emoji/customs.png
new file mode 100755
index 0000000000000000000000000000000000000000..92691e3117c69c9a4acf0ac264770f4b9528d46e
Binary files /dev/null and b/app/assets/images/emoji/customs.png differ
diff --git a/app/assets/images/emoji/cyclone.png b/app/assets/images/emoji/cyclone.png
new file mode 100755
index 0000000000000000000000000000000000000000..5fd2e4512f9165e5a9f5fcc5e84e057560fe91b7
Binary files /dev/null and b/app/assets/images/emoji/cyclone.png differ
diff --git a/app/assets/images/emoji/dancer.png b/app/assets/images/emoji/dancer.png
new file mode 100755
index 0000000000000000000000000000000000000000..6885a0bc3d5f23fa4be974ab6ca0356b8d35812e
Binary files /dev/null and b/app/assets/images/emoji/dancer.png differ
diff --git a/app/assets/images/emoji/dancers.png b/app/assets/images/emoji/dancers.png
new file mode 100755
index 0000000000000000000000000000000000000000..2dfb451a73a1566fb1d916861002b3c6dfe4572a
Binary files /dev/null and b/app/assets/images/emoji/dancers.png differ
diff --git a/app/assets/images/emoji/dango.png b/app/assets/images/emoji/dango.png
new file mode 100755
index 0000000000000000000000000000000000000000..2d042aebeb589162683b4eb8976acc2e4a3c21e7
Binary files /dev/null and b/app/assets/images/emoji/dango.png differ
diff --git a/app/assets/images/emoji/dart.png b/app/assets/images/emoji/dart.png
new file mode 100755
index 0000000000000000000000000000000000000000..0438fe54f9993a2e374cfcbf31b24a9c44111d89
Binary files /dev/null and b/app/assets/images/emoji/dart.png differ
diff --git a/app/assets/images/emoji/dash.png b/app/assets/images/emoji/dash.png
new file mode 100755
index 0000000000000000000000000000000000000000..dc2c0a8f4684186167596b0cbd7ca1fda70744a3
Binary files /dev/null and b/app/assets/images/emoji/dash.png differ
diff --git a/app/assets/images/emoji/date.png b/app/assets/images/emoji/date.png
new file mode 100755
index 0000000000000000000000000000000000000000..6ad2efa5fdcc5fb377fef6d565a0e72cef0990ca
Binary files /dev/null and b/app/assets/images/emoji/date.png differ
diff --git a/app/assets/images/emoji/de.png b/app/assets/images/emoji/de.png
new file mode 100755
index 0000000000000000000000000000000000000000..16a28548c9e5b2007a7d5443b58696c9bdf93509
Binary files /dev/null and b/app/assets/images/emoji/de.png differ
diff --git a/app/assets/images/emoji/deciduous_tree.png b/app/assets/images/emoji/deciduous_tree.png
new file mode 100755
index 0000000000000000000000000000000000000000..9bb16bdfecbc9f235fd9aa6a3bc3cb909dc7c4d1
Binary files /dev/null and b/app/assets/images/emoji/deciduous_tree.png differ
diff --git a/app/assets/images/emoji/department_store.png b/app/assets/images/emoji/department_store.png
new file mode 100755
index 0000000000000000000000000000000000000000..68d959c507de127674ab7f3176ce0adc2389306a
Binary files /dev/null and b/app/assets/images/emoji/department_store.png differ
diff --git a/app/assets/images/emoji/diamond_shape_with_a_dot_inside.png b/app/assets/images/emoji/diamond_shape_with_a_dot_inside.png
new file mode 100755
index 0000000000000000000000000000000000000000..dfd1098b3940104aaae590dfeb533fb22b230c9c
Binary files /dev/null and b/app/assets/images/emoji/diamond_shape_with_a_dot_inside.png differ
diff --git a/app/assets/images/emoji/diamonds.png b/app/assets/images/emoji/diamonds.png
new file mode 100755
index 0000000000000000000000000000000000000000..fe0827758b1b72c6668f208721a4e6c183305967
Binary files /dev/null and b/app/assets/images/emoji/diamonds.png differ
diff --git a/app/assets/images/emoji/disappointed.png b/app/assets/images/emoji/disappointed.png
new file mode 100755
index 0000000000000000000000000000000000000000..82552008719d2841dbab81f34008db4ef830e6a1
Binary files /dev/null and b/app/assets/images/emoji/disappointed.png differ
diff --git a/app/assets/images/emoji/dizzy.png b/app/assets/images/emoji/dizzy.png
new file mode 100755
index 0000000000000000000000000000000000000000..55213d2ddeea61ec219d71f3dd74e3b5c008ad3c
Binary files /dev/null and b/app/assets/images/emoji/dizzy.png differ
diff --git a/app/assets/images/emoji/dizzy_face.png b/app/assets/images/emoji/dizzy_face.png
new file mode 100755
index 0000000000000000000000000000000000000000..8001d6ff8f0b8380298d77a6238188f516e5a188
Binary files /dev/null and b/app/assets/images/emoji/dizzy_face.png differ
diff --git a/app/assets/images/emoji/do_not_litter.png b/app/assets/images/emoji/do_not_litter.png
new file mode 100755
index 0000000000000000000000000000000000000000..38c7ae7af239c5ba902718a37c1d9afeb2c0169c
Binary files /dev/null and b/app/assets/images/emoji/do_not_litter.png differ
diff --git a/app/assets/images/emoji/dog.png b/app/assets/images/emoji/dog.png
new file mode 100755
index 0000000000000000000000000000000000000000..389a02bf282628757e93ae97fe811379f0be592e
Binary files /dev/null and b/app/assets/images/emoji/dog.png differ
diff --git a/app/assets/images/emoji/dog2.png b/app/assets/images/emoji/dog2.png
new file mode 100755
index 0000000000000000000000000000000000000000..c7f6a24ac80bce9a79f66f4baf3c9de0a3a496aa
Binary files /dev/null and b/app/assets/images/emoji/dog2.png differ
diff --git a/app/assets/images/emoji/dollar.png b/app/assets/images/emoji/dollar.png
new file mode 100755
index 0000000000000000000000000000000000000000..63de884951966d1e0b09c3ce71542d1d59cf43d7
Binary files /dev/null and b/app/assets/images/emoji/dollar.png differ
diff --git a/app/assets/images/emoji/dolls.png b/app/assets/images/emoji/dolls.png
new file mode 100755
index 0000000000000000000000000000000000000000..47ce33900ca53b7372c0b6028aed797f8fa8f0b7
Binary files /dev/null and b/app/assets/images/emoji/dolls.png differ
diff --git a/app/assets/images/emoji/dolphin.png b/app/assets/images/emoji/dolphin.png
new file mode 100755
index 0000000000000000000000000000000000000000..9326077a927c4901c4c2f6f058f34d6366ce9627
Binary files /dev/null and b/app/assets/images/emoji/dolphin.png differ
diff --git a/app/assets/images/emoji/door.png b/app/assets/images/emoji/door.png
new file mode 100755
index 0000000000000000000000000000000000000000..83c819ae4669c093912601820f7f147bd37fc7e7
Binary files /dev/null and b/app/assets/images/emoji/door.png differ
diff --git a/app/assets/images/emoji/doughnut.png b/app/assets/images/emoji/doughnut.png
new file mode 100755
index 0000000000000000000000000000000000000000..ccf869129602e60a8b20e5d90d0258b8fda14591
Binary files /dev/null and b/app/assets/images/emoji/doughnut.png differ
diff --git a/app/assets/images/emoji/dragon.png b/app/assets/images/emoji/dragon.png
new file mode 100755
index 0000000000000000000000000000000000000000..e399d60e1d859dc26b3ef2a4f75e9ed7414c9bd9
Binary files /dev/null and b/app/assets/images/emoji/dragon.png differ
diff --git a/app/assets/images/emoji/dragon_face.png b/app/assets/images/emoji/dragon_face.png
new file mode 100755
index 0000000000000000000000000000000000000000..e5e556bd105c9a40a33b1b92fb226e68420a3d76
Binary files /dev/null and b/app/assets/images/emoji/dragon_face.png differ
diff --git a/app/assets/images/emoji/dress.png b/app/assets/images/emoji/dress.png
new file mode 100755
index 0000000000000000000000000000000000000000..6434e2e2f3982266931f943f41e2640eb0ca7c91
Binary files /dev/null and b/app/assets/images/emoji/dress.png differ
diff --git a/app/assets/images/emoji/dromedary_camel.png b/app/assets/images/emoji/dromedary_camel.png
new file mode 100755
index 0000000000000000000000000000000000000000..c8c7b9ffa0fa6d78ce7f1e53ff9a6a20cd0bd217
Binary files /dev/null and b/app/assets/images/emoji/dromedary_camel.png differ
diff --git a/app/assets/images/emoji/droplet.png b/app/assets/images/emoji/droplet.png
new file mode 100755
index 0000000000000000000000000000000000000000..9eff46339f81cc3b5aba26bc76cc114e0b76fcdf
Binary files /dev/null and b/app/assets/images/emoji/droplet.png differ
diff --git a/app/assets/images/emoji/dvd.png b/app/assets/images/emoji/dvd.png
new file mode 100755
index 0000000000000000000000000000000000000000..363c83d01c527179f47c224de01b2d29f750290a
Binary files /dev/null and b/app/assets/images/emoji/dvd.png differ
diff --git a/app/assets/images/emoji/e-mail.png b/app/assets/images/emoji/e-mail.png
new file mode 100755
index 0000000000000000000000000000000000000000..176a8e1e825a05c3d0b116ca4b29ece5f3250901
Binary files /dev/null and b/app/assets/images/emoji/e-mail.png differ
diff --git a/app/assets/images/emoji/ear.png b/app/assets/images/emoji/ear.png
new file mode 100755
index 0000000000000000000000000000000000000000..2bbbf10c9ef475424d699cbfbd03a33b33b24570
Binary files /dev/null and b/app/assets/images/emoji/ear.png differ
diff --git a/app/assets/images/emoji/ear_of_rice.png b/app/assets/images/emoji/ear_of_rice.png
new file mode 100755
index 0000000000000000000000000000000000000000..a9bba5c2c14682fef7ce33e17a968e2dd4a4ea18
Binary files /dev/null and b/app/assets/images/emoji/ear_of_rice.png differ
diff --git a/app/assets/images/emoji/earth_africa.png b/app/assets/images/emoji/earth_africa.png
new file mode 100755
index 0000000000000000000000000000000000000000..44ce5ecb621c885ae92e8567b1e819b16c4bca1d
Binary files /dev/null and b/app/assets/images/emoji/earth_africa.png differ
diff --git a/app/assets/images/emoji/earth_americas.png b/app/assets/images/emoji/earth_americas.png
new file mode 100755
index 0000000000000000000000000000000000000000..97d717671369fe6519a315de350b53a1445fa4ba
Binary files /dev/null and b/app/assets/images/emoji/earth_americas.png differ
diff --git a/app/assets/images/emoji/earth_asia.png b/app/assets/images/emoji/earth_asia.png
new file mode 100755
index 0000000000000000000000000000000000000000..95ec357ca87f342ca738361cd71be741cc0e350c
Binary files /dev/null and b/app/assets/images/emoji/earth_asia.png differ
diff --git a/app/assets/images/emoji/egg.png b/app/assets/images/emoji/egg.png
new file mode 100755
index 0000000000000000000000000000000000000000..c3de6ae4ea0d11983133e477346e6b93e4eaec00
Binary files /dev/null and b/app/assets/images/emoji/egg.png differ
diff --git a/app/assets/images/emoji/eggplant.png b/app/assets/images/emoji/eggplant.png
new file mode 100755
index 0000000000000000000000000000000000000000..66f25fce447f20aaa4770ecdf722ac416a0c6ca6
Binary files /dev/null and b/app/assets/images/emoji/eggplant.png differ
diff --git a/app/assets/images/emoji/eight.png b/app/assets/images/emoji/eight.png
new file mode 100755
index 0000000000000000000000000000000000000000..7bdb422327c4b93b3de666b37e3f487eddac4930
Binary files /dev/null and b/app/assets/images/emoji/eight.png differ
diff --git a/app/assets/images/emoji/eight_pointed_black_star.png b/app/assets/images/emoji/eight_pointed_black_star.png
new file mode 100755
index 0000000000000000000000000000000000000000..6ddaa21f47bf828b79d60eeeff7acdc99d789e3b
Binary files /dev/null and b/app/assets/images/emoji/eight_pointed_black_star.png differ
diff --git a/app/assets/images/emoji/eight_spoked_asterisk.png b/app/assets/images/emoji/eight_spoked_asterisk.png
new file mode 100755
index 0000000000000000000000000000000000000000..946a20333a2aa283469ed8937f1d2916e4e1a365
Binary files /dev/null and b/app/assets/images/emoji/eight_spoked_asterisk.png differ
diff --git a/app/assets/images/emoji/electric_plug.png b/app/assets/images/emoji/electric_plug.png
new file mode 100755
index 0000000000000000000000000000000000000000..7a3d6cee68365bf33fb4725d5c4c3ef1cfa765d1
Binary files /dev/null and b/app/assets/images/emoji/electric_plug.png differ
diff --git a/app/assets/images/emoji/elephant.png b/app/assets/images/emoji/elephant.png
new file mode 100755
index 0000000000000000000000000000000000000000..5ca04570e2425a77b566a17767864394f7657e93
Binary files /dev/null and b/app/assets/images/emoji/elephant.png differ
diff --git a/app/assets/images/emoji/email.png b/app/assets/images/emoji/email.png
new file mode 100755
index 0000000000000000000000000000000000000000..0e01fd5f0522bc64bd55fead245085e1c35dcf71
Binary files /dev/null and b/app/assets/images/emoji/email.png differ
diff --git a/app/assets/images/emoji/end.png b/app/assets/images/emoji/end.png
new file mode 100755
index 0000000000000000000000000000000000000000..edb0bda2450f079f6c534d5ba60ca5a214a232e3
Binary files /dev/null and b/app/assets/images/emoji/end.png differ
diff --git a/app/assets/images/emoji/envelope.png b/app/assets/images/emoji/envelope.png
new file mode 100755
index 0000000000000000000000000000000000000000..3631861bbfdcd90101dd9a2b3a2299c63e983af9
Binary files /dev/null and b/app/assets/images/emoji/envelope.png differ
diff --git a/app/assets/images/emoji/es.png b/app/assets/images/emoji/es.png
new file mode 100755
index 0000000000000000000000000000000000000000..71b30bff352e05df99c09a3cfb88fd0b9cb072ad
Binary files /dev/null and b/app/assets/images/emoji/es.png differ
diff --git a/app/assets/images/emoji/euro.png b/app/assets/images/emoji/euro.png
new file mode 100755
index 0000000000000000000000000000000000000000..1c5904b7144328c158169abbd1306a827334e4c5
Binary files /dev/null and b/app/assets/images/emoji/euro.png differ
diff --git a/app/assets/images/emoji/european_castle.png b/app/assets/images/emoji/european_castle.png
new file mode 100755
index 0000000000000000000000000000000000000000..8229b8a8a942abe7aa2474f3477c6f0d235dac31
Binary files /dev/null and b/app/assets/images/emoji/european_castle.png differ
diff --git a/app/assets/images/emoji/european_post_office.png b/app/assets/images/emoji/european_post_office.png
new file mode 100755
index 0000000000000000000000000000000000000000..0f65b1453056ac5c346693892dae0766c8617373
Binary files /dev/null and b/app/assets/images/emoji/european_post_office.png differ
diff --git a/app/assets/images/emoji/evergreen_tree.png b/app/assets/images/emoji/evergreen_tree.png
new file mode 100755
index 0000000000000000000000000000000000000000..ae8ad103763821e235450d70b2dacc46377341fb
Binary files /dev/null and b/app/assets/images/emoji/evergreen_tree.png differ
diff --git a/app/assets/images/emoji/exclamation.png b/app/assets/images/emoji/exclamation.png
new file mode 100755
index 0000000000000000000000000000000000000000..77bbdeabcf49dbc4f8b5278bd01f7e14292724b1
Binary files /dev/null and b/app/assets/images/emoji/exclamation.png differ
diff --git a/app/assets/images/emoji/eyeglasses.png b/app/assets/images/emoji/eyeglasses.png
new file mode 100755
index 0000000000000000000000000000000000000000..a3cf75a27a1c67f17e16d98b07a8dc5bfeab89f0
Binary files /dev/null and b/app/assets/images/emoji/eyeglasses.png differ
diff --git a/app/assets/images/emoji/eyes.png b/app/assets/images/emoji/eyes.png
new file mode 100755
index 0000000000000000000000000000000000000000..dc2216f63d638e743a339f0887b03c4b0885d365
Binary files /dev/null and b/app/assets/images/emoji/eyes.png differ
diff --git a/app/assets/images/emoji/facepunch.png b/app/assets/images/emoji/facepunch.png
new file mode 100755
index 0000000000000000000000000000000000000000..2d41fd37e8d42a282ce48d3fb13ead7605725fa1
Binary files /dev/null and b/app/assets/images/emoji/facepunch.png differ
diff --git a/app/assets/images/emoji/factory.png b/app/assets/images/emoji/factory.png
new file mode 100755
index 0000000000000000000000000000000000000000..6404634793e288a6c77d19918f71bf3b3b7e3b22
Binary files /dev/null and b/app/assets/images/emoji/factory.png differ
diff --git a/app/assets/images/emoji/fallen_leaf.png b/app/assets/images/emoji/fallen_leaf.png
new file mode 100755
index 0000000000000000000000000000000000000000..d49f9c1757d3ae2325089fc6e60fbcece999d181
Binary files /dev/null and b/app/assets/images/emoji/fallen_leaf.png differ
diff --git a/app/assets/images/emoji/family.png b/app/assets/images/emoji/family.png
new file mode 100755
index 0000000000000000000000000000000000000000..b4b365f3a5c033af7e6cad6c67b5c5f5135a7340
Binary files /dev/null and b/app/assets/images/emoji/family.png differ
diff --git a/app/assets/images/emoji/fast_forward.png b/app/assets/images/emoji/fast_forward.png
new file mode 100755
index 0000000000000000000000000000000000000000..8830e146e598f29e6b05e00cb08301dccd2ed348
Binary files /dev/null and b/app/assets/images/emoji/fast_forward.png differ
diff --git a/app/assets/images/emoji/fax.png b/app/assets/images/emoji/fax.png
new file mode 100755
index 0000000000000000000000000000000000000000..62be2c958f416e04a4533187fc929a123595a10d
Binary files /dev/null and b/app/assets/images/emoji/fax.png differ
diff --git a/app/assets/images/emoji/fearful.png b/app/assets/images/emoji/fearful.png
new file mode 100755
index 0000000000000000000000000000000000000000..513fce47b685b10757d425ec63bfd8b69258ca08
Binary files /dev/null and b/app/assets/images/emoji/fearful.png differ
diff --git a/app/assets/images/emoji/feelsgood.png b/app/assets/images/emoji/feelsgood.png
new file mode 100755
index 0000000000000000000000000000000000000000..361f969bc1b55695a8a68bca66abe045fd3af8a6
Binary files /dev/null and b/app/assets/images/emoji/feelsgood.png differ
diff --git a/app/assets/images/emoji/feet.png b/app/assets/images/emoji/feet.png
new file mode 100755
index 0000000000000000000000000000000000000000..1b0147b1d234c4043f8a07294c64888461324883
Binary files /dev/null and b/app/assets/images/emoji/feet.png differ
diff --git a/app/assets/images/emoji/ferris_wheel.png b/app/assets/images/emoji/ferris_wheel.png
new file mode 100755
index 0000000000000000000000000000000000000000..54a1dcfa1ef4f97ff8987581c7b0af4d1187c59b
Binary files /dev/null and b/app/assets/images/emoji/ferris_wheel.png differ
diff --git a/app/assets/images/emoji/file_folder.png b/app/assets/images/emoji/file_folder.png
new file mode 100755
index 0000000000000000000000000000000000000000..4d8bebf8a90354c38612398a95b9c23a6109af5e
Binary files /dev/null and b/app/assets/images/emoji/file_folder.png differ
diff --git a/app/assets/images/emoji/finnadie.png b/app/assets/images/emoji/finnadie.png
new file mode 100755
index 0000000000000000000000000000000000000000..bfc5a0d93de6a433bb15d1b994ade85cefe1ce67
Binary files /dev/null and b/app/assets/images/emoji/finnadie.png differ
diff --git a/app/assets/images/emoji/fire.png b/app/assets/images/emoji/fire.png
new file mode 100755
index 0000000000000000000000000000000000000000..f2a3149bbfdaccae39985a6e0f37b1630a49a351
Binary files /dev/null and b/app/assets/images/emoji/fire.png differ
diff --git a/app/assets/images/emoji/fire_engine.png b/app/assets/images/emoji/fire_engine.png
new file mode 100755
index 0000000000000000000000000000000000000000..9e6c59c99763489eb36b9641f515fbed096244b2
Binary files /dev/null and b/app/assets/images/emoji/fire_engine.png differ
diff --git a/app/assets/images/emoji/fireworks.png b/app/assets/images/emoji/fireworks.png
new file mode 100755
index 0000000000000000000000000000000000000000..b4eccd5775b319e38e4a9fb94661aa51cffbcb2c
Binary files /dev/null and b/app/assets/images/emoji/fireworks.png differ
diff --git a/app/assets/images/emoji/first_quarter_moon.png b/app/assets/images/emoji/first_quarter_moon.png
new file mode 100755
index 0000000000000000000000000000000000000000..f38c236937fa9e9dd0346392a72dd01d937a3cbe
Binary files /dev/null and b/app/assets/images/emoji/first_quarter_moon.png differ
diff --git a/app/assets/images/emoji/first_quarter_moon_with_face.png b/app/assets/images/emoji/first_quarter_moon_with_face.png
new file mode 100755
index 0000000000000000000000000000000000000000..85ae2ce72dc273d392eb8b2270c1c5f81b93e7ab
Binary files /dev/null and b/app/assets/images/emoji/first_quarter_moon_with_face.png differ
diff --git a/app/assets/images/emoji/fish.png b/app/assets/images/emoji/fish.png
new file mode 100755
index 0000000000000000000000000000000000000000..90bdda2c9203d6af0c0796434cd5138034a5305b
Binary files /dev/null and b/app/assets/images/emoji/fish.png differ
diff --git a/app/assets/images/emoji/fish_cake.png b/app/assets/images/emoji/fish_cake.png
new file mode 100755
index 0000000000000000000000000000000000000000..a8f22614d62a0398d77e51ae64f1e8e0031f32b8
Binary files /dev/null and b/app/assets/images/emoji/fish_cake.png differ
diff --git a/app/assets/images/emoji/fishing_pole_and_fish.png b/app/assets/images/emoji/fishing_pole_and_fish.png
new file mode 100755
index 0000000000000000000000000000000000000000..d84609c3b7bced2ed86fbb9e88ee08a017c04316
Binary files /dev/null and b/app/assets/images/emoji/fishing_pole_and_fish.png differ
diff --git a/app/assets/images/emoji/fist.png b/app/assets/images/emoji/fist.png
new file mode 100755
index 0000000000000000000000000000000000000000..ecc8874c2fdb9dac387bd6765ac8081034a75c85
Binary files /dev/null and b/app/assets/images/emoji/fist.png differ
diff --git a/app/assets/images/emoji/five.png b/app/assets/images/emoji/five.png
new file mode 100755
index 0000000000000000000000000000000000000000..794321aa22a38dfab90990ee34c608cbd50bb460
Binary files /dev/null and b/app/assets/images/emoji/five.png differ
diff --git a/app/assets/images/emoji/flags.png b/app/assets/images/emoji/flags.png
new file mode 100755
index 0000000000000000000000000000000000000000..540164e84e438ae269178f83a7d2a0cfb080a5c5
Binary files /dev/null and b/app/assets/images/emoji/flags.png differ
diff --git a/app/assets/images/emoji/flashlight.png b/app/assets/images/emoji/flashlight.png
new file mode 100755
index 0000000000000000000000000000000000000000..215940aa8f1bf0b8a0b077d6e93f98c8f60f1ab2
Binary files /dev/null and b/app/assets/images/emoji/flashlight.png differ
diff --git a/app/assets/images/emoji/floppy_disk.png b/app/assets/images/emoji/floppy_disk.png
new file mode 100755
index 0000000000000000000000000000000000000000..4ad56315ae65f7c669bfb8350514d22f58e8f8c0
Binary files /dev/null and b/app/assets/images/emoji/floppy_disk.png differ
diff --git a/app/assets/images/emoji/flower_playing_cards.png b/app/assets/images/emoji/flower_playing_cards.png
new file mode 100755
index 0000000000000000000000000000000000000000..cc46a6a1fa2e54b59f48a5896c1c6eec18ceff10
Binary files /dev/null and b/app/assets/images/emoji/flower_playing_cards.png differ
diff --git a/app/assets/images/emoji/flushed.png b/app/assets/images/emoji/flushed.png
new file mode 100755
index 0000000000000000000000000000000000000000..74b78c9c07a5643bdfaf33b89677e00fefb11b92
Binary files /dev/null and b/app/assets/images/emoji/flushed.png differ
diff --git a/app/assets/images/emoji/foggy.png b/app/assets/images/emoji/foggy.png
new file mode 100755
index 0000000000000000000000000000000000000000..3c7b8b04b9575a750a51567b444fcd09354c240c
Binary files /dev/null and b/app/assets/images/emoji/foggy.png differ
diff --git a/app/assets/images/emoji/football.png b/app/assets/images/emoji/football.png
new file mode 100755
index 0000000000000000000000000000000000000000..0e4e168fa8f93b343b0cc90ec5f5a3b1cec52a49
Binary files /dev/null and b/app/assets/images/emoji/football.png differ
diff --git a/app/assets/images/emoji/fork_and_knife.png b/app/assets/images/emoji/fork_and_knife.png
new file mode 100755
index 0000000000000000000000000000000000000000..8ba4bc6535efd138b2a43e0d6314851c54bca378
Binary files /dev/null and b/app/assets/images/emoji/fork_and_knife.png differ
diff --git a/app/assets/images/emoji/fountain.png b/app/assets/images/emoji/fountain.png
new file mode 100755
index 0000000000000000000000000000000000000000..da126e6486e1f857f43f13c532dd18cd15afeff2
Binary files /dev/null and b/app/assets/images/emoji/fountain.png differ
diff --git a/app/assets/images/emoji/four.png b/app/assets/images/emoji/four.png
new file mode 100755
index 0000000000000000000000000000000000000000..14782ba23b94d4f26e7ea5803d0474a184ba651e
Binary files /dev/null and b/app/assets/images/emoji/four.png differ
diff --git a/app/assets/images/emoji/four_leaf_clover.png b/app/assets/images/emoji/four_leaf_clover.png
new file mode 100755
index 0000000000000000000000000000000000000000..f2014bea44f84460551b0393a7de85cd1fb84a07
Binary files /dev/null and b/app/assets/images/emoji/four_leaf_clover.png differ
diff --git a/app/assets/images/emoji/fr.png b/app/assets/images/emoji/fr.png
new file mode 100755
index 0000000000000000000000000000000000000000..6311c91159e91db4beb5846355e0cb1ff33f4a44
Binary files /dev/null and b/app/assets/images/emoji/fr.png differ
diff --git a/app/assets/images/emoji/free.png b/app/assets/images/emoji/free.png
new file mode 100755
index 0000000000000000000000000000000000000000..c886cf2494c1367bec7134e9179519a52cc4bb1b
Binary files /dev/null and b/app/assets/images/emoji/free.png differ
diff --git a/app/assets/images/emoji/fried_shrimp.png b/app/assets/images/emoji/fried_shrimp.png
new file mode 100755
index 0000000000000000000000000000000000000000..c8c284bf14af14f06f4dbd45e61e035e3b8db52e
Binary files /dev/null and b/app/assets/images/emoji/fried_shrimp.png differ
diff --git a/app/assets/images/emoji/fries.png b/app/assets/images/emoji/fries.png
new file mode 100755
index 0000000000000000000000000000000000000000..cfef66966a729c48ccf081661403d43d802c6105
Binary files /dev/null and b/app/assets/images/emoji/fries.png differ
diff --git a/app/assets/images/emoji/frog.png b/app/assets/images/emoji/frog.png
new file mode 100755
index 0000000000000000000000000000000000000000..cfe11b18ff0e6865a22e204eaf7d435c23f79f32
Binary files /dev/null and b/app/assets/images/emoji/frog.png differ
diff --git a/app/assets/images/emoji/fuelpump.png b/app/assets/images/emoji/fuelpump.png
new file mode 100755
index 0000000000000000000000000000000000000000..54c29aeb1db3ba1c39626e80e7929d07f7e874c6
Binary files /dev/null and b/app/assets/images/emoji/fuelpump.png differ
diff --git a/app/assets/images/emoji/full_moon.png b/app/assets/images/emoji/full_moon.png
new file mode 100755
index 0000000000000000000000000000000000000000..8ff657a25936753687d44e607519b8b53e66b708
Binary files /dev/null and b/app/assets/images/emoji/full_moon.png differ
diff --git a/app/assets/images/emoji/full_moon_with_face.png b/app/assets/images/emoji/full_moon_with_face.png
new file mode 100755
index 0000000000000000000000000000000000000000..94395a4080b3a9d2a9aacef294256d8ff332c557
Binary files /dev/null and b/app/assets/images/emoji/full_moon_with_face.png differ
diff --git a/app/assets/images/emoji/game_die.png b/app/assets/images/emoji/game_die.png
new file mode 100755
index 0000000000000000000000000000000000000000..4136e78ec980c7b84b01085e65a5d69bfa9b8fef
Binary files /dev/null and b/app/assets/images/emoji/game_die.png differ
diff --git a/app/assets/images/emoji/gb.png b/app/assets/images/emoji/gb.png
new file mode 100755
index 0000000000000000000000000000000000000000..2a62c7a0810a8b4f3d06279330e0308bf2a78b68
Binary files /dev/null and b/app/assets/images/emoji/gb.png differ
diff --git a/app/assets/images/emoji/gem.png b/app/assets/images/emoji/gem.png
new file mode 100755
index 0000000000000000000000000000000000000000..8a5d8dad5c3ab032d0d986be788d309fe55cf3ad
Binary files /dev/null and b/app/assets/images/emoji/gem.png differ
diff --git a/app/assets/images/emoji/gemini.png b/app/assets/images/emoji/gemini.png
new file mode 100755
index 0000000000000000000000000000000000000000..d926f6e88e908cfbb7f7d116fdd50421826131d2
Binary files /dev/null and b/app/assets/images/emoji/gemini.png differ
diff --git a/app/assets/images/emoji/ghost.png b/app/assets/images/emoji/ghost.png
new file mode 100755
index 0000000000000000000000000000000000000000..671dd0c9e2ef5c61a08f7695b19defaa454f1e77
Binary files /dev/null and b/app/assets/images/emoji/ghost.png differ
diff --git a/app/assets/images/emoji/gift.png b/app/assets/images/emoji/gift.png
new file mode 100755
index 0000000000000000000000000000000000000000..552cfdc2b982d5d3ac41d44892872f038dfc2d60
Binary files /dev/null and b/app/assets/images/emoji/gift.png differ
diff --git a/app/assets/images/emoji/gift_heart.png b/app/assets/images/emoji/gift_heart.png
new file mode 100755
index 0000000000000000000000000000000000000000..f31c26a3fcc75e5e47d7e1092ac51aabaaee2e3f
Binary files /dev/null and b/app/assets/images/emoji/gift_heart.png differ
diff --git a/app/assets/images/emoji/girl.png b/app/assets/images/emoji/girl.png
new file mode 100755
index 0000000000000000000000000000000000000000..ea4126941f726eeeee2eabe1d429d6a87619cfe3
Binary files /dev/null and b/app/assets/images/emoji/girl.png differ
diff --git a/app/assets/images/emoji/globe_with_meridians.png b/app/assets/images/emoji/globe_with_meridians.png
new file mode 100755
index 0000000000000000000000000000000000000000..b198646670cf4cf4d4d307ad92949cae4af0f100
Binary files /dev/null and b/app/assets/images/emoji/globe_with_meridians.png differ
diff --git a/app/assets/images/emoji/goat.png b/app/assets/images/emoji/goat.png
new file mode 100755
index 0000000000000000000000000000000000000000..4be9cf30404771e0d7ec6d6e0d8a63dc4096f11a
Binary files /dev/null and b/app/assets/images/emoji/goat.png differ
diff --git a/app/assets/images/emoji/goberserk.png b/app/assets/images/emoji/goberserk.png
new file mode 100755
index 0000000000000000000000000000000000000000..59a742aaaa549287a5f9efbb07767ca97788bf40
Binary files /dev/null and b/app/assets/images/emoji/goberserk.png differ
diff --git a/app/assets/images/emoji/godmode.png b/app/assets/images/emoji/godmode.png
new file mode 100755
index 0000000000000000000000000000000000000000..7e75ab2081ba7f225146bad89ff4d5fd4d990e5c
Binary files /dev/null and b/app/assets/images/emoji/godmode.png differ
diff --git a/app/assets/images/emoji/golf.png b/app/assets/images/emoji/golf.png
new file mode 100755
index 0000000000000000000000000000000000000000..cba2116a7e2d627728bcfbbac86b95cfabef667f
Binary files /dev/null and b/app/assets/images/emoji/golf.png differ
diff --git a/app/assets/images/emoji/grapes.png b/app/assets/images/emoji/grapes.png
new file mode 100755
index 0000000000000000000000000000000000000000..0f9f007a12fbbad58ee2a8edf4e459aff73b4b2e
Binary files /dev/null and b/app/assets/images/emoji/grapes.png differ
diff --git a/app/assets/images/emoji/green_apple.png b/app/assets/images/emoji/green_apple.png
new file mode 100755
index 0000000000000000000000000000000000000000..337205cd125385e16d1b67fe21e2568f207e3de8
Binary files /dev/null and b/app/assets/images/emoji/green_apple.png differ
diff --git a/app/assets/images/emoji/green_book.png b/app/assets/images/emoji/green_book.png
new file mode 100755
index 0000000000000000000000000000000000000000..e86651e5c5c372afaad34b4ba16f84be46acc9fc
Binary files /dev/null and b/app/assets/images/emoji/green_book.png differ
diff --git a/app/assets/images/emoji/green_heart.png b/app/assets/images/emoji/green_heart.png
new file mode 100755
index 0000000000000000000000000000000000000000..7289cb8147c75c638ef01ce52fd777b166e2f661
Binary files /dev/null and b/app/assets/images/emoji/green_heart.png differ
diff --git a/app/assets/images/emoji/grey_exclamation.png b/app/assets/images/emoji/grey_exclamation.png
new file mode 100755
index 0000000000000000000000000000000000000000..a50d265e9d7b855710b7f31294ae4446bfd47caa
Binary files /dev/null and b/app/assets/images/emoji/grey_exclamation.png differ
diff --git a/app/assets/images/emoji/grey_question.png b/app/assets/images/emoji/grey_question.png
new file mode 100755
index 0000000000000000000000000000000000000000..fb97ba752fdc88e948c09be05f0358c007a80cca
Binary files /dev/null and b/app/assets/images/emoji/grey_question.png differ
diff --git a/app/assets/images/emoji/grin.png b/app/assets/images/emoji/grin.png
new file mode 100755
index 0000000000000000000000000000000000000000..591cfcef8bb86b07f085e81b99e16bb261c40e15
Binary files /dev/null and b/app/assets/images/emoji/grin.png differ
diff --git a/app/assets/images/emoji/guardsman.png b/app/assets/images/emoji/guardsman.png
new file mode 100755
index 0000000000000000000000000000000000000000..b67b335d68744d99bc23bb6b69b74f455e40987c
Binary files /dev/null and b/app/assets/images/emoji/guardsman.png differ
diff --git a/app/assets/images/emoji/guitar.png b/app/assets/images/emoji/guitar.png
new file mode 100755
index 0000000000000000000000000000000000000000..2b7fa43c941d33a524665cbff0cd178be13b8680
Binary files /dev/null and b/app/assets/images/emoji/guitar.png differ
diff --git a/app/assets/images/emoji/gun.png b/app/assets/images/emoji/gun.png
new file mode 100755
index 0000000000000000000000000000000000000000..c49dc52c6cbfea3614046401144b5e7cf5601aeb
Binary files /dev/null and b/app/assets/images/emoji/gun.png differ
diff --git a/app/assets/images/emoji/haircut.png b/app/assets/images/emoji/haircut.png
new file mode 100755
index 0000000000000000000000000000000000000000..902d273f6c4428d4a7b4746dd116c0c14e87a389
Binary files /dev/null and b/app/assets/images/emoji/haircut.png differ
diff --git a/app/assets/images/emoji/hamburger.png b/app/assets/images/emoji/hamburger.png
new file mode 100755
index 0000000000000000000000000000000000000000..9f1a3fdff6ec6d7ef4a52587f434b928b6b6b27e
Binary files /dev/null and b/app/assets/images/emoji/hamburger.png differ
diff --git a/app/assets/images/emoji/hammer.png b/app/assets/images/emoji/hammer.png
new file mode 100755
index 0000000000000000000000000000000000000000..482b1c747d1a515e09863a24f34d7451b7ebf852
Binary files /dev/null and b/app/assets/images/emoji/hammer.png differ
diff --git a/app/assets/images/emoji/hamster.png b/app/assets/images/emoji/hamster.png
new file mode 100755
index 0000000000000000000000000000000000000000..addfd2e6b03d1742832fecc47990ec2da4374c34
Binary files /dev/null and b/app/assets/images/emoji/hamster.png differ
diff --git a/app/assets/images/emoji/hand.png b/app/assets/images/emoji/hand.png
new file mode 100755
index 0000000000000000000000000000000000000000..5e45c25a56c6148a8122fb762179efbbf3cd2c62
Binary files /dev/null and b/app/assets/images/emoji/hand.png differ
diff --git a/app/assets/images/emoji/handbag.png b/app/assets/images/emoji/handbag.png
new file mode 100755
index 0000000000000000000000000000000000000000..d7adf04ddf2238ae16955df83d1d42819477e6eb
Binary files /dev/null and b/app/assets/images/emoji/handbag.png differ
diff --git a/app/assets/images/emoji/hankey.png b/app/assets/images/emoji/hankey.png
new file mode 100755
index 0000000000000000000000000000000000000000..73a4dc840085c7f42c7464d827751348b58acfba
Binary files /dev/null and b/app/assets/images/emoji/hankey.png differ
diff --git a/app/assets/images/emoji/hash.png b/app/assets/images/emoji/hash.png
new file mode 100755
index 0000000000000000000000000000000000000000..6765d7d3c2ef48438b5c8d629e0d499566c73693
Binary files /dev/null and b/app/assets/images/emoji/hash.png differ
diff --git a/app/assets/images/emoji/hatched_chick.png b/app/assets/images/emoji/hatched_chick.png
new file mode 100755
index 0000000000000000000000000000000000000000..39c25bc7ccde42bc18a5fb0aaaed47d88490bf98
Binary files /dev/null and b/app/assets/images/emoji/hatched_chick.png differ
diff --git a/app/assets/images/emoji/hatching_chick.png b/app/assets/images/emoji/hatching_chick.png
new file mode 100755
index 0000000000000000000000000000000000000000..005a55519f1c2668cc3b664dd1f7307f53cf3102
Binary files /dev/null and b/app/assets/images/emoji/hatching_chick.png differ
diff --git a/app/assets/images/emoji/headphones.png b/app/assets/images/emoji/headphones.png
new file mode 100755
index 0000000000000000000000000000000000000000..ad83000e687632a3da46502187b0b72a675a56d5
Binary files /dev/null and b/app/assets/images/emoji/headphones.png differ
diff --git a/app/assets/images/emoji/hear_no_evil.png b/app/assets/images/emoji/hear_no_evil.png
new file mode 100755
index 0000000000000000000000000000000000000000..f97a1f9a0901f16e373e349e32bcbaf7c6c659de
Binary files /dev/null and b/app/assets/images/emoji/hear_no_evil.png differ
diff --git a/app/assets/images/emoji/heart.png b/app/assets/images/emoji/heart.png
new file mode 100755
index 0000000000000000000000000000000000000000..7d7790ce4dfc69a8dcbbf706b75757dffec862e2
Binary files /dev/null and b/app/assets/images/emoji/heart.png differ
diff --git a/app/assets/images/emoji/heart_decoration.png b/app/assets/images/emoji/heart_decoration.png
new file mode 100755
index 0000000000000000000000000000000000000000..b8be44db343839258d488353c30890df963d169b
Binary files /dev/null and b/app/assets/images/emoji/heart_decoration.png differ
diff --git a/app/assets/images/emoji/heart_eyes.png b/app/assets/images/emoji/heart_eyes.png
new file mode 100755
index 0000000000000000000000000000000000000000..0e5794270ea393cd6295e0553ec87838e0a4d5b9
Binary files /dev/null and b/app/assets/images/emoji/heart_eyes.png differ
diff --git a/app/assets/images/emoji/heart_eyes_cat.png b/app/assets/images/emoji/heart_eyes_cat.png
new file mode 100755
index 0000000000000000000000000000000000000000..eeba240e533783c92e0d221489e78c7f54586027
Binary files /dev/null and b/app/assets/images/emoji/heart_eyes_cat.png differ
diff --git a/app/assets/images/emoji/heartbeat.png b/app/assets/images/emoji/heartbeat.png
new file mode 100755
index 0000000000000000000000000000000000000000..b6628f6fa70ab24c6e83172221781e4a5077c481
Binary files /dev/null and b/app/assets/images/emoji/heartbeat.png differ
diff --git a/app/assets/images/emoji/heartpulse.png b/app/assets/images/emoji/heartpulse.png
new file mode 100755
index 0000000000000000000000000000000000000000..a7491cbeae62ee924046a012219ada18aa4975fe
Binary files /dev/null and b/app/assets/images/emoji/heartpulse.png differ
diff --git a/app/assets/images/emoji/hearts.png b/app/assets/images/emoji/hearts.png
new file mode 100755
index 0000000000000000000000000000000000000000..e894715385710c5382bd052ad9a501c1fe6be376
Binary files /dev/null and b/app/assets/images/emoji/hearts.png differ
diff --git a/app/assets/images/emoji/heavy_check_mark.png b/app/assets/images/emoji/heavy_check_mark.png
new file mode 100755
index 0000000000000000000000000000000000000000..336d2626d0c9aab25d10df8570d1342cb65c1f6c
Binary files /dev/null and b/app/assets/images/emoji/heavy_check_mark.png differ
diff --git a/app/assets/images/emoji/heavy_division_sign.png b/app/assets/images/emoji/heavy_division_sign.png
new file mode 100755
index 0000000000000000000000000000000000000000..ac757a238ecde77e2e427fad0c9009b70480b876
Binary files /dev/null and b/app/assets/images/emoji/heavy_division_sign.png differ
diff --git a/app/assets/images/emoji/heavy_dollar_sign.png b/app/assets/images/emoji/heavy_dollar_sign.png
new file mode 100755
index 0000000000000000000000000000000000000000..361e26aef8be5ea9673c9e6822469b0bb4ce957a
Binary files /dev/null and b/app/assets/images/emoji/heavy_dollar_sign.png differ
diff --git a/app/assets/images/emoji/heavy_exclamation_mark.png b/app/assets/images/emoji/heavy_exclamation_mark.png
new file mode 100755
index 0000000000000000000000000000000000000000..4c560f5e3f46d3ec6361aebee9d689ef79525b71
Binary files /dev/null and b/app/assets/images/emoji/heavy_exclamation_mark.png differ
diff --git a/app/assets/images/emoji/heavy_minus_sign.png b/app/assets/images/emoji/heavy_minus_sign.png
new file mode 100755
index 0000000000000000000000000000000000000000..b8d3d82f2cd5141182c304ad90a6992eb2c5d4c1
Binary files /dev/null and b/app/assets/images/emoji/heavy_minus_sign.png differ
diff --git a/app/assets/images/emoji/heavy_multiplication_x.png b/app/assets/images/emoji/heavy_multiplication_x.png
new file mode 100755
index 0000000000000000000000000000000000000000..13d666078656729c570e62e9bf287f74391b8d36
Binary files /dev/null and b/app/assets/images/emoji/heavy_multiplication_x.png differ
diff --git a/app/assets/images/emoji/heavy_plus_sign.png b/app/assets/images/emoji/heavy_plus_sign.png
new file mode 100755
index 0000000000000000000000000000000000000000..61595387bb6936d4b5e238da4a8f8300209dc113
Binary files /dev/null and b/app/assets/images/emoji/heavy_plus_sign.png differ
diff --git a/app/assets/images/emoji/helicopter.png b/app/assets/images/emoji/helicopter.png
new file mode 100755
index 0000000000000000000000000000000000000000..8e82a0d587692e6210f28ac1e3f0015e27b2639b
Binary files /dev/null and b/app/assets/images/emoji/helicopter.png differ
diff --git a/app/assets/images/emoji/herb.png b/app/assets/images/emoji/herb.png
new file mode 100755
index 0000000000000000000000000000000000000000..de1ff1b73bf01beac7f18a3343778fba7d7206ec
Binary files /dev/null and b/app/assets/images/emoji/herb.png differ
diff --git a/app/assets/images/emoji/hibiscus.png b/app/assets/images/emoji/hibiscus.png
new file mode 100755
index 0000000000000000000000000000000000000000..9365ae2169f448da7f194d21cf6f097155a91a9c
Binary files /dev/null and b/app/assets/images/emoji/hibiscus.png differ
diff --git a/app/assets/images/emoji/high_brightness.png b/app/assets/images/emoji/high_brightness.png
new file mode 100755
index 0000000000000000000000000000000000000000..ba9de7d409c008610ea2228074f7a8b03f732bd5
Binary files /dev/null and b/app/assets/images/emoji/high_brightness.png differ
diff --git a/app/assets/images/emoji/high_heel.png b/app/assets/images/emoji/high_heel.png
new file mode 100755
index 0000000000000000000000000000000000000000..525b6a0dd6947b98e1950c822b8448c2ecdc0c2c
Binary files /dev/null and b/app/assets/images/emoji/high_heel.png differ
diff --git a/app/assets/images/emoji/hocho.png b/app/assets/images/emoji/hocho.png
new file mode 100755
index 0000000000000000000000000000000000000000..18eade0acfa91bf5a3531e0d80fea78e4d360ead
Binary files /dev/null and b/app/assets/images/emoji/hocho.png differ
diff --git a/app/assets/images/emoji/honey_pot.png b/app/assets/images/emoji/honey_pot.png
new file mode 100755
index 0000000000000000000000000000000000000000..73278898a4c568b23ac5bcd54b9de37d66aab1a0
Binary files /dev/null and b/app/assets/images/emoji/honey_pot.png differ
diff --git a/app/assets/images/emoji/honeybee.png b/app/assets/images/emoji/honeybee.png
new file mode 100755
index 0000000000000000000000000000000000000000..f53733953afad79cb582a1e7edc8d847b8767f1a
Binary files /dev/null and b/app/assets/images/emoji/honeybee.png differ
diff --git a/app/assets/images/emoji/horse.png b/app/assets/images/emoji/horse.png
new file mode 100755
index 0000000000000000000000000000000000000000..78d580ad3e9cb256589834fd6d61013127324b29
Binary files /dev/null and b/app/assets/images/emoji/horse.png differ
diff --git a/app/assets/images/emoji/horse_racing.png b/app/assets/images/emoji/horse_racing.png
new file mode 100755
index 0000000000000000000000000000000000000000..e3bbaec1d6c8f8e7257b73023ea7d52ed73b5ea8
Binary files /dev/null and b/app/assets/images/emoji/horse_racing.png differ
diff --git a/app/assets/images/emoji/hospital.png b/app/assets/images/emoji/hospital.png
new file mode 100755
index 0000000000000000000000000000000000000000..c05c49377fe19057ebaab5654041a9bd70f7e1b0
Binary files /dev/null and b/app/assets/images/emoji/hospital.png differ
diff --git a/app/assets/images/emoji/hotel.png b/app/assets/images/emoji/hotel.png
new file mode 100755
index 0000000000000000000000000000000000000000..d29f276a1805e58cdef33235312cc2f41be26c0f
Binary files /dev/null and b/app/assets/images/emoji/hotel.png differ
diff --git a/app/assets/images/emoji/hotsprings.png b/app/assets/images/emoji/hotsprings.png
new file mode 100755
index 0000000000000000000000000000000000000000..a0bc9d75f21878b0d9a663dc72b129c345215e55
Binary files /dev/null and b/app/assets/images/emoji/hotsprings.png differ
diff --git a/app/assets/images/emoji/hourglass.png b/app/assets/images/emoji/hourglass.png
new file mode 100755
index 0000000000000000000000000000000000000000..405aab41beb391ab072c9a0225038950417c40e4
Binary files /dev/null and b/app/assets/images/emoji/hourglass.png differ
diff --git a/app/assets/images/emoji/house.png b/app/assets/images/emoji/house.png
new file mode 100755
index 0000000000000000000000000000000000000000..95b9ee09480cb635876ddec024d6aba6e8d636bf
Binary files /dev/null and b/app/assets/images/emoji/house.png differ
diff --git a/app/assets/images/emoji/hurtrealbad.png b/app/assets/images/emoji/hurtrealbad.png
new file mode 100755
index 0000000000000000000000000000000000000000..146ef1a6a87c299c712aaba364f513a1f06203ff
Binary files /dev/null and b/app/assets/images/emoji/hurtrealbad.png differ
diff --git a/app/assets/images/emoji/ice_cream.png b/app/assets/images/emoji/ice_cream.png
new file mode 100755
index 0000000000000000000000000000000000000000..190be01650ed17340c4bfcdcf4ff82b4df5256a4
Binary files /dev/null and b/app/assets/images/emoji/ice_cream.png differ
diff --git a/app/assets/images/emoji/icecream.png b/app/assets/images/emoji/icecream.png
new file mode 100755
index 0000000000000000000000000000000000000000..871ce097689eb1fc452fcd8b2a0fc00833849ce6
Binary files /dev/null and b/app/assets/images/emoji/icecream.png differ
diff --git a/app/assets/images/emoji/id.png b/app/assets/images/emoji/id.png
new file mode 100755
index 0000000000000000000000000000000000000000..47437a76d39258a854a52ce98d7b2839b7f4f9a5
Binary files /dev/null and b/app/assets/images/emoji/id.png differ
diff --git a/app/assets/images/emoji/ideograph_advantage.png b/app/assets/images/emoji/ideograph_advantage.png
new file mode 100755
index 0000000000000000000000000000000000000000..e79af78442eb453059b8a8523cee71df02ca99d0
Binary files /dev/null and b/app/assets/images/emoji/ideograph_advantage.png differ
diff --git a/app/assets/images/emoji/imp.png b/app/assets/images/emoji/imp.png
new file mode 100755
index 0000000000000000000000000000000000000000..5acca3373b9148282131e383b0cdeeecdd52a1e0
Binary files /dev/null and b/app/assets/images/emoji/imp.png differ
diff --git a/app/assets/images/emoji/inbox_tray.png b/app/assets/images/emoji/inbox_tray.png
new file mode 100755
index 0000000000000000000000000000000000000000..e2df0f8970524c92f3ed147c889fe5e66a3acf5c
Binary files /dev/null and b/app/assets/images/emoji/inbox_tray.png differ
diff --git a/app/assets/images/emoji/incoming_envelope.png b/app/assets/images/emoji/incoming_envelope.png
new file mode 100755
index 0000000000000000000000000000000000000000..afc827125108517b06c96d0f94d7813c3e3a40aa
Binary files /dev/null and b/app/assets/images/emoji/incoming_envelope.png differ
diff --git a/app/assets/images/emoji/information_desk_person.png b/app/assets/images/emoji/information_desk_person.png
new file mode 100755
index 0000000000000000000000000000000000000000..52c0a50a3f61ada64000b53eac14887f228aebc8
Binary files /dev/null and b/app/assets/images/emoji/information_desk_person.png differ
diff --git a/app/assets/images/emoji/information_source.png b/app/assets/images/emoji/information_source.png
new file mode 100755
index 0000000000000000000000000000000000000000..9cb8b09b249492037ebcec0b0c319f728c6641f6
Binary files /dev/null and b/app/assets/images/emoji/information_source.png differ
diff --git a/app/assets/images/emoji/innocent.png b/app/assets/images/emoji/innocent.png
new file mode 100755
index 0000000000000000000000000000000000000000..503b614f8dcc32bad7a6f17f49d12602792215b0
Binary files /dev/null and b/app/assets/images/emoji/innocent.png differ
diff --git a/app/assets/images/emoji/interrobang.png b/app/assets/images/emoji/interrobang.png
new file mode 100755
index 0000000000000000000000000000000000000000..64304b9f5fb0120bf666e4ab13e6def7f9fbb846
Binary files /dev/null and b/app/assets/images/emoji/interrobang.png differ
diff --git a/app/assets/images/emoji/iphone.png b/app/assets/images/emoji/iphone.png
new file mode 100755
index 0000000000000000000000000000000000000000..df007103b0bd410bfd23be425d6654b0aa3eeb16
Binary files /dev/null and b/app/assets/images/emoji/iphone.png differ
diff --git a/app/assets/images/emoji/it.png b/app/assets/images/emoji/it.png
new file mode 100755
index 0000000000000000000000000000000000000000..70bc9f32463c11f26cf129ab031795a271f15b35
Binary files /dev/null and b/app/assets/images/emoji/it.png differ
diff --git a/app/assets/images/emoji/izakaya_lantern.png b/app/assets/images/emoji/izakaya_lantern.png
new file mode 100755
index 0000000000000000000000000000000000000000..18730ad559737ba68461687736483c1cb9bedb23
Binary files /dev/null and b/app/assets/images/emoji/izakaya_lantern.png differ
diff --git a/app/assets/images/emoji/jack_o_lantern.png b/app/assets/images/emoji/jack_o_lantern.png
new file mode 100755
index 0000000000000000000000000000000000000000..1f7667ea45897409431a8069a56d8a2683d7b345
Binary files /dev/null and b/app/assets/images/emoji/jack_o_lantern.png differ
diff --git a/app/assets/images/emoji/japan.png b/app/assets/images/emoji/japan.png
new file mode 100755
index 0000000000000000000000000000000000000000..45932803597c1ce7e8d073cc5fce00aeaecd01db
Binary files /dev/null and b/app/assets/images/emoji/japan.png differ
diff --git a/app/assets/images/emoji/japanese_castle.png b/app/assets/images/emoji/japanese_castle.png
new file mode 100755
index 0000000000000000000000000000000000000000..f225ab217c0ed0e570c9266369304b2f93e907ac
Binary files /dev/null and b/app/assets/images/emoji/japanese_castle.png differ
diff --git a/app/assets/images/emoji/japanese_goblin.png b/app/assets/images/emoji/japanese_goblin.png
new file mode 100755
index 0000000000000000000000000000000000000000..bd21b187570ae2263db7e1d50cc1aaee27358c4f
Binary files /dev/null and b/app/assets/images/emoji/japanese_goblin.png differ
diff --git a/app/assets/images/emoji/japanese_ogre.png b/app/assets/images/emoji/japanese_ogre.png
new file mode 100755
index 0000000000000000000000000000000000000000..e9f5471c9a28822445e6382e1c71dd9bda013c43
Binary files /dev/null and b/app/assets/images/emoji/japanese_ogre.png differ
diff --git a/app/assets/images/emoji/jeans.png b/app/assets/images/emoji/jeans.png
new file mode 100755
index 0000000000000000000000000000000000000000..d721cea54c3a2c831b80fe6af108c2ec28a456cb
Binary files /dev/null and b/app/assets/images/emoji/jeans.png differ
diff --git a/app/assets/images/emoji/joy.png b/app/assets/images/emoji/joy.png
new file mode 100755
index 0000000000000000000000000000000000000000..47df693d424f94fc2db1a0392148ca8f2cdb4923
Binary files /dev/null and b/app/assets/images/emoji/joy.png differ
diff --git a/app/assets/images/emoji/joy_cat.png b/app/assets/images/emoji/joy_cat.png
new file mode 100755
index 0000000000000000000000000000000000000000..6c60cb0efc83a744ab2774a5ce4f5f774c7b3de9
Binary files /dev/null and b/app/assets/images/emoji/joy_cat.png differ
diff --git a/app/assets/images/emoji/jp.png b/app/assets/images/emoji/jp.png
new file mode 100755
index 0000000000000000000000000000000000000000..b786efbbd8aa214f0dcc30b4859629a6f3feff47
Binary files /dev/null and b/app/assets/images/emoji/jp.png differ
diff --git a/app/assets/images/emoji/key.png b/app/assets/images/emoji/key.png
new file mode 100755
index 0000000000000000000000000000000000000000..34673213f64990f557e373c5736693b94e47dce1
Binary files /dev/null and b/app/assets/images/emoji/key.png differ
diff --git a/app/assets/images/emoji/keycap_ten.png b/app/assets/images/emoji/keycap_ten.png
new file mode 100755
index 0000000000000000000000000000000000000000..71dac1c1cc0484787804a817c702bec235264acd
Binary files /dev/null and b/app/assets/images/emoji/keycap_ten.png differ
diff --git a/app/assets/images/emoji/kimono.png b/app/assets/images/emoji/kimono.png
new file mode 100755
index 0000000000000000000000000000000000000000..34ffe137dcd21b83bdd62ea8e0f1ef247d181a27
Binary files /dev/null and b/app/assets/images/emoji/kimono.png differ
diff --git a/app/assets/images/emoji/kiss.png b/app/assets/images/emoji/kiss.png
new file mode 100755
index 0000000000000000000000000000000000000000..14fd9918d582e6165d4aed39fc87a4a41487b485
Binary files /dev/null and b/app/assets/images/emoji/kiss.png differ
diff --git a/app/assets/images/emoji/kissing_cat.png b/app/assets/images/emoji/kissing_cat.png
new file mode 100755
index 0000000000000000000000000000000000000000..adc62fbe3ce8ef1b016dff846de3b0067734e7e7
Binary files /dev/null and b/app/assets/images/emoji/kissing_cat.png differ
diff --git a/app/assets/images/emoji/kissing_face.png b/app/assets/images/emoji/kissing_face.png
new file mode 100755
index 0000000000000000000000000000000000000000..449de197048a504b2ac4ff5bc8b86fa5cfa098de
Binary files /dev/null and b/app/assets/images/emoji/kissing_face.png differ
diff --git a/app/assets/images/emoji/kissing_heart.png b/app/assets/images/emoji/kissing_heart.png
new file mode 100755
index 0000000000000000000000000000000000000000..af9a80b7f09fcd4926ddeb4b8849220514274b48
Binary files /dev/null and b/app/assets/images/emoji/kissing_heart.png differ
diff --git a/app/assets/images/emoji/koala.png b/app/assets/images/emoji/koala.png
new file mode 100755
index 0000000000000000000000000000000000000000..e17bd3cf531f0a752a4214ef1d272c51184826ad
Binary files /dev/null and b/app/assets/images/emoji/koala.png differ
diff --git a/app/assets/images/emoji/koko.png b/app/assets/images/emoji/koko.png
new file mode 100755
index 0000000000000000000000000000000000000000..3bef28c9fdbdb466221b47929c92869add843558
Binary files /dev/null and b/app/assets/images/emoji/koko.png differ
diff --git a/app/assets/images/emoji/kr.png b/app/assets/images/emoji/kr.png
new file mode 100755
index 0000000000000000000000000000000000000000..b4c0c1b673d7c490888041a189d14e833730c7c6
Binary files /dev/null and b/app/assets/images/emoji/kr.png differ
diff --git a/app/assets/images/emoji/large_blue_circle.png b/app/assets/images/emoji/large_blue_circle.png
new file mode 100755
index 0000000000000000000000000000000000000000..a5b4ad4aaa2cc405cc6ea52c6b30728feca77af8
Binary files /dev/null and b/app/assets/images/emoji/large_blue_circle.png differ
diff --git a/app/assets/images/emoji/large_blue_diamond.png b/app/assets/images/emoji/large_blue_diamond.png
new file mode 100755
index 0000000000000000000000000000000000000000..f4598ec0f20cadcdda6f1b9edfce8cfe1ece80f8
Binary files /dev/null and b/app/assets/images/emoji/large_blue_diamond.png differ
diff --git a/app/assets/images/emoji/large_orange_diamond.png b/app/assets/images/emoji/large_orange_diamond.png
new file mode 100755
index 0000000000000000000000000000000000000000..46d52e5cb6d8c53c21db0391ef4ea1592c1e2d24
Binary files /dev/null and b/app/assets/images/emoji/large_orange_diamond.png differ
diff --git a/app/assets/images/emoji/last_quarter_moon.png b/app/assets/images/emoji/last_quarter_moon.png
new file mode 100755
index 0000000000000000000000000000000000000000..355e3c3f79f588ee1c8f2c1380ea55f00408a271
Binary files /dev/null and b/app/assets/images/emoji/last_quarter_moon.png differ
diff --git a/app/assets/images/emoji/last_quarter_moon_with_face.png b/app/assets/images/emoji/last_quarter_moon_with_face.png
new file mode 100755
index 0000000000000000000000000000000000000000..9ece82dfec67560c8791e5e803657583a6fd84bf
Binary files /dev/null and b/app/assets/images/emoji/last_quarter_moon_with_face.png differ
diff --git a/app/assets/images/emoji/laughing.png b/app/assets/images/emoji/laughing.png
new file mode 100755
index 0000000000000000000000000000000000000000..11c91eb22e6a9ebb879071045a8d40ae9d15bce2
Binary files /dev/null and b/app/assets/images/emoji/laughing.png differ
diff --git a/app/assets/images/emoji/leaves.png b/app/assets/images/emoji/leaves.png
new file mode 100755
index 0000000000000000000000000000000000000000..5229e06bdd097f639b4860f386e138ea072b4ec8
Binary files /dev/null and b/app/assets/images/emoji/leaves.png differ
diff --git a/app/assets/images/emoji/ledger.png b/app/assets/images/emoji/ledger.png
new file mode 100755
index 0000000000000000000000000000000000000000..e4f72aceacfc3b715a504edcf14dd1b3e30e6bcd
Binary files /dev/null and b/app/assets/images/emoji/ledger.png differ
diff --git a/app/assets/images/emoji/left_luggage.png b/app/assets/images/emoji/left_luggage.png
new file mode 100755
index 0000000000000000000000000000000000000000..1c08b464db124bbad7c8f8b52f72f51d6c1b3683
Binary files /dev/null and b/app/assets/images/emoji/left_luggage.png differ
diff --git a/app/assets/images/emoji/left_right_arrow.png b/app/assets/images/emoji/left_right_arrow.png
new file mode 100755
index 0000000000000000000000000000000000000000..b9fd11c5158ba6e8d51e22a15ffaef865a6ef642
Binary files /dev/null and b/app/assets/images/emoji/left_right_arrow.png differ
diff --git a/app/assets/images/emoji/leftwards_arrow_with_hook.png b/app/assets/images/emoji/leftwards_arrow_with_hook.png
new file mode 100755
index 0000000000000000000000000000000000000000..bc45dfefd4adc427af9a75ecacb825784bf7b54d
Binary files /dev/null and b/app/assets/images/emoji/leftwards_arrow_with_hook.png differ
diff --git a/app/assets/images/emoji/lemon.png b/app/assets/images/emoji/lemon.png
new file mode 100755
index 0000000000000000000000000000000000000000..9814dc95989fd9655f21d125f7afe40a058e32dd
Binary files /dev/null and b/app/assets/images/emoji/lemon.png differ
diff --git a/app/assets/images/emoji/leo.png b/app/assets/images/emoji/leo.png
new file mode 100755
index 0000000000000000000000000000000000000000..e025933b2f875103d9ceb3faca054c3c15193c82
Binary files /dev/null and b/app/assets/images/emoji/leo.png differ
diff --git a/app/assets/images/emoji/leopard.png b/app/assets/images/emoji/leopard.png
new file mode 100755
index 0000000000000000000000000000000000000000..8abfc4a27291589330221ae83c48e395c0f60e91
Binary files /dev/null and b/app/assets/images/emoji/leopard.png differ
diff --git a/app/assets/images/emoji/libra.png b/app/assets/images/emoji/libra.png
new file mode 100755
index 0000000000000000000000000000000000000000..c9062dd2eeb0c3c79d33601f437cb135617268e7
Binary files /dev/null and b/app/assets/images/emoji/libra.png differ
diff --git a/app/assets/images/emoji/light_rail.png b/app/assets/images/emoji/light_rail.png
new file mode 100755
index 0000000000000000000000000000000000000000..bcfe801eec6f4165b37c3907527918ba6aae98c3
Binary files /dev/null and b/app/assets/images/emoji/light_rail.png differ
diff --git a/app/assets/images/emoji/link.png b/app/assets/images/emoji/link.png
new file mode 100755
index 0000000000000000000000000000000000000000..ffb8f62ceca689aebc5b5462b9c90a82a9c41dc9
Binary files /dev/null and b/app/assets/images/emoji/link.png differ
diff --git a/app/assets/images/emoji/lips.png b/app/assets/images/emoji/lips.png
new file mode 100755
index 0000000000000000000000000000000000000000..826ed1102dc6f3f74c008b3ce7bd03a4f0a44fa7
Binary files /dev/null and b/app/assets/images/emoji/lips.png differ
diff --git a/app/assets/images/emoji/lipstick.png b/app/assets/images/emoji/lipstick.png
new file mode 100755
index 0000000000000000000000000000000000000000..82f990c5679533d838d93215512229cb13f8043f
Binary files /dev/null and b/app/assets/images/emoji/lipstick.png differ
diff --git a/app/assets/images/emoji/lock.png b/app/assets/images/emoji/lock.png
new file mode 100755
index 0000000000000000000000000000000000000000..4892b023558f0b074010755353cf14fce785ca81
Binary files /dev/null and b/app/assets/images/emoji/lock.png differ
diff --git a/app/assets/images/emoji/lock_with_ink_pen.png b/app/assets/images/emoji/lock_with_ink_pen.png
new file mode 100755
index 0000000000000000000000000000000000000000..375e67e8253397b51cdbcfa1e8e3d308a24867b1
Binary files /dev/null and b/app/assets/images/emoji/lock_with_ink_pen.png differ
diff --git a/app/assets/images/emoji/lollipop.png b/app/assets/images/emoji/lollipop.png
new file mode 100755
index 0000000000000000000000000000000000000000..ba55e7093f125762c5e2bd38ac7c7afc69029eb7
Binary files /dev/null and b/app/assets/images/emoji/lollipop.png differ
diff --git a/app/assets/images/emoji/loop.png b/app/assets/images/emoji/loop.png
new file mode 100755
index 0000000000000000000000000000000000000000..ef34df3a404ab5ce6597c202d695665ea7c2870d
Binary files /dev/null and b/app/assets/images/emoji/loop.png differ
diff --git a/app/assets/images/emoji/loudspeaker.png b/app/assets/images/emoji/loudspeaker.png
new file mode 100755
index 0000000000000000000000000000000000000000..752385e523d44d308bbb86aaf2484c09cd6797ae
Binary files /dev/null and b/app/assets/images/emoji/loudspeaker.png differ
diff --git a/app/assets/images/emoji/love_hotel.png b/app/assets/images/emoji/love_hotel.png
new file mode 100755
index 0000000000000000000000000000000000000000..44d7db828ad1c6ffa0a782a83c506d99ea91c33f
Binary files /dev/null and b/app/assets/images/emoji/love_hotel.png differ
diff --git a/app/assets/images/emoji/love_letter.png b/app/assets/images/emoji/love_letter.png
new file mode 100755
index 0000000000000000000000000000000000000000..e29981f44533ec09c0c639a21ee8b7f4298f64e1
Binary files /dev/null and b/app/assets/images/emoji/love_letter.png differ
diff --git a/app/assets/images/emoji/low_brightness.png b/app/assets/images/emoji/low_brightness.png
new file mode 100755
index 0000000000000000000000000000000000000000..ea15bde4f0d4653bcbe6bc31de976d7522c7d248
Binary files /dev/null and b/app/assets/images/emoji/low_brightness.png differ
diff --git a/app/assets/images/emoji/m.png b/app/assets/images/emoji/m.png
new file mode 100755
index 0000000000000000000000000000000000000000..7424665e2bb49a431aa123905a6ecdfa08b6a54c
Binary files /dev/null and b/app/assets/images/emoji/m.png differ
diff --git a/app/assets/images/emoji/mag.png b/app/assets/images/emoji/mag.png
new file mode 100755
index 0000000000000000000000000000000000000000..aa5b1d7c46fbfb27876d4e5facd5d0dfa5436d44
Binary files /dev/null and b/app/assets/images/emoji/mag.png differ
diff --git a/app/assets/images/emoji/mag_right.png b/app/assets/images/emoji/mag_right.png
new file mode 100755
index 0000000000000000000000000000000000000000..6e6cf11e6d7693f8f7d4b97d4910e56e5213d7ac
Binary files /dev/null and b/app/assets/images/emoji/mag_right.png differ
diff --git a/app/assets/images/emoji/mahjong.png b/app/assets/images/emoji/mahjong.png
new file mode 100755
index 0000000000000000000000000000000000000000..f51ce65fdde8e3c2c0f69fbc1beb78ad7f83fa10
Binary files /dev/null and b/app/assets/images/emoji/mahjong.png differ
diff --git a/app/assets/images/emoji/mailbox.png b/app/assets/images/emoji/mailbox.png
new file mode 100755
index 0000000000000000000000000000000000000000..8351e70760cc342e4ece73aac4eafa921e3f90f0
Binary files /dev/null and b/app/assets/images/emoji/mailbox.png differ
diff --git a/app/assets/images/emoji/mailbox_closed.png b/app/assets/images/emoji/mailbox_closed.png
new file mode 100755
index 0000000000000000000000000000000000000000..a5982b69bb5059a3448bf949aa17d3db6ad5d44b
Binary files /dev/null and b/app/assets/images/emoji/mailbox_closed.png differ
diff --git a/app/assets/images/emoji/mailbox_with_mail.png b/app/assets/images/emoji/mailbox_with_mail.png
new file mode 100755
index 0000000000000000000000000000000000000000..dae34594367e43481d6af557562b4486d3ee4ddb
Binary files /dev/null and b/app/assets/images/emoji/mailbox_with_mail.png differ
diff --git a/app/assets/images/emoji/mailbox_with_no_mail.png b/app/assets/images/emoji/mailbox_with_no_mail.png
new file mode 100755
index 0000000000000000000000000000000000000000..59f15c5d7da88d816a9ed2f5a33cc23faa8633a7
Binary files /dev/null and b/app/assets/images/emoji/mailbox_with_no_mail.png differ
diff --git a/app/assets/images/emoji/man.png b/app/assets/images/emoji/man.png
new file mode 100755
index 0000000000000000000000000000000000000000..d9bfa26a67451b5c24e2b5f4c8e1fd2653e7404a
Binary files /dev/null and b/app/assets/images/emoji/man.png differ
diff --git a/app/assets/images/emoji/man_with_gua_pi_mao.png b/app/assets/images/emoji/man_with_gua_pi_mao.png
new file mode 100755
index 0000000000000000000000000000000000000000..7aad74b55e332c4b6dd2b5b93e6e06a325fd9845
Binary files /dev/null and b/app/assets/images/emoji/man_with_gua_pi_mao.png differ
diff --git a/app/assets/images/emoji/man_with_turban.png b/app/assets/images/emoji/man_with_turban.png
new file mode 100755
index 0000000000000000000000000000000000000000..036604caf2a4c8772c2544e9f76117cbd6025e94
Binary files /dev/null and b/app/assets/images/emoji/man_with_turban.png differ
diff --git a/app/assets/images/emoji/mans_shoe.png b/app/assets/images/emoji/mans_shoe.png
new file mode 100755
index 0000000000000000000000000000000000000000..ecba9ba7d04187bb878e987cc5512d7f2d436131
Binary files /dev/null and b/app/assets/images/emoji/mans_shoe.png differ
diff --git a/app/assets/images/emoji/maple_leaf.png b/app/assets/images/emoji/maple_leaf.png
new file mode 100755
index 0000000000000000000000000000000000000000..4e9b47207de601d11c1a76fdbcdfe63f978bb432
Binary files /dev/null and b/app/assets/images/emoji/maple_leaf.png differ
diff --git a/app/assets/images/emoji/mask.png b/app/assets/images/emoji/mask.png
new file mode 100755
index 0000000000000000000000000000000000000000..05887e99c6bb601fc395d9180efc7db2e684d86e
Binary files /dev/null and b/app/assets/images/emoji/mask.png differ
diff --git a/app/assets/images/emoji/massage.png b/app/assets/images/emoji/massage.png
new file mode 100755
index 0000000000000000000000000000000000000000..dd30d15975564504dd4fae61923675bfbeaa679b
Binary files /dev/null and b/app/assets/images/emoji/massage.png differ
diff --git a/app/assets/images/emoji/meat_on_bone.png b/app/assets/images/emoji/meat_on_bone.png
new file mode 100755
index 0000000000000000000000000000000000000000..d6b311b6b2477789a2767a4a35ac0154f3694f8b
Binary files /dev/null and b/app/assets/images/emoji/meat_on_bone.png differ
diff --git a/app/assets/images/emoji/mega.png b/app/assets/images/emoji/mega.png
new file mode 100755
index 0000000000000000000000000000000000000000..022df2f8d64a85484f6ac8053da61029aab73a2d
Binary files /dev/null and b/app/assets/images/emoji/mega.png differ
diff --git a/app/assets/images/emoji/melon.png b/app/assets/images/emoji/melon.png
new file mode 100755
index 0000000000000000000000000000000000000000..11c13cbbd44ff49892319b060b669b5adf6fc860
Binary files /dev/null and b/app/assets/images/emoji/melon.png differ
diff --git a/app/assets/images/emoji/memo.png b/app/assets/images/emoji/memo.png
new file mode 100755
index 0000000000000000000000000000000000000000..fc97ddbc92b0af4590d3d552bd771fd8d011828c
Binary files /dev/null and b/app/assets/images/emoji/memo.png differ
diff --git a/app/assets/images/emoji/mens.png b/app/assets/images/emoji/mens.png
new file mode 100755
index 0000000000000000000000000000000000000000..abccfc9f2c6f8f965d2234fc5f96146adea9f821
Binary files /dev/null and b/app/assets/images/emoji/mens.png differ
diff --git a/app/assets/images/emoji/metal.png b/app/assets/images/emoji/metal.png
new file mode 100755
index 0000000000000000000000000000000000000000..94f1fda2241a789dff11af72f6ca93dcd780b6f5
Binary files /dev/null and b/app/assets/images/emoji/metal.png differ
diff --git a/app/assets/images/emoji/metro.png b/app/assets/images/emoji/metro.png
new file mode 100755
index 0000000000000000000000000000000000000000..4acf5ab3e29ffd56ea4ff96a272117f4e26c7047
Binary files /dev/null and b/app/assets/images/emoji/metro.png differ
diff --git a/app/assets/images/emoji/microphone.png b/app/assets/images/emoji/microphone.png
new file mode 100755
index 0000000000000000000000000000000000000000..68c74adada1c82c1e9e03f409fa5027d181371cb
Binary files /dev/null and b/app/assets/images/emoji/microphone.png differ
diff --git a/app/assets/images/emoji/microscope.png b/app/assets/images/emoji/microscope.png
new file mode 100755
index 0000000000000000000000000000000000000000..f11d54c010aba5334671c401112e008c53226aa6
Binary files /dev/null and b/app/assets/images/emoji/microscope.png differ
diff --git a/app/assets/images/emoji/milky_way.png b/app/assets/images/emoji/milky_way.png
new file mode 100755
index 0000000000000000000000000000000000000000..901090a126598a9801c2c41296ae56416cd4ec47
Binary files /dev/null and b/app/assets/images/emoji/milky_way.png differ
diff --git a/app/assets/images/emoji/minibus.png b/app/assets/images/emoji/minibus.png
new file mode 100755
index 0000000000000000000000000000000000000000..c52cef23407809763b67a356783b9645bf949456
Binary files /dev/null and b/app/assets/images/emoji/minibus.png differ
diff --git a/app/assets/images/emoji/minidisc.png b/app/assets/images/emoji/minidisc.png
new file mode 100755
index 0000000000000000000000000000000000000000..e19cc5d01507966a1112cdf0a4456499cc7141cc
Binary files /dev/null and b/app/assets/images/emoji/minidisc.png differ
diff --git a/app/assets/images/emoji/mobile_phone_off.png b/app/assets/images/emoji/mobile_phone_off.png
new file mode 100755
index 0000000000000000000000000000000000000000..fa16c763c946c0a5de997dee5f5fb02a6ff26844
Binary files /dev/null and b/app/assets/images/emoji/mobile_phone_off.png differ
diff --git a/app/assets/images/emoji/money_with_wings.png b/app/assets/images/emoji/money_with_wings.png
new file mode 100755
index 0000000000000000000000000000000000000000..135e3981ed1307b19b7c20b00e56d38c5baa8d94
Binary files /dev/null and b/app/assets/images/emoji/money_with_wings.png differ
diff --git a/app/assets/images/emoji/moneybag.png b/app/assets/images/emoji/moneybag.png
new file mode 100755
index 0000000000000000000000000000000000000000..5546c04bad46b89e58906261f1d70a88a57832f1
Binary files /dev/null and b/app/assets/images/emoji/moneybag.png differ
diff --git a/app/assets/images/emoji/monkey.png b/app/assets/images/emoji/monkey.png
new file mode 100755
index 0000000000000000000000000000000000000000..64070359776727df50caf08cb59df7845a46c53a
Binary files /dev/null and b/app/assets/images/emoji/monkey.png differ
diff --git a/app/assets/images/emoji/monkey_face.png b/app/assets/images/emoji/monkey_face.png
new file mode 100755
index 0000000000000000000000000000000000000000..6964cf4d51ac3f2a67f2162e7a52807993c19b7b
Binary files /dev/null and b/app/assets/images/emoji/monkey_face.png differ
diff --git a/app/assets/images/emoji/monorail.png b/app/assets/images/emoji/monorail.png
new file mode 100755
index 0000000000000000000000000000000000000000..913d300246261bd48ea29813b5c693dcfa4a1404
Binary files /dev/null and b/app/assets/images/emoji/monorail.png differ
diff --git a/app/assets/images/emoji/moon.png b/app/assets/images/emoji/moon.png
new file mode 100755
index 0000000000000000000000000000000000000000..afdb450d1dff9e742955efbb03bef606e1aaba16
Binary files /dev/null and b/app/assets/images/emoji/moon.png differ
diff --git a/app/assets/images/emoji/mortar_board.png b/app/assets/images/emoji/mortar_board.png
new file mode 100755
index 0000000000000000000000000000000000000000..2e811b097a1b7f15bb1558b750d676a9410b7bb3
Binary files /dev/null and b/app/assets/images/emoji/mortar_board.png differ
diff --git a/app/assets/images/emoji/mount_fuji.png b/app/assets/images/emoji/mount_fuji.png
new file mode 100755
index 0000000000000000000000000000000000000000..4c313e583f02754e0b3ffc3ca2a1b208d000de12
Binary files /dev/null and b/app/assets/images/emoji/mount_fuji.png differ
diff --git a/app/assets/images/emoji/mountain_bicyclist.png b/app/assets/images/emoji/mountain_bicyclist.png
new file mode 100755
index 0000000000000000000000000000000000000000..b698897566a33f40ab827c3cec20b7912867f3c5
Binary files /dev/null and b/app/assets/images/emoji/mountain_bicyclist.png differ
diff --git a/app/assets/images/emoji/mountain_cableway.png b/app/assets/images/emoji/mountain_cableway.png
new file mode 100755
index 0000000000000000000000000000000000000000..5688bb239a7411950c9cf0a06c6f7efe3374f2dd
Binary files /dev/null and b/app/assets/images/emoji/mountain_cableway.png differ
diff --git a/app/assets/images/emoji/mountain_railway.png b/app/assets/images/emoji/mountain_railway.png
new file mode 100755
index 0000000000000000000000000000000000000000..1f3d1aab56c9af7ffe317c068161571dd28c1458
Binary files /dev/null and b/app/assets/images/emoji/mountain_railway.png differ
diff --git a/app/assets/images/emoji/mouse.png b/app/assets/images/emoji/mouse.png
new file mode 100755
index 0000000000000000000000000000000000000000..8ff162e2dbb09513aa1acae740710b2ea00b104c
Binary files /dev/null and b/app/assets/images/emoji/mouse.png differ
diff --git a/app/assets/images/emoji/mouse2.png b/app/assets/images/emoji/mouse2.png
new file mode 100755
index 0000000000000000000000000000000000000000..2d777e5e1ac5c9cdf8cb01f53a26112e19d2315a
Binary files /dev/null and b/app/assets/images/emoji/mouse2.png differ
diff --git a/app/assets/images/emoji/movie_camera.png b/app/assets/images/emoji/movie_camera.png
new file mode 100755
index 0000000000000000000000000000000000000000..9c1438409255b3f5211e6c14bf09af71e59743b0
Binary files /dev/null and b/app/assets/images/emoji/movie_camera.png differ
diff --git a/app/assets/images/emoji/moyai.png b/app/assets/images/emoji/moyai.png
new file mode 100755
index 0000000000000000000000000000000000000000..61a1a9c21a4246898e00359ff05123f2ad9f0ebe
Binary files /dev/null and b/app/assets/images/emoji/moyai.png differ
diff --git a/app/assets/images/emoji/muscle.png b/app/assets/images/emoji/muscle.png
new file mode 100755
index 0000000000000000000000000000000000000000..19f92efb66e8220e0d461e670898203084ef0c89
Binary files /dev/null and b/app/assets/images/emoji/muscle.png differ
diff --git a/app/assets/images/emoji/mushroom.png b/app/assets/images/emoji/mushroom.png
new file mode 100755
index 0000000000000000000000000000000000000000..5eeed8e7900e14bdae84de4949541976ec127d54
Binary files /dev/null and b/app/assets/images/emoji/mushroom.png differ
diff --git a/app/assets/images/emoji/musical_keyboard.png b/app/assets/images/emoji/musical_keyboard.png
new file mode 100755
index 0000000000000000000000000000000000000000..93647a4a32d9f967020c63e11c80380311c825e4
Binary files /dev/null and b/app/assets/images/emoji/musical_keyboard.png differ
diff --git a/app/assets/images/emoji/musical_note.png b/app/assets/images/emoji/musical_note.png
new file mode 100755
index 0000000000000000000000000000000000000000..68b261bcba6db5a4f20de1ba33f1d8dd95b3ab33
Binary files /dev/null and b/app/assets/images/emoji/musical_note.png differ
diff --git a/app/assets/images/emoji/musical_score.png b/app/assets/images/emoji/musical_score.png
new file mode 100755
index 0000000000000000000000000000000000000000..0c927d32fa43c5ec7cf8b9092069cdd23c41a62a
Binary files /dev/null and b/app/assets/images/emoji/musical_score.png differ
diff --git a/app/assets/images/emoji/mute.png b/app/assets/images/emoji/mute.png
new file mode 100755
index 0000000000000000000000000000000000000000..4cf67c367d366b60a3ae4a7aaeeee0674ddb16c7
Binary files /dev/null and b/app/assets/images/emoji/mute.png differ
diff --git a/app/assets/images/emoji/nail_care.png b/app/assets/images/emoji/nail_care.png
new file mode 100755
index 0000000000000000000000000000000000000000..6a66e63d2adb572ef0bee6a588d51f5ef2c70d29
Binary files /dev/null and b/app/assets/images/emoji/nail_care.png differ
diff --git a/app/assets/images/emoji/name_badge.png b/app/assets/images/emoji/name_badge.png
new file mode 100755
index 0000000000000000000000000000000000000000..2b712dcd55ac1be241aa4869a4eb7addbb52b84b
Binary files /dev/null and b/app/assets/images/emoji/name_badge.png differ
diff --git a/app/assets/images/emoji/neckbeard.png b/app/assets/images/emoji/neckbeard.png
new file mode 100755
index 0000000000000000000000000000000000000000..15108fc97da211162df37b5361f153a6701a1440
Binary files /dev/null and b/app/assets/images/emoji/neckbeard.png differ
diff --git a/app/assets/images/emoji/necktie.png b/app/assets/images/emoji/necktie.png
new file mode 100755
index 0000000000000000000000000000000000000000..80461c66f3a087c1f67d66b831b39bdf39eebaf6
Binary files /dev/null and b/app/assets/images/emoji/necktie.png differ
diff --git a/app/assets/images/emoji/negative_squared_cross_mark.png b/app/assets/images/emoji/negative_squared_cross_mark.png
new file mode 100755
index 0000000000000000000000000000000000000000..b47a0cece5c9608953ff98cd6eeb1f60bb72153e
Binary files /dev/null and b/app/assets/images/emoji/negative_squared_cross_mark.png differ
diff --git a/app/assets/images/emoji/neutral_face.png b/app/assets/images/emoji/neutral_face.png
new file mode 100755
index 0000000000000000000000000000000000000000..682a1ba066d8526f94fec4af76ca7fb83d0f0d8f
Binary files /dev/null and b/app/assets/images/emoji/neutral_face.png differ
diff --git a/app/assets/images/emoji/new.png b/app/assets/images/emoji/new.png
new file mode 100755
index 0000000000000000000000000000000000000000..28d1570e0a6fdbdb2b9138ff01009a6d193e1f89
Binary files /dev/null and b/app/assets/images/emoji/new.png differ
diff --git a/app/assets/images/emoji/new_moon.png b/app/assets/images/emoji/new_moon.png
new file mode 100755
index 0000000000000000000000000000000000000000..540239b1f3e1290f033d6c29a556259f6dc3c4c0
Binary files /dev/null and b/app/assets/images/emoji/new_moon.png differ
diff --git a/app/assets/images/emoji/new_moon_with_face.png b/app/assets/images/emoji/new_moon_with_face.png
new file mode 100755
index 0000000000000000000000000000000000000000..b9aff7a06831e41c7c715bda035297619294ea43
Binary files /dev/null and b/app/assets/images/emoji/new_moon_with_face.png differ
diff --git a/app/assets/images/emoji/newspaper.png b/app/assets/images/emoji/newspaper.png
new file mode 100755
index 0000000000000000000000000000000000000000..d171394e6a81cd3dcaf1e34fc6f571e53f17ff07
Binary files /dev/null and b/app/assets/images/emoji/newspaper.png differ
diff --git a/app/assets/images/emoji/ng.png b/app/assets/images/emoji/ng.png
new file mode 100755
index 0000000000000000000000000000000000000000..2ca180ae397ac5c12d5be7d481957e5a3834a7e8
Binary files /dev/null and b/app/assets/images/emoji/ng.png differ
diff --git a/app/assets/images/emoji/nine.png b/app/assets/images/emoji/nine.png
new file mode 100755
index 0000000000000000000000000000000000000000..8006cc909f35f5fc9ecd5722cb197d03f1e9f1c7
Binary files /dev/null and b/app/assets/images/emoji/nine.png differ
diff --git a/app/assets/images/emoji/no_bell.png b/app/assets/images/emoji/no_bell.png
new file mode 100755
index 0000000000000000000000000000000000000000..613b81cd21eb4816aabaa082b3b4979bea6d0802
Binary files /dev/null and b/app/assets/images/emoji/no_bell.png differ
diff --git a/app/assets/images/emoji/no_bicycles.png b/app/assets/images/emoji/no_bicycles.png
new file mode 100755
index 0000000000000000000000000000000000000000..4b2621664551902ff88f24fabe7f2fa4f32a5be6
Binary files /dev/null and b/app/assets/images/emoji/no_bicycles.png differ
diff --git a/app/assets/images/emoji/no_entry.png b/app/assets/images/emoji/no_entry.png
new file mode 100755
index 0000000000000000000000000000000000000000..cf2086a8e7470f33d323705e9ec3e54f8b3350ca
Binary files /dev/null and b/app/assets/images/emoji/no_entry.png differ
diff --git a/app/assets/images/emoji/no_entry_sign.png b/app/assets/images/emoji/no_entry_sign.png
new file mode 100755
index 0000000000000000000000000000000000000000..a8444d18d2a3e8d68e4aa24cfda2499a618e42e0
Binary files /dev/null and b/app/assets/images/emoji/no_entry_sign.png differ
diff --git a/app/assets/images/emoji/no_good.png b/app/assets/images/emoji/no_good.png
new file mode 100755
index 0000000000000000000000000000000000000000..d459a35bc1f462c1d830f993abda44b1bb584a9e
Binary files /dev/null and b/app/assets/images/emoji/no_good.png differ
diff --git a/app/assets/images/emoji/no_mobile_phones.png b/app/assets/images/emoji/no_mobile_phones.png
new file mode 100755
index 0000000000000000000000000000000000000000..41df57cf827e44fda8123082612713ce8cf573bb
Binary files /dev/null and b/app/assets/images/emoji/no_mobile_phones.png differ
diff --git a/app/assets/images/emoji/no_mouth.png b/app/assets/images/emoji/no_mouth.png
new file mode 100755
index 0000000000000000000000000000000000000000..d9ec7ca7d7938ad2002b81a3cd12f0ecb02fc963
Binary files /dev/null and b/app/assets/images/emoji/no_mouth.png differ
diff --git a/app/assets/images/emoji/no_pedestrians.png b/app/assets/images/emoji/no_pedestrians.png
new file mode 100755
index 0000000000000000000000000000000000000000..c35f530b22095e0ae4387dec8a1d7aef549077a3
Binary files /dev/null and b/app/assets/images/emoji/no_pedestrians.png differ
diff --git a/app/assets/images/emoji/no_smoking.png b/app/assets/images/emoji/no_smoking.png
new file mode 100755
index 0000000000000000000000000000000000000000..5880ddfd18897946a5da38910eb2325c90acffce
Binary files /dev/null and b/app/assets/images/emoji/no_smoking.png differ
diff --git a/app/assets/images/emoji/non-potable_water.png b/app/assets/images/emoji/non-potable_water.png
new file mode 100755
index 0000000000000000000000000000000000000000..1b29d35b98b45e6c394c61d0a1e3f76888b658cf
Binary files /dev/null and b/app/assets/images/emoji/non-potable_water.png differ
diff --git a/app/assets/images/emoji/nose.png b/app/assets/images/emoji/nose.png
new file mode 100755
index 0000000000000000000000000000000000000000..ad17c16c29eb60604aefac1705e4a23a542826b9
Binary files /dev/null and b/app/assets/images/emoji/nose.png differ
diff --git a/app/assets/images/emoji/notebook.png b/app/assets/images/emoji/notebook.png
new file mode 100755
index 0000000000000000000000000000000000000000..07ea6087ed4e252a198dced1ab374b0cec024a47
Binary files /dev/null and b/app/assets/images/emoji/notebook.png differ
diff --git a/app/assets/images/emoji/notebook_with_decorative_cover.png b/app/assets/images/emoji/notebook_with_decorative_cover.png
new file mode 100755
index 0000000000000000000000000000000000000000..4f3b14c85f33fd602150d5338a94c75bc8a7f338
Binary files /dev/null and b/app/assets/images/emoji/notebook_with_decorative_cover.png differ
diff --git a/app/assets/images/emoji/notes.png b/app/assets/images/emoji/notes.png
new file mode 100755
index 0000000000000000000000000000000000000000..0956d6ab2a83d1e8b30478102148dc22c5dab9e3
Binary files /dev/null and b/app/assets/images/emoji/notes.png differ
diff --git a/app/assets/images/emoji/nut_and_bolt.png b/app/assets/images/emoji/nut_and_bolt.png
new file mode 100755
index 0000000000000000000000000000000000000000..bddfa72a7d3b82384faf011ac15f95182c41af9e
Binary files /dev/null and b/app/assets/images/emoji/nut_and_bolt.png differ
diff --git a/app/assets/images/emoji/o.png b/app/assets/images/emoji/o.png
new file mode 100755
index 0000000000000000000000000000000000000000..0ededebe31284207489693cf0e781f9e4c402a6c
Binary files /dev/null and b/app/assets/images/emoji/o.png differ
diff --git a/app/assets/images/emoji/o2.png b/app/assets/images/emoji/o2.png
new file mode 100755
index 0000000000000000000000000000000000000000..d85f9fb98c7763d87db79971db65d49d39ae8806
Binary files /dev/null and b/app/assets/images/emoji/o2.png differ
diff --git a/app/assets/images/emoji/ocean.png b/app/assets/images/emoji/ocean.png
new file mode 100755
index 0000000000000000000000000000000000000000..f8d520cd49018adb042f879aba0466ca50843960
Binary files /dev/null and b/app/assets/images/emoji/ocean.png differ
diff --git a/app/assets/images/emoji/octocat.png b/app/assets/images/emoji/octocat.png
new file mode 100755
index 0000000000000000000000000000000000000000..3fc20503e9055727367dd2a79cd579b8ccff222d
Binary files /dev/null and b/app/assets/images/emoji/octocat.png differ
diff --git a/app/assets/images/emoji/octopus.png b/app/assets/images/emoji/octopus.png
new file mode 100755
index 0000000000000000000000000000000000000000..52ce64b46879ac282918695007cbf8b3f2bb3783
Binary files /dev/null and b/app/assets/images/emoji/octopus.png differ
diff --git a/app/assets/images/emoji/oden.png b/app/assets/images/emoji/oden.png
new file mode 100755
index 0000000000000000000000000000000000000000..73add1c73cfa766f29e2314d4ebd61c4ca051f31
Binary files /dev/null and b/app/assets/images/emoji/oden.png differ
diff --git a/app/assets/images/emoji/office.png b/app/assets/images/emoji/office.png
new file mode 100755
index 0000000000000000000000000000000000000000..ea9281a413d754cbed8ed20d4815bc7f08bb0f59
Binary files /dev/null and b/app/assets/images/emoji/office.png differ
diff --git a/app/assets/images/emoji/ok.png b/app/assets/images/emoji/ok.png
new file mode 100755
index 0000000000000000000000000000000000000000..6433d1a90a91d05fe34e6b9331d4d69e0302cf93
Binary files /dev/null and b/app/assets/images/emoji/ok.png differ
diff --git a/app/assets/images/emoji/ok_hand.png b/app/assets/images/emoji/ok_hand.png
new file mode 100755
index 0000000000000000000000000000000000000000..80c5aebb68091298f8995abba5e81e095938be25
Binary files /dev/null and b/app/assets/images/emoji/ok_hand.png differ
diff --git a/app/assets/images/emoji/ok_woman.png b/app/assets/images/emoji/ok_woman.png
new file mode 100755
index 0000000000000000000000000000000000000000..e8b98194edbf33071c1e0a445ba16b0243e8f65f
Binary files /dev/null and b/app/assets/images/emoji/ok_woman.png differ
diff --git a/app/assets/images/emoji/older_man.png b/app/assets/images/emoji/older_man.png
new file mode 100755
index 0000000000000000000000000000000000000000..149f0cfb8e132a709d353d7e24130e0085371b15
Binary files /dev/null and b/app/assets/images/emoji/older_man.png differ
diff --git a/app/assets/images/emoji/older_woman.png b/app/assets/images/emoji/older_woman.png
new file mode 100755
index 0000000000000000000000000000000000000000..f839565f478d5889125f05b0b6e4749006be5b99
Binary files /dev/null and b/app/assets/images/emoji/older_woman.png differ
diff --git a/app/assets/images/emoji/on.png b/app/assets/images/emoji/on.png
new file mode 100755
index 0000000000000000000000000000000000000000..3595387fb63292d20f0b515fe20de16d4f1400bc
Binary files /dev/null and b/app/assets/images/emoji/on.png differ
diff --git a/app/assets/images/emoji/oncoming_automobile.png b/app/assets/images/emoji/oncoming_automobile.png
new file mode 100755
index 0000000000000000000000000000000000000000..cb46de22cbbf544055f4fae8ff90624488420aef
Binary files /dev/null and b/app/assets/images/emoji/oncoming_automobile.png differ
diff --git a/app/assets/images/emoji/oncoming_bus.png b/app/assets/images/emoji/oncoming_bus.png
new file mode 100755
index 0000000000000000000000000000000000000000..3695f762353f05c80466f41673a45239196cc4e8
Binary files /dev/null and b/app/assets/images/emoji/oncoming_bus.png differ
diff --git a/app/assets/images/emoji/oncoming_police_car.png b/app/assets/images/emoji/oncoming_police_car.png
new file mode 100755
index 0000000000000000000000000000000000000000..af20e7eff03422580d2ddd045027c626bfc7ff1a
Binary files /dev/null and b/app/assets/images/emoji/oncoming_police_car.png differ
diff --git a/app/assets/images/emoji/oncoming_taxi.png b/app/assets/images/emoji/oncoming_taxi.png
new file mode 100755
index 0000000000000000000000000000000000000000..f78cf3103b8e3b6937a2e47430bd216880843d2e
Binary files /dev/null and b/app/assets/images/emoji/oncoming_taxi.png differ
diff --git a/app/assets/images/emoji/one.png b/app/assets/images/emoji/one.png
new file mode 100755
index 0000000000000000000000000000000000000000..2d1f9f8c49d7698fc333bcf023ec3a0376ef367a
Binary files /dev/null and b/app/assets/images/emoji/one.png differ
diff --git a/app/assets/images/emoji/open_file_folder.png b/app/assets/images/emoji/open_file_folder.png
new file mode 100755
index 0000000000000000000000000000000000000000..2bbbbf5e7cd63e53726d1acd25c07eaa1a6b0803
Binary files /dev/null and b/app/assets/images/emoji/open_file_folder.png differ
diff --git a/app/assets/images/emoji/open_hands.png b/app/assets/images/emoji/open_hands.png
new file mode 100755
index 0000000000000000000000000000000000000000..2cc25bd41a4739c6cf7002857e3ac2591e0383d9
Binary files /dev/null and b/app/assets/images/emoji/open_hands.png differ
diff --git a/app/assets/images/emoji/ophiuchus.png b/app/assets/images/emoji/ophiuchus.png
new file mode 100755
index 0000000000000000000000000000000000000000..4eef715bc28ef474baac0025f704e330112651ca
Binary files /dev/null and b/app/assets/images/emoji/ophiuchus.png differ
diff --git a/app/assets/images/emoji/orange_book.png b/app/assets/images/emoji/orange_book.png
new file mode 100755
index 0000000000000000000000000000000000000000..49650d59e598a330323eb3fa90211e2689adedb0
Binary files /dev/null and b/app/assets/images/emoji/orange_book.png differ
diff --git a/app/assets/images/emoji/outbox_tray.png b/app/assets/images/emoji/outbox_tray.png
new file mode 100755
index 0000000000000000000000000000000000000000..7ad15e649de070daf071f76d4f7452a66bd82e52
Binary files /dev/null and b/app/assets/images/emoji/outbox_tray.png differ
diff --git a/app/assets/images/emoji/ox.png b/app/assets/images/emoji/ox.png
new file mode 100755
index 0000000000000000000000000000000000000000..f7669802480b39883c1c405ea757b91daa538e80
Binary files /dev/null and b/app/assets/images/emoji/ox.png differ
diff --git a/app/assets/images/emoji/page_facing_up.png b/app/assets/images/emoji/page_facing_up.png
new file mode 100755
index 0000000000000000000000000000000000000000..64cd2e1b2a24cd26586e26fa87a33cb631df68d0
Binary files /dev/null and b/app/assets/images/emoji/page_facing_up.png differ
diff --git a/app/assets/images/emoji/page_with_curl.png b/app/assets/images/emoji/page_with_curl.png
new file mode 100755
index 0000000000000000000000000000000000000000..bf8f979d31c2751549f4ba5a6fa8cd9efd428653
Binary files /dev/null and b/app/assets/images/emoji/page_with_curl.png differ
diff --git a/app/assets/images/emoji/pager.png b/app/assets/images/emoji/pager.png
new file mode 100755
index 0000000000000000000000000000000000000000..e3e1fc44ee5eac6241a6fca608f00292f3e912c4
Binary files /dev/null and b/app/assets/images/emoji/pager.png differ
diff --git a/app/assets/images/emoji/palm_tree.png b/app/assets/images/emoji/palm_tree.png
new file mode 100755
index 0000000000000000000000000000000000000000..d534785ef96a75b185ca81bd61e691a993124224
Binary files /dev/null and b/app/assets/images/emoji/palm_tree.png differ
diff --git a/app/assets/images/emoji/panda_face.png b/app/assets/images/emoji/panda_face.png
new file mode 100755
index 0000000000000000000000000000000000000000..a794fb17f677b487e8d20b1237349512df3e159e
Binary files /dev/null and b/app/assets/images/emoji/panda_face.png differ
diff --git a/app/assets/images/emoji/paperclip.png b/app/assets/images/emoji/paperclip.png
new file mode 100755
index 0000000000000000000000000000000000000000..774412dc10f75e5c114073af9c3ac1c2b08b19a7
Binary files /dev/null and b/app/assets/images/emoji/paperclip.png differ
diff --git a/app/assets/images/emoji/parking.png b/app/assets/images/emoji/parking.png
new file mode 100755
index 0000000000000000000000000000000000000000..c24af81ccf6b07f74ae25a2a77f80cb161c46cfa
Binary files /dev/null and b/app/assets/images/emoji/parking.png differ
diff --git a/app/assets/images/emoji/part_alternation_mark.png b/app/assets/images/emoji/part_alternation_mark.png
new file mode 100755
index 0000000000000000000000000000000000000000..45dc9b851a123ea90fe39f4c7219c9205ea07326
Binary files /dev/null and b/app/assets/images/emoji/part_alternation_mark.png differ
diff --git a/app/assets/images/emoji/partly_sunny.png b/app/assets/images/emoji/partly_sunny.png
new file mode 100755
index 0000000000000000000000000000000000000000..020dd5ff69886f4fbbd5bbb4f2bb907f51760437
Binary files /dev/null and b/app/assets/images/emoji/partly_sunny.png differ
diff --git a/app/assets/images/emoji/passport_control.png b/app/assets/images/emoji/passport_control.png
new file mode 100755
index 0000000000000000000000000000000000000000..675b76d378cd498a1c9b073ca0e999b2acefcaaa
Binary files /dev/null and b/app/assets/images/emoji/passport_control.png differ
diff --git a/app/assets/images/emoji/paw_prints.png b/app/assets/images/emoji/paw_prints.png
new file mode 100755
index 0000000000000000000000000000000000000000..89b9fec9efac16d86556d666309b9730666f0a7d
Binary files /dev/null and b/app/assets/images/emoji/paw_prints.png differ
diff --git a/app/assets/images/emoji/peach.png b/app/assets/images/emoji/peach.png
new file mode 100755
index 0000000000000000000000000000000000000000..ee2139ecb884f0a39fe41aee800a1b2b3b94c574
Binary files /dev/null and b/app/assets/images/emoji/peach.png differ
diff --git a/app/assets/images/emoji/pear.png b/app/assets/images/emoji/pear.png
new file mode 100755
index 0000000000000000000000000000000000000000..f24aca8c0a8679992d680951eba831b9740843df
Binary files /dev/null and b/app/assets/images/emoji/pear.png differ
diff --git a/app/assets/images/emoji/pencil.png b/app/assets/images/emoji/pencil.png
new file mode 100755
index 0000000000000000000000000000000000000000..fc97ddbc92b0af4590d3d552bd771fd8d011828c
Binary files /dev/null and b/app/assets/images/emoji/pencil.png differ
diff --git a/app/assets/images/emoji/pencil2.png b/app/assets/images/emoji/pencil2.png
new file mode 100755
index 0000000000000000000000000000000000000000..e624373b4913017959d0711bb14633077403cec5
Binary files /dev/null and b/app/assets/images/emoji/pencil2.png differ
diff --git a/app/assets/images/emoji/penguin.png b/app/assets/images/emoji/penguin.png
new file mode 100755
index 0000000000000000000000000000000000000000..d8edbcb8fa9115a6f3e8c544c3ba5050c1d9b170
Binary files /dev/null and b/app/assets/images/emoji/penguin.png differ
diff --git a/app/assets/images/emoji/pensive.png b/app/assets/images/emoji/pensive.png
new file mode 100755
index 0000000000000000000000000000000000000000..4159f3c42ff0511a839076185ded2cacf4bc3f49
Binary files /dev/null and b/app/assets/images/emoji/pensive.png differ
diff --git a/app/assets/images/emoji/performing_arts.png b/app/assets/images/emoji/performing_arts.png
new file mode 100755
index 0000000000000000000000000000000000000000..899fbe5a7919025f9874440918a519bc654b0679
Binary files /dev/null and b/app/assets/images/emoji/performing_arts.png differ
diff --git a/app/assets/images/emoji/persevere.png b/app/assets/images/emoji/persevere.png
new file mode 100755
index 0000000000000000000000000000000000000000..f99f6da47c18dfe21bd7344d2522d3f60b4510d8
Binary files /dev/null and b/app/assets/images/emoji/persevere.png differ
diff --git a/app/assets/images/emoji/person_frowning.png b/app/assets/images/emoji/person_frowning.png
new file mode 100755
index 0000000000000000000000000000000000000000..6f34d5e159df433d493c57a427ff5a23f566b796
Binary files /dev/null and b/app/assets/images/emoji/person_frowning.png differ
diff --git a/app/assets/images/emoji/person_with_blond_hair.png b/app/assets/images/emoji/person_with_blond_hair.png
new file mode 100755
index 0000000000000000000000000000000000000000..c144301cbb8ee5634916231c06b7e65f963e70b7
Binary files /dev/null and b/app/assets/images/emoji/person_with_blond_hair.png differ
diff --git a/app/assets/images/emoji/person_with_pouting_face.png b/app/assets/images/emoji/person_with_pouting_face.png
new file mode 100755
index 0000000000000000000000000000000000000000..c4a95c3b2a2b10e60c565d173eb7cee4921b859f
Binary files /dev/null and b/app/assets/images/emoji/person_with_pouting_face.png differ
diff --git a/app/assets/images/emoji/phone.png b/app/assets/images/emoji/phone.png
new file mode 100755
index 0000000000000000000000000000000000000000..87d2559b55256935f097f9be4aea134a0800e099
Binary files /dev/null and b/app/assets/images/emoji/phone.png differ
diff --git a/app/assets/images/emoji/pig.png b/app/assets/images/emoji/pig.png
new file mode 100755
index 0000000000000000000000000000000000000000..f7f273c733b0255a6d3fbcbf1422c656d9326a12
Binary files /dev/null and b/app/assets/images/emoji/pig.png differ
diff --git a/app/assets/images/emoji/pig2.png b/app/assets/images/emoji/pig2.png
new file mode 100755
index 0000000000000000000000000000000000000000..fec3374d7096996be28e2be16931f5c3bd493291
Binary files /dev/null and b/app/assets/images/emoji/pig2.png differ
diff --git a/app/assets/images/emoji/pig_nose.png b/app/assets/images/emoji/pig_nose.png
new file mode 100755
index 0000000000000000000000000000000000000000..38d612446eb39e29ffd8c6312cd02a8936e360bc
Binary files /dev/null and b/app/assets/images/emoji/pig_nose.png differ
diff --git a/app/assets/images/emoji/pill.png b/app/assets/images/emoji/pill.png
new file mode 100755
index 0000000000000000000000000000000000000000..cd84a78ff75b02b4811b09704e6eeea41f1981a5
Binary files /dev/null and b/app/assets/images/emoji/pill.png differ
diff --git a/app/assets/images/emoji/pineapple.png b/app/assets/images/emoji/pineapple.png
new file mode 100755
index 0000000000000000000000000000000000000000..d6f8e28769287d169cf8a8640c4af9a575039d77
Binary files /dev/null and b/app/assets/images/emoji/pineapple.png differ
diff --git a/app/assets/images/emoji/pisces.png b/app/assets/images/emoji/pisces.png
new file mode 100755
index 0000000000000000000000000000000000000000..5a2da0a0599cdce96337ab16486002154461edef
Binary files /dev/null and b/app/assets/images/emoji/pisces.png differ
diff --git a/app/assets/images/emoji/pizza.png b/app/assets/images/emoji/pizza.png
new file mode 100755
index 0000000000000000000000000000000000000000..460367d02cd70cca7f4ab509bcf4a145d7e895e6
Binary files /dev/null and b/app/assets/images/emoji/pizza.png differ
diff --git a/app/assets/images/emoji/plus1.png b/app/assets/images/emoji/plus1.png
new file mode 100755
index 0000000000000000000000000000000000000000..81786c1d8f5ed810fd8351f74996f9b64dbf5ffb
Binary files /dev/null and b/app/assets/images/emoji/plus1.png differ
diff --git a/app/assets/images/emoji/point_down.png b/app/assets/images/emoji/point_down.png
new file mode 100755
index 0000000000000000000000000000000000000000..658c6d91875c8d13a3be0a9785238586133c436f
Binary files /dev/null and b/app/assets/images/emoji/point_down.png differ
diff --git a/app/assets/images/emoji/point_left.png b/app/assets/images/emoji/point_left.png
new file mode 100755
index 0000000000000000000000000000000000000000..38a99b43f7f3fb2bae43bca0ea80abbae1485d79
Binary files /dev/null and b/app/assets/images/emoji/point_left.png differ
diff --git a/app/assets/images/emoji/point_right.png b/app/assets/images/emoji/point_right.png
new file mode 100755
index 0000000000000000000000000000000000000000..6f9f029a420f06dadd6f66b04801771b4f92c48f
Binary files /dev/null and b/app/assets/images/emoji/point_right.png differ
diff --git a/app/assets/images/emoji/point_up.png b/app/assets/images/emoji/point_up.png
new file mode 100755
index 0000000000000000000000000000000000000000..01896e214aaa68dc307a2f9bea3fc3142f593494
Binary files /dev/null and b/app/assets/images/emoji/point_up.png differ
diff --git a/app/assets/images/emoji/point_up_2.png b/app/assets/images/emoji/point_up_2.png
new file mode 100755
index 0000000000000000000000000000000000000000..1cfe73672c0c48159a60bc287c5705f19ac4d873
Binary files /dev/null and b/app/assets/images/emoji/point_up_2.png differ
diff --git a/app/assets/images/emoji/police_car.png b/app/assets/images/emoji/police_car.png
new file mode 100755
index 0000000000000000000000000000000000000000..b8f17275ee16b155a5c8e1b3b6ea1c3d018051d4
Binary files /dev/null and b/app/assets/images/emoji/police_car.png differ
diff --git a/app/assets/images/emoji/poodle.png b/app/assets/images/emoji/poodle.png
new file mode 100755
index 0000000000000000000000000000000000000000..adac80bd97ad54de91b813874bb45bddc91cba75
Binary files /dev/null and b/app/assets/images/emoji/poodle.png differ
diff --git a/app/assets/images/emoji/poop.png b/app/assets/images/emoji/poop.png
new file mode 100755
index 0000000000000000000000000000000000000000..73a4dc840085c7f42c7464d827751348b58acfba
Binary files /dev/null and b/app/assets/images/emoji/poop.png differ
diff --git a/app/assets/images/emoji/post_office.png b/app/assets/images/emoji/post_office.png
new file mode 100755
index 0000000000000000000000000000000000000000..43b59e30ec2bb655c8b5229aabe25e8afcec6a63
Binary files /dev/null and b/app/assets/images/emoji/post_office.png differ
diff --git a/app/assets/images/emoji/postal_horn.png b/app/assets/images/emoji/postal_horn.png
new file mode 100755
index 0000000000000000000000000000000000000000..e9b713bbeca31aa0dbcf741d7011b8aad32e9b85
Binary files /dev/null and b/app/assets/images/emoji/postal_horn.png differ
diff --git a/app/assets/images/emoji/postbox.png b/app/assets/images/emoji/postbox.png
new file mode 100755
index 0000000000000000000000000000000000000000..ce04b7008ba911ec11299d8e1504a6872a606b24
Binary files /dev/null and b/app/assets/images/emoji/postbox.png differ
diff --git a/app/assets/images/emoji/potable_water.png b/app/assets/images/emoji/potable_water.png
new file mode 100755
index 0000000000000000000000000000000000000000..e9fd56079ca59aae56a8f5ef1d86cb8479f97116
Binary files /dev/null and b/app/assets/images/emoji/potable_water.png differ
diff --git a/app/assets/images/emoji/pouch.png b/app/assets/images/emoji/pouch.png
new file mode 100755
index 0000000000000000000000000000000000000000..0bc5879fcbb8db49f17b40af3691d4752a6c82bf
Binary files /dev/null and b/app/assets/images/emoji/pouch.png differ
diff --git a/app/assets/images/emoji/poultry_leg.png b/app/assets/images/emoji/poultry_leg.png
new file mode 100755
index 0000000000000000000000000000000000000000..43ad8596518e8102620b4ed8bf6a22250b1170fe
Binary files /dev/null and b/app/assets/images/emoji/poultry_leg.png differ
diff --git a/app/assets/images/emoji/pound.png b/app/assets/images/emoji/pound.png
new file mode 100755
index 0000000000000000000000000000000000000000..f8be91d7a4b68bdc84f4d374c16b27b6b1f8f982
Binary files /dev/null and b/app/assets/images/emoji/pound.png differ
diff --git a/app/assets/images/emoji/pouting_cat.png b/app/assets/images/emoji/pouting_cat.png
new file mode 100755
index 0000000000000000000000000000000000000000..4325fd48dd7e5aa0fc9be53991ee9526975c1e56
Binary files /dev/null and b/app/assets/images/emoji/pouting_cat.png differ
diff --git a/app/assets/images/emoji/pray.png b/app/assets/images/emoji/pray.png
new file mode 100755
index 0000000000000000000000000000000000000000..f86c992d5a7a086c52fc373803eff8d38a44eeaf
Binary files /dev/null and b/app/assets/images/emoji/pray.png differ
diff --git a/app/assets/images/emoji/princess.png b/app/assets/images/emoji/princess.png
new file mode 100755
index 0000000000000000000000000000000000000000..1ebb2ce9b13e9ec415872e9a123d4471cd17e5bd
Binary files /dev/null and b/app/assets/images/emoji/princess.png differ
diff --git a/app/assets/images/emoji/punch.png b/app/assets/images/emoji/punch.png
new file mode 100755
index 0000000000000000000000000000000000000000..277047b7c460cf2532412c6fbe66e172fb13e13b
Binary files /dev/null and b/app/assets/images/emoji/punch.png differ
diff --git a/app/assets/images/emoji/purple_heart.png b/app/assets/images/emoji/purple_heart.png
new file mode 100755
index 0000000000000000000000000000000000000000..d5f875043f00db01084fb1df635120e286bcab83
Binary files /dev/null and b/app/assets/images/emoji/purple_heart.png differ
diff --git a/app/assets/images/emoji/purse.png b/app/assets/images/emoji/purse.png
new file mode 100755
index 0000000000000000000000000000000000000000..8f06a2b932c55f7bf77168af46dba3c2baa3ba8e
Binary files /dev/null and b/app/assets/images/emoji/purse.png differ
diff --git a/app/assets/images/emoji/pushpin.png b/app/assets/images/emoji/pushpin.png
new file mode 100755
index 0000000000000000000000000000000000000000..540c4ecb885c4c28c9f67a98d6bfea6d33affc01
Binary files /dev/null and b/app/assets/images/emoji/pushpin.png differ
diff --git a/app/assets/images/emoji/put_litter_in_its_place.png b/app/assets/images/emoji/put_litter_in_its_place.png
new file mode 100755
index 0000000000000000000000000000000000000000..c2e350c2dc6b7ce3fa277ad51b11426643c13405
Binary files /dev/null and b/app/assets/images/emoji/put_litter_in_its_place.png differ
diff --git a/app/assets/images/emoji/question.png b/app/assets/images/emoji/question.png
new file mode 100755
index 0000000000000000000000000000000000000000..38cedf560fb5b16ba5605f351fa5dc2cf4020158
Binary files /dev/null and b/app/assets/images/emoji/question.png differ
diff --git a/app/assets/images/emoji/rabbit.png b/app/assets/images/emoji/rabbit.png
new file mode 100755
index 0000000000000000000000000000000000000000..5cb3ef6f0c6a49c648661eebd66ba2b02fe6fd1f
Binary files /dev/null and b/app/assets/images/emoji/rabbit.png differ
diff --git a/app/assets/images/emoji/rabbit2.png b/app/assets/images/emoji/rabbit2.png
new file mode 100755
index 0000000000000000000000000000000000000000..5bc993e799cb6d9e884acf0d9cf4bb822bc484ea
Binary files /dev/null and b/app/assets/images/emoji/rabbit2.png differ
diff --git a/app/assets/images/emoji/racehorse.png b/app/assets/images/emoji/racehorse.png
new file mode 100755
index 0000000000000000000000000000000000000000..4d09c64de7e1036c03827a24b28d346691d460af
Binary files /dev/null and b/app/assets/images/emoji/racehorse.png differ
diff --git a/app/assets/images/emoji/radio.png b/app/assets/images/emoji/radio.png
new file mode 100755
index 0000000000000000000000000000000000000000..ea589efe32cde0bdae7ae71d4c0c4f43a4b9f5cc
Binary files /dev/null and b/app/assets/images/emoji/radio.png differ
diff --git a/app/assets/images/emoji/radio_button.png b/app/assets/images/emoji/radio_button.png
new file mode 100755
index 0000000000000000000000000000000000000000..63755eec258a2de526b4f1fc025646d34fe96923
Binary files /dev/null and b/app/assets/images/emoji/radio_button.png differ
diff --git a/app/assets/images/emoji/rage.png b/app/assets/images/emoji/rage.png
new file mode 100755
index 0000000000000000000000000000000000000000..c65ddff552a9d58e30e2463ccce112c09ed3ad89
Binary files /dev/null and b/app/assets/images/emoji/rage.png differ
diff --git a/app/assets/images/emoji/rage1.png b/app/assets/images/emoji/rage1.png
new file mode 100755
index 0000000000000000000000000000000000000000..1506ba4032a549e9cb95ecb0b8767be3454d40bc
Binary files /dev/null and b/app/assets/images/emoji/rage1.png differ
diff --git a/app/assets/images/emoji/rage2.png b/app/assets/images/emoji/rage2.png
new file mode 100755
index 0000000000000000000000000000000000000000..f792e063b49c70f2e3bdf2bc3ed3ab233c205190
Binary files /dev/null and b/app/assets/images/emoji/rage2.png differ
diff --git a/app/assets/images/emoji/rage3.png b/app/assets/images/emoji/rage3.png
new file mode 100755
index 0000000000000000000000000000000000000000..58764cbcb3bcbfc88fab9ae50e5a47679494f79e
Binary files /dev/null and b/app/assets/images/emoji/rage3.png differ
diff --git a/app/assets/images/emoji/rage4.png b/app/assets/images/emoji/rage4.png
new file mode 100755
index 0000000000000000000000000000000000000000..c726c94a295f57a22d7af38b53e68a31a15b0176
Binary files /dev/null and b/app/assets/images/emoji/rage4.png differ
diff --git a/app/assets/images/emoji/railway_car.png b/app/assets/images/emoji/railway_car.png
new file mode 100755
index 0000000000000000000000000000000000000000..22361158fb3a6749ff3bd6d33cc9fa2ff0a48cd7
Binary files /dev/null and b/app/assets/images/emoji/railway_car.png differ
diff --git a/app/assets/images/emoji/rainbow.png b/app/assets/images/emoji/rainbow.png
new file mode 100755
index 0000000000000000000000000000000000000000..6b1faa0379326da692fdc7bb1cdc27c82987e166
Binary files /dev/null and b/app/assets/images/emoji/rainbow.png differ
diff --git a/app/assets/images/emoji/raised_hand.png b/app/assets/images/emoji/raised_hand.png
new file mode 100755
index 0000000000000000000000000000000000000000..e1741a40e7431a704247b0e3d00480889113b6fe
Binary files /dev/null and b/app/assets/images/emoji/raised_hand.png differ
diff --git a/app/assets/images/emoji/raised_hands.png b/app/assets/images/emoji/raised_hands.png
new file mode 100755
index 0000000000000000000000000000000000000000..e03142bdce92e3088e5a521f4ca6ec2b2ed33cfa
Binary files /dev/null and b/app/assets/images/emoji/raised_hands.png differ
diff --git a/app/assets/images/emoji/ram.png b/app/assets/images/emoji/ram.png
new file mode 100755
index 0000000000000000000000000000000000000000..5ea7bfbc0d845c6ddc1850cb1957c83b22254060
Binary files /dev/null and b/app/assets/images/emoji/ram.png differ
diff --git a/app/assets/images/emoji/ramen.png b/app/assets/images/emoji/ramen.png
new file mode 100755
index 0000000000000000000000000000000000000000..78dc7d537fb320a022c7dd5a53cb62b016a9acd4
Binary files /dev/null and b/app/assets/images/emoji/ramen.png differ
diff --git a/app/assets/images/emoji/rat.png b/app/assets/images/emoji/rat.png
new file mode 100755
index 0000000000000000000000000000000000000000..1c463dfde641fc9877cbd360f9dc10e027e15044
Binary files /dev/null and b/app/assets/images/emoji/rat.png differ
diff --git a/app/assets/images/emoji/recycle.png b/app/assets/images/emoji/recycle.png
new file mode 100755
index 0000000000000000000000000000000000000000..99104c0e9cd55f67d2099f1da6ba7f7e9eddd9b6
Binary files /dev/null and b/app/assets/images/emoji/recycle.png differ
diff --git a/app/assets/images/emoji/red_car.png b/app/assets/images/emoji/red_car.png
new file mode 100755
index 0000000000000000000000000000000000000000..d70a2f06263fa99a8553765a6bfbb8a9a86a5597
Binary files /dev/null and b/app/assets/images/emoji/red_car.png differ
diff --git a/app/assets/images/emoji/red_circle.png b/app/assets/images/emoji/red_circle.png
new file mode 100755
index 0000000000000000000000000000000000000000..b391289b203d6a802ee488582ae05534afcbcafe
Binary files /dev/null and b/app/assets/images/emoji/red_circle.png differ
diff --git a/app/assets/images/emoji/registered.png b/app/assets/images/emoji/registered.png
new file mode 100755
index 0000000000000000000000000000000000000000..31c68a80b08a5d203c922852dbed886da2dddf9a
Binary files /dev/null and b/app/assets/images/emoji/registered.png differ
diff --git a/app/assets/images/emoji/relaxed.png b/app/assets/images/emoji/relaxed.png
new file mode 100755
index 0000000000000000000000000000000000000000..bbab82d3bb5a809afa49e5781e28aae2ff435eb2
Binary files /dev/null and b/app/assets/images/emoji/relaxed.png differ
diff --git a/app/assets/images/emoji/relieved.png b/app/assets/images/emoji/relieved.png
new file mode 100755
index 0000000000000000000000000000000000000000..fa5f9e7f9f94a3ba9bdf23f3932cdd7c8a0a3fbc
Binary files /dev/null and b/app/assets/images/emoji/relieved.png differ
diff --git a/app/assets/images/emoji/repeat.png b/app/assets/images/emoji/repeat.png
new file mode 100755
index 0000000000000000000000000000000000000000..80113b6929b42158d5e5d7cc0cbedef74334b219
Binary files /dev/null and b/app/assets/images/emoji/repeat.png differ
diff --git a/app/assets/images/emoji/repeat_one.png b/app/assets/images/emoji/repeat_one.png
new file mode 100755
index 0000000000000000000000000000000000000000..3c47bcc1f3346c771a77ae3bda866be04b6c62c7
Binary files /dev/null and b/app/assets/images/emoji/repeat_one.png differ
diff --git a/app/assets/images/emoji/restroom.png b/app/assets/images/emoji/restroom.png
new file mode 100755
index 0000000000000000000000000000000000000000..d6c111b29b9fd50e40ab47979d38f0525d7c0aa1
Binary files /dev/null and b/app/assets/images/emoji/restroom.png differ
diff --git a/app/assets/images/emoji/revolving_hearts.png b/app/assets/images/emoji/revolving_hearts.png
new file mode 100755
index 0000000000000000000000000000000000000000..ea3317c47fbe90c47b91f5887eaae7d73e89b8d9
Binary files /dev/null and b/app/assets/images/emoji/revolving_hearts.png differ
diff --git a/app/assets/images/emoji/rewind.png b/app/assets/images/emoji/rewind.png
new file mode 100755
index 0000000000000000000000000000000000000000..26289dc3d2c2e9ed0111aed63f70a678d99c0c55
Binary files /dev/null and b/app/assets/images/emoji/rewind.png differ
diff --git a/app/assets/images/emoji/ribbon.png b/app/assets/images/emoji/ribbon.png
new file mode 100755
index 0000000000000000000000000000000000000000..63ee5ba5af22c884181d2a284802fa810e926b21
Binary files /dev/null and b/app/assets/images/emoji/ribbon.png differ
diff --git a/app/assets/images/emoji/rice.png b/app/assets/images/emoji/rice.png
new file mode 100755
index 0000000000000000000000000000000000000000..1fd22027bc5672bd967d014253192c195ccccc7f
Binary files /dev/null and b/app/assets/images/emoji/rice.png differ
diff --git a/app/assets/images/emoji/rice_ball.png b/app/assets/images/emoji/rice_ball.png
new file mode 100755
index 0000000000000000000000000000000000000000..04f8a88067c5ae3fbb39dea372a0b5b547c89771
Binary files /dev/null and b/app/assets/images/emoji/rice_ball.png differ
diff --git a/app/assets/images/emoji/rice_cracker.png b/app/assets/images/emoji/rice_cracker.png
new file mode 100755
index 0000000000000000000000000000000000000000..954c901e935b349cf6f1eed29fb6ade58ceb7e7c
Binary files /dev/null and b/app/assets/images/emoji/rice_cracker.png differ
diff --git a/app/assets/images/emoji/rice_scene.png b/app/assets/images/emoji/rice_scene.png
new file mode 100755
index 0000000000000000000000000000000000000000..14361988db7781e2103db212c5c21a8aec6a9669
Binary files /dev/null and b/app/assets/images/emoji/rice_scene.png differ
diff --git a/app/assets/images/emoji/ring.png b/app/assets/images/emoji/ring.png
new file mode 100755
index 0000000000000000000000000000000000000000..8a57fd68bac147d622d3eceb13d9812b6977cd89
Binary files /dev/null and b/app/assets/images/emoji/ring.png differ
diff --git a/app/assets/images/emoji/rocket.png b/app/assets/images/emoji/rocket.png
new file mode 100755
index 0000000000000000000000000000000000000000..783078d379839356e24e6346d594e33acdeadaed
Binary files /dev/null and b/app/assets/images/emoji/rocket.png differ
diff --git a/app/assets/images/emoji/roller_coaster.png b/app/assets/images/emoji/roller_coaster.png
new file mode 100755
index 0000000000000000000000000000000000000000..9180b9861dca156d934e7444925aad60a449d7e7
Binary files /dev/null and b/app/assets/images/emoji/roller_coaster.png differ
diff --git a/app/assets/images/emoji/rooster.png b/app/assets/images/emoji/rooster.png
new file mode 100755
index 0000000000000000000000000000000000000000..fab23ad3625ef60563c93b96bedaf044332628d3
Binary files /dev/null and b/app/assets/images/emoji/rooster.png differ
diff --git a/app/assets/images/emoji/rose.png b/app/assets/images/emoji/rose.png
new file mode 100755
index 0000000000000000000000000000000000000000..3479fbcbbd4b259651bc6bc450e364daa10dfb25
Binary files /dev/null and b/app/assets/images/emoji/rose.png differ
diff --git a/app/assets/images/emoji/rotating_light.png b/app/assets/images/emoji/rotating_light.png
new file mode 100755
index 0000000000000000000000000000000000000000..6cf4a775e0a42a07c796d135920fa4e3f9bdbcc1
Binary files /dev/null and b/app/assets/images/emoji/rotating_light.png differ
diff --git a/app/assets/images/emoji/round_pushpin.png b/app/assets/images/emoji/round_pushpin.png
new file mode 100755
index 0000000000000000000000000000000000000000..e498e92cf6ad3c040ba595a914e3223a60924b25
Binary files /dev/null and b/app/assets/images/emoji/round_pushpin.png differ
diff --git a/app/assets/images/emoji/rowboat.png b/app/assets/images/emoji/rowboat.png
new file mode 100755
index 0000000000000000000000000000000000000000..fe8ae3ecdab788978cfa127915efb4fa9344a42f
Binary files /dev/null and b/app/assets/images/emoji/rowboat.png differ
diff --git a/app/assets/images/emoji/ru.png b/app/assets/images/emoji/ru.png
new file mode 100755
index 0000000000000000000000000000000000000000..55fcf3549e239bad99eb3469bc6c87a6f67a7379
Binary files /dev/null and b/app/assets/images/emoji/ru.png differ
diff --git a/app/assets/images/emoji/rugby_football.png b/app/assets/images/emoji/rugby_football.png
new file mode 100755
index 0000000000000000000000000000000000000000..f8db67d7018102e8c6dcb6024d5764f832322c1e
Binary files /dev/null and b/app/assets/images/emoji/rugby_football.png differ
diff --git a/app/assets/images/emoji/runner.png b/app/assets/images/emoji/runner.png
new file mode 100755
index 0000000000000000000000000000000000000000..cb00429623d9c4d867a94e58faf8d53d21d021b3
Binary files /dev/null and b/app/assets/images/emoji/runner.png differ
diff --git a/app/assets/images/emoji/running.png b/app/assets/images/emoji/running.png
new file mode 100755
index 0000000000000000000000000000000000000000..1ecfd9059d8a8bfa4c8fe1843cc2167692541de6
Binary files /dev/null and b/app/assets/images/emoji/running.png differ
diff --git a/app/assets/images/emoji/running_shirt_with_sash.png b/app/assets/images/emoji/running_shirt_with_sash.png
new file mode 100755
index 0000000000000000000000000000000000000000..0d68bba09109711d4b3fb0d58040aac22dbcf558
Binary files /dev/null and b/app/assets/images/emoji/running_shirt_with_sash.png differ
diff --git a/app/assets/images/emoji/sa.png b/app/assets/images/emoji/sa.png
new file mode 100755
index 0000000000000000000000000000000000000000..387f098b99ce7b29cf335f6ba320f655cae8fd92
Binary files /dev/null and b/app/assets/images/emoji/sa.png differ
diff --git a/app/assets/images/emoji/sagittarius.png b/app/assets/images/emoji/sagittarius.png
new file mode 100755
index 0000000000000000000000000000000000000000..8b5435baaa9390991a35ccbb0023014319ee6e77
Binary files /dev/null and b/app/assets/images/emoji/sagittarius.png differ
diff --git a/app/assets/images/emoji/sailboat.png b/app/assets/images/emoji/sailboat.png
new file mode 100755
index 0000000000000000000000000000000000000000..ff656dc62bb78682ba3a1775eb4100459ac95bf5
Binary files /dev/null and b/app/assets/images/emoji/sailboat.png differ
diff --git a/app/assets/images/emoji/sake.png b/app/assets/images/emoji/sake.png
new file mode 100755
index 0000000000000000000000000000000000000000..1f69907e58a0256df362cd7590042c547931cc1f
Binary files /dev/null and b/app/assets/images/emoji/sake.png differ
diff --git a/app/assets/images/emoji/sandal.png b/app/assets/images/emoji/sandal.png
new file mode 100755
index 0000000000000000000000000000000000000000..0bb3f663f5c0be51ee8e68b0b8100bba53d91fb5
Binary files /dev/null and b/app/assets/images/emoji/sandal.png differ
diff --git a/app/assets/images/emoji/santa.png b/app/assets/images/emoji/santa.png
new file mode 100755
index 0000000000000000000000000000000000000000..a2240c07e7af2be38a5b9d27eca65b9a5c9222c3
Binary files /dev/null and b/app/assets/images/emoji/santa.png differ
diff --git a/app/assets/images/emoji/satellite.png b/app/assets/images/emoji/satellite.png
new file mode 100755
index 0000000000000000000000000000000000000000..3481cc2ef4a26d49f5f750db7f61f8d7d224242e
Binary files /dev/null and b/app/assets/images/emoji/satellite.png differ
diff --git a/app/assets/images/emoji/satisfied.png b/app/assets/images/emoji/satisfied.png
new file mode 100755
index 0000000000000000000000000000000000000000..fe5629f431e411f6870f9afe7662fe0b8022ecf4
Binary files /dev/null and b/app/assets/images/emoji/satisfied.png differ
diff --git a/app/assets/images/emoji/saxophone.png b/app/assets/images/emoji/saxophone.png
new file mode 100755
index 0000000000000000000000000000000000000000..011559a7673a28f96f7fba76d66d072574faea03
Binary files /dev/null and b/app/assets/images/emoji/saxophone.png differ
diff --git a/app/assets/images/emoji/school.png b/app/assets/images/emoji/school.png
new file mode 100755
index 0000000000000000000000000000000000000000..afd922bf13719d861e3c2f072f74db0946755d18
Binary files /dev/null and b/app/assets/images/emoji/school.png differ
diff --git a/app/assets/images/emoji/school_satchel.png b/app/assets/images/emoji/school_satchel.png
new file mode 100755
index 0000000000000000000000000000000000000000..edfb19aec916ed49a693b1e4493754d1b46d2c30
Binary files /dev/null and b/app/assets/images/emoji/school_satchel.png differ
diff --git a/app/assets/images/emoji/scissors.png b/app/assets/images/emoji/scissors.png
new file mode 100755
index 0000000000000000000000000000000000000000..be916043d2b45c7aa2940fabb847def27fc389a4
Binary files /dev/null and b/app/assets/images/emoji/scissors.png differ
diff --git a/app/assets/images/emoji/scorpius.png b/app/assets/images/emoji/scorpius.png
new file mode 100755
index 0000000000000000000000000000000000000000..67fcea1658acdede6fd5d1b0cb211278274fb0ea
Binary files /dev/null and b/app/assets/images/emoji/scorpius.png differ
diff --git a/app/assets/images/emoji/scream.png b/app/assets/images/emoji/scream.png
new file mode 100755
index 0000000000000000000000000000000000000000..9e93c885dbadcd5911704300344360d52dc6acfd
Binary files /dev/null and b/app/assets/images/emoji/scream.png differ
diff --git a/app/assets/images/emoji/scream_cat.png b/app/assets/images/emoji/scream_cat.png
new file mode 100755
index 0000000000000000000000000000000000000000..d94cd34ff5dafe1082a3e7627ac87453ca1da853
Binary files /dev/null and b/app/assets/images/emoji/scream_cat.png differ
diff --git a/app/assets/images/emoji/scroll.png b/app/assets/images/emoji/scroll.png
new file mode 100755
index 0000000000000000000000000000000000000000..c5a10e6b8f7efed52348a728b639238338214ae7
Binary files /dev/null and b/app/assets/images/emoji/scroll.png differ
diff --git a/app/assets/images/emoji/seat.png b/app/assets/images/emoji/seat.png
new file mode 100755
index 0000000000000000000000000000000000000000..d1cb864b4bf442e9e0132ff351f50ed9f0c91c31
Binary files /dev/null and b/app/assets/images/emoji/seat.png differ
diff --git a/app/assets/images/emoji/secret.png b/app/assets/images/emoji/secret.png
new file mode 100755
index 0000000000000000000000000000000000000000..82e383a60d1b71ea1d01e0c3afd848407faef5f9
Binary files /dev/null and b/app/assets/images/emoji/secret.png differ
diff --git a/app/assets/images/emoji/see_no_evil.png b/app/assets/images/emoji/see_no_evil.png
new file mode 100755
index 0000000000000000000000000000000000000000..0890a622279c4b6b379984640e7f6b15b5f011a6
Binary files /dev/null and b/app/assets/images/emoji/see_no_evil.png differ
diff --git a/app/assets/images/emoji/seedling.png b/app/assets/images/emoji/seedling.png
new file mode 100755
index 0000000000000000000000000000000000000000..f0eb5a6b99ae4022ad1e2a2383683fa5987fa139
Binary files /dev/null and b/app/assets/images/emoji/seedling.png differ
diff --git a/app/assets/images/emoji/seven.png b/app/assets/images/emoji/seven.png
new file mode 100755
index 0000000000000000000000000000000000000000..354e89ae75a0d10b68ae3f03cc8dc8fe52519bd7
Binary files /dev/null and b/app/assets/images/emoji/seven.png differ
diff --git a/app/assets/images/emoji/shaved_ice.png b/app/assets/images/emoji/shaved_ice.png
new file mode 100755
index 0000000000000000000000000000000000000000..0d0b382c22b20af966fbb889b93aa63a2e04d4cd
Binary files /dev/null and b/app/assets/images/emoji/shaved_ice.png differ
diff --git a/app/assets/images/emoji/sheep.png b/app/assets/images/emoji/sheep.png
new file mode 100755
index 0000000000000000000000000000000000000000..c7277d2898e27ce1e6e77101b8d5988b6fc5eb78
Binary files /dev/null and b/app/assets/images/emoji/sheep.png differ
diff --git a/app/assets/images/emoji/shell.png b/app/assets/images/emoji/shell.png
new file mode 100755
index 0000000000000000000000000000000000000000..3145b5649631a38f82ffb6326a709334137a3fa1
Binary files /dev/null and b/app/assets/images/emoji/shell.png differ
diff --git a/app/assets/images/emoji/ship.png b/app/assets/images/emoji/ship.png
new file mode 100755
index 0000000000000000000000000000000000000000..5d2d8b602bb56c64f1d73d7f6b2acd8f118dd936
Binary files /dev/null and b/app/assets/images/emoji/ship.png differ
diff --git a/app/assets/images/emoji/shipit.png b/app/assets/images/emoji/shipit.png
new file mode 100755
index 0000000000000000000000000000000000000000..a58a47f62f9ec4d8dba2ec2ff443ab984597d9ef
Binary files /dev/null and b/app/assets/images/emoji/shipit.png differ
diff --git a/app/assets/images/emoji/shirt.png b/app/assets/images/emoji/shirt.png
new file mode 100755
index 0000000000000000000000000000000000000000..297a6d63ed32a414f10aff5bd1e2856e606ef592
Binary files /dev/null and b/app/assets/images/emoji/shirt.png differ
diff --git a/app/assets/images/emoji/shit.png b/app/assets/images/emoji/shit.png
new file mode 100755
index 0000000000000000000000000000000000000000..73a4dc840085c7f42c7464d827751348b58acfba
Binary files /dev/null and b/app/assets/images/emoji/shit.png differ
diff --git a/app/assets/images/emoji/shoe.png b/app/assets/images/emoji/shoe.png
new file mode 100755
index 0000000000000000000000000000000000000000..45b82e61cf2e0a449f8f9e1c319db6bf3864afcf
Binary files /dev/null and b/app/assets/images/emoji/shoe.png differ
diff --git a/app/assets/images/emoji/shower.png b/app/assets/images/emoji/shower.png
new file mode 100755
index 0000000000000000000000000000000000000000..94f82aac02ec159b7a15a141c88f81f1e4049663
Binary files /dev/null and b/app/assets/images/emoji/shower.png differ
diff --git a/app/assets/images/emoji/signal_strength.png b/app/assets/images/emoji/signal_strength.png
new file mode 100755
index 0000000000000000000000000000000000000000..a4bd23ebf70f3ec3168425a277596edfe1efe2cd
Binary files /dev/null and b/app/assets/images/emoji/signal_strength.png differ
diff --git a/app/assets/images/emoji/six.png b/app/assets/images/emoji/six.png
new file mode 100755
index 0000000000000000000000000000000000000000..56880556577fae986257256cc11bb2d2d323a67d
Binary files /dev/null and b/app/assets/images/emoji/six.png differ
diff --git a/app/assets/images/emoji/six_pointed_star.png b/app/assets/images/emoji/six_pointed_star.png
new file mode 100755
index 0000000000000000000000000000000000000000..010f8f5f95f48fbad932cf135b1522868fb4d547
Binary files /dev/null and b/app/assets/images/emoji/six_pointed_star.png differ
diff --git a/app/assets/images/emoji/ski.png b/app/assets/images/emoji/ski.png
new file mode 100755
index 0000000000000000000000000000000000000000..98f5cb0f4608827c08cc12568735ffe623dbeb97
Binary files /dev/null and b/app/assets/images/emoji/ski.png differ
diff --git a/app/assets/images/emoji/skull.png b/app/assets/images/emoji/skull.png
new file mode 100755
index 0000000000000000000000000000000000000000..bd4ee38297aeb81713d926b2a8a936b494af47bd
Binary files /dev/null and b/app/assets/images/emoji/skull.png differ
diff --git a/app/assets/images/emoji/sleepy.png b/app/assets/images/emoji/sleepy.png
new file mode 100755
index 0000000000000000000000000000000000000000..df4f55efd9a45c4b5327b6531129ebe34908bad6
Binary files /dev/null and b/app/assets/images/emoji/sleepy.png differ
diff --git a/app/assets/images/emoji/slot_machine.png b/app/assets/images/emoji/slot_machine.png
new file mode 100755
index 0000000000000000000000000000000000000000..26f114830b8ce5fcf5264d88e1b00e16ae5c7e6c
Binary files /dev/null and b/app/assets/images/emoji/slot_machine.png differ
diff --git a/app/assets/images/emoji/small_blue_diamond.png b/app/assets/images/emoji/small_blue_diamond.png
new file mode 100755
index 0000000000000000000000000000000000000000..5a7b5d555a528c173c968a759aa56a6be053bc6a
Binary files /dev/null and b/app/assets/images/emoji/small_blue_diamond.png differ
diff --git a/app/assets/images/emoji/small_orange_diamond.png b/app/assets/images/emoji/small_orange_diamond.png
new file mode 100755
index 0000000000000000000000000000000000000000..04941d37b631baed5ff3af98070a5b6aded63962
Binary files /dev/null and b/app/assets/images/emoji/small_orange_diamond.png differ
diff --git a/app/assets/images/emoji/small_red_triangle.png b/app/assets/images/emoji/small_red_triangle.png
new file mode 100755
index 0000000000000000000000000000000000000000..8c4428da8fa57e44c82e759bb571a08c4df8d06f
Binary files /dev/null and b/app/assets/images/emoji/small_red_triangle.png differ
diff --git a/app/assets/images/emoji/small_red_triangle_down.png b/app/assets/images/emoji/small_red_triangle_down.png
new file mode 100755
index 0000000000000000000000000000000000000000..94832f060c453e5ffa2d190cff0616f034324df9
Binary files /dev/null and b/app/assets/images/emoji/small_red_triangle_down.png differ
diff --git a/app/assets/images/emoji/smile.png b/app/assets/images/emoji/smile.png
new file mode 100755
index 0000000000000000000000000000000000000000..81a8396899617698e6d4459d78bed8d2b968a2a9
Binary files /dev/null and b/app/assets/images/emoji/smile.png differ
diff --git a/app/assets/images/emoji/smile_cat.png b/app/assets/images/emoji/smile_cat.png
new file mode 100755
index 0000000000000000000000000000000000000000..ad333ba3b6bbbbf6525061dbea98aa32733f9ab3
Binary files /dev/null and b/app/assets/images/emoji/smile_cat.png differ
diff --git a/app/assets/images/emoji/smiley.png b/app/assets/images/emoji/smiley.png
new file mode 100755
index 0000000000000000000000000000000000000000..77b581d68faee6e9211a690b2ab3828a2ac5f70c
Binary files /dev/null and b/app/assets/images/emoji/smiley.png differ
diff --git a/app/assets/images/emoji/smiley_cat.png b/app/assets/images/emoji/smiley_cat.png
new file mode 100755
index 0000000000000000000000000000000000000000..dbf1b0276ab6648e9de49ba0d6ce0b5fcc7bf888
Binary files /dev/null and b/app/assets/images/emoji/smiley_cat.png differ
diff --git a/app/assets/images/emoji/smiling_imp.png b/app/assets/images/emoji/smiling_imp.png
new file mode 100755
index 0000000000000000000000000000000000000000..d904049309c60ff5cd4772f8aa55389847d8cad3
Binary files /dev/null and b/app/assets/images/emoji/smiling_imp.png differ
diff --git a/app/assets/images/emoji/smirk.png b/app/assets/images/emoji/smirk.png
new file mode 100755
index 0000000000000000000000000000000000000000..bc6e5082c8c62adbc3620c2c72c0fc28ee8ba3b9
Binary files /dev/null and b/app/assets/images/emoji/smirk.png differ
diff --git a/app/assets/images/emoji/smirk_cat.png b/app/assets/images/emoji/smirk_cat.png
new file mode 100755
index 0000000000000000000000000000000000000000..351565e2461bfe0bfbb826a6344f28118f821d08
Binary files /dev/null and b/app/assets/images/emoji/smirk_cat.png differ
diff --git a/app/assets/images/emoji/smoking.png b/app/assets/images/emoji/smoking.png
new file mode 100755
index 0000000000000000000000000000000000000000..4aad6cbd7c4064b69a83c718f7d4a891b8115404
Binary files /dev/null and b/app/assets/images/emoji/smoking.png differ
diff --git a/app/assets/images/emoji/snail.png b/app/assets/images/emoji/snail.png
new file mode 100755
index 0000000000000000000000000000000000000000..e75e69a84d351704e0d518b441d34a728f0a9510
Binary files /dev/null and b/app/assets/images/emoji/snail.png differ
diff --git a/app/assets/images/emoji/snake.png b/app/assets/images/emoji/snake.png
new file mode 100755
index 0000000000000000000000000000000000000000..ef58933e2b2f3caa55daa2d2aec81c1fcdd0292c
Binary files /dev/null and b/app/assets/images/emoji/snake.png differ
diff --git a/app/assets/images/emoji/snowboarder.png b/app/assets/images/emoji/snowboarder.png
new file mode 100755
index 0000000000000000000000000000000000000000..aeda5c8d872734428cf6f88af5e3db3441ce3407
Binary files /dev/null and b/app/assets/images/emoji/snowboarder.png differ
diff --git a/app/assets/images/emoji/snowflake.png b/app/assets/images/emoji/snowflake.png
new file mode 100755
index 0000000000000000000000000000000000000000..54b68ff4f136bda881912c379c2d77837bfcc965
Binary files /dev/null and b/app/assets/images/emoji/snowflake.png differ
diff --git a/app/assets/images/emoji/snowman.png b/app/assets/images/emoji/snowman.png
new file mode 100755
index 0000000000000000000000000000000000000000..a97902e53043d8393eb3a928da38b3686812e2be
Binary files /dev/null and b/app/assets/images/emoji/snowman.png differ
diff --git a/app/assets/images/emoji/sob.png b/app/assets/images/emoji/sob.png
new file mode 100755
index 0000000000000000000000000000000000000000..1561df92eee930f89483b6e5cf4377bab40649fc
Binary files /dev/null and b/app/assets/images/emoji/sob.png differ
diff --git a/app/assets/images/emoji/soccer.png b/app/assets/images/emoji/soccer.png
new file mode 100755
index 0000000000000000000000000000000000000000..1e118b5b1849619bb65488eb3ed219e3f77fa0d3
Binary files /dev/null and b/app/assets/images/emoji/soccer.png differ
diff --git a/app/assets/images/emoji/soon.png b/app/assets/images/emoji/soon.png
new file mode 100755
index 0000000000000000000000000000000000000000..9386615a32435ce2a8c1d8c55e7425213c4d22bd
Binary files /dev/null and b/app/assets/images/emoji/soon.png differ
diff --git a/app/assets/images/emoji/sos.png b/app/assets/images/emoji/sos.png
new file mode 100755
index 0000000000000000000000000000000000000000..e3e16ef73f830bb9922c37bab7c66a6179127e94
Binary files /dev/null and b/app/assets/images/emoji/sos.png differ
diff --git a/app/assets/images/emoji/sound.png b/app/assets/images/emoji/sound.png
new file mode 100755
index 0000000000000000000000000000000000000000..6aa4dbff4c0ac5730ba5e65fbbcc192f0e8c49ee
Binary files /dev/null and b/app/assets/images/emoji/sound.png differ
diff --git a/app/assets/images/emoji/space_invader.png b/app/assets/images/emoji/space_invader.png
new file mode 100755
index 0000000000000000000000000000000000000000..384049167473a2c58a94e006050f44f4b92a4323
Binary files /dev/null and b/app/assets/images/emoji/space_invader.png differ
diff --git a/app/assets/images/emoji/spades.png b/app/assets/images/emoji/spades.png
new file mode 100755
index 0000000000000000000000000000000000000000..133a1aba8a3d58bea8956a8ad670075e508889fc
Binary files /dev/null and b/app/assets/images/emoji/spades.png differ
diff --git a/app/assets/images/emoji/spaghetti.png b/app/assets/images/emoji/spaghetti.png
new file mode 100755
index 0000000000000000000000000000000000000000..08de243f554582f3ec082531844c5ab63504a143
Binary files /dev/null and b/app/assets/images/emoji/spaghetti.png differ
diff --git a/app/assets/images/emoji/sparkler.png b/app/assets/images/emoji/sparkler.png
new file mode 100755
index 0000000000000000000000000000000000000000..4aabd7e0ed3b5f9b9abe0dcb3e312be35fbc9aeb
Binary files /dev/null and b/app/assets/images/emoji/sparkler.png differ
diff --git a/app/assets/images/emoji/sparkles.png b/app/assets/images/emoji/sparkles.png
new file mode 100755
index 0000000000000000000000000000000000000000..92138828df08bce37374e0351988fda0a8006892
Binary files /dev/null and b/app/assets/images/emoji/sparkles.png differ
diff --git a/app/assets/images/emoji/speak_no_evil.png b/app/assets/images/emoji/speak_no_evil.png
new file mode 100755
index 0000000000000000000000000000000000000000..87944c4de543adf12926af9e33a4d15f8a863998
Binary files /dev/null and b/app/assets/images/emoji/speak_no_evil.png differ
diff --git a/app/assets/images/emoji/speaker.png b/app/assets/images/emoji/speaker.png
new file mode 100755
index 0000000000000000000000000000000000000000..470476e182eda3a17110e7610cb32c76e2a60069
Binary files /dev/null and b/app/assets/images/emoji/speaker.png differ
diff --git a/app/assets/images/emoji/speech_balloon.png b/app/assets/images/emoji/speech_balloon.png
new file mode 100755
index 0000000000000000000000000000000000000000..2896c278886cd6782383f19a58ca7e477d09ac57
Binary files /dev/null and b/app/assets/images/emoji/speech_balloon.png differ
diff --git a/app/assets/images/emoji/speedboat.png b/app/assets/images/emoji/speedboat.png
new file mode 100755
index 0000000000000000000000000000000000000000..da6689b3be7e17acfd71ecb71a2a00e43fdedfd1
Binary files /dev/null and b/app/assets/images/emoji/speedboat.png differ
diff --git a/app/assets/images/emoji/squirrel.png b/app/assets/images/emoji/squirrel.png
new file mode 100755
index 0000000000000000000000000000000000000000..a58a47f62f9ec4d8dba2ec2ff443ab984597d9ef
Binary files /dev/null and b/app/assets/images/emoji/squirrel.png differ
diff --git a/app/assets/images/emoji/star.png b/app/assets/images/emoji/star.png
new file mode 100755
index 0000000000000000000000000000000000000000..1bfddc8625535ef0c33e80f391ffffb0a7c1e3c5
Binary files /dev/null and b/app/assets/images/emoji/star.png differ
diff --git a/app/assets/images/emoji/star2.png b/app/assets/images/emoji/star2.png
new file mode 100755
index 0000000000000000000000000000000000000000..8b40ff4c8c8fbc0fa88a827d8deb4daaab6b7fdf
Binary files /dev/null and b/app/assets/images/emoji/star2.png differ
diff --git a/app/assets/images/emoji/stars.png b/app/assets/images/emoji/stars.png
new file mode 100755
index 0000000000000000000000000000000000000000..097a84241c1f6761a6dba4553c3dc53cd990a8c4
Binary files /dev/null and b/app/assets/images/emoji/stars.png differ
diff --git a/app/assets/images/emoji/station.png b/app/assets/images/emoji/station.png
new file mode 100755
index 0000000000000000000000000000000000000000..e77daa8a75fee7c6414af812146d9c54065fd4a8
Binary files /dev/null and b/app/assets/images/emoji/station.png differ
diff --git a/app/assets/images/emoji/statue_of_liberty.png b/app/assets/images/emoji/statue_of_liberty.png
new file mode 100755
index 0000000000000000000000000000000000000000..9ad902806895b5340313afccecafc6083fc6fe41
Binary files /dev/null and b/app/assets/images/emoji/statue_of_liberty.png differ
diff --git a/app/assets/images/emoji/steam_locomotive.png b/app/assets/images/emoji/steam_locomotive.png
new file mode 100755
index 0000000000000000000000000000000000000000..5495077667beb605feaf8caf77184295448968dd
Binary files /dev/null and b/app/assets/images/emoji/steam_locomotive.png differ
diff --git a/app/assets/images/emoji/stew.png b/app/assets/images/emoji/stew.png
new file mode 100755
index 0000000000000000000000000000000000000000..e9687f9ec26ecf5399896cd142e578741423dbc8
Binary files /dev/null and b/app/assets/images/emoji/stew.png differ
diff --git a/app/assets/images/emoji/straight_ruler.png b/app/assets/images/emoji/straight_ruler.png
new file mode 100755
index 0000000000000000000000000000000000000000..af8cb4bcffa37f89180f45cfdc7f095f0af357bd
Binary files /dev/null and b/app/assets/images/emoji/straight_ruler.png differ
diff --git a/app/assets/images/emoji/strawberry.png b/app/assets/images/emoji/strawberry.png
new file mode 100755
index 0000000000000000000000000000000000000000..13eb827ab870e4e2efc7af686317819dfabeea2d
Binary files /dev/null and b/app/assets/images/emoji/strawberry.png differ
diff --git a/app/assets/images/emoji/sun_with_face.png b/app/assets/images/emoji/sun_with_face.png
new file mode 100755
index 0000000000000000000000000000000000000000..ee276636fa405736a56a0e320d6e52bbc7d53481
Binary files /dev/null and b/app/assets/images/emoji/sun_with_face.png differ
diff --git a/app/assets/images/emoji/sunflower.png b/app/assets/images/emoji/sunflower.png
new file mode 100755
index 0000000000000000000000000000000000000000..d9bad194a210204ff2596feaca1da3e6308fc05e
Binary files /dev/null and b/app/assets/images/emoji/sunflower.png differ
diff --git a/app/assets/images/emoji/sunglasses.png b/app/assets/images/emoji/sunglasses.png
new file mode 100755
index 0000000000000000000000000000000000000000..1c468a1c91e677987140a9bfd70439be6541c60d
Binary files /dev/null and b/app/assets/images/emoji/sunglasses.png differ
diff --git a/app/assets/images/emoji/sunny.png b/app/assets/images/emoji/sunny.png
new file mode 100755
index 0000000000000000000000000000000000000000..d23c095e0804a23bc911a027530e12e86bdd7eda
Binary files /dev/null and b/app/assets/images/emoji/sunny.png differ
diff --git a/app/assets/images/emoji/sunrise.png b/app/assets/images/emoji/sunrise.png
new file mode 100755
index 0000000000000000000000000000000000000000..ec58dcc94ffb3be7451064ca34daa35e83bd2ffc
Binary files /dev/null and b/app/assets/images/emoji/sunrise.png differ
diff --git a/app/assets/images/emoji/sunrise_over_mountains.png b/app/assets/images/emoji/sunrise_over_mountains.png
new file mode 100755
index 0000000000000000000000000000000000000000..ebc3db146808ab1730f1c64457fa9e174f1c4417
Binary files /dev/null and b/app/assets/images/emoji/sunrise_over_mountains.png differ
diff --git a/app/assets/images/emoji/surfer.png b/app/assets/images/emoji/surfer.png
new file mode 100755
index 0000000000000000000000000000000000000000..b067e8cb32353197a5cd57e713f28638799bc1cc
Binary files /dev/null and b/app/assets/images/emoji/surfer.png differ
diff --git a/app/assets/images/emoji/sushi.png b/app/assets/images/emoji/sushi.png
new file mode 100755
index 0000000000000000000000000000000000000000..0d179bd975689446130a87bec6a2ff0da0089fed
Binary files /dev/null and b/app/assets/images/emoji/sushi.png differ
diff --git a/app/assets/images/emoji/suspect.png b/app/assets/images/emoji/suspect.png
new file mode 100755
index 0000000000000000000000000000000000000000..58e8921c0a72566c7ef109e5c3619b623f06bf28
Binary files /dev/null and b/app/assets/images/emoji/suspect.png differ
diff --git a/app/assets/images/emoji/suspension_railway.png b/app/assets/images/emoji/suspension_railway.png
new file mode 100755
index 0000000000000000000000000000000000000000..aaa45f61f1fddd0d26351dd35be7ec5ac20c9578
Binary files /dev/null and b/app/assets/images/emoji/suspension_railway.png differ
diff --git a/app/assets/images/emoji/sweat.png b/app/assets/images/emoji/sweat.png
new file mode 100755
index 0000000000000000000000000000000000000000..e894b7699606b17f68ec6059fc697c31416d8b83
Binary files /dev/null and b/app/assets/images/emoji/sweat.png differ
diff --git a/app/assets/images/emoji/sweat_drops.png b/app/assets/images/emoji/sweat_drops.png
new file mode 100755
index 0000000000000000000000000000000000000000..a83b3e960cdbaf111579370c614536f8e96460c2
Binary files /dev/null and b/app/assets/images/emoji/sweat_drops.png differ
diff --git a/app/assets/images/emoji/sweat_smile.png b/app/assets/images/emoji/sweat_smile.png
new file mode 100755
index 0000000000000000000000000000000000000000..3903f717f31eb58d5878cb89c16a810ec4cff914
Binary files /dev/null and b/app/assets/images/emoji/sweat_smile.png differ
diff --git a/app/assets/images/emoji/sweet_potato.png b/app/assets/images/emoji/sweet_potato.png
new file mode 100755
index 0000000000000000000000000000000000000000..32117fa9c7fe6c26003e03853addecb0f107f049
Binary files /dev/null and b/app/assets/images/emoji/sweet_potato.png differ
diff --git a/app/assets/images/emoji/swimmer.png b/app/assets/images/emoji/swimmer.png
new file mode 100755
index 0000000000000000000000000000000000000000..d3878a0652559d1d1341222401a97ae58bffca1d
Binary files /dev/null and b/app/assets/images/emoji/swimmer.png differ
diff --git a/app/assets/images/emoji/symbols.png b/app/assets/images/emoji/symbols.png
new file mode 100755
index 0000000000000000000000000000000000000000..16bc1da921f9a9a7d784197ac11a541b63ef32ea
Binary files /dev/null and b/app/assets/images/emoji/symbols.png differ
diff --git a/app/assets/images/emoji/syringe.png b/app/assets/images/emoji/syringe.png
new file mode 100755
index 0000000000000000000000000000000000000000..7314255e3cab40a581881ddca6dfb257526da690
Binary files /dev/null and b/app/assets/images/emoji/syringe.png differ
diff --git a/app/assets/images/emoji/tada.png b/app/assets/images/emoji/tada.png
new file mode 100755
index 0000000000000000000000000000000000000000..7411b5266a03ca75ec27e5c309fad815d99f3512
Binary files /dev/null and b/app/assets/images/emoji/tada.png differ
diff --git a/app/assets/images/emoji/tanabata_tree.png b/app/assets/images/emoji/tanabata_tree.png
new file mode 100755
index 0000000000000000000000000000000000000000..473346410f6d442ecc54c50b74eb316796239a98
Binary files /dev/null and b/app/assets/images/emoji/tanabata_tree.png differ
diff --git a/app/assets/images/emoji/tangerine.png b/app/assets/images/emoji/tangerine.png
new file mode 100755
index 0000000000000000000000000000000000000000..fc9d4f82ad9a116cabf5dbe690272a01ae62cdd7
Binary files /dev/null and b/app/assets/images/emoji/tangerine.png differ
diff --git a/app/assets/images/emoji/taurus.png b/app/assets/images/emoji/taurus.png
new file mode 100755
index 0000000000000000000000000000000000000000..6af582f69d27a33c8015e0b4a8d682fdf2a6f8b6
Binary files /dev/null and b/app/assets/images/emoji/taurus.png differ
diff --git a/app/assets/images/emoji/taxi.png b/app/assets/images/emoji/taxi.png
new file mode 100755
index 0000000000000000000000000000000000000000..60a50d365a41e99778338bc28198b0a654f69aa5
Binary files /dev/null and b/app/assets/images/emoji/taxi.png differ
diff --git a/app/assets/images/emoji/tea.png b/app/assets/images/emoji/tea.png
new file mode 100755
index 0000000000000000000000000000000000000000..3ece0b708af19a9d9b16ae5228ff5a7cf5325f6f
Binary files /dev/null and b/app/assets/images/emoji/tea.png differ
diff --git a/app/assets/images/emoji/telephone.png b/app/assets/images/emoji/telephone.png
new file mode 100755
index 0000000000000000000000000000000000000000..87d2559b55256935f097f9be4aea134a0800e099
Binary files /dev/null and b/app/assets/images/emoji/telephone.png differ
diff --git a/app/assets/images/emoji/telephone_receiver.png b/app/assets/images/emoji/telephone_receiver.png
new file mode 100755
index 0000000000000000000000000000000000000000..36e21e0123df2541043ae49139870a976769453a
Binary files /dev/null and b/app/assets/images/emoji/telephone_receiver.png differ
diff --git a/app/assets/images/emoji/telescope.png b/app/assets/images/emoji/telescope.png
new file mode 100755
index 0000000000000000000000000000000000000000..51fd8a07fae664cbf1d3467c6f9deda1efc1fae8
Binary files /dev/null and b/app/assets/images/emoji/telescope.png differ
diff --git a/app/assets/images/emoji/tennis.png b/app/assets/images/emoji/tennis.png
new file mode 100755
index 0000000000000000000000000000000000000000..278d904ee20101322293f94ebb941480210ce2c3
Binary files /dev/null and b/app/assets/images/emoji/tennis.png differ
diff --git a/app/assets/images/emoji/tent.png b/app/assets/images/emoji/tent.png
new file mode 100755
index 0000000000000000000000000000000000000000..5c0d20e48b6ec00123333e91654bc104b0c43312
Binary files /dev/null and b/app/assets/images/emoji/tent.png differ
diff --git a/app/assets/images/emoji/thought_balloon.png b/app/assets/images/emoji/thought_balloon.png
new file mode 100755
index 0000000000000000000000000000000000000000..701bdf0f64b4af0f5fba16ef36958c01b5530e1b
Binary files /dev/null and b/app/assets/images/emoji/thought_balloon.png differ
diff --git a/app/assets/images/emoji/three.png b/app/assets/images/emoji/three.png
new file mode 100755
index 0000000000000000000000000000000000000000..55644c9900c5a61a86309ec7a3764896891faf82
Binary files /dev/null and b/app/assets/images/emoji/three.png differ
diff --git a/app/assets/images/emoji/thumbsdown.png b/app/assets/images/emoji/thumbsdown.png
new file mode 100755
index 0000000000000000000000000000000000000000..41c6b825d6a6abf736a1b882c951c1eb942afabf
Binary files /dev/null and b/app/assets/images/emoji/thumbsdown.png differ
diff --git a/app/assets/images/emoji/thumbsup.png b/app/assets/images/emoji/thumbsup.png
new file mode 100755
index 0000000000000000000000000000000000000000..81786c1d8f5ed810fd8351f74996f9b64dbf5ffb
Binary files /dev/null and b/app/assets/images/emoji/thumbsup.png differ
diff --git a/app/assets/images/emoji/ticket.png b/app/assets/images/emoji/ticket.png
new file mode 100755
index 0000000000000000000000000000000000000000..cdacf1a70be4f6952922b7e07755072582f711ea
Binary files /dev/null and b/app/assets/images/emoji/ticket.png differ
diff --git a/app/assets/images/emoji/tiger.png b/app/assets/images/emoji/tiger.png
new file mode 100755
index 0000000000000000000000000000000000000000..d6cc84a3ba980695dd5e2430a174572d8ea4c955
Binary files /dev/null and b/app/assets/images/emoji/tiger.png differ
diff --git a/app/assets/images/emoji/tiger2.png b/app/assets/images/emoji/tiger2.png
new file mode 100755
index 0000000000000000000000000000000000000000..b0c7d8dc3ec2326be0b6bd349ce4bf91d06980ec
Binary files /dev/null and b/app/assets/images/emoji/tiger2.png differ
diff --git a/app/assets/images/emoji/tired_face.png b/app/assets/images/emoji/tired_face.png
new file mode 100755
index 0000000000000000000000000000000000000000..3a8eefe565d27d3d4e360bc7bdb40aa56b91771b
Binary files /dev/null and b/app/assets/images/emoji/tired_face.png differ
diff --git a/app/assets/images/emoji/tm.png b/app/assets/images/emoji/tm.png
new file mode 100755
index 0000000000000000000000000000000000000000..c7dec75a33adb03d4710789c4cfa0daa36e53843
Binary files /dev/null and b/app/assets/images/emoji/tm.png differ
diff --git a/app/assets/images/emoji/toilet.png b/app/assets/images/emoji/toilet.png
new file mode 100755
index 0000000000000000000000000000000000000000..e5cc4119a15d3346474b666ed1fd1bb8f3de7e79
Binary files /dev/null and b/app/assets/images/emoji/toilet.png differ
diff --git a/app/assets/images/emoji/tokyo_tower.png b/app/assets/images/emoji/tokyo_tower.png
new file mode 100755
index 0000000000000000000000000000000000000000..e1cbd7a3c5d7e8d7474bed03b17c762cf714a8f7
Binary files /dev/null and b/app/assets/images/emoji/tokyo_tower.png differ
diff --git a/app/assets/images/emoji/tomato.png b/app/assets/images/emoji/tomato.png
new file mode 100755
index 0000000000000000000000000000000000000000..a129700bbb5911fccd94b7d1546445d6dc1df6c3
Binary files /dev/null and b/app/assets/images/emoji/tomato.png differ
diff --git a/app/assets/images/emoji/tongue.png b/app/assets/images/emoji/tongue.png
new file mode 100755
index 0000000000000000000000000000000000000000..333716ee1fec3a36e0db015d73ec3c686660ec28
Binary files /dev/null and b/app/assets/images/emoji/tongue.png differ
diff --git a/app/assets/images/emoji/tongue2.png b/app/assets/images/emoji/tongue2.png
new file mode 100755
index 0000000000000000000000000000000000000000..b0bab12078fb12f9f1d2425cd4419c060c87ad7c
Binary files /dev/null and b/app/assets/images/emoji/tongue2.png differ
diff --git a/app/assets/images/emoji/top.png b/app/assets/images/emoji/top.png
new file mode 100755
index 0000000000000000000000000000000000000000..5aa4dd442da574464fbde3f5978730e4e9cad5f1
Binary files /dev/null and b/app/assets/images/emoji/top.png differ
diff --git a/app/assets/images/emoji/tophat.png b/app/assets/images/emoji/tophat.png
new file mode 100755
index 0000000000000000000000000000000000000000..7d27134d6a5d7c6b164712ee3e08af3ec1a11c5e
Binary files /dev/null and b/app/assets/images/emoji/tophat.png differ
diff --git a/app/assets/images/emoji/tractor.png b/app/assets/images/emoji/tractor.png
new file mode 100755
index 0000000000000000000000000000000000000000..058fd3eda551a9a80eea4b9ada7c9444a2794958
Binary files /dev/null and b/app/assets/images/emoji/tractor.png differ
diff --git a/app/assets/images/emoji/traffic_light.png b/app/assets/images/emoji/traffic_light.png
new file mode 100755
index 0000000000000000000000000000000000000000..50c781016cc0b21be8449cf2f4d6f32c738626d2
Binary files /dev/null and b/app/assets/images/emoji/traffic_light.png differ
diff --git a/app/assets/images/emoji/train.png b/app/assets/images/emoji/train.png
new file mode 100755
index 0000000000000000000000000000000000000000..3202d80ea9f438edffcb382df6a4a1f34a59c2f6
Binary files /dev/null and b/app/assets/images/emoji/train.png differ
diff --git a/app/assets/images/emoji/train2.png b/app/assets/images/emoji/train2.png
new file mode 100755
index 0000000000000000000000000000000000000000..9c0d3ab640757428e2840ae089f84fe1dea4e4ef
Binary files /dev/null and b/app/assets/images/emoji/train2.png differ
diff --git a/app/assets/images/emoji/tram.png b/app/assets/images/emoji/tram.png
new file mode 100755
index 0000000000000000000000000000000000000000..5eb29fb71cdcc8cf8b8b7f2f6d40003c7846d229
Binary files /dev/null and b/app/assets/images/emoji/tram.png differ
diff --git a/app/assets/images/emoji/triangular_flag_on_post.png b/app/assets/images/emoji/triangular_flag_on_post.png
new file mode 100755
index 0000000000000000000000000000000000000000..f9a3f32d7118988613c63f944691f0f2ae39b88a
Binary files /dev/null and b/app/assets/images/emoji/triangular_flag_on_post.png differ
diff --git a/app/assets/images/emoji/triangular_ruler.png b/app/assets/images/emoji/triangular_ruler.png
new file mode 100755
index 0000000000000000000000000000000000000000..383677cb74cb96f089804d8f488127707ccfb7e9
Binary files /dev/null and b/app/assets/images/emoji/triangular_ruler.png differ
diff --git a/app/assets/images/emoji/trident.png b/app/assets/images/emoji/trident.png
new file mode 100755
index 0000000000000000000000000000000000000000..d79a7b4cce5aceb3efb24c0bde909646f3b5b140
Binary files /dev/null and b/app/assets/images/emoji/trident.png differ
diff --git a/app/assets/images/emoji/triumph.png b/app/assets/images/emoji/triumph.png
new file mode 100755
index 0000000000000000000000000000000000000000..92f93bd1025035241022d89eb701bf7920a1a636
Binary files /dev/null and b/app/assets/images/emoji/triumph.png differ
diff --git a/app/assets/images/emoji/trolleybus.png b/app/assets/images/emoji/trolleybus.png
new file mode 100755
index 0000000000000000000000000000000000000000..b9740a53f87a245eca78d521c75ab53d00ca4608
Binary files /dev/null and b/app/assets/images/emoji/trolleybus.png differ
diff --git a/app/assets/images/emoji/trollface.png b/app/assets/images/emoji/trollface.png
new file mode 100755
index 0000000000000000000000000000000000000000..e234893cef05b0132924f61ce1705310d123ecc7
Binary files /dev/null and b/app/assets/images/emoji/trollface.png differ
diff --git a/app/assets/images/emoji/trophy.png b/app/assets/images/emoji/trophy.png
new file mode 100755
index 0000000000000000000000000000000000000000..95d3b63f524646adc51e00c3a6ca85b8a98e681f
Binary files /dev/null and b/app/assets/images/emoji/trophy.png differ
diff --git a/app/assets/images/emoji/tropical_drink.png b/app/assets/images/emoji/tropical_drink.png
new file mode 100755
index 0000000000000000000000000000000000000000..55ca9eeda75fd4e8ae6b010af6257b269497e708
Binary files /dev/null and b/app/assets/images/emoji/tropical_drink.png differ
diff --git a/app/assets/images/emoji/tropical_fish.png b/app/assets/images/emoji/tropical_fish.png
new file mode 100755
index 0000000000000000000000000000000000000000..a6d734987bb33df8f0ff5ed6a7952987d69cec12
Binary files /dev/null and b/app/assets/images/emoji/tropical_fish.png differ
diff --git a/app/assets/images/emoji/truck.png b/app/assets/images/emoji/truck.png
new file mode 100755
index 0000000000000000000000000000000000000000..3f25ba1f92a16371f50ca9b38221ce00059fd531
Binary files /dev/null and b/app/assets/images/emoji/truck.png differ
diff --git a/app/assets/images/emoji/trumpet.png b/app/assets/images/emoji/trumpet.png
new file mode 100755
index 0000000000000000000000000000000000000000..c84cfb13e10ef152b05978b6b14debd15cb4cc26
Binary files /dev/null and b/app/assets/images/emoji/trumpet.png differ
diff --git a/app/assets/images/emoji/tshirt.png b/app/assets/images/emoji/tshirt.png
new file mode 100755
index 0000000000000000000000000000000000000000..297a6d63ed32a414f10aff5bd1e2856e606ef592
Binary files /dev/null and b/app/assets/images/emoji/tshirt.png differ
diff --git a/app/assets/images/emoji/tulip.png b/app/assets/images/emoji/tulip.png
new file mode 100755
index 0000000000000000000000000000000000000000..b3ee1102a538d1fd1be9764c86b4c49f7327caf0
Binary files /dev/null and b/app/assets/images/emoji/tulip.png differ
diff --git a/app/assets/images/emoji/turtle.png b/app/assets/images/emoji/turtle.png
new file mode 100755
index 0000000000000000000000000000000000000000..04d1d9684709721989f9e0a4ae81c7f6ff4f9a62
Binary files /dev/null and b/app/assets/images/emoji/turtle.png differ
diff --git a/app/assets/images/emoji/tv.png b/app/assets/images/emoji/tv.png
new file mode 100755
index 0000000000000000000000000000000000000000..803dc3d412fcc0053b2d14798f17b29f5ac7ee53
Binary files /dev/null and b/app/assets/images/emoji/tv.png differ
diff --git a/app/assets/images/emoji/twisted_rightwards_arrows.png b/app/assets/images/emoji/twisted_rightwards_arrows.png
new file mode 100755
index 0000000000000000000000000000000000000000..25cde18b250190797ff713f1dc3047d60e74712d
Binary files /dev/null and b/app/assets/images/emoji/twisted_rightwards_arrows.png differ
diff --git a/app/assets/images/emoji/two.png b/app/assets/images/emoji/two.png
new file mode 100755
index 0000000000000000000000000000000000000000..c191f8a3221b516b2e739a23c69a65fe1a261aaf
Binary files /dev/null and b/app/assets/images/emoji/two.png differ
diff --git a/app/assets/images/emoji/two_hearts.png b/app/assets/images/emoji/two_hearts.png
new file mode 100755
index 0000000000000000000000000000000000000000..b189e9aea82ee62a9b483f480267b4ff2cab7bcb
Binary files /dev/null and b/app/assets/images/emoji/two_hearts.png differ
diff --git a/app/assets/images/emoji/two_men_holding_hands.png b/app/assets/images/emoji/two_men_holding_hands.png
new file mode 100755
index 0000000000000000000000000000000000000000..d1099f21ffe1046dbf70e62f101764cba29d35ac
Binary files /dev/null and b/app/assets/images/emoji/two_men_holding_hands.png differ
diff --git a/app/assets/images/emoji/two_women_holding_hands.png b/app/assets/images/emoji/two_women_holding_hands.png
new file mode 100755
index 0000000000000000000000000000000000000000..619646c4e02aa3887877851c1e462485a28e37b9
Binary files /dev/null and b/app/assets/images/emoji/two_women_holding_hands.png differ
diff --git a/app/assets/images/emoji/u5272.png b/app/assets/images/emoji/u5272.png
new file mode 100755
index 0000000000000000000000000000000000000000..2148253fc1045a53593347a7d79c6fbd23178a1f
Binary files /dev/null and b/app/assets/images/emoji/u5272.png differ
diff --git a/app/assets/images/emoji/u5408.png b/app/assets/images/emoji/u5408.png
new file mode 100755
index 0000000000000000000000000000000000000000..03ab0d8746ef374e63946de5dc323adeefc8baad
Binary files /dev/null and b/app/assets/images/emoji/u5408.png differ
diff --git a/app/assets/images/emoji/u55b6.png b/app/assets/images/emoji/u55b6.png
new file mode 100755
index 0000000000000000000000000000000000000000..ba946d3f339a999b72af3424b099370f01b14b8f
Binary files /dev/null and b/app/assets/images/emoji/u55b6.png differ
diff --git a/app/assets/images/emoji/u6307.png b/app/assets/images/emoji/u6307.png
new file mode 100755
index 0000000000000000000000000000000000000000..6557f5672fb8cd1be9303787f7c00eddf0cd6b83
Binary files /dev/null and b/app/assets/images/emoji/u6307.png differ
diff --git a/app/assets/images/emoji/u6708.png b/app/assets/images/emoji/u6708.png
new file mode 100755
index 0000000000000000000000000000000000000000..e4dfe5aa7626af6907ffb8821282c33f354183d2
Binary files /dev/null and b/app/assets/images/emoji/u6708.png differ
diff --git a/app/assets/images/emoji/u6709.png b/app/assets/images/emoji/u6709.png
new file mode 100755
index 0000000000000000000000000000000000000000..cd8fb3f62a59cbf5b9ca3d5d718b6502f0331bc4
Binary files /dev/null and b/app/assets/images/emoji/u6709.png differ
diff --git a/app/assets/images/emoji/u6e80.png b/app/assets/images/emoji/u6e80.png
new file mode 100755
index 0000000000000000000000000000000000000000..5df1cb878f70303b0d295c10a74a92464940102a
Binary files /dev/null and b/app/assets/images/emoji/u6e80.png differ
diff --git a/app/assets/images/emoji/u7121.png b/app/assets/images/emoji/u7121.png
new file mode 100755
index 0000000000000000000000000000000000000000..25f694ed3ff0b8865f7fc69e5115d8e5f9488997
Binary files /dev/null and b/app/assets/images/emoji/u7121.png differ
diff --git a/app/assets/images/emoji/u7533.png b/app/assets/images/emoji/u7533.png
new file mode 100755
index 0000000000000000000000000000000000000000..fc4a9901b461cf3f8a95d3ea2b775885632f7923
Binary files /dev/null and b/app/assets/images/emoji/u7533.png differ
diff --git a/app/assets/images/emoji/u7981.png b/app/assets/images/emoji/u7981.png
new file mode 100755
index 0000000000000000000000000000000000000000..f550a573da73ab7362b322ca22942516a2bc36d6
Binary files /dev/null and b/app/assets/images/emoji/u7981.png differ
diff --git a/app/assets/images/emoji/u7a7a.png b/app/assets/images/emoji/u7a7a.png
new file mode 100755
index 0000000000000000000000000000000000000000..c05f5cff73ba4cce11c158826a30839149c8e50c
Binary files /dev/null and b/app/assets/images/emoji/u7a7a.png differ
diff --git a/app/assets/images/emoji/uk.png b/app/assets/images/emoji/uk.png
new file mode 100755
index 0000000000000000000000000000000000000000..2a62c7a0810a8b4f3d06279330e0308bf2a78b68
Binary files /dev/null and b/app/assets/images/emoji/uk.png differ
diff --git a/app/assets/images/emoji/umbrella.png b/app/assets/images/emoji/umbrella.png
new file mode 100755
index 0000000000000000000000000000000000000000..1db722fa661ea4e74fca2dc29e7972716843d812
Binary files /dev/null and b/app/assets/images/emoji/umbrella.png differ
diff --git a/app/assets/images/emoji/unamused.png b/app/assets/images/emoji/unamused.png
new file mode 100755
index 0000000000000000000000000000000000000000..3722e6f57538db37176290abf5920c6c4949e448
Binary files /dev/null and b/app/assets/images/emoji/unamused.png differ
diff --git a/app/assets/images/emoji/underage.png b/app/assets/images/emoji/underage.png
new file mode 100755
index 0000000000000000000000000000000000000000..a789b3c6200cc2ef95766ed1404f4239a88eba03
Binary files /dev/null and b/app/assets/images/emoji/underage.png differ
diff --git a/app/assets/images/emoji/unlock.png b/app/assets/images/emoji/unlock.png
new file mode 100755
index 0000000000000000000000000000000000000000..22b429cd0219e50affa739049b7d30e661486b4d
Binary files /dev/null and b/app/assets/images/emoji/unlock.png differ
diff --git a/app/assets/images/emoji/up.png b/app/assets/images/emoji/up.png
new file mode 100755
index 0000000000000000000000000000000000000000..829219a868adf6e28def3d4bf6c7e131e97a6e52
Binary files /dev/null and b/app/assets/images/emoji/up.png differ
diff --git a/app/assets/images/emoji/us.png b/app/assets/images/emoji/us.png
new file mode 100755
index 0000000000000000000000000000000000000000..38137669aa9c889c10740b42f2dd628c2e46fe39
Binary files /dev/null and b/app/assets/images/emoji/us.png differ
diff --git a/app/assets/images/emoji/v.png b/app/assets/images/emoji/v.png
new file mode 100755
index 0000000000000000000000000000000000000000..f61267c281ded65c918ef42bc2c98042315f5c39
Binary files /dev/null and b/app/assets/images/emoji/v.png differ
diff --git a/app/assets/images/emoji/vertical_traffic_light.png b/app/assets/images/emoji/vertical_traffic_light.png
new file mode 100755
index 0000000000000000000000000000000000000000..7a5ba35f09d9a0f80fb46ee148d996f78ea1c953
Binary files /dev/null and b/app/assets/images/emoji/vertical_traffic_light.png differ
diff --git a/app/assets/images/emoji/vhs.png b/app/assets/images/emoji/vhs.png
new file mode 100755
index 0000000000000000000000000000000000000000..881081c17784ead2520ea5214664997afec38702
Binary files /dev/null and b/app/assets/images/emoji/vhs.png differ
diff --git a/app/assets/images/emoji/vibration_mode.png b/app/assets/images/emoji/vibration_mode.png
new file mode 100755
index 0000000000000000000000000000000000000000..a716e96c6353cfcc026eaaf8517f207122c2cb06
Binary files /dev/null and b/app/assets/images/emoji/vibration_mode.png differ
diff --git a/app/assets/images/emoji/video_camera.png b/app/assets/images/emoji/video_camera.png
new file mode 100755
index 0000000000000000000000000000000000000000..274cecdd6d4d1415fa251d88b6c206e0335a3320
Binary files /dev/null and b/app/assets/images/emoji/video_camera.png differ
diff --git a/app/assets/images/emoji/video_game.png b/app/assets/images/emoji/video_game.png
new file mode 100755
index 0000000000000000000000000000000000000000..59d45baeabbb4d839472ebf66bd538dd9341e390
Binary files /dev/null and b/app/assets/images/emoji/video_game.png differ
diff --git a/app/assets/images/emoji/violin.png b/app/assets/images/emoji/violin.png
new file mode 100755
index 0000000000000000000000000000000000000000..0dba5ba2b66507b4461f804978459c0286da9ab6
Binary files /dev/null and b/app/assets/images/emoji/violin.png differ
diff --git a/app/assets/images/emoji/virgo.png b/app/assets/images/emoji/virgo.png
new file mode 100755
index 0000000000000000000000000000000000000000..72e1763f5739ada7bce3cc5519d0b4760e7f2875
Binary files /dev/null and b/app/assets/images/emoji/virgo.png differ
diff --git a/app/assets/images/emoji/volcano.png b/app/assets/images/emoji/volcano.png
new file mode 100755
index 0000000000000000000000000000000000000000..9b434539b05655036d465500e296ccce84711ffe
Binary files /dev/null and b/app/assets/images/emoji/volcano.png differ
diff --git a/app/assets/images/emoji/vs.png b/app/assets/images/emoji/vs.png
new file mode 100755
index 0000000000000000000000000000000000000000..863638850e1e30e39cf82aa8cf9500e70468ec7f
Binary files /dev/null and b/app/assets/images/emoji/vs.png differ
diff --git a/app/assets/images/emoji/walking.png b/app/assets/images/emoji/walking.png
new file mode 100755
index 0000000000000000000000000000000000000000..52bc0381c72c99ac4fc7bb01ee796d5737488a4b
Binary files /dev/null and b/app/assets/images/emoji/walking.png differ
diff --git a/app/assets/images/emoji/waning_crescent_moon.png b/app/assets/images/emoji/waning_crescent_moon.png
new file mode 100755
index 0000000000000000000000000000000000000000..30387780fec8cd386766df2abe350c8afe3de37f
Binary files /dev/null and b/app/assets/images/emoji/waning_crescent_moon.png differ
diff --git a/app/assets/images/emoji/waning_gibbous_moon.png b/app/assets/images/emoji/waning_gibbous_moon.png
new file mode 100755
index 0000000000000000000000000000000000000000..8e324ec5f7f27a75259984cc7bf45826c274ac01
Binary files /dev/null and b/app/assets/images/emoji/waning_gibbous_moon.png differ
diff --git a/app/assets/images/emoji/warning.png b/app/assets/images/emoji/warning.png
new file mode 100755
index 0000000000000000000000000000000000000000..466658d99a8f4d3dede8bd41da34dde0b450f7dc
Binary files /dev/null and b/app/assets/images/emoji/warning.png differ
diff --git a/app/assets/images/emoji/watch.png b/app/assets/images/emoji/watch.png
new file mode 100755
index 0000000000000000000000000000000000000000..d503bb87c22990dc8fc76bf47343a6602a6a8e44
Binary files /dev/null and b/app/assets/images/emoji/watch.png differ
diff --git a/app/assets/images/emoji/water_buffalo.png b/app/assets/images/emoji/water_buffalo.png
new file mode 100755
index 0000000000000000000000000000000000000000..3bcde3edd9536e4c4e298daec98e18f0f244b479
Binary files /dev/null and b/app/assets/images/emoji/water_buffalo.png differ
diff --git a/app/assets/images/emoji/watermelon.png b/app/assets/images/emoji/watermelon.png
new file mode 100755
index 0000000000000000000000000000000000000000..fc212be784482c07bb3c49168c48784d6ef9e046
Binary files /dev/null and b/app/assets/images/emoji/watermelon.png differ
diff --git a/app/assets/images/emoji/wave.png b/app/assets/images/emoji/wave.png
new file mode 100755
index 0000000000000000000000000000000000000000..e78402eb086fcdccfed1822725e11879587c0ca9
Binary files /dev/null and b/app/assets/images/emoji/wave.png differ
diff --git a/app/assets/images/emoji/wavy_dash.png b/app/assets/images/emoji/wavy_dash.png
new file mode 100755
index 0000000000000000000000000000000000000000..77f626cc5cd0b7b89fdb2908e4e38fbc09f1a614
Binary files /dev/null and b/app/assets/images/emoji/wavy_dash.png differ
diff --git a/app/assets/images/emoji/waxing_crescent_moon.png b/app/assets/images/emoji/waxing_crescent_moon.png
new file mode 100755
index 0000000000000000000000000000000000000000..c8f13dd31c8d4035ebf1450601561f76fe3066e5
Binary files /dev/null and b/app/assets/images/emoji/waxing_crescent_moon.png differ
diff --git a/app/assets/images/emoji/waxing_gibbous_moon.png b/app/assets/images/emoji/waxing_gibbous_moon.png
new file mode 100755
index 0000000000000000000000000000000000000000..dd8c4845896cc5ebd80837b8662b24133df75a67
Binary files /dev/null and b/app/assets/images/emoji/waxing_gibbous_moon.png differ
diff --git a/app/assets/images/emoji/wc.png b/app/assets/images/emoji/wc.png
new file mode 100755
index 0000000000000000000000000000000000000000..dfe84d2a73a115232d71c5ef6cee80d97270f39b
Binary files /dev/null and b/app/assets/images/emoji/wc.png differ
diff --git a/app/assets/images/emoji/weary.png b/app/assets/images/emoji/weary.png
new file mode 100755
index 0000000000000000000000000000000000000000..0c5475411c11e45c977dc062aff314cedce15d6b
Binary files /dev/null and b/app/assets/images/emoji/weary.png differ
diff --git a/app/assets/images/emoji/wedding.png b/app/assets/images/emoji/wedding.png
new file mode 100755
index 0000000000000000000000000000000000000000..ead19d52cfb41c033796c39dfc8ba877d304df1e
Binary files /dev/null and b/app/assets/images/emoji/wedding.png differ
diff --git a/app/assets/images/emoji/whale.png b/app/assets/images/emoji/whale.png
new file mode 100755
index 0000000000000000000000000000000000000000..5bb113e4289400d3ae646aea7499b6a1be8fc03d
Binary files /dev/null and b/app/assets/images/emoji/whale.png differ
diff --git a/app/assets/images/emoji/whale2.png b/app/assets/images/emoji/whale2.png
new file mode 100755
index 0000000000000000000000000000000000000000..4af657b2fdc98c2d703742d682cf952625224d63
Binary files /dev/null and b/app/assets/images/emoji/whale2.png differ
diff --git a/app/assets/images/emoji/wheelchair.png b/app/assets/images/emoji/wheelchair.png
new file mode 100755
index 0000000000000000000000000000000000000000..eddcdd7977aa74caed3a4546628ba44aa9863d8d
Binary files /dev/null and b/app/assets/images/emoji/wheelchair.png differ
diff --git a/app/assets/images/emoji/white_circle.png b/app/assets/images/emoji/white_circle.png
new file mode 100755
index 0000000000000000000000000000000000000000..da782ae297f150f92843164ffddbdfc14edf31d6
Binary files /dev/null and b/app/assets/images/emoji/white_circle.png differ
diff --git a/app/assets/images/emoji/white_flower.png b/app/assets/images/emoji/white_flower.png
new file mode 100755
index 0000000000000000000000000000000000000000..c0929d0dd9947a58766c19db54bef0c25edadff9
Binary files /dev/null and b/app/assets/images/emoji/white_flower.png differ
diff --git a/app/assets/images/emoji/white_square.png b/app/assets/images/emoji/white_square.png
new file mode 100755
index 0000000000000000000000000000000000000000..60cb19a1371a7de1d486d120f9b050970237a3b1
Binary files /dev/null and b/app/assets/images/emoji/white_square.png differ
diff --git a/app/assets/images/emoji/wind_chime.png b/app/assets/images/emoji/wind_chime.png
new file mode 100755
index 0000000000000000000000000000000000000000..efacf5dd4be4decef0704614b26f8121bfc2a250
Binary files /dev/null and b/app/assets/images/emoji/wind_chime.png differ
diff --git a/app/assets/images/emoji/wine_glass.png b/app/assets/images/emoji/wine_glass.png
new file mode 100755
index 0000000000000000000000000000000000000000..82b0f00057d62354d3e51f1c166e0f50e1326109
Binary files /dev/null and b/app/assets/images/emoji/wine_glass.png differ
diff --git a/app/assets/images/emoji/wink.png b/app/assets/images/emoji/wink.png
new file mode 100755
index 0000000000000000000000000000000000000000..756766dd3e9702e42082555bca7c71ba2aadf544
Binary files /dev/null and b/app/assets/images/emoji/wink.png differ
diff --git a/app/assets/images/emoji/wink2.png b/app/assets/images/emoji/wink2.png
new file mode 100755
index 0000000000000000000000000000000000000000..6ae9d497d304b776aa9db1e8423d5d2c104e3fe8
Binary files /dev/null and b/app/assets/images/emoji/wink2.png differ
diff --git a/app/assets/images/emoji/wolf.png b/app/assets/images/emoji/wolf.png
new file mode 100755
index 0000000000000000000000000000000000000000..c60c96895f7eb489a5ce2521302ebf20b59372e2
Binary files /dev/null and b/app/assets/images/emoji/wolf.png differ
diff --git a/app/assets/images/emoji/woman.png b/app/assets/images/emoji/woman.png
new file mode 100755
index 0000000000000000000000000000000000000000..6bf0d2b129cce03be314dbeb433d821c3d8e33a6
Binary files /dev/null and b/app/assets/images/emoji/woman.png differ
diff --git a/app/assets/images/emoji/womans_clothes.png b/app/assets/images/emoji/womans_clothes.png
new file mode 100755
index 0000000000000000000000000000000000000000..aa297c7b65e5cf94553a915cc300a8c6175403bd
Binary files /dev/null and b/app/assets/images/emoji/womans_clothes.png differ
diff --git a/app/assets/images/emoji/womans_hat.png b/app/assets/images/emoji/womans_hat.png
new file mode 100755
index 0000000000000000000000000000000000000000..4cb2e6a6934f102c624bf793303448a6b56c4660
Binary files /dev/null and b/app/assets/images/emoji/womans_hat.png differ
diff --git a/app/assets/images/emoji/womens.png b/app/assets/images/emoji/womens.png
new file mode 100755
index 0000000000000000000000000000000000000000..110f88519e88b40ec41bdc6ced1bd4929da79ce4
Binary files /dev/null and b/app/assets/images/emoji/womens.png differ
diff --git a/app/assets/images/emoji/wrench.png b/app/assets/images/emoji/wrench.png
new file mode 100755
index 0000000000000000000000000000000000000000..a87072ad132df27ee739cc5b241a8dfa64919702
Binary files /dev/null and b/app/assets/images/emoji/wrench.png differ
diff --git a/app/assets/images/emoji/x.png b/app/assets/images/emoji/x.png
new file mode 100755
index 0000000000000000000000000000000000000000..dff9efa8b43b02c432cec1624199a479576ce547
Binary files /dev/null and b/app/assets/images/emoji/x.png differ
diff --git a/app/assets/images/emoji/yellow_heart.png b/app/assets/images/emoji/yellow_heart.png
new file mode 100755
index 0000000000000000000000000000000000000000..fa41ce78ac44f13cffe227d24c4f25663372454e
Binary files /dev/null and b/app/assets/images/emoji/yellow_heart.png differ
diff --git a/app/assets/images/emoji/yen.png b/app/assets/images/emoji/yen.png
new file mode 100755
index 0000000000000000000000000000000000000000..139bc936e0f33bd6c546c1f50de941f901af13fe
Binary files /dev/null and b/app/assets/images/emoji/yen.png differ
diff --git a/app/assets/images/emoji/yum.png b/app/assets/images/emoji/yum.png
new file mode 100755
index 0000000000000000000000000000000000000000..fc39637ecd81ba4da58e15352442be6929d0941c
Binary files /dev/null and b/app/assets/images/emoji/yum.png differ
diff --git a/app/assets/images/emoji/zap.png b/app/assets/images/emoji/zap.png
new file mode 100755
index 0000000000000000000000000000000000000000..260c531b9e23171ca25cd30971ba06e28a3d7c74
Binary files /dev/null and b/app/assets/images/emoji/zap.png differ
diff --git a/app/assets/images/emoji/zero.png b/app/assets/images/emoji/zero.png
new file mode 100755
index 0000000000000000000000000000000000000000..6e57b3343adae7fe290485ceb885e1ccb5381c21
Binary files /dev/null and b/app/assets/images/emoji/zero.png differ
diff --git a/app/assets/images/emoji/zzz.png b/app/assets/images/emoji/zzz.png
new file mode 100755
index 0000000000000000000000000000000000000000..30be04655af5ff06c524ef43ace5b4ab10bad850
Binary files /dev/null and b/app/assets/images/emoji/zzz.png differ
diff --git a/app/assets/images/file_dir.png b/app/assets/images/file_dir.png
index 97b0539393d29c78a596f565087b9282df0f0291..ea277bb14dba38fa633a32675ee58b88b88f80a4 100644
Binary files a/app/assets/images/file_dir.png and b/app/assets/images/file_dir.png differ
diff --git a/app/assets/images/merge.png b/app/assets/images/merge.png
new file mode 100644
index 0000000000000000000000000000000000000000..4a6bb2e154d6f724080f232e5bbb9dc21f99f7fc
Binary files /dev/null and b/app/assets/images/merge.png differ
diff --git a/app/assets/javascripts/admin.js b/app/assets/javascripts/admin.js
deleted file mode 100644
index bb0a499a60707f80cd4d35a53a5d9f78a0471d62..0000000000000000000000000000000000000000
--- a/app/assets/javascripts/admin.js
+++ /dev/null
@@ -1,11 +0,0 @@
-$(document).ready(function(){
-    $('input#user_force_random_password').on('change', function(elem) {
-        var elems = $('#user_password, #user_password_confirmation');
-        
-        if ($(this).attr('checked')) {
-            elems.val('').attr('disabled', true);
-        } else {
-            elems.removeAttr('disabled');
-        }
-    });
-});
diff --git a/app/assets/javascripts/admin.js.coffee b/app/assets/javascripts/admin.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..76454c29269bc1e5d55ab26fca38cb46e240fdfc
--- /dev/null
+++ b/app/assets/javascripts/admin.js.coffee
@@ -0,0 +1,12 @@
+$ ->
+  $('input#user_force_random_password').on 'change', (elem) ->
+    elems = $('#user_password, #user_password_confirmation')
+
+    if $(@).attr 'checked'
+      elems.val('').attr 'disabled', true
+    else
+      elems.removeAttr 'disabled'
+
+  $('.log-tabs a').click (e) ->
+    e.preventDefault()
+    $(this).tab('show')
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index 24d99a62ca558d0456ef280617cfdd6f117943f8..f9fdb0f7dc2bcec3b9c1c22607425c279b7ba245 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -11,120 +11,9 @@
 //= require jquery.endless-scroll
 //= require jquery.highlight
 //= require jquery.waitforimages
-//= require bootstrap-modal
+//= require bootstrap
 //= require modernizr
 //= require chosen-jquery
 //= require raphael
 //= require branch-graph
 //= require_tree .
-
-$(document).ready(function(){
-
-  $(".one_click_select").live("click", function(){
-    $(this).select();
-  });
-
-  $('body').on('ajax:complete, ajax:beforeSend, submit', 'form', function(e){
-    var buttons = $('[type="submit"]', this);
-    switch( e.type ){
-      case 'ajax:beforeSend':
-      case 'submit':
-        buttons.attr('disabled', 'disabled');
-      break;
-      case ' ajax:complete':
-      default:
-        buttons.removeAttr('disabled');
-      break;
-    }
-  })
-
-  $(".account-box").mouseenter(showMenu);
-  $(".account-box").mouseleave(resetMenu);
-
-  $("#projects-list .project").live('click', function(e){
-    if(e.target.nodeName != "A" && e.target.nodeName != "INPUT") {
-      location.href = $(this).attr("url");
-      e.stopPropagation();
-      return false;
-    }
-  });
-
-  /**
-   * Focus search field by pressing 's' key
-   */
-  $(document).keypress(function(e) {
-    if( $(e.target).is(":input") ) return;
-    switch(e.which)  {
-      case 115:  focusSearch();
-        e.preventDefault();
-    }
-  });
-
-  /**
-   * Commit show suppressed diff
-   *
-   */
-  $(".supp_diff_link").bind("click", function() {
-    showDiff(this);
-  });
-
-  /**
-   * Note markdown preview
-   *
-   */
-  $(document).on('click', '#preview-link', function(e) {
-    $('#preview-note').text('Loading...');
-
-    var previewLinkText = ($(this).text() == 'Preview' ? 'Edit' : 'Preview');
-    $(this).text(previewLinkText);
-
-    var note = $('#note_note').val();
-    if (note.trim().length === 0) { note = 'Nothing to preview'; }
-    $.post($(this).attr('href'), {note: note}, function(data) {
-      $('#preview-note').html(data);
-    });
-
-    $('#preview-note, #note_note').toggle();
-    e.preventDefault();
-  });
-});
-
-function focusSearch() {
-  $("#search").focus();
-}
-
-function updatePage(data){
-  $.ajax({type: "GET", url: location.href, data: data, dataType: "script"});
-}
-
-function showMenu() {
-  $(this).toggleClass('hover');
-}
-
-function resetMenu() {
-  $(this).removeClass("hover");
-}
-
-function slugify(text) {
-  return text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase();
-}
-
-function showDiff(link) {
-  $(link).next('table').show();
-  $(link).remove();
-}
-
-(function($){
-    var _chosen = $.fn.chosen;
-    $.fn.extend({
-        chosen: function(options) {
-            var default_options = {'search_contains' : 'true'};
-            $.extend(default_options, options);
-            return _chosen.apply(this, [default_options]);
-    }})
-})(jQuery);
-
-
-function ajaxGet(url) {
-  $.ajax({type: "GET", url: url, dataType: "script"});
-}
diff --git a/app/assets/javascripts/graph.js b/app/assets/javascripts/graph.js
deleted file mode 100644
index 434cf70ac65cf5c18fe60f73a8613d77b8576aeb..0000000000000000000000000000000000000000
--- a/app/assets/javascripts/graph.js
+++ /dev/null
@@ -1,10 +0,0 @@
-function initGraphNav() { 
-  $(".graph svg").css("position", "relative");
-  $("body").bind("keyup", function(e) {
-    if(e.keyCode == 37) { // left
-      $(".graph svg").animate({ left: "+=400" });
-    } else if(e.keyCode == 39) { // right
-      $(".graph svg").animate({ left: "-=400" });
-    }
-  });
-}
diff --git a/app/assets/javascripts/graph.js.coffee b/app/assets/javascripts/graph.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..5fe8ae3f02021eaf90c1bb7ccbf6fce124e8c5ca
--- /dev/null
+++ b/app/assets/javascripts/graph.js.coffee
@@ -0,0 +1,10 @@
+initGraphNav = ->
+  $('.graph svg').css 'position', 'relative'
+
+  $('body').bind 'keyup', (e) ->
+    if e.keyCode is 37 # left
+      $('.graph svg').animate left: '+=400'
+    else if e.keyCode is 39 # right
+      $('.graph svg').animate left: '-=400'
+
+window.initGraphNav = initGraphNav
diff --git a/app/assets/javascripts/issues.js b/app/assets/javascripts/issues.js
index bc0569654e1004e12556ea9ad3b25b996558d833..3ddc6926ecdad9b569487c17fc667ebf25e4237a 100644
--- a/app/assets/javascripts/issues.js
+++ b/app/assets/javascripts/issues.js
@@ -5,6 +5,7 @@ function switchToNewIssue(form){
     $('select#issue_milestone_id').chosen();
     $("#new_issue_dialog").show("fade", { direction: "right" }, 150);
     $('.top-tabs .add_new').hide();
+    disableButtonIfEmptyField("#issue_title", ".save-btn");
   });
 }
 
@@ -15,6 +16,7 @@ function switchToEditIssue(form){
     $('select#issue_milestone_id').chosen();
     $("#edit_issue_dialog").show("fade", { direction: "right" }, 150);
     $('.add_new').hide();
+    disableButtonIfEmptyField("#issue_title", ".save-btn");
   });
 }
 
@@ -78,6 +80,10 @@ function issuesPage(){
     $(this).closest("form").submit();
   });
 
+  $("#new_issue_link").click(function(){
+    updateNewIssueURL();
+  });
+
   $('body').on('ajax:success', '.close_issue, .reopen_issue, #new_issue', function(){
     var t = $(this),
         totalIssues,
@@ -124,3 +130,20 @@ function issuesCheckChanged() {
     $('.issues_filters').show();
   }
 }
+
+function updateNewIssueURL(){
+  var new_issue_link = $("#new_issue_link");
+  var milestone_id = $("#milestone_id").val();
+  var assignee_id = $("#assignee_id").val();
+  var new_href = "";
+  if(milestone_id){
+    new_href = "issue[milestone_id]=" + milestone_id + "&";
+  }
+  if(assignee_id){
+    new_href = new_href + "issue[assignee_id]=" + assignee_id;
+  }
+  if(new_href.length){
+    new_href = new_issue_link.attr("href") + "?" + new_href;
+    new_issue_link.attr("href", new_href);
+  }
+};
diff --git a/app/assets/javascripts/loader.js b/app/assets/javascripts/loader.js
deleted file mode 100644
index 6fa0b5258148ce855e9fff4e75c20224efc19f2f..0000000000000000000000000000000000000000
--- a/app/assets/javascripts/loader.js
+++ /dev/null
@@ -1,11 +0,0 @@
-var Loader = { 
-  img_src: "/assets/ajax-loader.gif", 
-
-  html: 
-    function(width) { 
-      img = $("<img>");
-      img.attr("width", width);
-      img.attr("src", this.img_src);
-      return img;
-    }
-}
diff --git a/app/assets/javascripts/loader.js.coffee b/app/assets/javascripts/loader.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..66f8e8b1bb3a4caeaad8b0e9cd609efdc04bd3b1
--- /dev/null
+++ b/app/assets/javascripts/loader.js.coffee
@@ -0,0 +1,5 @@
+Loader =
+  html: (width) ->
+    $('<img>').attr src: '/assets/ajax-loader.gif', width: width
+
+window.Loader = Loader
diff --git a/app/assets/javascripts/main.js.coffee b/app/assets/javascripts/main.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..86b191626b3780949cd0e55aa2ffe81415de862a
--- /dev/null
+++ b/app/assets/javascripts/main.js.coffee
@@ -0,0 +1,92 @@
+window.updatePage = (data) ->
+  $.ajax({type: "GET", url: location.href, data: data, dataType: "script"})
+
+window.slugify = (text) ->
+  text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase()
+
+window.ajaxGet = (url) ->
+  $.ajax({type: "GET", url: url, dataType: "script"})
+
+ # Disable button if text field is empty
+window.disableButtonIfEmptyField = (field_selector, button_selector) ->
+  field = $(field_selector)
+  closest_submit = field.closest("form").find(button_selector)
+
+  closest_submit.disable() if field.val() is ""
+
+  field.on "keyup", ->
+    if $(this).val() is ""
+      closest_submit.disable()
+    else
+      closest_submit.enable()
+
+$ ->
+  # Click a .one_click_select field, select the contents
+  $(".one_click_select").live 'click', -> $(this).select()
+
+  # Initialize chosen selects
+  $('select.chosen').chosen()
+
+  # Disable form buttons while a form is submitting
+  $('body').on 'ajax:complete, ajax:beforeSend, submit', 'form', (e) ->
+    buttons = $('[type="submit"]', this)
+
+    switch e.type
+      when 'ajax:beforeSend', 'submit'
+        buttons.disable()
+      else
+        buttons.enable()
+
+  # Show/Hide the profile menu when hovering the account box
+  $('.account-box').hover -> $(this).toggleClass('hover')
+
+  # Focus search field by pressing 's' key
+  $(document).keypress (e) ->
+    # Don't do anything if typing in an input
+    return if $(e.target).is(":input")
+
+    switch e.which
+      when 115
+        $("#search").focus()
+        e.preventDefault()
+
+  # Commit show suppressed diff
+  $(".supp_diff_link").bind "click", ->
+    $(this).next('table').show()
+    $(this).remove()
+
+  # Note markdown preview
+  $(document).on 'click', '#preview-link', (e) ->
+    $('#preview-note').text('Loading...')
+
+    previewLinkText = if $(this).text() == 'Preview' then 'Edit' else 'Preview'
+    $(this).text(previewLinkText)
+
+    note = $('#note_note').val()
+
+    if note.trim().length == 0
+      $('#preview-note').text("Nothing to preview.")
+    else
+      $.post $(this).attr('href'), {note: note}, (data) ->
+        $('#preview-note').html(data)
+
+    $('#preview-note, #note_note').toggle()
+    e.preventDefault()
+    false
+
+(($) ->
+  _chosen = $.fn.chosen
+  $.fn.extend chosen: (options) ->
+    default_options = search_contains: "true"
+    $.extend default_options, options
+    _chosen.apply this, [default_options]
+
+  # Disable an element and add the 'disabled' Bootstrap class
+  $.fn.extend disable: ->
+    $(this).attr('disabled', 'disabled').addClass('disabled')
+
+  # Enable an element and remove the 'disabled' Bootstrap class
+  $.fn.extend enable: ->
+    $(this).removeAttr('disabled').removeClass('disabled')
+
+)(jQuery)
diff --git a/app/assets/javascripts/note.js b/app/assets/javascripts/note.js
deleted file mode 100644
index d9ae45d93c7772afd0268525b297f5d625ce59c7..0000000000000000000000000000000000000000
--- a/app/assets/javascripts/note.js
+++ /dev/null
@@ -1,169 +0,0 @@
-var NoteList = {
-
-notes_path: null,
-target_params: null,
-target_id: 0,
-target_type: null,
-first_id: 0,
-last_id: 0,
-disable:false,
-
-init:
-  function(tid, tt, path) {
-    this.notes_path = path + ".js";
-    this.target_id = tid;
-    this.target_type = tt;
-    this.target_params = "&target_type=" + this.target_type + "&target_id=" + this.target_id;
-
-    // get notes
-    this.getContent();
-
-    // get new notes every n seconds
-    this.initRefresh();
-
-    $('.delete-note').live('ajax:success', function() {
-      $(this).closest('li').fadeOut(); });
-
-    $("#new_note").live("ajax:before", function(){
-      $(".submit_note").attr("disabled", "disabled");
-    })
-
-    $("#new_note").live("ajax:complete", function(){
-      $(".submit_note").removeAttr("disabled");
-    })
-
-    $("#note_note").live("focus", function(){
-      $(this).css("height", "80px");
-      $('.note_advanced_opts').show();
-    });
-
-    $("#note_attachment").change(function(e){
-        var val = $('.input-file').val();
-        var filename = val.replace(/^.*[\\\/]/, '');
-        $(".file_name").text(filename);
-    });
-
-  },
-
-
-/**
- * Load new notes to fresh list called 'new_notes_list': 
- * - Replace 'new_notes_list' with new list every n seconds
- * - Append new notes to this list after submit
- */
-
-initRefresh:
-  function() {
-    // init timer
-    var intNew = setInterval("NoteList.getNew()", 10000);
-  },
-
-replace:
-  function(html) {
-    $("#new_notes_list").html(html);
-  },
-
-prepend:
-  function(id, html) {
-    if(id != this.last_id) {
-      $("#new_notes_list").prepend(html);
-    }
-  },
-
-getNew:
-  function() {
-    // refersh notes list
-    $.ajax({
-      type: "GET",
-      url: this.notes_path,
-      data: "last_id=" + this.last_id + this.target_params,
-      dataType: "script"});
-  },
-
-refresh:
-  function() {
-    // refersh notes list
-    $.ajax({
-      type: "GET",
-      url: this.notes_path,
-      data: "first_id=" + this.first_id + "&last_id=" + this.last_id + this.target_params,
-      dataType: "script"});
-  },
-
-
-/**
- * Init load of notes: 
- * 1. Get content with ajax call
- * 2. Set content of notes list with loaded one
- */
-
-
-getContent: 
-  function() { 
-    $.ajax({
-      type: "GET",
-      url: this.notes_path,
-      data: "?" + this.target_params,
-      complete: function(){ $('.status').removeClass("loading")},
-      beforeSend: function() { $('.status').addClass("loading") },
-      dataType: "script"});
-  },
-
-setContent:
-  function(fid, lid, html) {
-      this.last_id = lid;
-      this.first_id = fid;
-      $("#notes-list").html(html);
-
-      // Init infinite scrolling
-      this.initLoadMore();
-  },
-
-
-/**
- * Paging for old notes when scroll to bottom: 
- * 1. Init scroll events with 'initLoadMore'
- * 2. Load onlder notes with 'getOld' method
- * 3. append old notes to bottom of list with 'append'
- *
- */
-
-
-getOld:
-  function() {
-    $('.loading').show();
-    $.ajax({
-      type: "GET",
-      url: this.notes_path,
-      data: "first_id=" + this.first_id + this.target_params,
-      complete: function(){ $('.status').removeClass("loading")},
-      beforeSend: function() { $('.status').addClass("loading") },
-      dataType: "script"});
-  },
-
-append:
-  function(id, html) {
-    if(this.first_id == id) { 
-      this.disable = true;
-    } else { 
-      this.first_id = id;
-      $("#notes-list").append(html);
-    }
-  },
-
-
-initLoadMore:
-  function() {
-    $(document).endlessScroll({
-      bottomPixels: 400,
-      fireDelay: 1000,
-      fireOnce:true,
-      ceaseFire: function() { 
-        return NoteList.disable;
-      },
-      callback: function(i) {
-        NoteList.getOld();
-      }
-   });
-  }
-}
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
new file mode 100644
index 0000000000000000000000000000000000000000..e1ad1d2f9e8c04d941863efa5854ae59c1be6cba
--- /dev/null
+++ b/app/assets/javascripts/notes.js
@@ -0,0 +1,293 @@
+var NoteList = {
+
+  notes_path: null,
+  target_params: null,
+  target_id: 0,
+  target_type: null,
+  top_id: 0,
+  bottom_id: 0,
+  loading_more_disabled: false,
+  reversed: false,
+
+  init:
+    function(tid, tt, path) {
+      this.notes_path = path + ".js";
+      this.target_id = tid;
+      this.target_type = tt;
+      this.reversed = $("#notes-list").hasClass("reversed");
+      this.target_params = "&target_type=" + this.target_type + "&target_id=" + this.target_id;
+
+      // get initial set of notes
+      this.getContent();
+
+      $("#notes-list, #new-notes-list").on("ajax:success", ".delete-note", function() {
+        $(this).closest('li').fadeOut(function() {
+          $(this).remove();
+          NoteList.updateVotes();
+        });
+      });
+
+      $(".note-form-holder").on("ajax:before", function(){
+        $(".submit_note").disable();
+      })
+
+      $(".note-form-holder").on("ajax:complete", function(){
+        $(".submit_note").enable();
+      })
+
+      disableButtonIfEmptyField(".note-text", ".submit_note");
+
+      $("#note_attachment").change(function(e){
+        var val = $('.input-file').val();
+        var filename = val.replace(/^.*[\\\/]/, '');
+        $(".file_name").text(filename);
+      });
+
+      if(this.reversed) {
+        var textarea = $(".note-text");
+        $('.note_advanced_opts').hide();
+        textarea.css("height", "40px");
+        textarea.on("focus", function(){
+          $(this).css("height", "80px");
+          $('.note_advanced_opts').show();
+        });
+      }
+    },
+
+
+  /**
+   * Handle loading the initial set of notes.
+   * And set up loading more notes when scrolling to the bottom of the page.
+   */
+
+
+  /**
+   * Gets an inital set of notes.
+   */
+  getContent:
+    function() {
+      $.ajax({
+        type: "GET",
+      url: this.notes_path,
+      data: "?" + this.target_params,
+      complete: function(){ $('.notes-status').removeClass("loading")},
+      beforeSend: function() { $('.notes-status').addClass("loading") },
+      dataType: "script"});
+    },
+
+  /**
+   * Called in response to getContent().
+   * Replaces the content of #notes-list with the given html.
+   */
+  setContent:
+    function(first_id, last_id, html) {
+      this.top_id = first_id;
+      this.bottom_id = last_id;
+      $("#notes-list").html(html);
+
+      // init infinite scrolling
+      this.initLoadMore();
+
+      // init getting new notes
+      if (this.reversed) {
+        this.initRefreshNew();
+      }
+    },
+
+
+  /**
+   * Handle loading more notes when scrolling to the bottom of the page.
+   * The id of the last note in the list is in this.bottom_id.
+   *
+   * Set up refreshing only new notes after all notes have been loaded.
+   */
+
+
+  /**
+   * Initializes loading more notes when scrolling to the bottom of the page.
+   */
+  initLoadMore:
+    function() {
+      $(document).endlessScroll({
+        bottomPixels: 400,
+        fireDelay: 1000,
+        fireOnce:true,
+        ceaseFire: function() {
+          return NoteList.loading_more_disabled;
+        },
+        callback: function(i) {
+          NoteList.getMore();
+        }
+      });
+    },
+
+  /**
+   * Gets an additional set of notes.
+   */
+  getMore:
+    function() {
+      // only load more notes if there are no "new" notes
+      $('.loading').show();
+      $.ajax({
+        type: "GET",
+        url: this.notes_path,
+        data: "loading_more=1&" + (this.reversed ? "before_id" : "after_id") + "=" + this.bottom_id + this.target_params,
+        complete: function(){ $('.notes-status').removeClass("loading")},
+        beforeSend: function() { $('.notes-status').addClass("loading") },
+        dataType: "script"});
+    },
+
+  /**
+   * Called in response to getMore().
+   * Append notes to #notes-list.
+   */
+  appendMoreNotes:
+    function(id, html) {
+      if(id != this.bottom_id) {
+        this.bottom_id = id;
+        $("#notes-list").append(html);
+      }
+    },
+
+  /**
+   * Called in response to getMore().
+   * Disables loading more notes when scrolling to the bottom of the page.
+   * Initalizes refreshing new notes.
+   */
+  finishedLoadingMore:
+    function() {
+      this.loading_more_disabled = true;
+
+      // from now on only get new notes
+      if (!this.reversed) {
+        this.initRefreshNew();
+      }
+      // make sure we are up to date
+      this.updateVotes();
+    },
+
+
+  /**
+   * Handle refreshing and adding of new notes.
+   *
+   * New notes are all notes that are created after the site has been loaded.
+   * The "old" notes are in #notes-list the "new" ones will be in #new-notes-list.
+   * The id of the last "old" note is in this.bottom_id.
+   */
+
+
+  /**
+   * Initializes getting new notes every n seconds.
+   */
+  initRefreshNew:
+    function() {
+      setInterval("NoteList.getNew()", 10000);
+    },
+
+  /**
+   * Gets the new set of notes.
+   */
+  getNew:
+    function() {
+      $.ajax({
+        type: "GET",
+      url: this.notes_path,
+      data: "loading_new=1&after_id=" + (this.reversed ? this.top_id : this.bottom_id) + this.target_params,
+      dataType: "script"});
+    },
+
+  /**
+   * Called in response to getNew().
+   * Replaces the content of #new-notes-list with the given html.
+   */
+  replaceNewNotes:
+    function(html) {
+      $("#new-notes-list").html(html);
+      this.updateVotes();
+    },
+
+  /**
+   * Adds a single note to #new-notes-list.
+   */
+  appendNewNote:
+    function(id, html) {
+      if (this.reversed) {
+        $("#new-notes-list").prepend(html);
+      } else {
+        $("#new-notes-list").append(html);
+      }
+      this.updateVotes();
+    },
+
+  /**
+   * Recalculates the votes and updates them (if they are displayed at all).
+   *
+   * Assumes all relevant notes are displayed (i.e. there are no more notes to
+   * load via getMore()).
+   * Might produce inaccurate results when not all notes have been loaded and a
+   * recalculation is triggered (e.g. when deleting a note).
+   */
+  updateVotes:
+    function() {
+      var votes = $("#votes .votes");
+      var notes = $("#notes-list, #new-notes-list").find(".note.vote");
+
+      // only update if there is a vote display
+      if (votes.size()) {
+        var upvotes = notes.filter(".upvote").size();
+        var downvotes = notes.filter(".downvote").size();
+        var votesCount = upvotes + downvotes;
+        var upvotesPercent = votesCount ? (100.0 / votesCount * upvotes) : 0;
+        var downvotesPercent = votesCount ? (100.0 - upvotesPercent) : 0;
+
+        // change vote bar lengths
+        votes.find(".bar-success").css("width", upvotesPercent+"%");
+        votes.find(".bar-danger").css("width", downvotesPercent+"%");
+        // replace vote numbers
+        votes.find(".upvotes").text(votes.find(".upvotes").text().replace(/\d+/, upvotes));
+        votes.find(".downvotes").text(votes.find(".downvotes").text().replace(/\d+/, downvotes));
+      }
+    }
+};
+
+var PerLineNotes = {
+  init:
+    function() {
+      /**
+       * Called when clicking on the "add note" or "reply" button for a diff line.
+       *
+       * Shows the note form below the line.
+       * Sets some hidden fields in the form.
+       */
+      $(".diff_file_content").on("click", ".line_note_link, .line_note_reply_link", function(e) {
+        var form = $(".per_line_form");
+        $(this).closest("tr").after(form);
+        form.find("#note_line_code").val($(this).data("lineCode"));
+        form.show();
+        return false;
+      });
+
+      disableButtonIfEmptyField(".line-note-text", ".submit_inline_note");
+
+      /**
+       * Called in response to successfully deleting a note on a diff line.
+       *
+       * Removes the actual note from view.
+       * Removes the reply button if the last note for that line has been removed.
+       */
+      $(".diff_file_content").on("ajax:success", ".delete-note", function() {
+        var trNote = $(this).closest("tr");
+        trNote.fadeOut(function() {
+          $(this).remove();
+        });
+
+        // check if this is the last note for this line
+        // elements must really be removed for this to work reliably
+        var trLine = trNote.prev();
+        var trRpl  = trNote.next();
+        if (trLine.hasClass("line_holder") && trRpl.hasClass("reply")) {
+          trRpl.fadeOut(function() { $(this).remove(); });
+        }
+      });
+    }
+}
diff --git a/app/assets/javascripts/projects.js b/app/assets/javascripts/projects.js
deleted file mode 100644
index 842726981d3faefd9b1d4db4426ad90fdfd52651..0000000000000000000000000000000000000000
--- a/app/assets/javascripts/projects.js
+++ /dev/null
@@ -1,14 +0,0 @@
-function Projects() { 
-  $("#project_name").live("change", function(){
-    var slug = slugify($(this).val());
-    $("#project_code").val(slug);
-    $("#project_path").val(slug);
-  });
-
-  $('.new_project, .edit_project').live('ajax:before', function() {
-    $('.project_new_holder, .project_edit_holder').hide();
-    $('.ajax_loader').show();
-  });
-
-  $('form #project_default_branch').chosen();
-}
diff --git a/app/assets/javascripts/projects.js.coffee b/app/assets/javascripts/projects.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..008fa8e91164c65a0492015e49da21b35c9dc1ef
--- /dev/null
+++ b/app/assets/javascripts/projects.js.coffee
@@ -0,0 +1,24 @@
+window.Projects = ->
+  $('#project_name').on 'change', ->
+    slug = slugify $(@).val()
+    $('#project_code, #project_path').val slug
+
+  $('.new_project, .edit_project').on 'ajax:before', ->
+    $('.project_new_holder, .project_edit_holder').hide()
+    $('.save-project-loader').show()
+
+  $('form #project_default_branch').chosen()
+  disableButtonIfEmptyField '#project_name', '.project-submit'
+
+$ ->
+  # Git clone panel switcher
+  scope = $ '.project_clone_holder'
+  if scope.length > 0
+    $('a, button', scope).click ->
+      $('a, button', scope).removeClass 'active'
+      $(@).addClass 'active'
+      $('#project_clone', scope).val $(@).data 'clone'
+
+  # Ref switcher
+  $('.project-refs-select').on 'change', ->
+    $(@).parents('form').submit()
diff --git a/app/assets/javascripts/snippets.js b/app/assets/javascripts/snippets.js
deleted file mode 100644
index 11e18eb779e91d61b75c283d1776e2e49988ca82..0000000000000000000000000000000000000000
--- a/app/assets/javascripts/snippets.js
+++ /dev/null
@@ -1,9 +0,0 @@
-$(document).ready(function(){
-  $("#snippets-table .snippet").live('click', function(e){
-    if(e.target.nodeName != "A" && e.target.nodeName != "INPUT") {
-      location.href = $(this).attr("url");
-      e.stopPropagation();
-      return false;
-    }
-  });
-});
diff --git a/app/assets/javascripts/snippets.js.coffee b/app/assets/javascripts/snippets.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..af4385deb51d5045307ba23b16cab0bd23b5d457
--- /dev/null
+++ b/app/assets/javascripts/snippets.js.coffee
@@ -0,0 +1,6 @@
+$ ->
+  $('#snippets-table .snippet').live 'click', (e) ->
+    if e.target.nodeName isnt 'A' and e.target.nodeName isnt 'INPUT'
+      location.href = $(@).attr 'url'
+      e.stopPropagation()
+      false
diff --git a/app/assets/javascripts/team.js b/app/assets/javascripts/team.js
deleted file mode 100644
index f4b04354f5307391ecfdf67492de63ae82ca14c6..0000000000000000000000000000000000000000
--- a/app/assets/javascripts/team.js
+++ /dev/null
@@ -1,8 +0,0 @@
-function backToMembers(){
-  $("#new_team_member").hide("slide", { direction: "right" }, 150, function(){
-    $("#team-table").show("slide", { direction: "left" }, 150, function() { 
-      $("#new_team_member").remove();
-      $(".add_new").show();
-    });
-  });
-}
diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss
index 3c160358428456d3e45a0c5a597d264a78bfbc05..c5b379160867a821ed5cf74f68c3939371203a9e 100644
--- a/app/assets/stylesheets/common.scss
+++ b/app/assets/stylesheets/common.scss
@@ -1,11 +1,9 @@
-.diff_file_header a,
-.file_stats a {
-  color:$style_color;
-}
-
-
 /** LAYOUT **/
 
+body {
+  margin-bottom:20px;
+}
+
 .container {
   padding-top:0;
   z-index:5;
@@ -40,30 +38,6 @@
   color: $link_color;
 }
 
-.widget {
-  @include shade;
-  padding:20px;
-  margin-bottom:20px;
-  border: 1px solid #DDD;
-  border-radius: 5px;
-  background:#fafafa;
-
-  .link_holder {
-    background:#eee;
-    position:relative;
-    left:-20px;
-    top:20px;
-    padding:10px 20px;
-    width:100%;
-    border-top:1px solid #ccc;
-
-    a {
-      font-size:14px;
-      color:#666;
-    }
-  }
-}
-
 .help li { color:#111 }
 
 .back_link {
@@ -88,16 +62,6 @@
   padding-left:20px;
 }
 
-.number {
-  border-radius: 4px;
-  text-shadow: none;
-  background: rgba(0,0,0,.12);
-  text-align: center;
-  padding: 2px 4px;
-  line-height:18px;
-  margin-left:2px;
-}
-
 table a code {
   position: relative;
   top: -2px;
@@ -129,26 +93,18 @@ table a code {
   border-bottom:1px solid #ccc;
 
   h4 {
-    color:#444;
-    font-size:22px;
+    color:#666;
+    font-size:18px;
+    line-height:38px;
     padding-top:5px;
     margin:2px;
+    font-weight:normal;
   }
 }
 
 .git_url_wrapper {
   margin-right:50px
 }
-.file_stats {
-  span {
-    img {
-      width:14px;
-      float:left;
-      margin-right:6px;
-      padding:2px 0;
-    }
-  }
-}
 
 .handle:hover {
   cursor:move;
@@ -172,10 +128,6 @@ span.update-author {
   display:block;
 }
 /** END UPDATE ITEM **/
-.ajax-tab-loading {
-  padding:40px;
-  display:none;
-}
 .dashboard-loader {
   float:left;
   margin:10px;
@@ -186,15 +138,144 @@ span.update-author {
   font-weight:bold;
 }
 
-a.project-update.titled {
-  position:relative;
-  padding-left:35% !important;
-  .title-block {
-    padding:10px;
-    width:35%;
-    position:absolute;
-    left:0;
-    top:0;
+.neib {
+  margin-right:10px;
+}
+
+.label {
+  background-color: #474D57;
+
+  &.label-tag {
+    background: none;
+    border: none;
+    padding:4px 6px;
+    color:#444;
+    text-shadow:0 0 1px #fff;
+
+    &.grouped {
+      float: left;
+      margin-right: 6px;
+      padding: 6px;
+    }
+  }
+  &.label-issue {
+    background-color: #eee;
+    border: 1px solid #ccc;
+    padding:4px 6px;
+    color:#444;
+    text-shadow:0 0 1px #fff;
+
+    &.grouped {
+      float: left;
+      margin-right: 6px;
+      padding: 6px;
+    }
+  }
+
+  &.label-success {
+    background-color: #8D8;
+    color: #333;
+    text-shadow: 0 1px 1px white;
+  }
+
+  &.label-error {
+    background-color: #D88;
+    color: #333;
+    text-shadow: 0 1px 1px white;
+  }
+}
+
+.event_label {
+  @extend .label;
+  background-color: #999;
+
+  &.pushed {
+    background-color: #4A97BD;
+  }
+
+  &.opened {
+    background-color: #469847;
+  }
+
+  &.closed {
+    background-color: #B94A48;
+  }
+
+  &.merged {
+    background-color: #2A2;
+  }
+
+  &.joined {
+    background-color: #1ca9dd;
+  }
+
+  &.left {
+    background-color: #888;
+    float:none;
+  }
+}
+
+form {
+  @extend .form-horizontal;
+
+  .actions {
+    @extend .form-actions;
+  }
+
+  .clearfix {
+    @extend .control-group;
+  }
+
+  .input {
+    @extend .controls;
+  }
+
+  label {
+    @extend .control-label;
+  }
+  .xlarge {
+    @extend .input-xlarge;
+  }
+  .xxlarge {
+    @extend .input-xxlarge;
+  }
+}
+
+
+.field_with_errors {
+  display:inline;
+}
+
+ul.breadcrumb {
+  background:white;
+  border:none;
+  li {
+    display: inline;
+    text-shadow: 0 1px 0 white
+  }
+
+  a {
+    color:#474D57;
+    font-weight:bold;
+    font-size:14px;
+  }
+
+  .arrow {
+    background: url("images.png") no-repeat -85px -77px;
+    width: 19px;
+    height: 16px;
+    float: left;
+    position: relative;
+    left: -10px;
+    padding:0;
+    margin:0;
+  }
+}
+
+input[type=text] {
+  &.large_text {
+    padding:6px;
+    font-size:16px;
   }
 }
 
@@ -270,40 +351,6 @@ p.time {
 }
 
 
-/**
- * Dashboard page
- *
- */
-.dashboard_category {
-  margin-bottom:30px;
-  h3 a {
-    color:#474D57;
-    &:hover {
-      text-decoration:underline;
-    }
-  }
-
-  .dashboard_block {
-    .dash_project_item {
-      margin-bottom:10px;
-      border:none;
-      padding:0px 5px;
-      .project_link {
-        color:#888;
-        &:hover {
-          color:#111;
-          .ico.project {
-            background-position:-209px -21px;
-          }
-        }
-      }
-      h4 {
-        color:#666;
-      }
-    }
-  }
-}
-
 .styled_image {
   border:2px solid #ddd;
 }
@@ -393,46 +440,48 @@ p.time {
   }
 }
 
-.btn {
-  &.very_small {
-    font-size:11px;
-    padding:2px 6px;
-    margin:2px;
+.votes {
+  font-size: 13px;
+  line-height: 15px;
+  .progress {
+    height: 4px;
+    margin: 0;
+    .bar {
+      float: left;
+      height: 100%;
+    }
+    .bar-success {
+      background-color: #468847;
+      @include bg-gradient(#62C462, #51A351);
+    }
+    .bar-danger {
+      background-color: #B94A48;
+      @include bg-gradient(#EE5F5B, #BD362F);
+    }
   }
-
-  &.grouped {
-    margin-right:7px;
-    float:left;
+  .upvotes {
+    display: inline-block;
+    color: #468847;
   }
-
-  &.padded {
-    margin-right:3px;
-    padding:4px 10px 4px;
+  .downvotes {
+    display: inline-block;
+    color: #B94A48;
   }
 }
-
-
-.prettyprint {
-  background-color: #fefbf3;
-  padding: 9px;
-  border: 1px solid rgba(0,0,0,.2);
-  -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.1);
-  -moz-box-shadow: 0 1px 2px rgba(0,0,0,.1);
-  box-shadow: 0 1px 2px rgba(0,0,0,.1);
-}
-
-.hint {
-  font-style: italic;
-  color: #999;
+.votes-block {
+  margin: 14px 6px 6px 0;
+  .downvotes {
+    float: right;
+  }
 }
-
-.upvotes {
-  font-size: 14px;
-  font-weight: bold;
-  color: #468847;
-  text-align: right;
-  padding: 4px;
-  margin: 2px;
+.votes-inline {
+  display: inline-block;
+  margin: 0 8px;
+  .progress {
+    display: inline-block;
+    padding: 0 0 2px;
+    width: 45px;
+  }
 }
 
 /* Fix for readme code (stopped it from being yellow) */
@@ -549,14 +598,6 @@ li.note {
 }
 
 
-/**
- * Milestones list
- *
- */
-
-.milestone {
-  @extend .wll;
-}
 
 /**
  * Admin area
@@ -603,11 +644,10 @@ li.note {
  *
  */
 .event_lp {
-  @extend .alert-info;
+  @extend .ui-box;
+  color:#777;
   margin-bottom:20px;
   padding:8px;
-  border-style: solid;
-  border-width: 1px;
   @include border-radius(4px);
   min-height:22px;
 
@@ -621,88 +661,19 @@ li.note {
   cursor:pointer;
 }
 
-/**
- *  Issues, MRs legend
- *
- */
-
-.list_legend {
-  float:left;
-  margin-right:20px;
-  .icon {
-    width:12px;
-    height:12px;
-    float:left;
-    margin-right:5px;
-    margin-top: 2px;
-    @include border-radius(4px);
-    &.today{
-      background: #ADA;
-      border:1px solid #8B8;
-    }
-    &.closed {
-      background: #DDD;
-      border:1px solid  #BBB;
-    }
-    &.yours {
-      background: #AAD;
-      border:1px solid #88B;
-    }
-    &.merged {
-      background: #DAD;
-      border:1px solid #B8B;
-    }
-  }
-  .text {
-    padding-bottom: 10px;
-    float:left;
-  }
-}
-
 .merge_request,
 .issue {
-  .list_legend {
-    margin-right: 5px;
-    margin-top: 14px;
-    .icon {
-      width:8px;
-      height:8px;
-      float:left;
-      margin-right:5px;
-      @include border-radius(4px);
-      border:1px solid #ddd;
-    }
-  }
-
   &.today{
     background: #EFE;
     border-color:#CEC;
-    .icon {
-      background: #ADA;
-      border:1px solid #8B8;
-    }
   }
   &.closed {
     background: #F5f5f5;
     border-color:#E5E5E5;
-    .icon {
-      background: #DDD;
-      border:1px solid  #BBB;
-    }
-  }
-  &.yours {
-    .icon {
-      background: #AAD;
-      border:1px solid #88B;
-    }
   }
   &.merged {
     background: #F5f5f5;
     border-color:#E5E5E5;
-    .icon {
-      background: #DAD;
-      border:1px solid #B8B;
-    }
   }
 }
 
@@ -714,7 +685,7 @@ li.note {
     margin-right:40px;
 
     .prev {
-      @extend .borders;
+      @extend .thumbnail;
       height:120px;
       width:175px;
       margin-bottom:10px;
@@ -743,3 +714,31 @@ li.note {
   text-align:center;
   margin-bottom:10px;
 }
+
+.oauth_select_holder {
+  padding:20px;
+  img {
+    padding:5px;
+    margin-right:10px;
+  }
+  .active {
+    img {
+      border:1px solid #ccc;
+      background:$hover;
+      @include border-radius(5px);
+    }
+  }
+}
+
+.btn-build-token {
+  float: left;
+  padding: 6px 20px;
+  margin-right: 12px;
+}
+
+.gitlab-promo {
+  a {
+    color:#aaa;
+    margin-right: 30px;
+  }
+}
diff --git a/app/assets/stylesheets/gitlab_bootstrap.scss b/app/assets/stylesheets/gitlab_bootstrap.scss
deleted file mode 100644
index 03beeaefd20113e571fade19bf05885dcf30c5b4..0000000000000000000000000000000000000000
--- a/app/assets/stylesheets/gitlab_bootstrap.scss
+++ /dev/null
@@ -1,832 +0,0 @@
-body {
-  margin-bottom:20px;
-}
-
-pre {
-  font-family:'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
-
-  &.dark {
-    background: #333;
-    color:#f5f5f5;
-  }
-}
-
-a {
-  outline: none;
-  color: $link_color;
-  &:hover {
-    text-decoration:none;
-    color: $blue_link;
-  }
-
-  &.btn {
-    color: $style_color;
-  }
-
-  &.dark {
-    color: $style_color;
-  }
-
-  &.lined {
-    text-decoration:underline;
-    &:hover { text-decoration:underline; }
-  }
-
-  &.gray {
-    color:gray;
-  }
-
-  &.supp_diff_link {
-    text-align:center;
-    padding:20px 0;
-    background:#f1f1f1;
-    width:100%;
-    float:left;
-  }
-
-  &.neib  {
-    margin-right:15px;
-  }
-}
-
-.neib {
-  margin-right:10px;
-}
-
-.alert-message {
-  @extend .alert;
-
-  &.success {
-    @extend .alert-success;
-  }
-
-  &.error {
-    @extend .alert-error;
-  }
-}
-
-.alert {
-  &.alert-well {
-    background:#ddd;
-    border:1px solid #ccc;
-    background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #ddd), to(#dfdfdf));
-    background-image: -webkit-linear-gradient(#ddd 6.6%, #dfdfdf);
-    background-image: -moz-linear-gradient(#ddd 6.6%, #dfdfdf);
-    background-image: -o-linear-gradient(#ddd 6.6%, #dfdfdf);
-    color:#111;
-  }
-}
-
-h3, h4, h5, h6 {
-  line-height: 36px;
-}
-
-h5 {
-  font-size:14px;
-}
-
-
-table {
-  width:100%;
-  th {
-    padding-top: 9px;
-    font-weight: bold;
-    vertical-align: middle;
-  }
-  th, td {
-    padding: 10px 10px 9px;
-    line-height: 18px;
-    text-align: left;
-  }
-
-  &.bordered-table {
-    border: 1px solid #DDD;
-    border-collapse: separate;
-    -webkit-border-radius: 4px;
-    -moz-border-radius: 4px;
-    border-radius: 4px;
-  }
-
-  &.zebra-striped {
-    @extend .table-striped;
-  }
-}
-
-.btn {
-  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f1f1f1), color-stop(25%, #f1f1f1), to(#e6e6e6));
-  background-image: -webkit-linear-gradient(#f1f1f1, #f1f1f1 25%, #e6e6e6);
-  background-image: -moz-linear-gradient(top, #f1f1f1, #f1f1f1 25%, #e6e6e6);
-  background-image: -ms-linear-gradient(#f1f1f1, #f1f1f1 25%, #e6e6e6);
-  background-image: -o-linear-gradient(#f1f1f1, #f1f1f1 25%, #e6e6e6);
-  background-image: linear-gradient(#f1f1f1, #f1f1f1 25%, #e6e6e6);
-
-  &:hover {
-  }
-
-  &.btn-primary {
-    background:$link_color;
-    border-color: #2A79A3;
-    &:hover {
-      background:$blue_link;
-    }
-  }
-  &.primary {
-    @extend .btn-primary;
-  }
-
-  &.success {
-    color: #fff;
-    text-shadow: 0 0 1px #111;
-    background: #5bb75b;;
-    font-weight: bold;
-
-    &:hover {
-      background-color: #51a351;
-      color: #fff;
-    }
-  }
-
-  &.danger,
-  &.btn-danger {
-    color:#fff;
-    background: #DA4E49;
-    border-color: #BD362F;
-
-    &:hover {
-      color:#fff;
-      background: #EE4E49;
-    }
-  }
-
-  &.danger {
-    @extend .btn-danger;
-  }
-
-  &.small {
-    @extend .btn-small;
-  }
-
-  &.active {
-    border-color:#aaa;
-    background-color:#ccc;
-  }
-}
-
-a:focus {
-  outline: none;
-}
-
-.nav-pills a:hover {
-  background-color:#888;
-}
-
-.nav-pills .active a {
-  background-color: $style_color;
-}
-
-.label {
-  background-color: #474D57;
-  &.label-important {
-    background-color: #B94A48;
-  }
-
-  &.label-issue {
-    background-color: #eee;
-    border: 1px solid #ccc;
-    padding:4px 6px;
-    color:#444;
-    text-shadow:0 0 1px #fff;
-
-    &.grouped {
-      float: left;
-      margin-right: 6px;
-      padding: 6px;
-    }
-  }
-}
-
-.nav-tabs > li > a, .nav-pills > li > a {
-  color:$style_color;
-}
-
-.nav-tabs > .active > a {
-  font-weight:bold;
-}
-
-/** COLORS **/
-.cgray { color:gray; }
-.cred { color:#D12F19; }
-.cgreen { color:#44aa22; }
-.cblack { color:#111; }
-.cdark { color:#444 }
-.cwhite { color:#fff !important }
-.bgred { background: #F2DEDE !important}
-
-/** COMMON STYLES **/
-.left {
-  float:left;
-}
-.right {
-  float:right !important;
-}
-.width-50p{
-  width:50%;
-}
-.width-49p{
-  width:49%;
-}
-.width-30p{
-  width:30%;
-}
-.width-65p{
-  width:65%;
-}
-.width-100p{
-  width:100%;
-}
-.append-bottom-10 {
-  margin-bottom:10px;
-}
-.append-bottom-20 {
-  margin-bottom:20px;
-}
-.prepend-top-10 {
-  margin-top:10px;
-}
-
-.prepend-top-20 {
-  margin-top:20px;
-}
-
-.padded {
-  padding:20px;
-}
-
-.ipadded {
-  padding:20px !important;
-}
-.lborder {
-  border-left:1px solid #eee;
-}
-
-.borders {
-  border: 1px solid #ccc;
-  @include shade;
-}
-.no-borders {
-  border:none;
-}
-table.no-borders {
-  border:none;
-  tr, td { border:none }
-}
-.no-padding {
-  padding:0 !important;
-}
-.underlined {
-  border-bottom: 1px solid $border_color;
-}
-.vlink {
-  color: $link_color !important;
-}
-
-.pretty_label {
-  @include round-borders-all(4px);
-  padding:2px 4px;
-  background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.076, #fefefe), to(#F6F7F8));
-  background-image: -webkit-linear-gradient(#fefefe 7.6%, #F6F7F8);
-  background-image: -moz-linear-gradient(#fefefe 7.6%, #F6F7F8);
-  background-image: -o-linear-gradient(#fefefe 7.6%, #F6F7F8);
-  color: #777;
-  border: 1px solid #DEDFE1;
-
-  &.branch {
-    border:none;
-    font-size:13px;
-    background: #474D57;
-    color:#fff;
-    font-weight:bold;
-    font-family: monospace;
-  }
-}
-
-.event_label {
-  @extend .label;
-  background-color: #999;
-
-  &.pushed {
-    background-color: #3A87AD;
-  }
-
-  &.opened {
-    background-color: #468847;
-  }
-
-  &.closed {
-    background-color: #B94A48;
-  }
-
-  &.merged {
-    background-color: #2A2;
-  }
-}
-
-img.avatar {
-  float:left;
-  margin-right:15px;
-  width:40px;
-  border:1px solid #ddd;
-  padding:1px;
-
-  &.s16 {
-    width:16px;
-    height:16px;
-  }
-  &.s24 {
-    width:24px;
-    height:24px;
-  }
-  &.s32 {
-    width:32px;
-    height:32px;
-  }
-}
-
-img.lil_av {
-  padding-left: 4px;
-  padding-right:3px;
-}
-
-form {
-  @extend .form-horizontal;
-
-  .actions {
-    @extend .form-actions;
-  }
-
-  .clearfix {
-    @extend .control-group;
-  }
-
-  .input {
-    @extend .controls;
-  }
-
-  label {
-    @extend .control-label;
-  }
-  .xlarge {
-    @extend .input-xlarge;
-  }
-  .xxlarge {
-    @extend .input-xxlarge;
-  }
-}
-
-/**
- * List li block element #1
- *
- */
-.wll {
-  background-color: #FFF;
-  padding: 10px 5px;
-  min-height: 20px;
-  border-bottom: 1px solid #eee;
-  border-bottom: 1px solid rgba(0, 0, 0, 0.05);
-  &.smoke {
-    background-color:#f5f5f5;
-  }
-  &:hover {
-    background:$hover;
-  }
-  &:last-child { border:none }
-  p { padding-top:5px; margin:0; color:$style_color;}
-  .author { color: #999; }
-  p {
-    color:#222;
-    margin-bottom: 0;
-    img {
-      position:relative;
-      top:3px;
-    }
-  }
-}
-
-
-/**
- * Block element #2
- *
- */
-.entry {
-  position: relative;
-  padding: 7px 15px;
-  margin-bottom: 18px;
-  color: #404040;
-  filter:none;
-
-  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
-  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
-
-  -webkit-border-radius: 4px;
-  -moz-border-radius: 4px;
-  border-radius: 4px;
-
-  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
-  -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
-  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
-
-  background:#F1F1F1;
-  border: 1px solid #ccc;
-
-
-  p {
-    color:$style_color;
-    margin-bottom: 0;
-    img {
-      position:relative;
-      top:3px;
-    }
-  }
-}
-
-
-/**
- * Big UI Block for show page content
- *
- */
-.ui-box {
-  background:#F9F9F9;
-  margin-bottom: 25px;
-  @include round-borders-all(4px);
-  border-color: #CCC;
-  @include solid_shade;
-
-  ul {
-    margin:0;
-  }
-
-  h5, .title {
-    padding: 0 10px;
-    @include round-borders-top(4px);
-    border-bottom: 1px solid #bbb;
-    background:#eee;
-    background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
-    background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
-    background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
-    background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
-
-    &.small {
-      line-height: 28px;
-      font-size: 14px;
-      line-height:28px;
-      text-shadow: 0 1px 1px white;
-    }
-
-    form {
-      padding:9px 0;
-      margin:0px;
-    }
-
-    .nav-pills {
-      li {
-        padding:3px 0;
-        &.active a { background-color:$style_color; }
-        a {
-          border-radius:7px;
-        }
-      }
-    }
-  }
-
-  .bottom {
-    background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
-    background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
-    background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
-    background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
-    @include round-borders-bottom(4px);
-    border-bottom:none;
-    border-top: 1px solid #bbb;
-  }
-
-  &.padded {
-    h5, .title {
-      margin: -20px;
-      margin-bottom: 0;
-      padding: 5px 20px;
-    }
-    .middle_title {
-      background:#f5f5f5;
-      margin:20px -20px;
-      padding: 0 20px;
-      border-top:1px solid #eee;
-      border-bottom:1px solid #eee;
-      font-size:14px;
-      color:#777;
-    }
-  }
-  .row_title {
-    font-weight:bold;
-    color:#444;
-    &:hover {
-      color:#444;
-      text-decoration:underline;
-    }
-  }
-
-  li, .wll {
-    padding:10px;
-    &:first-child {
-      @include round-borders-top(4px);
-      border-top:none;
-    }
-
-    &:last-child {
-      @include round-borders-bottom(4px);
-      border:none;
-    }
-  }
-
-}
-
-table.admin-table {
-  @extend .table-bordered;
-  @extend .zebra-striped;
-  @include solid_shade;
-  th {
-    border-color: #CCC;
-    border-bottom: 1px solid #bbb;
-    background:#eee;
-    background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
-    background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
-    background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
-    background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
-  }
-}
-
-.field_with_errors {
-  display:inline;
-}
-
-ul.breadcrumb {
-  background:white;
-  border:none;
-  li {
-    display: inline;
-    text-shadow: 0 1px 0 white
-  }
-
-  a {
-    color:#474D57;
-    font-weight:bold;
-    font-size:14px;
-  }
-
-  .arrow {
-    background: url("images.png") no-repeat -85px -77px;
-    width: 19px;
-    height: 16px;
-    float: left;
-    position: relative;
-    left: -10px;
-    padding:0;
-    margin:0;
-  }
-}
-
-.nothing_here_message {
-  text-align:center;
-  padding:20px;
-  color:#777;
-}
-
-/**
- *  UI box element
- *  contains top, middle, bottom blocks
- *
- */
-.main_box {
-  @extend .borders;
-  @extend .prepend-top-20;
-  @extend .append-bottom-20;
-  border-width:1px;
-  @include solid_shade;
-
-
-  img { max-width: 100%; }
-
-  pre {
-    code {
-      background: none !important;
-    }
-  }
-
-  .top_box_content,
-  .middle_box_content,
-  .bottom_box_content {
-    padding:15px;
-
-    pre {
-      background: none !important;
-      margin:0;
-      border:none;
-      padding:0;
-    }
-  }
-
-  .middle_box_content {
-    border-radius:0;
-    border:none;
-    font-size:12px;
-    background-color:#f5f5f5;
-    border:none;
-    border-top:1px solid #eee;
-  }
-
-  .bottom_box_content {
-    border-top:1px solid #eee;
-  }
-}
-
-input[type=text] {
-  &.large_text {
-    padding:6px;
-    font-size:16px;
-  }
-}
-
-p {
-  &.slead {
-    color:#456;
-    font-size:16px;
-    margin-bottom: 12px;
-    font-weight: 200;
-    line-height: 24px;
-  }
-}
-
-h3.page_title {
-  color:#456;
-  font-size:20px;
-  font-weight: normal;
-  line-height: 28px;
-}
-
-/**
- * File content holder
- *
- */
-.file_holder {
-  border:1px solid #CCC;
-  margin-bottom:1em;
-  @include solid_shade;
-
-  .file_title {
-    border-bottom: 1px solid #bbb;
-    background:#eee;
-    background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
-    background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
-    background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
-    background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
-    margin: 0;
-    font-weight: normal;
-    font-weight: bold;
-    text-align: left;
-    color: #666;
-    padding: 9px 10px;
-    height:18px;
-
-    .options {
-      float:right;
-      margin-top: -5px;
-    }
-
-    .file_name {
-      color:$style_color;
-      font-size:14px;
-      text-shadow: 0 1px 1px #fff;
-      small {
-        color:#999;
-        font-size:13px;
-      }
-    }
-  }
-  .file_content {
-    background:#fff;
-    font-size: 11px;
-
-    &.wiki {
-      font-size: 13px;
-      code {
-        padding:0 4px;
-      }
-      padding:20px;
-      h1, h2 {
-        line-height: 46px;
-      }
-      h3, h4 {
-        line-height: 40px;
-      }
-    }
-
-    &.image_file {
-      background:#eee;
-      text-align:center;
-      img {
-        padding:100px;
-        max-width:300px;
-      }
-    }
-
-    &.blob_file {
-
-    }
-
-    /**
-     *  Blame file
-     */
-    &.blame {
-      tr {
-        border-bottom: 1px solid #eee;
-      }
-      td {
-        padding:5px;
-      }
-      .author,
-      .blame_commit {
-        background:#f5f5f5;
-        vertical-align:top;
-      }
-      .lines {
-        pre {
-          padding:0;
-          margin:0;
-          background:none;
-          border:none;
-        }
-      }
-    }
-
-    &.logs {
-      background:#eee;
-      max-height: 700px;
-      overflow-y: auto;
-
-      ol {
-        margin-left:40px;
-        padding: 10px 0;
-        border-left: 1px solid #CCC;
-        margin-bottom:0;
-        background: white;
-        li {
-          color:#888;
-          p {
-            margin:0;
-            color:#333;
-            line-height:24px;
-            padding-left: 10px;
-          }
-
-          &:hover {
-            background:$hover;
-          }
-        }
-      }
-    }
-
-    /**
-     *  Code file
-     */
-    &.code {
-      padding:0;
-      td.code {
-        width: 100%;
-        .highlight {
-          margin-left: 55px;
-          overflow:auto;
-          overflow-y:hidden;
-        }
-      }
-      .highlight pre {
-        white-space: pre;
-        word-wrap:normal;
-      }
-
-      table.highlighttable {
-        border: none;
-      }
-      body.project-page table.highlighttable td { border: none }
-      table.highlighttable tr:hover { background:none;}
-
-      table.highlighttable pre{
-        line-height:16px !important;
-        font-size:12px !important;
-      }
-
-      table.highlighttable .linenodiv pre {
-        text-align: right;
-        padding-right: 4px;
-        color:#666;
-      }
-    }
-  }
-}
diff --git a/app/assets/stylesheets/gitlab_bootstrap/blocks.scss b/app/assets/stylesheets/gitlab_bootstrap/blocks.scss
new file mode 100644
index 0000000000000000000000000000000000000000..ae66bd201f88eca7094e056f8a0e69f298a6bce2
--- /dev/null
+++ b/app/assets/stylesheets/gitlab_bootstrap/blocks.scss
@@ -0,0 +1,153 @@
+/**
+ * ===================================
+ * Contain 3 main UI block elements:
+ *   .main_box - for show pages
+ *   .ui-box   - for simple block & widgets
+ * ===================================
+ */
+
+/**
+ *  UI box element
+ *  contains top, middle, bottom blocks
+ *
+ */
+.main_box {
+  @extend .borders;
+  @extend .prepend-top-20;
+  @extend .append-bottom-20;
+  border-width:1px;
+  @include solid_shade;
+
+
+  img { max-width: 100%; }
+
+  pre {
+    code {
+      background: none !important;
+    }
+  }
+
+  .top_box_content,
+  .middle_box_content,
+  .bottom_box_content {
+    padding:15px;
+
+    pre {
+      background: none !important;
+      margin:0;
+      border:none;
+      padding:0;
+    }
+  }
+
+  .middle_box_content {
+    border-radius:0;
+    border:none;
+    font-size:12px;
+    background-color:#f5f5f5;
+    border:none;
+    border-top:1px solid #eee;
+  }
+
+  .bottom_box_content {
+    border-top:1px solid #eee;
+  }
+}
+
+/**
+ * Big UI Block for show page content
+ *
+ */
+.ui-box {
+  background:#F9F9F9;
+  margin-bottom: 25px;
+  @include round-borders-all(4px);
+  border-color: #CCC;
+  @include solid_shade;
+
+  &.white {
+    background:#fff;
+  }
+
+  ul {
+    margin:0;
+  }
+
+  h5, .title {
+    padding: 0 10px;
+    @include round-borders-top(4px);
+    @include bg-gray-gradient;
+    border-bottom: 1px solid #bbb;
+
+    &.small {
+      line-height: 28px;
+      font-size: 14px;
+      line-height:28px;
+      text-shadow: 0 1px 1px white;
+    }
+
+    form {
+      padding:9px 0;
+      margin:0px;
+    }
+
+    .nav-pills {
+      li {
+        padding:3px 0;
+        &.active a { background-color:$style_color; }
+        a {
+          border-radius:7px;
+        }
+      }
+    }
+  }
+
+  .bottom {
+    @include bg-gray-gradient;
+    @include round-borders-bottom(4px);
+    border-bottom:none;
+    border-top: 1px solid #bbb;
+  }
+
+  &.padded {
+    h5, .title {
+      margin: -20px;
+      margin-bottom: 0;
+      padding: 5px 20px;
+    }
+    .middle_title {
+      background:#f5f5f5;
+      margin:20px -20px;
+      padding: 0 20px;
+      border-top:1px solid #eee;
+      border-bottom:1px solid #eee;
+      font-size:14px;
+      color:#777;
+    }
+  }
+  .row_title {
+    font-weight:bold;
+    color:#444;
+    &:hover {
+      color:#444;
+      text-decoration:underline;
+    }
+  }
+
+  li, .wll {
+    padding:10px;
+    &:first-child {
+      @include round-borders-top(4px);
+      border-top:none;
+    }
+
+    &:last-child {
+      @include round-borders-bottom(4px);
+      border:none;
+    }
+  }
+
+  .ui-box-body {
+    padding:10px;
+  }
+}
diff --git a/app/assets/stylesheets/gitlab_bootstrap/buttons.scss b/app/assets/stylesheets/gitlab_bootstrap/buttons.scss
new file mode 100644
index 0000000000000000000000000000000000000000..380fc3e3711d3458e4c1232d6f8df48c8935b2e5
--- /dev/null
+++ b/app/assets/stylesheets/gitlab_bootstrap/buttons.scss
@@ -0,0 +1,93 @@
+.btn {
+  @include bg-gradient(#f7f7f7, #d5d5d5);
+  border-color:#aaa;
+  &:hover {
+    @include bg-gray-gradient;
+    border-color:#bbb;
+    color:#333;
+  }
+
+  &.primary {
+    background:#2a79A3;
+    @include bg-gradient(#47A7b7, #2585b5);
+    border-color: #2A79A3;
+    color:#fff;
+    text-shadow: 0 1px 1px #268;
+    &:hover {
+      background:$blue_link;
+      color:#fff;
+    }
+
+    &.disabled {
+      color:#fff;
+      background:#29B;
+    }
+  }
+
+  &.success {
+    @extend .btn-success;
+
+    &:hover {
+      @extend .btn-success;
+      background: #51a351;
+    }
+
+    &.disabled {
+      color:#fff;
+      background:#2b2;
+    }
+  }
+
+  &.save-btn {
+    @extend .wide;
+    @extend .primary;
+  }
+
+  &.cancel-btn {
+    float:right;
+  }
+
+  &.wide {
+    padding-left:30px;
+    padding-right:30px;
+  }
+
+  &.danger {
+    @extend .btn-danger;
+    border-color: #BD362F;
+
+    &:hover {
+      color:#fff;
+      background: #EE4E49;
+    }
+  }
+
+  &.danger {
+    @extend .btn-danger;
+  }
+
+  &.small {
+    @extend .btn-small;
+  }
+
+  &.active {
+    border-color:#aaa;
+    background-color:#ccc;
+  }
+
+  &.very_small {
+    font-size:11px;
+    padding:2px 6px;
+    margin:2px;
+  }
+
+  &.grouped {
+    margin-right:7px;
+    float:left;
+  }
+
+  &.padded {
+    margin-right:3px;
+    padding:4px 10px 4px;
+  }
+}
diff --git a/app/assets/stylesheets/gitlab_bootstrap/common.scss b/app/assets/stylesheets/gitlab_bootstrap/common.scss
new file mode 100644
index 0000000000000000000000000000000000000000..b9459ee6559b08a33e1e7586dff7ea4e853841c3
--- /dev/null
+++ b/app/assets/stylesheets/gitlab_bootstrap/common.scss
@@ -0,0 +1,84 @@
+/** COLORS **/
+.cgray { color:gray }
+.cred { color:#D12F19 }
+.cgreen { color:#4a2 }
+.cblack { color:#111 }
+.cdark { color:#444 }
+.cwhite { color:#fff!important }
+.bgred { background:#F2DEDE!important }
+
+/** COMMON CLASSES **/
+.left { float:left }
+.right { float:right!important }
+.width-50p { width:50% }
+.width-49p { width:49% }
+.width-30p { width:30% }
+.width-65p { width:65% }
+.width-100p { width:100% }
+.append-bottom-10 { margin-bottom:10px }
+.append-bottom-20 { margin-bottom:20px }
+.prepend-top-10 { margin-top:10px }
+.prepend-top-20 { margin-top:20px }
+.padded { padding:20px }
+.ipadded { padding:20px!important }
+.lborder { border-left:1px solid #eee }
+.no-padding { padding:0 !important; }
+.underlined { border-bottom: 1px solid #CCC; }
+.no-borders { border:none; }
+.vlink { color: $link_color !important; }
+.borders { border: 1px solid #ccc; @include shade; }
+.hint { font-style: italic; color: #999; }
+
+/** PILLS & TABS**/
+.nav-pills a:hover { background-color:#888; }
+.nav-pills .active a { background-color: $style_color; }
+.nav-tabs > li > a, .nav-pills > li > a { color:$style_color; }
+.nav.nav-tabs {
+  li {
+    > a {
+      padding:8px 20px;
+      margin-right: 7px;
+      border-color: #EEE;
+      color:#888;
+      border-bottom: 1px solid #ddd;
+      .badge {
+        background-color: #eee;
+        color:#888;
+        text-shadow:0 1px 1px #fff;
+      }
+    }
+    &.active {
+      > a {
+        border-color: #CCC;
+        border-bottom: 1px solid #fff;
+        color:#333;
+      }
+    }
+  }
+}
+
+/** ALERT MESSAGES **/
+.alert-message { @extend .alert; }
+.alert-messag.success { @extend .alert-success; }
+.alert-message.error { @extend .alert-error; }
+
+/** AVATARS **/
+img.avatar { float:left; margin-right:15px; width:40px; border:1px solid #ddd; padding:1px; }
+img.avatar.s16 { width:16px; height:16px; }
+img.avatar.s24 { width:24px; height:24px; }
+img.avatar.s32 { width:32px; height:32px; }
+img.lil_av { padding-left: 4px; padding-right:3px; }
+
+/** HELPERS **/
+.nothing_here_message { text-align:center; padding:20px; color:#777; }
+p.slead { color:#456; font-size:16px; margin-bottom: 12px; font-weight: 200; line-height: 24px; }
+
+/** FORMS **/
+input[type='search'].search-text-input {
+  background-image: url("icon-search.png");
+  background-repeat: no-repeat;
+  background-position: 10px;
+  padding-left:25px;
+  @include border-radius(4px);
+  border:1px solid #ccc;
+}
diff --git a/app/assets/stylesheets/gitlab_bootstrap/files.scss b/app/assets/stylesheets/gitlab_bootstrap/files.scss
new file mode 100644
index 0000000000000000000000000000000000000000..d39fdb27cd46fd5c325077401b74b8ffc33cb038
--- /dev/null
+++ b/app/assets/stylesheets/gitlab_bootstrap/files.scss
@@ -0,0 +1,156 @@
+/**
+ * File content holder
+ *
+ */
+.file_holder {
+  border:1px solid #BBB;
+  margin-bottom:1em;
+  @include solid_shade;
+
+  .file_title {
+    border-bottom: 1px solid #bbb;
+    @include bg-dark-gray-gradient;
+    margin: 0;
+    font-weight: normal;
+    font-weight: bold;
+    text-align: left;
+    color: #666;
+    padding: 9px 10px;
+    height:18px;
+
+    .options {
+      float:right;
+      margin-top: -5px;
+    }
+
+    .file_name {
+      color:$style_color;
+      font-size:14px;
+      text-shadow: 0 1px 1px #fff;
+      small {
+        color:#999;
+        font-size:13px;
+      }
+    }
+  }
+  .file_content {
+    background:#fff;
+    font-size: 11px;
+
+    &.wiki {
+      font-size: 13px;
+      code {
+        padding:0 4px;
+      }
+      padding:20px;
+      h1, h2 {
+        line-height: 46px;
+      }
+      h3, h4 {
+        line-height: 40px;
+      }
+    }
+
+    &.image_file {
+      background:#eee;
+      text-align:center;
+      img {
+        padding:100px;
+        max-width:300px;
+      }
+    }
+
+    &.blob_file {
+
+    }
+
+    /**
+     *  Blame file
+     */
+    &.blame {
+      tr {
+        border-bottom: 1px solid #eee;
+      }
+      td {
+        padding:5px;
+      }
+      .author,
+      .blame_commit {
+        background:#f5f5f5;
+        vertical-align:top;
+      }
+      .lines {
+        pre {
+          padding:0;
+          margin:0;
+          background:none;
+          border:none;
+        }
+      }
+    }
+
+    &.logs {
+      background:#eee;
+      max-height: 700px;
+      overflow-y: auto;
+
+      ol {
+        margin-left:40px;
+        padding: 10px 0;
+        border-left: 1px solid #CCC;
+        margin-bottom:0;
+        background: white;
+        li {
+          color:#888;
+          p {
+            margin:0;
+            color:#333;
+            line-height:24px;
+            padding-left: 10px;
+          }
+
+          &:hover {
+            background:$hover;
+          }
+        }
+      }
+    }
+
+    /**
+     *  Code file
+     */
+    &.code {
+      padding:0;
+      td.code {
+        width: 100%;
+        .highlight {
+          margin-left: 55px;
+          overflow:auto;
+          overflow-y:hidden;
+        }
+      }
+      .highlight pre {
+        white-space: pre;
+        word-wrap:normal;
+      }
+
+      table.highlighttable {
+        border: none;
+      }
+      body.project-page table.highlighttable td { border: none }
+      table.highlighttable tr:hover { background:none;}
+
+      table.highlighttable pre{
+        line-height:16px !important;
+        font-size:12px !important;
+      }
+
+      table.highlighttable .linenodiv pre {
+        text-align: right;
+        padding-right: 4px;
+        color:#666;
+      }
+    }
+  }
+}
+
diff --git a/app/assets/stylesheets/gitlab_bootstrap/lists.scss b/app/assets/stylesheets/gitlab_bootstrap/lists.scss
new file mode 100644
index 0000000000000000000000000000000000000000..402ba04bd00dc565d25bb2da24595d01114d664e
--- /dev/null
+++ b/app/assets/stylesheets/gitlab_bootstrap/lists.scss
@@ -0,0 +1,30 @@
+/** LISTS **/
+
+ul { 
+  /**
+   * List li block element #1
+   *
+   */
+  .wll {
+    background-color: #FFF;
+    padding: 10px 5px;
+    min-height: 20px;
+    border-bottom: 1px solid #eee;
+    border-bottom: 1px solid rgba(0, 0, 0, 0.05);
+
+    &.smoke { background-color:#f5f5f5; }
+    &:hover { background:$hover; }
+    &:last-child { border:none }
+    .author { color: #999; }
+
+    p {
+      padding-top:5px; 
+      margin:0;
+      color:#222;
+      img {
+        position:relative;
+        top:3px;
+      }
+    }
+  }
+}
diff --git a/app/assets/stylesheets/gitlab_bootstrap/tables.scss b/app/assets/stylesheets/gitlab_bootstrap/tables.scss
new file mode 100644
index 0000000000000000000000000000000000000000..29293867ef7c109be5b6967b54fd7bd580c22b85
--- /dev/null
+++ b/app/assets/stylesheets/gitlab_bootstrap/tables.scss
@@ -0,0 +1,45 @@
+table {
+  @extend .table;
+  @extend .table-striped;
+  @include solid_shade;
+  border:1px solid #bbb;
+  width:100%;
+
+  th {
+    font-weight: bold;
+    vertical-align: middle;
+    border-bottom: 1px solid #bbb;
+    text-shadow: 0 1px 1px #fff;
+    @include bg-dark-gray-gradient;
+  }
+
+  th, td {
+    padding: 8px;
+    line-height: 18px;
+    text-align: left;
+  }
+
+  td {
+    border-color:#f1f1f1;
+    &:first-child {
+      border-left:1px solid #bbb;
+    }
+
+    &:last-child {
+      border-right:1px solid #bbb;
+    }
+  }
+
+  &.bordered {
+    @extend .table-bordered;
+  }
+
+  &.lite {
+    border:none;
+    box-shadow:none;
+    tr, td {
+      border:none;
+      background:none !important;
+    }
+  }
+}
diff --git a/app/assets/stylesheets/gitlab_bootstrap/typography.scss b/app/assets/stylesheets/gitlab_bootstrap/typography.scss
new file mode 100644
index 0000000000000000000000000000000000000000..97e854928753632daabb7d47ebd2cf84a20cac31
--- /dev/null
+++ b/app/assets/stylesheets/gitlab_bootstrap/typography.scss
@@ -0,0 +1,71 @@
+/**
+ * Headers
+ *
+ */
+h3, h4, h5, h6 { line-height: 36px; }
+h5 { font-size:14px; }
+h3.page_title {
+  color:#456;
+  font-size:20px;
+  font-weight: normal;
+  line-height: 28px;
+}
+
+/** CODE **/
+pre {
+  font-family:'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
+
+  &.dark {
+    background: #333;
+    color:#f5f5f5;
+  }
+}
+
+/**
+ * Links
+ *
+ */
+a {
+  outline: none;
+  color: $link_color;
+  &:hover {
+    text-decoration:none;
+    color: $blue_link;
+  }
+
+  &.btn {
+    color: $style_color;
+    &:hover {
+      color: $style_color;
+    }
+  }
+
+  &.dark {
+    color: $style_color;
+  }
+
+  &.lined {
+    text-decoration:underline;
+    &:hover { text-decoration:underline; }
+  }
+
+  &.gray {
+    color:gray;
+  }
+
+  &.supp_diff_link {
+    text-align:center;
+    padding:20px 0;
+    background:#f1f1f1;
+    width:100%;
+    float:left;
+  }
+
+  &.neib  {
+    margin-right:15px;
+  }
+}
+
+a:focus {
+  outline: none;
+}
diff --git a/app/assets/stylesheets/highlight/white.scss b/app/assets/stylesheets/highlight/white.scss
index a08f05bdb541b065425a832cdbb67953ca19bab3..9b003b8ace530bffd75a84f69c752083fe135503 100644
--- a/app/assets/stylesheets/highlight/white.scss
+++ b/app/assets/stylesheets/highlight/white.scss
@@ -1,12 +1,21 @@
-table.highlighttable
-{
+table.highlighttable {
   margin:0px;
   padding:0px;
   font-size:12px;
   table-layout:fixed;
   background: #EEE;
+  box-shadow: none;
+  border: none;
+  td.linenos {
+    background:#eee;
+    border-left:none;
+  }
+  td.code {
+    border-right:none;
+  }
 }
 
+
 td.code,
 td.linenos{
   padding:0;
diff --git a/app/assets/stylesheets/main.scss b/app/assets/stylesheets/main.scss
index ad8be0bc58d6bd2bead88ace9bba0116b63f7332..75001d3a7c34d23b29450409816ae3e58be2ba1d 100644
--- a/app/assets/stylesheets/main.scss
+++ b/app/assets/stylesheets/main.scss
@@ -1,30 +1,14 @@
 @import "bootstrap";
 @import "bootstrap-responsive";
 
-/** GITLAB colors **/
-$text_color:#222;
-$lite_text_color: #666;
-$link_color:#2A79A3;
-$active_link_color:#2FA0BB;
-$active_bg_color:#79C3E0;
-$active_bd_color: #2FA0BB;
-$border_color:#CCC;
-$lite_border_color:#EEE;
-$min_app_width:980px;
-$max_app_width:980px;
-$app_padding:20px;
-$bg_color: #FFF;
-$styled_border_color: #2FA0BB;
-$color: "#4BB8D2";
+/** GitLab colors **/
+$link_color:#3A89A3;
 $blue_link: #2fa0bb;
+$style_color: #474d57;
+$hover: #fdf5d9;
 
-
-/** Style colors **/
-$style_color: #474D57;
-$hover: #FDF5D9;
-
-/** GITLAB Fonts **/
-@font-face { font-family: Korolev; src: url('korolev-medium-compressed.otf'); } 
+/** GitLab Fonts **/
+@font-face { font-family: Korolev; src: url('korolev-medium-compressed.otf'); }
 
 /** MIXINS **/
 @mixin shade {
@@ -72,7 +56,27 @@ $hover: #FDF5D9;
   border-radius: $radius;
 }
 
+@mixin bg-gradient($from, $to) {
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from($from), to($to));
+  background-image: -webkit-linear-gradient($from, $to);
+  background-image: -moz-linear-gradient($from, $to);
+  background-image: -o-linear-gradient($from, $to);
+}
+
+@mixin bg-gray-gradient {
+  background:#eee;
+  background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
+  background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
+  background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
+  background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
+}
 
+@mixin bg-dark-gray-gradient {
+  background:#eee;
+  background-image: -webkit-linear-gradient(#e9e9e9, #d7d7d7);
+  background-image: -moz-linear-gradient(#e9e9e9, #d7d7d7);
+  background-image: -o-linear-gradient(#e9e9e9, #d7d7d7);
+}
 
 /**
  * Header of application.
@@ -109,11 +113,17 @@ $hover: #FDF5D9;
 @import "themes/ui_modern.scss";
 
 /**
- * Gitlab bootstrap.
+ * GitLab bootstrap.
  * Overrides some styles of twitter bootstrap.
- * Also give some common classes for gitlab app
+ * Also give some common classes for GitLab app
  */
-@import "gitlab_bootstrap.scss";
+@import "gitlab_bootstrap/common.scss";
+@import "gitlab_bootstrap/typography.scss";
+@import "gitlab_bootstrap/buttons.scss";
+@import "gitlab_bootstrap/blocks.scss";
+@import "gitlab_bootstrap/files.scss";
+@import "gitlab_bootstrap/tables.scss";
+@import "gitlab_bootstrap/lists.scss";
 
 
 /**
@@ -125,7 +135,6 @@ $hover: #FDF5D9;
  */
 @import "common.scss";
 
-
 /**
  * Styles related to specific part of app
  */
@@ -151,6 +160,11 @@ $hover: #FDF5D9;
  */
 @import "sections/notes.scss";
 
+/**
+ * This file represent profile styles
+ */
+@import "sections/profile.scss";
+
 /**
  * Devise styles
  */
diff --git a/app/assets/stylesheets/projects.css.scss b/app/assets/stylesheets/projects.css.scss
deleted file mode 100644
index 4bdf5dee2f5fe197fb813f374b4a8fbb7020b6bb..0000000000000000000000000000000000000000
--- a/app/assets/stylesheets/projects.css.scss
+++ /dev/null
@@ -1,385 +0,0 @@
-.git_url_wrapper { margin-right:50px }
-
-.sidebar aside a{
-  display: block;
-  position: relative; 
-  padding: 15px 10px; 
-  margin: 10px 0 0 0;
-
-  font-size:13px;
-  font-weight:bold;
-  color:#333;
-
-  &.current {
-    color: white;
-    background: $active_bg_color;
-    border: 1px solid $active_bd_color;
-    border-radius:5px;
-
-    -webkit-border-top-right-radius: 0;
-    -webkit-border-bottom-right-radius: 0;
-    -moz-border-radius-topright: 0px;
-    -moz-border-radius-bottomright: 0px;
-    border-top-right-radius: 0;
-    border-bottom-right-radius: 0;
-    margin-right: -1px;
-  }
-}
-
-body table .commit a{color: #{$blue_link}}
-body table th, body table td{  border-bottom: 1px solid #DEE2E3;}
-body .fixed{position: fixed; }
-
-/** File stat **/
-.file_stats {
-  span {
-    img {
-      width:14px;
-      float:left;
-      margin-right: 6px;
-      padding:2px 0;
-    }
-  }
-}
-
-.round-borders {
-  @include round-borders-all(4px);
-  padding: 4px 0px;
-}
-
-table.round-borders {
-  float:left;
-  text-align: left;
-}
-
-
-
-/** PROJECTS **/
-input.ssh_project_url {
-  padding:5px;
-  margin:0px;
-  float:right;
-  width:400px;
-  text-align:center;
-}
-
-#projects-list .project {
-  height:50px;
-}
-
-#tree-slider .tree-item,
-#projects-list .project,
-#snippets-table .snippet,
-#issues-table .issue{
-  cursor:pointer;
-}
-
-.clear {
-  clear: both;
-}
-
-
-
-#user_projects_limit{
-  width: 60px;
-}
-
-.handle:hover{
-  cursor: move;
-}
-
-.project-refs-form {
-  span {
-    background: none !important;
-    position:static !important;
-    width:auto !important;
-    height: auto !important;
-  }
-}
-
-.project-refs-select {
-  width:200px;
-}
-
-.filter .left { margin-right:15px; }
-
-body table .commit {
-  a.tree-commit-link {
-    color:#444;
-    &:hover {
-      text-decoration:underline;
-    }
-  }
-}
-
-/** NEW PROJECT **/
-.new-project-hodler {
-  .icon span { background-position: -31px -70px; }
-  td { border-bottom: 1px solid #DEE2E3; }
-}
-
-/** Feed entry **/
-.commit,
-.snippet,
-.message {
-  .title {
-    color:#666;
-    a { color:#666 !important; }
-    p { margin-top:0px; }
-  }
-  .author { color: #999 }
-}
-
-/** JQuery UI **/
-.ui-autocomplete { @include round-borders-all(5px); }
-.ui-menu-item { cursor: pointer }
-.ui-selectmenu{
-  @include round-borders-all(4px);
-  margin-right:10px;
-  font-size:1.5em;
-  height:auto;
-  font-weight:bold;
-  .ui-selectmenu-status {
-    padding:3px 10px;
-  }
-}
-
-#holder {
-  background:#FAFAFA;
-  border: 1px solid #EEE;
-  cursor: move;
-  height: 70%;
-  overflow: hidden;
-}
-
-/* Project Dashboard Page */
-html, body { height: 100%; }
-
-.news-feed h2{float: left;}
-.news-feed .project-updates  {margin-bottom: 20px; display: block; width: 100%;}
-.news-feed .project-updates .data{ padding: 0}
-.news-feed .project-updates a.project-update {padding: 10px; border-bottom: 1px solid #eee; overflow: hidden; display: block;}
-.news-feed .project-updates a.project-update:last-child{border-bottom: 0}
-.news-feed .project-updates a.project-update img{float: left; margin-right: 10px;}
-.news-feed .project-updates a.project-update span.update-title, .dashboard-page .news-feed .project-updates li a span.update-author{display: block;}
-.news-feed .project-updates a.project-update span.update-title{margin-bottom: 10px}
-.news-feed .project-updates a.project-update span.update-author{color: #999; font-weight: normal; font-style: italic;}
-.news-feed .project-updates a.project-update span.update-author strong{font-weight: bold; font-style: normal;}
-/* eo Dashboard Page */
-
-
-/** Update entry **/
-.update-data { padding: 0 }
-.update-data { width:100%; }
-.update-data.ui-box .data { padding:0; }
-a.update-item {padding: 10px; border-bottom: 1px solid #eee; overflow: hidden; display: block;}
-a.update-item:last-child{border-bottom: 0}
-a.update-item img{float: left; margin-right: 10px;}
-a.update-item span.update-title, .dashboard-page .news-feed .project-updates li a span.update-author{display: block;}
-a.update-item span.update-title{margin-bottom: 10px}
-a.update-item span.update-author{color: #999; font-weight: normal; font-style: italic;}
-a.update-item span.update-author strong{font-weight: bold; font-style: normal;}
-
-
-body .team_member_new .span-6, .team_member_edit .span-6{ padding:10px 0; }
-
-body.projects-page input.text.git-url.project_list_url { width:165px; }
-
-
-body table.no-borders th { 
-  background:none;
-  border-bottom:1px solid #CCC;
-  color:#333;
-}
-
-body table.no-borders tr,
-body table.no-borders td{
-  border:none;
-}
-
-.ajax-tab-loading {
-  padding:40px;
-  display:none;
-}
-
-#tree-content-holder { float:left; width:100%; }
-
-#tree-readme-holder {
-  float:left;
-  width:100%;
-
-  .readme {
-    @include round-borders-all(4px);
-    padding: 4px 15px;
-    background:#F7F7F7;
-  }
-}
-
-
-
-/* Commit Page */
-.entity-info {float: right;}
-.entity-button{
-  background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.192, #fff), to(#f4f4f4));
-  background-image: -webkit-linear-gradient(#fff 19.2%, #f4f4f4);
-  background-image: -moz-linear-gradient(#fff 19.2%, #f4f4f4);
-  background-image: -o-linear-gradient(#fff 19.2%, #f4f4f4);
-  box-shadow: 0 -1px 0 white inset;
-  display: block;
-  border: 1px solid #eee;
-  border-radius: 5px;
-  margin-bottom: 2px;
-  position: relative;
-  padding: 4px 10px;
-  font-size: 11px;
-  padding-right: 20px;
-}
-
-.entity-button i{
-  background: url('images.png') no-repeat -138px -27px;
-  width: 6px;
-  height: 9px;
-  float: right;
-  position: absolute;
-  top: 6px;
-  right: 5px;
-}
-.box-arrow{float: right; background: #E3E5EA; padding: 10px; border-radius: 5px; margin-top: 2px; text-shadow: none; color: #999; margin: 1.5em 0;}
-
-h4.dash-tabs { 
-  margin: 0; 
-  border-bottom: 1px solid #ccc; 
-  padding: 10px 10px;
-  font-size: 11px;
-  padding-left:20px;
-  font-weight: bold; text-transform: uppercase;
-  background: #F7F7F7;
-  margin-bottom:20px;
-  height:13px;
-
-}
-
-.dash-button { 
-  border-right: 1px solid #ddd;
-  background:none;
-  padding: 10px 15px;
-  float:left;
-  position:relative;
-  top:-10px;
-  left:0px;
-  height:13px;
-
-  &:first-child { 
-    border-left: 1px solid #ddd;
-  }
-  &.active { 
-    background: #eaeaea;
-  }
-}
-
-
-.dashboard-loader { 
-  float:right;
-  margin-right:30px;
-  display:none;
-}
-
-
-.merge-tabs { 
-  margin: 0; 
-  border: 1px solid #ccc; 
-  padding: 5px;
-  font-size: 12px;
-  background: #F7F7F7;
-  margin-bottom:20px;
-  height:26px;
-
-  -moz-border-radius: 4px;
-  -webkit-border-radius: 4px;
-  border-radius: 4px;
-
-  .tab { 
-    font-weight: bold;
-    border-right: 1px solid #ddd;
-    background:none;
-    padding: 10px;
-    min-width:60px;
-    float:left;
-    position:relative;
-    top:-5px;
-    left:-5px;
-    height:16px;
-    padding-left:34px;
-
-    span { 
-      width: 20px;
-      height: 20px;
-      display: inline-block;
-      position: absolute;
-      left: 8px;
-      top: 8px;
-    }
-
-    &.active {
-      background: #eaeaea;
-    }
-  }
-}
-.merge-tabs.repository .tab span{ background: url("images.png") no-repeat -38px -77px; }
-.activities-tab span {  background: url("images.png") no-repeat -161px -1px; } 
-.stat-tab span,
-.team-tab span,
-.snippets-tab span {  background: url("images.png") no-repeat -38px -77px; } 
-.files-tab span {  background: url("images.png") no-repeat -112px -23px; } 
-
-.merge-notes-tab span {  background: url("images.png") no-repeat -161px -1px; } 
-.merge-commits-tab span {  background: url("images.png") no-repeat -86px 1px; } 
-.merge-diffs-tab span {  background: url("images.png") no-repeat -118px 1px; } 
-.merge-tabs .dashboard-loader { padding:8px; }
-
-.user-mention { 
-  color: #2FA0BB;
-  font-weight: bold;
-}
-
-.author { 
-  color: #999;
-}
-
-
-
-
-.dark_scheme_box { 
-  padding:20px 0;
-
-  label { 
-    float:left;
-    box-shadow: 0 0px 5px rgba(0,0,0,.3);
-
-    img { 
-    }
-  }
-}
-
-a.project-update.titled { 
-  position: relative;
-  padding-left: 235px !important;
-
-  .title-block { 
-    padding: 10px;
-    width: 205px;
-    position: absolute;
-    left: 0;
-    top: 0;
-  }
-}
-
-.add_new { 
-  float: right;
-  background: #A6B807;
-  color: white;
-  padding: 4px 10px;
-  @include round-borders-all(4px);
-  font-size:11px;
-  margin: 10px 0;
-}
diff --git a/app/assets/stylesheets/ref_select.scss b/app/assets/stylesheets/ref_select.scss
index 6f6a1bc983d598a1c3669d9711696f400cffa352..ed6760f1b434252ac3994430070e2fcd0b26ba68 100644
--- a/app/assets/stylesheets/ref_select.scss
+++ b/app/assets/stylesheets/ref_select.scss
@@ -12,37 +12,45 @@
   width:120px;
 }
 
-.project-refs-form .chzn-container { 
+.project-refs-form .chzn-container {
   position: relative;
   top: 0;
   left: 0;
   margin-right: 10px;
 
-  .chzn-drop { 
+  .chzn-drop {
     margin:7px 0;
-    border: 1px solid #CCC;
-    min-width: 300px;
+    min-width: 400px;
+    border: 2px solid $blue_link;
+    @include border-radius(4px);
 
-    .chzn-results { 
+    .chzn-results {
       max-height:300px;
+
+      .group-result {
+        color: $blue_link;
+      }
+      .active-result {
+        &.highlighted {
+          background: $blue_link;
+        }
+      }
     }
 
     .chzn-search input {
-      min-width:200px;
+      min-width:365px;
     }
   }
 
-  .chzn-single { 
-    background:#ddd;
-    //border:none;
-    //box-shadow:none;
+  .chzn-single {
+    @include bg-gray-gradient;
 
-    div { 
+    div {
       background:transparent;
       border-left:none;
     }
 
-    span { 
+    span {
       font-weight: normal;
     }
   }
diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss
index e2db701db71cb64c2d8d7732ca396d8e596b1801..75e38aeea93cd1cb7684b2ce0749998ed4fad9f9 100644
--- a/app/assets/stylesheets/sections/commits.scss
+++ b/app/assets/stylesheets/sections/commits.scss
@@ -206,4 +206,24 @@
     min-width:65px;
     font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
   }
+  
+  .commit-author-name { 
+    color: #777;
+  }
+}
+
+.diff_file_header a,
+.file_stats a {
+  color:$style_color;
+}
+
+.file_stats {
+  span {
+    img {
+      width:14px;
+      float:left;
+      margin-right:6px;
+      padding:2px 0;
+    }
+  }
 }
diff --git a/app/assets/stylesheets/sections/graph.scss b/app/assets/stylesheets/sections/graph.scss
index 33d91de53912cc0e207a5e209223befddcc17dbb..2aa4463e45e0255db488f9e46edfee582412de44 100644
--- a/app/assets/stylesheets/sections/graph.scss
+++ b/app/assets/stylesheets/sections/graph.scss
@@ -6,11 +6,7 @@
   h4 { 
     padding:0 10px;
     border-bottom: 1px solid #bbb;
-    background:#eee;
-    background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
-    background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
-    background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
-    background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
+    @include bg-gray-gradient;
   }
 
   .graph { 
diff --git a/app/assets/stylesheets/sections/header.scss b/app/assets/stylesheets/sections/header.scss
index d0fb662e69e2958cd4e01afb3e1cfb2bb9593707..8328a5ab9a7f0f254eec4a16c093ae7600bb59d9 100644
--- a/app/assets/stylesheets/sections/header.scss
+++ b/app/assets/stylesheets/sections/header.scss
@@ -22,7 +22,7 @@ header {
    *
    */
   .app_logo {
-    width:230px;
+    width:200px;
     float:left;
     position:relative;
     top:-5px;
@@ -31,7 +31,7 @@ header {
 
       h1 {
         padding-top: 5px;
-        width:102px;
+        width:90px;
         background: url('logo_dark.png') no-repeat 0px -3px;
         float:left;
         margin-left:5px;
diff --git a/app/assets/stylesheets/sections/issues.scss b/app/assets/stylesheets/sections/issues.scss
index 1b61ec3fe85f2f0605a91d74e13b000ee2505b1b..10def51076d9fd571e4cc01eb78cfc3934c57dd1 100644
--- a/app/assets/stylesheets/sections/issues.scss
+++ b/app/assets/stylesheets/sections/issues.scss
@@ -1,55 +1,55 @@
-.issue_form_box { 
+.issue_form_box {
   @extend .main_box;
-  .issue_title { 
+  .issue_title {
     @extend .top_box_content;
-    .clearfix { 
-      margin-bottom:0px; 
-      input { 
+    .clearfix {
+      margin-bottom:0px;
+      input {
         @extend .span8;
       }
     }
   }
-  .issue_middle_block { 
+  .issue_middle_block {
     @extend .middle_box_content;
     height:30px;
-    .issue_assignee { 
+    .issue_assignee {
       @extend .span6;
       float:left;
     }
-    .issue_milestone { 
+    .issue_milestone {
       @extend .span4;
       float:left;
     }
   }
-  .issue_description { 
+  .issue_description {
     @extend .bottom_box_content;
   }
 }
 
-.issues_table { 
-  .issue { 
+.issues_table {
+  .issue {
     padding:7px 10px;
 
-    .issue_check { 
+    .issue_check {
       float:left;
       padding: 8px 0;
       padding-right: 8px;
       min-width: 15px;
     }
 
-    p { 
+    p {
       padding-top:0;
       padding-bottom:2px;
     }
 
-    img.avatar { 
+    img.avatar {
       width:32px;
       margin-top:4px;
     }
   }
 }
 
-input.check_all_issues { 
+input.check_all_issues {
   float:left;
   padding: 0;
   margin:0;
@@ -59,36 +59,41 @@ input.check_all_issues {
   height: 22px;
 }
 
-.issues_content { 
-  .title { 
+.issues_content {
+  .title {
     height: 40px;
   }
 }
 
-#issues-table-holder { 
-  .issues_filters { 
-    form { 
+@media (min-width: 800px) { .issues_filters select { width:160px; }  }
+@media (min-width: 1000px) { .issues_filters select { width:200px; }  }
+@media (min-width: 1200px) { .issues_filters select { width:220px; }  }
+
+
+#issues-table-holder {
+  .issues_filters {
+    form {
       padding:0;
       margin:0;
       margin-top:7px
     }
-  } 
+  }
 
-  .issues_bulk_update { 
+  .issues_bulk_update {
     margin: 0;
-    form { 
+    form {
       padding:0;
       margin:0;
       margin-top:7px
     }
-    .update_selected_issues { 
+    .update_selected_issues {
       position:relative;
       top:-2px;
       margin-left:4px;
       float:left;
     }
-    
-    .update_issues_text { 
+
+    .update_issues_text {
       padding:3px;
       line-height: 18px;
       float:left;
@@ -96,6 +101,15 @@ input.check_all_issues {
   }
 }
 
-#update_status { 
+#update_status {
   width:100px;
 }
+
+
+/**
+ * Milestones list
+ *
+ */
+.milestone {
+  @extend .wll;
+}
diff --git a/app/assets/stylesheets/sections/merge_requests.scss b/app/assets/stylesheets/sections/merge_requests.scss
index ec84a64e23af2e62bd85498f1882957f09c2f8a6..c932f0fc67bd1d1e75fa17e9d23185a221b29b00 100644
--- a/app/assets/stylesheets/sections/merge_requests.scss
+++ b/app/assets/stylesheets/sections/merge_requests.scss
@@ -1,52 +1,35 @@
-/** 
+/**
  * MR form
  *
  */
 
-.mr_branch_box { 
+.mr_branch_box {
   @extend .ui-box;
   margin-bottom:20px;
 
-  .body { 
+  .body {
     background:#f1f1f1;
   }
 
-  .commit { 
-    margin:0;
-    padding:0;
-    padding: 5px;
-    margin-bottom: 5px;
-
-    .committed_ago { 
-      display:none;
-    }
-    .browse_code_link_holder { 
-      display:none;
-    }
-    list-style:none;
-    &:hover { 
-      background:none;
-    }
-  }
 }
 
 /**
  * MR -> show: Automerge widget
  *
  */
-.automerge_widget { 
-  &.can_be_merged { 
+.automerge_widget {
+  &.can_be_merged {
     background: #DFF0D8;
   }
 
-  form { 
+  form {
     margin-bottom:0;
-    .clearfix { 
+    .clearfix {
       margin-bottom:0;
     }
   }
 
-  .accept_group { 
+  .accept_group {
     float:left;
     border: 1px solid #ADA;
     padding: 2px;
@@ -54,28 +37,29 @@
     border-radius: 5px;
     background: #CEB;
 
-    .accept_merge_request { 
+    .accept_merge_request {
+      font-size:13px;
       float:left;
     }
-    .remove_branch_holder { 
+    .remove_branch_holder {
       margin-left:20px;
       margin-right:10px;
       float:left;
     }
-    label { 
+    label {
       color:#444;
     }
   }
 
 
-  .how_to_merge_link { 
+  .how_to_merge_link {
     @extend .primary;
   }
 }
 
-.mr_nav_tabs { 
-  li { 
-    a { 
+.mr_nav_tabs {
+  li {
+    a {
       font-weight:bold;
       padding:8px 20px;
       text-align:center;
@@ -83,19 +67,57 @@
   }
 }
 
-li.merge_request { 
+li.merge_request {
   padding:7px 10px;
-  img.avatar { 
+  img.avatar {
     width: 32px;
     margin-top: 4px;
   }
-  p { 
+  p {
     padding: 0px;
     padding-bottom: 2px;
   }
 }
 
-.merge_in_progress { 
+.merge_in_progress {
   @extend .padded;
   @extend .append-bottom-10;
 }
+
+.label_branch {
+  @include round-borders-all(4px);
+  padding:2px 4px;
+  border:none;
+  font-size:14px;
+  background: #474D57;
+  color:#fff;
+  font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
+}
+
+.mr_source_commit,
+.mr_target_commit {
+  .commit {
+    margin:0;
+    padding:0;
+    padding: 5px;
+    margin-bottom: 5px;
+    .avatar { position:relative }
+    .row_title {
+      color:#444;
+    }
+    .commit-author-name,
+    .dash,
+    .committed_ago,
+    .browse_code_link_holder {
+      display:none;
+    }
+    list-style:none;
+    &:hover {
+      background:none;
+    }
+  }
+}
+
+.mr_direction_tip {
+  margin-top:40px
+}
diff --git a/app/assets/stylesheets/sections/nav.scss b/app/assets/stylesheets/sections/nav.scss
index 4a7736443afea6c34aab9a1291a8bdcc06e619a6..2d9029183a6fba2fa718b0843abdf41e23a1fd2e 100644
--- a/app/assets/stylesheets/sections/nav.scss
+++ b/app/assets/stylesheets/sections/nav.scss
@@ -2,21 +2,17 @@
  *  Main Menu of Application
  *
  */
-ul.main_menu { 
+ul.main_menu {
   border-radius: 4px;
   margin: auto;
   margin:30px 0;
-  background:#eee;
-  border:1px solid #bbb;
+  border:1px solid #AAA;
   height:37px;
-  background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
-  background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
-  background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
-  background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
+  @include bg-gray-gradient;
   position:relative;
   overflow:hidden;
   @include shade;
-  .count { 
+  .count {
     position: relative;
 	  top: -1px;
 	  display: inline-block;
@@ -33,12 +29,12 @@ ul.main_menu {
 	  border-radius: 8px;
 	 -moz-border-radius: 8px;
   }
-  .label { 
+  .label {
     background:$hover;
     text-shadow:none;
     color:$style_color;
   }
-  li { 
+  li {
     list-style-type: none;
     margin: 0;
     display: table-cell;
@@ -47,7 +43,7 @@ ul.main_menu {
     border-left: 1px solid #EEE;
     border-bottom:2px solid #CFCFCF;
 
-    &:first-child{ 
+    &:first-child{
       -webkit-border-top-left-radius: 4px;
       -webkit-border-bottom-left-radius: 4px;
       -moz-border-radius-topleft: 4px;
@@ -57,31 +53,30 @@ ul.main_menu {
       border-left: 0;
     }
 
-    &.current { 
+    &.current {
       background-color:#D5D5D5;
-      border-bottom: 2px solid $style_color;
       border-right: 1px solid #BBB;
       border-left: 1px solid #BBB;
       border-radius: 0 0 1px 1px;
-      &:first-child{ 
+      &:first-child{
         border-bottom:none;
         border-left:none;
       }
     }
 
-    &.home { 
-      a { 
+    &.home {
+      a {
         background: url(home_icon.PNG) no-repeat center center;
         text-indent:-9999px;
         min-width:20px;
-        img { 
+        img {
           position:relative;
           top:4px;
         }
       }
     }
   }
-  a { 
+  a {
     display: block;
     text-align: center;
     font-weight:bold;
@@ -89,7 +84,7 @@ ul.main_menu {
     line-height:36px;
     color: $style_color;
     text-shadow:0 1px 1px white;
-
+    padding:0 10px;
   }
 }
 /*
diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss
index 30587ef5b63f87661e48577cfe5b5be31a449fb6..267a9b4356c6e91ac7c5cf6b5e17ee1945e869dc 100644
--- a/app/assets/stylesheets/sections/notes.scss
+++ b/app/assets/stylesheets/sections/notes.scss
@@ -2,18 +2,14 @@
  * Notes
  *
  */
-#notes-list, 
-#new_notes_list {
+#notes-list,
+#new-notes-list {
   display:block;
   list-style:none;
   margin:0px;
   padding:0px;
 }
 
-#new_notes_list li:last-child{ 
-  border-bottom:1px solid #aaa;
-}
-
 .issue_notes,
 .wiki_notes {
   .note_content {
@@ -30,17 +26,21 @@
 }
 
 #new_note {
-  #note_note {
-    height:25px;
-  }
   .attach_holder {
     display:none;
   }
 }
 
-.note { 
-  padding: 8px 0; 
-  border-bottom: 1px solid #eee;
+.preview_note {
+  margin: 2px;
+  border: 1px solid #ddd;
+  padding: 10px;
+  min-height: 60px;
+  background:#f5f5f5;
+}
+
+.note {
+  padding: 8px 0;
   overflow: hidden;
   display: block;
   img {float: left; margin-right: 10px;}
@@ -49,19 +49,36 @@
   .note-author { color: $style_color;}
 
   .note-title { margin-left:45px; padding-top: 5px;}
-  .avatar { 
+  .avatar {
     margin-top:3px;
   }
 
-  .delete-note { 
-    display:none; 
+  .delete-note {
+    display:none;
     float:right;
   }
 
-  &:hover { 
+  &:hover {
     .delete-note { display:block; }
   }
 }
+#notes-list:not(.reversed) .note,
+#new-notes-list:not(.reversed) .note {
+  border-bottom: 1px solid #eee;
+}
+#notes-list.reversed .note,
+#new-notes-list.reversed .note {
+  border-top: 1px solid #eee;
+}
+
+/* mark vote notes */
+.voting_notes .note {
+  padding: 8px 0;
+}
+
+.notes-status {
+  margin: 18px;
+}
 
 
 p.notify_controls input{
@@ -72,18 +89,18 @@ p.notify_controls span{
   font-weight: 700;
 }
 
-tr.line_notes_row { 
+tr.line_notes_row {
   border-bottom:1px solid #DDD;
   border-left: 7px solid #2A79A3;
 
-  &.reply { 
+  &.reply {
     background:#eee;
     border-left: 7px solid #2A79A3;
     border-top:1px solid #ddd;
-    td { 
+    td {
       padding:7px 10px;
     }
-    a.line_note_reply_link { 
+    a.line_note_reply_link {
       @include round-borders-all(4px);
       padding: 3px 10px;
       margin-left:5px;
@@ -92,9 +109,9 @@ tr.line_notes_row {
       border-color: #2A79A3;
     }
   }
-  ul { 
+  ul {
     margin:0;
-    li { 
+    li {
       padding:0;
       border:none;
     }
@@ -103,26 +120,26 @@ tr.line_notes_row {
 
 .line_notes_row,  .per_line_form { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; }
 
-.per_line_form { 
+.per_line_form {
   background:#f5f5f5;
   border-top:1px solid #eee;
   form {  margin: 0; }
-  td { 
+  td {
     border-bottom:1px solid #ddd;
   }
-  .note_actions { 
+  .note_actions {
     margin:0;
     padding-top: 10px;
 
-    .buttons { 
+    .buttons {
       float:left;
       width:300px;
     }
-    .options { 
-      .labels { 
+    .options {
+      .labels {
         float:left;
         padding-left:10px;
-        label { 
+        label {
           padding: 6px 0;
           margin: 0;
           width:120px;
@@ -132,7 +149,7 @@ tr.line_notes_row {
   }
 }
 
-td .line_note_link { 
+td .line_note_link {
   position:absolute;
   margin-left:-70px;
   margin-top:-10px;
@@ -144,14 +161,14 @@ td .line_note_link {
   opacity: 0.0;
   filter: alpha(opacity=0);
 
-  &:hover { 
+  &:hover {
     opacity: 1.0;
     filter: alpha(opacity=100);
   }
 }
 
 .diff_file_content tr.line_holder:hover > td { background: $hover !important; }
-.diff_file_content tr.line_holder:hover > td .line_note_link { 
+.diff_file_content tr.line_holder:hover > td .line_note_link {
   opacity: 1.0;
   filter: alpha(opacity=100);
 }
@@ -169,8 +186,8 @@ td .line_note_link {
     margin: 0;
   }
 
-  .note_advanced_opts { 
-    h6 { 
+  .note_advanced_opts {
+    h6 {
       line-height: 32px;
       padding-right: 15px;
     }
@@ -183,7 +200,7 @@ td .line_note_link {
     overflow:hidden;
     margin:0 0 5px !important;
 
-    .input_file { 
+    .input_file {
       .file_upload {
         position: absolute;
         right:14px;
@@ -196,7 +213,7 @@ td .line_note_link {
         height:28px;
         overflow:hidden;
       }
-      .input-file { 
+      .input-file {
         width: 260px;
         height: 41px;
         float: right;
@@ -204,3 +221,8 @@ td .line_note_link {
     }
   }
 }
+
+.note-text {
+  border: 1px solid #aaa;
+  box-shadow:none;
+}
diff --git a/app/assets/stylesheets/sections/profile.scss b/app/assets/stylesheets/sections/profile.scss
new file mode 100644
index 0000000000000000000000000000000000000000..206da3a95f796910dc9bc41fd39f97147272ab36
--- /dev/null
+++ b/app/assets/stylesheets/sections/profile.scss
@@ -0,0 +1,8 @@
+.profile_history {
+  .event_feed {
+    min-height:20px;
+    .avatar {
+      width:20px;
+    }
+  }
+}
diff --git a/app/assets/stylesheets/sections/projects.scss b/app/assets/stylesheets/sections/projects.scss
index 0866b43f71da1556da6b7c7b3c089dca771352a5..92d0fc43c8804987ca8fe172c60d96d169a7fcf6 100644
--- a/app/assets/stylesheets/sections/projects.scss
+++ b/app/assets/stylesheets/sections/projects.scss
@@ -14,6 +14,32 @@
         text-shadow: 0 1px 1px #fff;
         padding: 2px 10px;
       }
+      ul {
+        li {
+          padding:0;
+          a {
+            display:block;
+            .project_name {
+              color:#4fa2bd;
+              font-size:14px;
+              line-height:18px;
+            }
+            .arrow {
+              float:right;
+              padding:10px;
+              margin:0;
+            }
+            .last_activity {
+              padding-top:5px;
+              display:block;
+              span, strong {
+                font-size:12px;
+                color:#666;
+              }
+            }
+          }
+        }
+      }
       @extend .leftbar;
       @extend .ui-box;
     }
@@ -33,9 +59,38 @@
       color:#888;
     }
     .btn {
-      padding:6px;
+      padding:6px 10px;
       margin-left:10px;
       margin-bottom:8px;
     }
   }
+  .adv_settings {
+    h6 { margin-left:40px; }
+  }
+}
+
+.project_clone_panel {
+  @include border-radius(4px);
+  @include bg-gray-gradient;
+  padding: 4px 7px;
+  border: 1px solid #CCC;
+  margin-bottom:5px;
+}
+
+.project_clone_holder {
+  input[type="text"] {
+    border: 1px solid #BBB;
+    box-shadow: none;
+  }
+}
+
+.save-project-loader {
+  img {
+    margin-top:50px;
+    margin-bottom:50px;
+  }
+  h3 {
+    @extend .page_title;
+  }
+
 }
diff --git a/app/assets/stylesheets/sections/tree.scss b/app/assets/stylesheets/sections/tree.scss
index 2663fc9a3ceedc0c0921d8d2d1ac27464040c2ef..07568706d9d2b859711ebcae080491714bc09f1a 100644
--- a/app/assets/stylesheets/sections/tree.scss
+++ b/app/assets/stylesheets/sections/tree.scss
@@ -1,4 +1,4 @@
-#tree-holder { 
+#tree-holder {
   #tree-content-holder {
     float:left;
     width:100%;
@@ -11,40 +11,44 @@
       padding:12px;
       background: #F7F7F7;
 
-      pre { 
+      pre {
         overflow: auto;
       }
     }
   }
 
-  .tree_progress { 
+  .tree_progress {
     display:none;
     margin:20px;
-    &.loading { 
+    &.loading {
       display:block;
     }
   }
 
   #tree-slider {
     @include border-radius(0);
-    .tree-item { 
-      &:hover { 
-        td { background: $hover; }
+    .tree-item {
+      &:hover {
+        td {
+          background: $hover;
+          border-top:1px solid #FEA;
+          border-bottom:1px solid #FEA;
+        }
         cursor:pointer;
       }
     }
   }
 
-  .tree-item { 
-    .tree-item-file-name { 
+  .tree-item {
+    .tree-item-file-name {
       vertical-align:middle;
-      a { 
-        &:hover { 
+      a {
+        &:hover {
           color:$blue_link;
         }
       }
 
-      img { 
+      img {
         position: relative;
         top:-1px;
       }
@@ -52,41 +56,19 @@
   }
 
 
-  #tree-slider { 
-    @include solid_shade;
-    width:100%;
-
-    border-color:#ccc;
-
-    td { 
-      padding:8px;
-      border-color:#f1f1f1;
+  #tree-slider {
+    td {
       background:#fafafa;
     }
-
-    tr:first-child td:first-child, 
-    tr:first-child td:last-child { 
-      border-radius:0;
-    }
-
-    th { 
-      border-color: #CCC;
-      border-bottom: 1px solid #bbb;
-      background:#eee;
-      background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
-      background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
-      background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
-      background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
-    }
   }
 
-  .tree-commit-link { 
+  .tree-commit-link {
     color:#333;
   }
 
-  a.tree-commit-link { 
+  a.tree-commit-link {
     color: #666;
-    &:hover { 
+    &:hover {
       text-decoration: underline;
     }
   }
diff --git a/app/contexts/merge_requests_load.rb b/app/contexts/merge_requests_load.rb
index 6778db3bce59dbf4c64c02ef9080775d43ef58cb..e2f68e3805b02de4a5a869ba7c3bc29f9b05a162 100644
--- a/app/contexts/merge_requests_load.rb
+++ b/app/contexts/merge_requests_load.rb
@@ -1,13 +1,13 @@
 class MergeRequestsLoad < BaseContext
   def execute
-    type = params[:f].to_i
+    type = params[:f]
 
     merge_requests = project.merge_requests
 
     merge_requests = case type
-                     when 1 then merge_requests
-                     when 2 then merge_requests.closed
-                     when 3 then merge_requests.opened.assigned(current_user)
+                     when 'all' then merge_requests
+                     when 'closed' then merge_requests.closed
+                     when 'assigned-to-me' then merge_requests.opened.assigned(current_user)
                      else merge_requests.opened
                      end.page(params[:page]).per(20)
 
diff --git a/app/contexts/notes/load_context.rb b/app/contexts/notes/load_context.rb
index c89a7d19761ba5118af4f9b3b22ec4e4c1303a24..f92a780187d8245e0c19c33779cb4787dfd0ac16 100644
--- a/app/contexts/notes/load_context.rb
+++ b/app/contexts/notes/load_context.rb
@@ -3,30 +3,31 @@ module Notes
     def execute
       target_type = params[:target_type]
       target_id   = params[:target_id]
-      first_id    = params[:first_id]
-      last_id     = params[:last_id]
+      after_id    = params[:after_id]
+      before_id   = params[:before_id]
 
 
       @notes = case target_type
-               when "commit" 
-                 then project.commit_notes(project.commit(target_id)).fresh.limit(20)
-               when "snippet"
-                 then  project.snippets.find(target_id).notes
-               when "wall"
-                 then project.common_notes.order("created_at DESC").fresh.limit(50)
+               when "commit"
+                 project.commit_notes(project.commit(target_id)).fresh.limit(20)
                when "issue"
-                 then project.issues.find(target_id).notes.inc_author.order("created_at DESC").limit(20)
+                 project.issues.find(target_id).notes.inc_author.fresh.limit(20)
                when "merge_request"
-                 then project.merge_requests.find(target_id).notes.inc_author.order("created_at DESC").limit(20)
+                 project.merge_requests.find(target_id).notes.inc_author.fresh.limit(20)
+               when "snippet"
+                 project.snippets.find(target_id).notes.fresh
+               when "wall"
+                 # this is the only case, where the order is DESC
+                 project.common_notes.order("created_at DESC, id DESC").limit(50)
                when "wiki"
-                 then project.wikis.reverse.map {|w| w.notes.fresh }.flatten[0..20]
+                 project.wiki_notes.limit(20)
                end
 
-      @notes = if last_id
-                 @notes.where("id > ?", last_id)
-               elsif first_id
-                 @notes.where("id < ?", first_id)
-               else 
+      @notes = if after_id
+                 @notes.where("id > ?", after_id)
+               elsif before_id
+                 @notes.where("id < ?", before_id)
+               else
                  @notes
                end
     end
diff --git a/app/controllers/admin/dashboard_controller.rb b/app/controllers/admin/dashboard_controller.rb
index ad80f4d59030fa53e1328635bf58f3378b292e24..5152f6fa83d139589cd309fe23f1919956f1f130 100644
--- a/app/controllers/admin/dashboard_controller.rb
+++ b/app/controllers/admin/dashboard_controller.rb
@@ -1,8 +1,4 @@
-class Admin::DashboardController < ApplicationController
-  layout "admin"
-  before_filter :authenticate_user!
-  before_filter :authenticate_admin!
-
+class Admin::DashboardController < AdminController
   def index
     @workers = Resque.workers
     @pending_jobs = Resque.size(:post_receive)
diff --git a/app/controllers/admin/hooks_controller.rb b/app/controllers/admin/hooks_controller.rb
index 7f832fd56974653c318f10eac5791a0418ea94cc..91a1d633590df04c31611bdd73e42bc7f0d45812 100644
--- a/app/controllers/admin/hooks_controller.rb
+++ b/app/controllers/admin/hooks_controller.rb
@@ -1,8 +1,4 @@
-class Admin::HooksController < ApplicationController
-  layout "admin"
-  before_filter :authenticate_user!
-  before_filter :authenticate_admin!
-  
+class Admin::HooksController < AdminController
   def index
     @hooks = SystemHook.all
     @hook = SystemHook.new
@@ -15,7 +11,7 @@ class Admin::HooksController < ApplicationController
       redirect_to admin_hooks_path, notice: 'Hook was successfully created.'
     else
       @hooks = SystemHook.all
-      render :index 
+      render :index
     end
   end
 
diff --git a/app/controllers/admin/logs_controller.rb b/app/controllers/admin/logs_controller.rb
index c130b4b85a51b1da0e00370597ebeb251697f123..28c321a9e5231aee09fab2ca653d913e1ac06e6a 100644
--- a/app/controllers/admin/logs_controller.rb
+++ b/app/controllers/admin/logs_controller.rb
@@ -1,6 +1,2 @@
-class Admin::LogsController < ApplicationController
-  layout "admin"
-  before_filter :authenticate_user!
-  before_filter :authenticate_admin!
+class Admin::LogsController < AdminController
 end
-
diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb
index 80d11f03ef0ad4cfa56b932e7999ef791b8df3de..24406525cd8da867556cb58ac330f07202c2ad4a 100644
--- a/app/controllers/admin/projects_controller.rb
+++ b/app/controllers/admin/projects_controller.rb
@@ -1,7 +1,4 @@
-class Admin::ProjectsController < ApplicationController
-  layout "admin"
-  before_filter :authenticate_user!
-  before_filter :authenticate_admin!
+class Admin::ProjectsController < AdminController
   before_filter :admin_project, only: [:edit, :show, :update, :destroy, :team_update]
 
   def index
@@ -43,7 +40,7 @@ class Admin::ProjectsController < ApplicationController
   def update
     owner_id = params[:project].delete(:owner_id)
 
-    if owner_id 
+    if owner_id
       @admin_project.owner = User.find(owner_id)
     end
 
@@ -60,7 +57,7 @@ class Admin::ProjectsController < ApplicationController
     redirect_to admin_projects_url, notice: 'Project was successfully deleted.'
   end
 
-  private 
+  private
 
   def admin_project
     @admin_project = Project.find_by_code(params[:id])
diff --git a/app/controllers/admin/resque_controller.rb b/app/controllers/admin/resque_controller.rb
index dc575cc27b2081d481f2aa1e644d27141206e153..9d8e7e3051f0520c288741ce497c49334933bd54 100644
--- a/app/controllers/admin/resque_controller.rb
+++ b/app/controllers/admin/resque_controller.rb
@@ -1,5 +1,4 @@
-class Admin::ResqueController < ApplicationController
-  layout 'admin'
+class Admin::ResqueController < AdminController
   def show
   end
-end
\ No newline at end of file
+end
diff --git a/app/controllers/admin/team_members_controller.rb b/app/controllers/admin/team_members_controller.rb
index 57803b01e60114f48f0d7f076fbb02c25bbe2f6b..073208057cabce9a48206a9ada82ce1f0dd51284 100644
--- a/app/controllers/admin/team_members_controller.rb
+++ b/app/controllers/admin/team_members_controller.rb
@@ -1,8 +1,4 @@
-class Admin::TeamMembersController < ApplicationController
-  layout "admin"
-  before_filter :authenticate_user!
-  before_filter :authenticate_admin!
-
+class Admin::TeamMembersController < AdminController
   def edit
     @admin_team_member = UsersProject.find(params[:id])
   end
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index 1e8f420b0989237385795c9fe716c760e8d5faf7..e2d61864076e672f287db5cec68829835834bfd1 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -1,8 +1,4 @@
-class Admin::UsersController < ApplicationController
-  layout "admin"
-  before_filter :authenticate_user!
-  before_filter :authenticate_admin!
-
+class Admin::UsersController < AdminController
   def index
     @admin_users = User.scoped
     @admin_users = @admin_users.filter(params[:filter])
@@ -24,7 +20,7 @@ class Admin::UsersController < ApplicationController
     @admin_user = User.find(params[:id])
 
     UsersProject.user_bulk_import(
-      @admin_user, 
+      @admin_user,
       params[:project_ids],
       params[:project_access]
     )
@@ -41,22 +37,22 @@ class Admin::UsersController < ApplicationController
     @admin_user = User.find(params[:id])
   end
 
-  def block 
+  def block
     @admin_user = User.find(params[:id])
 
     if @admin_user.block
       redirect_to :back, alert: "Successfully blocked"
-    else 
+    else
       redirect_to :back, alert: "Error occured. User was not blocked"
     end
   end
 
-  def unblock 
+  def unblock
     @admin_user = User.find(params[:id])
 
     if @admin_user.update_attribute(:blocked, false)
       redirect_to :back, alert: "Successfully unblocked"
-    else 
+    else
       redirect_to :back, alert: "Error occured. User was not unblocked"
     end
   end
diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..bce9f69238577379d926b3c53cfdf427234ebd72
--- /dev/null
+++ b/app/controllers/admin_controller.rb
@@ -0,0 +1,11 @@
+# Provides a base class for Admin controllers to subclass
+#
+# Automatically sets the layout and ensures an administrator is logged in
+class AdminController < ApplicationController
+  layout 'admin'
+  before_filter :authenticate_admin!
+
+  def authenticate_admin!
+    return render_404 unless current_user.is_admin?
+  end
+end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 7c1941ec85935e88b43e1ef329dca49a71be1adc..5ac5c639f398086a5575b3ed54e4b835e87b24ec 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -11,11 +11,11 @@ class ApplicationController < ActionController::Base
   helper_method :abilities, :can?
 
   rescue_from Gitlab::Gitolite::AccessDenied do |exception|
-    render "errors/gitolite", layout: "error"
+    render "errors/gitolite", layout: "error", status: 500
   end
 
   rescue_from Encoding::CompatibilityError do |exception|
-    render "errors/encoding", layout: "error", status: 404
+    render "errors/encoding", layout: "error", status: 500
   end
 
   rescue_from ActiveRecord::RecordNotFound do |exception|
@@ -84,10 +84,6 @@ class ApplicationController < ActionController::Base
     abilities << Ability
   end
 
-  def authenticate_admin!
-    return render_404 unless current_user.is_admin?
-  end
-
   def authorize_project!(action)
     return access_denied! unless can?(current_user, action, project)
   end
@@ -116,22 +112,12 @@ class ApplicationController < ActionController::Base
     end
   end
 
-  def load_refs
-    if params[:ref].blank?
-      @branch = params[:branch].blank? ? nil : params[:branch]
-      @tag = params[:tag].blank? ? nil : params[:tag]
-      @ref = @branch || @tag || @project.try(:default_branch) || Repository.default_ref
-    else
-      @ref = params[:ref]
-    end
-  end
-
   def render_404
     render file: File.join(Rails.root, "public", "404"), layout: false, status: "404"
   end
 
   def require_non_empty_project
-    redirect_to @project unless @project.repo_exists? && @project.has_commits?
+    redirect_to @project if @project.empty_repo?
   end
 
   def no_cache_headers
diff --git a/app/controllers/commits_controller.rb b/app/controllers/commits_controller.rb
index 717912d9e92eb0b709b9f2ae149ff9244a2eea5f..1e7aec005f15cecff98853b4117c7596ff72faee 100644
--- a/app/controllers/commits_controller.rb
+++ b/app/controllers/commits_controller.rb
@@ -52,6 +52,7 @@ class CommitsController < ApplicationController
     @commits = result[:commits]
     @commit  = result[:commit]
     @diffs   = result[:diffs]
+    @refs_are_same = result[:same]
     @line_notes = []
 
     @commits = CommitDecorator.decorate(@commits)
@@ -59,12 +60,19 @@ class CommitsController < ApplicationController
 
   def patch
     @commit = project.commit(params[:id])
-    
+
     send_data(
       @commit.to_patch,
       type: "text/plain",
       disposition: 'attachment',
-      filename: (@commit.id.to_s + ".patch")
+      filename: "#{@commit.id}.patch"
     )
   end
+
+  protected
+
+  def load_refs
+    @ref ||= params[:ref].presence || params[:branch].presence || params[:tag].presence
+    @ref ||= @ref || @project.try(:default_branch) || 'master'
+  end
 end
diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb
index 889a7d980339cdb53cface396bcc252248b12f92..1d78a6d9b80b0289cc144f0d21c0f3b92f0386ba 100644
--- a/app/controllers/issues_controller.rb
+++ b/app/controllers/issues_controller.rb
@@ -17,7 +17,7 @@ class IssuesController < ApplicationController
   before_filter :authorize_write_issue!, only: [:new, :create]
 
   # Allow modify issue
-  before_filter :authorize_modify_issue!, only: [:close, :edit, :update]
+  before_filter :authorize_modify_issue!, only: [:edit, :update]
 
   # Allow destroy issue
   before_filter :authorize_admin_issue!, only: [:destroy]
@@ -37,7 +37,7 @@ class IssuesController < ApplicationController
   end
 
   def new
-    @issue = @project.issues.new
+    @issue = @project.issues.new(params[:issue])
     respond_with(@issue)
   end
 
@@ -60,7 +60,13 @@ class IssuesController < ApplicationController
     @issue.save
 
     respond_to do |format|
-      format.html { redirect_to project_issue_path(@project, @issue) }
+      format.html do
+        if @issue.valid? 
+          redirect_to project_issue_path(@project, @issue)
+        else
+          render :new
+        end
+      end
       format.js
     end
   end
@@ -81,8 +87,6 @@ class IssuesController < ApplicationController
   end
 
   def destroy
-    return access_denied! unless can?(current_user, :admin_issue, @issue)
-
     @issue.destroy
 
     respond_to do |format|
@@ -162,10 +166,10 @@ class IssuesController < ApplicationController
 
   def issues_filter
     {
-      all: "1",
-      closed: "2",
-      to_me: "3",
-      open: "0" 
+      all: "all",
+      closed: "closed",
+      to_me: "assigned-to-me",
+      open: "open" 
     }
   end
 end
diff --git a/app/controllers/labels_controller.rb b/app/controllers/labels_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e703f822982898f6823c72f06c25dd1094756c40
--- /dev/null
+++ b/app/controllers/labels_controller.rb
@@ -0,0 +1,25 @@
+class LabelsController < ApplicationController
+  before_filter :authenticate_user!
+  before_filter :project
+  before_filter :module_enabled
+
+  layout "project"
+
+  # Authorize
+  before_filter :add_project_abilities
+
+  # Allow read any issue
+  before_filter :authorize_read_issue!
+
+  respond_to :js, :html
+
+  def index
+    @labels = @project.issues.tag_counts_on(:labels).order('count DESC')
+  end
+
+  protected
+
+  def module_enabled
+    return render_404 unless @project.issues_enabled
+  end
+end
diff --git a/app/controllers/merge_requests_controller.rb b/app/controllers/merge_requests_controller.rb
index 4938a294f60231d606194d1f03cea93bf51bc339..187bb407b2dff09fe39da7752fb155d4b803d2d1 100644
--- a/app/controllers/merge_requests_controller.rb
+++ b/app/controllers/merge_requests_controller.rb
@@ -103,10 +103,12 @@ class MergeRequestsController < ApplicationController
 
   def branch_from
     @commit = project.commit(params[:ref])
+    @commit = CommitDecorator.decorate(@commit)
   end
 
   def branch_to
     @commit = project.commit(params[:ref])
+    @commit = CommitDecorator.decorate(@commit)
   end
 
   protected
diff --git a/app/controllers/milestones_controller.rb b/app/controllers/milestones_controller.rb
index 7acb3781fbbbc9935191bad5c9edb52aae662e00..10f089f138b565a8bb64377b4fb0a6230a445f0b 100644
--- a/app/controllers/milestones_controller.rb
+++ b/app/controllers/milestones_controller.rb
@@ -17,8 +17,8 @@ class MilestonesController < ApplicationController
   respond_to :html
 
   def index
-    @milestones = case params[:f].to_i
-                  when 1; @project.milestones
+    @milestones = case params[:f]
+                  when 'all'; @project.milestones
                   else @project.milestones.active
                   end
 
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index d472936b4b40c093e199f4df4bf82ead5f8f59de..2fb783b289b00e2b6a68a9424c18596806e32343 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -1,4 +1,9 @@
 class OmniauthCallbacksController < Devise::OmniauthCallbacksController
+  Gitlab.config.omniauth_providers.each do |provider|
+    define_method provider['name'] do
+      handle_omniauth
+    end
+  end
 
   # Extend the standard message generation to accept our custom exception
   def failure_message
@@ -9,7 +14,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
     error ||= env["omniauth.error.type"].to_s
     error.to_s.humanize if error
   end
- 
+
   def ldap
     # We only find ourselves here if the authentication to LDAP was successful.
     @user = User.find_for_ldap_auth(request.env["omniauth.auth"], current_user)
@@ -19,4 +24,27 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
     sign_in_and_redirect @user
   end
 
+  private
+
+  def handle_omniauth
+    oauth = request.env['omniauth.auth']
+    provider, uid = oauth['provider'], oauth['uid']
+
+    if current_user
+      # Change a logged-in user's authentication method:
+      current_user.extern_uid = uid
+      current_user.provider = provider
+      current_user.save
+      redirect_to profile_path
+    else
+      @user = User.find_or_new_for_omniauth(oauth)
+
+      if @user
+        sign_in_and_redirect @user
+      else
+        flash[:notice] = "There's no such user!"
+        redirect_to new_user_session_path
+      end
+    end
+  end
 end
diff --git a/app/controllers/profile_controller.rb b/app/controllers/profile_controller.rb
index a95a331096a6d9192c69611a75343db37eae2183..7ddbfe1128dd100301235c97de34ba7769867d97 100644
--- a/app/controllers/profile_controller.rb
+++ b/app/controllers/profile_controller.rb
@@ -16,9 +16,6 @@ class ProfileController < ApplicationController
   def token
   end
 
-  def password
-  end
-
   def password_update
     params[:user].reject!{ |k, v| k != "password" && k != "password_confirmation"}
 
@@ -32,10 +29,14 @@ class ProfileController < ApplicationController
 
   def reset_private_token
     current_user.reset_authentication_token!
-    redirect_to profile_token_path
+    redirect_to profile_account_path
+  end
+
+  def history
+    @events = current_user.recent_events.page(params[:page]).per(20)
   end
 
-  private 
+  private
 
   def user
     @user = current_user
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index bd7f811e59f0f257f73d8a817bd61f78b9be0eb8..170b889293633155d914d3bd3c77f6b5b165f274 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -50,7 +50,7 @@ class ProjectsController < ApplicationController
 
     respond_to do |format|
       format.html do
-         if @project.repo_exists? && @project.has_commits?
+         unless @project.empty_repo?
            @last_push = current_user.recent_push(@project.id)
            render :show
          else
diff --git a/app/controllers/refs_controller.rb b/app/controllers/refs_controller.rb
index 3f81a2ca1a3cc00311982aae9f9822f1b1d9c359..9036143779c9e8e435b31dbed14803c8d8c169fd 100644
--- a/app/controllers/refs_controller.rb
+++ b/app/controllers/refs_controller.rb
@@ -1,3 +1,5 @@
+require 'github/markup'
+
 class RefsController < ApplicationController
   include Gitlab::Encode
   before_filter :project
diff --git a/app/controllers/team_members_controller.rb b/app/controllers/team_members_controller.rb
index 0846f09655405c05c744aff2d2cfc3412cb94f8d..a50dcd3eaeb9a0c75a8174f7ed81076d51ae7a79 100644
--- a/app/controllers/team_members_controller.rb
+++ b/app/controllers/team_members_controller.rb
@@ -5,7 +5,10 @@ class TeamMembersController < ApplicationController
   # Authorize
   before_filter :add_project_abilities
   before_filter :authorize_read_project!
-  before_filter :authorize_admin_project!, except: [:show]
+  before_filter :authorize_admin_project!, except: [:index, :show]
+
+  def index
+  end
 
   def show
     @team_member = project.users_projects.find(params[:id])
@@ -17,13 +20,12 @@ class TeamMembersController < ApplicationController
   end
 
   def create
-    @team_member = UsersProject.new(params[:team_member])
-    @team_member.project = project
-    if @team_member.save
-      redirect_to team_project_path(@project)
-    else
-      render "new"
-    end
+    @project.add_users_ids_to_team(
+      params[:user_ids],
+      params[:project_access]
+    )
+
+    redirect_to project_team_index_path(@project)
   end
 
   def update
@@ -33,7 +35,7 @@ class TeamMembersController < ApplicationController
     unless @team_member.valid?
       flash[:alert] = "User should have at least one role"
     end
-    redirect_to team_project_path(@project)
+    redirect_to project_team_index_path(@project)
   end
 
   def destroy
@@ -41,7 +43,7 @@ class TeamMembersController < ApplicationController
     @team_member.destroy
 
     respond_to do |format|
-      format.html { redirect_to team_project_path(@project) }
+      format.html { redirect_to project_team_index_path(@project) }
       format.js { render nothing: true }
     end
   end
diff --git a/app/decorators/commit_decorator.rb b/app/decorators/commit_decorator.rb
index cc8fa97587b53edfd2fe4eba453cbf897a92c8b0..c85f740027e8c3f973409bd98f700a20e7d6da49 100644
--- a/app/decorators/commit_decorator.rb
+++ b/app/decorators/commit_decorator.rb
@@ -1,12 +1,23 @@
 class CommitDecorator < ApplicationDecorator
   decorates :commit
 
+  # Returns a string describing the commit for use in a link title
+  #
+  # Example
+  #
+  #   "Commit: Alex Denisov - Project git clone panel"
+  def link_title
+    "Commit: #{author_name} - #{title}"
+  end
+
   # Returns the commits title.
   #
   # Usually, the commit title is the first line of the commit message.
   # In case this first line is longer than 80 characters, it is cut off
   # after 70 characters and ellipses (`&hellp;`) are appended.
   def title
+    return no_commit_message if safe_message.blank?
+
     title_end = safe_message.index(/\n/)
     if (!title_end && safe_message.length > 80) || (title_end && title_end > 80)
       safe_message[0..69] << "&hellip;".html_safe
@@ -26,4 +37,10 @@ class CommitDecorator < ApplicationDecorator
       safe_message.split(/\n/, 2)[1].try(:chomp)
     end
   end
+
+  protected
+
+  def no_commit_message
+    "--no commit message"
+  end
 end
diff --git a/app/decorators/event_decorator.rb b/app/decorators/event_decorator.rb
index 7df9081f04526f91b41e8a620d50dcaecbbd0dd8..ce0aaa039b9d9b7d2c3cc1ffab29b489df3f501e 100644
--- a/app/decorators/event_decorator.rb
+++ b/app/decorators/event_decorator.rb
@@ -8,7 +8,9 @@ class EventDecorator < ApplicationDecorator
       "#{self.author_name} #{self.action_name} MR ##{self.target_id}:" + self.merge_request_title
     elsif self.push?
       "#{self.author_name} #{self.push_action_name} #{self.ref_type} " + self.ref_name
-    else 
+    elsif self.membership_changed?
+      "#{self.author_name} #{self.action_name} #{self.project.name}"
+    else
       ""
     end
   end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 38191f5557116febfc252ebc496974163d8d4369..0938dc2322a3cd71314f716eaf74477547364ffc 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -62,7 +62,7 @@ module ApplicationHelper
         { label: "#{@project.name} / Wall", url: wall_project_path(@project) },
         { label: "#{@project.name} / Tree", url: tree_project_ref_path(@project, @project.root_ref) },
         { label: "#{@project.name} / Commits", url: project_commits_path(@project) },
-        { label: "#{@project.name} / Team", url: team_project_path(@project) }
+        { label: "#{@project.name} / Team", url: project_team_index_path(@project) }
       ]
     end
 
@@ -78,16 +78,16 @@ module ApplicationHelper
   end
 
   def show_last_push_widget?(event)
-    event && 
+    event &&
       event.last_push_to_non_root? &&
       !event.rm_ref? &&
-      event.project && 
+      event.project &&
       event.project.merge_requests_enabled
   end
 
   def tab_class(tab_key)
     active = case tab_key
-             
+
              # Project Area
              when :wall; wall_tab?
              when :wiki; controller.controller_name == "wikis"
@@ -104,7 +104,8 @@ module ApplicationHelper
 
              # Profile Area
              when :profile;  current_page?(controller: "profile", action: :show)
-             when :password; current_page?(controller: "profile", action: :password)
+             when :history;  current_page?(controller: "profile", action: :history)
+             when :account;  current_page?(controller: "profile", action: :account)
              when :token;    current_page?(controller: "profile", action: :token)
              when :design;   current_page?(controller: "profile", action: :design)
              when :ssh_keys; controller.controller_name == "keys"
@@ -126,4 +127,19 @@ module ApplicationHelper
   def hexdigest(string)
     Digest::SHA1.hexdigest string
   end
+
+  def project_last_activity project
+    activity = project.last_activity
+    if activity && activity.created_at
+      time_ago_in_words(activity.created_at) + " ago"
+    else
+      "Never"
+    end
+  end
+
+  def authbutton(provider, size = 64)
+    file_name = "#{provider.to_s.split('_').first}_#{size}.png"
+    image_tag("authbuttons/#{file_name}",
+              alt: "Sign in with #{provider.to_s.titleize}")
+  end
 end
diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb
index 88e3473baf27b5581486861da869f346833cc993..111982e9147ed5627ca4fda209f25d11263529ab 100644
--- a/app/helpers/gitlab_markdown_helper.rb
+++ b/app/helpers/gitlab_markdown_helper.rb
@@ -1,38 +1,5 @@
 module GitlabMarkdownHelper
-  # Replaces references (i.e. @abc, #123, !456, ...) in the text with links to
-  # the appropriate items in Gitlab.
-  #
-  # text          - the source text
-  # html_options  - extra options for the reference links as given to link_to
-  #
-  # note: reference links will only be generated if @project is set
-  #
-  # see Gitlab::Markdown for details on the supported syntax
-  def gfm(text, html_options = {})
-    return text if text.nil?
-    return text if @project.nil?
-
-    # Extract pre blocks so they are not altered
-    # from http://github.github.com/github-flavored-markdown/
-    extractions = {}
-    text.gsub!(%r{<pre>.*?</pre>|<code>.*?</code>}m) do |match|
-      md5 = Digest::MD5.hexdigest(match)
-      extractions[md5] = match
-      "{gfm-extraction-#{md5}}"
-    end
-
-    # TODO: add popups with additional information
-
-    parser = Gitlab::Markdown.new(@project, html_options)
-    text = parser.parse(text)
-
-    # Insert pre block extractions
-    text.gsub!(/\{gfm-extraction-(\h{32})\}/) do
-      extractions[$1]
-    end
-
-    text.html_safe
-  end
+  include Gitlab::Markdown
 
   # Use this in places where you would normally use link_to(gfm(...), ...).
   #
@@ -44,7 +11,9 @@ module GitlabMarkdownHelper
   # explicitly produce the correct linking behavior (i.e.
   # "<a>outer text </a><a>gfm ref</a><a> more outer text</a>").
   def link_to_gfm(body, url, html_options = {})
-    gfm_body = gfm(body, html_options)
+    return "" if body.blank?
+
+    gfm_body = gfm(escape_once(body), html_options)
 
     gfm_body.gsub!(%r{<a.*?>.*?</a>}m) do |match|
       "</a>#{match}#{link_to("", url, html_options)[0..-5]}" # "</a>".length +1
@@ -54,17 +23,24 @@ module GitlabMarkdownHelper
   end
 
   def markdown(text)
-    @__renderer ||= Redcarpet::Markdown.new(Redcarpet::Render::GitlabHTML.new(self, filter_html: true, with_toc_data: true), {
-      no_intra_emphasis: true,
-      tables: true,
-      fenced_code_blocks: true,
-      autolink: true,
-      strikethrough: true,
-      lax_html_blocks: true,
-      space_after_headers: true,
-      superscript: true
-    })
+    unless @markdown
+      gitlab_renderer = Redcarpet::Render::GitlabHTML.new(self,
+                          # see https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch-
+                          filter_html: true,
+                          with_toc_data: true,
+                          hard_wrap: true)
+      @markdown = Redcarpet::Markdown.new(gitlab_renderer,
+                      # see https://github.com/vmg/redcarpet#and-its-like-really-simple-to-use
+                      no_intra_emphasis: true,
+                      tables: true,
+                      fenced_code_blocks: true,
+                      autolink: true,
+                      strikethrough: true,
+                      lax_html_blocks: true,
+                      space_after_headers: true,
+                      superscript: true)
+    end
 
-    @__renderer.render(text).html_safe
+    @markdown.render(text).html_safe
   end
 end
diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb
new file mode 100644
index 0000000000000000000000000000000000000000..65389e383d93ae61c97802d6ebbe93171993dcab
--- /dev/null
+++ b/app/helpers/notes_helper.rb
@@ -0,0 +1,17 @@
+module NotesHelper
+  def loading_more_notes?
+    params[:loading_more].present?
+  end
+
+  def loading_new_notes?
+    params[:loading_new].present?
+  end
+
+  def note_vote_class(note)
+    if note.upvote?
+      "vote upvote"
+    elsif note.downvote?
+      "vote downvote"
+    end
+  end
+end
diff --git a/app/helpers/profile_helper.rb b/app/helpers/profile_helper.rb
new file mode 100644
index 0000000000000000000000000000000000000000..80d67009f597dc9b2a2b0f8eb10f700dbdd8b12f
--- /dev/null
+++ b/app/helpers/profile_helper.rb
@@ -0,0 +1,7 @@
+module ProfileHelper
+  def oauth_active_class provider
+    if current_user.provider == provider.to_s
+      'active'
+    end
+  end
+end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c7dc54ee93d88a47d7128959e7de312ed7624680
--- /dev/null
+++ b/app/helpers/projects_helper.rb
@@ -0,0 +1,10 @@
+module ProjectsHelper
+  def grouper_project_members(project)
+    @project.users_projects.sort_by(&:project_access).reverse.group_by(&:project_access)
+  end
+
+  def remove_from_team_message(project, member)
+    "You are going to remove #{member.user_name} from #{project.name}. Are you sure?"
+  end
+end
+
diff --git a/app/helpers/tab_helper.rb b/app/helpers/tab_helper.rb
index 1740864bbb21bf3ce5c59815b7fa3d1527dc6886..b5d7ccb7d3c816eb1f68712f4ae95bd59716867f 100644
--- a/app/helpers/tab_helper.rb
+++ b/app/helpers/tab_helper.rb
@@ -8,7 +8,7 @@ module TabHelper
   end
 
   def project_tab_class
-    [:show, :files, :team, :edit, :update].each do |action|
+    [:show, :files, :edit, :update].each do |action|
       return "current" if current_page?(controller: "projects", action: action, id: @project)
     end
 
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index ed3053d8af59d649ddad414e4719e1ccf9f65a0a..2b7265ca19e42e074f5517c13e75dd52fefc69d1 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -18,10 +18,25 @@ module TreeHelper
   end
 
   def tree_full_path(content)
-    if params[:path] 
+    content.name.force_encoding('utf-8')
+    if params[:path]
       File.join(params[:path], content.name)
     else
       content.name
     end
   end
+
+  # Public: Determines if a given filename is compatible with GitHub::Markup.
+  #
+  # filename - Filename string to check
+  #
+  # Returns boolean
+  def markup?(filename)
+    filename.end_with?(*%w(.textile .rdoc .org .creole
+                           .mediawiki .rst .asciidoc .pod))
+  end
+
+  def gitlab_markdown?(filename)
+    filename.end_with?(*%w(.mdown .md .markdown))
+  end
 end
diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb
index d0571b7b2c276070c69983e42e9ad581f6540b4b..0afc1d31ef472999d793e7c2ccb2b02b93401e14 100644
--- a/app/mailers/notify.rb
+++ b/app/mailers/notify.rb
@@ -76,6 +76,21 @@ class Notify < ActionMailer::Base
     mail(to: recipient(recipient_id), subject: subject("changed issue ##{@issue.id}", @issue.title))
   end
 
+  def project_access_granted_email(user_project_id)
+    @users_project = UsersProject.find user_project_id
+    @project = @users_project.project
+    mail(to: @users_project.user.email, 
+         subject: subject("access to project was granted"))
+  end
+
+  def issue_status_changed_email(recipient_id, issue_id, status, updated_by_user_id)
+    @issue = Issue.find issue_id
+    @issue_status = status
+    @updated_by = User.find updated_by_user_id
+    mail(to: recipient(recipient_id),
+        subject: subject("changed issue ##{@issue.id}", @issue.title))
+  end
+
   private
 
   # Look up a User by their ID and return their email address
@@ -96,18 +111,18 @@ class Notify < ActionMailer::Base
   # Examples
   #
   #   >> subject('Lorem ipsum')
-  #   => "gitlab | Lorem ipsum"
+  #   => "GitLab | Lorem ipsum"
   #
   #   # Automatically inserts Project name when @project is set
   #   >> @project = Project.last
   #   => #<Project id: 1, name: "Ruby on Rails", path: "ruby_on_rails", ...>
   #   >> subject('Lorem ipsum')
-  #   => "gitlab | Lorem ipsum | Ruby on Rails"
+  #   => "GitLab | Lorem ipsum | Ruby on Rails"
   #
   #   # Accepts multiple arguments
   #   >> subject('Lorem ipsum', 'Dolor sit amet')
-  #   => "gitlab | Lorem ipsum | Dolor sit amet"
+  #   => "GitLab | Lorem ipsum | Dolor sit amet"
   def subject(*extra)
-    "gitlab | " << extra.join(' | ') << (@project ? " | #{@project.name}" : "")
+    "GitLab | " << extra.join(' | ') << (@project ? " | #{@project.name}" : "")
   end
 end
diff --git a/app/models/commit.rb b/app/models/commit.rb
index 5c6b4d88d9673584d97c5eac2ae96af117048a1d..73583e9e7b795caf4d022bd7a95789e1b91d9fab 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -1,6 +1,7 @@
 class Commit
   include ActiveModel::Conversion
   include Gitlab::Encode
+  include StaticModel
   extend ActiveModel::Naming
 
   attr_accessor :commit
@@ -22,8 +23,7 @@ class Commit
     :to_patch,
     to: :commit
 
-
-  class << self 
+  class << self
     def find_or_first(repo, commit_id = nil, root_ref)
       commit = if commit_id
                  repo.commit(commit_id)
@@ -82,20 +82,24 @@ class Commit
     end
 
     def compare(project, from, to)
-      first = project.commit(to.try(:strip))
-      last = project.commit(from.try(:strip))
-
-      result = { 
+      result = {
         commits: [],
         diffs: [],
-        commit: nil
+        commit: nil,
+        same: false
       }
 
+      return result unless from && to
+
+      first = project.commit(to.try(:strip))
+      last = project.commit(from.try(:strip))
+
       if first && last
         commits = [first, last].sort_by(&:created_at)
         younger = commits.first
         older = commits.last
 
+        result[:same] = (younger.id == older.id)
         result[:commits] = project.repo.commits_between(younger.id, older.id).map {|c| Commit.new(c)}
         result[:diffs] = project.repo.diff(younger.id, older.id) rescue []
         result[:commit] = Commit.new(older)
@@ -105,10 +109,6 @@ class Commit
     end
   end
 
-  def persisted?
-    false
-  end
-
   def initialize(raw_commit, head = nil)
     @commit = raw_commit
     @head = head
@@ -155,7 +155,7 @@ class Commit
     prev_commit.try :id
   end
 
-  def parents_count 
+  def parents_count
     parents && parents.count || 0
   end
 end
diff --git a/app/models/event.rb b/app/models/event.rb
index e20b79e2a8285b1305357a77ca459cbc2505f18e..b11b21bda3b84bd8f9b300b2d3c093b9d65064de 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -10,6 +10,8 @@ class Event < ActiveRecord::Base
   Pushed    = 5
   Commented = 6
   Merged    = 7
+  Joined    = 8 # User joined project
+  Left      = 9 # User left project
 
   belongs_to :project
   belongs_to :target, polymorphic: true
@@ -33,11 +35,19 @@ class Event < ActiveRecord::Base
   end
 
   # Next events currently enabled for system
-  #  - push 
+  #  - push
   #  - new issue
   #  - merge request
   def allowed?
-    push? || issue? || merge_request?
+    push? || issue? || merge_request? || membership_changed?
+  end
+
+  def project_name
+    if project
+      project.name
+    else
+      "(deleted)"
+    end
   end
 
   def push?
@@ -56,35 +66,47 @@ class Event < ActiveRecord::Base
     action == self.class::Reopened
   end
 
-  def issue? 
+  def issue?
     target_type == "Issue"
   end
 
-  def merge_request? 
+  def merge_request?
     target_type == "MergeRequest"
   end
 
-  def new_issue? 
-    target_type == "Issue" && 
+  def new_issue?
+    target_type == "Issue" &&
       action == Created
   end
 
-  def new_merge_request? 
-    target_type == "MergeRequest" && 
+  def new_merge_request?
+    target_type == "MergeRequest" &&
       action == Created
   end
 
-  def changed_merge_request? 
-    target_type == "MergeRequest" && 
+  def changed_merge_request?
+    target_type == "MergeRequest" &&
       [Closed, Reopened].include?(action)
   end
 
-  def changed_issue? 
-    target_type == "Issue" && 
+  def changed_issue?
+    target_type == "Issue" &&
       [Closed, Reopened].include?(action)
   end
 
-  def issue 
+  def joined?
+    action == Joined
+  end
+
+  def left?
+    action == Left
+  end
+
+  def membership_changed?
+    joined? || left?
+  end
+
+  def issue
     target if target_type == "Issue"
   end
 
@@ -92,7 +114,7 @@ class Event < ActiveRecord::Base
     target if target_type == "MergeRequest"
   end
 
-  def author 
+  def author
     @author ||= User.find(author_id)
   end
 
@@ -101,7 +123,11 @@ class Event < ActiveRecord::Base
       "closed"
     elsif merged?
       "merged"
-    else 
+    elsif joined?
+      'joined'
+    elsif left?
+      'left'
+    else
       "opened"
     end
   end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 6409eebac6310044091634cbaaf26b817aa116e0..96a54907ca3cbd2cc2b4445880f53a8e9674d84f 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -1,6 +1,6 @@
 class Issue < ActiveRecord::Base
   include IssueCommonality
-  include Upvote
+  include Votes
 
   acts_as_taggable_on :labels
 
diff --git a/app/models/key.rb b/app/models/key.rb
index cfcb1f63c26694f6a2adcb220bf48fd4162413aa..a39a4a16c22dd60edbf6644b86ed1b1be5f4ddc7 100644
--- a/app/models/key.rb
+++ b/app/models/key.rb
@@ -1,16 +1,18 @@
 require 'digest/md5'
 
 class Key < ActiveRecord::Base
-  include SshKey
   belongs_to :user
   belongs_to :project
 
+  attr_protected :user_id
+
   validates :title,
             presence: true,
             length: { within: 0..255 }
 
   validates :key,
             presence: true,
+            format: { :with => /ssh-.{3} / },
             length: { within: 0..5000 }
 
   before_save :set_identifier
@@ -50,6 +52,10 @@ class Key < ActiveRecord::Base
       user.projects
     end
   end
+
+  def last_deploy?
+    Key.where(identifier: identifier).count == 0
+  end
 end
 # == Schema Information
 #
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 542817b0eeae90adbf3a6871f14613794bfef61a..184ac5fce19cbd28c10a23f92e11e9f9b1583dec 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -2,7 +2,7 @@ require File.join(Rails.root, "app/models/commit")
 
 class MergeRequest < ActiveRecord::Base
   include IssueCommonality
-  include Upvote
+  include Votes
 
   BROKEN_DIFF = "--broken-diff"
 
@@ -162,7 +162,7 @@ class MergeRequest < ActiveRecord::Base
   end
 
   def automerge!(current_user)
-    if Gitlab::Merge.new(self, current_user).merge
+    if Gitlab::Merge.new(self, current_user).merge && self.unmerged_commits.empty?
       self.merge!(current_user.id)
       true
     end
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index 592c57f948ce72cc9a7c5f947b6accad0464c46a..d416fb630c5db5e345e35cea1baaeada78349ffe 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -28,17 +28,9 @@ class Milestone < ActiveRecord::Base
   end
 
   def percent_complete
-    @percent_complete ||= begin
-                            total_i = self.issues.count
-                            closed_i = self.issues.closed.count
-                            if total_i > 0
-                              (closed_i * 100) / total_i
-                            else
-                              100
-                            end
-                          rescue => ex
-                            0
-                          end
+    ((self.issues.closed.count * 100) / self.issues.count).abs
+  rescue ZeroDivisionError
+    100
   end
 
   def expires_at
diff --git a/app/models/note.rb b/app/models/note.rb
index 711a4ee69355bbb7c1a967362001e92c534c0b3a..34edb94edca5cf64fafd764fb5587a25b99792fd 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -36,7 +36,7 @@ class Note < ActiveRecord::Base
   scope :today, where("created_at >= :date", date: Date.today)
   scope :last_week, where("created_at  >= :date", date: (Date.today - 7.days))
   scope :since, lambda { |day| where("created_at  >= :date", date: (day)) }
-  scope :fresh, order("created_at DESC")
+  scope :fresh, order("created_at ASC, id ASC")
   scope :inc_author_project, includes(:project, :author)
   scope :inc_author, includes(:author)
 
@@ -103,7 +103,13 @@ class Note < ActiveRecord::Base
   # Returns true if this is an upvote note,
   # otherwise false is returned
   def upvote?
-    note =~ /^\+1/ ? true : false
+    note.start_with?('+1') || note.start_with?(':+1:')
+  end
+
+  # Returns true if this is a downvote note,
+  # otherwise false is returned
+  def downvote?
+    note.start_with?('-1') || note.start_with?(':-1:')
   end
 end
 # == Schema Information
diff --git a/app/models/project.rb b/app/models/project.rb
index 3fe11916504818f65fb9b18bfe6eb9c3989289fb..56d5d7910b9827cd1efd43fc13c75c6600d153f8 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -8,7 +8,7 @@ class Project < ActiveRecord::Base
 
   #
   # Relations
-  # 
+  #
   belongs_to :owner, class_name: "User"
   has_many :users,          through: :users_projects
   has_many :events,         dependent: :destroy
@@ -25,12 +25,12 @@ class Project < ActiveRecord::Base
 
   attr_accessor :error_code
 
-  # 
+  #
   # Protected attributes
   #
   attr_protected :private_flag, :owner_id
 
-  # 
+  #
   # Scopes
   #
   scope :public_only, where(private_flag: false)
@@ -104,6 +104,8 @@ class Project < ActiveRecord::Base
             length: { within: 1..255 }
 
   validates :owner, presence: true
+  validates :issues_enabled, :wall_enabled, :merge_requests_enabled,
+            :wiki_enabled, inclusion: { in: [true, false] }
   validate :check_limit
   validate :repo_name
 
@@ -158,7 +160,7 @@ class Project < ActiveRecord::Base
   end
 
   def last_activity
-    events.last || nil
+    events.order("created_at ASC").last
   end
 
   def last_activity_date
@@ -169,6 +171,10 @@ class Project < ActiveRecord::Base
     end
   end
 
+  def wiki_notes
+    Note.where(noteable_id: wikis.map(&:id), noteable_type: 'Wiki', project_id: self.id)
+  end
+
   def project_id
     self.id
   end
@@ -187,7 +193,7 @@ end
 #  private_flag           :boolean(1)      default(TRUE), not null
 #  code                   :string(255)
 #  owner_id               :integer(4)
-#  default_branch         :string(255)     default("master"), not null
+#  default_branch         :string(255)
 #  issues_enabled         :boolean(1)      default(TRUE), not null
 #  wall_enabled           :boolean(1)      default(TRUE), not null
 #  merge_requests_enabled :boolean(1)      default(TRUE), not null
diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb
index 4da1432c1a99771c6ab17195fb5c2dc9c7928839..7c30f7a0b6d4fe9d90a9b5f20e268d55107d83ef 100644
--- a/app/models/protected_branch.rb
+++ b/app/models/protected_branch.rb
@@ -1,4 +1,6 @@
 class ProtectedBranch < ActiveRecord::Base
+  include GitHost
+
   belongs_to :project
   validates_presence_of :project_id
   validates_presence_of :name
@@ -7,7 +9,7 @@ class ProtectedBranch < ActiveRecord::Base
   after_destroy :update_repository
 
   def update_repository
-    Gitlab::GitHost.system.update_project(project.path, project)
+    git_host.update_repository(project)
   end
 
   def commit
diff --git a/app/models/tree.rb b/app/models/tree.rb
index bc95d335520abb0f3584b95e0735286b12d4e610..d65e50ab817f937777352c608b3388cbf25d998f 100644
--- a/app/models/tree.rb
+++ b/app/models/tree.rb
@@ -16,7 +16,7 @@ class Tree
   def initialize(raw_tree, project, ref = nil, path = nil)
     @project, @ref, @path = project, ref, path,
     @tree = if path
-              raw_tree / path
+              raw_tree / path.dup.force_encoding('ascii-8bit')
             else
               raw_tree
             end
diff --git a/app/models/user.rb b/app/models/user.rb
index ad6af6a6dd0cf524ec65d2460402b90a18edc5af..47876722755db329f48081131796be9324d2fdb0 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -86,33 +86,20 @@ class User < ActiveRecord::Base
     where('id NOT IN (SELECT DISTINCT(user_id) FROM users_projects)')
   end
 
-  def self.find_for_ldap_auth(auth, signed_in_resource=nil)
-    uid = auth.info.uid
-    provider = auth.provider
-    name = auth.info.name.force_encoding("utf-8")
-    email = auth.info.email.downcase unless auth.info.email.nil?
-    raise OmniAuth::Error, "LDAP accounts must provide an uid and email address" if uid.nil? or email.nil?
-
-    if @user = User.find_by_extern_uid_and_provider(uid, provider)
-      @user
-    # workaround for backward compatibility
-    elsif @user = User.find_by_email(email)
-      logger.info "Updating legacy LDAP user #{email} with extern_uid => #{uid}"
-      @user.update_attributes(:extern_uid => uid, :provider => provider)
-      @user
-    else
-      logger.info "Creating user from LDAP login {uid => #{uid}, name => #{name}, email => #{email}}"
-      password = Devise.friendly_token[0, 8].downcase
-      @user = User.create(
-        :extern_uid => uid,
-        :provider => provider,
-        :name => name,
-        :email => email,
-        :password => password,
-        :password_confirmation => password,
-        :projects_limit => Gitlab.config.default_projects_limit
-      )
-    end
+  def self.create_from_omniauth(auth, ldap = false)
+    gitlab_auth.create_from_omniauth(auth, ldap)
+  end
+
+  def self.find_or_new_for_omniauth(auth)
+    gitlab_auth.find_or_new_for_omniauth(auth)
+  end
+
+  def self.find_for_ldap_auth(auth, signed_in_resource = nil)
+    gitlab_auth.find_for_ldap_auth(auth, signed_in_resource)
+  end
+
+  def self.gitlab_auth
+    Gitlab::Auth.new
   end
 
   def self.search query
@@ -148,4 +135,3 @@ end
 #  bio                    :string(255)
 #  blocked                :boolean(1)      default(FALSE), not null
 #
-
diff --git a/app/models/users_project.rb b/app/models/users_project.rb
index 36e6d9045b6a4980a0cf6c9967b7348922e7e338..ce64a10f3f07fd8b85b105152d140458e1fe1bf4 100644
--- a/app/models/users_project.rb
+++ b/app/models/users_project.rb
@@ -1,4 +1,6 @@
 class UsersProject < ActiveRecord::Base
+  include GitHost
+
   GUEST     = 10
   REPORTER  = 20
   DEVELOPER = 30
@@ -12,12 +14,29 @@ class UsersProject < ActiveRecord::Base
   after_save :update_repository
   after_destroy :update_repository
 
-  validates_uniqueness_of :user_id, scope: [:project_id]
+  validates_uniqueness_of :user_id, scope: [:project_id], message: "already exists in project"
   validates_presence_of :user_id
   validates_presence_of :project_id
 
   delegate :name, :email, to: :user, prefix: true
 
+  def self.bulk_delete(project, user_ids)
+    UsersProject.transaction do
+      UsersProject.where(:user_id => user_ids, :project_id => project.id).each do |users_project|
+        users_project.destroy
+      end
+    end
+  end
+
+  def self.bulk_update(project, user_ids, project_access)
+    UsersProject.transaction do
+      UsersProject.where(:user_id => user_ids, :project_id => project.id).each do |users_project|
+        users_project.project_access = project_access
+        users_project.save
+      end
+    end
+  end
+
   def self.bulk_import(project, user_ids, project_access)
     UsersProject.transaction do
       user_ids.each do |user_id|
@@ -46,10 +65,10 @@ class UsersProject < ActiveRecord::Base
 
   def self.access_roles
     {
-      "Guest"   => GUEST,
-      "Reporter"   => REPORTER,
+      "Guest"     => GUEST,
+      "Reporter"  => REPORTER,
       "Developer" => DEVELOPER,
-      "Master"  => MASTER
+      "Master"    => MASTER
     }
   end
 
@@ -58,9 +77,7 @@ class UsersProject < ActiveRecord::Base
   end
 
   def update_repository
-    Gitlab::GitHost.system.new.configure do |c|
-      c.update_project(project.path, project)
-    end
+    git_host.update_repository(project)
   end
 
   def project_access_human
diff --git a/app/models/wiki.rb b/app/models/wiki.rb
index 3c4952cd291d52c4a33b439fbbcd607f600f4fdb..ebb1ff49c7a07e8f68d625beaf7c76433520c7c2 100644
--- a/app/models/wiki.rb
+++ b/app/models/wiki.rb
@@ -28,7 +28,6 @@ class Wiki < ActiveRecord::Base
       end
       new_wiki
     end
-
   end
 end
 # == Schema Information
diff --git a/app/observers/issue_observer.rb b/app/observers/issue_observer.rb
index 92b0f8368cb03492416818157667079e6d61fda4..62fd9bf8ac937b31e5c3ce29fb3efd3c98243304 100644
--- a/app/observers/issue_observer.rb
+++ b/app/observers/issue_observer.rb
@@ -9,8 +9,16 @@ class IssueObserver < ActiveRecord::Observer
 
   def after_update(issue)
     send_reassigned_email(issue) if issue.is_being_reassigned?
-    Note.create_status_change_note(issue, current_user, 'closed') if issue.is_being_closed?
-    Note.create_status_change_note(issue, current_user, 'reopened') if issue.is_being_reopened?
+
+    status = nil
+    status = 'closed' if issue.is_being_closed?
+    status = 'reopened' if issue.is_being_reopened?
+    if status
+      Note.create_status_change_note(issue, current_user, status) 
+      [issue.author, issue.assignee].compact.each do |recipient| 
+        Notify.issue_status_changed_email(recipient.id, issue.id, status, current_user)
+      end
+    end
   end
 
   protected
diff --git a/app/observers/key_observer.rb b/app/observers/key_observer.rb
index fac53a679252b49775eea61424548bbb9935b1c8..a3f17bdec92519be0e768d99deb78e679938b554 100644
--- a/app/observers/key_observer.rb
+++ b/app/observers/key_observer.rb
@@ -1,9 +1,12 @@
 class KeyObserver < ActiveRecord::Observer
+  include GitHost
+
   def after_save(key)
-    key.update_repository
+    git_host.set_key(key.identifier, key.key, key.projects)
   end
 
   def after_destroy(key)
-    key.repository_delete_key
+    return if key.is_deploy_key && !key.last_deploy?
+    git_host.remove_key(key.identifier, key.projects)
   end
 end
diff --git a/app/observers/project_observer.rb b/app/observers/project_observer.rb
index 135959ab738473e81f0a52edf49a5453124bd368..03a617098299c22ddcbaa97374ff4b13ae696fe9 100644
--- a/app/observers/project_observer.rb
+++ b/app/observers/project_observer.rb
@@ -4,6 +4,18 @@ class ProjectObserver < ActiveRecord::Observer
   end
 
   def after_destroy(project)
+    log_info("Project \"#{project.name}\" was removed")
+
     project.destroy_repository
   end
+
+  def after_create project
+    log_info("#{project.owner.name} created a new project \"#{project.name}\"")
+  end
+
+  protected
+
+  def log_info message
+    Gitlab::AppLogger.info message
+  end
 end
diff --git a/app/observers/user_observer.rb b/app/observers/user_observer.rb
index d12bcc99c83c980d9ebe5ba02e3e536c0b5bfae7..654621f7e1c9b0be102221811b97c650d8a7bd95 100644
--- a/app/observers/user_observer.rb
+++ b/app/observers/user_observer.rb
@@ -1,5 +1,17 @@
 class UserObserver < ActiveRecord::Observer
   def after_create(user)
+    log_info("User \"#{user.name}\" (#{user.email}) was created")
+
     Notify.new_user_email(user.id, user.password).deliver
   end
+
+  def after_destroy user
+    log_info("User \"#{user.name}\" (#{user.email})  was removed")
+  end
+
+  protected
+
+  def log_info message
+    Gitlab::AppLogger.info message
+  end
 end
diff --git a/app/observers/users_project_observer.rb b/app/observers/users_project_observer.rb
new file mode 100644
index 0000000000000000000000000000000000000000..0512e6067120fcb370bf917382a71d756843c523
--- /dev/null
+++ b/app/observers/users_project_observer.rb
@@ -0,0 +1,23 @@
+class UsersProjectObserver < ActiveRecord::Observer
+  def after_create(users_project)
+    Notify.project_access_granted_email(users_project.id).deliver
+
+    Event.create(
+      project_id: users_project.project.id,
+      action: Event::Joined,
+      author_id: users_project.user.id
+    )
+  end
+
+  def after_update(users_project)
+    Notify.project_access_granted_email(users_project.id).deliver
+  end
+
+  def after_destroy(users_project)
+    Event.create(
+      project_id: users_project.project.id,
+      action: Event::Left,
+      author_id: users_project.user.id
+    )
+  end
+end
diff --git a/app/roles/account.rb b/app/roles/account.rb
index 63a9b5c51bf921454df661636fa02aa1b2c89915..b8c445a3d5866e37ac79c4378759d859e698c54f 100644
--- a/app/roles/account.rb
+++ b/app/roles/account.rb
@@ -1,6 +1,13 @@
-module Account 
+module Account
+  # Returns a string for use as a Gitolite user identifier
+  #
+  # Note that Gitolite 2.x requires the following pattern for users:
+  #
+  #   ^@?[0-9a-zA-Z][0-9a-zA-Z._\@+-]*$
   def identifier
-    email.gsub /[^[:alnum:]]/, "_"
+    # Replace non-word chars with underscores, then make sure it starts with
+    # valid chars
+    email.gsub(/\W/, '_').gsub(/\A([\W\_])+/, '')
   end
 
   def is_admin?
diff --git a/app/roles/git_host.rb b/app/roles/git_host.rb
new file mode 100644
index 0000000000000000000000000000000000000000..aa620f77ea4275c44c9b761169517dd5932be6fd
--- /dev/null
+++ b/app/roles/git_host.rb
@@ -0,0 +1,5 @@
+module GitHost
+  def git_host
+    Gitlab::Gitolite.new
+  end
+end
diff --git a/app/roles/git_merge.rb b/app/roles/git_merge.rb
deleted file mode 100644
index 95e5942fb00a26ec443fc4a6d1babb8341bccbd7..0000000000000000000000000000000000000000
--- a/app/roles/git_merge.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-module GitMerge
-end
diff --git a/app/roles/issue_commonality.rb b/app/roles/issue_commonality.rb
index a8fd679df810748ad6163ef098088190a0fe839c..ac972a70df2ba6204783f1231dd528602fb11729 100644
--- a/app/roles/issue_commonality.rb
+++ b/app/roles/issue_commonality.rb
@@ -16,7 +16,7 @@ module IssueCommonality
     validates :title,
               presence: true,
               length: { within: 0..255 }
-
+    validates :closed, inclusion: { in: [true, false] }
 
     scope :opened, where(closed: false)
     scope :closed, where(closed: true)
diff --git a/app/roles/push_event.rb b/app/roles/push_event.rb
index ff8e28a2db27c601f9c50ba570678618e7932bcc..a607f212f2a520bd8b3bde0f91672581983ce34b 100644
--- a/app/roles/push_event.rb
+++ b/app/roles/push_event.rb
@@ -90,6 +90,8 @@ module PushEvent
 
   def push_with_commits? 
     md_ref? && commits.any? && parent_commit && last_commit
+  rescue Grit::NoSuchPathError
+    false
   end
 
   def last_push_to_non_root?
diff --git a/app/roles/push_observer.rb b/app/roles/push_observer.rb
index 1067404d5afab7596db92f5ed7593a851d7b6f07..947ed42345d494762cdf4deba278888c8e6c0f2b 100644
--- a/app/roles/push_observer.rb
+++ b/app/roles/push_observer.rb
@@ -1,3 +1,6 @@
+# Includes methods for handling Git Push events
+#
+# Triggered by PostReceive job
 module PushObserver
   def observe_push(oldrev, newrev, ref, user)
     data = post_receive_data(oldrev, newrev, ref, user)
@@ -84,11 +87,10 @@ module PushObserver
     data
   end
 
-
-  # This method will be called after each post receive
-  # and only if user present in gitlab.
-  # All callbacks for post receive should be placed here
+  # This method will be called after each post receive and only if the provided
+  # user is present in GitLab.
   #
+  # All callbacks for post receive should be placed here.
   def trigger_post_receive(oldrev, newrev, ref, user)
     # Create push event
     self.observe_push(oldrev, newrev, ref, user)
@@ -101,5 +103,11 @@ module PushObserver
 
     # Create satellite
     self.satellite.create unless self.satellite.exists?
+
+    # Discover the default branch, but only if it hasn't already been set to
+    # something else
+    if default_branch.nil?
+      update_attributes(default_branch: discover_default_branch)
+    end
   end
 end
diff --git a/app/roles/repository.rb b/app/roles/repository.rb
index 7f1d6f845496e61094db8b6b2f7f6f07f8c97516..01156ac18b70ed2cc19cf294a71f4b07e32b73d4 100644
--- a/app/roles/repository.rb
+++ b/app/roles/repository.rb
@@ -1,4 +1,6 @@
 module Repository
+  include GitHost
+
   def valid_repo?
     repo
   rescue
@@ -6,6 +8,10 @@ module Repository
     false
   end
 
+  def empty_repo?
+    !repo_exists? || !has_commits?
+  end
+
   def commit(commit_id = nil)
     Commit.find_or_first(repo, commit_id, root_ref)
   end
@@ -36,7 +42,7 @@ module Repository
 
   def has_post_receive_file?
     hook_file = File.join(path_to_repo, 'hooks', 'post-receive')
-    File.exists?(hook_file) 
+    File.exists?(hook_file)
   end
 
   def tags
@@ -48,7 +54,7 @@ module Repository
   end
 
   def url_to_repo
-    Gitlab::GitHost.url_to_repo(path)
+    git_host.url_to_repo(path)
   end
 
   def path_to_repo
@@ -56,16 +62,16 @@ module Repository
   end
 
   def update_repository
-    Gitlab::GitHost.system.update_project(path, self)
+    git_host.update_repository(self)
   end
 
   def destroy_repository
-    Gitlab::GitHost.system.destroy_project(self)
+    git_host.remove_repository(self)
   end
 
   def repo_exists?
     @repo_exists ||= (repo && !repo.branches.empty?)
-  rescue 
+  rescue
     @repo_exists = false
   end
 
@@ -73,6 +79,14 @@ module Repository
     @heads ||= repo.heads
   end
 
+  def branches_names
+    heads.map(&:name)
+  end
+
+  def ref_names
+    [branches_names + tags].flatten
+  end
+
   def tree(fcommit, path = nil)
     fcommit = commit if fcommit == :head
     tree = fcommit.tree
@@ -88,24 +102,42 @@ module Repository
     end.sort_by(&:name)
   end
 
+  # Discovers the default branch based on the repository's available branches
+  #
+  # - If no branches are present, returns nil
+  # - If one branch is present, returns its name
+  # - If two or more branches are present, returns the one that has a name
+  #   matching root_ref (default_branch or 'master' if default_branch is nil)
+  def discover_default_branch
+    branches = heads.collect(&:name)
+
+    if branches.length == 0
+      nil
+    elsif branches.length == 1
+      branches.first
+    else
+      branches.select { |v| v == root_ref }.first
+    end
+  end
+
   def has_commits?
     !!commit
   end
 
-  def root_ref 
+  def root_ref
     default_branch || "master"
   end
 
-  def root_ref? branch
+  def root_ref?(branch)
     root_ref == branch
   end
 
   # Archive Project to .tar.gz
   #
-  # Already packed repo archives stored at 
+  # Already packed repo archives stored at
   # app_root/tmp/repositories/project_name/project_name-commit-id.tag.gz
   #
-  def archive_repo ref
+  def archive_repo(ref)
     ref = ref || self.root_ref
     commit = self.commit(ref)
     return nil unless commit
@@ -115,10 +147,13 @@ module Repository
     storage_path = File.join(Rails.root, "tmp", "repositories", self.code)
     file_path = File.join(storage_path, file_name)
 
+    # Put files into a directory before archiving
+    prefix = self.code + "/"
+
     # Create file if not exists
     unless File.exists?(file_path)
       FileUtils.mkdir_p storage_path
-      file = self.repo.archive_to_file(ref, nil,  file_path)
+      file = self.repo.archive_to_file(ref, prefix,  file_path)
     end
 
     file_path
@@ -129,6 +164,6 @@ module Repository
   end
 
   def http_url_to_repo
-    http_url = [Gitlab.config.url, "/", path, ".git"].join()
+    http_url = [Gitlab.config.url, "/", path, ".git"].join('')
   end
 end
diff --git a/app/roles/ssh_key.rb b/app/roles/ssh_key.rb
deleted file mode 100644
index 5e1d2c23d159cb5ca1f139bec1b00cb57d36f9f6..0000000000000000000000000000000000000000
--- a/app/roles/ssh_key.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-module SshKey
-  def update_repository
-    Gitlab::GitHost.system.new.configure do |c|
-      c.update_keys(identifier, key)
-      c.update_projects(projects)
-    end
-  end
-
-  def repository_delete_key
-    Gitlab::GitHost.system.new.configure do |c|
-      #delete key file is there is no identically deploy keys
-      if !is_deploy_key || Key.where(identifier: identifier).count() == 0
-        c.delete_key(identifier)
-      end
-      c.update_projects(projects)
-    end
-  end
-end
diff --git a/app/roles/static_model.rb b/app/roles/static_model.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d26c8f4750132afb8a07022f64c977b59e1b4f72
--- /dev/null
+++ b/app/roles/static_model.rb
@@ -0,0 +1,35 @@
+# Provides an ActiveRecord-like interface to a model whose data is not persisted to a database.
+module StaticModel
+  extend ActiveSupport::Concern
+
+  module ClassMethods
+    # Used by ActiveRecord's polymorphic association to set object_id
+    def primary_key
+      'id'
+    end
+
+    # Used by ActiveRecord's polymorphic association to set object_type
+    def base_class
+      self
+    end
+  end
+
+  # Used by AR for fetching attributes
+  #
+  # Pass it along if we respond to it.
+  def [](key)
+    send(key) if respond_to?(key)
+  end
+
+  def to_param
+    id
+  end
+
+  def persisted?
+    false
+  end
+
+  def destroyed?
+    false
+  end
+end
diff --git a/app/roles/team.rb b/app/roles/team.rb
index 27b1cc6589727cbac6eaf97e048724018d771a2e..8aef405aaf36d8691a7121f209cdaadf301742e2 100644
--- a/app/roles/team.rb
+++ b/app/roles/team.rb
@@ -36,4 +36,17 @@ module Team
     UsersProject.bulk_import(self, users_ids, access_role)
     self.update_repository
   end
+
+  # Update multiple project users
+  # to same access role by user ids
+  def update_users_ids_to_role(users_ids, access_role)
+    UsersProject.bulk_update(self, users_ids, access_role)
+    self.update_repository
+  end
+
+  # Delete multiple users from project by user ids
+  def delete_users_ids_from_team(users_ids)
+    UsersProject.bulk_delete(self, users_ids)
+    self.update_repository
+  end
 end
diff --git a/app/roles/upvote.rb b/app/roles/upvote.rb
deleted file mode 100644
index 7efa6f20cfcc321968f4e00dd00b8420ac3171b5..0000000000000000000000000000000000000000
--- a/app/roles/upvote.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Upvote
-  # Return the number of +1 comments (upvotes)
-  def upvotes
-    notes.select(&:upvote?).size
-  end
-end
diff --git a/app/roles/votes.rb b/app/roles/votes.rb
new file mode 100644
index 0000000000000000000000000000000000000000..043a6feb7775b9e0cdd98811f31c0c7d49a20df0
--- /dev/null
+++ b/app/roles/votes.rb
@@ -0,0 +1,32 @@
+module Votes
+  # Return the number of +1 comments (upvotes)
+  def upvotes
+    notes.select(&:upvote?).size
+  end
+
+  def upvotes_in_percent
+    if votes_count.zero?
+      0
+    else
+      100.0 / votes_count * upvotes
+    end
+  end
+
+  # Return the number of -1 comments (downvotes)
+  def downvotes
+    notes.select(&:downvote?).size
+  end
+
+  def downvotes_in_percent
+    if votes_count.zero?
+      0
+    else
+      100.0 - upvotes_in_percent
+    end
+  end
+
+  # Return the total number of votes
+  def votes_count
+    upvotes + downvotes
+  end
+end
diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml
index 2e67abfc16d48882d28d7d893e449fef77fe1754..3e26f566a2eef91c253b5ddde1009a615975e470 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -35,11 +35,13 @@
     %h3 Latest projects
     %hr
     - @projects.each do |project|
-      %h5
+      %p
         = link_to project.name, [:admin, project]
   .span6
     %h3 Latest users
     %hr
     - @users.each do |user|
-      %h5
-        = link_to user.name, [:admin, user]
+      %p
+        = link_to [:admin, user] do 
+          = user.name
+          %small= user.email
diff --git a/app/views/admin/hooks/index.html.haml b/app/views/admin/hooks/index.html.haml
index 43288424e8ed47c81b7b81e1e72bfbf9504e7cd6..f17355fb2c2996f77851c7fa5704e50c454c52bb 100644
--- a/app/views/admin/hooks/index.html.haml
+++ b/app/views/admin/hooks/index.html.haml
@@ -23,7 +23,7 @@
     Hooks
     %small (#{@hooks.count})
   %br
-  %table.admin-table
+  %table
     %tr
       %th URL
       %th Method
diff --git a/app/views/admin/logs/show.html.haml b/app/views/admin/logs/show.html.haml
index 800d3bb288f0af9cedd53a4c8733a020fc1c2a67..0efe6db7483242f2f5e516782af8ab79c27f4dbb 100644
--- a/app/views/admin/logs/show.html.haml
+++ b/app/views/admin/logs/show.html.haml
@@ -1,9 +1,26 @@
-.file_holder#README
-  .file_title
-    %i.icon-file
-    githost.log
-  .file_content.logs
-    %ol
-      - Gitlab::Logger.read_latest.each do |line|
-        %li
-          %p= line
+%ul.nav.nav-tabs.log-tabs
+  %li.active
+    = link_to "githost.log", "#githost", 'data-toggle' => 'tab'
+  %li
+    = link_to "application.log", "#application", 'data-toggle' => 'tab'
+.tab-content
+  .tab-pane.active#githost
+    .file_holder#README
+      .file_title
+        %i.icon-file
+        githost.log
+      .file_content.logs
+        %ol
+          - Gitlab::GitLogger.read_latest.each do |line|
+            %li
+              %p= line
+  .tab-pane#application
+    .file_holder#README
+      .file_title
+        %i.icon-file
+        application.log
+      .file_content.logs
+        %ol
+          - Gitlab::AppLogger.read_latest.each do |line|
+            %li
+              %p= line
diff --git a/app/views/admin/projects/_form.html.haml b/app/views/admin/projects/_form.html.haml
index 7cebddf28900a4579806c46adc275a23bee09ef5..4848e7391a3370f7b093da3d7691f217ec954e05 100644
--- a/app/views/admin/projects/_form.html.haml
+++ b/app/views/admin/projects/_form.html.haml
@@ -10,19 +10,17 @@
       Project name is
     .input
       = f.text_field :name, placeholder: "Example Project", class: "xxlarge"
-      = f.submit project.new_record? ? 'Create project' : 'Save Project', class: "btn primary"
 
   %hr
-  .alert.alert-info
-    %h5 Advanced settings:
+  .adv_settings
+    %h6 Advanced settings:
     .clearfix
       = f.label :path do
-        Git Clone
+        Path
       .input
         .input-prepend
-          %span.add-on= Gitlab.config.ssh_path
-          = f.text_field :path, placeholder: "example_project", disabled: !!project.id
-          %span.add-on= ".git"
+          %strong
+            = text_field_tag :ppath, @admin_project.path_to_repo, class: "xlarge", disabled: true
     .clearfix
       = f.label :code do
         URL
@@ -34,7 +32,7 @@
     - unless project.new_record?
       .clearfix
         = f.label :owner_id
-        .input= f.select :owner_id, User.all.map { |user| [user.name, user.id] }
+        .input= f.select :owner_id, User.all.map { |user| [user.name, user.id] }, {}, {class: 'chosen'}
 
       - if project.repo_exists?
         .clearfix
@@ -42,8 +40,9 @@
           .input= f.select(:default_branch, project.heads.map(&:name), {}, style: "width:210px;")
 
   - unless project.new_record?
-    .alert.alert-info
-      %h5 Features:
+    %hr
+    .adv_settings
+      %h6 Features:
 
       .clearfix
         = f.label :issues_enabled, "Issues"
@@ -63,13 +62,13 @@
 
   - unless project.new_record?
     .actions
-      = f.submit 'Save Project', class: "btn primary"
+      = f.submit 'Save Project', class: "btn save-btn"
+      = link_to 'Cancel', admin_projects_path, class: "btn cancel-btn"
 
 
 
 :javascript
   $(function(){
-    $('#project_owner_id').chosen();
     new Projects();
   })
 
diff --git a/app/views/admin/projects/_new_form.html.haml b/app/views/admin/projects/_new_form.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..d793b6f3affbc75765a89b4ded930c324a89f5a5
--- /dev/null
+++ b/app/views/admin/projects/_new_form.html.haml
@@ -0,0 +1,29 @@
+= form_for [:admin, @admin_project] do |f|
+  - if @admin_project.errors.any?
+    .alert-message.block-message.error
+      %span= @admin_project.errors.full_messages.first
+  .clearfix.project_name_holder
+    = f.label :name do
+      Project name is
+    .input
+      = f.text_field :name, placeholder: "Example Project", class: "xxlarge"
+      = f.submit 'Create project', class: "btn primary project-submit"
+
+  %hr
+  %div.adv_settings
+    %h6 Advanced settings:
+    .clearfix
+      = f.label :path do
+        Git Clone
+      .input
+        .input-prepend
+          %span.add-on= Gitlab.config.ssh_path
+          = f.text_field :path, placeholder: "example_project", disabled: !@admin_project.new_record?
+          %span.add-on= ".git"
+    .clearfix
+      = f.label :code do
+        URL
+      .input
+        .input-prepend
+          %span.add-on= web_app_url
+          = f.text_field :code, placeholder: "example"
diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml
index 882b2ab5ff2765fccbf5f5ea2140a729343742ac..bd38ae72f7c41d9dbece9977735200bad7567c88 100644
--- a/app/views/admin/projects/index.html.haml
+++ b/app/views/admin/projects/index.html.haml
@@ -1,4 +1,4 @@
-%h3
+%h3.page_title
   Projects
   = link_to 'New Project', new_admin_project_path, class: "btn small right"
 %br
@@ -6,7 +6,7 @@
   = text_field_tag :name, params[:name], class: "xlarge"
   = submit_tag "Search", class: "btn submit primary"
 
-%table.admin-table
+%table
   %thead
     %th Name
     %th Path
diff --git a/app/views/admin/projects/new.html.haml b/app/views/admin/projects/new.html.haml
index ac6526bfa4b6b9b4b15e0e4853e3749ebc789077..933cb671142881c0a1a347786fd41565bc3df221 100644
--- a/app/views/admin/projects/new.html.haml
+++ b/app/views/admin/projects/new.html.haml
@@ -1,3 +1,12 @@
-%h3.page_title New project
-%hr
-= render 'form', project: @admin_project
+.project_new_holder
+  %h3.page_title
+    New Project
+  %hr
+  = render 'new_form'
+%div.save-project-loader.hide
+  %center
+    = image_tag "ajax_loader.gif"
+    %h3 Creating project &amp; repository. Please wait a few minutes
+
+:javascript
+  $(function(){ new Projects(); });
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index 5ed564779055a4da529ab8cee412dfc92b2dfbf5..639874109eb17dd12ce7fa04d652cb2bd4d1cec9 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -3,7 +3,11 @@
   = link_to 'Edit', edit_admin_project_path(@admin_project), class: "btn right small"
 
 %br
-%table.zebra-striped.table-bordered
+%table.zebra-striped
+  %thead
+    %tr
+      %th Project
+      %th
   %tr
     %td
       %b
@@ -40,7 +44,7 @@
   %small
     (#{@admin_project.users_projects.count})
 %br
-%table.zebra-striped.table-bordered
+%table.zebra-striped
   %thead
     %tr
       %th Name
@@ -60,32 +64,18 @@
 %h3 Add new team member
 %br
 = form_tag team_update_admin_project_path(@admin_project), class: "bulk_import", method: :put  do
-  %table.zebra-striped.table-bordered
+  %table.zebra-striped
     %thead
       %tr
         %th Users
         %th Project Access:
 
     %tr
-      %td= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name),  multiple: true
-      %td= select_tag :project_access, options_for_select(Project.access_options), class: "project-access-select"
+      %td= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name), multiple: true, data: {placeholder: 'Select users'}, class: 'chosen span5'
+      %td= select_tag :project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3"}
 
     %tr
       %td= submit_tag 'Add', class: "btn primary"
       %td
         Read more about project permissions
         %strong= link_to "here", help_permissions_path, class: "vlink"
-
-:css
-  form select {
-    width:150px;
-  }
-
-  #user_ids {
-    width:300px;
-  }
-
-:javascript
-  $('select#user_ids').chosen();
-  $('select#repo_access').chosen();
-  $('select#project_access').chosen();
diff --git a/app/views/admin/resque/show.html.haml b/app/views/admin/resque/show.html.haml
index 0375d94bc9de06b605031bb7deb2c8839144650d..8850e378a6ccbc6cfa8db5c9f452a586f1ac76e9 100644
--- a/app/views/admin/resque/show.html.haml
+++ b/app/views/admin/resque/show.html.haml
@@ -1,2 +1,4 @@
-%h3 Resque
-%iframe{src: "/info/resque", width: 1168, height: 600, style: "border: none"}
\ No newline at end of file
+%h3.page_title Resque
+%br
+.ui-box
+  %iframe{src: resque_url, width: '100%', height: 600, style: "border: none"}
diff --git a/app/views/admin/team_members/_form.html.haml b/app/views/admin/team_members/_form.html.haml
index 6a128de94b265e452a15a1b895ba1dfb30e02e02..9cd94fdd30f11e7cb40943b930f084031accd709 100644
--- a/app/views/admin/team_members/_form.html.haml
+++ b/app/views/admin/team_members/_form.html.haml
@@ -8,20 +8,9 @@
   .clearfix
     %label Project Access:
     .input
-      = f.select :project_access, options_for_select(Project.access_options, @admin_team_member.project_access), {}, class: "project-access-select"
+      = f.select :project_access, options_for_select(Project.access_options, @admin_team_member.project_access), {}, class: "project-access-select chosen span3"
 
   %br
   .actions
     = f.submit 'Save', class: "btn primary"
     = link_to 'Cancel', :back, class: "btn"
-
-:css
-  form select {
-    width:300px;
-  }
-
-:javascript
-  $('select#team_member_user_id').chosen();
-  $('select#team_member_project_id').chosen();
-  $('select#team_member_repo_access').chosen();
-  $('select#team_member_project_access').chosen();
diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml
index 5e68a23f494c0bb176a1abff32e93558a1a759dd..7010c2727c6085dedd892ab13e0e4f6d32934bdc 100644
--- a/app/views/admin/users/_form.html.haml
+++ b/app/views/admin/users/_form.html.haml
@@ -2,71 +2,79 @@
   = form_for [:admin, @admin_user] do |f|
     -if @admin_user.errors.any?
       #error_explanation
-        %ul
+        %ul.unstyled.alert.alert-error
           - @admin_user.errors.full_messages.each do |msg|
             %li= msg
 
     .row
-      .span6
-        .clearfix
-          = f.label :name
-          .input
-            = f.text_field :name
-            %span.help-inline * required
-        .clearfix
-          = f.label :email
-          .input
-            = f.text_field :email
-            %span.help-inline * required
-        %hr
-
-        -if f.object.new_record?
-          .clearfix 
-            = f.label :admin, class: "checkbox" do
-              = f.check_box :force_random_password, {}, true, nil
-            %span Generate random password
-        
-        %div.password-fields
+      .span7
+        .ui-box
+          %br
           .clearfix
-            = f.label :password
-            .input= f.password_field :password, disabled: f.object.force_random_password 
+            = f.label :name
+            .input
+              = f.text_field :name
+              %span.help-inline * required
           .clearfix
-            = f.label :password_confirmation
-            .input= f.password_field :password_confirmation, disabled: f.object.force_random_password
-        %hr
-        .clearfix
-          = f.label :skype
-          .input= f.text_field :skype
-        .clearfix
-          = f.label :linkedin
-          .input= f.text_field :linkedin
-        .clearfix
-          = f.label :twitter
-          .input= f.text_field :twitter
-      .span6
-        .clearfix
-          = f.label :projects_limit
-          .input= f.text_field :projects_limit, class: "small_input"
+            = f.label :email
+            .input
+              = f.text_field :email
+              %span.help-inline * required
+          %hr
+          -if f.object.new_record?
+            .clearfix
+              = f.label :force_random_password do
+                %span Generate random password
+              .input= f.check_box :force_random_password, {}, true, nil
+          
+          %div.password-fields
+            .clearfix
+              = f.label :password
+              .input= f.password_field :password, disabled: f.object.force_random_password 
+            .clearfix
+              = f.label :password_confirmation
+              .input= f.password_field :password_confirmation, disabled: f.object.force_random_password
+          %hr
+          .clearfix
+            = f.label :skype
+            .input= f.text_field :skype
+          .clearfix
+            = f.label :linkedin
+            .input= f.text_field :linkedin
+          .clearfix
+            = f.label :twitter
+            .input= f.text_field :twitter
+      .span5
+        .ui-box
+          %br
+          .clearfix
+            = f.label :projects_limit
+            .input= f.number_field :projects_limit
 
-        .alert
           .clearfix
-            %p Make the user a GitLab administrator.
-            = f.label :admin, class: "checkbox" do
-              = f.check_box :admin
-              %span Administrator
-        - unless @admin_user.new_record?
-          .alert.alert-error
-            - if @admin_user.blocked
-              %span
-                = link_to 'Unblock', unblock_admin_user_path(@admin_user), method: :put, class: "btn small"
-                This user is blocked and is not able to login to GitLab
-            - else
-              %span
-                = link_to 'Block', block_admin_user_path(@admin_user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn small danger"
-                Blocked users will be removed from all projects &amp; will not be able to login to GitLab.
+            = f.label :admin do
+              %strong.cred Administrator
+            .input= f.check_box :admin
+          - unless @admin_user.new_record?
+            %hr
+            .padded.cred
+              - if @admin_user.blocked
+                %span
+                  This user is blocked and is not able to login to GitLab
+                  .clearfix
+                    = link_to 'Unblock User', unblock_admin_user_path(@admin_user), method: :put, class: "btn small right"
+              - else
+                %span
+                  Blocked users will be removed from all projects &amp; will not be able to login to GitLab.
+                  .clearfix
+                    = link_to 'Block User', block_admin_user_path(@admin_user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn small right danger"
+
+    .row
+      .span6
+      .span6
     .actions
-      = f.submit 'Save', class: "btn primary"
+      = f.submit 'Save', class: "btn save-btn"
       - if @admin_user.new_record?
-        = link_to 'Cancel', admin_users_path, class: "btn"
+        = link_to 'Cancel', admin_users_path, class: "btn cancel-btn"
       - else
-        = link_to 'Cancel', admin_user_path(@admin_user), class: "btn"
+        = link_to 'Cancel', admin_user_path(@admin_user), class: "btn cancel-btn"
diff --git a/app/views/admin/users/edit.html.haml b/app/views/admin/users/edit.html.haml
index 0e94be9e12c042379d5ed9ef21f644ce9aa6e500..032e3cfaa996b7251a10b5333abbd6ba3afdf9ef 100644
--- a/app/views/admin/users/edit.html.haml
+++ b/app/views/admin/users/edit.html.haml
@@ -1,3 +1,3 @@
-%h3= @admin_user.name
+%h3.page_title #{@admin_user.name} &rarr; Edit user
 %hr
 = render 'form'
diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml
index 3d0272179c4489af33583a32fa820d5a6b817dc9..5ef94ef5f34b267d03a711e569407d47587e7038 100644
--- a/app/views/admin/users/index.html.haml
+++ b/app/views/admin/users/index.html.haml
@@ -1,4 +1,4 @@
-%h3
+%h3.page_title
   Users
   = link_to 'New User', new_admin_user_path, class: "btn small right"
 %br
@@ -19,7 +19,7 @@
     = link_to admin_users_path(filter: "wop") do
       Without projects
 
-%table.admin-table
+%table
   %thead
     %th Admin
     %th Name
diff --git a/app/views/admin/users/new.html.haml b/app/views/admin/users/new.html.haml
index 87d6b0f27574168e017cf95349dcd87b33424555..70ead0d3f7d6109ec9cb4dd7b8f9e9469e0b8793 100644
--- a/app/views/admin/users/new.html.haml
+++ b/app/views/admin/users/new.html.haml
@@ -1,3 +1,3 @@
-%h2 New user
-%hr
+%h3.page_title New user
+%br
 = render 'form'
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index 4cca8ed7a4ec6bca22cf7f69d167d98cf039434a..731916e97de5b05b3dea8bc908c871e3ac62e996 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -8,7 +8,11 @@
 
 %br
 
-%table.zebra-striped.table-bordered
+%table.zebra-striped
+  %thead
+    %tr
+      %th Profile
+      %th
   %tr
     %td
       %b
@@ -57,15 +61,15 @@
 %h3 Add User to Projects
 %br
 = form_tag team_update_admin_user_path(@admin_user), class: "bulk_import", method: :put  do
-  %table.table-bordered
+  %table
     %thead
       %tr
         %th Projects
         %th Project Access:
 
     %tr
-      %td= select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name),  multiple: true
-      %td= select_tag :project_access, options_for_select(Project.access_options), class: "project-access-select"
+      %td= select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name),  multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5'
+      %td= select_tag :project_access, options_for_select(Project.access_options), class: "project-access-select chosen span3"
 
     %tr
       %td= submit_tag 'Add', class: "btn primary"
@@ -78,9 +82,9 @@
   %h3 Projects
   %br
 
-  %table.zebra-striped.table-bordered
-    %tr
-      %thead
+  %table.zebra-striped
+    %thead
+      %tr
         %th Name
         %th Project Access
         %th
@@ -93,17 +97,3 @@
         %td= select_tag :tm_project_access, options_for_select(Project.access_options, tm.project_access), class: "medium project-access-select", disabled: :disabled
         %td= link_to 'Edit Access', edit_admin_team_member_path(tm), class: "btn small"
         %td= link_to 'Remove from team', admin_team_member_path(tm), confirm: 'Are you sure?', method: :delete, class: "btn small danger"
-
-:css
-  form select {
-    width:150px;
-  }
-
-  #project_ids {
-    width:300px;
-  }
-
-:javascript
-  $('select#project_ids').chosen();
-  $('select#repo_access').chosen();
-  $('select#project_access').chosen();
diff --git a/app/views/commits/_commit.html.haml b/app/views/commits/_commit.html.haml
index 686a4337b3a4a44b00af33405699697d3f513dfa..61371d14c5f10759decbc6555cf106902e3fde74 100644
--- a/app/views/commits/_commit.html.haml
+++ b/app/views/commits/_commit.html.haml
@@ -4,8 +4,8 @@
       %strong= link_to "Browse Code »", tree_project_ref_path(@project, commit.id), class: "right"
   %p
     = link_to commit.short_id(8), project_commit_path(@project, id: commit.id), class: "commit_short_id"
-    %strong.cgray= commit.author_name
-    &ndash;
+    %strong.commit-author-name= commit.author_name
+    %span.dash &ndash;
     = image_tag gravatar_icon(commit.author_email), class: "avatar", width: 16
     = link_to_gfm truncate(commit.title, length: 50), project_commit_path(@project, id: commit.id), class: "row_title"
 
diff --git a/app/views/commits/_commit_box.html.haml b/app/views/commits/_commit_box.html.haml
index 506f4e092a1e406da28b826ce3d5c88227fd1454..572337debc889ff04f3698aa737a2e113fab609b 100644
--- a/app/views/commits/_commit_box.html.haml
+++ b/app/views/commits/_commit_box.html.haml
@@ -11,10 +11,10 @@
       = link_to tree_project_ref_path(@project, @commit.id), class: "browse-button primary grouped" do
         %strong Browse Code »
     %h3.commit-title.page_title
-      = gfm @commit.title
+      = gfm escape_once(@commit.title)
     - if @commit.description.present?
       %pre.commit-description
-        = gfm @commit.description
+        = gfm escape_once(@commit.description)
   .commit-info
     .row
       .span4
diff --git a/app/views/commits/_head.html.haml b/app/views/commits/_head.html.haml
index a211329f3497cd8a54ffbb2c1b38e991d3c98a5d..a8111a72ed57f7a2fd6490d03ef3ffff8746dff2 100644
--- a/app/views/commits/_head.html.haml
+++ b/app/views/commits/_head.html.haml
@@ -1,9 +1,5 @@
 %ul.nav.nav-tabs
-  %li
-    = form_tag switch_project_refs_path(@project), method: :get, class: "project-refs-form" do
-      = select_tag "ref", grouped_options_refs, onchange: "$(this.form).trigger('submit');", class: "project-refs-select"
-      = hidden_field_tag :destination, "commits"
-
+  %li= render partial: 'shared/ref_switcher', locals: {destination: 'commits'}
   %li{class: "#{'active' if current_page?(project_commits_path(@project)) }"}
     = link_to project_commits_path(@project) do
       Commits
@@ -20,14 +16,8 @@
       Tags
       %span.badge= @project.repo.tag_count
 
-
   - if current_page?(project_commits_path(@project)) && current_user.private_token
     %li.right
       %span.rss-icon
         = link_to project_commits_path(@project, :atom, { private_token: current_user.private_token, ref: @ref }), title: "Feed" do
           = image_tag "rss_ui.png", title: "feed"
-
-:javascript
-  $(function(){
-    $('.project-refs-select').chosen();
-  });
diff --git a/app/views/commits/_text_file.html.haml b/app/views/commits/_text_file.html.haml
index 0f6210f2b5a0c094d542425ad87158f1d70df24e..9f5b5345d5f76a735b335a283c5d53d0f3910b97 100644
--- a/app/views/commits/_text_file.html.haml
+++ b/app/views/commits/_text_file.html.haml
@@ -13,14 +13,11 @@
         %td.old_line
           = link_to raw(type == "new" ? "&nbsp;" : line_old), "##{line_code}", id: line_code
           - if @comments_allowed
-            = link_to "", "#", class: "line_note_link", "line_code" => line_code, title: "Add note for this line"
+            = render "notes/per_line_note_link", line_code: line_code
         %td.new_line= link_to raw(type == "old" ? "&nbsp;" : line_new) , "##{line_code}", id: line_code
         %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw "#{line} &nbsp;"
 
         - if @comments_allowed
-          - comments = @line_notes.select { |n| n.line_code == line_code }.sort_by(&:created_at).reverse
+          - comments = @line_notes.select { |n| n.line_code == line_code }.sort_by(&:created_at)
           - unless comments.empty?
-            - comments.each_with_index do |note, i|
-              = render "notes/reply_button", line_code: line_code if i.zero?
-              = render "notes/per_line_show", note: note
-              - @line_notes.reject!{ |n| n == note }
+            = render "notes/per_line_notes_with_reply", notes: comments
diff --git a/app/views/commits/compare.html.haml b/app/views/commits/compare.html.haml
index be915cd10386ae6c3489622e58b3685b5ac3c94c..db15ba53823ab5f473a4fef9c5d30c8fefad49e7 100644
--- a/app/views/commits/compare.html.haml
+++ b/app/views/commits/compare.html.haml
@@ -1,16 +1,16 @@
 = render "head"
 
-%h3
+%h3.page_title
   Compare View
 %hr
 
 %div
-  %p
+  %p.slead
     Fill input field with commit id like
-    %code '4eedf23'
+    %code.label_branch 4eedf23
     or branch/tag name like
-    %code master
-    &amp; press compare button for commits list, code diff.
+    %code.label_branch master
+    and press compare button for commits list, code diff.
 
   %br
 
@@ -19,22 +19,24 @@
       = text_field_tag :from, params[:from], placeholder: "master", class: "xlarge"
       = "..."
       = text_field_tag :to, params[:to], placeholder: "aa8b4ef", class: "xlarge"
+    - if @refs_are_same
+      .alert
+        %span Refs are the same
     .actions
-      = submit_tag "Compare", class: "btn btn-primary"
+      = submit_tag "Compare", class: "btn primary wide commits-compare-btn"
 
-
-- unless @commits.empty?
+- if @commits.present?
   %div.ui-box
     %h5.small Commits (#{@commits.count})
     %ul.unstyled= render @commits
 
-- unless @diffs.empty?
-  %h4 Diff
-  = render "commits/diffs", diffs: @diffs
+  - unless @diffs.empty?
+    %h4 Diff
+    = render "commits/diffs", diffs: @diffs
 
 :javascript
   $(function() {
-    var availableTags = #{@project.heads.map(&:name).to_json};
+    var availableTags = #{@project.ref_names.to_json};
 
     $("#from").autocomplete({
       source: availableTags,
@@ -45,5 +47,7 @@
       source: availableTags,
       minLength: 1
     });
+
+    disableButtonIfEmptyField('#to', '.commits-compare-btn');
   });
 
diff --git a/app/views/commits/show.html.haml b/app/views/commits/show.html.haml
index 9a483aa2a9ac8fcbf58763772e95ae4e8c5c2ed6..d12fff96835e5f77adba037c8ade5535d524bfb5 100644
--- a/app/views/commits/show.html.haml
+++ b/app/views/commits/show.html.haml
@@ -1,16 +1,10 @@
 = render "commits/commit_box"
 = render "commits/diffs", diffs: @commit.diffs
-= render "notes/notes", tid: @commit.id, tt: "commit"
+= render "notes/notes_with_form", tid: @commit.id, tt: "commit"
 = render "notes/per_line_form"
 
 
 :javascript
-  $(document).ready(function(){
-    $(".line_note_link, .line_note_reply_link").live("click", function(e) {
-      var form = $(".per_line_form");
-      $(this).parent().parent().after(form);
-      form.find("#note_line_code").val($(this).attr("line_code"));
-      form.show();
-      return false;
-    });
+  $(function(){
+    PerLineNotes.init();
   });
diff --git a/app/views/dashboard/index.html.haml b/app/views/dashboard/index.html.haml
index ba7d019cb638ff9ba7f6310cd04ac39b2a9bb655..791c18e353966d77ea70afccdb02036a469402bc 100644
--- a/app/views/dashboard/index.html.haml
+++ b/app/views/dashboard/index.html.haml
@@ -19,22 +19,31 @@
               = link_to new_project_path, class: "btn very_small info" do
                 %i.icon-plus
                 New Project
-        - @projects.each do |project|
-          = link_to project_path(project), class: dom_class(project) do
-            %h4
-              %span.ico.project
-              = truncate(project.name, length: 25)
-              %span.right
-                &rarr;
+        %ul.unstyled
+          - @projects.each do |project|
+            %li.wll
+              = link_to project_path(project), class: dom_class(project) do
+                %strong.project_name= truncate(project.name, length: 25)
+                %span.arrow
+                  &rarr;
+                %span.last_activity
+                  %strong Last activity:
+                  %span= project_last_activity(project)
         .bottom= paginate @projects, theme: "gitlab"
 
-      %hr
       %div
         %span.rss-icon
           = link_to dashboard_path(:atom, { private_token: current_user.private_token }) do
             = image_tag "rss_ui.png", title: "feed"
             %strong News Feed
 
+      %hr
+      .gitlab-promo
+        = link_to "Homepage", "http://gitlabhq.com"
+        = link_to "Blog", "http://blog.gitlabhq.com"
+        = link_to "@gitlabhq", "https://twitter.com/gitlabhq"
+
+
 - else
   %h3.nothing_here_message There are no projects you have access to.
   %br
diff --git a/app/views/deploy_keys/_form.html.haml b/app/views/deploy_keys/_form.html.haml
index 461f1f5d84ac0e4eebf3ccb730e04da8dbc43087..6beba562a9508967fa429e3a30dafe00dbbf94f5 100644
--- a/app/views/deploy_keys/_form.html.haml
+++ b/app/views/deploy_keys/_form.html.haml
@@ -11,8 +11,13 @@
       .input= f.text_field :title
     .clearfix
       = f.label :key
-      .input= f.text_area :key, class: "xlarge"
+      .input
+        = f.text_area :key, class: [:xxlarge, :thin_area]
+        %p.hint
+          Paste a machine public key here. Read more about how generate it
+          = link_to "here", help_ssh_path
+
     .actions
-      = f.submit 'Save', class: "primary btn"
-      = link_to "Cancel", project_deploy_keys_path(@project), class: "btn"
+      = f.submit 'Save', class: "save-btn btn"
+      = link_to "Cancel", project_deploy_keys_path(@project), class: "btn cancel-btn"
 
diff --git a/app/views/deploy_keys/index.html.haml b/app/views/deploy_keys/index.html.haml
index 0ee9d03b0f5d355dac6ffd7ee4781ffc2db396e8..b9c654a1abe5cbbc7d974f0f3ba66638e430daaf 100644
--- a/app/views/deploy_keys/index.html.haml
+++ b/app/views/deploy_keys/index.html.haml
@@ -1,11 +1,17 @@
 = render "repositories/head"
-- if can? current_user, :admin_project, @project
-  .alert-message.block-message
-    Deploy keys allow read-only access to repository.
+
+%p.slead
+  Deploy keys allow read-only access to repository. It matches perfectly for CI, staging or production servers.
+
+  - if can? current_user, :admin_project, @project
     = link_to new_project_deploy_key_path(@project), class: "btn small", title: "New Deploy Key" do
       Add Deploy Key
-
 - if @keys.any?
   %table
+    %thead
+      %tr
+        %th Keys
+        %th
+        %th
     - @keys.each do |key|
       = render(partial: 'show', locals: {key: key})
diff --git a/app/views/deploy_keys/new.html.haml b/app/views/deploy_keys/new.html.haml
index a2f1010b45473c24dfe86c5ba67bf757102f0618..e973cb7d305778f1f32bb895d075297c25a45c43 100644
--- a/app/views/deploy_keys/new.html.haml
+++ b/app/views/deploy_keys/new.html.haml
@@ -1,6 +1,6 @@
 = render "repositories/head"
 
-%h3 New Deploy key
+%h3.page_title New Deploy key
 %hr
 
 = render 'form'
diff --git a/app/views/deploy_keys/show.html.haml b/app/views/deploy_keys/show.html.haml
index b1e0dc5ce27563d962bac3ef8a3965b6d670bb50..c94cf10dde09a62dd15258c9cad2ca5108d741b6 100644
--- a/app/views/deploy_keys/show.html.haml
+++ b/app/views/deploy_keys/show.html.haml
@@ -1,7 +1,14 @@
 = render "repositories/head"
-%h3= @key.title
+%h3.page_title
+  Deploy key:
+  = @key.title
+  %small
+    created at
+    = @key.created_at.stamp("Aug 21, 2011")
+.back_link
+  = link_to project_deploy_keys_path(@project) do
+    &larr; To keys list
 %hr
 %pre= @key.key
-.actions
+.right
   = link_to 'Remove', project_deploy_key_path(@key.project, @key), confirm: 'Are you sure?', method: :delete, class: "danger btn delete-key"
-  .clear
diff --git a/app/views/devise/sessions/_new_ldap.html.erb b/app/views/devise/sessions/_new_ldap.html.erb
deleted file mode 100644
index 35dfaf714092c4295abff24d8c007e90a15eb0a2..0000000000000000000000000000000000000000
--- a/app/views/devise/sessions/_new_ldap.html.erb
+++ /dev/null
@@ -1,39 +0,0 @@
-<%= form_tag(user_omniauth_callback_path(:ldap), :class => "login-box", :id => 'new_ldap_user' ) do %>
-  <%= image_tag "login-logo.png", :width => "304", :height => "66", :class => "login-logo", :alt => "Login Logo" %>
-
-  <%= text_field_tag :username, nil, {:class => "text top", :placeholder => "LDAP Login"} %>
-  <%= password_field_tag :password, nil, {:class => "text bottom", :placeholder => "Password"} %>
-
-  <br/>
-  <%= submit_tag "LDAP Sign in", :class => "primary btn" %>
-
-  <%- if devise_mapping.omniauthable? %>
-    <%- (resource_class.omniauth_providers - [:ldap]).each do |provider| %>
-      <hr/>
-      <%= link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider), :class => "btn primary" %><br />
-    <% end -%>
-  <% end -%>
-
-  <hr/>
-  <a href="#" id="other_form_toggle" onclick="javascript:$('#new_user').toggle();">Other Sign in</a>
-  <!-- inline for right now just to illustrate -->
-  <script type="text/javascript">
-    $(function() {
-      $('#new_user').toggle();
-    });
-  </script>
-<% end %>
-
-
-<%= form_for(resource, :as => resource_name, :url => session_path(resource_name), :html => { :class => "login-box" }) do |f| %>
-  <%= f.text_field :email, :class => "text top", :placeholder => "Email" %>
-  <%= f.password_field :password, :class => "text bottom", :placeholder => "Password"  %>
-
-  <% if devise_mapping.rememberable? -%>
-    <div class="clearfix inputs-list"> <label class="checkbox remember_me" for="user_remember_me"><%= f.check_box :remember_me %><span>Remember me</span></label></div>
-  <% end -%>
-  <br/>
-  <%= f.submit "Sign in", :class => "primary btn" %>
-  <div class="right"> <%= render :partial => "devise/shared/links" %></div>
-
-<% end %>
diff --git a/app/views/devise/sessions/_new_ldap.html.haml b/app/views/devise/sessions/_new_ldap.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..4233aa61ecb5d80bab88186b737bb3435670eba0
--- /dev/null
+++ b/app/views/devise/sessions/_new_ldap.html.haml
@@ -0,0 +1,29 @@
+= form_tag(user_omniauth_callback_path(:ldap), :class => "login-box", :id => 'new_ldap_user' ) do
+  = image_tag "login-logo.png", :width => "304", :height => "66", :class => "login-logo", :alt => "Login Logo"
+  = text_field_tag :username, nil, {:class => "text top", :placeholder => "LDAP Login"}
+  = password_field_tag :password, nil, {:class => "text bottom", :placeholder => "Password"}
+  %br/
+  = submit_tag "LDAP Sign in", :class => "primary btn"
+  - if devise_mapping.omniauthable?
+    - (resource_class.omniauth_providers - [:ldap]).each do |provider|
+      %hr/
+      = link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider), :class => "btn primary"
+      %br/
+  %hr/
+  %a#other_form_toggle{:href => "#", :onclick => "javascript:$('#new_user').toggle();"} Other Sign in
+  :javascript
+    $(function() {
+      $('#new_user').toggle();
+    });
+= form_for(resource, :as => resource_name, :url => session_path(resource_name), :html => { :class => "login-box" }) do |f|
+  = f.text_field :email, :class => "text top", :placeholder => "Email"
+  = f.password_field :password, :class => "text bottom", :placeholder => "Password"
+  - if devise_mapping.rememberable?
+    .clearfix.inputs-list
+      %label.checkbox.remember_me{:for => "user_remember_me"}
+        = f.check_box :remember_me
+        %span Remember me
+  %br/
+  = f.submit "Sign in", :class => "primary btn"
+  .right
+    = render :partial => "devise/shared/links"
diff --git a/app/views/devise/sessions/new.html.erb b/app/views/devise/sessions/new.html.erb
deleted file mode 100644
index a03838669cf9c8c859f9d92d10247910fb0c84c0..0000000000000000000000000000000000000000
--- a/app/views/devise/sessions/new.html.erb
+++ /dev/null
@@ -1,27 +0,0 @@
-<% unless ldap_enable? -%>
-
-  <%= form_for(resource, :as => resource_name, :url => session_path(resource_name), :html => { :class => "login-box" }) do |f| %>
-    <%= image_tag "login-logo.png", :width => "304", :height => "66", :class => "login-logo", :alt => "Login Logo" %>
-
-    <%= f.text_field :email, :class => "text top", :placeholder => "Email" %>
-    <%= f.password_field :password, :class => "text bottom", :placeholder => "Password"  %>
-
-    <% if devise_mapping.rememberable? -%>
-      <div class="clearfix inputs-list"> <label class="checkbox remember_me" for="user_remember_me"><%= f.check_box :remember_me %><span>Remember me</span></label></div>
-    <% end -%>
-    <br/>
-    <%= f.submit "Sign in", :class => "primary btn" %>
-    <div class="right"> <%= render :partial => "devise/shared/links" %></div>
-
-    <%- if devise_mapping.omniauthable? %>
-      <%- resource_class.omniauth_providers.each do |provider| %>
-        <hr/>
-        <%= link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider), :class => "btn primary" %><br />
-      <% end -%>
-    <% end -%>
-
-  <% end %>
-
-<% else %>
-  <%= render :partial => 'devise/sessions/new_ldap' %>
-<% end %>
diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..07ecf70b6c912cc5be2261df72f84a84e8d1fc49
--- /dev/null
+++ b/app/views/devise/sessions/new.html.haml
@@ -0,0 +1,21 @@
+- if ldap_enable?
+  = render :partial => 'devise/sessions/new_ldap'
+- else
+  = form_for(resource, :as => resource_name, :url => session_path(resource_name), :html => { :class => "login-box" }) do |f|
+    = image_tag "login-logo.png", :width => "304", :height => "66", :class => "login-logo", :alt => "Login Logo"
+    = f.text_field :email, :class => "text top", :placeholder => "Email"
+    = f.password_field :password, :class => "text bottom", :placeholder => "Password"
+    - if devise_mapping.rememberable?
+      .clearfix.inputs-list
+        %label.checkbox.remember_me{:for => "user_remember_me"}
+          = f.check_box :remember_me
+          %span Remember me
+    %br/
+    = f.submit "Sign in", :class => "primary btn wide"
+    .right
+      = render :partial => "devise/shared/links"
+    - if devise_mapping.omniauthable?
+      %hr/
+      - resource_class.omniauth_providers.each do |provider|
+        %span
+          = link_to authbutton(provider, 32), omniauth_authorize_path(resource_name, provider)
diff --git a/app/views/errors/encoding.html.haml b/app/views/errors/encoding.html.haml
index 4662437f2d21f14e6f37eb2b9f464fc5a3fbbe0f..d7b5e68e870db0516324a8a29d0271a56793e57d 100644
--- a/app/views/errors/encoding.html.haml
+++ b/app/views/errors/encoding.html.haml
@@ -1,5 +1,3 @@
-.alert-message.block-message.error
-  %h3 Encoding Error
-  %hr
-  %p
-    Page can't be loaded because of an encoding error.
+%h1 Encoding Error
+%hr
+%p Page can't be loaded because of an encoding error.
diff --git a/app/views/errors/gitolite.html.haml b/app/views/errors/gitolite.html.haml
index 50268b1ad27c2a53003c857323114778dc1d68be..699e6984db6357472d3b3edd92ee3aa7f1f66527 100644
--- a/app/views/errors/gitolite.html.haml
+++ b/app/views/errors/gitolite.html.haml
@@ -1,6 +1,6 @@
 %h1 Git Error
 %hr
-%h2 Gitlab was unable to access your Gitolite system.
+%h2 GitLab was unable to access your Gitolite system.
 
 .git_error_tips
   %h4 Tips for Administrator:
@@ -21,5 +21,5 @@
         Permissions:
       %pre
         = preserve do
-          sudo chmod -R 770 /home/git/repositories/
-          sudo chown -R git:git /home/git/repositories/
+          sudo chmod -R 770 #{Gitlab.config.git_base_path}
+          sudo chown -R git:git #{Gitlab.config.git_base_path}
diff --git a/app/views/events/_commit.html.haml b/app/views/events/_commit.html.haml
index 1e5c00cb4f441ad47c00ae8d60866d872b8f98fb..cb25d831bca423fc589fa3b11a170e890c7f29ff 100644
--- a/app/views/events/_commit.html.haml
+++ b/app/views/events/_commit.html.haml
@@ -5,4 +5,4 @@
     %strong.cdark= commit.author_name
     &ndash;
     = image_tag gravatar_icon(commit.author_email), class: "avatar", width: 16
-    = gfm truncate(commit.title, length: 50) rescue "--broken encoding"
+    = gfm escape_once(truncate(commit.title, length: 50)) rescue "--broken encoding"
diff --git a/app/views/events/_event.html.haml b/app/views/events/_event.html.haml
index d49f0382deaf159d97b90344a508d9231dd88d35..7bae8db13f7c1f6e49667e05263581bcbfab0b74 100644
--- a/app/views/events/_event.html.haml
+++ b/app/views/events/_event.html.haml
@@ -11,3 +11,7 @@
     .event_feed
       = render "events/event_push", event: event
 
+  - elsif event.membership_changed?
+    .event_feed
+      = render "events/event_membership_changed", event: event
+
diff --git a/app/views/events/_event_last_push.html.haml b/app/views/events/_event_last_push.html.haml
index 4ef927495ae37eaa3ac4736fd246a5a19445e1c8..aa1d28f2be31699e77b1f2dae6632547b2c85cbf 100644
--- a/app/views/events/_event_last_push.html.haml
+++ b/app/views/events/_event_last_push.html.haml
@@ -2,12 +2,12 @@
   .event_lp
     %div
       = image_tag gravatar_icon(event.author_email), class: "avatar"
-      %span Your pushed to 
+      %span Your pushed to
       = event.ref_type
       = link_to project_commits_path(event.project, ref: event.ref_name) do
         %strong= truncate(event.ref_name, length: 28)
       at
       %strong= link_to event.project.name, event.project
 
-      = link_to new_mr_path_from_push_event(event), title: "New Merge Request", class: "btn very_small primary" do
+      = link_to new_mr_path_from_push_event(event), title: "New Merge Request", class: "btn very_small" do
         Create Merge Request
diff --git a/app/views/events/_event_membership_changed.html.haml b/app/views/events/_event_membership_changed.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..464f24b3f0377222f372544892750f500c2b82a9
--- /dev/null
+++ b/app/views/events/_event_membership_changed.html.haml
@@ -0,0 +1,9 @@
+= image_tag gravatar_icon(event.author_email), class: "avatar"
+%strong #{event.author_name}
+%span.event_label{class: event.action_name}= event.action_name
+project
+%strong= link_to event.project_name, event.project
+%span.cgray
+  = time_ago_in_words(event.created_at)
+  ago.
+
diff --git a/app/views/help/api.html.haml b/app/views/help/api.html.haml
index 344f8ade7557519667a29e5994ff823748bcbb6d..00085166bcf93f3a8661e6f9c1aa2fe769d8e7f3 100644
--- a/app/views/help/api.html.haml
+++ b/app/views/help/api.html.haml
@@ -1,53 +1,96 @@
-%h3 API
+%h3.page_title API
 .back_link
   = link_to help_path do
     &larr; to index
-%hr
+%br
 
-%ol
+%ul.nav.nav-tabs.log-tabs
+  %li.active
+    = link_to "README", "#README", 'data-toggle' => 'tab'
+  %li
+    = link_to "Projects", "#projects", 'data-toggle' => 'tab'
+  %li
+    = link_to "Snippets", "#snippets", 'data-toggle' => 'tab'
+  %li
+    = link_to "Repositories", "#repositories", 'data-toggle' => 'tab'
   %li
-    %a{href: "#README"} README
+    = link_to "Users", "#users", 'data-toggle' => 'tab'
   %li
-    %a{href: "#projects"} Projects
+    = link_to "Session", "#session", 'data-toggle' => 'tab'
   %li
-    %a{href: "#users"} Users
+    = link_to "Issues", "#issues", 'data-toggle' => 'tab'
   %li
-    %a{href: "#issues"} Issues
+    = link_to "Milestones", "#milestones", 'data-toggle' => 'tab'
 
-.file_holder#README
-  .file_title
-    %i.icon-file
-    README
-  .file_content.wiki
-    = preserve do
-      = markdown File.read(Rails.root.join("doc", "api", "README.md"))
+.tab-content
+  .tab-pane.active#README
+    .file_holder
+      .file_title
+        %i.icon-file
+        README
+      .file_content.wiki
+        = preserve do
+          = markdown File.read(Rails.root.join("doc", "api", "README.md"))
 
-%br
+  .tab-pane#projects
+    .file_holder
+      .file_title
+        %i.icon-file
+        Projects
+      .file_content.wiki
+        = preserve do
+          = markdown File.read(Rails.root.join("doc", "api", "projects.md"))
 
-.file_holder#projects
-  .file_title
-    %i.icon-file
-    Projects
-  .file_content.wiki
-    = preserve do
-      = markdown File.read(Rails.root.join("doc", "api", "projects.md"))
+  .tab-pane#snippets
+    .file_holder
+      .file_title
+        %i.icon-file
+        Projects Snippets
+      .file_content.wiki
+        = preserve do
+          = markdown File.read(Rails.root.join("doc", "api", "snippets.md"))
 
-%br
+  .tab-pane#repositories
+    .file_holder
+      .file_title
+        %i.icon-file
+        Projects
+      .file_content.wiki
+        = preserve do
+          = markdown File.read(Rails.root.join("doc", "api", "repositories.md"))
 
-.file_holder#users
-  .file_title
-    %i.icon-file
-    Users
-  .file_content.wiki
-    = preserve do
-      = markdown File.read(Rails.root.join("doc", "api", "users.md"))
+  .tab-pane#users
+    .file_holder
+      .file_title
+        %i.icon-file
+        Users
+      .file_content.wiki
+        = preserve do
+          = markdown File.read(Rails.root.join("doc", "api", "users.md"))
 
-%br
+  .tab-pane#session
+    .file_holder
+      .file_title
+        %i.icon-file
+        Session
+      .file_content.wiki
+        = preserve do
+          = markdown File.read(Rails.root.join("doc", "api", "session.md"))
+
+  .tab-pane#issues
+    .file_holder
+      .file_title
+        %i.icon-file
+        Issues
+      .file_content.wiki
+        = preserve do
+          = markdown File.read(Rails.root.join("doc", "api", "issues.md"))
 
-.file_holder#issues
-  .file_title
-    %i.icon-file
-    Issues
-  .file_content.wiki
-    = preserve do
-      = markdown File.read(Rails.root.join("doc", "api", "issues.md"))
+  .tab-pane#milestones
+    .file_holder
+      .file_title
+        %i.icon-file
+        Milestones
+      .file_content.wiki
+        = preserve do
+          = markdown File.read(Rails.root.join("doc", "api", "milestones.md"))
diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml
index 025495772825e0d05eb5849e76d33f12cc738c7c..962f2175126e9616ae8cdfa180a515cbe6c3bd54 100644
--- a/app/views/help/index.html.haml
+++ b/app/views/help/index.html.haml
@@ -30,7 +30,7 @@
     %h5= link_to "API", help_api_path
 
   %li
-    %h5= link_to "Gitlab Markdown", help_markdown_path
+    %h5= link_to "GitLab Markdown", help_markdown_path
 
   %li
     %h5= link_to "SSH keys", help_ssh_path
diff --git a/app/views/help/markdown.html.haml b/app/views/help/markdown.html.haml
index 8d6fb2a590fbc444ef08165bec1b42785027e11e..aa608ed6d9a96269b64bab565eeed97c431b584c 100644
--- a/app/views/help/markdown.html.haml
+++ b/app/views/help/markdown.html.haml
@@ -1,25 +1,129 @@
-- bash_lexer = Pygments::Lexer[:bash]
-%h3.page_title Gitlab Markdown
+%h3.page_title GitLab Flavored Markdown
 .back_link
   = link_to help_path do 
     &larr; to index
 %hr
 
-%p.slead We extend Markdown with some GITLAB specific syntax. It allows you to link to:
+.row
+  .span8
+    %p
+      For GitLab we developed something we call "GitLab Flavored Markdown" (GFM).
+      It extends the standard Markdown in a few significant ways adds some useful functionality.
 
-%ul
-  %li issues (#123)
-  %li merge request (!123)
-  %li commits (1234567)
-  %li team members (@foo)
-  %li snippets ($123)
+    %p You can use GFM in:
+    %ul
+      %li commit messages
+      %li comments
+      %li wall posts
+      %li issues
+      %li merge requests
+      %li milestones
+      %li wiki pages
 
-%p.slead in
+  .span4
+    .alert.alert-info
+      %p
+        If you're not already familiar with Markdown, you should spend 15 minutes and go over the excellent
+        %strong= link_to "Markdown Syntax Guide", "http://daringfireball.net/projects/markdown/syntax"
+        at Daring Fireball.
 
-%ul
-  %li commit messages
-  %li notes/comments/wall posts
-  %li issues
-  %li merge requests
-  %li milestones
-  %li wiki pages
+.row
+  .span8
+    %h3 Differences from traditional Markdown
+
+    %h4 Newlines
+
+    %p
+      The biggest difference that GFM introduces is in the handling of linebreaks.
+      With traditional Markdown you can hard wrap paragraphs of text and they will be combined into a single paragraph. We find this to be the cause of a huge number of unintentional formatting errors.
+      GFM treats newlines in paragraph-like content as real line breaks, which is probably what you intended.
+
+
+    %p The next paragraph contains two phrases separated by a single newline character:
+    %pre= "Roses are red\nViolets are blue"
+    %p becomes
+    = markdown "Roses are red\nViolets are blue"
+
+    %h4 Multiple underscores in words
+
+    %p
+      It is not reasonable to italicize just <em>part</em> of a word, especially when you're dealing with code and names often appear with multiple underscores.
+      Therefore, GFM ignores multiple underscores in words.
+
+    %pre= "perform_complicated_task\ndo_this_and_do_that_and_another_thing"
+    %p becomes
+    = markdown "perform_complicated_task\ndo_this_and_do_that_and_another_thing"
+
+    %h4 URL autolinking
+
+    %p
+      GFM will autolink standard URLs you copy and paste into your text.
+      So if you want to link to a URL (instead of a textual link), you can simply put the URL in verbatim and it will be turned into a link to that URL.
+
+    %h4 Fenced code blocks
+
+    %p
+      Markdown converts text with four spaces at the front of each line to code blocks.
+      GFM supports that, but we also support fenced blocks.
+      Just wrap your code blocks in <code>```</code> and you won't need to indent manually to trigger a code block.
+
+    %pre= %Q{```ruby\nrequire 'redcarpet'\nmarkdown = Redcarpet.new("Hello World!")\nputs markdown.to_html\n```}
+    %p becomes
+    = markdown %Q{```ruby\nrequire 'redcarpet'\nmarkdown = Redcarpet.new("Hello World!")\nputs markdown.to_html\n```}
+
+    %h4 Emoji
+
+.row
+  .span8
+    :ruby
+      puts markdown %Q{Sometimes you want to be :cool: and add some :sparkles: to your :speech_balloon:. Well we have a :gift: for you:
+
+        :exclamation: You can use emoji anywhere GFM is supported. :sunglasses:
+
+        You can use it to point out a :bug: or warn about :monkey:patches. And if someone improves your really :snail: code, send them a :bouquet: or some :candy:. People will :heart: you for that.
+
+        If you are :new: to this, don't be :fearful:. You can easily join the emoji :circus_tent:. All you need to do is to :book: up on the supported codes.
+        }
+
+  .span4
+    .alert.alert-info
+      %p
+        Consult the
+        %strong= link_to "Emoji Cheat Sheet", "http://www.emoji-cheat-sheet.com/"
+        for a list of all supported emoji codes.
+
+.row
+  .span8
+    %h4 Special GitLab references
+
+    %p
+      GFM recognizes special references.
+      You can easily reference e.g. a team member, an issue or a commit within a project.
+      GFM will turn that reference into a link so you can navigate between them easily.
+
+    %p GFM will recognize the following references:
+    %ul
+      %li
+        %code @foo
+        for team members
+      %li
+        %code #123
+        for issues
+      %li
+        %code !123
+        for merge request
+      %li
+        %code $123
+        for snippets
+      %li
+        %code 1234567
+        for commits
+
+    -# this example will only be shown if the user has a project with at least one issue
+    - if @project = current_user.projects.first
+      - if issue = @project.issues.first
+        %p For example in your #{link_to @project.name, project_path(@project)} project, writing:
+        %pre= "This is related to ##{issue.id}. @#{current_user.name} is working on solving it."
+        %p becomes:
+        = markdown "This is related to ##{issue.id}. @#{current_user.name} is working on solving it."
+      - @project = nil # Prevent this from bubbling up to page title
diff --git a/app/views/help/ssh.html.haml b/app/views/help/ssh.html.haml
index 6a5812040e78cc0fab1e4c5ac04609097647efe6..3f082333a76303f10f3510c1ce25d304edd3c012 100644
--- a/app/views/help/ssh.html.haml
+++ b/app/views/help/ssh.html.haml
@@ -5,7 +5,7 @@
 %hr
 
 %p.slead
-  SSH key allows you to establish a secure connection between your computer and Gitlab
+  SSH key allows you to establish a secure connection between your computer and GitLab
 
 %p.slead
   To generate a new SSH key just open your terminal and use code below.
@@ -17,7 +17,7 @@
   \# Generating public/private rsa key pair...
 
 %p.slead
-  Next just use code below to dump your public key and add to GITLAB SSH Keys
+  Next just use code below to dump your public key and add to GitLab SSH Keys
 
 %pre.dark
   cat ~/.ssh/id_rsa.pub
diff --git a/app/views/help/system_hooks.html.haml b/app/views/help/system_hooks.html.haml
index 9fc8cbabf17e839d1d9706ac75e5ee10208d1a2e..736c818bc57cc72b0fb3d0e8655c245e51722d45 100644
--- a/app/views/help/system_hooks.html.haml
+++ b/app/views/help/system_hooks.html.haml
@@ -5,7 +5,7 @@
 %hr
 
 %p.slead
-  Your Gitlab instance can perform HTTP POST request on next event: create_project, delete_project, create_user, delete_user, change_team_member.
+  Your GitLab instance can perform HTTP POST request on next event: create_project, delete_project, create_user, delete_user, change_team_member.
   %br
   System Hooks can be used for logging or change information in LDAP server.
   %br
diff --git a/app/views/help/web_hooks.html.haml b/app/views/help/web_hooks.html.haml
index 263eadf6583ad090219600c4793d0c1a3d1a3a65..65036613fa7474c53781dfa88a6c8b55f0cad2ac 100644
--- a/app/views/help/web_hooks.html.haml
+++ b/app/views/help/web_hooks.html.haml
@@ -5,11 +5,11 @@
 %hr
 
 %p.slead
-  Every Gitlab project can trigger a web server whenever the repo is pushed to.
+  Every GitLab project can trigger a web server whenever the repo is pushed to.
   %br
   Web Hooks can be used to update an external issue tracker, trigger CI builds, update a backup mirror, or even deploy to your production server.
   %br
-  GITLAB will send POST request with commits information on every push.
+  GitLab will send POST request with commits information on every push.
 %h5 Hooks request example:
 = render "hooks/data_ex"
 
diff --git a/app/views/help/workflow.html.haml b/app/views/help/workflow.html.haml
index a3fe3b01d469242cb678a0680f0cb0e81576b43c..6062ca091bd87b7d6be2598897567b424bbb34e3 100644
--- a/app/views/help/workflow.html.haml
+++ b/app/views/help/workflow.html.haml
@@ -24,7 +24,7 @@
         git commit -am "My feature is ready"
 
   %li
-    %p Push your branch to gitlabhq
+    %p Push your branch to GitLab
     .bash
       %pre.dark
         git push origin $feature_name
diff --git a/app/views/hooks/_data_ex.html.erb b/app/views/hooks/_data_ex.html.erb
index 8d3de3f0bf23397db23b4e0890b440ee21d822f5..7dd6b9e0750ea5c02e09721d1cc071b2f8b423e5 100644
--- a/app/views/hooks/_data_ex.html.erb
+++ b/app/views/hooks/_data_ex.html.erb
@@ -32,12 +32,12 @@
             :timestamp => "2012-01-03T23:36:29+02:00",
                   :url => "http://localhost/diaspora/commits/da1560886d...",
                :author => {
-                 :name => "gitlab dev user",
+                 :name => "GitLab dev user",
                 :email => "gitlabdev@dv6700.(none)"
             }
         }
     ],
-   total_commits_count => 3
+   total_commits_count => 4
 }
 eos
 %>
diff --git a/app/views/hooks/index.html.haml b/app/views/hooks/index.html.haml
index 3d2a381e746c39cca8827b164cb347680ba9b792..1b59c8e81aba0fe4f5d0270533bce8a7cc586727 100644
--- a/app/views/hooks/index.html.haml
+++ b/app/views/hooks/index.html.haml
@@ -26,11 +26,12 @@
     Hooks
     %small (#{@hooks.count})
   %br
-  %table.admin-table
-    %tr
-      %th URL
-      %th Method
-      %th
+  %table
+    %thead
+      %tr
+        %th URL
+        %th Method
+        %th
     - @hooks.each do |hook|
       %tr
         %td
diff --git a/app/views/issues/_form.html.haml b/app/views/issues/_form.html.haml
index 1b67eabd5a591d67d920444b26fb9bdcdbb49828..813ecab2d19ad9c24c6d8fd388a3c5e39cfc17cf 100644
--- a/app/views/issues/_form.html.haml
+++ b/app/views/issues/_form.html.haml
@@ -18,12 +18,12 @@
           = f.label :assignee_id do
             %i.icon-user
             Assign to
-          .input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select a user" })
+          .input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select a user" }, {class: 'chosen'})
         .issue_milestone
           = f.label :milestone_id do
             %i.icon-time
             Milestone
-          .input= f.select(:milestone_id, @project.milestones.active.all.collect {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" })
+          .input= f.select(:milestone_id, @project.milestones.active.all.collect {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" }, {class: 'chosen'})
 
       .issue_description
         .clearfix
@@ -38,19 +38,20 @@
           = f.label :description, "Details"
           .input
             = f.text_area :description, maxlength: 2000, class: "xxlarge", rows: 14
-            %p.hint Markdown is enabled.
+            %p.hint Issues are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
 
 
     .actions
       - if @issue.new_record?
-        = f.submit 'Submit new issue', class: "primary btn"
+        = f.submit 'Submit new issue', class: "btn save-btn"
       -else
-        = f.submit 'Save changes', class: "primary btn"
+        = f.submit 'Save changes', class: "save-btn btn"
 
+      - cancel_class = 'btn cancel-btn'
       - if request.xhr?
-        = link_to "Cancel", "#back", onclick: "backToIssues();", class: "btn"
+        = link_to "Cancel", "#back", onclick: "backToIssues();", class: cancel_class
       - else
         - if @issue.new_record?
-          = link_to "Cancel", project_issues_path(@project), class: "btn"
+          = link_to "Cancel", project_issues_path(@project), class: cancel_class
         - else
-          = link_to "Cancel", project_issue_path(@project, @issue), class: "btn"
+          = link_to "Cancel", project_issue_path(@project, @issue), class: cancel_class
diff --git a/app/views/issues/_head.html.haml b/app/views/issues/_head.html.haml
index 1f6e7d7f81f285c620305404bc4c1dd183c34fc2..8ebe3e057bc2b83a95f10ffe40e9ff6aa3624ec3 100644
--- a/app/views/issues/_head.html.haml
+++ b/app/views/issues/_head.html.haml
@@ -5,6 +5,9 @@
   %li{class: "#{'active' if current_page?(project_milestones_path(@project))}"}
     = link_to project_milestones_path(@project), class: "tab" do
       Milestones
+  %li{class: "#{'active' if current_page?(project_labels_path(@project))}"}
+    = link_to project_labels_path(@project), class: "tab" do
+      Labels
   %li.right
     %span.rss-icon
       = link_to project_issues_path(@project, :atom, { private_token: current_user.private_token }) do
diff --git a/app/views/issues/_show.html.haml b/app/views/issues/_show.html.haml
index 8500cd40a6e683dac9bb9269828e1637e53dbfef..64401bdd85e27b2a7e8092cabc5fc1d4868b94c2 100644
--- a/app/views/issues/_show.html.haml
+++ b/app/views/issues/_show.html.haml
@@ -4,7 +4,7 @@
       = check_box_tag dom_id(issue,"selected"), nil, false, 'data-id' => issue.id, class: "selected_issue", disabled: !can?(current_user, :modify_issue, issue)
   .right
     - issue.labels.each do |label|
-      %span.label.label-issue.grouped
+      %span.label.label-tag.grouped
         %i.icon-tag
         = label.name
     - if issue.notes.any?
@@ -34,5 +34,5 @@
     - else
       &nbsp;
 
-    - if issue.upvotes > 0
-      %span.badge.badge-success= "+#{issue.upvotes}"
+    - if issue.votes_count > 0
+      = render 'votes/votes_inline', votable: issue
diff --git a/app/views/issues/edit.html.haml b/app/views/issues/edit.html.haml
index 3c9877f842fd94082f9c78bcbaef19438cfbdb42..b1bc3ba0eba684a146b503fa89225bda4614e840 100644
--- a/app/views/issues/edit.html.haml
+++ b/app/views/issues/edit.html.haml
@@ -1,8 +1 @@
 = render "form"
-
-:javascript
-  $(function(){
-    $('select#issue_assignee_id').chosen();
-    $('select#issue_milestone_id').chosen();
-  });
-
diff --git a/app/views/issues/index.html.haml b/app/views/issues/index.html.haml
index a6836fd4fd19bb2785c1c5aa4b8dfc6b3f30a05f..22c34baaccd65f767cb67beb2402e19cccb48b40 100644
--- a/app/views/issues/index.html.haml
+++ b/app/views/issues/index.html.haml
@@ -6,13 +6,13 @@
     .right
       .span5
         - if can? current_user, :write_issue, @project
-          = link_to new_project_issue_path(@project), class: "right btn small", title: "New Issue", remote: true do
+          = link_to new_project_issue_path(@project), class: "right btn", title: "New Issue", remote: true, id: "new_issue_link" do
             %i.icon-plus
             New Issue
         = form_tag search_project_issues_path(@project), method: :get, remote: true, id: "issue_search_form", class: :right  do
           = hidden_field_tag :project_id, @project.id, { id: 'project_id' }
           = hidden_field_tag :status, params[:f]
-          = search_field_tag :issue_search, nil, { placeholder: 'Search', class: 'issue_search span3 right neib' }
+          = search_field_tag :issue_search, nil, { placeholder: 'Search', class: 'issue_search span3 right neib search-text-input' }
 
   .clearfix
 
diff --git a/app/views/issues/new.html.haml b/app/views/issues/new.html.haml
index 3c9877f842fd94082f9c78bcbaef19438cfbdb42..b1bc3ba0eba684a146b503fa89225bda4614e840 100644
--- a/app/views/issues/new.html.haml
+++ b/app/views/issues/new.html.haml
@@ -1,8 +1 @@
 = render "form"
-
-:javascript
-  $(function(){
-    $('select#issue_assignee_id').chosen();
-    $('select#issue_milestone_id').chosen();
-  });
-
diff --git a/app/views/issues/show.html.haml b/app/views/issues/show.html.haml
index dce8cf6a59de2e9d6fd0bdee191e2c32c259179f..da2aeac433d9716e04e1758c9ae860cff59c25a4 100644
--- a/app/views/issues/show.html.haml
+++ b/app/views/issues/show.html.haml
@@ -8,22 +8,22 @@
   %span.right
     - if can?(current_user, :admin_project, @project) || @issue.author == current_user
       - if @issue.closed
-        = link_to 'Reopen', project_issue_path(@project, @issue, issue: {closed: false }, status_only: true), method: :put,  class: "btn small"
+        = link_to 'Reopen', project_issue_path(@project, @issue, issue: {closed: false }, status_only: true), method: :put,  class: "btn grouped success"
       - else
-        = link_to 'Close', project_issue_path(@project, @issue, issue: {closed: true }, status_only: true), method: :put, class: "btn small", title: "Close Issue"
+        = link_to 'Close', project_issue_path(@project, @issue, issue: {closed: true }, status_only: true), method: :put, class: "btn grouped danger", title: "Close Issue"
     - if can?(current_user, :admin_project, @project) || @issue.author == current_user
-      = link_to edit_project_issue_path(@project, @issue), class: "btn small" do
+      = link_to edit_project_issue_path(@project, @issue), class: "btn grouped" do
         %i.icon-edit
         Edit
 
-    %br
-    - if @issue.upvotes > 0
-      .upvotes#upvotes= "+#{pluralize @issue.upvotes, 'upvote'}"
+.right
+  .span3#votes= render 'votes/votes_block', votable: @issue
 
 .back_link
   = link_to project_issues_path(@project) do
     &larr; To issues list
 
+
 .main_box
   .top_box_content
     %h4
@@ -31,7 +31,7 @@
         .alert-message.error.status_info Closed
       - else
         .alert-message.success.status_info Open
-      = gfm @issue.title
+      = gfm escape_once(@issue.title)
 
   .middle_box_content
     %cite.cgray Created by
@@ -61,4 +61,4 @@
         = markdown @issue.description
 
 
-.issue_notes#notes= render "notes/notes", tid: @issue.id, tt: "issue"
+.issue_notes.voting_notes#notes= render "notes/notes_with_form", tid: @issue.id, tt: "issue"
diff --git a/app/views/keys/_form.html.haml b/app/views/keys/_form.html.haml
index 9c6e229bf49980dcae0181fd27d5a6703dfba2ae..26700803e61247fbb76eab513cb2e575feb4cb92 100644
--- a/app/views/keys/_form.html.haml
+++ b/app/views/keys/_form.html.haml
@@ -19,6 +19,6 @@
 
 
     .actions
-      = f.submit 'Save', class: "primary btn"
-      = link_to "Cancel", keys_path, class: "btn"
+      = f.submit 'Save', class: "btn save-btn"
+      = link_to "Cancel", keys_path, class: "btn cancel-btn"
 
diff --git a/app/views/keys/index.html.haml b/app/views/keys/index.html.haml
index 04e9e4cbc330734868da31af3d189e2f31110e5c..fd5a9dad2385dd1a888e7fda1141827b4573e6ac 100644
--- a/app/views/keys/index.html.haml
+++ b/app/views/keys/index.html.haml
@@ -1,13 +1,13 @@
 %h3.page_title
   SSH Keys
-  = link_to "Add new", new_key_path, class: "btn small right"
+  = link_to "Add new", new_key_path, class: "btn right"
 
 %hr
-%p.slead 
-  SSH key allows you to establish a secure connection between your computer and Gitlab
+%p.slead
+  SSH key allows you to establish a secure connection between your computer and GitLab
 
 
-%table#keys-table.admin-table
+%table#keys-table
   %thead
     %tr
       %th Name
@@ -15,7 +15,7 @@
       %th
   - @keys.each do |key|
     = render(partial: 'show', locals: {key: key})
-  - if @keys.blank? 
+  - if @keys.blank?
     %tr
       %td{colspan: 3}
         %h3.nothing_here_message There are no SSH keys with access to your account.
diff --git a/app/views/keys/show.html.haml b/app/views/keys/show.html.haml
index ffd52b96e5a4f94ad8d9d0c4a4a48722105cb71b..a8cba6c8f9ecfb1ba76d91aab8c6cadd65825398 100644
--- a/app/views/keys/show.html.haml
+++ b/app/views/keys/show.html.haml
@@ -10,5 +10,5 @@
 %hr
 
 %pre= @key.key
-.actions
+.right
   = link_to 'Remove', @key, confirm: 'Are you sure?', method: :delete, class: "btn danger delete-key"
diff --git a/app/views/labels/_label.html.haml b/app/views/labels/_label.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..8a465a9e02cb8433f9dc1b62f7dd133912f1011c
--- /dev/null
+++ b/app/views/labels/_label.html.haml
@@ -0,0 +1,9 @@
+%li.wll
+  %strong
+    %i.icon-tag
+    = label.name
+  .right
+    = link_to project_issues_path(label_name: label.name) do
+      %strong
+        = pluralize(label.count, 'issue')
+        = "»"
diff --git a/app/views/labels/index.html.haml b/app/views/labels/index.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..4e41d375d6abcb9dd022d104552cd3626274c90d
--- /dev/null
+++ b/app/views/labels/index.html.haml
@@ -0,0 +1,14 @@
+= render "issues/head"
+
+%h3.page_title
+  Labels
+%br
+%div.ui-box
+  %ul.unstyled.labels-table
+    - @labels.each do |label|
+      = render 'label', label: label
+
+    - unless @labels.present?
+      %li
+        %h3.nothing_here_message Nothing to show here
+
diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml
index d6247d36b0df86e5018ca6ac2b29e70e0c73e014..f5e423a5abf3c59331cebe0d22cf2384c50abf2e 100644
--- a/app/views/layouts/_head_panel.html.haml
+++ b/app/views/layouts/_head_panel.html.haml
@@ -34,12 +34,4 @@
       source: #{raw search_autocomplete_source},
       select: function(event, ui) { location.href = ui.item.url }
     });
-
-    $(document).keypress(function(e) {
-      if($(e.target).is(":input")) return;
-        switch(e.which)  {
-        case 115:  focusSearch();
-        e.preventDefault();
-      }
-    });
   });
diff --git a/app/views/layouts/notify.html.haml b/app/views/layouts/notify.html.haml
index a1938df43a13c04712ec3d55ef0075e5b8fc5132..7b79897b653f85e26079db4cda305799a6ff8644 100644
--- a/app/views/layouts/notify.html.haml
+++ b/app/views/layouts/notify.html.haml
@@ -2,7 +2,7 @@
   %head
     %meta{content: "text/html; charset=utf-8", "http-equiv" => "Content-Type"}
       %title
-        gitlabhq
+        GitLab
       :css
         .header h1 {color: #BBBBBB !important; font: bold 32px Helvetica, Arial, sans-serif; margin: 0; padding: 0; line-height: 40px;}
         .header p {color: #c6c6c6; font: normal 12px Helvetica, Arial, sans-serif; margin: 0; padding: 0; line-height: 18px;}
@@ -21,7 +21,7 @@
                 \ 
               %td{align: "left", style: "padding: 18px 0 10px;", width: "580"}
                 %h1{style: "color: #BBBBBB; font: normal 32px Helvetica, Arial, sans-serif; margin: 0; padding: 0; line-height: 40px;"}
-                  gitlab
+                  GITLAB
                   - if @project
                     | #{@project.name}
           %table{align: "center", bgcolor: "#fff", border: "0", cellpadding: "0", cellspacing: "0", style: "font-family: Helvetica, Arial, sans-serif; background: #fff;", width: "600"}
diff --git a/app/views/layouts/profile.html.haml b/app/views/layouts/profile.html.haml
index b624415dfe119934dbc618a7a664c7a70a55bd90..62c8db5be125757fb563b300a144fa7d9c3d4af3 100644
--- a/app/views/layouts/profile.html.haml
+++ b/app/views/layouts/profile.html.haml
@@ -9,20 +9,20 @@
         %li.home{class: tab_class(:profile)}
           = link_to "Profile", profile_path
 
-        %li{class: tab_class(:password)}
-          = link_to "Password", profile_password_path
+        %li{class: tab_class(:account)}
+          = link_to "Account", profile_account_path
 
         %li{class: tab_class(:ssh_keys)}
           = link_to keys_path do
             SSH Keys
             %span.count= current_user.keys.count
 
-        %li{class: tab_class(:token)}
-          = link_to "Token", profile_token_path
-
         %li{class: tab_class(:design)}
           = link_to "Design", profile_design_path
 
+        %li{class: tab_class(:history)}
+          = link_to "History", profile_history_path
+
 
       .content
         = yield
diff --git a/app/views/merge_requests/_form.html.haml b/app/views/merge_requests/_form.html.haml
index b6c12397d6c6c362472625852295d21cb9ce2060..96692c0f93d2f9236436c51f347553f2eb70272f 100644
--- a/app/views/merge_requests/_form.html.haml
+++ b/app/views/merge_requests/_form.html.haml
@@ -9,27 +9,27 @@
   %br
 
   .row
-    .span6
+    .span5
       .mr_branch_box
         %h5 From (Head Branch)
         .body 
           .padded
             = f.label :source_branch, "From", class: "control-label"
             .controls
-              = f.select(:source_branch, @project.heads.map(&:name), { include_blank: "Select branch" }, style: "width:250px")
-        .bottom_commit
-          .mr_source_commit
+              = f.select(:source_branch, @project.heads.map(&:name), { include_blank: "Select branch" }, {class: 'chosen span3'})
+      .mr_source_commit
 
-    .span6
+    .span2
+      %center= image_tag "merge.png", class: 'mr_direction_tip'
+    .span5
       .mr_branch_box
         %h5 To (Base Branch)
         .body
           .padded
             = f.label :target_branch, "To", class: "control-label"
             .controls
-              = f.select(:target_branch, @project.heads.map(&:name), { include_blank: "Select branch" }, style: "width:250px")
-        .bottom_commit
-          .mr_target_commit
+              = f.select(:target_branch, @project.heads.map(&:name), { include_blank: "Select branch" }, {class: 'chosen span3'})
+      .mr_target_commit
 
   %h4.cdark 2. Fill info
 
@@ -43,30 +43,25 @@
         = f.label :assignee_id do 
           %i.icon-user 
           Assign to
-        .input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select user" }, style: "width:250px")
+        .input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select user" }, {class: 'chosen span3'})
 
   .control-group
 
   .form-actions
-    = f.submit 'Save', class: "btn-primary btn"
+    = f.submit 'Save', class: "btn save-btn"
     - if @merge_request.new_record?
-      = link_to project_merge_requests_path(@project), class: "btn" do
+      = link_to project_merge_requests_path(@project), class: "btn cancel-btn" do
         Cancel
     - else
-      = link_to project_merge_request_path(@project, @merge_request), class: "btn" do
+      = link_to project_merge_request_path(@project, @merge_request), class: "btn cancel-btn" do
         Cancel
 
-
-
 :javascript
   $(function(){
-    $('select#merge_request_assignee_id').chosen();
-    $('select#merge_request_source_branch').chosen();
-    $('select#merge_request_target_branch').chosen();
+    disableButtonIfEmptyField("#merge_request_title", ".save-btn");
     var source_branch = $("#merge_request_source_branch");
     var target_branch = $("#merge_request_target_branch");
 
-    
     $.get("#{branch_from_project_merge_requests_path(@project)}", {ref: source_branch.val() });
     $.get("#{branch_to_project_merge_requests_path(@project)}", {ref: target_branch.val() });
 
@@ -78,4 +73,3 @@
       $.get("#{branch_to_project_merge_requests_path(@project)}", {ref: $(this).val() });
     });
   });
-
diff --git a/app/views/merge_requests/_merge_request.html.haml b/app/views/merge_requests/_merge_request.html.haml
index 7499609066a37f0e10942c21ec360f3c968bc16e..9d94d67052501ea43ff2d7d9015a48bc29da2c44 100644
--- a/app/views/merge_requests/_merge_request.html.haml
+++ b/app/views/merge_requests/_merge_request.html.haml
@@ -23,5 +23,6 @@
     authored by #{merge_request.author_name}
     = time_ago_in_words(merge_request.created_at)
     ago
-    - if merge_request.upvotes > 0
-      %span.badge.badge-success= "+#{merge_request.upvotes}"
+
+    - if merge_request.votes_count > 0
+      = render 'votes/votes_inline', votable: merge_request
diff --git a/app/views/merge_requests/_show.html.haml b/app/views/merge_requests/_show.html.haml
index f1b3fa9fe984458532ce63c95cda14108cfa3282..f1d0c8aaafbbbcaa1551452c5bfdcfd837d7f721 100644
--- a/app/views/merge_requests/_show.html.haml
+++ b/app/views/merge_requests/_show.html.haml
@@ -15,8 +15,8 @@
         %i.icon-list-alt
         Diff
 
-.merge_request_notes#notes{ class: (controller.action_name == 'show') ? "" : "hide" }
-  = render("notes/notes", tid: @merge_request.id, tt: "merge_request")
+.merge_request_notes.voting_notes#notes{ class: (controller.action_name == 'show') ? "" : "hide" }
+  = render("notes/notes_with_form", tid: @merge_request.id, tt: "merge_request")
 .merge-request-diffs
   = render "merge_requests/show/diffs" if @diffs
 .status
diff --git a/app/views/merge_requests/diffs.html.haml b/app/views/merge_requests/diffs.html.haml
index 176b19bcbbb29a6450362d4f4cba8ccdbe727657..a755491c42ef91d96da908424c071cc1205c0d45 100644
--- a/app/views/merge_requests/diffs.html.haml
+++ b/app/views/merge_requests/diffs.html.haml
@@ -1,2 +1,6 @@
 = render "show"
 
+:javascript
+  $(function(){
+    PerLineNotes.init();
+  });
diff --git a/app/views/merge_requests/diffs.js.haml b/app/views/merge_requests/diffs.js.haml
index b147e5be71c3b36b9765f75ad9bf80d31fffae80..985399853249657cec53da8e9f47715f9c6ba77c 100644
--- a/app/views/merge_requests/diffs.js.haml
+++ b/app/views/merge_requests/diffs.js.haml
@@ -1,4 +1,7 @@
 :plain
   $(".merge-request-diffs").html("#{escape_javascript(render(partial: "merge_requests/show/diffs"))}");
 
+  $(function(){
+    PerLineNotes.init();
+  });
 
diff --git a/app/views/merge_requests/index.html.haml b/app/views/merge_requests/index.html.haml
index 4ad6e5c18ce7a55c3db4e89bd52bd1fd75926507..bbf35dc72d225b5d19947c48c1fc14df98b6c762 100644
--- a/app/views/merge_requests/index.html.haml
+++ b/app/views/merge_requests/index.html.haml
@@ -1,7 +1,7 @@
 %h3.page_title
   Merge Requests
   - if can? current_user, :write_issue, @project
-    = link_to new_project_merge_request_path(@project), class: "right btn small", title: "New Merge Request" do
+    = link_to new_project_merge_request_path(@project), class: "right btn", title: "New Merge Request" do
       New Merge Request
 
 %br
@@ -10,17 +10,17 @@
 .ui-box
   .title
     %ul.nav.nav-pills
-      %li{class: ("active" if (params[:f] == "0" || !params[:f]))}
-        = link_to project_merge_requests_path(@project, f: 0) do
+      %li{class: ("active" if (params[:f] == 'open' || !params[:f]))}
+        = link_to project_merge_requests_path(@project, f: 'open') do
           Open
-      %li{class: ("active" if params[:f] == "2")}
-        = link_to project_merge_requests_path(@project, f: 2) do
+      %li{class: ("active" if params[:f] == "closed")}
+        = link_to project_merge_requests_path(@project, f: "closed") do
           Closed
-      %li{class: ("active" if params[:f] == "3")}
-        = link_to project_merge_requests_path(@project, f: 3) do
+      %li{class: ("active" if params[:f] == 'assigned-to-me')}
+        = link_to project_merge_requests_path(@project, f: 'assigned-to-me') do
           To Me
-      %li{class: ("active" if params[:f] == "1")}
-        = link_to project_merge_requests_path(@project, f: 1) do
+      %li{class: ("active" if params[:f] == 'all')}
+        = link_to project_merge_requests_path(@project, f: 'all') do
           All
 
   %ul.unstyled
diff --git a/app/views/merge_requests/show.js.haml b/app/views/merge_requests/show.js.haml
index 7a27b1668499571c454383d9f85b88da627911c2..f44ccbb5127a52c7ea8031de48b588b19dc66c07 100644
--- a/app/views/merge_requests/show.js.haml
+++ b/app/views/merge_requests/show.js.haml
@@ -1,2 +1,2 @@
 :plain
-  $(".merge-request-notes").html("#{escape_javascript(render("notes/notes", tid: @merge_request.id, tt: "merge_request"))}");
+  $(".merge-request-notes").html("#{escape_javascript(render notes/notes_with_form", tid: @merge_request.id, tt: "merge_request")}");
diff --git a/app/views/merge_requests/show/_mr_box.html.haml b/app/views/merge_requests/show/_mr_box.html.haml
index 81ab83f343620736b5986a5dae0e6bdc721e2c02..89c3110bddfe8b43c99f92afe4a2a934fe3518e0 100644
--- a/app/views/merge_requests/show/_mr_box.html.haml
+++ b/app/views/merge_requests/show/_mr_box.html.haml
@@ -5,7 +5,7 @@
         .alert-message.error.status_info Closed
       - else
         .alert-message.success.status_info Open
-      = gfm @merge_request.title
+      = gfm escape_once(@merge_request.title)
 
   .middle_box_content
     %div
diff --git a/app/views/merge_requests/show/_mr_title.html.haml b/app/views/merge_requests/show/_mr_title.html.haml
index 31fa0779fd26ec1db9a8e755da18a73f817b8da4..8708469cc5deb1c1f47730f5841c529b5c554870 100644
--- a/app/views/merge_requests/show/_mr_title.html.haml
+++ b/app/views/merge_requests/show/_mr_title.html.haml
@@ -1,9 +1,9 @@
 %h3.page_title
   = "Merge Request ##{@merge_request.id}:"
   &nbsp;
-  %span.pretty_label.branch= @merge_request.source_branch
+  %span.label_branch= @merge_request.source_branch
   &rarr;
-  %span.pretty_label.branch= @merge_request.target_branch
+  %span.label_branch= @merge_request.target_branch
 
   %span.right
     - if @merge_request.merged?
@@ -23,10 +23,8 @@
           %i.icon-edit
           Edit
 
-    %br
-    - if @merge_request.upvotes > 0
-      .upvotes#upvotes= "+#{pluralize @merge_request.upvotes, 'upvote'}"
-
+.right
+  .span3#votes= render 'votes/votes_block', votable: @merge_request
 
 .back_link
   = link_to project_merge_requests_path(@project) do
diff --git a/app/views/milestones/_form.html.haml b/app/views/milestones/_form.html.haml
index 1cd08ac3bcf91c33c1e17a7a61f094d632f718ba..194eac7783ce34067f49b80c4217dbc37e044a34 100644
--- a/app/views/milestones/_form.html.haml
+++ b/app/views/milestones/_form.html.haml
@@ -22,7 +22,7 @@
         = f.label :description, "Description", class: "control-label"
         .controls
           = f.text_area :description, maxlength: 2000, class: "input-xlarge", rows: 10
-          %p.hint Markdown is enabled.
+          %p.hint Milestones are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
     .span6
       .control-group
         = f.label :due_date, "Due Date", class: "control-label"
@@ -32,20 +32,16 @@
 
   .form-actions
     - if @milestone.new_record?
-      = f.submit 'Create milestone', class: "primary btn"
+      = f.submit 'Create milestone', class: "save-btn btn"
+      = link_to "Cancel", project_milestones_path(@project), class: "btn cancel-btn"
     -else
-      = f.submit 'Save changes', class: "primary btn"
+      = f.submit 'Save changes', class: "save-btn btn"
+      = link_to "Cancel", project_milestone_path(@project, @milestone), class: "btn cancel-btn"
 
-    - if request.xhr?
-      = link_to "Cancel", "#back", onclick: "backToIssues();", class: "btn"
-    - else
-      - if @milestone.new_record?
-        = link_to "Cancel", project_milestones_path(@project), class: "btn"
-      - else
-        = link_to "Cancel", project_milestone_path(@project, @milestone), class: "btn"
 
 :javascript
   $(function() {
+    disableButtonIfEmptyField("#milestone_title", ".save-btn");
     $( ".datepicker" ).datepicker({
       dateFormat: "yy-mm-dd",
       onSelect: function(dateText, inst) { $("#milestone_due_date").val(dateText) }
diff --git a/app/views/milestones/edit.html.haml b/app/views/milestones/edit.html.haml
index af975a84a49f45b15912429b129d16f477285e8e..b1bc3ba0eba684a146b503fa89225bda4614e840 100644
--- a/app/views/milestones/edit.html.haml
+++ b/app/views/milestones/edit.html.haml
@@ -1,7 +1 @@
 = render "form"
-
-:javascript
-  $(function(){
-    $('select#issue_assignee_id').chosen();
-  });
-
diff --git a/app/views/milestones/index.html.haml b/app/views/milestones/index.html.haml
index ecb008dc144fd06b5f849f1b535085872e2a4729..c5333b08fdcf388a74a4555af5b551bcdcef13ae 100644
--- a/app/views/milestones/index.html.haml
+++ b/app/views/milestones/index.html.haml
@@ -8,11 +8,11 @@
   %div.ui-box
     .title
       %ul.nav.nav-pills
-        %li{class: ("active" if (params[:f] == "0" || !params[:f]))}
-          = link_to project_milestones_path(@project, f: 0) do
+        %li{class: ("active" if (params[:f] == "active" || !params[:f]))}
+          = link_to project_milestones_path(@project, f: "active") do
             Active
-        %li{class: ("active" if params[:f] == "1")}
-          = link_to project_milestones_path(@project, f: 1) do
+        %li{class: ("active" if params[:f] == "all")}
+          = link_to project_milestones_path(@project, f: "all") do
             All
 
     %ul.unstyled
diff --git a/app/views/milestones/show.html.haml b/app/views/milestones/show.html.haml
index b7da7b668ea15a36f8e597b189e15904e93aaceb..ba71ead73113432d2542a7956f0ac6042c551b7f 100644
--- a/app/views/milestones/show.html.haml
+++ b/app/views/milestones/show.html.haml
@@ -21,7 +21,7 @@
         .alert-message.error.status_info Closed
       - else
         .alert-message.success.status_info Open
-      = gfm @milestone.title
+      = gfm escape_once(@milestone.title)
       %small.right= @milestone.expires_at
 
   .middle_box_content
@@ -42,7 +42,7 @@
 
 .row
   .span6
-    %table.admin-table
+    %table
       %thead
         %th Open Issues
       - @issues.each do |issue|
@@ -56,7 +56,7 @@
     = paginate @issues, theme: "gitlab"
 
   .span6
-    %table.admin-table
+    %table
       %thead
         %th Participants
       - @users.each do |user|
diff --git a/app/views/notes/_common_form.html.haml b/app/views/notes/_common_form.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..fc6e3c7ee6ebcf152dd93b5af9227a31982905d0
--- /dev/null
+++ b/app/views/notes/_common_form.html.haml
@@ -0,0 +1,39 @@
+.note-form-holder
+  = form_for [@project, @note], remote: "true", multipart: true do |f|
+    %h3.page_title Leave a comment
+    -if @note.errors.any?
+      .alert-message.block-message.error
+        - @note.errors.full_messages.each do |msg|
+          %div= msg
+
+    = f.hidden_field :noteable_id
+    = f.hidden_field :noteable_type
+    = f.text_area :note, size: 255, class: 'note-text'
+    #preview-note.preview_note.hide
+    .hint
+      .right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
+      .clearfix
+
+    .row.note_advanced_opts
+      .span3
+        = f.submit 'Add Comment', class: "btn success submit_note grouped", id: "submit_note"
+        = link_to 'Preview', preview_project_notes_path(@project), class: 'btn grouped', id: 'preview-link'
+      .span4.notify_opts
+        %h6.left Notify via email:
+        = label_tag :notify do
+          = check_box_tag :notify, 1, @note.noteable_type != "Commit"
+          %span Project team
+
+        - if @note.notify_only_author?(current_user)
+          = label_tag :notify_author do
+            = check_box_tag :notify_author, 1 , @note.noteable_type == "Commit"
+            %span Commit author
+      .span5.attachments
+        %h6.left Attachment:
+        %span.file_name File name...
+
+        .input.input_file
+          %a.file_upload.btn.small Upload File
+          = f.file_field :attachment, class: "input-file"
+        %span.hint Any file less than 10 MB
+
diff --git a/app/views/notes/_create_common.js.haml b/app/views/notes/_create_common.js.haml
deleted file mode 100644
index e95389027541c1c2084b5e62e6e236edd51eff90..0000000000000000000000000000000000000000
--- a/app/views/notes/_create_common.js.haml
+++ /dev/null
@@ -1,11 +0,0 @@
-- if note.valid?
-  :plain
-    $("#new_note .error").remove();
-    $('#new_note textarea').val("");
-    $('#preview-link').text('Preview');
-    $('#preview-note').hide(); $('#note_note').show();
-    NoteList.prepend(#{note.id}, "#{escape_javascript(render partial: "notes/show", locals: {note: note})}");
-- else
-  :plain
-    $("#new_note").replaceWith("#{escape_javascript(render('form'))}");
-
diff --git a/app/views/notes/_create_common_note.js.haml b/app/views/notes/_create_common_note.js.haml
new file mode 100644
index 0000000000000000000000000000000000000000..bbebc2478c54f08d81f607cff864453d17f369e9
--- /dev/null
+++ b/app/views/notes/_create_common_note.js.haml
@@ -0,0 +1,13 @@
+- if note.valid?
+  :plain
+    $(".note-form-holder .error").remove();
+    $('.note-form-holder textarea').val("");
+    $('.note-form-holder #preview-link').text('Preview');
+    $('.note-form-holder #preview-note').hide();
+    $('.note-form-holder').show();
+    NoteList.appendNewNote(#{note.id}, "#{escape_javascript(render "notes/note", note: note)}");
+
+- else
+  :plain
+    $(".note-form-holder").replaceWith("#{escape_javascript(render 'form')}");
+
diff --git a/app/views/notes/_create_line.js.haml b/app/views/notes/_create_line.js.haml
deleted file mode 100644
index 13809bec1b9142621c67fae3a281c9a8f03bcdc1..0000000000000000000000000000000000000000
--- a/app/views/notes/_create_line.js.haml
+++ /dev/null
@@ -1,8 +0,0 @@
-- if note.valid?
-  :plain
-    $(".per_line_form").hide();
-    $('#new_note textarea').val("");
-    $("a.line_note_reply_link[line_code='#{note.line_code}']").closest("tr").remove();
-    var trEl = $(".#{note.line_code}").parent();
-    trEl.after("#{escape_javascript(render partial: "notes/per_line_show", locals: {note: note})}");
-    trEl.after("#{escape_javascript(render partial: "notes/reply_button", locals: {line_code: note.line_code})}");
diff --git a/app/views/notes/_create_per_line_note.js.haml b/app/views/notes/_create_per_line_note.js.haml
new file mode 100644
index 0000000000000000000000000000000000000000..180960e38e4e357afa0429b92f6c677309ae3aac
--- /dev/null
+++ b/app/views/notes/_create_per_line_note.js.haml
@@ -0,0 +1,19 @@
+- if note.valid?
+  :plain
+    // hide and reset the form
+    $(".per_line_form").hide();
+    $('.line-note-form-holder textarea').val("");
+
+    // find the reply button for this line
+    // (might not be there if this is the first note)
+    var trRpl = $("a.line_note_reply_link[data-line-code='#{note.line_code}']").closest("tr");
+    if (trRpl.size() == 0) {
+      // find the commented line ...
+      var trEl = $(".#{note.line_code}").parent();
+      // ... and insert the note and the reply button after it
+      trEl.after("#{escape_javascript(render "notes/per_line_reply_button", line_code: note.line_code)}");
+      trEl.after("#{escape_javascript(render "notes/per_line_note", note: note)}");
+    } else {
+      // instert new note before reply button
+      trRpl.before("#{escape_javascript(render "notes/per_line_note", note: note)}");
+    }
diff --git a/app/views/notes/_form.html.haml b/app/views/notes/_form.html.haml
deleted file mode 100644
index dac026bd23d02f8bea2dffe7055dcfe6a1860631..0000000000000000000000000000000000000000
--- a/app/views/notes/_form.html.haml
+++ /dev/null
@@ -1,38 +0,0 @@
-= form_for [@project, @note], remote: "true", multipart: true do |f|
-  %h3.page_title Leave a comment
-  -if @note.errors.any?
-    .alert-message.block-message.error
-      - @note.errors.full_messages.each do |msg|
-        %div= msg
-
-  = f.hidden_field :noteable_id
-  = f.hidden_field :noteable_type
-  = f.text_area :note, size: 255
-  #preview-note.well.hide
-  %p.hint
-    = link_to "Gitlab Markdown", help_markdown_path, target: '_blank'
-    is enabled.
-    = link_to 'Preview', preview_project_notes_path(@project), id: 'preview-link'
-
-  .row.note_advanced_opts.hide
-    .span2
-      = f.submit 'Add Comment', class: "btn primary submit_note", id: "submit_note"
-    .span4.notify_opts
-      %h6.left Notify via email:
-      = label_tag :notify do
-        = check_box_tag :notify, 1, @note.noteable_type != "Commit"
-        %span Project team
-
-      - if @note.notify_only_author?(current_user)
-        = label_tag :notify_author do
-          = check_box_tag :notify_author, 1 , @note.noteable_type == "Commit"
-          %span Commit author
-    .span6.attachments
-      %h6.left Attachment:
-      %span.file_name File name...
-      
-      .input.input_file
-        %a.file_upload.btn.small Upload File
-        = f.file_field :attachment, class: "input-file"
-      %span.hint Any file less than 10 MB
-
diff --git a/app/views/notes/_load.js.haml b/app/views/notes/_load.js.haml
deleted file mode 100644
index c16a699a1b7091d4e5aaaa4ebeb086b22b3dfe0a..0000000000000000000000000000000000000000
--- a/app/views/notes/_load.js.haml
+++ /dev/null
@@ -1,17 +0,0 @@
-- unless @notes.blank?
-  - if params[:last_id]
-    :plain
-      NoteList.replace("#{escape_javascript(render(partial: 'notes/notes_list'))}");
-
-  - elsif params[:first_id]
-    :plain
-      NoteList.append(#{@notes.last.id}, "#{escape_javascript(render(partial: 'notes/notes_list'))}");
-
-  - else
-    :plain
-      NoteList.setContent(#{@notes.last.id}, #{@notes.first.id}, "#{escape_javascript(render(partial: 'notes/notes_list'))}");
-
-- else
-  - if params[:first_id]
-    :plain
-      NoteList.append(#{params[:first_id]}, "");
diff --git a/app/views/notes/_show.html.haml b/app/views/notes/_note.html.haml
similarity index 73%
rename from app/views/notes/_show.html.haml
rename to app/views/notes/_note.html.haml
index 3412e4ebae5baa18c4388c4f8f09c4152582c95b..5234e55dcd098754717f22ded7e2a8f5e38bf5cd 100644
--- a/app/views/notes/_show.html.haml
+++ b/app/views/notes/_note.html.haml
@@ -1,4 +1,4 @@
-%li{id: dom_id(note), class: "note"}
+%li{id: dom_id(note), class: "note #{note_vote_class(note)}"}
   = image_tag gravatar_icon(note.author.email), class: "avatar s32"
   %div.note-author
     %strong= note.author_name
@@ -6,8 +6,16 @@
       %cite.cgray
         = time_ago_in_words(note.updated_at)
         ago
+    - if note.upvote?
+      %span.label.label-success
+        %i.icon-thumbs-up
+        \+1
+    - if note.downvote?
+      %span.label.label-error
+        %i.icon-thumbs-down
+        \-1
     - if(note.author_id == current_user.id) || can?(current_user, :admin_note, @project)
-      = link_to [@project, note], confirm: 'Are you sure?', method: :delete, remote: true, class: "cred delete-note btn very_small" do 
+      = link_to [@project, note], confirm: 'Are you sure?', method: :delete, remote: true, class: "cred delete-note btn very_small" do
         %i.icon-trash
         Remove
 
diff --git a/app/views/notes/_notes.html.haml b/app/views/notes/_notes.html.haml
index e692e7464658c60c524353cff4e3b0fa1d1bf158..adb5dfcbf18741de0e635f3958670f0d65a88be2 100644
--- a/app/views/notes/_notes.html.haml
+++ b/app/views/notes/_notes.html.haml
@@ -1,13 +1,4 @@
-- if can? current_user, :write_note, @project
-  = render "notes/form"
-.clear
-%hr
-%ul#new_notes_list
-%ul#notes-list
-.status
+- @notes.each do |note|
+  - next unless note.author
+  = render "note", note: note
 
-
-:javascript
-  $(function(){
-    NoteList.init("#{tid}", "#{tt}", "#{project_notes_path(@project)}");
-  });
diff --git a/app/views/notes/_notes_list.html.haml b/app/views/notes/_notes_list.html.haml
deleted file mode 100644
index 5673988d87d23b95923a1e389d4f0784472a8650..0000000000000000000000000000000000000000
--- a/app/views/notes/_notes_list.html.haml
+++ /dev/null
@@ -1,4 +0,0 @@
-- @notes.each do |note|
-  - next unless note.author
-  = render partial: "notes/show", locals: {note: note}
-
diff --git a/app/views/notes/_notes_with_form.html.haml b/app/views/notes/_notes_with_form.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..53716c1d3f4ddd3317bdcf63ad528e0db230a8c3
--- /dev/null
+++ b/app/views/notes/_notes_with_form.html.haml
@@ -0,0 +1,11 @@
+%ul#notes-list
+%ul#new-notes-list
+.notes-status
+
+- if can? current_user, :write_note, @project
+  = render "notes/common_form"
+
+:javascript
+  $(function(){
+    NoteList.init("#{tid}", "#{tt}", "#{project_notes_path(@project)}");
+  });
diff --git a/app/views/notes/_per_line_form.html.haml b/app/views/notes/_per_line_form.html.haml
index afb0b30dca3c1ef7508541abd635464739f450c1..8e31b59e9f02a736efdab3163c33488b04bfe813 100644
--- a/app/views/notes/_per_line_form.html.haml
+++ b/app/views/notes/_per_line_form.html.haml
@@ -1,33 +1,34 @@
 %table{style: "display:none;"}
   %tr.per_line_form
     %td{colspan: 3 }
-      = form_for [@project, @note], remote: "true", multipart: true do |f|
-        %h3.page_title Leave a note
-        %div.span10
-          -if @note.errors.any?
-            .alert-message.block-message.error
-              - @note.errors.full_messages.each do |msg|
-                %div= msg
+      .line-note-form-holder
+        = form_for [@project, @note], remote: "true", multipart: true do |f|
+          %h3.page_title Leave a note
+          %div.span10
+            -if @note.errors.any?
+              .alert-message.block-message.error
+                - @note.errors.full_messages.each do |msg|
+                  %div= msg
 
-          = f.hidden_field :noteable_id
-          = f.hidden_field :noteable_type
-          = f.hidden_field :line_code
-          = f.text_area :note,  size: 255
-          .note_actions
-            .buttons
-              = f.submit 'Add note', class: "btn primary submit_note", id: "submit_note"
-              = link_to "Cancel", "#", class: "btn hide-button"
-            .options
-              %h6.left Notify via email:
-              .labels
-                = label_tag :notify do
-                  = check_box_tag :notify, 1, @note.noteable_type != "Commit"
-                  %span Project team
+            = f.hidden_field :noteable_id
+            = f.hidden_field :noteable_type
+            = f.hidden_field :line_code
+            = f.text_area :note,  size: 255, class: 'line-note-text'
+            .note_actions
+              .buttons
+                = f.submit 'Add note', class: "btn save-btn submit_note submit_inline_note", id: "submit_note"
+                = link_to "Cancel", "#", class: "btn hide-button"
+              .options
+                %h6.left Notify via email:
+                .labels
+                  = label_tag :notify do
+                    = check_box_tag :notify, 1, @note.noteable_type != "Commit"
+                    %span Project team
 
-                - if @note.notify_only_author?(current_user)
-                  = label_tag :notify_author do
-                    = check_box_tag :notify_author, 1 , @note.noteable_type == "Commit"
-                    %span Commit author
+                  - if @note.notify_only_author?(current_user)
+                    = label_tag :notify_author do
+                      = check_box_tag :notify_author, 1 , @note.noteable_type == "Commit"
+                      %span Commit author
 
 :javascript
   $(function(){
diff --git a/app/views/notes/_per_line_note.html.haml b/app/views/notes/_per_line_note.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..28bcd6e0c94f3e5779f1a8718340673a3671f1af
--- /dev/null
+++ b/app/views/notes/_per_line_note.html.haml
@@ -0,0 +1,5 @@
+%tr.line_notes_row
+  %td{colspan: 3}
+    %ul
+      = render "notes/note", note: note
+
diff --git a/app/views/notes/_per_line_note_link.html.haml b/app/views/notes/_per_line_note_link.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..72b59a596a352d02897948f85f4ddd3fd742991f
--- /dev/null
+++ b/app/views/notes/_per_line_note_link.html.haml
@@ -0,0 +1 @@
+= link_to "", "#", class: "line_note_link", data: { line_code: line_code }, title: "Add note for this line"
diff --git a/app/views/notes/_per_line_notes_with_reply.html.haml b/app/views/notes/_per_line_notes_with_reply.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..1bcfc41fe203b81162ef6447ee8c8bca8ab7f37e
--- /dev/null
+++ b/app/views/notes/_per_line_notes_with_reply.html.haml
@@ -0,0 +1,3 @@
+- notes.each do |note|
+  = render "notes/per_line_note", note: note
+= render "notes/per_line_reply_button", line_code: notes.first.line_code
diff --git a/app/views/notes/_per_line_reply_button.html.haml b/app/views/notes/_per_line_reply_button.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..42c737c75ae130e31ab518020ae427a4a0f7be79
--- /dev/null
+++ b/app/views/notes/_per_line_reply_button.html.haml
@@ -0,0 +1,4 @@
+%tr.line_notes_row.reply
+  %td{colspan: 3}
+    %i.icon-comment
+    = link_to "Reply", "#", class: "line_note_reply_link", data: { line_code: line_code }, title: "Add note for this line"
diff --git a/app/views/notes/_per_line_show.html.haml b/app/views/notes/_per_line_show.html.haml
deleted file mode 100644
index cf1769c0517d702eebc64d51a018c97e6a47d62a..0000000000000000000000000000000000000000
--- a/app/views/notes/_per_line_show.html.haml
+++ /dev/null
@@ -1,5 +0,0 @@
-%tr.line_notes_row
-  %td{colspan: 3}
-    %ul
-      = render partial: "notes/show", locals: {note: note}
-
diff --git a/app/views/notes/_reply_button.html.haml b/app/views/notes/_reply_button.html.haml
deleted file mode 100644
index c981fb9fc726ade9557bc227941a4870aa85af43..0000000000000000000000000000000000000000
--- a/app/views/notes/_reply_button.html.haml
+++ /dev/null
@@ -1,4 +0,0 @@
-%tr.line_notes_row.reply
-  %td{colspan: 3}
-    %i.icon-comment
-    = link_to "Reply", "#", class: "line_note_reply_link", "line_code" => line_code, title: "Add note for this line"
diff --git a/app/views/notes/_reversed_notes_with_form.html.haml b/app/views/notes/_reversed_notes_with_form.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..24d599244b40fe7cbe9dc61ce13d58ef49672de1
--- /dev/null
+++ b/app/views/notes/_reversed_notes_with_form.html.haml
@@ -0,0 +1,11 @@
+- if can? current_user, :write_note, @project
+  = render "notes/common_form"
+
+%ul.reversed#new-notes-list
+%ul.reversed#notes-list
+.notes-status
+
+:javascript
+  $(function(){
+    NoteList.init("#{tid}", "#{tt}", "#{project_notes_path(@project)}");
+  });
diff --git a/app/views/notes/create.js.haml b/app/views/notes/create.js.haml
index 8f631f38f79bd9897eb460d0d499cabacc5c9f57..03866591c4fde9e97afb22daf5fc8fb75b3e1a6b 100644
--- a/app/views/notes/create.js.haml
+++ b/app/views/notes/create.js.haml
@@ -1,7 +1,7 @@
 - if @note.line_code
-  = render "create_line", note: @note
+  = render "create_per_line_note", note: @note
 - else
-  = render "create_common", note: @note
+  = render "create_common_note", note: @note
 
 -# Enable submit button
 :plain
diff --git a/app/views/notes/index.js.haml b/app/views/notes/index.js.haml
index ee31c0b8d3c1c8112471bbee240b14ef816f01ac..3814dbd46a2aa05a5eef17510e18d1ece396700a 100644
--- a/app/views/notes/index.js.haml
+++ b/app/views/notes/index.js.haml
@@ -1 +1,17 @@
-= render "notes/load"
+- unless @notes.blank?
+  - if loading_more_notes?
+    :plain
+      NoteList.appendMoreNotes(#{@notes.last.id}, "#{escape_javascript(render 'notes/notes')}");
+
+  - elsif loading_new_notes?
+    :plain
+      NoteList.replaceNewNotes("#{escape_javascript(render 'notes/notes')}");
+
+  - else
+    :plain
+      NoteList.setContent(#{@notes.first.id}, #{@notes.last.id}, "#{escape_javascript(render 'notes/notes')}");
+
+- else
+  - if loading_more_notes?
+    :plain
+      NoteList.finishedLoadingMore();
diff --git a/app/views/notify/issue_status_changed_email.html.haml b/app/views/notify/issue_status_changed_email.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..59130f79d6cbbf2e6b90dec237b0b15bdcf5bd0f
--- /dev/null
+++ b/app/views/notify/issue_status_changed_email.html.haml
@@ -0,0 +1,16 @@
+%td.content{align: "left", style: "font-family: Helvetica, Arial, sans-serif; padding: 20px 0 0;", valign: "top", width: "600"}
+  %table{border: "0", cellpadding: "0", cellspacing: "0", style: "color: #717171; font: normal 11px Helvetica, Arial, sans-serif; margin: 0; padding: 0;", width: "600"}
+    %tr
+      %td{style: "font-size: 1px; line-height: 1px;", width: "21"}
+      %td{align: "left", style: "padding: 20px 0 0;"}
+        %h2{style: "color:#646464; font-weight: bold; margin: 0; padding: 0; line-height: 26px; font-size: 18px; font-family: Helvetica, Arial, sans-serif; "}
+          = "Issue was #{@issue_status} by #{@updated_by.name}"
+      %td{style: "font-size: 1px; line-height: 1px;", width: "21"}
+    %tr
+      %td{style: "font-size: 1px; line-height: 1px;", width: "21"}
+      %td{align: "left", style: "padding: 20px 0 0;"}
+        %h2{style: "color:#646464 !important; font-weight: bold; margin: 0; padding: 0; line-height: 26px; font-size: 18px; font-family: Helvetica, Arial, sans-serif; "}
+          = "Issue ##{@issue.id}"
+          = link_to_gfm truncate(@issue.title, length: 45), project_issue_url(@issue.project, @issue), title: @issue.title
+        %br
+
diff --git a/app/views/notify/new_user_email.html.haml b/app/views/notify/new_user_email.html.haml
index d96afc92fe27482e88e1c8363d7154198ac1a831..93bf7c50229bd6e393cb55d369a7bbe6377cda75 100644
--- a/app/views/notify/new_user_email.html.haml
+++ b/app/views/notify/new_user_email.html.haml
@@ -6,7 +6,7 @@
         %h2{style: "color:#646464; font-weight: bold; margin: 0; padding: 0; line-height: 26px; font-size: 18px; font-family: Helvetica, Arial, sans-serif; "}
           Hi #{@user['name']}!
         %p{style: "color:#767676; font-weight: normal; margin: 0; padding: 0; line-height: 20px; font-size: 12px;font-family: Helvetica, Arial, sans-serif; "}
-          Administrator created account for you. Now you are a member of company gitlab application.
+          Administrator created account for you. Now you are a member of company GitLab application.
       %td{style: "font-size: 1px; line-height: 1px;", width: "21"}
     %tr
       %td{style: "font-size: 1px; line-height: 1px;", width: "21"}
diff --git a/app/views/notify/project_access_granted_email.html.haml b/app/views/notify/project_access_granted_email.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..154c2aaa01e65d0c45e450fa2e15e40cba92a4ec
--- /dev/null
+++ b/app/views/notify/project_access_granted_email.html.haml
@@ -0,0 +1,14 @@
+%td.content{align: "left", style: "font-family: Helvetica, Arial, sans-serif; padding: 20px 0 0;", valign: "top", width: "600"}
+  %table{border: "0", cellpadding: "0", cellspacing: "0", style: "color: #717171; font: normal 11px Helvetica, Arial, sans-serif; margin: 0; padding: 0;", width: "600"}
+    %tr
+      %td{style: "font-size: 1px; line-height: 1px;", width: "21"}
+      %td{align: "left", style: "padding: 20px 0 0;"}
+        %h2{style: "color:#646464; font-weight: bold; margin: 0; padding: 0; line-height: 26px; font-size: 18px; font-family: Helvetica, Arial, sans-serif; "}
+          = "You got granted #{@users_project.project_access_human} access to project"
+      %td{style: "font-size: 1px; line-height: 1px;", width: "21"}
+    %tr
+      %td{style: "font-size: 1px; line-height: 1px;", width: "21"}
+      %td{align: "left", style: "padding: 20px 0 0;"}
+        %h2{style: "color:#646464 !important; font-weight: bold; margin: 0; padding: 0; line-height: 26px; font-size: 18px; font-family: Helvetica, Arial, sans-serif; "}
+          = link_to_gfm truncate(@project.name, length: 45), project_url(@project), title: @project.name
+        %br
diff --git a/app/views/profile/account.html.haml b/app/views/profile/account.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..6707a8ff443c47cd53a9bb2a7091b311d1b5a9ba
--- /dev/null
+++ b/app/views/profile/account.html.haml
@@ -0,0 +1,57 @@
+- if Gitlab.config.omniauth_enabled?
+  %fieldset
+    %legend
+      %h3.page_title Social Accounts
+    .oauth_select_holder
+      %p.hint Tip: Click on icon to activate sigin with one of the following services
+      - User.omniauth_providers.each do |provider|
+        %span{class: oauth_active_class(provider) }
+          = link_to authbutton(provider, 32), omniauth_authorize_path(User, provider)
+
+
+%fieldset
+  %legend
+    %h3.page_title
+      Private token
+      %span.cred.right
+        keep it in secret!
+  .padded
+    = form_for @user, url: profile_reset_private_token_path, method: :put do |f|
+      .data
+        %p.slead
+          Private token used to access application resources without authentication.
+          %br
+          It can be used for atom feed or API
+        %p.cgray
+          - if current_user.private_token
+            = text_field_tag "token", current_user.private_token, class: "xxlarge large_text"
+            = f.submit 'Reset', confirm: "Are you sure?", class: "btn primary btn-build-token"
+          - else
+            %span You don`t have one yet. Click generate to fix it.
+            = f.submit 'Generate', class: "btn success btn-build-token"
+
+%fieldset
+  %legend
+    %h3.page_title Password
+  = form_for @user, url: profile_password_path, method: :put do |f|
+    .padded
+      %p.slead After successful password update you will be redirected to login page where you should login with new password
+      -if @user.errors.any?
+        .alert-message.block-message.error
+          %ul
+            - @user.errors.full_messages.each do |msg|
+              %li= msg
+
+      .clearfix
+        = f.label :password
+        .input= f.password_field :password
+      .clearfix
+        = f.label :password_confirmation
+        .input= f.password_field :password_confirmation
+    .actions
+      = f.submit 'Save', class: "btn save-btn"
+
+
+
+
+
diff --git a/app/views/profile/history.html.haml b/app/views/profile/history.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..aa7006c569be75052d9504cd0c44761b98fe59d6
--- /dev/null
+++ b/app/views/profile/history.html.haml
@@ -0,0 +1,5 @@
+.profile_history
+  = render @events
+%hr
+= paginate @events, theme: "gitlab"
+
diff --git a/app/views/profile/password.html.haml b/app/views/profile/password.html.haml
deleted file mode 100644
index 257dacb1ad37b90787ad6d09f9e5455b825678f2..0000000000000000000000000000000000000000
--- a/app/views/profile/password.html.haml
+++ /dev/null
@@ -1,19 +0,0 @@
-%h3.page_title Password
-%hr
-= form_for @user, url: profile_password_path, method: :put do |f|
-  .data
-    %p.slead After successful password update you will be redirected to login page where you should login with new password
-    -if @user.errors.any?
-      .alert-message.block-message.error
-        %ul
-          - @user.errors.full_messages.each do |msg|
-            %li= msg
-
-    .clearfix
-      = f.label :password
-      .input= f.password_field :password
-    .clearfix
-      = f.label :password_confirmation
-      .input= f.password_field :password_confirmation
-  .actions
-    = f.submit 'Save', class: "btn primary"
diff --git a/app/views/profile/show.html.haml b/app/views/profile/show.html.haml
index 95cce2bb6b6c4642b9388f4c8934aa0dca3af694..7b62529116e35253a2b53001949a67049a0aff23 100644
--- a/app/views/profile/show.html.haml
+++ b/app/views/profile/show.html.haml
@@ -6,7 +6,6 @@
   %small
     = @user.email
 
-
 %hr
 
 = form_for @user, url: profile_update_path, method: :put, html: { class: "edit_user form-horizontal" }  do |f|
@@ -28,7 +27,23 @@
           = f.text_field :email, class: "input-xlarge"
           %span.help-block We also use email for avatar detection.
 
-      %hr
+    .span5.right
+      %div.tips
+        %h6 Tips:
+        %ul
+          -unless Gitlab.config.disable_gravatar?
+            %li
+              %p.hint You can change your avatar at #{link_to "gravatar.com", "http://gravatar.com"}
+
+          - if Gitlab.config.omniauth_enabled? && @user.provider?
+            %li
+              %p.hint
+                You can login through #{@user.provider.titleize}!
+                = link_to "click here to change", profile_account_path
+
+  %hr
+  .row
+    .span7
       .control-group
         = f.label :skype, class: "control-label"
         .controls= f.text_field :skype, class: "input-xlarge"
@@ -44,26 +59,24 @@
           = f.text_area :bio, rows: 6, class: "input-xlarge", maxlength: 250
           %span.help-block Tell us about yourself in fewer than 250 characters.
     .span5.right
+      .ui-box.white
+        .ui-box-body
+          %h4
+            Personal projects:
+            %small.right
+              %span= current_user.my_own_projects.count
+              of
+              %span= current_user.projects_limit
+          .progress
+            .bar{style: "width: #{current_user.projects_limit_percent}%;"}
 
-      %p.alert.alert-info
-        %strong Tip:
-        You can change your avatar at gravatar.com
-
-      %h4
-        Personal projects:
-        %small.right
-          %span= current_user.my_own_projects.count
-          of
-          %span= current_user.projects_limit
-      .progress
-        .bar{style: "width: #{current_user.projects_limit_percent}%;"}
-
-      %h4
-        SSH public keys:
-        %small.right
-          %span= link_to current_user.keys.count, keys_path
+      .ui-box.white
+        .ui-box-body
+          %h4
+            SSH public keys:
+            %strong.right= link_to current_user.keys.count, keys_path
 
-      = link_to "Add Public Key", new_key_path, class: "btn small right"
+          = link_to "Add Public Key", new_key_path, class: "btn small"
 
   .form-actions
-    = f.submit 'Save', class: "btn-primary btn"
+    = f.submit 'Save', class: "btn save-btn"
diff --git a/app/views/profile/token.html.haml b/app/views/profile/token.html.haml
deleted file mode 100644
index 6c870c364de1509678c71bdaeabc9d614444bdf1..0000000000000000000000000000000000000000
--- a/app/views/profile/token.html.haml
+++ /dev/null
@@ -1,23 +0,0 @@
-%h3.page_title
-  Private token
-  %span.cred.right
-    keep it in secret!
-%hr
-= form_for @user, url: profile_reset_private_token_path, method: :put do |f|
-  .data
-    %p.slead
-      Private token used to access application resources without authentication.
-      %br
-      It can be used for atom feed or API
-    %p.cgray
-      - if current_user.private_token
-        = text_field_tag "token", current_user.private_token, class: "xxlarge large_text"
-      - else
-        You don`t have one yet. Click generate to fix it.
-  .actions
-    - if current_user.private_token
-      = f.submit 'Reset', confirm: "Are you sure?", class: "btn"
-    - else
-      = f.submit 'Generate', class: "btn primary"
-
-
diff --git a/app/views/projects/_clone_panel.html.haml b/app/views/projects/_clone_panel.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..20891610ace12d7da89d355eb3bdb40e760eb6bd
--- /dev/null
+++ b/app/views/projects/_clone_panel.html.haml
@@ -0,0 +1,21 @@
+.project_clone_panel
+  .row
+    .span7
+      .form-horizontal
+        .input-prepend.project_clone_holder
+          %button{class: "btn small active", :"data-clone" => @project.ssh_url_to_repo} SSH
+          %button{class: "btn small", :"data-clone" => @project.http_url_to_repo} HTTP
+          = text_field_tag :project_clone, @project.url_to_repo, class: "one_click_select span5"
+    .span4.right
+      .right
+        - unless @project.empty_repo?
+          - if can? current_user, :download_code, @project
+            = link_to archive_project_repository_path(@project), class: "btn small grouped" do
+              %i.icon-download-alt
+              Download
+          - if @project.merge_requests_enabled && can?(current_user, :write_merge_request, @project)
+            = link_to new_project_merge_request_path(@project), title: "New Merge Request", class: "btn small grouped" do
+              Merge Request
+          - if @project.issues_enabled && can?(current_user, :write_issue, @project)
+            = link_to new_project_issue_path(@project), title: "New Issue", class: "btn small grouped" do
+              Issue
diff --git a/app/views/projects/_form.html.haml b/app/views/projects/_form.html.haml
index ce66b2cf9307b1566e09d5eb9f9f6351170da0f0..8bdeda1cafe15ab13b2836e53801af5df17a79b9 100644
--- a/app/views/projects/_form.html.haml
+++ b/app/views/projects/_form.html.haml
@@ -10,9 +10,9 @@
     .input
       = f.text_field :name, placeholder: "Example Project", class: "xxlarge"
 
-  %h5.page_title 
-  .alert.alert-info
-    %h5 Advanced settings:
+  %hr
+  .adv_settings
+    %h6 Advanced settings:
     .clearfix
       = f.label :path do
         Path
@@ -34,8 +34,9 @@
         .input= f.select(:default_branch, @project.heads.map(&:name), {}, style: "width:210px;")
 
   - unless @project.new_record?
-    .alert.alert-info
-      %h5 Features:
+    %hr
+    .adv_settings
+      %h6 Features:
 
       .clearfix
         = f.label :issues_enabled, "Issues"
@@ -56,7 +57,7 @@
   %br
 
   .actions
-    = f.submit 'Save', class: "btn primary"
+    = f.submit 'Save', class: "btn save-btn"
     = link_to 'Cancel', @project, class: "btn"
     - unless @project.new_record?
       .right
diff --git a/app/views/projects/_new_form.html.haml b/app/views/projects/_new_form.html.haml
index 5104df83a2c7d0fa4f1d08d74b98a7c6e1f1aa54..e6d5e93fca76985a48cf171089913181ec52bccc 100644
--- a/app/views/projects/_new_form.html.haml
+++ b/app/views/projects/_new_form.html.haml
@@ -7,11 +7,11 @@
       Project name is
     .input
       = f.text_field :name, placeholder: "Example Project", class: "xxlarge"
-      = f.submit 'Create project', class: "btn primary"
+      = f.submit 'Create project', class: "btn primary project-submit"
 
   %hr
-  .alert.alert-info
-    %h5 Advanced settings:
+  %div.adv_settings
+    %h6 Advanced settings:
     .clearfix
       = f.label :path do
         Git Clone
diff --git a/app/views/projects/_project_head.html.haml b/app/views/projects/_project_head.html.haml
index ba64ee7f99637d716860805375623b6f84bcfb0e..4f38bef8b48b3d00cd8a9071da3ca9ebadd84775 100644
--- a/app/views/projects/_project_head.html.haml
+++ b/app/views/projects/_project_head.html.haml
@@ -3,8 +3,8 @@
     = link_to project_path(@project), class: "activities-tab tab" do
       %i.icon-home
       Show
-  %li{ class: " #{'active' if (controller.controller_name == "team_members") || current_page?(team_project_path(@project)) }" }
-    = link_to team_project_path(@project), class: "team-tab tab" do
+  %li{ class: " #{'active' if (controller.controller_name == "team_members") || current_page?(project_team_index_path(@project)) }" }
+    = link_to project_team_index_path(@project), class: "team-tab tab" do
       %i.icon-user
       Team
   %li{ class: "#{'active' if current_page?(files_project_path(@project)) }" }
diff --git a/app/views/projects/_refs.html.haml b/app/views/projects/_refs.html.haml
deleted file mode 100644
index 804b852340e3f4c22ab603b59636856ce7692017..0000000000000000000000000000000000000000
--- a/app/views/projects/_refs.html.haml
+++ /dev/null
@@ -1,8 +0,0 @@
-= form_tag switch_project_refs_path(@project), method: :get, class: "project-refs-form" do
-  = select_tag "ref", grouped_options_refs, onchange: "this.form.submit();", class: "project-refs-select"
-  = hidden_field_tag :destination, destination
-
-:javascript
-  $(function(){
-    $('.project-refs-select').chosen();
-  })
diff --git a/app/views/projects/_show.html.haml b/app/views/projects/_show.html.haml
deleted file mode 100644
index e8a5b00dd0e22cf1e60ecf49b4d7e5c06723722d..0000000000000000000000000000000000000000
--- a/app/views/projects/_show.html.haml
+++ /dev/null
@@ -1,23 +0,0 @@
-%h5.title
-  = @project.name
-%br
-%div
-  %a.btn.info{href: tree_project_ref_path(@project, @project.root_ref)} Browse code
-  &nbsp;
-  %a.btn{href: project_commits_path(@project)} Commits
-  %strong.right
-    = link_to project_path(@project) do
-      Switch to project &rarr;
-%br
-.alert-message.block-message.warning
-  .input
-    .input-prepend
-      %span.add-on git clone
-      = text_field_tag :project_clone, @project.url_to_repo, class: "xlarge one_click_select git_clone_url"
-
-= simple_format @project.description
-- unless @events.blank?
-  %h4.middle_title Recent Activity
-  .content_list= render @events
-
-
diff --git a/app/views/projects/_team.html.haml b/app/views/projects/_team.html.haml
deleted file mode 100644
index 175aea27ed49ab6612e44c65f3b33b1178f3a0c1..0000000000000000000000000000000000000000
--- a/app/views/projects/_team.html.haml
+++ /dev/null
@@ -1,16 +0,0 @@
-%table.admin-table
-  %thead
-    %tr
-      %th User
-      %th Permissions
-  %tbody
-    - @project.users_projects.each do |up|
-      = render(partial: 'team_members/show', locals: {member: up})
-
-
-:javascript
-  $(function(){
-    $('.repo-access-select, .project-access-select').live("change", function() {
-      $(this.form).submit();
-    });
-  })
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index 987d43ec5408203a1f200a044edb5545b0abffca..fdd537da3aab494fa815754f421e1eee896889c6 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -3,10 +3,10 @@
   %h3.page_title Edit Project
   %hr
   = render "projects/form"
-%div.ajax_loader.hide
+%div.save-project-loader.hide
   %center
-    %div.padded= image_tag "ajax_loader.gif"
-    %h3.prepend-top Saving project &amp; repository. Please wait...
+    = image_tag "ajax_loader.gif"
+    %h3 Saving project. Please wait a few minutes
 
 :javascript
   $(function(){ new Projects(); });
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index 907d5ef4666a1b5d762c2e994278b6a951d27ef2..d9a151fc706e19eecc5275cb654280f89648f58b 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -1,4 +1,6 @@
 = render 'shared/no_ssh'
+= render 'clone_panel'
+
 %div.git-empty
   %h4 Git global setup:
   %pre.dark
diff --git a/app/views/projects/files.html.haml b/app/views/projects/files.html.haml
index 68d51df0b5606ed1977d952cd10e021808aa35f0..ce8ba876065d4cbac3480653c3388e4f89948dbd 100644
--- a/app/views/projects/files.html.haml
+++ b/app/views/projects/files.html.haml
@@ -1,6 +1,11 @@
 = render "project_head"
 - unless @notes.empty?
-  %table.zebra-striped.borders
+  %table
+    %thead
+      %tr
+        %th File name
+        %th 
+
     - @notes.each do |note|
       %tr
         %td
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index 703e558ae41fe6df65c34a6f3986ef3b9416d7a3..933cb671142881c0a1a347786fd41565bc3df221 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -3,10 +3,10 @@
     New Project
   %hr
   = render 'new_form'
-%div.ajax_loader.hide
+%div.save-project-loader.hide
   %center
-    %div.padded= image_tag "ajax_loader.gif"
-    %h3.prepend-top Creating project &amp; repository. Please wait a few minutes
+    = image_tag "ajax_loader.gif"
+    %h3 Creating project &amp; repository. Please wait a few minutes
 
 :javascript
   $(function(){ new Projects(); });
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index ebd2c8e449528295284016931d435e95d38ea674..21459da256f7b9398f7f2845c8ebb13fba84592e 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -1,37 +1,4 @@
 = render "project_head"
-
-.entry
-  .row
-    .span7
-      .form-horizontal
-        .input-prepend.project_clone_holder
-
-          %span.add-on git clone
-          = link_to "SSH", "#", class: "btn small active", :"data-clone" => @project.ssh_url_to_repo
-          = link_to "HTTP", "#", class: "btn small", :"data-clone" => @project.http_url_to_repo
-          = text_field_tag :project_clone, @project.url_to_repo, class: "one_click_select span5"
-    .span4.right
-      .right
-        - if can? current_user, :download_code, @project
-          = link_to archive_project_repository_path(@project), class: "btn small grouped" do
-            %i.icon-download-alt
-            Download
-        - if @project.merge_requests_enabled && can?(current_user, :write_merge_request, @project)
-          = link_to new_project_merge_request_path(@project), title: "New Merge Request", class: "btn small grouped" do
-            Merge Request
-        - if @project.issues_enabled && can?(current_user, :write_issue, @project)
-          = link_to new_project_issue_path(@project), title: "New Issue", class: "btn small grouped" do
-            Issue
-
+= render 'clone_panel'
 = render "events/event_last_push", event: @last_push
 .content_list= render @events
-
-:javascript 
-  $(function(){
-    var link_sel = ".project_clone_holder a";
-    $(link_sel).bind("click", function() { 
-      $(link_sel).removeClass("active");
-      $(this).addClass("active");
-      $("#project_clone").val($(this).attr("data-clone"));
-    })
-  })
diff --git a/app/views/projects/wall.html.haml b/app/views/projects/wall.html.haml
index 97765d7ac887ad8fb86deb0684376b57eb88a2b1..591a8cd06d4b05a3241b707a84de0ae77d979e2c 100644
--- a/app/views/projects/wall.html.haml
+++ b/app/views/projects/wall.html.haml
@@ -1,2 +1,2 @@
 %div.wall_page
-  = render "notes/notes", tid: nil, tt: "wall"
+  = render "notes/reversed_notes_with_form", tid: nil, tt: "wall"
diff --git a/app/views/protected_branches/index.html.haml b/app/views/protected_branches/index.html.haml
index 2b93b0a83db6b0582252da42d10b84f3bc06fd6d..43884de1db5962a080c4633dd37894e553f6d416 100644
--- a/app/views/protected_branches/index.html.haml
+++ b/app/views/protected_branches/index.html.haml
@@ -19,12 +19,12 @@
     .entry.clearfix
       = f.label :name, "Branch"
       .span3
-        = f.select(:name, @project.open_branches.map { |br| [br.name, br.name] } , { include_blank: "-- Select branch" }, { class: "span3" })
+        = f.select(:name, @project.open_branches.map { |br| [br.name, br.name] } , {include_blank: "Select branch"}, {class: "chosen span3"})
       &nbsp;
       = f.submit 'Protect', class: "primary btn"
 
 - unless @branches.empty?
-  %table.admin-table
+  %table
     %thead
       %tr
         %th Name
@@ -46,6 +46,3 @@
           %td
             - if can? current_user, :admin_project, @project
               = link_to 'Unprotect', [@project, branch], confirm: 'Are you sure?', method: :delete, class: "danger btn small"
-
-:javascript
-  $('select#protected_branch_name').chosen();
diff --git a/app/views/refs/_head.html.haml b/app/views/refs/_head.html.haml
index 8825493a0ec514592d79d7a9499d9b2bd9f884b9..3592f5737cec523815fe3e2befef1a6cfeab520f 100644
--- a/app/views/refs/_head.html.haml
+++ b/app/views/refs/_head.html.haml
@@ -1,10 +1,11 @@
 %ul.nav.nav-tabs
   %li
-    = form_tag switch_project_refs_path(@project), method: :get, class: "project-refs-form", remote: true do
-      = select_tag "ref", grouped_options_refs, onchange: "$(this.form).trigger('submit');", class: "project-refs-select"
-      = hidden_field_tag :destination, "tree"
-      = hidden_field_tag :path, params[:path]
+    = render partial: 'shared/ref_switcher', locals: {destination: 'tree', path: params[:path]}
   %li{class: "#{'active' if (controller.controller_name == "refs") }"}
     = link_to tree_project_ref_path(@project, @ref) do
       Source
-
+  %li.right
+    .input-prepend.project_clone_holder
+      %button{class: "btn small active", :"data-clone" => @project.ssh_url_to_repo} SSH
+      %button{class: "btn small", :"data-clone" => @project.http_url_to_repo} HTTP
+      = text_field_tag :project_clone, @project.url_to_repo, class: "one_click_select span5"
diff --git a/app/views/refs/_tree.html.haml b/app/views/refs/_tree.html.haml
index c231c40735c3bd73a2cf0940bd4e1b941ef40419..55078718b79f26793100b0bc507612e1dee55166 100644
--- a/app/views/refs/_tree.html.haml
+++ b/app/views/refs/_tree.html.haml
@@ -13,7 +13,7 @@
     = render partial: "refs/tree_file", locals: { name: tree.name, content: tree.data, file: tree }
   - else
     - contents = tree.contents
-    %table#tree-slider.bordered-table.table{class: "table_#{@hex_path}" }
+    %table#tree-slider{class: "table_#{@hex_path}" }
       %thead
         %th Name
         %th Last Update
@@ -43,25 +43,23 @@
           %i.icon-file
           = content.name
         .file_content.wiki
-          - if content.name =~ /\.(md|markdown)$/i
+          - if gitlab_markdown?(content.name)
             = preserve do
               = markdown(content.data)
           - else
-            = simple_format(content.data)
+            = raw GitHub::Markup.render(content.name, content.data)
 
 :javascript
   $(function(){
-    $('.project-refs-select').chosen();
-
     history.pushState({ path: this.path }, '', "#{@history_path}");
-
-  });
-
-  // Load last commit log for each file in tree
-  $(window).load(function(){
-    ajaxGet('#{@logs_path}'); 
   });
 
+- unless tree.is_blob?
+  :javascript
+    // Load last commit log for each file in tree
+    $(window).load(function(){
+      ajaxGet('#{@logs_path}');
+    });
 
 - if params[:path] && request.xhr?
   :javascript
diff --git a/app/views/refs/_tree_file.html.haml b/app/views/refs/_tree_file.html.haml
index b5ed61bb45a282a1dbfc041e29442da0d2659f60..76173e24246ac9d1d64472887dec068e0a68cf91 100644
--- a/app/views/refs/_tree_file.html.haml
+++ b/app/views/refs/_tree_file.html.haml
@@ -2,17 +2,20 @@
   .file_title
     %i.icon-file
     %span.file_name
-      = name
+      = name.force_encoding('utf-8')
       %small #{file.mode}
     %span.options
       = link_to "raw", blob_project_ref_path(@project, @ref, path: params[:path]), class: "btn very_small", target: "_blank"
       = link_to "history", project_commits_path(@project, path: params[:path], ref: @ref), class: "btn very_small"
       = link_to "blame", blame_file_project_ref_path(@project, @ref, path: params[:path]), class: "btn very_small"
   - if file.text?
-    - if name =~ /\.(md|markdown)$/i
+    - if gitlab_markdown?(name)
       .file_content.wiki
         = preserve do
           = markdown(file.data)
+    - elsif markup?(name)
+      .file_content.wiki
+        = raw GitHub::Markup.render(name, file.data)
     - else
       .file_content.code
         - unless file.empty?
diff --git a/app/views/refs/_tree_item.html.haml b/app/views/refs/_tree_item.html.haml
index 2e6bbf6221bfa4b3674a36997040d6ea77589458..d4c4ee8de49c1f1400e470e8e4bd836f9b885061 100644
--- a/app/views/refs/_tree_item.html.haml
+++ b/app/views/refs/_tree_item.html.haml
@@ -2,7 +2,7 @@
 %tr{ class: "tree-item #{tree_hex_class(content)}", url: tree_file_project_ref_path(@project, @ref, file) }
   %td.tree-item-file-name
     = tree_icon(content)
-    = link_to truncate(content.name, length: 40), tree_file_project_ref_path(@project, @ref || @commit.id, file), remote: :true
+    %strong= link_to truncate(content.name, length: 40), tree_file_project_ref_path(@project, @ref || @commit.id, file), remote: :true
   %td.tree_time_ago.cgray
     - if index == 1
       %span.log_loading
diff --git a/app/views/refs/blame.html.haml b/app/views/refs/blame.html.haml
index 34478d4b4911b38f6f3dd77baaa239f42b6aba7d..eb66f59760bd7e171da3dbd7bf860a67b66498b6 100644
--- a/app/views/refs/blame.html.haml
+++ b/app/views/refs/blame.html.haml
@@ -38,8 +38,3 @@
               = preserve do
                 %pre
                   = Gitlab::Encode.utf8 lines.join("\n")
-
-:javascript
-  $(function(){
-    $('.project-refs-select').chosen();
-  });
diff --git a/app/views/refs/tree.js.haml b/app/views/refs/tree.js.haml
index 2eccf8c19a6df2558cfe9e72d729175a7ceaeb58..92e90579304faed6c25424590e83c75435fa4145 100644
--- a/app/views/refs/tree.js.haml
+++ b/app/views/refs/tree.js.haml
@@ -6,5 +6,5 @@
 
   //  Load last commit log for each file in tree
   $('#tree-slider').waitForImages(function() {
-    ajaxGet('#{@logs_path}'); 
+    ajaxGet('#{@logs_path}');
   });
diff --git a/app/views/repositories/_branch.html.haml b/app/views/repositories/_branch.html.haml
index cf8558ec33e3e5c44f374ede769bb2df4afedfa9..64a633be8ac854976d4f93533f48d68c70ce0b19 100644
--- a/app/views/repositories/_branch.html.haml
+++ b/app/views/repositories/_branch.html.haml
@@ -11,7 +11,7 @@
       %code= commit.short_id
 
     = image_tag gravatar_icon(commit.author_email), class: "", width: 16
-    = gfm truncate(commit.title, length: 40)
+    = gfm escape_once(truncate(commit.title, length: 40))
     %span.update-author.right
       = time_ago_in_words(commit.committed_date)
       ago
diff --git a/app/views/repositories/_feed.html.haml b/app/views/repositories/_feed.html.haml
index ac4eb48394527b0f7976c6f66e4d2a76a7b13434..0c13551d60782c3365947114f910b0ee03c3f35e 100644
--- a/app/views/repositories/_feed.html.haml
+++ b/app/views/repositories/_feed.html.haml
@@ -13,7 +13,7 @@
       = link_to project_commits_path(@project, commit.id) do
         %code= commit.short_id
       = image_tag gravatar_icon(commit.author_email), class: "", width: 16
-      = gfm truncate(commit.title, length: 40)
+      = gfm escape_once(truncate(commit.title, length: 40))
   %td
     %span.right.cgray
       = time_ago_in_words(commit.committed_date)
diff --git a/app/views/repositories/branches.html.haml b/app/views/repositories/branches.html.haml
index 45004bdff430f8b7e67a004fb5e6654da2ee21a5..4c246c69d7c4f0705c4f33a8f21c735b27e55eeb 100644
--- a/app/views/repositories/branches.html.haml
+++ b/app/views/repositories/branches.html.haml
@@ -1,6 +1,6 @@
 = render "repositories/branches_head"
 - unless @branches.empty?
-  %table.admin-table
+  %table
     %thead
       %tr
         %th Name
diff --git a/app/views/repositories/show.html.haml b/app/views/repositories/show.html.haml
index a09cdd6212b2c31f88ad151750d1afa75b065885..fd0abac841419b4cc6296da5f027607a23ed873c 100644
--- a/app/views/repositories/show.html.haml
+++ b/app/views/repositories/show.html.haml
@@ -1,6 +1,6 @@
 = render "branches_head"
 
-%table.admin-table
+%table
   %thead
     %tr
       %th Name
diff --git a/app/views/repositories/tags.html.haml b/app/views/repositories/tags.html.haml
index 7fc2c3bfd2fb49d4c52d96217c759f9220cb5109..a41145867e94dd7a2f5999f680bc735fc6919713 100644
--- a/app/views/repositories/tags.html.haml
+++ b/app/views/repositories/tags.html.haml
@@ -1,6 +1,6 @@
 = render "commits/head"
 - unless @tags.empty?
-  %table.admin-table
+  %table
     %thead
       %tr
         %th Name
@@ -17,7 +17,7 @@
           = link_to project_commit_path(@project, commit.id) do
             %code= commit.short_id
           = image_tag gravatar_icon(commit.author_email), class: "", width: 16
-          = gfm truncate(commit.title, length: 40)
+          = gfm escape_once(truncate(commit.title, length: 40))
         %td
           %span.update-author.right
             = time_ago_in_words(commit.committed_date)
diff --git a/app/views/search/show.html.haml b/app/views/search/show.html.haml
index 9a0b47895884e04cfafe584e5778a3e7e86e5709..d85c24ec1057f2ba277cf744abcbb5c9a7f15f64 100644
--- a/app/views/search/show.html.haml
+++ b/app/views/search/show.html.haml
@@ -3,8 +3,8 @@
     = label_tag :search do
       %strong Looking for
     .input
-      = text_field_tag :search, params[:search], placeholder: "issue 143", class: "input-xxlarge", id: "dashboard_search"
-      = submit_tag 'Search', class: "btn btn-primary"
+      = search_field_tag :search, params[:search], placeholder: "issue 143", class: "input-xxlarge search-text-input", id: "dashboard_search"
+      = submit_tag 'Search', class: "btn primary wide"
 - if params[:search].present?
   %br
   %h3
@@ -14,9 +14,10 @@
   .search_results
     .row
       .span6
-        %table.admin-table
-          %tr
-            %th Projects
+        %table
+          %thead
+            %tr
+              %th Projects
           %tbody
             - @projects.each do |project|
               %tr
@@ -31,9 +32,10 @@
                 %td
                   %h4.nothing_here_message No Projects
         %br
-        %table.admin-table
-          %tr
-            %th Merge Requests
+        %table
+          %thead
+            %tr
+              %th Merge Requests
           %tbody
             - @merge_requests.each do |merge_request|
               %tr
@@ -49,9 +51,10 @@
                 %td
                   %h4.nothing_here_message No Merge Requests
       .span6
-        %table.admin-table
-          %tr
-            %th Issues
+        %table
+          %thead
+            %tr
+              %th Issues
           %tbody
             - @issues.each do |issue|
               %tr
diff --git a/app/views/shared/_ref_switcher.html.haml b/app/views/shared/_ref_switcher.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..e0c89522c1157a12fea15772d51a557ccf7b10bf
--- /dev/null
+++ b/app/views/shared/_ref_switcher.html.haml
@@ -0,0 +1,5 @@
+= form_tag switch_project_refs_path(@project), method: :get, class: "project-refs-form" do
+  = select_tag "ref", grouped_options_refs, class: "project-refs-select chosen"
+  = hidden_field_tag :destination, destination
+  - if respond_to?(:path)
+    = hidden_field_tag :path, path
diff --git a/app/views/snippets/_form.html.haml b/app/views/snippets/_form.html.haml
index b8d8c09849d45642f1f0c555d701cbc7d9743166..e61e61a7e5e209a7d724caeaa27034848ab7145f 100644
--- a/app/views/snippets/_form.html.haml
+++ b/app/views/snippets/_form.html.haml
@@ -16,7 +16,7 @@
       .input= f.text_field :file_name, placeholder: "example.rb"
     .clearfix
       = f.label "Lifetime"
-      .input= f.select :expires_at, lifetime_select_options, {}, style: "width:200px;"
+      .input= f.select :expires_at, lifetime_select_options, {}, {class: 'chosen span2'}
     .clearfix
       = f.label :content, "Code"
       .input= f.text_area :content, class: "span8"
@@ -26,11 +26,3 @@
     = link_to "Cancel", project_snippets_path(@project), class: " btn"
     - unless @snippet.new_record?
       .right= link_to 'Destroy', [@project, @snippet], confirm: 'Are you sure?', method: :delete, class: "btn right danger delete-snippet", id: "destroy_snippet_#{@snippet.id}"
-
-
-
-:javascript
-  $(function(){
-    $('select#snippet_expires_at').chosen();
-  });
-
diff --git a/app/views/snippets/index.html.haml b/app/views/snippets/index.html.haml
index 7229b587bc823ae80c2d6145fbc3516937fd26f8..515daec6207b4380a58c95596758d68ed278c736 100644
--- a/app/views/snippets/index.html.haml
+++ b/app/views/snippets/index.html.haml
@@ -8,7 +8,7 @@
     %br
     To add new snippet - click on button.
 
-%table.admin-table
+%table
   %thead
     %tr
       %th Title
diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml
index 0800b81d330d6fff31a0067a775e805067c49ffe..4188a9f198c976698a96f3e6a7176c71282a02fd 100644
--- a/app/views/snippets/show.html.haml
+++ b/app/views/snippets/show.html.haml
@@ -17,4 +17,4 @@
     %div{class: current_user.dark_scheme ? "black" : ""}
       = raw @snippet.colorize(options: { linenos: 'True'})
 
-= render "notes/notes", tid: @snippet.id, tt: "snippet"
+= render "notes/notes_with_form", tid: @snippet.id, tt: "snippet"
diff --git a/app/views/team_members/_form.html.haml b/app/views/team_members/_form.html.haml
index 208794b9ee2fda5881ba5e777d4ec4663c7473c8..92167138081df5b29c5568a2af86c2e312e64c18 100644
--- a/app/views/team_members/_form.html.haml
+++ b/app/views/team_members/_form.html.haml
@@ -1,4 +1,5 @@
-%h3= "New Team member"
+%h3.page_title
+  = "New Team member(s)"
 %hr
 = form_for @team_member, as: :team_member, url: project_team_members_path(@project, @team_member) do |f|
   -if @team_member.errors.any?
@@ -7,27 +8,16 @@
         - @team_member.errors.full_messages.each do |msg|
           %li= msg
 
+  %h6 1. Choose people you want in the team
   .clearfix
-    = f.label :user_id, "Name"
-    .input= f.select(:user_id, User.not_in_project(@project).all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select user" }, { style: "width:300px" })
-
+    = f.label :user_ids, "People"
+    .input= select_tag(:user_ids, options_from_collection_for_select(User.not_in_project(@project).all, :id, :name), {data: {placeholder: "Select users"}, class: "chosen xxlarge", multiple: true})
 
+  %h6 2. Set access level for them
   .clearfix
     = f.label :project_access, "Project Access"
-    .input= f.select :project_access, options_for_select(Project.access_options, @team_member.project_access), {}, class: "project-access-select"
-
+    .input= select_tag :project_access, options_for_select(Project.access_options, @team_member.project_access), class: "project-access-select chosen"
 
   .actions
-    = f.submit 'Save', class: "btn primary"
-    = link_to "Cancel", team_project_path(@project), class: "btn"
-
-:css
-  form select {
-    width:300px;
-  }
-
-:javascript
-  $('select#team_member_user_id').chosen();
-  $('select#team_member_project_access').chosen();
-  //$('select#team_member_repo_access').chosen();
-  //$('select#team_member_project_access').chosen();
+    = f.submit 'Save', class: "btn save-btn"
+    = link_to "Cancel", project_team_index_path(@project), class: "btn cancel-btn"
diff --git a/app/views/team_members/_show.html.haml b/app/views/team_members/_show.html.haml
index 2dc4fb652ddc0c031a3cf923825ab175b6119753..f68f8eb471fb25bc3645cda0403ae859dcf4ce93 100644
--- a/app/views/team_members/_show.html.haml
+++ b/app/views/team_members/_show.html.haml
@@ -1,20 +1,26 @@
 - user = member.user
 - allow_admin = can? current_user, :admin_project, @project
 %tr{id: dom_id(member), class: "team_member_row user_#{user.id}"}
-  %td
-    .right
-      - if @project.owner == user
-        %span.label Project Owner
-      - if user.blocked
-        %span.label Blocked
-
+  %td.span6
     = link_to project_team_member_path(@project, member), title: user.name, class: "dark" do
       = image_tag gravatar_icon(user.email, 40), class: "avatar s32"
     = link_to project_team_member_path(@project, member), title: user.name, class: "dark" do
       %strong= truncate(user.name, lenght: 40)
-    %br
-    %div.cgray= user.email
+      %br
+      %small.cgray= user.email
+
+  %td.span5
+    .right
+      - if current_user == user
+        %span.btn.disabled This is you!
+      - if @project.owner == user
+        %span.btn.disabled.success Owner
+      - elsif user.blocked
+        %span.btn.disabled.blocked Blocked
+      - elsif allow_admin
+        = link_to project_team_member_path(project_id: @project, id: member.id), confirm: remove_from_team_message(@project, member), method: :delete, class: "very_small btn danger" do
+          %i.icon-minus.icon-white
 
-  %td
-    = form_for(member, as: :team_member, url: project_team_member_path(@project, member)) do |f|
-      = f.select :project_access, options_for_select(UsersProject.access_roles, member.project_access), {}, class: "medium project-access-select", disabled: !allow_admin
+    - if allow_admin
+      = form_for(member, as: :team_member, url: project_team_member_path(@project, member)) do |f|
+        = f.select :project_access, options_for_select(UsersProject.access_roles, member.project_access), {}, class: "medium project-access-select span2"
diff --git a/app/views/team_members/_team.html.haml b/app/views/team_members/_team.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..a0c88b5987f9246a9b0e2b210a91da9c4ce2a5d4
--- /dev/null
+++ b/app/views/team_members/_team.html.haml
@@ -0,0 +1,18 @@
+- grouper_project_members(@project).each do |access, members|
+  %table
+    %thead
+      %tr
+        %th.span7
+          = Project.access_options.key(access).pluralize
+        %th
+    %tbody
+      - members.each do |up|
+        = render(partial: 'team_members/show', locals: {member: up})
+
+
+:javascript
+  $(function(){
+    $('.repo-access-select, .project-access-select').live("change", function() {
+      $(this.form).submit();
+    });
+  })
diff --git a/app/views/projects/team.html.haml b/app/views/team_members/index.html.haml
similarity index 79%
rename from app/views/projects/team.html.haml
rename to app/views/team_members/index.html.haml
index e8a825c741e9fd812378428be7e1b02794f05583..b3b7b72a15036160921b95fe2c136fdeebcdb441 100644
--- a/app/views/projects/team.html.haml
+++ b/app/views/team_members/index.html.haml
@@ -1,4 +1,4 @@
-= render "project_head"
+= render "projects/project_head"
 %h3.page_title
   Team Members
   %small (#{@project.users_projects.count})
@@ -10,6 +10,4 @@
     Read more about project permissions
     %strong= link_to "here", help_permissions_path, class: "vlink"
 
-
-= render partial: "team", locals: {project: @project}
-
+= render partial: "team_members/team", locals: {project: @project}
diff --git a/app/views/team_members/show.html.haml b/app/views/team_members/show.html.haml
index 6cb357cddfc6e82a4d5e10297c6a658db7d355e9..9d03cd2cb1fc9752172b693037e04da37460b8b0 100644
--- a/app/views/team_members/show.html.haml
+++ b/app/views/team_members/show.html.haml
@@ -3,7 +3,7 @@
 
 .team_member_show
   - if can? current_user, :admin_project, @project
-    = link_to 'Remove from team', project_team_member_path(project_id: @project, id: @team_member.id), confirm: 'Are you sure?', method: :delete, class: "right btn btn-danger"
+    = link_to 'Remove from team', project_team_member_path(project_id: @project, id: @team_member.id), confirm: 'Are you sure?', method: :delete, class: "right btn danger"
   .profile_avatar_holder
     = image_tag gravatar_icon(user.email, 60), class: "borders"
   %h3
@@ -14,12 +14,12 @@
   %hr
   .back_link
     %br
-    = link_to team_project_path(@project), class: "" do
+    = link_to project_team_index_path(@project), class: "" do
       &larr; To team list
   %br
   .row
     .span6
-      %table.no-borders
+      %table.lite
         %tr
           %td Email
           %td= mail_to user.email
@@ -39,7 +39,7 @@
             %td Bio
             %td= user.bio
     .span6
-      %table.no-borders
+      %table.lite
         %tr
           %td Member since
           %td= @team_member.created_at.stamp("Aug 21, 2011")
diff --git a/app/views/votes/_votes_block.html.haml b/app/views/votes/_votes_block.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..bded53b2f21e1bef0a6a5db9ff5604892f74da4d
--- /dev/null
+++ b/app/views/votes/_votes_block.html.haml
@@ -0,0 +1,6 @@
+.votes.votes-block
+  .progress
+    .bar.bar-success{style: "width: #{votable.upvotes_in_percent}%;"}
+    .bar.bar-danger{style: "width: #{votable.downvotes_in_percent}%;"}
+  .upvotes= "#{votable.upvotes} up"
+  .downvotes= "#{votable.downvotes} down"
diff --git a/app/views/votes/_votes_inline.html.haml b/app/views/votes/_votes_inline.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..91bd200df44fd261d770910906723a5f09d73cfc
--- /dev/null
+++ b/app/views/votes/_votes_inline.html.haml
@@ -0,0 +1,6 @@
+.votes.votes-inline
+  .upvotes= votable.upvotes
+  .progress
+    .bar.bar-success{style: "width: #{votable.upvotes_in_percent}%;"}
+    .bar.bar-danger{style: "width: #{votable.downvotes_in_percent}%;"}
+  .downvotes= votable.downvotes
diff --git a/app/views/wikis/_form.html.haml b/app/views/wikis/_form.html.haml
index 6b6411be55be39d060e30471202e444e00aa5c85..b05d0a7899210cfdfe76b74ed2dea440026325a2 100644
--- a/app/views/wikis/_form.html.haml
+++ b/app/views/wikis/_form.html.haml
@@ -14,13 +14,14 @@
     .middle_box_content
       .input
         %span.cgray
-          Wiki content is parsed with #{link_to "Markdown", "http://en.wikipedia.org/wiki/Markdown"}.
-          To add link to new page you can just type
+          Wiki content is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
+          To link to a (new) page you can just type
           %code [Link Title](page-slug)
+          \.
 
     .bottom_box_content
       = f.label :content
       .input= f.text_area :content, class: 'span8'
   .actions
-    = f.submit 'Save', class: "primary btn"
-    = link_to "Cancel", project_wiki_path(@project, :index), class: "btn"
+    = f.submit 'Save', class: "save-btn btn"
+    = link_to "Cancel", project_wiki_path(@project, :index), class: "btn cancel-btn"
diff --git a/app/views/wikis/history.html.haml b/app/views/wikis/history.html.haml
index e31c5dc24260aa82ea23d696726139928e6f139a..0a81817c5e7730548a77bf9469824dcda8e5b418 100644
--- a/app/views/wikis/history.html.haml
+++ b/app/views/wikis/history.html.haml
@@ -2,7 +2,7 @@
   %span.cgray History for
   = @wikis.last.title
 %br
-%table.admin-table
+%table
   %thead
     %tr
       %th #
diff --git a/app/views/wikis/pages.html.haml b/app/views/wikis/pages.html.haml
index 2bfd0deb14973e535df33f65787670d4d5d67b15..7421d8f967548ebd0f9e3a7f4b33ec891e213787 100644
--- a/app/views/wikis/pages.html.haml
+++ b/app/views/wikis/pages.html.haml
@@ -1,6 +1,6 @@
 %h3.page_title All Pages
 %br
-%table.admin-table
+%table
   %thead
     %tr
       %th Title
diff --git a/app/views/wikis/show.html.haml b/app/views/wikis/show.html.haml
index fc2352271d586758f21c802793ce41c7a0198eba..579ea1b3ad68719a54e336e3365ca3b334567796 100644
--- a/app/views/wikis/show.html.haml
+++ b/app/views/wikis/show.html.haml
@@ -21,4 +21,4 @@
     Delete this page
 
 %hr
-.wiki_notes#notes= render "notes/notes", tid: @wiki.id, tt: "wiki"
+.wiki_notes#notes= render "notes/notes_with_form", tid: @wiki.id, tt: "wiki"
diff --git a/config/application.rb b/config/application.rb
index ecd88b15d15d9f08b52ab452827ab0bbd3649684..ad41f19657f52f737b85650e484fb5896c1d6153 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -23,7 +23,7 @@ module Gitlab
     # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
 
     # Activate observers that should always be running.
-    config.active_record.observers = :mailer_observer, :activity_observer, :project_observer, :key_observer, :issue_observer, :user_observer, :system_hook_observer
+    config.active_record.observers = :mailer_observer, :activity_observer, :project_observer, :key_observer, :issue_observer, :user_observer, :system_hook_observer, :users_project_observer
 
     # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
     # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
diff --git a/config/cucumber.yml b/config/cucumber.yml
deleted file mode 100644
index 19b288df9d5e4e28c7dc9df108a3b112ca44e3b5..0000000000000000000000000000000000000000
--- a/config/cucumber.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-<%
-rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : ""
-rerun_opts = rerun.to_s.strip.empty? ? "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}"
-std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} --strict --tags ~@wip"
-%>
-default: <%= std_opts %> features
-wip: --tags @wip:3 --wip features
-rerun: <%= rerun_opts %> --format rerun --out rerun.txt --strict --tags ~@wip
diff --git a/config/environment.rb b/config/environment.rb
index c880a7adc420aacb77f0ffff96aa098ba62ae5d2..3b186a9d57afddfdae94306877719d2b98ea1945 100644
--- a/config/environment.rb
+++ b/config/environment.rb
@@ -3,5 +3,3 @@ require File.expand_path('../application', __FILE__)
 
 # Initialize the rails application
 Gitlab::Application.initialize!
-
-require File.join(Rails.root, "lib", "gitlab", "git_host")
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index be36ee6da0dfdc8d4fdfadfd0a857ce14892ba62..28323484a3744e576fea23f0d1a31bad2c00d1cc 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -25,18 +25,55 @@ app:
   # backup_keep_time: 604800      # default: 0 (forever) (in seconds)
   # disable_gravatar: true        # default: false - Disable user avatars from Gravatar.com
 
+
+#
+# 2. Auth settings
+# ==========================
+ldap: 
+  enabled: false
+  host: '_your_ldap_server'
+  base: '_the_base_where_you_search_for_users'
+  port: 636
+  uid: 'sAMAccountName'
+  method: 'ssl' # plain
+  bind_dn: '_the_full_dn_of_the_user_you_will_bind_with'
+  password: '_the_password_of_the_bind_user'
+
+omniauth:
+  # Enable ability for users
+  # to login via twitter, google ..
+  enabled: false
+
+  # IMPORTANT! 
+  # It allows user to login without having user account
+  allow_single_sign_on: false
+  block_auto_created_users: true
+
+  # Auth providers 
+  providers:
+    # - { name: 'google_oauth2', app_id: 'YOUR APP ID',
+    #     app_secret: 'YOUR APP SECRET',
+    #     args: { access_type: 'offline', approval_prompt: '' } }
+    # - { name: 'twitter', app_id: 'YOUR APP ID',
+    #     app_secret: 'YOUR APP SECRET'}
+    # - { name: 'github', app_id: 'YOUR APP ID',
+    #     app_secret: 'YOUR APP SECRET' }
+
+
 #
-# 2. Advanced settings:
+# 3. Advanced settings:
 # ==========================
 
 # Git Hosting configuration
 git_host:
   admin_uri: git@localhost:gitolite-admin
   base_path: /home/git/repositories/
-  # host: localhost
+  hooks_path: /home/git/.gitolite/hooks/
+  gitolite_admin_key: gitlab 
   git_user: git
   upload_pack: true
   receive_pack: true
+  # host: localhost
   # port: 22
 
 # Git settings
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 8165d6c2eeaf258ef6bc13a6e3cc0ac0933bff04..7a7ca43f1d0f67b103192cffec6d71f3a7f77c32 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -6,7 +6,7 @@ class Settings < Settingslogic
       self.web['protocol'] ||= web.https ? "https" : "http"
     end
 
-    def web_host 
+    def web_host
       self.web['host'] ||= 'localhost'
     end
 
@@ -14,11 +14,11 @@ class Settings < Settingslogic
       self.email['from'] ||= ("notify@" + web_host)
     end
 
-    def url 
+    def url
       self['url'] ||= build_url
-    end 
+    end
 
-    def web_port 
+    def web_port
       if web.https
         web['port'] = 443
       else
@@ -36,7 +36,7 @@ class Settings < Settingslogic
       raw_url << web_host
 
       if web_custom_port?
-        raw_url << ":#{web_port}" 
+        raw_url << ":#{web_port}"
       end
 
       raw_url
@@ -66,6 +66,10 @@ class Settings < Settingslogic
       git_host['base_path'] || '/home/git/repositories/'
     end
 
+    def git_hooks_path
+      git_host['hooks_path'] || '/home/git/share/gitolite/hooks/'
+    end
+
     def git_upload_pack
       if git_host['upload_pack'] != false
         true
@@ -98,6 +102,10 @@ class Settings < Settingslogic
       git_host['admin_uri'] || 'git@localhost:gitolite-admin'
     end
 
+    def gitolite_admin_key
+      git_host['gitolite_admin_key'] || 'gitlab'
+    end
+
     def default_projects_limit
       app['default_projects_limit'] || 10
     end
@@ -112,6 +120,22 @@ class Settings < Settingslogic
       app['backup_keep_time'] || 0
     end
 
+    def ldap_enabled?
+      ldap && ldap['enabled']
+    rescue Settingslogic::MissingSetting
+      false
+    end
+
+    def omniauth_enabled?
+      omniauth && omniauth['enabled']
+    rescue Settingslogic::MissingSetting
+      false
+    end
+
+    def omniauth_providers
+      (omniauth_enabled? && omniauth['providers']) || []
+    end
+
     def disable_gravatar?
       app['disable_gravatar'] || false
     end
diff --git a/config/initializers/5_backend.rb b/config/initializers/5_backend.rb
new file mode 100644
index 0000000000000000000000000000000000000000..85f747ac334033ad1dd464dfc2cfbb60e3da1739
--- /dev/null
+++ b/config/initializers/5_backend.rb
@@ -0,0 +1,5 @@
+# GIT over HTTP
+require Rails.root.join("lib", "gitlab", "backend", "grack_auth")
+
+# GITOLITE backend
+require Rails.root.join("lib", "gitlab", "backend", "gitolite")
diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb
index 54011ba5ea3982f3a7ee2e164be078153e6d1b58..8f3cef5a2ac769578a219ad580dd04ee461aab37 100644
--- a/config/initializers/devise.rb
+++ b/config/initializers/devise.rb
@@ -204,4 +204,21 @@ Devise.setup do |config|
   #   manager.intercept_401 = false
   #   manager.default_strategies(:scope => :user).unshift :some_external_strategy
   # end
+
+  gl = Gitlab.config
+
+  if gl.ldap_enabled?
+    config.omniauth :ldap,
+      :host     => gl.ldap['host'],
+      :base     => gl.ldap['base'],
+      :uid      => gl.ldap['uid'],
+      :port     => gl.ldap['port'],
+      :method   => gl.ldap['method'],
+      :bind_dn  => gl.ldap['bind_dn'],
+      :password => gl.ldap['password']
+  end
+
+  gl.omniauth_providers.each do |gl_provider|
+    config.omniauth gl_provider['name'].to_sym, gl_provider['app_id'], gl_provider['app_secret']
+  end
 end
diff --git a/config/initializers/kaminari_config.rb b/config/initializers/kaminari_config.rb
new file mode 100644
index 0000000000000000000000000000000000000000..3cbe9a058d7f0fc2480b692269335b4ee33ac6b2
--- /dev/null
+++ b/config/initializers/kaminari_config.rb
@@ -0,0 +1,10 @@
+Kaminari.configure do |config|
+  config.default_per_page = 20
+  config.max_per_page = 100
+  # config.window = 4
+  # config.outer_window = 0
+  # config.left = 0
+  # config.right = 0
+  # config.page_method_name = :page
+  # config.param_name = :page
+end
diff --git a/config/initializers/omniauth.rb.sample b/config/initializers/omniauth.rb.sample
deleted file mode 100644
index 6e844efde2387b722d980ef8af122fe2c7d9d3c6..0000000000000000000000000000000000000000
--- a/config/initializers/omniauth.rb.sample
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copy this file to 'omniauth.rb' and configure it as necessary.
-# The wiki has further details on configuring each provider.
-
-Devise.setup do |config|
-  # config.omniauth :github, 'APP_ID', 'APP_SECRET', :scope => 'user,public_repo'
-
-  # config.omniauth :ldap, 
-  #     :host => 'YOUR_LDAP_SERVER',
-  #     :base => 'THE_BASE_WHERE_YOU_SEARCH_FOR_USERS',
-  #     :uid => 'sAMAccountName',
-  #     :port => 389,
-  #     :method => :plain,
-  #     :bind_dn => 'THE_FULL_DN_OF_THE_USER_YOU_WILL_BIND_WITH',
-  #     :password => 'THE_PASSWORD_OF_THE_BIND_USER'
-end
diff --git a/config/initializers/resque.rb b/config/initializers/resque.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b333ceeea1ae683d5e2cff393b933b1ad9872e08
--- /dev/null
+++ b/config/initializers/resque.rb
@@ -0,0 +1,8 @@
+rails_root  = ENV['RAILS_ROOT'] || File.dirname(__FILE__) + '/../..'
+rails_env   = ENV['RAILS_ENV'] || 'development'
+config_file = File.join(rails_root, 'config', 'resque.yml')
+
+if File.exists?(config_file)
+  resque_config = YAML.load_file(config_file)
+  Resque.redis = resque_config[rails_env]
+end
diff --git a/config/resque.yml.example b/config/resque.yml.example
new file mode 100644
index 0000000000000000000000000000000000000000..cd3d487408a4cf1e817c12a2343ecfac48abd758
--- /dev/null
+++ b/config/resque.yml.example
@@ -0,0 +1,3 @@
+development: localhost:6379
+test: localhost:6379
+production: redis.example.com:6379
diff --git a/config/routes.rb b/config/routes.rb
index 97594d577a7e796b37576208246679cffe840551..cfb9bdb957ce37fe3b629acef54f66030c4b1df7 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -10,7 +10,7 @@ Gitlab::Application.routes.draw do
 
   # Optionally, enable Resque here
   require 'resque/server'
-  mount Resque::Server.new, at: '/info/resque'
+  mount Resque::Server => '/info/resque', as: 'resque'
 
   # Enable Grack support
   mount Grack::Bundle.new({
@@ -23,14 +23,14 @@ Gitlab::Application.routes.draw do
   #
   # Help
   #
-  get 'help' => 'help#index'
-  get 'help/permissions' => 'help#permissions'
-  get 'help/workflow' => 'help#workflow'
-  get 'help/api' => 'help#api'
-  get 'help/web_hooks' => 'help#web_hooks'
+  get 'help'              => 'help#index'
+  get 'help/permissions'  => 'help#permissions'
+  get 'help/workflow'     => 'help#workflow'
+  get 'help/api'          => 'help#api'
+  get 'help/web_hooks'    => 'help#web_hooks'
   get 'help/system_hooks' => 'help#system_hooks'
-  get 'help/markdown' => 'help#markdown'
-  get 'help/ssh' => 'help#ssh'
+  get 'help/markdown'     => 'help#markdown'
+  get 'help/ssh'          => 'help#ssh'
 
   #
   # Admin Area
@@ -43,23 +43,19 @@ Gitlab::Application.routes.draw do
         put :unblock
       end
     end
-    resources :projects, :constraints => { :id => /[^\/]+/ } do
+    resources :projects, constraints: { id: /[^\/]+/ } do
       member do
         get :team
         put :team_update
       end
     end
-    resources :team_members, :only => [:edit, :update, :destroy]
-    get 'mailer/preview_note'
-    get 'mailer/preview_user_new'
-    get 'mailer/preview_issue_new'
-
-    resources :hooks, :only => [:index, :create, :destroy] do
+    resources :team_members, only: [:edit, :update, :destroy]
+    resources :hooks, only: [:index, :create, :destroy] do
       get :test
     end
-    resource :logs
-    resource :resque, :controller => 'resque'
-    root :to => "dashboard#index"
+    resource :logs, only: [:show]
+    resource :resque, controller: 'resque', only: [:show]
+    root to: "dashboard#index"
   end
 
   get "errors/githost"
@@ -67,38 +63,39 @@ Gitlab::Application.routes.draw do
   #
   # Profile Area
   #
-  get "profile/password", :to => "profile#password"
-  put "profile/password", :to => "profile#password_update"
-  get "profile/token", :to => "profile#token"
-  put "profile/reset_private_token", :to => "profile#reset_private_token"
-  get "profile", :to => "profile#show"
-  get "profile/design", :to => "profile#design"
-  put "profile/update", :to => "profile#update"
+  get "profile/account"             => "profile#account"
+  get "profile/history"             => "profile#history"
+  put "profile/password"            => "profile#password_update"
+  get "profile/token"               => "profile#token"
+  put "profile/reset_private_token" => "profile#reset_private_token"
+  get "profile"                     => "profile#show"
+  get "profile/design"              => "profile#design"
+  put "profile/update"              => "profile#update"
+
   resources :keys
 
   #
   # Dashboard Area
   #
-  get "dashboard", :to => "dashboard#index"
-  get "dashboard/issues", :to => "dashboard#issues"
-  get "dashboard/merge_requests", :to => "dashboard#merge_requests"
+  get "dashboard"                => "dashboard#index"
+  get "dashboard/issues"         => "dashboard#issues"
+  get "dashboard/merge_requests" => "dashboard#merge_requests"
 
-  resources :projects, :constraints => { :id => /[^\/]+/ }, :only => [:new, :create]
+  resources :projects, constraints: { id: /[^\/]+/ }, only: [:new, :create]
 
-  devise_for :users, :controllers => { :omniauth_callbacks => :omniauth_callbacks }
+  devise_for :users, controllers: { omniauth_callbacks: :omniauth_callbacks }
 
   #
   # Project Area
   #
-  resources :projects, :constraints => { :id => /[^\/]+/ }, :except => [:new, :create, :index], :path => "/" do
+  resources :projects, constraints: { id: /[^\/]+/ }, except: [:new, :create, :index], path: "/" do
     member do
-      get "team"
       get "wall"
       get "graph"
       get "files"
     end
 
-    resources :wikis, :only => [:show, :edit, :destroy, :create] do
+    resources :wikis, only: [:show, :edit, :destroy, :create] do
       collection do
         get :pages
       end
@@ -117,46 +114,45 @@ Gitlab::Application.routes.draw do
     end
 
     resources :deploy_keys
-    resources :protected_branches, :only => [:index, :create, :destroy]
+    resources :protected_branches, only: [:index, :create, :destroy]
 
-    resources :refs, :only => [], :path => "/" do
+    resources :refs, only: [], path: "/" do
       collection do
         get "switch"
       end
 
       member do
-        get "tree", :constraints => { :id => /[a-zA-Z.\/0-9_\-]+/ }
-        get "logs_tree", :constraints => { :id => /[a-zA-Z.\/0-9_\-]+/ }
+        get "tree",      constraints: { id: /[a-zA-Z.\/0-9_\-]+/ }
+        get "logs_tree", constraints: { id: /[a-zA-Z.\/0-9_\-]+/ }
 
         get "blob",
-          :constraints => {
-            :id => /[a-zA-Z.0-9\/_\-]+/,
-            :path => /.*/
+          constraints: {
+            id:   /[a-zA-Z.0-9\/_\-]+/,
+            path: /.*/
           }
 
-
         # tree viewer
         get "tree/:path" => "refs#tree",
-          :as => :tree_file,
-          :constraints => {
-            :id => /[a-zA-Z.0-9\/_\-]+/,
-            :path => /.*/
+          as: :tree_file,
+          constraints: {
+            id:   /[a-zA-Z.0-9\/_\-]+/,
+            path: /.*/
           }
 
         # tree viewer
         get "logs_tree/:path" => "refs#logs_tree",
-          :as => :logs_file,
-          :constraints => {
-            :id => /[a-zA-Z.0-9\/_\-]+/,
-            :path => /.*/
+          as: :logs_file,
+          constraints: {
+            id:   /[a-zA-Z.0-9\/_\-]+/,
+            path: /.*/
           }
 
         # blame
         get "blame/:path" => "refs#blame",
-          :as => :blame_file,
-          :constraints => {
-            :id => /[a-zA-Z.0-9\/_\-]+/,
-            :path => /.*/
+          as: :blame_file,
+          constraints: {
+            id:   /[a-zA-Z.0-9\/_\-]+/,
+            path: /.*/
           }
       end
     end
@@ -181,7 +177,7 @@ Gitlab::Application.routes.draw do
       end
     end
 
-    resources :hooks, :only => [:index, :create, :destroy] do
+    resources :hooks, only: [:index, :create, :destroy] do
       member do
         get :test
       end
@@ -195,20 +191,24 @@ Gitlab::Application.routes.draw do
         get :patch
       end
     end
+    resources :team, controller: 'team_members', only: [:index]
     resources :team_members
     resources :milestones
+    resources :labels, only: [:index]
     resources :issues do
+
       collection do
         post  :sort
         post  :bulk_update
         get   :search
       end
     end
-    resources :notes, :only => [:index, :create, :destroy] do
+    resources :notes, only: [:index, :create, :destroy] do
       collection do
         post :preview
       end
     end
   end
-  root :to => "dashboard#index"
+
+  root to: "dashboard#index"
 end
diff --git a/config/unicorn.rb.orig b/config/unicorn.rb.example
similarity index 100%
rename from config/unicorn.rb.orig
rename to config/unicorn.rb.example
diff --git a/db/fixtures/test/001_repo.rb b/db/fixtures/test/001_repo.rb
index ebf005a14679e873e3c11f6eaa55e32a40581882..67d4e7bfbde5c4c50d8145d58181da64717c2e5a 100644
--- a/db/fixtures/test/001_repo.rb
+++ b/db/fixtures/test/001_repo.rb
@@ -1,15 +1,23 @@
-# create tmp dir if not exist
-tmp_dir = File.join(Rails.root, "tmp")
-Dir.mkdir(tmp_dir) unless File.exists?(tmp_dir)
-
-# Create dir for test repo
-repo_dir = File.join(Rails.root, "tmp", "tests")
-Dir.mkdir(repo_dir) unless File.exists?(repo_dir)
-
-`cp spec/seed_project.tar.gz tmp/tests/`
-Dir.chdir(repo_dir)
-`tar -xf seed_project.tar.gz`
-3.times do |i|
-`cp -r gitlabhq/ gitlabhq_#{i}/`
-puts "Unpacked seed repo - tmp/tests/gitlabhq_#{i}"
+require 'fileutils'
+
+print "Unpacking seed repository..."
+
+SEED_REPO = 'seed_project.tar.gz'
+REPO_PATH = File.join(Rails.root, 'tmp', 'repositories')
+
+# Make whatever directories we need to make
+FileUtils.mkdir_p(REPO_PATH)
+
+# Copy the archive to the repo path
+FileUtils.cp(File.join(Rails.root, 'spec', SEED_REPO), REPO_PATH)
+
+# chdir to the repo path
+FileUtils.cd(REPO_PATH) do
+  # Extract the archive
+  `tar -xf #{SEED_REPO}`
+
+  # Remove the copy
+  FileUtils.rm(SEED_REPO)
 end
+
+puts ' done.'
diff --git a/db/migrate/20120905043334_set_default_branch_default_to_nil.rb b/db/migrate/20120905043334_set_default_branch_default_to_nil.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f5956fe875184473481fe8673e57a9bab967c95e
--- /dev/null
+++ b/db/migrate/20120905043334_set_default_branch_default_to_nil.rb
@@ -0,0 +1,12 @@
+class SetDefaultBranchDefaultToNil < ActiveRecord::Migration
+  def up
+    # Set the default_branch to allow nil, and default it to nil
+    change_column_null(:projects, :default_branch, true)
+    change_column_default(:projects, :default_branch, nil)
+  end
+
+  def down
+    change_column_null(:projects, :default_branch, false)
+    change_column_default(:projects, :default_branch, 'master')
+  end
+end
diff --git a/db/pkey.example b/db/pkey.example
deleted file mode 100644
index ae045772430fe4b452a7c592d5f91083d19d7cef..0000000000000000000000000000000000000000
--- a/db/pkey.example
+++ /dev/null
@@ -1,3 +0,0 @@
-AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
-596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
-soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=
diff --git a/db/schema.rb b/db/schema.rb
index 46461e44aad59d13087ad2fcd9a62075e3e56d01..00bb55234af668359c6f26365cbdb68a212644fe 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
 #
 # It's strongly recommended to check this file into your version control system.
 
-ActiveRecord::Schema.define(:version => 20120729131232) do
+ActiveRecord::Schema.define(:version => 20120905043334) do
 
   create_table "events", :force => true do |t|
     t.string   "target_type"
@@ -98,16 +98,16 @@ ActiveRecord::Schema.define(:version => 20120729131232) do
     t.string   "name"
     t.string   "path"
     t.text     "description"
-    t.datetime "created_at",                                   :null => false
-    t.datetime "updated_at",                                   :null => false
-    t.boolean  "private_flag",           :default => true,     :null => false
+    t.datetime "created_at",                               :null => false
+    t.datetime "updated_at",                               :null => false
+    t.boolean  "private_flag",           :default => true, :null => false
     t.string   "code"
     t.integer  "owner_id"
-    t.string   "default_branch",         :default => "master", :null => false
-    t.boolean  "issues_enabled",         :default => true,     :null => false
-    t.boolean  "wall_enabled",           :default => true,     :null => false
-    t.boolean  "merge_requests_enabled", :default => true,     :null => false
-    t.boolean  "wiki_enabled",           :default => true,     :null => false
+    t.string   "default_branch"
+    t.boolean  "issues_enabled",         :default => true, :null => false
+    t.boolean  "wall_enabled",           :default => true, :null => false
+    t.boolean  "merge_requests_enabled", :default => true, :null => false
+    t.boolean  "wiki_enabled",           :default => true, :null => false
   end
 
   create_table "protected_branches", :force => true do |t|
diff --git a/doc/api/README.md b/doc/api/README.md
index e01119661f08c2343429ebca9e09c7dff8ff1e26..36a36f8f6a4dcea55ee8894fc07207cbe913b54f 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -1,10 +1,8 @@
-# Gitlab API
+# GitLab API
 
-All API requests require authentication. You need to pass `private_token` parameter to authenticate.
+All API requests require authentication. You need to pass a `private_token` parameter to authenticate. You can find or reset your private token in your profile.
 
-To get or reset your token visit your profile.
-
-If no or invalid `private_token` provided error message will be returned with status code 401:
+If no, or an invalid, `private_token` is provided then an error message will be returned with status code 401:
 
 ```json
 {
@@ -12,10 +10,9 @@ If no or invalid `private_token` provided error message will be returned with st
 }
 ```
 
-API requests should be prefixed with `api` and the API version.
-API version is equal to Gitlab major version number and defined in `lib/api.rb`.
+API requests should be prefixed with `api` and the API version. The API version is equal to the GitLab major version number, which is defined in `lib/api.rb`.
 
-Example of valid API request:
+Example of a valid API request:
 
 ```
 GET http://example.com/api/v2/projects?private_token=QVy1PB7sTxfy4pqfZM1U
@@ -23,8 +20,19 @@ GET http://example.com/api/v2/projects?private_token=QVy1PB7sTxfy4pqfZM1U
 
 The API uses JSON to serialize data. You don't need to specify `.json` at the end of API URL.
 
+#### Pagination
+
+When listing resources you can pass the following parameters:
+
++ `page` (default: `1`) - page number
++ `per_page` (default: `20`, max: `100`) - how many items to list per page
+
 ## Contents
 
 + [Users](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/users.md)
++ [Session](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/session.md)
 + [Projects](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/projects.md)
++ [Snippets](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/snippets.md)
++ [Repositories](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/repositories.md)
 + [Issues](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/issues.md)
++ [Milestones](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/milestones.md)
diff --git a/doc/api/milestones.md b/doc/api/milestones.md
new file mode 100644
index 0000000000000000000000000000000000000000..f68d8eb7d58ebb6802dfd189b071d709d0aa6b69
--- /dev/null
+++ b/doc/api/milestones.md
@@ -0,0 +1,57 @@
+## List project milestones
+
+Get a list of project milestones.
+
+```
+GET /projects/:id/milestones
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
+
+## Single milestone
+
+Get a single project milestone.
+
+```
+GET /projects/:id/milestones/:milestone_id
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
++ `milestone_id` (required) - The ID of a project milestone
+
+## New milestone
+
+Create a new project milestone.
+
+```
+POST /projects/:id/milestones
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
++ `milestone_id` (required) - The ID of a project milestone
++ `title` (required) - The title of an milestone
++ `description` (optional) - The description of the milestone
++ `due_date` (optional) - The due date of the milestone
+
+## Edit milestone
+
+Update an existing project milestone.
+
+```
+PUT /projects/:id/milestones/:milestone_id
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
++ `milestone_id` (required) - The ID of a project milestone
++ `title` (optional) - The title of a milestone
++ `description` (optional) - The description of a milestone
++ `due_date` (optional) - The due date of the milestone
++ `closed` (optional) - The status of the milestone
diff --git a/doc/api/projects.md b/doc/api/projects.md
index ead310035121ba89142a83d1fcf90cb1692a7bc8..d06a41c2d744ae87d3a03b26848a13a20f98fa8f 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -1,6 +1,6 @@
 ## List projects
 
-Get a list of authenticated user's projects.
+Get a list of projects owned by the authenticated user.
 
 ```
 GET /projects
@@ -55,7 +55,7 @@ GET /projects
 
 ## Single project
 
-Get an authenticated user's project.
+Get a specific project, identified by project ID, which is owned by the authentication user.
 
 ```
 GET /projects/:id
@@ -89,235 +89,153 @@ Parameters:
 }
 ```
 
-## Project repository branches
+## Create project
 
-Get a list of project repository branches sorted by name alphabetically.
+Create new project owned by user
 
 ```
-GET /projects/:id/repository/branches
+POST /projects
 ```
 
 Parameters:
 
-+ `id` (required) - The ID or code name of a project
++ `name` (required) - new project name
++ `code` (optional) - new project code, uses project name if not set
++ `path` (optional) - new project path, uses project name if not set
++ `description` (optional) - short project description
++ `default_branch` (optional) - 'master' by default
++ `issues_enabled` (optional) - enabled by default
++ `wall_enabled` (optional) - enabled by default
++ `merge_requests_enabled` (optional) - enabled by default
++ `wiki_enabled` (optional) - enabled by default
 
-```json
-[
-  {
-    "name": "master",
-    "commit": {
-      "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
-      "parents": [
-        {
-          "id": "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
-        }
-      ],
-      "tree": "46e82de44b1061621357f24c05515327f2795a95",
-      "message": "add projects API",
-      "author": {
-        "name": "John Smith",
-        "email": "john@example.com"
-      },
-      "committer": {
-        "name": "John Smith",
-        "email": "john@example.com"
-      },
-      "authored_date": "2012-06-27T05:51:39-07:00",
-      "committed_date": "2012-06-28T03:44:20-07:00"
-    }
-  }
-]
-```
+Will return created project with status `201 Created` on success, or `404 Not
+found` on fail.
+
+## List project team members
 
-Get a single project repository branch.
+Get a list of project team members.
 
 ```
-GET /projects/:id/repository/branches/:branch
+GET /projects/:id/members
 ```
 
 Parameters:
 
 + `id` (required) - The ID or code name of a project
-+ `branch` (required) - The name of the branch
-
-```json
-{
-  "name": "master",
-  "commit": {
-    "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
-    "parents": [
-      {
-        "id": "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
-      }
-    ],
-    "tree": "46e82de44b1061621357f24c05515327f2795a95",
-    "message": "add projects API",
-    "author": {
-      "name": "John Smith",
-      "email": "john@example.com"
-    },
-    "committer": {
-      "name": "John Smith",
-      "email": "john@example.com"
-    },
-    "authored_date": "2012-06-27T05:51:39-07:00",
-    "committed_date": "2012-06-28T03:44:20-07:00"
-  }
-}
-```
 
-## Project repository tags
+## Get project team member
 
-Get a list of project repository tags sorted by name in reverse alphabetical order.
+Get a project team member.
 
 ```
-GET /projects/:id/repository/tags
+GET /projects/:id/members/:user_id
 ```
 
 Parameters:
 
 + `id` (required) - The ID or code name of a project
++ `user_id` (required) - The ID of a user
 
 ```json
-[
-  {
-    "name": "v1.0.0",
-    "commit": {
-      "id": "2695effb5807a22ff3d138d593fd856244e155e7",
-      "parents": [
-
-      ],
-      "tree": "38017f2f189336fe4497e9d230c5bb1bf873f08d",
-      "message": "Initial commit",
-      "author": {
-        "name": "John Smith",
-        "email": "john@example.com"
-      },
-      "committer": {
-        "name": "Jack Smith",
-        "email": "jack@example.com"
-      },
-      "authored_date": "2012-05-28T04:42:42-07:00",
-      "committed_date": "2012-05-28T04:42:42-07:00"
-    }
-  }
-]
-```
-
-# Project Snippets
-
-## List snippets
+{
 
-Not implemented.
+  "id": 1,
+  "email": "john@example.com",
+  "name": "John Smith",
+  "blocked": false,
+  "created_at": "2012-05-23T08:00:58Z",
+  "access_level": 40
+}
+```
 
-## Single snippet
+## Add project team member
 
-Get a project snippet.
+Add a user to a project team.
 
 ```
-GET /projects/:id/snippets/:snippet_id
+POST /projects/:id/members
 ```
 
 Parameters:
 
 + `id` (required) - The ID or code name of a project
-+ `snippet_id` (required) - The ID of a project's snippet
++ `user_id` (required) - The ID of a user to add
++ `access_level` (required) - Project access level
 
-```json
-{
-  "id": 1,
-  "title": "test",
-  "file_name": "add.rb",
-  "author": {
-    "id": 1,
-    "email": "john@example.com",
-    "name": "John Smith",
-    "blocked": false,
-    "created_at": "2012-05-23T08:00:58Z"
-  },
-  "expires_at": null,
-  "updated_at": "2012-06-28T10:52:04Z",
-  "created_at": "2012-06-28T10:52:04Z"
-}
-```
+Will return status `201 Created` on success, or `404 Not found` on fail.
 
-## Snippet content
+## Edit project team member
 
-Get a raw project snippet.
+Update project team member to specified access level.
 
 ```
-GET /projects/:id/snippets/:snippet_id/raw
+PUT /projects/:id/members/:user_id
 ```
 
 Parameters:
 
 + `id` (required) - The ID or code name of a project
-+ `snippet_id` (required) - The ID of a project's snippet
++ `user_id` (required) - The ID of a team member
++ `access_level` (required) - Project access level
+
+Will return status `200 OK` on success, or `404 Not found` on fail.
 
-## New snippet
+## Remove project team member
 
-Create a new project snippet.
+Removes user from project team.
 
 ```
-POST /projects/:id/snippets
+DELETE /projects/:id/members/:user_id
 ```
 
 Parameters:
 
 + `id` (required) - The ID or code name of a project
-+ `title` (required) - The title of a snippet
-+ `file_name` (required) - The name of a snippet file
-+ `lifetime` (optional) - The expiration date of a snippet
-+ `code` (required) - The content of a snippet
++ `user_id` (required) - The ID of a team member
 
-Will return created snippet with status `201 Created` on success, or `404 Not found` on fail.
+Status code `200` will be returned on success.
 
-## Edit snippet
+## Get project hooks
 
-Update an existing project snippet.
+Get hooks for project
 
 ```
-PUT /projects/:id/snippets/:snippet_id
+GET /projects/:id/hooks
 ```
 
 Parameters:
 
 + `id` (required) - The ID or code name of a project
-+ `snippet_id` (required) - The ID of a project's snippet
-+ `title` (optional) - The title of a snippet
-+ `file_name` (optional) - The name of a snippet file
-+ `lifetime` (optional) - The expiration date of a snippet
-+ `code` (optional) - The content of a snippet
 
-Will return updated snippet with status `200 OK` on success, or `404 Not found` on fail.
+Will return hooks with status `200 OK` on success, or `404 Not found` on fail.
 
-## Delete snippet
+## Add project hook
 
-Delete existing project snippet.
+Add hook to project
 
 ```
-DELETE /projects/:id/snippets/:snippet_id
+POST /projects/:id/hooks
 ```
 
 Parameters:
 
 + `id` (required) - The ID or code name of a project
-+ `snippet_id` (required) - The ID of a project's snippet
++ `url` (required) - The hook URL
 
-Status code `200` will be returned on success.
+Will return status `201 Created` on success, or `404 Not found` on fail.
 
-## Raw blob content
+## Delete project hook
 
-Get the raw file contents for a file.
+Delete hook from project
 
 ```
-GET /projects/:id/repository/commits/:sha/blob
+DELETE /projects/:id/hooks
 ```
 
 Parameters:
 
 + `id` (required) - The ID or code name of a project
-+ `sha` (required) - The commit or branch name
-+ `filepath` (required) - The path the file 
++ `hook_id` (required) - The ID of hook to delete
 
-Will return the raw file contents.
+Will return status `200 OK` on success, or `404 Not found` on fail.
diff --git a/doc/api/repositories.md b/doc/api/repositories.md
new file mode 100644
index 0000000000000000000000000000000000000000..487ad9b27184b5dcba1a9e12adbf9c8c40318515
--- /dev/null
+++ b/doc/api/repositories.md
@@ -0,0 +1,166 @@
+## Project repository branches
+
+Get a list of repository branches from a project, sorted by name alphabetically.
+
+```
+GET /projects/:id/repository/branches
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
+
+```json
+[
+  {
+    "name": "master",
+    "commit": {
+      "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
+      "parents": [
+        {
+          "id": "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
+        }
+      ],
+      "tree": "46e82de44b1061621357f24c05515327f2795a95",
+      "message": "add projects API",
+      "author": {
+        "name": "John Smith",
+        "email": "john@example.com"
+      },
+      "committer": {
+        "name": "John Smith",
+        "email": "john@example.com"
+      },
+      "authored_date": "2012-06-27T05:51:39-07:00",
+      "committed_date": "2012-06-28T03:44:20-07:00"
+    }
+  }
+]
+```
+
+## Project repository branch
+
+Get a single project repository branch.
+
+```
+GET /projects/:id/repository/branches/:branch
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
++ `branch` (required) - The name of the branch
+
+```json
+{
+  "name": "master",
+  "commit": {
+    "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
+    "parents": [
+      {
+        "id": "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
+      }
+    ],
+    "tree": "46e82de44b1061621357f24c05515327f2795a95",
+    "message": "add projects API",
+    "author": {
+      "name": "John Smith",
+      "email": "john@example.com"
+    },
+    "committer": {
+      "name": "John Smith",
+      "email": "john@example.com"
+    },
+    "authored_date": "2012-06-27T05:51:39-07:00",
+    "committed_date": "2012-06-28T03:44:20-07:00"
+  }
+}
+```
+
+## Project repository tags
+
+Get a list of repository tags from a project, sorted by name in reverse alphabetical order.
+
+```
+GET /projects/:id/repository/tags
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
+
+```json
+[
+  {
+    "name": "v1.0.0",
+    "commit": {
+      "id": "2695effb5807a22ff3d138d593fd856244e155e7",
+      "parents": [
+
+      ],
+      "tree": "38017f2f189336fe4497e9d230c5bb1bf873f08d",
+      "message": "Initial commit",
+      "author": {
+        "name": "John Smith",
+        "email": "john@example.com"
+      },
+      "committer": {
+        "name": "Jack Smith",
+        "email": "jack@example.com"
+      },
+      "authored_date": "2012-05-28T04:42:42-07:00",
+      "committed_date": "2012-05-28T04:42:42-07:00"
+    }
+  }
+]
+```
+
+## Project repository commits
+
+Get a list of repository commits in a project.
+
+```
+GET /projects/:id/repository/commits
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
++ `ref_name` (optional) - The name of a repository branch or tag
+
+```json
+[
+  {
+    "id": "ed899a2f4b50b4370feeea94676502b42383c746",
+    "short_id": "ed899a2f4b5",
+    "title": "Replace sanitize with escape once",
+    "author_name": "Dmitriy Zaporozhets",
+    "author_email": "dzaporozhets@sphereconsultinginc.com",
+    "created_at": "2012-09-20T11:50:22+03:00"
+  },
+  {
+    "id": "6104942438c14ec7bd21c6cd5bd995272b3faff6",
+    "short_id": "6104942438c",
+    "title": "Sanitize for network graph",
+    "author_name": "randx",
+    "author_email": "dmitriy.zaporozhets@gmail.com",
+    "created_at": "2012-09-20T09:06:12+03:00"
+  }
+]
+```
+
+## Raw blob content
+
+Get the raw file contents for a file.
+
+```
+GET /projects/:id/repository/commits/:sha/blob
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
++ `sha` (required) - The commit or branch name
++ `filepath` (required) - The path the file
+
+Will return the raw file contents.
diff --git a/doc/api/session.md b/doc/api/session.md
new file mode 100644
index 0000000000000000000000000000000000000000..9fdbeb439a4047c52c84a9b0702e23d7386f65ef
--- /dev/null
+++ b/doc/api/session.md
@@ -0,0 +1,22 @@
+Login to get private token
+
+```
+POST /session
+```
+
+Parameters:
+
++ `email` (required) - The email of user
++ `password` (required) - Valid password
+
+
+```json
+{
+  "id": 1,
+  "email": "john@example.com",
+  "name": "John Smith",
+  "private_token": "dd34asd13as",
+  "created_at": "2012-05-23T08:00:58Z",
+  "blocked": true
+}
+```
diff --git a/doc/api/snippets.md b/doc/api/snippets.md
new file mode 100644
index 0000000000000000000000000000000000000000..0cd29ce530b37f87ab1dfb2eb7b87e8c993272b5
--- /dev/null
+++ b/doc/api/snippets.md
@@ -0,0 +1,100 @@
+## List snippets
+
+Not implemented.
+
+## Single snippet
+
+Get a project snippet.
+
+```
+GET /projects/:id/snippets/:snippet_id
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
++ `snippet_id` (required) - The ID of a project's snippet
+
+```json
+{
+  "id": 1,
+  "title": "test",
+  "file_name": "add.rb",
+  "author": {
+    "id": 1,
+    "email": "john@example.com",
+    "name": "John Smith",
+    "blocked": false,
+    "created_at": "2012-05-23T08:00:58Z"
+  },
+  "expires_at": null,
+  "updated_at": "2012-06-28T10:52:04Z",
+  "created_at": "2012-06-28T10:52:04Z"
+}
+```
+
+## Snippet content
+
+Get a raw project snippet.
+
+```
+GET /projects/:id/snippets/:snippet_id/raw
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
++ `snippet_id` (required) - The ID of a project's snippet
+
+## New snippet
+
+Create a new project snippet.
+
+```
+POST /projects/:id/snippets
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
++ `title` (required) - The title of a snippet
++ `file_name` (required) - The name of a snippet file
++ `lifetime` (optional) - The expiration date of a snippet
++ `code` (required) - The content of a snippet
+
+Will return created snippet with status `201 Created` on success, or `404 Not found` on fail.
+
+## Edit snippet
+
+Update an existing project snippet.
+
+```
+PUT /projects/:id/snippets/:snippet_id
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
++ `snippet_id` (required) - The ID of a project's snippet
++ `title` (optional) - The title of a snippet
++ `file_name` (optional) - The name of a snippet file
++ `lifetime` (optional) - The expiration date of a snippet
++ `code` (optional) - The content of a snippet
+
+Will return updated snippet with status `200 OK` on success, or `404 Not found` on fail.
+
+## Delete snippet
+
+Delete existing project snippet.
+
+```
+DELETE /projects/:id/snippets/:snippet_id
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
++ `snippet_id` (required) - The ID of a project's snippet
+
+Status code `200` will be returned on success.
+
diff --git a/doc/api/users.md b/doc/api/users.md
index b9b04dc5399ae03a3120ee74df3b6814518b07c5..4f806b145d154ed2f51707038317cfc141cd1c4e 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -88,3 +88,81 @@ GET /user
   "theme_id": 1
 }
 ```
+
+## List SSH keys
+
+Get a list of currently authenticated user's SSH keys.
+
+```
+GET /user/keys
+```
+
+```json
+[
+  {
+    "id": 1,
+    "title" : "Public key"
+    "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
+      596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
+      soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
+  },
+  {
+    "id": 3,
+    "title" : "Another Public key"
+    "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
+      596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
+      soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
+  }
+]
+```
+
+## Single SSH key
+
+Get a single key.
+
+```
+GET /user/keys/:id
+```
+
+Parameters:
+
++ `id` (required) - The ID of an SSH key
+
+```json
+{
+  "id": 1,
+  "title" : "Public key"
+  "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
+      596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
+      soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
+}
+```
+## Add SSH key
+
+Create new key owned by currently authenticated user
+
+```
+POST /user/keys
+```
+
+Parameters:
+
++ `title` (required) - new SSH Key's title
++ `key` (required) - new SSH key
+
+Will return created key with status `201 Created` on success, or `404 Not
+found` on fail.
+
+## Delete SSH key
+
+Delete key owned by currently authenticated user
+
+```
+DELETE /user/keys/:id
+```
+
+Parameters:
+
++ `id` (required) - SSH key ID
+
+Will return `200 OK` on success, or `404 Not Found` on fail.
diff --git a/doc/debian_ubuntu.sh b/doc/debian_ubuntu.sh
deleted file mode 100644
index a0b4710b5ebcc023ed2794f387297a0691f3aac6..0000000000000000000000000000000000000000
--- a/doc/debian_ubuntu.sh
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/bin/sh
-
-sudo apt-get update
-sudo apt-get upgrade
-
-sudo apt-get install -y git git-core wget curl gcc checkinstall libxml2-dev libxslt-dev sqlite3 libsqlite3-dev libcurl4-openssl-dev libreadline-gplv2-dev libc6-dev libssl-dev libmysql++-dev make build-essential zlib1g-dev libicu-dev redis-server openssh-server python-dev python-pip libyaml-dev postfix
-
-wget http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-p194.tar.gz
-tar xfvz ruby-1.9.3-p194.tar.gz
-cd ruby-1.9.3-p194
-./configure
-make
-sudo make install
-
-sudo adduser \
-  --system \
-  --shell /bin/sh \
-  --gecos 'git version control' \
-  --group \
-  --disabled-password \
-  --home /home/git \
-  git
-
-sudo adduser --disabled-login --gecos 'gitlab system' gitlab
-
-sudo usermod -a -G git gitlab
-
-sudo -H -u gitlab ssh-keygen -q -N '' -t rsa -f /home/gitlab/.ssh/id_rsa
-
-cd /home/git
-sudo -H -u git git clone git://github.com/gitlabhq/gitolite /home/git/gitolite
-
-sudo -u git -H sh -c "PATH=/home/git/bin:$PATH; /home/git/gitolite/src/gl-system-install"
-sudo cp /home/gitlab/.ssh/id_rsa.pub /home/git/gitlab.pub
-sudo chmod 777 /home/git/gitlab.pub
-
-sudo -u git -H sed -i 's/0077/0007/g' /home/git/share/gitolite/conf/example.gitolite.rc
-sudo -u git -H sh -c "PATH=/home/git/bin:$PATH; gl-setup -q /home/git/gitlab.pub"
-
-sudo chmod -R g+rwX /home/git/repositories/
-sudo chown -R git:git /home/git/repositories/
-
-sudo -u gitlab -H git clone git@localhost:gitolite-admin.git /tmp/gitolite-admin
-sudo rm -rf /tmp/gitolite-admin
diff --git a/doc/development.md b/doc/development.md
new file mode 100644
index 0000000000000000000000000000000000000000..67bcb8e1c9605c2b0718a4fff5be8b6b93afb78e
--- /dev/null
+++ b/doc/development.md
@@ -0,0 +1,45 @@
+## Development tips: 
+
+### Start application in development mode
+
+#### 1. Via foreman 
+
+    bundle exec foreman -p 3000
+
+#### 2. Via gitlab cli
+
+    ./gitlab start
+
+#### 3. Manually
+
+   bundle exec rails s
+   bundle exec rake environment resque:work QUEUE=* VVERBOSE=1
+
+
+### Run tests: 
+ 
+#### 1. Packages
+
+    # ubuntu
+    sudo apt-get install libqt4-dev libqtwebkit-dev
+    sudo apt-get install xvfb
+   
+    # Mac 
+    brew install qt
+    brew install xvfb
+
+#### 2. DB & seeds
+
+    bundle exec rake db:setup RAILS_ENV=test
+    bundle exec rake db:seed_fu RAILS_ENV=test
+
+###  3. Run Tests
+
+    # All in one
+    bundle exec rake gitlab:test
+    
+    # Rspec 
+    bundle exec rake spec
+    
+    # Spinach
+    bundle exec rake spinach
diff --git a/doc/installation.md b/doc/installation.md
index 2da63ae8ba3d9009fb8da20e83951134e6a484e0..865cde3cc412253b5a00188a64967493dd8e0ace 100644
--- a/doc/installation.md
+++ b/doc/installation.md
@@ -20,7 +20,7 @@ You might have some luck using these, but no guarantees:
  - MacOS X
  - FreeBSD
 
-Gitlab does **not** run on Windows and we have no plans of making Gitlab compatible.
+GitLab does **not** run on Windows and we have no plans of making GitLab compatible.
 
 ## This installation guide created for Debian/Ubuntu and properly tested.
 
@@ -28,21 +28,21 @@ The installation consists of 6 steps:
 
 1. Install packages / dependencies
 2. Install ruby
-3. Install gitolite
-4. Install and configure Gitlab.
+3. Install Gitolite
+4. Install and configure GitLab.
 5. Start the web front-end
 6. Start a Resque worker (for background processing)
 
 ### IMPORTANT
 
-Please make sure you have followed all the steps below before posting to the mailinglist with installation and configuration questions.
+Please make sure you have followed all the steps below before posting to the mailing list with installation and configuration questions.
 
-Only create a Github Issue if you want a specific part of this installation guide updated.
+Only create a GitHub Issue if you want a specific part of this installation guide updated.
 
 Also read the [Read this before you submit an issue](https://github.com/gitlabhq/gitlabhq/wiki/Read-this-before-you-submit-an-issue) wiki page.
 
 > - - -
-> First 3 steps can be easily skipped with simply install script:
+> The first 3 steps of this guide can be easily skipped by executing an install script:
 >
 >     # Install curl and sudo
 >     apt-get install curl sudo
@@ -61,7 +61,11 @@ Also read the [Read this before you submit an issue](https://github.com/gitlabhq
 
 # 1. Install packages
 
-*Keep in mind that `sudo` is not installed for debian by default. You should install it with as root:*     **apt-get update && apt-get upgrade && apt-get install sudo**
+*Keep in mind that `sudo` is not installed on Debian by default. You should install it as root:*
+
+    apt-get update && apt-get upgrade && apt-get install sudo
+
+Now install the required packages:
 
     sudo apt-get update
     sudo apt-get upgrade
@@ -71,7 +75,7 @@ Also read the [Read this before you submit an issue](https://github.com/gitlabhq
     # If you want to use MySQL:
     sudo apt-get install -y mysql-server mysql-client libmysqlclient-dev
 
-# 2. Install ruby
+# 2. Install Ruby
 
     wget http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-p194.tar.gz
     tar xfvz ruby-1.9.3-p194.tar.gz
@@ -80,7 +84,7 @@ Also read the [Read this before you submit an issue](https://github.com/gitlabhq
     make
     sudo make install
 
-# 3. Install gitolite
+# 3. Install Gitolite
 
 Create user for git:
 
@@ -93,12 +97,12 @@ Create user for git:
       --home /home/git \
       git
 
-Create user for gitlab:
+Create user for GitLab:
 
     # ubuntu/debian
     sudo adduser --disabled-login --gecos 'gitlab system' gitlab
 
-Add your user to git group:
+Add your user to the `git` group:
 
     sudo usermod -a -G git gitlab
 
@@ -106,20 +110,23 @@ Generate key:
 
     sudo -H -u gitlab ssh-keygen -q -N '' -t rsa -f /home/gitlab/.ssh/id_rsa
 
-Get gitolite source code:
+Clone GitLab's fork of the Gitolite source code:
 
     cd /home/git
-    sudo -H -u git git clone git://github.com/gitlabhq/gitolite /home/git/gitolite
+    sudo -H -u git git clone -b gl-v304 https://github.com/gitlabhq/gitolite.git /home/git/gitolite
 
 Setup:
 
+    cd /home/git
+    sudo -u git -H mkdir bin
     sudo -u git sh -c 'echo -e "PATH=\$PATH:/home/git/bin\nexport PATH" >> /home/git/.profile'
-    sudo -u git -H sh -c "PATH=/home/git/bin:$PATH; /home/git/gitolite/src/gl-system-install"
+    sudo -u git sh -c 'gitolite/install -ln /home/git/bin'
+
     sudo cp /home/gitlab/.ssh/id_rsa.pub /home/git/gitlab.pub
     sudo chmod 0444 /home/git/gitlab.pub
 
-    sudo -u git -H sed -i 's/0077/0007/g' /home/git/share/gitolite/conf/example.gitolite.rc
-    sudo -u git -H sh -c "PATH=/home/git/bin:$PATH; gl-setup -q /home/git/gitlab.pub"
+    sudo -u git -H sh -c "PATH=/home/git/bin:$PATH; gitolite setup -pk /home/git/gitlab.pub"
+    sudo -u git -H sed -i 's/0077/0007/g' /home/git/.gitolite.rc
 
 Permissions:
 
@@ -135,23 +142,30 @@ Permissions:
     # if succeed  you can remove it
     sudo rm -rf /tmp/gitolite-admin
 
-**IMPORTANT! If you cant clone `gitolite-admin` repository - DONT PROCEED INSTALLATION**
+**IMPORTANT! If you can't clone `gitolite-admin` repository - DO NOT PROCEED WITH INSTALLATION**
+Check the [Trouble Shooting Guide](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Trouble-Shooting-Guide)
+and ensure you have followed all of the above steps carefully.
 
-# 4. Install gitlab and configuration. Check status configuration.
+# 4. Clone GitLab source and install prerequisites
 
     sudo gem install charlock_holmes --version '0.6.8'
     sudo pip install pygments
     sudo gem install bundler
     cd /home/gitlab
-    sudo -H -u gitlab git clone -b stable git://github.com/gitlabhq/gitlabhq.git gitlab
-    cd gitlab
 
-    sudo -u gitlab mkdir tmp
+    # Get gitlab code. Use this for stable setup
+    sudo -H -u gitlab git clone -b stable https://github.com/gitlabhq/gitlabhq.git gitlab
+
+    # Skip this for stable setup.
+    # Master branch (recent changes, less stable)
+    sudo -H -u gitlab git clone -b master https://github.com/gitlabhq/gitlabhq.git gitlab
+
+    cd gitlab
 
     # Rename config files
     sudo -u gitlab cp config/gitlab.yml.example config/gitlab.yml
 
-#### Select db you want to use
+#### Select the database you want to use
 
     # SQLite
     sudo -u gitlab cp config/database.yml.sqlite config/database.yml
@@ -163,7 +177,7 @@ Permissions:
     # Login to MySQL
     $ mysql -u root -p
 
-    # Create the gitlabhq production database
+    # Create the GitLab production database
     mysql> CREATE DATABASE IF NOT EXISTS `gitlabhq_production` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`;
 
     # Create the MySQL User change $password to a real password
@@ -179,14 +193,16 @@ Permissions:
 
     sudo -u gitlab -H bundle install --without development test --deployment
 
-#### Setup DB
+#### Setup database
 
     sudo -u gitlab bundle exec rake gitlab:app:setup RAILS_ENV=production
 
-#### Setup gitlab hooks
+#### Setup GitLab hooks
+
+    sudo cp ./lib/hooks/post-receive /home/git/.gitolite/hooks/common/post-receive
+    sudo chown git:git /home/git/.gitolite/hooks/common/post-receive
 
-    sudo cp ./lib/hooks/post-receive /home/git/share/gitolite/hooks/common/post-receive
-    sudo chown git:git /home/git/share/gitolite/hooks/common/post-receive
+#### Check application status
 
 Checking status:
 
@@ -208,9 +224,9 @@ Checking status:
     UMASK for .gitolite.rc is 0007? ............YES
     /home/git/share/gitolite/hooks/common/post-receive exists? ............YES
 
-If you got all YES - congrats! You can go to next step.
+If you got all YES - congratulations! You can go to the next step.
 
-# 5. Server up
+# 5. Start the web server
 
 Application can be started with next command:
 
@@ -225,33 +241,41 @@ You can login via web using admin generated with setup:
     admin@local.host
     5iveL!fe
 
-#  6. Run resque process (for processing queue).
+#  6. Run Resque process (for processing job queue).
 
     # Manually
     sudo -u gitlab bundle exec rake environment resque:work QUEUE=* RAILS_ENV=production BACKGROUND=yes
 
-    # Gitlab start script
+    # GitLab start script
     sudo -u gitlab ./resque.sh
     # if you run this as root /home/gitlab/gitlab/tmp/pids/resque_worker.pid will be owned by root
     # causing the resque worker not to start via init script on next boot/service restart
 
-**Ok - we have a working application now. **
-**But keep going - there are some thing that should be done **
+## Customizing Resque's Redis connection
 
-# Nginx && Unicorn
+If you'd like Resque to connect to a Redis server on a non-standard port or on
+a different host, you can configure its connection string in the
+**config/resque.yml** file:
 
-### Install Nginx
+    production: redis.example.com:6379
 
-    sudo apt-get install nginx
+**Ok - we have a working application now. **
+**But keep going - there are some things that should be done **
 
-## Unicorn
+# Nginx && Unicorn
+
+## 1. Unicorn
 
     cd /home/gitlab/gitlab
-    sudo -u gitlab cp config/unicorn.rb.orig config/unicorn.rb
+    sudo -u gitlab cp config/unicorn.rb.example config/unicorn.rb
     sudo -u gitlab bundle exec unicorn_rails -c config/unicorn.rb -E production -D
 
-Add GitLab to nginx sites & change with your host specific settings
+## 2. Nginx
+
+    # Install first
+    sudo apt-get install nginx
 
+    # Add GitLab to nginx sites & change with your host specific settings
     sudo wget https://raw.github.com/gitlabhq/gitlab-recipes/master/nginx/gitlab -P /etc/nginx/sites-available/
     sudo ln -s /etc/nginx/sites-available/gitlab /etc/nginx/sites-enabled/gitlab
 
@@ -260,22 +284,20 @@ Add GitLab to nginx sites & change with your host specific settings
     # of the host serving GitLab.
     sudo vim /etc/nginx/sites-enabled/gitlab
 
-Restart nginx:
-
+    # Restart nginx:
     /etc/init.d/nginx restart
 
+## 3. Init script
+
 Create init script in /etc/init.d/gitlab:
 
     sudo wget https://raw.github.com/gitlabhq/gitlab-recipes/master/init.d/gitlab -P /etc/init.d/
-
-Adding permission:
-
     sudo chmod +x /etc/init.d/gitlab
 
-Gitlab autostart:
+GitLab autostart:
 
     sudo update-rc.d gitlab defaults
 
-Now you can start/restart/stop gitlab like:
+Now you can start/restart/stop GitLab like:
 
     sudo /etc/init.d/gitlab restart
diff --git a/features/dashboard/dashboard.feature b/features/dashboard/dashboard.feature
index a8c2205c143d57f6c02730e70ddd0fa114e35bc9..9756bc7f64d26b1488b2c5ae9a0d4b85c7faa8de 100644
--- a/features/dashboard/dashboard.feature
+++ b/features/dashboard/dashboard.feature
@@ -1,9 +1,9 @@
 Feature: Dashboard
-  Background: 
-    Given I signin as a user
+  Background:
+    Given I sign in as a user
     And I own project "Shop"
     And project "Shop" has push event
-    And I visit dashboard page 
+    And I visit dashboard page
 
   Scenario: I should see projects list
     Then I should see "New Project" link
@@ -15,4 +15,13 @@ Feature: Dashboard
     And I click "Create Merge Request" link
     Then I see prefilled new Merge Request page
 
+  Scenario: I should see User joined Project event
+    Given user with name "John Doe" joined project "Shop"
+    When I visit dashboard page
+    Then I should see "John Doe joined project Shop" event
 
+  Scenario: I should see User left Project event
+    Given user with name "John Doe" joined project "Shop"
+    And user with name "John Doe" left project "Shop"
+    When I visit dashboard page
+    Then I should see "John Doe left project Shop" event
diff --git a/features/dashboard/issues.feature b/features/dashboard/issues.feature
index c3361bb313f8b55cdd99b821850ac1dea970aa01..895b89aa38a5c4cdd8a73cdb8689ce34225a23cb 100644
--- a/features/dashboard/issues.feature
+++ b/features/dashboard/issues.feature
@@ -1,8 +1,8 @@
 Feature: Dashboard Issues
-  Background: 
-    Given I signin as a user
+  Background:
+    Given I sign in as a user
     And I have assigned issues
-    And I visit dashboard issues page 
+    And I visit dashboard issues page
 
   Scenario: I should see issues list
     Then I should see issues assigned to me
diff --git a/features/dashboard/merge_requests.feature b/features/dashboard/merge_requests.feature
index 90b8749c5a762c63831cfc064ad335e66f85c58d..cad65b0d79a08620145dba3d0716339ffc3b1f06 100644
--- a/features/dashboard/merge_requests.feature
+++ b/features/dashboard/merge_requests.feature
@@ -1,8 +1,8 @@
-Feature: Dashboard MR
-  Background: 
-    Given I signin as a user
+Feature: Dashboard Merge Requests
+  Background:
+    Given I sign in as a user
     And I have authored merge requests
-    And I visit dashboard merge requests page 
+    And I visit dashboard merge requests page
 
   Scenario: I should see projects list
     Then I should see my merge requests
diff --git a/features/dashboard/search.feature b/features/dashboard/search.feature
index f053fe86fc8398df20efbca1e4d7e46f6a6a98b7..91d870f46f3bf57c6c6baeb70a151f7723572e99 100644
--- a/features/dashboard/search.feature
+++ b/features/dashboard/search.feature
@@ -1,11 +1,9 @@
 Feature: Dashboard Search
-  Background: 
-    Given I signin as a user
+  Background:
+    Given I sign in as a user
     And I own project "Shop"
-    And I visit dashboard search page 
+    And I visit dashboard search page
 
-  Scenario: I should see project i'm looking for
+  Scenario: I should see project I am looking for
     Given I search for "Sho"
     Then I should see "Shop" project link
-
-
diff --git a/features/profile/profile.feature b/features/profile/profile.feature
index afda4b55081c3d9e1602eeb1a651049417d017ae..134cabb506fda63be1d3d8510e5accb55d624091 100644
--- a/features/profile/profile.feature
+++ b/features/profile/profile.feature
@@ -1,6 +1,6 @@
 Feature: Profile
-  Background: 
-    Given I signin as a user
+  Background:
+    Given I sign in as a user
 
   Scenario: I look at my profile
     Given I visit profile page
@@ -12,11 +12,11 @@ Feature: Profile
     And I should see new contact info
 
   Scenario: I change my password
-    Given I visit profile password page
+    Given I visit profile account page
     Then I change my password
     And I should be redirected to sign in page
 
   Scenario: I reset my token
-    Given I visit profile token page
+    Given I visit profile account page
     Then I reset my token
     And I should see new token
diff --git a/features/profile/ssh_keys.feature b/features/profile/ssh_keys.feature
index c3a92f30ee04d38690c93184d2701962976360fb..018d124e41230c9a97ff59ffbff04572f5aae750 100644
--- a/features/profile/ssh_keys.feature
+++ b/features/profile/ssh_keys.feature
@@ -1,13 +1,10 @@
-Feature: SSH Keys
-  Background: 
-    Given I signin as a user
-    And I have ssh keys:
-      | title | 
-      | Work |
-      | Home | 
+Feature: Profile SSH Keys
+  Background:
+    Given I sign in as a user
+    And I have ssh key "ssh-rsa Work"
     And I visit profile keys page
 
-  Scenario: I should see SSH keys
+  Scenario: I should see ssh keys
     Then I should see my ssh keys
 
   Scenario: Add new ssh key
diff --git a/features/projects/commits/branches.feature b/features/project/commits/branches.feature
similarity index 66%
rename from features/projects/commits/branches.feature
rename to features/project/commits/branches.feature
index 74575c51c5a4a169733b97272f1e94f86d4a1a7c..4fa4dc26a1bf235b8c56d936599d585c2cc070b5 100644
--- a/features/projects/commits/branches.feature
+++ b/features/project/commits/branches.feature
@@ -1,6 +1,6 @@
-Feature: Browse branches
-  Background: 
-    Given I signin as a user
+Feature: Project Browse branches
+  Background:
+    Given I sign in as a user
     And I own project "Shop"
     And project "Shop" has protected branches
     Given I visit project branches page
@@ -16,8 +16,11 @@ Feature: Browse branches
     Given I click link "Protected"
     Then I should see "Shop" protected branches list
 
-  Scenario: I can download project by branch
+  # @wip
+  # Scenario: I can download project by branch
 
-  Scenario: I can view protected branches
+  # @wip
+  # Scenario: I can view protected branches
 
-  Scenario: I can manage protected branches
+  # @wip
+  # Scenario: I can manage protected branches
diff --git a/features/projects/commits/commit_comments.feature b/features/project/commits/commit_comments.feature
similarity index 72%
rename from features/projects/commits/commit_comments.feature
rename to features/project/commits/commit_comments.feature
index 9bd56d29f1e449a7b2c404190cfbad17f31b10bf..5acf541ab96e9f9e541f08bf6e795a06e601f193 100644
--- a/features/projects/commits/commit_comments.feature
+++ b/features/project/commits/commit_comments.feature
@@ -1,6 +1,6 @@
-Feature: Comment commit
-  Background: 
-    Given I signin as a user
+Feature: Project Comment commit
+  Background:
+    Given I sign in as a user
     And I own project "Shop"
     Given I visit project commit page
 
diff --git a/features/projects/commits/commits.feature b/features/project/commits/commits.feature
similarity index 82%
rename from features/projects/commits/commits.feature
rename to features/project/commits/commits.feature
index 69d39d78f895bd4d9adc928a7da974e7684c56c8..53de6e6a264a939ac5883bde1f3efbe69d9ebd35 100644
--- a/features/projects/commits/commits.feature
+++ b/features/project/commits/commits.feature
@@ -1,6 +1,6 @@
-Feature: Browse commits
-  Background: 
-    Given I signin as a user
+Feature: Project Browse commits
+  Background:
+    Given I sign in as a user
     And I own project "Shop"
     Given I visit project commits page
 
@@ -18,5 +18,4 @@ Feature: Browse commits
   Scenario: I compare refs
     Given I visit compare refs page
     And I fill compare fields with refs
-    And I see compared refs 
-
+    And I see compared refs
diff --git a/features/projects/commits/tags.feature b/features/project/commits/tags.feature
similarity index 53%
rename from features/projects/commits/tags.feature
rename to features/project/commits/tags.feature
index f7899fc3ce01beec792475dc0ca8ab486d7782b4..1ac0f8bfa45ad6f496203763d19078c4fe1c6f53 100644
--- a/features/projects/commits/tags.feature
+++ b/features/project/commits/tags.feature
@@ -1,10 +1,11 @@
-Feature: Browse tags
-  Background: 
-    Given I signin as a user
+Feature: Project Browse tags
+  Background:
+    Given I sign in as a user
     And I own project "Shop"
     Given I visit project tags page
 
   Scenario: I can see all git tags
     Then I should see "Shop" all tags list
 
-  Scenario: I can download project by tag
+  # @wip
+  # Scenario: I can download project by tag
diff --git a/features/projects/create_project.feature b/features/project/create_project.feature
similarity index 91%
rename from features/projects/create_project.feature
rename to features/project/create_project.feature
index 42d25b3f33110063ceffed0bb268b85682436ec8..b7cdfdb818e4986462c718fc8b9cb80152110040 100644
--- a/features/projects/create_project.feature
+++ b/features/project/create_project.feature
@@ -4,7 +4,7 @@ Feature: Create Project
   Should be able to create a new one
 
   Scenario: User create a project
-    Given I signin as a user
+    Given I sign in as a user
     When I visit new project page
     And fill project form with valid data
     Then I should see project page
diff --git a/features/project/issues/issues.feature b/features/project/issues/issues.feature
new file mode 100644
index 0000000000000000000000000000000000000000..596e8bd7d4188c7301394a94608ff10487dba0ce
--- /dev/null
+++ b/features/project/issues/issues.feature
@@ -0,0 +1,81 @@
+Feature: Project Issues
+  Background:
+    Given I sign in as a user
+    And I own project "Shop"
+    And project "Shop" have "Release 0.4" open issue
+    And project "Shop" have "Release 0.3" closed issue
+    And I visit project "Shop" issues page
+
+  Scenario: I should see open issues
+    Given I should see "Release 0.4" in issues
+    And I should not see "Release 0.3" in issues
+
+  Scenario: I should see closed issues
+    Given I click link "Closed"
+    Then I should see "Release 0.3" in issues
+    And I should not see "Release 0.4" in issues
+
+  Scenario: I should see all issues
+    Given I click link "All"
+    Then I should see "Release 0.3" in issues
+    And I should see "Release 0.4" in issues
+
+  Scenario: I visit issue page
+    Given I click link "Release 0.4"
+    Then I should see issue "Release 0.4"
+
+  @javascript
+  Scenario: I submit new unassigned issue
+    Given I click link "New Issue"
+    And I submit new issue "500 error on profile"
+    Given I click link "500 error on profile"
+    Then I should see issue "500 error on profile"
+
+  @javascript
+  Scenario: I comment issue
+    Given I visit issue page "Release 0.4"
+    And I leave a comment like "XML attached"
+    Then I should see comment "XML attached"
+
+  @javascript
+  Scenario: I search issue
+    Given I fill in issue search with "Release"
+    Then I should see "Release 0.4" in issues
+    And I should not see "Release 0.3" in issues
+
+  @javascript
+  Scenario: I search issue that not exist
+    Given I fill in issue search with "Bug"
+    Then I should not see "Release 0.4" in issues
+    And I should not see "Release 0.3" in issues
+
+
+  @javascript
+  Scenario: I search all issues
+    Given I click link "All"
+    And I fill in issue search with "0.3"
+    Then I should see "Release 0.3" in issues
+    And I should not see "Release 0.4" in issues
+
+  @javascript
+  Scenario: I clear search
+    Given I click link "All"
+    And I fill in issue search with "Something"
+    And I fill in issue search with ""
+    Then I should see "Release 0.4" in issues
+    And I should see "Release 0.3" in issues
+
+  @javascript
+  Scenario: I create Issue with pre-selected milestone
+    Given project "Shop" has milestone "v2.2"
+    And project "Shop" has milestone "v3.0"
+    And I visit project "Shop" issues page
+    When I select milestone "v3.0"
+    And I click link "New Issue"
+    Then I should see selected milestone with title "v3.0"
+
+  @javascript
+  Scenario: I create Issue with pre-selected assignee
+    When I select first assignee from "Shop" project
+    And I click link "New Issue"
+    Then I should see first assignee from "Shop" as selected assignee
diff --git a/features/project/issues/labels.feature b/features/project/issues/labels.feature
new file mode 100644
index 0000000000000000000000000000000000000000..e601a41bfc4ac96c396279dc834c5394d960a64b
--- /dev/null
+++ b/features/project/issues/labels.feature
@@ -0,0 +1,10 @@
+Feature: Project Labels
+  Background:
+    Given I sign in as a user
+    And I own project "Shop"
+    And project "Shop" have issues tags: "bug", "feature"
+    Given I visit project "Shop" labels page
+
+  Scenario: I should see active milestones
+    Then I should see label "bug"
+    And I should see label "feature"
diff --git a/features/projects/issues/milestones.feature b/features/project/issues/milestones.feature
similarity index 79%
rename from features/projects/issues/milestones.feature
rename to features/project/issues/milestones.feature
index d78096a4f169627572099a34ef5b13022a84c551..a57f67d6815ec928d168182fd28abb4eca814dbf 100644
--- a/features/projects/issues/milestones.feature
+++ b/features/project/issues/milestones.feature
@@ -1,9 +1,9 @@
-Feature: Milestones
+Feature: Project Milestones
   Background:
-    Given I signin as a user
+    Given I sign in as a user
     And I own project "Shop"
     And project "Shop" has milestone "v2.2"
-    Given I visit project "Shop" milestones page 
+    Given I visit project "Shop" milestones page
 
   Scenario: I should see active milestones
     Then I should see milestone "v2.2"
diff --git a/features/projects/merge_requests.feature b/features/project/merge_requests.feature
similarity index 92%
rename from features/projects/merge_requests.feature
rename to features/project/merge_requests.feature
index 54b6ccde7f956fd3934dd4579f5394787eef21e9..80f009864662be4375ba8cf24577d8ec43bde52a 100644
--- a/features/projects/merge_requests.feature
+++ b/features/project/merge_requests.feature
@@ -1,10 +1,10 @@
-Feature: Merge Requests
+Feature: Project Merge Requests
   Background:
-    Given I signin as a user
+    Given I sign in as a user
     And I own project "Shop"
     And project "Shop" have "Bug NS-04" open merge request
     And project "Shop" have "Feature NS-03" closed merge request
-    And I visit project "Shop" merge requests page 
+    And I visit project "Shop" merge requests page
 
   Scenario: I should see open merge requests
     Then I should see "Bug NS-04" in merge requests
diff --git a/features/projects/network.feature b/features/project/network.feature
similarity index 81%
rename from features/projects/network.feature
rename to features/project/network.feature
index 61c05eb367e27038d8712f486b5af573c4e04b74..31ce5ad327959822e2e635567c24e414ee9383ae 100644
--- a/features/projects/network.feature
+++ b/features/project/network.feature
@@ -1,10 +1,9 @@
-@javascript
 Feature: Project Network Graph
-
   Background:
-    Given I signin as a user
+    Given I sign in as a user
     And I own project "Shop"
     And I visit project "Shop" network page
 
+  @javascript
   Scenario: I should see project network
     Then page should have network graph
diff --git a/features/project/project.feature b/features/project/project.feature
new file mode 100644
index 0000000000000000000000000000000000000000..1c9f201df507688f42d48984505e16564e70fa9f
--- /dev/null
+++ b/features/project/project.feature
@@ -0,0 +1,14 @@
+Feature: Projects
+  Background:
+    Given I signin as a user
+    And I own project "Shop"
+    And I visit project "Shop" page
+
+  # @wip
+  # Scenario: I should see project activity
+
+  # @wip
+  # Scenario: I edit project
+
+  # @wip
+  # Scenario: I visit attachments
diff --git a/features/projects/source/browse_files.feature b/features/project/source/browse_files.feature
similarity index 71%
rename from features/projects/source/browse_files.feature
rename to features/project/source/browse_files.feature
index 04aebc19732c7c15483e0f8f724cf6ea397e93c0..b12b0ee3e3612f513030423ee2d00b3392c494eb 100644
--- a/features/projects/source/browse_files.feature
+++ b/features/project/source/browse_files.feature
@@ -1,6 +1,6 @@
-Feature: Browse git repo
-  Background: 
-    Given I signin as a user
+Feature: Project Browse files
+  Background:
+    Given I sign in as a user
     And I own project "Shop"
     Given I visit project source page
 
@@ -12,12 +12,10 @@ Feature: Browse git repo
     Then I should see files from repository for "8470d70"
 
   Scenario: I browse file content
-    Given I click on file from repo
+    Given I click on "Gemfile" file in repo
     Then I should see it content
 
   Scenario: I browse raw file
-    Given I visit blob file from repo 
-    And I click on raw button
+    Given I visit blob file from repo
+    And I click link "raw"
     Then I should see raw file content
-
-
diff --git a/features/project/source/git_blame.feature b/features/project/source/git_blame.feature
new file mode 100644
index 0000000000000000000000000000000000000000..93ed20a8c42d68048d6880313b5aa07e761769bc
--- /dev/null
+++ b/features/project/source/git_blame.feature
@@ -0,0 +1,10 @@
+Feature: Project Browse git repo
+  Background:
+    Given I sign in as a user
+    And I own project "Shop"
+    Given I visit project source page
+
+  Scenario: I blame file
+    Given I click on "Gemfile" file in repo
+    And I click blame button
+    Then I should see git file blame
diff --git a/features/projects/team_management.feature b/features/project/team_management.feature
similarity index 78%
rename from features/projects/team_management.feature
rename to features/project/team_management.feature
index b5b485e2dc02f937d31dfbe41c1dcb90cffeed05..ae0c459f3339a6466f702a838277d396c9d2a6cf 100644
--- a/features/projects/team_management.feature
+++ b/features/project/team_management.feature
@@ -1,11 +1,11 @@
 Feature: Project Team management
-  Background: 
-    Given I signin as a user
+  Background:
+    Given I sign in as a user
     And I own project "Shop"
-    And gitlab user "Mike" 
-    And gitlab user "Sam" 
+    And gitlab user "Mike"
+    And gitlab user "Sam"
     And "Sam" is "Shop" developer
-    And I visit project "Shop" team page 
+    And I visit project "Shop" team page
 
   Scenario: See all team members
     Then I should be able to see myself in team
@@ -20,7 +20,7 @@ Feature: Project Team management
   Scenario: Update user access
     Given I should see "Sam" in team list as "Developer"
     And I change "Sam" role to "Reporter"
-    Then I visit project "Shop" team page 
+    Then I visit project "Shop" team page
     And I should see "Sam" in team list as "Reporter"
 
   Scenario: View team member profile
@@ -30,6 +30,5 @@ Feature: Project Team management
   Scenario: Cancel team member
     Given I click link "Sam"
     And I click link "Remove from team"
-    Then I visit project "Shop" team page 
+    Then I visit project "Shop" team page
     And I should not see "Sam" in team list
-
diff --git a/features/projects/wall.feature b/features/project/wall.feature
similarity index 63%
rename from features/projects/wall.feature
rename to features/project/wall.feature
index ed675e2c4776563a338aeffba6daea7af5b1fc97..c38d046a8502bafdd8a7d75ced899461bf098e7e 100644
--- a/features/projects/wall.feature
+++ b/features/project/wall.feature
@@ -1,17 +1,16 @@
-@javascript
 Feature: Project Wall
   In order to use Project Wall
-  A user
-  Should be able to read & write messages
+  A user should be able to read and write messages
 
   Background:
-    Given I signin as a user
+    Given I sign in as a user
     And I own project "Shop"
-    And I visit project "Shop" wall page 
+    And I visit project "Shop" wall page
 
+  @javascript
   Scenario: Write comment
     Given I write new comment "my special test message"
     Then I should see project wall note "my special test message"
 
-    Then I visit project "Shop" wall page 
+    Then I visit project "Shop" wall page
     And I should see project wall note "my special test message"
diff --git a/features/projects/wiki.feature b/features/project/wiki.feature
similarity index 83%
rename from features/projects/wiki.feature
rename to features/project/wiki.feature
index 4441ada28477444fbc38822c03448a833dffd25c..51370565a3b982c8a61d32bc3f134e7f5c224539 100644
--- a/features/projects/wiki.feature
+++ b/features/project/wiki.feature
@@ -1,6 +1,6 @@
-Feature: Wiki
-  Background: 
-    Given I signin as a user
+Feature: Project Wiki
+  Background:
+    Given I sign in as a user
     And I own project "Shop"
     Given I visit project wiki page
 
diff --git a/features/projects/issues/issues.feature b/features/projects/issues/issues.feature
deleted file mode 100644
index 180710cf6bce8f108854d3e9cc768e97bfb63ff6..0000000000000000000000000000000000000000
--- a/features/projects/issues/issues.feature
+++ /dev/null
@@ -1,38 +0,0 @@
-Feature: Issues
-  Background:
-    Given I signin as a user
-    And I own project "Shop"
-    And project "Shop" have "Release 0.4" open issue
-    And project "Shop" have "Release 0.3" closed issue
-    And I visit project "Shop" issues page 
-
-  Scenario: I should see open issues
-    Given I should see "Release 0.4" in issues
-    And I should not see "Release 0.3" in issues
-
-  Scenario: I should see closed issues
-    Given I click link "Closed"
-    Then I should see "Release 0.3" in issues
-    And I should not see "Release 0.4" in issues
-
-  Scenario: I should see all issues
-    Given I click link "All"
-    Then I should see "Release 0.3" in issues
-    And I should see "Release 0.4" in issues
-
-  Scenario: I visit issue page
-    Given I click link "Release 0.4"
-    Then I should see issue "Release 0.4"
-
-  @javascript
-  Scenario: I submit new unassigned issue
-    Given I click link "New Issue"
-    And I submit new issue "500 error on profile"
-    Given I click link "500 error on profile"
-    Then I should see issue "500 error on profile"
-
-  @javascript
-  Scenario: I comment issue
-    Given I visit issue page "Release 0.4"
-    And I leave a comment like "XML attached"
-    Then I should see comment "XML attached"
diff --git a/features/projects/project.feature b/features/projects/project.feature
deleted file mode 100644
index 895a928ff81fd950ec444f3d6fdc1935f1440715..0000000000000000000000000000000000000000
--- a/features/projects/project.feature
+++ /dev/null
@@ -1,11 +0,0 @@
-Feature: Project
-  Background:
-    Given I signin as a user
-    And I own project "Shop"
-    And I visit project "Shop" page 
-
-  Scenario: I should see project activity
-
-  Scenario: I edit project
-
-  Scenario: I visit attachments
diff --git a/features/projects/snippets.feature b/features/projects/snippets.feature
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/features/projects/source/git_blame.feature b/features/projects/source/git_blame.feature
deleted file mode 100644
index 6aa6be47debefe8f5d5c11a16fd5d850d0449bef..0000000000000000000000000000000000000000
--- a/features/projects/source/git_blame.feature
+++ /dev/null
@@ -1,10 +0,0 @@
-Feature: Browse git repo
-  Background: 
-    Given I signin as a user
-    And I own project "Shop"
-    Given I visit project source page
-
-  Scenario: I blame file
-    Given I click on file from repo
-    And I click blame button
-    Then I should see git file blame 
diff --git a/features/projects/web_hooks.feature b/features/projects/web_hooks.feature
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/features/step_definitions/dashboard_steps.rb b/features/step_definitions/dashboard_steps.rb
deleted file mode 100644
index 1eec761920152d3725d02c86830033bcc1b64c81..0000000000000000000000000000000000000000
--- a/features/step_definitions/dashboard_steps.rb
+++ /dev/null
@@ -1,127 +0,0 @@
-Given /^I visit dashboard page$/ do
-  visit dashboard_path
-end
-
-Then /^I should see "(.*?)" link$/ do |arg1|
-  page.should have_link(arg1)
-end
-
-Then /^I should see "(.*?)" project link$/ do |arg1|
-  page.should have_link(arg1)
-end
-
-Then /^I should see project "(.*?)" activity feed$/ do |arg1|
-  project = Project.find_by_name(arg1)
-  page.should have_content "#{@user.name} pushed new branch new_design at #{project.name}"
-end
-
-Given /^project "(.*?)" has push event$/ do |arg1|
-  @project = Project.find_by_name(arg1)
-
-  data = {
-    :before => "0000000000000000000000000000000000000000",
-    :after => "0220c11b9a3e6c69dc8fd35321254ca9a7b98f7e",
-    :ref => "refs/heads/new_design",
-    :user_id => @user.id,
-    :user_name => @user.name,
-    :repository => {
-      :name => @project.name,
-      :url => "localhost/rubinius",
-      :description => "",
-      :homepage => "localhost/rubinius",
-      :private => true
-    }
-  }
-
-  @event = Event.create(
-    :project => @project,
-    :action => Event::Pushed,
-    :data => data,
-    :author_id => @user.id
-  )
-end
-
-Then /^I should see last push widget$/ do
-  page.should have_content "Your pushed to branch new_design"
-  page.should have_link "Create Merge Request"
-end
-
-Then /^I click "(.*?)" link$/ do |arg1|
-  click_link arg1 #Create Merge Request"
-end
-
-Then /^I see prefilled new Merge Request page$/ do
-  current_path.should == new_project_merge_request_path(@project) 
-  find("#merge_request_source_branch").value.should == "new_design" 
-  find("#merge_request_target_branch").value.should == "master" 
-  find("#merge_request_title").value.should == "New Design" 
-end
-
-Given /^I visit dashboard search page$/ do
-  visit search_path
-end
-
-Given /^I search for "(.*?)"$/ do |arg1|
-  fill_in "dashboard_search", :with => arg1
-  click_button "Search"
-end
-
-Given /^I visit dashboard issues page$/ do
-  visit dashboard_issues_path
-end
-
-Then /^I should see issues assigned to me$/ do
-  issues = @user.issues
-  issues.each do |issue|
-    page.should have_content(issue.title[0..10])
-    page.should have_content(issue.project.name)
-  end
-end
-
-Given /^I visit dashboard merge requests page$/ do
-  visit dashboard_merge_requests_path
-end
-
-Then /^I should see my merge requests$/ do
-  merge_requests = @user.merge_requests
-  merge_requests.each do |mr|
-    page.should have_content(mr.title[0..10])
-    page.should have_content(mr.project.name)
-  end
-end
-
-Given /^I have assigned issues$/ do
-  project = Factory :project
-  project.add_access(@user, :read, :write)
-
-  issue1 = Factory :issue,
-   :author => @user,
-   :assignee => @user,
-   :project => project
-
-  issue2 = Factory :issue,
-   :author => @user,
-   :assignee => @user,
-   :project => project
-end
-
-Given /^I have authored merge requests$/ do
-  project1 = Factory :project,
-   :path => "project1",
-   :code => "gitlabhq_1"
-
-  project2 = Factory :project,
-   :path => "project2",
-   :code => "gitlabhq_2"
-
-  project1.add_access(@user, :read, :write)
-  project2.add_access(@user, :read, :write)
-
-  merge_request1 = Factory :merge_request,
-   :author => @user,
-   :project => project1
-
-  merge_request2 = Factory :merge_request,
-   :author => @user,
-   :project => project2
-end
diff --git a/features/step_definitions/profile/profile_keys_steps.rb b/features/step_definitions/profile/profile_keys_steps.rb
deleted file mode 100644
index 5ab7e0480ad34ebf559109ea5724acf249ebe458..0000000000000000000000000000000000000000
--- a/features/step_definitions/profile/profile_keys_steps.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-Given /^I visit profile keys page$/ do
-  visit keys_path
-end
-
-Then /^I should see my ssh keys$/ do
-  @user.keys.each do |key|
-    page.should have_content(key.title)
-  end
-end
-
-Given /^I have ssh keys:$/ do |table|
-  table.hashes.each do |row|
-    Factory :key, :user => @user, :title => row[:title], :key => "jfKLJDFKSFJSHFJ#{row[:title]}"
-  end
-end
-
-Given /^I submit new ssh key "(.*?)"$/ do |arg1|
-  fill_in "key_title", :with => arg1
-  fill_in "key_key", :with => "publickey234="
-  click_button "Save"
-end
-
-Then /^I should see new ssh key "(.*?)"$/ do |arg1|
-  key = Key.find_by_title(arg1)
-  page.should have_content(key.title)
-  page.should have_content(key.key)
-  current_path.should == key_path(key)
-end
-
-Then /^I should not see "(.*?)" ssh key$/ do |arg1|
-  within "#keys-table" do
-    page.should_not have_content(arg1)
-  end
-end
diff --git a/features/step_definitions/profile/profile_steps.rb b/features/step_definitions/profile/profile_steps.rb
deleted file mode 100644
index 4661139c1808e209994c26bfb0ad2a81aaf5a830..0000000000000000000000000000000000000000
--- a/features/step_definitions/profile/profile_steps.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-Given /^I visit profile page$/ do
-  visit profile_path
-end
-
-Then /^I should see my profile info$/ do
-  page.should have_content "Profile"
-  page.should have_content @user.name
-  page.should have_content @user.email
-end
-
-Given /^I visit profile password page$/ do
-  visit profile_password_path
-end
-
-Then /^I change my password$/ do
-  fill_in "user_password", :with => "222333"
-  fill_in "user_password_confirmation", :with => "222333"
-  click_button "Save"
-end
-
-Then /^I should be redirected to sign in page$/ do
-  current_path.should == new_user_session_path
-end
-
-Given /^I visit profile token page$/ do
-  visit profile_token_path
-end
-
-Then /^I reset my token$/ do
-  @old_token = @user.private_token
-  click_button "Reset"
-end
-
-Then /^I should see new token$/ do
-  find("#token").value.should_not == @old_token
-  find("#token").value.should == @user.reload.private_token
-end
-
-Then /^I change my contact info$/ do
-  fill_in "user_skype", :with => "testskype"
-  fill_in "user_linkedin", :with => "testlinkedin"
-  fill_in "user_twitter", :with => "testtwitter"
-  click_button "Save"
-  @user.reload
-end
-
-Then /^I should see new contact info$/ do
-  @user.skype.should == 'testskype'
-  @user.linkedin.should == 'testlinkedin'
-  @user.twitter.should == 'testtwitter'
-end
diff --git a/features/step_definitions/project/browse_code_steps.rb b/features/step_definitions/project/browse_code_steps.rb
deleted file mode 100644
index 7f9001bb989a66e55bc190133e79b91710f42c41..0000000000000000000000000000000000000000
--- a/features/step_definitions/project/browse_code_steps.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-Given /^I visit project source page$/ do
-  visit tree_project_ref_path(@project, @project.root_ref)
-end
-
-Then /^I should see files from repository$/ do
-  page.should have_content("app")
-  page.should have_content("History")
-  page.should have_content("Gemfile")
-end
-
-Given /^I visit project source page for "(.*?)"$/ do |arg1|
-  visit tree_project_ref_path(@project, arg1)
-end
-
-Then /^I should see files from repository for "(.*?)"$/ do |arg1|
-  current_path.should == tree_project_ref_path(@project, arg1)
-  page.should have_content("app")
-  page.should have_content("History")
-  page.should have_content("Gemfile")
-end
-
-Given /^I click on file from repo$/ do
-  click_link "Gemfile"
-end
-
-Then /^I should see it content$/ do
-  page.should have_content("rubygems.org")
-end
-
-Given /^I click on raw button$/ do
-  click_link "raw"
-end
-
-Given /^I visit blob file from repo$/ do
-  visit tree_project_ref_path(@project, ValidCommit::ID, :path => ValidCommit::BLOB_FILE_PATH)
-end
-
-Then /^I should see raw file content$/ do
-  page.source.should == ValidCommit::BLOB_FILE
-end
-
-Given /^I click blame button$/ do
-  click_link "blame"
-end
-
-Then /^I should see git file blame$/ do
-  page.should have_content("rubygems.org")
-  page.should have_content("Dmitriy Zaporozhets")
-  page.should have_content("bc3735004cb Moving to rails 3.2")
-end
diff --git a/features/step_definitions/project/project_commits_steps.rb b/features/step_definitions/project/project_commits_steps.rb
deleted file mode 100644
index 35fcb4d11ab09ba47c75d3d28a3d154ccff58ce3..0000000000000000000000000000000000000000
--- a/features/step_definitions/project/project_commits_steps.rb
+++ /dev/null
@@ -1,88 +0,0 @@
-Given /^I visit project commits page$/ do
-  visit project_commits_path(@project)
-end
-
-Then /^I see project commits$/ do
-  current_path.should == project_commits_path(@project)
-
-  commit = @project.commit
-  page.should have_content(@project.name)
-  page.should have_content(commit.message)
-  page.should have_content(commit.id.to_s[0..5])
-end
-
-Given /^I click atom feed link$/ do
-  click_link "Feed"
-end
-
-Then /^I see commits atom feed$/ do
-  commit = CommitDecorator.decorate(@project.commit)
-  page.response_headers['Content-Type'].should have_content("application/atom+xml")
-  page.body.should have_selector("title", :text => "Recent commits to #{@project.name}")
-  page.body.should have_selector("author email", :text => commit.author_email)
-  page.body.should have_selector("entry summary", :text => commit.description)
-end
-
-Given /^I click on commit link$/ do
-  visit project_commit_path(@project, ValidCommit::ID)
-end
-
-Then /^I see commit info$/ do
-  page.should have_content ValidCommit::MESSAGE
-  page.should have_content "Showing 1 changed file"
-end
-
-Given /^I visit compare refs page$/ do
-  visit compare_project_commits_path(@project)
-end
-
-Given /^I fill compare fields with refs$/ do
-  fill_in "from", :with => "master"
-  fill_in "to", :with => "stable"
-  click_button "Compare"
-end
-
-Given /^I see compared refs$/ do
-  page.should have_content "Commits (27)"
-  page.should have_content "Compare View"
-  page.should have_content "Showing 73 changed files"
-end
-
-Given /^I visit project branches page$/ do
-  visit branches_project_repository_path(@project)
-end
-
-Given /^I visit project commit page$/ do
-  visit project_commit_path(@project, ValidCommit::ID)
-end
-
-Given /^I visit project tags page$/ do
-  visit tags_project_repository_path(@project)
-end
-
-Then /^I should see "(.*?)" recent branches list$/ do |arg1|
-  page.should have_content("Branches")
-  page.should have_content("master")
-end
-
-Then /^I should see "(.*?)" all branches list$/ do |arg1|
-  page.should have_content("Branches")
-  page.should have_content("master")
-end
-
-Then /^I should see "(.*?)" all tags list$/ do |arg1|
-  page.should have_content("Tags")
-  page.should have_content("v1.2.1")
-end
-
-Then /^I should see "(.*?)" protected branches list$/ do |arg1|
-  within "table" do 
-    page.should have_content "stable"
-    page.should_not have_content "master"
-  end
-end
-
-Given /^project "(.*?)" has protected branches$/ do |arg1|
-  project = Project.find_by_name(arg1)
-  project.protected_branches.create(:name => "stable")
-end
diff --git a/features/step_definitions/project/project_issues_steps.rb b/features/step_definitions/project/project_issues_steps.rb
deleted file mode 100644
index 00a1721f8de6577a48fd284b41e2170f41a52285..0000000000000000000000000000000000000000
--- a/features/step_definitions/project/project_issues_steps.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-Given /^project "(.*?)" have "(.*?)" open issue$/ do |arg1, arg2|
-  project = Project.find_by_name(arg1)
-  Factory.create(:issue, :title => arg2, :project => project, :author => project.users.first)
-end
-
-Given /^project "(.*?)" have "(.*?)" closed issue$/ do |arg1, arg2|
-  project = Project.find_by_name(arg1)
-  Factory.create(:issue, :title => arg2, :project => project, :author => project.users.first, :closed => true)
-end
-
-Given /^I visit project "(.*?)" issues page$/ do |arg1|
-  visit project_issues_path(Project.find_by_name(arg1))
-end
-
-Given /^I should see "(.*?)" in issues$/ do |arg1|
-  page.should have_content arg1 
-end
-
-Given /^I should not see "(.*?)" in issues$/ do |arg1|
-  page.should_not have_content arg1 
-end
-
-Then /^I should see issue "(.*?)"$/ do |arg1|
-  issue = Issue.find_by_title(arg1)
-  page.should have_content issue.title
-  page.should have_content issue.author_name
-  page.should have_content issue.project.name
-end
-
-Given /^I visit issue page "(.*?)"$/ do |arg1|
-  issue = Issue.find_by_title(arg1)
-  visit project_issue_path(issue.project, issue)
-end
-
-Given /^I submit new issue "(.*?)"$/ do |arg1|
-  fill_in "issue_title", :with => arg1
-  click_button "Submit new issue"
-end
diff --git a/features/step_definitions/project/project_merge_requests_steps.rb b/features/step_definitions/project/project_merge_requests_steps.rb
deleted file mode 100644
index 2bdb967d3c5c3db607128c6cb74a652deeb0b2ea..0000000000000000000000000000000000000000
--- a/features/step_definitions/project/project_merge_requests_steps.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-Given /^project "(.*?)" have "(.*?)" open merge request$/ do |arg1, arg2|
-  project = Project.find_by_name(arg1)
-  Factory.create(:merge_request, :title => arg2, :project => project, :author => project.users.first)
-end
-
-Given /^project "(.*?)" have "(.*?)" closed merge request$/ do |arg1, arg2|
-  project = Project.find_by_name(arg1)
-  Factory.create(:merge_request, :title => arg2, :project => project, :author => project.users.first, :closed => true)
-end
-
-Given /^I visit project "(.*?)" merge requests page$/ do |arg1|
-  visit project_merge_requests_path(Project.find_by_name(arg1))
-end
-
-Then /^I should see "(.*?)" in merge requests$/ do |arg1|
-  page.should have_content arg1 
-end
-
-Then /^I should not see "(.*?)" in merge requests$/ do |arg1|
-  page.should_not have_content arg1 
-end
-
-Then /^I should see merge request "(.*?)"$/ do |arg1|
-  merge_request = MergeRequest.find_by_title(arg1)
-  page.should have_content(merge_request.title[0..10]) 
-  page.should have_content(merge_request.target_branch)
-  page.should have_content(merge_request.source_branch)
-end
-
-Given /^I submit new merge request "(.*?)"$/ do |arg1|
-  fill_in "merge_request_title", :with => arg1
-  select "master", :from => "merge_request_source_branch"
-  select "stable", :from => "merge_request_target_branch"
-  click_button "Save"
-end
-
-Given /^I visit merge request page "(.*?)"$/ do |arg1|
-  mr = MergeRequest.find_by_title(arg1)
-  visit project_merge_request_path(mr.project, mr)
-end
-
-Then /^I should see closed merge request "(.*?)"$/ do |arg1|
-  mr = MergeRequest.find_by_title(arg1)
-  mr.closed.should be_true
-  page.should have_content "Closed by"
-end
-
diff --git a/features/step_definitions/project/project_milestones_steps.rb b/features/step_definitions/project/project_milestones_steps.rb
deleted file mode 100644
index 6749773e2b5b46e1dbe8644893cae26518f5fcd1..0000000000000000000000000000000000000000
--- a/features/step_definitions/project/project_milestones_steps.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-Given /^project "(.*?)" has milestone "(.*?)"$/ do |arg1, arg2|
-  project = Project.find_by_name(arg1)
-
-  milestone = Factory :milestone,
-    :title => arg2,
-    :project => project
-
-  3.times do |i|
-    issue = Factory :issue,
-      :project => project,
-      :milestone => milestone
-  end
-end
-
-Given /^I visit project "(.*?)" milestones page$/ do |arg1|
-  @project = Project.find_by_name(arg1)
-  visit project_milestones_path(@project)
-end
-
-Then /^I should see active milestones$/ do
-  milestone = @project.milestones.first
-  page.should have_content(milestone.title[0..10])
-  page.should have_content(milestone.expires_at)
-  page.should have_content("Browse Issues")
-end
-
-Then /^I should see milestone "(.*?)"$/ do |arg1|
-  milestone = @project.milestones.find_by_title(arg1)
-  page.should have_content(milestone.title[0..10])
-  page.should have_content(milestone.expires_at)
-  page.should have_content("Browse Issues")
-end
-
-Given /^I submit new milestone "(.*?)"$/ do |arg1|
-  fill_in "milestone_title", :with => arg1
-  click_button "Create milestone"
-end
-
diff --git a/features/step_definitions/project/project_team_steps.rb b/features/step_definitions/project/project_team_steps.rb
deleted file mode 100644
index f0bab29a6f8380427912b4176e338ccfdfcb5006..0000000000000000000000000000000000000000
--- a/features/step_definitions/project/project_team_steps.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-Given /^gitlab user "(.*?)"$/ do |arg1|
-  Factory :user, :name => arg1
-end
-
-Given /^"(.*?)" is "(.*?)" developer$/ do |arg1, arg2|
-  user = User.find_by_name(arg1)
-  project = Project.find_by_name(arg2)
-  project.add_access(user, :write)
-end
-
-Given /^I visit project "(.*?)" team page$/ do |arg1|
-  visit team_project_path(Project.find_by_name(arg1))
-end
-
-Then /^I should be able to see myself in team$/ do
-  page.should have_content(@user.name)
-  page.should have_content(@user.email)
-end
-
-Then /^I should see "(.*?)" in team list$/ do |arg1|
-  user = User.find_by_name(arg1)
-  page.should have_content(user.name)
-  page.should have_content(user.email)
-end
-
-Given /^I click link "(.*?)"$/ do |arg1|
-  click_link arg1
-end
-
-Given /^I select "(.*?)" as "(.*?)"$/ do |arg1, arg2|
-  user = User.find_by_name(arg1)
-  within "#new_team_member" do 
-    select user.name, :from => "team_member_user_id"
-    select arg2, :from => "team_member_project_access"
-  end
-  click_button "Save"
-end
-
-Then /^I should see "(.*?)" in team list as "(.*?)"$/ do |arg1, arg2|
-  user = User.find_by_name(arg1)
-  role_id = find(".user_#{user.id} #team_member_project_access").value
-  role_id.should == UsersProject.access_roles[arg2].to_s
-end
-
-Given /^I change "(.*?)" role to "(.*?)"$/ do |arg1, arg2|
-  user = User.find_by_name(arg1)
-  within ".user_#{user.id}" do 
-    select arg2, :from => "team_member_project_access"
-  end
-end
-
-Then /^I should see "(.*?)" team profile$/ do |arg1|
-  user = User.find_by_name(arg1)
-  page.should have_content(user.name)
-  page.should have_content(user.email)
-  page.should have_content("To team list")
-end
-
-Then /^I should not see "(.*?)" in team list$/ do |arg1|
-  user = User.find_by_name(arg1)
-  page.should_not have_content(user.name)
-  page.should_not have_content(user.email)
-end
diff --git a/features/step_definitions/project/project_wiki_steps.rb b/features/step_definitions/project/project_wiki_steps.rb
deleted file mode 100644
index 10de38d9ae3df74e1876e501514c9075f500c643..0000000000000000000000000000000000000000
--- a/features/step_definitions/project/project_wiki_steps.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-Given /^I visit project wiki page$/ do
-  visit project_wiki_path(@project, :index)
-end
-
-Given /^I create Wiki page$/ do
-  fill_in "Title", :with => 'Test title'
-  fill_in "Content", :with => '[link test](test)'
-  click_on "Save"
-end
-
-Then /^I should see newly created wiki page$/ do
-  page.should have_content("Test title")
-  page.should have_content("link test")
-
-  click_link "link test"
-
-  page.should have_content("Editing page")
-end
diff --git a/features/step_definitions/project/projects_steps.rb b/features/step_definitions/project/projects_steps.rb
deleted file mode 100644
index 3ff08d584489df7f5e6f8897eebf26d93381a924..0000000000000000000000000000000000000000
--- a/features/step_definitions/project/projects_steps.rb
+++ /dev/null
@@ -1,87 +0,0 @@
-include LoginMacros
-
-Given /^I signin as a user$/ do
-  login_as :user
-end
-
-When /^I visit new project page$/ do
-  visit new_project_path
-end
-
-When /^fill project form with valid data$/ do
-  fill_in 'project_name', :with => 'NewProject'
-  fill_in 'project_code', :with => 'NPR'
-  fill_in 'project_path', :with => 'newproject'
-  click_button "Create project"
-end
-
-Then /^I should see project page$/ do
-  current_path.should == project_path(Project.last)
-  page.should have_content('NewProject')
-end
-
-Then /^I should see empty project instuctions$/ do
-  page.should have_content("git init")
-  page.should have_content("git remote")
-  page.should have_content(Project.last.url_to_repo)
-end
-
-Given /^I own project "(.*?)"$/ do |arg1|
-  @project = Factory :project, :name => arg1
-  @project.add_access(@user, :admin)
-end
-
-Given /^I visit project "(.*?)" wall page$/ do |arg1|
-  project = Project.find_by_name(arg1)
-  visit wall_project_path(project)
-end
-
-Then /^I should see project wall note "(.*?)"$/ do |arg1|
-  page.should have_content arg1
-end
-
-Given /^project "(.*?)" has comment "(.*?)"$/ do |arg1, arg2|
-  project = Project.find_by_name(arg1)
-  project.notes.create(:note => arg1, :author => project.users.first)
-end
-
-Given /^I write new comment "(.*?)"$/ do |arg1|
-  fill_in "note_note", :with => arg1
-  click_button "Add Comment"
-end
-
-Given /^I visit project "(.*?)" page$/ do |arg1|
-  project = Project.find_by_name(arg1)
-  visit project_path(project)
-end
-
-Given /^I visit project "(.*?)" network page$/ do |arg1|
-  project = Project.find_by_name(arg1)
-
-  # Stub out find_all to speed this up (10 commits vs. 650)
-  commits = Grit::Commit.find_all(project.repo, nil, {max_count: 10})
-  Grit::Commit.stub(:find_all).and_return(commits)
-
-  visit graph_project_path(project)
-end
-
-Given /^show me page$/ do
-  save_and_open_page
-end
-
-Given /^page should have network graph$/ do
-  page.should have_content "Project Network Graph"
-  within ".graph" do
-    page.should have_content "master"
-    page.should have_content "scss_refactor..."
-  end
-end
-
-Given /^I leave a comment like "(.*?)"$/ do |arg1|
-  fill_in "note_note", :with => arg1
-  click_button "Add Comment"
-end
-
-Then /^I should see comment "(.*?)"$/ do |arg1|
-  page.should have_content(arg1)
-end
diff --git a/features/steps/dashboard/dashboard.rb b/features/steps/dashboard/dashboard.rb
new file mode 100644
index 0000000000000000000000000000000000000000..6c603bbea5587e90ba06b2a3f4a465ea8aefed52
--- /dev/null
+++ b/features/steps/dashboard/dashboard.rb
@@ -0,0 +1,92 @@
+class Dashboard < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedPaths
+
+  Then 'I should see "New Project" link' do
+    page.should have_link "New Project"
+  end
+
+  Then 'I should see "Shop" project link' do
+    page.should have_link "Shop"
+  end
+
+  Then 'I should see project "Shop" activity feed' do
+    project = Project.find_by_name("Shop")
+    page.should have_content "#{@user.name} pushed new branch new_design at #{project.name}"
+  end
+
+  Then 'I should see last push widget' do
+    page.should have_content "Your pushed to branch new_design"
+    page.should have_link "Create Merge Request"
+  end
+
+  And 'I click "Create Merge Request" link' do
+    click_link "Create Merge Request"
+  end
+
+  Then 'I see prefilled new Merge Request page' do
+    current_path.should == new_project_merge_request_path(@project)
+    find("#merge_request_source_branch").value.should == "new_design"
+    find("#merge_request_target_branch").value.should == "master"
+    find("#merge_request_title").value.should == "New Design"
+  end
+
+  Given 'user with name "John Doe" joined project "Shop"' do
+    user = Factory.create(:user, {name: "John Doe"})
+    project = Project.find_by_name "Shop"
+    Event.create(
+      project: project,
+      author_id: user.id,
+      action: Event::Joined
+    )
+  end
+
+  Then 'I should see "John Doe joined project Shop" event' do
+    page.should have_content "John Doe joined project Shop"
+  end
+
+  And 'user with name "John Doe" left project "Shop"' do
+    user = User.find_by_name "John Doe"
+    project = Project.find_by_name "Shop"
+    Event.create(
+      project: project,
+      author_id: user.id,
+      action: Event::Left
+    )
+  end
+
+  Then 'I should see "John Doe left project Shop" event' do
+    page.should have_content "John Doe left project Shop"
+  end
+
+  And 'I own project "Shop"' do
+    @project = Factory :project, :name => 'Shop'
+    @project.add_access(@user, :admin)
+  end
+
+  And 'project "Shop" has push event' do
+    @project = Project.find_by_name("Shop")
+
+    data = {
+      :before => "0000000000000000000000000000000000000000",
+      :after => "0220c11b9a3e6c69dc8fd35321254ca9a7b98f7e",
+      :ref => "refs/heads/new_design",
+      :user_id => @user.id,
+      :user_name => @user.name,
+      :repository => {
+        :name => @project.name,
+        :url => "localhost/rubinius",
+        :description => "",
+        :homepage => "localhost/rubinius",
+        :private => true
+      }
+    }
+
+    @event = Event.create(
+      :project => @project,
+      :action => Event::Pushed,
+      :data => data,
+      :author_id => @user.id
+    )
+  end
+end
diff --git a/features/steps/dashboard/dashboard_issues.rb b/features/steps/dashboard/dashboard_issues.rb
new file mode 100644
index 0000000000000000000000000000000000000000..9368782bf99e2127d0b3c41441821c53e9e22d78
--- /dev/null
+++ b/features/steps/dashboard/dashboard_issues.rb
@@ -0,0 +1,19 @@
+class DashboardIssues < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedPaths
+
+  Then 'I should see issues assigned to me' do
+    issues = @user.issues
+    issues.each do |issue|
+      page.should have_content(issue.title[0..10])
+      page.should have_content(issue.project.name)
+    end
+  end
+
+  And 'I have assigned issues' do
+    project = Factory :project
+    project.add_access(@user, :read, :write)
+
+    2.times { Factory :issue, :author => @user, :assignee => @user, :project => project }
+  end
+end
diff --git a/features/steps/dashboard/dashboard_merge_requests.rb b/features/steps/dashboard/dashboard_merge_requests.rb
new file mode 100644
index 0000000000000000000000000000000000000000..fc339e756d8219f85b2cd5bfef642f9c2e20adb0
--- /dev/null
+++ b/features/steps/dashboard/dashboard_merge_requests.rb
@@ -0,0 +1,23 @@
+class DashboardMergeRequests < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedPaths
+
+  Then 'I should see my merge requests' do
+    merge_requests = @user.merge_requests
+    merge_requests.each do |mr|
+      page.should have_content(mr.title[0..10])
+      page.should have_content(mr.project.name)
+    end
+  end
+
+  And 'I have authored merge requests' do
+    project1 = Factory :project
+    project2 = Factory :project
+
+    project1.add_access(@user, :read, :write)
+    project2.add_access(@user, :read, :write)
+
+    merge_request1 = Factory :merge_request, :author => @user, :project => project1
+    merge_request2 = Factory :merge_request, :author => @user, :project => project2
+  end
+end
diff --git a/features/steps/dashboard/dashboard_search.rb b/features/steps/dashboard/dashboard_search.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e35858985d688a89b7c965468dacb7e7417764bc
--- /dev/null
+++ b/features/steps/dashboard/dashboard_search.rb
@@ -0,0 +1,18 @@
+class DashboardSearch < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedPaths
+
+  Given 'I search for "Sho"' do
+    fill_in "dashboard_search", :with => "Sho"
+    click_button "Search"
+  end
+
+  Then 'I should see "Shop" project link' do
+    page.should have_link "Shop"
+  end
+
+  And 'I own project "Shop"' do
+    @project = Factory :project, :name => "Shop"
+    @project.add_access(@user, :admin)
+  end
+end
diff --git a/features/steps/profile/profile.rb b/features/steps/profile/profile.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d3261a1669018a53e8c8fdc51b449e329b89838c
--- /dev/null
+++ b/features/steps/profile/profile.rb
@@ -0,0 +1,44 @@
+class Profile < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedPaths
+
+  Then 'I should see my profile info' do
+    page.should have_content "Profile"
+    page.should have_content @user.name
+    page.should have_content @user.email
+  end
+
+  Then 'I change my contact info' do
+    fill_in "user_skype", :with => "testskype"
+    fill_in "user_linkedin", :with => "testlinkedin"
+    fill_in "user_twitter", :with => "testtwitter"
+    click_button "Save"
+    @user.reload
+  end
+
+  And 'I should see new contact info' do
+    @user.skype.should == 'testskype'
+    @user.linkedin.should == 'testlinkedin'
+    @user.twitter.should == 'testtwitter'
+  end
+
+  Then 'I change my password' do
+    fill_in "user_password", :with => "222333"
+    fill_in "user_password_confirmation", :with => "222333"
+    click_button "Save"
+  end
+
+  And 'I should be redirected to sign in page' do
+    current_path.should == new_user_session_path
+  end
+
+  Then 'I reset my token' do
+    @old_token = @user.private_token
+    click_button "Reset"
+  end
+
+  And 'I should see new token' do
+    find("#token").value.should_not == @old_token
+    find("#token").value.should == @user.reload.private_token
+  end
+end
diff --git a/features/steps/profile/profile_ssh_keys.rb b/features/steps/profile/profile_ssh_keys.rb
new file mode 100644
index 0000000000000000000000000000000000000000..96df2d7342fd8e609c2d41cce65123945f035044
--- /dev/null
+++ b/features/steps/profile/profile_ssh_keys.rb
@@ -0,0 +1,48 @@
+class ProfileSshKeys < Spinach::FeatureSteps
+  include SharedAuthentication
+
+  Then 'I should see my ssh keys' do
+    @user.keys.each do |key|
+      page.should have_content(key.title)
+    end
+  end
+
+  Given 'I click link "Add new"' do
+    click_link "Add new"
+  end
+
+  And 'I submit new ssh key "Laptop"' do
+    fill_in "key_title", :with => "Laptop"
+    fill_in "key_key", :with => "ssh-rsa publickey234="
+    click_button "Save"
+  end
+
+  Then 'I should see new ssh key "Laptop"' do
+    key = Key.find_by_title("Laptop")
+    page.should have_content(key.title)
+    page.should have_content(key.key)
+    current_path.should == key_path(key)
+  end
+
+  Given 'I click link "Work"' do
+    click_link "Work"
+  end
+
+  And 'I click link "Remove"' do
+    click_link "Remove"
+  end
+
+  Then 'I visit profile keys page' do
+    visit keys_path
+  end
+
+  And 'I should not see "Work" ssh key' do
+    within "#keys-table" do
+      page.should_not have_content "Work"
+    end
+  end
+
+  And 'I have ssh key "ssh-rsa Work"' do
+    Factory :key, :user => @user, :title => "ssh-rsa Work", :key => "jfKLJDFKSFJSHFJssh-rsa Work"
+  end
+end
diff --git a/features/steps/project/create_project.rb b/features/steps/project/create_project.rb
new file mode 100644
index 0000000000000000000000000000000000000000..6d2ca3f9b568bc126b738f93728ed6a0b73a4aec
--- /dev/null
+++ b/features/steps/project/create_project.rb
@@ -0,0 +1,22 @@
+class CreateProject < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedPaths
+
+  And 'fill project form with valid data' do
+    fill_in 'project_name', :with => 'NewProject'
+    fill_in 'project_code', :with => 'NPR'
+    fill_in 'project_path', :with => 'newproject'
+    click_button "Create project"
+  end
+
+  Then 'I should see project page' do
+    current_path.should == project_path(Project.last)
+    page.should have_content "NewProject"
+  end
+
+  And 'I should see empty project instuctions' do
+    page.should have_content "git init"
+    page.should have_content "git remote"
+    page.should have_content Project.last.url_to_repo
+  end
+end
diff --git a/features/steps/project/project.rb b/features/steps/project/project.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f33f12eb0a8b79eb28905038a1662820c717245f
--- /dev/null
+++ b/features/steps/project/project.rb
@@ -0,0 +1,5 @@
+class Projects < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedProject
+  include SharedPaths
+end
diff --git a/features/steps/project/project_browse_branches.rb b/features/steps/project/project_browse_branches.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2f6e185deea0140e04222b1e26f0b93f9526e7d0
--- /dev/null
+++ b/features/steps/project/project_browse_branches.rb
@@ -0,0 +1,35 @@
+class ProjectBrowseBranches < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedProject
+  include SharedPaths
+
+  Then 'I should see "Shop" recent branches list' do
+    page.should have_content "Branches"
+    page.should have_content "master"
+  end
+
+  Given 'I click link "All"' do
+    click_link "All"
+  end
+
+  Then 'I should see "Shop" all branches list' do
+    page.should have_content "Branches"
+    page.should have_content "master"
+  end
+
+  Given 'I click link "Protected"' do
+    click_link "Protected"
+  end
+
+  Then 'I should see "Shop" protected branches list' do
+    within "table" do
+      page.should have_content "stable"
+      page.should_not have_content "master"
+    end
+  end
+
+  And 'project "Shop" has protected branches' do
+    project = Project.find_by_name("Shop")
+    project.protected_branches.create(:name => "stable")
+  end
+end
diff --git a/features/steps/project/project_browse_commits.rb b/features/steps/project/project_browse_commits.rb
new file mode 100644
index 0000000000000000000000000000000000000000..014799879e80849c54cacbbabd680c9c0e1ddc7f
--- /dev/null
+++ b/features/steps/project/project_browse_commits.rb
@@ -0,0 +1,47 @@
+class ProjectBrowseCommits < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedProject
+  include SharedPaths
+
+  Then 'I see project commits' do
+    current_path.should == project_commits_path(@project)
+
+    commit = @project.commit
+    page.should have_content(@project.name)
+    page.should have_content(commit.message)
+    page.should have_content(commit.id.to_s[0..5])
+  end
+
+  Given 'I click atom feed link' do
+    click_link "Feed"
+  end
+
+  Then 'I see commits atom feed' do
+    commit = CommitDecorator.decorate(@project.commit)
+    page.response_headers['Content-Type'].should have_content("application/atom+xml")
+    page.body.should have_selector("title", :text => "Recent commits to #{@project.name}")
+    page.body.should have_selector("author email", :text => commit.author_email)
+    page.body.should have_selector("entry summary", :text => commit.description)
+  end
+
+  Given 'I click on commit link' do
+    visit project_commit_path(@project, ValidCommit::ID)
+  end
+
+  Then 'I see commit info' do
+    page.should have_content ValidCommit::MESSAGE
+    page.should have_content "Showing 1 changed file"
+  end
+
+  And 'I fill compare fields with refs' do
+    fill_in "from", :with => "master"
+    fill_in "to", :with => "stable"
+    click_button "Compare"
+  end
+
+  And 'I see compared refs' do
+    page.should have_content "Commits (27)"
+    page.should have_content "Compare View"
+    page.should have_content "Showing 73 changed files"
+  end
+end
diff --git a/features/steps/project/project_browse_files.rb b/features/steps/project/project_browse_files.rb
new file mode 100644
index 0000000000000000000000000000000000000000..67c553ced4091e3850842f9029deab1a7aadeeb2
--- /dev/null
+++ b/features/steps/project/project_browse_files.rb
@@ -0,0 +1,34 @@
+class ProjectBrowseFiles < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedProject
+  include SharedPaths
+
+  Then 'I should see files from repository' do
+    page.should have_content "app"
+    page.should have_content "History"
+    page.should have_content "Gemfile"
+  end
+
+  Then 'I should see files from repository for "8470d70"' do
+    current_path.should == tree_project_ref_path(@project, "8470d70")
+    page.should have_content "app"
+    page.should have_content "History"
+    page.should have_content "Gemfile"
+  end
+
+  Given 'I click on "Gemfile" file in repo' do
+    click_link "Gemfile"
+  end
+
+  Then 'I should see it content' do
+    page.should have_content "rubygems.org"
+  end
+
+  And 'I click link "raw"' do
+    click_link "raw"
+  end
+
+  Then 'I should see raw file content' do
+    page.source.should == ValidCommit::BLOB_FILE
+  end
+end
diff --git a/features/steps/project/project_browse_git_repo.rb b/features/steps/project/project_browse_git_repo.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e966f40773843c7be6b362937fdd3b07426cf115
--- /dev/null
+++ b/features/steps/project/project_browse_git_repo.rb
@@ -0,0 +1,19 @@
+class ProjectBrowseGitRepo < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedProject
+  include SharedPaths
+
+  Given 'I click on "Gemfile" file in repo' do
+    click_link "Gemfile"
+  end
+
+  And 'I click blame button' do
+    click_link "blame"
+  end
+
+  Then 'I should see git file blame' do
+    page.should have_content "rubygems.org"
+    page.should have_content "Dmitriy Zaporozhets"
+    page.should have_content "bc3735004cb Moving to rails 3.2"
+  end
+end
diff --git a/features/steps/project/project_browse_tags.rb b/features/steps/project/project_browse_tags.rb
new file mode 100644
index 0000000000000000000000000000000000000000..0cbfa0d80aaf33d0637fa2b2e5e53be1630ebb39
--- /dev/null
+++ b/features/steps/project/project_browse_tags.rb
@@ -0,0 +1,10 @@
+class ProjectBrowseTags < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedProject
+  include SharedPaths
+
+  Then 'I should see "Shop" all tags list' do
+    page.should have_content "Tags"
+    page.should have_content "v1.2.1"
+  end
+end
diff --git a/features/steps/project/project_comment_commit.rb b/features/steps/project/project_comment_commit.rb
new file mode 100644
index 0000000000000000000000000000000000000000..cb8385e1ce56b9b478d1a90c4b5645ce15422578
--- /dev/null
+++ b/features/steps/project/project_comment_commit.rb
@@ -0,0 +1,6 @@
+class ProjectCommentCommit < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedProject
+  include SharedNote
+  include SharedPaths
+end
diff --git a/features/steps/project/project_issues.rb b/features/steps/project/project_issues.rb
new file mode 100644
index 0000000000000000000000000000000000000000..64af24490aa3ce4753f2783aaddcc17cc3347312
--- /dev/null
+++ b/features/steps/project/project_issues.rb
@@ -0,0 +1,134 @@
+class ProjectIssues < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedProject
+  include SharedNote
+  include SharedPaths
+
+  Given 'I should see "Release 0.4" in issues' do
+    page.should have_content "Release 0.4"
+  end
+
+  And 'I should not see "Release 0.3" in issues' do
+    page.should_not have_content "Release 0.3"
+  end
+
+  Given 'I click link "Closed"' do
+    click_link "Closed"
+  end
+
+  Then 'I should see "Release 0.3" in issues' do
+    page.should have_content "Release 0.3"
+  end
+
+  And 'I should not see "Release 0.4" in issues' do
+    page.should_not have_content "Release 0.4"
+  end
+
+  Given 'I click link "All"' do
+    click_link "All"
+  end
+
+  Given 'I click link "Release 0.4"' do
+    click_link "Release 0.4"
+  end
+
+  Then 'I should see issue "Release 0.4"' do
+    page.should have_content "Release 0.4"
+  end
+
+  Given 'I click link "New Issue"' do
+    click_link "New Issue"
+  end
+
+  And 'I submit new issue "500 error on profile"' do
+    fill_in "issue_title", :with => "500 error on profile"
+    click_button "Submit new issue"
+  end
+
+  Given 'I click link "500 error on profile"' do
+    click_link "500 error on profile"
+  end
+
+  Then 'I should see issue "500 error on profile"' do
+    issue = Issue.find_by_title("500 error on profile")
+    page.should have_content issue.title
+    page.should have_content issue.author_name
+    page.should have_content issue.project.name
+  end
+
+  Given 'I fill in issue search with "Release"' do
+    fill_in 'issue_search', with: "Release"
+  end
+
+  Given 'I fill in issue search with "Bug"' do
+    fill_in 'issue_search', with: "Bug"
+  end
+
+  And 'I fill in issue search with "0.3"' do
+    fill_in 'issue_search', with: "0.3"
+  end
+
+  And 'I fill in issue search with "Something"' do
+    fill_in 'issue_search', with: "Something"
+  end
+
+  And 'I fill in issue search with ""' do
+    page.execute_script("$('.issue_search').val('').keyup();");
+    fill_in 'issue_search', with: ""
+  end
+
+  Given 'project "Shop" has milestone "v2.2"' do
+    project = Project.find_by_name("Shop")
+    milestone = Factory :milestone, :title => "v2.2", :project => project
+
+    3.times { Factory :issue, :project => project, :milestone => milestone }
+  end
+
+  And 'project "Shop" has milestone "v3.0"' do
+    project = Project.find_by_name("Shop")
+    milestone = Factory :milestone, :title => "v3.0", :project => project
+
+    3.times { Factory :issue, :project => project, :milestone => milestone }
+  end
+
+  When 'I select milestone "v3.0"' do
+    select "v3.0", from: "milestone_id"
+  end
+
+  Then 'I should see selected milestone with title "v3.0"' do
+    issues_milestone_selector = "#issue_milestone_id_chzn/a"
+    wait_until { page.has_content?("Details") }
+    page.find(issues_milestone_selector).should have_content("v3.0")
+  end
+
+  When 'I select first assignee from "Shop" project' do
+    project = Project.find_by_name "Shop"
+    first_assignee = project.users.first
+    select first_assignee.name, from: "assignee_id"
+  end
+
+  Then 'I should see first assignee from "Shop" as selected assignee' do
+    issues_assignee_selector = "#issue_assignee_id_chzn/a"
+    wait_until { page.has_content?("Details") }
+    project = Project.find_by_name "Shop"
+    assignee_name = project.users.first.name
+    page.find(issues_assignee_selector).should have_content(assignee_name)
+  end
+
+  And 'project "Shop" have "Release 0.4" open issue' do
+    project = Project.find_by_name("Shop")
+    Factory.create(:issue,
+      :title => "Release 0.4",
+      :project => project,
+      :author => project.users.first)
+  end
+
+  And 'project "Shop" have "Release 0.3" closed issue' do
+    project = Project.find_by_name("Shop")
+    Factory.create(:issue,
+      :title => "Release 0.3",
+      :project => project,
+      :author => project.users.first,
+      :closed => true)
+  end
+end
diff --git a/features/steps/project/project_labels.rb b/features/steps/project/project_labels.rb
new file mode 100644
index 0000000000000000000000000000000000000000..1a347bf358f6c1ce8edb116f27a4737a03c166d3
--- /dev/null
+++ b/features/steps/project/project_labels.rb
@@ -0,0 +1,24 @@
+class ProjectLabels < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedProject
+  include SharedPaths
+
+  Then 'I should see label "bug"' do
+    within ".labels-table" do
+      page.should have_content "bug"
+    end
+  end
+
+  And 'I should see label "feature"' do
+    within ".labels-table" do
+      page.should have_content "feature"
+    end
+  end
+
+  And 'project "Shop" have issues tags: "bug", "feature"' do
+    project = Project.find_by_name("Shop")
+    ['bug', 'feature'].each do |label|
+      Factory :issue, project: project, label_list: label
+    end
+  end
+end
diff --git a/features/steps/project/project_merge_requests.rb b/features/steps/project/project_merge_requests.rb
new file mode 100644
index 0000000000000000000000000000000000000000..80e83906c723e93ff069857f7b29fd3e4982e500
--- /dev/null
+++ b/features/steps/project/project_merge_requests.rb
@@ -0,0 +1,80 @@
+class ProjectMergeRequests < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedProject
+  include SharedNote
+  include SharedPaths
+
+  Then 'I should see "Bug NS-04" in merge requests' do
+    page.should have_content "Bug NS-04"
+  end
+
+  And 'I should not see "Feature NS-03" in merge requests' do
+    page.should_not have_content "Feature NS-03"
+  end
+
+  Given 'I click link "Closed"' do
+    click_link "Closed"
+  end
+
+  Then 'I should see "Feature NS-03" in merge requests' do
+    page.should have_content "Feature NS-03"
+  end
+
+  And 'I should not see "Bug NS-04" in merge requests' do
+    page.should_not have_content "Bug NS-04"
+  end
+
+  Given 'I click link "All"' do
+    click_link "All"
+  end
+
+  Given 'I click link "Bug NS-04"' do
+    click_link "Bug NS-04"
+  end
+
+  Then 'I should see merge request "Bug NS-04"' do
+    page.should have_content "Bug NS-04"
+  end
+
+  And 'I click link "Close"' do
+    click_link "Close"
+  end
+
+  Then 'I should see closed merge request "Bug NS-04"' do
+    mr = MergeRequest.find_by_title("Bug NS-04")
+    mr.closed.should be_true
+    page.should have_content "Closed by"
+  end
+
+  Given 'I click link "New Merge Request"' do
+    click_link "New Merge Request"
+  end
+
+  And 'I submit new merge request "Wiki Feature"' do
+    fill_in "merge_request_title", :with => "Wiki Feature"
+    select "master", :from => "merge_request_source_branch"
+    select "stable", :from => "merge_request_target_branch"
+    click_button "Save"
+  end
+
+  Then 'I should see merge request "Wiki Feature"' do
+    page.should have_content "Wiki Feature"
+  end
+
+  And 'project "Shop" have "Bug NS-04" open merge request' do
+    project = Project.find_by_name("Shop")
+    Factory.create(:merge_request,
+      :title => "Bug NS-04",
+      :project => project,
+      :author => project.users.first)
+  end
+
+  And 'project "Shop" have "Feature NS-03" closed merge request' do
+    project = Project.find_by_name("Shop")
+    Factory.create(:merge_request,
+      :title => "Feature NS-03",
+      :project => project,
+      :author => project.users.first,
+      :closed => true)
+  end
+end
diff --git a/features/steps/project/project_milestones.rb b/features/steps/project/project_milestones.rb
new file mode 100644
index 0000000000000000000000000000000000000000..83ed6859f1b1a2f8247255747338fcd7c0456eff
--- /dev/null
+++ b/features/steps/project/project_milestones.rb
@@ -0,0 +1,39 @@
+class ProjectMilestones < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedProject
+  include SharedPaths
+
+  Then 'I should see milestone "v2.2"' do
+    milestone = @project.milestones.find_by_title("v2.2")
+    page.should have_content(milestone.title[0..10])
+    page.should have_content(milestone.expires_at)
+    page.should have_content("Browse Issues")
+  end
+
+  Given 'I click link "v2.2"' do
+    click_link "v2.2"
+  end
+
+  Given 'I click link "New Milestone"' do
+    click_link "New Milestone"
+  end
+
+  And 'I submit new milestone "v2.3"' do
+    fill_in "milestone_title", :with => "v2.3"
+    click_button "Create milestone"
+  end
+
+  Then 'I should see milestone "v2.3"' do
+    milestone = @project.milestones.find_by_title("v2.3")
+    page.should have_content(milestone.title[0..10])
+    page.should have_content(milestone.expires_at)
+    page.should have_content("Browse Issues")
+  end
+
+  And 'project "Shop" has milestone "v2.2"' do
+    project = Project.find_by_name("Shop")
+    milestone = Factory :milestone, :title => "v2.2", :project => project
+
+    3.times { Factory :issue, :project => project, :milestone => milestone }
+  end
+end
diff --git a/features/steps/project/project_network_graph.rb b/features/steps/project/project_network_graph.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f34a81a408d0866d97958543a22e0eabe9f9ff94
--- /dev/null
+++ b/features/steps/project/project_network_graph.rb
@@ -0,0 +1,22 @@
+class ProjectNetworkGraph < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedProject
+
+  Then 'page should have network graph' do
+    page.should have_content "Project Network Graph"
+    within ".graph" do
+      page.should have_content "master"
+      page.should have_content "scss_refactor..."
+    end
+  end
+
+  And 'I visit project "Shop" network page' do
+    project = Project.find_by_name("Shop")
+
+    # Stub out find_all to speed this up (10 commits vs. 650)
+    commits = Grit::Commit.find_all(project.repo, nil, {max_count: 10})
+    Grit::Commit.stub(:find_all).and_return(commits)
+
+    visit graph_project_path(project)
+  end
+end
diff --git a/features/steps/project/project_team_management.rb b/features/steps/project/project_team_management.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7beca257e36a4a505533f63ef133bd67803795a2
--- /dev/null
+++ b/features/steps/project/project_team_management.rb
@@ -0,0 +1,89 @@
+class ProjectTeamManagement < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedProject
+  include SharedPaths
+
+  Then 'I should be able to see myself in team' do
+    page.should have_content(@user.name)
+    page.should have_content(@user.email)
+  end
+
+  And 'I should see "Sam" in team list' do
+    user = User.find_by_name("Sam")
+    page.should have_content(user.name)
+    page.should have_content(user.email)
+  end
+
+  Given 'I click link "New Team Member"' do
+    click_link "New Team Member"
+  end
+
+  And 'I select "Mike" as "Reporter"' do
+    user = User.find_by_name("Mike")
+    within "#new_team_member" do
+      select user.name, :from => "user_ids"
+      select "Reporter", :from => "project_access"
+    end
+    click_button "Save"
+  end
+
+  Then 'I should see "Mike" in team list as "Reporter"' do
+    user = User.find_by_name("Mike")
+    role_id = find(".user_#{user.id} #team_member_project_access").value
+    role_id.should == UsersProject.access_roles["Reporter"].to_s
+  end
+
+  Given 'I should see "Sam" in team list as "Developer"' do
+    user = User.find_by_name("Sam")
+    role_id = find(".user_#{user.id} #team_member_project_access").value
+    role_id.should == UsersProject.access_roles["Developer"].to_s
+  end
+
+  And 'I change "Sam" role to "Reporter"' do
+    user = User.find_by_name("Sam")
+    within ".user_#{user.id}" do
+      select "Reporter", :from => "team_member_project_access"
+    end
+  end
+
+  And 'I should see "Sam" in team list as "Reporter"' do
+    user = User.find_by_name("Sam")
+    role_id = find(".user_#{user.id} #team_member_project_access").value
+    role_id.should == UsersProject.access_roles["Reporter"].to_s
+  end
+
+  Given 'I click link "Sam"' do
+    click_link "Sam"
+  end
+
+  Then 'I should see "Sam" team profile' do
+    user = User.find_by_name("Sam")
+    page.should have_content(user.name)
+    page.should have_content(user.email)
+    page.should have_content("To team list")
+  end
+
+  And 'I click link "Remove from team"' do
+    click_link "Remove from team"
+  end
+
+  And 'I should not see "Sam" in team list' do
+    user = User.find_by_name("Sam")
+    page.should_not have_content(user.name)
+    page.should_not have_content(user.email)
+  end
+
+  And 'gitlab user "Mike"' do
+    Factory :user, :name => "Mike"
+  end
+
+  And 'gitlab user "Sam"' do
+    Factory :user, :name => "Sam"
+  end
+
+  And '"Sam" is "Shop" developer' do
+    user = User.find_by_name("Sam")
+    project = Project.find_by_name("Shop")
+    project.add_access(user, :write)
+  end
+end
diff --git a/features/steps/project/project_wall.rb b/features/steps/project/project_wall.rb
new file mode 100644
index 0000000000000000000000000000000000000000..ba9d3533b2cd68a3048bf48940eb2a4e068e815b
--- /dev/null
+++ b/features/steps/project/project_wall.rb
@@ -0,0 +1,6 @@
+class ProjectWall < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedProject
+  include SharedNote
+  include SharedPaths
+end
diff --git a/features/steps/project/project_wiki.rb b/features/steps/project/project_wiki.rb
new file mode 100644
index 0000000000000000000000000000000000000000..902e9ce158ca19137372ae721ab703ad2a15161e
--- /dev/null
+++ b/features/steps/project/project_wiki.rb
@@ -0,0 +1,20 @@
+class ProjectWiki < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedProject
+  include SharedNote
+  include SharedPaths
+
+  Given 'I create Wiki page' do
+    fill_in "Title", :with => 'Test title'
+    fill_in "Content", :with => '[link test](test)'
+    click_on "Save"
+  end
+
+  Then 'I should see newly created wiki page' do
+    page.should have_content "Test title"
+    page.should have_content "link test"
+
+    click_link "link test"
+    page.should have_content "Editing page"
+  end
+end
diff --git a/features/steps/shared/authentication.rb b/features/steps/shared/authentication.rb
new file mode 100644
index 0000000000000000000000000000000000000000..77d9839f5b7f31d8309fb0ad92d7d45b4bcf2d64
--- /dev/null
+++ b/features/steps/shared/authentication.rb
@@ -0,0 +1,10 @@
+require Rails.root.join('spec', 'support', 'login_helpers')
+
+module SharedAuthentication
+  include Spinach::DSL
+  include LoginHelpers
+
+  Given 'I sign in as a user' do
+    login_as :user
+  end
+end
diff --git a/features/steps/shared/note.rb b/features/steps/shared/note.rb
new file mode 100644
index 0000000000000000000000000000000000000000..923e69b6b073da9cf8a461319a2c0e5ae86dfa7b
--- /dev/null
+++ b/features/steps/shared/note.rb
@@ -0,0 +1,21 @@
+module SharedNote
+  include Spinach::DSL
+
+  Given 'I leave a comment like "XML attached"' do
+    fill_in "note_note", :with => "XML attached"
+    click_button "Add Comment"
+  end
+
+  Then 'I should see comment "XML attached"' do
+    page.should have_content "XML attached"
+  end
+
+  Given 'I write new comment "my special test message"' do
+    fill_in "note_note", :with => "my special test message"
+    click_button "Add Comment"
+  end
+
+  Then 'I should see project wall note "my special test message"' do
+    page.should have_content "my special test message"
+  end
+end
diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb
new file mode 100644
index 0000000000000000000000000000000000000000..93ad0219d3dcd1608b78cdb64756d316da4c15b7
--- /dev/null
+++ b/features/steps/shared/paths.rb
@@ -0,0 +1,112 @@
+module SharedPaths
+  include Spinach::DSL
+
+  And 'I visit dashboard search page' do
+    visit search_path
+  end
+
+  And 'I visit dashboard merge requests page' do
+    visit dashboard_merge_requests_path
+  end
+
+  And 'I visit dashboard issues page' do
+    visit dashboard_issues_path
+  end
+
+  When 'I visit dashboard page' do
+    visit dashboard_path
+  end
+
+  Given 'I visit profile page' do
+    visit profile_path
+  end
+
+  Given 'I visit profile account page' do
+    visit profile_account_path
+  end
+
+  Given 'I visit profile token page' do
+    visit profile_token_path
+  end
+
+  When 'I visit new project page' do
+    visit new_project_path
+  end
+
+  And 'I visit project "Shop" page' do
+    project = Project.find_by_name("Shop")
+    visit project_path(project)
+  end
+
+  Given 'I visit project branches page' do
+    visit branches_project_repository_path(@project)
+  end
+
+  Given 'I visit compare refs page' do
+    visit compare_project_commits_path(@project)
+  end
+
+  Given 'I visit project commits page' do
+    visit project_commits_path(@project)
+  end
+
+  Given 'I visit project source page' do
+    visit tree_project_ref_path(@project, @project.root_ref)
+  end
+
+  Given 'I visit blob file from repo' do
+    visit tree_project_ref_path(@project, ValidCommit::ID, :path => ValidCommit::BLOB_FILE_PATH)
+  end
+
+  Given 'I visit project source page for "8470d70"' do
+    visit tree_project_ref_path(@project, "8470d70")
+  end
+
+  Given 'I visit project tags page' do
+    visit tags_project_repository_path(@project)
+  end
+
+  Given 'I visit project commit page' do
+    visit project_commit_path(@project, ValidCommit::ID)
+  end
+
+  And 'I visit project "Shop" issues page' do
+    visit project_issues_path(Project.find_by_name("Shop"))
+  end
+
+  Given 'I visit issue page "Release 0.4"' do
+    issue = Issue.find_by_title("Release 0.4")
+    visit project_issue_path(issue.project, issue)
+  end
+
+  Given 'I visit project "Shop" labels page' do
+    visit project_labels_path(Project.find_by_name("Shop"))
+  end
+
+  Given 'I visit merge request page "Bug NS-04"' do
+    mr = MergeRequest.find_by_title("Bug NS-04")
+    visit project_merge_request_path(mr.project, mr)
+  end
+
+  And 'I visit project "Shop" merge requests page' do
+    visit project_merge_requests_path(Project.find_by_name("Shop"))
+  end
+
+  Given 'I visit project "Shop" milestones page' do
+    @project = Project.find_by_name("Shop")
+    visit project_milestones_path(@project)
+  end
+
+  Then 'I visit project "Shop" team page' do
+    visit project_team_index_path(Project.find_by_name("Shop"))
+  end
+
+  Then 'I visit project "Shop" wall page' do
+    project = Project.find_by_name("Shop")
+    visit wall_project_path(project)
+  end
+
+  Given 'I visit project wiki page' do
+    visit project_wiki_path(@project, :index)
+  end
+end
diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb
new file mode 100644
index 0000000000000000000000000000000000000000..9b64ca59a3b87d59e537f66a688008205c93fdd1
--- /dev/null
+++ b/features/steps/shared/project.rb
@@ -0,0 +1,8 @@
+module SharedProject
+  include Spinach::DSL
+
+  And 'I own project "Shop"' do
+    @project = Factory :project, :name => "Shop"
+    @project.add_access(@user, :admin)
+  end
+end
diff --git a/features/support/env.rb b/features/support/env.rb
index b69a5fe7f072c546c9b92d004c42262aa8a20d94..9c6cef07298cf51c0813685bcf82c4654b53016c 100644
--- a/features/support/env.rb
+++ b/features/support/env.rb
@@ -1,50 +1,27 @@
-unless ENV['CI']
-  require 'simplecov'
-  SimpleCov.start 'rails'
-end
+ENV['RAILS_ENV'] = 'test'
+require './config/environment'
 
-require 'cucumber/rails'
-require 'webmock/cucumber'
-WebMock.allow_net_connect!
+require 'rspec'
+require 'database_cleaner'
+require 'spinach/capybara'
 
-require Rails.root.join 'spec/monkeypatch'
-require Rails.root.join 'spec/factories'
-require Rails.root.join 'spec/support/login'
-require Rails.root.join 'spec/support/valid_commit'
+%w(gitolite_stub stubbed_repository valid_commit).each do |f|
+  require Rails.root.join('spec', 'support', f)
+end
 
-Capybara.default_selector = :css
-Capybara.javascript_driver = :webkit
+Dir["#{Rails.root}/features/steps/shared/*.rb"].each {|file| require file}
 
-# By default, any exception happening in your Rails application will bubble up
-# to Cucumber so that your scenario will fail. This is a different from how
-# your application behaves in the production environment, where an error page will
-# be rendered instead.
-#
-# Sometimes we want to override this default behaviour and allow Rails to rescue
-# exceptions and display an error page (just like when the app is running in production).
-# Typical scenarios where you want to do this is when you test your error pages.
-# There are two ways to allow Rails to rescue exceptions:
-#
-# 1) Tag your scenario (or feature) with @allow-rescue
-#
-# 2) Set the value below to true. Beware that doing this globally is not
-# recommended as it will mask a lot of errors for you!
-#
-ActionController::Base.allow_rescue = false
-
-# Remove/comment out the lines below if your app doesn't have a database.
-# For some databases (like MongoDB and CouchDB) you may need to use :truncation instead.
-begin
-  DatabaseCleaner.strategy = :transaction
-rescue NameError
-  raise "You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it."
-end
+include GitoliteStub
 
-Cucumber::Rails::Database.javascript_strategy = :truncation
+WebMock.allow_net_connect!
+Capybara.javascript_driver = :webkit
 
-require 'headless'
+DatabaseCleaner.strategy = :truncation
+Spinach.hooks.before_scenario { DatabaseCleaner.start }
+Spinach.hooks.after_scenario  { DatabaseCleaner.clean }
 
-headless = Headless.new
-headless.start
+Spinach.hooks.before_run do
+  RSpec::Mocks::setup self
 
-require 'cucumber/rspec/doubles'
+  stub_gitolite!
+end
diff --git a/gitlab b/gitlab
new file mode 100755
index 0000000000000000000000000000000000000000..acafb3f10c44f92c0fab3ff83f7bda01255baf63
--- /dev/null
+++ b/gitlab
@@ -0,0 +1,75 @@
+#!/usr/bin/env ruby
+
+class GitlabCli
+  def initialize
+    @path = File.dirname(__FILE__)
+    @command = ARGV.shift
+    @mode = ARGV.shift
+  end
+
+  def execute
+    case @command
+    when 'start' then start
+    when 'stop' then stop
+    else
+      puts "-- Usage gitlab start production or gitlab stop development"
+    end
+  end
+
+  private
+
+  def start
+    case @mode
+    when 'production';
+      system(unicorn_start_cmd)
+      system(resque_start_cmd)
+    else
+      system(rails_start_cmd)
+      system(resque_dev_start_cmd)
+    end
+  end
+
+  def stop
+    case @mode
+    when 'production';
+      system(unicorn_stop_cmd)
+    else
+      system(rails_stop_cmd)
+    end
+    system(resque_stop_cmd)
+  end
+
+  def rails_start_cmd
+    "bundle exec rails s -d"
+  end
+
+  def rails_stop_cmd
+    pid = File.join(@path, "tmp/pids/server.pid")
+    "kill -QUIT `cat #{pid}`"
+  end
+
+  def unicorn_start_cmd
+    unicorn_conf  = File.join(@path, "config/unicorn.rb")
+    "bundle exec unicorn_rails -c #{unicorn_conf} -E production -D"
+  end
+
+  def unicorn_stop_cmd
+    pid = File.join(@path, "/tmp/pids/unicorn.pid")
+    "kill -QUIT `cat #{pid}`"
+  end
+
+  def resque_dev_start_cmd
+    "./resque_dev.sh > /dev/null 2>&1"
+  end
+
+  def resque_start_cmd
+    "./resque.sh > /dev/null 2>&1"
+  end
+
+  def resque_stop_cmd
+    pid = File.join(@path, "tmp/pids/resque_worker.pid")
+    "kill -QUIT `cat #{pid}`"
+  end
+end
+
+GitlabCli.new.execute
diff --git a/lib/api.rb b/lib/api.rb
index 3ff3b3836f4f6f8e1f983d03cd62a7a972aeba17..2890a8cc9e8f13e2881f001ec7389dfe19f28728 100644
--- a/lib/api.rb
+++ b/lib/api.rb
@@ -16,5 +16,7 @@ module Gitlab
     mount Users
     mount Projects
     mount Issues
+    mount Milestones
+    mount Session
   end
 end
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 96ccd87a4074a1cd4643143b9682428b8b246563..ee693de699e21c389a6796585b0fc389ad18d81a 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -9,6 +9,14 @@ module Gitlab
       expose :id, :email, :name, :blocked, :created_at
     end
 
+    class UserLogin < UserBasic
+      expose :private_token
+    end
+
+    class Hook < Grape::Entity
+      expose :id, :url
+    end
+
     class Project < Grape::Entity
       expose :id, :code, :name, :description, :path, :default_branch
       expose :owner, using: Entities::UserBasic
@@ -16,10 +24,20 @@ module Gitlab
       expose :issues_enabled, :merge_requests_enabled, :wall_enabled, :wiki_enabled, :created_at
     end
 
+    class ProjectMember < UserBasic
+      expose :project_access, :as => :access_level do |user, options|
+        options[:project].users_projects.find_by_user_id(user.id).project_access
+      end
+    end
+
     class RepoObject < Grape::Entity
       expose :name, :commit
     end
 
+    class RepoCommit < Grape::Entity
+      expose :id, :short_id, :title, :author_name, :author_email, :created_at
+    end
+
     class ProjectSnippet < Grape::Entity
       expose :id, :title, :file_name
       expose :author, using: Entities::UserBasic
@@ -27,7 +45,9 @@ module Gitlab
     end
 
     class Milestone < Grape::Entity
-      expose :id, :title, :description, :due_date, :closed, :updated_at, :created_at
+      expose :id
+      expose (:project_id) {|milestone| milestone.project.id}
+      expose :title, :description, :due_date, :closed, :updated_at, :created_at
     end
 
     class Issue < Grape::Entity
@@ -39,5 +59,9 @@ module Gitlab
       expose :assignee, :author, using: Entities::UserBasic
       expose :closed, :updated_at, :created_at
     end
+
+    class SSHKey < Grape::Entity
+      expose :id, :title, :key
+    end
   end
 end
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index c1ea05667aebb1e10922c67fd25cc10b2d090c6b..14390545bd5eb1030a3c8a01f1f831e3b643f901 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -8,14 +8,67 @@ module Gitlab
       if @project ||= current_user.projects.find_by_id(params[:id]) ||
                       current_user.projects.find_by_code(params[:id])
       else
-        error!({'message' => '404 Not found'}, 404)
+        not_found!
       end
 
       @project
     end
 
+    def paginate(object)
+      object.page(params[:page]).per(params[:per_page].to_i)
+    end
+
     def authenticate!
-      error!({'message' => '401 Unauthorized'}, 401) unless current_user
+      unauthorized! unless current_user
+    end
+
+    def authorize! action, subject
+      unless abilities.allowed?(current_user, action, subject)
+        forbidden!
+      end
+    end
+
+    def attributes_for_keys(keys)
+      attrs = {}
+      keys.each do |key|
+        attrs[key] = params[key] if params[key].present?
+      end
+      attrs
+    end
+
+    # error helpers
+
+    def forbidden!
+      render_api_error!('403 Forbidden', 403)
+    end
+
+    def not_found!(resource = nil)
+      message = ["404"]
+      message << resource if resource
+      message << "Not Found"
+      render_api_error!(message.join(' '), 404)
+    end
+
+    def unauthorized!
+      render_api_error!('401 Unauthorized', 401)
+    end
+
+    def not_allowed!
+      render_api_error!('Method Not Allowed', 405)
+    end
+
+    def render_api_error!(message, status)
+      error!({'message' => message}, status)
+    end
+
+    private
+
+    def abilities
+      @abilities ||= begin
+                       abilities = Six.new
+                       abilities << Ability
+                       abilities
+                     end
     end
   end
 end
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index 2abc20ad34ebae4d4d7e36b4c4ea5f5250a83f72..4ee2d11f15febf8382493141c8c02167bc935d92 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -9,7 +9,7 @@ module Gitlab
       # Example Request:
       #   GET /issues
       get do
-        present current_user.issues, with: Entities::Issue
+        present paginate(current_user.issues), with: Entities::Issue
       end
     end
 
@@ -21,7 +21,7 @@ module Gitlab
       # Example Request:
       #   GET /projects/:id/issues
       get ":id/issues" do
-        present user_project.issues, with: Entities::Issue
+        present paginate(user_project.issues), with: Entities::Issue
       end
 
       # Get a single project issue
@@ -48,19 +48,14 @@ module Gitlab
       # Example Request:
       #   POST /projects/:id/issues
       post ":id/issues" do
-        @issue = user_project.issues.new(
-          title: params[:title],
-          description: params[:description],
-          assignee_id: params[:assignee_id],
-          milestone_id: params[:milestone_id],
-          label_list: params[:labels]
-        )
+        attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id]
+        attrs[:label_list] = params[:labels] if params[:labels].present?
+        @issue = user_project.issues.new attrs
         @issue.author = current_user
-
         if @issue.save
           present @issue, with: Entities::Issue
         else
-          error!({'message' => '404 Not found'}, 404)
+          not_found!
         end
       end
 
@@ -79,23 +74,18 @@ module Gitlab
       #   PUT /projects/:id/issues/:issue_id
       put ":id/issues/:issue_id" do
         @issue = user_project.issues.find(params[:issue_id])
-        parameters = {
-          title: (params[:title] || @issue.title),
-          description: (params[:description] || @issue.description),
-          assignee_id: (params[:assignee_id] || @issue.assignee_id),
-          milestone_id: (params[:milestone_id] || @issue.milestone_id),
-          label_list: (params[:labels] || @issue.label_list),
-          closed: (params[:closed] || @issue.closed)
-        }
+        authorize! :modify_issue, @issue
 
-        if @issue.update_attributes(parameters)
+        attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id, :closed]
+        attrs[:label_list] = params[:labels] if params[:labels].present?
+        if @issue.update_attributes attrs
           present @issue, with: Entities::Issue
         else
-          error!({'message' => '404 Not found'}, 404)
+          not_found!
         end
       end
 
-      # Delete a project issue
+      # Delete a project issue (deprecated)
       #
       # Parameters:
       #   id (required) - The ID or code name of a project
@@ -103,8 +93,7 @@ module Gitlab
       # Example Request:
       #   DELETE /projects/:id/issues/:issue_id
       delete ":id/issues/:issue_id" do
-        @issue = user_project.issues.find(params[:issue_id])
-        @issue.destroy
+        not_allowed!
       end
     end
   end
diff --git a/lib/api/milestones.rb b/lib/api/milestones.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f55dfd04cc5b593c34c241708a5126e8fb876041
--- /dev/null
+++ b/lib/api/milestones.rb
@@ -0,0 +1,78 @@
+module Gitlab
+  # Milestones API
+  class Milestones < Grape::API
+    before { authenticate! }
+
+    resource :projects do
+      # Get a list of project milestones
+      #
+      # Parameters:
+      #   id (required) - The ID or code name of a project
+      # Example Request:
+      #   GET /projects/:id/milestones
+      get ":id/milestones" do
+        authorize! :read_milestone, user_project
+
+        present paginate(user_project.milestones), with: Entities::Milestone
+      end
+
+      # Get a single project milestone
+      #
+      # Parameters:
+      #   id (required) - The ID or code name of a project
+      #   milestone_id (required) - The ID of a project milestone
+      # Example Request:
+      #   GET /projects/:id/milestones/:milestone_id
+      get ":id/milestones/:milestone_id" do
+        authorize! :read_milestone, user_project
+
+        @milestone = user_project.milestones.find(params[:milestone_id])
+        present @milestone, with: Entities::Milestone
+      end
+
+      # Create a new project milestone
+      #
+      # Parameters:
+      #   id (required) - The ID or code name of the project
+      #   title (required) - The title of the milestone
+      #   description (optional) - The description of the milestone
+      #   due_date (optional) - The due date of the milestone
+      # Example Request:
+      #   POST /projects/:id/milestones
+      post ":id/milestones" do
+        authorize! :admin_milestone, user_project
+
+        attrs = attributes_for_keys [:title, :description, :due_date]
+        @milestone = user_project.milestones.new attrs
+        if @milestone.save
+          present @milestone, with: Entities::Milestone
+        else
+          not_found!
+        end
+      end
+
+      # Update an existing project milestone
+      #
+      # Parameters:
+      #   id (required) - The ID or code name of a project
+      #   milestone_id (required) - The ID of a project milestone
+      #   title (optional) - The title of a milestone
+      #   description (optional) - The description of a milestone
+      #   due_date (optional) - The due date of a milestone
+      #   closed (optional) - The status of the milestone
+      # Example Request:
+      #   PUT /projects/:id/milestones/:milestone_id
+      put ":id/milestones/:milestone_id" do
+        authorize! :admin_milestone, user_project
+
+        @milestone = user_project.milestones.find(params[:milestone_id])
+        attrs = attributes_for_keys [:title, :description, :due_date, :closed]
+        if @milestone.update_attributes attrs
+          present @milestone, with: Entities::Milestone
+        else
+          not_found!
+        end
+      end
+    end
+  end
+end
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index eb23641c605dd34807958a320240d01796d5d5c2..c3dc3da6facd5a35d542f35bd2dfe3bc9ef3648f 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -9,7 +9,7 @@ module Gitlab
       # Example Request:
       #   GET /projects
       get do
-        @projects = current_user.projects
+        @projects = paginate current_user.projects
         present @projects, with: Entities::Project
       end
 
@@ -23,6 +23,162 @@ module Gitlab
         present user_project, with: Entities::Project
       end
 
+      # Create new project
+      #
+      # Parameters:
+      #   name (required) - name for new project
+      #   code (optional) - code for new project, uses project name if not set
+      #   path (optional) - path for new project, uses project name if not set
+      #   description (optional) - short project description
+      #   default_branch (optional) - 'master' by default
+      #   issues_enabled (optional) - enabled by default
+      #   wall_enabled (optional) - enabled by default
+      #   merge_requests_enabled (optional) - enabled by default
+      #   wiki_enabled (optional) - enabled by default
+      # Example Request
+      #   POST /projects
+      post do
+        params[:code] ||= params[:name]
+        params[:path] ||= params[:name]
+        attrs = attributes_for_keys [:code,
+                                    :path,
+                                    :name,
+                                    :description,
+                                    :default_branch,
+                                    :issues_enabled,
+                                    :wall_enabled,
+                                    :merge_requests_enabled,
+                                    :wiki_enabled]
+        @project = Project.create_by_user(attrs, current_user)
+        if @project.saved?
+          present @project, with: Entities::Project
+        else
+          not_found!
+        end
+      end
+
+      # Get a project team members
+      #
+      # Parameters:
+      #   id (required) - The ID or code name of a project
+      # Example Request:
+      #   GET /projects/:id/members
+      get ":id/members" do
+        @members = paginate user_project.users
+        present @members, with: Entities::ProjectMember, project: user_project
+      end
+
+      # Get a project team members
+      #
+      # Parameters:
+      #   id (required) - The ID or code name of a project
+      #   user_id (required) - The ID of a user
+      # Example Request:
+      #   GET /projects/:id/members/:user_id
+      get ":id/members/:user_id" do
+        @member = user_project.users.find params[:user_id]
+        present @member, with: Entities::ProjectMember, project: user_project
+      end
+
+      # Add a new project team member
+      #
+      # Parameters:
+      #   id (required) - The ID or code name of a project
+      #   user_id (required) - The ID of a user
+      #   access_level (required) - Project access level
+      # Example Request:
+      #   POST /projects/:id/members
+      post ":id/members" do
+        authorize! :admin_project, user_project
+        users_project = user_project.users_projects.new(
+          user_id: params[:user_id],
+          project_access: params[:access_level]
+        )
+
+        if users_project.save
+          @member = users_project.user
+          present @member, with: Entities::ProjectMember, project: user_project
+        else
+          not_found!
+        end
+      end
+
+      # Update project team member
+      #
+      # Parameters:
+      #   id (required) - The ID or code name of a project
+      #   user_id (required) - The ID of a team member
+      #   access_level (required) - Project access level
+      # Example Request:
+      #   PUT /projects/:id/members/:user_id
+      put ":id/members/:user_id" do
+        authorize! :admin_project, user_project
+        users_project = user_project.users_projects.find_by_user_id params[:user_id]
+
+        if users_project.update_attributes(project_access: params[:access_level])
+          @member = users_project.user
+          present @member, with: Entities::ProjectMember, project: user_project
+        else
+          not_found!
+        end
+      end
+
+      # Remove a team member from project
+      #
+      # Parameters:
+      #   id (required) - The ID or code name of a project
+      #   user_id (required) - The ID of a team member
+      # Example Request:
+      #   DELETE /projects/:id/members/:user_id
+      delete ":id/members/:user_id" do
+        authorize! :admin_project, user_project
+        users_project = user_project.users_projects.find_by_user_id params[:user_id]
+        users_project.destroy
+      end
+
+      # Get project hooks
+      #
+      # Parameters:
+      #   id (required) - The ID or code name of a project
+      # Example Request:
+      #   GET /projects/:id/hooks
+      get ":id/hooks" do
+        authorize! :admin_project, user_project
+        @hooks = paginate user_project.hooks
+        present @hooks, with: Entities::Hook
+      end
+
+      # Add hook to project
+      #
+      # Parameters:
+      #   id (required) - The ID or code name of a project
+      #   url (required) - The hook URL
+      # Example Request:
+      #   POST /projects/:id/hooks
+      post ":id/hooks" do
+        authorize! :admin_project, user_project
+        @hook = user_project.hooks.new({"url" => params[:url]})
+        if @hook.save
+          present @hook, with: Entities::Hook
+        else
+          error!({'message' => '404 Not found'}, 404)
+        end
+      end
+
+      # Delete project hook
+      #
+      # Parameters:
+      #   id (required) - The ID or code name of a project
+      #   hook_id (required) - The ID of hook to delete
+      # Example Request:
+      #   DELETE /projects/:id/hooks
+      delete ":id/hooks" do
+        authorize! :admin_project, user_project
+        @hook = user_project.hooks.find(params[:hook_id])
+        @hook.destroy
+        nil
+      end
+
       # Get a project repository branches
       #
       # Parameters:
@@ -55,6 +211,24 @@ module Gitlab
         present user_project.repo.tags.sort_by(&:name).reverse, with: Entities::RepoObject
       end
 
+      # Get a project repository commits
+      #
+      # Parameters:
+      #   id (required) - The ID or code name of a project
+      #   ref_name (optional) - The name of a repository branch or tag
+      # Example Request:
+      #   GET /projects/:id/repository/commits
+      get ":id/repository/commits" do
+        authorize! :download_code, user_project
+
+        page = params[:page] || 0
+        per_page = params[:per_page] || 20
+        ref = params[:ref_name] || user_project.try(:default_branch) || 'master'
+
+        commits = user_project.commits(ref, nil, per_page, page * per_page)
+        present CommitDecorator.decorate(commits), with: Entities::RepoCommit
+      end
+
       # Get a project snippet
       #
       # Parameters:
@@ -78,18 +252,18 @@ module Gitlab
       # Example Request:
       #   POST /projects/:id/snippets
       post ":id/snippets" do
-        @snippet = user_project.snippets.new(
-          title: params[:title],
-          file_name: params[:file_name],
-          expires_at: params[:lifetime],
-          content: params[:code]
-        )
+        authorize! :write_snippet, user_project
+
+        attrs = attributes_for_keys [:title, :file_name]
+        attrs[:expires_at] = params[:lifetime] if params[:lifetime].present?
+        attrs[:content] = params[:code] if params[:code].present?
+        @snippet = user_project.snippets.new attrs
         @snippet.author = current_user
 
         if @snippet.save
           present @snippet, with: Entities::ProjectSnippet
         else
-          error!({'message' => '404 Not found'}, 404)
+          not_found!
         end
       end
 
@@ -106,17 +280,16 @@ module Gitlab
       #   PUT /projects/:id/snippets/:snippet_id
       put ":id/snippets/:snippet_id" do
         @snippet = user_project.snippets.find(params[:snippet_id])
-        parameters = {
-          title: (params[:title] || @snippet.title),
-          file_name: (params[:file_name] || @snippet.file_name),
-          expires_at: (params[:lifetime] || @snippet.expires_at),
-          content: (params[:code] || @snippet.content)
-        }
-
-        if @snippet.update_attributes(parameters)
+        authorize! :modify_snippet, @snippet
+
+        attrs = attributes_for_keys [:title, :file_name]
+        attrs[:expires_at] = params[:lifetime] if params[:lifetime].present?
+        attrs[:content] = params[:code] if params[:code].present?
+
+        if @snippet.update_attributes attrs
           present @snippet, with: Entities::ProjectSnippet
         else
-          error!({'message' => '404 Not found'}, 404)
+          not_found!
         end
       end
 
@@ -129,6 +302,8 @@ module Gitlab
       #   DELETE /projects/:id/snippets/:snippet_id
       delete ":id/snippets/:snippet_id" do
         @snippet = user_project.snippets.find(params[:snippet_id])
+        authorize! :modify_snippet, @snippet
+
         @snippet.destroy
       end
 
@@ -154,13 +329,15 @@ module Gitlab
       # Example Request:
       #   GET /projects/:id/repository/commits/:sha/blob
       get ":id/repository/commits/:sha/blob" do
+        authorize! :download_code, user_project
+
         ref = params[:sha]
 
         commit = user_project.commit ref
-        error!('404 Commit Not Found', 404) unless commit
+        not_found! "Commit" unless commit
 
         tree = Tree.new commit.tree, user_project, ref, params[:filepath]
-        error!('404 File Not Found', 404) unless tree.try(:tree)
+        not_found! "File" unless tree.try(:tree)
 
         if tree.text?
           encoding = Gitlab::Encode.detect_encoding(tree.data)
diff --git a/lib/api/session.rb b/lib/api/session.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b4050160ae42facebe03ae10f0af4c7f631454cc
--- /dev/null
+++ b/lib/api/session.rb
@@ -0,0 +1,20 @@
+module Gitlab
+  # Users API
+  class Session < Grape::API
+    # Login to get token
+    #
+    # Example Request:
+    #  POST /session
+    post "/session" do
+      resource = User.find_for_database_authentication(email: params[:email])
+
+      return unauthorized! unless resource
+
+      if resource.valid_password?(params[:password])
+        present resource, with: Entities::UserLogin
+      else
+        unauthorized!
+      end
+    end
+  end
+end
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 81cb2a0e68417a8fc472ae08cb35ad762965c149..0ca8fb2a1ae6d960adc9249ed7bddfb75c007c17 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -9,7 +9,7 @@ module Gitlab
       # Example Request:
       #  GET /users
       get do
-        @users = User.all
+        @users = paginate User
         present @users, with: Entities::User
       end
 
@@ -25,12 +25,59 @@ module Gitlab
       end
     end
 
-    # Get currently authenticated user
-    #
-    # Example Request:
-    #   GET /user
-    get "/user" do
-      present @current_user, with: Entities::User
+    resource :user do
+      # Get currently authenticated user
+      #
+      # Example Request:
+      #   GET /user
+      get do
+        present @current_user, with: Entities::User
+      end
+
+      # Get currently authenticated user's keys
+      #
+      # Example Request:
+      #   GET /user/keys
+      get "keys" do
+        present current_user.keys, with: Entities::SSHKey
+      end
+
+      # Get single key owned by currently authenticated user
+      #
+      # Example Request:
+      #   GET /user/keys/:id
+      get "keys/:id" do
+        key = current_user.keys.find params[:id]
+        present key, with: Entities::SSHKey
+      end
+
+      # Add new ssh key to currently authenticated user
+      #
+      # Parameters:
+      #   key (required) - New SSH Key
+      #   title (required) - New SSH Key's title
+      # Example Request:
+      #   POST /user/keys
+      post "keys" do
+        attrs = attributes_for_keys [:title, :key]
+        key = current_user.keys.new attrs
+        if key.save
+          present key, with: Entities::SSHKey
+        else
+          not_found!
+        end
+      end
+
+      # Delete existed ssh key of currently authenticated user
+      #
+      # Parameters:
+      #   id (required) - SSH Key ID
+      # Example Request:
+      #   DELETE /user/keys/:id
+      delete "keys/:id" do
+        key = current_user.keys.find params[:id]
+        key.delete
+      end
     end
   end
 end
diff --git a/lib/gitlab/app_logger.rb b/lib/gitlab/app_logger.rb
new file mode 100644
index 0000000000000000000000000000000000000000..8e4717b46e6a0ab8b00b6b71884e3656d31ca324
--- /dev/null
+++ b/lib/gitlab/app_logger.rb
@@ -0,0 +1,11 @@
+module Gitlab
+  class AppLogger < Gitlab::Logger
+    def self.file_name
+      'application.log'
+    end
+
+    def format_message(severity, timestamp, progname, msg)
+      "#{timestamp.to_s(:long)}: #{msg}\n"
+    end
+  end
+end
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
new file mode 100644
index 0000000000000000000000000000000000000000..90bd5d740811ea01851949d39f39a24e5767e680
--- /dev/null
+++ b/lib/gitlab/auth.rb
@@ -0,0 +1,66 @@
+module Gitlab
+  class Auth
+    def find_for_ldap_auth(auth, signed_in_resource = nil)
+      uid = auth.info.uid
+      provider = auth.provider
+      email = auth.info.email.downcase unless auth.info.email.nil?
+      raise OmniAuth::Error, "LDAP accounts must provide an uid and email address" if uid.nil? or email.nil?
+
+      if @user = User.find_by_extern_uid_and_provider(uid, provider)
+        @user
+      elsif @user = User.find_by_email(email)
+        log.info "Updating legacy LDAP user #{email} with extern_uid => #{uid}"
+        @user.update_attributes(:extern_uid => uid, :provider => provider)
+        @user
+      else
+        create_from_omniauth(auth, true)
+      end
+    end
+
+    def create_from_omniauth(auth, ldap = false)
+      provider = auth.provider
+      uid = auth.info.uid || auth.uid
+      name = auth.info.name.force_encoding("utf-8")
+      email = auth.info.email.downcase unless auth.info.email.nil?
+
+      ldap_prefix = ldap ? '(LDAP) ' : ''
+      raise OmniAuth::Error, "#{ldap_prefix}#{provider} does not provide an email"\
+        " address" if auth.info.email.blank?
+
+      log.info "#{ldap_prefix}Creating user from #{provider} login"\
+        " {uid => #{uid}, name => #{name}, email => #{email}}"
+      password = Devise.friendly_token[0, 8].downcase
+      @user = User.new(
+        extern_uid: uid,
+        provider: provider,
+        name: name,
+        email: email,
+        password: password,
+        password_confirmation: password,
+        projects_limit: Gitlab.config.default_projects_limit,
+      )
+      if Gitlab.config.omniauth['block_auto_created_users'] && !ldap
+        @user.blocked = true
+      end
+      @user.save!
+      @user
+    end
+
+    def find_or_new_for_omniauth(auth)
+      provider, uid = auth.provider, auth.uid
+
+      if @user = User.find_by_provider_and_extern_uid(provider, uid)
+        @user
+      else
+        if Gitlab.config.omniauth['allow_single_sign_on']
+          @user = create_from_omniauth(auth)
+          @user
+        end
+      end
+    end
+
+    def log
+      Gitlab::AppLogger
+    end
+  end
+end
diff --git a/lib/gitlab/backend/gitolite.rb b/lib/gitlab/backend/gitolite.rb
new file mode 100644
index 0000000000000000000000000000000000000000..fe5dcef40a9fd5543fe0d97162e94f6e654ca5ba
--- /dev/null
+++ b/lib/gitlab/backend/gitolite.rb
@@ -0,0 +1,43 @@
+require_relative 'gitolite_config'
+
+module Gitlab
+  class Gitolite
+    class AccessDenied < StandardError; end
+
+    def config
+      Gitlab::GitoliteConfig.new
+    end
+
+    def set_key key_id, key_content, projects
+      config.apply do |config|
+        config.write_key(key_id, key_content)
+        config.update_projects(projects)
+      end
+    end
+
+    def remove_key key_id, projects
+      config.apply do |config|
+        config.rm_key(key_id)
+        config.update_projects(projects)
+      end
+    end
+
+    def update_repository project
+      config.update_project!(project.path, project)
+    end
+
+    def remove_repository project
+      config.destroy_project!(project)
+    end
+
+    def url_to_repo path
+      Gitlab.config.ssh_path + "#{path}.git"
+    end
+
+    def enable_automerge
+      config.admin_all_repo!
+    end
+
+    alias_method :create_repository, :update_repository
+  end
+end
diff --git a/lib/gitlab/backend/gitolite_config.rb b/lib/gitlab/backend/gitolite_config.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f51e8efc3706836a065f8b2606f0622080eba204
--- /dev/null
+++ b/lib/gitlab/backend/gitolite_config.rb
@@ -0,0 +1,196 @@
+require 'gitolite'
+require 'timeout'
+require 'fileutils'
+
+module Gitlab
+  class GitoliteConfig
+    class PullError < StandardError; end
+    class PushError < StandardError; end
+
+    attr_reader :config_tmp_dir, :ga_repo, :conf
+
+    def config_tmp_dir
+      @config_tmp_dir ||= File.join(Rails.root, 'tmp',"gitlabhq-gitolite-#{Time.now.to_i}")
+    end
+
+    def ga_repo
+      @ga_repo ||= ::Gitolite::GitoliteAdmin.new(File.join(config_tmp_dir,'gitolite'))
+    end
+
+    def apply
+      Timeout::timeout(30) do
+        File.open(File.join(Rails.root, 'tmp', "gitlabhq-gitolite.lock"), "w+") do |f|
+          begin
+            # Set exclusive lock
+            # to prevent race condition
+            f.flock(File::LOCK_EX)
+
+            # Pull gitolite-admin repo
+            # in tmp dir before do any changes
+            pull(config_tmp_dir)
+
+            # Build ga_repo object and @conf
+            # to access gitolite-admin configuration
+            @conf = ga_repo.config
+
+            # Do any changes
+            # in gitolite-admin
+            # config here
+            yield(self)
+
+            # Save changes in
+            # gitolite-admin repo
+            # before pusht it
+            ga_repo.save
+
+            # Push gitolite-admin repo
+            # to apply all changes
+            push(config_tmp_dir)
+
+            # Remove tmp dir
+            # wiith gitolite-admin
+            FileUtils.rm_rf(config_tmp_dir)
+          ensure
+            # unlock so other task cann access
+            # gitolite configuration
+            f.flock(File::LOCK_UN)
+          end
+        end
+      end
+    rescue PullError => ex
+      log("Pull error ->  " + ex.message)
+      raise Gitolite::AccessDenied, ex.message
+
+    rescue PushError => ex
+      log("Push error ->  " + " " + ex.message)
+      raise Gitolite::AccessDenied, ex.message
+
+    rescue Exception => ex
+      log(ex.class.name + " " + ex.message)
+      raise Gitolite::AccessDenied.new("gitolite timeout")
+    end
+
+    def log message
+      Gitlab::GitLogger.error(message)
+    end
+
+    def destroy_project(project)
+      FileUtils.rm_rf(project.path_to_repo)
+      conf.rm_repo(project.path)
+    end
+
+    def destroy_project!(project)
+      apply do |config|
+        config.destroy_project(project)
+      end
+    end
+
+    def write_key(id, key)
+      File.open(File.join(config_tmp_dir, 'gitolite/keydir',"#{id}.pub"), 'w') do |f|
+        f.write(key.gsub(/\n/,''))
+      end
+    end
+
+    def rm_key(user)
+      File.unlink(File.join(config_tmp_dir, 'gitolite/keydir',"#{user}.pub"))
+      `cd #{File.join(config_tmp_dir,'gitolite')} ; git rm keydir/#{user}.pub`
+    end
+
+    # update or create
+    def update_project(repo_name, project)
+      repo = update_project_config(project, conf)
+      conf.add_repo(repo, true)
+    end
+
+    def update_project!(repo_name, project)
+      apply do |config|
+        config.update_project(repo_name, project)
+      end
+    end
+
+    # Updates many projects and uses project.path as the repo path
+    # An order of magnitude faster than update_project
+    def update_projects(projects)
+      projects.each do |project|
+        repo = update_project_config(project, conf)
+        conf.add_repo(repo, true)
+      end
+    end
+
+    def update_project_config(project, conf)
+      repo_name = project.path
+
+      repo = if conf.has_repo?(repo_name)
+               conf.get_repo(repo_name)
+             else
+               ::Gitolite::Config::Repo.new(repo_name)
+             end
+
+      name_readers = project.repository_readers
+      name_writers = project.repository_writers
+      name_masters = project.repository_masters
+
+      pr_br = project.protected_branches.map(&:name).join("$ ")
+
+      repo.clean_permissions
+
+      # Deny access to protected branches for writers
+      unless name_writers.blank? || pr_br.blank?
+        repo.add_permission("-", pr_br.strip + "$ ", name_writers)
+      end
+
+      # Add read permissions
+      repo.add_permission("R", "", name_readers) unless name_readers.blank?
+
+      # Add write permissions
+      repo.add_permission("RW+", "", name_writers) unless name_writers.blank?
+      repo.add_permission("RW+", "", name_masters) unless name_masters.blank?
+
+      repo
+    end
+
+    # Enable access to all repos for gitolite admin.
+    # We use it for accept merge request feature
+    def admin_all_repo
+      owner_name = Gitlab.config.gitolite_admin_key
+
+      # @ALL repos premission for gitolite owner
+      repo_name = "@all"
+      repo = if conf.has_repo?(repo_name)
+               conf.get_repo(repo_name)
+             else
+               ::Gitolite::Config::Repo.new(repo_name)
+             end
+
+      repo.add_permission("RW+", "", owner_name)
+      conf.add_repo(repo, true)
+    end
+
+    def admin_all_repo!
+      apply { |config| config.admin_all_repo }
+    end
+
+    private
+
+    def pull tmp_dir
+      Dir.mkdir tmp_dir
+      `git clone #{Gitlab.config.gitolite_admin_uri} #{tmp_dir}/gitolite`
+
+      unless File.exists?(File.join(tmp_dir, 'gitolite', 'conf', 'gitolite.conf'))
+        raise PullError, "unable to clone gitolite-admin repo"
+      end
+    end
+
+    def push tmp_dir
+      Dir.chdir(File.join(tmp_dir, "gitolite"))
+      system('git add -A')
+      system('git commit -am "GitLab"')
+      if system('git push')
+        Dir.chdir(Rails.root)
+      else
+        raise PushError, "unable to push gitolite-admin repo"
+      end
+    end
+  end
+end
+
diff --git a/config/initializers/grack_auth.rb b/lib/gitlab/backend/grack_auth.rb
similarity index 64%
rename from config/initializers/grack_auth.rb
rename to lib/gitlab/backend/grack_auth.rb
index 5995b873de94d105b8f46a7e967bbb5a6fb29b2f..43a75cc377bffc13b8556ca42be126e3728ebe87 100644
--- a/config/initializers/grack_auth.rb
+++ b/lib/gitlab/backend/grack_auth.rb
@@ -12,21 +12,22 @@ module Grack
       # Pass Gitolite update hook
       ENV['GL_BYPASS_UPDATE_HOOK'] = "true"
 
-      # Need this patch because the rails mount
-      @env['PATH_INFO'] = @env['REQUEST_PATH']
+      # Need this patch due to the rails mount
+      @env['PATH_INFO'] = @request.path
+      @env['SCRIPT_NAME'] = ""
 
       # Find project by PATH_INFO from env
-      if m = /^\/([\w-]+).git/.match(@env['PATH_INFO']).to_a
+      if m = /^\/([\w-]+).git/.match(@request.path_info).to_a
         return false unless project = Project.find_by_path(m.last)
       end
 
       # Git upload and receive
-      if @env['REQUEST_METHOD'] == 'GET'
+      if @request.get?
         true
-      elsif @env['REQUEST_METHOD'] == 'POST'
-        if @env['REQUEST_URI'].end_with?('git-upload-pack')
+      elsif @request.post?
+        if @request.path_info.end_with?('git-upload-pack')
           return project.dev_access_for?(user)
-        elsif @env['REQUEST_URI'].end_with?('git-receive-pack')
+        elsif @request.path_info.end_with?('git-receive-pack')
           if project.protected_branches.map(&:name).include?(current_ref)
             project.master_access_for?(user)
           else
@@ -42,13 +43,13 @@ module Grack
 
     def current_ref
       if @env["HTTP_CONTENT_ENCODING"] =~ /gzip/
-        input = Zlib::GzipReader.new(@request.body).string
+        input = Zlib::GzipReader.new(@request.body).read
       else
-        input = @request.body.string
+        input = @request.body.read
       end
-
-      oldrev, newrev, ref = input.split(' ')
-      /refs\/heads\/([\w-]+)/.match(ref).to_a.last
+      # Need to reset seek point
+      @request.body.rewind
+      /refs\/heads\/([\w-]+)/.match(input).to_a.first
     end
   end# Auth
 end# Grack
diff --git a/lib/gitlab/git_host.rb b/lib/gitlab/git_host.rb
deleted file mode 100644
index 76b2c7b19e494214bec60e47d76f1153f1f8bd59..0000000000000000000000000000000000000000
--- a/lib/gitlab/git_host.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-require File.join(Rails.root, "lib", "gitlab", "gitolite")
-
-module Gitlab
-  class GitHost
-    def self.system
-      Gitlab::Gitolite
-    end
-
-    def self.admin_uri
-      Gitlab.config.git_host.admin_uri
-    end
-
-    def self.url_to_repo(path)
-      Gitlab.config.ssh_path + "#{path}.git"
-    end
-  end
-end
diff --git a/lib/gitlab/git_logger.rb b/lib/gitlab/git_logger.rb
new file mode 100644
index 0000000000000000000000000000000000000000..fbfed205a0f4c6554727cf7d0c88e1ac5fda7ca3
--- /dev/null
+++ b/lib/gitlab/git_logger.rb
@@ -0,0 +1,11 @@
+module Gitlab
+  class GitLogger < Gitlab::Logger
+    def self.file_name
+      'githost.log'
+    end
+
+    def format_message(severity, timestamp, progname, msg)
+      "#{timestamp.to_s(:long)} -> #{severity} -> #{msg}\n"
+    end
+  end
+end
diff --git a/lib/gitlab/gitolite.rb b/lib/gitlab/gitolite.rb
deleted file mode 100644
index e82f9e6230798d628adcac9695247b142133c32e..0000000000000000000000000000000000000000
--- a/lib/gitlab/gitolite.rb
+++ /dev/null
@@ -1,157 +0,0 @@
-require 'gitolite'
-require 'timeout'
-require 'fileutils'
-
-module Gitlab
-  class Gitolite
-    class AccessDenied < StandardError; end
-
-    def self.update_project(path, project)
-      self.new.configure { |git| git.update_project(path, project) }
-    end
-
-    def self.destroy_project(project)
-      self.new.configure { |git| git.destroy_project(project) }
-    end
-
-    def pull
-      # create tmp dir
-      @local_dir = File.join(Rails.root, 'tmp',"gitlabhq-gitolite-#{Time.now.to_i}")
-      Dir.mkdir @local_dir
-
-      `git clone #{GitHost.admin_uri} #{@local_dir}/gitolite`
-    end
-
-    def push
-      Dir.chdir(File.join(@local_dir, "gitolite"))
-      `git add -A`
-      `git commit -am "Gitlab"`
-      `git push`
-      Dir.chdir(Rails.root)
-
-      FileUtils.rm_rf(@local_dir)
-    end
-
-    def configure
-      Timeout::timeout(30) do
-        File.open(File.join(Rails.root, 'tmp', "gitlabhq-gitolite.lock"), "w+") do |f|
-          begin 
-            f.flock(File::LOCK_EX)
-            pull
-            yield(self)
-            push
-          ensure
-            f.flock(File::LOCK_UN)
-          end
-        end
-      end
-    rescue Exception => ex
-      Gitlab::Logger.error(ex.message)
-      raise Gitolite::AccessDenied.new("gitolite timeout")
-    end
-
-    def destroy_project(project)
-      FileUtils.rm_rf(project.path_to_repo)
-
-      ga_repo = ::Gitolite::GitoliteAdmin.new(File.join(@local_dir,'gitolite'))
-      conf = ga_repo.config
-      conf.rm_repo(project.path)
-      ga_repo.save
-    end
-
-    #update or create
-    def update_keys(user, key)
-      File.open(File.join(@local_dir, 'gitolite/keydir',"#{user}.pub"), 'w') {|f| f.write(key.gsub(/\n/,'')) }
-    end
-
-    def delete_key(user)
-      File.unlink(File.join(@local_dir, 'gitolite/keydir',"#{user}.pub"))
-      `cd #{File.join(@local_dir,'gitolite')} ; git rm keydir/#{user}.pub`
-    end
-
-    # update or create
-    def update_project(repo_name, project)
-      ga_repo = ::Gitolite::GitoliteAdmin.new(File.join(@local_dir,'gitolite'))
-      conf = ga_repo.config
-      repo = update_project_config(project, conf)
-      conf.add_repo(repo, true)
-      
-      ga_repo.save
-    end
-
-    # Updates many projects and uses project.path as the repo path
-    # An order of magnitude faster than update_project
-    def update_projects(projects)
-      ga_repo = ::Gitolite::GitoliteAdmin.new(File.join(@local_dir,'gitolite'))
-      conf = ga_repo.config
-
-      projects.each do |project|
-        repo = update_project_config(project, conf)
-        conf.add_repo(repo, true)
-      end
-
-      ga_repo.save
-    end
-
-    def update_project_config(project, conf)
-      repo_name = project.path
-
-      repo = if conf.has_repo?(repo_name)
-               conf.get_repo(repo_name)
-             else 
-               ::Gitolite::Config::Repo.new(repo_name)
-             end
-
-      name_readers = project.repository_readers
-      name_writers = project.repository_writers
-      name_masters = project.repository_masters
-
-      pr_br = project.protected_branches.map(&:name).join(" ")
-
-      repo.clean_permissions
-
-      # Deny access to protected branches for writers
-      unless name_writers.blank? || pr_br.blank?
-        repo.add_permission("-", pr_br, name_writers)
-      end
-
-      # Add read permissions
-      repo.add_permission("R", "", name_readers) unless name_readers.blank?
-
-      # Add write permissions
-      repo.add_permission("RW+", "", name_writers) unless name_writers.blank?
-      repo.add_permission("RW+", "", name_masters) unless name_masters.blank?
-
-      repo
-    end
-
-    def admin_all_repo
-      ga_repo = ::Gitolite::GitoliteAdmin.new(File.join(@local_dir,'gitolite'))
-      conf = ga_repo.config
-      owner_name = ""
-
-      # Read gitolite-admin user
-      #
-      begin 
-        repo = conf.get_repo("gitolite-admin")
-        owner_name = repo.permissions[0]["RW+"][""][0]
-        raise StandardError if owner_name.blank?
-      rescue => ex
-        puts "Can't determine gitolite-admin owner".red
-        raise StandardError
-      end
-
-      # @ALL repos premission for gitolite owner
-      repo_name = "@all"
-      repo = if conf.has_repo?(repo_name)
-               conf.get_repo(repo_name)
-             else 
-               ::Gitolite::Config::Repo.new(repo_name)
-             end
-
-      repo.add_permission("RW+", "", owner_name)
-      conf.add_repo(repo, true)
-      ga_repo.save
-    end
-  end
-end
diff --git a/lib/gitlab/graph_commit.rb b/lib/gitlab/graph_commit.rb
index b9859d792745ee7d369435be149918fa4cce8016..d3668a991073940e3a53e1e06446c0855783a198 100644
--- a/lib/gitlab/graph_commit.rb
+++ b/lib/gitlab/graph_commit.rb
@@ -5,6 +5,8 @@ module Gitlab
     attr_accessor :time, :space
     attr_accessor :refs
 
+    include ActionView::Helpers::TagHelper
+
     def self.to_graph(project)
       @repo = project.repo
       commits = Grit::Commit.find_all(@repo, nil, {max_count: 650})
@@ -164,7 +166,7 @@ module Gitlab
       h[:refs]    = refs.collect{|r|r.name}.join(" ") unless refs.nil?
       h[:id]      = sha
       h[:date]    = date
-      h[:message] = Gitlab::Encode.utf8(message)
+      h[:message] = escape_once(Gitlab::Encode.utf8(message))
       h[:login]   = author.email
       h
     end
diff --git a/lib/gitlab/logger.rb b/lib/gitlab/logger.rb
index c3a19e71c10d8defdb46b953c1fe2fa11e8dc4a1..9405163dced0bb64387265a22dc3b70e3866bcf6 100644
--- a/lib/gitlab/logger.rb
+++ b/lib/gitlab/logger.rb
@@ -9,17 +9,13 @@ module Gitlab
     end
 
     def self.read_latest
-      path = Rails.root.join("log/githost.log")
+      path = Rails.root.join("log", file_name)
       self.build unless File.exist?(path)
       logs = File.read(path).split("\n")
     end
 
     def self.build
-      new(File.join(Rails.root, "log/githost.log"))
+      new(File.join(Rails.root, "log", file_name))
     end
-
-    def format_message(severity, timestamp, progname, msg)
-      "#{timestamp.to_s(:long)} -> #{severity} -> #{msg}\n" 
-    end 
   end
 end
diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb
index 75fa835d5028045fbd309b565edf28f37965a7b2..9201003e2e1275d9bf2f49be80922ac3c4a0186f 100644
--- a/lib/gitlab/markdown.rb
+++ b/lib/gitlab/markdown.rb
@@ -1,7 +1,8 @@
 module Gitlab
-  # Custom parser for Gitlab-flavored Markdown
+  # Custom parser for GitLab-flavored Markdown
   #
-  # It replaces references in the text with links to the appropriate items in Gitlab.
+  # It replaces references in the text with links to the appropriate items in
+  # GitLab.
   #
   # Supported reference formats are:
   #   * @foo for team members
@@ -10,44 +11,99 @@ module Gitlab
   #   * $123 for snippets
   #   * 123456 for commits
   #
-  # Examples
+  # It also parses Emoji codes to insert images. See
+  # http://www.emoji-cheat-sheet.com/ for a list of the supported icons.
   #
-  #   >> m = Markdown.new(...)
+  # Examples
   #
-  #   >> m.parse("Hey @david, can you fix this?")
+  #   >> gfm("Hey @david, can you fix this?")
   #   => "Hey <a href="/gitlab/team_members/1">@david</a>, can you fix this?"
   #
-  #   >> m.parse("Commit 35d5f7c closes #1234")
+  #   >> gfm("Commit 35d5f7c closes #1234")
   #   => "Commit <a href="/gitlab/commits/35d5f7c">35d5f7c</a> closes <a href="/gitlab/issues/1234">#1234</a>"
-  class Markdown
-    include Rails.application.routes.url_helpers
-    include ActionView::Helpers
-
+  #
+  #   >> gfm(":trollface:")
+  #   => "<img alt=\":trollface:\" class=\"emoji\" src=\"/images/trollface.png" title=\":trollface:\" />
+  module Markdown
     REFERENCE_PATTERN = %r{
-      ([^\w&;])?      # Prefix (1)
+      (\W)?           # Prefix (1)
       (               # Reference (2)
         @([\w\._]+)   # User name (3)
         |[#!$](\d+)   # Issue/MR/Snippet ID (4)
         |([\h]{6,40}) # Commit ID (5)
       )
-      ([^\w&;])?      # Suffix (6)
+      (\W)?           # Suffix (6)
     }x.freeze
 
+    EMOJI_PATTERN = %r{(:(\S+):)}.freeze
+
     attr_reader :html_options
 
-    def initialize(project, html_options = {})
-      @project      = project
+    # Public: Parse the provided text with GitLab-Flavored Markdown
+    #
+    # text         - the source text
+    # html_options - extra options for the reference links as given to link_to
+    #
+    # Note: reference links will only be generated if @project is set
+    def gfm(text, html_options = {})
+      return text if text.nil?
+
+      # Duplicate the string so we don't alter the original, then call to_str
+      # to cast it back to a String instead of a SafeBuffer. This is required
+      # for gsub calls to work as we need them to.
+      text = text.dup.to_str
+
       @html_options = html_options
+
+      # Extract pre blocks so they are not altered
+      # from http://github.github.com/github-flavored-markdown/
+      extractions = {}
+      text.gsub!(%r{<pre>.*?</pre>|<code>.*?</code>}m) do |match|
+        md5 = Digest::MD5.hexdigest(match)
+        extractions[md5] = match
+        "{gfm-extraction-#{md5}}"
+      end
+
+      # TODO: add popups with additional information
+
+      text = parse(text)
+
+      # Insert pre block extractions
+      text.gsub!(/\{gfm-extraction-(\h{32})\}/) do
+        extractions[$1]
+      end
+
+      sanitize text.html_safe, attributes: ActionView::Base.sanitized_allowed_attributes + %w(id class)
     end
 
+    private
+
+    # Private: Parses text for references and emoji
+    #
+    # text - Text to parse
+    #
+    # Note: reference links will only be generated if @project is set
+    #
+    # Returns parsed text
     def parse(text)
-      text.gsub(REFERENCE_PATTERN) do |match|
+      parse_references(text) if @project
+      parse_emoji(text)
+
+      text
+    end
+
+    def parse_references(text)
+      # parse reference links
+      text.gsub!(REFERENCE_PATTERN) do |match|
         prefix     = $1 || ''
         reference  = $2
         identifier = $3 || $4 || $5
         suffix     = $6 || ''
 
-        if ref_link = reference_link(reference, identifier)
+        # Avoid HTML entities
+        if prefix.ends_with?('&') || suffix.starts_with?(';')
+          match
+        elsif ref_link = reference_link(reference, identifier)
           prefix + ref_link + suffix
         else
           match
@@ -55,7 +111,25 @@ module Gitlab
       end
     end
 
-    private
+    def parse_emoji(text)
+      # parse emoji
+      text.gsub!(EMOJI_PATTERN) do |match|
+        if valid_emoji?($2)
+          image_tag("emoji/#{$2}.png", size: "20x20", class: 'emoji', title: $1, alt: $1)
+        else
+          match
+        end
+      end
+    end
+
+    # Private: Checks if an emoji icon exists in the image asset directory
+    #
+    # emoji - Identifier of the emoji as a string (e.g., "+1", "heart")
+    #
+    # Returns boolean
+    def valid_emoji?(emoji)
+      File.exists?(Rails.root.join('app', 'assets', 'images', 'emoji', "#{emoji}.png"))
+    end
 
     # Private: Dispatches to a dedicated processing method based on reference
     #
@@ -100,7 +174,7 @@ module Gitlab
 
     def reference_commit(identifier)
       if commit = @project.commit(identifier)
-        link_to(identifier, project_commit_path(@project, id: commit.id), html_options.merge(title: "Commit: #{commit.author_name} - #{CommitDecorator.new(commit).title}", class: "gfm gfm-commit #{html_options[:class]}"))
+        link_to(identifier, project_commit_path(@project, id: commit.id), html_options.merge(title: CommitDecorator.new(commit).link_title, class: "gfm gfm-commit #{html_options[:class]}"))
       end
     end
   end
diff --git a/lib/gitlab/merge.rb b/lib/gitlab/merge.rb
index 134695ce21c3fd4023be41f6de1dafa833c5c88d..180135745f84977fd0d2ea13f657a32fa76fa0c5 100644
--- a/lib/gitlab/merge.rb
+++ b/lib/gitlab/merge.rb
@@ -21,8 +21,7 @@ module Gitlab
         if output =~ /CONFLICT/
           false  
         else 
-          repo.git.push({}, "origin", merge_request.target_branch)
-          true
+          !!repo.git.push({}, "origin", merge_request.target_branch)
         end
       end
     end
diff --git a/lib/hooks/post-receive b/lib/hooks/post-receive
index d38bd13e19d8fa0b85c4b88ea3b10959b2823451..a4fa9f1c2346670412ecf2f32dfc8786c88a5252 100755
--- a/lib/hooks/post-receive
+++ b/lib/hooks/post-receive
@@ -1,6 +1,6 @@
 #!/usr/bin/env bash
 
-# This file was placed here by Gitlab. It makes sure that your pushed commits
+# This file was placed here by GitLab. It makes sure that your pushed commits
 # will be processed properly.
 
 while read oldrev newrev ref
diff --git a/lib/tasks/bulk_add_permission.rake b/lib/tasks/bulk_add_permission.rake
new file mode 100644
index 0000000000000000000000000000000000000000..55797825e0cf816e71b7899fa878617eea54d6a8
--- /dev/null
+++ b/lib/tasks/bulk_add_permission.rake
@@ -0,0 +1,26 @@
+desc "Add all users to all projects, system administratos are added as masters"
+task :add_users_to_project_teams => :environment  do |t, args|
+  users = User.find_all_by_admin(false, :select => 'id').map(&:id)
+  admins = User.find_all_by_admin(true, :select => 'id').map(&:id)
+
+  users.each do |user|
+    puts "#{user}"
+  end
+
+  Project.all.each do |project|
+    puts "Importing #{users.length} users into #{project.path}"
+    UsersProject.bulk_import(project, users, UsersProject::DEVELOPER)
+    puts "Importing #{admins.length} admins into #{project.path}"
+    UsersProject.bulk_import(project, admins, UsersProject::MASTER)
+  end
+end
+
+desc "Add user to as a developer to all projects"
+task :add_user_to_project_teams, [:email] => :environment  do |t, args|
+  user_email = args.email
+  user = User.find_by_email(user_email)
+
+  project_ids = Project.all.map(&:id)
+
+  UsersProject.user_bulk_import(user,project_ids,UsersProject::DEVELOPER)
+end
diff --git a/lib/tasks/bulk_import.rake b/lib/tasks/bulk_import.rake
index 607250f177018644975c0d0070042452ac304c0c..edb4a599eb0ca67f609c0db11334c7eb6913d2bb 100644
--- a/lib/tasks/bulk_import.rake
+++ b/lib/tasks/bulk_import.rake
@@ -1,11 +1,10 @@
-IMPORT_DIRECTORY = 'import_projects'
-REPOSITORY_DIRECTORY = '/home/git/repositories'
 
-desc "Imports existing Git repos into new projects from the import_projects folder"
-task :import_projects, [:email] => :environment  do |t, args|
+desc "Imports existing Git repos from a directory into new projects in git_base_path"
+task :import_projects, [:directory,:email] => :environment  do |t, args|
   user_email = args.email
-  repos_to_import = Dir.glob("#{IMPORT_DIRECTORY}/*")
-
+  import_directory = args.directory
+  repos_to_import = Dir.glob("#{import_directory}/*")
+  git_base_path = Gitlab.config.git_base_path
   puts "Found #{repos_to_import.length} repos to import"
 
   imported_count = 0
@@ -13,11 +12,9 @@ task :import_projects, [:email] => :environment  do |t, args|
   failed_count = 0
   repos_to_import.each do |repo_path|
     repo_name = File.basename repo_path
-    repo_full_path = File.join(Rails.root, repo_path)
 
     puts "  Processing #{repo_name}"
-
-    clone_path = "#{REPOSITORY_DIRECTORY}/#{repo_name}.git"
+    clone_path = "#{git_base_path}#{repo_name}.git"
 
     if Dir.exists? clone_path
       if Project.find_by_code(repo_name)
@@ -29,7 +26,7 @@ task :import_projects, [:email] => :environment  do |t, args|
       end
     else
       # Clone the repo
-      unless clone_bare_repo_as_git(repo_full_path, clone_path)
+      unless clone_bare_repo_as_git(repo_path, clone_path)
         failed_count += 1
         next
       end
@@ -47,14 +44,17 @@ task :import_projects, [:email] => :environment  do |t, args|
   puts "Finished importing #{imported_count} projects (skipped #{skipped_count}, failed #{failed_count})."
 end
 
-# Clones a repo as bare git repo using the git user
+# Clones a repo as bare git repo using the git_user
 def clone_bare_repo_as_git(existing_path, new_path)
+  git_user = Gitlab.config.ssh_user
   begin
-    sh "sudo -u git -i git clone --bare '#{existing_path}' #{new_path}"
+    sh "sudo -u #{git_user} -i git clone --bare '#{existing_path}' #{new_path}"
     true
-  rescue
+  rescue Exception=> msg
     puts "  ERROR: Faild to clone #{existing_path} to #{new_path}"
-    false
+	puts "	Make sure #{git_user} can reach #{existing_path}"
+	puts "	Exception-MSG: #{msg}"
+	false
   end
 end
 
diff --git a/lib/tasks/cucumber.rake b/lib/tasks/cucumber.rake
deleted file mode 100644
index 83f79471e59f606e24ea78921be60d709e1b8f50..0000000000000000000000000000000000000000
--- a/lib/tasks/cucumber.rake
+++ /dev/null
@@ -1,65 +0,0 @@
-# IMPORTANT: This file is generated by cucumber-rails - edit at your own peril.
-# It is recommended to regenerate this file in the future when you upgrade to a 
-# newer version of cucumber-rails. Consider adding your own code to a new file 
-# instead of editing this one. Cucumber will automatically load all features/**/*.rb
-# files.
-
-
-unless ARGV.any? {|a| a =~ /^gems/} # Don't load anything when running the gems:* tasks
-
-vendored_cucumber_bin = Dir["#{Rails.root}/vendor/{gems,plugins}/cucumber*/bin/cucumber"].first
-$LOAD_PATH.unshift(File.dirname(vendored_cucumber_bin) + '/../lib') unless vendored_cucumber_bin.nil?
-
-begin
-  require 'cucumber/rake/task'
-
-  namespace :cucumber do
-    Cucumber::Rake::Task.new({:ok => 'db:test:prepare'}, 'Run features that should pass') do |t|
-      t.binary = vendored_cucumber_bin # If nil, the gem's binary is used.
-      t.fork = true # You may get faster startup if you set this to false
-      t.profile = 'default'
-    end
-
-    Cucumber::Rake::Task.new({:wip => 'db:test:prepare'}, 'Run features that are being worked on') do |t|
-      t.binary = vendored_cucumber_bin
-      t.fork = true # You may get faster startup if you set this to false
-      t.profile = 'wip'
-    end
-
-    Cucumber::Rake::Task.new({:rerun => 'db:test:prepare'}, 'Record failing features and run only them if any exist') do |t|
-      t.binary = vendored_cucumber_bin
-      t.fork = true # You may get faster startup if you set this to false
-      t.profile = 'rerun'
-    end
-
-    desc 'Run all features'
-    task :all => [:ok, :wip]
-
-    task :statsetup do
-      require 'rails/code_statistics'
-      ::STATS_DIRECTORIES << %w(Cucumber\ features features) if File.exist?('features')
-      ::CodeStatistics::TEST_TYPES << "Cucumber features" if File.exist?('features')
-    end
-  end
-  desc 'Alias for cucumber:ok'
-  task :cucumber => 'cucumber:ok'
-
-  task :default => :cucumber
-
-  task :features => :cucumber do
-    STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***"
-  end
-
-  # In case we don't have ActiveRecord, append a no-op task that we can depend upon.
-  task 'db:test:prepare' do
-  end
-
-  task :stats => 'cucumber:statsetup'
-rescue LoadError
-  desc 'cucumber rake task not available (cucumber not installed)'
-  task :cucumber do
-    abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
-  end
-end
-
-end
diff --git a/lib/tasks/gitlab/backup.rake b/lib/tasks/gitlab/backup.rake
index d9053c232cdadb5ae5d8a5562c468409512fa10d..04d240f6b12a178cfb94cb9fdea5e06cbe82adb8 100644
--- a/lib/tasks/gitlab/backup.rake
+++ b/lib/tasks/gitlab/backup.rake
@@ -144,8 +144,7 @@ namespace :gitlab do
         if Kernel.system("cd #{File.dirname(project.second)} > /dev/null 2>&1 && git clone --bare #{backup_path_repo}/#{project.first}.bundle #{project.first}.git > /dev/null 2>&1")
           permission_commands = [
             "sudo chmod -R g+rwX #{Gitlab.config.git_base_path}",
-            "sudo chown -R #{Gitlab.config.ssh_user}:#{Gitlab.config.ssh_user} #{Gitlab.config.git_base_path}",
-            "sudo chown gitlab:gitlab /home/git/repositories/**/hooks/post-receive"
+            "sudo chown -R #{Gitlab.config.ssh_user}:#{Gitlab.config.ssh_user} #{Gitlab.config.git_base_path}"
           ]
           permission_commands.each { |command| Kernel.system(command) }
           puts "[DONE]".green
diff --git a/lib/tasks/gitlab/enable_automerge.rake b/lib/tasks/gitlab/enable_automerge.rake
index 07f80586c60f42d13c099e094a4af809a8d2c1b6..0a1a0fa7350185dfbc783ca3aec7e1d6c2898678 100644
--- a/lib/tasks/gitlab/enable_automerge.rake
+++ b/lib/tasks/gitlab/enable_automerge.rake
@@ -2,9 +2,7 @@ namespace :gitlab do
   namespace :app do
     desc "GITLAB | Enable auto merge"
     task :enable_automerge => :environment  do
-      Gitlab::GitHost.system.new.configure do |git|
-        git.admin_all_repo
-      end
+      Gitlab::Gitolite.new.enable_automerge
 
       Project.find_each do |project|
         if project.repo_exists? && !project.satellite.exists?
diff --git a/lib/tasks/gitlab/gitolite_rebuild.rake b/lib/tasks/gitlab/gitolite_rebuild.rake
index 5ab176060fbb545a5cda3d6a28f0c4403a023b02..534aa3156311cfdc0b2266293c5f234682a6d2c8 100644
--- a/lib/tasks/gitlab/gitolite_rebuild.rake
+++ b/lib/tasks/gitlab/gitolite_rebuild.rake
@@ -16,7 +16,7 @@ namespace :gitlab do
     task :update_keys => :environment  do
       puts "Starting Key"
       Key.find_each(:batch_size => 100) do |key|
-        key.update_repository
+        Gitlab::Gitolite.new.set_key(key.identifier, key.key, key.projects)
         print '.'
       end
       puts "Done with keys"
diff --git a/lib/tasks/gitlab/status.rake b/lib/tasks/gitlab/status.rake
index 02d27d4bbcc793144e4d6f054149ddec1174b5ca..e5b5e122a18acfa506dc091e23f4fbe5018ecd01 100644
--- a/lib/tasks/gitlab/status.rake
+++ b/lib/tasks/gitlab/status.rake
@@ -56,7 +56,7 @@ namespace :gitlab do
         return
       end
 
-      gitolite_hooks_path = File.join("/home", Gitlab.config.ssh_user, "share", "gitolite", "hooks", "common")
+      gitolite_hooks_path = File.join(Gitlab.config.git_hooks_path, "common")
       gitlab_hook_files = ['post-receive']
       gitlab_hook_files.each do |file_name|
         dest = File.join(gitolite_hooks_path, file_name)
@@ -81,7 +81,7 @@ namespace :gitlab do
             next
           end
 
-          puts "post-reveice file ok".green
+          puts "post-receive file ok".green
         end
       end
 
diff --git a/lib/tasks/gitlab/test.rake b/lib/tasks/gitlab/test.rake
index 77e148cf18c153b3e31f2e65ec981dc0f2660ba7..ad1bfb2e4b3fc783b1d945207aeaa71632c6819b 100644
--- a/lib/tasks/gitlab/test.rake
+++ b/lib/tasks/gitlab/test.rake
@@ -1,5 +1,4 @@
 namespace :gitlab do
-  desc "GITLAB | Run both cucumber & rspec"
-  task :test => ['cucumber', 'spec']
+  desc "GITLAB | Run both spinach and rspec"
+  task :test => ['spinach', 'spec']
 end
-
diff --git a/lib/tasks/gitlab/write_hook.rake b/lib/tasks/gitlab/write_hook.rake
index 098331b8cd7ac465d1a59819abcc1cdff5eaebd6..5e9fc8eb3d1f7b427cf3eb20ba268acf917cedf7 100644
--- a/lib/tasks/gitlab/write_hook.rake
+++ b/lib/tasks/gitlab/write_hook.rake
@@ -1,8 +1,8 @@
 namespace :gitlab do
   namespace :gitolite do
-    desc "GITLAB | Write GITLAB hook for gitolite"
+    desc "GITLAB | Write GitLab hook for gitolite"
     task :write_hooks => :environment  do
-      gitolite_hooks_path = File.join("/home", Gitlab.config.ssh_user, "share", "gitolite", "hooks", "common")
+      gitolite_hooks_path = File.join(Gitlab.config.git_hooks_path, "common")
       gitlab_hooks_path = Rails.root.join("lib", "hooks")
 
       gitlab_hook_files = ['post-receive']
diff --git a/lib/tasks/travis.rake b/lib/tasks/travis.rake
index 58767e10611427874083ab6bb114502dcf65989b..13e32135c66d10a709da613c0bc48b16635f37c7 100644
--- a/lib/tasks/travis.rake
+++ b/lib/tasks/travis.rake
@@ -1,5 +1,5 @@
 task :travis do
-  ["cucumber", "rspec spec"].each do |cmd|
+  ["spinach", "rspec spec"].each do |cmd|
     puts "Starting to run #{cmd}..."
     system("export DISPLAY=:99.0 && bundle exec #{cmd}")
     raise "#{cmd} failed!" unless $?.exitstatus == 0
diff --git a/resque_dev.sh b/resque_dev.sh
index b09cfd9e3830babb846892fc5600bd9270eba922..0f1d6edb41f687592dfe8b6f72a76e54167ffc10 100755
--- a/resque_dev.sh
+++ b/resque_dev.sh
@@ -1 +1,2 @@
-bundle exec rake environment resque:work QUEUE=post_receive,mailer,system_hook VVERBOSE=1
+mkdir -p tmp/pids
+bundle exec rake environment resque:work QUEUE=post_receive,mailer,system_hook VVERBOSE=1 PIDFILE=tmp/pids/resque_worker.pid RAILS_ENV=development BACKGROUND=yes
diff --git a/script/cucumber b/script/cucumber
deleted file mode 100755
index 7fa5c9208675ca06c02b2d3a3279f17623d1cbc9..0000000000000000000000000000000000000000
--- a/script/cucumber
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/env ruby
-
-vendored_cucumber_bin = Dir["#{File.dirname(__FILE__)}/../vendor/{gems,plugins}/cucumber*/bin/cucumber"].first
-if vendored_cucumber_bin
-  load File.expand_path(vendored_cucumber_bin)
-else
-  require 'rubygems' unless ENV['NO_RUBYGEMS']
-  require 'cucumber'
-  load Cucumber::BINARY
-end
diff --git a/spec/api/projects_spec.rb b/spec/api/projects_spec.rb
deleted file mode 100644
index ff45619e58af31069ca412e32638ea62e94619ea..0000000000000000000000000000000000000000
--- a/spec/api/projects_spec.rb
+++ /dev/null
@@ -1,136 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::API do
-  let(:user) { Factory :user }
-  let!(:project) { Factory :project, owner: user }
-  let!(:snippet) { Factory :snippet, author: user, project: project, title: 'example' }
-  before { project.add_access(user, :read) }
-
-  describe "GET /projects" do
-    it "should return authentication error" do
-      get "#{api_prefix}/projects"
-      response.status.should == 401
-    end
-
-    describe "authenticated GET /projects" do
-      it "should return an array of projects" do
-        get "#{api_prefix}/projects?private_token=#{user.private_token}"
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.first['name'].should == project.name
-        json_response.first['owner']['email'].should == user.email
-      end
-    end
-  end
-
-  describe "GET /projects/:id" do
-    it "should return a project by id" do
-      get "#{api_prefix}/projects/#{project.id}?private_token=#{user.private_token}"
-      response.status.should == 200
-      json_response['name'].should == project.name
-      json_response['owner']['email'].should == user.email
-    end
-
-    it "should return a project by code name" do
-      get "#{api_prefix}/projects/#{project.code}?private_token=#{user.private_token}"
-      response.status.should == 200
-      json_response['name'].should == project.name
-    end
-
-    it "should return a 404 error if not found" do
-      get "#{api_prefix}/projects/42?private_token=#{user.private_token}"
-      response.status.should == 404
-      json_response['message'].should == '404 Not found'
-    end
-  end
-
-  describe "GET /projects/:id/repository/branches" do
-    it "should return an array of project branches" do
-      get "#{api_prefix}/projects/#{project.code}/repository/branches?private_token=#{user.private_token}"
-      response.status.should == 200
-      json_response.should be_an Array
-      json_response.first['name'].should == project.repo.heads.sort_by(&:name).first.name
-    end
-  end
-
-  describe "GET /projects/:id/repository/branches/:branch" do
-    it "should return the branch information for a single branch" do
-      get "#{api_prefix}/projects/#{project.code}/repository/branches/new_design?private_token=#{user.private_token}"
-      response.status.should == 200
-
-      json_response['name'].should == 'new_design'
-      json_response['commit']['id'].should == '621491c677087aa243f165eab467bfdfbee00be1'
-    end
-  end
-
-  describe "GET /projects/:id/repository/tags" do
-    it "should return an array of project tags" do
-      get "#{api_prefix}/projects/#{project.code}/repository/tags?private_token=#{user.private_token}"
-      response.status.should == 200
-      json_response.should be_an Array
-      json_response.first['name'].should == project.repo.tags.sort_by(&:name).reverse.first.name
-    end
-  end
-
-  describe "GET /projects/:id/snippets/:snippet_id" do
-    it "should return a project snippet" do
-      get "#{api_prefix}/projects/#{project.code}/snippets/#{snippet.id}?private_token=#{user.private_token}"
-      response.status.should == 200
-      json_response['title'].should == snippet.title
-    end
-  end
-
-  describe "POST /projects/:id/snippets" do
-    it "should create a new project snippet" do
-      post "#{api_prefix}/projects/#{project.code}/snippets?private_token=#{user.private_token}",
-        title: 'api test', file_name: 'sample.rb', code: 'test'
-      response.status.should == 201
-      json_response['title'].should == 'api test'
-    end
-  end
-
-  describe "PUT /projects/:id/snippets" do
-    it "should update an existing project snippet" do
-      put "#{api_prefix}/projects/#{project.code}/snippets/#{snippet.id}?private_token=#{user.private_token}",
-        code: 'updated code'
-      response.status.should == 200
-      json_response['title'].should == 'example'
-      snippet.reload.content.should == 'updated code'
-    end
-  end
-
-  describe "DELETE /projects/:id/snippets/:snippet_id" do
-    it "should delete existing project snippet" do
-      expect {
-        delete "#{api_prefix}/projects/#{project.code}/snippets/#{snippet.id}?private_token=#{user.private_token}"
-      }.to change { Snippet.count }.by(-1)
-    end
-  end
-
-  describe "GET /projects/:id/snippets/:snippet_id/raw" do
-    it "should get a raw project snippet" do
-      get "#{api_prefix}/projects/#{project.code}/snippets/#{snippet.id}/raw?private_token=#{user.private_token}"
-      response.status.should == 200
-    end
-  end
-
-  describe "GET /projects/:id/:sha/blob" do
-    it "should get the raw file contents" do
-      get "#{api_prefix}/projects/#{project.code}/repository/commits/master/blob?filepath=README.md&private_token=#{user.private_token}"
-      
-      response.status.should == 200
-    end
-
-    it "should return 404 for invalid branch_name" do
-      get "#{api_prefix}/projects/#{project.code}/repository/commits/invalid_branch_name/blob?filepath=README.md&private_token=#{user.private_token}"
-      
-      response.status.should == 404
-    end
-
-    it "should return 404 for invalid file" do
-      get "#{api_prefix}/projects/#{project.code}/repository/commits/master/blob?filepath=README.invalid&private_token=#{user.private_token}"
-      
-      response.status.should == 404
-    end
-  end
-end
diff --git a/spec/api/users_spec.rb b/spec/api/users_spec.rb
deleted file mode 100644
index 32b9379d212969d789b529bff5cca9380351eca4..0000000000000000000000000000000000000000
--- a/spec/api/users_spec.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::API do
-  let(:user) { Factory :user }
-
-  describe "GET /users" do
-    it "should return authentication error" do
-      get "#{api_prefix}/users"
-      response.status.should == 401
-    end
-
-    describe "authenticated GET /users" do
-      it "should return an array of users" do
-        get "#{api_prefix}/users?private_token=#{user.private_token}"
-        response.status.should == 200
-        json_response.should be_an Array
-        json_response.first['email'].should == user.email
-      end
-    end
-  end
-
-  describe "GET /users/:id" do
-    it "should return a user by id" do
-      get "#{api_prefix}/users/#{user.id}?private_token=#{user.private_token}"
-      response.status.should == 200
-      json_response['email'].should == user.email
-    end
-  end
-
-  describe "GET /user" do
-    it "should return current user" do
-      get "#{api_prefix}/user?private_token=#{user.private_token}"
-      response.status.should == 200
-      json_response['email'].should == user.email
-    end
-  end
-end
diff --git a/spec/factories.rb b/spec/factories.rb
index ab2ca4687da799ebe1701ed6b655992fd8ce3d9d..92790a3fdb7a51425ab9bc8d40ba1319a98c88d4 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -1,92 +1,133 @@
-require File.join(Rails.root, 'spec', 'factory')
-
-Factory.add(:project, Project) do |obj|
-  obj.name = Faker::Internet.user_name
-  obj.path = 'gitlabhq'
-  obj.owner = Factory(:user)
-  obj.code = 'LGT'
+# Backwards compatibility with the old method
+def Factory(type, *args)
+  FactoryGirl.create(type, *args)
 end
 
-Factory.add(:project_without_owner, Project) do |obj|
-  obj.name = Faker::Internet.user_name
-  obj.path = 'gitlabhq'
-  obj.code = 'LGT'
-end
+module Factory
+  def self.create(type, *args)
+    FactoryGirl.create(type, *args)
+  end
 
-Factory.add(:public_project, Project) do |obj|
-  obj.name = Faker::Internet.user_name
-  obj.path = 'gitlabhq'
-  obj.private_flag = false
-  obj.owner = Factory(:user)
-  obj.code = 'LGT'
+  def self.new(type, *args)
+    FactoryGirl.build(type, *args)
+  end
+  def self.attributes(type, *args)
+    FactoryGirl.attributes_for(type, *args)
+  end
 end
 
-Factory.add(:user, User) do |obj|
-  obj.email = Faker::Internet.email
-  obj.password = "123456"
-  obj.name = Faker::Name.name
-  obj.password_confirmation = "123456"
-end
+FactoryGirl.define do
+  sequence :sentence, aliases: [:title, :content] do
+    Faker::Lorem.sentence
+  end
 
-Factory.add(:admin, User) do |obj|
-  obj.email = Faker::Internet.email
-  obj.password = "123456"
-  obj.name = Faker::Name.name
-  obj.password_confirmation = "123456"
-  obj.admin = true
-end
+  sequence :name, aliases: [:file_name] do
+    Faker::Name.name
+  end
 
-Factory.add(:issue, Issue) do |obj|
-  obj.title = Faker::Lorem.sentence
-  obj.author = Factory :user
-  obj.assignee = Factory :user
-end
+  sequence(:url) { Faker::Internet.uri('http') }
 
-Factory.add(:merge_request, MergeRequest) do |obj|
-  obj.title = Faker::Lorem.sentence
-  obj.author = Factory :user
-  obj.assignee = Factory :user
-  obj.source_branch = "master"
-  obj.target_branch = "stable"
-  obj.closed = false
-end
+  factory :user, aliases: [:author, :assignee, :owner] do
+    email { Faker::Internet.email }
+    name
+    password "123456"
+    password_confirmation { password }
 
-Factory.add(:snippet, Snippet) do |obj|
-  obj.title = Faker::Lorem.sentence
-  obj.file_name = Faker::Lorem.sentence
-  obj.content = Faker::Lorem.sentences
-end
+    trait :admin do
+      admin true
+    end
 
-Factory.add(:note, Note) do |obj|
-  obj.note = Faker::Lorem.sentence
-end
+    factory :admin, traits: [:admin]
+  end
 
-Factory.add(:key, Key) do |obj|
-  obj.title = "Example key"
-  obj.key = File.read(File.join(Rails.root, "db", "pkey.example"))
-end
+  factory :project do
+    sequence(:name) { |n| "project#{n}" }
+    path { name }
+    code { name }
+    owner
+  end
 
-Factory.add(:project_hook, ProjectHook) do |obj|
-  obj.url = Faker::Internet.uri("http")
-end
+  factory :users_project do
+    user
+    project
+  end
 
-Factory.add(:system_hook, SystemHook) do |obj|
-  obj.url = Faker::Internet.uri("http")
-end
+  factory :issue do
+    title
+    author
+    project
 
-Factory.add(:wiki, Wiki) do |obj|
-  obj.title = Faker::Lorem.sentence
-  obj.content = Faker::Lorem.sentence
-  obj.user = Factory(:user)
-  obj.project = Factory(:project)
-end
+    trait :closed do
+      closed true
+    end
 
-Factory.add(:event, Event) do |obj|
-  obj.title = Faker::Lorem.sentence
-  obj.project = Factory(:project)
-end
+    factory :closed_issue, traits: [:closed]
+  end
+
+  factory :merge_request do
+    title
+    author
+    project
+    source_branch "master"
+    target_branch "stable"
+  end
+
+  factory :note do
+    project
+    note "Note"
+  end
+
+  factory :event do
+  end
+
+  factory :key do
+    title
+    key do
+      """
+      ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
+      596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
+      soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=
+      """
+    end
+
+    factory :deploy_key do
+      project
+    end
+
+    factory :personal_key do
+      user
+    end
+  end
+
+  factory :milestone do
+    title
+    project
+  end
+
+  factory :system_hook do
+    url
+  end
+
+  factory :project_hook do
+    url
+  end
+
+  factory :wiki do
+    title
+    content
+    user
+  end
+
+  factory :snippet do
+    project
+    author
+    title
+    content
+    file_name
+  end
 
-Factory.add(:milestone, Milestone) do |obj|
-  obj.title = Faker::Lorem.sentence
-  obj.due_date = Date.today + 1.month
+  factory :protected_branch do
+    name
+    project
+  end
 end
diff --git a/spec/factories_spec.rb b/spec/factories_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..5ccc17bddc9315a3864c5ad0ecf68eb9990c6163
--- /dev/null
+++ b/spec/factories_spec.rb
@@ -0,0 +1,9 @@
+require 'spec_helper'
+
+FactoryGirl.factories.map(&:name).each do |factory_name|
+  describe "#{factory_name} factory" do
+    it 'should be valid' do
+      build(factory_name).should be_valid
+    end
+  end
+end
diff --git a/spec/factory.rb b/spec/factory.rb
deleted file mode 100644
index 1758b4d69d702adbb48dc177da680890629ccd72..0000000000000000000000000000000000000000
--- a/spec/factory.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-class Factory
-  @factories = {}
-
-  class << self
-    def add(name, klass, &block)
-      @factories[name] = [klass, block]
-    end
-
-    def create(name, opts = {})
-      new(name, opts).tap(&:save!)
-    end
-
-    def new(name, opts = {})
-      factory= @factories[name]
-      factory[0].new.tap do |obj|
-        factory[1].call(obj)
-      end.tap do |obj|
-        opts.each do |k, opt|
-          obj.send("#{k}=", opt)
-        end
-      end
-    end
-  end
-end
-
-def Factory(name, opts={})
-  Factory.create name, opts
-end
-
diff --git a/spec/helpers/gitlab_flavored_markdown_spec.rb b/spec/helpers/gitlab_flavored_markdown_spec.rb
deleted file mode 100644
index e147cb39375bf3ab5dfddc8ffec83db43ad59493..0000000000000000000000000000000000000000
--- a/spec/helpers/gitlab_flavored_markdown_spec.rb
+++ /dev/null
@@ -1,232 +0,0 @@
-require "spec_helper"
-
-describe GitlabMarkdownHelper do
-  before do
-    @project = Project.find_by_path("gitlabhq") || Factory(:project)
-    @commit = @project.repo.commits.first.parents.first
-    @commit = CommitDecorator.decorate(Commit.new(@commit))
-    @other_project = Factory :project, path: "OtherPath", code: "OtherCode"
-    @fake_user = Factory :user, name: "fred"
-  end
-
-  describe "#gfm" do
-    it "should return text if @project is not set" do
-      @project = nil
-
-      gfm("foo").should == "foo"
-    end
-
-    describe "referencing a commit" do
-      it "should link using a full id" do
-        gfm("Reverts changes from #{@commit.id}").should == "Reverts changes from #{link_to @commit.id, project_commit_path(@project, id: @commit.id), title: "Commit: #{@commit.author_name} - #{@commit.title}", class: "gfm gfm-commit "}"
-      end
-
-      it "should link using a short id" do
-        gfm("Backported from #{@commit.id[0, 6]}").should == "Backported from #{link_to @commit.id[0, 6], project_commit_path(@project, id: @commit.id), title: "Commit: #{@commit.author_name} - #{@commit.title}", class: "gfm gfm-commit "}"
-      end
-
-      it "should link with adjecent text" do
-        gfm("Reverted (see #{@commit.id})").should == "Reverted (see #{link_to @commit.id, project_commit_path(@project, id: @commit.id), title: "Commit: #{@commit.author_name} - #{@commit.title}", class: "gfm gfm-commit "})"
-      end
-
-      it "should not link with an invalid id" do
-        gfm("What happened in 12345678?").should == "What happened in 12345678?"
-      end
-    end
-
-    describe "referencing a team member" do
-      it "should link using a simple name" do
-        user = Factory :user, name: "barry"
-        @project.users << user
-        member = @project.users_projects.where(user_id: user).first
-
-        gfm("@#{user.name} you are right").should == "#{link_to "@#{user.name}", project_team_member_path(@project, member), class: "gfm gfm-team_member "} you are right"
-      end
-
-      it "should link using a name with dots" do
-        user = Factory :user, name: "alphA.Beta"
-        @project.users << user
-        member = @project.users_projects.where(user_id: user).first
-
-        gfm("@#{user.name} you are right").should == "#{link_to "@#{user.name}", project_team_member_path(@project, member), class: "gfm gfm-team_member "} you are right"
-      end
-
-      it "should link using name with underscores" do
-        user = Factory :user, name: "ping_pong_king"
-        @project.users << user
-        member = @project.users_projects.where(user_id: user).first
-
-        gfm("@#{user.name} you are right").should == "#{link_to "@#{user.name}", project_team_member_path(@project, member), class: "gfm gfm-team_member "} you are right"
-      end
-
-      it "should link with adjecent text" do
-        user = Factory.create(:user, name: "ace")
-        @project.users << user
-        member = @project.users_projects.where(user_id: user).first
-
-        gfm("Mail the Admin (@#{user.name})").should == "Mail the Admin (#{link_to "@#{user.name}", project_team_member_path(@project, member), class: "gfm gfm-team_member "})"
-      end
-
-      it "should add styles" do
-        user = Factory :user, name: "barry"
-        @project.users << user
-        gfm("@#{user.name} you are right").should have_selector(".gfm.gfm-team_member")
-      end
-
-      it "should not link using a bogus name" do
-        gfm("What hapened to @foo?").should == "What hapened to @foo?"
-      end
-    end
-
-    describe "referencing an issue" do
-      before do
-        @issue = Factory :issue, assignee: @fake_user, author: @fake_user, project: @project
-        @invalid_issue = Factory :issue, assignee: @fake_user, author: @fake_user, project: @other_project
-      end
-
-      it "should link using a correct id" do
-        gfm("Fixes ##{@issue.id}").should == "Fixes #{link_to "##{@issue.id}", project_issue_path(@project, @issue), title: "Issue: #{@issue.title}", class: "gfm gfm-issue "}"
-      end
-
-      it "should link with adjecent text" do
-        gfm("This has already been discussed (see ##{@issue.id})").should == "This has already been discussed (see #{link_to "##{@issue.id}", project_issue_path(@project, @issue), title: "Issue: #{@issue.title}", class: "gfm gfm-issue "})"
-      end
-
-      it "should add styles" do
-        gfm("Fixes ##{@issue.id}").should have_selector(".gfm.gfm-issue")
-      end
-
-      it "should not link using an invalid id" do
-        gfm("##{@invalid_issue.id} has been marked duplicate of this").should == "##{@invalid_issue.id} has been marked duplicate of this"
-      end
-    end
-
-    describe "referencing a merge request" do
-      before do
-        @merge_request = Factory :merge_request, assignee: @fake_user, author: @fake_user, project: @project
-        @invalid_merge_request = Factory :merge_request, assignee: @fake_user, author: @fake_user, project: @other_project
-      end
-
-      it "should link using a correct id" do
-        gfm("Fixed in !#{@merge_request.id}").should == "Fixed in #{link_to "!#{@merge_request.id}", project_merge_request_path(@project, @merge_request), title: "Merge Request: #{@merge_request.title}", class: "gfm gfm-merge_request "}"
-      end
-
-      it "should link with adjecent text" do
-        gfm("This has been fixed already (see !#{@merge_request.id})").should == "This has been fixed already (see #{link_to "!#{@merge_request.id}", project_merge_request_path(@project, @merge_request), title: "Merge Request: #{@merge_request.title}", class: "gfm gfm-merge_request "})"
-      end
-
-      it "should add styles" do
-        gfm("Fixed in !#{@merge_request.id}").should have_selector(".gfm.gfm-merge_request")
-      end
-
-      it "should not link using an invalid id" do
-        gfm("!#{@invalid_merge_request.id} violates our coding guidelines")
-      end
-    end
-
-    describe "referencing a snippet" do
-      before do
-        @snippet = Factory.create(:snippet,
-                                  title: "Render asset to string",
-                                  author: @fake_user,
-                                  project: @project)
-      end
-
-      it "should link using a correct id" do
-        gfm("Check out $#{@snippet.id}").should == "Check out #{link_to "$#{@snippet.id}", project_snippet_path(@project, @snippet), title: "Snippet: #{@snippet.title}", class: "gfm gfm-snippet "}"
-      end
-
-      it "should link with adjecent text" do
-        gfm("I have created a snippet for that ($#{@snippet.id})").should == "I have created a snippet for that (#{link_to "$#{@snippet.id}", project_snippet_path(@project, @snippet), title: "Snippet: #{@snippet.title}", class: "gfm gfm-snippet "})"
-      end
-
-      it "should add styles" do
-        gfm("Check out $#{@snippet.id}").should have_selector(".gfm.gfm-snippet")
-      end
-
-      it "should not link using an invalid id" do
-        gfm("Don't use $1234").should == "Don't use $1234"
-      end
-    end
-
-    it "should link to multiple things" do
-      user = Factory :user, name: "barry"
-      @project.users << user
-      member = @project.users_projects.where(user_id: user).first
-
-      gfm("Let @#{user.name} fix the *mess* in #{@commit.id}").should == "Let #{link_to "@#{user.name}", project_team_member_path(@project, member), class: "gfm gfm-team_member "} fix the *mess* in #{link_to @commit.id, project_commit_path(@project, id: @commit.id), title: "Commit: #{@commit.author_name} - #{@commit.title}", class: "gfm gfm-commit "}"
-    end
-
-    it "should not trip over other stuff", focus: true do
-      gfm("_Please_ *stop* 'helping' and all the other b*$#%' you do.").should == "_Please_ *stop* 'helping' and all the other b*$#%' you do."
-    end
-
-    it "should not touch HTML entities" do
-      gfm("We&#39;ll accept good pull requests.").should == "We&#39;ll accept good pull requests."
-    end
-
-    it "should forward HTML options to links" do
-      gfm("fixed in #{@commit.id}", class: "foo").should have_selector("a.foo")
-    end
-  end
-
-  describe "#link_to_gfm" do
-    let(:issue1) { Factory :issue, assignee: @fake_user, author: @fake_user, project: @project }
-    let(:issue2) { Factory :issue, assignee: @fake_user, author: @fake_user, project: @project }
-
-    it "should handle references nested in links with all the text" do
-      link_to_gfm("This should finally fix ##{issue1.id} and ##{issue2.id} for real", project_commit_path(@project, id: @commit.id)).should == "#{link_to "This should finally fix ", project_commit_path(@project, id: @commit.id)}#{link_to "##{issue1.id}", project_issue_path(@project, issue1), title: "Issue: #{issue1.title}", class: "gfm gfm-issue "}#{link_to " and ", project_commit_path(@project, id: @commit.id)}#{link_to "##{issue2.id}", project_issue_path(@project, issue2), title: "Issue: #{issue2.title}", class: "gfm gfm-issue "}#{link_to " for real", project_commit_path(@project, id: @commit.id)}"
-    end
-
-    it "should forward HTML options" do
-      link_to_gfm("This should finally fix ##{issue1.id} for real", project_commit_path(@project, id: @commit.id), class: "foo").should have_selector(".foo")
-    end
-  end
-
-  describe "#markdown" do
-    before do
-      @issue = Factory :issue, assignee: @fake_user, author: @fake_user, project: @project
-      @merge_request = Factory :merge_request, assignee: @fake_user, author: @fake_user, project: @project
-      @note = Factory.create(:note,
-                              note: "Screenshot of the new feature",
-                              project: @project,
-                              noteable_id: @commit.id,
-                              noteable_type: "Commit",
-                              attachment: "screenshot123.jpg")
-      @snippet = Factory.create(:snippet,
-                                title: "Render asset to string",
-                                author: @fake_user,
-                                project: @project)
-
-      @other_user = Factory :user, name: "bill"
-      @project.users << @other_user
-      @member = @project.users_projects.where(user_id: @other_user).first
-    end
-
-    it "should handle references in paragraphs" do
-      markdown("\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit. #{@commit.id} Nam pulvinar sapien eget odio adipiscing at faucibus orci vestibulum.\n").should == "<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. #{link_to @commit.id, project_commit_path(@project, id: @commit.id), title: "Commit: #{@commit.author_name} - #{@commit.title}", class: "gfm gfm-commit "} Nam pulvinar sapien eget odio adipiscing at faucibus orci vestibulum.</p>\n"
-    end
-
-    it "should handle references in headers" do
-      markdown("\n# Working around ##{@issue.id} for now\n## Apply !#{@merge_request.id}").should == "<h1 id=\"toc_0\">Working around #{link_to "##{@issue.id}", project_issue_path(@project, @issue), title: "Issue: #{@issue.title}", class: "gfm gfm-issue "} for now</h1>\n\n<h2 id=\"toc_1\">Apply #{link_to "!#{@merge_request.id}", project_merge_request_path(@project, @merge_request), title: "Merge Request: #{@merge_request.title}", class: "gfm gfm-merge_request "}</h2>\n"
-    end
-
-    it "should handle references in lists" do
-      markdown("\n* dark: ##{@issue.id}\n* light by @#{@other_user.name}\n").should == "<ul>\n<li>dark: #{link_to "##{@issue.id}", project_issue_path(@project, @issue), title: "Issue: #{@issue.title}", class: "gfm gfm-issue "}</li>\n<li>light by #{link_to "@#{@other_user.name}", project_team_member_path(@project, @member), class: "gfm gfm-team_member "}</li>\n</ul>\n"
-    end
-
-    it "should handle references in <em>" do
-      markdown("Apply _!#{@merge_request.id}_ ASAP").should == "<p>Apply <em>#{link_to "!#{@merge_request.id}", project_merge_request_path(@project, @merge_request), title: "Merge Request: #{@merge_request.title}", class: "gfm gfm-merge_request "}</em> ASAP</p>\n"
-    end
-
-    it "should leave code blocks untouched" do
-      markdown("\n    some code from $#{@snippet.id}\n    here too\n").should == "<div class=\"highlight\"><pre><span class=\"n\">some</span> <span class=\"n\">code</span> <span class=\"n\">from</span> $#{@snippet.id}\n<span class=\"n\">here</span> <span class=\"n\">too</span>\n</pre>\n</div>\n"
-
-      markdown("\n```\nsome code from $#{@snippet.id}\nhere too\n```\n").should == "<div class=\"highlight\"><pre><span class=\"n\">some</span> <span class=\"n\">code</span> <span class=\"n\">from</span> $#{@snippet.id}\n<span class=\"n\">here</span> <span class=\"n\">too</span>\n</pre>\n</div>\n"
-    end
-
-    it "should leave inline code untouched" do
-      markdown("\nDon't use `$#{@snippet.id}` here.\n").should == "<p>Don&#39;t use <code>$#{@snippet.id}</code> here.</p>\n"
-    end
-  end
-end
diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a6708a7acd634024f761b6a0f50f1ed4ec7cbece
--- /dev/null
+++ b/spec/helpers/gitlab_markdown_helper_spec.rb
@@ -0,0 +1,341 @@
+require "spec_helper"
+
+describe GitlabMarkdownHelper do
+  let!(:project) { create(:project) }
+
+  let(:user)          { create(:user, name: 'gfm') }
+  let(:commit)        { CommitDecorator.decorate(project.commit) }
+  let(:issue)         { create(:issue, project: project) }
+  let(:merge_request) { create(:merge_request, project: project) }
+  let(:snippet)       { create(:snippet, project: project) }
+  let(:member)        { project.users_projects.where(user_id: user).first }
+
+  before do
+    # Helper expects a @project instance variable
+    @project = project
+  end
+
+  describe "#gfm" do
+    it "should return unaltered text if project is nil" do
+      actual = "Testing references: ##{issue.id}"
+
+      gfm(actual).should_not == actual
+
+      @project = nil
+      gfm(actual).should == actual
+    end
+
+    it "should not alter non-references" do
+      actual = expected = "_Please_ *stop* 'helping' and all the other b*$#%' you do."
+      gfm(actual).should == expected
+    end
+
+    it "should not touch HTML entities" do
+      @project.issues.stub(:where).with(id: '39').and_return([issue])
+      actual = expected = "We&#39;ll accept good pull requests."
+      gfm(actual).should == expected
+    end
+
+    it "should forward HTML options to links" do
+      gfm("Fixed in #{commit.id}", class: "foo").should have_selector("a.gfm.foo")
+    end
+
+    describe "referencing a commit" do
+      let(:expected) { project_commit_path(project, commit) }
+
+      it "should link using a full id" do
+        actual = "Reverts #{commit.id}"
+        gfm(actual).should match(expected)
+      end
+
+      it "should link using a short id" do
+        actual = "Backported from #{commit.short_id(6)}"
+        gfm(actual).should match(expected)
+      end
+
+      it "should link with adjacent text" do
+        actual = "Reverted (see #{commit.id})"
+        gfm(actual).should match(expected)
+      end
+
+      it "should keep whitespace intact" do
+        actual   = "Changes #{commit.id} dramatically"
+        expected = /Changes <a.+>#{commit.id}<\/a> dramatically/
+        gfm(actual).should match(expected)
+      end
+
+      it "should not link with an invalid id" do
+        actual = expected = "What happened in #{commit.id.reverse}"
+        gfm(actual).should == expected
+      end
+
+      it "should include a title attribute" do
+        actual = "Reverts #{commit.id}"
+        gfm(actual).should match(/title="#{commit.link_title}"/)
+      end
+
+      it "should include standard gfm classes" do
+        actual = "Reverts #{commit.id}"
+        gfm(actual).should match(/class="\s?gfm gfm-commit\s?"/)
+      end
+    end
+
+    describe "referencing a team member" do
+      let(:actual)   { "@#{user.name} you are right." }
+      let(:expected) { project_team_member_path(project, member) }
+
+      before do
+        project.users << user
+      end
+
+      it "should link using a simple name" do
+        gfm(actual).should match(expected)
+      end
+
+      it "should link using a name with dots" do
+        user.update_attributes(name: "alphA.Beta")
+        gfm(actual).should match(expected)
+      end
+
+      it "should link using name with underscores" do
+        user.update_attributes(name: "ping_pong_king")
+        gfm(actual).should match(expected)
+      end
+
+      it "should link with adjacent text" do
+        actual = "Mail the admin (@gfm)"
+        gfm(actual).should match(expected)
+      end
+
+      it "should keep whitespace intact" do
+        actual   = "Yes, @#{user.name} is right."
+        expected = /Yes, <a.+>@#{user.name}<\/a> is right/
+        gfm(actual).should match(expected)
+      end
+
+      it "should not link with an invalid id" do
+        actual = expected = "@#{user.name.reverse} you are right."
+        gfm(actual).should == expected
+      end
+
+      it "should include standard gfm classes" do
+        gfm(actual).should match(/class="\s?gfm gfm-team_member\s?"/)
+      end
+    end
+
+    # Shared examples for referencing an object
+    #
+    # Expects the following attributes to be available in the example group:
+    #
+    # - object    - The object itself
+    # - reference - The object reference string (e.g., #1234, $1234, !1234)
+    #
+    # Currently limited to Snippets, Issues and MergeRequests
+    shared_examples 'referenced object' do
+      let(:actual)   { "Reference to #{reference}" }
+      let(:expected) { polymorphic_path([project, object]) }
+
+      it "should link using a valid id" do
+        gfm(actual).should match(expected)
+      end
+
+      it "should link with adjacent text" do
+        # Wrap the reference in parenthesis
+        gfm(actual.gsub(reference, "(#{reference})")).should match(expected)
+
+        # Append some text to the end of the reference
+        gfm(actual.gsub(reference, "#{reference}, right?")).should match(expected)
+      end
+
+      it "should keep whitespace intact" do
+        actual   = "Referenced #{reference} already."
+        expected = /Referenced <a.+>[^\s]+<\/a> already/
+        gfm(actual).should match(expected)
+      end
+
+      it "should not link with an invalid id" do
+        # Modify the reference string so it's still parsed, but is invalid
+        reference.gsub!(/^(.)(\d+)$/, '\1' + ('\2' * 2))
+        gfm(actual).should == actual
+      end
+
+      it "should include a title attribute" do
+        title = "#{object.class.to_s.titlecase}: #{object.title}"
+        gfm(actual).should match(/title="#{title}"/)
+      end
+
+      it "should include standard gfm classes" do
+        css = object.class.to_s.underscore
+        gfm(actual).should match(/class="\s?gfm gfm-#{css}\s?"/)
+      end
+    end
+
+    describe "referencing an issue" do
+      let(:object)    { issue }
+      let(:reference) { "##{issue.id}" }
+
+      include_examples 'referenced object'
+    end
+
+    describe "referencing a merge request" do
+      let(:object)    { merge_request }
+      let(:reference) { "!#{merge_request.id}" }
+
+      include_examples 'referenced object'
+    end
+
+    describe "referencing a snippet" do
+      let(:object)    { snippet }
+      let(:reference) { "$#{snippet.id}" }
+
+      include_examples 'referenced object'
+    end
+
+    describe "referencing multiple objects" do
+      let(:actual) { "!#{merge_request.id} -> #{commit.id} -> ##{issue.id}" }
+
+      it "should link to the merge request" do
+        expected = project_merge_request_path(project, merge_request)
+        gfm(actual).should match(expected)
+      end
+
+      it "should link to the commit" do
+        expected = project_commit_path(project, commit)
+        gfm(actual).should match(expected)
+      end
+
+      it "should link to the issue" do
+        expected = project_issue_path(project, issue)
+        gfm(actual).should match(expected)
+      end
+    end
+
+    describe "emoji" do
+      it "matches at the start of a string" do
+        gfm(":+1:").should match(/<img/)
+      end
+
+      it "matches at the end of a string" do
+        gfm("This gets a :-1:").should match(/<img/)
+      end
+
+      it "matches with adjacent text" do
+        gfm("+1 (:+1:)").should match(/<img/)
+      end
+
+      it "has a title attribute" do
+        gfm(":-1:").should match(/title=":-1:"/)
+      end
+
+      it "has an alt attribute" do
+        gfm(":-1:").should match(/alt=":-1:"/)
+      end
+
+      it "has an emoji class" do
+        gfm(":+1:").should match('class="emoji"')
+      end
+
+      it "sets height and width" do
+        actual = gfm(":+1:")
+        actual.should match(/width="20"/)
+        actual.should match(/height="20"/)
+      end
+
+      it "keeps whitespace intact" do
+        gfm("This deserves a :+1: big time.").should match(/deserves a <img.+\/> big time/)
+      end
+
+      it "ignores invalid emoji" do
+        gfm(":invalid-emoji:").should_not match(/<img/)
+      end
+
+      it "should work independet of reference links (i.e. without @project being set)" do
+        @project = nil
+        gfm(":+1:").should match(/<img/)
+      end
+    end
+  end
+
+  describe "#link_to_gfm" do
+    let(:commit_path) { project_commit_path(project, commit) }
+    let(:issues)      { create_list(:issue, 2, project: project) }
+
+    it "should handle references nested in links with all the text" do
+      actual = link_to_gfm("This should finally fix ##{issues[0].id} and ##{issues[1].id} for real", commit_path)
+
+      # Break the result into groups of links with their content, without
+      # closing tags
+      groups = actual.split("</a>")
+
+      # Leading commit link
+      groups[0].should match(/href="#{commit_path}"/)
+      groups[0].should match(/This should finally fix $/)
+
+      # First issue link
+      groups[1].should match(/href="#{project_issue_path(project, issues[0])}"/)
+      groups[1].should match(/##{issues[0].id}$/)
+
+      # Internal commit link
+      groups[2].should match(/href="#{commit_path}"/)
+      groups[2].should match(/ and /)
+
+      # Second issue link
+      groups[3].should match(/href="#{project_issue_path(project, issues[1])}"/)
+      groups[3].should match(/##{issues[1].id}$/)
+
+      # Trailing commit link
+      groups[4].should match(/href="#{commit_path}"/)
+      groups[4].should match(/ for real$/)
+    end
+
+    it "should forward HTML options" do
+      actual = link_to_gfm("Fixed in #{commit.id}", commit_path, class: 'foo')
+      actual.should have_selector 'a.gfm.gfm-commit.foo'
+    end
+
+    it "escapes HTML passed in as the body" do
+      actual = "This is a <h1>test</h1> - see ##{issues[0].id}"
+      link_to_gfm(actual, commit_path).should match('&lt;h1&gt;test&lt;/h1&gt;')
+    end
+  end
+
+  describe "#markdown" do
+    it "should handle references in paragraphs" do
+      actual = "\n\nLorem ipsum dolor sit amet. #{commit.id} Nam pulvinar sapien eget.\n"
+      expected = project_commit_path(project, commit)
+      markdown(actual).should match(expected)
+    end
+
+    it "should handle references in headers" do
+      actual = "\n# Working around ##{issue.id}\n## Apply !#{merge_request.id}"
+
+      markdown(actual).should match(%r{<h1[^<]*>Working around <a.+>##{issue.id}</a></h1>})
+      markdown(actual).should match(%r{<h2[^<]*>Apply <a.+>!#{merge_request.id}</a></h2>})
+    end
+
+    it "should handle references in lists" do
+      project.users << user
+
+      actual = "\n* dark: ##{issue.id}\n* light by @#{member.user_name}"
+
+      markdown(actual).should match(%r{<li>dark: <a.+>##{issue.id}</a></li>})
+      markdown(actual).should match(%r{<li>light by <a.+>@#{member.user_name}</a></li>})
+    end
+
+    it "should handle references in <em>" do
+      actual = "Apply _!#{merge_request.id}_ ASAP"
+
+      markdown(actual).should match(%r{Apply <em><a.+>!#{merge_request.id}</a></em>})
+    end
+
+    it "should leave code blocks untouched" do
+      markdown("\n    some code from $#{snippet.id}\n    here too\n").should == "<div class=\"highlight\"><pre><span class=\"n\">some</span> <span class=\"n\">code</span> <span class=\"n\">from</span> $#{snippet.id}\n<span class=\"n\">here</span> <span class=\"n\">too</span>\n</pre>\n</div>\n"
+
+      markdown("\n```\nsome code from $#{snippet.id}\nhere too\n```\n").should == "<div class=\"highlight\"><pre><span class=\"n\">some</span> <span class=\"n\">code</span> <span class=\"n\">from</span> $#{snippet.id}\n<span class=\"n\">here</span> <span class=\"n\">too</span>\n</pre>\n</div>\n"
+    end
+
+    it "should leave inline code untouched" do
+      markdown("\nDon't use `$#{snippet.id}` here.\n").should == "<p>Don&#39;t use <code>$#{snippet.id}</code> here.</p>\n"
+    end
+  end
+end
diff --git a/spec/helpers/tree_helper_spec.rb b/spec/helpers/tree_helper_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d450b687cafef2b508e2f818805e95748c486433
--- /dev/null
+++ b/spec/helpers/tree_helper_spec.rb
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+describe TreeHelper do
+  describe '#markup?' do
+    %w(textile rdoc org creole mediawiki rst asciidoc pod).each do |type|
+      it "returns true for #{type} files" do
+        markup?("README.#{type}").should be_true
+      end
+    end
+
+    it "returns false when given a non-markup filename" do
+      markup?('README.rb').should_not be_true
+    end
+  end
+end
diff --git a/spec/lib/auth_spec.rb b/spec/lib/auth_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..1e03bc591b485b6a5a08eef89025478bfd3f6cf4
--- /dev/null
+++ b/spec/lib/auth_spec.rb
@@ -0,0 +1,95 @@
+require 'spec_helper'
+
+describe Gitlab::Auth do
+  let(:gl_auth) { Gitlab::Auth.new }
+
+  before do
+    Gitlab.config.stub(omniauth: {})
+
+    @info = mock(
+      uid: '12djsak321',
+      name: 'John',
+      email: 'john@mail.com'
+    )
+  end
+
+  describe :find_for_ldap_auth do
+    before do
+      @auth = mock(
+        uid: '12djsak321',
+        info: @info,
+        provider: 'ldap'
+      )
+    end
+
+    it "should find by uid & provider" do
+      User.should_receive :find_by_extern_uid_and_provider
+      gl_auth.find_for_ldap_auth(@auth)
+    end
+
+    it "should update credentials by email if missing uid" do
+      user = double('User')
+      User.stub find_by_extern_uid_and_provider: nil
+      User.stub find_by_email: user
+      user.should_receive :update_attributes
+      gl_auth.find_for_ldap_auth(@auth)
+    end
+
+
+    it "should create from auth if user doesnot exist"do
+      User.stub find_by_extern_uid_and_provider: nil
+      User.stub find_by_email: nil
+      gl_auth.should_receive :create_from_omniauth
+      gl_auth.find_for_ldap_auth(@auth)
+    end
+  end
+
+  describe :find_or_new_for_omniauth do
+    before do
+      @auth = mock(
+        info: @info,
+        provider: 'twitter',
+        uid: '12djsak321',
+      )
+    end
+
+    it "should find user"do
+      User.should_receive :find_by_provider_and_extern_uid
+      gl_auth.should_not_receive :create_from_omniauth
+      gl_auth.find_or_new_for_omniauth(@auth)
+    end
+
+    it "should not create user"do
+      User.stub find_by_provider_and_extern_uid: nil
+      gl_auth.should_not_receive :create_from_omniauth
+      gl_auth.find_or_new_for_omniauth(@auth)
+    end
+
+    it "should create user if single_sing_on"do
+      Gitlab.config.omniauth['allow_single_sign_on'] = true
+      User.stub find_by_provider_and_extern_uid: nil
+      gl_auth.should_receive :create_from_omniauth
+      gl_auth.find_or_new_for_omniauth(@auth)
+    end
+  end
+
+  describe :create_from_omniauth do
+    it "should create user from LDAP" do
+      @auth = mock(info: @info, provider: 'ldap')
+      user = gl_auth.create_from_omniauth(@auth, true)
+
+      user.should be_valid
+      user.extern_uid.should == @info.uid
+      user.provider.should == 'ldap'
+    end
+
+    it "should create user from Omniauth" do
+      @auth = mock(info: @info, provider: 'twitter')
+      user = gl_auth.create_from_omniauth(@auth, false)
+
+      user.should be_valid
+      user.extern_uid.should == @info.uid
+      user.provider.should == 'twitter'
+    end
+  end
+end
diff --git a/spec/lib/gitolite_config_spec.rb b/spec/lib/gitolite_config_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c3ce0db569aef71093eefac45a2acb61bc07b093
--- /dev/null
+++ b/spec/lib/gitolite_config_spec.rb
@@ -0,0 +1,16 @@
+require 'spec_helper'
+
+describe Gitlab::GitoliteConfig do
+  let(:gitolite) { Gitlab::GitoliteConfig.new }
+
+  it { should respond_to :write_key }
+  it { should respond_to :rm_key }
+  it { should respond_to :update_project }
+  it { should respond_to :update_project! }
+  it { should respond_to :update_projects }
+  it { should respond_to :destroy_project }
+  it { should respond_to :destroy_project! }
+  it { should respond_to :apply }
+  it { should respond_to :admin_all_repo }
+  it { should respond_to :admin_all_repo! }
+end
diff --git a/spec/lib/gitolite_spec.rb b/spec/lib/gitolite_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..cc8ce8b2ccefac97dd6954e2659c89a543d4a227
--- /dev/null
+++ b/spec/lib/gitolite_spec.rb
@@ -0,0 +1,25 @@
+require 'spec_helper'
+
+describe Gitlab::Gitolite do
+  let(:project) { double('Project', path: 'diaspora') }
+  let(:gitolite_config) { double('Gitlab::GitoliteConfig') }
+  let(:gitolite) { Gitlab::Gitolite.new }
+
+  before do
+    gitolite.stub(config: gitolite_config)
+  end
+
+  it { should respond_to :set_key }
+  it { should respond_to :remove_key }
+
+  it { should respond_to :update_repository }
+  it { should respond_to :create_repository }
+  it { should respond_to :remove_repository }
+
+  it { gitolite.url_to_repo('diaspora').should == Gitlab.config.ssh_path + "diaspora.git" }
+
+  it "should call config update" do
+    gitolite_config.should_receive(:update_project!)
+    gitolite.update_repository project
+  end
+end
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index 93427ebfacd86e18c25e72421f89238b3d63b5d9..4a9f142e50dcf1f6f87ad7e437a86d2b34faf622 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -24,7 +24,7 @@ describe Notify do
     end
 
     it 'has the correct subject' do
-      should have_subject /^gitlab \| Account was created for you$/
+      should have_subject /^gitlab \| Account was created for you$/i
     end
 
     it 'contains the new user\'s login name' do
@@ -91,6 +91,29 @@ describe Notify do
             should have_body_text /#{project_issue_path project, issue}/
           end
         end
+
+        describe 'status changed' do
+          let(:current_user) { Factory.create :user, email: "current@email.com" }
+          let(:status) { 'closed' }
+          subject { Notify.issue_status_changed_email(recipient.id, issue.id, status, current_user) }
+        
+          it 'has the correct subject' do
+            should have_subject /changed issue ##{issue.id} \| #{issue.title}/i
+          end
+
+          it 'contains the new status' do
+            should have_body_text /#{status}/i
+          end
+
+          it 'contains the user name' do
+            should have_body_text /#{current_user.name}/i
+          end
+
+          it 'contains a link to the issue' do
+            should have_body_text /#{project_issue_path project, issue}/
+          end
+        end
+
       end
 
       context 'for merge requests' do
@@ -145,6 +168,26 @@ describe Notify do
       end
     end
 
+    describe 'project access changed' do
+      let(:project) { Factory.create(:project, 
+                                      path: "Fuu", 
+                                      code: "Fuu") }
+      let(:user) { Factory.create :user }
+      let(:users_project) { Factory.create(:users_project, 
+                                           project: project, 
+                                           user: user) }
+      subject { Notify.project_access_granted_email(users_project.id) }
+      it 'has the correct subject' do
+        should have_subject /access to project was granted/
+      end
+      it 'contains name of project' do
+        should have_body_text /#{project.name}/
+      end
+      it 'contains new user role' do
+        should have_body_text /#{users_project.project_access_human}/
+      end
+    end
+
     context 'items that are noteable, the email for a note' do
       let(:note_author) { Factory.create(:user, name: 'author_name') }
       let(:note) { Factory.create(:note, project: project, author: note_author) }
diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb
index 188f09978a7bf6c84a7a36d6db7200ff7df0140c..5cb68761b29b064105e8f9c75934b51144828464 100644
--- a/spec/models/event_spec.rb
+++ b/spec/models/event_spec.rb
@@ -1,24 +1,9 @@
-# == Schema Information
-#
-# Table name: events
-#
-#  id          :integer(4)      not null, primary key
-#  target_type :string(255)
-#  target_id   :integer(4)
-#  title       :string(255)
-#  data        :text
-#  project_id  :integer(4)
-#  created_at  :datetime        not null
-#  updated_at  :datetime        not null
-#  action      :integer(4)
-#  author_id   :integer(4)
-#
-
 require 'spec_helper'
 
 describe Event do
   describe "Associations" do
     it { should belong_to(:project) }
+    it { should belong_to(:target) }
   end
 
   describe "Respond to" do
@@ -29,22 +14,12 @@ describe Event do
     it { should respond_to(:commits) }
   end
 
-  describe "Creation" do
-    before do 
-      @event = Factory :event
-    end
-
-    it "should create a valid event" do 
-      @event.should be_valid
-    end
-  end
-
-  describe "Push event" do 
-    before do 
+  describe "Push event" do
+    before do
       project = Factory :project
       @user = project.owner
 
-      data = { 
+      data = {
         before: "0000000000000000000000000000000000000000",
         after: "0220c11b9a3e6c69dc8fd35321254ca9a7b98f7e",
         ref: "refs/heads/master",
@@ -74,4 +49,25 @@ describe Event do
     it { @event.branch_name.should == "master" }
     it { @event.author.should == @user }
   end
+
+  describe 'Team events' do
+    let(:user_project) { stub.as_null_object }
+    let(:observer) { UsersProjectObserver.instance }
+
+    before {
+      Event.should_receive :create
+    }
+
+    describe "Joined project team" do
+      it "should create event" do
+        observer.after_create user_project
+      end
+    end
+
+    describe "Left project team" do
+      it "should create event" do
+        observer.after_destroy user_project
+      end
+    end
+  end
 end
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index e9cbd72589a78414bd443ea9cf6f17bae73f3b1a..34192da94ad0bb0d1d1a2ae3cd6da12644daca70 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -2,28 +2,20 @@ require 'spec_helper'
 
 describe Issue do
   describe "Associations" do
-    it { should belong_to(:project) }
-    it { should belong_to(:author) }
-    it { should belong_to(:assignee) }
     it { should belong_to(:milestone) }
   end
 
   describe "Validation" do
-    it { should validate_presence_of(:title) }
-    it { should validate_presence_of(:author_id) }
-    it { should validate_presence_of(:project_id) }
+    it { should ensure_length_of(:description).is_within(0..2000) }
+    it { should ensure_inclusion_of(:closed).in_array([true, false]) }
   end
 
-  describe "Scope" do
-    it { Issue.should respond_to :closed }
-    it { Issue.should respond_to :opened }
+  describe 'modules' do
+    it { should include_module(IssueCommonality) }
+    it { should include_module(Votes) }
   end
 
-  subject { Factory.create(:issue,
-                           author: Factory(:user),
-                           assignee: Factory(:user),
-                           project: Factory.create(:project)) }
-  it { should be_valid }
+  subject { Factory.create(:issue) }
 
   describe '#is_being_reassigned?' do
     it 'returns true if the issue assignee has changed' do
@@ -41,11 +33,7 @@ describe Issue do
       subject.is_being_closed?.should be_true
     end
     it 'returns false if the closed attribute has changed and is now false' do
-      issue = Factory.create(:issue,
-                             closed: true,
-                             author: Factory(:user),
-                             assignee: Factory(:user),
-                             project: Factory.create(:project))
+      issue = Factory.create(:closed_issue)
       issue.closed = false
       issue.is_being_closed?.should be_false
     end
@@ -57,11 +45,7 @@ describe Issue do
 
   describe '#is_being_reopened?' do
     it 'returns true if the closed attribute has changed and is now false' do
-      issue = Factory.create(:issue,
-                             closed: true,
-                             author: Factory(:user),
-                             assignee: Factory(:user),
-                             project: Factory.create(:project))
+      issue = Factory.create(:closed_issue)
       issue.closed = false
       issue.is_being_reopened?.should be_true
     end
@@ -73,64 +57,4 @@ describe Issue do
       subject.is_being_reopened?.should be_false
     end
   end
-
-  describe "plus 1" do
-    let(:project) { Factory(:project) }
-    subject {
-      Factory.create(:issue,
-                     author: Factory(:user),
-                     assignee: Factory(:user),
-                     project: project)
-    }
-
-    it "with no notes has a 0/0 score" do
-      subject.upvotes.should == 0
-    end
-
-    it "should recognize non-+1 notes" do
-      subject.notes << Factory(:note, note: "No +1 here", project: Factory(:project, path: 'plusone', code: 'plusone'))
-      subject.should have(1).note
-      subject.notes.first.upvote?.should be_false
-      subject.upvotes.should == 0
-    end
-
-    it "should recognize a single +1 note" do
-      subject.notes << Factory(:note, note: "+1 This is awesome", project: Factory(:project, path: 'plusone', code: 'plusone'))
-      subject.upvotes.should == 1
-    end
-
-    it "should recognize a multiple +1 notes" do
-      subject.notes << Factory(:note, note: "+1 This is awesome", project: Factory(:project, path: 'plusone', code: 'plusone'))
-      subject.notes << Factory(:note, note: "+1 I want this", project: Factory(:project, path: 'plustwo', code: 'plustwo'))
-      subject.upvotes.should == 2
-    end
-  end
-
-  describe ".search" do
-    let!(:issue) { Factory.create(:issue, title: "Searchable issue",
-                                 project: Factory.create(:project)) }
-
-    it "matches by title" do
-      Issue.search('able').all.should == [issue]
-    end
-  end
 end
-# == Schema Information
-#
-# Table name: issues
-#
-#  id           :integer(4)      not null, primary key
-#  title        :string(255)
-#  assignee_id  :integer(4)
-#  author_id    :integer(4)
-#  project_id   :integer(4)
-#  created_at   :datetime        not null
-#  updated_at   :datetime        not null
-#  closed       :boolean(1)      default(FALSE), not null
-#  position     :integer(4)      default(0)
-#  critical     :boolean(1)      default(FALSE), not null
-#  branch_name  :string(255)
-#  description  :text
-#  milestone_id :integer(4)
-#
-
diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb
index 0f9b31778df18c648efc867be7bc70e37c7577f9..85cd291d6818e425986e0b37b13756e9e5b4cfa6 100644
--- a/spec/models/key_spec.rb
+++ b/spec/models/key_spec.rb
@@ -2,12 +2,15 @@ require 'spec_helper'
 
 describe Key do
   describe "Associations" do
-    it { should belong_to(:user) or belong_to(:project)  }
+    it { should belong_to(:user) }
+    it { should belong_to(:project) }
   end
 
   describe "Validation" do
     it { should validate_presence_of(:title) }
     it { should validate_presence_of(:key) }
+    it { should ensure_length_of(:title).is_within(0..255) }
+    it { should ensure_length_of(:key).is_within(0..5000) }
   end
 
   describe "Methods" do
@@ -17,20 +20,15 @@ describe Key do
   context "validation of uniqueness" do
 
     context "as a deploy key" do
-      let(:project) { Factory.create(:project, path: 'alpha', code: 'alpha') }
-      let(:another_project) { Factory.create(:project, path: 'beta', code: 'beta') }
-
-      before do
-        deploy_key = Factory.create(:key, project: project)
-      end
+      let!(:deploy_key) { create(:deploy_key) }
 
       it "does not accept the same key twice for a project" do
-        key = Factory.new(:key, project: project)
+        key = build(:key, project: deploy_key.project)
         key.should_not be_valid
       end
 
       it "does accept the same key for another project" do
-        key = Factory.new(:key, project: another_project)
+        key = build(:key, project_id: 0)
         key.should be_valid
       end
     end
@@ -39,27 +37,13 @@ describe Key do
       let(:user) { Factory.create(:user) }
 
       it "accepts the key once" do
-        Factory.new(:key, user: user).should be_valid
+        build(:key, user: user).should be_valid
       end
 
       it "does not accepts the key twice" do
-        Factory.create(:key, user: user)
-        Factory.new(:key, user: user).should_not be_valid
+        create(:key, user: user)
+        build(:key, user: user).should_not be_valid
       end
     end
   end
 end
-# == Schema Information
-#
-# Table name: keys
-#
-#  id         :integer(4)      not null, primary key
-#  user_id    :integer(4)
-#  created_at :datetime        not null
-#  updated_at :datetime        not null
-#  key        :text
-#  title      :string(255)
-#  identifier :string(255)
-#  project_id :integer(4)
-#
-
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index c7ad08a1e06c7ebc9d33c89286d49e1c20f4bda2..523e823de34358add83f11fa88805e0ceff725fe 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -1,88 +1,13 @@
 require 'spec_helper'
 
 describe MergeRequest do
-  describe "Associations" do
-    it { should belong_to(:project) }
-    it { should belong_to(:author) }
-    it { should belong_to(:assignee) }
-  end
-
   describe "Validation" do
     it { should validate_presence_of(:target_branch) }
     it { should validate_presence_of(:source_branch) }
-    it { should validate_presence_of(:title) }
-    it { should validate_presence_of(:author_id) }
-    it { should validate_presence_of(:project_id) }
   end
 
-  describe "Scope" do
-    it { MergeRequest.should respond_to :closed }
-    it { MergeRequest.should respond_to :opened }
-  end
-
-  it { Factory.create(:merge_request,
-                      author: Factory(:user),
-                      assignee: Factory(:user),
-                      project: Factory.create(:project)).should be_valid }
-
-  describe "plus 1" do
-    let(:project) { Factory(:project) }
-    subject {
-      Factory.create(:merge_request,
-                     author: Factory(:user),
-                     assignee: Factory(:user),
-                     project: project)
-    }
-
-    it "with no notes has a 0/0 score" do
-      subject.upvotes.should == 0
-    end
-
-    it "should recognize non-+1 notes" do
-      subject.notes << Factory(:note, note: "No +1 here", project: Factory(:project, path: 'plusone', code: 'plusone'))
-      subject.should have(1).note
-      subject.notes.first.upvote?.should be_false
-      subject.upvotes.should == 0
-    end
-
-    it "should recognize a single +1 note" do
-      subject.notes << Factory(:note, note: "+1 This is awesome", project: Factory(:project, path: 'plusone', code: 'plusone'))
-      subject.upvotes.should == 1
-    end
-
-    it "should recognize a multiple +1 notes" do
-      subject.notes << Factory(:note, note: "+1 This is awesome", project: Factory(:project, path: 'plusone', code: 'plusone'))
-      subject.notes << Factory(:note, note: "+1 I want this", project: Factory(:project, path: 'plustwo', code: 'plustwo'))
-      subject.upvotes.should == 2
-    end
-  end
-
-  describe ".search" do
-    let!(:issue) { Factory.create(:issue, title: "Searchable issue",
-                                 project: Factory.create(:project)) }
-
-    it "matches by title" do
-      Issue.search('able').all.should == [issue]
-    end
+  describe 'modules' do
+    it { should include_module(IssueCommonality) }
+    it { should include_module(Votes) }
   end
 end
-# == Schema Information
-#
-# Table name: merge_requests
-#
-#  id            :integer(4)      not null, primary key
-#  target_branch :string(255)     not null
-#  source_branch :string(255)     not null
-#  project_id    :integer(4)      not null
-#  author_id     :integer(4)
-#  assignee_id   :integer(4)
-#  title         :string(255)
-#  closed        :boolean(1)      default(FALSE), not null
-#  created_at    :datetime        not null
-#  updated_at    :datetime        not null
-#  st_commits    :text(2147483647
-#  st_diffs      :text(2147483647
-#  merged        :boolean(1)      default(FALSE), not null
-#  state         :integer(4)      default(1), not null
-#
-
diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb
index 880d3f307a328928d945a4a80bc02e7e67bbb8ee..f0f0f88303f7ca424b3fd3c39fd1f8bf97fa3fce 100644
--- a/spec/models/milestone_spec.rb
+++ b/spec/models/milestone_spec.rb
@@ -1,17 +1,3 @@
-# == Schema Information
-#
-# Table name: milestones
-#
-#  id          :integer(4)      not null, primary key
-#  title       :string(255)     not null
-#  project_id  :integer(4)      not null
-#  description :text
-#  due_date    :date
-#  closed      :boolean(1)      default(FALSE), not null
-#  created_at  :datetime        not null
-#  updated_at  :datetime        not null
-#
-
 require 'spec_helper'
 
 describe Milestone do
@@ -23,32 +9,39 @@ describe Milestone do
   describe "Validation" do
     it { should validate_presence_of(:title) }
     it { should validate_presence_of(:project_id) }
+    it { should ensure_inclusion_of(:closed).in_array([true, false]) }
   end
 
-  let(:project) { Factory :project }
-  let(:milestone) { Factory :milestone, project: project }
-  let(:issue) { Factory :issue, project: project }
-
-  it { milestone.should be_valid }
+  let(:milestone) { Factory :milestone }
+  let(:issue) { Factory :issue }
 
-  describe "Issues" do 
-    before do 
+  describe "#percent_complete" do
+    it "should not count open issues" do
       milestone.issues << issue
+      milestone.percent_complete.should == 0
     end
 
-    it { milestone.percent_complete.should == 0 }
+    it "should count closed issues" do
+      issue.update_attributes(closed: true)
+      milestone.issues << issue
+      milestone.percent_complete.should == 100
+    end
 
-    it do 
-      issue.update_attributes closed: true
+    it "should recover from dividing by zero" do
+      milestone.issues.should_receive(:count).and_return(0)
       milestone.percent_complete.should == 100
     end
   end
 
-  describe :expires_at do 
-    before do 
-      milestone.update_attributes due_date: Date.today + 1.day
+  describe "#expires_at" do
+    it "should be nil when due_date is unset" do
+      milestone.update_attributes(due_date: nil)
+      milestone.expires_at.should be_nil
     end
 
-    it { milestone.expires_at.should_not be_nil }
+    it "should not be nil when due_date is set" do
+      milestone.update_attributes(due_date: Date.tomorrow)
+      milestone.expires_at.should be_present
+    end
   end
 end
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index c97b23cb4fa55b98901ae748fb5a62cffd335116..7809953f5b32fd8d386e8aa5779f7351df0593a5 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -1,11 +1,10 @@
 require 'spec_helper'
 
 describe Note do
-  let(:project) { Factory :project }
-  let!(:commit) { project.commit }
-
   describe "Associations" do
     it { should belong_to(:project) }
+    it { should belong_to(:noteable) }
+    it { should belong_to(:author).class_name('User') }
   end
 
   describe "Validation" do
@@ -13,8 +12,6 @@ describe Note do
     it { should validate_presence_of(:project) }
   end
 
-  it { Factory.create(:note,
-                      project: project).should be_valid }
   describe "Scopes" do
     it "should have a today named scope that returns ..." do
       Note.today.where_values.should == ["created_at >= '#{Date.today}'"]
@@ -25,26 +22,44 @@ describe Note do
     let(:project) { Factory(:project) }
 
     it "recognizes a neutral note" do
-      note = Factory(:note, project: project, note: "This is not a +1 note")
+      note = Factory(:note, note: "This is not a +1 note")
+      note.should_not be_upvote
+      note.should_not be_downvote
+    end
+
+    it "recognizes a neutral emoji note" do
+      note = build(:note, note: "I would :+1: this, but I don't want to")
       note.should_not be_upvote
+      note.should_not be_downvote
     end
 
     it "recognizes a +1 note" do
-      note = Factory(:note, project: project, note: "+1 for this")
+      note = Factory(:note, note: "+1 for this")
       note.should be_upvote
     end
 
-    it "recognizes a -1 note as no vote" do
-      note = Factory(:note, project: project, note: "-1 for this")
-      note.should_not be_upvote
+    it "recognizes a +1 emoji as a vote" do
+      note = build(:note, note: ":+1: for this")
+      note.should be_upvote
+    end
+
+    it "recognizes a -1 note" do
+      note = Factory(:note, note: "-1 for this")
+      note.should be_downvote
+    end
+
+    it "recognizes a -1 emoji as a vote" do
+      note = build(:note, note: ":-1: for this")
+      note.should be_downvote
     end
   end
 
-  describe "Commit notes" do
+  let(:project) { create(:project) }
+  let(:commit) { project.commit }
 
+  describe "Commit notes" do
     before do
       @note = Factory :note,
-        project: project,
         noteable_id: commit.id,
         noteable_type: "Commit"
     end
@@ -58,7 +73,6 @@ describe Note do
   describe "Pre-line commit notes" do
     before do
       @note = Factory :note,
-        project: project,
         noteable_id: commit.id,
         noteable_type: "Commit",
         line_code: "0_16_1"
@@ -91,8 +105,8 @@ describe Note do
 
   describe :authorization do
     before do
-      @p1 = project
-      @p2 = Factory :project, code: "alien", path: "gitlabhq_1"
+      @p1 = create(:project)
+      @p2 = Factory :project
       @u1 = Factory :user
       @u2 = Factory :user
       @u3 = Factory :user
@@ -135,19 +149,3 @@ describe Note do
     end
   end
 end
-# == Schema Information
-#
-# Table name: notes
-#
-#  id            :integer(4)      not null, primary key
-#  note          :text
-#  noteable_id   :string(255)
-#  noteable_type :string(255)
-#  author_id     :integer(4)
-#  created_at    :datetime        not null
-#  updated_at    :datetime        not null
-#  project_id    :integer(4)
-#  attachment    :string(255)
-#  line_code     :string(255)
-#
-
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index af193295ee3e78e1231c8cd1dfeb6495b6f2ca69..756f69ded56425e01e40de3d8461623cc552aea6 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -2,23 +2,56 @@ require 'spec_helper'
 
 describe Project do
   describe "Associations" do
+    it { should belong_to(:owner).class_name('User') }
     it { should have_many(:users) }
-    it { should have_many(:protected_branches).dependent(:destroy) }
     it { should have_many(:events).dependent(:destroy) }
-    it { should have_many(:wikis).dependent(:destroy) }
     it { should have_many(:merge_requests).dependent(:destroy) }
-    it { should have_many(:users_projects).dependent(:destroy) }
     it { should have_many(:issues).dependent(:destroy) }
+    it { should have_many(:milestones).dependent(:destroy) }
+    it { should have_many(:users_projects).dependent(:destroy) }
     it { should have_many(:notes).dependent(:destroy) }
     it { should have_many(:snippets).dependent(:destroy) }
-    it { should have_many(:hooks).dependent(:destroy) }
     it { should have_many(:deploy_keys).dependent(:destroy) }
+    it { should have_many(:hooks).dependent(:destroy) }
+    it { should have_many(:wikis).dependent(:destroy) }
+    it { should have_many(:protected_branches).dependent(:destroy) }
   end
 
   describe "Validation" do
+    let!(:project) { create(:project) }
+
     it { should validate_presence_of(:name) }
+    it { should validate_uniqueness_of(:name) }
+    it { should ensure_length_of(:name).is_within(0..255) }
+
     it { should validate_presence_of(:path) }
+    it { should validate_uniqueness_of(:path) }
+    it { should ensure_length_of(:path).is_within(0..255) }
+    # TODO: Formats
+
+    it { should ensure_length_of(:description).is_within(0..2000) }
+
     it { should validate_presence_of(:code) }
+    it { should validate_uniqueness_of(:code) }
+    it { should ensure_length_of(:code).is_within(1..255) }
+    # TODO: Formats
+
+    it { should validate_presence_of(:owner) }
+    it { should ensure_inclusion_of(:issues_enabled).in_array([true, false]) }
+    it { should ensure_inclusion_of(:wall_enabled).in_array([true, false]) }
+    it { should ensure_inclusion_of(:merge_requests_enabled).in_array([true, false]) }
+    it { should ensure_inclusion_of(:wiki_enabled).in_array([true, false]) }
+
+    it "should not allow new projects beyond user limits" do
+      project.stub(:owner).and_return(double(can_create_project?: false, projects_limit: 1))
+      project.should_not be_valid
+      project.errors[:base].first.should match(/Your own projects limit is 1/)
+    end
+
+    it "should not allow 'gitolite-admin' as repo name" do
+      should allow_value("blah").for(:path)
+      should_not allow_value("gitolite-admin").for(:path)
+    end
   end
 
   describe "Respond to" do
@@ -73,9 +106,11 @@ describe Project do
     it { should respond_to(:trigger_post_receive) }
   end
 
-  it "should not allow 'gitolite-admin' as repo name" do
-    should allow_value("blah").for(:path)
-    should_not allow_value("gitolite-admin").for(:path)
+  describe 'modules' do
+    it { should include_module(Repository) }
+    it { should include_module(PushObserver) }
+    it { should include_module(Authority) }
+    it { should include_module(Team) }
   end
 
   it "should return valid url to repo" do
@@ -85,7 +120,7 @@ describe Project do
 
   it "should return path to repo" do
     project = Project.new(path: "somewhere")
-    project.path_to_repo.should == File.join(Rails.root, "tmp", "tests", "somewhere")
+    project.path_to_repo.should == File.join(Rails.root, "tmp", "repositories", "somewhere")
   end
 
   it "returns the full web URL for this repo" do
@@ -110,7 +145,7 @@ describe Project do
     let(:last_event) { double }
 
     before do
-      project.stub(:events).and_return( [ double, double, last_event ] )
+      project.stub_chain(:events, :order).and_return( [ double, double, last_event ] )
     end
 
     it { project.last_activity.should == last_event }
@@ -208,7 +243,7 @@ describe Project do
     end
   end
 
-  describe :update_merge_requests do 
+  describe :update_merge_requests do
     let(:project) { Factory :project }
 
     before do
@@ -228,7 +263,7 @@ describe Project do
       @merge_request.closed.should be_true
     end
 
-    it "should update merge request commits with new one if pushed to source branch" do 
+    it "should update merge request commits with new one if pushed to source branch" do
       @merge_request.last_commit.should == nil
       project.update_merge_requests("8716fc78f3c65bbf7bcf7b574febd583bc5d2812", "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a", "refs/heads/master", @key.user)
       @merge_request.reload
@@ -236,23 +271,3 @@ describe Project do
     end
   end
 end
-# == Schema Information
-#
-# Table name: projects
-#
-#  id                     :integer(4)      not null, primary key
-#  name                   :string(255)
-#  path                   :string(255)
-#  description            :text
-#  created_at             :datetime        not null
-#  updated_at             :datetime        not null
-#  private_flag           :boolean(1)      default(TRUE), not null
-#  code                   :string(255)
-#  owner_id               :integer(4)
-#  default_branch         :string(255)     default("master"), not null
-#  issues_enabled         :boolean(1)      default(TRUE), not null
-#  wall_enabled           :boolean(1)      default(TRUE), not null
-#  merge_requests_enabled :boolean(1)      default(TRUE), not null
-#  wiki_enabled           :boolean(1)      default(TRUE), not null
-#
-
diff --git a/spec/models/protected_branch_spec.rb b/spec/models/protected_branch_spec.rb
index 1654e3b6f56b9f859d13f865363abb072d4a9eff..9180bc3bca63d2f0e281c7f6bd21e4353aadf9dd 100644
--- a/spec/models/protected_branch_spec.rb
+++ b/spec/models/protected_branch_spec.rb
@@ -1,19 +1,6 @@
-# == Schema Information
-#
-# Table name: protected_branches
-#
-#  id         :integer(4)      not null, primary key
-#  project_id :integer(4)      not null
-#  name       :string(255)     not null
-#  created_at :datetime        not null
-#  updated_at :datetime        not null
-#
-
 require 'spec_helper'
 
 describe ProtectedBranch do
-  let(:project) { Factory(:project) }
-
   describe 'Associations' do
     it { should belong_to(:project) }
   end
@@ -24,26 +11,26 @@ describe ProtectedBranch do
   end
 
   describe 'Callbacks' do
-    subject { ProtectedBranch.new(project: project, name: 'branch_name') }
+    let(:branch) { build(:protected_branch) }
 
     it 'call update_repository after save' do
-      subject.should_receive(:update_repository)
-      subject.save
+      branch.should_receive(:update_repository)
+      branch.save
     end
 
     it 'call update_repository after destroy' do
-      subject.should_receive(:update_repository)
-      subject.destroy
+      branch.save
+      branch.should_receive(:update_repository)
+      branch.destroy
     end
   end
 
   describe '#commit' do
-    subject { ProtectedBranch.new(project: project, name: 'cant_touch_this') }
+    let(:branch) { create(:protected_branch) }
 
     it 'commits itself to its project' do
-      project.should_receive(:commit).with('cant_touch_this')
-
-      subject.commit
+      branch.project.should_receive(:commit).with(branch.name)
+      branch.commit
     end
   end
 end
diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb
index 9b4aaa13f74d73204414943410b775aecbb980da..ffb861c4910c1c59d5b79964e0fa2a8a8b89325f 100644
--- a/spec/models/snippet_spec.rb
+++ b/spec/models/snippet_spec.rb
@@ -3,29 +3,21 @@ require 'spec_helper'
 describe Snippet do
   describe "Associations" do
     it { should belong_to(:project) }
-    it { should belong_to(:author) }
+    it { should belong_to(:author).class_name('User') }
+    it { should have_many(:notes).dependent(:destroy) }
   end
 
   describe "Validation" do
-    it { should validate_presence_of(:title) }
     it { should validate_presence_of(:author_id) }
     it { should validate_presence_of(:project_id) }
+
+    it { should validate_presence_of(:title) }
+    it { should ensure_length_of(:title).is_within(0..255) }
+
     it { should validate_presence_of(:file_name) }
+    it { should ensure_length_of(:title).is_within(0..255) }
+
     it { should validate_presence_of(:content) }
+    it { should ensure_length_of(:content).is_within(0..10_000) }
   end
 end
-# == Schema Information
-#
-# Table name: snippets
-#
-#  id         :integer(4)      not null, primary key
-#  title      :string(255)
-#  content    :text
-#  author_id  :integer(4)      not null
-#  project_id :integer(4)      not null
-#  created_at :datetime        not null
-#  updated_at :datetime        not null
-#  file_name  :string(255)
-#  expires_at :datetime
-#
-
diff --git a/spec/models/system_hook_spec.rb b/spec/models/system_hook_spec.rb
index 56d76ed08cf59d9f69190638a012dacbe08ee6c0..fe2a5836fe73c7a3f45b5fffe4de1d49fea2306b 100644
--- a/spec/models/system_hook_spec.rb
+++ b/spec/models/system_hook_spec.rb
@@ -10,13 +10,12 @@ describe SystemHook do
     end
 
     it "project_create hook" do
-      user = Factory :user
       with_resque do
-        project = Factory :project_without_owner, owner: user
+        project = Factory :project
       end
       WebMock.should have_requested(:post, @system_hook.url).with(body: /project_create/).once
     end
-    
+
     it "project_destroy hook" do
       project = Factory :project
       with_resque do
@@ -31,7 +30,7 @@ describe SystemHook do
       end
       WebMock.should have_requested(:post, @system_hook.url).with(body: /user_create/).once
     end
-    
+
     it "user_destroy hook" do
       user = Factory :user
       with_resque do
@@ -39,7 +38,7 @@ describe SystemHook do
       end
       WebMock.should have_requested(:post, @system_hook.url).with(body: /user_destroy/).once
     end
-    
+
     it "project_create hook" do
       user = Factory :user
       project = Factory :project
@@ -48,7 +47,7 @@ describe SystemHook do
       end
       WebMock.should have_requested(:post, @system_hook.url).with(body: /user_add_to_team/).once
     end
-    
+
     it "project_destroy hook" do
       user = Factory :user
       project = Factory :project
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 265dcef1e775f1ebd8bed7ea51d5598825e306b2..081767543e2f1ed355a50cd98a82b5cb401d13bf 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -2,12 +2,26 @@ require 'spec_helper'
 
 describe User do
   describe "Associations" do
+    it { should have_many(:users_projects).dependent(:destroy) }
     it { should have_many(:projects) }
-    it { should have_many(:users_projects) }
-    it { should have_many(:issues) }
-    it { should have_many(:assigned_issues) }
-    it { should have_many(:merge_requests) }
-    it { should have_many(:assigned_merge_requests) }
+    it { should have_many(:my_own_projects).class_name('Project') }
+    it { should have_many(:keys).dependent(:destroy) }
+    it { should have_many(:events).class_name('Event').dependent(:destroy) }
+    it { should have_many(:recent_events).class_name('Event') }
+    it { should have_many(:issues).dependent(:destroy) }
+    it { should have_many(:notes).dependent(:destroy) }
+    it { should have_many(:assigned_issues).dependent(:destroy) }
+    it { should have_many(:merge_requests).dependent(:destroy) }
+    it { should have_many(:assigned_merge_requests).dependent(:destroy) }
+  end
+
+  describe 'validations' do
+    it { should validate_presence_of(:projects_limit) }
+    it { should validate_numericality_of(:projects_limit) }
+    it { should allow_value(0).for(:projects_limit) }
+    it { should_not allow_value(-1).for(:projects_limit) }
+
+    it { should ensure_length_of(:bio).is_within(0..255) }
   end
 
   describe "Respond to" do
@@ -17,81 +31,46 @@ describe User do
     it { should respond_to(:private_token) }
   end
 
-  it "should return valid identifier" do
-    user = User.new(email: "test@mail.com")
-    user.identifier.should == "test_mail_com"
-  end
-
-  it "should return identifier without + sign" do
-    user = User.new(email: "test+foo@mail.com")
-    user.identifier.should == "test_foo_mail_com"
-  end
+  describe '#identifier' do
+    it "should return valid identifier" do
+      user = build(:user, email: "test@mail.com")
+      user.identifier.should == "test_mail_com"
+    end
 
-  it "should execute callback when force_random_password specified" do
-    user = User.new(email: "test@mail.com", force_random_password: true)
-    user.should_receive(:generate_password)
-    user.save
-  end
+    it "should return identifier without + sign" do
+      user = build(:user, email: "test+foo@mail.com")
+      user.identifier.should == "test_foo_mail_com"
+    end
 
-  it "should not generate password by default" do
-    user = Factory(:user, password: 'abcdefg', password_confirmation: 'abcdefg')
-    user.password.should == 'abcdefg'
+    it "should conform to Gitolite's required identifier pattern" do
+      user = build(:user, email: "_test@example.com")
+      user.identifier.should == 'test_example_com'
+    end
   end
 
-  it "should generate password when forcing random password" do
-    Devise.stub(:friendly_token).and_return('123456789')
-    user = User.create(email: "test1@mail.com", force_random_password: true)
-    user.password.should == user.password_confirmation
-    user.password.should == '12345678'
-  end
+  describe '#generate_password' do
+    it "should execute callback when force_random_password specified" do
+      user = build(:user, force_random_password: true)
+      user.should_receive(:generate_password)
+      user.save
+    end
 
-  it "should have authentication token" do
-    user = Factory(:user)
-    user.authentication_token.should_not == ""
-  end
+    it "should not generate password by default" do
+      user = create(:user, password: 'abcdefg')
+      user.password.should == 'abcdefg'
+    end
 
-  describe "dependent" do
-    before do
-      @user = Factory :user
-      @note = Factory :note,
-        author: @user,
-        project: Factory(:project)
+    it "should generate password when forcing random password" do
+      Devise.stub(:friendly_token).and_return('123456789')
+      user = create(:user, password: 'abcdefg', force_random_password: true)
+      user.password.should == '12345678'
     end
+  end
 
-    it "should destroy all notes with user" do
-      Note.find_by_id(@note.id).should_not be_nil
-      @user.destroy
-      Note.find_by_id(@note.id).should be_nil
+  describe 'authentication token' do
+    it "should have authentication token" do
+      user = Factory(:user)
+      user.authentication_token.should_not be_blank
     end
   end
 end
-# == Schema Information
-#
-# Table name: users
-#
-#  id                     :integer(4)      not null, primary key
-#  email                  :string(255)     default(""), not null
-#  encrypted_password     :string(128)     default(""), not null
-#  reset_password_token   :string(255)
-#  reset_password_sent_at :datetime
-#  remember_created_at    :datetime
-#  sign_in_count          :integer(4)      default(0)
-#  current_sign_in_at     :datetime
-#  last_sign_in_at        :datetime
-#  current_sign_in_ip     :string(255)
-#  last_sign_in_ip        :string(255)
-#  created_at             :datetime        not null
-#  updated_at             :datetime        not null
-#  name                   :string(255)
-#  admin                  :boolean(1)      default(FALSE), not null
-#  projects_limit         :integer(4)      default(10)
-#  skype                  :string(255)     default(""), not null
-#  linkedin               :string(255)     default(""), not null
-#  twitter                :string(255)     default(""), not null
-#  authentication_token   :string(255)
-#  dark_scheme            :boolean(1)      default(FALSE), not null
-#  theme_id               :integer(4)      default(1), not null
-#  bio                    :string(255)
-#  blocked                :boolean(1)      default(FALSE), not null
-#
-
diff --git a/spec/models/users_project_spec.rb b/spec/models/users_project_spec.rb
index 87fbfbf2a8c2c420313456c41e56295d1e3c35cf..33cb358e7bd5111b428eea5d00236bb6abab57cc 100644
--- a/spec/models/users_project_spec.rb
+++ b/spec/models/users_project_spec.rb
@@ -7,7 +7,11 @@ describe UsersProject do
   end
 
   describe "Validation" do
+    let!(:users_project) { create(:users_project) }
+
     it { should validate_presence_of(:user_id) }
+    it { should validate_uniqueness_of(:user_id).scoped_to(:project_id).with_message(/already exists/) }
+
     it { should validate_presence_of(:project_id) }
   end
 
@@ -16,15 +20,3 @@ describe UsersProject do
     it { should respond_to(:user_email) }
   end
 end
-# == Schema Information
-#
-# Table name: users_projects
-#
-#  id             :integer(4)      not null, primary key
-#  user_id        :integer(4)      not null
-#  project_id     :integer(4)      not null
-#  created_at     :datetime        not null
-#  updated_at     :datetime        not null
-#  project_access :integer(4)      default(0), not null
-#
-
diff --git a/spec/models/web_hook_spec.rb b/spec/models/web_hook_spec.rb
index 885947614d798fa7d30839ae2cc994ecdd7d0081..3cba5b64ff0ff4b235885b14fb5b76783d174b2c 100644
--- a/spec/models/web_hook_spec.rb
+++ b/spec/models/web_hook_spec.rb
@@ -52,14 +52,3 @@ describe ProjectHook do
     end
   end
 end
-# == Schema Information
-#
-# Table name: web_hooks
-#
-#  id         :integer(4)      not null, primary key
-#  url        :string(255)
-#  project_id :integer(4)
-#  created_at :datetime        not null
-#  updated_at :datetime        not null
-#
-
diff --git a/spec/models/wiki_spec.rb b/spec/models/wiki_spec.rb
index 892d0e8fe17ccbb273f212b8dd67e0cf41b5cdcf..de6ce42633192c0bd0302084175cdee0cd95ff62 100644
--- a/spec/models/wiki_spec.rb
+++ b/spec/models/wiki_spec.rb
@@ -4,27 +4,13 @@ describe Wiki do
   describe "Associations" do
     it { should belong_to(:project) }
     it { should belong_to(:user) }
+    it { should have_many(:notes).dependent(:destroy) }
   end
 
   describe "Validation" do
     it { should validate_presence_of(:title) }
+    it { should ensure_length_of(:title).is_within(1..250) }
     it { should validate_presence_of(:content) }
     it { should validate_presence_of(:user_id) }
   end
-
-  it { Factory(:wiki).should be_valid }
 end
-# == Schema Information
-#
-# Table name: wikis
-#
-#  id         :integer(4)      not null, primary key
-#  title      :string(255)
-#  content    :text
-#  project_id :integer(4)
-#  created_at :datetime        not null
-#  updated_at :datetime        not null
-#  slug       :string(255)
-#  user_id    :integer(4)
-#
-
diff --git a/spec/monkeypatch.rb b/spec/monkeypatch.rb
deleted file mode 100644
index 855a31f06de8d6fb0946d95cc270b996bfaf4c9d..0000000000000000000000000000000000000000
--- a/spec/monkeypatch.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-# Stubbing Project <-> git host path
-# create project using Factory only
-class Project
-  def update_repository
-    true
-  end
-
-  def destroy_repository
-    true
-  end
-
-  def path_to_repo
-    File.join(Rails.root, "tmp", "tests", path)
-  end
-
-  def satellite
-    @satellite ||= FakeSatellite.new
-  end
-end
-
-class Key
-  def update_repository
-    true
-  end
-
-  def repository_delete_key
-    true
-  end
-end
-
-class UsersProject
-  def update_repository
-    true
-  end
-end
-
-class FakeSatellite
-  def exists?
-    true
-  end
-
-  def create
-    true
-  end
-end
-
-class ProtectedBranch
-  def update_repository
-    true
-  end
-end
diff --git a/spec/models/activity_observer_spec.rb b/spec/observers/activity_observer_spec.rb
similarity index 100%
rename from spec/models/activity_observer_spec.rb
rename to spec/observers/activity_observer_spec.rb
diff --git a/spec/models/issue_observer_spec.rb b/spec/observers/issue_observer_spec.rb
similarity index 58%
rename from spec/models/issue_observer_spec.rb
rename to spec/observers/issue_observer_spec.rb
index c6a405f1c1be4a41dbb037cd92c9909bf032c812..b5943f2c5399c6733a6b5c7ac98f52ff03faafe5 100644
--- a/spec/models/issue_observer_spec.rb
+++ b/spec/observers/issue_observer_spec.rb
@@ -3,7 +3,8 @@ require 'spec_helper'
 describe IssueObserver do
   let(:some_user) { double(:user, id: 1) }
   let(:assignee) { double(:user, id: 2) }
-  let(:issue)    { double(:issue, id: 42, assignee: assignee) }
+  let(:author) { double(:user, id: 3) }
+  let(:issue)    { double(:issue, id: 42, assignee: assignee, author: author) }
 
   before(:each) { subject.stub(:current_user).and_return(some_user) }
 
@@ -67,36 +68,90 @@ describe IssueObserver do
       end
     end
 
-    context 'a status "closed" note' do
-      it 'is created if the issue is being closed' do
+    context 'a status "closed"' do
+      it 'note is created if the issue is being closed' do
         issue.should_receive(:is_being_closed?).and_return(true)
         Note.should_receive(:create_status_change_note).with(issue, some_user, 'closed')
 
         subject.after_update(issue)
       end
 
-      it 'is not created if the issue is not being closed' do
+      it 'note is not created if the issue is not being closed' do
         issue.should_receive(:is_being_closed?).and_return(false)
         Note.should_not_receive(:create_status_change_note).with(issue, some_user, 'closed')
 
         subject.after_update(issue)
       end
+
+      it 'notification is delivered if the issue being closed' do
+        issue.stub(:is_being_closed?).and_return(true)
+        Notify.should_receive(:issue_status_changed_email).twice
+        Note.should_receive(:create_status_change_note).with(issue, some_user, 'closed')
+
+        subject.after_update(issue)
+      end
+
+      it 'notification is not delivered if the issue not being closed' do
+        issue.stub(:is_being_closed?).and_return(false)
+        Notify.should_not_receive(:issue_status_changed_email)
+        Note.should_not_receive(:create_status_change_note).with(issue, some_user, 'closed')
+
+        subject.after_update(issue)
+      end
+
+      it 'notification is delivered only to author if the issue being closed' do
+        issue_without_assignee = double(:issue, id: 42, author: author, assignee: nil)
+        issue_without_assignee.stub(:is_being_reassigned?).and_return(false)
+        issue_without_assignee.stub(:is_being_closed?).and_return(true)
+        issue_without_assignee.stub(:is_being_reopened?).and_return(false)
+        Notify.should_receive(:issue_status_changed_email).once
+        Note.should_receive(:create_status_change_note).with(issue_without_assignee, some_user, 'closed')
+
+        subject.after_update(issue_without_assignee)
+      end
     end
 
-    context 'a status "reopened" note' do
-      it 'is created if the issue is being reopened' do
+    context 'a status "reopened"' do
+      it 'note is created if the issue is being reopened' do
         issue.should_receive(:is_being_reopened?).and_return(true)
         Note.should_receive(:create_status_change_note).with(issue, some_user, 'reopened')
 
         subject.after_update(issue)
       end
 
-      it 'is not created if the issue is not being reopened' do
+      it 'note is not created if the issue is not being reopened' do
         issue.should_receive(:is_being_reopened?).and_return(false)
         Note.should_not_receive(:create_status_change_note).with(issue, some_user, 'reopened')
 
         subject.after_update(issue)
       end
+
+      it 'notification is delivered if the issue being reopened' do
+        issue.stub(:is_being_reopened?).and_return(true)
+        Notify.should_receive(:issue_status_changed_email).twice
+        Note.should_receive(:create_status_change_note).with(issue, some_user, 'reopened')
+
+        subject.after_update(issue)
+      end
+
+      it 'notification is not delivered if the issue not being reopened' do
+        issue.stub(:is_being_reopened?).and_return(false)
+        Notify.should_not_receive(:issue_status_changed_email)
+        Note.should_not_receive(:create_status_change_note).with(issue, some_user, 'reopened')
+
+        subject.after_update(issue)
+      end
+
+      it 'notification is delivered only to author if the issue being reopened' do
+        issue_without_assignee = double(:issue, id: 42, author: author, assignee: nil)
+        issue_without_assignee.stub(:is_being_reassigned?).and_return(false)
+        issue_without_assignee.stub(:is_being_closed?).and_return(false)
+        issue_without_assignee.stub(:is_being_reopened?).and_return(true)
+        Notify.should_receive(:issue_status_changed_email).once
+        Note.should_receive(:create_status_change_note).with(issue_without_assignee, some_user, 'reopened')
+
+        subject.after_update(issue_without_assignee)
+      end
     end
   end
 
diff --git a/spec/observers/key_observer_spec.rb b/spec/observers/key_observer_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7f2a76a320c02e6f0f89b96239401679faabbe3f
--- /dev/null
+++ b/spec/observers/key_observer_spec.rb
@@ -0,0 +1,34 @@
+require 'spec_helper'
+
+describe KeyObserver do
+  before do 
+    @key = double('Key',
+      identifier: 'admin_654654',
+      key: '== a vaild ssh key',
+      projects: [],
+      is_deploy_key: false
+    )
+
+    @gitolite = double('Gitlab::Gitolite',
+      set_key: true,
+      remove_key: true
+    )
+
+    @observer = KeyObserver.instance
+    @observer.stub(:git_host => @gitolite)
+  end
+
+  context :after_save do
+    it do
+      @gitolite.should_receive(:set_key).with(@key.identifier, @key.key, @key.projects)
+      @observer.after_save(@key)
+    end
+  end
+
+  context :after_destroy do 
+    it do
+      @gitolite.should_receive(:remove_key).with(@key.identifier, @key.projects)
+      @observer.after_destroy(@key)
+    end
+  end
+end
diff --git a/spec/models/user_observer_spec.rb b/spec/observers/user_observer_spec.rb
similarity index 74%
rename from spec/models/user_observer_spec.rb
rename to spec/observers/user_observer_spec.rb
index 23dac98bb7438327c4e00d3e02a61b955cedff95..0420a250c8aa981a4e1a0bbef836c5211080c172 100644
--- a/spec/models/user_observer_spec.rb
+++ b/spec/observers/user_observer_spec.rb
@@ -13,7 +13,7 @@ describe UserObserver do
   end
 
   context 'when a new user is created' do
-    let(:user) { double(:user, id: 42, password: 'P@ssword!') }
+    let(:user) { double(:user, id: 42, password: 'P@ssword!', name: 'John', email: 'u@mail.local') }
     let(:notification) { double :notification }
 
     it 'sends an email' do
@@ -22,5 +22,10 @@ describe UserObserver do
 
       subject.after_create(user)
     end
+
+    it 'trigger logger' do
+      Gitlab::AppLogger.should_receive(:info)
+      subject.after_create(user)
+    end
   end
 end
diff --git a/spec/observers/users_project_observer_spec.rb b/spec/observers/users_project_observer_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..07d71da8c714374419803f3a076b91dba9369caa
--- /dev/null
+++ b/spec/observers/users_project_observer_spec.rb
@@ -0,0 +1,68 @@
+require 'spec_helper'
+
+describe UsersProjectObserver do
+  let(:users_project) { stub.as_null_object }
+  subject { UsersProjectObserver.instance }
+
+  describe "#after_create" do
+    it "should called when UsersProject created" do
+      subject.should_receive(:after_create)
+
+      UsersProject.observers.enable :users_project_observer do
+        create(:users_project)
+      end
+    end
+
+    it "should send email to user" do
+      Event.stub(:create => true)
+      Notify.should_receive(:project_access_granted_email).and_return(stub(deliver: true))
+
+      subject.after_create(users_project)
+    end
+
+    it "should create new event" do
+      Event.should_receive(:create).with(
+        project_id: users_project.project.id,
+        action: Event::Joined,
+        author_id: users_project.user.id
+      )
+
+      subject.after_create(users_project)
+    end
+  end
+
+  describe "#after_update" do
+    it "should called when UsersProject updated" do
+      subject.should_receive(:after_update)
+
+      UsersProject.observers.enable :users_project_observer do
+        create(:users_project).update_attribute(:project_access, 40)
+      end
+    end
+
+    it "should send email to user" do
+      Notify.should_receive(:project_access_granted_email).with(users_project.id).and_return(double(deliver: true))
+
+      subject.after_update(users_project)
+    end
+  end
+
+  describe "#after_destroy" do
+    it "should called when UsersProject destroyed" do
+      subject.should_receive(:after_destroy)
+
+      UsersProject.observers.enable :users_project_observer do
+        create(:users_project).destroy
+      end
+    end
+
+    it "should create new event" do
+      Event.should_receive(:create).with(
+        project_id: users_project.project.id,
+        action: Event::Left,
+        author_id: users_project.user.id
+      )
+      subject.after_destroy(users_project)
+    end
+  end
+end
diff --git a/spec/requests/admin/admin_projects_spec.rb b/spec/requests/admin/admin_projects_spec.rb
index 0ce66f5f868d6b1604694fc281cf233639c1d0f6..2edfb59231da43a5469b132395e4b85aa3f66d80 100644
--- a/spec/requests/admin/admin_projects_spec.rb
+++ b/spec/requests/admin/admin_projects_spec.rb
@@ -87,7 +87,7 @@ describe "Admin::Projects" do
       visit new_admin_project_path
       fill_in 'project_name', with: 'NewProject'
       fill_in 'project_code', with: 'NPR'
-      fill_in 'project_path', with: 'gitlabhq_1'
+      fill_in 'project_path', with: 'newproject'
       expect { click_button "Create project" }.to change { Project.count }.by(1)
       @project = Project.last
     end
diff --git a/spec/requests/admin/security_spec.rb b/spec/requests/admin/security_spec.rb
index 0c369740cffcd296f12054373f1b94ede8e56ae5..6306832628b8ba6aac2bbcd6b197d501341bccc9 100644
--- a/spec/requests/admin/security_spec.rb
+++ b/spec/requests/admin/security_spec.rb
@@ -2,20 +2,26 @@ require 'spec_helper'
 
 describe "Admin::Projects" do
   describe "GET /admin/projects" do
-    it { admin_projects_path.should be_allowed_for :admin }
-    it { admin_projects_path.should be_denied_for :user }
-    it { admin_projects_path.should be_denied_for :visitor }
+    subject { admin_projects_path }
+
+    it { should be_allowed_for :admin }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
   end
 
   describe "GET /admin/users" do
-    it { admin_users_path.should be_allowed_for :admin }
-    it { admin_users_path.should be_denied_for :user }
-    it { admin_users_path.should be_denied_for :visitor }
+    subject { admin_users_path }
+
+    it { should be_allowed_for :admin }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
   end
 
   describe "GET /admin/hooks" do
-    it { admin_hooks_path.should be_allowed_for :admin }
-    it { admin_hooks_path.should be_denied_for :user }
-    it { admin_hooks_path.should be_denied_for :visitor }
+    subject { admin_hooks_path }
+
+    it { should be_allowed_for :admin }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
   end
 end
diff --git a/spec/api/issues_spec.rb b/spec/requests/api/issues_spec.rb
similarity index 68%
rename from spec/api/issues_spec.rb
rename to spec/requests/api/issues_spec.rb
index f6d8e3792c2bf7fd24ce2309af80670c5caf47c8..442e9c730dc8d9d4c4fbdb4fda158dc23b6210e6 100644
--- a/spec/api/issues_spec.rb
+++ b/spec/requests/api/issues_spec.rb
@@ -1,20 +1,24 @@
 require 'spec_helper'
 
 describe Gitlab::API do
+  include ApiHelpers
+
   let(:user) { Factory :user }
   let!(:project) { Factory :project, owner: user }
   let!(:issue) { Factory :issue, author: user, assignee: user, project: project }
   before { project.add_access(user, :read) }
 
   describe "GET /issues" do
-    it "should return authentication error" do
-      get "#{api_prefix}/issues"
-      response.status.should == 401
+    context "when unauthenticated" do
+      it "should return authentication error" do
+        get api("/issues")
+        response.status.should == 401
+      end
     end
 
-    describe "authenticated GET /issues" do
+    context "when authenticated" do
       it "should return an array of issues" do
-        get "#{api_prefix}/issues?private_token=#{user.private_token}"
+        get api("/issues", user)
         response.status.should == 200
         json_response.should be_an Array
         json_response.first['title'].should == issue.title
@@ -24,7 +28,7 @@ describe Gitlab::API do
 
   describe "GET /projects/:id/issues" do
     it "should return project issues" do
-      get "#{api_prefix}/projects/#{project.code}/issues?private_token=#{user.private_token}"
+      get api("/projects/#{project.code}/issues", user)
       response.status.should == 200
       json_response.should be_an Array
       json_response.first['title'].should == issue.title
@@ -33,7 +37,7 @@ describe Gitlab::API do
 
   describe "GET /projects/:id/issues/:issue_id" do
     it "should return a project issue by id" do
-      get "#{api_prefix}/projects/#{project.code}/issues/#{issue.id}?private_token=#{user.private_token}"
+      get api("/projects/#{project.code}/issues/#{issue.id}", user)
       response.status.should == 200
       json_response['title'].should == issue.title
     end
@@ -41,7 +45,7 @@ describe Gitlab::API do
 
   describe "POST /projects/:id/issues" do
     it "should create a new project issue" do
-      post "#{api_prefix}/projects/#{project.code}/issues?private_token=#{user.private_token}",
+      post api("/projects/#{project.code}/issues", user),
         title: 'new issue', labels: 'label, label2'
       response.status.should == 201
       json_response['title'].should == 'new issue'
@@ -52,7 +56,7 @@ describe Gitlab::API do
 
   describe "PUT /projects/:id/issues/:issue_id" do
     it "should update a project issue" do
-      put "#{api_prefix}/projects/#{project.code}/issues/#{issue.id}?private_token=#{user.private_token}",
+      put api("/projects/#{project.code}/issues/#{issue.id}", user),
         title: 'updated title', labels: 'label2', closed: 1
       response.status.should == 200
       json_response['title'].should == 'updated title'
@@ -63,9 +67,8 @@ describe Gitlab::API do
 
   describe "DELETE /projects/:id/issues/:issue_id" do
     it "should delete a project issue" do
-      expect {
-        delete "#{api_prefix}/projects/#{project.code}/issues/#{issue.id}?private_token=#{user.private_token}"
-      }.to change { Issue.count }.by(-1)
+      delete api("/projects/#{project.code}/issues/#{issue.id}", user)
+      response.status.should == 405
     end
   end
 end
diff --git a/spec/requests/api/milestones_spec.rb b/spec/requests/api/milestones_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..cf5f65f068ceb3b9762dc0720ccd54b9d706358c
--- /dev/null
+++ b/spec/requests/api/milestones_spec.rb
@@ -0,0 +1,47 @@
+require 'spec_helper'
+
+describe Gitlab::API do
+  include ApiHelpers
+
+  let(:user) { Factory :user }
+  let!(:project) { Factory :project, owner: user }
+  let!(:milestone) { Factory :milestone, project: project }
+
+  before { project.add_access(user, :read) }
+
+  describe "GET /projects/:id/milestones" do
+    it "should return project milestones" do
+      get api("/projects/#{project.code}/milestones", user)
+      response.status.should == 200
+      json_response.should be_an Array
+      json_response.first['title'].should == milestone.title
+    end
+  end
+
+  describe "GET /projects/:id/milestones/:milestone_id" do
+    it "should return a project milestone by id" do
+      get api("/projects/#{project.code}/milestones/#{milestone.id}", user)
+      response.status.should == 200
+      json_response['title'].should == milestone.title
+    end
+  end
+
+  describe "POST /projects/:id/milestones" do
+    it "should create a new project milestone" do
+      post api("/projects/#{project.code}/milestones", user),
+        title: 'new milestone'
+      response.status.should == 201
+      json_response['title'].should == 'new milestone'
+      json_response['description'].should be_nil
+    end
+  end
+
+  describe "PUT /projects/:id/milestones/:milestone_id" do
+    it "should update a project milestone" do
+      put api("/projects/#{project.code}/milestones/#{milestone.id}", user),
+        title: 'updated title'
+      response.status.should == 200
+      json_response['title'].should == 'updated title'
+    end
+  end
+end
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..498bbad6179fb9f59dbe1463744e28c553776c1f
--- /dev/null
+++ b/spec/requests/api/projects_spec.rb
@@ -0,0 +1,281 @@
+require 'spec_helper'
+
+describe Gitlab::API do
+  include ApiHelpers
+
+  let(:user) { Factory :user }
+  let(:user2) { Factory.create(:user) }
+  let(:user3) { Factory.create(:user) }
+  let!(:hook) { Factory :project_hook, project: project, url: "http://example.com" }
+  let!(:project) { Factory :project, owner: user }
+  let!(:snippet) { Factory :snippet, author: user, project: project, title: 'example' }
+  let!(:users_project) { Factory :users_project, user: user, project: project, project_access: UsersProject::MASTER  }
+  let!(:users_project2) { Factory :users_project, user: user3, project: project, project_access: UsersProject::DEVELOPER  }
+  before { project.add_access(user, :read) }
+
+  describe "GET /projects" do
+    context "when unauthenticated" do
+      it "should return authentication error" do
+        get api("/projects")
+        response.status.should == 401
+      end
+    end
+
+    context "when authenticated" do
+      it "should return an array of projects" do
+        get api("/projects", user)
+        response.status.should == 200
+        json_response.should be_an Array
+        json_response.first['name'].should == project.name
+        json_response.first['owner']['email'].should == user.email
+      end
+    end
+  end
+
+  describe "POST /projects" do
+    it "should create new project without code and path" do
+      expect { post api("/projects", user), name: 'foo' }.to change {Project.count}.by(1)
+    end
+
+    it "should not create new project without name" do
+      expect { post api("/projects", user) }.to_not change {Project.count}
+    end
+
+    it "should respond with 201 on success" do
+      post api("/projects", user), name: 'foo'
+      response.status.should == 201
+    end
+
+    it "should repsond with 404 on failure" do
+      post api("/projects", user)
+      response.status.should == 404
+    end
+
+    it "should assign attributes to project" do
+      project = Factory.attributes(:project, {
+        path: 'path',
+        code: 'code',
+        description: Faker::Lorem.sentence,
+        default_branch: 'stable',
+        issues_enabled: false,
+        wall_enabled: false,
+        merge_requests_enabled: false,
+        wiki_enabled: false
+      })
+
+      post api("/projects", user), project
+
+      project.each_pair do |k,v|
+        json_response[k.to_s].should == v
+      end
+    end
+  end
+
+  describe "GET /projects/:id" do
+    it "should return a project by id" do
+      get api("/projects/#{project.id}", user)
+      response.status.should == 200
+      json_response['name'].should == project.name
+      json_response['owner']['email'].should == user.email
+    end
+
+    it "should return a project by code name" do
+      get api("/projects/#{project.code}", user)
+      response.status.should == 200
+      json_response['name'].should == project.name
+    end
+
+    it "should return a 404 error if not found" do
+      get api("/projects/42", user)
+      response.status.should == 404
+      json_response['message'].should == '404 Not Found'
+    end
+  end
+
+  describe "GET /projects/:id/repository/branches" do
+    it "should return an array of project branches" do
+      get api("/projects/#{project.code}/repository/branches", user)
+      response.status.should == 200
+      json_response.should be_an Array
+      json_response.first['name'].should == project.repo.heads.sort_by(&:name).first.name
+    end
+  end
+
+  describe "GET /projects/:id/repository/branches/:branch" do
+    it "should return the branch information for a single branch" do
+      get api("/projects/#{project.code}/repository/branches/new_design", user)
+      response.status.should == 200
+
+      json_response['name'].should == 'new_design'
+      json_response['commit']['id'].should == '621491c677087aa243f165eab467bfdfbee00be1'
+    end
+  end
+
+  describe "GET /projects/:id/members" do
+    it "should return project team members" do
+      get api("/projects/#{project.code}/members", user)
+      response.status.should == 200
+      json_response.should be_an Array
+      json_response.count.should == 2
+      json_response.first['email'].should == user.email
+    end
+  end
+
+  describe "GET /projects/:id/members/:user_id" do
+    it "should return project team member" do
+      get api("/projects/#{project.code}/members/#{user.id}", user)
+      response.status.should == 200
+      json_response['email'].should == user.email
+      json_response['access_level'].should == UsersProject::MASTER
+    end
+  end
+
+  describe "POST /projects/:id/members" do
+    it "should add user to project team" do
+      expect {
+        post api("/projects/#{project.code}/members", user), user_id: user2.id,
+          access_level: UsersProject::DEVELOPER
+      }.to change { UsersProject.count }.by(1)
+
+      response.status.should == 201
+      json_response['email'].should == user2.email
+      json_response['access_level'].should == UsersProject::DEVELOPER
+    end
+  end
+
+  describe "PUT /projects/:id/members/:user_id" do
+    it "should update project team member" do
+      put api("/projects/#{project.code}/members/#{user3.id}", user), access_level: UsersProject::MASTER
+      response.status.should == 200
+      json_response['email'].should == user3.email
+      json_response['access_level'].should == UsersProject::MASTER
+    end
+  end
+
+  describe "DELETE /projects/:id/members/:user_id" do
+    it "should remove user from project team" do
+      expect {
+        delete api("/projects/#{project.code}/members/#{user3.id}", user)
+      }.to change { UsersProject.count }.by(-1)
+    end
+  end
+
+  describe "GET /projects/:id/hooks" do
+    it "should return project hooks" do
+      get api("/projects/#{project.code}/hooks", user)
+
+      response.status.should == 200
+
+      json_response.should be_an Array
+      json_response.count.should == 1
+      json_response.first['url'].should == "http://example.com"
+    end
+  end
+
+  describe "POST /projects/:id/users" do
+    it "should add hook to project" do
+      expect {
+        post api("/projects/#{project.code}/hooks", user),
+          "url" => "http://example.com"
+      }.to change {project.hooks.count}.by(1)
+    end
+  end
+
+  describe "DELETE /projects/:id/hooks" do
+    it "should delete hook from project" do
+      expect {
+        delete api("/projects/#{project.code}/hooks", user),
+          hook_id: hook.id
+      }.to change {project.hooks.count}.by(-1)
+    end
+  end
+
+  describe "GET /projects/:id/repository/tags" do
+    it "should return an array of project tags" do
+      get api("/projects/#{project.code}/repository/tags", user)
+      response.status.should == 200
+      json_response.should be_an Array
+      json_response.first['name'].should == project.repo.tags.sort_by(&:name).reverse.first.name
+    end
+  end
+
+  describe "GET /projects/:id/repository/commits" do
+    context "authorized user" do
+      before { project.add_access(user2, :read) }
+
+      it "should return project commits" do
+        get api("/projects/#{project.code}/repository/commits", user)
+        response.status.should == 200
+
+        json_response.should be_an Array
+        json_response.first['id'].should == project.commit.id
+      end
+    end
+
+    context "unauthorized user" do
+      it "should not return project commits" do
+        get api("/projects/#{project.code}/repository/commits")
+        response.status.should == 401
+      end
+    end
+  end
+
+  describe "GET /projects/:id/snippets/:snippet_id" do
+    it "should return a project snippet" do
+      get api("/projects/#{project.code}/snippets/#{snippet.id}", user)
+      response.status.should == 200
+      json_response['title'].should == snippet.title
+    end
+  end
+
+  describe "POST /projects/:id/snippets" do
+    it "should create a new project snippet" do
+      post api("/projects/#{project.code}/snippets", user),
+        title: 'api test', file_name: 'sample.rb', code: 'test'
+      response.status.should == 201
+      json_response['title'].should == 'api test'
+    end
+  end
+
+  describe "PUT /projects/:id/snippets" do
+    it "should update an existing project snippet" do
+      put api("/projects/#{project.code}/snippets/#{snippet.id}", user),
+        code: 'updated code'
+      response.status.should == 200
+      json_response['title'].should == 'example'
+      snippet.reload.content.should == 'updated code'
+    end
+  end
+
+  describe "DELETE /projects/:id/snippets/:snippet_id" do
+    it "should delete existing project snippet" do
+      expect {
+        delete api("/projects/#{project.code}/snippets/#{snippet.id}", user)
+      }.to change { Snippet.count }.by(-1)
+    end
+  end
+
+  describe "GET /projects/:id/snippets/:snippet_id/raw" do
+    it "should get a raw project snippet" do
+      get api("/projects/#{project.code}/snippets/#{snippet.id}/raw", user)
+      response.status.should == 200
+    end
+  end
+
+  describe "GET /projects/:id/:sha/blob" do
+    it "should get the raw file contents" do
+      get api("/projects/#{project.code}/repository/commits/master/blob?filepath=README.md", user)
+      response.status.should == 200
+    end
+
+    it "should return 404 for invalid branch_name" do
+      get api("/projects/#{project.code}/repository/commits/invalid_branch_name/blob?filepath=README.md", user)
+      response.status.should == 404
+    end
+
+    it "should return 404 for invalid file" do
+      get api("/projects/#{project.code}/repository/commits/master/blob?filepath=README.invalid", user)
+      response.status.should == 404
+    end
+  end
+end
diff --git a/spec/requests/api/session_spec.rb b/spec/requests/api/session_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f251f3921acacde95418deb7b3bae3cd54256a45
--- /dev/null
+++ b/spec/requests/api/session_spec.rb
@@ -0,0 +1,39 @@
+require 'spec_helper'
+
+describe Gitlab::API do
+  include ApiHelpers
+
+  let(:user) { Factory :user }
+
+  describe "POST /session" do
+    context "when valid password" do
+      it "should return private token" do
+        post api("/session"), email: user.email, password: '123456'
+        response.status.should == 201
+
+        json_response['email'].should == user.email
+        json_response['private_token'].should == user.private_token
+      end
+    end
+
+    context "when invalid password" do
+      it "should return authentication error" do
+        post api("/session"), email: user.email, password: '123'
+        response.status.should == 401
+
+        json_response['email'].should be_nil
+        json_response['private_token'].should be_nil
+      end
+    end
+
+    context "when empty password" do
+      it "should return authentication error" do
+        post api("/session"), email: user.email
+        response.status.should == 401
+
+        json_response['email'].should be_nil
+        json_response['private_token'].should be_nil
+      end
+    end
+  end
+end
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..243f70f5230db474e0fe7484a1bd1cd80bc8fe61
--- /dev/null
+++ b/spec/requests/api/users_spec.rb
@@ -0,0 +1,106 @@
+require 'spec_helper'
+
+describe Gitlab::API do
+  include ApiHelpers
+
+  let(:user)  { Factory :user }
+  let(:key)   { Factory :key, user: user }
+
+  describe "GET /users" do
+    context "when unauthenticated" do
+      it "should return authentication error" do
+        get api("/users")
+        response.status.should == 401
+      end
+    end
+
+    context "when authenticated" do
+      it "should return an array of users" do
+        get api("/users", user)
+        response.status.should == 200
+        json_response.should be_an Array
+        json_response.first['email'].should == user.email
+      end
+    end
+  end
+
+  describe "GET /users/:id" do
+    it "should return a user by id" do
+      get api("/users/#{user.id}", user)
+      response.status.should == 200
+      json_response['email'].should == user.email
+    end
+  end
+
+  describe "GET /user" do
+    it "should return current user" do
+      get api("/user", user)
+      response.status.should == 200
+      json_response['email'].should == user.email
+    end
+  end
+
+  describe "GET /user/keys" do
+    context "when unauthenticated" do
+      it "should return authentication error" do
+        get api("/user/keys")
+        response.status.should == 401
+      end
+    end
+
+    context "when authenticated" do
+      it "should return array of ssh keys" do
+        user.keys << key
+        user.save
+        get api("/user/keys", user)
+        response.status.should == 200
+        json_response.should be_an Array
+        json_response.first["title"].should == key.title
+      end
+    end
+  end
+
+  describe "GET /user/keys/:id" do
+    it "should returm single key" do
+      user.keys << key
+      user.save
+      get api("/user/keys/#{key.id}", user)
+      response.status.should == 200
+      json_response["title"].should == key.title
+    end
+
+    it "should return 404 Not Found within invalid ID" do
+      get api("/user/keys/42", user)
+      response.status.should == 404
+    end
+  end
+
+  describe "POST /user/keys" do
+    it "should not create invalid ssh key" do
+      post api("/user/keys", user), { title: "invalid key" }
+      response.status.should == 404
+    end
+
+    it "should create ssh key" do
+      key_attrs = Factory.attributes :key
+      expect {
+        post api("/user/keys", user), key_attrs
+      }.to change{ user.keys.count }.by(1)
+    end
+  end
+
+  describe "DELETE /user/keys/:id" do
+    it "should delete existed key" do
+      user.keys << key
+      user.save
+      expect {
+        delete api("/user/keys/#{key.id}", user)
+      }.to change{user.keys.count}.by(-1)
+    end
+
+    it "should return 404 Not Found within invalid ID" do
+      delete api("/user/keys/42", user)
+      response.status.should == 404
+    end
+  end
+end
diff --git a/spec/requests/atom/dashboard_issues_spec.rb b/spec/requests/atom/dashboard_issues_spec.rb
index 9b4ffc0e326a484a97553218afb8a1d8864dceed..8d1111fc7701a5de91485c3c395c2a92a15014ba 100644
--- a/spec/requests/atom/dashboard_issues_spec.rb
+++ b/spec/requests/atom/dashboard_issues_spec.rb
@@ -1,46 +1,23 @@
 require 'spec_helper'
 
-describe "User Issues Dashboard" do
+describe "Dashboard Issues Feed" do
   describe "GET /issues" do
-    before do
+    let!(:user)     { Factory :user }
+    let!(:project1) { Factory :project }
+    let!(:project2) { Factory :project }
+    let!(:issue1)   { Factory :issue, author: user, assignee: user, project: project1 }
+    let!(:issue2)   { Factory :issue, author: user, assignee: user, project: project2 }
 
-      login_as :user
-
-      @project1 = Factory :project,
-        path: "project1",
-        code: "TEST1"
-
-      @project2 = Factory :project,
-        path: "project2",
-        code: "TEST2"
-
-      @project1.add_access(@user, :read, :write)
-      @project2.add_access(@user, :read, :write)
-
-      @issue1 = Factory :issue,
-        author: @user,
-        assignee: @user,
-        project: @project1
-
-      @issue2 = Factory :issue,
-        author: @user,
-        assignee: @user,
-        project: @project2
-
-      visit dashboard_issues_path
-    end
-
-    describe "atom feed", js: false do
+    describe "atom feed" do
       it "should render atom feed via private token" do
-        logout
-        visit dashboard_issues_path(:atom, private_token: @user.private_token)
+        visit dashboard_issues_path(:atom, private_token: user.private_token)
 
         page.response_headers['Content-Type'].should have_content("application/atom+xml")
-        page.body.should have_selector("title", text: "#{@user.name} issues")
-        page.body.should have_selector("author email", text: @issue1.author_email)
-        page.body.should have_selector("entry summary", text: @issue1.title)
-        page.body.should have_selector("author email", text: @issue2.author_email)
-        page.body.should have_selector("entry summary", text: @issue2.title)
+        page.body.should have_selector("title", text: "#{user.name} issues")
+        page.body.should have_selector("author email", text: issue1.author_email)
+        page.body.should have_selector("entry summary", text: issue1.title)
+        page.body.should have_selector("author email", text: issue2.author_email)
+        page.body.should have_selector("entry summary", text: issue2.title)
       end
     end
   end
diff --git a/spec/requests/atom/dashboard_spec.rb b/spec/requests/atom/dashboard_spec.rb
index 00c7a5255ca044ac08c8e5a2ca6c762618be1951..9459dd01e2221a7bab0ac792b227eff1fbea6258 100644
--- a/spec/requests/atom/dashboard_spec.rb
+++ b/spec/requests/atom/dashboard_spec.rb
@@ -1,27 +1,21 @@
 require 'spec_helper'
 
-describe "User Dashboard" do
-  before { login_as :user }
-
+describe "Dashboard Feed" do
   describe "GET /" do
-    before do
-      @project = Factory :project, owner: @user
-      @project.add_access(@user, :read)
-      visit dashboard_path
-    end
+    let!(:user) { Factory :user }
 
-    it "should render projects atom feed via private token" do
-      logout
-
-      visit dashboard_path(:atom, private_token: @user.private_token)
-      page.body.should have_selector("feed title")
+    context "projects atom feed via private token" do
+      it "should render projects atom feed" do
+        visit dashboard_path(:atom, private_token: user.private_token)
+        page.body.should have_selector("feed title")
+      end
     end
 
-    it "should not render projects page via private token" do
-      logout
-
-      visit dashboard_path(private_token: @user.private_token)
-      current_path.should == new_user_session_path
+    context "projects page via private token" do
+      it "should redirect to login page" do
+        visit dashboard_path(private_token: user.private_token)
+        current_path.should == new_user_session_path
+      end
     end
   end
 end
diff --git a/spec/requests/atom/issues_spec.rb b/spec/requests/atom/issues_spec.rb
index 468d1b2260a4e27d345b0d82d6d24fcb9e4b7171..c86719798708a57deb378a2f1657aeba33a1ca02 100644
--- a/spec/requests/atom/issues_spec.rb
+++ b/spec/requests/atom/issues_spec.rb
@@ -1,40 +1,34 @@
 require 'spec_helper'
 
-describe "Issues" do
-  let(:project) { Factory :project }
-
-  before do
-    login_as :user
-    project.add_access(@user, :read, :write)
-  end
-
+describe "Issues Feed" do
   describe "GET /issues" do
-    before do
-      @issue = Factory :issue,
-        author: @user,
-        assignee: @user,
-        project: project
-
-      visit project_issues_path(project)
-    end
-
-    it "should render atom feed" do
-      visit project_issues_path(project, :atom)
-
-      page.response_headers['Content-Type'].should have_content("application/atom+xml")
-      page.body.should have_selector("title", text: "#{project.name} issues")
-      page.body.should have_selector("author email", text: @issue.author_email)
-      page.body.should have_selector("entry summary", text: @issue.title)
+    let!(:user)     { Factory :user }
+    let!(:project)  { Factory :project, owner: user }
+    let!(:issue)    { Factory :issue, author: user, project: project }
+
+    before { project.add_access(user, :read, :write) }
+
+    context "when authenticated" do
+      it "should render atom feed" do
+        login_with user
+        visit project_issues_path(project, :atom)
+
+        page.response_headers['Content-Type'].should have_content("application/atom+xml")
+        page.body.should have_selector("title", text: "#{project.name} issues")
+        page.body.should have_selector("author email", text: issue.author_email)
+        page.body.should have_selector("entry summary", text: issue.title)
+      end
     end
 
-    it "should render atom feed via private token" do
-      logout
-      visit project_issues_path(project, :atom, private_token: @user.private_token)
+    context "when authenticated via private token" do
+      it "should render atom feed" do
+        visit project_issues_path(project, :atom, private_token: user.private_token)
 
-      page.response_headers['Content-Type'].should have_content("application/atom+xml")
-      page.body.should have_selector("title", text: "#{project.name} issues")
-      page.body.should have_selector("author email", text: @issue.author_email)
-      page.body.should have_selector("entry summary", text: @issue.title)
+        page.response_headers['Content-Type'].should have_content("application/atom+xml")
+        page.body.should have_selector("title", text: "#{project.name} issues")
+        page.body.should have_selector("author email", text: issue.author_email)
+        page.body.should have_selector("entry summary", text: issue.title)
+      end
     end
   end
 end
diff --git a/spec/requests/gitlab_flavored_markdown_spec.rb b/spec/requests/gitlab_flavored_markdown_spec.rb
index 1076e90c42baa53e015ec57644934e1a251b1a73..68d354b7bc746431307913b0ab29b8e85716fd7a 100644
--- a/spec/requests/gitlab_flavored_markdown_spec.rb
+++ b/spec/requests/gitlab_flavored_markdown_spec.rb
@@ -25,6 +25,7 @@ describe "Gitlab Flavored Markdown" do
     @tag_name = "gfm-test-tag"
     r.git.native(:tag, {}, @tag_name, commit.id)
   end
+
   after do
     # delete test branch and tag
     project.repo.git.native(:branch, {D: true}, @branch_name)
diff --git a/spec/requests/projects_deploy_keys_spec.rb b/spec/requests/projects_deploy_keys_spec.rb
index 0fea7b46ce2be88292e4d3d6cf80a326791a8bc2..894aa6d3a8d6576759e3574629099dc1c616a6bd 100644
--- a/spec/requests/projects_deploy_keys_spec.rb
+++ b/spec/requests/projects_deploy_keys_spec.rb
@@ -42,7 +42,7 @@ describe "Projects", "DeployKeys" do
     describe "fill in" do
       before do
         fill_in "key_title", with: "laptop"
-        fill_in "key_key", with: "publickey234="
+        fill_in "key_key", with: "ssh-rsa publickey234="
       end
 
       it { expect { click_button "Save" }.to change {Key.count}.by(1) }
@@ -55,12 +55,12 @@ describe "Projects", "DeployKeys" do
     end
   end
 
-  describe "Show page" do 
+  describe "Show page" do
     before do
       @key = Factory :key, project: project
-      visit project_deploy_key_path(project, @key) 
+      visit project_deploy_key_path(project, @key)
     end
-    
+
     it { page.should have_content @key.title }
     it { page.should have_content @key.key[0..10] }
   end
diff --git a/spec/requests/projects_spec.rb b/spec/requests/projects_spec.rb
index 63f8a69675438707c35012e595351815a1d3f3a7..92e89a162afe856938f3d2a358dfc025d7fdd2c5 100644
--- a/spec/requests/projects_spec.rb
+++ b/spec/requests/projects_spec.rb
@@ -3,6 +3,16 @@ require 'spec_helper'
 describe "Projects" do
   before { login_as :user }
 
+  describe 'GET /project/new' do
+    it "should work autocomplete", :js => true do
+      visit new_project_path
+      
+      fill_in 'project_name', with: 'Awesome'
+      find("#project_path").value.should == 'awesome'
+      find("#project_code").value.should == 'awesome'
+    end
+  end
+
   describe "GET /projects/show" do
     before do
       @project = Factory :project, owner: @user
diff --git a/spec/requests/security/profile_access_spec.rb b/spec/requests/security/profile_access_spec.rb
index b8ed27f031ca1a1648f30abb178d88a1f5692304..69c1c29cf12022bfb03ffbc0373079e6f89941f4 100644
--- a/spec/requests/security/profile_access_spec.rb
+++ b/spec/requests/security/profile_access_spec.rb
@@ -11,24 +11,30 @@ describe "Users Security" do
     end
 
     describe "GET /keys" do
-      it { keys_path.should be_allowed_for @u1 }
-      it { keys_path.should be_allowed_for :admin }
-      it { keys_path.should be_allowed_for :user }
-      it { keys_path.should be_denied_for :visitor }
+      subject { keys_path }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for :admin }
+      it { should be_allowed_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /profile" do
-      it { profile_path.should be_allowed_for @u1 }
-      it { profile_path.should be_allowed_for :admin }
-      it { profile_path.should be_allowed_for :user }
-      it { profile_path.should be_denied_for :visitor }
+      subject { profile_path }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for :admin }
+      it { should be_allowed_for :user }
+      it { should be_denied_for :visitor }
     end
 
-    describe "GET /profile/password" do
-      it { profile_password_path.should be_allowed_for @u1 }
-      it { profile_password_path.should be_allowed_for :admin }
-      it { profile_password_path.should be_allowed_for :user }
-      it { profile_password_path.should be_denied_for :visitor }
+    describe "GET /profile/account" do
+      subject { profile_account_path }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for :admin }
+      it { should be_allowed_for :user }
+      it { should be_denied_for :visitor }
     end
   end
 end
diff --git a/spec/requests/security/project_access_spec.rb b/spec/requests/security/project_access_spec.rb
index d503cf857b54ce0695cc1f1ca2d0e910c30510a5..af0d5fcd3fedef10dad5551b71f3b7bebca434c6 100644
--- a/spec/requests/security/project_access_spec.rb
+++ b/spec/requests/security/project_access_spec.rb
@@ -26,64 +26,76 @@ describe "Application access" do
     end
 
     describe "GET /project_code" do
-      it { project_path(@project).should be_allowed_for @u1 }
-      it { project_path(@project).should be_allowed_for @u3 }
-      it { project_path(@project).should be_denied_for :admin }
-      it { project_path(@project).should be_denied_for @u2 }
-      it { project_path(@project).should be_denied_for :user }
-      it { project_path(@project).should be_denied_for :visitor }
+      subject { project_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/master/tree" do
-      it { tree_project_ref_path(@project, @project.root_ref).should be_allowed_for @u1 }
-      it { tree_project_ref_path(@project, @project.root_ref).should be_allowed_for @u3 }
-      it { tree_project_ref_path(@project, @project.root_ref).should be_denied_for :admin }
-      it { tree_project_ref_path(@project, @project.root_ref).should be_denied_for @u2 }
-      it { tree_project_ref_path(@project, @project.root_ref).should be_denied_for :user }
-      it { tree_project_ref_path(@project, @project.root_ref).should be_denied_for :visitor }
+      subject { tree_project_ref_path(@project, @project.root_ref) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/commits" do
-      it { project_commits_path(@project).should be_allowed_for @u1 }
-      it { project_commits_path(@project).should be_allowed_for @u3 }
-      it { project_commits_path(@project).should be_denied_for :admin }
-      it { project_commits_path(@project).should be_denied_for @u2 }
-      it { project_commits_path(@project).should be_denied_for :user }
-      it { project_commits_path(@project).should be_denied_for :visitor }
+      subject { project_commits_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/commit" do
-      it { project_commit_path(@project, @project.commit.id).should be_allowed_for @u1 }
-      it { project_commit_path(@project, @project.commit.id).should be_allowed_for @u3 }
-      it { project_commit_path(@project, @project.commit.id).should be_denied_for :admin }
-      it { project_commit_path(@project, @project.commit.id).should be_denied_for @u2 }
-      it { project_commit_path(@project, @project.commit.id).should be_denied_for :user }
-      it { project_commit_path(@project, @project.commit.id).should be_denied_for :visitor }
+      subject { project_commit_path(@project, @project.commit.id) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/team" do
-      it { team_project_path(@project).should be_allowed_for @u1 }
-      it { team_project_path(@project).should be_allowed_for @u3 }
-      it { team_project_path(@project).should be_denied_for :admin }
-      it { team_project_path(@project).should be_denied_for @u2 }
-      it { team_project_path(@project).should be_denied_for :user }
-      it { team_project_path(@project).should be_denied_for :visitor }
+      subject { project_team_index_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/wall" do
-      it { wall_project_path(@project).should be_allowed_for @u1 }
-      it { wall_project_path(@project).should be_allowed_for @u3 }
-      it { wall_project_path(@project).should be_denied_for :admin }
-      it { wall_project_path(@project).should be_denied_for @u2 }
-      it { wall_project_path(@project).should be_denied_for :user }
-      it { wall_project_path(@project).should be_denied_for :visitor }
+      subject { wall_project_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/blob" do
       before do
-        @commit = @project.commit
-        @path = @commit.tree.contents.select { |i| i.is_a?(Grit::Blob)}.first.name
-        @blob_path = blob_project_ref_path(@project, @commit.id, path: @path)
+        commit = @project.commit
+        path = commit.tree.contents.select { |i| i.is_a?(Grit::Blob)}.first.name
+        @blob_path = blob_project_ref_path(@project, commit.id, path: path)
       end
 
       it { @blob_path.should be_allowed_for @u1 }
@@ -95,93 +107,113 @@ describe "Application access" do
     end
 
     describe "GET /project_code/edit" do
-      it { edit_project_path(@project).should be_allowed_for @u1 }
-      it { edit_project_path(@project).should be_denied_for @u3 }
-      it { edit_project_path(@project).should be_denied_for :admin }
-      it { edit_project_path(@project).should be_denied_for @u2 }
-      it { edit_project_path(@project).should be_denied_for :user }
-      it { edit_project_path(@project).should be_denied_for :visitor }
+      subject { edit_project_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_denied_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/deploy_keys" do
-      it { project_deploy_keys_path(@project).should be_allowed_for @u1 }
-      it { project_deploy_keys_path(@project).should be_denied_for @u3 }
-      it { project_deploy_keys_path(@project).should be_denied_for :admin }
-      it { project_deploy_keys_path(@project).should be_denied_for @u2 }
-      it { project_deploy_keys_path(@project).should be_denied_for :user }
-      it { project_deploy_keys_path(@project).should be_denied_for :visitor }
+      subject { project_deploy_keys_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_denied_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/issues" do
-      it { project_issues_path(@project).should be_allowed_for @u1 }
-      it { project_issues_path(@project).should be_allowed_for @u3 }
-      it { project_issues_path(@project).should be_denied_for :admin }
-      it { project_issues_path(@project).should be_denied_for @u2 }
-      it { project_issues_path(@project).should be_denied_for :user }
-      it { project_issues_path(@project).should be_denied_for :visitor }
+      subject { project_issues_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/snippets" do
-      it { project_snippets_path(@project).should be_allowed_for @u1 }
-      it { project_snippets_path(@project).should be_allowed_for @u3 }
-      it { project_snippets_path(@project).should be_denied_for :admin }
-      it { project_snippets_path(@project).should be_denied_for @u2 }
-      it { project_snippets_path(@project).should be_denied_for :user }
-      it { project_snippets_path(@project).should be_denied_for :visitor }
+      subject { project_snippets_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/merge_requests" do
-      it { project_merge_requests_path(@project).should be_allowed_for @u1 }
-      it { project_merge_requests_path(@project).should be_allowed_for @u3 }
-      it { project_merge_requests_path(@project).should be_denied_for :admin }
-      it { project_merge_requests_path(@project).should be_denied_for @u2 }
-      it { project_merge_requests_path(@project).should be_denied_for :user }
-      it { project_merge_requests_path(@project).should be_denied_for :visitor }
+      subject { project_merge_requests_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/repository" do
-      it { project_repository_path(@project).should be_allowed_for @u1 }
-      it { project_repository_path(@project).should be_allowed_for @u3 }
-      it { project_repository_path(@project).should be_denied_for :admin }
-      it { project_repository_path(@project).should be_denied_for @u2 }
-      it { project_repository_path(@project).should be_denied_for :user }
-      it { project_repository_path(@project).should be_denied_for :visitor }
+      subject { project_repository_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/repository/branches" do
-      it { branches_project_repository_path(@project).should be_allowed_for @u1 }
-      it { branches_project_repository_path(@project).should be_allowed_for @u3 }
-      it { branches_project_repository_path(@project).should be_denied_for :admin }
-      it { branches_project_repository_path(@project).should be_denied_for @u2 }
-      it { branches_project_repository_path(@project).should be_denied_for :user }
-      it { branches_project_repository_path(@project).should be_denied_for :visitor }
+      subject { branches_project_repository_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/repository/tags" do
-      it { tags_project_repository_path(@project).should be_allowed_for @u1 }
-      it { tags_project_repository_path(@project).should be_allowed_for @u3 }
-      it { tags_project_repository_path(@project).should be_denied_for :admin }
-      it { tags_project_repository_path(@project).should be_denied_for @u2 }
-      it { tags_project_repository_path(@project).should be_denied_for :user }
-      it { tags_project_repository_path(@project).should be_denied_for :visitor }
+      subject { tags_project_repository_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/hooks" do
-      it { project_hooks_path(@project).should be_allowed_for @u1 }
-      it { project_hooks_path(@project).should be_allowed_for @u3 }
-      it { project_hooks_path(@project).should be_denied_for :admin }
-      it { project_hooks_path(@project).should be_denied_for @u2 }
-      it { project_hooks_path(@project).should be_denied_for :user }
-      it { project_hooks_path(@project).should be_denied_for :visitor }
+      subject { project_hooks_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/files" do
-      it { files_project_path(@project).should be_allowed_for @u1 }
-      it { files_project_path(@project).should be_allowed_for @u3 }
-      it { files_project_path(@project).should be_denied_for :admin }
-      it { files_project_path(@project).should be_denied_for @u2 }
-      it { files_project_path(@project).should be_denied_for :user }
-      it { files_project_path(@project).should be_denied_for :visitor }
+      subject { files_project_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
   end
 end
diff --git a/spec/roles/issue_commonality_spec.rb b/spec/roles/issue_commonality_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..77b98b46ed91ae9f164c97b97b64520fb9777b82
--- /dev/null
+++ b/spec/roles/issue_commonality_spec.rb
@@ -0,0 +1,69 @@
+require 'spec_helper'
+
+describe Issue, "IssueCommonality" do
+  let(:issue) { create(:issue) }
+
+  describe "Associations" do
+    it { should belong_to(:project) }
+    it { should belong_to(:author) }
+    it { should belong_to(:assignee) }
+    it { should have_many(:notes).dependent(:destroy) }
+  end
+
+  describe "Validation" do
+    it { should validate_presence_of(:project_id) }
+    it { should validate_presence_of(:author_id) }
+    it { should validate_presence_of(:title) }
+    it { should ensure_length_of(:title).is_at_least(0).is_at_most(255) }
+  end
+
+  describe "Scope" do
+    it { described_class.should respond_to(:opened) }
+    it { described_class.should respond_to(:closed) }
+    it { described_class.should respond_to(:assigned) }
+  end
+
+  it "has an :author_id_of_changes accessor" do
+    issue.should respond_to(:author_id_of_changes)
+    issue.should respond_to(:author_id_of_changes=)
+  end
+
+  describe ".search" do
+    let!(:searchable_issue) { create(:issue, title: "Searchable issue") }
+
+    it "matches by title" do
+      described_class.search('able').all.should == [searchable_issue]
+    end
+  end
+
+  describe "#today?" do
+    it "returns true when created today" do
+      # Avoid timezone differences and just return exactly what we want
+      Date.stub(:today).and_return(issue.created_at.to_date)
+      issue.today?.should be_true
+    end
+
+    it "returns false when not created today" do
+      Date.stub(:today).and_return(Date.yesterday)
+      issue.today?.should be_false
+    end
+  end
+
+  describe "#new?" do
+    it "returns true when created today and record hasn't been updated" do
+      issue.stub(:today?).and_return(true)
+      issue.new?.should be_true
+    end
+
+    it "returns false when not created today" do
+      issue.stub(:today?).and_return(false)
+      issue.new?.should be_false
+    end
+
+    it "returns false when record has been updated" do
+      issue.stub(:today?).and_return(true)
+      issue.touch
+      issue.new?.should be_false
+    end
+  end
+end
diff --git a/spec/roles/repository_spec.rb b/spec/roles/repository_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..0fda57a3e271aae6d7b7d7894f0e10143bfe09c9
--- /dev/null
+++ b/spec/roles/repository_spec.rb
@@ -0,0 +1,72 @@
+require 'spec_helper'
+
+describe Project, "Repository" do
+  let(:project) { build(:project) }
+
+  describe "#empty_repo?" do
+    it "should return true if the repo doesn't exist" do
+      project.stub(repo_exists?: false, has_commits?: true)
+      project.should be_empty_repo
+    end
+
+    it "should return true if the repo has commits" do
+      project.stub(repo_exists?: true, has_commits?: false)
+      project.should be_empty_repo
+    end
+
+    it "should return false if the repo exists and has commits" do
+      project.stub(repo_exists?: true, has_commits?: true)
+      project.should_not be_empty_repo
+    end
+  end
+
+  describe "#discover_default_branch" do
+    let(:master) { double(name: 'master') }
+    let(:stable) { double(name: 'stable') }
+
+    it "returns 'master' when master exists" do
+      project.should_receive(:heads).and_return([stable, master])
+      project.discover_default_branch.should == 'master'
+    end
+
+    it "returns non-master when master exists but default branch is set to something else" do
+      project.default_branch = 'stable'
+      project.should_receive(:heads).and_return([stable, master])
+      project.discover_default_branch.should == 'stable'
+    end
+
+    it "returns a non-master branch when only one exists" do
+      project.should_receive(:heads).and_return([stable])
+      project.discover_default_branch.should == 'stable'
+    end
+
+    it "returns nil when no branch exists" do
+      project.should_receive(:heads).and_return([])
+      project.discover_default_branch.should be_nil
+    end
+  end
+
+  describe "#root_ref" do
+    it "returns default_branch when set" do
+      project.default_branch = 'stable'
+      project.root_ref.should == 'stable'
+    end
+
+    it "returns 'master' when default_branch is nil" do
+      project.default_branch = nil
+      project.root_ref.should == 'master'
+    end
+  end
+
+  describe "#root_ref?" do
+    it "returns true when branch is root_ref" do
+      project.default_branch = 'stable'
+      project.root_ref?('stable').should be_true
+    end
+
+    it "returns false when branch is not root_ref" do
+      project.default_branch = nil
+      project.root_ref?('stable').should be_false
+    end
+  end
+end
diff --git a/spec/roles/votes_spec.rb b/spec/roles/votes_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..98666022a8fcbd7f22b70862937dbbdad25adc58
--- /dev/null
+++ b/spec/roles/votes_spec.rb
@@ -0,0 +1,132 @@
+require 'spec_helper'
+
+describe Issue do
+  let(:issue) { create(:issue) }
+
+  describe "#upvotes" do
+    it "with no notes has a 0/0 score" do
+      issue.upvotes.should == 0
+    end
+
+    it "should recognize non-+1 notes" do
+      issue.notes << create(:note, note: "No +1 here")
+      issue.should have(1).note
+      issue.notes.first.upvote?.should be_false
+      issue.upvotes.should == 0
+    end
+
+    it "should recognize a single +1 note" do
+      issue.notes << create(:note, note: "+1 This is awesome")
+      issue.upvotes.should == 1
+    end
+
+    it "should recognize multiple +1 notes" do
+      issue.notes << create(:note, note: "+1 This is awesome")
+      issue.notes << create(:note, note: "+1 I want this")
+      issue.upvotes.should == 2
+    end
+  end
+
+  describe "#downvotes" do
+    it "with no notes has a 0/0 score" do
+      issue.downvotes.should == 0
+    end
+
+    it "should recognize non--1 notes" do
+      issue.notes << create(:note, note: "Almost got a -1")
+      issue.should have(1).note
+      issue.notes.first.downvote?.should be_false
+      issue.downvotes.should == 0
+    end
+
+    it "should recognize a single -1 note" do
+      issue.notes << create(:note, note: "-1 This is bad")
+      issue.downvotes.should == 1
+    end
+
+    it "should recognize multiple -1 notes" do
+      issue.notes << create(:note, note: "-1 This is bad")
+      issue.notes << create(:note, note: "-1 Away with this")
+      issue.downvotes.should == 2
+    end
+  end
+
+  describe "#votes_count" do
+    it "with no notes has a 0/0 score" do
+      issue.votes_count.should == 0
+    end
+
+    it "should recognize non notes" do
+      issue.notes << create(:note, note: "No +1 here")
+      issue.should have(1).note
+      issue.votes_count.should == 0
+    end
+
+    it "should recognize a single +1 note" do
+      issue.notes << create(:note, note: "+1 This is awesome")
+      issue.votes_count.should == 1
+    end
+
+    it "should recognize a single -1 note" do
+      issue.notes << create(:note, note: "-1 This is bad")
+      issue.votes_count.should == 1
+    end
+
+    it "should recognize multiple notes" do
+      issue.notes << create(:note, note: "+1 This is awesome")
+      issue.notes << create(:note, note: "-1 This is bad")
+      issue.notes << create(:note, note: "+1 I want this")
+      issue.votes_count.should == 3
+    end
+  end
+
+  describe "#upvotes_in_percent" do
+    it "with no notes has a 0% score" do
+      issue.upvotes_in_percent.should == 0
+    end
+
+    it "should count a single 1 note as 100%" do
+      issue.notes << create(:note, note: "+1 This is awesome")
+      issue.upvotes_in_percent.should == 100
+    end
+
+    it "should count multiple +1 notes as 100%" do
+      issue.notes << create(:note, note: "+1 This is awesome")
+      issue.notes << create(:note, note: "+1 I want this")
+      issue.upvotes_in_percent.should == 100
+    end
+
+    it "should count fractions for multiple +1 and -1 notes correctly" do
+      issue.notes << create(:note, note: "+1 This is awesome")
+      issue.notes << create(:note, note: "+1 I want this")
+      issue.notes << create(:note, note: "-1 This is bad")
+      issue.notes << create(:note, note: "+1 me too")
+      issue.upvotes_in_percent.should == 75
+    end
+  end
+
+  describe "#downvotes_in_percent" do
+    it "with no notes has a 0% score" do
+      issue.downvotes_in_percent.should == 0
+    end
+
+    it "should count a single -1 note as 100%" do
+      issue.notes << create(:note, note: "-1 This is bad")
+      issue.downvotes_in_percent.should == 100
+    end
+
+    it "should count multiple -1 notes as 100%" do
+      issue.notes << create(:note, note: "-1 This is bad")
+      issue.notes << create(:note, note: "-1 Away with this")
+      issue.downvotes_in_percent.should == 100
+    end
+
+    it "should count fractions for multiple +1 and -1 notes correctly" do
+      issue.notes << create(:note, note: "+1 This is awesome")
+      issue.notes << create(:note, note: "+1 I want this")
+      issue.notes << create(:note, note: "-1 This is bad")
+      issue.notes << create(:note, note: "+1 me too")
+      issue.downvotes_in_percent.should == 25
+    end
+  end
+end
diff --git a/spec/routing/admin_routing_spec.rb b/spec/routing/admin_routing_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..60261c7ae7102139540b931a4f72fddef0dfd93a
--- /dev/null
+++ b/spec/routing/admin_routing_spec.rb
@@ -0,0 +1,166 @@
+require 'spec_helper'
+
+# team_update_admin_user PUT    /admin/users/:id/team_update(.:format) admin/users#team_update
+#       block_admin_user PUT    /admin/users/:id/block(.:format)       admin/users#block
+#     unblock_admin_user PUT    /admin/users/:id/unblock(.:format)     admin/users#unblock
+#            admin_users GET    /admin/users(.:format)                 admin/users#index
+#                        POST   /admin/users(.:format)                 admin/users#create
+#         new_admin_user GET    /admin/users/new(.:format)             admin/users#new
+#        edit_admin_user GET    /admin/users/:id/edit(.:format)        admin/users#edit
+#             admin_user GET    /admin/users/:id(.:format)             admin/users#show
+#                        PUT    /admin/users/:id(.:format)             admin/users#update
+#                        DELETE /admin/users/:id(.:format)             admin/users#destroy
+describe Admin::UsersController, "routing" do
+  it "to #team_update" do
+    put("/admin/users/1/team_update").should route_to('admin/users#team_update', id: '1')
+  end
+
+  it "to #block" do
+    put("/admin/users/1/block").should route_to('admin/users#block', id: '1')
+  end
+
+  it "to #unblock" do
+    put("/admin/users/1/unblock").should route_to('admin/users#unblock', id: '1')
+  end
+
+  it "to #index" do
+    get("/admin/users").should route_to('admin/users#index')
+  end
+
+  it "to #show" do
+    get("/admin/users/1").should route_to('admin/users#show', id: '1')
+  end
+
+  it "to #create" do
+    post("/admin/users").should route_to('admin/users#create')
+  end
+
+  it "to #new" do
+    get("/admin/users/new").should route_to('admin/users#new')
+  end
+
+  it "to #edit" do
+    get("/admin/users/1/edit").should route_to('admin/users#edit', id: '1')
+  end
+
+  it "to #show" do
+    get("/admin/users/1").should route_to('admin/users#show', id: '1')
+  end
+
+  it "to #update" do
+    put("/admin/users/1").should route_to('admin/users#update', id: '1')
+  end
+
+  it "to #destroy" do
+    delete("/admin/users/1").should route_to('admin/users#destroy', id: '1')
+  end
+end
+
+#        team_admin_project GET    /admin/projects/:id/team(.:format)        admin/projects#team {:id=>/[^\/]+/}
+# team_update_admin_project PUT    /admin/projects/:id/team_update(.:format) admin/projects#team_update {:id=>/[^\/]+/}
+#            admin_projects GET    /admin/projects(.:format)                 admin/projects#index {:id=>/[^\/]+/}
+#                           POST   /admin/projects(.:format)                 admin/projects#create {:id=>/[^\/]+/}
+#         new_admin_project GET    /admin/projects/new(.:format)             admin/projects#new {:id=>/[^\/]+/}
+#        edit_admin_project GET    /admin/projects/:id/edit(.:format)        admin/projects#edit {:id=>/[^\/]+/}
+#             admin_project GET    /admin/projects/:id(.:format)             admin/projects#show {:id=>/[^\/]+/}
+#                           PUT    /admin/projects/:id(.:format)             admin/projects#update {:id=>/[^\/]+/}
+#                           DELETE /admin/projects/:id(.:format)             admin/projects#destroy {:id=>/[^\/]+/}
+describe Admin::ProjectsController, "routing" do
+  it "to #team" do
+    get("/admin/projects/gitlab/team").should route_to('admin/projects#team', id: 'gitlab')
+  end
+
+  it "to #team_update" do
+    put("/admin/projects/gitlab/team_update").should route_to('admin/projects#team_update', id: 'gitlab')
+  end
+
+  it "to #index" do
+    get("/admin/projects").should route_to('admin/projects#index')
+  end
+
+  it "to #create" do
+    post("/admin/projects").should route_to('admin/projects#create')
+  end
+
+  it "to #new" do
+    get("/admin/projects/new").should route_to('admin/projects#new')
+  end
+
+  it "to #edit" do
+    get("/admin/projects/gitlab/edit").should route_to('admin/projects#edit', id: 'gitlab')
+  end
+
+  it "to #show" do
+    get("/admin/projects/gitlab").should route_to('admin/projects#show', id: 'gitlab')
+  end
+
+  it "to #update" do
+    put("/admin/projects/gitlab").should route_to('admin/projects#update', id: 'gitlab')
+  end
+
+  it "to #destroy" do
+    delete("/admin/projects/gitlab").should route_to('admin/projects#destroy', id: 'gitlab')
+  end
+end
+
+# edit_admin_team_member GET    /admin/team_members/:id/edit(.:format) admin/team_members#edit
+#      admin_team_member PUT    /admin/team_members/:id(.:format)      admin/team_members#update
+#                        DELETE /admin/team_members/:id(.:format)      admin/team_members#destroy
+describe Admin::TeamMembersController, "routing" do
+  it "to #edit" do
+    get("/admin/team_members/1/edit").should route_to('admin/team_members#edit', id: '1')
+  end
+
+  it "to #update" do
+    put("/admin/team_members/1").should route_to('admin/team_members#update', id: '1')
+  end
+
+  it "to #destroy" do
+    delete("/admin/team_members/1").should route_to('admin/team_members#destroy', id: '1')
+  end
+end
+
+# admin_hook_test GET    /admin/hooks/:hook_id/test(.:format) admin/hooks#test
+#     admin_hooks GET    /admin/hooks(.:format)               admin/hooks#index
+#                 POST   /admin/hooks(.:format)               admin/hooks#create
+#      admin_hook DELETE /admin/hooks/:id(.:format)           admin/hooks#destroy
+describe Admin::HooksController, "routing" do
+  it "to #test" do
+    get("/admin/hooks/1/test").should route_to('admin/hooks#test', hook_id: '1')
+  end
+
+  it "to #index" do
+    get("/admin/hooks").should route_to('admin/hooks#index')
+  end
+
+  it "to #create" do
+    post("/admin/hooks").should route_to('admin/hooks#create')
+  end
+
+  it "to #destroy" do
+    delete("/admin/hooks/1").should route_to('admin/hooks#destroy', id: '1')
+  end
+
+end
+
+# admin_logs GET    /admin/logs(.:format) admin/logs#show
+describe Admin::LogsController, "routing" do
+  it "to #show" do
+    get("/admin/logs").should route_to('admin/logs#show')
+  end
+end
+
+# admin_resque GET    /admin/resque(.:format) admin/resque#show
+describe Admin::ResqueController, "routing" do
+  it "to #show" do
+    get("/admin/resque").should route_to('admin/resque#show')
+  end
+end
+
+# admin_root        /admin(.:format) admin/dashboard#index
+describe Admin::DashboardController, "routing" do
+  it "to #index" do
+    get("/admin").should route_to('admin/dashboard#index')
+  end
+end
+
diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b3f9db01ab32d5412651fba2035f624e4b0dbdb0
--- /dev/null
+++ b/spec/routing/project_routing_spec.rb
@@ -0,0 +1,398 @@
+require 'spec_helper'
+
+# Shared examples for a resource inside a Project
+#
+# By default it tests all the default REST actions: index, create, new, edit,
+# show, update, and destroy. You can remove actions by customizing the
+# `actions` variable.
+#
+# It also expects a `controller` variable to be available which defines both
+# the path to the resource as well as the controller name.
+#
+# Examples
+#
+#   # Default behavior
+#   it_behaves_like "RESTful project resources" do
+#     let(:controller) { 'issues' }
+#   end
+#
+#   # Customizing actions
+#   it_behaves_like "RESTful project resources" do
+#     let(:actions)    { [:index] }
+#     let(:controller) { 'issues' }
+#   end
+shared_examples "RESTful project resources" do
+  let(:actions) { [:index, :create, :new, :edit, :show, :update, :destroy] }
+
+  it "to #index" do
+    get("/gitlabhq/#{controller}").should route_to("#{controller}#index", project_id: 'gitlabhq') if actions.include?(:index)
+  end
+
+  it "to #create" do
+    post("/gitlabhq/#{controller}").should route_to("#{controller}#create", project_id: 'gitlabhq') if actions.include?(:create)
+  end
+
+  it "to #new" do
+    get("/gitlabhq/#{controller}/new").should route_to("#{controller}#new", project_id: 'gitlabhq') if actions.include?(:new)
+  end
+
+  it "to #edit" do
+    get("/gitlabhq/#{controller}/1/edit").should route_to("#{controller}#edit", project_id: 'gitlabhq', id: '1') if actions.include?(:edit)
+  end
+
+  it "to #show" do
+    get("/gitlabhq/#{controller}/1").should route_to("#{controller}#show", project_id: 'gitlabhq', id: '1') if actions.include?(:show)
+  end
+
+  it "to #update" do
+    put("/gitlabhq/#{controller}/1").should route_to("#{controller}#update", project_id: 'gitlabhq', id: '1') if actions.include?(:update)
+  end
+
+  it "to #destroy" do
+    delete("/gitlabhq/#{controller}/1").should route_to("#{controller}#destroy", project_id: 'gitlabhq', id: '1') if actions.include?(:destroy)
+  end
+end
+
+#      projects POST   /projects(.:format)     projects#create
+#   new_project GET    /projects/new(.:format) projects#new
+#  wall_project GET    /:id/wall(.:format)     projects#wall
+# graph_project GET    /:id/graph(.:format)    projects#graph
+# files_project GET    /:id/files(.:format)    projects#files
+#  edit_project GET    /:id/edit(.:format)     projects#edit
+#       project GET    /:id(.:format)          projects#show
+#               PUT    /:id(.:format)          projects#update
+#               DELETE /:id(.:format)          projects#destroy
+describe ProjectsController, "routing" do
+  it "to #create" do
+    post("/projects").should route_to('projects#create')
+  end
+
+  it "to #new" do
+    get("/projects/new").should route_to('projects#new')
+  end
+
+  it "to #wall" do
+    get("/gitlabhq/wall").should route_to('projects#wall', id: 'gitlabhq')
+  end
+
+  it "to #graph" do
+    get("/gitlabhq/graph").should route_to('projects#graph', id: 'gitlabhq')
+  end
+
+  it "to #files" do
+    get("/gitlabhq/files").should route_to('projects#files', id: 'gitlabhq')
+  end
+
+  it "to #edit" do
+    get("/gitlabhq/edit").should route_to('projects#edit', id: 'gitlabhq')
+  end
+
+  it "to #show" do
+    get("/gitlabhq").should route_to('projects#show', id: 'gitlabhq')
+  end
+
+  it "to #update" do
+    put("/gitlabhq").should route_to('projects#update', id: 'gitlabhq')
+  end
+
+  it "to #destroy" do
+    delete("/gitlabhq").should route_to('projects#destroy', id: 'gitlabhq')
+  end
+end
+
+#  pages_project_wikis GET    /:project_id/wikis/pages(.:format)       wikis#pages
+# history_project_wiki GET    /:project_id/wikis/:id/history(.:format) wikis#history
+#        project_wikis POST   /:project_id/wikis(.:format)             wikis#create
+#    edit_project_wiki GET    /:project_id/wikis/:id/edit(.:format)    wikis#edit
+#         project_wiki GET    /:project_id/wikis/:id(.:format)         wikis#show
+#                      DELETE /:project_id/wikis/:id(.:format)         wikis#destroy
+describe WikisController, "routing" do
+  it "to #pages" do
+    get("/gitlabhq/wikis/pages").should route_to('wikis#pages', project_id: 'gitlabhq')
+  end
+
+  it "to #history" do
+    get("/gitlabhq/wikis/1/history").should route_to('wikis#history', project_id: 'gitlabhq', id: '1')
+  end
+
+  it_behaves_like "RESTful project resources" do
+    let(:actions)    { [:create, :edit, :show, :destroy] }
+    let(:controller) { 'wikis' }
+  end
+end
+
+# branches_project_repository GET    /:project_id/repository/branches(.:format) repositories#branches
+#     tags_project_repository GET    /:project_id/repository/tags(.:format)     repositories#tags
+#  archive_project_repository GET    /:project_id/repository/archive(.:format)  repositories#archive
+#          project_repository POST   /:project_id/repository(.:format)          repositories#create
+#      new_project_repository GET    /:project_id/repository/new(.:format)      repositories#new
+#     edit_project_repository GET    /:project_id/repository/edit(.:format)     repositories#edit
+#                             GET    /:project_id/repository(.:format)          repositories#show
+#                             PUT    /:project_id/repository(.:format)          repositories#update
+#                             DELETE /:project_id/repository(.:format)          repositories#destroy
+describe RepositoriesController, "routing" do
+  it "to #branches" do
+    get("/gitlabhq/repository/branches").should route_to('repositories#branches', project_id: 'gitlabhq')
+  end
+
+  it "to #tags" do
+    get("/gitlabhq/repository/tags").should route_to('repositories#tags', project_id: 'gitlabhq')
+  end
+
+  it "to #archive" do
+    get("/gitlabhq/repository/archive").should route_to('repositories#archive', project_id: 'gitlabhq')
+  end
+
+  it "to #create" do
+    post("/gitlabhq/repository").should route_to('repositories#create', project_id: 'gitlabhq')
+  end
+
+  it "to #new" do
+    get("/gitlabhq/repository/new").should route_to('repositories#new', project_id: 'gitlabhq')
+  end
+
+  it "to #edit" do
+    get("/gitlabhq/repository/edit").should route_to('repositories#edit', project_id: 'gitlabhq')
+  end
+
+  it "to #show" do
+    get("/gitlabhq/repository").should route_to('repositories#show', project_id: 'gitlabhq')
+  end
+
+  it "to #update" do
+    put("/gitlabhq/repository").should route_to('repositories#update', project_id: 'gitlabhq')
+  end
+
+  it "to #destroy" do
+    delete("/gitlabhq/repository").should route_to('repositories#destroy', project_id: 'gitlabhq')
+  end
+end
+
+#     project_deploy_keys GET    /:project_id/deploy_keys(.:format)          deploy_keys#index
+#                         POST   /:project_id/deploy_keys(.:format)          deploy_keys#create
+#  new_project_deploy_key GET    /:project_id/deploy_keys/new(.:format)      deploy_keys#new
+# edit_project_deploy_key GET    /:project_id/deploy_keys/:id/edit(.:format) deploy_keys#edit
+#      project_deploy_key GET    /:project_id/deploy_keys/:id(.:format)      deploy_keys#show
+#                         PUT    /:project_id/deploy_keys/:id(.:format)      deploy_keys#update
+#                         DELETE /:project_id/deploy_keys/:id(.:format)      deploy_keys#destroy
+describe DeployKeysController, "routing" do
+  it_behaves_like "RESTful project resources" do
+    let(:controller) { 'deploy_keys' }
+  end
+end
+
+# project_protected_branches GET    /:project_id/protected_branches(.:format)     protected_branches#index
+#                            POST   /:project_id/protected_branches(.:format)     protected_branches#create
+#   project_protected_branch DELETE /:project_id/protected_branches/:id(.:format) protected_branches#destroy
+describe ProtectedBranchesController, "routing" do
+  it_behaves_like "RESTful project resources" do
+    let(:actions)    { [:index, :create, :destroy] }
+    let(:controller) { 'protected_branches' }
+  end
+end
+
+#    switch_project_refs GET    /:project_id/switch(.:format)              refs#switch
+#       tree_project_ref GET    /:project_id/:id/tree(.:format)            refs#tree
+#  logs_tree_project_ref GET    /:project_id/:id/logs_tree(.:format)       refs#logs_tree
+#       blob_project_ref GET    /:project_id/:id/blob(.:format)            refs#blob
+#  tree_file_project_ref GET    /:project_id/:id/tree/:path(.:format)      refs#tree
+#  logs_file_project_ref GET    /:project_id/:id/logs_tree/:path(.:format) refs#logs_tree
+# blame_file_project_ref GET    /:project_id/:id/blame/:path(.:format)     refs#blame
+describe RefsController, "routing" do
+  it "to #switch" do
+    get("/gitlabhq/switch").should route_to('refs#switch', project_id: 'gitlabhq')
+  end
+
+  it "to #tree" do
+    get("/gitlabhq/stable/tree").should             route_to('refs#tree', project_id: 'gitlabhq', id: 'stable')
+    get("/gitlabhq/stable/tree/foo/bar/baz").should route_to('refs#tree', project_id: 'gitlabhq', id: 'stable', path: 'foo/bar/baz')
+  end
+
+  it "to #logs_tree" do
+    get("/gitlabhq/stable/logs_tree").should             route_to('refs#logs_tree', project_id: 'gitlabhq', id: 'stable')
+    get("/gitlabhq/stable/logs_tree/foo/bar/baz").should route_to('refs#logs_tree', project_id: 'gitlabhq', id: 'stable', path: 'foo/bar/baz')
+  end
+
+  it "to #blob" do
+    get("/gitlabhq/stable/blob").should route_to('refs#blob', project_id: 'gitlabhq', id: 'stable')
+  end
+
+  it "to #blame" do
+    get("/gitlabhq/stable/blame/foo/bar/baz").should route_to('refs#blame', project_id: 'gitlabhq', id: 'stable', path: 'foo/bar/baz')
+  end
+end
+
+#           diffs_project_merge_request GET    /:project_id/merge_requests/:id/diffs(.:format)           merge_requests#diffs
+#       automerge_project_merge_request GET    /:project_id/merge_requests/:id/automerge(.:format)       merge_requests#automerge
+# automerge_check_project_merge_request GET    /:project_id/merge_requests/:id/automerge_check(.:format) merge_requests#automerge_check
+#             raw_project_merge_request GET    /:project_id/merge_requests/:id/raw(.:format)             merge_requests#raw
+#    branch_from_project_merge_requests GET    /:project_id/merge_requests/branch_from(.:format)         merge_requests#branch_from
+#      branch_to_project_merge_requests GET    /:project_id/merge_requests/branch_to(.:format)           merge_requests#branch_to
+#                project_merge_requests GET    /:project_id/merge_requests(.:format)                     merge_requests#index
+#                                       POST   /:project_id/merge_requests(.:format)                     merge_requests#create
+#             new_project_merge_request GET    /:project_id/merge_requests/new(.:format)                 merge_requests#new
+#            edit_project_merge_request GET    /:project_id/merge_requests/:id/edit(.:format)            merge_requests#edit
+#                 project_merge_request GET    /:project_id/merge_requests/:id(.:format)                 merge_requests#show
+#                                       PUT    /:project_id/merge_requests/:id(.:format)                 merge_requests#update
+#                                       DELETE /:project_id/merge_requests/:id(.:format)                 merge_requests#destroy
+describe MergeRequestsController, "routing" do
+  it "to #diffs" do
+    get("/gitlabhq/merge_requests/1/diffs").should route_to('merge_requests#diffs', project_id: 'gitlabhq', id: '1')
+  end
+
+  it "to #automerge" do
+    get("/gitlabhq/merge_requests/1/automerge").should route_to('merge_requests#automerge', project_id: 'gitlabhq', id: '1')
+  end
+
+  it "to #automerge_check" do
+    get("/gitlabhq/merge_requests/1/automerge_check").should route_to('merge_requests#automerge_check', project_id: 'gitlabhq', id: '1')
+  end
+
+  it "to #raw" do
+    get("/gitlabhq/merge_requests/1/raw").should route_to('merge_requests#raw', project_id: 'gitlabhq', id: '1')
+  end
+
+  it "to #branch_from" do
+    get("/gitlabhq/merge_requests/branch_from").should route_to('merge_requests#branch_from', project_id: 'gitlabhq')
+  end
+
+  it "to #branch_to" do
+    get("/gitlabhq/merge_requests/branch_to").should route_to('merge_requests#branch_to', project_id: 'gitlabhq')
+  end
+
+  it_behaves_like "RESTful project resources" do
+    let(:controller) { 'merge_requests' }
+  end
+end
+
+#  raw_project_snippet GET    /:project_id/snippets/:id/raw(.:format)  snippets#raw
+#     project_snippets GET    /:project_id/snippets(.:format)          snippets#index
+#                      POST   /:project_id/snippets(.:format)          snippets#create
+#  new_project_snippet GET    /:project_id/snippets/new(.:format)      snippets#new
+# edit_project_snippet GET    /:project_id/snippets/:id/edit(.:format) snippets#edit
+#      project_snippet GET    /:project_id/snippets/:id(.:format)      snippets#show
+#                      PUT    /:project_id/snippets/:id(.:format)      snippets#update
+#                      DELETE /:project_id/snippets/:id(.:format)      snippets#destroy
+describe SnippetsController, "routing" do
+  it "to #raw" do
+    get("/gitlabhq/snippets/1/raw").should route_to('snippets#raw', project_id: 'gitlabhq', id: '1')
+  end
+
+  it_behaves_like "RESTful project resources" do
+    let(:controller) { 'snippets' }
+  end
+end
+
+# test_project_hook GET    /:project_id/hooks/:id/test(.:format) hooks#test
+#     project_hooks GET    /:project_id/hooks(.:format)          hooks#index
+#                   POST   /:project_id/hooks(.:format)          hooks#create
+#      project_hook DELETE /:project_id/hooks/:id(.:format)      hooks#destroy
+describe HooksController, "routing" do
+  it "to #test" do
+    get("/gitlabhq/hooks/1/test").should route_to('hooks#test', project_id: 'gitlabhq', id: '1')
+  end
+
+  it_behaves_like "RESTful project resources" do
+    let(:actions)    { [:index, :create, :destroy] }
+    let(:controller) { 'hooks' }
+  end
+end
+
+# compare_project_commits GET    /:project_id/commits/compare(.:format)   commits#compare
+#    patch_project_commit GET    /:project_id/commits/:id/patch(.:format) commits#patch
+#         project_commits GET    /:project_id/commits(.:format)           commits#index
+#                         POST   /:project_id/commits(.:format)           commits#create
+#      new_project_commit GET    /:project_id/commits/new(.:format)       commits#new
+#     edit_project_commit GET    /:project_id/commits/:id/edit(.:format)  commits#edit
+#          project_commit GET    /:project_id/commits/:id(.:format)       commits#show
+#                         PUT    /:project_id/commits/:id(.:format)       commits#update
+#                         DELETE /:project_id/commits/:id(.:format)       commits#destroy
+describe CommitsController, "routing" do
+  it "to #compare" do
+    get("/gitlabhq/commits/compare").should route_to('commits#compare', project_id: 'gitlabhq')
+  end
+
+  it "to #patch" do
+    get("/gitlabhq/commits/1/patch").should route_to('commits#patch', project_id: 'gitlabhq', id: '1')
+  end
+
+  it_behaves_like "RESTful project resources" do
+    let(:controller) { 'commits' }
+  end
+end
+
+#     project_team_members GET    /:project_id/team_members(.:format)          team_members#index
+#                          POST   /:project_id/team_members(.:format)          team_members#create
+#  new_project_team_member GET    /:project_id/team_members/new(.:format)      team_members#new
+# edit_project_team_member GET    /:project_id/team_members/:id/edit(.:format) team_members#edit
+#      project_team_member GET    /:project_id/team_members/:id(.:format)      team_members#show
+#                          PUT    /:project_id/team_members/:id(.:format)      team_members#update
+#                          DELETE /:project_id/team_members/:id(.:format)      team_members#destroy
+describe TeamMembersController, "routing" do
+  it_behaves_like "RESTful project resources" do
+    let(:controller) { 'team_members' }
+  end
+end
+
+#     project_milestones GET    /:project_id/milestones(.:format)          milestones#index
+#                        POST   /:project_id/milestones(.:format)          milestones#create
+#  new_project_milestone GET    /:project_id/milestones/new(.:format)      milestones#new
+# edit_project_milestone GET    /:project_id/milestones/:id/edit(.:format) milestones#edit
+#      project_milestone GET    /:project_id/milestones/:id(.:format)      milestones#show
+#                        PUT    /:project_id/milestones/:id(.:format)      milestones#update
+#                        DELETE /:project_id/milestones/:id(.:format)      milestones#destroy
+describe MilestonesController, "routing" do
+  it_behaves_like "RESTful project resources" do
+    let(:controller) { 'milestones' }
+  end
+end
+
+# project_labels GET    /:project_id/labels(.:format) labels#index
+describe LabelsController, "routing" do
+  it "to #index" do
+    get("/gitlabhq/labels").should route_to('labels#index', project_id: 'gitlabhq')
+  end
+end
+
+#        sort_project_issues POST   /:project_id/issues/sort(.:format)        issues#sort
+# bulk_update_project_issues POST   /:project_id/issues/bulk_update(.:format) issues#bulk_update
+#      search_project_issues GET    /:project_id/issues/search(.:format)      issues#search
+#             project_issues GET    /:project_id/issues(.:format)             issues#index
+#                            POST   /:project_id/issues(.:format)             issues#create
+#          new_project_issue GET    /:project_id/issues/new(.:format)         issues#new
+#         edit_project_issue GET    /:project_id/issues/:id/edit(.:format)    issues#edit
+#              project_issue GET    /:project_id/issues/:id(.:format)         issues#show
+#                            PUT    /:project_id/issues/:id(.:format)         issues#update
+#                            DELETE /:project_id/issues/:id(.:format)         issues#destroy
+describe IssuesController, "routing" do
+  it "to #sort" do
+    post("/gitlabhq/issues/sort").should route_to('issues#sort', project_id: 'gitlabhq')
+  end
+
+  it "to #bulk_update" do
+    post("/gitlabhq/issues/bulk_update").should route_to('issues#bulk_update', project_id: 'gitlabhq')
+  end
+
+  it "to #search" do
+    get("/gitlabhq/issues/search").should route_to('issues#search', project_id: 'gitlabhq')
+  end
+
+  it_behaves_like "RESTful project resources" do
+    let(:controller) { 'issues' }
+  end
+end
+
+# preview_project_notes POST   /:project_id/notes/preview(.:format) notes#preview
+#         project_notes GET    /:project_id/notes(.:format)         notes#index
+#                       POST   /:project_id/notes(.:format)         notes#create
+#          project_note DELETE /:project_id/notes/:id(.:format)     notes#destroy
+describe NotesController, "routing" do
+  it "to #preview" do
+    post("/gitlabhq/notes/preview").should route_to('notes#preview', project_id: 'gitlabhq')
+  end
+
+  it_behaves_like "RESTful project resources" do
+    let(:actions)    { [:index, :create, :destroy] }
+    let(:controller) { 'notes' }
+  end
+end
diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..cb8dbf373baa82f9c0eb49bba48ae7d7dc1dcd10
--- /dev/null
+++ b/spec/routing/routing_spec.rb
@@ -0,0 +1,186 @@
+require 'spec_helper'
+
+# search GET    /search(.:format) search#show
+describe SearchController, "routing" do
+  it "to #show" do
+    get("/search").should route_to('search#show')
+  end
+end
+
+# gitlab_api /api         Gitlab::API
+#     resque /info/resque Resque::Server
+#            /:path       Grack
+describe "Mounted Apps", "routing" do
+  it "to API" do
+    get("/api").should be_routable
+  end
+
+  it "to Resque" do
+    pending
+    get("/info/resque").should be_routable
+  end
+
+  it "to Grack" do
+    get("/gitlabhq.git").should be_routable
+  end
+end
+
+#              help GET    /help(.:format)              help#index
+#  help_permissions GET    /help/permissions(.:format)  help#permissions
+#     help_workflow GET    /help/workflow(.:format)     help#workflow
+#          help_api GET    /help/api(.:format)          help#api
+#    help_web_hooks GET    /help/web_hooks(.:format)    help#web_hooks
+# help_system_hooks GET    /help/system_hooks(.:format) help#system_hooks
+#     help_markdown GET    /help/markdown(.:format)     help#markdown
+#          help_ssh GET    /help/ssh(.:format)          help#ssh
+describe HelpController, "routing" do
+  it "to #index" do
+    get("/help").should route_to('help#index')
+  end
+
+  it "to #permissions" do
+    get("/help/permissions").should route_to('help#permissions')
+  end
+
+  it "to #workflow" do
+    get("/help/workflow").should route_to('help#workflow')
+  end
+
+  it "to #api" do
+    get("/help/api").should route_to('help#api')
+  end
+
+  it "to #web_hooks" do
+    get("/help/web_hooks").should route_to('help#web_hooks')
+  end
+
+  it "to #system_hooks" do
+    get("/help/system_hooks").should route_to('help#system_hooks')
+  end
+
+  it "to #markdown" do
+    get("/help/markdown").should route_to('help#markdown')
+  end
+
+  it "to #ssh" do
+    get("/help/ssh").should route_to('help#ssh')
+  end
+end
+
+# errors_githost GET    /errors/githost(.:format) errors#githost
+describe ErrorsController, "routing" do
+  it "to #githost" do
+    get("/errors/githost").should route_to('errors#githost')
+  end
+end
+
+#             profile_account GET    /profile/account(.:format)             profile#account
+#             profile_history GET    /profile/history(.:format)             profile#history
+#            profile_password PUT    /profile/password(.:format)            profile#password_update
+#               profile_token GET    /profile/token(.:format)               profile#token
+# profile_reset_private_token PUT    /profile/reset_private_token(.:format) profile#reset_private_token
+#                     profile GET    /profile(.:format)                     profile#show
+#              profile_design GET    /profile/design(.:format)              profile#design
+#              profile_update PUT    /profile/update(.:format)              profile#update
+describe ProfileController, "routing" do
+  it "to #account" do
+    get("/profile/account").should route_to('profile#account')
+  end
+
+  it "to #history" do
+    get("/profile/history").should route_to('profile#history')
+  end
+
+  it "to #password_update" do
+    put("/profile/password").should route_to('profile#password_update')
+  end
+
+  it "to #token" do
+    get("/profile/token").should route_to('profile#token')
+  end
+
+  it "to #reset_private_token" do
+    put("/profile/reset_private_token").should route_to('profile#reset_private_token')
+  end
+
+  it "to #show" do
+    get("/profile").should route_to('profile#show')
+  end
+
+  it "to #design" do
+    get("/profile/design").should route_to('profile#design')
+  end
+
+  it "to #update" do
+    put("/profile/update").should route_to('profile#update')
+  end
+end
+
+#     keys GET    /keys(.:format)          keys#index
+#          POST   /keys(.:format)          keys#create
+#  new_key GET    /keys/new(.:format)      keys#new
+# edit_key GET    /keys/:id/edit(.:format) keys#edit
+#      key GET    /keys/:id(.:format)      keys#show
+#          PUT    /keys/:id(.:format)      keys#update
+#          DELETE /keys/:id(.:format)      keys#destroy
+describe KeysController, "routing" do
+  it "to #index" do
+    get("/keys").should route_to('keys#index')
+  end
+
+  it "to #create" do
+    post("/keys").should route_to('keys#create')
+  end
+
+  it "to #new" do
+    get("/keys/new").should route_to('keys#new')
+  end
+
+  it "to #edit" do
+    get("/keys/1/edit").should route_to('keys#edit', id: '1')
+  end
+
+  it "to #show" do
+    get("/keys/1").should route_to('keys#show', id: '1')
+  end
+
+  it "to #update" do
+    put("/keys/1").should route_to('keys#update', id: '1')
+  end
+
+  it "to #destroy" do
+    delete("/keys/1").should route_to('keys#destroy', id: '1')
+  end
+end
+
+#                dashboard GET    /dashboard(.:format)                dashboard#index
+#         dashboard_issues GET    /dashboard/issues(.:format)         dashboard#issues
+# dashboard_merge_requests GET    /dashboard/merge_requests(.:format) dashboard#merge_requests
+#                     root        /                                   dashboard#index
+describe DashboardController, "routing" do
+  it "to #index" do
+    get("/dashboard").should route_to('dashboard#index')
+    get("/").should route_to('dashboard#index')
+  end
+
+  it "to #issues" do
+    get("/dashboard/issues").should route_to('dashboard#issues')
+  end
+
+  it "to #merge_requests" do
+    get("/dashboard/merge_requests").should route_to('dashboard#merge_requests')
+  end
+end
+
+#        new_user_session GET    /users/sign_in(.:format)               devise/sessions#new
+#            user_session POST   /users/sign_in(.:format)               devise/sessions#create
+#    destroy_user_session DELETE /users/sign_out(.:format)              devise/sessions#destroy
+# user_omniauth_authorize        /users/auth/:provider(.:format)        omniauth_callbacks#passthru
+#  user_omniauth_callback        /users/auth/:action/callback(.:format) omniauth_callbacks#(?-mix:(?!))
+#           user_password POST   /users/password(.:format)              devise/passwords#create
+#       new_user_password GET    /users/password/new(.:format)          devise/passwords#new
+#      edit_user_password GET    /users/password/edit(.:format)         devise/passwords#edit
+#                         PUT    /users/password(.:format)              devise/passwords#update
+describe "Authentication", "routing" do
+  # pending
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index cd931475486b92a766b1e6be86f26636bad20700..d381b3f1e2edcfda1bb023c853cd503e4ebd42f0 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -9,10 +9,7 @@ require File.expand_path("../../config/environment", __FILE__)
 require 'rspec/rails'
 require 'capybara/rails'
 require 'capybara/rspec'
-require 'capybara/dsl'
 require 'webmock/rspec'
-require 'factories'
-require 'monkeypatch'
 require 'email_spec'
 require 'headless'
 
@@ -23,10 +20,14 @@ Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
 # Use capybara-webkit
 Capybara.javascript_driver = :webkit
 
+WebMock.disable_net_connect!(allow_localhost: true)
+
 RSpec.configure do |config|
   config.mock_with :rspec
 
-  config.include LoginMacros
+  config.include LoginHelpers, type: :request
+  config.include GitoliteStub
+  config.include FactoryGirl::Syntax::Methods
 
   # If you're not using ActiveRecord, or you'd prefer not to run each of your
   # examples within a transaction, remove the following line or assign false
@@ -38,35 +39,11 @@ RSpec.configure do |config|
     headless.start
   end
 
-  config.before :each, type: :integration do
-    DeviseSessionMock.disable
-  end
-
   config.before do
-    if example.metadata[:js]
-      DatabaseCleaner.strategy = :truncation
-      Capybara::Selenium::Driver::DEFAULT_OPTIONS[:resynchronize] = true
-    else
-      DatabaseCleaner.strategy = :transaction
-    end
-
-    DatabaseCleaner.start
-
-    WebMock.disable_net_connect!(allow_localhost: true)
+    stub_gitolite!
 
     # !!! Observers disabled by default in tests
-    #
-    #   Use next code to enable observers
-    #   before(:each) { ActiveRecord::Base.observers.enable(:all) }
-    #
-    ActiveRecord::Base.observers.disable :all
-  end
-
-  config.after do
-    DatabaseCleaner.clean
+    ActiveRecord::Base.observers.disable(:all)
+    # ActiveRecord::Base.observers.enable(:all)
   end
-
-  config.include RSpec::Rails::RequestExampleGroup, type: :request, example_group: {
-    file_path: /spec\/api/
-  }
 end
diff --git a/spec/support/api.rb b/spec/support/api.rb
deleted file mode 100644
index d363d8b9a578eae234c0e049f0b4f03e83ce14a2..0000000000000000000000000000000000000000
--- a/spec/support/api.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-def api_prefix
-  "/api/#{Gitlab::API::VERSION}"
-end
-
-def json_response
-  JSON.parse(response.body)
-end
diff --git a/spec/support/api_helpers.rb b/spec/support/api_helpers.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7d9011971dd1a91482ff11c2d63ac156993fbdbc
--- /dev/null
+++ b/spec/support/api_helpers.rb
@@ -0,0 +1,34 @@
+module ApiHelpers
+  # Public: Prepend a request path with the path to the API
+  #
+  # path - Path to append
+  # user - User object - If provided, automatically appends private_token query
+  #          string for authenticated requests
+  #
+  # Examples
+  #
+  #   >> api('/issues')
+  #   => "/api/v2/issues"
+  #
+  #   >> api('/issues', User.last)
+  #   => "/api/v2/issues?private_token=..."
+  #
+  #   >> api('/issues?foo=bar', User.last)
+  #   => "/api/v2/issues?foo=bar&private_token=..."
+  #
+  # Returns the relative path to the requested API resource
+  def api(path, user = nil)
+    "/api/#{Gitlab::API::VERSION}#{path}" +
+
+      # Normalize query string
+      (path.index('?') ? '' : '?') +
+
+      # Append private_token if given a User object
+      (user.respond_to?(:private_token) ?
+        "&private_token=#{user.private_token}" : "")
+  end
+
+  def json_response
+    JSON.parse(response.body)
+  end
+end
diff --git a/spec/support/db_cleaner.rb b/spec/support/db_cleaner.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f1e072aa15f7f71974cb4633cf9fc1da4c42e39d
--- /dev/null
+++ b/spec/support/db_cleaner.rb
@@ -0,0 +1,18 @@
+require 'database_cleaner'
+
+RSpec.configure do |config|
+  config.before do
+    if example.metadata[:js]
+      DatabaseCleaner.strategy = :truncation
+      Capybara::Selenium::Driver::DEFAULT_OPTIONS[:resynchronize] = true
+    else
+      DatabaseCleaner.strategy = :transaction
+    end
+
+    DatabaseCleaner.start
+  end
+
+  config.after do
+    DatabaseCleaner.clean
+  end
+end
diff --git a/spec/support/gitolite_stub.rb b/spec/support/gitolite_stub.rb
new file mode 100644
index 0000000000000000000000000000000000000000..574bb5a12a3f9e52d2f84be600523d0560fcd866
--- /dev/null
+++ b/spec/support/gitolite_stub.rb
@@ -0,0 +1,21 @@
+module GitoliteStub
+  def stub_gitolite!
+    stub_gitlab_gitolite
+    stub_gitolite_admin
+  end
+
+  def stub_gitolite_admin
+    gitolite_admin = double('Gitolite::GitoliteAdmin')
+    gitolite_admin.as_null_object
+
+    Gitolite::GitoliteAdmin.stub(new: gitolite_admin)
+  end
+
+  def stub_gitlab_gitolite
+    gitolite_config = double('Gitlab::GitoliteConfig')
+    gitolite_config.stub(apply: ->() { yield(self) })
+    gitolite_config.as_null_object
+
+    Gitlab::GitoliteConfig.stub(new: gitolite_config)
+  end
+end
diff --git a/spec/support/js_patch.rb b/spec/support/js_patch.rb
deleted file mode 100644
index 0d4ab264e858956c04146a28f001d670646362ad..0000000000000000000000000000000000000000
--- a/spec/support/js_patch.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module JsPatch
-  def confirm_js_popup
-    page.evaluate_script("window.alert = function(msg) { return true; }")
-    page.evaluate_script("window.confirm = function(msg) { return true; }")
-  end
-end
diff --git a/spec/support/login.rb b/spec/support/login.rb
deleted file mode 100644
index 78a907bad0b196f176811588df88b714072f1874..0000000000000000000000000000000000000000
--- a/spec/support/login.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-module LoginMacros
-  def login_as role
-    @user = User.create(email: "user#{User.count}@mail.com",
-                        name: "John Smith",
-                        password: "123456",
-                        password_confirmation: "123456",
-                        skype: 'user_skype')
-
-    if role == :admin
-      @user.admin = true
-      @user.save!
-    end
-
-    visit new_user_session_path
-    fill_in "user_email", with: @user.email
-    fill_in "user_password", with: "123456"
-    click_button "Sign in"
-  end
-
-  def login_with(user)
-    visit new_user_session_path
-    fill_in "user_email", with: user.email
-    fill_in "user_password", with: "123456"
-    click_button "Sign in"
-  end
-
-  def logout
-    click_link "Logout" rescue nil
-  end
-end
diff --git a/spec/support/login_helpers.rb b/spec/support/login_helpers.rb
new file mode 100644
index 0000000000000000000000000000000000000000..769034e2286ddc8bad23d613c775d0b6b0f46051
--- /dev/null
+++ b/spec/support/login_helpers.rb
@@ -0,0 +1,23 @@
+module LoginHelpers
+  # Internal: Create and log in as a user of the specified role
+  #
+  # role - User role (e.g., :admin, :user)
+  def login_as(role)
+    @user = Factory(role)
+    login_with(@user)
+  end
+
+  # Internal: Login as the specified user
+  #
+  # user - User instance to login with
+  def login_with(user)
+    visit new_user_session_path
+    fill_in "user_email", with: user.email
+    fill_in "user_password", with: "123456"
+    click_button "Sign in"
+  end
+
+  def logout
+    click_link "Logout" rescue nil
+  end
+end
diff --git a/spec/support/matchers.rb b/spec/support/matchers.rb
index e0672166e923afbec165b9d5ec00de0aadd72e71..809453c4a3b45d1bb709e30aa68b3623516870fc 100644
--- a/spec/support/matchers.rb
+++ b/spec/support/matchers.rb
@@ -28,6 +28,16 @@ RSpec::Matchers.define :be_404_for do |user|
   end
 end
 
+RSpec::Matchers.define :include_module do |expected|
+  match do
+    described_class.included_modules.include?(expected)
+  end
+
+  failure_message_for_should do
+    "expected #{described_class} to include the #{expected} module"
+  end
+end
+
 module UrlAccess
   def url_allowed?(user, url)
     emulate_user(user)
@@ -57,3 +67,13 @@ module UrlAccess
     login_with(user) if user
   end
 end
+
+# Extend shoulda-matchers
+module Shoulda::Matchers::ActiveModel
+  class EnsureLengthOfMatcher
+    # Shortcut for is_at_least and is_at_most
+    def is_within(range)
+      is_at_least(range.min) && is_at_most(range.max)
+    end
+  end
+end
diff --git a/spec/support/shared_examples.rb b/spec/support/shared_examples.rb
deleted file mode 100644
index 9fd207d0db25771e7410edac89654f6dbf0c36ae..0000000000000000000000000000000000000000
--- a/spec/support/shared_examples.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-shared_examples_for :project_side_pane do
-  subject { page }
-  it { should have_content((@project || project).name) }
-  it { should have_content("Commits") }
-  it { should have_content("Files") }
-end
-
-shared_examples_for :tree_view do
-  subject { page }
-
-  it "should have Tree View of project" do
-    should have_content("app")
-    should have_content("History")
-    should have_content("Gemfile")
-  end
-end
diff --git a/spec/support/stubbed_repository.rb b/spec/support/stubbed_repository.rb
new file mode 100644
index 0000000000000000000000000000000000000000..90491e430b4be2a5175f345d7e9f1318e18c2755
--- /dev/null
+++ b/spec/support/stubbed_repository.rb
@@ -0,0 +1,31 @@
+# Stubs out all Git repository access done by models so that specs can run
+# against fake repositories without Grit complaining that they don't exist.
+module StubbedRepository
+  def path_to_repo
+    if new_record? || path == 'newproject'
+      # There are a couple Project specs and features that expect the Project's
+      # path to be in the returned path, so let's patronize them.
+      File.join(Rails.root, 'tmp', 'repositories', path)
+    else
+      # For everything else, just give it the path to one of our real seeded
+      # repos.
+      File.join(Rails.root, 'tmp', 'repositories', 'gitlabhq')
+    end
+  end
+
+  def satellite
+    FakeSatellite.new
+  end
+
+  class FakeSatellite
+    def exists?
+      true
+    end
+
+    def create
+      true
+    end
+  end
+end
+
+Project.send(:include, StubbedRepository)
diff --git a/features/projects/deploy_keys.feature b/tmp/.gitkeep
similarity index 100%
rename from features/projects/deploy_keys.feature
rename to tmp/.gitkeep
diff --git a/vendor/assets/images/authbuttons/github_32.png b/vendor/assets/images/authbuttons/github_32.png
new file mode 100644
index 0000000000000000000000000000000000000000..247e52a5f4282110243afa350cd4a13b0154c2a1
Binary files /dev/null and b/vendor/assets/images/authbuttons/github_32.png differ
diff --git a/vendor/assets/images/authbuttons/github_64.png b/vendor/assets/images/authbuttons/github_64.png
new file mode 100644
index 0000000000000000000000000000000000000000..fca7bf44652470a58edd12b410613656da95aed3
Binary files /dev/null and b/vendor/assets/images/authbuttons/github_64.png differ
diff --git a/vendor/assets/images/authbuttons/google_32.png b/vendor/assets/images/authbuttons/google_32.png
new file mode 100644
index 0000000000000000000000000000000000000000..3909e9de93b22e1f3a2e6c264f6289331412a3bb
Binary files /dev/null and b/vendor/assets/images/authbuttons/google_32.png differ
diff --git a/vendor/assets/images/authbuttons/google_64.png b/vendor/assets/images/authbuttons/google_64.png
new file mode 100644
index 0000000000000000000000000000000000000000..e55f34f1b7d57c52172eb2bab0964037c532629b
Binary files /dev/null and b/vendor/assets/images/authbuttons/google_64.png differ
diff --git a/vendor/assets/images/authbuttons/twitter_32.png b/vendor/assets/images/authbuttons/twitter_32.png
new file mode 100644
index 0000000000000000000000000000000000000000..daadcffd315f11026cface9d99409997050ab9b9
Binary files /dev/null and b/vendor/assets/images/authbuttons/twitter_32.png differ
diff --git a/vendor/assets/images/authbuttons/twitter_64.png b/vendor/assets/images/authbuttons/twitter_64.png
new file mode 100644
index 0000000000000000000000000000000000000000..68b74530c06b558b6c4848c2637d4caeaf4c969b
Binary files /dev/null and b/vendor/assets/images/authbuttons/twitter_64.png differ