diff --git a/.gitignore b/.gitignore
index b1dc17929f2feca60ae3dee171759bd8055e74a0..084edd30df7b7ae1e87c0c57ae1040c1808ac5d3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,8 @@ coverage/*
 backups/*
 *.swp
 public/uploads/
+.ruby-version
+.ruby-gemset
 .rvmrc
 .rbenv-version
 .directory
@@ -18,6 +20,7 @@ Vagrantfile
 config/gitlab.yml
 config/database.yml
 config/initializers/omniauth.rb
+config/initializers/rack_attack.rb
 config/unicorn.rb
 config/resque.yml
 config/aws.yml
diff --git a/.rspec b/.rspec
index 5902dd3af1fa401f8b3a8fd2f20cdeb562ee50ad..7488cbe7792e3f584f6bcc8fc283dc8036f25b50 100644
--- a/.rspec
+++ b/.rspec
@@ -1 +1 @@
---colour --drb
+--color --drb
diff --git a/.travis.yml b/.travis.yml
index d7fbbc7bbcbaf39223dbbe9bfbbb2328f2ec6028..f0fc2fb8829b09e50fb6286fc86c23ba6f3a98c1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,7 +8,6 @@ branches:
   only:
     - 'master'
 rvm:
-  - 1.9.3-p392
   - 2.0.0
 services:
   - mysql
@@ -16,7 +15,4 @@ services:
 before_script:
   - "cp config/database.yml.$DB config/database.yml"
   - "cp config/gitlab.yml.example config/gitlab.yml"
-  - "bundle exec rake db:setup RAILS_ENV=test"
-  - "bundle exec rake db:seed_fu RAILS_ENV=test"
-  - "sh -e /etc/init.d/xvfb start"
-script: "bundle exec rake travis --trace"
+script: "bundle exec rake gitlab:test --trace"
diff --git a/CHANGELOG b/CHANGELOG
index a6648d950b13a87c15850ceb7645d2a73b1c5d47..c4e411e2df54658dc3ef197ab9874006185ab918 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,11 +1,40 @@
+v 6.2.0
+  - Public projects are visible from the outside
+  - Add group access to permissions page
+  - Require current password to change one
+  - Group owner or admin can remove other group owners
+  - Remove group transfer since we have multiple owners
+  - Respect authorization in Repository API
+  - Improve UI for Project#files page
+  - Add more security specs
+  - Added search for projects by name to api (Izaak Alpert)
+  - Make default user theme configurable (Izaak Alpert)
+  - Update logic for validates_merge_request for tree of MR (Andrew Kumanyaev)
+  - Rake tasks for web hooks management (Jonhnny Weslley)
+  - Extended User API to expose admin and can_create_group for user creation/updating (Boyan Tabakov)
+  - API: Remove group
+
 v 6.1.0
-  - Link issues, merge requests, and commits when they reference each other with GFM
+  - Project specific IDs for issues, mr, milestones
+    Above items will get a new id and for example all bookmarked issue urls will change.
+    Old issue urls are redirected to the new one if the issue id is too high for an internal id.
+  - Description field added to Merge Request
+  - API: Sudo api calls (Izaak Alpert)
+  - API: Group membership api (Izaak Alpert)
+  - Improved commit diff
+  - Improved large commit handling (Boyan Tabakov)
+  - Rewrite: Init script now less prone to errors and keeps better track of the service (Rovanion Luckey)
+  - Link issues, merge requests, and commits when they reference each other with GFM (Ash Wilson)
   - Close issues automatically when pushing commits with a special message
-  - Project internal ids for issues, mr, milestones
   - Improve user removal from admin area
+  - Invalidate events cache when project was moved
   - Remove deprecated classes and rake tasks
   - Add event filter for group and project show pages
   - Add links to create branch/tag from project home page
+  - Add public-project? checkbox to new-project view
+  - Improved compare page. Added link to proceed into Merge Request
+  - Send email to user when he was added to group
+  - New landing page when you have 0 projects
 
 v 6.0.0
   - Feature: Replace teams with group membership
diff --git a/Gemfile b/Gemfile
index c80705af3168a0418362f0df7c0a87307f80822c..fb67f301f72bc76f0d1828b57d996687e536356f 100644
--- a/Gemfile
+++ b/Gemfile
@@ -23,7 +23,7 @@ gem 'omniauth-github'
 
 # Extracting information from a git repository
 # Provide access to Gitlab::Git library
-gem "gitlab_git", '2.1.1'
+gem "gitlab_git", "~> 3.0.0.beta1"
 
 # Ruby/Rack Git Smart-HTTP Server Handler
 gem 'gitlab-grack', '~> 1.0.1', require: 'grack'
@@ -111,6 +111,9 @@ gem 'tinder', '~> 1.9.2'
 # HipChat integration
 gem "hipchat", "~> 0.9.0"
 
+# Flowdock integration
+gem "gitlab-flowdock-git-hook", "~> 0.4.2"
+
 # d3
 gem "d3_rails", "~> 3.1.4"
 
@@ -120,6 +123,9 @@ gem "underscore-rails", "~> 1.4.4"
 # Sanitize user input
 gem "sanitize"
 
+# Protect against bruteforcing
+gem "rack-attack"
+
 group :assets do
   gem "sass-rails"
   gem "coffee-rails"
@@ -134,7 +140,7 @@ group :assets do
   gem "jquery-rails",     "2.1.3"
   gem "jquery-ui-rails",  "2.0.2"
   gem "modernizr",        "2.6.2"
-  gem "raphael-rails",    git: "https://github.com/gitlabhq/raphael-rails.git"
+  gem "raphael-rails", "~> 2.1.2"
   gem 'bootstrap-sass'
   gem "font-awesome-rails"
   gem "gemoji", "~> 1.2.1", require: 'emoji/railtie'
@@ -142,10 +148,11 @@ group :assets do
 end
 
 group :development do
-  gem "annotate", git: "https://github.com/ctran/annotate_models.git"
+  gem "annotate", "~> 2.6.0.beta2"
   gem "letter_opener"
   gem 'quiet_assets', '~> 1.0.1'
   gem 'rack-mini-profiler'
+
   # Better errors handler
   gem 'better_errors'
   gem 'binding_of_caller'
@@ -187,7 +194,7 @@ group :development, :test do
   gem 'rb-inotify', require: linux_only('rb-inotify')
 
   # PhantomJS driver for Capybara
-  gem 'poltergeist', '~> 1.3.0'
+  gem 'poltergeist', '~> 1.4.1'
 
   gem 'spork', '~> 1.0rc'
   gem 'jasmine'
diff --git a/Gemfile.lock b/Gemfile.lock
index e608afad1e7fa06ea6f98116e9cafb1925373c0f..ce3aeb7994b11caacd945685a478c6a0221d340a 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,17 +1,3 @@
-GIT
-  remote: https://github.com/ctran/annotate_models.git
-  revision: 18a4e2eb77c8f3ef695b563e4a7ca45dfede819b
-  specs:
-    annotate (2.6.0.beta2)
-      activerecord (>= 2.3.0)
-      rake (>= 0.8.7)
-
-GIT
-  remote: https://github.com/gitlabhq/raphael-rails.git
-  revision: cb2c92a040b9b941a5f1aa1ea866cc26e944fe58
-  specs:
-    raphael-rails (2.1.0)
-
 GEM
   remote: https://rubygems.org/
   specs:
@@ -45,17 +31,20 @@ GEM
     acts-as-taggable-on (2.4.1)
       rails (>= 3, < 5)
     addressable (2.3.4)
+    annotate (2.6.0.beta2)
+      activerecord (>= 2.3.0)
+      rake (>= 0.8.7)
     arel (3.0.2)
     asciidoctor (0.1.3)
-    awesome_print (1.1.0)
+    awesome_print (1.2.0)
     backports (3.3.2)
     bcrypt-ruby (3.1.1)
-    better_errors (0.9.0)
+    better_errors (1.0.1)
       coderay (>= 1.0.0)
       erubis (>= 2.6.6)
     binding_of_caller (0.7.2)
       debug_inspector (>= 0.0.1)
-    bootstrap-sass (2.3.2.0)
+    bootstrap-sass (2.3.2.2)
       sass (~> 3.2)
     builder (3.0.4)
     capybara (2.1.0)
@@ -78,7 +67,8 @@ GEM
       railties (>= 3.0)
       sass-rails (>= 3.2)
     chunky_png (1.2.8)
-    code_analyzer (0.3.2)
+    cliver (0.2.1)
+    code_analyzer (0.4.3)
       sexp_processor
     coderay (1.0.9)
     coffee-rails (3.2.2)
@@ -97,18 +87,18 @@ GEM
     compass-rails (1.0.3)
       compass (>= 0.12.2, < 0.14)
     connection_pool (1.1.0)
-    coveralls (0.6.7)
-      colorize
+    coveralls (0.7.0)
       multi_json (~> 1.3)
       rest-client
       simplecov (>= 0.7)
+      term-ansicolor
       thor
     crack (0.4.0)
       safe_yaml (~> 0.9.0)
     d3_rails (3.1.10)
       railties (>= 3.1.0)
     daemons (1.1.9)
-    database_cleaner (1.0.1)
+    database_cleaner (1.1.1)
     debug_inspector (0.0.2)
     descendants_tracker (0.0.1)
     devise (2.2.5)
@@ -138,9 +128,7 @@ GEM
       multipart-post (~> 1.1)
     faraday_middleware (0.9.0)
       faraday (>= 0.7.4, < 0.9)
-    faye-websocket (0.4.7)
-      eventmachine (>= 0.12.0)
-    ffaker (1.16.1)
+    ffaker (1.18.0)
     ffi (1.9.0)
     fog (1.3.1)
       builder
@@ -152,7 +140,7 @@ GEM
       net-ssh (>= 2.1.3)
       nokogiri (~> 1.5.0)
       ruby-hmac
-    font-awesome-rails (3.2.1.2)
+    font-awesome-rails (3.2.1.3)
       railties (>= 3.2, < 5.0)
     foreman (0.63.0)
       dotenv (>= 0.7)
@@ -168,6 +156,9 @@ GEM
       pygments.rb (>= 0.2.13)
     github-markdown (0.5.3)
     github-markup (0.7.5)
+    gitlab-flowdock-git-hook (0.4.2.2)
+      gitlab-grit (>= 2.4.1)
+      multi_json
     gitlab-gollum-lib (1.0.1)
       github-markdown (~> 0.5.3)
       github-markup (>= 0.7.5, < 1.0.0)
@@ -186,7 +177,7 @@ GEM
     gitlab-pygments.rb (0.3.2)
       posix-spawn (~> 0.3.6)
       yajl-ruby (~> 1.1.0)
-    gitlab_git (2.1.1)
+    gitlab_git (3.0.0.beta1)
       activesupport (~> 3.2.13)
       github-linguist (~> 2.3.4)
       gitlab-grit (~> 2.6.0)
@@ -281,11 +272,11 @@ GEM
       mime-types (~> 1.16)
       treetop (~> 1.4.8)
     method_source (0.8.1)
-    mime-types (1.23)
+    mime-types (1.25)
     minitest (4.7.4)
     modernizr (2.6.2)
       sprockets (~> 2.0)
-    multi_json (1.7.9)
+    multi_json (1.8.0)
     multi_xml (0.5.4)
     multipart-post (1.2.0)
     mysql2 (0.3.11)
@@ -321,10 +312,11 @@ GEM
       omniauth-oauth (~> 1.0)
     orm_adapter (0.4.0)
     pg (0.15.1)
-    poltergeist (1.3.0)
+    poltergeist (1.4.1)
       capybara (~> 2.1.0)
-      faye-websocket (>= 0.4.4, < 0.5.0)
-      http_parser.rb (~> 0.5.3)
+      cliver (~> 0.2.1)
+      multi_json (~> 1.0)
+      websocket-driver (>= 0.2.0)
     polyglot (0.3.3)
     posix-spawn (0.3.6)
     pry (0.9.12.2)
@@ -340,9 +332,11 @@ GEM
     rack (1.4.5)
     rack-accept (0.4.5)
       rack (>= 0.4)
+    rack-attack (2.2.1)
+      rack
     rack-cache (1.2)
       rack (>= 0.4)
-    rack-mini-profiler (0.1.26)
+    rack-mini-profiler (0.1.31)
       rack (>= 1.1.3)
     rack-mount (0.8.3)
       rack (>= 1.0.0)
@@ -363,13 +357,14 @@ GEM
     rails-dev-tweaks (0.6.1)
       actionpack (~> 3.1)
       railties (~> 3.1)
-    rails_best_practices (1.13.8)
+    rails_best_practices (1.14.4)
       activesupport
       awesome_print
-      code_analyzer
+      code_analyzer (>= 0.4.3)
       colored
       erubis
       i18n
+      require_all
       ruby-progressbar
     railties (3.2.13)
       actionpack (= 3.2.13)
@@ -380,6 +375,7 @@ GEM
       thor (>= 0.14.6, < 2.0)
     raindrops (0.11.0)
     rake (10.1.0)
+    raphael-rails (2.1.2)
     rb-fsevent (0.9.3)
     rb-inotify (0.9.0)
       ffi (>= 0.5.0)
@@ -408,6 +404,7 @@ GEM
     redis-store (1.1.4)
       redis (>= 2.2)
     ref (1.0.5)
+    require_all (1.3.1)
     rest-client (1.6.7)
       mime-types (>= 1.16)
     rspec (2.13.0)
@@ -426,13 +423,13 @@ GEM
       rspec-expectations (~> 2.13.0)
       rspec-mocks (~> 2.13.0)
     ruby-hmac (0.4.0)
-    ruby-progressbar (1.1.1)
+    ruby-progressbar (1.2.0)
     rubyntlm (0.1.1)
     rubyzip (0.9.9)
     safe_yaml (0.9.3)
     sanitize (2.0.3)
       nokogiri (>= 1.4.4, < 1.6)
-    sass (3.2.9)
+    sass (3.2.11)
     sass-rails (3.2.6)
       railties (~> 3.2.0)
       sass (>= 3.1.10)
@@ -452,7 +449,7 @@ GEM
       rubyzip
       websocket (~> 1.0.4)
     settingslogic (2.0.9)
-    sexp_processor (4.2.1)
+    sexp_processor (4.3.0)
     shoulda-matchers (2.1.0)
       activesupport (>= 3.0.0)
     sidekiq (2.14.0)
@@ -492,7 +489,9 @@ GEM
     state_machine (1.2.0)
     stringex (1.5.1)
     temple (0.6.5)
-    test_after_commit (0.2.0)
+    term-ansicolor (1.2.2)
+      tins (~> 0.8)
+    test_after_commit (0.2.1)
     therubyracer (0.11.4)
       libv8 (~> 3.11.8.12)
       ref
@@ -512,6 +511,7 @@ GEM
       mime-types (~> 1.19)
       multi_json (~> 1.5)
       twitter-stream (~> 0.1)
+    tins (0.11.0)
     treetop (1.4.14)
       polyglot
       polyglot (>= 0.3.1)
@@ -539,6 +539,7 @@ GEM
       addressable (>= 2.2.7)
       crack (>= 0.3.2)
     websocket (1.0.7)
+    websocket-driver (0.3.0)
     xpath (2.0.0)
       nokogiri (~> 1.3)
     yajl-ruby (1.1.0)
@@ -548,7 +549,7 @@ PLATFORMS
 
 DEPENDENCIES
   acts-as-taggable-on
-  annotate!
+  annotate (~> 2.6.0.beta2)
   asciidoctor
   awesome_print
   better_errors
@@ -573,10 +574,11 @@ DEPENDENCIES
   gemoji (~> 1.2.1)
   github-linguist
   github-markup (~> 0.7.4)
+  gitlab-flowdock-git-hook (~> 0.4.2)
   gitlab-gollum-lib (~> 1.0.1)
   gitlab-grack (~> 1.0.1)
   gitlab-pygments.rb (~> 0.3.2)
-  gitlab_git (= 2.1.1)
+  gitlab_git (~> 3.0.0.beta1)
   gitlab_meta (= 6.0)
   gitlab_omniauth-ldap (= 1.0.3)
   gon
@@ -604,14 +606,15 @@ DEPENDENCIES
   omniauth-google-oauth2
   omniauth-twitter
   pg
-  poltergeist (~> 1.3.0)
+  poltergeist (~> 1.4.1)
   pry
   quiet_assets (~> 1.0.1)
+  rack-attack
   rack-mini-profiler
   rails (= 3.2.13)
   rails-dev-tweaks
   rails_best_practices
-  raphael-rails!
+  raphael-rails (~> 2.1.2)
   rb-fsevent
   rb-inotify
   redcarpet (~> 2.2.2)
diff --git a/PROCESS.md b/PROCESS.md
index 17684ae5c7134b44dd054bf5bea3e7378897af76..668cacc870a3e6110d5d49c15f5aae9f2c94b5a5 100644
--- a/PROCESS.md
+++ b/PROCESS.md
@@ -2,23 +2,47 @@
 
 ## Purpose of describing the contributing process
 
-Below we describe the contributing process for two reasons. Contributors know what to expect from maintainers (initial, response within xx days, friendly treatment, etc). And maintainers know what to expect from contributors (use latest version, confirm the issue is addressed, friendly treatment, etc).
+Below we describe the contributing process to GitLab for two reasons. So that contributors know what to expect from maintainers (possible responses, friendly treatment, etc.). And so that maintainers know what to expect from contributors (use the latest version, ensure that the issue is addressed, friendly treatment, etc.).
 
-## How we handle issues
+## Common actions
+
+### Issue team
+- Looks for issues without workflow labels and triages issue
+- Monitors pull requests
+- Closes invalid issues and pull requests with a comment (duplicates, [feature requests](#feature-requests), [fixed in newer version](#issue-fixed-in-newer-version), [issue report for old version](#issue-report-for-old-version), not a problem in GitLab, etc.)
+- Assigns appropriate [labels](#how-we-handle-issues)
+- Asks for feedback from issue reporter/pull request initiator ([invalid issue reports](#improperly-formatted-issue), [format code](#code-format), etc.)
+- Asks for feedback from the relevant developer(s) based on the [list of members and their specialities](http://gitlab.org/team/)
+- Monitors all issues/pull requests for feedback (but especially ones commented on since automatically watching them):
+- Closes issues with no feedback from the reporter for two weeks
+- Closes stale pull requests
 
-The priority should be mentioning people that can help and assigning workflow labels. Workflow labels are purposely not very detailed since that would be hard to keep updated as you would need to reevaluate them after every comment. We optionally use functional labels on demand when want to group related issues to get an overview (for example all issues related to RVM, to tackle them in one go) and to add details to the issue. 
+### Development team
+
+- Responds to issues and pull requests the issue team mentions them in
+- Monitors for new issues in _Awaiting developer action/feedback_ with no developer activity (once a week)
+- Monitors for new pull requests (at least once a week)
+- Manages their work queue by looking at issues and pull requests assigned to them
+- Close fixed issues (via commit messages or manually)
+- Codes [new features](http://feedback.gitlab.com/forums/176466-general/filters/top)!
+- Response guidelines
+- Be kind to people trying to contribute. Be aware that people can be a non-native or a native English speaker, they might not understand thing or they might be very sensitive to how your word things. Use emoji to express your feelings (heart, star, smile, etc.). Some good tips about giving feedback to pull requests is in the [Thoughtbot code review guide](https://github.com/thoughtbot/guides/tree/master/code-review).
 
-If an issue is complex and needs the attention of a specific person, assignment is a good option but assigning issues might discourage other people from contributing to that issue. We need all the contributions we can get so this should never be discouraged. Also, an assigned person might not have time for a few weeks, so others should feel free to takeover. 
+## Priorities of the issue team
 
-Priority (from high to low):
+1. Mentioning people (critical)
+2. Workflow labels (normal)
+3. Functional labels (minor)
+4. Assigning issues (avoid if possible)
 
-1. Mentioning people (very important)
-2. Workflow labels
-3. Functional labels (less important)
-4. Assigning issues (optional)
+## Mentioning people
+
+The most important thing is making sure valid issues receive feedback from the development team. Therefore the priority is mentioning developers that can help on those issue. Please select someone with relevant experience from [GitLab core team](http://gitlab.org/team/). If there is nobody mentioned with that expertise look in the commit history for the affected files to find someone. Avoid mentioning the lead developer, this is the person that is least likely to give a timely response. If the involvement of the lead developer is needed the other core team members will mention this person.
 
 ## Workflow labels
 
+Workflow labels are purposely not very detailed since that would be hard to keep updated as you would need to reevaluate them after every comment. We optionally use functional labels on demand when want to group related issues to get an overview (for example all issues related to RVM, to tackle them in one go) and to add details to the issue. 
+
 - _Awaiting feedback_: Feedback pending from the reporter
 - _Awaiting confirmation of fix_: The issue should already be solved in **master** (generally you can avoid this workflow item and just close the issue right away)
 - _Attached PR_: There is a PR attached and the discussion should happen there
@@ -29,6 +53,10 @@ Priority (from high to low):
 
 These labels describe what development specialities are involved such as: PostgreSQL, UX, LDAP.
 
+## Assigning issues
+
+If an issue is complex and needs the attention of a specific person, assignment is a good option but assigning issues might discourage other people from contributing to that issue. We need all the contributions we can get so this should never be discouraged. Also, an assigned person might not have time for a few weeks, so others should feel free to takeover.
+
 ## Label colors
 - Light orange `#fef2c0`: workflow labels for issue team members (awaiting feedback, awaiting confirmation of fix)
 - Bright orange `#eb6420`: workflow labels for core team members (attached PR, awaiting developer action/feedback)
@@ -37,32 +65,6 @@ These labels describe what development specialities are involved such as: Postgr
   - Feature request (see copy & paste response: [Feature requests](#feature-requests))
   - Support (see copy & paste response: [Support requests and configuration questions](#support-requests-and-configuration-questions)
 
-## Common actions
-
-### Issue team
-- Looks for issues without workflow labels and triages issue
-- Monitors pull requests
-- Closes invalid issues and pull requests with a comment (duplicates, [feature requests](#feature-requests), [fixed in newer version](#issue-fixed-in-newer-version), [issue report for old version](#issue-report-for-old-version), not a problem in GitLab, etc.)
-- Assigns appropriate [labels](#how-we-handle-issues)
-- Asks for feedback from issue reporter/pull request initiator ([invalid issue reports](#improperly-formatted-issue), [format code](#code-format), etc.)
-- Asks for feedback from the relevant developer(s) based on the [list of members and their specialities](http://gitlab.org/team/)
-- Monitors all issues/pull requests for feedback (but especially ones commented on since automatically watching them):
-- Assigns issues to developers if they indicate they are fixing it
-- Assigns pull requests to developers if they indicate they will take care of merge
-- Closes issues with no feedback from the reporter for two weeks
-- Closes stale pull requests
-
-### Development team
-
-- Responds to issues and pull requests the issue team mentions them in
-- Monitors for new issues in _Awaiting developer action/feedback_ with no developer activity (once a week)
-- Monitors for new pull requests (at least once a week)
-- Manages their work queue by looking at issues and pull requests assigned to them
-- Close fixed issues (via commit messages or manually)
-- Codes [new features](http://feedback.gitlab.com/forums/176466-general/filters/top)!
-- Response guidelines
-- Be kind to people trying to contribute. Be aware that people can be a non-native or a native English speaker, they might not understand thing or they might be very sensitive to how your word things. Use emoji to express your feelings (hearth, star, smile, etc.). Some good tips about giving feedback to pull requests is in the [Thoughtbot code review guide](https://github.com/thoughtbot/guides/tree/master/code-review).
-
 ## Copy & paste responses
 
 ### Improperly formatted issue
diff --git a/README.md b/README.md
index 19e7cbaad687b2a9e3b4455f913bebb0bea50d4f..b1c109950a0cdb7ee9c90e949c1706c5ef49e6fc 100644
--- a/README.md
+++ b/README.md
@@ -20,8 +20,6 @@
 
 * [![build status](http://ci.gitlab.org/projects/1/status.png?ref=master)](http://ci.gitlab.org/projects/1?ref=master) on ci.gitlab.org (master branch)
 
-* [![build status](https://secure.travis-ci.org/gitlabhq/gitlabhq.png)](https://travis-ci.org/gitlabhq/gitlabhq) on travis-ci.org (master branch)
-
 * [![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.png)](https://codeclimate.com/github/gitlabhq/gitlabhq)
 
 * [![Dependency Status](https://gemnasium.com/gitlabhq/gitlabhq.png)](https://gemnasium.com/gitlabhq/gitlabhq) this button can be yellow (small updates are available) but must not be red (a security fix or an important update is available), gems are updated in major releases of GitLab.
@@ -39,11 +37,10 @@
 ### Requirements
 
 * Ubuntu/Debian**
-* ruby 1.9.3
+* ruby 1.9.3+
+* git 1.7.10+
+* redis 2.0+
 * MySQL or PostgreSQL
-* git
-* gitlab-shell
-* redis
 
 ** More details are in the [requirements doc](doc/install/requirements.md)
 
@@ -80,7 +77,7 @@ Since 2011 GitLab is released on the 22nd of every month. Every new release incl
 
 * [Changelog](CHANGELOG)
 
-* Features that will be in the next releases are listed on [the feedback and suggestions forum](http://feedback.gitlab.com/forums/176466-general) with the status ["started"](http://feedback.gitlab.com/forums/176466-general/status/796456) and [completed](http://feedback.gitlab.com/forums/176466-general/status/796457).
+* Features that will be in the next releases are listed on [the feedback and suggestions forum](http://feedback.gitlab.com/forums/176466-general) with the status [started](http://feedback.gitlab.com/forums/176466-general/status/796456) and [completed](http://feedback.gitlab.com/forums/176466-general/status/796457).
 
 
 ### Run in production mode
@@ -130,14 +127,17 @@ or start each component separately
 
 ### GitLab interfaces
 
-* [GitLab API](doc/api/README.md)
+* [GitLab API doc](doc/api/README.md) or see the [GitLab API website](http://api.gitlab.org/)
 
-* [Rake tasks](doc/raketasks)
+* [Rake tasks](doc/raketasks) including a [backup and restore procedure](doc/raketasks/backup_restore.md)
 
 * [Directory structure](doc/install/structure.md)
 
-* [Databases](doc/install/databases.md)
+* [Database installation](doc/install/databases.md)
+
+* [Markdown specification](doc/markdown/markdown.md)
 
+* [Security guide](doc/security/rack_attack.md) to throttle abusive requests
 
 ### Getting help
 
@@ -160,10 +160,8 @@ or start each component separately
 
 ### Getting in touch
 
-* [Core team](https://github.com/gitlabhq?tab=members)
-
-* [Contributors](https://github.com/gitlabhq/gitlabhq/graphs/contributors)
+* [Core team](http://gitlab.org/team/)
 
-* [Leader](https://github.com/randx)
+* [Contributors](http://contributors.gitlab.org/)
 
-* [Contact page](http://gitlab.org/contact/)
+* [Community](http://gitlab.org/community/)
diff --git a/VERSION b/VERSION
index ce3de5830655bb4531bb4844edd62493d0404e49..79e046f49a5ed42b0fedcf1b17a2b1927015a6e0 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-6.1.0.pre
+6.2.0.pre
diff --git a/app/assets/images/login-logo.png b/app/assets/images/login-logo.png
deleted file mode 100644
index a61c41303c4d6a13cfd9cbd762bff96820233299..0000000000000000000000000000000000000000
Binary files a/app/assets/images/login-logo.png and /dev/null differ
diff --git a/app/assets/javascripts/api.js.coffee b/app/assets/javascripts/api.js.coffee
index db80e7b0f3cd5c92e0f45d9bc583c29e7dd3458e..a36d944cbcb6f9d9f31372abe516b529a6c5a1ad 100644
--- a/app/assets/javascripts/api.js.coffee
+++ b/app/assets/javascripts/api.js.coffee
@@ -3,12 +3,12 @@
   user_path: "/api/:version/users/:id.json"
   notes_path: "/api/:version/projects/:id/notes.json"
 
-  # Get 20 (depends on api) recent notes 
+  # Get 20 (depends on api) recent notes
   # and sort the ascending from oldest to newest
   notes: (project_id, callback) ->
     url = Api.buildUrl(Api.notes_path)
     url = url.replace(':id', project_id)
-    
+
     $.ajax(
       url: url,
       data:
@@ -37,7 +37,7 @@
   # Only active users retrieved
   users: (query, callback) ->
     url = Api.buildUrl(Api.users_path)
-    
+
     $.ajax(
       url: url
       data:
diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee
index c8ddbed5097d69bee8d48654571672e4103a1dcd..e264e281309eea1c2b01f38ef26eb0274dc968a3 100644
--- a/app/assets/javascripts/dispatcher.js.coffee
+++ b/app/assets/javascripts/dispatcher.js.coffee
@@ -18,6 +18,8 @@ class Dispatcher
     switch page
       when 'projects:issues:index'
         Issues.init()
+      when 'projects:issues:new', 'projects:merge_requests:new'
+        GitLab.GfmAutoComplete.setup()
       when 'dashboard:show'
         new Dashboard()
         new Activities()
diff --git a/app/assets/javascripts/merge_requests.js.coffee b/app/assets/javascripts/merge_requests.js.coffee
index 153198ca5c5cfd8f701aa5b39074e277cb1d5aec..5400bc5c1ad08199d92e0007f2ec785307593bbe 100644
--- a/app/assets/javascripts/merge_requests.js.coffee
+++ b/app/assets/javascripts/merge_requests.js.coffee
@@ -11,7 +11,7 @@ class MergeRequest
 
   constructor: (@opts) ->
     this.$el = $('.merge-request')
-    @diffs_loaded = false
+    @diffs_loaded = if @opts.action == 'diffs' then true else false
     @commits_loaded = false
 
     this.activateTab(@opts.action)
diff --git a/app/assets/javascripts/project.js.coffee b/app/assets/javascripts/project.js.coffee
index 780292daa11b6bbc0814df40548393efd0f293e4..83236b348147a59cedccbc720d517f41c6749041 100644
--- a/app/assets/javascripts/project.js.coffee
+++ b/app/assets/javascripts/project.js.coffee
@@ -35,6 +35,7 @@ $ ->
       $('a, button', scope).removeClass 'active'
       $(@).addClass 'active'
       $('#project_clone', scope).val $(@).data 'clone'
+      $(".clone").text("").append 'git remote add origin ' + $(@).data 'clone'
 
   # Ref switcher
   $('.project-refs-select').on 'change', ->
diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss
index 66cc2ffc92df953760b16b8a0e0e38b2b80ee8d7..1572227ec3a5b7fa3af9794717c4ef34ab64d2dd 100644
--- a/app/assets/stylesheets/common.scss
+++ b/app/assets/stylesheets/common.scss
@@ -373,3 +373,17 @@ table {
     text-align: center;
   }
 }
+
+.dashboard-intro-icon {
+  float: left;
+  font-size: 32px;
+  color: #AAA;
+  padding: 5px 0;
+  width: 50px;
+  min-height: 100px;
+}
+
+.navbar-gitlab .navbar-inner .nav > li .btn-sign-in {
+  @extend .btn-new;
+  padding: 5px 15px;
+}
diff --git a/app/assets/stylesheets/gitlab_bootstrap.scss b/app/assets/stylesheets/gitlab_bootstrap.scss
index 1b24683fd978ae41b018557f8933934784f14868..faf36b702c080ea02964966bac06d00f93da1679 100644
--- a/app/assets/stylesheets/gitlab_bootstrap.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap.scss
@@ -62,6 +62,5 @@ $baseLineHeight: 18px !default;
 @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";
 @import "gitlab_bootstrap/forms.scss";
diff --git a/app/assets/stylesheets/gitlab_bootstrap/files.scss b/app/assets/stylesheets/gitlab_bootstrap/files.scss
index a0d6682eb8f13f9ec513ad103ab81757df51c68d..a286e530cd6025a1b958c7c24ba98d0cd887c52a 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/files.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/files.scss
@@ -6,6 +6,10 @@
   border: 1px solid #CCC;
   margin-bottom: 1em;
 
+  table {
+    @extend .table;
+  }
+
   .file-title {
     border-bottom: 1px solid #bbb;
     @include bg-dark-gray-gradient;
@@ -65,6 +69,12 @@
 
     }
 
+    &.blob-no-preview {
+      background: #eee;
+      text-shadow: 0 1px 2px #FFF;
+      padding: 100px 0;
+    }
+
     /**
      *  Blame file
      */
diff --git a/app/assets/stylesheets/gitlab_bootstrap/forms.scss b/app/assets/stylesheets/gitlab_bootstrap/forms.scss
index 020a0bf7fd567bf067f31c1998de216241c52748..a2612166c7858f6feedb29af472bb794ead65edc 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/forms.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/forms.scss
@@ -6,10 +6,9 @@ form {
   }
 }
 
-input {
-  &.input-xpadding {
-    padding: 6px 10px;
-  }
+input.input-xpadding,
+.add-on.input-xpadding {
+  padding: 6px 10px;
 }
 
 .control-group {
diff --git a/app/assets/stylesheets/gitlab_bootstrap/mixins.scss b/app/assets/stylesheets/gitlab_bootstrap/mixins.scss
index e7daf8f43b42d47a196fab20e347ee14a6ce5f9a..8b975a12cf75f25e990e31e7ca417ec0ec3ff24e 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/mixins.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/mixins.scss
@@ -95,6 +95,14 @@
     font-size: 14px;
     line-height: 1.5;
   }
+
+  table {
+    @extend .table;
+    @extend .table-bordered;
+    th {
+      background: #EEE;
+    }
+  }
 }
 
 @mixin page-title {
diff --git a/app/assets/stylesheets/gitlab_bootstrap/tables.scss b/app/assets/stylesheets/gitlab_bootstrap/tables.scss
deleted file mode 100644
index a1a5139cda9b0139282dc1d80a887f5187e48a85..0000000000000000000000000000000000000000
--- a/app/assets/stylesheets/gitlab_bootstrap/tables.scss
+++ /dev/null
@@ -1,68 +0,0 @@
-table {
-  @extend .table;
-  @extend .table-striped;
-  border: 1px solid #CCC;
-  width: 100%;
-
-  &.low {
-    td {
-      line-height: 18px;
-    }
-  }
-
-  &.headless {
-    tr:first-child td{
-      border-top: 1px solid #CCC;
-    }
-  }
-
-  th {
-    font-weight: bold;
-    vertical-align: middle;
-    border-bottom: 1px solid #CCC;
-    text-shadow: 0 1px 1px #fff;
-    @include bg-dark-gray-gradient;
-
-    ul.nav {
-      text-shadow: none;
-      margin: 0;
-    }
-  }
-
-  th, td {
-    padding: 10px;
-    line-height: 18px;
-    text-align: left;
-  }
-
-  td {
-    border-color: #f1f1f1;
-    line-height: 28px;
-
-    .s16 {
-      margin-top: 5px;
-      margin-right: 5px;
-    }
-
-    &:first-child {
-      border-left: 1px solid #CCC;
-    }
-
-    &:last-child {
-      border-right: 1px solid #CCC;
-    }
-  }
-
-  &.bordered {
-    @extend .table-bordered;
-  }
-
-  &.lite {
-    border: none;
-    box-shadow: none;
-    tr, td {
-      border: none;
-      background:none !important;
-    }
-  }
-}
diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss
index faae0e127d971c23d8aad01d485b9b9ef0d750c4..be6fb29c817630852410d1e6a0af754e05b2c9f2 100644
--- a/app/assets/stylesheets/sections/commits.scss
+++ b/app/assets/stylesheets/sections/commits.scss
@@ -67,6 +67,7 @@
     }
 
     table {
+      width: 100%;
       font-family: $monospace_font;
       border: none;
       margin: 0px;
@@ -345,37 +346,6 @@
 }
 
 
-/**
- * COMMIT ROW
- */
-.commit {
-  .browse_code_link_holder {
-    float: right;
-  }
-
-  .committed_ago {
-    float: right;
-    @extend .cgray;
-  }
-
-  .notes_count {
-    float: right;
-    margin-right: 10px;
-  }
-
-  code {
-    background: #FCEEC1;
-    color: $style_color;
-  }
-
-  .commit_short_id {
-    float: left;
-    @extend .lined;
-    min-width: 65px;
-    font-family: $monospace_font;
-  }
-}
-
 .file-stats a {
   color: $style_color;
 }
@@ -463,24 +433,6 @@
   line-height: 2;
 }
 
-li.commit {
-  .avatar {
-    width: 24px;
-    top:-5px;
-    margin-right: 5px;
-    margin-left: 10px;
-  }
-
-  code {
-    padding: 2px 2px 0;
-    margin-top: -2px;
-    &:hover {
-      color: black;
-      border: 1px solid #ccc;
-    }
-  }
-}
-
 .commit-breadcrumb {
   padding: 0;
 }
@@ -496,3 +448,61 @@ li.commit {
     font-weight: bold;
   }
 }
+
+.lists-separator {
+  margin: 10px 0;
+  border-top: 1px dashed #CCC;
+}
+
+/**
+ * COMMIT ROW
+ */
+li.commit {
+  padding: 8px;
+
+  .commit-row-title {
+    font-size: 14px;
+    margin-bottom: 2px;
+
+    .notes_count {
+      float: right;
+      margin-right: 10px;
+    }
+
+    .commit_short_id {
+      min-width: 65px;
+      font-family: $monospace_font;
+    }
+
+    .commit-row-message {
+      color: #555;
+      font-weight: bolder;
+      &:hover {
+        color: #444;
+        text-decoration: underline;
+      }
+    }
+  }
+
+  .commit-row-info {
+    a {
+      color: #777;
+    }
+
+    .committed_ago {
+      float: right;
+      @extend .cgray;
+    }
+  }
+
+  &.inline-commit {
+    .commit-row-title {
+      font-size: 13px;
+    }
+
+    .committed_ago {
+      float: right;
+      @extend .cgray;
+    }
+  }
+}
\ No newline at end of file
diff --git a/app/assets/stylesheets/sections/dashboard.scss b/app/assets/stylesheets/sections/dashboard.scss
index 15bfad96f6c85de4abc83f60cf5cc0293f01c726..3f7825d71ce43cc88cb0c2ba854e4dc78af7f477 100644
--- a/app/assets/stylesheets/sections/dashboard.scss
+++ b/app/assets/stylesheets/sections/dashboard.scss
@@ -66,7 +66,7 @@
 }
 
 .project-row, .group-row {
-  padding: 12px 15px !important;
+  padding: 10px 15px !important;
 
   .namespace-name {
     color: #666;
@@ -77,7 +77,6 @@
     font-size: 16px;
   }
 
-
   .arrow {
     float: right;
     padding: 10px 5px;
@@ -86,12 +85,18 @@
     color: #666;
   }
 
-  .last-activity, .owner-info {
+  .last-activity {
     color: #AAA;
     display: block;
     margin-top: 5px;
-    .date, .owner {
+    .date {
       color: #777;
     }
   }
 }
+
+.group-row {
+  .arrow {
+    padding: 2px 5px;
+  }
+}
diff --git a/app/assets/stylesheets/sections/events.scss b/app/assets/stylesheets/sections/events.scss
index 80ee6b6323c76cad5ccb19d17e5f4f080395fb7b..39b2ad7a09cdf1deacee5b8aa1f9b701797b656d 100644
--- a/app/assets/stylesheets/sections/events.scss
+++ b/app/assets/stylesheets/sections/events.scss
@@ -46,8 +46,8 @@
   border-bottom: 1px solid #eee;
   .event-title {
     color: #333;
-    font-weight: bold;
-    font-size: 14px;
+    font-weight: normal;
+    font-size: 15px;
     .author_name {
       color: #333;
     }
@@ -56,10 +56,6 @@
     margin-left: 35px;
     margin-right: 100px;
 
-    .commit p {
-      color: #666;
-      padding-top: 5px;
-    }
     .event-info {
       color: #666;
     }
@@ -107,13 +103,6 @@
     }
   }
 
-  ul {
-    .avatar {
-      width: 18px;
-      margin: 2px 4px;
-    }
-  }
-
   &:last-child { border:none }
 
   .event_commits {
@@ -124,12 +113,14 @@
         background: transparent;
         padding: 3px;
         border: none;
-        font-size: 12px;
+        color: #666;
+        .commit-row-title {
+          font-size: 12px;
+        }
       }
       &.commits-stat {
         display: block;
         padding: 3px;
-        margin-top: 3px;
 
         &:hover {
           background: none;
diff --git a/app/assets/stylesheets/sections/login.scss b/app/assets/stylesheets/sections/login.scss
index 8d9fd037bce2118362035dcb6822780108815ecc..33bef59c089d9b0a2889d26f28cb527a84e3acfc 100644
--- a/app/assets/stylesheets/sections/login.scss
+++ b/app/assets/stylesheets/sections/login.scss
@@ -1,7 +1,8 @@
 /* Login Page */
 body.login-page{
-  background: #474D57;
-  .container .content { padding-top: 4%; }
+  .container > .content {
+    padding-top: 20px;
+  }
 }
 
 .login-box{
diff --git a/app/assets/stylesheets/sections/merge_requests.scss b/app/assets/stylesheets/sections/merge_requests.scss
index bdab306a57d172ad79e2522bb1867da456ef78bc..aa61cae4b9a02d6cca0eae422aafc1a4cd17e18c 100644
--- a/app/assets/stylesheets/sections/merge_requests.scss
+++ b/app/assets/stylesheets/sections/merge_requests.scss
@@ -64,13 +64,6 @@
     margin: 0;
     padding: 0;
     padding: 5px 0;
-    .avatar { position:relative }
-    .commit-author-name,
-    .dash,
-    .committed_ago,
-    .browse_code_link_holder {
-      display: none;
-    }
     list-style: none;
     &:hover {
       background: none;
@@ -117,7 +110,7 @@
 
 .merge-request-angle {
   text-align: center;
-  margin-top: 45px;
+  margin: 0;
 }
 
 .merge-request-form-info {
diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss
index bae1ac3aa9a91023578c4bb83990025cc8b3e736..94b9ca3b181722e8ef03fbd217d97631d6a6b8aa 100644
--- a/app/assets/stylesheets/sections/notes.scss
+++ b/app/assets/stylesheets/sections/notes.scss
@@ -135,11 +135,15 @@ ul.notes {
       background-color: $white;
       border-width: 1px 0;
       padding-top: 0;
+
+      li {
+        padding: 5px;
+      }
     }
   }
 
   .reply-btn {
-    margin-top: 8px;
+    margin: 5px;
   }
 }
 
diff --git a/app/assets/stylesheets/sections/projects.scss b/app/assets/stylesheets/sections/projects.scss
index 9c079bbb9ff111235fbb5635e0cbbb779958006c..0491b68db57ddcdda5d34d89e7e72670abae4227 100644
--- a/app/assets/stylesheets/sections/projects.scss
+++ b/app/assets/stylesheets/sections/projects.scss
@@ -36,6 +36,12 @@
   }
 }
 
+.project-public-holder {
+  .help-inline {
+    padding-top: 7px;
+  }
+}
+
 .save-project-loader {
   img {
     margin-top: 50px;
@@ -73,21 +79,6 @@ ul.nav.nav-projects-tabs {
   margin: 0px;
 }
 
-.public-projects {
-  li {
-    .project-title {
-      font-size: 14px;
-      line-height: 2;
-      font-weight: normal;
-    }
-
-    .description {
-      margin-left: 15px;
-      color: #aaa;
-    }
-  }
-}
-
 .my-projects {
   li {
     .project-title {
@@ -104,7 +95,6 @@ ul.nav.nav-projects-tabs {
   }
 }
 
-
 .public-clone {
   background: #333;
   color: #f5f5f5;
@@ -117,3 +107,11 @@ ul.nav.nav-projects-tabs {
   position: relative;
   top: -5px;
 }
+
+.public-projects .repo-info {
+  color: #777;
+
+  a {
+    color: #777;
+  }
+}
diff --git a/app/assets/stylesheets/sections/tree.scss b/app/assets/stylesheets/sections/tree.scss
index b8b82bcf68c6bb2bf849512b03a52cceaa3915f5..96f2a5711fa139749fbda31aaa823dbbae66a0cf 100644
--- a/app/assets/stylesheets/sections/tree.scss
+++ b/app/assets/stylesheets/sections/tree.scss
@@ -13,8 +13,22 @@
   }
 
   .tree-table {
+    @extend .table;
     @include border-radius(0);
-    .tree-item {
+
+    tr {
+      td, th {
+        padding: 8px 10px;
+        line-height: 20px;
+      }
+      th {
+        font-weight: normal;
+        font-size: 15px;
+        border-bottom: 1px solid #CCC;
+      }
+      td {
+        border-color: #F1F1F1;
+      }
       &:hover {
         td {
           background: $hover;
@@ -23,12 +37,11 @@
         }
         cursor: pointer;
       }
-
       &.selected {
         td {
-          background: $hover;
-          border-top: 1px solid #ADF;
-          border-bottom: 1px solid #ADF;
+          background: #f5f5f5;
+          border-top: 1px solid #EEE;
+          border-bottom: 1px solid #EEE;
         }
       }
     }
@@ -50,24 +63,8 @@
     }
   }
 
-  .tree-table {
-    th .btn {
-      margin: -2px -1px;
-      padding: 2px 10px;
-    }
-    td {
-      line-height: 20px;
-      background: #fafafa;
-    }
-  }
-
   .tree_author {
     padding-right: 8px;
-
-    img.avatar {
-      margin-top: 0;
-      width: 16px;
-    }
   }
 
   .tree_commit {
diff --git a/app/contexts/commit_load_context.rb b/app/contexts/commit_load_context.rb
index 2cf5420d62dae3900dc935f6bf546559d696ae58..2930c5b1668f1124f676fe4a630b08b71183b592 100644
--- a/app/contexts/commit_load_context.rb
+++ b/app/contexts/commit_load_context.rb
@@ -20,7 +20,8 @@ class CommitLoadContext < BaseContext
       result[:notes_count] = project.notes.for_commit_id(commit.id).count
 
       begin
-        result[:suppress_diff] = true if commit.diffs.size > Commit::DIFF_SAFE_SIZE && !params[:force_show_diff]
+        result[:suppress_diff] = true if commit.diff_suppress? && !params[:force_show_diff]
+        result[:force_suppress_diff] = commit.diff_force_suppress?
       rescue Grit::Git::GitTimeout
         result[:suppress_diff] = true
         result[:status] = :huge_commit
diff --git a/app/contexts/projects/create_context.rb b/app/contexts/projects/create_context.rb
index 1ee3e45907464a0df5269ec485deefbe996bb8a0..1c60a5de141afa8e344b516b57cf0ca8967ab67d 100644
--- a/app/contexts/projects/create_context.rb
+++ b/app/contexts/projects/create_context.rb
@@ -16,8 +16,9 @@ module Projects
         wiki_enabled: default_features.wiki,
         wall_enabled: default_features.wall,
         snippets_enabled: default_features.snippets,
-        merge_requests_enabled: default_features.merge_requests
-      }
+        merge_requests_enabled: default_features.merge_requests,
+        public: default_features.public
+      }.stringify_keys
 
       @project = Project.new(default_opts.merge(params))
 
diff --git a/app/contexts/search_context.rb b/app/contexts/search_context.rb
index 0817d52cd00c265207b8e2d2a833d8e184ea2eaf..48def0784fdba884f21753e954638b18046b8482 100644
--- a/app/contexts/search_context.rb
+++ b/app/contexts/search_context.rb
@@ -13,7 +13,7 @@ class SearchContext
     projects = Project.where(id: project_ids)
     result[:projects] = projects.search(query).limit(20)
 
-    # Search inside singe project
+    # Search inside single project
     project = projects.first if projects.length == 1
 
     if params[:search_code].present?
diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb
index a2201f732e6620602f09dbba54e2a598c6b143df..89b395786b316e92e4bbcdcd838e4067317ac9ec 100644
--- a/app/controllers/admin/groups_controller.rb
+++ b/app/controllers/admin/groups_controller.rb
@@ -20,9 +20,9 @@ class Admin::GroupsController < Admin::ApplicationController
   def create
     @group = Group.new(params[:group])
     @group.path = @group.name.dup.parameterize if @group.name
-    @group.owner = current_user
 
     if @group.save
+      @group.add_owner(current_user)
       redirect_to [:admin, @group], notice: 'Group was successfully created.'
     else
       render "new"
@@ -30,14 +30,7 @@ class Admin::GroupsController < Admin::ApplicationController
   end
 
   def update
-    group_params = params[:group].dup
-    owner_id =group_params.delete(:owner_id)
-
-    if owner_id
-      @group.change_owner(User.find(owner_id))
-    end
-
-    if @group.update_attributes(group_params)
+    if @group.update_attributes(params[:group])
       redirect_to [:admin, @group], notice: 'Group was successfully updated.'
     else
       render "edit"
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index 7809a157dbc5280d8e8f4e9aceee97dc79ed0ee8..70bbe306562e9035700a490f01736dd93cb191df 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -13,7 +13,7 @@ class Admin::UsersController < Admin::ApplicationController
   end
 
   def new
-    @user = User.new.with_defaults
+    @user = User.build_user
   end
 
   def edit
@@ -44,7 +44,7 @@ class Admin::UsersController < Admin::ApplicationController
       password_expires_at: Time.now
     }
 
-    @user = User.new(params[:user].merge(opts), as: :admin)
+    @user = User.build_user(params[:user].merge(opts), as: :admin)
     @user.admin = (admin && admin.to_i > 0)
     @user.created_by_id = current_user.id
 
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index b93bf0f98eba9ce18f544f687eae05f7ce26136e..d974600dcc17c66789f1f9fa90f541fada30c39c 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -151,7 +151,7 @@ class ApplicationController < ActionController::Base
   end
 
   def check_password_expiration
-    if current_user && current_user.password_expires_at && current_user.password_expires_at < Time.now
+    if current_user && current_user.password_expires_at && current_user.password_expires_at < Time.now  && !current_user.ldap_user?
       redirect_to new_profile_password_path and return
     end
   end
diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
index 33b2a5cd7e7f885d42754296f059e1d0abb4c2f1..ac319384434e66dea478489a58818c15875f8979 100644
--- a/app/controllers/dashboard_controller.rb
+++ b/app/controllers/dashboard_controller.rb
@@ -5,10 +5,14 @@ class DashboardController < ApplicationController
   before_filter :event_filter, only: :show
 
   def show
+    # Fetch only 30 projects.
+    # If user needs more - point to Dashboard#projects page
+    @projects_limit = 30
+
     @groups = current_user.authorized_groups.sort_by(&:human_name)
     @has_authorized_projects = @projects.count > 0
     @projects_count = @projects.count
-    @projects = @projects.limit(20)
+    @projects = @projects.limit(@projects_limit)
 
     @events = Event.in_projects(current_user.authorized_projects.pluck(:id))
     @events = @event_filter.apply_filter(@events)
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 3378675692a24edc09e24fd947033b8e2ae5effc..f80167da4cb5bbb5def5bed81302a0ac42738cc8 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -21,9 +21,9 @@ class GroupsController < ApplicationController
   def create
     @group = Group.new(params[:group])
     @group.path = @group.name.dup.parameterize if @group.name
-    @group.owner = current_user
 
     if @group.save
+      @group.add_owner(current_user)
       redirect_to @group, notice: 'Group was successfully created.'
     else
       render action: "new"
@@ -73,15 +73,7 @@ class GroupsController < ApplicationController
   end
 
   def update
-    group_params = params[:group].dup
-    owner_id = group_params.delete(:owner_id)
-
-    if owner_id
-      @group.owner = User.find(owner_id)
-      @group.save
-    end
-
-    if @group.update_attributes(group_params)
+    if @group.update_attributes(params[:group])
       redirect_to @group, notice: 'Group was successfully updated.'
     else
       render action: "edit"
@@ -110,7 +102,7 @@ class GroupsController < ApplicationController
 
   # Dont allow unauthorized access to group
   def authorize_read_group!
-    unless projects.present? or can?(current_user, :manage_group, @group)
+    unless projects.present? or can?(current_user, :read_group, @group)
       return render_404
     end
   end
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index c4ebf0e48896b511b7c75cec48624a90edefa685..7131e0fe181cdc86b3a57b3a2dc66ad7ff198c4f 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -16,35 +16,41 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
   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)
-    if @user.persisted?
-      @user.remember_me = true
-    end
-    sign_in_and_redirect @user
+    # We only find ourselves here
+    # if the authentication to LDAP was successful.
+    @user = Gitlab::LDAP::User.find_or_create(oauth)
+    @user.remember_me = true if @user.persisted?
+    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.extern_uid = oauth['uid']
+      current_user.provider = oauth['provider']
       current_user.save
       redirect_to profile_path
     else
-      @user = User.find_or_new_for_omniauth(oauth)
+      @user = Gitlab::OAuth::User.find(oauth)
+
+      # Create user if does not exist
+      # and allow_single_sign_on is true
+      if Gitlab.config.omniauth['allow_single_sign_on']
+        @user ||= Gitlab::OAuth::User.create(oauth)
+      end
 
       if @user
-        sign_in_and_redirect @user
+        sign_in_and_redirect(@user)
       else
         flash[:notice] = "There's no such user!"
         redirect_to new_user_session_path
       end
     end
   end
+
+  def oauth
+    @oauth ||= request.env['omniauth.auth']
+  end
 end
diff --git a/app/controllers/profiles/groups_controller.rb b/app/controllers/profiles/groups_controller.rb
index e276d07b48965f3842b14efc8a61d483104c5f3b..378ff6bcf34a978526c363921a52885ecaffd5e2 100644
--- a/app/controllers/profiles/groups_controller.rb
+++ b/app/controllers/profiles/groups_controller.rb
@@ -8,8 +8,8 @@ class Profiles::GroupsController < ApplicationController
   def leave
     @users_group = group.users_groups.where(user_id: current_user.id).first
 
-    if group.owner == current_user
-      redirect_to(profile_groups_path, alert: "You can't leave group. You must transfer it to another owner before leaving.")
+    if group.last_owner?(current_user)
+      redirect_to(profile_groups_path, alert: "You can't leave group. You must add at least one more owner to it.")
     else
       @users_group.destroy
       redirect_to(profile_groups_path, info: "You left #{group.name} group.")
diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb
index 6fa635d0e365a8999bb6800f6bd41f5d3f2c1af3..75f12f8a6af8621ebdfc193d42353fed62909860 100644
--- a/app/controllers/profiles_controller.rb
+++ b/app/controllers/profiles_controller.rb
@@ -33,9 +33,16 @@ class ProfilesController < ApplicationController
   end
 
   def update_password
-    params[:user].reject!{ |k, v| k != "password" && k != "password_confirmation"}
+    password_attributes = params[:user].select do |key, value|
+      %w(password password_confirmation).include?(key.to_s)
+    end
 
-    if @user.update_attributes(params[:user])
+    unless @user.valid_password?(params[:user][:current_password])
+      redirect_to account_profile_path, alert: 'You must provide a valid current password'
+      return
+    end
+
+    if @user.update_attributes(password_attributes)
       flash[:notice] = "Password was successfully updated. Please login with it"
       redirect_to new_user_session_path
     else
diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb
index 1f2a75175cf83b852525f9021af37244767e2231..8fd4565f3677fedeafd08578ef4acb365352f62d 100644
--- a/app/controllers/projects/application_controller.rb
+++ b/app/controllers/projects/application_controller.rb
@@ -1,5 +1,26 @@
 class Projects::ApplicationController < ApplicationController
   before_filter :project
   before_filter :repository
-  layout 'projects'
+  layout :determine_layout
+
+  def authenticate_user!
+    # Restrict access to Projects area only
+    # for non-signed users
+    if !current_user
+      id = params[:project_id] || params[:id]
+      @project = Project.find_with_namespace(id)
+
+      return if @project && @project.public
+    end
+
+    super
+  end
+
+  def determine_layout
+    if current_user
+      'projects'
+    else
+      'public_projects'
+    end
+  end
 end
diff --git a/app/controllers/projects/blame_controller.rb b/app/controllers/projects/blame_controller.rb
index e58b450720212df28c4726230d7c461d26bfa45b..a3c41301676500b053e95472513f99264691b902 100644
--- a/app/controllers/projects/blame_controller.rb
+++ b/app/controllers/projects/blame_controller.rb
@@ -8,7 +8,7 @@ class Projects::BlameController < Projects::ApplicationController
   before_filter :require_non_empty_project
 
   def show
-    @blob = Gitlab::Git::Blob.new(@repository, @commit.id, @ref, @path)
+    @blob = @repository.blob_at(@commit.id, @path)
     @blame = Gitlab::Git::Blame.new(project.repository, @commit.id, @path)
   end
 end
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index b1329c01ce77c83144df87b4dc6bd7546dc67540..ba466251b29db862d5b3220f5338d4bf9e0f2b93 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -8,6 +8,8 @@ class Projects::BlobController < Projects::ApplicationController
   before_filter :require_non_empty_project
 
   def show
-    @blob = Gitlab::Git::Blob.new(@repository, @commit.id, @ref, @path)
+    @blob = @repository.blob_at(@commit.id, @path)
+
+    not_found! unless @blob
   end
 end
diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb
index 6a2d2315c1da5bf5b102888887b79d25bdab0add..bdc501d73bbfeda1f93fc1c49551736f44331ec4 100644
--- a/app/controllers/projects/commit_controller.rb
+++ b/app/controllers/projects/commit_controller.rb
@@ -18,6 +18,7 @@ class Projects::CommitController < Projects::ApplicationController
     end
 
     @suppress_diff = result[:suppress_diff]
+    @force_suppress_diff = result[:force_suppress_diff]
 
     @note        = result[:note]
     @line_notes  = result[:line_notes]
diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb
index 126a2ea50c9dd821d264d6460b4bf788e43cd83a..b7531e2cefbf082121ef751b84a021cf4252b56f 100644
--- a/app/controllers/projects/compare_controller.rb
+++ b/app/controllers/projects/compare_controller.rb
@@ -8,13 +8,17 @@ class Projects::CompareController < Projects::ApplicationController
   end
 
   def show
-    compare = Gitlab::Git::Compare.new(project.repository, params[:from], params[:to])
+    compare = Gitlab::Git::Compare.new(@repository.raw_repository, params[:from], params[:to])
 
     @commits       = compare.commits
     @commit        = compare.commit
     @diffs         = compare.diffs
     @refs_are_same = compare.same
     @line_notes    = []
+
+    diff_line_count = Commit::diff_line_count(@diffs)
+    @suppress_diff = Commit::diff_suppress?(@diffs, diff_line_count) && !params[:force_show_diff]
+    @force_suppress_diff = Commit::diff_force_suppress?(@diffs, diff_line_count)
   end
 
   def create
diff --git a/app/controllers/projects/edit_tree_controller.rb b/app/controllers/projects/edit_tree_controller.rb
index 3b945fc7126c29deff2b5a3f3b0bb8abf9c3520c..5d05c585ecc635d24959be93364e40fb879994e7 100644
--- a/app/controllers/projects/edit_tree_controller.rb
+++ b/app/controllers/projects/edit_tree_controller.rb
@@ -10,7 +10,7 @@ class Projects::EditTreeController < Projects::ApplicationController
   before_filter :edit_requirements, only: [:show, :update]
 
   def show
-    @last_commit = Gitlab::Git::Commit.last_for_path(@project.repository, @ref, @path).sha
+    @last_commit = Gitlab::Git::Commit.last_for_path(@repository, @ref, @path).sha
   end
 
   def update
@@ -32,9 +32,9 @@ class Projects::EditTreeController < Projects::ApplicationController
   private
 
   def edit_requirements
-    @blob = Gitlab::Git::Blob.new(@repository, @commit.id, @ref, @path)
+    @blob = @repository.blob_at(@commit.id, @path)
 
-    unless @blob.exists? && @blob.text?
+    unless @blob
       redirect_to project_blob_path(@project, @id), notice: "You can only edit text files"
     end
 
diff --git a/app/controllers/projects/hooks_controller.rb b/app/controllers/projects/hooks_controller.rb
index 3367ddb5d141f3e8b0c0fa6291e1ae5ade7078b1..1a94dbab5ea538fe6daa9f175e1d73c841b396d8 100644
--- a/app/controllers/projects/hooks_controller.rb
+++ b/app/controllers/projects/hooks_controller.rb
@@ -1,7 +1,6 @@
 class Projects::HooksController < Projects::ApplicationController
   # Authorize
-  before_filter :authorize_read_project!
-  before_filter :authorize_admin_project!, only: [:new, :create, :destroy]
+  before_filter :authorize_admin_project!
 
   respond_to :html
 
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 55d2c3f04fc8e09e26acf59e4b9a8b0f562045cc..3bc50b0418f417bc57f143f1cf0c8db65a054c22 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -40,6 +40,10 @@ class Projects::MergeRequestsController < Projects::ApplicationController
     @comments_target = {noteable_type: 'MergeRequest',
                         noteable_id: @merge_request.id}
     @line_notes = @merge_request.notes.where("line_code is not null")
+
+    diff_line_count = Commit::diff_line_count(@merge_request.diffs)
+    @suppress_diff = Commit::diff_suppress?(@merge_request.diffs, diff_line_count) && !params[:force_show_diff]
+    @force_suppress_diff = Commit::diff_force_suppress?(@merge_request.diffs, diff_line_count)
   end
 
   def new
diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb
index 39cd579cce5b75b38eaa0016e7d8712c9496118a..3e88656cdf159fad6ea70c89d648129253b2d61f 100644
--- a/app/controllers/projects/milestones_controller.rb
+++ b/app/controllers/projects/milestones_controller.rb
@@ -14,7 +14,7 @@ class Projects::MilestonesController < Projects::ApplicationController
     @milestones = case params[:f]
                   when 'all'; @project.milestones.order("state, due_date DESC")
                   when 'closed'; @project.milestones.closed.order("due_date DESC")
-                  else @project.milestones.active.order("due_date DESC")
+                  else @project.milestones.active.order("due_date ASC")
                   end
 
     @milestones = @milestones.includes(:project)
diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb
index 0d35f373e9c7511e10b12c69b1705019f7ff97fd..18ace028b0c8dc9c5de9576b7e5e0833632d6ebc 100644
--- a/app/controllers/projects/raw_controller.rb
+++ b/app/controllers/projects/raw_controller.rb
@@ -8,12 +8,20 @@ class Projects::RawController < Projects::ApplicationController
   before_filter :require_non_empty_project
 
   def show
-    @blob = Gitlab::Git::Blob.new(@repository, @commit.id, @ref, @path)
+    @blob = @repository.blob_at(@commit.id, @path)
+
+    if @blob
+      type = if @blob.mime_type =~ /html|javascript/
+               'text/plain; charset=utf-8'
+             else
+               @blob.mime_type
+             end
+
+      headers['X-Content-Type-Options'] = 'nosniff'
 
-    if @blob.exists?
       send_data(
         @blob.data,
-        type: @blob.mime_type,
+        type: type,
         disposition: 'inline',
         filename: @blob.name
       )
diff --git a/app/controllers/projects/refs_controller.rb b/app/controllers/projects/refs_controller.rb
index e5c090e1f4dab63e565723a5d107d78d4518865d..16621c0371e1b7e6eaae25f05a1f136614133a84 100644
--- a/app/controllers/projects/refs_controller.rb
+++ b/app/controllers/projects/refs_controller.rb
@@ -24,13 +24,14 @@ class Projects::RefsController < Projects::ApplicationController
       format.js do
         @ref = params[:ref]
         define_tree_vars
+        tree
         render "tree"
       end
     end
   end
 
   def logs_tree
-    contents = @tree.entries
+    contents = tree.entries
     @logs = contents.map do |content|
       file = params[:path] ? File.join(params[:path], content.name) : content.name
       last_commit = @repo.commits(@commit.id, file, 1).last
diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb
index 59063103ecb78a91d58e168db7964cb8cab9586b..dd0c1a57089e51ae8f28e1b7e968ffccac14454d 100644
--- a/app/controllers/projects/snippets_controller.rb
+++ b/app/controllers/projects/snippets_controller.rb
@@ -14,8 +14,6 @@ class Projects::SnippetsController < Projects::ApplicationController
   # Allow destroy snippet
   before_filter :authorize_admin_project_snippet!, only: [:destroy]
 
-  layout 'projects'
-
   respond_to :html
 
   def index
diff --git a/app/controllers/projects/team_members_controller.rb b/app/controllers/projects/team_members_controller.rb
index 6fee770cae2f510bbe57ddf7081efa055762a6a5..b4b318fa59e95669187da58d845c3ffff26f2fbd 100644
--- a/app/controllers/projects/team_members_controller.rb
+++ b/app/controllers/projects/team_members_controller.rb
@@ -1,7 +1,6 @@
 class Projects::TeamMembersController < Projects::ApplicationController
   # Authorize
-  before_filter :authorize_read_project!
-  before_filter :authorize_admin_project!, except: [:index, :show]
+  before_filter :authorize_admin_project!
 
   layout "project_settings"
 
diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb
index 5d543f356658059e39421267adad8a4dc69bc1de..1150efbea9d947b47e70046049a5bfbeb8bf1646 100644
--- a/app/controllers/projects/tree_controller.rb
+++ b/app/controllers/projects/tree_controller.rb
@@ -8,6 +8,8 @@ class Projects::TreeController < Projects::ApplicationController
   before_filter :require_non_empty_project
 
   def show
+    return not_found! if tree.entries.empty?
+
     respond_to do |format|
       format.html
       # Disable cache so browser history works
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 23b54ec44a897b5de54005fd65d713f8d6cc00ea..7264128691ee93eb3ffc0b3cee854f22e9085e58 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -1,6 +1,7 @@
-class ProjectsController < Projects::ApplicationController
-  skip_before_filter :project, only: [:new, :create]
-  skip_before_filter :repository, only: [:new, :create]
+class ProjectsController < ApplicationController
+  skip_before_filter :authenticate_user!, only: [:show]
+  before_filter :project, except: [:new, :create]
+  before_filter :repository, except: [:new, :create]
 
   # Authorize
   before_filter :authorize_read_project!, except: [:index, :new, :create]
@@ -54,8 +55,9 @@ class ProjectsController < Projects::ApplicationController
   end
 
   def show
-    limit = (params[:limit] || 20).to_i
+    return authenticate_user! unless @project.public || current_user
 
+    limit = (params[:limit] || 20).to_i
     @events = @project.events.recent
     @events = event_filter.apply_filter(@events)
     @events = @events.limit(limit).offset(params[:offset] || 0)
@@ -67,10 +69,12 @@ class ProjectsController < Projects::ApplicationController
     respond_to do |format|
       format.html do
         if @project.empty_repo?
-          render "projects/empty"
+          render "projects/empty", layout: user_layout
         else
-          @last_push = current_user.recent_push(@project.id)
-          render :show
+          if current_user
+            @last_push = current_user.recent_push(@project.id)
+          end
+          render :show, layout: user_layout
         end
       end
       format.js
@@ -121,4 +125,8 @@ class ProjectsController < Projects::ApplicationController
   def set_title
     @title = 'New Project'
   end
+
+  def user_layout
+    current_user ? "projects" : "public_projects"
+  end
 end
diff --git a/app/controllers/public/projects_controller.rb b/app/controllers/public/projects_controller.rb
index 85216cd32714d38689a1f1b66fc38b0cf7dcc628..87e903a1d2df38b327c26adc147840dc89580ebb 100644
--- a/app/controllers/public/projects_controller.rb
+++ b/app/controllers/public/projects_controller.rb
@@ -1,7 +1,7 @@
 class Public::ProjectsController < ApplicationController
   skip_before_filter :authenticate_user!,
-    :reject_blocked, :set_current_user_for_observers,
-    :add_abilities
+                     :reject_blocked, :set_current_user_for_observers,
+                     :add_abilities
 
   layout 'public'
 
@@ -10,15 +10,4 @@ class Public::ProjectsController < ApplicationController
     @projects = @projects.search(params[:search]) if params[:search].present?
     @projects = @projects.includes(:namespace).order("namespaces.path, projects.name ASC").page(params[:page]).per(20)
   end
-
-  def show
-    @project = Project.public_only.find_with_namespace(params[:id])
-    render_404 and return unless @project
-
-    @repository = @project.repository
-    @recent_tags = @repository.tags.first(10)
-
-    @commit = @repository.commit(params[:ref])
-    @tree = Tree.new(@repository, @commit.id)
-  end
 end
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index 194dfcd4122838a0a51b11e9e04781d5502b4daf..5f18bac82edb8769c17940ed1b5c4338d2c4ec8a 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -2,9 +2,6 @@ class RegistrationsController < Devise::RegistrationsController
   before_filter :signup_enabled?
 
   def destroy
-    if current_user.owned_projects.count > 0
-      redirect_to account_profile_path, alert: "Remove projects and groups before removing account." and return
-    end
     current_user.destroy
 
     respond_to do |format|
diff --git a/app/controllers/users_groups_controller.rb b/app/controllers/users_groups_controller.rb
index df13b86fdcd14ab7a8fa09cb7baba3e318647cd2..749da1e1413456a34fe7d21a95e44a01c7fa9050 100644
--- a/app/controllers/users_groups_controller.rb
+++ b/app/controllers/users_groups_controller.rb
@@ -19,7 +19,7 @@ class UsersGroupsController < ApplicationController
 
   def destroy
     @users_group = @group.users_groups.find(params[:id])
-    @users_group.destroy unless @users_group.user == @group.owner
+    @users_group.destroy
 
     respond_to do |format|
       format.html { redirect_to members_group_path(@group), notice: 'User was  successfully removed from group.' }
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 0a49892ca0acfef21b80919f9e201ab39917910c..7e5c10fee05ed803db180ed75e9443fa408c0040 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -90,6 +90,8 @@ module ApplicationHelper
   end
 
   def search_autocomplete_source
+    return unless current_user
+
     projects = current_user.authorized_projects.map { |p| { label: "project: #{simple_sanitize(p.name_with_namespace)}", url: project_path(p) } }
     groups = current_user.authorized_groups.map { |group| { label: "group: #{simple_sanitize(group.name)}", url: group_path(group) } }
 
@@ -235,4 +237,11 @@ module ApplicationHelper
       "Search"
     end
   end
+
+  def first_line(str)
+    lines = str.split("\n")
+    line = lines.first
+    line += "..." if lines.size > 1
+    line
+  end
 end
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index e889b3909685f2e21d72785c6baa66faf30e3ac6..f8f84ff8b62ed638ace978cd56efd4ee6ea59597 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -56,8 +56,9 @@ module CommitsHelper
     end
   end
 
-  def commit_to_html commit, project
-    escape_javascript(render 'projects/commits/commit', commit: commit, project: project) unless commit.nil?
+  def commit_to_html(commit, project, inline = true)
+    template = inline ? "inline_commit" : "commit"
+    escape_javascript(render "projects/commits/#{template}", commit: commit, project: project) unless commit.nil?
   end
 
   def diff_line_content(line)
diff --git a/app/helpers/compare_helper.rb b/app/helpers/compare_helper.rb
new file mode 100644
index 0000000000000000000000000000000000000000..ea2540bf385e31511bc1c438cb5fd14391e4082a
--- /dev/null
+++ b/app/helpers/compare_helper.rb
@@ -0,0 +1,13 @@
+module CompareHelper
+  def compare_to_mr_button?
+    params[:from].present? && params[:to].present? &&
+      @repository.branch_names.include?(params[:from]) &&
+      @repository.branch_names.include?(params[:to]) &&
+      params[:from] != params[:to] &&
+      !@refs_are_same
+  end
+
+  def compare_mr_path
+    new_project_merge_request_path(@project, merge_request: {source_branch: params[:to], target_branch: params[:from]})
+  end
+end
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
index 3c637404c4f443e24c706d8725c09e82818e3e75..cd8761a6113f6774ec799aec57f683176cad04b4 100644
--- a/app/helpers/events_helper.rb
+++ b/app/helpers/events_helper.rb
@@ -123,6 +123,8 @@ module EventsHelper
   end
 
   def event_note(text)
-    sanitize(markdown(truncate(text, length: 150)), tags: %w(a img b pre p))
+    text = first_line(text)
+    text = truncate(text, length: 150)
+    sanitize(markdown(text), tags: %w(a img b pre p))
   end
 end
diff --git a/app/helpers/profile_helper.rb b/app/helpers/profile_helper.rb
index 80d67009f597dc9b2a2b0f8eb10f700dbdd8b12f..88d9f184d0e50f879113df5a6c9a26ca9806c1d3 100644
--- a/app/helpers/profile_helper.rb
+++ b/app/helpers/profile_helper.rb
@@ -4,4 +4,16 @@ module ProfileHelper
       'active'
     end
   end
+
+  def show_profile_username_tab?
+    current_user.can_change_username?
+  end
+
+  def show_profile_social_tab?
+    Gitlab.config.omniauth.enabled && !current_user.ldap_user?
+  end
+
+  def show_profile_remove_tab?
+    Gitlab.config.gitlab.signup_enabled && !current_user.ldap_user?
+  end
 end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 3a1cf59fd1ab92b908cfb75a091a9dfe9bbc6a36..9071c688df1328c9e37b9dfa0e484a9b67d6af43 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -103,4 +103,20 @@ module ProjectsHelper
 
     nav_tabs.flatten
   end
+
+  def git_user_name
+    if current_user
+      current_user.name
+    else
+      "Your name"
+    end
+  end
+
+  def git_user_email
+    if current_user
+      current_user.email
+    else
+      "your@email.com"
+    end
+  end
 end
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index 73d36d0801c75b14b83a4885bd0249b6e80141d5..2dbc1cffb16c7ecfe7120d8333408ff9cde2b706 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -67,9 +67,9 @@ module TreeHelper
   end
 
   def tree_breadcrumbs(tree, max_links = 2)
-    if tree.path
+    if @path.present?
       part_path = ""
-      parts = tree.path.split("\/")
+      parts = @path.split("\/")
 
       yield('..', nil) if parts.count > max_links
 
@@ -78,14 +78,14 @@ module TreeHelper
         part_path = part if part_path.empty?
 
         next unless parts.last(2).include?(part) if parts.count > max_links
-        yield(part, tree_join(tree.ref, part_path))
+        yield(part, tree_join(@ref, part_path))
       end
     end
   end
 
   def up_dir_path tree
-    file = File.join(tree.path, "..")
-    tree_join(tree.ref, file)
+    file = File.join(@path, "..")
+    tree_join(@ref, file)
   end
 
   def leave_edit_message
diff --git a/app/mailers/emails/groups.rb b/app/mailers/emails/groups.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2e9d28981e37f2f987ae5144ef7c74d88ce5e081
--- /dev/null
+++ b/app/mailers/emails/groups.rb
@@ -0,0 +1,11 @@
+module Emails
+  module Groups
+    def group_access_granted_email(user_group_id)
+      @membership = UsersGroup.find(user_group_id)
+      @group = @membership.group
+
+      mail(to: @membership.user.email,
+           subject: subject("access to group was granted"))
+    end
+  end
+end
diff --git a/app/mailers/emails/profile.rb b/app/mailers/emails/profile.rb
new file mode 100644
index 0000000000000000000000000000000000000000..bcd44f9476c2150ead37af7c0aa81f3743110b1e
--- /dev/null
+++ b/app/mailers/emails/profile.rb
@@ -0,0 +1,15 @@
+module Emails
+  module Profile
+    def new_user_email(user_id, password)
+      @user = User.find(user_id)
+      @password = password
+      mail(to: @user.email, subject: subject("Account was created for you"))
+    end
+
+    def new_ssh_key_email(key_id)
+      @key = Key.find(key_id)
+      @user = @key.user
+      mail(to: @user.email, subject: subject("SSH key was added to your account"))
+    end
+  end
+end
diff --git a/app/mailers/emails/projects.rb b/app/mailers/emails/projects.rb
index 1ad7ca588bd2cf5fec24654aa23c07a8a709e848..4d5fe9ef6142858ca51797ff56d3e9d5c7d9b05e 100644
--- a/app/mailers/emails/projects.rb
+++ b/app/mailers/emails/projects.rb
@@ -7,7 +7,6 @@ module Emails
            subject: subject("access to project was granted"))
     end
 
-
     def project_was_moved_email(project_id, user_id)
       @user = User.find user_id
       @project = Project.find project_id
diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb
index 7890ca7793baa86258ba42690558aae2f98f8af8..2f7be00c33ed48e37d18fffc33952ee87f81a7b2 100644
--- a/app/mailers/notify.rb
+++ b/app/mailers/notify.rb
@@ -3,6 +3,8 @@ class Notify < ActionMailer::Base
   include Emails::MergeRequests
   include Emails::Notes
   include Emails::Projects
+  include Emails::Profile
+  include Emails::Groups
 
   add_template_helper ApplicationHelper
   add_template_helper GitlabMarkdownHelper
@@ -20,18 +22,6 @@ class Notify < ActionMailer::Base
     delay_for(2.seconds)
   end
 
-  def new_user_email(user_id, password)
-    @user = User.find(user_id)
-    @password = password
-    mail(to: @user.email, subject: subject("Account was created for you"))
-  end
-
-  def new_ssh_key_email(key_id)
-    @key = Key.find(key_id)
-    @user = @key.user
-    mail(to: @user.email, subject: subject("SSH key was added to your account"))
-  end
-
   private
 
   # Look up a User by their ID and return their email address
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 74f92fe743876fe2da05d50861ba0fdfad723df6..85476089145fab798b5251fb20ed174302109932 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -1,6 +1,7 @@
 class Ability
   class << self
     def allowed(user, subject)
+      return not_auth_abilities(user, subject) if user.nil?
       return [] unless user.kind_of?(User)
       return [] if user.blocked?
 
@@ -17,6 +18,34 @@ class Ability
       end.concat(global_abilities(user))
     end
 
+    # List of possible abilities
+    # for non-authenticated user
+    def not_auth_abilities(user, subject)
+      project = if subject.kind_of?(Project)
+                  subject
+                elsif subject.respond_to?(:project)
+                  subject.project
+                else
+                  nil
+                end
+
+      if project && project.public
+        [
+          :read_project,
+          :read_wiki,
+          :read_issue,
+          :read_milestone,
+          :read_project_snippet,
+          :read_team_member,
+          :read_merge_request,
+          :read_note,
+          :download_code
+        ]
+      else
+        []
+      end
+    end
+
     def global_abilities(user)
       rules = []
       rules << :create_group if user.can_create_group
@@ -50,7 +79,7 @@ class Ability
         rules << project_admin_rules
       end
 
-      if project.group && project.group.owners.include?(user)
+      if project.group && project.group.has_owner?(user)
         rules << project_admin_rules
       end
 
@@ -58,19 +87,9 @@ class Ability
     end
 
     def public_project_rules
-      [
+      project_guest_rules + [
         :download_code,
         :fork_project,
-        :read_project,
-        :read_wiki,
-        :read_issue,
-        :read_milestone,
-        :read_project_snippet,
-        :read_team_member,
-        :read_merge_request,
-        :read_note,
-        :write_issue,
-        :write_note
       ]
     end
 
@@ -135,8 +154,12 @@ class Ability
     def group_abilities user, group
       rules = []
 
+      if group.users.include?(user) || user.admin?
+        rules << :read_group
+      end
+
       # Only group owner and administrators can manage group
-      if group.owners.include?(user) || user.admin?
+      if group.has_owner?(user) || user.admin?
         rules << [
           :manage_group,
           :manage_namespace
diff --git a/app/models/commit.rb b/app/models/commit.rb
index f8ca6a5fe82d13b5dd73a3f305ec26f912c576f2..dd1f980187852f2fc8131e57c2a33e93442b8297 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -6,15 +6,41 @@ class Commit
 
   attr_mentionable :safe_message
 
-  # Safe amount of files with diffs in one commit to render
+  # Safe amount of changes (files and lines) in one commit to render
   # Used to prevent 500 error on huge commits by suppressing diff
   #
-  DIFF_SAFE_SIZE = 100
+  # User can force display of diff above this size
+  DIFF_SAFE_FILES  = 100
+  DIFF_SAFE_LINES  = 5000
+  # Commits above this size will not be rendered in HTML
+  DIFF_HARD_LIMIT_FILES = 500
+  DIFF_HARD_LIMIT_LINES = 10000
 
   def self.decorate(commits)
     commits.map { |c| self.new(c) }
   end
 
+  # Calculate number of lines to render for diffs
+  def self.diff_line_count(diffs)
+    diffs.reduce(0){|sum, d| sum + d.diff.lines.count}
+  end
+
+  def self.diff_suppress?(diffs, line_count = nil)
+    # optimize - check file count first
+    return true if diffs.size > DIFF_SAFE_FILES
+
+    line_count ||= Commit::diff_line_count(diffs)
+    line_count > DIFF_SAFE_LINES
+  end
+
+  def self.diff_force_suppress?(diffs, line_count = nil)
+    # optimize - check file count first
+    return true if diffs.size > DIFF_HARD_LIMIT_FILES
+
+    line_count ||= Commit::diff_line_count(diffs)
+    line_count > DIFF_HARD_LIMIT_LINES
+  end
+
   attr_accessor :raw
 
   def initialize(raw_commit)
@@ -27,6 +53,19 @@ class Commit
     @raw.id
   end
 
+  def diff_line_count
+    @diff_line_count ||= Commit::diff_line_count(self.diffs)
+    @diff_line_count
+  end
+
+  def diff_suppress?
+    Commit::diff_suppress?(self.diffs, diff_line_count)
+  end
+
+  def diff_force_suppress?
+    Commit::diff_force_suppress?(self.diffs, diff_line_count)
+  end
+
   # Returns a string describing the commit for use in a link title
   #
   # Example
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index a05dba7f6b6438a7bcad17cb66dd16c1acce492d..7f820f950b02b02d601eca4779ad4b586009945b 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -37,6 +37,8 @@ module Issuable
              prefix: true
 
     attr_accessor :author_id_of_changes
+
+    attr_mentionable :title, :description
   end
 
   module ClassMethods
diff --git a/app/models/concerns/mentionable.rb b/app/models/concerns/mentionable.rb
index 27e39339ae80df14ddca82219c342a0b61444aee..5858fe1bb6fd2c813df588d984f51fdd64131f54 100644
--- a/app/models/concerns/mentionable.rb
+++ b/app/models/concerns/mentionable.rb
@@ -50,7 +50,7 @@ module Mentionable
     matches.each do |match|
       identifier = match.delete "@"
       if has_project
-        id = project.users_projects.joins(:user).where(users: { username: identifier }).pluck(:user_id).first
+        id = project.team.members.find { |u| u.username == identifier }.try(:id)
       else
         id = User.where(username: identifier).pluck(:id).first
       end
diff --git a/app/models/flowdock_service.rb b/app/models/flowdock_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..6ec431d4a10715d9843f52105fe283f9cfc49429
--- /dev/null
+++ b/app/models/flowdock_service.rb
@@ -0,0 +1,52 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id          :integer          not null, primary key
+#  type        :string(255)
+#  title       :string(255)
+#  token       :string(255)
+#  project_id  :integer          not null
+#  created_at  :datetime         not null
+#  updated_at  :datetime         not null
+#  active      :boolean          default(FALSE), not null
+#  project_url :string(255)
+#
+
+require "flowdock-git-hook"
+
+class FlowdockService < Service
+  validates :token, presence: true, if: :activated?
+
+  def title
+    'Flowdock'
+  end
+
+  def description
+    'Flowdock is a collaboration web app for technical teams.'
+  end
+
+  def to_param
+    'flowdock'
+  end
+
+  def fields
+    [
+      { type: 'text', name: 'token',     placeholder: '' }
+    ]
+  end
+
+  def execute(push_data)
+    repo_path = File.join(Gitlab.config.gitlab_shell.repos_path, "#{project.path_with_namespace}.git")
+    Flowdock::Git.post(
+      push_data[:ref],
+      push_data[:before],
+      push_data[:after],
+      token: token,
+      repo: repo_path,
+      repo_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}",
+      commit_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/commit/%s",
+      diff_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/compare/%s...%s",
+      )
+  end
+end
diff --git a/app/models/group.rb b/app/models/group.rb
index fce8d71217bb08c0af100d634a6b2c84b85cf287..d6272ca46f57ff63d104c26bd4132635a3dde801 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -5,7 +5,7 @@
 #  id          :integer          not null, primary key
 #  name        :string(255)      not null
 #  path        :string(255)      not null
-#  owner_id    :integer          not null
+#  owner_id    :integer
 #  created_at  :datetime         not null
 #  updated_at  :datetime         not null
 #  type        :string(255)
@@ -16,14 +16,12 @@ class Group < Namespace
   has_many :users_groups, dependent: :destroy
   has_many :users, through: :users_groups
 
-  after_create :add_owner
-
   def human_name
     name
   end
 
   def owners
-    @owners ||= (users_groups.owners.map(&:user) << owner).uniq
+    @owners ||= users_groups.owners.map(&:user)
   end
 
   def add_users(user_ids, group_access)
@@ -32,20 +30,23 @@ class Group < Namespace
     end
   end
 
-  def change_owner(user)
-    self.owner = user
-    membership = users_groups.where(user_id: user.id).first
+  def add_user(user, group_access)
+    self.users_groups.create(user_id: user.id, group_access: group_access)
+  end
 
-    if membership
-      membership.update_attributes(group_access: UsersGroup::OWNER)
-    else
-      add_owner
-    end
+  def add_owner(user)
+    self.add_user(user, UsersGroup::OWNER)
   end
 
-  private
+  def has_owner?(user)
+    owners.include?(user)
+  end
+
+  def last_owner?(user)
+    has_owner?(user) && owners.size == 1
+  end
 
-  def add_owner
-    self.add_users([owner.id], UsersGroup::OWNER)
+  def members
+    users_groups
   end
 end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index ffe9681fc83ee26a7c347113fdcd23e79f7faa25..f3ec322126facfbbac0bdd9ef6763afd82e03a46 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -32,7 +32,6 @@ class Issue < ActiveRecord::Base
   attr_accessible :title, :assignee_id, :position, :description,
                   :milestone_id, :label_list, :author_id_of_changes,
                   :state_event
-  attr_mentionable :title, :description
 
   acts_as_taggable_on :labels
 
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 514fc79f7c5442a71722176dc0815d35b9bae8df..b164ea11073d97681c39a75eec829c1a5cceb9da 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -18,6 +18,7 @@
 #  merge_status      :string(255)
 #  target_project_id :integer          not null
 #  iid               :integer
+#  description       :text
 #
 
 require Rails.root.join("app/models/commit")
@@ -30,8 +31,7 @@ class MergeRequest < ActiveRecord::Base
   belongs_to :target_project, foreign_key: :target_project_id, class_name: "Project"
   belongs_to :source_project, foreign_key: :source_project_id, class_name: "Project"
 
-  attr_accessible :title, :assignee_id, :source_project_id, :source_branch, :target_project_id, :target_branch, :milestone_id, :author_id_of_changes, :state_event
-  attr_mentionable :title
+  attr_accessible :title, :assignee_id, :source_project_id, :source_branch, :target_project_id, :target_branch, :milestone_id, :author_id_of_changes, :state_event, :description
 
   attr_accessor :should_remove_source_branch
 
@@ -222,7 +222,11 @@ class MergeRequest < ActiveRecord::Base
 
   def mr_and_commit_notes
     commit_ids = commits.map(&:id)
-    Note.where("(noteable_type = 'MergeRequest' AND noteable_id = :mr_id) OR (noteable_type = 'Commit' AND commit_id IN (:commit_ids))", mr_id: id, commit_ids: commit_ids)
+    project.notes.where(
+      "(noteable_type = 'MergeRequest' AND noteable_id = :mr_id) OR (noteable_type = 'Commit' AND commit_id IN (:commit_ids))",
+      mr_id: id,
+      commit_ids: commit_ids
+    )
   end
 
   # Returns the raw diff for this merge request
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 189591669312fe7148e85cac2fdec018a6fb1f0c..fde06649c7883f75c9ee7d6cabda5e62696689b8 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -5,7 +5,7 @@
 #  id          :integer          not null, primary key
 #  name        :string(255)      not null
 #  path        :string(255)      not null
-#  owner_id    :integer          not null
+#  owner_id    :integer
 #  created_at  :datetime         not null
 #  updated_at  :datetime         not null
 #  type        :string(255)
@@ -20,7 +20,7 @@ class Namespace < ActiveRecord::Base
   has_many :projects, dependent: :destroy
   belongs_to :owner, class_name: "User"
 
-  validates :owner, presence: true
+  validates :owner, presence: true, unless: ->(n) { n.type == "Group" }
   validates :name, presence: true, uniqueness: true,
             length: { within: 0..255 },
             format: { with: Gitlab::Regex.name_regex,
diff --git a/app/models/network/commit.rb b/app/models/network/commit.rb
index e31adcebbe7346041d3aeec1dd6e7e40de2eec80..8417f200e366bd61f94374e6644d81e8f5afaa07 100644
--- a/app/models/network/commit.rb
+++ b/app/models/network/commit.rb
@@ -1,5 +1,3 @@
-require "grit"
-
 module Network
   class Commit
     include ActionView::Helpers::TagHelper
diff --git a/app/models/note.rb b/app/models/note.rb
index e819a5516b5c926c1ff3cca552bd2b574f19941a..7e7387abed6f92fb23abe9a3b99607beb25bfd96 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -14,6 +14,7 @@
 #  commit_id     :string(255)
 #  noteable_id   :integer
 #  st_diff       :text
+#  system        :boolean          default(FALSE), not null
 #
 
 require 'carrierwave/orm/activerecord'
diff --git a/app/models/pivotaltracker_service.rb b/app/models/pivotaltracker_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c5b1b9ab8d30cbd952413063fa24e35c69dd81ac
--- /dev/null
+++ b/app/models/pivotaltracker_service.rb
@@ -0,0 +1,62 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id          :integer          not null, primary key
+#  type        :string(255)
+#  title       :string(255)
+#  token       :string(255)
+#  project_id  :integer          not null
+#  created_at  :datetime         not null
+#  updated_at  :datetime         not null
+#  active      :boolean          default(FALSE), not null
+#  project_url :string(255)
+#  subdomain   :string(255)
+#  room        :string(255)
+#
+
+class PivotaltrackerService < Service
+  include HTTParty
+
+  validates :token, presence: true, if: :activated?
+
+  def title
+    'PivotalTracker'
+  end
+
+  def description
+    'Project Management Software (Source Commits Endpoint)'
+  end
+
+  def to_param
+    'pivotaltracker'
+  end
+
+  def fields
+    [
+      { type: 'text', name: 'token', placeholder: '' }
+    ]
+  end
+
+  def execute(push)
+    url = 'https://www.pivotaltracker.com/services/v5/source_commits'
+    push[:commits].each do |commit|
+      message = {
+        'source_commit' => {
+          'commit_id' => commit[:id],
+          'author' => commit[:author][:name],
+          'url' => commit[:url],
+          'message' => commit[:message]
+        }
+      }
+      PivotaltrackerService.post(
+        url,
+        body: message.to_json,
+        headers: {
+          'Content-Type' => 'application/json',
+          'X-TrackerToken' => token
+        }
+      )
+    end
+  end
+end
diff --git a/app/models/project.rb b/app/models/project.rb
index 6c4f3075e1c0cff2473feb852ee224c1316044e1..d2dcf26ac69bec0749db92ed6de9f4e43dc3f3a1 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -24,8 +24,6 @@
 #  import_url             :string(255)
 #
 
-require "grit"
-
 class Project < ActiveRecord::Base
   include Gitlab::ShellAdapter
   extend Enumerize
@@ -46,13 +44,16 @@ class Project < ActiveRecord::Base
   has_one :last_event, class_name: 'Event', order: 'events.created_at DESC', foreign_key: 'project_id'
   has_one :gitlab_ci_service, dependent: :destroy
   has_one :campfire_service, dependent: :destroy
+  has_one :pivotaltracker_service, dependent: :destroy
   has_one :hipchat_service, dependent: :destroy
+  has_one :flowdock_service, dependent: :destroy
   has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id"
   has_one :forked_from_project, through: :forked_project_link
 
   has_many :services,           dependent: :destroy
   has_many :events,             dependent: :destroy
   has_many :merge_requests,     dependent: :destroy, foreign_key: "target_project_id"
+  has_many :fork_merge_requests,dependent: :destroy, foreign_key: "source_project_id", class_name: MergeRequest
   has_many :issues,             dependent: :destroy, order: "state DESC, created_at DESC"
   has_many :milestones,         dependent: :destroy
   has_many :notes,              dependent: :destroy
@@ -83,6 +84,7 @@ class Project < ActiveRecord::Base
             :wiki_enabled, inclusion: { in: [true, false] }
   validates :issues_tracker_id, length: { within: 0..255 }
 
+  validates :namespace, presence: true
   validates_uniqueness_of :name, scope: :namespace_id
   validates_uniqueness_of :path, scope: :namespace_id
 
@@ -165,11 +167,7 @@ class Project < ActiveRecord::Base
   end
 
   def to_param
-    if namespace
-      namespace.path + "/" + path
-    else
-      path
-    end
+    namespace.path + "/" + path
   end
 
   def web_url
@@ -223,7 +221,7 @@ class Project < ActiveRecord::Base
   end
 
   def available_services_names
-    %w(gitlab_ci campfire hipchat)
+    %w(gitlab_ci campfire hipchat pivotaltracker flowdock)
   end
 
   def gitlab_ci?
@@ -251,10 +249,10 @@ class Project < ActiveRecord::Base
   end
 
   def owner
-    if namespace
-      namespace_owner
+    if group
+      group
     else
-      creator
+      namespace.try(:owner)
     end
   end
 
@@ -278,10 +276,6 @@ class Project < ActiveRecord::Base
                              end
   end
 
-  def namespace_owner
-    namespace.try(:owner)
-  end
-
   def path_with_namespace
     if namespace
       namespace.path + '/' + path
@@ -319,8 +313,11 @@ class Project < ActiveRecord::Base
     branch_name = ref.gsub("refs/heads/", "")
     c_ids = self.repository.commits_between(oldrev, newrev).map(&:id)
 
-    # Update code for merge requests
+    # Update code for merge requests into project between project branches
     mrs = self.merge_requests.opened.by_branch(branch_name).all
+    # Update code for merge requests between project and project fork
+    mrs += self.fork_merge_requests.opened.by_branch(branch_name).all
+    
     mrs.each { |merge_request| merge_request.reload_code; merge_request.mark_as_unchecked }
 
     # Close merge requests
diff --git a/app/models/repository.rb b/app/models/repository.rb
index aeec48ee5cc82e40c249494621ae6bb1aeb9298b..97b4330092a4cde7cbef289640c6682ccb97b569 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -1,14 +1,19 @@
 class Repository
   include Gitlab::ShellAdapter
 
-  attr_accessor :raw_repository
+  attr_accessor :raw_repository, :path_with_namespace
 
   def initialize(path_with_namespace, default_branch)
-    @raw_repository = Gitlab::Git::Repository.new(path_with_namespace, default_branch)
+    @path_with_namespace = path_with_namespace
+    @raw_repository = Gitlab::Git::Repository.new(path_to_repo) if path_with_namespace
   rescue Gitlab::Git::Repository::NoRepository
     nil
   end
 
+  def path_to_repo
+    @path_to_repo ||= File.join(Gitlab.config.gitlab_shell.repos_path, path_with_namespace + ".git")
+  end
+
   def exists?
     raw_repository
   end
@@ -150,4 +155,8 @@ class Repository
 
     super
   end
+
+  def blob_at(sha, path)
+    Gitlab::Git::Blob.find(self, sha, path)
+  end
 end
diff --git a/app/models/tree.rb b/app/models/tree.rb
index 042050527c1df0979055cf3fa9804330005a1506..5fbad19b468a11bab4fd78b5e6c5eb1c0a71527f 100644
--- a/app/models/tree.rb
+++ b/app/models/tree.rb
@@ -1,17 +1,25 @@
 class Tree
-  attr_accessor :raw
+  attr_accessor :entries, :readme
 
-  def initialize(repository, sha, ref = nil, path = nil)
-    @raw = Gitlab::Git::Tree.new(repository, sha, ref, path)
+  def initialize(repository, sha, path = '/')
+    path = '/' if path.blank?
+    git_repo = repository.raw_repository
+    @entries = Gitlab::Git::Tree.where(git_repo, sha, path)
+
+    if readme_tree = @entries.find(&:readme?)
+      @readme = Gitlab::Git::Blob.find(git_repo, sha, readme_tree.name)
+    end
   end
 
-  def method_missing(m, *args, &block)
-    @raw.send(m, *args, &block)
+  def trees
+    @entries.select(&:dir?)
   end
 
-  def respond_to?(method)
-    return true if @raw.respond_to?(method)
+  def blobs
+    @entries.select(&:file?)
+  end
 
-    super
+  def submodules
+    @entries.select(&:submodule?)
   end
 end
diff --git a/app/models/user.rb b/app/models/user.rb
index b44c063c32f9d08f5fd3918e8c5faa8a3f9e14b7..c61b074f5040e80c865375fb4768db12586f27f0 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -135,7 +135,7 @@ class User < ActiveRecord::Base
       # Remove user from all groups
       user.users_groups.find_each do |membership|
         # skip owned resources
-        next if membership.group.owners.include?(user)
+        next if membership.group.last_owner?(user)
 
         return false unless membership.destroy
       end
@@ -159,6 +159,7 @@ class User < ActiveRecord::Base
   scope :not_in_team, ->(team){ where('users.id NOT IN (:ids)', ids: team.member_ids) }
   scope :not_in_project, ->(project) { project.users.present? ? where("id not in (:ids)", ids: project.users.map(&:id) ) : scoped }
   scope :without_projects, -> { where('id NOT IN (SELECT DISTINCT(user_id) FROM users_projects)') }
+  scope :ldap, -> { where(provider:  'ldap') }
 
   scope :potential_team_members, ->(team) { team.members.any? ? active.not_in_team(team) : active  }
 
@@ -166,7 +167,7 @@ class User < ActiveRecord::Base
   # Class methods
   #
   class << self
-    # Devise method overridden to allow sing in with email or username
+    # Devise method overridden to allow sign in with email or username
     def find_for_database_authentication(warden_conditions)
       conditions = warden_conditions.dup
       if login = conditions.delete(:login)
@@ -186,24 +187,32 @@ class User < ActiveRecord::Base
       end
     end
 
-    def create_from_omniauth(auth, ldap = false)
-      gitlab_auth.create_from_omniauth(auth, ldap)
-    end
-
-    def find_or_new_for_omniauth(auth)
-      gitlab_auth.find_or_new_for_omniauth(auth)
+    def search query
+      where("name LIKE :query OR email LIKE :query OR username LIKE :query", query: "%#{query}%")
     end
 
-    def find_for_ldap_auth(auth, signed_in_resource = nil)
-      gitlab_auth.find_for_ldap_auth(auth, signed_in_resource)
+    def by_username_or_id(name_or_id)
+      if (name_or_id.is_a?(Integer))
+        User.find_by_id(name_or_id)
+      else
+        User.find_by_username(name_or_id)
+      end
     end
 
-    def gitlab_auth
-      Gitlab::Auth.new
+    def build_user(attrs = {}, options= {})
+      if options[:as] == :admin
+        User.new(defaults.merge(attrs.symbolize_keys), options)
+      else
+        User.new(attrs, options).with_defaults
+      end
     end
 
-    def search query
-      where("name LIKE :query OR email LIKE :query OR username LIKE :query", query: "%#{query}%")
+    def defaults
+      {
+        projects_limit: Gitlab.config.gitlab.default_projects_limit,
+        can_create_group: Gitlab.config.gitlab.default_can_create_group,
+        theme_id: Gitlab.config.gitlab.default_theme
+      }
     end
   end
 
@@ -215,14 +224,6 @@ class User < ActiveRecord::Base
     username
   end
 
-  def with_defaults
-    tap do |u|
-      u.projects_limit = Gitlab.config.gitlab.default_projects_limit
-      u.can_create_group = Gitlab.config.gitlab.default_can_create_group
-      u.theme_id = Gitlab::Theme::MARS
-    end
-  end
-
   def notification
     @notification ||= Notification.new(self)
   end
@@ -329,7 +330,7 @@ class User < ActiveRecord::Base
   end
 
   def several_namespaces?
-    namespaces.many?
+    namespaces.many? || owned_groups.any?
   end
 
   def namespace_id
@@ -382,4 +383,12 @@ class User < ActiveRecord::Base
       group.owners == [self]
     end
   end
+
+  def with_defaults
+    User.defaults.each do |k, v|
+      self.send("#{k}=", v)
+    end
+
+    self
+  end
 end
diff --git a/app/models/web_hook.rb b/app/models/web_hook.rb
index 3f22b1082fb0aaad525f8b57be062622b5501240..767d766a26add1eafcbf1c5f1e4a755ca9ac78f2 100644
--- a/app/models/web_hook.rb
+++ b/app/models/web_hook.rb
@@ -17,7 +17,7 @@ class WebHook < ActiveRecord::Base
   attr_accessible :url
 
   # HTTParty timeout
-  default_timeout 10
+  default_timeout Gitlab.config.gitlab.webhook_timeout
 
   validates :url, presence: true,
                   format: { with: URI::regexp(%w(http https)), message: "should be a valid url" }
diff --git a/app/observers/users_group_observer.rb b/app/observers/users_group_observer.rb
new file mode 100644
index 0000000000000000000000000000000000000000..ecdbede89d96b1f29e5f1839660f552886b0cc28
--- /dev/null
+++ b/app/observers/users_group_observer.rb
@@ -0,0 +1,9 @@
+class UsersGroupObserver < BaseObserver
+  def after_create(membership)
+    notification.new_group_member(membership)
+  end
+
+  def after_update(membership)
+    notification.update_group_member(membership)
+  end
+end
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index c20b07e69f076293215bd9db40badf22edd2f11c..750a71aea6bc1f84f06f163f43ba7411cae35d34 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -107,12 +107,6 @@ class NotificationService
 
     opts = { noteable_type: note.noteable_type, project_id: note.project_id }
 
-    if note.commit_id.present?
-      opts.merge!(commit_id: note.commit_id)
-    else
-      opts.merge!(noteable_id: note.noteable_id)
-    end
-
     target = note.noteable
     if target.respond_to?(:participants)
       recipients = target.participants
@@ -120,6 +114,13 @@ class NotificationService
       recipients = note.mentioned_users
     end
 
+    if note.commit_id.present?
+      opts.merge!(commit_id: note.commit_id)
+      recipients << note.commit_author
+    else
+      opts.merge!(noteable_id: note.noteable_id)
+    end
+
     # Get users who left comment in thread
     recipients = recipients.concat(User.where(id: Note.where(opts).pluck(:author_id)))
 
@@ -148,6 +149,14 @@ class NotificationService
     mailer.project_access_granted_email(users_project.id)
   end
 
+  def new_group_member(users_group)
+    mailer.group_access_granted_email(users_group.id)
+  end
+
+  def update_group_member(users_group)
+    mailer.group_access_granted_email(users_group.id)
+  end
+
   protected
 
   # Get project users with WATCH notification level
diff --git a/app/services/system_hooks_service.rb b/app/services/system_hooks_service.rb
index c872b27ba393540b9601b45717c555c4900182a1..de4fa9b79e72aa55a8728eea6e00716875e680c2 100644
--- a/app/services/system_hooks_service.rb
+++ b/app/services/system_hooks_service.rb
@@ -23,18 +23,21 @@ class SystemHooksService
 
     case model
     when Project
+      owner = model.owner
+
       data.merge!({
         name: model.name,
         path: model.path,
         path_with_namespace: model.path_with_namespace,
         project_id: model.id,
-        owner_name: model.owner.name,
-        owner_email: model.owner.email
+        owner_name: owner.name,
+        owner_email: owner.respond_to?(:email) ?  owner.email : nil
       })
     when User
       data.merge!({
         name: model.name,
-        email: model.email
+        email: model.email,
+        user_id: model.id
       })
     when UsersProject
       data.merge!({
diff --git a/app/views/admin/groups/index.html.haml b/app/views/admin/groups/index.html.haml
index 8e45dc76ec64e04a602265c9aa6a4728bdf74fa3..c9d7c24f204f54fe18e7778c09bcf3e1af5a6727 100644
--- a/app/views/admin/groups/index.html.haml
+++ b/app/views/admin/groups/index.html.haml
@@ -31,11 +31,8 @@
 
       .clearfix.light.append-bottom-10
         %span
-          %b Owner:
-          - if group.owner
-            = link_to group.owner_name, admin_user_path(group.owner)
-          - else
-            (deleted)
+          %b Members:
+          %span.badge= group.members.size
         \|
         %span
           %b Projects:
diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml
index 5509811bae5e1b1b88692699f43728bc449d1c3e..1566c3458093822a99f6821a3cc88343a89571d7 100644
--- a/app/views/admin/groups/show.html.haml
+++ b/app/views/admin/groups/show.html.haml
@@ -24,26 +24,6 @@
           %strong
             = @group.description
 
-        %li
-          %span.light Owned by:
-          %strong
-            - if @group.owner
-              = link_to @group.owner_name, admin_user_path(@group.owner)
-            - else
-              (deleted)
-          .pull-right
-            = link_to "#", class: "btn btn-small change-owner-link" do
-              %i.icon-edit
-              Change owner
-        %li.change-owner-holder.hide.bgred
-          .form-holder
-            %strong.cred New Owner:
-            = form_for [:admin, @group] do |f|
-              = users_select_tag(:"group[owner_id]")
-              .prepend-top-10
-                = f.submit 'Change Owner', class: "btn btn-remove"
-                = link_to "Cancel", "#", class: "btn change-owner-cancel-link"
-
         %li
           %span.light Created at:
           %strong
@@ -92,4 +72,5 @@
               = link_to user.name, admin_user_path(user)
             %span.pull-right.light
               = member.human_access
-
+              = link_to group_users_group_path(@group, member), confirm: remove_user_from_group_message(@group, user), method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
+                %i.icon-minus.icon-white
diff --git a/app/views/admin/hooks/_data_ex.html.erb b/app/views/admin/hooks/_data_ex.html.erb
index b69aa92716dc9444e98b0c845b487c23efce5c39..5b16dfb398a12c1ec40a691a02bef22c699e0dbf 100644
--- a/app/views/admin/hooks/_data_ex.html.erb
+++ b/app/views/admin/hooks/_data_ex.html.erb
@@ -52,7 +52,8 @@
    "created_at": "2012-07-21T07:44:07Z",
         "email": "js@gitlabhq.com",
    "event_name": "user_create",
-         "name": "John Smith" 
+         "name": "John Smith", 
+      "user_id": 41 
 }
 
 6. User removed:
@@ -60,7 +61,8 @@
    "created_at": "2012-07-21T07:44:07Z",
         "email": "js@gitlabhq.com",
    "event_name": "user_destroy",
-         "name": "John Smith" 
+         "name": "John Smith",
+      "user_id": 41 
 }
 
 eos
diff --git a/app/views/admin/hooks/index.html.haml b/app/views/admin/hooks/index.html.haml
index eb6570af30e2a271341b89f0d3ae94b668813f0c..1bd7b8eac622eea89da62dadfb4ad451766f6519 100644
--- a/app/views/admin/hooks/index.html.haml
+++ b/app/views/admin/hooks/index.html.haml
@@ -1,9 +1,12 @@
-.alert.alert-info
-  %span
-    Post-receive hooks for binding events.
-    %br
-    Read more about system hooks
-    %strong #{link_to "here", help_system_hooks_path, class: "vlink"}
+%h3.page-title
+  System Hooks
+
+%p.light
+  #{link_to "System hooks ", help_system_hooks_path, class: "vlink"} can be
+  used for binding events when GitLab creates a User or Project.
+
+%hr
+
 
 = form_for @hook, as: :hook, url: admin_hooks_path, html: { class: 'form-inline' } do |f|
   -if @hook.errors.any?
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index 72317bb8efec6e3be087df6393e859bf9b2e87fa..c8a87328207d389326718c6e3d482c31d1a4f003 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -12,7 +12,8 @@
       %ul.well-list
         %li
           %span.light Name:
-          %strong= @project.name
+          %strong
+            = link_to @project.name, project_path(@project)
         %li
           %span.light Namespace:
           %strong
@@ -24,7 +25,7 @@
           %span.light Owned by:
           %strong
             - if @project.owner
-              = link_to @project.owner_name, admin_user_path(@project.owner)
+              = link_to @project.owner_name, [:admin, @project.owner]
             - else
               (deleted)
 
@@ -77,8 +78,8 @@
     - if @group
       .ui-box
         .title
-          %strong #{@group.name} Group
-          members (#{@group.users_groups.count})
+          %strong #{@group.name}
+          group members (#{@group.users_groups.count})
           .pull-right
             = link_to admin_group_path(@group), class: 'btn btn-small' do
               %i.icon-edit
@@ -88,7 +89,7 @@
 
     .ui-box
       .title
-        Team
+        Project members
         %small
           (#{@project.users.count})
         .pull-right
@@ -98,7 +99,7 @@
       %ul.well-list.team_members
         - @project.users_projects.each do |users_project|
           - user = users_project.user
-          %li
+          %li.users_project
             %strong
               = link_to user.name, admin_user_path(user)
             .pull-right
@@ -106,5 +107,5 @@
                 %span.light Owner
               - else
                 %span.light= users_project.human_access
-                = link_to admin_project_member_path(@project, user), confirm: remove_from_project_team_message(@project, user), method: :delete, class: "btn btn-small btn-remove" do
+                = link_to project_team_member_path(@project, user), confirm: remove_from_project_team_message(@project, user), method: :delete, remote: true, class: "btn btn-small btn-remove" do
                   %i.icon-remove
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index 95257a4594ee1830599f180d7d2684f2e063b62f..3df9903e40905d96a17f1cfb6e74be0b6cbfe9fa 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -33,7 +33,14 @@
           %span.light Email:
           %strong
             = mail_to @user.email
-
+        %li
+          %span.light Can create groups:
+          %strong
+            = @user.can_create_group ? "Yes" : "No"
+        %li
+          %span.light Personal projects limit:
+          %strong
+            = @user.projects_limit
         %li
           %span.light Member since:
           %strong
diff --git a/app/views/dashboard/_groups.html.haml b/app/views/dashboard/_groups.html.haml
index 8b32c5642bb95b485981ee80592484de6095fbd9..b4f3866228deced6e1e55142035cdd48c4a4e91a 100644
--- a/app/views/dashboard/_groups.html.haml
+++ b/app/views/dashboard/_groups.html.haml
@@ -14,9 +14,6 @@
             = truncate(group.name, length: 35)
           %span.arrow
             %i.icon-angle-right
-          %span.owner-info
-            %span Owner:
-            %span.owner= group.owner_name
     - if groups.blank?
       %li
         %h3.nothing_here_message You have no groups yet.
diff --git a/app/views/dashboard/_project.html.haml b/app/views/dashboard/_project.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..50b833f3d82239f5ac6469ba14096cdf8b5addce
--- /dev/null
+++ b/app/views/dashboard/_project.html.haml
@@ -0,0 +1,12 @@
+= link_to project_path(project), class: dom_class(project) do
+  %span.namespace-name
+    - if project.namespace
+      = project.namespace.human_name
+      \/
+  %span.project-name.filter-title
+    = truncate(project.name, length: 25)
+  %span.arrow
+    %i.icon-angle-right
+  %span.last-activity
+    %span Last activity:
+    %span.date= project_last_activity(project)
diff --git a/app/views/dashboard/_projects.html.haml b/app/views/dashboard/_projects.html.haml
index 90b843de016d665e469a6138046dd46092ae69f3..b79b27fc95add93c413c1b77c839d3085e095cb9 100644
--- a/app/views/dashboard/_projects.html.haml
+++ b/app/views/dashboard/_projects.html.haml
@@ -10,21 +10,16 @@
   %ul.well-list.dash-list
     - projects.each do |project|
       %li.project-row
-        = link_to project_path(project), class: dom_class(project) do
-          %span.namespace-name
-            - if project.namespace
-              = project.namespace.human_name
-              \/
-          %span.project-name.filter-title
-            = truncate(project.name, length: 25)
-          %span.arrow
-            %i.icon-angle-right
-          %span.last-activity
-            %span Last activity:
-            %span.date= project_last_activity(project)
+        = render "project", project: project
+
     - if projects.blank?
       %li
         %h3.nothing_here_message There are no projects here.
-    - if @projects_count > 20
+    - if @projects_count > @projects_limit
       %li.bottom
-        %strong= link_to "show all projects", projects_dashboard_path
+        %span.light
+          #{@projects_limit} of #{pluralize(@projects_count, 'project')} displayed.
+        .pull-right.append-right-10
+          = link_to projects_dashboard_path do
+            Show all
+            %i.icon-angle-right
diff --git a/app/views/dashboard/_zero_authorized_projects.html.haml b/app/views/dashboard/_zero_authorized_projects.html.haml
index ea5d8d6376fa9fb71df11f2bc37b2e9bd768a577..79d5dca8845d74dce9ce7732847d8d8b4511cc4c 100644
--- a/app/views/dashboard/_zero_authorized_projects.html.haml
+++ b/app/views/dashboard/_zero_authorized_projects.html.haml
@@ -1,12 +1,36 @@
-%h3.nothing_here_message
-  You don't have access to any projects.
-  %br
-  - if current_user.can_create_project?
-    You can create up to
-    = pluralize(current_user.projects_limit, "project") + "."
-    Click on the button below to add a new one
-    .link_holder
-      = link_to new_project_path, class: "btn btn-primary" do
-        New Project »
-  - else
-    If you are added to a project, it will be displayed here
+%h3.page-title Welcome to GitLab!
+%p.light Self Hosted Git Management application.
+%hr
+%div
+  .dashboard-intro-icon
+    %i.icon-bookmark-empty
+  %div
+    %p.slead
+      You don't have access to any projects right now.
+      %br
+      - if current_user.can_create_project?
+        You can create up to
+        %strong= pluralize(current_user.projects_limit, "project") + "."
+        Click on the button below to add a new one
+      - else
+        If you are added to a project, it will be displayed here
+
+    - if current_user.can_create_project?
+      .link_holder
+        = link_to new_project_path, class: "btn btn-new" do
+          New project »
+
+- if current_user.can_create_group?
+  %hr
+  %div
+    .dashboard-intro-icon
+      %i.icon-group
+    %div
+      %p.slead
+        You can create a group for several dependent projects.
+        %br
+        Group is the best way to manage projects and members
+      .link_holder
+        = link_to new_group_path, class: "btn btn-new" do
+          New group »
+
diff --git a/app/views/devise/shared/_links.erb b/app/views/devise/shared/_links.erb
index a47b5ff1ec78074acc447dd45e89b4c3164115de..db931b86288effeb3cf6b65ce8bb49b90384598a 100644
--- a/app/views/devise/shared/_links.erb
+++ b/app/views/devise/shared/_links.erb
@@ -2,7 +2,7 @@
   <%= link_to "Sign in", new_session_path(resource_name), class: "btn" %><br />
 <% end -%>
 
-<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
+<%- if devise_mapping.registerable? && controller_name != 'registrations' && Gitlab.config.gitlab.signup_enabled %>
   <%= link_to "Sign up", new_registration_path(resource_name) %><br />
 <% end -%>
 
diff --git a/app/views/events/_commit.html.haml b/app/views/events/_commit.html.haml
index b50faf5a25cbe3dd46326e3d5904d8263bf90842..4d4b24009f43cd9923cb0b878eebe1d7cfb14b4a 100644
--- a/app/views/events/_commit.html.haml
+++ b/app/views/events/_commit.html.haml
@@ -1,7 +1,5 @@
 %li.commit
-  %p
+  .commit-row-title
     = link_to commit[:id][0..8], project_commit_path(project, commit[:id]), class: "commit_short_id", alt: ''
-    %span= commit[:author][:name]
-    &ndash;
-    = image_tag gravatar_icon(commit[:author][:email]), class: "avatar", width: 16
-    = gfm escape_once(truncate(commit[:message], length: 50)) rescue "--broken encoding"
+    &nbsp;
+    = gfm escape_once(truncate(commit[:message], length: 70)) rescue "--broken encoding"
diff --git a/app/views/events/event/_push.html.haml b/app/views/events/event/_push.html.haml
index f2b8dc4238c6462dd18df32bda9ff9fea8b06829..adba9a5f61975994590eb9ac704d9e3cd5c520a6 100644
--- a/app/views/events/event/_push.html.haml
+++ b/app/views/events/event/_push.html.haml
@@ -5,7 +5,7 @@
     %strong= event.ref_name
   - else
     = link_to project_commits_path(event.project, event.ref_name) do
-      %strong= event.ref_name
+      %strong= truncate(event.ref_name, length: 30)
   at
   %strong= link_to_project event.project
 
diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml
index 8aefdf7f5132922a06c4aff2f090cc3a2a306d34..2682d31ff470600641734b1673d608dc4c06379e 100644
--- a/app/views/groups/edit.html.haml
+++ b/app/views/groups/edit.html.haml
@@ -9,8 +9,6 @@
         = link_to '#tab-projects', 'data-toggle' => 'tab' do
           %i.icon-folder-close
           Projects
-      %li
-        = link_to 'Transfer', '#tab-transfer', 'data-toggle' => 'tab'
       %li
         = link_to 'Remove', '#tab-remove', 'data-toggle' => 'tab'
 
@@ -65,17 +63,6 @@
             - if @group.projects.blank?
               %p.nothing_here_message This group has no projects yet
 
-      .tab-pane#tab-transfer
-        .ui-box.ui-box-danger
-          .title Transfer group
-          .ui-box-body
-            %p
-              Transferring group will cause loss of admin control over group and all child projects
-            = form_for @group do |f|
-              = users_select_tag(:'group[owner_id]')
-              %hr
-              = f.submit 'Transfer group', class: "btn btn-small btn-remove"
-
       .tab-pane#tab-remove
         .ui-box.ui-box-danger
           .title Remove group
diff --git a/app/views/groups/members.html.haml b/app/views/groups/members.html.haml
index 77bab11b33130f8656938f4801bab109bbbea1e3..124560e4786fa28a428c6a627e29368094c9a638 100644
--- a/app/views/groups/members.html.haml
+++ b/app/views/groups/members.html.haml
@@ -2,6 +2,9 @@
   Group members
 %p.light
   Members of group have access to all group projects.
+  Read more about permissions
+  %strong= link_to "here", help_permissions_path, class: "vlink"
+
 %hr
 - can_manage_group =  current_user.can? :manage_group, @group
 .ui-box
diff --git a/app/views/help/_layout.html.haml b/app/views/help/_layout.html.haml
index ac8660dcbb4f8738dc3c9eb8b46874ec1b1cab47..da917888eeece82f46355f29d4f224fbb3ef3577 100644
--- a/app/views/help/_layout.html.haml
+++ b/app/views/help/_layout.html.haml
@@ -30,5 +30,8 @@
         %li
           %strong= link_to "Public Access", help_public_access_path
 
+        %li
+          %strong= link_to "Security", help_security_path
+
   .span9.pull-right
     = yield
diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml
index ff01136f5bb23caaf68bbf8dc88a775f1ad3ea54..fadc2dc21cbc5f5f23df8f488ac249535153eb15 100644
--- a/app/views/help/index.html.haml
+++ b/app/views/help/index.html.haml
@@ -79,3 +79,7 @@
         %li
           %strong= link_to "Public Access", help_public_access_path
           %p Learn how you can allow public access to a project.
+
+        %li
+          %strong= link_to "Security", help_security_path
+          %p Learn what you can do to secure your GitLab instance.
diff --git a/app/views/help/permissions.html.haml b/app/views/help/permissions.html.haml
index da5210bad3de9995d3c7c7bd4c8bc0a1bd909aec..bab1e7c0a41efc12b279b2ced1608f9a847b924a 100644
--- a/app/views/help/permissions.html.haml
+++ b/app/views/help/permissions.html.haml
@@ -1,6 +1,9 @@
 = render layout: 'help/layout' do
   %h3.page-title Permissions
+  %p.light User has different abilities depends on access level he has in particular group or project
+  %hr
 
+  %h4 Project:
   %table.table
     %thead
       %tr
@@ -158,3 +161,50 @@
         %td
         %td
         %td.permission-x &#10003;
+
+  %h4 Group
+  %table.table
+    %thead
+      %tr
+        %th Action
+        %th Guest
+        %th Reporter
+        %th Developer
+        %th Master
+        %th Owner
+    %tbody
+      %tr
+        %td Browse group
+        %td.permission-x &#10003;
+        %td.permission-x &#10003;
+        %td.permission-x &#10003;
+        %td.permission-x &#10003;
+        %td.permission-x &#10003;
+      %tr
+        %td Edit group
+        %td
+        %td
+        %td
+        %td
+        %td.permission-x &#10003;
+      %tr
+        %td Create project in group
+        %td
+        %td
+        %td
+        %td
+        %td.permission-x &#10003;
+      %tr
+        %td Manage group members
+        %td
+        %td
+        %td
+        %td
+        %td.permission-x &#10003;
+      %tr
+        %td Remove group
+        %td
+        %td
+        %td
+        %td
+        %td.permission-x &#10003;
diff --git a/app/views/help/security.html.haml b/app/views/help/security.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..72f21e9f634d5ef7b743a7aa6e5e2564acc6240e
--- /dev/null
+++ b/app/views/help/security.html.haml
@@ -0,0 +1,15 @@
+= render layout: 'help/layout' do
+  %h3.page-title Security
+
+  %p.slead
+    If your GitLab instance is visible from the internet chances are it will be 'tested' by bots sooner or later.
+    %br
+    %br
+    %br
+    .file-holder
+      .file-title
+        %i.icon-file
+        Dealing with bruteforcing
+      .file-content.wiki
+        = preserve do
+          = markdown File.read(Rails.root.join("doc", "security", "rack_attack.md"))
diff --git a/app/views/layouts/_public_head_panel.html.haml b/app/views/layouts/_public_head_panel.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..3c4bd857c22055e523d6206713149c5708c71c8a
--- /dev/null
+++ b/app/views/layouts/_public_head_panel.html.haml
@@ -0,0 +1,22 @@
+%header.navbar.navbar-static-top.navbar-gitlab
+  .navbar-inner
+    .container
+      %div.app_logo
+        %span.separator
+        = link_to public_root_path, class: "home" do
+          %h1 GITLAB
+        %span.separator
+      %h1.project_name
+        - if @project
+          = project_title(@project)
+        - else
+          Public Projects
+
+      %ul.nav
+        %li
+          %a
+            %div.hide.turbolink-spinner
+              %i.icon-refresh.icon-spin
+              Loading...
+        %li
+          = link_to "Sign in", new_session_path(:user), class: 'btn btn-sign-in'
diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml
index 0fa362117395791279c3a9184caa89fac1a80bc3..c4729836faac292d1a6ed494d124ab6282bdf2f0 100644
--- a/app/views/layouts/devise.html.haml
+++ b/app/views/layouts/devise.html.haml
@@ -6,5 +6,10 @@
     .container
       .content
         %center
-          = image_tag image_path "login-logo.png"
+          %h1 GitLab
+          %p.light
+            GitLab is open source software to collaborate on code.
+            %br
+            #{link_to "Sign in", new_user_session_path} or browse for #{link_to "public projects", public_projects_path}.
+        %hr
         = yield
diff --git a/app/views/layouts/public.html.haml b/app/views/layouts/public.html.haml
index 7dce0cbeae2b9c6d85a403d0f65a96013149ceb3..f922dcc420378f0fbca72a14c5933b0adedd5f93 100644
--- a/app/views/layouts/public.html.haml
+++ b/app/views/layouts/public.html.haml
@@ -1,28 +1,11 @@
 !!! 5
 %html{ lang: "en"}
   = render "layouts/head", title: "Public Projects"
-  %body{class: "#{app_theme} application", :'data-page' => body_data_page}
+  %body{class: "ui_mars application", :'data-page' => body_data_page}
     - if current_user
       = render "layouts/head_panel", title: "Public Projects"
     - else
-      %header.navbar.navbar-static-top.navbar-gitlab
-        .navbar-inner
-          .container
-            %div.app_logo
-              %span.separator
-              = link_to public_root_path, class: "home" do
-                %h1 GITLAB
-              %span.separator
-            %h1.project_name Public Projects
-            %ul.nav
-              %li
-                %a
-                  %div.hide.turbolink-spinner
-                    %i.icon-refresh.icon-spin
-                    Loading...
-              %li
-                = link_to "Sign in", new_session_path(:user)
+      = render "layouts/public_head_panel"
 
     .container.navless-container
-      .content
-        = yield
+      .content= yield
diff --git a/app/views/layouts/public_projects.html.haml b/app/views/layouts/public_projects.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..cfe6a63055adde65f7b4bb944df87f12fa107fb7
--- /dev/null
+++ b/app/views/layouts/public_projects.html.haml
@@ -0,0 +1,9 @@
+!!! 5
+%html{ lang: "en"}
+  = render "layouts/head", title: @project.name_with_namespace
+  %body{class: "ui_mars application", :'data-page' => body_data_page}
+    = render "layouts/public_head_panel"
+    %nav.main-nav
+      .container= render 'layouts/nav/project'
+    .container
+      .content= yield
diff --git a/app/views/notify/closed_issue_email.html.haml b/app/views/notify/closed_issue_email.html.haml
index 23ccc4538dea8773e1f82c9b4952dacb43234c39..325cd44eb4b0807e626a9dfa3be538adc167e2fb 100644
--- a/app/views/notify/closed_issue_email.html.haml
+++ b/app/views/notify/closed_issue_email.html.haml
@@ -1,5 +1,5 @@
 %p
   = "Issue was closed by #{@updated_by.name}"
 %p
-  = "Issue ##{@issue.id}"
+  = "Issue ##{@issue.iid}"
   = link_to_gfm truncate(@issue.title, length: 45), project_issue_url(@issue.project, @issue), title: @issue.title
diff --git a/app/views/notify/closed_issue_email.text.haml b/app/views/notify/closed_issue_email.text.haml
index 0cca321552c1530e13f10d04aa8a56c708923602..49f160a0d5fbf397b237e36a036d05fa9412bf56 100644
--- a/app/views/notify/closed_issue_email.text.haml
+++ b/app/views/notify/closed_issue_email.text.haml
@@ -1,3 +1,3 @@
 = "Issue was closed by #{@updated_by.name}"
 
-Issue ##{@issue.id}: #{project_issue_url(@issue.project, @issue)}
+Issue ##{@issue.iid}: #{project_issue_url(@issue.project, @issue)}
diff --git a/app/views/notify/closed_merge_request_email.html.haml b/app/views/notify/closed_merge_request_email.html.haml
index c6b45b1710a65dfdc81a1c51c6a5887dc35c2057..45770cc85ded25554b503f75ea64c822c3cba2ff 100644
--- a/app/views/notify/closed_merge_request_email.html.haml
+++ b/app/views/notify/closed_merge_request_email.html.haml
@@ -1,5 +1,5 @@
 %p
-  = "Merge Request #{@merge_request.id} was closed by #{@updated_by.name}"
+  = "Merge Request #{@merge_request.iid} was closed by #{@updated_by.name}"
 %p
   = link_to_gfm truncate(@merge_request.title, length: 40), project_merge_request_url(@merge_request.target_project, @merge_request)
 %p
diff --git a/app/views/notify/closed_merge_request_email.text.haml b/app/views/notify/closed_merge_request_email.text.haml
index 9a5bce5915afdf7411c09cc2d6291fd0ee012ef2..ee434ec8cb21cec7cebd6ab4d00e21edc947daee 100644
--- a/app/views/notify/closed_merge_request_email.text.haml
+++ b/app/views/notify/closed_merge_request_email.text.haml
@@ -1,4 +1,4 @@
-= "Merge Request #{@merge_request.id} was closed by #{@updated_by.name}"
+= "Merge Request #{@merge_request.iid} was closed by #{@updated_by.name}"
 
 Merge Request url: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
 
diff --git a/app/views/notify/group_access_granted_email.html.haml b/app/views/notify/group_access_granted_email.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..5023ec737a50b947528a03284b8d25a28c24e79f
--- /dev/null
+++ b/app/views/notify/group_access_granted_email.html.haml
@@ -0,0 +1,5 @@
+%p
+  = "You have been granted #{@membership.human_access} access to group"
+%p
+  = link_to group_url(@group) do
+    = @group.name
diff --git a/app/views/notify/group_access_granted_email.text.erb b/app/views/notify/group_access_granted_email.text.erb
new file mode 100644
index 0000000000000000000000000000000000000000..331bb98d5c94ab22439e93c8617a00b59f5cdc7f
--- /dev/null
+++ b/app/views/notify/group_access_granted_email.text.erb
@@ -0,0 +1,4 @@
+
+You have been granted <%= @membership.human_access %> access to group <%= @group.name %>
+
+<%= url_for(group_url(@group)) %>
diff --git a/app/views/notify/issue_status_changed_email.html.haml b/app/views/notify/issue_status_changed_email.html.haml
index 4cdb70994ce46fca3be76e0f13a4faf6588925c3..7706b3f7516259fb74b434c08bb12bcb76e7a553 100644
--- a/app/views/notify/issue_status_changed_email.html.haml
+++ b/app/views/notify/issue_status_changed_email.html.haml
@@ -1,5 +1,5 @@
 %p
   = "Issue was #{@issue_status} by #{@updated_by.name}"
 %p
-  = "Issue ##{@issue.id}"
+  = "Issue ##{@issue.iid}"
   = link_to_gfm truncate(@issue.title, length: 45), project_issue_url(@issue.project, @issue), title: @issue.title
diff --git a/app/views/notify/issue_status_changed_email.text.erb b/app/views/notify/issue_status_changed_email.text.erb
index bbca3474d5053f4471c7ea88b850ece9f3df8b08..4200881f7e8a009086be96aac46dcc8b8b41accd 100644
--- a/app/views/notify/issue_status_changed_email.text.erb
+++ b/app/views/notify/issue_status_changed_email.text.erb
@@ -1,4 +1,4 @@
 Issue was <%= @issue_status %> by <%= @updated_by.name %>
 
-Issue <%= @issue.id %>: <%= url_for(project_issue_url(@issue.project, @issue)) %>
+Issue <%= @issue.iid %>: <%= url_for(project_issue_url(@issue.project, @issue)) %>
 
diff --git a/app/views/notify/merged_merge_request_email.html.haml b/app/views/notify/merged_merge_request_email.html.haml
index e3ae41819f872f488b62d6f2c39a8a9642d4c4bd..e2bc9cf5c0442fdbeeadc7fc58fd2a31ab3b0d34 100644
--- a/app/views/notify/merged_merge_request_email.html.haml
+++ b/app/views/notify/merged_merge_request_email.html.haml
@@ -1,5 +1,5 @@
 %p
-  = "Merge Request #{@merge_request.id} was merged"
+  = "Merge Request #{@merge_request.iid} was merged"
 %p
   = link_to_gfm truncate(@merge_request.title, length: 40), project_merge_request_url(@merge_request.target_project, @merge_request)
 %p
diff --git a/app/views/notify/merged_merge_request_email.text.haml b/app/views/notify/merged_merge_request_email.text.haml
index fa9ef0a4b3216fe339dc4b9755da70b89aae0cbb..550f677fed49c8f3717e7aad6de900217b1205e3 100644
--- a/app/views/notify/merged_merge_request_email.text.haml
+++ b/app/views/notify/merged_merge_request_email.text.haml
@@ -1,4 +1,4 @@
-= "Merge Request #{@merge_request.id} was merged"
+= "Merge Request #{@merge_request.iid} was merged"
 
 Merge Request Url: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
 
diff --git a/app/views/notify/new_issue_email.html.haml b/app/views/notify/new_issue_email.html.haml
index f11c850641bf3ff3ecc247eb88ed8025112c3a37..3b3c148517a485ee5d696d55560ff4c3c97b87ce 100644
--- a/app/views/notify/new_issue_email.html.haml
+++ b/app/views/notify/new_issue_email.html.haml
@@ -1,7 +1,7 @@
 %p
   New Issue was created.
 %p
-  = "Issue ##{@issue.id}"
+  = "Issue ##{@issue.iid}"
   = link_to_gfm truncate(@issue.title, length: 45), project_issue_url(@issue.project, @issue), title: @issue.title
 %p
   Author: #{@issue.author_name}
diff --git a/app/views/notify/new_issue_email.text.erb b/app/views/notify/new_issue_email.text.erb
index 9907ca83247227543b9e744cc48c46f5b4d6adae..d36f54eb1ca582d6fd271bf666f56ce2df187976 100644
--- a/app/views/notify/new_issue_email.text.erb
+++ b/app/views/notify/new_issue_email.text.erb
@@ -1,5 +1,5 @@
 New Issue was created.
-          
-Issue <%= @issue.id %>: <%= url_for(project_issue_url(@issue.project, @issue)) %>
+
+Issue <%= @issue.iid %>: <%= url_for(project_issue_url(@issue.project, @issue)) %>
 Author:   <%= @issue.author_name %>
 Asignee:  <%= @issue.assignee_name %>
diff --git a/app/views/notify/new_merge_request_email.html.haml b/app/views/notify/new_merge_request_email.html.haml
index 3b060001e6bada597d6bc70687f0732b25f45b6b..6b2782ebb0b9b7a03477336c607632837fe68c1d 100644
--- a/app/views/notify/new_merge_request_email.html.haml
+++ b/app/views/notify/new_merge_request_email.html.haml
@@ -1,5 +1,5 @@
 %p
-  = "New Merge Request !#{@merge_request.id}"
+  = "New Merge Request !#{@merge_request.iid}"
 %p
   = link_to_gfm truncate(@merge_request.title, length: 40), project_merge_request_url(@merge_request.target_project, @merge_request)
 %p
diff --git a/app/views/notify/new_merge_request_email.text.erb b/app/views/notify/new_merge_request_email.text.erb
index 3f711840a516617f9412021355f3856edcbefe9f..2d27350486e4f0e36a1393ab890ec50157ff300e 100644
--- a/app/views/notify/new_merge_request_email.text.erb
+++ b/app/views/notify/new_merge_request_email.text.erb
@@ -1,4 +1,4 @@
-New Merge Request <%= @merge_request.id %>
+New Merge Request <%= @merge_request.iid %>
 
 <%= url_for(project_merge_request_url(@merge_request.target_project, @merge_request)) %>
 
diff --git a/app/views/notify/new_user_email.text.erb b/app/views/notify/new_user_email.text.erb
index 50ed595b38ac3d8a871bc3eb5fc40469aba9589e..c21c95d30474ec3dc20d39a2f22142fae02772d7 100644
--- a/app/views/notify/new_user_email.text.erb
+++ b/app/views/notify/new_user_email.text.erb
@@ -5,7 +5,7 @@ The Administrator created an account for you. Now you are a member of the compan
 login.................. <%= @user.email %>
 <% if @user.created_by_id %>
   password............... <%= @password %>
-  
+
   You will be forced to change this password immediately after login.
 <% end %>
 
diff --git a/app/views/notify/note_issue_email.html.haml b/app/views/notify/note_issue_email.html.haml
index ca1331260d358d4106bc7d69f2711f1af3775dae..b3230953e7ded9183ec393156b426b658930ea6d 100644
--- a/app/views/notify/note_issue_email.html.haml
+++ b/app/views/notify/note_issue_email.html.haml
@@ -1,4 +1,4 @@
 %p
-  = "New comment for Issue ##{@issue.id}"
+  = "New comment for Issue ##{@issue.iid}"
   = link_to_gfm truncate(@issue.title, length: 35), project_issue_url(@issue.project, @issue, anchor: "note_#{@note.id}")
 = render 'note_message'
diff --git a/app/views/notify/note_issue_email.text.erb b/app/views/notify/note_issue_email.text.erb
index a476b286ae457707115410affac11a356dcbd412..8a61f54a33744880c46f9ff36bbb57df1bd7df40 100644
--- a/app/views/notify/note_issue_email.text.erb
+++ b/app/views/notify/note_issue_email.text.erb
@@ -1,4 +1,4 @@
-New comment for Issue <%= @issue.id %>
+New comment for Issue <%= @issue.iid %>
 
 <%= url_for(project_issue_url(@issue.project, @issue, anchor: "note_#{@note.id}")) %>
 
diff --git a/app/views/notify/note_merge_request_email.html.haml b/app/views/notify/note_merge_request_email.html.haml
index 14abcca607014b4b140b87e1d4a173a4a5409f92..d587b0684863d5adfba8e27cb7bee5f7eeab6a48 100644
--- a/app/views/notify/note_merge_request_email.html.haml
+++ b/app/views/notify/note_merge_request_email.html.haml
@@ -3,6 +3,6 @@
     = link_to "New comment on diff", diffs_project_merge_request_url(@merge_request.target_project, @merge_request, anchor: "note_#{@note.id}")
   - else
     = link_to "New comment", project_merge_request_url(@merge_request.target_project, @merge_request, anchor: "note_#{@note.id}")
-  for Merge Request ##{@merge_request.id}
+  for Merge Request ##{@merge_request.iid}
   %cite "#{truncate(@merge_request.title, length: 20)}"
 = render 'note_message'
diff --git a/app/views/notify/note_merge_request_email.text.erb b/app/views/notify/note_merge_request_email.text.erb
index 3daa091db81d6b520182cfca99421aefb73300d6..79e72ca16c6fbb7d1cdcbd16dd461251830cd53d 100644
--- a/app/views/notify/note_merge_request_email.text.erb
+++ b/app/views/notify/note_merge_request_email.text.erb
@@ -1,9 +1,9 @@
-New comment for Merge Request <%= @merge_request.id %>
+New comment for Merge Request <%= @merge_request.iid %>
 
 <%= url_for(project_merge_request_url(@merge_request.target_project, @merge_request, anchor: "note_#{@note.id}")) %>
-      
+
 
 <%= @note.author_name %>
-                  
+
 <%= @note.note %>
 
diff --git a/app/views/notify/note_wall_email.text.erb b/app/views/notify/note_wall_email.text.erb
index 97910d5eb7988b602e3f2e9407e53b2cf85a0181..ee0dc3db1dbb54e194febce8762477e8447a7210 100644
--- a/app/views/notify/note_wall_email.text.erb
+++ b/app/views/notify/note_wall_email.text.erb
@@ -1,7 +1,7 @@
 New message on the project wall <%= @note.project %>
 
 <%= url_for(project_wall_url(@note.project, anchor: "note_#{@note.id}")) %>
-          
+
 
 <%= @note.author_name %>
 
diff --git a/app/views/notify/project_was_moved_email.text.erb b/app/views/notify/project_was_moved_email.text.erb
index 9c41073fddc93cf9e87963c5716466a692ee6d5b..7889c7b9cc4297a32f2d47a93e3ea7660ca630f5 100644
--- a/app/views/notify/project_was_moved_email.text.erb
+++ b/app/views/notify/project_was_moved_email.text.erb
@@ -1,8 +1,8 @@
 Project was moved to another location
-          
+
 The project is now located under 
 <%= project_url(@project) %>
-          
+
 
 To update the remote url in your local repository run:
   git remote set-url origin <%= @project.ssh_url_to_repo %>
diff --git a/app/views/notify/reassigned_issue_email.html.haml b/app/views/notify/reassigned_issue_email.html.haml
index 6d332af3d7008242594bd74658715685b17fc0d8..b0edff44ce6009dd7641d7f006879270694a0ff1 100644
--- a/app/views/notify/reassigned_issue_email.html.haml
+++ b/app/views/notify/reassigned_issue_email.html.haml
@@ -1,5 +1,5 @@
 %p
-  = "Reassigned Issue ##{@issue.id}"
+  = "Reassigned Issue ##{@issue.iid}"
   = link_to_gfm truncate(@issue.title, length: 30), project_issue_url(@issue.project, @issue)
 %p
   Assignee changed
diff --git a/app/views/notify/reassigned_issue_email.text.erb b/app/views/notify/reassigned_issue_email.text.erb
index 867c4d01da51c529c9b013ae1b0d7a8dfbe7dfa0..bc0d0567922f40fcfbe424c04d7c9e221f8824bb 100644
--- a/app/views/notify/reassigned_issue_email.text.erb
+++ b/app/views/notify/reassigned_issue_email.text.erb
@@ -1,5 +1,5 @@
-Reassigned Issue <%= @issue.id %>
+Reassigned Issue <%= @issue.iid %>
 
 <%= url_for(project_issue_url(@issue.project, @issue)) %>
-          
+
 Assignee changed <%= "from #{@previous_assignee.name}" if @previous_assignee %> to <%= @issue.assignee_name %>
diff --git a/app/views/notify/reassigned_merge_request_email.html.haml b/app/views/notify/reassigned_merge_request_email.html.haml
index 314b2882672203cbcb09e8a9a531b3de82383864..3a615f86e69edce9ffc5dba7bc6e29f042bb2ecb 100644
--- a/app/views/notify/reassigned_merge_request_email.html.haml
+++ b/app/views/notify/reassigned_merge_request_email.html.haml
@@ -1,5 +1,5 @@
 %p
-  = "Reassigned Merge Request !#{@merge_request.id}"
+  = "Reassigned Merge Request !#{@merge_request.iid}"
   = link_to_gfm truncate(@merge_request.title, length: 30), project_merge_request_url(@merge_request.target_project, @merge_request)
 %p
   Assignee changed
diff --git a/app/views/notify/reassigned_merge_request_email.text.erb b/app/views/notify/reassigned_merge_request_email.text.erb
index 05a9797165da850a77eef3ba52a6b6174801512d..eecf055ff6f800821168e293d9ec1088a9136f62 100644
--- a/app/views/notify/reassigned_merge_request_email.text.erb
+++ b/app/views/notify/reassigned_merge_request_email.text.erb
@@ -1,7 +1,7 @@
-Reassigned Merge Request <%= @merge_request.id %>
+Reassigned Merge Request <%= @merge_request.iid %>
 
 <%= url_for(project_merge_request_url(@merge_request.target_project, @merge_request)) %>
-          
+
 
 Assignee changed <%= "from #{@previous_assignee.name}" if @previous_assignee %> to <%= @merge_request.assignee_name %>
 
diff --git a/app/views/profiles/account.html.haml b/app/views/profiles/account.html.haml
index d711d55ec99da82b685ba431bee71ca3acc16a29..42c7ec051cbbdd05ad216027483c2efefe9ad1c6 100644
--- a/app/views/profiles/account.html.haml
+++ b/app/views/profiles/account.html.haml
@@ -5,91 +5,137 @@
   - if current_user.ldap_user?
     Some options are unavailable for LDAP accounts
 %hr
-- unless current_user.ldap_user?
-  - if Gitlab.config.omniauth.enabled
-    %fieldset
-      %legend Social Accounts
-      .oauth_select_holder
-        %p.hint Tip: Click on icon to activate signin with one of the following services
-        - enabled_social_providers.each do |provider|
-          %span{class: oauth_active_class(provider) }
-            = link_to authbutton(provider, 32), omniauth_authorize_path(User, provider)
 
 
-  %fieldset.update-password
-    %legend Password
-    = form_for @user, url: update_password_profile_path, method: :put do |f|
-      .padded
-        %p.slead After a successful password update you will be redirected to login page where you should login with your new password
-        -if @user.errors.any?
-          .alert.alert-error
-            %ul
-              - @user.errors.full_messages.each do |msg|
-                %li= msg
+.row
+  .span2
+    %ul.nav.nav-pills.nav-stacked.nav-stacked-menu
+      %li.active
+        = link_to '#tab-token', 'data-toggle' => 'tab' do
+          Private Token
+      %li
+        = link_to '#tab-password', 'data-toggle' => 'tab' do
+          Password
 
-        .control-group
-          = f.label :password
-          .controls= f.password_field :password, required: true
-        .control-group
-          = f.label :password_confirmation
-          .controls
-            = f.password_field :password_confirmation, required: true
-        .control-group
-          .controls
-            = f.submit 'Save password', class: "btn btn-save"
+      - if show_profile_social_tab?
+        %li
+          = link_to '#tab-social', 'data-toggle' => 'tab' do
+            Social Accounts
 
+      - if show_profile_username_tab?
+        %li
+          = link_to '#tab-username', 'data-toggle' => 'tab' do
+            Change Username
 
+      - if show_profile_remove_tab?
+        %li
+          = link_to '#tab-remove', 'data-toggle' => 'tab' do
+            Remove Account
+  .span10
+    .tab-content
+      .tab-pane.active#tab-token
+        %fieldset.update-token
+          %legend
+            Private token
+            %span.cred.pull-right
+              keep it secret!
+          %div
+            = form_for @user, url: reset_private_token_profile_path, method: :put do |f|
+              .data
+                %p.slead
+                  Your private token is used to access application resources without authentication.
+                  %br
+                  It can be used for atom feeds or the API.
+                %p.cgray
+                  - if current_user.private_token
+                    = text_field_tag "token", current_user.private_token, class: "input-xxlarge large_text input-xpadding"
+                    = f.submit 'Reset', confirm: "Are you sure?", class: "btn 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.update-token
-  %legend
-    Private token
-    %span.cred.pull-right
-      keep it secret!
-  .padded
-    = form_for @user, url: reset_private_token_profile_path, method: :put do |f|
-      .data
-        %p.slead
-          Your private token is used to access application resources without authentication.
-          %br
-          It can be used for atom feeds or the API.
-        %p.cgray
-          - if current_user.private_token
-            = text_field_tag "token", current_user.private_token, class: "input-xxlarge large_text input-xpadding"
-            = f.submit 'Reset', confirm: "Are you sure?", class: "btn btn-primary btn-build-token"
+      .tab-pane#tab-password
+        %fieldset.update-password
+          %legend Password
+          - if current_user.ldap_user?
+            %h3.nothing_here_message Not available for LDAP user
           - else
-            %span You don`t have one yet. Click generate to fix it.
-            = f.submit 'Generate', class: "btn success btn-build-token"
+            = form_for @user, url: update_password_profile_path, method: :put do |f|
+              %div
+                %p.slead
+                  You must provide current password in order to change it.
+                  %br
+                  After a successful password update you will be redirected to login page where you should login with your new password
+                -if @user.errors.any?
+                  .alert.alert-error
+                    %ul
+                      - @user.errors.full_messages.each do |msg|
+                        %li= msg
+                .control-group
+                  = f.label :current_password, class: 'cgreen'
+                  .controls= f.password_field :current_password, required: true
+                .control-group
+                  = f.label :password, 'New password'
+                  .controls= f.password_field :password, required: true
+                .control-group
+                  = f.label :password_confirmation
+                  .controls
+                    = f.password_field :password_confirmation, required: true
+                .control-group
+                  .controls
+                    = f.submit 'Save password', class: "btn btn-save"
 
+      - if show_profile_social_tab?
+        .tab-pane#tab-social
+          %fieldset
+            %legend Social Accounts
+            .oauth_select_holder
+              %p.hint Tip: Click on icon to activate signin with one of the following services
+              - enabled_social_providers.each do |provider|
+                %span{class: oauth_active_class(provider) }
+                  = link_to authbutton(provider, 32), omniauth_authorize_path(User, provider)
 
-- if current_user.can_change_username?
-  %fieldset.update-username
-    %legend
-      Username
-      %small.cred.pull-right
-        Changing your username can have unintended side effects!
-    = form_for @user, url: update_username_profile_path,  method: :put, remote: true do |f|
-      .padded
-        = f.label :username
-        .controls
-          = f.text_field :username, required: true
-          &nbsp;
-          %span.loading-gif.hide= image_tag "ajax_loader.gif"
-          %span.update-success.cgreen.hide
-            %i.icon-ok
-            Saved
-          %span.update-failed.cred.hide
-            %i.icon-remove
-            Failed
-          %ul.cred
-            %li This will change the web URL for personal projects.
-            %li This will change the git path to repositories for personal projects.
-        .controls
-          = f.submit 'Save username', class: "btn btn-save"
+      - if show_profile_username_tab?
+        .tab-pane#tab-username
+          %fieldset.update-username
+            %legend
+              Username
+              %small.cred.pull-right
+                Changing your username can have unintended side effects!
+            = form_for @user, url: update_username_profile_path,  method: :put, remote: true do |f|
+              %div
+              .control-group
+                = f.label :username
+                .controls
+                  = f.text_field :username, required: true
+                  &nbsp;
+                  %span.loading-gif.hide= image_tag "ajax_loader.gif"
+                  %span.update-success.cgreen.hide
+                    %i.icon-ok
+                    Saved
+                  %span.update-failed.cred.hide
+                    %i.icon-remove
+                    Failed
+                  %ul.cred
+                    %li This will change the web URL for personal projects.
+                    %li This will change the git path to repositories for personal projects.
+                .controls
+                  = f.submit 'Save username', class: "btn btn-save"
 
-- if gitlab_config.signup_enabled
-  %fieldset.remove-account
-    %legend
-      Remove account
-      %small.cred.pull-right
-        Before removing the account you must remove all projects!
-    = link_to 'Delete account', user_registration_path, confirm: "REMOVE #{current_user.name}? Are you sure?", method: :delete, class: "btn btn-remove delete-key btn-small pull-right"
+      - if show_profile_remove_tab?
+        .tab-pane#tab-remove
+          %fieldset.remove-account
+            %legend
+              Remove account
+            %div
+              %p Deleting an account has the following effects:
+              %ul
+                %li All user content like authored issues, snippets, comments will be removed
+                - rp = current_user.personal_projects.count
+                - unless rp.zero?
+                  %li #{pluralize rp, 'personal project'} will be removed and cannot be restored
+                - if current_user.solo_owned_groups.present?
+                  %li
+                    Next groups will be abandoned. You should transfer or remove them:
+                    %strong #{current_user.solo_owned_groups.map(&:name).join(', ')}
+              = link_to 'Delete account', user_registration_path, confirm: "REMOVE #{current_user.name}? Are you sure?", method: :delete, class: "btn btn-remove"
diff --git a/app/views/projects/_clone_panel.html.haml b/app/views/projects/_clone_panel.html.haml
index 7228c760d27cdceb4cd4ba274a581078507f63be..c2f85e8ebe8329229a9872fcd847b17f4e0cd256 100644
--- a/app/views/projects/_clone_panel.html.haml
+++ b/app/views/projects/_clone_panel.html.haml
@@ -5,7 +5,7 @@
     .span3.pull-right
       .pull-right
         - unless @project.empty_repo?
-          - if can?(current_user, :fork_project, @project) && @project.namespace != current_user.namespace
+          - if current_user && can?(current_user, :fork_project, @project) && @project.namespace != current_user.namespace
             - if current_user.already_forked?(@project)
               = link_to project_path(current_user.fork_of(@project)), class: 'btn grouped disabled' do
                 %i.icon-code-fork
@@ -19,37 +19,38 @@
               %i.icon-download-alt
               %span.only-wide Download
 
-        .dropdown.pull-right
-          %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
-            %i.icon-plus-sign-alt
-            %span.only-wide New
-            %b.caret
-          %ul.dropdown-menu
-            - if @project.issues_enabled && can?(current_user, :write_issue, @project)
-              %li
-                = link_to url_for_new_issue, title: "New Issue" do
-                  Issue
-            - if @project.merge_requests_enabled && can?(current_user, :write_merge_request, @project)
-              %li
-                = link_to new_project_merge_request_path(@project), title: "New Merge Request" do
-                  Merge Request
-            - if @project.snippets_enabled && can?(current_user, :write_snippet, @project)
-              %li
-                = link_to new_project_snippet_path(@project), title: "New Snippet" do
-                  Snippet
-            - if can? current_user, :push_code, @project
-              %li.divider
-              %li
-                = link_to new_project_branch_path(@project) do
-                  %i.icon-code-fork
-                  Git branch
-              %li
-                = link_to new_project_tag_path(@project) do
-                  %i.icon-tag
-                  Git tag
+        - if current_user
+          .dropdown.pull-right
+            %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
+              %i.icon-plus-sign-alt
+              %span.only-wide New
+              %b.caret
+            %ul.dropdown-menu
+              - if @project.issues_enabled && can?(current_user, :write_issue, @project)
+                %li
+                  = link_to url_for_new_issue, title: "New Issue" do
+                    Issue
+              - if @project.merge_requests_enabled && can?(current_user, :write_merge_request, @project)
+                %li
+                  = link_to new_project_merge_request_path(@project), title: "New Merge Request" do
+                    Merge Request
+              - if @project.snippets_enabled && can?(current_user, :write_snippet, @project)
+                %li
+                  = link_to new_project_snippet_path(@project), title: "New Snippet" do
+                    Snippet
+              - if can? current_user, :push_code, @project
+                %li.divider
+                %li
+                  = link_to new_project_branch_path(@project) do
+                    %i.icon-code-fork
+                    Git branch
+                %li
+                  = link_to new_project_tag_path(@project) do
+                    %i.icon-tag
+                    Git tag
 
-            - if can?(current_user, :admin_team_member, @project)
-              %li.divider
-              %li
-                = link_to new_project_team_member_path(@project), title: "New project member" do
-                  Project member
+              - if can?(current_user, :admin_team_member, @project)
+                %li.divider
+                %li
+                  = link_to new_project_team_member_path(@project), title: "New project member" do
+                    Project member
diff --git a/app/views/projects/blob/_download.html.haml b/app/views/projects/blob/_download.html.haml
index f3da1a2a2196609e2f0f9f406b50f89b83259334..ff317f9020967e356bb81d4e773d411220b2c3ef 100644
--- a/app/views/projects/blob/_download.html.haml
+++ b/app/views/projects/blob/_download.html.haml
@@ -1,8 +1,7 @@
-.file-content.blob_file
+.file-content.blob_file.blob-no-preview
   %center
     = link_to project_raw_path(@project, @id) do
-      %div.padded
-        %h4
-          %i.icon-download-alt
-          %br
-          Download (#{number_to_human_size blob.size})
+      %h1.light
+        %i.icon-download-alt
+      %h4
+        Download (#{number_to_human_size blob.size})
diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml
index 026948aa0275fea71d540880d98ea0987b880ec8..b83925257918ee631f1d464824941a701c16e8f0 100644
--- a/app/views/projects/branches/_branch.html.haml
+++ b/app/views/projects/branches/_branch.html.haml
@@ -13,6 +13,10 @@
         = link_to archive_project_repository_path(@project, ref: branch.name), class: 'btn grouped btn-small' do
           %i.icon-download-alt
           Download
+      = link_to project_compare_index_path(@project, from: branch.name, to: branch.name), class: 'btn grouped btn-small', title: "Compare" do
+        %i.icon-copy
+        Compare
+
       - if can?(current_user, :admin_project, @project) && branch.name != @repository.root_ref
         = link_to project_branch_path(@project, branch.name), class: 'btn grouped btn-small remove-row', method: :delete, confirm: 'Removed branch cannot be restored. Are you sure?', remote: true do
           %i.icon-trash
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index eb5bdb886e29e39894684887d140f92c85de77f1..d70fd96accdf22d8f5872b5b9073e45a02fa91fb 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -1,21 +1,19 @@
 %li.commit
-  .browse_code_link_holder
-    %p
-      %strong= link_to "Browse Code »", project_tree_path(project, commit), class: "right"
-  %p
+  .commit-row-title
     = link_to commit.short_id(8), project_commit_path(project, commit), class: "commit_short_id"
-    = commit_author_link(commit, avatar: true, size: 24)
     &nbsp;
-    = link_to_gfm truncate(commit.title, length: 70), project_commit_path(project, commit.id), class: "row_title"
-
-    %time.committed_ago{ datetime: commit.committed_date, title: commit.committed_date.stamp("Aug 21, 2011 9:23pm") }
-      = time_ago_in_words(commit.committed_date)
-      ago
-      &nbsp;
-
-    %span.notes_count
+    = link_to_gfm truncate(commit.title, length: 70), project_commit_path(project, commit.id), class: "commit-row-message"
+    = link_to "Browse Code »", project_tree_path(project, commit), class: "pull-right"
+    .notes_count
       - notes = project.notes.for_commit_id(commit.id)
       - if notes.any?
         %span.badge.badge-info
           %i.icon-comment
           = notes.count
+
+  .commit-row-info
+    = commit_author_link(commit, avatar: true, size: 16)
+    %time.committed_ago{ datetime: commit.committed_date, title: commit.committed_date.stamp("Aug 21, 2011 9:23pm") }
+      = time_ago_in_words(commit.committed_date)
+      ago
+      &nbsp;
diff --git a/app/views/projects/commits/_commits.html.haml b/app/views/projects/commits/_commits.html.haml
index fd0616f9acc4dfe117d82abd494a6655c3c54e51..b6404778073e5bb3ef3dd8d9318ac8d4f314c83b 100644
--- a/app/views/projects/commits/_commits.html.haml
+++ b/app/views/projects/commits/_commits.html.haml
@@ -1,8 +1,11 @@
 - @commits.group_by { |c| c.committed_date.to_date }.sort.reverse.each do |day, commits|
-  .ui-box.small-box
-    .title
-      %i.icon-calendar
-      %span= day.stamp("28 Aug, 2010")
-      .pull-right
-        %small= pluralize(commits.count, 'commit')
-    %ul.well-list= render commits, project: @project
+  .row.commits-row
+    .span2
+      %h4
+        %i.icon-calendar
+        %span= day.stamp("28 Aug, 2010")
+      %p= pluralize(commits.count, 'commit')
+    .span10
+      %ul.well-list
+        = render commits, project: @project
+  %hr.lists-separator
diff --git a/app/views/projects/commits/_diffs.html.haml b/app/views/projects/commits/_diffs.html.haml
index 5a3a9bd16aff682d30a027d27a92df191203d534..2e61b9ece19b77e66725f32e122430b96f3873a5 100644
--- a/app/views/projects/commits/_diffs.html.haml
+++ b/app/views/projects/commits/_diffs.html.haml
@@ -1,11 +1,25 @@
+- @suppress_diff ||= @suppress_diff || @force_suppress_diff
 - if @suppress_diff
   .alert.alert-block
     %p
-      %strong Warning! Large commit with more than #{Commit::DIFF_SAFE_SIZE} files changed.
-    %p To preserve performance the diff is not shown.
+      %strong Warning! This is a large diff.
     %p
-      But if you still want to see the diff
-      = link_to "click this link", project_commit_path(project, @commit, force_show_diff: true), class: "underlined_link"
+      To preserve performance the diff is not shown.
+      - if current_controller?(:commit) or current_controller?(:merge_requests)
+        Please, download the diff as
+        - if current_controller?(:commit)
+          = link_to "plain diff", project_commit_path(@project, @commit, format: :diff), class: "underlined_link"
+          or
+          = link_to "email patch", project_commit_path(@project, @commit, format: :patch), class: "underlined_link"
+        - else
+          = link_to "plain diff", project_merge_request_path(@project, @merge_request, format: :diff), class: "underlined_link"
+          or
+          = link_to "email patch", project_merge_request_path(@project, @merge_request, format: :patch), class: "underlined_link"
+        instead.
+    - unless @force_suppress_diff
+      %p
+        If you still want to see the diff
+        = link_to "click this link", url_for(force_show_diff: true), class: "underlined_link"
 
 %p.commit-stat-summary
   Showing
@@ -23,9 +37,9 @@
   - unless @suppress_diff
     - diffs.each_with_index do |diff, i|
       - next if diff.diff.empty?
-      - file = Gitlab::Git::Blob.new(project.repository, @commit.id, @ref, diff.new_path)
-      - file = Gitlab::Git::Blob.new(project.repository, @commit.parent_id, @ref, diff.old_path) unless file.exists?
-      - next unless file.exists?
+      - file = project.repository.blob_at(@commit.id, diff.new_path)
+      - file = project.repository.blob_at(@commit.parent_id, diff.old_path) unless file
+      - next unless file
       .file{id: "diff-#{i}"}
         .header
           - if diff.deleted_file
@@ -50,7 +64,7 @@
           - if file.text?
             = render "projects/commits/text_file", diff: diff, index: i
           - elsif file.image?
-            - old_file = Gitlab::Git::Blob.new(project.repository, @commit.parent_id, @ref, diff.old_path) if @commit.parent_id
+            - old_file = project.repository.blob_at(@commit.parent_id, diff.old_path) if @commit.parent_id
             = render "projects/commits/image", diff: diff, old_file: old_file, file: file, index: i
           - else
             %p.nothing_here_message No preview for this file type
diff --git a/app/views/projects/commits/_head.html.haml b/app/views/projects/commits/_head.html.haml
index c16abac7f171c0860f706348c9899ac619f2424f..c2da9f273b3ed835986c5d7e4c3eb0dade26b4b8 100644
--- a/app/views/projects/commits/_head.html.haml
+++ b/app/views/projects/commits/_head.html.haml
@@ -4,7 +4,7 @@
   = nav_link(controller: [:commit, :commits]) do
     = link_to 'Commits', project_commits_path(@project, @repository.root_ref)
   = nav_link(controller: :compare) do
-    = link_to 'Compare', project_compare_index_path(@project)
+    = link_to 'Compare', project_compare_index_path(@project, from: @repository.root_ref, to: @ref || @repository.root_ref)
 
   = nav_link(html_options: {class: branches_tab_class}) do
     = link_to recent_project_branches_path(@project) do
@@ -21,7 +21,7 @@
       Stats
 
 
-  - if current_controller?(:commits) && current_user.private_token
+  - if current_user && current_controller?(:commits) && current_user.private_token
     %li.pull-right
       = link_to project_commits_path(@project, @ref, {format: :atom, private_token: current_user.private_token}), title: "Feed" do
         %i.icon-rss
diff --git a/app/views/projects/commits/_image.html.haml b/app/views/projects/commits/_image.html.haml
index db02fa333b93779587b9414e406df83f10a6c902..73f87289d3db1486de190791dbb764709fd09d21 100644
--- a/app/views/projects/commits/_image.html.haml
+++ b/app/views/projects/commits/_image.html.haml
@@ -9,7 +9,7 @@
     %div.two-up.view
       %span.wrap
         .frame.deleted
-          %a{href: project_tree_path(@project, tree_join(@commit.id, diff.old_path))}
+          %a{href: project_blob_path(@project, tree_join(@commit.parent_id, diff.old_path))}
             %img{src: "data:#{old_file.mime_type};base64,#{Base64.encode64(old_file.data)}"}
         %p.image-info.hide
           %span.meta-filesize= "#{number_to_human_size old_file.size}"
@@ -21,7 +21,7 @@
           %span.meta-height
       %span.wrap
         .frame.added
-          %a{href: project_tree_path(@project, tree_join(@commit.id, diff.new_path))}
+          %a{href: project_blob_path(@project, tree_join(@commit.id, diff.new_path))}
             %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"}
         %p.image-info.hide
           %span.meta-filesize= "#{number_to_human_size file.size}"
diff --git a/app/views/projects/commits/_inline_commit.html.haml b/app/views/projects/commits/_inline_commit.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..5be8460e06130ed38abf51f7d1f07e442f99f577
--- /dev/null
+++ b/app/views/projects/commits/_inline_commit.html.haml
@@ -0,0 +1,9 @@
+%li.commit.inline-commit
+  .commit-row-title
+    = link_to commit.short_id(8), project_commit_path(project, commit), class: "commit_short_id"
+    &nbsp;
+    = link_to_gfm truncate(commit.title, length: 40), project_commit_path(project, commit.id), class: "commit-row-message"
+    %time.committed_ago{ datetime: commit.committed_date, title: commit.committed_date.stamp("Aug 21, 2011 9:23pm") }
+      = time_ago_in_words(commit.committed_date)
+      ago
+      &nbsp;
diff --git a/app/views/projects/compare/_form.html.haml b/app/views/projects/compare/_form.html.haml
index 503b39c0663858db7b1d2494d6b98fef7e668f26..ca1ea4073e6ea4b51fc453d1241a93cb27d20651 100644
--- a/app/views/projects/compare/_form.html.haml
+++ b/app/views/projects/compare/_form.html.haml
@@ -1,30 +1,21 @@
-%div
-  - unless params[:to]
-    %p.slead
-      Fill input field with commit id like
-      %code.label-branch 4eedf23
-      or branch/tag name like
-      %code.label-branch master
-      and press compare button for the commits list and a code diff.
-      %br
-      Changes are shown <b>from</b> the version in the first field <b>to</b> the version in the second field.
-
-
-  = form_tag project_compare_index_path(@project), method: :post do
-    .clearfix
-      .pull-left
-        - if params[:to] && params[:from]
-          = link_to 'switch', {from: params[:to], to: params[:from]}, {class: 'commits-compare-switch has_tooltip', title: 'Switch base of comparison'}
-        = text_field_tag :from, params[:from], placeholder: "from", class: "input-xlarge input-xpadding"
-        = "..."
-        = text_field_tag :to, params[:to], placeholder: "to", class: "input-xlarge input-xpadding"
-      .pull-left
-        &nbsp;
-        = submit_tag "Compare", class: "btn btn-create commits-compare-btn"
-    - if @refs_are_same
-      .alert
-        %span Refs are the same
-
+= form_tag project_compare_index_path(@project), method: :post do
+  .clearfix
+    .pull-left
+      - if params[:to] && params[:from]
+        = link_to 'switch', {from: params[:to], to: params[:from]}, {class: 'commits-compare-switch has_tooltip', title: 'Switch base of comparison'}
+      .input-prepend
+        %span.add-on.input-xpadding from
+        = text_field_tag :from, params[:from], class: "span3 input-xpadding"
+      = "..."
+      .input-prepend
+        %span.add-on.input-xpadding to
+        = text_field_tag :to, params[:to], class: "span3 input-xpadding"
+    .pull-left
+      &nbsp;
+      = submit_tag "Compare", class: "btn btn-create commits-compare-btn"
+      - if compare_to_mr_button?
+        = link_to compare_mr_path, class: 'prepend-left-10' do
+          %strong Make a merge request
 
 
 :javascript
diff --git a/app/views/projects/compare/index.html.haml b/app/views/projects/compare/index.html.haml
index 8f108ed0b08932898859200945c0075536b31f29..4745bfbeaaf061e5a1f896ed2864f0ac76b2be73 100644
--- a/app/views/projects/compare/index.html.haml
+++ b/app/views/projects/compare/index.html.haml
@@ -2,5 +2,15 @@
 
 %h3.page-title
   Compare View
+%p.slead
+  Compare branches, tags or commit ranges.
+  %br
+  Fill input field with commit id like
+  %code.label-branch 4eedf23
+  or branch/tag name like
+  %code.label-branch master
+  and press compare button for the commits list and a code diff.
+  %br
+  Changes are shown <b>from</b> the version in the first field <b>to</b> the version in the second field.
 
 = render "form"
diff --git a/app/views/projects/compare/show.html.haml b/app/views/projects/compare/show.html.haml
index af9273f9315b5eee7eec8ba9dbe40891eaea3485..4be62d3691742dcfad2c00f6f616b99117d6b4fa 100644
--- a/app/views/projects/compare/show.html.haml
+++ b/app/views/projects/compare/show.html.haml
@@ -20,3 +20,16 @@
   - unless @diffs.empty?
     %h4 Diff
     = render "projects/commits/diffs", diffs: @diffs, project: @project
+- else
+  .light-well
+    %center
+      %h4
+        There isn't anything to compare.
+      %p.slead
+        - if params[:to] == params[:from]
+          You'll need to use different branch names to get a valid comparison.
+        - else
+          %span.label-branch #{params[:from]}
+          and
+          %span.label-branch #{params[:to]}
+          are the same.
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index 99e334cc6b8225b09b6f904b6c62e89b003e7434..9f3502e90de9b0fef2f7c88f9f4ffba18b6eb0f3 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -16,8 +16,8 @@
       %legend Git global setup:
       %pre.dark
         :preserve
-          git config --global user.name "#{current_user.name}"
-          git config --global user.email "#{current_user.email}"
+          git config --global user.name "#{git_user_name}"
+          git config --global user.email "#{git_user_email}"
 
     %fieldset
       %legend Create Repository
@@ -29,7 +29,8 @@
           touch README
           git add README
           git commit -m 'first commit'
-          git remote add origin #{@project.url_to_repo}
+        %span.clone= "git remote add origin #{@project.url_to_repo}"
+        :preserve
           git push -u origin master
 
     %fieldset
@@ -37,7 +38,8 @@
       %pre.dark
         :preserve
           cd existing_git_repo
-          git remote add origin #{@project.url_to_repo}
+        %span.clone= "git remote add origin #{@project.url_to_repo}"
+        :preserve
           git push -u origin master
 
   - if can? current_user, :remove_project, @project
diff --git a/app/views/projects/issues/_form.html.haml b/app/views/projects/issues/_form.html.haml
index 957cc5a7e2d9ed49116b9bd3fab775fda935731b..6acad9134d1e67eead4fba2bf79d76fb119834d4 100644
--- a/app/views/projects/issues/_form.html.haml
+++ b/app/views/projects/issues/_form.html.haml
@@ -67,8 +67,8 @@
         event.preventDefault();
       }
     })
-    .bind( "click", function( event ) {
-        $( this ).autocomplete("search", "");
+    .bind("click", function(event) {
+      $(this).autocomplete("search", "");
     })
     .autocomplete({
       minLength: 0,
diff --git a/app/views/projects/issues/_head.html.haml b/app/views/projects/issues/_head.html.haml
index 44d14d5cdf9299e0284eab1b96ab91501b9595c4..438cc02b47719c29ac5e36bb925cf0194f2d2b4d 100644
--- a/app/views/projects/issues/_head.html.haml
+++ b/app/views/projects/issues/_head.html.haml
@@ -5,6 +5,7 @@
     = link_to 'Milestones', project_milestones_path(@project), class: "tab"
   = nav_link(controller: :labels) do
     = link_to 'Labels', project_labels_path(@project), class: "tab"
-  %li.pull-right
-    = link_to project_issues_path(@project, :atom, { private_token: current_user.private_token }) do
-      %i.icon-rss
+  - if current_user
+    %li.pull-right
+      = link_to project_issues_path(@project, :atom, { private_token: current_user.private_token }) do
+        %i.icon-rss
diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index d36a831432d7e95b3fb2c2033b131cc66520f145..6d1a088721ccb33eec75953847904f9a45df0d4d 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -6,9 +6,10 @@
     = @issue.created_at.stamp("Aug 21, 2011")
 
   %span.pull-right
-    = link_to new_project_issue_path(@project), class: "btn grouped", title: "New Issue", id: "new_issue_link" do
-      %i.icon-plus
-      New Issue
+    - if can?(current_user, :write_issue, @project)
+      = link_to new_project_issue_path(@project), class: "btn grouped", title: "New Issue", id: "new_issue_link" do
+        %i.icon-plus
+        New Issue
     - if can?(current_user, :modify_issue, @issue)
       - if @issue.closed?
         = link_to 'Reopen', project_issue_path(@project, @issue, issue: {state_event: :reopen }, status_only: true), method: :put,  class: "btn grouped reopen_issue"
diff --git a/app/views/projects/merge_requests/_form.html.haml b/app/views/projects/merge_requests/_form.html.haml
index 5e94f1fdf18ae37f3ef88302c4bc82a2ae7a95f1..ce72756303e76ce190f710720ac6fc65a482c67b 100644
--- a/app/views/projects/merge_requests/_form.html.haml
+++ b/app/views/projects/merge_requests/_form.html.haml
@@ -5,41 +5,32 @@
         - @merge_request.errors.full_messages.each do |msg|
           %li= msg
 
-  %h3.page-title
-    Branches
   .merge-request-branches
-  .row
-    .span5
-      .ui-box
-        .title From
-        .ui-box-head
-          Project:
-          = f.select(:source_project_id,[[@merge_request.source_project.path_with_namespace,@merge_request.source_project.id]] , {}, {class: 'source_project chosen span4'})
-          .prepend-top-10
+    .row
+      .span5
+        .clearfix
+          .pull-left
+            = f.select(:source_project_id,[[@merge_request.source_project.path_with_namespace,@merge_request.source_project.id]] , {}, {class: 'source_project chosen span3'})
+          .pull-left
+            &nbsp;
             %i.icon-code-fork
-            Branch:
-            = f.select(:source_branch, @merge_request.source_project.repository.branch_names, { include_blank: "Select branch" }, {class: 'source_branch chosen span3'})
-          .mr_source_commit.prepend-top-10
-    .span2
-      %h1.merge-request-angle
-        %i.icon-angle-right
-    .span5
-      .ui-box
-        .title To
-        .ui-box-head
-          - projects =  @project.forked_from_project.nil? ? [@project] : [ @project,@project.forked_from_project]
-          Project:
-          = f.select(:target_project_id, projects.map { |proj| [proj.path_with_namespace,proj.id] }, {include_blank: "Select Target Project" }, {class: 'target_project chosen span4'})
-          .prepend-top-10
+            = f.select(:source_branch, @merge_request.source_project.repository.branch_names, { include_blank: "Select branch" }, {class: 'source_branch chosen span2'})
+        .mr_source_commit.prepend-top-10
+      .span2
+        %h2.merge-request-angle.light
+          %i.icon-long-arrow-right
+      .span5
+        .clearfix
+          .pull-left
+            - projects =  @project.forked_from_project.nil? ? [@project] : [ @project,@project.forked_from_project]
+            = f.select(:target_project_id, projects.map { |proj| [proj.path_with_namespace,proj.id] }, {include_blank: "Select Target Project" }, {class: 'target_project chosen span3'})
+          .pull-left
+            &nbsp;
             %i.icon-code-fork
-            Branch:
-            = f.select(:target_branch, @target_branches, { include_blank: "Select branch" }, {class: 'target_branch chosen span3'})
-          .mr_target_commit.prepend-top-10
+            = f.select(:target_branch, @target_branches, { include_blank: "Select branch" }, {class: 'target_branch chosen span2'})
+        .mr_target_commit.prepend-top-10
 
   %hr
-
-  %h3.page-title
-    Details
   .merge-request-form-info
     .control-group
       = f.label :title do
@@ -56,6 +47,12 @@
           %i.icon-time
           Milestone
         .controls= f.select(:milestone_id, @project.milestones.active.all.map {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" }, {class: 'chosen'})
+    .control-group
+      = f.label :description, "Description"
+      .controls
+        = f.text_area :description, class: "input-xxlarge js-gfm-input", rows: 14
+        %p.hint Description is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
+
 
   .form-actions
     - if @merge_request.new_record?
diff --git a/app/views/projects/merge_requests/show/_mr_box.html.haml b/app/views/projects/merge_requests/show/_mr_box.html.haml
index c4b614b51da467e33a63aa132ebe6b93019ca9e1..1f750e22c6571439914c2f3e336309f7ab5033dd 100644
--- a/app/views/projects/merge_requests/show/_mr_box.html.haml
+++ b/app/views/projects/merge_requests/show/_mr_box.html.haml
@@ -21,6 +21,12 @@
         %strong= link_to_gfm truncate(milestone.title, length: 20), project_milestone_path(milestone.project, milestone)
 
 
+  - if @merge_request.description.present?
+    .ui-box-bottom
+      .wiki
+        = preserve do
+          = markdown @merge_request.description
+
   - if @merge_request.closed?
     .ui-box-bottom.alert-error
       %span
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index 736da85952a688caec9b8063be1eb50e182d6fab..0213576927bc5710bb66b835cb8d8ff084a48442 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -2,9 +2,7 @@
   .project-edit-errors
     = render 'projects/errors'
   .project-edit-content
-    %p.slead
-      New projects are private by default. You choose who can see the project and commit to repository.
-    %hr
+
     = form_for @project, remote: true do |f|
       .control-group.project-name-holder
         = f.label :name do
@@ -49,6 +47,12 @@
           %span.light (optional)
         .controls
           = f.text_area :description, placeholder: "awesome project", class: "input-xlarge", rows: 3, maxlength: 250, tabindex: 3
+      .control-group.project-public-holder
+        = f.label :public do
+          %span Public project
+        .controls
+          = f.check_box :public, { checked: Gitlab.config.gitlab.default_projects_features.public }, true, false
+          %span.help-inline Make project visible to everyone
 
       .form-actions
         = f.submit 'Create project', class: "btn btn-create project-submit", tabindex: 4
diff --git a/app/views/projects/notes/_note.html.haml b/app/views/projects/notes/_note.html.haml
index fbc924c4e1de96233e85856a31f536321acb97bf..324b698f3b581cd4accfcf3b4ccfb8d5e545bb55 100644
--- a/app/views/projects/notes/_note.html.haml
+++ b/app/views/projects/notes/_note.html.haml
@@ -5,7 +5,7 @@
         %i.icon-link
         Link here
       &nbsp;
-      - if(note.author_id == current_user.id) || can?(current_user, :admin_note, @project)
+      - if(note.author_id == current_user.try(:id)) || can?(current_user, :admin_note, @project)
         = link_to "#", title: "Edit comment", class: "js-note-edit" do
           %i.icon-edit
           Edit
diff --git a/app/views/projects/snippets/_form.html.haml b/app/views/projects/snippets/_form.html.haml
index e83f5d0d65d2ba79d534cf895dea716ae648eb65..d414ee2d1ec70a33dd079652b38779c2e91ae0fe 100644
--- a/app/views/projects/snippets/_form.html.haml
+++ b/app/views/projects/snippets/_form.html.haml
@@ -31,10 +31,10 @@
         = f.submit 'Create snippet', class: "btn-create btn"
       - else
         = f.submit 'Save', class: "btn-save btn"
-      = link_to "Cancel", project_snippets_path(@project), class: " btn btn-cancel"
-      - unless @snippet.new_record?
-        .pull-right= link_to 'Destroy', project_snippet_path(@project, @snippet), confirm: 'Are you sure?', method: :delete, class: "btn pull-right danger delete-snippet", id: "destroy_snippet_#{@snippet.id}"
+      = link_to "Cancel", project_snippets_path(@project), class: "btn btn-cancel"
 
+    - unless @snippet.new_record?
+      = link_to 'Remove snippet', project_snippet_path(@project, @snippet), confirm: 'Are you sure?', method: :delete, class: "btn pull-right btn-remove delete-snippet prepend-left-10", id: "destroy_snippet_#{@snippet.id}"
 
 :javascript
   var editor = ace.edit("editor");
diff --git a/app/views/projects/tree/_blob_item.html.haml b/app/views/projects/tree/_blob_item.html.haml
index ec15b608f8589d2d53afe42429cfda27f97a1982..b179ad7d245f051a95db77c2909996a179375c68 100644
--- a/app/views/projects/tree/_blob_item.html.haml
+++ b/app/views/projects/tree/_blob_item.html.haml
@@ -1,7 +1,7 @@
 %tr{ class: "tree-item #{tree_hex_class(blob_item)}" }
   %td.tree-item-file-name
     = tree_icon(type)
-    %strong= link_to truncate(blob_item.name, length: 40), project_blob_path(@project, tree_join(@id || @commit.id, blob_item.name))
+    %span= link_to truncate(blob_item.name, length: 40), project_blob_path(@project, tree_join(@id || @commit.id, blob_item.name))
   %td.tree_time_ago.cgray
     %span.log_loading.hide
       Loading commit data...
diff --git a/app/views/projects/tree/_submodule_item.html.haml b/app/views/projects/tree/_submodule_item.html.haml
index 092a024afbc0677442d7515c5482f09c31aae165..26aad16e2c00cfcda5917f7af5e6c955b34ff678 100644
--- a/app/views/projects/tree/_submodule_item.html.haml
+++ b/app/views/projects/tree/_submodule_item.html.haml
@@ -4,7 +4,7 @@
 %tr{ class: "tree-item", url: url }
   %td.tree-item-file-name
     = image_tag "submodule.png"
-    %strong= truncate(name, length: 40)
+    %span= truncate(name, length: 40)
   %td
     %code= submodule_item.id[0..10]
   %td{ colspan: 2 }
diff --git a/app/views/projects/tree/_tree.html.haml b/app/views/projects/tree/_tree.html.haml
index 0b1148b3e74f80fc5425f9f2635c2850b0405fdd..eadfd33bd3cb21dc7d6ec719aab0ed8df3c007a3 100644
--- a/app/views/projects/tree/_tree.html.haml
+++ b/app/views/projects/tree/_tree.html.haml
@@ -26,9 +26,9 @@
             = link_to @commit.short_id, project_commit_path(@project, @commit)
             &ndash;
             = truncate(@commit.title, length: 50)
-        %th= link_to "history", project_commits_path(@project, @id), class: "btn btn-tiny pull-right"
+        %th= link_to "history", project_commits_path(@project, @id), class: "pull-right"
 
-    - if tree.up_dir?
+    - if @path.present?
       %tr.tree-item
         %td.tree-item-file-name
           = image_tag "file_empty.png", size: '16x16'
diff --git a/app/views/projects/tree/_tree_commit_column.html.haml b/app/views/projects/tree/_tree_commit_column.html.haml
index 7ae2582c130af4537208212f692f8708452860d0..67b5b2b96e280f8eee69e56a62ac78f7ec2a3bfc 100644
--- a/app/views/projects/tree/_tree_commit_column.html.haml
+++ b/app/views/projects/tree/_tree_commit_column.html.haml
@@ -1,2 +1,2 @@
-%span.tree_author= commit_author_link(commit, avatar: true)
+%span.tree_author= commit_author_link(commit, avatar: true, size: 16)
 = link_to_gfm truncate(commit.title, length: 80), project_commit_path(@project, commit.id), class: "tree-commit-link"
diff --git a/app/views/projects/tree/_tree_item.html.haml b/app/views/projects/tree/_tree_item.html.haml
index 0a76d5c21b678e61ed179d06307b67b9bb5adf4a..f8856afc8664b31e719832df14979c63618a94f8 100644
--- a/app/views/projects/tree/_tree_item.html.haml
+++ b/app/views/projects/tree/_tree_item.html.haml
@@ -1,7 +1,7 @@
 %tr{ class: "tree-item #{tree_hex_class(tree_item)}" }
   %td.tree-item-file-name
     = tree_icon(type)
-    %strong= link_to truncate(tree_item.name, length: 40), project_tree_path(@project, tree_join(@id || @commit.id, tree_item.name))
+    %span= link_to truncate(tree_item.name, length: 40), project_tree_path(@project, tree_join(@id || @commit.id, tree_item.name))
   %td.tree_time_ago.cgray
     %span.log_loading.hide
       Loading commit data...
diff --git a/app/views/public/projects/_tree.html.haml b/app/views/public/projects/_tree.html.haml
deleted file mode 100644
index bd09c236a0b2fd7ad5cd23e9d3940c3f7268fe97..0000000000000000000000000000000000000000
--- a/app/views/public/projects/_tree.html.haml
+++ /dev/null
@@ -1,5 +0,0 @@
-- if tree.readme
-  = render "projects/tree/readme", readme: tree.readme
-- else
-  .alert
-    %h3.nothing_here_message This project does not have README file
diff --git a/app/views/public/projects/index.html.haml b/app/views/public/projects/index.html.haml
index bfede94917af1da1220754bf54fde86015ce248e..21aee6445795df849988cbf5d7cb24784c55c9bd 100644
--- a/app/views/public/projects/index.html.haml
+++ b/app/views/public/projects/index.html.haml
@@ -2,29 +2,40 @@
   .span6
     %h3.page-title
       Projects (#{@projects.total_count})
-      %small with read-only access
+    .light
+      You can browse public projects in read-only mode until signed in.
+
   .span6
     .pull-right
       = form_tag public_projects_path, method: :get, class: 'form-inline' do |f|
         .search-holder
-          .controls
-            = search_field_tag :search, params[:search], placeholder: "gitlab-ci", class: "span3 search-text-input", id: "projects_search"
-            = submit_tag 'Search', class: "btn btn-primary wide"
-
+          = search_field_tag :search, params[:search], placeholder: "Filter by name", class: "span3 search-text-input", id: "projects_search"
+          = submit_tag 'Search', class: "btn btn-primary wide"
+%hr
 .public-projects
-  %ul.bordered-list
+  %ul.bordered-list.top-list
     - @projects.each do |project|
       %li
-        .project-title
-          %i.icon-share.cgray
-          = link_to public_project_path(project) do
-            %strong= project.name_with_namespace
+        %h4
+          = link_to project_path(project) do
+            = project.name_with_namespace
           .pull-right
             %pre.public-clone git clone #{project.http_url_to_repo}
 
         - if project.description.present?
-          %div.description
+          %p
             = project.description
+
+        .repo-info
+          - unless project.empty_repo?
+            = link_to pluralize(project.repository.round_commit_count, 'commit'), project_commits_path(project, project.default_branch)
+            &middot;
+            = link_to pluralize(project.repository.branch_names.count, 'branch'), project_branches_path(project)
+            &middot;
+            = link_to pluralize(project.repository.tag_names.count, 'tag'), project_tags_path(project)
+          - else
+            %i.icon-warning-sign
+            Empty repository
     - unless @projects.present?
       %h3.nothing_here_message No public projects
 
diff --git a/app/views/public/projects/show.html.haml b/app/views/public/projects/show.html.haml
deleted file mode 100644
index c4d8a4f5a5fce0f582348c585185ab1c5ef52e79..0000000000000000000000000000000000000000
--- a/app/views/public/projects/show.html.haml
+++ /dev/null
@@ -1,46 +0,0 @@
-%h3.page-title
-  = @project.name_with_namespace
-  .pull-right
-    %pre.public-clone git clone #{@project.http_url_to_repo}
-  .pull-right
-    - if current_user
-      = link_to 'Browse project', @project, class: 'btn btn-create append-right-10'
-
-
-%div
-  = link_to public_root_path do
-    &larr; To projects list
-  .pull-right
-    %span.light= @project.description
-
-%br
-.row
-  .span9
-    = render 'tree', tree: @tree
-  .span3
-    %h5 Repository:
-    %div
-      %p
-        %span.light Bare size is
-        #{@project.repository.size} MB
-
-      %p
-        = pluralize(@repository.round_commit_count, 'commit')
-      %p
-        = pluralize(@repository.branch_names.count, 'branch')
-      %p
-        = pluralize(@repository.tag_names.count, 'tag')
-
-    - if @recent_tags.present?
-      %hr
-      %h5 Most Recent Tags:
-      %ul.unstyled
-        - @recent_tags.each do |tag|
-          %li
-            %p
-              %i.icon-tag
-              %strong= tag.name
-              %small.light.pull-right
-                %i.icon-calendar
-                  = time_ago_in_words(tag.commit.committed_date)
-                ago
diff --git a/app/views/shared/_project_filter.html.haml b/app/views/shared/_project_filter.html.haml
index 5e0f503c8195997e1a7b2bcd90774343e85959fd..f3d032ef98661914c7fc323d39593aea7cc84595 100644
--- a/app/views/shared/_project_filter.html.haml
+++ b/app/views/shared/_project_filter.html.haml
@@ -1,15 +1,16 @@
 = form_tag project_entities_path, method: 'get' do
   %fieldset
-    %ul.nav.nav-pills.nav-stacked
-      %li{class: ("active" if params[:scope].blank?)}
-        = link_to project_filter_path(scope: nil) do
-          Everyone's
-      %li{class: ("active" if params[:scope] == 'assigned-to-me')}
-        = link_to project_filter_path(scope: 'assigned-to-me') do
-          Assigned to me
-      %li{class: ("active" if params[:scope] == 'created-by-me')}
-        = link_to project_filter_path(scope: 'created-by-me') do
-          Created by me
+    - if current_user
+      %ul.nav.nav-pills.nav-stacked
+        %li{class: ("active" if params[:scope].blank?)}
+          = link_to project_filter_path(scope: nil) do
+            Everyone's
+        %li{class: ("active" if params[:scope] == 'assigned-to-me')}
+          = link_to project_filter_path(scope: 'assigned-to-me') do
+            Assigned to me
+        %li{class: ("active" if params[:scope] == 'created-by-me')}
+          = link_to project_filter_path(scope: 'created-by-me') do
+            Created by me
 
     %ul.nav.nav-pills.nav-stacked
       %li{class: ("active" if params[:state].blank?)}
diff --git a/app/views/users_groups/_users_group.html.haml b/app/views/users_groups/_users_group.html.haml
index c8d306838f7261df68bacb9d43d5e8a17056281c..5cdb5bb8c4031064a0a431669bc0ed325715e251 100644
--- a/app/views/users_groups/_users_group.html.haml
+++ b/app/views/users_groups/_users_group.html.haml
@@ -10,7 +10,7 @@
   %span.pull-right
     %strong= member.human_access
 
-    - if show_controls && user != @group.owner && user != current_user
+    - if show_controls && can?(current_user, :manage_group, @group) && current_user != user
       = link_to '#', class: "btn-tiny btn js-toggle-button", title: 'Edit access level' do
         %i.icon-edit
       = link_to group_users_group_path(@group, member), confirm: remove_user_from_group_message(@group, user), method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
@@ -20,4 +20,4 @@
     = form_for [@group, member], remote: true do |f|
       .alert.prepend-top-20
         = f.select :group_access, options_for_select(UsersGroup.group_access_roles, member.group_access)
-        = f.submit 'Save', class: 'btn btn-save'
+        = f.submit 'Save', class: 'btn btn-save btn-small'
diff --git a/config/application.rb b/config/application.rb
index f7349fa009bb1da41e53f3083db3a9f26900d663..d85bcab7885b62bc6f656ea5486b2c672be5269d 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -32,6 +32,7 @@ module Gitlab
                                      :project_observer,
                                      :system_hook_observer,
                                      :user_observer,
+                                     :users_group_observer,
                                      :users_project_observer
 
     # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
@@ -69,12 +70,15 @@ module Gitlab
     config.assets.version = '1.0'
 
     # Uncomment and customize the last line to run in a non-root path
-    # WARNING: This feature is no longer supported
+    # WARNING: This feature is known to work, but unsupported
     # Note that three settings need to be changed for this to work.
     # 1) In your application.rb file: config.relative_url_root = "/gitlab"
     # 2) In your gitlab.yml file: relative_url_root: /gitlab
-    # 3) In your unicorn.rb: ENV['RAILS_RELATIVE_URL_ROOT']
+    # 3) In your unicorn.rb: ENV['RAILS_RELATIVE_URL_ROOT'] = "/gitlab"
     #
     # config.relative_url_root = "/gitlab"
+
+    # Uncomment to enable rack attack middleware
+    # config.middleware.use Rack::Attack
   end
 end
diff --git a/config/database.yml.mysql b/config/database.yml.mysql
index a3eff1a74f8a5b4fa8acc57994371b3f6bcac0e8..e7a9227e41e935fda40da67d6e9e336fe97acb79 100644
--- a/config/database.yml.mysql
+++ b/config/database.yml.mysql
@@ -7,7 +7,7 @@ production:
   reconnect: false
   database: gitlabhq_production
   pool: 10
-  username: root
+  username: gitlab
   password: "secure password"
   # host: localhost
   # socket: /tmp/mysql.sock
diff --git a/config/database.yml.postgresql b/config/database.yml.postgresql
index 4b74f3348f8a3a54baeb9df9c53d34926c3e7a9a..66960551cfde14278d8f5e166ed9d0e3ba7431ab 100644
--- a/config/database.yml.postgresql
+++ b/config/database.yml.postgresql
@@ -6,8 +6,8 @@ production:
   encoding: unicode
   database: gitlabhq_production
   pool: 10
-  username: git
-  password:
+  # username: git
+  # password:
   # host: localhost
   # port: 5432 
   # socket: /tmp/postgresql.sock
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 389dba59c9d27011d19f3fe9a242cef9be2905d5..0c66218eda56ada7f37aeab1c376bdd7ed8cfa67 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -20,11 +20,11 @@ production: &base
     https: false
 
     # Uncomment and customize the last line to run in a non-root path
-    # WARNING: This feature is no longer supported
+    # WARNING: This feature is known to work, but unsupported
     # Note that three settings need to be changed for this to work.
     # 1) In your application.rb file: config.relative_url_root = "/gitlab"
     # 2) In your gitlab.yml file: relative_url_root: /gitlab
-    # 3) In your unicorn.rb: ENV['RAILS_RELATIVE_URL_ROOT']
+    # 3) In your unicorn.rb: ENV['RAILS_RELATIVE_URL_ROOT'] = "/gitlab"
     #
     # relative_url_root: /gitlab
 
@@ -42,14 +42,24 @@ production: &base
     default_projects_limit: 10
     # default_can_create_group: false  # default: true
     # username_changing_enabled: false # default: true - User can change her username/namespace
+    ## Default theme
+    ##   BASIC  = 1
+    ##   MARS   = 2
+    ##   MODERN = 3
+    ##   GRAY   = 4
+    ##   COLOR  = 5
+    # default_theme: 2 # default: 2
+
 
     ## Users management
-    # signup_enabled: true          # default: false - Account passwords are not sent via the email if signup is enabled.
+    # default: false - Account passwords are not sent via the email if signup is enabled. 
+    # signup_enabled: true
 
     ## Automatic issue closing
-    # If a commit message matches this regular express, all issues referenced from the matched text will be closed
-    # if it's pushed to a project's default branch.
-    # issue_closing_pattern: "^([Cc]loses|[Ff]ixes) +#\d+"
+    # If a commit message matches this regular expression, all issues referenced from the matched text will be closed.
+    # This  happends when the commit is pushed or merged into the default branch of a project.
+    # When not specified the default issue_closing_pattern as specified below will be used.
+    # issue_closing_pattern: ([Cc]loses|[Ff]ixes) +#\d+
 
     ## Default project features settings
     default_projects_features:
@@ -58,6 +68,12 @@ production: &base
       wiki: true
       wall: false
       snippets: false
+      public: false
+ 
+    ## Webhook settings
+    # Number of seconds to wait for HTTP response after sending webhook HTTP POST request (default: 10)
+    # webhook_timeout: 10
+
 
   ## External issues trackers
   issues_tracker:
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index b3a19783b14ad2d80a953ced8493f0662a4c12de..1adb5c4e64d8a66403fa0e8a91fcdc04acd3f6f3 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -52,6 +52,7 @@ Settings['issues_tracker']  ||= {}
 Settings['gitlab'] ||= Settingslogic.new({})
 Settings.gitlab['default_projects_limit'] ||= 10
 Settings.gitlab['default_can_create_group'] = true if Settings.gitlab['default_can_create_group'].nil?
+Settings.gitlab['default_theme'] = Gitlab::Theme::MARS if Settings.gitlab['default_theme'].nil?
 Settings.gitlab['host']       ||= 'localhost'
 Settings.gitlab['https']        = false if Settings.gitlab['https'].nil?
 Settings.gitlab['port']       ||= Settings.gitlab.https ? 443 : 80
@@ -68,13 +69,15 @@ rescue ArgumentError # no user configured
 end
 Settings.gitlab['signup_enabled'] ||= false
 Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil?
-Settings.gitlab['issue_closing_pattern'] = '^([Cc]loses|[Ff]ixes) #(\d+)' if Settings.gitlab['issue_closing_pattern'].nil?
+Settings.gitlab['issue_closing_pattern'] = '([Cc]loses|[Ff]ixes) #(\d+)' if Settings.gitlab['issue_closing_pattern'].nil?
 Settings.gitlab['default_projects_features'] ||= {}
+Settings.gitlab['webhook_timeout'] ||= 10   
 Settings.gitlab.default_projects_features['issues']         = true if Settings.gitlab.default_projects_features['issues'].nil?
 Settings.gitlab.default_projects_features['merge_requests'] = true if Settings.gitlab.default_projects_features['merge_requests'].nil?
 Settings.gitlab.default_projects_features['wiki']           = true if Settings.gitlab.default_projects_features['wiki'].nil?
 Settings.gitlab.default_projects_features['wall']           = false if Settings.gitlab.default_projects_features['wall'].nil?
 Settings.gitlab.default_projects_features['snippets']       = false if Settings.gitlab.default_projects_features['snippets'].nil?
+Settings.gitlab.default_projects_features['public']         = false if Settings.gitlab.default_projects_features['public'].nil?
 
 #
 # Gravatar
diff --git a/config/initializers/5_backend.rb b/config/initializers/5_backend.rb
index e60d9559c9462852abd8f1ae9a7c0b6426fff7a2..7c2e7f3900053c1b1b9b893faa0f1dc9c2c244ba 100644
--- a/config/initializers/5_backend.rb
+++ b/config/initializers/5_backend.rb
@@ -6,6 +6,3 @@ require Rails.root.join("lib", "gitlab", "backend", "shell")
 
 # GitLab shell adapter
 require Rails.root.join("lib", "gitlab", "backend", "shell_adapter")
-
-# Gitlab Git repos path
-Gitlab::Git::Repository.repos_path = Gitlab.config.gitlab_shell.repos_path
diff --git a/config/initializers/rack_attack.rb.example b/config/initializers/rack_attack.rb.example
new file mode 100644
index 0000000000000000000000000000000000000000..76fa7ad282e9350fa1b14b0f882493e42deee3b3
--- /dev/null
+++ b/config/initializers/rack_attack.rb.example
@@ -0,0 +1,16 @@
+# To enable rack-attack for your GitLab instance do the following:
+# 1. In config/application.rb find and uncomment the following line:
+# config.middleware.use Rack::Attack
+# 2. Rename this file to rack_attack.rb
+# 3. Review the paths_to_be_protected and add any other path you need protecting
+# 4. Restart GitLab instance
+#
+
+paths_to_be_protected = [
+  "#{Rails.application.config.relative_url_root}/users/password",
+  "#{Rails.application.config.relative_url_root}/users/sign_in",
+  "#{Rails.application.config.relative_url_root}/users"
+]
+Rack::Attack.throttle('protected paths', limit: 6, period: 60.seconds) do |req|
+  req.ip if paths_to_be_protected.include?(req.path) && req.post?
+end
diff --git a/config/routes.rb b/config/routes.rb
index d0e29a5ab96b0e0aeb7be1f0d38c57dad41b6419..612a7327ec565c1cc45ae687caaa3a67c128ee1c 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -39,6 +39,7 @@ Gitlab::Application.routes.draw do
   get 'help/web_hooks'      => 'help#web_hooks'
   get 'help/workflow'       => 'help#workflow'
   get 'help/shortcuts'
+  get 'help/security'
 
   #
   # Global snippets
@@ -55,8 +56,6 @@ Gitlab::Application.routes.draw do
   #
   namespace :public do
     resources :projects, only: [:index]
-    resources :projects, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ }, only: [:show]
-
     root to: "projects#index"
   end
 
@@ -157,7 +156,7 @@ Gitlab::Application.routes.draw do
   #
   # Project Area
   #
-  resources :projects, constraints: { id: /(?:[a-zA-Z.0-9_\-]+\/)?[a-zA-Z.0-9_\-]+/ }, except: [:new, :create, :index], path: "/" do
+  resources :projects, constraints: { id: /[a-zA-Z.0-9_\-]+\/[a-zA-Z.0-9_\-]+/ }, except: [:new, :create, :index], path: "/" do
     member do
       put :transfer
       post :fork
@@ -177,13 +176,13 @@ Gitlab::Application.routes.draw do
       resources :graphs, only: [:show], constraints: {id: /(?:[^.]|\.(?!json$))+/, format: /json/}
       match "/compare/:from...:to" => "compare#show", as: "compare", via: [:get, :post], constraints: {from: /.+/, to: /.+/}
 
-        resources :snippets do
+        resources :snippets, constraints: {id: /\d+/} do
           member do
             get "raw"
           end
         end
 
-      resources :wikis, only: [:show, :edit, :destroy, :create] do
+      resources :wikis, only: [:show, :edit, :destroy, :create], constraints: {id: /[a-zA-Z.0-9_\-]+/} do
         collection do
           get :pages
           put ':id' => 'wikis#update'
@@ -195,7 +194,7 @@ Gitlab::Application.routes.draw do
         end
       end
 
-      resource :wall, only: [:show] do
+      resource :wall, only: [:show], constraints: {id: /\d+/} do
         member do
           get 'notes'
         end
@@ -214,21 +213,21 @@ Gitlab::Application.routes.draw do
         end
       end
 
-      resources :deploy_keys do
+      resources :deploy_keys, constraints: {id: /\d+/} do
         member do
           put :enable
           put :disable
         end
       end
 
-      resources :branches, only: [:index, :new, :create, :destroy] do
+      resources :branches, only: [:index, :new, :create, :destroy], constraints: { id: /[a-zA-Z.\/0-9_\-#%+]+/ } do
         collection do
           get :recent
         end
       end
 
-      resources :tags, only: [:index, :new, :create, :destroy]
-      resources :protected_branches, only: [:index, :create, :destroy]
+      resources :tags, only: [:index, :new, :create, :destroy], constraints: { id: /[a-zA-Z.\/0-9_\-#%+]+/ }
+      resources :protected_branches, only: [:index, :create, :destroy], constraints: { id: /[a-zA-Z.\/0-9_\-#%+]+/ }
 
       resources :refs, only: [] do
         collection do
@@ -262,14 +261,14 @@ Gitlab::Application.routes.draw do
         end
       end
 
-      resources :hooks, only: [:index, :create, :destroy] do
+      resources :hooks, only: [:index, :create, :destroy], constraints: {id: /\d+/} do
         member do
           get :test
         end
       end
 
       resources :team, controller: 'team_members', only: [:index]
-      resources :milestones, except: [:destroy]
+      resources :milestones, except: [:destroy], constraints: {id: /\d+/}
 
       resources :labels, only: [:index] do
         collection do
@@ -283,7 +282,7 @@ Gitlab::Application.routes.draw do
         end
       end
 
-      resources :team_members, except: [:index, :edit] do
+      resources :team_members, except: [:index, :edit], constraints: { id: /[a-zA-Z.\/0-9_\-#%+]+/ } do
         collection do
 
           # Used for import team
@@ -293,7 +292,7 @@ Gitlab::Application.routes.draw do
         end
       end
 
-      resources :notes, only: [:index, :create, :destroy, :update] do
+      resources :notes, only: [:index, :create, :destroy, :update], constraints: {id: /\d+/} do
         member do
           delete :delete_attachment
         end
diff --git a/config/unicorn.rb.example b/config/unicorn.rb.example
index 812fd5b74498c785caf15177e9ea5084568fc2a7..e4e1342683187a6f2a2b30b56aa7d50a0cb2c304 100644
--- a/config/unicorn.rb.example
+++ b/config/unicorn.rb.example
@@ -8,6 +8,15 @@
 # See http://unicorn.bogomips.org/Unicorn/Configurator.html for complete
 # documentation.
 
+# Uncomment and customize the last line to run in a non-root path
+# WARNING: This feature is known to work, but unsupported
+# Note that three settings need to be changed for this to work.
+# 1) In your application.rb file: config.relative_url_root = "/gitlab"
+# 2) In your gitlab.yml file: relative_url_root: /gitlab
+# 3) In your unicorn.rb: ENV['RAILS_RELATIVE_URL_ROOT'] = "/gitlab"
+#
+# ENV['RAILS_RELATIVE_URL_ROOT'] = "/gitlab"
+
 # Use at least one worker per core if you're on a dedicated server,
 # more will usually help for _short_ waits on databases/caches.
 worker_processes 2
@@ -35,7 +44,7 @@ timeout 30
 pid "/home/git/gitlab/tmp/pids/unicorn.pid"
 
 # By default, the Unicorn logger will write to stderr.
-# Additionally, ome applications/frameworks log to stderr or stdout,
+# Additionally, some applications/frameworks log to stderr or stdout,
 # so prevent them from going to /dev/null when daemonized here:
 stderr_path "/home/git/gitlab/log/unicorn.stderr.log"
 stdout_path "/home/git/gitlab/log/unicorn.stdout.log"
diff --git a/db/migrate/20130909132950_add_description_to_merge_request.rb b/db/migrate/20130909132950_add_description_to_merge_request.rb
new file mode 100644
index 0000000000000000000000000000000000000000..9bcd0c7ee0689122e979b5ea63f7b04a0348f768
--- /dev/null
+++ b/db/migrate/20130909132950_add_description_to_merge_request.rb
@@ -0,0 +1,5 @@
+class AddDescriptionToMergeRequest < ActiveRecord::Migration
+  def change
+    add_column :merge_requests, :description, :text, null: true
+  end
+end
diff --git a/db/migrate/20130926081215_change_owner_id_for_group.rb b/db/migrate/20130926081215_change_owner_id_for_group.rb
new file mode 100644
index 0000000000000000000000000000000000000000..8f1992c37ab0bb51c4b54c0e8b82da7798fce568
--- /dev/null
+++ b/db/migrate/20130926081215_change_owner_id_for_group.rb
@@ -0,0 +1,9 @@
+class ChangeOwnerIdForGroup < ActiveRecord::Migration
+  def up
+    change_column :namespaces, :owner_id, :integer, null: true
+  end
+
+  def down
+    change_column :namespaces, :owner_id, :integer, null: false
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 5020230d8319013b912be46f297d0f958af2b203..713d9f733d6b50f3c8e660088aab4ae850bb31eb 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 => 20130821090531) do
+ActiveRecord::Schema.define(:version => 20130926081215) do
 
   create_table "deploy_keys_projects", :force => true do |t|
     t.integer  "deploy_key_id", :null => false
@@ -100,6 +100,7 @@ ActiveRecord::Schema.define(:version => 20130821090531) do
     t.string   "merge_status"
     t.integer  "target_project_id",                       :null => false
     t.integer  "iid"
+    t.text     "description"
   end
 
   add_index "merge_requests", ["assignee_id"], :name => "index_merge_requests_on_assignee_id"
@@ -128,7 +129,7 @@ ActiveRecord::Schema.define(:version => 20130821090531) do
   create_table "namespaces", :force => true do |t|
     t.string   "name",                        :null => false
     t.string   "path",                        :null => false
-    t.integer  "owner_id",                    :null => false
+    t.integer  "owner_id"
     t.datetime "created_at",                  :null => false
     t.datetime "updated_at",                  :null => false
     t.string   "type"
@@ -144,8 +145,8 @@ ActiveRecord::Schema.define(:version => 20130821090531) do
     t.text     "note"
     t.string   "noteable_type"
     t.integer  "author_id"
-    t.datetime "created_at",    :null => false
-    t.datetime "updated_at",    :null => false
+    t.datetime "created_at",                       :null => false
+    t.datetime "updated_at",                       :null => false
     t.integer  "project_id"
     t.string   "attachment"
     t.string   "line_code"
diff --git a/doc/api/README.md b/doc/api/README.md
index 7668df07af1a44a035a020057ef82770db5e6300..ee24449343a4aa5e6f66e3ba391460b0a701889d 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -58,7 +58,43 @@ Return values:
 * `409 Conflict` - A conflicting resource already exists, e.g. creating a project with a name that already exists
 * `500 Server Error` - While handling the request something went wrong on the server side
 
+## Sudo
+All API requests support performing an api call as if you were another user, if your private token is for an administration account. You need to pass  `sudo` parameter by url or header with an id or username of the user you want to perform the operation as. If passed as header, the header name must be "SUDO" (capitals).
 
+If a non administrative `private_token` is provided then an error message will be returned with status code 403:
+
+```json
+{
+  "message": "403 Forbidden: Must be admin to use sudo"
+}
+```
+
+If the sudo user id or username cannot be found then an error message will be returned with status code 404:
+
+```json
+{
+  "message": "404 Not Found: No user id or username for: <id/username>"
+}
+```
+
+Example of a valid API with sudo request:
+
+```
+GET http://example.com/api/v3/projects?private_token=QVy1PB7sTxfy4pqfZM1U&sudo=username
+```
+```
+GET http://example.com/api/v3/projects?private_token=QVy1PB7sTxfy4pqfZM1U&sudo=23
+```
+
+
+Example for a valid API request with sudo using curl and authentication via header:
+
+```
+curl --header "PRIVATE-TOKEN: QVy1PB7sTxfy4pqfZM1U" --header "SUDO: username" "http://example.com/api/v3/projects"
+```
+```
+curl --header "PRIVATE-TOKEN: QVy1PB7sTxfy4pqfZM1U" --header "SUDO: 23" "http://example.com/api/v3/projects"
+```
 
 #### Pagination
 
@@ -81,7 +117,7 @@ When listing resources you can pass the following parameters:
 + [Deploy Keys](deploy_keys.md)
 + [System Hooks](system_hooks.md)
 + [Groups](groups.md)
-+ [User Teams](user_teams.md)
+
 
 ## Clients
 
diff --git a/doc/api/deploy_keys.md b/doc/api/deploy_keys.md
index 5a394094fe611e5622522f022b9be2b66d725245..50d2b82c36f4143ab7a1f1714b600e8aaa83b499 100644
--- a/doc/api/deploy_keys.md
+++ b/doc/api/deploy_keys.md
@@ -16,17 +16,19 @@ Parameters:
 [
   {
     "id": 1,
-    "title" : "Public key"
+    "title" : "Public key",
     "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
       596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
       soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
+    "created_at":"2013-10-02T10:12:29Z"
   },
   {
     "id": 3,
-    "title" : "Another Public key"
+    "title" : "Another Public key",
     "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
       596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
-      soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
+      soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
+    "created_at":"2013-10-02T11:12:29Z"
   }
 ]
 ```
@@ -48,10 +50,11 @@ Parameters:
 ```json
 {
   "id": 1,
-  "title" : "Public key"
+  "title" : "Public key",
   "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
       596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
-      soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
+      soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
+  "created_at":"2013-10-02T10:12:29Z"
 }
 ```
 
diff --git a/doc/api/groups.md b/doc/api/groups.md
index e9702ea2cd16c8a92a7d53347f77126a7f2fb80f..f5f5d7690509cccd3184caefb53284d4c32222b2 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -8,12 +8,12 @@ GET /groups
 
 ```json
 [
-    {
-        "id": 1,
-        "name": "Foobar Group",
-        "path": "foo-bar",
-        "owner_id": 18
-    }
+  {
+    "id": 1,
+    "name": "Foobar Group",
+    "path": "foo-bar",
+    "owner_id": 18
+  }
 ]
 ```
 
@@ -54,4 +54,92 @@ POST  /groups/:id/projects/:project_id
 
 Parameters:
 + `id` (required) - The ID of a group
-+ `project_id (required) - The ID of a project
++ `project_id` (required) - The ID of a project
+
+
+## Remove group
+
+Removes group with all projects inside.
+
+```
+DELETE /groups/:id
+```
+
+Parameters:
+
++ `id` (required) - The ID of a user group
+
+
+## Group members
+
+
+**Group access levels**
+
+The group access levels are defined in the `Gitlab::Access` module. Currently, these levels are recognized:
+
+```
+  GUEST     = 10
+  REPORTER  = 20
+  DEVELOPER = 30
+  MASTER    = 40
+  OWNER     = 50
+```
+
+### List group members
+
+Get a list of group members viewable by the authenticated user.
+
+```
+GET /groups/:id/members
+```
+
+```json
+[
+  {
+    "id": 1,
+    "username": "raymond_smith",
+    "email": "ray@smith.org",
+    "name": "Raymond Smith",
+    "state": "active",
+    "created_at": "2012-10-22T14:13:35Z",
+    "access_level": 30
+  },
+  {
+    "id": 2,
+    "username": "john_doe",
+    "email": "joh@doe.org",
+    "name": "John Doe",
+    "state": "active",
+    "created_at": "2012-10-22T14:13:35Z",
+    "access_level": 30
+  }
+]
+```
+
+### Add group member
+
+Adds a user to the list of group members.
+
+```
+POST /groups/:id/members
+```
+
+Parameters:
+
++ `id` (required) - The ID of a group
++ `user_id` (required) - The ID of a user to add
++ `access_level` (required) - Project access level
+
+
+### Remove user team member
+
+Removes user from user team.
+
+```
+DELETE /groups/:id/members/:user_id
+```
+
+Parameters:
+
++ `id` (required) - The ID of a user group
++ `user_id` (required) - The ID of a group member
diff --git a/doc/api/issues.md b/doc/api/issues.md
index 723c8acf381604c104b1465c00c7099de04584ed..9082cbb50ba1cefe7a47e62efbf0f3d64913e760 100644
--- a/doc/api/issues.md
+++ b/doc/api/issues.md
@@ -22,10 +22,10 @@ GET /issues
       "username": "john_smith",
       "email": "john@example.com",
       "name": "John Smith",
-      "blocked": false,
+      "state": "active",
       "created_at": "2012-05-23T08:00:58Z"
     },
-    "state": 'closed',
+    "state": "closed",
     "updated_at": "2012-07-02T17:53:12Z",
     "created_at": "2012-07-02T17:53:12Z"
   },
@@ -42,7 +42,7 @@ GET /issues
       "title": "v1.0",
       "description": "",
       "due_date": "2012-07-20",
-      "state": 'reopenend',
+      "state": "reopenend",
       "updated_at": "2012-07-04T13:42:48Z",
       "created_at": "2012-07-04T13:42:48Z"
     },
@@ -51,7 +51,7 @@ GET /issues
       "username": "jack_smith",
       "email": "jack@example.com",
       "name": "Jack Smith",
-      "blocked": false,
+      "state": "active",
       "created_at": "2012-05-23T08:01:01Z"
     },
     "author": {
@@ -59,10 +59,10 @@ GET /issues
       "username": "john_smith",
       "email": "john@example.com",
       "name": "John Smith",
-      "blocked": false,
+      "state": "active",
       "created_at": "2012-05-23T08:00:58Z"
     },
-    "state": 'opened',
+    "state": "opened",
     "updated_at": "2012-07-12T13:43:19Z",
     "created_at": "2012-06-28T12:58:06Z"
   }
@@ -111,7 +111,7 @@ Parameters:
     "title": "v1.0",
     "description": "",
     "due_date": "2012-07-20",
-    "state": 'closed',
+    "state": "closed",
     "updated_at": "2012-07-04T13:42:48Z",
     "created_at": "2012-07-04T13:42:48Z"
   },
@@ -120,7 +120,7 @@ Parameters:
     "username": "jack_smith",
     "email": "jack@example.com",
     "name": "Jack Smith",
-    "blocked": false,
+    "state": "active",
     "created_at": "2012-05-23T08:01:01Z"
   },
   "author": {
@@ -128,10 +128,10 @@ Parameters:
     "username": "john_smith",
     "email": "john@example.com",
     "name": "John Smith",
-    "blocked": false,
+    "state": "active",
     "created_at": "2012-05-23T08:00:58Z"
   },
-  "state": 'opened',
+  "state": "opened",
   "updated_at": "2012-07-12T13:43:19Z",
   "created_at": "2012-06-28T12:58:06Z"
 }
@@ -190,4 +190,3 @@ Parameters:
 
 + `id` (required) - The project ID
 + `issue_id` (required) - The ID of the issue
-
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index 111c52112ebc806c8a70a1adc1e336160176a930..dae12f03ef5e9682bfcc1b5952162cdf273cd645 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -19,14 +19,15 @@ Parameters:
         "source_branch":"test1",
         "project_id":3,
         "title":"test1",
-        "closed":true,
-        "merged":false,
+        "state":"opened",
+        "upvotes":0,
+        "downvotes":0,
         "author":{
             "id":1,
             "username": "admin",
             "email":"admin@local.host",
             "name":"Administrator",
-            "blocked":false,
+            "state":"active",
             "created_at":"2012-04-29T08:46:00Z"
         },
         "assignee":{
@@ -34,7 +35,7 @@ Parameters:
             "username": "admin",
             "email":"admin@local.host",
             "name":"Administrator",
-            "blocked":false,
+            "state":"active",
             "created_at":"2012-04-29T08:46:00Z"
         }
     }
@@ -62,14 +63,15 @@ Parameters:
     "source_branch":"test1",
     "project_id":3,
     "title":"test1",
-    "closed":true,
-    "merged":false,
+    "state":"merged",
+    "upvotes":0,
+    "downvotes":0,
     "author":{
         "id":1,
         "username": "admin",
         "email":"admin@local.host",
         "name":"Administrator",
-        "blocked":false,
+        "state":"active",
         "created_at":"2012-04-29T08:46:00Z"
     },
     "assignee":{
@@ -77,7 +79,7 @@ Parameters:
         "username": "admin",
         "email":"admin@local.host",
         "name":"Administrator",
-        "blocked":false,
+        "state":"active",
         "created_at":"2012-04-29T08:46:00Z"
     }
 }
@@ -97,7 +99,7 @@ Parameters:
 + `id` (required) - The ID of a project
 + `source_branch` (required) - The source branch
 + `target_branch` (required) - The target branch
-+ `assignee_id`              - Assignee user ID
++ `assignee_id` (optional)   - Assignee user ID
 + `title` (required)         - Title of MR
 
 ```json
@@ -107,14 +109,15 @@ Parameters:
     "source_branch":"test1",
     "project_id":3,
     "title":"test1",
-    "closed":true,
-    "merged":false,
+    "state":"opened",
+    "upvotes":0,
+    "downvotes":0,
     "author":{
         "id":1,
         "username": "admin",
         "email":"admin@local.host",
         "name":"Administrator",
-        "blocked":false,
+        "state":"active",
         "created_at":"2012-04-29T08:46:00Z"
     },
     "assignee":{
@@ -122,7 +125,7 @@ Parameters:
         "username": "admin",
         "email":"admin@local.host",
         "name":"Administrator",
-        "blocked":false,
+        "state":"active",
         "created_at":"2012-04-29T08:46:00Z"
     }
 }
@@ -145,24 +148,24 @@ Parameters:
 + `target_branch`               - The target branch
 + `assignee_id`                 - Assignee user ID
 + `title`                       - Title of MR
-+ `closed`                      - Status of MR. true - closed
-
 
 ```json
+
 {
     "id":1,
     "target_branch":"master",
     "source_branch":"test1",
     "project_id":3,
     "title":"test1",
-    "closed":true,
-    "merged":false,
+    "state":"opened",
+    "upvotes":0,
+    "downvotes":0,
     "author":{
         "id":1,
         "username": "admin",
         "email":"admin@local.host",
         "name":"Administrator",
-        "blocked":false,
+        "state":"active",
         "created_at":"2012-04-29T08:46:00Z"
     },
     "assignee":{
@@ -170,7 +173,7 @@ Parameters:
         "username": "admin",
         "email":"admin@local.host",
         "name":"Administrator",
-        "blocked":false,
+        "state":"active",
         "created_at":"2012-04-29T08:46:00Z"
     }
 }
diff --git a/doc/api/milestones.md b/doc/api/milestones.md
index aa8f1bf5e02b846e588583324a96b336bef8d4ab..2bdca68351bd6bd7208a1402d8e72fd6f1f03441 100644
--- a/doc/api/milestones.md
+++ b/doc/api/milestones.md
@@ -6,6 +6,21 @@ Returns a list of project milestones.
 GET /projects/:id/milestones
 ```
 
+```json
+[
+  {
+    "id":12,
+    "project_id":16,
+    "title":"10.0",
+    "description":"Version",
+    "due_date":"2013-11-29",
+    "state":"active",
+    "updated_at":"2013-10-02T09:24:18Z",
+    "created_at":"2013-10-02T09:24:18Z"
+  }
+]
+```
+
 Parameters:
 
 + `id` (required) - The ID of a project
diff --git a/doc/api/notes.md b/doc/api/notes.md
index 4b57f636a0143e6075b2bb761f58a31ffa939d1f..397aa87aadff10aa72e6a74098e77a8ad0622ef7 100644
--- a/doc/api/notes.md
+++ b/doc/api/notes.md
@@ -8,17 +8,22 @@ Get a list of project wall notes.
 GET /projects/:id/notes
 ```
 
+Parameters:
+
++ `id` (required) - The ID of a project
+
 ```json
 [
   {
     "id": 522,
     "body": "The solution is rather tricky",
+    "attachment":null,
     "author": {
       "id": 1,
       "username": "john_smith",
       "email": "john@example.com",
       "name": "John Smith",
-      "blocked": false,
+      "state": "active",
       "created_at": "2012-05-23T08:00:58Z"
     },
     "created_at": "2012-11-27T19:16:44Z"
@@ -26,11 +31,6 @@ GET /projects/:id/notes
 ]
 ```
 
-Parameters:
-
-+ `id` (required) - The ID of a project
-
-
 ### Get single wall note
 
 Returns a single wall note.
@@ -74,6 +74,38 @@ Parameters:
 + `id` (required) - The ID of a project
 + `issue_id` (required) - The ID of an issue
 
+```json
+[
+  {
+    "id":302,
+    "body":"_Status changed to closed_",
+    "attachment":null,
+    "author":{
+      "id":1,
+      "username":"pipin",
+      "email":"admin@example.com",
+      "name":"Pip",
+      "state":"active",
+      "created_at":"2013-09-30T13:46:01Z"
+    },
+    "created_at":"2013-10-02T09:22:45Z"
+  },
+  {
+    "id":305,
+    "body":"Text of the comment\r\n",
+    "attachment":null,
+    "author":{
+      "id":1,
+      "username":"pipin",
+      "email":"admin@example.com",
+      "name":"Pip",
+      "state":"active",
+      "created_at":"2013-09-30T13:46:01Z"
+    },
+    "created_at":"2013-10-02T09:56:03Z"
+  }
+]
+```
 
 ### Get single issue note
 
@@ -135,6 +167,24 @@ Parameters:
 + `snippet_id` (required) - The ID of a project snippet
 + `note_id` (required) - The ID of an snippet note
 
+```json
+{
+  "id":52,
+  "title":"Snippet",
+  "file_name":"snippet.rb",
+  "author":{
+    "id":1,
+    "username":"pipin",
+    "email":"admin@example.com",
+    "name":"Pip",
+    "state":"active",
+    "created_at":"2013-09-30T13:46:01Z"
+  },
+  "expires_at":null,
+  "updated_at":"2013-10-02T07:34:20Z",
+  "created_at":"2013-10-02T07:34:20Z"
+}
+```
 
 ### Create new snippet note
 
@@ -181,6 +231,22 @@ Parameters:
 + `merge_request_id` (required) - The ID of a project merge request
 + `note_id` (required) - The ID of a merge request note
 
+```json
+{
+  "id":301,
+  "body":"Comment for MR",
+  "attachment":null,
+  "author":{
+    "id":1,
+    "username":"pipin",
+    "email":"admin@example.com",
+    "name":"Pip",
+    "state":"active",
+    "created_at":"2013-09-30T13:46:01Z"
+  },
+  "created_at":"2013-10-02T08:57:14Z"
+}
+```
 
 ### Create new merge request note
 
diff --git a/doc/api/project_snippets.md b/doc/api/project_snippets.md
index 04ea367d51807cf1033f230e5f9a0a8ed041df49..f7b7fc8fbb5bfbaba45e4c740e6afb43f307dbd4 100644
--- a/doc/api/project_snippets.md
+++ b/doc/api/project_snippets.md
@@ -34,7 +34,7 @@ Parameters:
     "username": "john_smith",
     "email": "john@example.com",
     "name": "John Smith",
-    "blocked": false,
+    "state": "active",
     "created_at": "2012-05-23T08:00:58Z"
   },
   "expires_at": null,
diff --git a/doc/api/projects.md b/doc/api/projects.md
index 9afffcbaa80685f86ac2ae9400a454b12b5e3d0b..0f73fb434da98bf021a442ba86e73e8ea86de1cc 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -11,51 +11,72 @@ GET /projects
 ```json
 [
   {
-    "id": 3,
-    "name": "rails",
+    "id": 4,
     "description": null,
     "default_branch": "master",
+    "public": false,
+    "ssh_url_to_repo": "git@example.com:diaspora/diaspora-client.git",
+    "http_url_to_repo": "http://example.com/diaspora/diaspora-client.git",
+    "web_url": "http://example.com/diaspora/diaspora-client",
     "owner": {
-      "id": 1,
-      "username": "john_smith",
-      "email": "john@example.com",
-      "name": "John Smith",
-      "blocked": false,
-      "created_at": "2012-05-23T08:00:58Z"
+      "id": 3,
+      "name": "Diaspora",
+      "created_at": "2013-09-30T13: 46: 02Z"
     },
-    "public": true,
-    "path": "rails",
-    "path_with_namespace": "rails/rails",
-    "issues_enabled": false,
-    "merge_requests_enabled": false,
-    "wall_enabled": true,
+    "name": "Diaspora Client",
+    "name_with_namespace": "Diaspora / Diaspora Client",
+    "path": "diaspora-client",
+    "path_with_namespace": "diaspora/diaspora-client",
+    "issues_enabled": true,
+    "merge_requests_enabled": true,
+    "wall_enabled": false,
     "wiki_enabled": true,
-    "created_at": "2012-05-23T08:05:02Z",
-    "last_activity_at": "2012-05-23T08:05:02Z"
+    "snippets_enabled": false,
+    "created_at": "2013-09-30T13: 46: 02Z",
+    "last_activity_at": "2013-09-30T13: 46: 02Z",
+    "namespace": {
+      "created_at": "2013-09-30T13: 46: 02Z",
+      "description": "",
+      "id": 3,
+      "name": "Diaspora",
+      "owner_id": 1,
+      "path": "diaspora",
+      "updated_at": "2013-09-30T13: 46: 02Z"
+    }
   },
   {
-    "id": 5,
-    "name": "gitlab",
+    "id": 6,
     "description": null,
-    "default_branch": "api",
-    "owner": {
-      "id": 1,
-      "username": "john_smith",
-      "email": "john@example.com",
-      "name": "John Smith",
-      "blocked": false,
-      "created_at": "2012-05-23T08:00:58Z"
+    "default_branch": "master",
+    "public": false,
+    "ssh_url_to_repo": "git@example.com:brightbox/puppet.git",
+    "http_url_to_repo": "http://example.com/brightbox/puppet.git",
+    "web_url": "http://example.com/brightbox/puppet",
+    "owner":  {
+      "id": 4,
+      "name": "Brightbox",
+      "created_at": "2013-09-30T13:46:02Z"
     },
-    "public": true,
-    "path": "gitlab",
-    "path_with_namespace": "randx/gitlab",
+    "name": "Puppet",
+    "name_with_namespace": "Brightbox / Puppet",
+    "path": "puppet",
+    "path_with_namespace": "brightbox/puppet",
     "issues_enabled": true,
     "merge_requests_enabled": true,
-    "wall_enabled": true,
+    "wall_enabled": false,
     "wiki_enabled": true,
-    "snippets_enabled": true,
-    "created_at": "2012-05-30T12:49:20Z",
-    "last_activity_at": "2012-05-23T08:05:02Z"
+    "snippets_enabled": false,
+    "created_at": "2013-09-30T13:46:02Z",
+    "last_activity_at": "2013-09-30T13:46:02Z",
+    "namespace":  {
+      "created_at": "2013-09-30T13:46:02Z",
+      "description": "",
+      "id": 4,
+      "name": "Brightbox",
+      "owner_id": 1,
+      "path": "brightbox",
+      "updated_at": "2013-09-30T13:46:02Z"
+    }
   }
 ]
 ```
@@ -76,29 +97,38 @@ Parameters:
 
 ```json
 {
-  "id": 5,
-  "name": "gitlab",
-  "name_with_namespace": "GitLab / gitlabhq",
+  "id": 3,
   "description": null,
-  "default_branch": "api",
+  "default_branch": "master",
+  "public": false,
+  "ssh_url_to_repo": "git@example.com:diaspora/diaspora-project-site.git",
+  "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git",
+  "web_url": "http://example.com/diaspora/diaspora-project-site",
   "owner": {
-    "id": 1,
-    "username": "john_smith",
-    "email": "john@example.com",
-    "name": "John Smith",
-    "blocked": false,
-    "created_at": "2012-05-23T08:00:58Z"
+    "id": 3,
+    "name": "Diaspora",
+    "created_at": "2013-09-30T13: 46: 02Z"
   },
-  "public": true,
-  "path": "gitlab",
-  "path_with_namespace": "randx/gitlab",
+  "name": "Diaspora Project Site",
+  "name_with_namespace": "Diaspora / Diaspora Project Site",
+  "path": "diaspora-project-site",
+  "path_with_namespace": "diaspora/diaspora-project-site",
   "issues_enabled": true,
   "merge_requests_enabled": true,
-  "wall_enabled": true,
+  "wall_enabled": false,
   "wiki_enabled": true,
-  "snippets_enabled": true,
-  "created_at": "2012-05-30T12:49:20Z",
-  "last_activity_at": "2012-05-23T08:05:02Z"
+  "snippets_enabled": false,
+  "created_at": "2013-09-30T13: 46: 02Z",
+  "last_activity_at": "2013-09-30T13: 46: 02Z",
+  "namespace": {
+    "created_at": "2013-09-30T13: 46: 02Z",
+    "description": "",
+    "id": 3,
+    "name": "Diaspora",
+    "owner_id": 1,
+    "path": "diaspora",
+    "updated_at": "2013-09-30T13: 46: 02Z"
+  }
 }
 ```
 
@@ -191,17 +221,6 @@ Parameters:
 + `snippets_enabled` (optional)
 + `public` (optional)
 
-**Project access levels**
-
-The project access levels are defined in the `user_project.rb` class. Currently, these levels are recognized:
-
-```
-  GUEST     = 10
-  REPORTER  = 20
-  DEVELOPER = 30
-  MASTER    = 40
-```
-
 
 ### Create project for user
 
@@ -261,7 +280,7 @@ Parameters:
   "username": "john_smith",
   "email": "john@example.com",
   "name": "John Smith",
-  "blocked": false,
+  "state": "active",
   "created_at": "2012-05-23T08:00:58Z",
   "access_level": 40
 }
@@ -417,6 +436,55 @@ Parameters:
 
 + `id` (required) - The ID of the project
 
+```json
+[
+  {
+    "name":"async",
+    "commit": {
+      "id":"a2b702edecdf41f07b42653eb1abe30ce98b9fca",
+      "parents": [{
+        "id":"3f94fc7c85061973edc9906ae170cc269b07ca55"
+      }],
+      "tree": "c68537c6534a02cc2b176ca1549f4ffa190b58ee",
+      "message":"give caolan his credit where it's due (up top)",
+      "author": {
+        "name":"Jeremy Ashkenas",
+        "email":"jashkenas@example.com"
+      },
+      "committer": {
+        "name":"Jeremy Ashkenas",
+        "email":"jashkenas@example.com"
+      },
+      "authored_date":"2010-12-08T21:28:50+00:00",
+      "committed_date":"2010-12-08T21:28:50+00:00"
+    },
+    "protected":false
+  },
+  {
+    "name": "gh-pages",
+    "commit": {
+      "id": "101c10a60019fe870d21868835f65c25d64968fc",
+      "parents": [{
+        "id": "9c15d2e26945a665131af5d7b6d30a06ba338aaa"
+      }],
+      "tree": "fb5cc9d45da3014b17a876ad539976a0fb9b352a",
+      "message": "Underscore.js 1.5.2",
+      "author": {
+        "name": "Jeremy Ashkenas",
+        "email": "jashkenas@example.com"
+      },
+      "committer": {
+        "name": "Jeremy Ashkenas",
+        "email": "jashkenas@example.com"
+      },
+      "authored_date": "2013-09-07T12: 58: 21+00: 00",
+      "committed_date": "2013-09-07T12: 58: 21+00: 00"
+    },
+    "protected": false
+  }
+]
+
+```
 
 ### List single branch
 
@@ -484,3 +552,18 @@ DELETE /projects/:id/fork
 Parameter:
 
 + `id` (required) - The ID of the project
+
+
+## Search for projects by name
+
+Search for projects by name which are public or the calling user has access to
+
+```
+GET /projects/search/:query
+```
+
+Parameters:
+
++   query (required) - A string contained in the project name
++   per_page (optional) - number of projects to return per page
++   page (optional) - the page to retrieve
diff --git a/doc/api/session.md b/doc/api/session.md
index 8caf5fe1862e5224c7f2da3d36f27d0a9f696ae5..162d4c8bf78282c2b6003fe17bfd20f764289cd5 100644
--- a/doc/api/session.md
+++ b/doc/api/session.md
@@ -27,7 +27,7 @@ __You can login with both GitLab and LDAP credentials now__
   "linkedin": "",
   "twitter": "",
   "dark_scheme": false,
-  "theme_id": 1
+  "theme_id": 1,
   "is_admin": false,
   "can_create_group" : true,
   "can_create_team" : true,
diff --git a/doc/api/system_hooks.md b/doc/api/system_hooks.md
index dca22c43f833fc0a903ce3a71873c1ba755adfff..5eeb3652d577a13a5e2c1de1732932c7f026bcbd 100644
--- a/doc/api/system_hooks.md
+++ b/doc/api/system_hooks.md
@@ -12,6 +12,15 @@ Parameters:
 
 + **none**
 
+```json
+[
+  {
+    "id":3,
+    "url":"http://example.com/hook",
+    "created_at":"2013-10-02T10:15:31Z"
+  }
+]
+```
 
 ## Add new system hook hook
 
@@ -34,6 +43,16 @@ Parameters:
 
 + `id` (required) - The ID of hook
 
+```json
+{
+  "event_name":"project_create",
+  "name":"Ruby",
+  "path":"ruby",
+  "project_id":1,
+  "owner_name":"Someone",
+  "owner_email":"example@gitlabhq.com"
+}
+```
 
 ## Delete system hook
 
diff --git a/doc/api/user_teams.md b/doc/api/user_teams.md
deleted file mode 100644
index cf467a54667d942331332b5079cbd6e3acfd51fb..0000000000000000000000000000000000000000
--- a/doc/api/user_teams.md
+++ /dev/null
@@ -1,209 +0,0 @@
-## User teams
-
-### List user teams
-
-Get a list of user teams viewable by the authenticated user.
-
-```
-GET /user_teams
-```
-
-```json
-[
-    {
-        id: 1,
-        name: "User team 1",
-        path: "user_team1",
-        owner_id: 1
-    },
-    {
-        id: 2,
-        name: "User team 2",
-        path: "user_team2",
-        owner_id: 1
-    }
-]
-```
-
-
-### Get single user team
-
-Get a specific user team, identified by user team ID, which is viewable by the authenticated user.
-
-```
-GET /user_teams/:id
-```
-
-Parameters:
-
-+ `id` (required) - The ID of a user_team
-
-```json
-{
-    id: 1,
-    name: "User team 1",
-    path: "user_team1",
-    owner_id: 1
-}
-```
-
-
-### Create user team
-
-Creates new user team owned by user. Available only for admins.
-
-```
-POST /user_teams
-```
-
-Parameters:
-
-+ `name` (required) - new user team name
-+ `path` (required) - new user team internal name
-
-
-
-## User team members
-
-### List user team members
-
-Get a list of project team members.
-
-```
-GET /user_teams/:id/members
-```
-
-Parameters:
-
-+ `id` (required) - The ID of a user_team
-
-
-### Get user team member
-
-Gets a user team member.
-
-```
-GET /user_teams/:id/members/:user_id
-```
-
-Parameters:
-
-+ `id` (required) - The ID of a user_team
-+ `user_id` (required) - The ID of a user
-
-```json
-{
-    id: 2,
-    username: "john_doe",
-    email: "joh@doe.org",
-    name: "John Doe",
-    state: "active",
-    created_at: "2012-10-22T14:13:35Z",
-    access_level: 30
-}
-```
-
-
-### Add user team member
-
-Adds a user to a user team.
-
-```
-POST /user_teams/:id/members
-```
-
-Parameters:
-
-+ `id` (required) - The ID of a user team
-+ `user_id` (required) - The ID of a user to add
-+ `access_level` (required) - Project access level
-
-
-### Remove user team member
-
-Removes user from user team.
-
-```
-DELETE /user_teams/:id/members/:user_id
-```
-
-Parameters:
-
-+ `id` (required) - The ID of a user team
-+ `user_id` (required) - The ID of a team member
-
-## User team projects
-
-### List user team projects
-
-Get a list of project team projects.
-
-```
-GET /user_teams/:id/projects
-```
-
-Parameters:
-
-+ `id` (required) - The ID of a user_team
-
-
-### Get user team project
-
-Gets a user team project.
-
-```
-GET /user_teams/:id/projects/:project_id
-```
-
-Parameters:
-
-+ `id` (required) - The ID of a user_team
-+ `project_id` (required) - The ID of a user
-
-```json
-{
-    id: 12,
-    name: "project1",
-    description: null,
-    default_branch: "develop",
-    public: false,
-    path: "project1",
-    path_with_namespace: "group1/project1",
-    issues_enabled: false,
-    merge_requests_enabled: true,
-    wall_enabled: true,
-    wiki_enabled: false,
-    created_at: "2013-03-11T12:59:08Z",
-    greatest_access_level: 30
-}
-```
-
-
-### Add user team project
-
-Adds a project to a user team.
-
-```
-POST /user_teams/:id/projects
-```
-
-Parameters:
-
-+ `id` (required) - The ID of a user team
-+ `project_id` (required) - The ID of a project to add
-+ `greatest_access_level` (required) - Maximum project access level
-
-
-### Remove user team project
-
-Removes project from user team.
-
-```
-DELETE /user_teams/:id/projects/:project_id
-```
-
-Parameters:
-
-+ `id` (required) - The ID of a user team
-+ `project_id` (required) - The ID of a team project
-
diff --git a/doc/api/users.md b/doc/api/users.md
index 20664f1e7407d978ff08ced800f17cb746df67b9..16479ea6e0df7cf35b32b4f5f904f3bb929d44af 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -22,8 +22,10 @@ GET /users
     "twitter": "",
     "extern_uid": "john.smith",
     "provider": "provider_name",
-    "theme_id": 1
-    "color_scheme_id": 2
+    "theme_id": 1,
+    "color_scheme_id": 2,
+    "is_admin": false,
+    "can_create_group": true
   },
   {
     "id": 2,
@@ -38,8 +40,11 @@ GET /users
     "twitter": "",
     "extern_uid": "jack.smith",
     "provider": "provider_name",
-    "theme_id": 1
-    "color_scheme_id": 3
+    "theme_id": 1,
+    "color_scheme_id": 3,
+    "is_admin": false,
+    "can_create_group": true,
+    "can_create_project": true
   }
 ]
 ```
@@ -71,8 +76,11 @@ Parameters:
   "twitter": "",
   "extern_uid": "john.smith",
   "provider": "provider_name",
-  "theme_id": 1
-  "color_scheme_id": 2
+  "theme_id": 1,
+  "color_scheme_id": 2,
+  "is_admin": false,
+  "can_create_group": true,
+  "can_create_project": true
 }
 ```
 
@@ -87,17 +95,19 @@ POST /users
 
 Parameters:
 
-+ `email` (required)          - Email
-+ `password` (required)       - Password
-+ `username` (required)       - Username
-+ `name` (required)           - Name
-+ `skype` (optional)          - Skype ID
-+ `linkedin` (optional)       - Linkedin
-+ `twitter` (optional)        - Twitter account
-+ `projects_limit` (optional) - Number of projects user can create
-+ `extern_uid` (optional)     - External UID
-+ `provider` (optional)       - External provider name
-+ `bio` (optional)            - User's bio
++ `email` (required)            - Email
++ `password` (required)         - Password
++ `username` (required)         - Username
++ `name` (required)             - Name
++ `skype` (optional)            - Skype ID
++ `linkedin` (optional)         - Linkedin
++ `twitter` (optional)          - Twitter account
++ `projects_limit` (optional)   - Number of projects user can create
++ `extern_uid` (optional)       - External UID
++ `provider` (optional)         - External provider name
++ `bio` (optional)              - User's bio
++ `admin` (optional)            - User is admin - true or false (default)
++ `can_create_group` (optional) - User can create groups - true or false
 
 
 ## User modification
@@ -121,6 +131,8 @@ Parameters:
 + `extern_uid`                        - External UID
 + `provider`                          - External provider name
 + `bio`                               - User's bio
++ `admin` (optional)                  - User is admin - true or false (default)
++ `can_create_group` (optional)       - User can create groups - true or false
 
 Note, at the moment this method does only return a 404 error, even in cases where a 409 (Conflict) would
 be more appropriate, e.g. when renaming the email address to some existing one.
@@ -162,11 +174,10 @@ GET /user
   "skype": "",
   "linkedin": "",
   "twitter": "",
-  "theme_id": 1
-  "color_scheme_id": 2
+  "theme_id": 1,
+  "color_scheme_id": 2,
   "is_admin": false,
   "can_create_group" : true,
-  "can_create_team" : true,
   "can_create_project" : true
 }
 ```
@@ -184,14 +195,14 @@ GET /user/keys
 [
   {
     "id": 1,
-    "title" : "Public key"
+    "title" : "Public key",
     "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
       596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
       soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
   },
   {
     "id": 3,
-    "title" : "Another Public key"
+    "title" : "Another Public key",
     "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
       596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
       soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
@@ -219,7 +230,7 @@ Parameters:
 ```json
 {
   "id": 1,
-  "title" : "Public key"
+  "title" : "Public key",
   "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
       596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
       soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
diff --git a/doc/install/databases.md b/doc/install/databases.md
index 5ec1d0c6524e41c76ce7f752e7e8fe0cab2068a4..be7bc0aad2ec471782a096548ad4b5f87aaca1ae 100644
--- a/doc/install/databases.md
+++ b/doc/install/databases.md
@@ -14,6 +14,9 @@ GitLab supports the following databases:
     # Pick a database root password (can be anything), type it and press enter
     # Retype the database root password and press enter
 
+    # Secure your installation.
+    sudo mysql_secure_installation
+    
     # Login to MySQL
     mysql -u root -p
 
@@ -55,7 +58,7 @@ GitLab supports the following databases:
     sudo -u postgres psql -d template1
 
     # Create a user for GitLab. (change $password to a real password)
-    template1=# CREATE USER git WITH PASSWORD '$password';
+    template1=# CREATE USER git;
 
     # Create the GitLab production database & grant all privileges on database
     template1=# CREATE DATABASE gitlabhq_production OWNER git;
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 6523961d4d59a29a715dbe115e6110fd184620f1..933799776bd12aa0ceea781d26b0fa9a641e86f2 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -86,7 +86,7 @@ Then select 'Internet Site' and press enter to confirm the hostname.
 
 Remove the old Ruby 1.8 if present
 
-    sudo apt-get remove -y ruby1.8
+    sudo apt-get remove ruby1.8
 
 Download Ruby and compile it:
 
@@ -111,7 +111,7 @@ Create a `git` user for Gitlab:
 
 # 4. GitLab shell
 
-GitLab Shell is a ssh access and repository management software developed specially for GitLab.
+GitLab Shell is an ssh access and repository management software developed specially for GitLab.
 
     # Go to home directory
     cd /home/git
@@ -122,7 +122,7 @@ GitLab Shell is a ssh access and repository management software developed specia
     cd gitlab-shell
 
     # switch to right version
-    sudo -u git -H git checkout v1.7.0
+    sudo -u git -H git checkout v1.7.1
 
     sudo -u git -H cp config.yml.example config.yml
 
@@ -153,10 +153,10 @@ To setup the MySQL/PostgreSQL database and dependencies please see [`doc/install
     cd /home/git/gitlab
 
     # Checkout to stable release
-    sudo -u git -H git checkout 6-0-stable
+    sudo -u git -H git checkout 6-1-stable
 
 **Note:**
-You can change `6-0-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
+You can change `6-1-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
 
 ## Configure it
 
@@ -195,6 +195,13 @@ You can change `6-0-stable` to `master` if you want the *bleeding edge* version,
     # Ex. change amount of workers to 3 for 2GB RAM server
     sudo -u git -H editor config/unicorn.rb
 
+    # Copy the example Rack attack config
+    sudo -u git -H cp config/initializers/rack_attack.rb.example config/initializers/rack_attack.rb
+
+    # Enable rack attack middleware
+    # Find and uncomment the line 'config.middleware.use Rack::Attack'
+    sudo -u git -H editor config/application.rb
+
     # Configure Git global settings for git user, useful when editing via web
     # Edit user.email according to what is set in gitlab.yml
     sudo -u git -H git config --global user.name "GitLab"
@@ -209,18 +216,18 @@ Make sure to edit both `gitlab.yml` and `unicorn.rb` to match your setup.
     # Mysql
     sudo -u git cp config/database.yml.mysql config/database.yml
 
-    or
-
-    # PostgreSQL
-    sudo -u git cp config/database.yml.postgresql config/database.yml
-
     # Make sure to update username/password in config/database.yml.
     # You only need to adapt the production settings (first part).
     # If you followed the database guide then please do as follows:
-    # Change 'root' to 'gitlab'
     # Change 'secure password' with the value you have given to $password
     # You can keep the double quotes around the password
     sudo -u git -H editor config/database.yml
+
+    or
+
+    # PostgreSQL
+    sudo -u git cp config/database.yml.postgresql config/database.yml
+
     
     # Make config/database.yml readable to git only
     sudo -u git -H chmod o-rwx config/database.yml
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index 1dba04f4237033c498406e2d05d5a8f7c75ee4c7..30a9564674105e7ed847e5328c1786e630b238ea 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -41,23 +41,30 @@ some work on your part.
 
 ## CPU
 
-We recommend a processor with **4 cores**. At a minimum you need a processor with 2 cores to responsively run an unmodified installation.
+- 1 core works for under 100 users but the responsiveness might suffer
+- **2 cores** is the **recommended** number of cores and supports up to 100 users
+- 4 cores supports about 1,000 users
+- 8 cores supports up to 10,000 users
 
 ## Memory
 
 - 512MB is too little memory, GitLab will be very slow and you will need 250MB of swap
-- 768MB is the minimal memory size and supports up to 100 users
-- **1GB** is the **recommended** memory size and supports up to 1,000 users
-- 1.5GB supports up to 10,000 users
+- 768MB is the minimal memory size but we advise against this
+- 1GB supports up to 100 users if you do not have individual repo's over 250MB
+- **2GB** is the **recommended** memory size and supports up to 1,000 users
+- 4GB supports up to 10,000 users
 
 ## Storage
 
 The necessary hard drive space largely depends on the size of the repos you want
 to store in GitLab. But as a *rule of thumb* you should have at least twice as much
-free space as your all repos combined take up. You need twice the storage because [GitLab satellites](structure.md) contain an extra copy of each repo. Apart from a local hard drive you can also mount a volume that supports the network file system (NFS) protocol. This volume might be located on a file server, a network attached storage (NAS) device, a storage area network (SAN) or on an Amazon Web Services (AWS) Elastic Block Store (EBS) volume.
+free space as your all repos combined take up. You need twice the storage because [GitLab satellites](structure.md) contain an extra copy of each repo.
 
-If you have enough RAM memory and a recent CPU the speed of GitLab is mainly limited by hard drive seek times. Having a fast drive (7200 RPM and up) or a solid state drive (SSD) will improve the responsiveness of GitLab.
+If you want to be flexible about growing your hard drive space in the future consider mounting it using LVM so you can add more hard drives when you need them.
+
+Apart from a local hard drive you can also mount a volume that supports the network file system (NFS) protocol. This volume might be located on a file server, a network attached storage (NAS) device, a storage area network (SAN) or on an Amazon Web Services (AWS) Elastic Block Store (EBS) volume.
 
+If you have enough RAM memory and a recent CPU the speed of GitLab is mainly limited by hard drive seek times. Having a fast drive (7200 RPM and up) or a solid state drive (SSD) will improve the responsiveness of GitLab.
 
 # Installation troubles and reporting success or failure
 
diff --git a/doc/raketasks/maintenance.md b/doc/raketasks/maintenance.md
index 68c1a72b230396d8d8a6f4caf58b614181fd5221..3033d8c46b4e4c2b9015a4c9fa7fb508ee6e88db 100644
--- a/doc/raketasks/maintenance.md
+++ b/doc/raketasks/maintenance.md
@@ -122,7 +122,7 @@ Notes:
 
 How to use:
 
-1. copy your bare repos under git base_path (see `config/gitlab.yml` git_host -> base_path)
+1. copy your bare repos under git repos_path (see `config/gitlab.yml` gitlab_shell -> repos_path)
 2. run the command below
 
 ```
diff --git a/doc/raketasks/web_hooks.md b/doc/raketasks/web_hooks.md
new file mode 100644
index 0000000000000000000000000000000000000000..1ca5bacb9d104050c6317ce8e76a46759c6eca32
--- /dev/null
+++ b/doc/raketasks/web_hooks.md
@@ -0,0 +1,31 @@
+### Add a web hook for **ALL** projects:
+
+    RAILS_ENV=production bundle exec rake gitlab:web_hook:add URL="http://example.com/hook"
+
+
+### Add a web hook for projects in a given **NAMESPACE**:
+
+    RAILS_ENV=production bundle exec rake gitlab:web_hook:add URL="http://example.com/hook" NAMESPACE=acme
+
+
+### Remove a web hook from **ALL** projects using:
+
+    RAILS_ENV=production bundle exec rake gitlab:web_hook:rm URL="http://example.com/hook"
+
+
+### Remove a web hook from projects in a given **NAMESPACE**:
+
+    RAILS_ENV=production bundle exec rake gitlab:web_hook:rm URL="http://example.com/hook" NAMESPACE=acme
+
+
+### List **ALL** web hooks:
+
+    RAILS_ENV=production bundle exec rake gitlab:web_hook:list
+
+
+### List the web hooks from projects in a given **NAMESPACE**:
+
+    RAILS_ENV=production bundle exec rake gitlab:web_hook:list NAMESPACE=/
+
+> Note: `/` is the global namespace.
+
diff --git a/doc/security/rack_attack.md b/doc/security/rack_attack.md
new file mode 100644
index 0000000000000000000000000000000000000000..a0d02b1650f3e4453451fb1de424a1e665267dbd
--- /dev/null
+++ b/doc/security/rack_attack.md
@@ -0,0 +1,19 @@
+To prevent abusive clients doing damage GitLab uses rack-attack gem.
+If you installed or upgraded GitLab by following the official guides this should be enabled by default.
+If you are missing `config/initializers/rack_attack.rb` the following steps need to be taken in order to enable protection for your GitLab instance:
+
+1. In config/application.rb find and uncomment the following line:
+  config.middleware.use Rack::Attack
+2. Rename config/initializers/rack_attack.rb.example to config/initializers/rack_attack.rb
+3. Review the paths_to_be_protected and add any other path you need protecting
+4. Restart GitLab instance
+
+By default, user sign-in, user sign-up(if enabled) and user password reset is limited to 6 requests per minute.
+After trying for 6 times, client will have to wait for the next minute to be able to try again.
+These settings can be found in `config/initializers/rack_attack.rb`
+
+If you want more restrictive/relaxed throttle rule change the `limit` or `period` values. For example, more relaxed throttle rule will be if you set limit: 3 and period: 1.second(this will allow 3 requests per second). You can also add other paths to the protected list by adding to `paths_to_be_protected` variable. If you change any of these settings do not forget to restart your GitLab instance.
+
+In case you find throttling is not enough to protect you against abusive clients, rack-attack gem offers IP whitelisting, blacklisting, Fail2ban style filter and tracking.
+
+For more information on how to use these options check out [rack-attack README](https://github.com/kickstarter/rack-attack/blob/master/README.md).
\ No newline at end of file
diff --git a/doc/update/4.1-to-4.2.md b/doc/update/4.1-to-4.2.md
index 536f22415e229b1f215e05357145f801ad31cd2a..3aaf17b7727bf2f33880d71f23f88bd10ec82db9 100644
--- a/doc/update/4.1-to-4.2.md
+++ b/doc/update/4.1-to-4.2.md
@@ -12,15 +12,15 @@
 cd /home/gitlab/gitlab/
 
 # Get latest code
-sudo -u gitlab git fetch
+sudo -u gitlab -H git fetch
 
-sudo -u gitlab git checkout 4-2-stable
+sudo -u gitlab -H git checkout 4-2-stable
 
 # Install libs
-sudo -u gitlab bundle install --without development test postgres --deployment
+sudo -u gitlab -H bundle install --without development test postgres --deployment
 
 # update db
-sudo -u gitlab bundle exec rake db:migrate RAILS_ENV=production
+sudo -u gitlab -H bundle exec rake db:migrate RAILS_ENV=production
 
 ```
 
diff --git a/doc/update/4.2-to-5.0.md b/doc/update/4.2-to-5.0.md
index 053a50ebc88405008e2e78fe8a2794355daebbae..64b89ee93cfc9976979c2b4636a705052dcc3e47 100644
--- a/doc/update/4.2-to-5.0.md
+++ b/doc/update/4.2-to-5.0.md
@@ -85,7 +85,7 @@ sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
 sudo -u git -H bundle exec rake gitlab:shell:setup RAILS_ENV=production
 sudo -u git -H bundle exec rake gitlab:shell:build_missing_projects RAILS_ENV=production
 
-sudo -u git -H mkdir /home/git/gitlab-satellites
+sudo -u git -H mkdir -p /home/git/gitlab-satellites
 sudo -u git -H bundle exec rake gitlab:satellites:create RAILS_ENV=production
 
 # migrate wiki to git
@@ -101,7 +101,7 @@ sudo chown -R git /home/git/gitlab/log/
 sudo chown -R git /home/git/gitlab/tmp/
 sudo chmod -R u+rwX  /home/git/gitlab/log/
 sudo chmod -R u+rwX  /home/git/gitlab/tmp/
-sudo -u git -H mkdir /home/git/gitlab/tmp/pids/
+sudo -u git -H mkdir -p /home/git/gitlab/tmp/pids/
 sudo chmod -R u+rwX  /home/git/gitlab/tmp/pids
 
 ```
diff --git a/doc/update/5.1-to-5.2.md b/doc/update/5.1-to-5.2.md
index 8599c4323eae0a41cc07c17db40add1f29cf089d..27f992ecfe6831436ed4c48cb9620859f76d1b4c 100644
--- a/doc/update/5.1-to-5.2.md
+++ b/doc/update/5.1-to-5.2.md
@@ -7,7 +7,7 @@ It's useful to make a backup just in case things go south:
 
 ```bash
 cd /home/git/gitlab
-sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:create
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
 ```
 
 ### 1. Stop server
@@ -95,5 +95,5 @@ Follow the [`upgrade guide from 5.0 to 5.1`](5.0-to-5.1.md), except for the data
 
 ```bash
 cd /home/git/gitlab
-sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:restore
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
 ```
diff --git a/doc/update/5.2-to-5.3.md b/doc/update/5.2-to-5.3.md
index e00dfa3951a47f79bb0d09274b4e98f8ab5ede4d..a8bb530902c37fa11c63bf8bbaaef1b2c42da6f4 100644
--- a/doc/update/5.2-to-5.3.md
+++ b/doc/update/5.2-to-5.3.md
@@ -7,7 +7,7 @@ It's useful to make a backup just in case things go south:
 
 ```bash
 cd /home/git/gitlab
-sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:create
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
 ```
 
 ### 1. Stop server
@@ -78,5 +78,5 @@ Follow the [`upgrade guide from 5.1 to 5.2`](5.1-to-5.2.md), except for the data
 
 ```bash
 cd /home/git/gitlab
-sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:restore
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
 ```
diff --git a/doc/update/5.3-to-5.4.md b/doc/update/5.3-to-5.4.md
index 5fba0e26afa437727f281bca4df1b250ce03c4e0..315bf03a6deb5fb0169377bd2e12a60764802ce0 100644
--- a/doc/update/5.3-to-5.4.md
+++ b/doc/update/5.3-to-5.4.md
@@ -7,7 +7,7 @@ It's useful to make a backup just in case things go south:
 
 ```bash
 cd /home/git/gitlab
-sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:create
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
 ```
 
 ### 1. Stop server
@@ -86,5 +86,5 @@ Follow the [`upgrade guide from 5.2 to 5.3`](5.2-to-5.3.md), except for the data
 
 ```bash
 cd /home/git/gitlab
-sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:restore
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
 ```
diff --git a/doc/update/5.4-to-6.0.md b/doc/update/5.4-to-6.0.md
index 0869dd833f9c21630170de790129a85ca890a93b..0027d91d60aca886d08ac0edb82ca961ece3ac76 100644
--- a/doc/update/5.4-to-6.0.md
+++ b/doc/update/5.4-to-6.0.md
@@ -4,8 +4,8 @@
 
 #### Global projects
 
-We deprecated root(global) namespace for projects.
-So you need to move all your global projects under group/users manually before update or they will be automatically moved to the owner namespace during the update.
+The root (global) namespace for projects is deprecated.
+So you need to move all your global projects under groups or users manually before update or they will be automatically moved to the project owner namespace during the update. When a project is moved all its members will receive an email with instructions how to update their git remote url. Please make sure you disable ssending email when you do a test of the upgrade.
 
 #### Teams
 
@@ -24,7 +24,7 @@ It's useful to make a backup just in case things go south:
 
 ```bash
 cd /home/git/gitlab
-sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:create
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
 ```
 
 ### 1. Stop server
@@ -70,6 +70,7 @@ sudo -u git -H bundle exec rake migrate_groups RAILS_ENV=production
 sudo -u git -H bundle exec rake migrate_global_projects RAILS_ENV=production
 sudo -u git -H bundle exec rake migrate_keys RAILS_ENV=production
 sudo -u git -H bundle exec rake migrate_inline_notes RAILS_ENV=production
+sudo -u git -H bundle exec rake gitlab:satellites:create RAILS_ENV=production
 
 # Clear redis cache
 sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
diff --git a/doc/update/6.0-to-6.1.md b/doc/update/6.0-to-6.1.md
index c9a3a31fd27b1f139ec1ef4954a1d8f1659da17a..c3851a10df00ebbf81c750a47f7407b3bbd753ca 100644
--- a/doc/update/6.0-to-6.1.md
+++ b/doc/update/6.0-to-6.1.md
@@ -16,7 +16,7 @@ It's useful to make a backup just in case things go south:
 
 ```bash
 cd /home/git/gitlab
-sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:create
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
 ```
 
 ### 1. Stop server
@@ -36,7 +36,7 @@ sudo -u git -H git checkout 6-1-stable
 ```bash
 cd /home/git/gitlab-shell
 sudo -u git -H git fetch
-sudo -u git -H git checkout v1.7.0
+sudo -u git -H git checkout v1.7.1
 ```
 
 ### 4. Install libs, migrations, etc.
@@ -53,13 +53,15 @@ sudo -u git -H bundle install --without development test mysql --deployment
 
 sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
 sudo -u git -H bundle exec rake migrate_iids RAILS_ENV=production
+sudo -u git -H bundle exec rake assets:clean RAILS_ENV=production
 sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
+sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
 ```
 
 ### 5. Update config files
 
-* Make `/home/git/gitlab/config/gitlab.yml` same as https://github.com/gitlabhq/gitlabhq/blob/5-4-stable/config/gitlab.yml.example but with your settings.
-* Make `/home/git/gitlab/config/unicorn.rb` same as https://github.com/gitlabhq/gitlabhq/blob/5-4-stable/config/unicorn.rb.example but with your settings.
+* Make `/home/git/gitlab/config/gitlab.yml` same as https://github.com/gitlabhq/gitlabhq/blob/6-1-stable/config/gitlab.yml.example but with your settings.
+* Make `/home/git/gitlab/config/unicorn.rb` same as https://github.com/gitlabhq/gitlabhq/blob/6-1-stable/config/unicorn.rb.example but with your settings.
 
 ### 6. Update Init script
 
@@ -78,6 +80,7 @@ sudo chmod +x /etc/init.d/gitlab
 
 Check if GitLab and its environment are configured correctly:
 
+    cd /home/git/gitlab
     sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
 
 To make sure you didn't miss anything run a more thorough check with:
@@ -96,5 +99,5 @@ Follow the [`upgrade guide from 5.4 to 6.0`](5.4-to-6.0.md), except for the data
 
 ```bash
 cd /home/git/gitlab
-sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:restore
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
 ```
diff --git a/doc/update/6.1-to-6.2.md b/doc/update/6.1-to-6.2.md
new file mode 100644
index 0000000000000000000000000000000000000000..9f3a869a0ee1874225ba8c35bed5cdc9ec672fcf
--- /dev/null
+++ b/doc/update/6.1-to-6.2.md
@@ -0,0 +1,100 @@
+# From 6.1 to 6.2
+
+# You should update to 6.1 before installing 6.2 so all the necessary conversions are run.
+
+### 0. Backup
+
+It's useful to make a backup just in case things go south:
+(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version)
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
+```
+
+### 1. Stop server
+
+    sudo service gitlab stop
+
+### 2. Get latest code
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H git fetch
+sudo -u git -H git checkout 6-2-stable
+```
+
+### 3. Update gitlab-shell
+
+```bash
+cd /home/git/gitlab-shell
+sudo -u git -H git fetch
+sudo -u git -H git checkout v1.7.1
+```
+
+### 4. Install libs, migrations, etc.
+
+```bash
+cd /home/git/gitlab
+
+# MySQL
+sudo -u git -H bundle install --without development test postgres --deployment
+
+#PostgreSQL
+sudo -u git -H bundle install --without development test mysql --deployment
+
+
+sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
+sudo -u git -H bundle exec rake migrate_iids RAILS_ENV=production
+sudo -u git -H bundle exec rake assets:clean RAILS_ENV=production
+sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
+sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
+```
+
+### 5. Update config files
+
+* Make `/home/git/gitlab/config/gitlab.yml` same as https://github.com/gitlabhq/gitlabhq/blob/6-2-stable/config/gitlab.yml.example but with your settings.
+* Make `/home/git/gitlab/config/unicorn.rb` same as https://github.com/gitlabhq/gitlabhq/blob/6-2-stable/config/unicorn.rb.example but with your settings.
+* Copy rack attack middleware config
+```bash
+sudo -u git -H cp config/initializers/rack_attack.rb.example config/initializers/rack_attack.rb
+```
+* Uncomment `config.middleware.use Rack::Attack` in `/home/git/gitlab/config/application.rb`
+
+### 6. Update Init script
+
+```bash
+sudo rm /etc/init.d/gitlab
+sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlabhq/6-2-stable/lib/support/init.d/gitlab
+sudo chmod +x /etc/init.d/gitlab
+```
+
+### 7. Start application
+
+    sudo service gitlab start
+    sudo service nginx restart
+
+### 8. Check application status
+
+Check if GitLab and its environment are configured correctly:
+
+    sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
+
+To make sure you didn't miss anything run a more thorough check with:
+
+    sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
+
+If all items are green, then congratulations upgrade complete!
+
+## Things went south? Revert to previous version (6.1)
+
+### 1. Revert the code to the previous version
+Follow the [`upgrade guide from 6.0 to 6.1`](6.0-to-6.1.md), except for the database migration 
+(The backup is already migrated to the previous version)
+
+### 2. Restore from the backup:
+
+```bash
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
+```
diff --git a/features/admin/users.feature b/features/admin/users.feature
index 4c951df9fe2cf67de7d67e069bf5ee66a465d3ac..7f503cf923584e25537549aa4d55d537e110415e 100644
--- a/features/admin/users.feature
+++ b/features/admin/users.feature
@@ -13,4 +13,4 @@ Feature: Admin Users
     And Input non ascii char in username
     And Click save
     Then See username error message
-    And Not chenged form action url
+    And Not changed form action url
diff --git a/features/profile/profile.feature b/features/profile/profile.feature
index 53a93b0f9087d76f6dd0a8aa56bb910c9907cd1e..c74b0993fb33fc41719c9547f06ddad4836eaac0 100644
--- a/features/profile/profile.feature
+++ b/features/profile/profile.feature
@@ -11,6 +11,12 @@ Feature: Profile
     Then I change my contact info
     And I should see new contact info
 
+  Scenario: I change my password without old one
+    Given I visit profile account page
+    When I try change my password w/o old one
+    Then I should see a missing password error message
+    And I should be redirected to account page
+
   Scenario: I change my password
     Given I visit profile account page
     Then I change my password
@@ -18,6 +24,7 @@ Feature: Profile
 
   Scenario: My password is expired
     Given my password is expired
+    And I am not an ldap user
     And I visit profile account page
     Then I redirected to expired password page
     And I submit new password
diff --git a/features/project/commits/commits.feature b/features/project/commits/commits.feature
index 56069cdc977840cf5c1e80ab0febbad75b5aea57..fe470f5ac99d52b142dd820e97a3ac30c0a3b78c 100644
--- a/features/project/commits/commits.feature
+++ b/features/project/commits/commits.feature
@@ -27,3 +27,15 @@ Feature: Project Browse commits
   Scenario: I browse commits stats
     Given I visit my project's commits stats page
     Then I see commits stats
+
+  Scenario: I browse big commit
+    Given I visit big commit page
+    Then I see big commit warning
+
+  Scenario: I browse huge commit
+    Given I visit huge commit page
+    Then I see huge commit message
+
+  Scenario: I browse a commit with an image
+    Given I visit a commit with an image that changed
+    Then The diff links to both the previous and current image
diff --git a/features/project/create_project.feature b/features/project/create_project.feature
index b7cdfdb818e4986462c718fc8b9cb80152110040..395a3218b2bbcdc93df34ac31b6eacac5d154bcc 100644
--- a/features/project/create_project.feature
+++ b/features/project/create_project.feature
@@ -9,3 +9,14 @@ Feature: Create Project
     And fill project form with valid data
     Then I should see project page
     And I should see empty project instuctions
+
+  @javascript
+  Scenario: Empty project instructions
+    Given I sign in as a user
+    When I visit new project page
+    And fill project form with valid data
+    Then I see empty project instuctions
+    And I click on HTTP
+    Then Remote url should update to http link
+    And If I click on SSH
+    Then Remote url should update to ssh link
\ No newline at end of file
diff --git a/features/project/forked_merge_requests.feature b/features/project/forked_merge_requests.feature
index 2c6c1ef574cbbcab56dd28bf2ea5172ba19a4c1c..966905645a29fb00a56b8bdb2d8514695139bafb 100644
--- a/features/project/forked_merge_requests.feature
+++ b/features/project/forked_merge_requests.feature
@@ -4,15 +4,6 @@ Feature: Project Forked Merge Requests
     And I am a member of project "Shop"
     And I have a project forked off of "Shop" called "Forked Shop"
 
-  # TODO: fix
-  #@javascript
-  #Scenario: I can visit the target projects commit for a forked merge request
-    #Given I visit project "Forked Shop" merge requests page
-    #And I click link "New Merge Request"
-    #And I fill out a "Merge Request On Forked Project" merge request
-    #And I follow the target commit link
-    #Then I should see the commit under the forked from project
-
   @javascript
   Scenario: I submit new unassigned merge request to a forked project
     Given I visit project "Forked Shop" merge requests page
diff --git a/features/project/issues/issues.feature b/features/project/issues/issues.feature
index d6ef384c9a63d470d7c9baffb0df275c3edd3c7f..67986784bc728c2810641416c9fa2c323b82f970 100644
--- a/features/project/issues/issues.feature
+++ b/features/project/issues/issues.feature
@@ -3,6 +3,7 @@ Feature: Project Issues
     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 "Tweet control" open issue
     And project "Shop" have "Release 0.3" closed issue
     And I visit project "Shop" issues page
 
@@ -37,37 +38,20 @@ Feature: Project Issues
 
   @javascript
   Scenario: I search issue
-    Given I fill in issue search with "Release"
+    Given I fill in issue search with "Re"
     Then I should see "Release 0.4" in issues
     And I should not see "Release 0.3" in issues
+    And I should not see "Tweet control" in issues
 
   @javascript
   Scenario: I search issue that not exist
-    Given I fill in issue search with "Bug"
+    Given I fill in issue search with "Bu"
     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"
+    And I fill in issue search with ".3"
     Then I should see "Release 0.3" in issues
     And I should not see "Release 0.4" in issues
-
-  # Disable this two cause of random failing
-  # TODO: fix after v4.0 released
-  #@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/service.feature b/features/project/service.feature
index 6bb0c3e2c5734527b960151ba579746ca4683fb0..4805d2befbea9abcdc0d5cd046d704720e2e0602 100644
--- a/features/project/service.feature
+++ b/features/project/service.feature
@@ -18,3 +18,15 @@ Feature: Project Services
     And I click hipchat service link
     And I fill hipchat settings
     Then I should see hipchat service settings saved
+
+  Scenario: Activate pivotaltracker service
+    When I visit project "Shop" services page
+    And I click pivotaltracker service link
+    And I fill pivotaltracker settings
+    Then I should see pivotaltracker service settings saved
+
+  Scenario: Activate Flowdock service
+    When I visit project "Shop" services page
+    And I click Flowdock service link
+    And I fill Flowdock settings
+    Then I should see Flowdock service settings saved
diff --git a/features/project/snippets.feature b/features/project/snippets.feature
index a26c8dc84747f3561666611bd81fb1ae5757319e..dfaa02663a03b38934f38df23df828cad3cdad94 100644
--- a/features/project/snippets.feature
+++ b/features/project/snippets.feature
@@ -31,5 +31,5 @@ Feature: Project Snippets
   Scenario: I destroy "Snippet one"
     Given I visit snippet page "Snippet one"
     And I click link "Edit"
-    And I click link "Destroy"
+    And I click link "Remove Snippet"
     Then I should not see "Snippet one" in snippets
diff --git a/features/public/public_projects.feature b/features/public/public_projects.feature
index c4f1b6203e7ca62d475e7b4e935f007a21480e72..178a769194c38b50e0dcfd31256b7a1e5179b88c 100644
--- a/features/public/public_projects.feature
+++ b/features/public/public_projects.feature
@@ -9,6 +9,10 @@ Feature: Public Projects Feature
     And I should not see project "Enterprise"
 
   Scenario: I visit public project page
-    When I visit public page for "Community" project
-    Then I should see public project details
-    And I should see project readme
+    When I visit project "Community" page
+    Then I should see project "Community" home page
+
+  Scenario: I visit an empty public project page
+    Given public empty project "Empty Public Project"
+    When I visit empty project page
+    Then I should see empty public project details
diff --git a/features/steps/admin/admin_users.rb b/features/steps/admin/admin_users.rb
index 61b3ed91beb74447f942734ffe715d12c9860b51..33c1344eaeb4c6ca812d59e7f67ef3b6df4ef8bf 100644
--- a/features/steps/admin/admin_users.rb
+++ b/features/steps/admin/admin_users.rb
@@ -28,7 +28,7 @@ class AdminUsers < Spinach::FeatureSteps
     end
   end
 
-  And 'Not chenged form action url' do
+  And 'Not changed form action url' do
     page.should have_selector %(form[action="/admin/users/#{@user.username}"])
   end
 end
diff --git a/features/steps/dashboard/dashboard.rb b/features/steps/dashboard/dashboard.rb
index 5baf4e757aca534190527f58082bacdc274285da..bde32128b9237695e733b4df283801f4f4f20d88 100644
--- a/features/steps/dashboard/dashboard.rb
+++ b/features/steps/dashboard/dashboard.rb
@@ -57,7 +57,7 @@ class Dashboard < Spinach::FeatureSteps
 
   And 'I have group with projects' do
     @group   = create(:group)
-    @project = create(:project, group: @group)
+    @project = create(:project, namespace: @group)
     @event   = create(:closed_issue_event, project: @project)
 
     @project.team << [current_user, :master]
diff --git a/features/steps/group/group.rb b/features/steps/group/group.rb
index 45dda6ff55ee1af33dd1c77b559a4e28f789c4ed..99ec77a7613870f1aaf3b479e4153729d8de0aa5 100644
--- a/features/steps/group/group.rb
+++ b/features/steps/group/group.rb
@@ -10,8 +10,9 @@ class Groups < Spinach::FeatureSteps
   end
 
   And 'I have group with projects' do
-    @group   = create(:group, owner: current_user)
-    @project = create(:project, group: @group)
+    @group   = create(:group)
+    @group.add_owner(current_user)
+    @project = create(:project, namespace: @group)
     @event   = create(:closed_issue_event, project: @project)
 
     @project.team << [current_user, :master]
diff --git a/features/steps/profile/profile.rb b/features/steps/profile/profile.rb
index 23eeac447b02546113050576178c766ed1b1a020..5b2a6321265f31e9ec99a9cd6b3d63654d3ea2af 100644
--- a/features/steps/profile/profile.rb
+++ b/features/steps/profile/profile.rb
@@ -22,8 +22,17 @@ class Profile < Spinach::FeatureSteps
     @user.twitter.should == 'testtwitter'
   end
 
+  step 'I try change my password w/o old one' do
+    within '.update-password' do
+      fill_in "user_password", with: "222333"
+      fill_in "user_password_confirmation", with: "222333"
+      click_button "Save"
+    end
+  end
+
   step 'I change my password' do
     within '.update-password' do
+      fill_in "user_current_password", with: "123456"
       fill_in "user_password", with: "222333"
       fill_in "user_password_confirmation", with: "222333"
       click_button "Save"
@@ -32,12 +41,17 @@ class Profile < Spinach::FeatureSteps
 
   step 'I unsuccessfully change my password' do
     within '.update-password' do
+      fill_in "user_current_password", with: "123456"
       fill_in "user_password", with: "password"
       fill_in "user_password_confirmation", with: "confirmation"
       click_button "Save"
     end
   end
 
+  step "I should see a missing password error message" do
+    page.should have_content "You must provide a valid current password"
+  end
+
   step "I should see a password error message" do
     page.should have_content "Password doesn't match confirmation"
   end
@@ -91,6 +105,11 @@ class Profile < Spinach::FeatureSteps
     current_user.update_attributes(password_expires_at: Time.now - 1.hour)
   end
 
+  step "I am not an ldap user" do
+    current_user.update_attributes(extern_uid: nil,  provider: '')
+    current_user.ldap_user?.should be_false
+  end
+
   step 'I redirected to expired password page' do
     current_path.should == new_profile_password_path
   end
@@ -105,6 +124,10 @@ class Profile < Spinach::FeatureSteps
     current_path.should == new_user_session_path
   end
 
+  step 'I should be redirected to account page' do
+    current_path.should == account_profile_path
+  end
+
   step 'I click on my profile picture' do
     click_link 'profile-pic'
   end
diff --git a/features/steps/project/create_project.rb b/features/steps/project/create_project.rb
index 0d9727732c7cdbb10b093873568417aa9bcbc0b9..b59345e7078a1b805abcc69f86f10e6d9eb11cf0 100644
--- a/features/steps/project/create_project.rb
+++ b/features/steps/project/create_project.rb
@@ -17,4 +17,26 @@ class CreateProject < Spinach::FeatureSteps
     page.should have_content "git remote"
     page.should have_content Project.last.url_to_repo
   end
+
+  Then 'I 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
+
+  And 'I click on HTTP' do
+    click_button 'HTTP'
+  end
+
+  Then 'Remote url should update to http link' do
+    page.should have_content "git remote add origin #{Project.last.http_url_to_repo}"
+  end
+
+  And 'If I click on SSH' do
+    click_button 'SSH'
+  end
+
+  Then 'Remote url should update to ssh link' do
+    page.should have_content "git remote add origin #{Project.last.url_to_repo}"
+  end
 end
diff --git a/features/steps/project/project_browse_commits.rb b/features/steps/project/project_browse_commits.rb
index 71f4bd79f7eaa112bff4e85733384219be38f58b..650bc3a16f7ad1363443da3f63aabd409bead6ee 100644
--- a/features/steps/project/project_browse_commits.rb
+++ b/features/steps/project/project_browse_commits.rb
@@ -58,4 +58,34 @@ class ProjectBrowseCommits < Spinach::FeatureSteps
     page.should have_content 'Total commits'
     page.should have_content 'Authors'
   end
+
+  Given 'I visit big commit page' do
+    visit project_commit_path(@project, BigCommits::BIG_COMMIT_ID)
+  end
+
+  Then 'I see big commit warning' do
+    page.should have_content BigCommits::BIG_COMMIT_MESSAGE
+    page.should have_content "Warning! This is a large diff"
+    page.should have_content "If you still want to see the diff"
+  end
+
+  Given 'I visit huge commit page' do
+    visit project_commit_path(@project, BigCommits::HUGE_COMMIT_ID)
+  end
+
+  Then 'I see huge commit message' do
+    page.should have_content BigCommits::HUGE_COMMIT_MESSAGE
+    page.should have_content "Warning! This is a large diff"
+    page.should_not have_content "If you still want to see the diff"
+  end
+
+  Given 'I visit a commit with an image that changed' do
+    visit project_commit_path(@project, 'cc1ba255d6c5ffdce87a357ba7ccc397a4f4026b')
+  end
+
+  Then 'The diff links to both the previous and current image' do
+    links = page.all('.two-up span div a')
+    links[0]['href'].should =~ %r{blob/bc3735004cb45cec5e0e4fa92710897a910a5957}
+    links[1]['href'].should =~ %r{blob/cc1ba255d6c5ffdce87a357ba7ccc397a4f4026b}
+  end
 end
diff --git a/features/steps/project/project_forked_merge_requests.rb b/features/steps/project/project_forked_merge_requests.rb
index 86f16d3bac50fc7abb721758815ad9f9071f924b..f7bf085a4231199a0fbbcefcd469ce89858df72f 100644
--- a/features/steps/project/project_forked_merge_requests.rb
+++ b/features/steps/project/project_forked_merge_requests.rb
@@ -175,10 +175,9 @@ class ProjectForkedMergeRequests < Spinach::FeatureSteps
     @project ||= Project.find_by_name!("Shop")
   end
 
-  #Verify a link is generated against the correct project
+  # Verify a link is generated against the correct project
   def verify_commit_link(container_div, container_project)
-    #This should force a wait for the javascript to execute
-    find(:div,container_div).should have_css ".browse_code_link_holder"
+    # This should force a wait for the javascript to execute
     find(:div,container_div).find(".commit_short_id")['href'].should have_content "#{container_project.path_with_namespace}/commit"
   end
 end
diff --git a/features/steps/project/project_issues.rb b/features/steps/project/project_issues.rb
index 6c18177498f638da66ea25b6ff88ab1db1dd722e..801fff78a52289a06fadc7b63f4cc192045e015c 100644
--- a/features/steps/project/project_issues.rb
+++ b/features/steps/project/project_issues.rb
@@ -12,6 +12,10 @@ class ProjectIssues < Spinach::FeatureSteps
     page.should_not have_content "Release 0.3"
   end
 
+  And 'I should not see "Tweet control" in issues' do
+    page.should_not have_content "Tweet control"
+  end
+
   Given 'I click link "Closed"' do
     click_link "Closed"
   end
@@ -56,16 +60,16 @@ class ProjectIssues < Spinach::FeatureSteps
     page.should have_content issue.project.name
   end
 
-  Given 'I fill in issue search with "Release"' do
-    fill_in 'issue_search', with: "Release"
+  Given 'I fill in issue search with "Re"' do
+    fill_in 'issue_search', with: "Re"
   end
 
-  Given 'I fill in issue search with "Bug"' do
-    fill_in 'issue_search', with: "Bug"
+  Given 'I fill in issue search with "Bu"' do
+    fill_in 'issue_search', with: "Bu"
   end
 
-  And 'I fill in issue search with "0.3"' do
-    fill_in 'issue_search', with: "0.3"
+  And 'I fill in issue search with ".3"' do
+    fill_in 'issue_search', with: ".3"
   end
 
   And 'I fill in issue search with "Something"' do
@@ -120,6 +124,14 @@ class ProjectIssues < Spinach::FeatureSteps
            author: project.users.first)
   end
 
+  And 'project "Shop" have "Tweet control" open issue' do
+    project = Project.find_by_name("Shop")
+    create(:issue,
+           title: "Tweet control",
+           project: project,
+           author: project.users.first)
+  end
+
   And 'project "Shop" have "Release 0.3" closed issue' do
     project = Project.find_by_name("Shop")
     create(:closed_issue,
diff --git a/features/steps/project/project_network_graph.rb b/features/steps/project/project_network_graph.rb
index 57015f766261cbbb129d2bdfed4f9e9ed49785f5..127adecf7ed089f37ade7086cc84ec7a1d6fdc87 100644
--- a/features/steps/project/project_network_graph.rb
+++ b/features/steps/project/project_network_graph.rb
@@ -38,11 +38,6 @@ class ProjectNetworkGraph < Spinach::FeatureSteps
     sleep 2
   end
 
-  When 'I switch ref to "v2.1.0"' do
-    page.select 'v2.1.0', from: 'ref'
-    sleep 2
-  end
-
   When 'click "Show only selected branch" checkbox' do
     find('#filter_ref').click
     sleep 2
diff --git a/features/steps/project/project_services.rb b/features/steps/project/project_services.rb
index 10feb8ea8be0376c70169a5bc7d78a0ecb7f23ef..70eafc875d484483ce18b064fb7921ea31a60e0a 100644
--- a/features/steps/project/project_services.rb
+++ b/features/steps/project/project_services.rb
@@ -44,4 +44,32 @@ class ProjectServices < Spinach::FeatureSteps
     find_field('Room').value.should == 'gitlab'
   end
 
+
+  And 'I click pivotaltracker service link' do
+    click_link 'PivotalTracker'
+  end
+
+  And 'I fill pivotaltracker settings' do
+    check 'Active'
+    fill_in 'Token', with: 'verySecret'
+    click_button 'Save'
+  end
+
+  Then 'I should see pivotaltracker service settings saved' do
+    find_field('Token').value.should == 'verySecret'
+  end
+
+  And 'I click Flowdock service link' do
+    click_link 'Flowdock'
+  end
+
+  And 'I fill Flowdock settings' do
+    check 'Active'
+    fill_in 'Token', with: 'verySecret'
+    click_button 'Save'
+  end
+
+  Then 'I should see Flowdock service settings saved' do
+    find_field('Token').value.should == 'verySecret'
+  end
 end
diff --git a/features/steps/project/project_snippets.rb b/features/steps/project/project_snippets.rb
index 86c0685256a2d6fcb4660f518396a1d0e64fcfcb..5082b31198acaf249a423b0cff8e5d87204acd02 100644
--- a/features/steps/project/project_snippets.rb
+++ b/features/steps/project/project_snippets.rb
@@ -47,8 +47,8 @@ class ProjectSnippets < Spinach::FeatureSteps
     end
   end
 
-  And 'I click link "Destroy"' do
-    click_link "Destroy"
+  And 'I click link "Remove Snippet"' do
+    click_link "Remove snippet"
   end
 
   And 'I submit new snippet "Snippet three"' do
diff --git a/features/steps/public/projects_feature.rb b/features/steps/public/projects_feature.rb
index 8d612498fb9a3a5f832be0bde0601fd3297e3e50..e9a4d56e36b7f572608dbc11f445370b02644aad 100644
--- a/features/steps/public/projects_feature.rb
+++ b/features/steps/public/projects_feature.rb
@@ -9,6 +9,10 @@ class Spinach::Features::PublicProjectsFeature < Spinach::FeatureSteps
     page.should_not have_content "Enterprise"
   end
 
+  step 'I should see project "Empty Public Project"' do
+    page.should have_content "Empty Public Project"
+  end
+
   step 'I should see public project details' do
     page.should have_content '32 branches'
     page.should have_content '16 tags'
@@ -19,13 +23,35 @@ class Spinach::Features::PublicProjectsFeature < Spinach::FeatureSteps
   end
 
   step 'public project "Community"' do
-    create :project_with_code, name: 'Community', public: true
+    create :project_with_code, name: 'Community', public: true, default_branch: 'master'
+  end
+
+  step 'public empty project "Empty Public Project"' do
+    create :project, name: 'Empty Public Project', public: true
+  end
+
+  step 'I visit empty project page' do
+    project = Project.find_by_name('Empty Public Project')
+    visit project_path(project)
+  end
+
+  step 'I visit project "Community" page' do
+    project = Project.find_by_name('Community')
+    visit project_path(project)
+  end
+
+  step 'I should see empty public project details' do
+    page.should have_content 'Git global setup'
   end
 
   step 'private project "Enterprise"' do
     create :project, name: 'Enterprise'
   end
 
+  step 'I should see project "Community" home page' do
+    page.should have_content 'Repo size is'
+  end
+
   private
 
   def project
diff --git a/features/support/env.rb b/features/support/env.rb
index 0cc7d8d2fe9d35a29b8cb6019f0872ecd1e37192..8798e62ea725fd8d4135c6f965cc96fad7b30fa4 100644
--- a/features/support/env.rb
+++ b/features/support/env.rb
@@ -14,7 +14,7 @@ require 'spinach/capybara'
 require 'sidekiq/testing/inline'
 
 
-%w(valid_commit select2_helper chosen_helper test_env).each do |f|
+%w(valid_commit big_commits select2_helper chosen_helper test_env).each do |f|
   require Rails.root.join('spec', 'support', f)
 end
 
@@ -26,10 +26,13 @@ WebMock.allow_net_connect!
 #
 require 'capybara/poltergeist'
 Capybara.javascript_driver = :poltergeist
+Capybara.register_driver :poltergeist do |app|
+    Capybara::Poltergeist::Driver.new(app, :js_errors => false, :timeout => 60)
+end
 Spinach.hooks.on_tag("javascript") do
   ::Capybara.current_driver = ::Capybara.javascript_driver
 end
-Capybara.default_wait_time = 10
+Capybara.default_wait_time = 60
 Capybara.ignore_hidden_elements = false
 
 DatabaseCleaner.strategy = :truncation
diff --git a/lib/api/deploy_keys.rb b/lib/api/deploy_keys.rb
index 55c947eb176a31c4dde5486f4ad3c8fa50bc5da7..218b3d8eee2e7c4c90a1e27d7f73088e0daaea7a 100644
--- a/lib/api/deploy_keys.rb
+++ b/lib/api/deploy_keys.rb
@@ -2,6 +2,7 @@ module API
   # Projects API
   class DeployKeys < Grape::API
     before { authenticate! }
+    before { authorize_admin_project }
 
     resource :projects do
       helpers do
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index f15ca35e9546fe4992da2fd45d1c983c994e5129..b4771eecc7f713f4a7ca2a422271655073e96dc5 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -3,6 +3,9 @@ module API
     class User < Grape::Entity
       expose :id, :username, :email, :name, :bio, :skype, :linkedin, :twitter,
              :theme_id, :color_scheme_id, :state, :created_at, :extern_uid, :provider
+      expose :is_admin?, as: :is_admin
+      expose :can_create_group?, as: :can_create_group
+      expose :can_create_project?, as: :can_create_project
     end
 
     class UserSafe < Grape::Entity
@@ -15,10 +18,6 @@ module API
 
     class UserLogin < User
       expose :private_token
-      expose :is_admin?, as: :is_admin
-      expose :can_create_group?, as: :can_create_group
-      expose :can_create_project?, as: :can_create_project
-      expose :can_create_team?, as: :can_create_team
     end
 
     class Hook < Grape::Entity
@@ -67,6 +66,12 @@ module API
       expose :projects, using: Entities::Project
     end
 
+    class GroupMember < UserBasic
+      expose :group_access, as: :access_level do |user, options|
+        options[:group].users_groups.find_by_user_id(user.id).group_access
+      end
+    end
+
     class RepoObject < Grape::Entity
       expose :name, :commit
       expose :protected do |repo, options|
@@ -107,7 +112,7 @@ module API
     end
 
     class MergeRequest < Grape::Entity
-      expose :id, :target_branch, :source_branch, :title, :state
+      expose :id, :target_branch, :source_branch, :title, :state, :upvotes, :downvotes
       expose :target_project_id, as: :project_id
       expose :author, :assignee, using: Entities::UserBasic
     end
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index 701f6777b77d6f0a06a088bf47be01105ce356f2..265417fd6bcd0dfc4762fda27d7821c89d0d10bb 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -4,6 +4,22 @@ module API
     before { authenticate! }
 
     resource :groups do
+      helpers do
+        def find_group(id)
+          group = Group.find(id)
+
+          if can?(current_user, :read_group, group)
+            group
+          else
+            render_api_error!("403 Forbidden - #{current_user.username} lacks sufficient access to #{group.name}", 403)
+          end
+        end
+
+        def validate_access_level?(level)
+          Gitlab::Access.options_with_owner.values.include? level.to_i
+        end
+      end
+
       # Get a groups list
       #
       # Example Request:
@@ -46,12 +62,21 @@ module API
       # Example Request:
       #   GET /groups/:id
       get ":id" do
-        @group = Group.find(params[:id])
-        if current_user.admin or current_user.groups.include? @group
-          present @group, with: Entities::GroupDetail
-        else
-          not_found!
-        end
+        group = find_group(params[:id])
+        present group, with: Entities::GroupDetail
+      end
+
+
+      # Remove group
+      #
+      # Parameters:
+      #   id (required) - The ID of a group
+      # Example Request:
+      #   DELETE /groups/:id
+      delete ":id" do
+        group = find_group(params[:id])
+        authorize! :manage_group, group
+        group.destroy
       end
 
       # Transfer a project to the Group namespace
@@ -71,6 +96,57 @@ module API
           not_found!
         end
       end
+
+      # Get a list of group members viewable by the authenticated user.
+      #
+      # Example Request:
+      #  GET /groups/:id/members
+      get ":id/members" do
+        group = find_group(params[:id])
+        members = group.users_groups
+        users = (paginate members).collect(&:user)
+        present users, with: Entities::GroupMember, group: group
+      end
+
+      # Add a user to the list of group members
+      #
+      # Parameters:
+      #   id (required) - group id
+      #   user_id (required) - the users id
+      #   access_level (required) - Project access level
+      # Example Request:
+      #  POST /groups/:id/members
+      post ":id/members" do
+        required_attributes! [:user_id, :access_level]
+        unless validate_access_level?(params[:access_level])
+          render_api_error!("Wrong access level", 422)
+        end
+        group = find_group(params[:id])
+        if group.users_groups.find_by_user_id(params[:user_id])
+          render_api_error!("Already exists", 409)
+        end
+        group.add_users([params[:user_id]], params[:access_level])
+        member = group.users_groups.find_by_user_id(params[:user_id])
+        present member.user, with: Entities::GroupMember, group: group
+      end
+
+      # Remove member.
+      #
+      # Parameters:
+      #   id (required) - group id
+      #   user_id (required) - the users id
+      #
+      # Example Request:
+      #   DELETE /groups/:id/members/:user_id
+      delete ":id/members/:user_id" do
+        group = find_group(params[:id])
+        member =  group.users_groups.find_by_user_id(params[:user_id])
+        if member.nil?
+          render_api_error!("404 Not Found - user_id:#{params[:user_id]} not a member of group #{group.name}",404)
+        else
+          member.destroy
+        end
+      end
     end
   end
 end
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index f857d4133b21fde3f1392a2d9282c844b2c13a2a..2b0c672c7fa8a0b23e26a8f0a2709fce68a13cc2 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -1,7 +1,34 @@
 module API
   module APIHelpers
+    PRIVATE_TOKEN_HEADER = "HTTP_PRIVATE_TOKEN"
+    PRIVATE_TOKEN_PARAM = :private_token
+    SUDO_HEADER ="HTTP_SUDO"
+    SUDO_PARAM = :sudo
+
     def current_user
-      @current_user ||= User.find_by_authentication_token(params[:private_token] || env["HTTP_PRIVATE_TOKEN"])
+      @current_user ||= User.find_by_authentication_token(params[PRIVATE_TOKEN_PARAM] || env[PRIVATE_TOKEN_HEADER])
+      identifier = sudo_identifier()
+      # If the sudo is the current user do nothing
+      if (identifier && !(@current_user.id == identifier || @current_user.username == identifier))
+        render_api_error!('403 Forbidden: Must be admin to use sudo', 403) unless @current_user.is_admin?
+        begin
+          @current_user = User.by_username_or_id(identifier)
+        rescue => ex
+          not_found!("No user id or username for: #{identifier}")
+        end
+        not_found!("No user id or username for: #{identifier}") if current_user.nil?
+      end
+      @current_user
+    end
+
+    def sudo_identifier()
+      identifier ||= params[SUDO_PARAM] ||= env[SUDO_HEADER]
+      # Regex for integers
+      if (!!(identifier =~ /^[0-9]+$/))
+        identifier.to_i
+      else
+        identifier
+      end
     end
 
     def user_project
@@ -37,6 +64,10 @@ module API
       end
     end
 
+    def authorize_admin_project
+      authorize! :admin_project, user_project
+    end
+
     def can?(object, action, subject)
       abilities.allowed?(object, action, subject)
     end
@@ -55,7 +86,7 @@ module API
     def attributes_for_keys(keys)
       attrs = {}
       keys.each do |key|
-        attrs[key] = params[key] if params[key].present?
+        attrs[key] = params[key] if params[key].present? or (params.has_key?(key) and params[key] == false)
       end
       attrs
     end
diff --git a/lib/api/internal.rb b/lib/api/internal.rb
index 79f8eb3a543adfe20766738e4a110969ad262491..ed6b50c3a6a4986204fd2baf6ca89052b8419830 100644
--- a/lib/api/internal.rb
+++ b/lib/api/internal.rb
@@ -35,6 +35,7 @@ module API
           user = key.user
 
           return false if user.blocked?
+          return false if user.ldap_user? && Gitlab::LDAP::User.blocked?(user.extern_uid)
 
           action = case git_cmd
                    when *DOWNLOAD_COMMANDS
diff --git a/lib/api/project_hooks.rb b/lib/api/project_hooks.rb
index 2850125679554471c5347bc3c519198122d8cfdc..738974955f3dc6c6dad4025c16c5c889f85af273 100644
--- a/lib/api/project_hooks.rb
+++ b/lib/api/project_hooks.rb
@@ -2,6 +2,7 @@ module API
   # Projects API
   class ProjectHooks < Grape::API
     before { authenticate! }
+    before { authorize_admin_project }
 
     resource :projects do
       helpers do
@@ -20,7 +21,6 @@ module API
       # 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
@@ -33,7 +33,6 @@ module API
       # Example Request:
       #   GET /projects/:id/hooks/:hook_id
       get ":id/hooks/:hook_id" do
-        authorize! :admin_project, user_project
         @hook = user_project.hooks.find(params[:hook_id])
         present @hook, with: Entities::Hook
       end
@@ -47,7 +46,6 @@ module API
       # Example Request:
       #   POST /projects/:id/hooks
       post ":id/hooks" do
-        authorize! :admin_project, user_project
         required_attributes! [:url]
 
         @hook = user_project.hooks.new({"url" => params[:url]})
@@ -71,7 +69,6 @@ module API
       #   PUT /projects/:id/hooks/:hook_id
       put ":id/hooks/:hook_id" do
         @hook = user_project.hooks.find(params[:hook_id])
-        authorize! :admin_project, user_project
         required_attributes! [:url]
 
         attrs = attributes_for_keys [:url]
@@ -93,7 +90,6 @@ module API
       # Example Request:
       #   DELETE /projects/:id/hooks/:hook_id
       delete ":id/hooks/:hook_id" do
-        authorize! :admin_project, user_project
         required_attributes! [:hook_id]
 
         begin
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index c6ff524cb0603b318fc64a24b0826d91ea2a68fb..cf357b23c406fbbd6074162794d559fe069a79f4 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -73,16 +73,16 @@ module API
       post do
         required_attributes! [:name]
         attrs = attributes_for_keys [:name,
-                                    :path,
-                                    :description,
-                                    :default_branch,
-                                    :issues_enabled,
-                                    :wall_enabled,
-                                    :merge_requests_enabled,
-                                    :wiki_enabled,
-                                    :snippets_enabled,
-                                    :namespace_id,
-                                    :public]
+                                     :path,
+                                     :description,
+                                     :default_branch,
+                                     :issues_enabled,
+                                     :wall_enabled,
+                                     :merge_requests_enabled,
+                                     :wiki_enabled,
+                                     :snippets_enabled,
+                                     :namespace_id,
+                                     :public]
         @project = ::Projects::CreateContext.new(current_user, attrs).execute
         if @project.saved?
           present @project, with: Entities::Project
@@ -113,14 +113,14 @@ module API
         authenticated_as_admin!
         user = User.find(params[:user_id])
         attrs = attributes_for_keys [:name,
-                                    :description,
-                                    :default_branch,
-                                    :issues_enabled,
-                                    :wall_enabled,
-                                    :merge_requests_enabled,
-                                    :wiki_enabled,
-                                    :snippets_enabled,
-                                    :public]
+                                     :description,
+                                     :default_branch,
+                                     :issues_enabled,
+                                     :wall_enabled,
+                                     :merge_requests_enabled,
+                                     :wiki_enabled,
+                                     :snippets_enabled,
+                                     :public]
         @project = ::Projects::CreateContext.new(user, attrs).execute
         if @project.saved?
           present @project, with: Entities::Project
@@ -165,7 +165,6 @@ module API
         end
       end
 
-
       # Get a project team members
       #
       # Parameters:
@@ -262,6 +261,20 @@ module API
           {message: "Access revoked", id: params[:user_id].to_i}
         end
       end
+
+      # search for projects current_user has access to
+      #
+      # Parameters:
+      #   query (required) - A string contained in the project name
+      #   per_page (optional) - number of projects to return per page
+      #   page (optional) - the page to retrieve
+      # Example Request:
+      #   GET /projects/search/:query
+      get "/search/:query" do
+        ids = current_user.authorized_projects.map(&:id)
+        projects = Project.where("(id in (?) OR public = true) AND (name LIKE (?))", ids, "%#{params[:query]}%")
+        present paginate(projects), with: Entities::Project
+      end
     end
   end
 end
diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb
index fef32d3a2fe5893971c24fc3b927858a1b466383..1a911eae2bb13c8cbcb082d216498cadb6337f8e 100644
--- a/lib/api/repositories.rb
+++ b/lib/api/repositories.rb
@@ -2,6 +2,7 @@ module API
   # Projects API
   class Repositories < Grape::API
     before { authenticate! }
+    before { authorize! :download_code, user_project }
 
     resource :projects do
       helpers do
@@ -44,13 +45,12 @@ module API
       # Example Request:
       #   PUT /projects/:id/repository/branches/:branch/protect
       put ":id/repository/branches/:branch/protect" do
-        @branch = user_project.repo.heads.find { |item| item.name == params[:branch] }
-        not_found! unless @branch
-        protected = user_project.protected_branches.find_by_name(@branch.name)
+        authorize_admin_project
 
-        unless protected
-          user_project.protected_branches.create(name: @branch.name)
-        end
+        @branch = user_project.repository.find_branch(params[:branch])
+        not_found! unless @branch
+        protected_branch = user_project.protected_branches.find_by_name(@branch.name)
+        user_project.protected_branches.create(name: @branch.name) unless protected_branch
 
         present @branch, with: Entities::RepoObject, project: user_project
       end
@@ -63,13 +63,12 @@ module API
       # Example Request:
       #   PUT /projects/:id/repository/branches/:branch/unprotect
       put ":id/repository/branches/:branch/unprotect" do
-        @branch = user_project.repo.heads.find { |item| item.name == params[:branch] }
-        not_found! unless @branch
-        protected = user_project.protected_branches.find_by_name(@branch.name)
+        authorize_admin_project
 
-        if protected
-          protected.destroy
-        end
+        @branch = user_project.repository.find_branch(params[:branch])
+        not_found! unless @branch
+        protected_branch = user_project.protected_branches.find_by_name(@branch.name)
+        protected_branch.destroy if protected_branch
 
         present @branch, with: Entities::RepoObject, project: user_project
       end
@@ -92,8 +91,6 @@ module API
       # Example Request:
       #   GET /projects/:id/repository/commits
       get ":id/repository/commits" do
-        authorize! :download_code, user_project
-
         page = (params[:page] || 0).to_i
         per_page = (params[:per_page] || 20).to_i
         ref = params[:ref_name] || user_project.try(:default_branch) || 'master'
@@ -110,7 +107,6 @@ module API
       # Example Request:
       #   GET /projects/:id/repository/commits/:sha
       get ":id/repository/commits/:sha" do
-        authorize! :download_code, user_project
         sha = params[:sha]
         commit = user_project.repository.commit(sha)
         not_found! "Commit" unless commit
@@ -125,7 +121,6 @@ module API
       # Example Request:
       #   GET /projects/:id/repository/commits/:sha/diff
       get ":id/repository/commits/:sha/diff" do
-        authorize! :download_code, user_project
         sha = params[:sha]
         result = CommitLoadContext.new(user_project, current_user, {id: sha}).execute
         not_found! "Commit" unless result[:commit]
@@ -140,13 +135,11 @@ module API
       # Example Request:
       #   GET /projects/:id/repository/tree
       get ":id/repository/tree" do
-        authorize! :download_code, user_project
-
         ref = params[:ref_name] || user_project.try(:default_branch) || 'master'
         path = params[:path] || nil
 
         commit = user_project.repository.commit(ref)
-        tree = Tree.new(user_project.repository, commit.id, ref, path)
+        tree = Tree.new(user_project.repository, commit.id, path)
 
         trees = []
 
@@ -166,7 +159,6 @@ module API
       # Example Request:
       #   GET /projects/:id/repository/blobs/:sha
       get [ ":id/repository/blobs/:sha", ":id/repository/commits/:sha/blob" ] do
-        authorize! :download_code, user_project
         required_attributes! [:filepath]
 
         ref = params[:sha]
@@ -176,8 +168,8 @@ module API
         commit = repo.commit(ref)
         not_found! "Commit" unless commit
 
-        blob = Gitlab::Git::Blob.new(repo, commit.id, ref, params[:filepath])
-        not_found! "File" unless blob.exists?
+        blob = Gitlab::Git::Blob.find(repo, commit.id, params[:filepath])
+        not_found! "File" unless blob
 
         env['api.format'] = :txt
 
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 84256b51124ea8c58ed2f810dff47dd8476a28d2..54d3aeecb7041d6afe4ba1b05c386d813d08b148 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -40,14 +40,17 @@ module API
       #   extern_uid                        - External authentication provider UID
       #   provider                          - External provider
       #   bio                               - Bio
+      #   admin                             - User is admin - true or false (default)
+      #   can_create_group                  - User can create groups - true or false
       # Example Request:
       #   POST /users
       post do
         authenticated_as_admin!
         required_attributes! [:email, :password, :name, :username]
-
-        attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio]
-        user = User.new attrs, as: :admin
+        attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio, :can_create_group, :admin]
+        user = User.build_user(attrs, as: :admin)
+        admin = attrs.delete(:admin)
+        user.admin = admin unless admin.nil?
         if user.save
           present user, with: Entities::User
         else
@@ -68,16 +71,20 @@ module API
       #   extern_uid                        - External authentication provider UID
       #   provider                          - External provider
       #   bio                               - Bio
+      #   admin                             - User is admin - true or false (default)
+      #   can_create_group                  - User can create groups - true or false
       # Example Request:
       #   PUT /users/:id
       put ":id" do
         authenticated_as_admin!
 
-        attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio]
+        attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio, :can_create_group, :admin]
         user = User.find(params[:id])
         not_found!("User not found") unless user
 
-        if user.update_attributes(attrs)
+        admin = attrs.delete(:admin)
+        user.admin = admin unless admin.nil?
+        if user.update_attributes(attrs, as: :admin)
           present user, with: Entities::User
         else
           not_found!
diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb
index 53bc079296aedb6faed3732742053601ac730795..6e7872dcd033655dfe70ab1cb0f9a309f8ca3d3e 100644
--- a/lib/extracts_path.rb
+++ b/lib/extracts_path.rb
@@ -86,7 +86,6 @@ module ExtractsPath
   # - @ref    - A string representing the ref (e.g., the branch, tag, or commit SHA)
   # - @path   - A string representing the filesystem path
   # - @commit - A Commit representing the commit from the given ref
-  # - @tree   - A Tree representing the tree at the given ref/path
   #
   # If the :id parameter appears to be requesting a specific response format,
   # that will be handled as well.
@@ -107,15 +106,20 @@ module ExtractsPath
     else
       @commit = @repo.commit(@options[:extended_sha1])
     end
-    @tree = Tree.new(@repo, @commit.id, @ref, @path)
+
+    raise InvalidPathError unless @commit
+
     @hex_path = Digest::SHA1.hexdigest(@path)
     @logs_path = logs_file_project_ref_path(@project, @ref, @path)
 
-    raise InvalidPathError unless @tree.exists?
   rescue RuntimeError, NoMethodError, InvalidPathError
     not_found!
   end
 
+  def tree
+    @tree ||= Tree.new(@repo, @commit.id, @path)
+  end
+
   private
 
   def get_id
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index de70c5ce780f6c01205d0ffd2990c89b363db3c3..0f1962974771e494e42c754dbc7ef762dfd478b0 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -7,97 +7,16 @@ module Gitlab
         # Second chance - try LDAP authentication
         return nil unless ldap_conf.enabled
 
-        ldap_auth(login, password)
+        Gitlab::LDAP::User.authenticate(login, password)
       else
         user if user.valid_password?(password)
       end
     end
 
-    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
-      uid = uid.to_s.force_encoding("utf-8")
-      name = auth.info.name.to_s.force_encoding("utf-8")
-      email = auth.info.email.to_s.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,
-        username: email.match(/^[^@]*/)[0],
-        email: email,
-        password: password,
-        password_confirmation: password,
-      }, as: :admin).with_defaults
-      @user.save!
-
-      if Gitlab.config.omniauth['block_auto_created_users'] && !ldap
-        @user.block
-      end
-
-      @user
-    end
-
-    def find_or_new_for_omniauth(auth)
-      provider, uid = auth.provider, auth.uid
-      email = auth.info.email.downcase unless auth.info.email.nil?
-
-      if @user = User.find_by_provider_and_extern_uid(provider, uid)
-        @user
-      elsif @user = User.find_by_email(email)
-        @user.update_attributes(extern_uid: uid, provider: provider)
-        @user
-      else
-        if Gitlab.config.omniauth['allow_single_sign_on']
-          @user = create_from_omniauth(auth)
-          @user
-        end
-      end
-    end
-
     def log
       Gitlab::AppLogger
     end
 
-    def ldap_auth(login, password)
-      # Check user against LDAP backend if user is not authenticated
-      # Only check with valid login and password to prevent anonymous bind results
-      return nil unless ldap_conf.enabled && !login.blank? && !password.blank?
-
-      ldap = OmniAuth::LDAP::Adaptor.new(ldap_conf)
-      ldap_user = ldap.bind_as(
-        filter: Net::LDAP::Filter.eq(ldap.uid, login),
-        size: 1,
-        password: password
-      )
-
-      User.find_by_extern_uid_and_provider(ldap_user.dn, 'ldap') if ldap_user
-    end
-
     def ldap_conf
       @ldap_conf ||= Gitlab.config.ldap
     end
diff --git a/lib/gitlab/backend/grack_auth.rb b/lib/gitlab/backend/grack_auth.rb
index be5c58bb5a680d1560984eb53622e7ff8538abaa..c522e0a413b69252014fbcda90811a799bcdf76b 100644
--- a/lib/gitlab/backend/grack_auth.rb
+++ b/lib/gitlab/backend/grack_auth.rb
@@ -1,10 +1,8 @@
 require_relative 'shell_env'
-require_relative 'grack_ldap'
 require_relative 'grack_helpers'
 
 module Grack
   class Auth < Rack::Auth::Basic
-    include LDAP
     include Helpers
 
     attr_accessor :user, :project, :ref, :env
diff --git a/lib/gitlab/backend/grack_ldap.rb b/lib/gitlab/backend/grack_ldap.rb
deleted file mode 100644
index 45e98fbac1ef67a043f1b4ce583f3a18d056aad4..0000000000000000000000000000000000000000
--- a/lib/gitlab/backend/grack_ldap.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-require 'omniauth-ldap'
-
-module Grack
-  module LDAP
-    def ldap_auth(login, password)
-      # Check user against LDAP backend if user is not authenticated
-      # Only check with valid login and password to prevent anonymous bind results
-      return nil unless ldap_conf.enabled && !login.blank? && !password.blank?
-
-      ldap = OmniAuth::LDAP::Adaptor.new(ldap_conf)
-      ldap_user = ldap.bind_as(
-        filter: Net::LDAP::Filter.eq(ldap.uid, login),
-        size: 1,
-        password: password
-      )
-
-      User.find_by_extern_uid_and_provider(ldap_user.dn, 'ldap') if ldap_user
-    end
-
-    def ldap_conf
-      @ldap_conf ||= Gitlab.config.ldap
-    end
-  end
-end
diff --git a/lib/gitlab/blacklist.rb b/lib/gitlab/blacklist.rb
index 26f987b200c67a35a930ab238403b571ad2cc62f..2f9091e07df23308f9ae89c7db581779d4544e17 100644
--- a/lib/gitlab/blacklist.rb
+++ b/lib/gitlab/blacklist.rb
@@ -3,7 +3,7 @@ module Gitlab
     extend self
 
     def path
-      %w(admin dashboard groups help profile projects search public assets u s teams merge_requests issues users snippets services repository hooks)
+      %w(admin dashboard groups help profile projects search public assets u s teams merge_requests issues users snippets services repository hooks notes)
     end
   end
 end
diff --git a/lib/gitlab/inline_diff.rb b/lib/gitlab/inline_diff.rb
index 44cf49b40473a359a2c7c41fbf95705996ad8d91..89c8e0680c30b1c70353290a323a30911e45c694 100644
--- a/lib/gitlab/inline_diff.rb
+++ b/lib/gitlab/inline_diff.rb
@@ -13,6 +13,9 @@ module Gitlab
           second_line = diff_arr[index+2]
           max_length = [first_line.size, second_line.size].max
 
+          # Skip inline diff if empty line was replaced with content
+          next if first_line == "-\n"
+
           first_the_same_symbols = 0
           (0..max_length + 1).each do |i|
             first_the_same_symbols = i - 1
@@ -20,10 +23,19 @@ module Gitlab
               break
             end
           end
+
           first_token = first_line[0..first_the_same_symbols][1..-1]
           start = first_token + START
-          diff_arr[index+1].sub!(first_token, first_token => start)
-          diff_arr[index+2].sub!(first_token, first_token => start)
+
+          if first_token.empty?
+            # In case if we remove string of spaces in commit
+            diff_arr[index+1].sub!("-", "-" => "-#{START}")
+            diff_arr[index+2].sub!("+", "+" => "+#{START}")
+          else
+            diff_arr[index+1].sub!(first_token, first_token => start)
+            diff_arr[index+2].sub!(first_token, first_token => start)
+          end
+
           last_the_same_symbols = 0
           (1..max_length + 1).each do |i|
             last_the_same_symbols = -i
diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb
new file mode 100644
index 0000000000000000000000000000000000000000..78fc5dab9cbe439caa4f2e8de1ad7e691963ea3f
--- /dev/null
+++ b/lib/gitlab/ldap/user.rb
@@ -0,0 +1,104 @@
+require 'gitlab/oauth/user'
+
+# LDAP extension for User model
+#
+# * Find or create user from omniauth.auth data
+# * Links LDAP account with existing user
+# * Auth LDAP user with login and password
+#
+module Gitlab
+  module LDAP
+    class User < Gitlab::OAuth::User
+      class << self
+        def find_or_create(auth)
+          @auth = auth
+
+          if uid.blank? || email.blank?
+            raise_error("Account must provide an uid and email address")
+          end
+
+          user = find(auth)
+
+          unless user
+            # Look for user with same emails
+            #
+            # Possible cases:
+            # * When user already has account and need to link his LDAP account.
+            # * LDAP uid changed for user with same email and we need to update his uid
+            #
+            user = find_user(email)
+
+            if user
+              user.update_attributes(extern_uid: uid, provider: provider)
+              log.info("(LDAP) Updating legacy LDAP user #{email} with extern_uid => #{uid}")
+            else
+              # Create a new user inside GitLab database
+              # based on LDAP credentials
+              #
+              #
+              user = create(auth)
+            end
+          end
+
+          user
+        end
+
+        def find_user(email)
+          user = model.find_by_email(email)
+
+          # If no user found and allow_username_or_email_login is true
+          # we look for user by extracting part of his email
+          if !user && email && ldap_conf['allow_username_or_email_login']
+            uname = email.partition('@').first
+            user = model.find_by_username(uname)
+          end
+
+          user
+        end
+
+        def authenticate(login, password)
+          # Check user against LDAP backend if user is not authenticated
+          # Only check with valid login and password to prevent anonymous bind results
+          return nil unless ldap_conf.enabled && login.present? && password.present?
+
+          ldap = OmniAuth::LDAP::Adaptor.new(ldap_conf)
+          ldap_user = ldap.bind_as(
+            filter: Net::LDAP::Filter.eq(ldap.uid, login),
+            size: 1,
+            password: password
+          )
+
+          find_by_uid(ldap_user.dn) if ldap_user
+        end
+
+        # Check LDAP user existance by dn. User in git over ssh check
+        #
+        # It covers 2 cases:
+        # * when ldap account was removed
+        # * when ldap account was deactivated by change of OU membership in 'dn'
+        def blocked?(dn)
+          ldap = OmniAuth::LDAP::Adaptor.new(ldap_conf)
+          ldap.connection.search(base: dn, size: 1).blank?
+        end
+
+        private
+
+        def find_by_uid(uid)
+          model.where(provider: provider, extern_uid: uid).last
+        end
+
+        def provider
+          'ldap'
+        end
+
+        def raise_error(message)
+          raise OmniAuth::Error, "(LDAP) " + message
+        end
+
+        def ldap_conf
+          Gitlab.config.ldap
+        end
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/oauth/user.rb b/lib/gitlab/oauth/user.rb
new file mode 100644
index 0000000000000000000000000000000000000000..1b32b99f4ba44b24228aafa83188b1be48a46201
--- /dev/null
+++ b/lib/gitlab/oauth/user.rb
@@ -0,0 +1,85 @@
+# OAuth extension for User model
+#
+# * Find GitLab user based on omniauth uid and provider
+# * Create new user from omniauth data
+#
+module Gitlab
+  module OAuth
+    class User
+      class << self
+        attr_reader :auth
+
+        def find(auth)
+          @auth = auth
+          find_by_uid_and_provider
+        end
+
+        def create(auth)
+          @auth = auth
+          password = Devise.friendly_token[0, 8].downcase
+          opts = {
+            extern_uid: uid,
+            provider: provider,
+            name: name,
+            username: username,
+            email: email,
+            password: password,
+            password_confirmation: password,
+          }
+
+          user = model.build_user(opts, as: :admin)
+          user.save!
+          log.info "(OAuth) Creating user #{email} from login with extern_uid => #{uid}"
+
+          if Gitlab.config.omniauth['block_auto_created_users'] && !ldap?
+            user.block
+          end
+
+          user
+        end
+
+        private
+
+        def find_by_uid_and_provider
+          model.where(provider: provider, extern_uid: uid).last
+        end
+
+        def uid
+          auth.info.uid || auth.uid
+        end
+
+        def email
+          auth.info.email.downcase unless auth.info.email.nil?
+        end
+
+        def name
+          auth.info.name.to_s.force_encoding("utf-8")
+        end
+
+        def username
+          email.match(/^[^@]*/)[0]
+        end
+
+        def provider
+          auth.provider
+        end
+
+        def log
+          Gitlab::AppLogger
+        end
+
+        def model
+          ::User
+        end
+
+        def raise_error(message)
+          raise OmniAuth::Error, "(OAuth) " + message
+        end
+
+        def ldap?
+          provider == 'ldap'
+        end
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/satellite/merge_action.rb b/lib/gitlab/satellite/merge_action.rb
index 156483be8dd935923c9b73efe81e58f1f6c8b482..d74d4194ff62914f25cd12bd6e6de3b179983ee0 100644
--- a/lib/gitlab/satellite/merge_action.rb
+++ b/lib/gitlab/satellite/merge_action.rb
@@ -146,10 +146,8 @@ module Gitlab
           repo.remote_fetch('source')
           repo.git.checkout(default_options({b: true}), merge_request.target_branch, "origin/#{merge_request.target_branch}")
         else
-          # We can't trust the input here being branch names, we can't always check it out because it could be a relative ref i.e. HEAD~3
-          # we could actually remove the if true, because it should never ever happen (as long as the satellite has been prepared)
           repo.git.checkout(default_options, "#{merge_request.source_branch}")
-          repo.git.checkout(default_options, "#{merge_request.target_branch}")
+          repo.git.checkout(default_options({t: true}), "origin/#{merge_request.target_branch}")
         end
       rescue Grit::Git::CommandFailed => ex
         handle_exception(ex)
diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab
old mode 100644
new mode 100755
index 6f97643f9e0a96d3401eb672ef2303fa0f51da7d..6aff7b5a8f9b3dcd5b8561dc78ebc2a98dfa1a44
--- a/lib/support/init.d/gitlab
+++ b/lib/support/init.d/gitlab
@@ -1,7 +1,8 @@
-#! /bin/bash
+#! /bin/sh
 
 # GITLAB
 # Maintainer: @randx
+# Authors: rovanion.luckey@gmail.com, @randx
 # App Version: 6.0
 
 ### BEGIN INIT INFO
@@ -14,102 +15,227 @@
 # Description:       GitLab git repository management
 ### END INIT INFO
 
+### Environment variables
+RAILS_ENV="production"
 
-APP_ROOT="/home/git/gitlab"
-APP_USER="git"
-DAEMON_OPTS="-c $APP_ROOT/config/unicorn.rb -E production"
-PID_PATH="$APP_ROOT/tmp/pids"
-SOCKET_PATH="$APP_ROOT/tmp/sockets"
-WEB_SERVER_PID="$PID_PATH/unicorn.pid"
-SIDEKIQ_PID="$PID_PATH/sidekiq.pid"
-STOP_SIDEKIQ="RAILS_ENV=production bundle exec rake sidekiq:stop"
-START_SIDEKIQ="RAILS_ENV=production bundle exec rake sidekiq:start"
-NAME="gitlab"
-DESC="GitLab service"
-
-check_pid(){
-  if [ -f $WEB_SERVER_PID ]; then
-    PID=`cat $WEB_SERVER_PID`
-    SPID=`cat $SIDEKIQ_PID`
-    STATUS=`ps aux | grep $PID | grep -v grep | wc -l`
+# Script variable names should be lower-case not to conflict with internal
+# /bin/sh variables such as PATH, EDITOR or SHELL.
+app_root="/home/git/gitlab"
+app_user="git"
+unicorn_conf="$app_root/config/unicorn.rb"
+pid_path="$app_root/tmp/pids"
+socket_path="$app_root/tmp/sockets"
+web_server_pid_path="$pid_path/unicorn.pid"
+sidekiq_pid_path="$pid_path/sidekiq.pid"
+
+
+
+### Here ends user configuration ###
+
+
+# Switch to the app_user if it is not he/she who is running the script.
+if [ "$USER" != "$app_user" ]; then
+  sudo -u "$app_user" -H -i $0 "$@"; exit;
+fi
+
+# Switch to the gitlab path, if it fails exit with an error.
+if ! cd "$app_root" ; then
+ echo "Failed to cd into $app_root, exiting!";  exit 1
+fi
+
+### Init Script functions
+
+check_pids(){
+  if ! mkdir -p "$pid_path"; then
+    echo "Could not create the path $pid_path needed to store the pids."
+    exit 1
+  fi
+  # If there exists a file which should hold the value of the Unicorn pid: read it.
+  if [ -f "$web_server_pid_path" ]; then
+    wpid=$(cat "$web_server_pid_path")
   else
-    STATUS=0
-    PID=0
+    wpid=0
+  fi
+  if [ -f "$sidekiq_pid_path" ]; then
+    spid=$(cat "$sidekiq_pid_path")
+  else
+    spid=0
   fi
 }
 
-execute() {
-  sudo -u $APP_USER -H bash -l -c "$1"
-}
+# We use the pids in so many parts of the script it makes sense to always check them.
+# Only after start() is run should the pids change. Sidekiq sets it's own pid.
+check_pids
 
-start() {
-  cd $APP_ROOT
-  check_pid
-  if [ "$PID" -ne 0 -a "$STATUS" -ne 0 ]; then
-    # Program is running, exit with error code 1.
-    echo "Error! $DESC $NAME is currently running!"
-    exit 1
+
+# Checks whether the different parts of the service are already running or not.
+check_status(){
+  check_pids
+  # If the web server is running kill -0 $wpid returns true, or rather 0.
+  # Checks of *_status should only check for == 0 or != 0, never anything else.
+  if [ $wpid -ne 0 ]; then
+    kill -0 "$wpid" 2>/dev/null
+    web_status="$?"
   else
-    if [ `whoami` = root ]; then
-      execute "rm -f $SOCKET_PATH/gitlab.socket"
-      execute "RAILS_ENV=production bundle exec unicorn_rails $DAEMON_OPTS  > /dev/null  2>&1 &"
-      execute "mkdir -p $PID_PATH && $START_SIDEKIQ  > /dev/null  2>&1 &"
-      echo "$DESC started"
+    web_status="-1"
+  fi
+  if [ $spid -ne 0 ]; then
+    kill -0 "$spid" 2>/dev/null
+    sidekiq_status="$?"
+  else
+    sidekiq_status="-1"
+  fi
+}
+
+# Check for stale pids and remove them if necessary
+check_stale_pids(){
+  check_status
+  # If there is a pid it is something else than 0, the service is running if
+  # *_status is == 0.
+  if [ "$wpid" != "0" -a "$web_status" != "0" ]; then
+    echo "Removing stale Unicorn web server pid. This is most likely caused by the web server crashing the last time it ran."
+    if ! rm "$web_server_pid_path"; then
+      echo "Unable to remove stale pid, exiting"
+      exit 1
+    fi
+  fi
+  if [ "$spid" != "0" -a "$sidekiq_status" != "0" ]; then
+    echo "Removing stale Sidekiq web server pid. This is most likely caused by the Sidekiq crashing the last time it ran."
+    if ! rm "$sidekiq_pid_path"; then
+      echo "Unable to remove stale pid, exiting"
+      exit 1
     fi
   fi
 }
 
-stop() {
-  cd $APP_ROOT
-  check_pid
-  if [ "$PID" -ne 0 -a "$STATUS" -ne 0 ]; then
-    ## Program is running, stop it.
-    kill -QUIT `cat $WEB_SERVER_PID`
-    execute "mkdir -p $PID_PATH && $STOP_SIDEKIQ  > /dev/null  2>&1 &"
-    rm "$WEB_SERVER_PID" >> /dev/null
-    echo "$DESC stopped"
+# If no parts of the service is running, bail out.
+exit_if_not_running(){
+  check_stale_pids
+  if [ "$web_status" != "0" -a "$sidekiq_status" != "0" ]; then
+    echo "GitLab is not running."
+    exit
+  fi
+}
+
+# Starts Unicorn and Sidekiq.
+start() {
+  check_stale_pids
+
+  # Then check if the service is running. If it is: don't start again.
+  if [ "$web_status" = "0" ]; then
+    echo "The Unicorn web server already running with pid $wpid, not restarting."
   else
-    ## Program is not running, exit with error.
-    echo "Error! $DESC not started!"
-    exit 1
+    echo "Starting the GitLab Unicorn web server..."
+    # Remove old socket if it exists
+    rm -f "$socket_path"/gitlab.socket 2>/dev/null
+    # Start the webserver
+    bundle exec unicorn_rails -D -c "$unicorn_conf" -E "$RAILS_ENV"
+  fi
+
+  # If sidekiq is already running, don't start it again.
+  if [ "$sidekiq_status" = "0" ]; then
+    echo "The Sidekiq job dispatcher is already running with pid $spid, not restarting"
+  else
+    echo "Starting the GitLab Sidekiq event dispatcher..."
+    RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:start
+    # We are sleeping a bit here because sidekiq is slow at writing it's pid
+    sleep 2
   fi
+
+  # Finally check the status to tell wether or not GitLab is running
+  status
 }
 
-restart() {
-  cd $APP_ROOT
-  check_pid
-  if [ "$PID" -ne 0 -a "$STATUS" -ne 0 ]; then
-    echo "Restarting $DESC..."
-    kill -USR2 `cat $WEB_SERVER_PID`
-    execute "mkdir -p $PID_PATH && $STOP_SIDEKIQ  > /dev/null  2>&1"
-    if [ `whoami` = root ]; then
-      execute "mkdir -p $PID_PATH && $START_SIDEKIQ  > /dev/null  2>&1 &"
-    fi
-    echo "$DESC restarted."
+# Asks the Unicorn and the Sidekiq if they would be so kind as to stop, if not kills them.
+stop() {
+  exit_if_not_running
+  # If the Unicorn web server is running, tell it to stop;
+  if [ "$web_status" = "0" ]; then
+    kill -QUIT "$wpid"
+    echo "Stopping the GitLab Unicorn web server..."
+    stopping=true
   else
-    echo "Error, $NAME not running!"
-    exit 1
+    echo "The Unicorn web was not running, doing nothing."
+  fi
+  # And do the same thing for the Sidekiq.
+  if [ "$sidekiq_status" = "0" ]; then
+    printf "Stopping Sidekiq job dispatcher."
+    RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:stop
+    stopping=true
+  else
+    echo "The Sidekiq was not running, must have run out of breath."
   fi
+
+
+  # If something needs to be stopped, lets wait for it to stop. Never use SIGKILL in a script.
+  while [ "$stopping" = "true" ]; do
+    sleep 1
+    check_status
+    if [ "$web_status" = "0" -o "$sidekiq_status" = "0" ]; then
+      printf "."
+    else
+      printf "\n"
+      break
+    fi
+  done
+  sleep 1
+  # Cleaning up unused pids
+  rm "$web_server_pid_path" 2>/dev/null
+  # rm "$sidekiq_pid_path" # Sidekiq seems to be cleaning up it's own pid.
+
+  status
 }
 
+# Returns the status of GitLab and it's components
 status() {
-  cd $APP_ROOT
-  check_pid
-  if [ "$PID" -ne 0 -a "$STATUS" -ne 0 ]; then
-    echo "$DESC / Unicorn with PID $PID is running."
-    echo "$DESC / Sidekiq with PID $SPID is running."
+  check_status
+  if [ "$web_status" != "0" -a "$sidekiq_status" != "0" ]; then
+    echo "GitLab is not running."
+    return
+  fi
+  if [ "$web_status" = "0" ]; then
+      echo "The GitLab Unicorn webserver with pid $wpid is running."
   else
-    echo "$DESC is not running."
-    exit 1
+      printf "The GitLab Unicorn webserver is \033[31mnot running\033[0m.\n"
+  fi
+  if [ "$sidekiq_status" = "0" ]; then
+      echo "The GitLab Sidekiq job dispatcher with pid $spid is running."
+  else
+      printf "The GitLab Sidekiq job dispatcher is \033[31mnot running\033[0m.\n"
+  fi
+  if [ "$web_status" = "0" -a "$sidekiq_status" = "0" ]; then
+    printf "GitLab and all its components are \033[32mup and running\033[0m.\n"
   fi
 }
 
-## Check to see if we are running as root first.
-## Found at http://www.cyberciti.biz/tips/shell-root-user-check-script.html
-if [ "$(id -u)" != "0" ]; then
-    echo "This script must be run as root"
+reload(){
+  exit_if_not_running
+  if [ "$wpid" = "0" ];then
+    echo "The GitLab Unicorn Web server is not running thus its configuration can't be reloaded."
     exit 1
-fi
+  fi
+  printf "Reloading GitLab Unicorn configuration... "
+  kill -USR2 "$wpid"
+  echo "Done."
+  echo "Restarting GitLab Sidekiq since it isn't capable of reloading its config..."
+  RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:stop
+  echo "Starting Sidekiq..."
+  RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:start
+  # Waiting 2 seconds for sidekiq to write it.
+  sleep 2
+  status
+}
+
+restart(){
+  check_status
+  if [ "$web_status" = "0" -o "$sidekiq_status" = "0" ]; then
+    stop
+  fi
+  start
+}
+
+
+## Finally the input handling.
 
 case "$1" in
   start)
@@ -122,17 +248,15 @@ case "$1" in
         restart
         ;;
   reload|force-reload)
-        echo -n "Reloading $NAME configuration: "
-        kill -HUP `cat $PID`
-        echo "done."
+	reload
         ;;
   status)
         status
         ;;
   *)
-        echo "Usage: sudo service gitlab {start|stop|restart|reload}" >&2
+        echo "Usage: service gitlab {start|stop|restart|reload|status}"
         exit 1
         ;;
 esac
 
-exit 0
+exit
diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake
index 74b3e7787e663b471a2315da88eafe601492ab4a..3396c7102ebec0461ca015a3ad7fd6fbb31b9fb2 100644
--- a/lib/tasks/gitlab/check.rake
+++ b/lib/tasks/gitlab/check.rake
@@ -22,6 +22,7 @@ namespace :gitlab do
       check_tmp_writable
       check_init_script_exists
       check_init_script_up_to_date
+      check_projects_have_namespace
       check_satellites_exist
       check_redis_version
       check_git_version
@@ -288,7 +289,6 @@ namespace :gitlab do
     ########################
 
     def check_gitlab_git_config
-      gitlab_user = Gitlab.config.gitlab.user
       print "Git configured for #{gitlab_user} user? ... "
 
       options = {
@@ -391,14 +391,20 @@ namespace :gitlab do
       hook_file = "update"
       gitlab_shell_hooks_path = Gitlab.config.gitlab_shell.hooks_path
       gitlab_shell_hook_file  = File.join(gitlab_shell_hooks_path, hook_file)
-      gitlab_shell_ssh_user = Gitlab.config.gitlab_shell.ssh_user
 
-      unless File.exists?(gitlab_shell_hook_file)
-        puts "can't check because of previous errors".magenta
-        return
+      if File.exists?(gitlab_shell_hook_file)
+        puts "yes".green
+      else
+        puts "no".red
+        puts "Could not find #{gitlab_shell_hook_file}"
+        try_fixing_it(
+          'Check the hooks_path in config/gitlab.yml',
+          'Check your gitlab-shell installation'
+        )
+        for_more_information(
+          see_installation_guide_section "GitLab Shell"
+        )
       end
-
-      puts "yes".green
     end
 
     def check_repo_base_exists
@@ -479,11 +485,13 @@ namespace :gitlab do
         return
       end
 
-      if File.stat(repo_base_path).uid == uid_for(gitlab_shell_ssh_user) &&
-         File.stat(repo_base_path).gid == gid_for(gitlab_shell_owner_group)
+      uid = uid_for(gitlab_shell_ssh_user)
+      gid = gid_for(gitlab_shell_owner_group)
+      if File.stat(repo_base_path).uid == uid && File.stat(repo_base_path).gid == gid
         puts "yes".green
       else
         puts "no".red
+        puts "  User id for #{gitlab_shell_ssh_user}: #{uid}. Groupd id for #{gitlab_shell_owner_group}: #{gid}".blue
         try_fixing_it(
           "sudo chown -R #{gitlab_shell_ssh_user}:#{gitlab_shell_owner_group} #{repo_base_path}"
         )
@@ -550,6 +558,32 @@ namespace :gitlab do
       end
     end
 
+    def check_projects_have_namespace
+      print "projects have namespace: ... "
+
+      unless Project.count > 0
+        puts "can't check, you have no projects".magenta
+        return
+      end
+      puts ""
+
+      Project.find_each(batch_size: 100) do |project|
+        print "#{project.name_with_namespace.yellow} ... "
+
+        if project.namespace
+          puts "yes".green
+        else
+          puts "no".red
+          try_fixing_it(
+            "Migrate global projects"
+          )
+          for_more_information(
+            "doc/update/5.4-to-6.0.md in section \"#global-projects\""
+          )
+          fix_and_rerun
+        end
+      end
+    end
 
     # Helper methods
     ########################
@@ -579,6 +613,7 @@ namespace :gitlab do
       start_checking "Sidekiq"
 
       check_sidekiq_running
+      only_one_sidekiq_running
 
       finished_checking "Sidekiq"
     end
@@ -590,7 +625,7 @@ namespace :gitlab do
     def check_sidekiq_running
       print "Running? ... "
 
-      if run_and_match("ps aux | grep -i sidekiq", /sidekiq \d+\.\d+\.\d+.+$/)
+      if sidekiq_process_match
         puts "yes".green
       else
         puts "no".red
@@ -604,6 +639,29 @@ namespace :gitlab do
         fix_and_rerun
       end
     end
+
+    def only_one_sidekiq_running
+      sidekiq_match = sidekiq_process_match
+      return unless sidekiq_match
+
+      print 'Number of Sidekiq processes ... '
+      if sidekiq_match.length == 1
+        puts '1'.green
+      else
+        puts "#{sidekiq_match.length}".red
+        try_fixing_it(
+          'sudo service gitlab stop',
+          "sudo pkill -u #{gitlab_user} -f sidekiq",
+          "sleep 10 && sudo pkill -9 -u #{gitlab_user} -f sidekiq",
+          'sudo service gitlab start'
+        )
+        fix_and_rerun
+      end
+    end
+
+    def sidekiq_process_match
+      run_and_match("ps ux | grep -i sidekiq", /(sidekiq \d+\.\d+\.\d+.+$)/)
+    end
   end
 
 
@@ -638,10 +696,13 @@ namespace :gitlab do
   end
 
   def sudo_gitlab(command)
-    gitlab_user = Gitlab.config.gitlab.user
     "sudo -u #{gitlab_user} -H #{command}"
   end
 
+  def gitlab_user
+    Gitlab.config.gitlab.user
+  end
+
   def start_checking(component)
     puts "Checking #{component.yellow} ..."
     puts ""
@@ -657,7 +718,7 @@ namespace :gitlab do
   end
 
   def check_gitlab_shell
-    required_version = Gitlab::VersionInfo.new(1, 7, 0)
+    required_version = Gitlab::VersionInfo.new(1, 7, 1)
     current_version = Gitlab::VersionInfo.parse(gitlab_shell_version)
 
     print "GitLab Shell version >= #{required_version} ? ... "
diff --git a/lib/tasks/gitlab/import.rake b/lib/tasks/gitlab/import.rake
index 668ef1d23009b785d989d3ebc1230db557783279..8fa8927085493f919535d79c5a12791f55d40651 100644
--- a/lib/tasks/gitlab/import.rake
+++ b/lib/tasks/gitlab/import.rake
@@ -2,14 +2,14 @@ namespace :gitlab do
   namespace :import do
     # How to use:
     #
-    #  1. copy your bare repos under git base_path
+    #  1. copy your bare repos under git repos_path
     #  2. run bundle exec rake gitlab:import:repos RAILS_ENV=production
     #
     # Notes:
     #  * project owner will be a first admin
     #  * existing projects will be skipped
     #
-    desc "GITLAB | Import bare repositories from git_host -> base_path into GitLab project instance"
+    desc "GITLAB | Import bare repositories from gitlab_shell -> repos_path into GitLab project instance"
     task repos: :environment do
 
       git_base_path = Gitlab.config.gitlab_shell.repos_path
diff --git a/lib/tasks/gitlab/task_helpers.rake b/lib/tasks/gitlab/task_helpers.rake
index f84257d15b5265500c9345744bae1902bc5f8253..ac2c4577c7722cc2c21d5674eb830292145ee4a7 100644
--- a/lib/tasks/gitlab/task_helpers.rake
+++ b/lib/tasks/gitlab/task_helpers.rake
@@ -80,7 +80,11 @@ namespace :gitlab do
   end
 
   def gid_for(group_name)
-    Etc.getgrnam(group_name).gid
+    begin
+      Etc.getgrnam(group_name).gid
+    rescue ArgumentError # no group
+      "group #{group_name} doesn't exist"
+    end
   end
 
   def warn_user_is_not_gitlab
diff --git a/lib/tasks/gitlab/test.rake b/lib/tasks/gitlab/test.rake
index 03b3fc5ea20836fcb18060a21bdd19f8b3ca3503..011748c97111679e3190cd7f4b0de212f4711a2c 100644
--- a/lib/tasks/gitlab/test.rake
+++ b/lib/tasks/gitlab/test.rake
@@ -1,4 +1,18 @@
 namespace :gitlab do
-  desc "GITLAB | Run both spinach and rspec"
-  task test: ['spinach', 'spec']
+  desc "GITLAB | Run all tests"
+  task :test do
+    cmds = [
+      "rake db:setup",
+      "rake db:seed_fu",
+      "rake spinach",
+      "rake spec",
+      "rake jasmine:ci"
+    ]
+
+    cmds.each do |cmd|
+      system(cmd + " RAILS_ENV=test")
+
+      raise "#{cmd} failed!" unless $?.exitstatus.zero?
+    end
+  end
 end
diff --git a/lib/tasks/gitlab/web_hook.rake b/lib/tasks/gitlab/web_hook.rake
new file mode 100644
index 0000000000000000000000000000000000000000..f9f586db93c0c42ef56bb538bc7f78e2361754cf
--- /dev/null
+++ b/lib/tasks/gitlab/web_hook.rake
@@ -0,0 +1,65 @@
+namespace :gitlab do
+  namespace :web_hook do
+    desc "GITLAB | Adds a web hook to the projects"
+    task :add => :environment do
+      web_hook_url = ENV['URL']
+      namespace_path = ENV['NAMESPACE']
+
+      projects = find_projects(namespace_path)
+
+      puts "Adding web hook '#{web_hook_url}' to:"
+      projects.find_each(batch_size: 1000) do |project|
+        print "- #{project.name} ... "
+        web_hook = project.hooks.new(url: web_hook_url)
+        if web_hook.save
+          puts "added".green
+        else
+          print "failed".red
+          puts "  [#{web_hook.errors.full_messages.to_sentence}]"
+        end
+      end
+    end
+
+    desc "GITLAB | Remove a web hook from the projects"
+    task :rm => :environment do
+      web_hook_url = ENV['URL']
+      namespace_path = ENV['NAMESPACE']
+
+      projects = find_projects(namespace_path)
+      projects_ids = projects.pluck(:id)
+
+      puts "Removing web hooks with the url '#{web_hook_url}' ... "
+      count = WebHook.where(url: web_hook_url, project_id: projects_ids, type: 'ProjectHook').delete_all
+      puts "#{count} web hooks were removed."
+    end
+
+    desc "GITLAB | List web hooks"
+    task :list => :environment do
+      namespace_path = ENV['NAMESPACE']
+
+      projects = find_projects(namespace_path)
+      web_hooks = projects.all.map(&:hooks).flatten
+      web_hooks.each do |hook|
+        puts "#{hook.project.name.truncate(20).ljust(20)} -> #{hook.url}"
+      end
+
+      puts "\n#{web_hooks.size} web hooks found."
+    end
+  end
+
+  def find_projects(namespace_path)
+    if namespace_path.blank?
+      Project
+    elsif namespace_path == '/'
+      Project.where(namespace_id: nil)
+    else
+      namespace = Namespace.where(path: namespace_path).first
+      if namespace
+        Project.where(namespace_id: namespace.id)
+      else
+        puts "Namespace not found: #{namespace_path}".red
+        exit 2
+      end
+    end
+  end
+end
diff --git a/lib/tasks/travis.rake b/lib/tasks/travis.rake
deleted file mode 100644
index bc1b8aadbc597757962b3b6e9779841e9d7e1ab7..0000000000000000000000000000000000000000
--- a/lib/tasks/travis.rake
+++ /dev/null
@@ -1,5 +0,0 @@
-desc "Travis run tests"
-task travis: [
-  :spinach,
-  :spec
-]
diff --git a/spec/contexts/issues/bulk_update_context_spec.rb b/spec/contexts/issues/bulk_update_context_spec.rb
index 0966ee35745fe7c754e3fa835889109ce02ced1f..058e43ba0905accdbdfc24b69cc6d200ff53a53a 100644
--- a/spec/contexts/issues/bulk_update_context_spec.rb
+++ b/spec/contexts/issues/bulk_update_context_spec.rb
@@ -1,6 +1,8 @@
 require 'spec_helper'
 
 describe Issues::BulkUpdateContext do
+  before(:each) { ActiveRecord::Base.observers.enable(:user_observer) }
+  after(:each) { ActiveRecord::Base.observers.disable(:user_observer) }
 
   let(:issue) {
     create(:issue, project: @project)
@@ -9,7 +11,8 @@ describe Issues::BulkUpdateContext do
   before do
     @user = create :user
     opts = {
-      name: "GitLab"
+      name: "GitLab",
+      namespace: @user.namespace
     }
     @project = Projects::CreateContext.new(@user, opts).execute
   end
diff --git a/spec/contexts/projects_create_context_spec.rb b/spec/contexts/projects_create_context_spec.rb
index dd10dd3ede8f61e5f27bdb85098f1f09d884466d..8b2a49dbee575551a16dd33d2a962ffd67a2db40 100644
--- a/spec/contexts/projects_create_context_spec.rb
+++ b/spec/contexts/projects_create_context_spec.rb
@@ -1,11 +1,15 @@
 require 'spec_helper'
 
 describe Projects::CreateContext do
+  before(:each) { ActiveRecord::Base.observers.enable(:user_observer) }
+  after(:each) { ActiveRecord::Base.observers.disable(:user_observer) }
+
   describe :create_by_user do
     before do
       @user = create :user
       @opts = {
-        name: "GitLab"
+        name: "GitLab",
+        namespace: @user.namespace
       }
     end
 
@@ -21,15 +25,48 @@ describe Projects::CreateContext do
 
     context 'group namespace' do
       before do
-        @group = create :group, owner: @user
+        @group = create :group
+        @group.add_owner(@user)
+
         @opts.merge!(namespace_id: @group.id)
         @project = create_project(@user, @opts)
       end
 
       it { @project.should be_valid }
-      it { @project.owner.should == @user }
+      it { @project.owner.should == @group }
       it { @project.namespace.should == @group }
     end
+
+    context 'respect configured public setting' do
+      before(:each) do
+        @settings = double("settings")
+        @settings.stub(:issues) { true }
+        @settings.stub(:merge_requests) { true }
+        @settings.stub(:wiki) { true }
+        @settings.stub(:wall) { true }
+        @settings.stub(:snippets) { true }
+        stub_const("Settings", Class.new)
+        Settings.stub_chain(:gitlab, :default_projects_features).and_return(@settings)
+      end
+
+      context 'should be public when setting is public' do
+        before do
+          @settings.stub(:public) { true }
+          @project = create_project(@user, @opts)
+        end
+
+        it { @project.public.should be_true }
+      end
+
+      context 'should be private when setting is not public' do
+        before do
+          @settings.stub(:public) { false }
+          @project = create_project(@user, @opts)
+        end
+
+        it { @project.public.should be_false }
+      end
+    end
   end
 
   def create_project(user, opts)
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d528d12c66c3e88b1b2cda7d445637c638b29403
--- /dev/null
+++ b/spec/controllers/application_controller_spec.rb
@@ -0,0 +1,33 @@
+require 'spec_helper'
+
+describe ApplicationController do
+  describe '#check_password_expiration' do
+    let(:user) { create(:user) }
+    let(:controller) { ApplicationController.new }
+
+    it 'should redirect if the user is over their password expiry' do
+      user.password_expires_at = Time.new(2002)
+      user.ldap_user?.should be_false
+      controller.stub!(:current_user).and_return(user)
+      controller.should_receive(:redirect_to)
+      controller.should_receive(:new_profile_password_path)
+      controller.send(:check_password_expiration)
+    end
+
+    it 'should not redirect if the user is under their password expiry' do
+      user.password_expires_at = Time.now + 20010101
+      user.ldap_user?.should be_false
+      controller.stub!(:current_user).and_return(user)
+      controller.should_not_receive(:redirect_to)
+      controller.send(:check_password_expiration)
+    end
+
+    it 'should not redirect if the user is over their password expiry but they are an ldap user' do
+      user.password_expires_at = Time.new(2002)
+      user.stub!(:ldap_user?).and_return(true)
+      controller.stub!(:current_user).and_return(user)
+      controller.should_not_receive(:redirect_to)
+      controller.send(:check_password_expiration)
+    end
+  end
+end
\ No newline at end of file
diff --git a/spec/controllers/blob_controller_spec.rb b/spec/controllers/blob_controller_spec.rb
index 05d16f35545483fe9b16c8dbdb5a5048ca617ac6..479d8fc1a1de0faf75cb76766a9443469f92ec4e 100644
--- a/spec/controllers/blob_controller_spec.rb
+++ b/spec/controllers/blob_controller_spec.rb
@@ -17,7 +17,7 @@ describe Projects::BlobController do
   describe "GET show" do
     render_views
 
-    before { get :show, project_id: project.code, id: id }
+    before { get :show, project_id: project.to_param, id: id }
 
     context "valid branch, valid file" do
       let(:id) { 'master/README.md' }
diff --git a/spec/controllers/commit_controller_spec.rb b/spec/controllers/commit_controller_spec.rb
index 893d0fe089a68343aa3459244c167ec09be3b48d..fdf0884f4e260c3053fbc880d340c28aa1b412e6 100644
--- a/spec/controllers/commit_controller_spec.rb
+++ b/spec/controllers/commit_controller_spec.rb
@@ -13,7 +13,7 @@ describe Projects::CommitController do
   describe "#show" do
     shared_examples "export as" do |format|
       it "should generally work" do
-        get :show, project_id: project.code, id: commit.id, format: format
+        get :show, project_id: project.to_param, id: commit.id, format: format
 
         expect(response).to be_success
       end
@@ -21,11 +21,11 @@ describe Projects::CommitController do
       it "should generate it" do
         Commit.any_instance.should_receive(:"to_#{format}")
 
-        get :show, project_id: project.code, id: commit.id, format: format
+        get :show, project_id: project.to_param, id: commit.id, format: format
       end
 
       it "should render it" do
-        get :show, project_id: project.code, id: commit.id, format: format
+        get :show, project_id: project.to_param, id: commit.id, format: format
 
         expect(response.body).to eq(commit.send(:"to_#{format}"))
       end
@@ -33,7 +33,7 @@ describe Projects::CommitController do
       it "should not escape Html" do
         Commit.any_instance.stub(:"to_#{format}").and_return('HTML entities &<>" ')
 
-        get :show, project_id: project.code, id: commit.id, format: format
+        get :show, project_id: project.to_param, id: commit.id, format: format
 
         expect(response.body).to_not include('&amp;')
         expect(response.body).to_not include('&gt;')
@@ -47,7 +47,7 @@ describe Projects::CommitController do
       let(:format) { :diff }
 
       it "should really only be a git diff" do
-        get :show, project_id: project.code, id: commit.id, format: format
+        get :show, project_id: project.to_param, id: commit.id, format: format
 
         expect(response.body).to start_with("diff --git")
       end
@@ -58,13 +58,13 @@ describe Projects::CommitController do
       let(:format) { :patch }
 
       it "should really be a git email patch" do
-        get :show, project_id: project.code, id: commit.id, format: format
+        get :show, project_id: project.to_param, id: commit.id, format: format
 
         expect(response.body).to start_with("From #{commit.id}")
       end
 
       it "should contain a git diff" do
-        get :show, project_id: project.code, id: commit.id, format: format
+        get :show, project_id: project.to_param, id: commit.id, format: format
 
         expect(response.body).to match(/^diff --git/)
       end
diff --git a/spec/controllers/commits_controller_spec.rb b/spec/controllers/commits_controller_spec.rb
index facae17a0ada36e22cc88cf4bc6ca11742a7cf5e..8263afc97a2f988e32ecfcafefcffeaeb17fd90d 100644
--- a/spec/controllers/commits_controller_spec.rb
+++ b/spec/controllers/commits_controller_spec.rb
@@ -13,7 +13,7 @@ describe Projects::CommitsController do
   describe "GET show" do
     context "as atom feed" do
       it "should render as atom" do
-        get :show, project_id: project.path, id: "master", format: "atom"
+        get :show, project_id: project.to_param, id: "master", format: "atom"
         response.should be_success
         response.content_type.should == 'application/atom+xml'
       end
diff --git a/spec/controllers/merge_requests_controller_spec.rb b/spec/controllers/merge_requests_controller_spec.rb
index 3c1a9cb72687976eb203c489e5757905641759f9..69708edd8b100e1a0df6b0fd620520a7fcee3950 100644
--- a/spec/controllers/merge_requests_controller_spec.rb
+++ b/spec/controllers/merge_requests_controller_spec.rb
@@ -14,7 +14,7 @@ describe Projects::MergeRequestsController do
   describe "#show" do
     shared_examples "export merge as" do |format|
       it "should generally work" do
-        get :show, project_id: project.code, id: merge_request.iid, format: format
+        get :show, project_id: project.to_param, id: merge_request.iid, format: format
 
         expect(response).to be_success
       end
@@ -22,11 +22,11 @@ describe Projects::MergeRequestsController do
       it "should generate it" do
         MergeRequest.any_instance.should_receive(:"to_#{format}")
 
-        get :show, project_id: project.code, id: merge_request.iid, format: format
+        get :show, project_id: project.to_param, id: merge_request.iid, format: format
       end
 
       it "should render it" do
-        get :show, project_id: project.code, id: merge_request.iid, format: format
+        get :show, project_id: project.to_param, id: merge_request.iid, format: format
 
         expect(response.body).to eq((merge_request.send(:"to_#{format}",user)).to_s)
       end
@@ -34,7 +34,7 @@ describe Projects::MergeRequestsController do
       it "should not escape Html" do
         MergeRequest.any_instance.stub(:"to_#{format}").and_return('HTML entities &<>" ')
 
-        get :show, project_id: project.code, id: merge_request.iid, format: format
+        get :show, project_id: project.to_param, id: merge_request.iid, format: format
 
         expect(response.body).to_not include('&amp;')
         expect(response.body).to_not include('&gt;')
@@ -48,7 +48,7 @@ describe Projects::MergeRequestsController do
       let(:format) { :diff }
 
       it "should really only be a git diff" do
-        get :show, project_id: project.code, id: merge_request.iid, format: format
+        get :show, project_id: project.to_param, id: merge_request.iid, format: format
 
         expect(response.body).to start_with("diff --git")
       end
@@ -59,13 +59,13 @@ describe Projects::MergeRequestsController do
       let(:format) { :patch }
 
       it "should really be a git email patch with commit" do
-        get :show, project_id: project.code, id: merge_request.iid, format: format
+        get :show, project_id: project.to_param, id: merge_request.iid, format: format
 
         expect(response.body[0..100]).to start_with("From #{merge_request.commits.last.id}")
       end
 
       it "should contain git diffs" do
-        get :show, project_id: project.code, id: merge_request.iid, format: format
+        get :show, project_id: project.to_param, id: merge_request.iid, format: format
 
         expect(response.body).to match(/^diff --git/)
       end
diff --git a/spec/controllers/tree_controller_spec.rb b/spec/controllers/tree_controller_spec.rb
index 3e41b406c4f80a18f71952321f48e57e029e59a6..bb1232e6264b9f46445f854d02883868d938944b 100644
--- a/spec/controllers/tree_controller_spec.rb
+++ b/spec/controllers/tree_controller_spec.rb
@@ -18,7 +18,7 @@ describe Projects::TreeController do
     # Make sure any errors accessing the tree in our views bubble up to this spec
     render_views
 
-    before { get :show, project_id: project.code, id: id }
+    before { get :show, project_id: project.to_param, id: id }
 
     context "valid branch, no path" do
       let(:id) { 'master' }
diff --git a/spec/factories.rb b/spec/factories.rb
index e657321c294ce7b6483dff7960fc5516b2086496..56561fe45955461fd285ecb7be250327f6284788 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -28,6 +28,7 @@ FactoryGirl.define do
   factory :project do
     sequence(:name) { |n| "project#{n}" }
     path { name.downcase.gsub(/\s/, '_') }
+    namespace
     creator
 
     trait :source do
@@ -70,7 +71,6 @@ FactoryGirl.define do
   factory :group do
     sequence(:name) { |n| "group#{n}" }
     path { name.downcase.gsub(/\s/, '_') }
-    owner
     type 'Group'
   end
 
diff --git a/spec/features/atom/issues_spec.rb b/spec/features/atom/issues_spec.rb
index 0488c1f2266da9ded1408092ea43e8fe0601901a..c9bbdad380f54c6232183ba308b55115389e16d0 100644
--- a/spec/features/atom/issues_spec.rb
+++ b/spec/features/atom/issues_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
 describe "Issues Feed" do
   describe "GET /issues" do
     let!(:user)     { create(:user) }
-    let!(:project)  { create(:project, namespace: user.namespace) }
+    let!(:project)  { create(:project) }
     let!(:issue)    { create(:issue, author: user, project: project) }
 
     before { project.team << [user, :developer] }
diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb
index 6fff59f036f5fa5c4531f9cbbb1803f3001483f9..0c09279e3dc6eaa750b7968be6e481cbf0926b15 100644
--- a/spec/features/issues_spec.rb
+++ b/spec/features/issues_spec.rb
@@ -45,40 +45,6 @@ describe "Issues" do
     end
   end
 
-  describe "Search issue", js: true do
-    before do
-      ['foobar', 'foobar2', 'gitlab'].each do |title|
-        create(:issue,
-               author: @user,
-               assignee: @user,
-               project: project,
-               title: title)
-      end
-    end
-
-    it "should be able to search on different statuses" do
-      issue = Issue.first # with title 'foobar'
-      issue.close
-
-      visit project_issues_path(project)
-      click_link 'Closed'
-      fill_in 'issue_search', with: 'foobar'
-
-      page.should have_content 'foobar'
-      page.should_not have_content 'foobar2'
-      page.should_not have_content 'gitlab'
-    end
-
-    it "should search for term and return the correct results" do
-      visit project_issues_path(project)
-      fill_in 'issue_search', with: 'foobar'
-
-      page.should have_content 'foobar'
-      page.should have_content 'foobar2'
-      page.should_not have_content 'gitlab'
-    end
-  end
-
   describe "Filter issue" do
     before do
       ['foobar', 'barbaz', 'gitlab'].each do |title|
diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb
index 16bdaf0f83c2fad644e30c5552ebd52f038f24fc..ba580d9484dcc079a004bd265e112cb52af95425 100644
--- a/spec/features/notes_on_merge_requests_spec.rb
+++ b/spec/features/notes_on_merge_requests_spec.rb
@@ -206,17 +206,6 @@ describe "On a merge request diff", js: true, focus: true do
           find(".js-note-preview-button").trigger("click")
         end
       end
-
-      # TODO: fix
-      #it 'should check if previews were rendered separately' do
-      #within("tr[id='4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185'] + .js-temp-notes-holder") do
-      #should have_css(".js-note-preview", text: "One comment on line 185")
-      #end
-
-      #within("tr[id='342e16cbbd482ac2047dc679b2749d248cc1428f_18_17'] + .js-temp-notes-holder") do
-      #should have_css(".js-note-preview", text: "Another comment on line 17")
-      #end
-      #end
     end
 
     describe "posting a note" do
@@ -239,42 +228,8 @@ describe "On a merge request diff", js: true, focus: true do
         should have_css(".notes_holder .note", count: 1)
         should have_link("Reply")
       end
-
-      # TODO: fix
-      #it "should remove last note of a discussion" do
-      # within("tr[id='342e16cbbd482ac2047dc679b2749d248cc1428f_18_17'] + .notes-holder") do
-      #   find(".js-note-delete").click
-      # end
-      # should_not have_css(".note_holder")
-      #end
     end
   end
-
-  # TODO: fix
-  #describe "when replying to a note" do
-  #before do
-  ## create first note
-  # find('a[data-line-code="4735dfc552ad7bf15ca468adc3cad9d05b624490_184_184"]').click
-
-  # within(".js-temp-notes-holder") do
-  # fill_in "note[note]", with: "One comment on line 184"
-  # click_button("Add Comment")
-  #end
-
-  # within(".js-temp-notes-holder") do
-  # find(".js-discussion-reply-button").click
-  # fill_in "note[note]", with: "An additional comment in reply"
-  # click_button("Add Comment")
-  # end
-  #end
-
-  #it 'should be inserted and form removed from reply' do
-  # should have_content("An additional comment in reply")
-  # within(".notes_holder") { should have_css(".note", count: 2) }
-  # within(".notes_holder") { should have_no_css("form") }
-  # within(".notes_holder") { should have_link("Reply") }
-  # end
-  #end
 end
 
 describe "On merge request discussion", js: true do
diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb
index 7fa474d0ea1c35a8292d934b18621eaed86011ec..80c9f5d7f14ac8e7ade7626ad0f8d23449acdd17 100644
--- a/spec/features/profile_spec.rb
+++ b/spec/features/profile_spec.rb
@@ -17,26 +17,12 @@ describe "Profile account page" do
 
     it { page.should have_content("Remove account") }
 
-    it "should delete the account", js: true do
+    it "should delete the account" do
       expect { click_link "Delete account" }.to change {User.count}.by(-1)
       current_path.should == new_user_session_path
     end
   end
 
-  describe "when signup is enabled and user has a project" do
-    before do
-      Gitlab.config.gitlab.stub(:signup_enabled).and_return(true)
-      @project = create(:project, namespace: @user.namespace)
-      @project.team << [@user, :master]
-      visit account_profile_path
-    end
-    it { page.should have_content("Remove account") }
-
-    it "should not allow user to delete the account" do
-      expect { click_link "Delete account" }.not_to change {User.count}.by(-1)
-    end
-  end
-
   describe "when signup is disabled" do
     before do
       Gitlab.config.gitlab.stub(:signup_enabled).and_return(false)
diff --git a/spec/features/security/dashboard_access_spec.rb b/spec/features/security/dashboard_access_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..adec5926c6f68bb629faa841651625d72f6e2f78
--- /dev/null
+++ b/spec/features/security/dashboard_access_spec.rb
@@ -0,0 +1,55 @@
+require 'spec_helper'
+
+describe "Dashboard access" do
+  describe "GET /dashboard" do
+    subject { dashboard_path }
+
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /dashboard/issues" do
+    subject { issues_dashboard_path }
+
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /dashboard/merge_requests" do
+    subject { merge_requests_dashboard_path }
+
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /dashboard/projects" do
+    subject { projects_dashboard_path }
+
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /help" do
+    subject { help_path }
+
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /projects/new" do
+    it { new_project_path.should be_allowed_for :admin }
+    it { new_project_path.should be_allowed_for :user }
+    it { new_project_path.should be_denied_for :visitor }
+  end
+
+  describe "GET /groups/new" do
+    it { new_group_path.should be_allowed_for :admin }
+    it { new_group_path.should be_allowed_for :user }
+    it { new_group_path.should be_denied_for :visitor }
+  end
+end
diff --git a/spec/features/security/group_access_spec.rb b/spec/features/security/group_access_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..dea957962a8800837f3f10b0546d2cb7f85131cc
--- /dev/null
+++ b/spec/features/security/group_access_spec.rb
@@ -0,0 +1,85 @@
+require 'spec_helper'
+
+describe "Group access" do
+  describe "GET /projects/new" do
+    it { new_group_path.should be_allowed_for :admin }
+    it { new_group_path.should be_allowed_for :user }
+    it { new_group_path.should be_denied_for :visitor }
+  end
+
+  describe "Group" do
+    let(:group) { create(:group) }
+
+    let(:owner)   { create(:owner) }
+    let(:master)   { create(:user) }
+    let(:reporter) { create(:user) }
+    let(:guest)    { create(:user) }
+
+    before do
+      group.add_user(owner, Gitlab::Access::OWNER)
+      group.add_user(master, Gitlab::Access::MASTER)
+      group.add_user(reporter, Gitlab::Access::REPORTER)
+      group.add_user(guest, Gitlab::Access::GUEST)
+    end
+
+    describe "GET /groups/:path" do
+      subject { group_path(group) }
+
+      it { should be_allowed_for owner }
+      it { should be_allowed_for master }
+      it { should be_allowed_for reporter }
+      it { should be_allowed_for :admin }
+      it { should be_allowed_for guest }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
+    end
+
+    describe "GET /groups/:path/issues" do
+      subject { issues_group_path(group) }
+
+      it { should be_allowed_for owner }
+      it { should be_allowed_for master }
+      it { should be_allowed_for reporter }
+      it { should be_allowed_for :admin }
+      it { should be_allowed_for guest }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
+    end
+
+    describe "GET /groups/:path/merge_requests" do
+      subject { merge_requests_group_path(group) }
+
+      it { should be_allowed_for owner }
+      it { should be_allowed_for master }
+      it { should be_allowed_for reporter }
+      it { should be_allowed_for :admin }
+      it { should be_allowed_for guest }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
+    end
+
+    describe "GET /groups/:path/members" do
+      subject { members_group_path(group) }
+
+      it { should be_allowed_for owner }
+      it { should be_allowed_for master }
+      it { should be_allowed_for reporter }
+      it { should be_allowed_for :admin }
+      it { should be_allowed_for guest }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
+    end
+
+    describe "GET /groups/:path/edit" do
+      subject { edit_group_path(group) }
+
+      it { should be_allowed_for owner }
+      it { should be_denied_for master }
+      it { should be_denied_for reporter }
+      it { should be_allowed_for :admin }
+      it { should be_denied_for guest }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
+    end
+  end
+end
diff --git a/spec/features/security/profile_access_spec.rb b/spec/features/security/profile_access_spec.rb
index 52130b3f8c6c1d8878102e4bfc5dc3d412a2dc1b..7754b28347aa29635a8fecc1b55c6542375765a6 100644
--- a/spec/features/security/profile_access_spec.rb
+++ b/spec/features/security/profile_access_spec.rb
@@ -45,5 +45,32 @@ describe "Users Security" do
       it { should be_allowed_for :user }
       it { should be_denied_for :visitor }
     end
+
+    describe "GET /profile/history" do
+      subject { history_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/notifications" do
+      subject { profile_notifications_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/groups" do
+      subject { profile_groups_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/features/security/project/private_access_spec.rb b/spec/features/security/project/private_access_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7f3f8c50f02b2f30d3e67c45a2f00f4eec73381e
--- /dev/null
+++ b/spec/features/security/project/private_access_spec.rb
@@ -0,0 +1,218 @@
+require 'spec_helper'
+
+describe "Private Project Access" do
+  let(:project) { create(:project_with_code) }
+
+  let(:master)   { create(:user) }
+  let(:guest)    { create(:user) }
+  let(:reporter) { create(:user) }
+
+  before do
+    # full access
+    project.team << [master, :master]
+
+    # readonly
+    project.team << [reporter, :reporter]
+  end
+
+  describe "GET /:project_path" do
+    subject { project_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/tree/master" do
+    subject { project_tree_path(project, project.repository.root_ref) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/commits/master" do
+    subject { project_commits_path(project, project.repository.root_ref, limit: 1) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/commit/:sha" do
+    subject { project_commit_path(project, project.repository.commit) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/compare" do
+    subject { project_compare_index_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/team" do
+    subject { project_team_index_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_denied_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/wall" do
+    subject { project_wall_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/blob" do
+    before do
+      commit = project.repository.commit
+      path = commit.tree.contents.select { |i| i.is_a?(Grit::Blob) }.first.name
+      @blob_path = project_blob_path(project, File.join(commit.id, path))
+    end
+
+    it { @blob_path.should be_allowed_for master }
+    it { @blob_path.should be_allowed_for reporter }
+    it { @blob_path.should be_allowed_for :admin }
+    it { @blob_path.should be_denied_for guest }
+    it { @blob_path.should be_denied_for :user }
+    it { @blob_path.should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/edit" do
+    subject { edit_project_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_denied_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/deploy_keys" do
+    subject { project_deploy_keys_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_denied_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/issues" do
+    subject { project_issues_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/snippets" do
+    subject { project_snippets_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/merge_requests" do
+    subject { project_merge_requests_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/branches/recent" do
+    subject { recent_project_branches_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/branches" do
+    subject { project_branches_path(project) }
+
+    before do
+      # Speed increase
+      Project.any_instance.stub(:branches).and_return([])
+    end
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/tags" do
+    subject { project_tags_path(project) }
+
+    before do
+      # Speed increase
+      Project.any_instance.stub(:tags).and_return([])
+    end
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/hooks" do
+    subject { project_hooks_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_denied_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+end
diff --git a/spec/features/security/project/public_access_spec.rb b/spec/features/security/project/public_access_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..267643fd8ef2d485002e6f0da81b141b7716bf02
--- /dev/null
+++ b/spec/features/security/project/public_access_spec.rb
@@ -0,0 +1,251 @@
+require 'spec_helper'
+
+describe "Public Project Access" do
+  let(:project) { create(:project_with_code) }
+
+  let(:master) { create(:user) }
+  let(:guest) { create(:user) }
+  let(:reporter) { create(:user) }
+
+  before do
+    # public project
+    project.public = true
+    project.save!
+
+    # full access
+    project.team << [master, :master]
+
+    # readonly
+    project.team << [reporter, :reporter]
+
+  end
+
+  describe "Project should be public" do
+    subject { project }
+
+    its(:public?) { should be_true }
+  end
+
+  describe "GET /:project_path" do
+    subject { project_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for guest }
+    it { should be_allowed_for :user }
+    it { should be_allowed_for :visitor }
+  end
+
+  describe "GET /:project_path/tree/master" do
+    subject { project_tree_path(project, project.repository.root_ref) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for guest }
+    it { should be_allowed_for :user }
+    it { should be_allowed_for :visitor }
+  end
+
+  describe "GET /:project_path/commits/master" do
+    subject { project_commits_path(project, project.repository.root_ref, limit: 1) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for guest }
+    it { should be_allowed_for :user }
+    it { should be_allowed_for :visitor }
+  end
+
+  describe "GET /:project_path/commit/:sha" do
+    subject { project_commit_path(project, project.repository.commit) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for guest }
+    it { should be_allowed_for :user }
+    it { should be_allowed_for :visitor }
+  end
+
+  describe "GET /:project_path/compare" do
+    subject { project_compare_index_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for guest }
+    it { should be_allowed_for :user }
+    it { should be_allowed_for :visitor }
+  end
+
+  describe "GET /:project_path/team" do
+    subject { project_team_index_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_denied_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/wall" do
+    subject { project_wall_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for guest }
+    it { should be_allowed_for :user }
+    it { should be_allowed_for :visitor }
+  end
+
+  describe "GET /:project_path/blob" do
+    before do
+      commit = project.repository.commit
+      path = commit.tree.contents.select { |i| i.is_a?(Grit::Blob) }.first.name
+      @blob_path = project_blob_path(project, File.join(commit.id, path))
+    end
+
+    it { @blob_path.should be_allowed_for master }
+    it { @blob_path.should be_allowed_for reporter }
+    it { @blob_path.should be_allowed_for :admin }
+    it { @blob_path.should be_allowed_for guest }
+    it { @blob_path.should be_allowed_for :user }
+    it { @blob_path.should be_allowed_for :visitor }
+  end
+
+  describe "GET /:project_path/edit" do
+    subject { edit_project_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_denied_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/deploy_keys" do
+    subject { project_deploy_keys_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_denied_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/issues" do
+    subject { project_issues_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for guest }
+    it { should be_allowed_for :user }
+    it { should be_allowed_for :visitor }
+  end
+
+  describe "GET /:project_path/snippets" do
+    subject { project_snippets_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for guest }
+    it { should be_allowed_for :user }
+    it { should be_allowed_for :visitor }
+  end
+
+  describe "GET /:project_path/snippets/new" do
+    subject { new_project_snippet_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/merge_requests" do
+    subject { project_merge_requests_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for guest }
+    it { should be_allowed_for :user }
+    it { should be_allowed_for :visitor }
+  end
+
+  describe "GET /:project_path/merge_requests/new" do
+    subject { new_project_merge_request_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_denied_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+
+  describe "GET /:project_path/branches/recent" do
+    subject { recent_project_branches_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for guest }
+    it { should be_allowed_for :user }
+    it { should be_allowed_for :visitor }
+  end
+
+  describe "GET /:project_path/branches" do
+    subject { project_branches_path(project) }
+
+    before do
+      # Speed increase
+      Project.any_instance.stub(:branches).and_return([])
+    end
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for guest }
+    it { should be_allowed_for :user }
+    it { should be_allowed_for :visitor }
+  end
+
+  describe "GET /:project_path/tags" do
+    subject { project_tags_path(project) }
+
+    before do
+      # Speed increase
+      Project.any_instance.stub(:tags).and_return([])
+    end
+
+    it { should be_allowed_for master }
+    it { should be_allowed_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_allowed_for guest }
+    it { should be_allowed_for :user }
+    it { should be_allowed_for :visitor }
+  end
+
+  describe "GET /:project_path/hooks" do
+    subject { project_hooks_path(project) }
+
+    it { should be_allowed_for master }
+    it { should be_denied_for reporter }
+    it { should be_allowed_for :admin }
+    it { should be_denied_for guest }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
+  end
+end
diff --git a/spec/features/security/project_access_spec.rb b/spec/features/security/project_access_spec.rb
deleted file mode 100644
index d0964a947dba1c7861a765a453b5196a77d551bf..0000000000000000000000000000000000000000
--- a/spec/features/security/project_access_spec.rb
+++ /dev/null
@@ -1,474 +0,0 @@
-require 'spec_helper'
-
-describe "Application access" do
-  describe "GET /" do
-    it { root_path.should be_allowed_for :admin }
-    it { root_path.should be_allowed_for :user }
-    it { root_path.should be_denied_for :visitor }
-  end
-
-  describe "GET /projects/new" do
-    it { new_project_path.should be_allowed_for :admin }
-    it { new_project_path.should be_allowed_for :user }
-    it { new_project_path.should be_denied_for :visitor }
-  end
-
-  describe "Project" do
-    let(:project) { create(:project_with_code) }
-
-    let(:master) { create(:user) }
-    let(:guest) { create(:user) }
-    let(:reporter) { create(:user) }
-
-    before do
-      # full access
-      project.team << [master, :master]
-
-      # readonly
-      project.team << [reporter, :reporter]
-    end
-
-    describe "GET /project_code" do
-      subject { project_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/tree/master" do
-      subject { project_tree_path(project, project.repository.root_ref) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/commits/master" do
-      subject { project_commits_path(project, project.repository.root_ref, limit: 1) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/commit/:sha" do
-      subject { project_commit_path(project, project.repository.commit) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/compare" do
-      subject { project_compare_index_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/team" do
-      subject { project_team_index_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/wall" do
-      subject { project_wall_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/blob" do
-      before do
-        commit = project.repository.commit
-        path = commit.tree.contents.select { |i| i.is_a?(Grit::Blob) }.first.name
-        @blob_path = project_blob_path(project, File.join(commit.id, path))
-      end
-
-      it { @blob_path.should be_allowed_for master }
-      it { @blob_path.should be_allowed_for reporter }
-      it { @blob_path.should be_allowed_for :admin }
-      it { @blob_path.should be_denied_for guest }
-      it { @blob_path.should be_denied_for :user }
-      it { @blob_path.should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/edit" do
-      subject { edit_project_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_denied_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/deploy_keys" do
-      subject { project_deploy_keys_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_denied_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/issues" do
-      subject { project_issues_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/snippets" do
-      subject { project_snippets_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/merge_requests" do
-      subject { project_merge_requests_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/branches/recent" do
-      subject { recent_project_branches_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/branches" do
-      subject { project_branches_path(project) }
-
-      before do
-        # Speed increase
-        Project.any_instance.stub(:branches).and_return([])
-      end
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/tags" do
-      subject { project_tags_path(project) }
-
-      before do
-        # Speed increase
-        Project.any_instance.stub(:tags).and_return([])
-      end
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/hooks" do
-      subject { project_hooks_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-  end
-
-
-  describe "PublicProject" do
-    let(:project) { create(:project_with_code) }
-
-    let(:master) { create(:user) }
-    let(:guest) { create(:user) }
-    let(:reporter) { create(:user) }
-
-    let(:admin) { create(:user) }
-
-    before do
-      # public project
-      project.public = true
-      project.save!
-
-      # full access
-      project.team << [master, :master]
-
-      # readonly
-      project.team << [reporter, :reporter]
-
-    end
-
-    describe "Project should be public" do
-      subject { project }
-
-      its(:public?) { should be_true }
-    end
-
-    describe "GET /project_code" do
-      subject { project_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/tree/master" do
-      subject { project_tree_path(project, project.repository.root_ref) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/commits/master" do
-      subject { project_commits_path(project, project.repository.root_ref, limit: 1) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/commit/:sha" do
-      subject { project_commit_path(project, project.repository.commit) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/compare" do
-      subject { project_compare_index_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/team" do
-      subject { project_team_index_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/wall" do
-      subject { project_wall_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/blob" do
-      before do
-        commit = project.repository.commit
-        path = commit.tree.contents.select { |i| i.is_a?(Grit::Blob) }.first.name
-        @blob_path = project_blob_path(project, File.join(commit.id, path))
-      end
-
-      it { @blob_path.should be_allowed_for master }
-      it { @blob_path.should be_allowed_for reporter }
-      it { @blob_path.should be_allowed_for :admin }
-      it { @blob_path.should be_allowed_for guest }
-      it { @blob_path.should be_allowed_for :user }
-      it { @blob_path.should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/edit" do
-      subject { edit_project_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_denied_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/deploy_keys" do
-      subject { project_deploy_keys_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_denied_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/issues" do
-      subject { project_issues_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/snippets" do
-      subject { project_snippets_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/snippets/new" do
-      subject { new_project_snippet_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_denied_for guest }
-      it { should be_denied_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/merge_requests" do
-      subject { project_merge_requests_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/branches/recent" do
-      subject { recent_project_branches_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/branches" do
-      subject { project_branches_path(project) }
-
-      before do
-        # Speed increase
-        Project.any_instance.stub(:branches).and_return([])
-      end
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/tags" do
-      subject { project_tags_path(project) }
-
-      before do
-        # Speed increase
-        Project.any_instance.stub(:tags).and_return([])
-      end
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-
-    describe "GET /project_code/hooks" do
-      subject { project_hooks_path(project) }
-
-      it { should be_allowed_for master }
-      it { should be_allowed_for reporter }
-      it { should be_allowed_for :admin }
-      it { should be_allowed_for guest }
-      it { should be_allowed_for :user }
-      it { should be_denied_for :visitor }
-    end
-  end
-end
diff --git a/spec/javascripts/stat_graph_contributors_util_spec.js b/spec/javascripts/stat_graph_contributors_util_spec.js
index 367f0af05f8f32d925f1755859ac3660f4c9aa1b..2e52479ccbb309691dc6e07ab42a56d1743318ef 100644
--- a/spec/javascripts/stat_graph_contributors_util_spec.js
+++ b/spec/javascripts/stat_graph_contributors_util_spec.js
@@ -3,10 +3,10 @@ describe("ContributorsStatGraphUtil", function () {
   describe("#parse_log", function () {
     it("returns a correctly parsed log", function () {
       var fake_log = [
-            {author: "Karlo Soriano", date: "2013-05-09", additions: 471},
-            {author: "Dmitriy Zaporozhets", date: "2013-05-08", additions: 6, deletions: 1},
-            {author: "Dmitriy Zaporozhets", date: "2013-05-08", additions: 19, deletions: 3},
-            {author: "Dmitriy Zaporozhets", date: "2013-05-08", additions: 29, deletions: 3}]
+            {author_email: "karlo@email.com", author_name: "Karlo Soriano", date: "2013-05-09", additions: 471},
+            {author_email: "dzaporozhets@email.com", author_name: "Dmitriy Zaporozhets", date: "2013-05-08", additions: 6, deletions: 1},
+            {author_email: "dzaporozhets@email.com", author_name: "Dmitriy Zaporozhets", date: "2013-05-08", additions: 19, deletions: 3},
+            {author_email: "dzaporozhets@email.com", author_name: "Dmitriy Zaporozhets", date: "2013-05-08", additions: 29, deletions: 3}]
       
       var correct_parsed_log = {
         total: [
@@ -15,11 +15,11 @@ describe("ContributorsStatGraphUtil", function () {
         by_author:
         [
         { 
-          author: "Karlo Soriano", 
+          author_name: "Karlo Soriano", author_email: "karlo@email.com",
           "2013-05-09": {date: "2013-05-09", additions: 471, deletions: 0, commits: 1}
         },
         {
-          author: "Dmitriy Zaporozhets",
+          author_name: "Dmitriy Zaporozhets",author_email: "dzaporozhets@email.com",
           "2013-05-08": {date: "2013-05-08", additions: 54, deletions: 7, commits: 3}
         }
         ]
@@ -112,10 +112,10 @@ describe("ContributorsStatGraphUtil", function () {
 
   describe("#add_author", function () {
     it("adds an author field to the collection", function () {
-      var fake_author = "Author"
+      var fake_author = { author_name: "Author", author_email: 'fake@email.com' }
       var fake_collection = {}
       ContributorsStatGraphUtil.add_author(fake_author, fake_collection)
-      expect(fake_collection[fake_author].author).toEqual("Author")
+      expect(fake_collection[fake_author.author_name].author_name).toEqual("Author")
     })
   })
 
@@ -153,30 +153,35 @@ describe("ContributorsStatGraphUtil", function () {
   describe("#get_author_data", function () {
     it("returns the log by author sorted by specified field", function () {
       var fake_parsed_log = {
-      total: [{date: "2013-05-09", additions: 471, deletions: 0, commits: 1},
-      {date: "2013-05-08", additions: 54, deletions: 7, commits: 3}],
-      by_author:[
-      { 
-        author: "Karlo Soriano", 
-        "2013-05-09": {date: "2013-05-09", additions: 471, deletions: 0, commits: 1}
-      },
-      {
-        author: "Dmitriy Zaporozhets",
-        "2013-05-08": {date: "2013-05-08", additions: 54, deletions: 7, commits: 3}
+        total: [
+          {date: "2013-05-09", additions: 471, deletions: 0, commits: 1}, 
+          {date: "2013-05-08", additions: 54, deletions: 7, commits: 3}
+        ],
+        by_author: [
+          { 
+            author_name: "Karlo Soriano", author_email: "karlo@email.com",
+            "2013-05-09": {date: "2013-05-09", additions: 471, deletions: 0, commits: 1}
+          },
+          {
+            author_name: "Dmitriy Zaporozhets", author_email: "dzaporozhets@email.com",
+            "2013-05-08": {date: "2013-05-08", additions: 54, deletions: 7, commits: 3}
+          }
+        ]
       }
-      ]}
-      var correct_author_data = [{author:"Dmitriy Zaporozhets",dates:{"2013-05-08":3},deletions:7,additions:54,"commits":3},
-      {author:"Karlo Soriano",dates:{"2013-05-09":1},deletions:0,additions:471,commits:1}]
+      var correct_author_data = [
+        {author_name:"Dmitriy Zaporozhets",author_email:"dzaporozhets@email.com",dates:{"2013-05-08":3},deletions:7,additions:54,"commits":3},
+        {author_name:"Karlo Soriano",author_email:"karlo@email.com",dates:{"2013-05-09":1},deletions:0,additions:471,commits:1}
+      ]
       expect(ContributorsStatGraphUtil.get_author_data(fake_parsed_log, "commits")).toEqual(correct_author_data)
     })
   })
 
   describe("#parse_log_entry", function () {
     it("adds the corresponding info from the log entry to the author", function () {
-      var fake_log_entry =    { author: "Karlo Soriano", 
+      var fake_log_entry =    { author_name: "Karlo Soriano", author_email: "karlo@email.com",
         "2013-05-09": {date: "2013-05-09", additions: 471, deletions: 0, commits: 1}
       }
-      var correct_parsed_log = {author:"Karlo Soriano",dates:{"2013-05-09":1},deletions:0,additions:471,commits:1}
+      var correct_parsed_log = {author_name:"Karlo Soriano",author_email:"karlo@email.com",dates:{"2013-05-09":1},deletions:0,additions:471,commits:1}
       expect(ContributorsStatGraphUtil.parse_log_entry(fake_log_entry, 'commits', null)).toEqual(correct_parsed_log)
     })
   })
@@ -197,4 +202,4 @@ describe("ContributorsStatGraphUtil", function () {
   })
 
 
-})
\ No newline at end of file
+})
diff --git a/spec/javascripts/support/jasmine_helper.rb b/spec/javascripts/support/jasmine_helper.rb
index 986a4c16f3e03e83f0b7ecec54ef695bd02e5759..34b418a9ca35fa1a5bb68ee4826dd6413277e2f4 100644
--- a/spec/javascripts/support/jasmine_helper.rb
+++ b/spec/javascripts/support/jasmine_helper.rb
@@ -1,11 +1,5 @@
-#Use this file to set/override Jasmine configuration options
-#You can remove it if you don't need it.
-#This file is loaded *after* jasmine.yml is interpreted.
-#
-#Example: using a different boot file.
-#Jasmine.configure do |config|
-#   @config.boot_dir = '/absolute/path/to/boot_dir'
-#   @config.boot_files = lambda { ['/absolute/path/to/boot_dir/file.js'] }
-#end
-#
+WebMock.allow_net_connect!
 
+Jasmine.configure do |config|
+  config.browser = :phantomjs
+end
diff --git a/spec/lib/auth_spec.rb b/spec/lib/auth_spec.rb
index 2784d4e2fbed5dc22f7caa804295f19b617bd3dc..e05fde95731a6ff8ba3b3756be33e6d3695865a9 100644
--- a/spec/lib/auth_spec.rb
+++ b/spec/lib/auth_spec.rb
@@ -3,102 +3,26 @@ 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
+  describe :find do
     before do
-      @auth = mock(
-        uid: '12djsak321',
-        info: @info,
-        provider: 'ldap'
+      @user = create(
+        :user,
+        username: 'john',
+        password: '888777',
+        password_confirmation: '888777'
       )
     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 does not 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',
-      )
+    it "should find user by valid login/password" do
+      gl_auth.find('john', '888777').should == @user
     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)
+    it "should not find user with invalid password" do
+      gl_auth.find('john', 'invalid').should_not == @user
     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
-
-    it "should apply defaults to user" do
-      @auth = mock(info: @info, provider: 'ldap')
-      user = gl_auth.create_from_omniauth(@auth, true)
-
-      user.should be_valid
-      user.projects_limit.should == Gitlab.config.gitlab.default_projects_limit
-      user.can_create_group.should == Gitlab.config.gitlab.default_can_create_group
+    it "should not find user with invalid login and password" do
+      gl_auth.find('jon', 'invalid').should_not == @user
     end
   end
 end
diff --git a/spec/lib/gitlab/ldap/ldap_user_auth_spec.rb b/spec/lib/gitlab/ldap/ldap_user_auth_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b1c583c047672e33b03043e5019e9fd386a76dfa
--- /dev/null
+++ b/spec/lib/gitlab/ldap/ldap_user_auth_spec.rb
@@ -0,0 +1,57 @@
+require 'spec_helper'
+
+describe Gitlab::LDAP do
+  let(:gl_auth) { Gitlab::LDAP::User }
+
+  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 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_or_create(@auth)
+    end
+
+    it "should update credentials by username if missing uid and Gitlab.config.ldap.allow_username_or_email_login is true" do
+      user = double('User')
+      value = Gitlab.config.ldap.allow_username_or_email_login
+      Gitlab.config.ldap['allow_username_or_email_login'] = true
+      User.stub find_by_extern_uid_and_provider: nil
+      User.stub find_by_email: nil
+      User.stub find_by_username: user
+      user.should_receive :update_attributes
+      gl_auth.find_or_create(@auth)
+      Gitlab.config.ldap['allow_username_or_email_login'] = value
+    end
+
+    it "should not update credentials by username if missing uid and Gitlab.config.ldap.allow_username_or_email_login is false" do
+      user = double('User')
+      value = Gitlab.config.ldap.allow_username_or_email_login
+      Gitlab.config.ldap['allow_username_or_email_login'] = false
+      User.stub find_by_extern_uid_and_provider: nil
+      User.stub find_by_email: nil
+      User.stub find_by_username: user
+      user.should_not_receive :update_attributes
+      gl_auth.find_or_create(@auth)
+      Gitlab.config.ldap['allow_username_or_email_login'] = value
+    end
+  end
+end
diff --git a/spec/lib/oauth_spec.rb b/spec/lib/oauth_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e21074554b65452921e0b179e1f1dd78456c3da3
--- /dev/null
+++ b/spec/lib/oauth_spec.rb
@@ -0,0 +1,44 @@
+require 'spec_helper'
+
+describe Gitlab::OAuth::User do
+  let(:gl_auth) { Gitlab::OAuth::User }
+
+  before do
+    Gitlab.config.stub(omniauth: {})
+
+    @info = mock(
+      uid: '12djsak321',
+      name: 'John',
+      email: 'john@mail.com'
+    )
+  end
+
+  describe :create do
+    it "should create user from LDAP" do
+      @auth = mock(info: @info, provider: 'ldap')
+      user = gl_auth.create(@auth)
+
+      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(@auth)
+
+      user.should be_valid
+      user.extern_uid.should == @info.uid
+      user.provider.should == 'twitter'
+    end
+
+    it "should apply defaults to user" do
+      @auth = mock(info: @info, provider: 'ldap')
+      user = gl_auth.create(@auth)
+
+      user.should be_valid
+      user.projects_limit.should == Gitlab.config.gitlab.default_projects_limit
+      user.can_create_group.should == Gitlab.config.gitlab.default_can_create_group
+    end
+  end
+end
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index 2f0475e5f02bb4a4872fd842479686f1db6e6e87..0787bdbea6fffff83041d798ce71fdb0e9bba90c 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -347,4 +347,24 @@ describe Notify do
       end
     end
   end
+
+  describe 'group access changed' do
+    let(:group) { create(:group) }
+    let(:user) { create(:user) }
+    let(:membership) { create(:users_group, group: group, user: user) }
+
+    subject { Notify.group_access_granted_email(membership.id) }
+
+    it 'has the correct subject' do
+      should have_subject /access to group was granted/
+    end
+
+    it 'contains name of project' do
+      should have_body_text /#{group.name}/
+    end
+
+    it 'contains new user role' do
+      should have_body_text /#{membership.human_access}/
+    end
+  end
 end
diff --git a/spec/models/flowdock_service_spec.rb b/spec/models/flowdock_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b22193c9e930716826cef3ad7c81508e4f3860ed
--- /dev/null
+++ b/spec/models/flowdock_service_spec.rb
@@ -0,0 +1,48 @@
+# == Schema Information
+#
+# Table name: services
+#
+#  id          :integer          not null, primary key
+#  type        :string(255)
+#  title       :string(255)
+#  token       :string(255)
+#  project_id  :integer          not null
+#  created_at  :datetime         not null
+#  updated_at  :datetime         not null
+#  active      :boolean          default(FALSE), not null
+#  project_url :string(255)
+#
+
+require 'spec_helper'
+
+describe FlowdockService do
+  describe "Associations" do
+    it { should belong_to :project }
+    it { should have_one :service_hook }
+  end
+
+  describe "Execute" do
+    let(:user)    { create(:user) }
+    let(:project) { create(:project_with_code) }
+
+    before do
+      @flowdock_service = FlowdockService.new
+      @flowdock_service.stub(
+        project_id: project.id,
+        project: project,
+        service_hook: true,
+        token: 'verySecret'
+      )
+      @sample_data = GitPushService.new.sample_data(project, user)
+      @api_url = 'https://api.flowdock.com/v1/git/verySecret'
+      WebMock.stub_request(:post, @api_url)
+    end
+
+    it "should call FlowDock API" do
+      @flowdock_service.execute(@sample_data)
+      WebMock.should have_requested(:post, @api_url).with(
+        body: /#{@sample_data[:before]}.*#{@sample_data[:after]}.*#{project.path}/
+      ).once
+    end
+  end
+end
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index 78c39548eb45fa9c293ddae138f45f3883dc495d..4a08ad3bb158d1140324f8de93144f9494847e51 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -5,7 +5,7 @@
 #  id          :integer          not null, primary key
 #  name        :string(255)      not null
 #  path        :string(255)      not null
-#  owner_id    :integer          not null
+#  owner_id    :integer
 #  created_at  :datetime         not null
 #  updated_at  :datetime         not null
 #  type        :string(255)
@@ -26,10 +26,10 @@ describe Group do
   it { should validate_uniqueness_of(:name) }
   it { should validate_presence_of :path }
   it { should validate_uniqueness_of(:path) }
-  it { should validate_presence_of :owner }
+  it { should_not validate_presence_of :owner }
 
   describe :users do
-    it { group.users.should == [group.owner] }
+    it { group.users.should == group.owners }
   end
 
   describe :human_name do
@@ -38,7 +38,7 @@ describe Group do
 
   describe :add_users do
     let(:user) { create(:user) }
-    before { group.add_users([user.id], UsersGroup::MASTER) }
+    before { group.add_user(user, UsersGroup::MASTER) }
 
     it { group.users_groups.masters.map(&:user).should include(user) }
   end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 18c32d4fb74d1020530bd73be52acb8c35bea145..b17183a281c221e797a5146374eb341a06d9193a 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -18,6 +18,7 @@
 #  merge_status      :string(255)
 #  target_project_id :integer          not null
 #  iid               :integer
+#  description       :text
 #
 
 require 'spec_helper'
@@ -48,8 +49,8 @@ describe MergeRequest do
 
     before do
       merge_request.stub(:commits) { [merge_request.source_project.repository.commit] }
-      create(:note, commit_id: merge_request.commits.first.id, noteable_type: 'Commit')
-      create(:note, noteable: merge_request)
+      create(:note, commit_id: merge_request.commits.first.id, noteable_type: 'Commit', project: merge_request.project)
+      create(:note, noteable: merge_request, project: merge_request.project)
     end
 
     it "should include notes for commits" do
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index 0a0509bcd27fed36006db352acd4e50e35bec7c7..c38554e2f77ebfd50cdebf1841599973436db640 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -5,7 +5,7 @@
 #  id          :integer          not null, primary key
 #  name        :string(255)      not null
 #  path        :string(255)      not null
-#  owner_id    :integer          not null
+#  owner_id    :integer
 #  created_at  :datetime         not null
 #  updated_at  :datetime         not null
 #  type        :string(255)
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index ef143debcc18b25babf5cc716acda864bfb3f57d..42c405d8e506cb05a5f582d67bf1ae61bed75468 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -14,6 +14,7 @@
 #  commit_id     :string(255)
 #  noteable_id   :integer
 #  st_diff       :text
+#  system        :boolean          default(FALSE), not null
 #
 
 require 'spec_helper'
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 172adb5fc7a3c7b64a1b7e558ebf67fb014565cc..47ae760a7eddfa9cababed328678624025ee9399 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -58,15 +58,16 @@ describe Project do
     let!(:project) { create(:project) }
 
     it { should validate_presence_of(:name) }
-    it { should validate_uniqueness_of(:name) }
+    it { should validate_uniqueness_of(:name).scoped_to(:namespace_id) }
     it { should ensure_length_of(:name).is_within(0..255) }
 
     it { should validate_presence_of(:path) }
-    it { should validate_uniqueness_of(:path) }
+    it { should validate_uniqueness_of(:path).scoped_to(:namespace_id) }
     it { should ensure_length_of(:path).is_within(0..255) }
     it { should ensure_length_of(:description).is_within(0..2000) }
     it { should validate_presence_of(:creator) }
     it { should ensure_length_of(:issues_tracker_id).is_within(0..255) }
+    it { should validate_presence_of(:namespace) }
 
     it "should not allow new projects beyond user limits" do
       project2 = build(:project)
@@ -84,7 +85,6 @@ describe Project do
     it { should respond_to(:execute_hooks) }
     it { should respond_to(:transfer) }
     it { should respond_to(:name_with_namespace) }
-    it { should respond_to(:namespace_owner) }
     it { should respond_to(:owner) }
     it { should respond_to(:path_with_namespace) }
   end
@@ -157,15 +157,6 @@ describe Project do
       it { Project.find_with_namespace('gitlab/gitlab-ci').should == @project }
       it { Project.find_with_namespace('gitlab-ci').should be_nil }
     end
-
-    context 'w/o namespace' do
-      before do
-        @project = create(:project, name: 'gitlab-ci')
-      end
-
-      it { Project.find_with_namespace('gitlab-ci').should == @project }
-      it { Project.find_with_namespace('gitlab/gitlab-ci').should be_nil }
-    end
   end
 
   describe :to_param do
@@ -177,14 +168,6 @@ describe Project do
 
       it { @project.to_param.should == "gitlab/gitlab-ci" }
     end
-
-    context 'w/o namespace' do
-      before do
-        @project = create(:project, name: 'gitlab-ci')
-      end
-
-      it { @project.to_param.should == "gitlab-ci" }
-    end
   end
 
   describe :repository do
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 695f0ae68462addf79fbe2321f417da71d9376ca..f6c9f82c4ee010e4c1253ac055d33e440c417e4e 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -130,15 +130,30 @@ describe User do
     before do
       ActiveRecord::Base.observers.enable(:user_observer)
       @user = create :user
-      @group = create :group, owner: @user
+      @group = create :group
+      @group.add_owner(@user)
     end
 
     it { @user.several_namespaces?.should be_true }
-    it { @user.namespaces.should include(@user.namespace, @group) }
+    it { @user.namespaces.should include(@user.namespace) }
     it { @user.authorized_groups.should == [@group] }
     it { @user.owned_groups.should == [@group] }
   end
 
+  describe 'group multiple owners' do
+    before do
+      ActiveRecord::Base.observers.enable(:user_observer)
+      @user = create :user
+      @user2 = create :user
+      @group = create :group
+      @group.add_owner(@user)
+
+      @group.add_user(@user2, UsersGroup::OWNER)
+    end
+
+    it { @user2.several_namespaces?.should be_true }
+  end
+
   describe 'namespaced' do
     before do
       ActiveRecord::Base.observers.enable(:user_observer)
@@ -183,29 +198,82 @@ describe User do
     it { User.not_in_project(@project).should include(@user, @project.owner) }
   end
 
-  describe 'normal user' do
-    let(:user) { create(:user, name: 'John Smith') }
+  describe 'user creation' do
+    describe 'normal user' do
+      let(:user) { create(:user, name: 'John Smith') }
 
-    it { user.is_admin?.should be_false }
-    it { user.require_ssh_key?.should be_true }
-    it { user.can_create_group?.should be_true }
-    it { user.can_create_project?.should be_true }
-    it { user.first_name.should == 'John' }
-  end
+      it { user.is_admin?.should be_false }
+      it { user.require_ssh_key?.should be_true }
+      it { user.can_create_group?.should be_true }
+      it { user.can_create_project?.should be_true }
+      it { user.first_name.should == 'John' }
+    end
 
-  describe 'without defaults' do
-    let(:user) { User.new }
-    it "should not apply defaults to user" do
-      user.projects_limit.should == 10
-      user.can_create_group.should == true
+    describe 'without defaults' do
+      let(:user) { User.new }
+
+      it "should not apply defaults to user" do
+        user.projects_limit.should == 10
+        user.can_create_group.should be_true
+        user.theme_id.should == Gitlab::Theme::BASIC
+      end
+    end
+    context 'as admin' do
+      describe 'with defaults' do
+        let(:user) { User.build_user({}, as: :admin) }
+
+        it "should apply defaults to user" do
+          user.projects_limit.should == Gitlab.config.gitlab.default_projects_limit
+          user.can_create_group.should == Gitlab.config.gitlab.default_can_create_group
+          user.theme_id.should == Gitlab.config.gitlab.default_theme
+        end
+      end
+
+      describe 'with default overrides' do
+        let(:user) { User.build_user({projects_limit: 123, can_create_group: true, can_create_team: true, theme_id: Gitlab::Theme::BASIC}, as: :admin) }
+
+        it "should apply defaults to user" do
+          Gitlab.config.gitlab.default_projects_limit.should_not == 123
+          Gitlab.config.gitlab.default_can_create_group.should_not be_true
+          Gitlab.config.gitlab.default_theme.should_not == Gitlab::Theme::BASIC
+          user.projects_limit.should == 123
+          user.can_create_group.should be_true
+          user.theme_id.should == Gitlab::Theme::BASIC
+        end
+      end
+    end
+
+    context 'as user' do
+      describe 'with defaults' do
+        let(:user) { User.build_user }
+
+        it "should apply defaults to user" do
+          user.projects_limit.should == Gitlab.config.gitlab.default_projects_limit
+          user.can_create_group.should == Gitlab.config.gitlab.default_can_create_group
+          user.theme_id.should == Gitlab.config.gitlab.default_theme
+        end
+      end
+
+      describe 'with default overrides' do
+        let(:user) { User.build_user(projects_limit: 123, can_create_group: true, theme_id: Gitlab::Theme::BASIC) }
+
+        it "should apply defaults to user" do
+          user.projects_limit.should == Gitlab.config.gitlab.default_projects_limit
+          user.can_create_group.should == Gitlab.config.gitlab.default_can_create_group
+          user.theme_id.should == Gitlab.config.gitlab.default_theme
+        end
+      end
     end
   end
 
-  describe 'with defaults' do
-    let(:user) { User.new.with_defaults }
-    it "should apply defaults to user" do
-      user.projects_limit.should == 42
-      user.can_create_group.should == false
+  describe 'by_username_or_id' do
+    let(:user1) { create(:user, username: 'foo') }
+
+    it "should get the correct user" do
+      User.by_username_or_id(user1.id).should == user1
+      User.by_username_or_id('foo').should == user1
+      User.by_username_or_id(-1).should be_nil
+      User.by_username_or_id('bar').should be_nil
     end
   end
 end
diff --git a/spec/observers/users_group_observer_spec.rb b/spec/observers/users_group_observer_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..3bf562edbb759004313135742d71d37cda75655e
--- /dev/null
+++ b/spec/observers/users_group_observer_spec.rb
@@ -0,0 +1,27 @@
+require 'spec_helper'
+
+describe UsersGroupObserver do
+  before(:each) { enable_observers }
+  after(:each) { disable_observers }
+
+  subject { UsersGroupObserver.instance }
+  before { subject.stub(notification: mock('NotificationService').as_null_object) }
+
+  describe "#after_create" do
+    it "should send email to user" do
+      subject.should_receive(:notification)
+      create(:users_group)
+    end
+  end
+
+  describe "#after_update" do
+    before do
+      @membership = create :users_group
+    end
+
+    it "should send email to user" do
+      subject.should_receive(:notification)
+      @membership.update_attribute(:group_access, UsersGroup::MASTER)
+    end
+  end
+end
diff --git a/spec/requests/api/api_helpers_spec.rb b/spec/requests/api/api_helpers_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2fc78a7e3907ee2dbd1383035f74e4f0a0f51f71
--- /dev/null
+++ b/spec/requests/api/api_helpers_spec.rb
@@ -0,0 +1,161 @@
+require 'spec_helper'
+
+describe API do
+  include API::APIHelpers
+  include ApiHelpers
+  let(:user) { create(:user) }
+  let(:admin) { create(:admin) }
+  let(:key) { create(:key, user: user) }
+
+  let(:params) { {} }
+  let(:env) { {} }
+
+  def set_env(token_usr, identifier)
+    clear_env
+    clear_param
+    env[API::APIHelpers::PRIVATE_TOKEN_HEADER] = token_usr.private_token
+    env[API::APIHelpers::SUDO_HEADER] = identifier
+  end
+
+  def set_param(token_usr, identifier)
+    clear_env
+    clear_param
+    params[API::APIHelpers::PRIVATE_TOKEN_PARAM] = token_usr.private_token
+    params[API::APIHelpers::SUDO_PARAM] = identifier
+  end
+
+  def clear_env
+    env.delete(API::APIHelpers::PRIVATE_TOKEN_HEADER)
+    env.delete(API::APIHelpers::SUDO_HEADER)
+  end
+
+  def clear_param
+    params.delete(API::APIHelpers::PRIVATE_TOKEN_PARAM)
+    params.delete(API::APIHelpers::SUDO_PARAM)
+  end
+
+  def error!(message, status)
+    raise Exception
+  end
+
+  describe ".current_user" do
+    it "should leave user as is when sudo not specified" do
+      env[API::APIHelpers::PRIVATE_TOKEN_HEADER] = user.private_token
+      current_user.should == user
+      clear_env
+      params[API::APIHelpers::PRIVATE_TOKEN_PARAM] = user.private_token
+      current_user.should == user
+    end
+
+    it "should change current user to sudo when admin" do
+      set_env(admin, user.id)
+      current_user.should == user
+      set_param(admin, user.id)
+      current_user.should == user
+      set_env(admin, user.username)
+      current_user.should == user
+      set_param(admin, user.username)
+      current_user.should == user
+    end
+
+    it "should throw an error when the current user is not an admin and attempting to sudo" do
+      set_env(user, admin.id)
+      expect { current_user }.to raise_error
+      set_param(user, admin.id)
+      expect { current_user }.to raise_error
+      set_env(user, admin.username)
+      expect { current_user }.to raise_error
+      set_param(user, admin.username)
+      expect { current_user }.to raise_error
+    end
+
+    it "should throw an error when the user cannot be found for a given id" do
+      id = user.id + admin.id
+      user.id.should_not == id
+      admin.id.should_not == id
+      set_env(admin, id)
+      expect { current_user }.to raise_error
+
+      set_param(admin, id)
+      expect { current_user }.to raise_error
+    end
+
+    it "should throw an error when the user cannot be found for a given username" do
+      username = "#{user.username}#{admin.username}"
+      user.username.should_not == username
+      admin.username.should_not == username
+      set_env(admin, username)
+      expect { current_user }.to raise_error
+
+      set_param(admin, username)
+      expect { current_user }.to raise_error
+    end
+
+    it "should handle sudo's to oneself" do
+      set_env(admin, admin.id)
+      current_user.should == admin
+      set_param(admin, admin.id)
+      current_user.should == admin
+      set_env(admin, admin.username)
+      current_user.should == admin
+      set_param(admin, admin.username)
+      current_user.should == admin
+    end
+
+    it "should handle multiple sudo's to oneself" do
+      set_env(admin, user.id)
+      current_user.should == user
+      current_user.should == user
+      set_env(admin, user.username)
+      current_user.should == user
+      current_user.should == user
+
+      set_param(admin, user.id)
+      current_user.should == user
+      current_user.should == user
+      set_param(admin, user.username)
+      current_user.should == user
+      current_user.should == user
+    end
+
+    it "should handle multiple sudo's to oneself using string ids" do
+      set_env(admin, user.id.to_s)
+      current_user.should == user
+      current_user.should == user
+
+      set_param(admin, user.id.to_s)
+      current_user.should == user
+      current_user.should == user
+    end
+  end
+
+  describe '.sudo_identifier' do
+    it "should return integers when input is an int" do
+      set_env(admin, '123')
+      sudo_identifier.should == 123
+      set_env(admin, '0001234567890')
+      sudo_identifier.should == 1234567890
+
+      set_param(admin, '123')
+      sudo_identifier.should == 123
+      set_param(admin, '0001234567890')
+      sudo_identifier.should == 1234567890
+    end
+
+    it "should return string when input is an is not an int" do
+      set_env(admin, '12.30')
+      sudo_identifier.should == "12.30"
+      set_env(admin, 'hello')
+      sudo_identifier.should == 'hello'
+      set_env(admin, ' 123')
+      sudo_identifier.should == ' 123'
+
+      set_param(admin, '12.30')
+      sudo_identifier.should == "12.30"
+      set_param(admin, 'hello')
+      sudo_identifier.should == 'hello'
+      set_param(admin, ' 123')
+      sudo_identifier.should == ' 123'
+    end
+  end
+end
\ No newline at end of file
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index d2e25fb9e23782dbf1f53f91696a5c30954a0b30..25b9a10bd8c1f8f6f1a499b3512ddd376244bfa7 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -3,11 +3,16 @@ require 'spec_helper'
 describe API::API do
   include ApiHelpers
 
-  let(:user1)  { create(:user) }
-  let(:user2)  { create(:user) }
+  let(:user1) { create(:user) }
+  let(:user2) { create(:user) }
   let(:admin) { create(:admin) }
-  let!(:group1)  { create(:group, owner: user1) }
-  let!(:group2)  { create(:group, owner: user2) }
+  let!(:group1) { create(:group) }
+  let!(:group2) { create(:group) }
+
+  before do
+    group1.add_owner(user1)
+    group2.add_owner(user2)
+  end
 
   describe "GET /groups" do
     context "when unauthenticated" do
@@ -52,7 +57,7 @@ describe API::API do
 
       it "should not return a group not attached to user1" do
         get api("/groups/#{group2.id}", user1)
-        response.status.should == 404
+        response.status.should == 403
       end
     end
 
@@ -90,7 +95,7 @@ describe API::API do
       end
 
       it "should return 400 bad request error if name not given" do
-        post api("/groups", admin), { path: group2.path }
+        post api("/groups", admin), {path: group2.path}
         response.status.should == 400
       end
 
@@ -101,14 +106,51 @@ describe API::API do
     end
   end
 
+  describe "DELETE /groups/:id" do
+    context "when authenticated as user" do
+      it "should remove group" do
+        delete api("/groups/#{group1.id}", user1)
+        response.status.should == 200
+      end
+
+      it "should not remove a group if not an owner" do
+        user3 = create(:user)
+        group1.add_user(user3, Gitlab::Access::MASTER)
+        delete api("/groups/#{group1.id}", user3)
+        response.status.should == 403
+      end
+
+      it "should not remove a non existing group" do
+        delete api("/groups/1328", user1)
+        response.status.should == 404
+      end
+
+      it "should not remove a group not attached to user1" do
+        delete api("/groups/#{group2.id}", user1)
+        response.status.should == 403
+      end
+    end
+
+    context "when authenticated as admin" do
+      it "should remove any existing group" do
+        delete api("/groups/#{group2.id}", admin)
+        response.status.should == 200
+      end
+
+      it "should not remove a non existing group" do
+        delete api("/groups/1328", admin)
+        response.status.should == 404
+      end
+    end
+  end
+
   describe "POST /groups/:id/projects/:project_id" do
     let(:project) { create(:project) }
     before(:each) do
-       project.stub!(:transfer).and_return(true)
-       Project.stub(:find).and_return(project)
+      project.stub!(:transfer).and_return(true)
+      Project.stub(:find).and_return(project)
     end
 
-
     context "when authenticated as user" do
       it "should not transfer project to group" do
         post api("/groups/#{group1.id}/projects/#{project.id}", user2)
@@ -123,4 +165,114 @@ describe API::API do
       end
     end
   end
+
+  describe "members" do
+    let(:owner) { create(:user) }
+    let(:reporter) { create(:user) }
+    let(:developer) { create(:user) }
+    let(:master) { create(:user) }
+    let(:guest) { create(:user) }
+    let!(:group_with_members) do
+      group = create(:group)
+      group.add_users([reporter.id], UsersGroup::REPORTER)
+      group.add_users([developer.id], UsersGroup::DEVELOPER)
+      group.add_users([master.id], UsersGroup::MASTER)
+      group.add_users([guest.id], UsersGroup::GUEST)
+      group
+    end
+    let!(:group_no_members) { create(:group) }
+
+    before do
+      group_with_members.add_owner owner
+      group_no_members.add_owner owner
+    end
+
+    describe "GET /groups/:id/members" do
+      context "when authenticated as user that is part or the group" do
+        it "each user: should return an array of members groups of group3" do
+          [owner, master, developer, reporter, guest].each do |user|
+            get api("/groups/#{group_with_members.id}/members", user)
+            response.status.should == 200
+            json_response.should be_an Array
+            json_response.size.should == 5
+            json_response.find { |e| e['id']==owner.id }['access_level'].should == UsersGroup::OWNER
+            json_response.find { |e| e['id']==reporter.id }['access_level'].should == UsersGroup::REPORTER
+            json_response.find { |e| e['id']==developer.id }['access_level'].should == UsersGroup::DEVELOPER
+            json_response.find { |e| e['id']==master.id }['access_level'].should == UsersGroup::MASTER
+            json_response.find { |e| e['id']==guest.id }['access_level'].should == UsersGroup::GUEST
+          end
+        end
+
+        it "users not part of the group should get access error" do
+          get api("/groups/#{group_with_members.id}/members", user1)
+          response.status.should == 403
+        end
+      end
+    end
+
+    describe "POST /groups/:id/members" do
+      context "when not a member of the group" do
+        it "should not add guest as member of group_no_members when adding being done by person outside the group" do
+          post api("/groups/#{group_no_members.id}/members", reporter), user_id: guest.id, access_level: UsersGroup::MASTER
+          response.status.should == 403
+        end
+      end
+
+      context "when a member of the group" do
+        it "should return ok and add new member" do
+          count_before=group_no_members.users_groups.count
+          new_user = create(:user)
+          post api("/groups/#{group_no_members.id}/members", owner), user_id: new_user.id, access_level: UsersGroup::MASTER
+          response.status.should == 201
+          json_response['name'].should == new_user.name
+          json_response['access_level'].should == UsersGroup::MASTER
+          group_no_members.users_groups.count.should == count_before + 1
+        end
+
+        it "should return error if member already exists" do
+          post api("/groups/#{group_with_members.id}/members", owner), user_id: master.id, access_level: UsersGroup::MASTER
+          response.status.should == 409
+        end
+
+        it "should return a 400 error when user id is not given" do
+          post api("/groups/#{group_no_members.id}/members", owner), access_level: UsersGroup::MASTER
+          response.status.should == 400
+        end
+
+        it "should return a 400 error when access level is not given" do
+          post api("/groups/#{group_no_members.id}/members", owner), user_id: master.id
+          response.status.should == 400
+        end
+
+        it "should return a 422 error when access level is not known" do
+          post api("/groups/#{group_no_members.id}/members", owner), user_id: master.id, access_level: 1234
+          response.status.should == 422
+        end
+      end
+    end
+
+    describe "DELETE /groups/:id/members/:user_id" do
+      context "when not a member of the group" do
+        it "should not delete guest's membership of group_with_members" do
+          random_user = create(:user)
+          delete api("/groups/#{group_with_members.id}/members/#{owner.id}", random_user)
+          response.status.should == 403
+        end
+      end
+
+      context "when a member of the group" do
+        it "should delete guest's membership of group" do
+          count_before=group_with_members.users_groups.count
+          delete api("/groups/#{group_with_members.id}/members/#{guest.id}", owner)
+          response.status.should == 200
+          group_with_members.users_groups.count.should == count_before - 1
+        end
+
+        it "should return a 404 error when user id is not known" do
+          delete api("/groups/#{group_with_members.id}/members/1328", owner)
+          response.status.should == 404
+        end
+      end
+    end
+  end
 end
diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb
index 028617aa08e64dadac589a577716bbbe7d67c74f..e8870f4d5d8c83401e78d224f67f2a2cd0a78cd9 100644
--- a/spec/requests/api/internal_spec.rb
+++ b/spec/requests/api/internal_spec.rb
@@ -2,6 +2,8 @@ require 'spec_helper'
 
 describe API::API do
   include ApiHelpers
+  before(:each) { ActiveRecord::Base.observers.enable(:user_observer) }
+  after(:each) { ActiveRecord::Base.observers.disable(:user_observer) }
 
   let(:user) { create(:user) }
   let(:key) { create(:key, user: user) }
diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb
index d5f75367e4ad905967c780b8e4ae1b876033005d..a97d6a282a9bf55195ef6920146280b395f513a1 100644
--- a/spec/requests/api/issues_spec.rb
+++ b/spec/requests/api/issues_spec.rb
@@ -2,6 +2,8 @@ require 'spec_helper'
 
 describe API::API do
   include ApiHelpers
+  before(:each) { ActiveRecord::Base.observers.enable(:user_observer) }
+  after(:each) { ActiveRecord::Base.observers.disable(:user_observer) }
 
   let(:user) { create(:user) }
   let!(:project) { create(:project, namespace: user.namespace ) }
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index 7b893c43379ebf9b6362039104fc82d9d655c246..2f11f562aa1c4898bf11071891ced6cc2553dc03 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -2,9 +2,10 @@ require "spec_helper"
 
 describe API::API do
   include ApiHelpers
-
+  before(:each) { ActiveRecord::Base.observers.enable(:user_observer) }
+  after(:each) { ActiveRecord::Base.observers.disable(:user_observer) }
   let(:user) { create(:user) }
-  let!(:project) {create(:project_with_code, creator_id: user.id) }
+  let!(:project) {create(:project_with_code, creator_id: user.id, namespace: user.namespace) }
   let!(:merge_request) { create(:merge_request, author: user, assignee: user, source_project: project, target_project: project, title: "Test") }
   before {
     project.team << [user, :reporters]
diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb
index 48a2d111f8cab72ab0b3f88be3bdaea2f0cb6d01..ba18b123039c97912ef97eb2b3d8417bd4cab497 100644
--- a/spec/requests/api/notes_spec.rb
+++ b/spec/requests/api/notes_spec.rb
@@ -2,6 +2,8 @@ require 'spec_helper'
 
 describe API::API do
   include ApiHelpers
+  before(:each) { ActiveRecord::Base.observers.enable(:user_observer) }
+  after(:each) { ActiveRecord::Base.observers.disable(:user_observer) }
 
   let(:user) { create(:user) }
   let!(:project) { create(:project, namespace: user.namespace ) }
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 2de3dc55e4030037d4781f9adbc57d1b3441af8f..b8c0b6f33edf4c3180164fb541b1cc4321f35ea2 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -692,4 +692,42 @@ describe API::API do
       end
     end
   end
+
+  describe "GET /projects/search/:query" do
+    let!(:query) { 'query'}
+    let!(:search) { create(:project, name: query, creator_id: user.id, namespace: user.namespace) }
+    let!(:pre) { create(:project, name: "pre_#{query}", creator_id: user.id, namespace: user.namespace) }
+    let!(:post) { create(:project, name: "#{query}_post", creator_id: user.id, namespace: user.namespace) }
+    let!(:pre_post) { create(:project, name: "pre_#{query}_post", creator_id: user.id, namespace: user.namespace) }
+    let!(:unfound) { create(:project, name: 'unfound', creator_id: user.id, namespace: user.namespace) }
+    let!(:public) { create(:project, name: "another #{query}",public: true) }
+    let!(:unfound_public) { create(:project, name: 'unfound public', public: true) }
+
+    context "when unauthenticated" do
+      it "should return authentication error" do
+        get api("/projects/search/#{query}")
+        response.status.should == 401
+      end
+    end
+
+    context "when authenticated" do
+      it "should return an array of projects" do
+        get api("/projects/search/#{query}",user)
+        response.status.should == 200
+        json_response.should be_an Array
+        json_response.size.should == 5
+        json_response.each {|project| project['name'].should =~ /.*query.*/}
+      end
+    end
+
+    context "when authenticated as a different user" do
+      it "should return matching public projects" do
+        get api("/projects/search/#{query}", user2)
+        response.status.should == 200
+        json_response.should be_an Array
+        json_response.size.should == 1
+        json_response.first['name'].should == "another #{query}"
+      end
+    end
+  end
 end
diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb
index f15abdd358106595d163a9b6d3eb940a5ec1734b..2e509ea2933ccedf42b7ec925a591386fa0fa8bc 100644
--- a/spec/requests/api/repositories_spec.rb
+++ b/spec/requests/api/repositories_spec.rb
@@ -8,7 +8,8 @@ describe API::API do
   let(:user) { create(:user) }
   let(:user2) { create(:user) }
   let!(:project) { create(:project_with_code, creator_id: user.id) }
-  let!(:users_project) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) }
+  let!(:master) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) }
+  let!(:guest) { create(:users_project, user: user2, project: project, project_access: UsersProject::GUEST) }
 
   before { project.team << [user, :reporter] }
 
@@ -32,6 +33,11 @@ describe API::API do
       json_response['protected'].should == false
     end
 
+    it "should return a 403 error if guest" do
+      get api("/projects/#{project.id}/repository/branches", user2)
+      response.status.should == 403
+    end
+
     it "should return a 404 error if branch is not available" do
       get api("/projects/#{project.id}/repository/branches/unknown", user)
       response.status.should == 404
@@ -53,6 +59,11 @@ describe API::API do
       response.status.should == 404
     end
 
+    it "should return a 403 error if guest" do
+      put api("/projects/#{project.id}/repository/branches/new_design/protect", user2)
+      response.status.should == 403
+    end
+
     it "should return success when protect branch again" do
       put api("/projects/#{project.id}/repository/branches/new_design/protect", user)
       put api("/projects/#{project.id}/repository/branches/new_design/protect", user)
diff --git a/spec/requests/api/session_spec.rb b/spec/requests/api/session_spec.rb
index 88c17f26a69d1373e3f172904b92e8c7f54d8524..0fd90c567e060be81786ce06d24e077f8926d4b1 100644
--- a/spec/requests/api/session_spec.rb
+++ b/spec/requests/api/session_spec.rb
@@ -14,7 +14,6 @@ describe API::API do
         json_response['email'].should == user.email
         json_response['private_token'].should == user.private_token
         json_response['is_admin'].should == user.is_admin?
-        json_response['can_create_team'].should == user.can_create_team?
         json_response['can_create_project'].should == user.can_create_project?
         json_response['can_create_group'].should == user.can_create_group?
       end
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 2f4aaae38901149173a25c324abc6300892e9b12..4ef78b8e5d023d537691dd223b27dc7b23c3193f 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -52,11 +52,53 @@ describe API::API do
       }.to change { User.count }.by(1)
     end
 
+    it "should create user with correct attributes" do
+      post api('/users', admin), attributes_for(:user, admin: true, can_create_group: true)
+      response.status.should == 201
+      user_id = json_response['id']
+      new_user = User.find(user_id)
+      new_user.should_not == nil
+      new_user.admin.should == true
+      new_user.can_create_group.should == true
+    end
+
+    it "should create non-admin user" do
+      post api('/users', admin), attributes_for(:user, admin: false, can_create_group: false)
+      response.status.should == 201
+      user_id = json_response['id']
+      new_user = User.find(user_id)
+      new_user.should_not == nil
+      new_user.admin.should == false
+      new_user.can_create_group.should == false
+    end
+
+    it "should create non-admin users by default" do
+      post api('/users', admin), attributes_for(:user)
+      response.status.should == 201
+      user_id = json_response['id']
+      new_user = User.find(user_id)
+      new_user.should_not == nil
+      new_user.admin.should == false
+    end
+
     it "should return 201 Created on success" do
       post api("/users", admin), attributes_for(:user, projects_limit: 3)
       response.status.should == 201
     end
 
+    it "creating a user should respect default project limit" do
+      limit = 123456
+      Gitlab.config.gitlab.stub(:default_projects_limit).and_return(limit)
+      attr = attributes_for(:user )
+      expect {
+        post api("/users", admin), attr
+      }.to change { User.count }.by(1)
+      user = User.find_by_username(attr[:username])
+      user.projects_limit.should == limit
+      user.theme_id.should == Gitlab::Theme::MARS
+      Gitlab.config.gitlab.unstub(:default_projects_limit)
+    end
+
     it "should not create user with invalid email" do
       post api("/users", admin), { email: "invalid email", password: 'password' }
       response.status.should == 400
@@ -122,6 +164,8 @@ describe API::API do
   end
 
   describe "PUT /users/:id" do
+    let!(:admin_user) { create(:admin) }
+
     before { admin }
 
     it "should update user with new bio" do
@@ -131,6 +175,21 @@ describe API::API do
       user.reload.bio.should == 'new test bio'
     end
 
+    it "should update admin status" do
+      put api("/users/#{user.id}", admin), {admin: true}
+      response.status.should == 200
+      json_response['is_admin'].should == true
+      user.reload.admin.should == true
+    end
+
+    it "should not update admin status" do
+      put api("/users/#{admin_user.id}", admin), {can_create_group: false}
+      response.status.should == 200
+      json_response['is_admin'].should == true
+      admin_user.reload.admin.should == true
+      admin_user.can_create_group.should == false
+    end
+
     it "should not allow invalid update" do
       put api("/users/#{user.id}", admin), {email: 'invalid email'}
       response.status.should == 404
@@ -215,7 +274,6 @@ describe API::API do
       response.status.should == 200
       json_response['email'].should == user.email
       json_response['is_admin'].should == user.is_admin?
-      json_response['can_create_team'].should == user.can_create_team?
       json_response['can_create_project'].should == user.can_create_project?
       json_response['can_create_group'].should == user.can_create_group?
     end
diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb
index 5fb0f860c42c45e12640be1e0ff44a5766e36f8a..20c04e94c24704339da8c0e1bcbe887cd168275c 100644
--- a/spec/routing/project_routing_spec.rb
+++ b/spec/routing/project_routing_spec.rb
@@ -25,31 +25,31 @@ 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("projects/#{controller}#index", project_id: 'gitlabhq') if actions.include?(:index)
+    get("/gitlab/gitlabhq/#{controller}").should route_to("projects/#{controller}#index", project_id: 'gitlab/gitlabhq') if actions.include?(:index)
   end
 
   it "to #create" do
-    post("/gitlabhq/#{controller}").should route_to("projects/#{controller}#create", project_id: 'gitlabhq') if actions.include?(:create)
+    post("/gitlab/gitlabhq/#{controller}").should route_to("projects/#{controller}#create", project_id: 'gitlab/gitlabhq') if actions.include?(:create)
   end
 
   it "to #new" do
-    get("/gitlabhq/#{controller}/new").should route_to("projects/#{controller}#new", project_id: 'gitlabhq') if actions.include?(:new)
+    get("/gitlab/gitlabhq/#{controller}/new").should route_to("projects/#{controller}#new", project_id: 'gitlab/gitlabhq') if actions.include?(:new)
   end
 
   it "to #edit" do
-    get("/gitlabhq/#{controller}/1/edit").should route_to("projects/#{controller}#edit", project_id: 'gitlabhq', id: '1') if actions.include?(:edit)
+    get("/gitlab/gitlabhq/#{controller}/1/edit").should route_to("projects/#{controller}#edit", project_id: 'gitlab/gitlabhq', id: '1') if actions.include?(:edit)
   end
 
   it "to #show" do
-    get("/gitlabhq/#{controller}/1").should route_to("projects/#{controller}#show", project_id: 'gitlabhq', id: '1') if actions.include?(:show)
+    get("/gitlab/gitlabhq/#{controller}/1").should route_to("projects/#{controller}#show", project_id: 'gitlab/gitlabhq', id: '1') if actions.include?(:show)
   end
 
   it "to #update" do
-    put("/gitlabhq/#{controller}/1").should route_to("projects/#{controller}#update", project_id: 'gitlabhq', id: '1') if actions.include?(:update)
+    put("/gitlab/gitlabhq/#{controller}/1").should route_to("projects/#{controller}#update", project_id: 'gitlab/gitlabhq', id: '1') if actions.include?(:update)
   end
 
   it "to #destroy" do
-    delete("/gitlabhq/#{controller}/1").should route_to("projects/#{controller}#destroy", project_id: 'gitlabhq', id: '1') if actions.include?(:destroy)
+    delete("/gitlab/gitlabhq/#{controller}/1").should route_to("projects/#{controller}#destroy", project_id: 'gitlab/gitlabhq', id: '1') if actions.include?(:destroy)
   end
 end
 
@@ -72,31 +72,31 @@ describe ProjectsController, "routing" do
   end
 
   it "to #fork" do
-    post("/gitlabhq/fork").should route_to('projects#fork', id: 'gitlabhq')
+    post("/gitlab/gitlabhq/fork").should route_to('projects#fork', id: 'gitlab/gitlabhq')
   end
 
   it "to #wall" do
-    get("/gitlabhq/wall").should route_to('projects/walls#show', project_id: 'gitlabhq')
+    get("/gitlab/gitlabhq/wall").should route_to('projects/walls#show', project_id: 'gitlab/gitlabhq')
   end
 
   it "to #edit" do
-    get("/gitlabhq/edit").should route_to('projects#edit', id: 'gitlabhq')
+    get("/gitlab/gitlabhq/edit").should route_to('projects#edit', id: 'gitlab/gitlabhq')
   end
 
   it "to #autocomplete_sources" do
-    get('/gitlabhq/autocomplete_sources').should route_to('projects#autocomplete_sources', id: "gitlabhq")
+    get('/gitlab/gitlabhq/autocomplete_sources').should route_to('projects#autocomplete_sources', id: "gitlab/gitlabhq")
   end
 
   it "to #show" do
-    get("/gitlabhq").should route_to('projects#show', id: 'gitlabhq')
+    get("/gitlab/gitlabhq").should route_to('projects#show', id: 'gitlab/gitlabhq')
   end
 
   it "to #update" do
-    put("/gitlabhq").should route_to('projects#update', id: 'gitlabhq')
+    put("/gitlab/gitlabhq").should route_to('projects#update', id: 'gitlab/gitlabhq')
   end
 
   it "to #destroy" do
-    delete("/gitlabhq").should route_to('projects#destroy', id: 'gitlabhq')
+    delete("/gitlab/gitlabhq").should route_to('projects#destroy', id: 'gitlab/gitlabhq')
   end
 end
 
@@ -108,11 +108,11 @@ end
 #                      DELETE /:project_id/wikis/:id(.:format)         projects/wikis#destroy
 describe Projects::WikisController, "routing" do
   it "to #pages" do
-    get("/gitlabhq/wikis/pages").should route_to('projects/wikis#pages', project_id: 'gitlabhq')
+    get("/gitlab/gitlabhq/wikis/pages").should route_to('projects/wikis#pages', project_id: 'gitlab/gitlabhq')
   end
 
   it "to #history" do
-    get("/gitlabhq/wikis/1/history").should route_to('projects/wikis#history', project_id: 'gitlabhq', id: '1')
+    get("/gitlab/gitlabhq/wikis/1/history").should route_to('projects/wikis#history', project_id: 'gitlab/gitlabhq', id: '1')
   end
 
   it_behaves_like "RESTful project resources" do
@@ -127,23 +127,23 @@ end
 #     edit_project_repository GET    /:project_id/repository/edit(.:format)     projects/repositories#edit
 describe Projects::RepositoriesController, "routing" do
   it "to #archive" do
-    get("/gitlabhq/repository/archive").should route_to('projects/repositories#archive', project_id: 'gitlabhq')
+    get("/gitlab/gitlabhq/repository/archive").should route_to('projects/repositories#archive', project_id: 'gitlab/gitlabhq')
   end
 
   it "to #show" do
-    get("/gitlabhq/repository").should route_to('projects/repositories#show', project_id: 'gitlabhq')
+    get("/gitlab/gitlabhq/repository").should route_to('projects/repositories#show', project_id: 'gitlab/gitlabhq')
   end
 end
 
 describe Projects::BranchesController, "routing" do
   it "to #branches" do
-    get("/gitlabhq/branches").should route_to('projects/branches#index', project_id: 'gitlabhq')
+    get("/gitlab/gitlabhq/branches").should route_to('projects/branches#index', project_id: 'gitlab/gitlabhq')
   end
 end
 
 describe Projects::TagsController, "routing" do
   it "to #tags" do
-    get("/gitlabhq/tags").should route_to('projects/tags#index', project_id: 'gitlabhq')
+    get("/gitlab/gitlabhq/tags").should route_to('projects/tags#index', project_id: 'gitlab/gitlabhq')
   end
 end
 
@@ -176,16 +176,16 @@ end
 #  logs_file_project_ref GET    /:project_id/refs/:id/logs_tree/:path(.:format) refs#logs_tree
 describe Projects::RefsController, "routing" do
   it "to #switch" do
-    get("/gitlabhq/refs/switch").should route_to('projects/refs#switch', project_id: 'gitlabhq')
+    get("/gitlab/gitlabhq/refs/switch").should route_to('projects/refs#switch', project_id: 'gitlab/gitlabhq')
   end
 
   it "to #logs_tree" do
-    get("/gitlabhq/refs/stable/logs_tree").should             route_to('projects/refs#logs_tree', project_id: 'gitlabhq', id: 'stable')
-    get("/gitlabhq/refs/feature%2345/logs_tree").should             route_to('projects/refs#logs_tree', project_id: 'gitlabhq', id: 'feature#45')
-    get("/gitlabhq/refs/feature%2B45/logs_tree").should             route_to('projects/refs#logs_tree', project_id: 'gitlabhq', id: 'feature+45')
-    get("/gitlabhq/refs/stable/logs_tree/foo/bar/baz").should route_to('projects/refs#logs_tree', project_id: 'gitlabhq', id: 'stable', path: 'foo/bar/baz')
-    get("/gitlabhq/refs/feature%2345/logs_tree/foo/bar/baz").should route_to('projects/refs#logs_tree', project_id: 'gitlabhq', id: 'feature#45', path: 'foo/bar/baz')
-    get("/gitlabhq/refs/feature%2B45/logs_tree/foo/bar/baz").should route_to('projects/refs#logs_tree', project_id: 'gitlabhq', id: 'feature+45', path: 'foo/bar/baz')
+    get("/gitlab/gitlabhq/refs/stable/logs_tree").should             route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'stable')
+    get("/gitlab/gitlabhq/refs/feature%2345/logs_tree").should             route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature#45')
+    get("/gitlab/gitlabhq/refs/feature%2B45/logs_tree").should             route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature+45')
+    get("/gitlab/gitlabhq/refs/stable/logs_tree/foo/bar/baz").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'stable', path: 'foo/bar/baz')
+    get("/gitlab/gitlabhq/refs/feature%2345/logs_tree/foo/bar/baz").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature#45', path: 'foo/bar/baz')
+    get("/gitlab/gitlabhq/refs/feature%2B45/logs_tree/foo/bar/baz").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature+45', path: 'foo/bar/baz')
     get("/gitlab/gitlabhq/refs/stable/logs_tree/files.scss").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'stable', path: 'files.scss')
   end
 end
@@ -204,28 +204,28 @@ end
 #                                       DELETE /:project_id/merge_requests/:id(.:format)                 projects/merge_requests#destroy
 describe Projects::MergeRequestsController, "routing" do
   it "to #diffs" do
-    get("/gitlabhq/merge_requests/1/diffs").should route_to('projects/merge_requests#diffs', project_id: 'gitlabhq', id: '1')
+    get("/gitlab/gitlabhq/merge_requests/1/diffs").should route_to('projects/merge_requests#diffs', project_id: 'gitlab/gitlabhq', id: '1')
   end
 
   it "to #automerge" do
-    get("/gitlabhq/merge_requests/1/automerge").should route_to('projects/merge_requests#automerge', project_id: 'gitlabhq', id: '1')
+    get("/gitlab/gitlabhq/merge_requests/1/automerge").should route_to('projects/merge_requests#automerge', project_id: 'gitlab/gitlabhq', id: '1')
   end
 
   it "to #automerge_check" do
-    get("/gitlabhq/merge_requests/1/automerge_check").should route_to('projects/merge_requests#automerge_check', project_id: 'gitlabhq', id: '1')
+    get("/gitlab/gitlabhq/merge_requests/1/automerge_check").should route_to('projects/merge_requests#automerge_check', project_id: 'gitlab/gitlabhq', id: '1')
   end
 
   it "to #branch_from" do
-    get("/gitlabhq/merge_requests/branch_from").should route_to('projects/merge_requests#branch_from', project_id: 'gitlabhq')
+    get("/gitlab/gitlabhq/merge_requests/branch_from").should route_to('projects/merge_requests#branch_from', project_id: 'gitlab/gitlabhq')
   end
 
   it "to #branch_to" do
-    get("/gitlabhq/merge_requests/branch_to").should route_to('projects/merge_requests#branch_to', project_id: 'gitlabhq')
+    get("/gitlab/gitlabhq/merge_requests/branch_to").should route_to('projects/merge_requests#branch_to', project_id: 'gitlab/gitlabhq')
   end
 
   it "to #show" do
-    get("/gitlabhq/merge_requests/1.diff").should route_to('projects/merge_requests#show', project_id: 'gitlabhq', id: '1', format: 'diff')
-    get("/gitlabhq/merge_requests/1.patch").should route_to('projects/merge_requests#show', project_id: 'gitlabhq', id: '1', format: 'patch')
+    get("/gitlab/gitlabhq/merge_requests/1.diff").should route_to('projects/merge_requests#show', project_id: 'gitlab/gitlabhq', id: '1', format: 'diff')
+    get("/gitlab/gitlabhq/merge_requests/1.patch").should route_to('projects/merge_requests#show', project_id: 'gitlab/gitlabhq', id: '1', format: 'patch')
   end
 
   it_behaves_like "RESTful project resources" do
@@ -244,35 +244,35 @@ end
 #                      DELETE /:project_id/snippets/:id(.:format)      snippets#destroy
 describe SnippetsController, "routing" do
   it "to #raw" do
-    get("/gitlabhq/snippets/1/raw").should route_to('projects/snippets#raw', project_id: 'gitlabhq', id: '1')
+    get("/gitlab/gitlabhq/snippets/1/raw").should route_to('projects/snippets#raw', project_id: 'gitlab/gitlabhq', id: '1')
   end
 
   it "to #index" do
-    get("/gitlabhq/snippets").should route_to("projects/snippets#index", project_id: 'gitlabhq')
+    get("/gitlab/gitlabhq/snippets").should route_to("projects/snippets#index", project_id: 'gitlab/gitlabhq')
   end
 
   it "to #create" do
-    post("/gitlabhq/snippets").should route_to("projects/snippets#create", project_id: 'gitlabhq')
+    post("/gitlab/gitlabhq/snippets").should route_to("projects/snippets#create", project_id: 'gitlab/gitlabhq')
   end
 
   it "to #new" do
-    get("/gitlabhq/snippets/new").should route_to("projects/snippets#new", project_id: 'gitlabhq')
+    get("/gitlab/gitlabhq/snippets/new").should route_to("projects/snippets#new", project_id: 'gitlab/gitlabhq')
   end
 
   it "to #edit" do
-    get("/gitlabhq/snippets/1/edit").should route_to("projects/snippets#edit", project_id: 'gitlabhq', id: '1')
+    get("/gitlab/gitlabhq/snippets/1/edit").should route_to("projects/snippets#edit", project_id: 'gitlab/gitlabhq', id: '1')
   end
 
   it "to #show" do
-    get("/gitlabhq/snippets/1").should route_to("projects/snippets#show", project_id: 'gitlabhq', id: '1')
+    get("/gitlab/gitlabhq/snippets/1").should route_to("projects/snippets#show", project_id: 'gitlab/gitlabhq', id: '1')
   end
 
   it "to #update" do
-    put("/gitlabhq/snippets/1").should route_to("projects/snippets#update", project_id: 'gitlabhq', id: '1')
+    put("/gitlab/gitlabhq/snippets/1").should route_to("projects/snippets#update", project_id: 'gitlab/gitlabhq', id: '1')
   end
 
   it "to #destroy" do
-    delete("/gitlabhq/snippets/1").should route_to("projects/snippets#destroy", project_id: 'gitlabhq', id: '1')
+    delete("/gitlab/gitlabhq/snippets/1").should route_to("projects/snippets#destroy", project_id: 'gitlab/gitlabhq', id: '1')
   end
 end
 
@@ -282,7 +282,7 @@ end
 #      project_hook DELETE /:project_id/hooks/:id(.:format)      hooks#destroy
 describe Projects::HooksController, "routing" do
   it "to #test" do
-    get("/gitlabhq/hooks/1/test").should route_to('projects/hooks#test', project_id: 'gitlabhq', id: '1')
+    get("/gitlab/gitlabhq/hooks/1/test").should route_to('projects/hooks#test', project_id: 'gitlab/gitlabhq', id: '1')
   end
 
   it_behaves_like "RESTful project resources" do
@@ -294,10 +294,10 @@ end
 # project_commit GET    /:project_id/commit/:id(.:format) commit#show {id: /[[:alnum:]]{6,40}/, project_id: /[^\/]+/}
 describe Projects::CommitController, "routing" do
   it "to #show" do
-    get("/gitlabhq/commit/4246fb").should route_to('projects/commit#show', project_id: 'gitlabhq', id: '4246fb')
-    get("/gitlabhq/commit/4246fb.diff").should route_to('projects/commit#show', project_id: 'gitlabhq', id: '4246fb', format: 'diff')
-    get("/gitlabhq/commit/4246fb.patch").should route_to('projects/commit#show', project_id: 'gitlabhq', id: '4246fb', format: 'patch')
-    get("/gitlabhq/commit/4246fbd13872934f72a8fd0d6fb1317b47b59cb5").should route_to('projects/commit#show', project_id: 'gitlabhq', id: '4246fbd13872934f72a8fd0d6fb1317b47b59cb5')
+    get("/gitlab/gitlabhq/commit/4246fb").should route_to('projects/commit#show', project_id: 'gitlab/gitlabhq', id: '4246fb')
+    get("/gitlab/gitlabhq/commit/4246fb.diff").should route_to('projects/commit#show', project_id: 'gitlab/gitlabhq', id: '4246fb', format: 'diff')
+    get("/gitlab/gitlabhq/commit/4246fb.patch").should route_to('projects/commit#show', project_id: 'gitlab/gitlabhq', id: '4246fb', format: 'patch')
+    get("/gitlab/gitlabhq/commit/4246fbd13872934f72a8fd0d6fb1317b47b59cb5").should route_to('projects/commit#show', project_id: 'gitlab/gitlabhq', id: '4246fbd13872934f72a8fd0d6fb1317b47b59cb5')
   end
 end
 
@@ -347,7 +347,7 @@ end
 # project_labels GET    /:project_id/labels(.:format) labels#index
 describe Projects::LabelsController, "routing" do
   it "to #index" do
-    get("/gitlabhq/labels").should route_to('projects/labels#index', project_id: 'gitlabhq')
+    get("/gitlab/gitlabhq/labels").should route_to('projects/labels#index', project_id: 'gitlab/gitlabhq')
   end
 end
 
@@ -363,7 +363,7 @@ end
 #                            DELETE /:project_id/issues/:id(.:format)         issues#destroy
 describe Projects::IssuesController, "routing" do
   it "to #bulk_update" do
-    post("/gitlabhq/issues/bulk_update").should route_to('projects/issues#bulk_update', project_id: 'gitlabhq')
+    post("/gitlab/gitlabhq/issues/bulk_update").should route_to('projects/issues#bulk_update', project_id: 'gitlab/gitlabhq')
   end
 
   it_behaves_like "RESTful project resources" do
@@ -378,7 +378,7 @@ end
 #          project_note DELETE /:project_id/notes/:id(.:format)     notes#destroy
 describe Projects::NotesController, "routing" do
   it "to #preview" do
-    post("/gitlabhq/notes/preview").should route_to('projects/notes#preview', project_id: 'gitlabhq')
+    post("/gitlab/gitlabhq/notes/preview").should route_to('projects/notes#preview', project_id: 'gitlab/gitlabhq')
   end
 
   it_behaves_like "RESTful project resources" do
@@ -390,7 +390,7 @@ end
 # project_blame GET    /:project_id/blame/:id(.:format) blame#show {id: /.+/, project_id: /[^\/]+/}
 describe Projects::BlameController, "routing" do
   it "to #show" do
-    get("/gitlabhq/blame/master/app/models/project.rb").should route_to('projects/blame#show', project_id: 'gitlabhq', id: 'master/app/models/project.rb')
+    get("/gitlab/gitlabhq/blame/master/app/models/project.rb").should route_to('projects/blame#show', project_id: 'gitlab/gitlabhq', id: 'master/app/models/project.rb')
     get("/gitlab/gitlabhq/blame/master/files.scss").should route_to('projects/blame#show', project_id: 'gitlab/gitlabhq', id: 'master/files.scss')
   end
 end
@@ -398,8 +398,8 @@ end
 # project_blob GET    /:project_id/blob/:id(.:format) blob#show {id: /.+/, project_id: /[^\/]+/}
 describe Projects::BlobController, "routing" do
   it "to #show" do
-    get("/gitlabhq/blob/master/app/models/project.rb").should route_to('projects/blob#show', project_id: 'gitlabhq', id: 'master/app/models/project.rb')
-    get("/gitlabhq/blob/master/app/models/compare.rb").should route_to('projects/blob#show', project_id: 'gitlabhq', id: 'master/app/models/compare.rb')
+    get("/gitlab/gitlabhq/blob/master/app/models/project.rb").should route_to('projects/blob#show', project_id: 'gitlab/gitlabhq', id: 'master/app/models/project.rb')
+    get("/gitlab/gitlabhq/blob/master/app/models/compare.rb").should route_to('projects/blob#show', project_id: 'gitlab/gitlabhq', id: 'master/app/models/compare.rb')
     get("/gitlab/gitlabhq/blob/master/files.scss").should route_to('projects/blob#show', project_id: 'gitlab/gitlabhq', id: 'master/files.scss')
   end
 end
@@ -407,7 +407,7 @@ end
 # project_tree GET    /:project_id/tree/:id(.:format) tree#show {id: /.+/, project_id: /[^\/]+/}
 describe Projects::TreeController, "routing" do
   it "to #show" do
-    get("/gitlabhq/tree/master/app/models/project.rb").should route_to('projects/tree#show', project_id: 'gitlabhq', id: 'master/app/models/project.rb')
+    get("/gitlab/gitlabhq/tree/master/app/models/project.rb").should route_to('projects/tree#show', project_id: 'gitlab/gitlabhq', id: 'master/app/models/project.rb')
     get("/gitlab/gitlabhq/tree/master/files.scss").should route_to('projects/tree#show', project_id: 'gitlab/gitlabhq', id: 'master/files.scss')
   end
 end
@@ -417,28 +417,28 @@ end
 #       project_compare        /:project_id/compare/:from...:to(.:format) compare#show {from: /.+/, to: /.+/, id: /[^\/]+/, project_id: /[^\/]+/}
 describe Projects::CompareController, "routing" do
   it "to #index" do
-    get("/gitlabhq/compare").should route_to('projects/compare#index', project_id: 'gitlabhq')
+    get("/gitlab/gitlabhq/compare").should route_to('projects/compare#index', project_id: 'gitlab/gitlabhq')
   end
 
   it "to #compare" do
-    post("/gitlabhq/compare").should route_to('projects/compare#create', project_id: 'gitlabhq')
+    post("/gitlab/gitlabhq/compare").should route_to('projects/compare#create', project_id: 'gitlab/gitlabhq')
   end
 
   it "to #show" do
-    get("/gitlabhq/compare/master...stable").should     route_to('projects/compare#show', project_id: 'gitlabhq', from: 'master', to: 'stable')
-    get("/gitlabhq/compare/issue/1234...stable").should route_to('projects/compare#show', project_id: 'gitlabhq', from: 'issue/1234', to: 'stable')
+    get("/gitlab/gitlabhq/compare/master...stable").should     route_to('projects/compare#show', project_id: 'gitlab/gitlabhq', from: 'master', to: 'stable')
+    get("/gitlab/gitlabhq/compare/issue/1234...stable").should route_to('projects/compare#show', project_id: 'gitlab/gitlabhq', from: 'issue/1234', to: 'stable')
   end
 end
 
 describe Projects::NetworkController, "routing" do
   it "to #show" do
-    get("/gitlabhq/network/master").should route_to('projects/network#show', project_id: 'gitlabhq', id: 'master')
-    get("/gitlabhq/network/master.json").should route_to('projects/network#show', project_id: 'gitlabhq', id: 'master', format: "json")
+    get("/gitlab/gitlabhq/network/master").should route_to('projects/network#show', project_id: 'gitlab/gitlabhq', id: 'master')
+    get("/gitlab/gitlabhq/network/master.json").should route_to('projects/network#show', project_id: 'gitlab/gitlabhq', id: 'master', format: "json")
   end
 end
 
 describe Projects::GraphsController, "routing" do
   it "to #show" do
-    get("/gitlabhq/graphs/master").should route_to('projects/graphs#show', project_id: 'gitlabhq', id: 'master')
+    get("/gitlab/gitlabhq/graphs/master").should route_to('projects/graphs#show', project_id: 'gitlab/gitlabhq', id: 'master')
   end
 end
diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb
index cc2a141c454e463ff50d6f7e86f9b9ec24bfe13a..946ef7c28cb18de515088701767f9aa4d0cbaa39 100644
--- a/spec/routing/routing_spec.rb
+++ b/spec/routing/routing_spec.rb
@@ -11,11 +11,11 @@ end
 #            /:path       Grack
 describe "Mounted Apps", "routing" do
   it "to API" do
-    get("/api").should be_routable
+    get("/api/issues").should be_routable
   end
 
   it "to Grack" do
-    get("/gitlabhq.git").should be_routable
+    get("/gitlab/gitlabhq.git").should be_routable
   end
 end
 
diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb
index 1f6ee818a42fdca7875fda25f446f9bd6e4583cb..e3c25fa046985d163a1c9624f1208e668edda21c 100644
--- a/spec/services/git_push_service_spec.rb
+++ b/spec/services/git_push_service_spec.rb
@@ -48,7 +48,7 @@ describe GitPushService do
         it { should include(id: @commit.id) }
         it { should include(message: @commit.safe_message) }
         it { should include(timestamp: @commit.date.xmlschema) }
-        it { should include(url: "#{Gitlab.config.gitlab.url}/#{project.code}/commit/#{@commit.id}") }
+        it { should include(url: "#{Gitlab.config.gitlab.url}/#{project.to_param}/commit/#{@commit.id}") }
 
         context "with a author" do
           subject { @push_data[:commits].first[:author] }
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index 6a63a8aceb2c6883e8992fbe5fc5bc8d6e59042d..a112835d4d004afb88ad68bbcbdda652e0dc0bb7 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -52,10 +52,12 @@ describe NotificationService do
 
       before do
         build_team(note.project)
+        note.stub(:commit_author => @u_committer)
       end
 
       describe :new_note do
         it do
+          should_email(@u_committer.id, note)
           should_email(@u_watcher.id, note)
           should_not_email(@u_mentioned.id, note)
           should_not_email(note.author_id, note)
@@ -65,18 +67,14 @@ describe NotificationService do
         end
 
         it do
-          new_note = create(:note_on_commit,
-                 author: @u_participating,
-                 project_id: note.project_id,
-                 commit_id: note.commit_id,
-                 note: '@mention referenced')
-
-          should_email(@u_watcher.id, new_note)
-          should_email(@u_mentioned.id, new_note)
-          should_not_email(new_note.author_id, new_note)
-          should_not_email(@u_participating.id, new_note)
-          should_not_email(@u_disabled.id, new_note)
-          notification.new_note(new_note)
+          note.update_attribute(:note, '@mention referenced')
+          should_email(@u_committer.id, note)
+          should_email(@u_watcher.id, note)
+          should_email(@u_mentioned.id, note)
+          should_not_email(note.author_id, note)
+          should_not_email(@u_participating.id, note)
+          should_not_email(@u_disabled.id, note)
+          notification.new_note(note)
         end
 
         def should_email(user_id, n)
@@ -240,10 +238,12 @@ describe NotificationService do
     @u_participating = create(:user, notification_level: Notification::N_PARTICIPATING)
     @u_disabled = create(:user, notification_level: Notification::N_DISABLED)
     @u_mentioned = create(:user, username: 'mention', notification_level: Notification::N_PARTICIPATING)
+    @u_committer = create(:user, username: 'committer')
 
     project.team << [@u_watcher, :master]
     project.team << [@u_participating, :master]
     project.team << [@u_disabled, :master]
     project.team << [@u_mentioned, :master]
+    project.team << [@u_committer, :master]
   end
 end
diff --git a/spec/services/project_transfer_service_spec.rb b/spec/services/project_transfer_service_spec.rb
index bc26403b7f4607c703baf6195138885c156007d4..109b429967eb612778e11cac6d576e4a55cf44b7 100644
--- a/spec/services/project_transfer_service_spec.rb
+++ b/spec/services/project_transfer_service_spec.rb
@@ -21,25 +21,7 @@ describe ProjectTransferService do
     let(:user) { create(:user) }
     let(:project) { create(:project, namespace: user.namespace) }
 
-    before do
-      @result = service.transfer(project, nil)
-    end
-
-
-    it { @result.should be_true }
-    it { project.namespace.should == nil }
-  end
-
-  context 'no namespace -> namespace' do
-    let(:project) { create(:project) }
-    let(:user) { create(:user) }
-
-    before do
-      @result = service.transfer(project, user.namespace)
-    end
-
-    it { @result.should be_true }
-    it { project.namespace.should == user.namespace }
+    it { lambda{service.transfer(project, nil)}.should raise_error(ActiveRecord::RecordInvalid) }
   end
 
   def service
diff --git a/spec/services/system_hooks_service_spec.rb b/spec/services/system_hooks_service_spec.rb
index 7f1590f559ea097540c86f8be1a37bdf586f4d4a..ebc1ed51d2ede3f116be6f7c869f2a3b6d3d92b1 100644
--- a/spec/services/system_hooks_service_spec.rb
+++ b/spec/services/system_hooks_service_spec.rb
@@ -5,37 +5,29 @@ describe SystemHooksService do
   let (:project)       { create :project }
   let (:users_project) { create :users_project }
 
-  context 'it should build event data' do
-    it 'should build event data for user' do
-      SystemHooksService.build_event_data(user, :create).should include(:event_name, :name, :created_at, :email)
-    end
-
-    it 'should build event data for project' do
-      SystemHooksService.build_event_data(project, :create).should include(:event_name, :name, :created_at, :path, :project_id, :owner_name, :owner_email)
-    end
-
-    it 'should build event data for users project' do
-      SystemHooksService.build_event_data(users_project, :create).should include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :project_access)
-    end
+  context 'event data' do
+    it { event_data(user, :create).should include(:event_name, :name, :created_at, :email, :user_id) }
+    it { event_data(user, :destroy).should include(:event_name, :name, :created_at, :email, :user_id) }
+    it { event_data(project, :create).should include(:event_name, :name, :created_at, :path, :project_id, :owner_name, :owner_email) }
+    it { event_data(project, :destroy).should include(:event_name, :name, :created_at, :path, :project_id, :owner_name, :owner_email) }
+    it { event_data(users_project, :create).should include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :project_access) }
+    it { event_data(users_project, :destroy).should include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :project_access) }
   end
 
-  context 'it should build event names' do
-    it 'should build event names for user' do
-      SystemHooksService.build_event_name(user, :create).should eq "user_create"
-
-      SystemHooksService.build_event_name(user, :destroy).should eq "user_destroy"
-    end
-
-    it 'should build event names for project' do
-      SystemHooksService.build_event_name(project, :create).should eq "project_create"
-
-      SystemHooksService.build_event_name(project, :destroy).should eq "project_destroy"
-    end
+  context 'event names' do
+    it { event_name(user, :create).should eq "user_create" }
+    it { event_name(user, :destroy).should eq "user_destroy" }
+    it { event_name(project, :create).should eq "project_create" }
+    it { event_name(project, :destroy).should eq "project_destroy" }
+    it { event_name(users_project, :create).should eq "user_add_to_team" }
+    it { event_name(users_project, :destroy).should eq "user_remove_from_team" }
+  end
 
-    it 'should build event names for users project' do
-      SystemHooksService.build_event_name(users_project, :create).should eq "user_add_to_team"
+  def event_data(*args)
+    SystemHooksService.build_event_data(*args)
+  end
 
-      SystemHooksService.build_event_name(users_project, :destroy).should eq "user_remove_from_team"
-    end
+  def event_name(*args)
+    SystemHooksService.build_event_name(*args)
   end
 end
diff --git a/spec/support/big_commits.rb b/spec/support/big_commits.rb
new file mode 100644
index 0000000000000000000000000000000000000000..69daa709dd966515db234faef20908f90b9f1013
--- /dev/null
+++ b/spec/support/big_commits.rb
@@ -0,0 +1,8 @@
+module BigCommits
+  HUGE_COMMIT_ID = "7f92534f767fa20357a11c63f973ae3b79cc5b85"
+  HUGE_COMMIT_MESSAGE = "pybments.rb version up. gitignore improved"
+
+  BIG_COMMIT_ID = "d62200cad430565bd9f80befaf329297120330b5"
+  BIG_COMMIT_MESSAGE = "clean-up code"
+end
+