diff --git a/CHANGELOG b/CHANGELOG
index bbd752fb1d04fcb4d3a82d3faed57763a6f7f8ec..67f70e676c2f9ebd28a495217dd7f05f1bc79829 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,9 +1,13 @@
 Please view this file on the master branch, on stable branches it's out of date.
 
 v 8.3.0 (unreleased)
+  - Bump gollum-lib to 4.1.0 (Stan Hu)
+  - Fix broken group avatar upload under "New group" (Stan Hu)
+  - Update project repositorize size and commit count during import:repos task (Stan Hu)
   - Fix API setting of 'public' attribute to false will make a project private (Stan Hu)
   - Handle and report SSL errors in Web hook test (Stan Hu)
   - Fix: Assignee selector is empty when 'Unassigned' is selected (Jose Corcuera)
+  - Add rake tasks for git repository maintainance (Zeger-Jan van de Weg)
   - Fix 500 error when update group member permission
   - Trim leading and trailing whitespace of milestone and issueable titles (Jose Corcuera)
   - Recognize issue/MR/snippet/commit links as references
@@ -18,6 +22,8 @@ v 8.3.0 (unreleased)
   - Fix 500 error when creating a merge request that removes a submodule
   - Run custom Git hooks when branch is created or deleted.
   - Fix bug when simultaneously accepting multiple MRs results in MRs that are of "merged" status, but not merged to the target branch
+  - Add languages page to graphs
+  - Block LDAP user when they are no longer found in the LDAP server
 
 v 8.2.3
   - Fix application settings cache not expiring after changes (Stan Hu)
diff --git a/Gemfile b/Gemfile
index fc4d565fc844e18a9149ae2ed53a71e62406c257..91ad4b6fb4d434d1a9eefe9ba7287e08f0eab170 100644
--- a/Gemfile
+++ b/Gemfile
@@ -52,7 +52,7 @@ gem "gitlab_git", '~> 7.2.20'
 gem 'gitlab_omniauth-ldap', '~> 1.2.1', require: "omniauth-ldap"
 
 # Git Wiki
-gem 'gollum-lib', '~> 4.0.2'
+gem 'gollum-lib', '~> 4.1.0'
 
 # Language detection
 gem "github-linguist", "~> 4.7.0", require: "linguist"
diff --git a/Gemfile.lock b/Gemfile.lock
index 5d70788d9817b561a5e5b83ce6fb23bd62de88b9..3979418ed457a3512e5d492cb6c234dbc43cbda7 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -314,7 +314,7 @@ GEM
       posix-spawn (~> 0.3)
     gitlab_emoji (0.2.0)
       gemojione (~> 2.1)
-    gitlab_git (7.2.20)
+    gitlab_git (7.2.21)
       activesupport (~> 4.0)
       charlock_holmes (~> 0.7.3)
       github-linguist (~> 4.7.0)
@@ -329,11 +329,11 @@ GEM
       activesupport (>= 4.1.0)
     gollum-grit_adapter (1.0.0)
       gitlab-grit (~> 2.7, >= 2.7.1)
-    gollum-lib (4.0.3)
+    gollum-lib (4.1.0)
       github-markup (~> 1.3.3)
       gollum-grit_adapter (~> 1.0)
       nokogiri (~> 1.6.4)
-      rouge (~> 1.10.1)
+      rouge (~> 1.9)
       sanitize (~> 2.1.0)
       stringex (~> 2.5.1)
     gon (6.0.1)
@@ -884,7 +884,7 @@ DEPENDENCIES
   gitlab_git (~> 7.2.20)
   gitlab_meta (= 7.0)
   gitlab_omniauth-ldap (~> 1.2.1)
-  gollum-lib (~> 4.0.2)
+  gollum-lib (~> 4.1.0)
   gon (~> 6.0.1)
   grape (~> 0.13.0)
   grape-entity (~> 0.4.2)
diff --git a/app/assets/javascripts/api.js.coffee b/app/assets/javascripts/api.js.coffee
index 9e5d594c861d6867308d9c47b571795fe5f51efd..746fa3cea871322fe7f5b42d15197107391bab39 100644
--- a/app/assets/javascripts/api.js.coffee
+++ b/app/assets/javascripts/api.js.coffee
@@ -2,6 +2,8 @@
   groups_path: "/api/:version/groups.json"
   group_path: "/api/:version/groups/:id.json"
   namespaces_path: "/api/:version/namespaces.json"
+  group_projects_path: "/api/:version/groups/:id/projects.json"
+  projects_path: "/api/:version/projects.json"
 
   group: (group_id, callback) ->
     url = Api.buildUrl(Api.group_path)
@@ -44,6 +46,35 @@
     ).done (namespaces) ->
       callback(namespaces)
 
+  # Return projects list. Filtered by query
+  projects: (query, callback) ->
+    url = Api.buildUrl(Api.projects_path)
+
+    $.ajax(
+      url: url
+      data:
+        private_token: gon.api_token
+        search: query
+        per_page: 20
+      dataType: "json"
+    ).done (projects) ->
+      callback(projects)
+
+  # Return group projects list. Filtered by query
+  groupProjects: (group_id, query, callback) ->
+    url = Api.buildUrl(Api.group_projects_path)
+    url = url.replace(':id', group_id)
+
+    $.ajax(
+      url: url
+      data:
+        private_token: gon.api_token
+        search: query
+        per_page: 20
+      dataType: "json"
+    ).done (projects) ->
+      callback(projects)
+
   buildUrl: (url) ->
     url = gon.relative_url_root + url if gon.relative_url_root?
     return url.replace(':version', gon.api_version)
diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee
index 4059fc39c67b5d20c2c58e7cfb59b4048f8b836e..599b4c4954001823ebd5a7a77a01bac97069b28e 100644
--- a/app/assets/javascripts/dispatcher.js.coffee
+++ b/app/assets/javascripts/dispatcher.js.coffee
@@ -83,7 +83,7 @@ class Dispatcher
       when 'projects:project_members:index'
         new ProjectMembers()
         new UsersSelect()
-      when 'groups:new', 'groups:edit', 'admin:groups:edit'
+      when 'groups:new', 'groups:edit', 'admin:groups:edit', 'admin:groups:new'
         new GroupAvatar()
       when 'projects:tree:show'
         new TreeView()
diff --git a/app/assets/javascripts/new_commit_form.js.coffee b/app/assets/javascripts/new_commit_form.js.coffee
index 2e561dea3e1eafe8a52f0bba807d36d8040d2fec..3c7b776155fb2929da92df64237075e0bff6bc52 100644
--- a/app/assets/javascripts/new_commit_form.js.coffee
+++ b/app/assets/javascripts/new_commit_form.js.coffee
@@ -3,7 +3,7 @@ class @NewCommitForm
     @newBranch = form.find('.js-new-branch')
     @originalBranch = form.find('.js-original-branch')
     @createMergeRequest = form.find('.js-create-merge-request')
-    @createMergeRequestFormGroup = form.find('.js-create-merge-request-form-group')
+    @createMergeRequestContainer = form.find('.js-create-merge-request-container')
 
     @renderDestination()
     @newBranch.keyup @renderDestination
@@ -12,10 +12,10 @@ class @NewCommitForm
     different = @newBranch.val() != @originalBranch.val()
 
     if different
-      @createMergeRequestFormGroup.show()
+      @createMergeRequestContainer.show()
       @createMergeRequest.prop('checked', true) unless @wasDifferent
     else
-      @createMergeRequestFormGroup.hide()
+      @createMergeRequestContainer.hide()
       @createMergeRequest.prop('checked', false)
 
     @wasDifferent = different
diff --git a/app/assets/javascripts/project_select.js.coffee b/app/assets/javascripts/project_select.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..0ae274f33632dc71ca5862ec68c18971b94d9525
--- /dev/null
+++ b/app/assets/javascripts/project_select.js.coffee
@@ -0,0 +1,39 @@
+class @ProjectSelect
+  constructor: ->
+    $('.ajax-project-select').each (i, select) ->
+      @groupId = $(select).data('group-id')
+      @includeGroups = $(select).data('include-groups')
+
+      placeholder = "Search for project"
+      placeholder += " or group" if @includeGroups
+
+      $(select).select2
+        placeholder: placeholder
+        minimumInputLength: 0
+        query: (query) =>
+          finalCallback = (projects) ->
+            data = { results: projects }
+            query.callback(data)
+
+          if @includeGroups
+            projectsCallback = (projects) ->
+              groupsCallback = (groups) ->
+                data = groups.concat(projects)
+                finalCallback(data)
+
+              Api.groups query.term, false, groupsCallback
+          else
+            projectsCallback = finalCallback
+
+          if @groupId
+            Api.groupProjects @groupId, query.term, projectsCallback
+          else
+            Api.projects query.term, projectsCallback
+
+        id: (project) ->
+          project.web_url
+
+        text: (project) ->
+          project.name_with_namespace || project.name
+
+        dropdownCssClass: "ajax-project-dropdown"
diff --git a/app/assets/stylesheets/framework/callout.scss b/app/assets/stylesheets/framework/callout.scss
index f3ce4e3c2194787cb02a06785283718a66396ea1..20a9bfb9816b3222d64c5d21aaeb99c008698ec7 100644
--- a/app/assets/stylesheets/framework/callout.scss
+++ b/app/assets/stylesheets/framework/callout.scss
@@ -7,8 +7,8 @@
 
 /* Common styles for all types */
 .bs-callout {
-  margin: 20px 0;
-  padding: 20px;
+  margin: $gl-padding 0;
+  padding: $gl-padding;
   border-left: 3px solid $border-color;
   color: $text-color;
   background: $background-color;
@@ -42,4 +42,3 @@
   border-color: #5cA64d;
   color: #3c763d;
 }
-
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index d2f491daf789133ff1694d1bd79a74088accbc59..2e8515668f6609abba27b14069e20b1f3c6f93f8 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -333,7 +333,7 @@ table {
 }
 
 .well {
-  margin-bottom: 0;
+  margin-bottom: $gl-padding;
 }
 
 .search_box {
@@ -379,9 +379,8 @@ table {
   text-align: center;
   margin-top: 5px;
   margin-bottom: $gl-padding;
-  height: 56px;
+  height: auto;
   margin-top: -$gl-padding;
-  padding-top: $gl-padding;
 
   &.no-bottom {
     margin-bottom: 0;
@@ -390,6 +389,18 @@ table {
   &.no-top {
     margin-top: 0;
   }
+
+  li a {
+    display: inline-block;
+    padding-top: $gl-padding;
+    padding-bottom: 11px;
+    margin-bottom: -1px;
+  }
+
+  &.bottom-border {
+    border-bottom: 1px solid $border-color;
+    height: 57px;
+  }
 }
 
 .center-middle-menu {
@@ -437,3 +448,16 @@ table {
 .alert, .progress {
   margin-bottom: $gl-padding;
 }
+
+.new-project-item-select-holder {
+  display: inline-block;
+  position: relative;
+
+  .new-project-item-select {
+    position: absolute;
+    top: 0;
+    right: 0;
+    width: 250px !important;
+    visibility: hidden;
+  }
+}
diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss
index 6bf2857e83a291f3c4c4a128e82b3c5a4d16eb3c..cbfd4bc29b636fdde456116b7f970c0aea75e7d2 100644
--- a/app/assets/stylesheets/framework/files.scss
+++ b/app/assets/stylesheets/framework/files.scss
@@ -21,7 +21,6 @@
     position: relative;
     background: $background-color;
     border-bottom: 1px solid $border-color;
-    text-shadow: 0 1px 1px #fff;
     margin: 0;
     text-align: left;
     padding: 10px $gl-padding;
diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss
index a798ae812e3bbd73d5853877fe116e1ae1570d0c..927641216e454151e786a24db1b7a66d344beb04 100644
--- a/app/assets/stylesheets/framework/lists.scss
+++ b/app/assets/stylesheets/framework/lists.scss
@@ -72,13 +72,6 @@
   }
 }
 
-ol, ul {
-  &.styled {
-    li {
-      padding: 2px;
-    }
-  }
-}
 
 /** light list with border-bottom between li **/
 ul.bordered-list {
diff --git a/app/assets/stylesheets/framework/mobile.scss b/app/assets/stylesheets/framework/mobile.scss
index cea47fba19226c8ba688f5f9882c44a7b7a29549..6f44c323732325d73eed22088c5ee1f8c43883b7 100644
--- a/app/assets/stylesheets/framework/mobile.scss
+++ b/app/assets/stylesheets/framework/mobile.scss
@@ -82,9 +82,6 @@
   }
 
   .center-top-menu {
-    height: 45px;
-    margin-bottom: 30px;
-
     li a {
       font-size: 14px;
       padding: 19px 10px;
diff --git a/app/assets/stylesheets/framework/panels.scss b/app/assets/stylesheets/framework/panels.scss
index 406aff3d72cffaf9325e9f1259f81a196a7098fa..61053aff91a27185066b1aee3b65bd32f765dddd 100644
--- a/app/assets/stylesheets/framework/panels.scss
+++ b/app/assets/stylesheets/framework/panels.scss
@@ -1,9 +1,11 @@
 .panel {
   margin-bottom: $gl-padding;
-  
+
   .panel-heading {
-    padding: 10px $gl-padding;
+    padding: 7px $gl-padding;
+    line-height: 42px !important;
   }
+
   .panel-body {
     padding: $gl-padding;
 
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
index aef338cfa568f2e5dae0007424010710a0671e05..c3e4ad0ad0039317a6a099ed988936f783473e9f 100644
--- a/app/assets/stylesheets/framework/typography.scss
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -220,6 +220,7 @@ pre {
 
 .monospace {
   font-family: $monospace_font;
+  font-size: 90%;
 }
 
 code {
diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss
index da9965f007af1e409d432381dc49b728cdde31bb..3c2997c1d5adc11330a4db8794abbdea1736e962 100644
--- a/app/assets/stylesheets/pages/builds.scss
+++ b/app/assets/stylesheets/pages/builds.scss
@@ -67,9 +67,4 @@
       color: #3084bb !important;
     }
   }
-
-  .build-top-menu {
-    margin-top: 0;
-    margin-bottom: 2px;
-  }
 }
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index ab7df978768787c19933e51f08cc9e94f124d489..7ab93bdb95a03cae4dff5cbaeb06091a9f48bd5f 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -140,7 +140,7 @@
   font-family: $monospace_font;
   font-weight: bold;
   overflow: hidden;
-  font-size: 14px;
+  font-size: 90%;
   margin: 0 3px;
 }
 
diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss
index 1d6ca0dfc1302663afdd50099bf7cf78a974aa7b..95fc26a608a70c6f65600965cd153937c8ad6675 100644
--- a/app/assets/stylesheets/pages/profile.scss
+++ b/app/assets/stylesheets/pages/profile.scss
@@ -5,12 +5,6 @@
   }
 }
 
-.btn-build-token {
-  float: left;
-  padding: 6px 20px;
-  margin-right: 12px;
-}
-
 .profile-avatar-form-option {
   hr {
     margin: 10px 0;
diff --git a/app/assets/stylesheets/pages/ui_dev_kit.scss b/app/assets/stylesheets/pages/ui_dev_kit.scss
index 277afa1db9e5cce2fea4627a381afae859a8f6a1..185f3622e6474475d96c0c46ad706b224f86b62f 100644
--- a/app/assets/stylesheets/pages/ui_dev_kit.scss
+++ b/app/assets/stylesheets/pages/ui_dev_kit.scss
@@ -1,9 +1,6 @@
 .gitlab-ui-dev-kit {
   > h2 {
-    font-size: 27px;
-    border-bottom: 1px solid #CCC;
-    color: #666;
-    margin: 30px 0;
+    margin: 35px 0 20px;
     font-weight: bold;
   }
 }
diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb
index d3f926b62bcdaabdfaa9ddb37864c56aeba78a44..c2aaf094e689fda389b79ee713e2a8c68a27ddb2 100644
--- a/app/controllers/projects/application_controller.rb
+++ b/app/controllers/projects/application_controller.rb
@@ -28,7 +28,7 @@ class Projects::ApplicationController < ApplicationController
 
   private
 
-  def ci_enabled
+  def builds_enabled
     return render_404 unless @project.builds_enabled?
   end
 
diff --git a/app/controllers/projects/graphs_controller.rb b/app/controllers/projects/graphs_controller.rb
index 418b92040bcfc2c84222ffb8f9c9634624e160d9..a8f47069bb49768df85c115aa165947a32c44b2d 100644
--- a/app/controllers/projects/graphs_controller.rb
+++ b/app/controllers/projects/graphs_controller.rb
@@ -5,7 +5,7 @@ class Projects::GraphsController < Projects::ApplicationController
   before_action :require_non_empty_project
   before_action :assign_ref_vars
   before_action :authorize_download_code!
-  before_action :ci_enabled, only: :ci
+  before_action :builds_enabled, only: :ci
 
   def show
     respond_to do |format|
@@ -34,6 +34,26 @@ class Projects::GraphsController < Projects::ApplicationController
     @charts[:build_times] = Ci::Charts::BuildTime.new(ci_project)
   end
 
+  def languages
+    @languages = Linguist::Repository.new(@repository.rugged, @repository.rugged.head.target_id).languages
+    total = @languages.map(&:last).sum
+
+    @languages = @languages.map do |language|
+      name, share = language
+      color = Digest::SHA256.hexdigest(name)[0...6]
+      {
+        value: (share.to_f * 100 / total).round(2),
+        label: name,
+        color: "##{color}",
+        highlight: "##{color}"
+      }
+    end
+
+    @languages.sort! do |x, y|
+      y[:value] <=> x[:value]
+    end
+  end
+
   private
 
   def fetch_graph
diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb
index d5ee6ac8663b24aadaa88818becf516764454741..be7d5c187feae79d67fd6d24e8b032030b35ca8f 100644
--- a/app/controllers/projects/raw_controller.rb
+++ b/app/controllers/projects/raw_controller.rb
@@ -10,15 +10,13 @@ class Projects::RawController < Projects::ApplicationController
     @blob = @repository.blob_at(@commit.id, @path)
 
     if @blob
-      type = get_blob_type
-
       headers['X-Content-Type-Options'] = 'nosniff'
 
-      send_data(
-        @blob.data,
-        type: type,
-        disposition: 'inline'
-      )
+      if @blob.lfs_pointer?
+        send_lfs_object
+      else
+        stream_data
+      end
     else
       render_404
     end
@@ -35,4 +33,33 @@ class Projects::RawController < Projects::ApplicationController
       'application/octet-stream'
     end
   end
+
+  def stream_data
+    type = get_blob_type
+
+    send_data(
+      @blob.data,
+      type: type,
+      disposition: 'inline'
+    )
+  end
+
+  def send_lfs_object
+    lfs_object = find_lfs_object
+
+    if lfs_object && lfs_object.project_allowed_access?(@project)
+      send_file lfs_object.file.path, filename: @blob.name, disposition: 'attachment'
+    else
+      render_404
+    end
+  end
+
+  def find_lfs_object
+    lfs_object = LfsObject.find_by_oid(@blob.lfs_oid)
+    if lfs_object && lfs_object.file.exists?
+      lfs_object
+    else
+      nil
+    end
+  end
 end
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index df5f5fae23cbcb8305768a185273f9548075b8d1..4a3d971f7c6a164db6a51978d5b80919e1471436 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -30,7 +30,7 @@ module BlobHelper
         nil
       end
 
-    if blob && blob.text?
+    if blob_viewable?(blob)
       text = 'Edit'
       after = options[:after] || ''
       from_mr = options[:from_merge_request_id]
@@ -71,4 +71,16 @@ module BlobHelper
   def blob_icon(mode, name)
     icon("#{file_type_icon_class('file', mode, name)} fw")
   end
+
+  def blob_viewable?(blob)
+    blob && blob.text? && !blob.lfs_pointer?
+  end
+
+  def blob_size(blob)
+    if blob.lfs_pointer?
+      blob.lfs_size
+    else
+      blob.size
+    end
+  end
 end
diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb
index 0ecf77bb45ee99052bb664d631f19bdffa462c83..70f8c9ae22168fb5d1cb594e2c70ce85c1665d6d 100644
--- a/app/helpers/ci_status_helper.rb
+++ b/app/helpers/ci_status_helper.rb
@@ -8,6 +8,10 @@ module CiStatusHelper
     ci_icon_for_status(ci_commit.status)
   end
 
+  def ci_status_label(ci_commit)
+    ci_label_for_status(ci_commit.status)
+  end
+
   def ci_status_color(ci_commit)
     case ci_commit.status
     when 'success'
@@ -23,7 +27,15 @@ module CiStatusHelper
 
   def ci_status_with_icon(status)
     content_tag :span, class: "ci-status ci-#{status}" do
-      ci_icon_for_status(status) + '&nbsp;'.html_safe + status
+      ci_icon_for_status(status) + '&nbsp;'.html_safe + ci_label_for_status(status)
+    end
+  end
+
+  def ci_label_for_status(status)
+    if status == 'success'
+      'passed'
+    else
+      status
     end
   end
 
@@ -46,7 +58,7 @@ module CiStatusHelper
   def render_ci_status(ci_commit)
     link_to ci_status_path(ci_commit),
       class: "c#{ci_status_color(ci_commit)}",
-      title: "Build status: #{ci_commit.status}",
+      title: "Build status: #{ci_status_label(ci_commit)}",
       data: { toggle: 'tooltip', placement: 'left' } do
       ci_status_icon(ci_commit)
     end
diff --git a/app/helpers/page_layout_helper.rb b/app/helpers/page_layout_helper.rb
index 775cf5a3dd4d2dc119bffc629a4c4f988a4605b4..9bf750124b25085361aafff6c982916ef10a2c27 100644
--- a/app/helpers/page_layout_helper.rb
+++ b/app/helpers/page_layout_helper.rb
@@ -4,7 +4,8 @@ module PageLayoutHelper
 
     @page_title.push(*titles.compact) if titles.any?
 
-    @page_title.join(" | ")
+    # Segments are seperated by middot
+    @page_title.join(" \u00b7 ")
   end
 
   def header_title(title = nil, title_url = nil)
diff --git a/app/helpers/selects_helper.rb b/app/helpers/selects_helper.rb
index 7e175d0de8a7cfa7b3c3f195c78f983abbc93dcf..05386d790ca887ba4c465b5f0ebcd846d7245c35 100644
--- a/app/helpers/selects_helper.rb
+++ b/app/helpers/selects_helper.rb
@@ -48,6 +48,19 @@ module SelectsHelper
     select2_tag(id, opts)
   end
 
+  def project_select_tag(id, opts = {})
+    opts[:class] ||= ''
+    opts[:class] << ' ajax-project-select'
+
+    unless opts.delete(:scope) == :all
+      if @group
+        opts['data-group-id'] = @group.id
+      end
+    end
+
+    hidden_field_tag(id, opts[:selected], opts)
+  end
+
   def select2_tag(id, opts = {})
     css_class = ''
     css_class << 'multiselect ' if opts[:multiple]
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index 03a49e119b8441210e89c526f72a8fbdc46342cf..6afa1aacc5b0a488e84ff2fcec20f8ab018f1b83 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -54,6 +54,10 @@ module TreeHelper
     ::Gitlab::GitAccess.new(current_user, project).can_push_to_branch?(ref)
   end
 
+  def can_delete_or_replace?(blob)
+    allowed_tree_edit? && !blob.lfs_pointer?
+  end
+
   def tree_breadcrumbs(tree, max_links = 2)
     if @path.present?
       part_path = ""
diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb
index 971e899de847b6c6a5043c4f37d3404e080dd628..cb90b0de63d28dd3a94c4408144da99af3da4676 100644
--- a/app/models/ci/commit.rb
+++ b/app/models/ci/commit.rb
@@ -199,7 +199,7 @@ module Ci
     end
 
     def ci_yaml_file
-      gl_project.repository.blob_at(sha, '.gitlab-ci.yml').data
+      @ci_yaml_file ||= gl_project.repository.blob_at(sha, '.gitlab-ci.yml').data
     rescue
       nil
     end
diff --git a/app/models/lfs_object.rb b/app/models/lfs_object.rb
index 3c1426f59d08c085e17e92fdc0d8dc0a94af9e99..18657c3e1c893e68dbc5ad215b56a0f7fe3c48c6 100644
--- a/app/models/lfs_object.rb
+++ b/app/models/lfs_object.rb
@@ -5,4 +5,16 @@ class LfsObject < ActiveRecord::Base
   validates :oid, presence: true, uniqueness: true
 
   mount_uploader :file, LfsObjectUploader
+
+  def storage_project(project)
+    if project && project.forked?
+      storage_project(project.forked_from_project)
+    else
+      project
+    end
+  end
+
+  def project_allowed_access?(project)
+    projects.exists?(storage_project(project).id)
+  end
 end
diff --git a/app/views/dashboard/_projects_head.html.haml b/app/views/dashboard/_projects_head.html.haml
index 991e67b1cd3987bee9d4c8e26c1a0676fffa4708..2e77afb7525923d48e085aaaf47d61cc39c1e781 100644
--- a/app/views/dashboard/_projects_head.html.haml
+++ b/app/views/dashboard/_projects_head.html.haml
@@ -2,7 +2,7 @@
   = render 'shared/project_limit'
 
 %ul.center-top-menu
-  = nav_link(path: ['projects#index', 'root#index']) do
+  = nav_link(page: [dashboard_projects_path, root_path]) do
     = link_to dashboard_projects_path, title: 'Home', class: 'shortcuts-activity', data: {placement: 'right'} do
       Your Projects
   = nav_link(page: starred_dashboard_projects_path) do
diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml
index cd602e897b7f0809034389d3bf34ef4af9b32f94..2d3da01178a0a6adf4b353e85333e30f3b8858e1 100644
--- a/app/views/dashboard/issues.html.haml
+++ b/app/views/dashboard/issues.html.haml
@@ -4,14 +4,20 @@
   - if current_user
     = auto_discovery_link_tag(:atom, issues_dashboard_url(format: :atom, private_token: current_user.private_token), title: "#{current_user.name} issues")
 
+.project-issuable-filter
+  .controls
+    .pull-left
+      - if current_user
+        .hidden-xs.pull-left
+          = link_to issues_dashboard_url(format: :atom, private_token: current_user.private_token), class: 'btn' do
+            %i.fa.fa-rss
 
-.append-bottom-20
-  .pull-right
-    - if current_user
-      .hidden-xs.pull-left.prepend-top-20
-        = link_to issues_dashboard_url(format: :atom, private_token: current_user.private_token), class: '' do
-          %i.fa.fa-rss
+    = render 'shared/new_project_item_select', path: 'issues/new', label: "New Issue"
 
   = render 'shared/issuable/filter', type: :issues
 
-= render 'shared/issues'
+.gray-content-block.second-block
+  List all issues from all projects you have access to.
+
+.prepend-top-default
+  = render 'shared/issues'
diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml
index d1f332fa0d3ad3fd4b32ec032ff199ab58595a1c..c5a5ec21f78aa35e3b0f2501cd88cfae96ac2e97 100644
--- a/app/views/dashboard/merge_requests.html.haml
+++ b/app/views/dashboard/merge_requests.html.haml
@@ -1,6 +1,14 @@
 - page_title "Merge Requests"
 - header_title  "Merge Requests", merge_requests_dashboard_path(assignee_id: current_user.id)
 
-.append-bottom-20
+.project-issuable-filter
+  .controls
+    = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New Merge Request"
+
   = render 'shared/issuable/filter', type: :merge_requests
-= render 'shared/merge_requests'
+
+.gray-content-block.second-block
+  List all merge requests from all projects you have access to.
+
+.prepend-top-default
+  = render 'shared/merge_requests'
diff --git a/app/views/dashboard/milestones/index.html.haml b/app/views/dashboard/milestones/index.html.haml
index 635251e2374e82ceed3bc9b4a31b80489a9fe4b8..bec1692a4dedda7647d8ed053a1c1d04914fb227 100644
--- a/app/views/dashboard/milestones/index.html.haml
+++ b/app/views/dashboard/milestones/index.html.haml
@@ -1,12 +1,14 @@
 - page_title "Milestones"
-- header_title  "Milestones", dashboard_milestones_path
+- header_title "Milestones", dashboard_milestones_path
 
+.project-issuable-filter
+  .controls
+    = render 'shared/new_project_item_select', path: 'milestones/new', label: "New Milestone", include_groups: true
 
-= render 'shared/milestones_filter'
+  = render 'shared/milestones_filter'
 
 .gray-content-block
-  .oneline
-    List all milestones from all projects you have access to.
+  List all milestones from all projects you have access to.
 
 .milestones
   %ul.content-list
diff --git a/app/views/groups/issues.html.haml b/app/views/groups/issues.html.haml
index 08d97e418a334083bb0ca55f9424103d035759e0..90ade1e1680b07b60b9063e75ab2afd17d9f8620 100644
--- a/app/views/groups/issues.html.haml
+++ b/app/views/groups/issues.html.haml
@@ -4,21 +4,24 @@
   - if current_user
     = auto_discovery_link_tag(:atom, issues_group_url(@group, format: :atom, private_token: current_user.private_token), title: "#{@group.name} issues")
 
+.project-issuable-filter
+  .controls
+    .pull-left
+      - if current_user
+        .hidden-xs.pull-left
+          = link_to issues_group_url(@group, format: :atom, private_token: current_user.private_token), class: 'btn' do
+            %i.fa.fa-rss
 
+    = render 'shared/new_project_item_select', path: 'issues/new', label: "New Issue"
+
+  = render 'shared/issuable/filter', type: :issues
 
-= render 'shared/issuable/filter', type: :issues
 .gray-content-block.second-block
-  .pull-right
-    - if current_user
-      .hidden-xs.pull-left
-        = link_to issues_group_url(@group, format: :atom, private_token: current_user.private_token) do
-          %i.fa.fa-rss
-  %div
-    Only issues from
-    %strong #{@group.name}
-    group are listed here.
-    - if current_user
-      To see all issues you should visit #{link_to 'dashboard', issues_dashboard_path} page.
+  Only issues from
+  %strong #{@group.name}
+  group are listed here.
+  - if current_user
+    To see all issues you should visit #{link_to 'dashboard', issues_dashboard_path} page.
 
 .prepend-top-default
   = render 'shared/issues'
diff --git a/app/views/groups/merge_requests.html.haml b/app/views/groups/merge_requests.html.haml
index 425ad8331bffb6228a5f4e8f2d8970e499aae712..f662f5a8c17e2fd72c9350297604321babe93fd4 100644
--- a/app/views/groups/merge_requests.html.haml
+++ b/app/views/groups/merge_requests.html.haml
@@ -1,13 +1,18 @@
 - page_title "Merge Requests"
 - header_title group_title(@group, "Merge Requests", merge_requests_group_path(@group))
 
-= render 'shared/issuable/filter', type: :merge_requests
+.project-issuable-filter
+  .controls
+    = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New Merge Request"
+
+  = render 'shared/issuable/filter', type: :merge_requests
+
 .gray-content-block.second-block
-  %div
-    Only merge requests from
-    %strong #{@group.name}
-    group are listed here.
-    - if current_user
-      To see all merge requests you should visit #{link_to 'dashboard', merge_requests_dashboard_path} page.
+  Only merge requests from
+  %strong #{@group.name}
+  group are listed here.
+  - if current_user
+    To see all merge requests you should visit #{link_to 'dashboard', merge_requests_dashboard_path} page.
+
 .prepend-top-default
   = render 'shared/merge_requests'
diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml
index 84ec77c61888e082a057a9e6e74230bf8520e416..b221d3a89a4a5654b46f6ad50b4555da30f2a1e7 100644
--- a/app/views/groups/milestones/index.html.haml
+++ b/app/views/groups/milestones/index.html.haml
@@ -1,18 +1,22 @@
 - page_title "Milestones"
 - header_title group_title(@group, "Milestones", group_milestones_path(@group))
 
-= render 'shared/milestones_filter'
+.project-issuable-filter
+  .controls
+    - if can?(current_user, :admin_milestones, @group)
+      .pull-right
+        %span.pull-right.hidden-xs
+          = link_to new_group_milestone_path(@group), class: "btn btn-new" do
+            = icon('plus')
+            New Milestone
+
+  = render 'shared/milestones_filter'
+
 .gray-content-block
-  - if can?(current_user, :admin_milestones, @group)
-    .pull-right
-      %span.pull-right.hidden-xs
-        = link_to new_group_milestone_path(@group), class: "btn btn-new" do
-          New Milestone
+  Only milestones from
+  %strong #{@group.name}
+  group are listed here.
 
-  .oneline
-    Only milestones from
-    %strong #{@group.name}
-    group are listed here.
 .milestones
   %ul.content-list
     - if @milestones.blank?
diff --git a/app/views/help/ui.html.haml b/app/views/help/ui.html.haml
index 2169a821fb24c6fc22c7c6a01224430d82726610..d9ffda884c8c56663721fa1f568365b7d293829e 100644
--- a/app/views/help/ui.html.haml
+++ b/app/views/help/ui.html.haml
@@ -31,11 +31,9 @@
 
   %h2#blocks Blocks
 
-  %h3
+  %h4
     %code .gray-content-block
 
-
-
   .gray-content-block.middle-block
     %h4 Normal block inside content
     = lorem
@@ -45,9 +43,28 @@
     = lorem
 
 
+  %h4
+    %code .cover-block
+  %br
+  .cover-block
+    .avatar-holder
+      = image_tag avatar_icon('admin@example.com', 90), class: "avatar s90", alt: ''
+    .cover-title
+      John Smith
+
+    .cover-desc
+      = lorem
+
+    .cover-controls
+      = link_to '#', class: 'btn btn-gray' do
+        = icon('pencil')
+      &nbsp;
+      = link_to '#', class: 'btn btn-gray' do
+        = icon('rss')
+
   %h2#lists Lists
 
-  %h3
+  %h4
     %code .content-list
   %ul.content-list
     %li
@@ -57,7 +74,7 @@
     %li
       One item
 
-  %h3
+  %h4
     %code .well-list
   %ul.well-list
     %li
@@ -67,7 +84,7 @@
     %li
       One item
 
-  %h3
+  %h4
     %code .panel .well-list
 
   .panel.panel-default
@@ -80,7 +97,7 @@
       %li
         One item
 
-  %h3
+  %h4
     %code .bordered-list
   %ul.bordered-list
     %li
@@ -121,7 +138,7 @@
 
   %h2#navs Navigation
 
-  %h3
+  %h4
     %code .center-top-menu
   .example
     %ul.center-top-menu
@@ -130,7 +147,7 @@
       %li
         %a Closed
 
-  %h3
+  %h4
     %code .btn-group.btn-group-next
   .example
     %div.btn-group.btn-group-next
@@ -138,7 +155,7 @@
       %a.btn Closed
 
 
-  %h3
+  %h4
     %code .nav.nav-tabs
   .example
     %ul.nav.nav-tabs
@@ -204,7 +221,7 @@
 
   %h2#forms Forms
 
-  %h3
+  %h4
     %code form.horizontal-form
 
   %form.form-horizontal
@@ -226,7 +243,7 @@
       .col-sm-offset-2.col-sm-10
         %button.btn.btn-default{:type => "submit"} Sign in
 
-  %h3
+  %h4
     %code form
 
   %form
@@ -243,7 +260,7 @@
     %button.btn.btn-default{:type => "submit"} Sign in
 
   %h2#file File
-  %h3
+  %h4
     %code .file-holder
 
   - blob = Snippet.new(content: "Wow\nSuch\nFile")
@@ -254,13 +271,12 @@
         .file-actions
           .btn-group
             %a.btn Edit
-            %a.btn Remove
+            %a.btn.btn-danger Remove
       .file-contenta.code
         = render 'shared/file_highlight', blob: blob
 
-
   %h2#markdown Markdown
-  %h3
+  %h4
     %code .md or .wiki and others
 
   Markdown rendering has a bit different css and presented in next UI elements:
diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml
index 319bdd57c39a5091a56ef5758f4b337913e8037d..17e47c622ceec6d1645f6cda4cd60f3e926d1519 100644
--- a/app/views/profiles/accounts/show.html.haml
+++ b/app/views/profiles/accounts/show.html.haml
@@ -26,11 +26,11 @@
             - else
               %span You don`t have one yet. Click generate to fix it.
 
-          .form-actions
-            - if current_user.private_token
-              = f.submit 'Reset private token', data: { confirm: "Are you sure?" }, class: "btn btn-default btn-build-token"
-            - else
-              = f.submit 'Generate', class: "btn btn-default btn-build-token"
+        .form-actions
+          - if current_user.private_token
+            = f.submit 'Reset private token', data: { confirm: "Are you sure?" }, class: "btn btn-default"
+          - else
+            = f.submit 'Generate', class: "btn btn-default"
 
   - unless current_user.ldap_user?
     .panel.panel-default
diff --git a/app/views/profiles/keys/new.html.haml b/app/views/profiles/keys/new.html.haml
index 2bf207a322161b7f2e2e5864a1083aee1e5a28ef..11166dc6d9985e4b626289a4e28b09c817533c78 100644
--- a/app/views/profiles/keys/new.html.haml
+++ b/app/views/profiles/keys/new.html.haml
@@ -9,7 +9,7 @@
   $('#key_key').on('focusout', function(){
     var title = $('#key_title'),
         val      = $('#key_key').val(),
-        comment = val.match(/^\S+ \S+ (.+)$/);
+        comment = val.match(/^\S+ \S+ (.+)\n?$/);
 
     if( comment && comment.length > 1 && title.val() == '' ){
       $('#key_title').val( comment[1] );
diff --git a/app/views/projects/_last_commit.html.haml b/app/views/projects/_last_commit.html.haml
index 7e1ee2b7fc1ab92aa0c46a0f60d45528a016e883..386d72e77872333baab57b66ac26386bb24bcbd1 100644
--- a/app/views/projects/_last_commit.html.haml
+++ b/app/views/projects/_last_commit.html.haml
@@ -3,7 +3,7 @@
   - if ci_commit
     = link_to ci_status_path(ci_commit), class: "ci-status ci-#{ci_commit.status}" do
       = ci_status_icon(ci_commit)
-      = ci_commit.status
+      = ci_status_label(ci_commit)
 
   = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id"
   = link_to_gfm commit.title, namespace_project_commit_path(project.namespace, project, commit), class: "commit-row-message"
diff --git a/app/views/projects/blob/_actions.html.haml b/app/views/projects/blob/_actions.html.haml
index ba3e0c3c590b1759c8a68f40be3bc106adf52b98..0e54e59e953aa3128e16f2df7bfe2d55bfeebe2f 100644
--- a/app/views/projects/blob/_actions.html.haml
+++ b/app/views/projects/blob/_actions.html.haml
@@ -3,7 +3,7 @@
   = link_to 'Raw', namespace_project_raw_path(@project.namespace, @project, @id),
       class: 'btn btn-sm', target: '_blank'
   -# only show normal/blame view links for text files
-  - if @blob.text?
+  - if blob_viewable?(@blob)
     - if current_page? namespace_project_blame_path(@project.namespace, @project, @id)
       = link_to 'Normal View', namespace_project_blob_path(@project.namespace, @project, @id),
           class: 'btn btn-sm'
@@ -16,7 +16,7 @@
     = link_to 'Permalink', namespace_project_blob_path(@project.namespace, @project,
         tree_join(@commit.sha, @path)), class: 'btn btn-sm'
 
-- if allowed_tree_edit?
+- if can_delete_or_replace?(@blob)
   .btn-group{ role: "group" }
     %button.btn.btn-default{ 'data-target' => '#modal-upload-blob', 'data-toggle' => 'modal' } Replace
     %button.btn.btn-remove{ 'data-target' => '#modal-remove-blob', 'data-toggle' => 'modal' } Delete
diff --git a/app/views/projects/blob/_blob.html.haml b/app/views/projects/blob/_blob.html.haml
index 42f632b38efea9748a4cf361a96750bab1a46fab..2a3315da3dbffa54200168ea6b7801a8a316860e 100644
--- a/app/views/projects/blob/_blob.html.haml
+++ b/app/views/projects/blob/_blob.html.haml
@@ -29,10 +29,12 @@
       %strong
         = blob.name
       %small
-        = number_to_human_size(blob.size)
+        = number_to_human_size(blob_size(blob))
       .file-actions.hidden-xs
         = render "actions"
-    - if blob.text?
+    - if blob.lfs_pointer?
+      = render "download", blob: blob
+    - elsif blob.text?
       = render "text", blob: blob
     - elsif blob.image?
       = render "image", blob: blob
diff --git a/app/views/projects/blob/_download.html.haml b/app/views/projects/blob/_download.html.haml
index f2c5e95ecf4252d8612c8399d1ff2525b2e4907c..7908fcae3de1db6f9c32aae52a2111a4c9f19799 100644
--- a/app/views/projects/blob/_download.html.haml
+++ b/app/views/projects/blob/_download.html.haml
@@ -4,4 +4,4 @@
       %h1.light
         %i.fa.fa-download
       %h4
-        Download (#{number_to_human_size blob.size})
+        Download (#{number_to_human_size blob_size(blob)})
diff --git a/app/views/projects/blob/show.html.haml b/app/views/projects/blob/show.html.haml
index b7276868ce67da31a75007d4ee7811c74baedb8d..09d6fc18e3e7c0ecb6366a6645108014d1aa1a1e 100644
--- a/app/views/projects/blob/show.html.haml
+++ b/app/views/projects/blob/show.html.haml
@@ -6,7 +6,7 @@
 %div#tree-holder.tree-holder
   = render 'blob', blob: @blob
 
-- if allowed_tree_edit?
+- if can_delete_or_replace?(@blob)
   = render 'projects/blob/remove'
 
   - title = "Replace #{@blob.name}"
diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml
index 3f95e2a1bf6ec42d1d9dc5cde598f2acb844e0a7..5081bae6801d0cdde8a0060374f328e8a2ab23dc 100644
--- a/app/views/projects/branches/_branch.html.haml
+++ b/app/views/projects/branches/_branch.html.haml
@@ -3,17 +3,17 @@
   %div
     = link_to namespace_project_tree_path(@project.namespace, @project, branch.name) do
       %strong.str-truncated= branch.name
-      &nbsp;
-      - if branch.name == @repository.root_ref
-        %span.label.label-primary default
-      - elsif @repository.merged_to_root_ref? branch.name
-        %span.label.label-info.has_tooltip(title="Merged into #{@repository.root_ref}")
-          merged
+    &nbsp;
+    - if branch.name == @repository.root_ref
+      %span.label.label-primary default
+    - elsif @repository.merged_to_root_ref? branch.name
+      %span.label.label-info.has_tooltip(title="Merged into #{@repository.root_ref}")
+        merged
 
-      - if @project.protected_branch? branch.name
-        %span.label.label-success
-          %i.fa.fa-lock
-          protected
+    - if @project.protected_branch? branch.name
+      %span.label.label-success
+        %i.fa.fa-lock
+        protected
     .controls.hidden-xs
       - if create_mr_button?(@repository.root_ref, branch.name)
         = link_to create_mr_path(@repository.root_ref, branch.name), class: 'btn btn-grouped btn-xs' do
@@ -26,7 +26,7 @@
           Compare
 
       - if can_remove_branch?(@project, branch.name)
-        = link_to namespace_project_branch_path(@project.namespace, @project, branch.name), class: 'btn btn-grouped btn-xs btn-remove remove-row', method: :delete, data: { confirm: "Deleting the '#{branch.name}' branch cannot be undone. Are you sure?" }, remote: true do
+        = link_to namespace_project_branch_path(@project.namespace, @project, branch.name), class: 'btn btn-grouped btn-xs btn-remove remove-row has_tooltip', title: "Delete branch", method: :delete, data: { confirm: "Deleting the '#{branch.name}' branch cannot be undone. Are you sure?", container: 'body' }, remote: true do
           = icon("trash-o")
 
   - if commit
diff --git a/app/views/projects/builds/index.html.haml b/app/views/projects/builds/index.html.haml
index dab7164153ff119783297a10e48d2f53794aff2e..742676305a9ce886ac585690bb5823c5de59e3dc 100644
--- a/app/views/projects/builds/index.html.haml
+++ b/app/views/projects/builds/index.html.haml
@@ -3,10 +3,10 @@
 
 .project-issuable-filter
   .controls
-    - if @ci_project && current_user && can?(current_user, :manage_builds, @project)
+    - if @ci_project && can?(current_user, :manage_builds, @project)
       .pull-left.hidden-xs
         - if @all_builds.running_or_pending.any?
-          = link_to 'Cancel all', cancel_all_namespace_project_builds_path(@project.namespace, @project), data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post
+          = link_to 'Cancel running', cancel_all_namespace_project_builds_path(@project.namespace, @project), data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post
 
   %ul.center-top-menu
     %li{class: ('active' if @scope.nil?)}
@@ -50,4 +50,3 @@
           = render 'projects/commit_statuses/commit_status', commit_status: build, commit_sha: true, stage: true, allow_retry: true
 
     = paginate @builds, theme: 'gitlab'
-
diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml
index 907e1ce10bddaf600fa7d406abad12505e164b44..d5e81f84b56c1f78aee764a0636b0dddb6941931 100644
--- a/app/views/projects/builds/show.html.haml
+++ b/app/views/projects/builds/show.html.haml
@@ -1,17 +1,16 @@
-- page_title "#{@build.name} (#{@build.id})", "Builds"
+- page_title "#{@build.name} (##{@build.id})", "Builds"
 = render "header_title"
 
 .build-page
-  .gray-content-block
+  .gray-content-block.top-block
     Build ##{@build.id} for commit
-    %strong.monospace
-      = link_to @build.commit.short_sha, ci_status_path(@build.commit)
+    %strong.monospace= link_to @build.commit.short_sha, ci_status_path(@build.commit)
     from
     = link_to @build.ref, namespace_project_commits_path(@project.namespace, @project, @build.ref)
 
   #up-build-trace
   - if @commit.matrix_for_ref?(@build.ref)
-    %ul.center-top-menu.build-top-menu
+    %ul.center-top-menu.no-top.no-bottom
       - @commit.latest_builds_for_ref(@build.ref).each do |build|
         %li{class: ('active' if build == @build) }
           = link_to namespace_project_build_path(@project.namespace, @project, build) do
@@ -22,7 +21,6 @@
               - else
                 = build.id
 
-
       - if @build.retried?
         %li.active
           %a
@@ -31,7 +29,7 @@
             %i.fa.fa-warning
             This build was retried.
 
-  .gray-content-block.second-block
+  .gray-content-block.middle-block
     .build-head
       .clearfix
         = ci_status_with_icon(@build.status)
@@ -140,7 +138,7 @@
         %h4.title
           Commit
           .pull-right
-            %small 
+            %small
               = link_to @build.commit.short_sha, ci_status_path(@build.commit), class: "monospace"
         %p
           %span.attr-name Branch:
@@ -162,7 +160,7 @@
 
       - if @builds.present?
         .build-widget
-          %h4.title #{pluralize(@builds.count(:id), "other build")} for 
+          %h4.title #{pluralize(@builds.count(:id), "other build")} for
           = succeed ":" do
             = link_to @build.commit.short_sha, ci_status_path(@build.commit), class: "monospace"
           %table.table.builds
diff --git a/app/views/projects/commit/_commit_box.html.haml b/app/views/projects/commit/_commit_box.html.haml
index d8bfe6a07ac6ec2d90f890e0390185262dca1c1f..bb37e4a7049c9aa91e17c02bf792b5218ed5afe3 100644
--- a/app/views/projects/commit/_commit_box.html.haml
+++ b/app/views/projects/commit/_commit_box.html.haml
@@ -20,7 +20,8 @@
 
 %p
   %span.light Commit
-  = link_to @commit.id, namespace_project_commit_path(@project.namespace, @project, @commit), class: "monospace"
+  = link_to @commit.id, namespace_project_commit_path(@project.namespace, @project, @commit), class: "monospace", data: { clipboard_text: @commit.id }
+  = clipboard_button
 .commit-info-row
   %span.light Authored by
   %strong
@@ -44,7 +45,7 @@
     = link_to ci_status_path(@ci_commit), class: "ci-status ci-#{@ci_commit.status}" do
       = ci_status_icon(@ci_commit)
       build:
-      = @ci_commit.status
+      = ci_status_label(@ci_commit)
 
 .commit-info-row.branches
   %i.fa.fa-spinner.fa-spin
diff --git a/app/views/projects/commit_statuses/_commit_status.html.haml b/app/views/projects/commit_statuses/_commit_status.html.haml
index 9a0e7bff3f1ebc805551909e1fe04cee147fb254..a527bb2f84a4ad7ababc2f98a06c889739a3ba5e 100644
--- a/app/views/projects/commit_statuses/_commit_status.html.haml
+++ b/app/views/projects/commit_statuses/_commit_status.html.haml
@@ -1,13 +1,18 @@
 %tr.commit_status
   %td.status
-    = ci_status_with_icon(commit_status.status)
+    - if commit_status.target_url
+      = link_to commit_status.target_url, class: "ci-status ci-#{commit_status.status}" do
+        = ci_icon_for_status(commit_status.status)
+        = commit_status.status
+    - else
+      = ci_status_with_icon(commit_status.status)
 
   %td.commit_status-link
     - if commit_status.target_url
       = link_to commit_status.target_url do
-        %strong Build ##{commit_status.id}
+        %strong ##{commit_status.id}
     - else
-      %strong Build ##{commit_status.id}
+      %strong ##{commit_status.id}
 
     - if commit_status.show_warning?
       %i.fa.fa-warning.text-warning
diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml
index b77e9f9f4038b684c89a47df060137f9fc8ea0d8..327e7d9245a625f916a538e0d3805a546c99d3db 100644
--- a/app/views/projects/diffs/_file.html.haml
+++ b/app/views/projects/diffs/_file.html.haml
@@ -24,7 +24,7 @@
             = "#{diff_file.diff.a_mode} → #{diff_file.diff.b_mode}"
 
       .diff-controls
-        - if blob.text?
+        - if blob_viewable?(blob)
           = link_to '#', class: 'js-toggle-diff-comments btn btn-sm active has_tooltip', title: "Toggle comments for this file" do
             %i.fa.fa-comments
           &nbsp;
@@ -39,7 +39,7 @@
   .diff-content.diff-wrap-lines
     -# Skipp all non non-supported blobs
     - return unless blob.respond_to?('text?')
-    - if blob.text?
+    - if blob_viewable?(blob)
       - if diff_view == 'parallel'
         = render "projects/diffs/parallel_view", diff_file: diff_file, project: project, blob: blob, index: i
       - else
diff --git a/app/views/projects/graphs/_head.html.haml b/app/views/projects/graphs/_head.html.haml
index 03d0733f913268357e05805f9fc0ebba6b76aef7..a47643bd09c642add4a0abca355b2253b0b9881f 100644
--- a/app/views/projects/graphs/_head.html.haml
+++ b/app/views/projects/graphs/_head.html.haml
@@ -3,6 +3,8 @@
     = link_to 'Contributors', namespace_project_graph_path
   = nav_link(action: :commits) do
     = link_to 'Commits', commits_namespace_project_graph_path
+  = nav_link(action: :languages) do
+    = link_to 'Languages', languages_namespace_project_graph_path
   - if @project.builds_enabled?
     = nav_link(action: :ci) do
       = link_to ci_namespace_project_graph_path do
diff --git a/app/views/projects/graphs/languages.html.haml b/app/views/projects/graphs/languages.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..a7fab5b6d72b3122f288352fd5a78f6baa7ed398
--- /dev/null
+++ b/app/views/projects/graphs/languages.html.haml
@@ -0,0 +1,32 @@
+- page_title "Languages", "Graphs"
+= render "header_title"
+= render 'head'
+
+.gray-content-block.append-bottom-default
+  .oneline
+    Programming languages used in this repository
+
+.row
+  .col-md-8
+    %canvas#languages-chart{ height: 400 }
+  .col-md-4
+    %ul.bordered-list
+      - @languages.each do |language|
+        %li
+          %span{ style: "color: #{language[:color]}" }
+            = icon('circle')
+          &nbsp;
+          = language[:label]
+          .pull-right
+            = language[:value]
+            \%
+
+:javascript
+  var data = #{@languages.to_json};
+  var ctx = $("#languages-chart").get(0).getContext("2d");
+  var options = {
+    scaleOverlay: true,
+    responsive: true,
+    maintainAspectRatio: false
+  }
+  var myPieChart = new Chart(ctx).Pie(data, options);
diff --git a/app/views/projects/issues/_discussion.html.haml b/app/views/projects/issues/_discussion.html.haml
index b5f522f2079362a6dc870504533205ff25f212d4..f2011542ca766698b78b94ed609220255ff43ad2 100644
--- a/app/views/projects/issues/_discussion.html.haml
+++ b/app/views/projects/issues/_discussion.html.haml
@@ -12,15 +12,12 @@
     .col-md-9
       .votes-holder.pull-right
         #votes= render 'votes/votes_block', votable: @issue
-      .participants
-        %span= pluralize(@participants.count, 'participant')
-        - @participants.each do |participant|
-          = link_to_member(@project, participant, name: false, size: 24)
+      = render "shared/issuable/participants"
     .col-md-3
       .input-group.cross-project-reference
         %span#cross-project-reference.slead.has_tooltip{title: 'Cross-project reference'}
           = cross_project_reference(@project, @issue)
-        = clipboard_button(clipboard_target: '#cross-project-reference')
+        = clipboard_button(clipboard_target: 'span#cross-project-reference')
 
 .row
   %section.col-md-9
diff --git a/app/views/projects/merge_requests/_discussion.html.haml b/app/views/projects/merge_requests/_discussion.html.haml
index ea462561668ffebc5705051dfff622e010812b24..d64b19ae91aff54c0619188f2d6dd8dd249c7ac0 100644
--- a/app/views/projects/merge_requests/_discussion.html.haml
+++ b/app/views/projects/merge_requests/_discussion.html.haml
@@ -12,16 +12,16 @@
     .col-md-9
       .votes-holder.pull-right
         #votes= render 'votes/votes_block', votable: @merge_request
-      = render "projects/merge_requests/show/participants"
+      = render "shared/issuable/participants"
     .col-md-3
       .input-group.cross-project-reference
         %span#cross-project-reference.slead.has_tooltip{title: 'Cross-project reference'}
           = cross_project_reference(@project, @merge_request)
-        = clipboard_button(clipboard_target: '#cross-project-reference')
+        = clipboard_button(clipboard_target: 'span#cross-project-reference')
 
 .row
   %section.col-md-9
-    = render "projects/notes/notes_with_form"
+    .voting_notes#notes= render "projects/notes/notes_with_form"
   %aside.col-md-3
     .issuable-affix
       .context
diff --git a/app/views/projects/merge_requests/_new_submit.html.haml b/app/views/projects/merge_requests/_new_submit.html.haml
index f0a821d2d9fd2cc77e43fa0dbfa289f52ae30e96..3f6e421fcd79190459d7a804a3809cb90fd08fbc 100644
--- a/app/views/projects/merge_requests/_new_submit.html.haml
+++ b/app/views/projects/merge_requests/_new_submit.html.haml
@@ -20,7 +20,7 @@
 .mr-compare.merge-request
   %ul.merge-request-tabs.center-top-menu.no-top.no-bottom
     %li.commits-tab
-      = link_to url_for(params), data: {target: '#commits', action: 'commits', toggle: 'tab'} do
+      = link_to url_for(params), data: {target: 'div#commits', action: 'commits', toggle: 'tab'} do
         Commits
         %span.badge= @commits.size
     - if @ci_commit
@@ -29,7 +29,7 @@
           Builds
           %span.badge= @statuses.size
     %li.diffs-tab.active
-      = link_to url_for(params), data: {target: '#diffs', action: 'diffs', toggle: 'tab'} do
+      = link_to url_for(params), data: {target: 'div#diffs', action: 'diffs', toggle: 'tab'} do
         Changes
         %span.badge= @diffs.size
 
diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml
index 79d71a784c11a41d27a54fe524ae77d6843560b9..686a9a2c758c4c550379f5c22db08bbb57103b76 100644
--- a/app/views/projects/merge_requests/_show.html.haml
+++ b/app/views/projects/merge_requests/_show.html.haml
@@ -43,11 +43,11 @@
   - if @commits.present?
     %ul.merge-request-tabs.center-top-menu.no-top.no-bottom
       %li.notes-tab
-        = link_to namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: '#notes', action: 'notes', toggle: 'tab'} do
+        = link_to namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#notes', action: 'notes', toggle: 'tab'} do
           Discussion
           %span.badge= @merge_request.mr_and_commit_notes.user.count
       %li.commits-tab
-        = link_to commits_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: '#commits', action: 'commits', toggle: 'tab'} do
+        = link_to commits_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#commits', action: 'commits', toggle: 'tab'} do
           Commits
           %span.badge= @commits.size
       - if @ci_commit
@@ -56,7 +56,7 @@
             Builds
             %span.badge= @statuses.size
       %li.diffs-tab
-        = link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: '#diffs', action: 'diffs', toggle: 'tab'} do
+        = link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#diffs', action: 'diffs', toggle: 'tab'} do
           Changes
           %span.badge= @merge_request.diffs.size
 
diff --git a/app/views/projects/merge_requests/widget/_heading.html.haml b/app/views/projects/merge_requests/widget/_heading.html.haml
index e94b07eaeaadedef632cb4a94ad9a27f2291b5ae..b05ab8692156a0a8fce868d58b311d7537bd6912 100644
--- a/app/views/projects/merge_requests/widget/_heading.html.haml
+++ b/app/views/projects/merge_requests/widget/_heading.html.haml
@@ -1,10 +1,10 @@
-- ci_commit = @merge_request.ci_commit
-- if ci_commit
-  - status = ci_commit.status
+- if @ci_commit
   .mr-widget-heading
-    .ci_widget{class: "ci-#{status}"}
-      = ci_status_icon(ci_commit)
-      %span Build #{status}
+    .ci_widget{class: "ci-#{@ci_commit.status}"}
+      = ci_status_icon(@ci_commit)
+      %span
+        Build
+        = ci_status_label(@ci_commit)
       for
       = succeed "." do
         = link_to @ci_commit.short_sha, namespace_project_commit_path(@merge_request.source_project.namespace, @merge_request.source_project, @ci_commit.sha), class: "monospace"
@@ -15,21 +15,19 @@
   - # Compatibility with old CI integrations (ex jenkins) when you request status from CI server via AJAX
   - # Remove in later versions when services like Jenkins will set CI status via Commit status API
   .mr-widget-heading
-    - [:success, :skipped, :canceled, :failed, :running, :pending].each do |status|
+    - %w[success skipped canceled failed running pending].each do |status|
       .ci_widget{class: "ci-#{status}", style: "display:none"}
-        - if status == :success
-          - status = "passed"
-          = icon("check-circle")
-        - else
-          = icon("circle")
-        %span CI build #{status}
+        = ci_icon_for_status(status)
+        %span
+          CI build
+          = ci_label_for_status(status)
         for
         - commit = @merge_request.last_commit
         = succeed "." do
           = link_to commit.short_id, namespace_project_commit_path(@merge_request.source_project.namespace, @merge_request.source_project, commit), class: "monospace"
         %span.ci-coverage
-        - if ci_build_details_path(@merge_request)
-          = link_to "View details", ci_build_details_path(@merge_request), :"data-no-turbolink" => "data-no-turbolink"
+        - if details_path = ci_build_details_path(@merge_request)
+          = link_to "View details", details_path, :"data-no-turbolink" => "data-no-turbolink"
 
     .ci_widget
       = icon("spinner spin")
diff --git a/app/views/projects/merge_requests/widget/open/_accept.html.haml b/app/views/projects/merge_requests/widget/open/_accept.html.haml
index 9b31014b581768aea12f28e6fb4d0068816aad20..6d12af16140f3227e859983eb07f3a1fa5939c3a 100644
--- a/app/views/projects/merge_requests/widget/open/_accept.html.haml
+++ b/app/views/projects/merge_requests/widget/open/_accept.html.haml
@@ -1,4 +1,4 @@
-- status_class = @merge_request.ci_commit ? " ci-#{@merge_request.ci_commit.status}" : nil
+- status_class = @ci_commit ? " ci-#{@ci_commit.status}" : nil
 
 = form_for [:merge, @project.namespace.becomes(Namespace), @project, @merge_request], remote: true, method: :post, html: { class: 'accept-mr-form js-requires-input' } do |f|
   = hidden_field_tag :authenticity_token, form_authenticity_token
diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml
index a207385bd4351984a40d0073b66c6cec30c6377b..114b06457a52aead1faea05a1e3c89e506527ae0 100644
--- a/app/views/projects/milestones/index.html.haml
+++ b/app/views/projects/milestones/index.html.haml
@@ -1,15 +1,18 @@
 - page_title "Milestones"
 = render "header_title"
-= render 'shared/milestones_filter'
 
-.gray-content-block
-  .pull-right
-    - if can? current_user, :admin_milestone, @project
+
+.project-issuable-filter
+  .controls
+    - if can?(current_user, :admin_milestone, @project)
       = link_to new_namespace_project_milestone_path(@project.namespace, @project), class: "pull-right btn btn-new", title: "New Milestone" do
         %i.fa.fa-plus
         New Milestone
-  .oneline
-    Milestone allows you to group issues and set due date for it
+
+  = render 'shared/milestones_filter'
+
+.gray-content-block
+  Milestone allows you to group issues and set due date for it
 
 .milestones
   %ul.content-list
diff --git a/app/views/projects/network/_head.html.haml b/app/views/projects/network/_head.html.haml
index 415c98ec6a6aed0561730427d782f8db9e48a344..9e0e0dc6bb0f31857ea9b4715eea54c4e3dc33dd 100644
--- a/app/views/projects/network/_head.html.haml
+++ b/app/views/projects/network/_head.html.haml
@@ -1,3 +1,6 @@
-.append-bottom-20
-  = render partial: 'shared/ref_switcher', locals: {destination: 'graph'}
-  .pull-right.visible-lg.light You can move around the graph by using the arrow keys.
+.gray-content-block.top-block.append-bottom-default
+  .tree-ref-holder
+    = render partial: 'shared/ref_switcher', locals: {destination: 'graph'}
+
+  .oneline
+    You can move around the graph by using the arrow keys.
diff --git a/app/views/projects/project_members/_group_members.html.haml b/app/views/projects/project_members/_group_members.html.haml
index 0c73d7e34acf7e8c15cbea20435b5d535b74e18a..d2810f9707afe04f8bc356a4ad4a3c2f78488164 100644
--- a/app/views/projects/project_members/_group_members.html.haml
+++ b/app/views/projects/project_members/_group_members.html.haml
@@ -4,10 +4,11 @@
     group members
     %small
       (#{members.count})
-    .pull-right
-      = link_to group_group_members_path(@group), class: 'btn' do
-        = icon('pencil-square-o')
-        Edit group members
+    - if can?(current_user, :admin_group_member, @group)
+      .pull-right
+        = link_to group_group_members_path(@group), class: 'btn' do
+          = icon('pencil-square-o')
+          Manage group members
   %ul.content-list
     - members.each do |member|
       = render 'groups/group_members/group_member', member: member, show_controls: false
diff --git a/app/views/projects/protected_branches/index.html.haml b/app/views/projects/protected_branches/index.html.haml
index 2541105b0077f1a9d098847c44411d75f2af690f..cfd7e1534ca81c1d24778fa72787f9a3b7353e99 100644
--- a/app/views/projects/protected_branches/index.html.haml
+++ b/app/views/projects/protected_branches/index.html.haml
@@ -3,7 +3,7 @@
 %p.light Keep stable branches secure and force developers to use Merge Requests
 %hr
 
-.well.append-bottom-20
+.well
   %p Protected branches are designed to
   %ul
     %li prevent pushes from everybody except #{link_to "masters", help_page_path("permissions", "permissions"), class: "vlink"}
diff --git a/app/views/projects/tags/_tag.html.haml b/app/views/projects/tags/_tag.html.haml
index e2c5178185e475e03e4d2f8b61e977420b831b77..28b706c5c7e85f95f928229d0ca5944b1005dffd 100644
--- a/app/views/projects/tags/_tag.html.haml
+++ b/app/views/projects/tags/_tag.html.haml
@@ -11,11 +11,17 @@
       = strip_gpg_signature(tag.message)
 
     .controls
-      = link_to edit_namespace_project_tag_release_path(@project.namespace, @project, tag.name), class: 'btn-grouped btn' do
-        = icon("pencil")
-      - if can? current_user, :download_code, @project
+      - if can?(current_user, :download_code, @project)
         = render 'projects/tags/download', ref: tag.name, project: @project
 
+      - if can?(current_user, :push_code, @project)
+        = link_to edit_namespace_project_tag_release_path(@project.namespace, @project, tag.name), class: 'btn-grouped btn has_tooltip', title: "Edit release notes" do
+          = icon("pencil")
+
+      - if can?(current_user, :admin_project, @project)
+        = link_to namespace_project_tag_path(@project.namespace, @project, tag.name), class: 'btn btn-grouped btn-xs btn-remove remove-row has_tooltip', title: "Delete tag", method: :delete, data: { confirm: "Deleting the '#{tag.name}' tag cannot be undone. Are you sure?", container: 'body' }, remote: true do
+          = icon("trash-o")
+
   - if commit
     = render 'projects/branches/commit', commit: commit, project: @project
   - else
diff --git a/app/views/projects/tags/show.html.haml b/app/views/projects/tags/show.html.haml
index 879c6c7d310bccd5ebd76d3a744d0c6c0b09dfe2..b594d4f1f27674e40232a9f8ac46914b8c8e81a3 100644
--- a/app/views/projects/tags/show.html.haml
+++ b/app/views/projects/tags/show.html.haml
@@ -5,17 +5,17 @@
 .gray-content-block
   .pull-right
     - if can?(current_user, :push_code, @project)
-      = link_to edit_namespace_project_tag_release_path(@project.namespace, @project, @tag.name), class: 'btn-grouped btn', title: 'Edit release notes' do
+      = link_to edit_namespace_project_tag_release_path(@project.namespace, @project, @tag.name), class: 'btn-grouped btn has_tooltip', title: 'Edit release notes' do
         = icon("pencil")
-    = link_to namespace_project_tree_path(@project.namespace, @project, @tag.name), class: 'btn btn-grouped', title: 'Browse source code' do
+    = link_to namespace_project_tree_path(@project.namespace, @project, @tag.name), class: 'btn btn-grouped has_tooltip', title: 'Browse files' do
       = icon('files-o')
-    = link_to namespace_project_commits_path(@project.namespace, @project, @tag.name), class: 'btn btn-grouped', title: 'Browse commits' do
+    = link_to namespace_project_commits_path(@project.namespace, @project, @tag.name), class: 'btn btn-grouped has_tooltip', title: 'Browse commits' do
       = icon('history')
     - if can? current_user, :download_code, @project
       = render 'projects/tags/download', ref: @tag.name, project: @project
     - if can?(current_user, :admin_project, @project)
       .pull-right
-        = link_to namespace_project_tag_path(@project.namespace, @project, @tag.name), class: 'btn btn-remove remove-row grouped', method: :delete, data: { confirm: "Deleting the '#{@tag.name}' tag cannot be undone. Are you sure?" } do
+        = link_to namespace_project_tag_path(@project.namespace, @project, @tag.name), class: 'btn btn-remove remove-row grouped has_tooltip', title: "Delete tag", method: :delete, data: { confirm: "Deleting the '#{@tag.name}' tag cannot be undone. Are you sure?" } do
           %i.fa.fa-trash-o
   .title
     %strong= @tag.name
diff --git a/app/views/projects/tree/_tree_header.html.haml b/app/views/projects/tree/_tree_header.html.haml
index 1115ca6b4caaf333d997f4eff4efea2243fc218c..12356dbcb6b265b09723922a5e8361a422345069 100644
--- a/app/views/projects/tree/_tree_header.html.haml
+++ b/app/views/projects/tree/_tree_header.html.haml
@@ -14,7 +14,7 @@
   - if allowed_tree_edit?
     %li
       %span.dropdown
-        %a.dropdown-toggle.btn.add-to-tree{href: '#', "data-toggle" => "dropdown"}
+        %a.dropdown-toggle.btn.btn-sm.add-to-tree{href: '#', "data-toggle" => "dropdown"}
           = icon('plus')
         %ul.dropdown-menu
           %li
diff --git a/app/views/shared/_new_commit_form.html.haml b/app/views/shared/_new_commit_form.html.haml
index 31b02ed93d027cbb22fdc91543c6b536a3eec51f..55aa045fd59d3eb67b77ca69e59726e92bfb082d 100644
--- a/app/views/shared/_new_commit_form.html.haml
+++ b/app/views/shared/_new_commit_form.html.haml
@@ -6,12 +6,11 @@
     .col-sm-10
       = text_field_tag 'new_branch', @new_branch || @ref, required: true, class: "form-control js-new-branch"
 
-  .form-group.js-create-merge-request-form-group
-    .col-sm-offset-2.col-sm-10
-      .checkbox
-        - nonce = SecureRandom.hex
-        = label_tag "create_merge_request-#{nonce}" do
-          = check_box_tag 'create_merge_request', 1, true, class: 'js-create-merge-request', id: "create_merge_request-#{nonce}"
-          Start a <strong>new merge request</strong> with this commit
+      .js-create-merge-request-container
+        .checkbox
+          - nonce = SecureRandom.hex
+          = label_tag "create_merge_request-#{nonce}" do
+            = check_box_tag 'create_merge_request', 1, true, class: 'js-create-merge-request', id: "create_merge_request-#{nonce}"
+            Start a <strong>new merge request</strong> with these changes
 
   = hidden_field_tag 'original_branch', @ref, class: 'js-original-branch'
diff --git a/app/views/shared/_new_project_item_select.html.haml b/app/views/shared/_new_project_item_select.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..c4431d66927eb999b7fd5958e6e69d118b450f57
--- /dev/null
+++ b/app/views/shared/_new_project_item_select.html.haml
@@ -0,0 +1,20 @@
+- if @projects.any?
+  .prepend-left-10.new-project-item-select-holder
+    = project_select_tag :project_path, class: "new-project-item-select", data: { include_groups: local_assigns[:include_groups] }
+    %a.btn.btn-new.new-project-item-select-button
+      = icon('plus')
+      = local_assigns[:label]
+      %b.caret
+
+  :javascript
+    $('.new-project-item-select-button').on('click', function() {
+      $('.new-project-item-select').select2('open');
+    });
+
+    var relativePath = '#{local_assigns[:path]}';
+
+    $('.new-project-item-select').on('click', function() {
+      window.location = $(this).val() + '/' + relativePath;
+    });
+
+    new ProjectSelect()
diff --git a/app/views/projects/merge_requests/show/_participants.html.haml b/app/views/shared/issuable/_participants.html.haml
similarity index 67%
rename from app/views/projects/merge_requests/show/_participants.html.haml
rename to app/views/shared/issuable/_participants.html.haml
index c67afe963e7be2abdf1e1906c4b4d7d9299d66f9..b4e0def48b62fd4e85edcca0be20945bd4e49a46 100644
--- a/app/views/projects/merge_requests/show/_participants.html.haml
+++ b/app/views/shared/issuable/_participants.html.haml
@@ -1,4 +1,5 @@
 .participants
-  %span #{@participants.count} participants
+  %span
+    = pluralize @participants.count, "participant"
   - @participants.each do |participant|
     = link_to_member(@project, participant, name: false, size: 24)
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index d5a92cb816adf83ea7e507a43a91ca97b41c855d..a0a6e2d9810b0f071f61e95b33de961638dcefd0 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -73,7 +73,7 @@
   .user-calendar-activities
 
 
-%ul.center-middle-menu
+%ul.center-top-menu.no-top.no-bottom.bottom-border
   %li.active
     = link_to "#activity", 'data-toggle' => 'tab' do
       Activity
diff --git a/bin/parallel-rsync-repos b/bin/parallel-rsync-repos
new file mode 100755
index 0000000000000000000000000000000000000000..21921148fa0913558473077c23f1b17bea8701fd
--- /dev/null
+++ b/bin/parallel-rsync-repos
@@ -0,0 +1,54 @@
+#!/usr/bin/env bash
+# this script should run as the 'git' user, not root, because 'root' should not
+# own intermediate directories created by rsync.
+#
+# Example invocation:
+# find /var/opt/gitlab/git-data/repositories -maxdepth 2 | \
+#   parallel-rsync-repos transfer-success.log /var/opt/gitlab/git-data/repositories /mnt/gitlab/repositories
+#
+# You can also rsync to a remote destination.
+#
+# parallel-rsync-repos transfer-success.log /var/opt/gitlab/git-data/repositories user@host:/mnt/gitlab/repositories
+#
+# If you need to pass extra options to rsync, set the RSYNC variable
+#
+# env RSYNC='rsync --rsh="foo bar"' parallel-rsync-repos transfer-success.log /src dest
+#
+
+LOGFILE=$1
+SRC=$2
+DEST=$3
+
+if [ -z "$LOGFILE" ] || [ -z "$SRC" ] || [ -z "$DEST" ] ; then
+  echo "Usage: $0 LOGFILE SRC DEST"
+  exit 1
+fi
+
+if [ -z "$JOBS" ] ; then
+  JOBS=10
+fi
+
+if [ -z "$RSYNC" ] ; then
+  RSYNC=rsync
+fi
+
+if ! cd $SRC ; then
+  echo "cd $SRC failed"
+  exit 1
+fi
+
+rsyncjob() {
+  relative_dir="./${1#$SRC}"
+
+  if ! $RSYNC --delete --relative -a "$relative_dir" "$DEST" ; then
+    echo "rsync $1 failed"
+    return 1
+  fi
+
+  echo "$1" >> $LOGFILE
+}
+
+export LOGFILE SRC DEST RSYNC
+export -f rsyncjob
+
+parallel -j$JOBS --progress rsyncjob
diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb
index 70ed10e8275ef461c703d98064f2b31cf3fb643f..4c164119fff1db68d07d60b6dfbfafcc8d63a731 100644
--- a/config/initializers/omniauth.rb
+++ b/config/initializers/omniauth.rb
@@ -16,7 +16,7 @@ OmniAuth.config.allowed_request_methods = [:post]
 #In case of auto sign-in, the GET method is used (users don't get to click on a button)
 OmniAuth.config.allowed_request_methods << :get if Gitlab.config.omniauth.auto_sign_in_with_provider.present?
 OmniAuth.config.before_request_phase do |env|
-  OmniAuth::RequestForgeryProtection.new(env).call
+  OmniAuth::RequestForgeryProtection.call(env)
 end
 
 if Gitlab.config.omniauth.enabled
diff --git a/config/routes.rb b/config/routes.rb
index 38f0b16a412736a9eda82d5ca59a6e575dd797ec..359cd08e1345a8b57f7d4e2f47a224a1355edb20 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -500,6 +500,7 @@ Rails.application.routes.draw do
           member do
             get :commits
             get :ci
+            get :languages
           end
         end
 
diff --git a/doc/api/groups.md b/doc/api/groups.md
index 0b9f6406d8dd71a7c7c3b8a181666c50326117b2..808675d8605006c142a25eb188d66190c6bb73da 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -1,6 +1,6 @@
 # Groups
 
-## List project groups
+## List groups
 
 Get a list of groups. (As user: my groups, as admin: all groups)
 
@@ -21,6 +21,70 @@ GET /groups
 
 You can search for groups by name or path, see below.
 
+
+## List a group's projects
+
+Get a list of projects in this group.
+
+```
+GET /groups/:id/projects
+```
+
+Parameters:
+
+- `archived` (optional) - if passed, limit by archived status
+- `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at`
+- `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
+- `search` (optional) - Return list of authorized projects according to a search criteria
+- `ci_enabled_first` - Return projects ordered by ci_enabled flag. Projects with enabled GitLab CI go first
+
+```json
+[
+  {
+    "id": 4,
+    "description": null,
+    "default_branch": "master",
+    "public": false,
+    "visibility_level": 0,
+    "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",
+    "tag_list": [
+      "example",
+      "disapora client"
+    ],
+    "owner": {
+      "id": 3,
+      "name": "Diaspora",
+      "created_at": "2013-09-30T13: 46: 02Z"
+    },
+    "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,
+    "builds_enabled": true,
+    "wiki_enabled": true,
+    "snippets_enabled": false,
+    "created_at": "2013-09-30T13: 46: 02Z",
+    "last_activity_at": "2013-09-30T13: 46: 02Z",
+    "creator_id": 3,
+    "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"
+    },
+    "archived": false,
+    "avatar_url": "http://example.com/uploads/project/avatar/4/uploads/avatar.png"
+  }
+]
+```
+
 ## Details of a group
 
 Get all details of a group.
@@ -186,7 +250,7 @@ To get more (up to 100), pass the following as an argument to the API call:
 /groups?per_page=100
 ```
 
-And to switch pages add: 
+And to switch pages add:
 ```
 /groups?per_page=100&page=2
-```
\ No newline at end of file
+```
diff --git a/doc/integration/ldap.md b/doc/integration/ldap.md
index 7e2920b8865e6aeb7d4dfed2af12cb67640e5360..845f588f913808451ceef55dfb823ddeabcf663e 100644
--- a/doc/integration/ldap.md
+++ b/doc/integration/ldap.md
@@ -13,6 +13,12 @@ An LDAP user who is allowed to change their email on the LDAP server can [take o
 
 We recommend against using GitLab LDAP integration if your LDAP users are allowed to change their 'mail', 'email' or 'userPrincipalName'  attribute on the LDAP server.
 
+If a user is deleted from the LDAP server, they will be blocked in GitLab as well.
+Users will be immediately blocked from logging in. However, there is an LDAP check
+cache time of one hour. The means users that are already logged in or are using Git
+over SSH will still be able to access GitLab for up to one hour. Manually block
+the user in the GitLab Admin area to immediately block all access.
+
 ## Configuring GitLab for LDAP integration
 
 To enable GitLab LDAP integration you need to add your LDAP server settings in `/etc/gitlab/gitlab.rb` or `/home/git/gitlab/config/gitlab.yml`.
@@ -192,4 +198,4 @@ Not supported by GitLab's configuration options.
 When setting `method: ssl`, the underlying authentication method used by 
 `omniauth-ldap` is `simple_tls`.  This method establishes TLS encryption with 
 the LDAP server before any LDAP-protocol data is exchanged but no validation of
-the LDAP server's SSL certificate is performed.
\ No newline at end of file
+the LDAP server's SSL certificate is performed.
diff --git a/doc/operations/moving_repositories.md b/doc/operations/moving_repositories.md
new file mode 100644
index 0000000000000000000000000000000000000000..39086b7a2519e24eb3d22e9b5d99fcd592dd09a8
--- /dev/null
+++ b/doc/operations/moving_repositories.md
@@ -0,0 +1,180 @@
+# Moving repositories managed by GitLab
+
+Sometimes you need to move all repositories managed by GitLab to
+another filesystem or another server. In this document we will look
+at some of the ways you can copy all your repositories from
+`/var/opt/gitlab/git-data/repositories` to `/mnt/gitlab/repositories`.
+
+We will look at three scenarios: the target directory is empty, the
+target directory contains an outdated copy of the repositories, and
+how to deal with thousands of repositories.
+
+**Each of the approaches we list can/will overwrite data in the
+target directory `/mnt/gitlab/repositories`. Do not mix up the
+source and the target.**
+
+## Target directory is empty: use a tar pipe
+
+If the target directory `/mnt/gitlab/repositories` is empty the
+simplest thing to do is to use a tar pipe.  This method has low
+overhead and tar is almost always already installed on your system.
+However, it is not possible to resume an interrupted tar pipe:  if
+that happens then all data must be copied again.
+
+```
+# As the git user
+tar -C /var/opt/gitlab/git-data/repositories -cf - -- . |\
+  tar -C /mnt/gitlab/repositories -xf -
+```
+
+If you want to see progress, replace `-xf` with `-xvf`.
+
+### Tar pipe to another server
+
+You can also use a tar pipe to copy data to another server. If your
+'git' user has SSH access to the newserver as 'git@newserver', you
+can pipe the data through SSH.
+
+```
+# As the git user
+tar -C /var/opt/gitlab/git-data/repositories -cf - -- . |\
+  ssh git@newserver tar -C /mnt/gitlab/repositories -xf -
+```
+
+If you want to compress the data before it goes over the network
+(which will cost you CPU cycles) you can replace `ssh` with `ssh -C`.
+
+## The target directory contains an outdated copy of the repositories: use rsync
+
+If the target directory already contains a partial / outdated copy
+of the repositories it may be wasteful to copy all the data again
+with tar. In this scenario it is better to use rsync. This utility
+is either already installed on your system or easily installable
+via apt, yum etc.
+
+```
+# As the 'git' user
+rsync -a --delete /var/opt/gitlab/git-data/repositories/. \
+  /mnt/gitlab/repositories
+```
+
+The `/.` in the command above is very important, without it you can
+easily get the wrong directory structure in the target directory.
+If you want to see progress, replace `-a` with `-av`.
+
+### Single rsync to another server
+
+If the 'git' user on your source system has SSH access to the target
+server you can send the repositories over the network with rsync.
+
+```
+# As the 'git' user
+rsync -a --delete /var/opt/gitlab/git-data/repositories/. \
+  git@newserver:/mnt/gitlab/repositories
+```
+
+## Thousands of Git repositories: use one rsync per repository
+
+Every time you start an rsync job it has to inspect all files in
+the source directory, all files in the target directory, and then
+decide what files to copy or not. If the source or target directory
+has many contents this startup phase of rsync can become a burden
+for your GitLab server. In cases like this you can make rsync's
+life easier by dividing its work in smaller pieces, and sync one
+repository at a time.
+
+In addition to rsync we will use [GNU
+Parallel](http://www.gnu.org/software/parallel/). This utility is
+not included in GitLab so you need to install it yourself with apt
+or yum.  Also note that the GitLab scripts we used below were added
+in GitLab 8.1.
+
+** This process does not clean up repositories at the target location that no
+longer exist at the source. ** If you start using your GitLab instance with
+`/mnt/gitlab/repositories`, you need to run `gitlab-rake gitlab:cleanup:repos`
+after switching to the new repository storage directory.
+
+### Parallel rsync for all repositories known to GitLab
+
+This will sync repositories with 10 rsync processes at a time. We keep
+track of progress so that the transfer can be restarted if necessary.
+
+First we create a new directory, owned by 'git', to hold transfer
+logs. We assume the directory is empty before we start the transfer
+procedure, and that we are the only ones writing files in it.
+
+```
+# Omnibus
+sudo mkdir /var/opt/gitlab/transfer-logs
+sudo chown git:git /var/opt/gitlab/transfer-logs
+
+# Source
+sudo -u git -H mkdir /home/git/transfer-logs
+```
+
+We seed the process with a list of the directories we want to copy.
+
+```
+# Omnibus
+sudo -u git sh -c 'gitlab-rake gitlab:list_repos > /var/opt/gitlab/transfer-logs/all-repos-$(date +%s).txt'
+
+# Source
+cd /home/git/gitlab
+sudo -u git -H sh -c 'bundle exec rake gitlab:list_repos > /home/git/transfer-logs/all-repos-$(date +%s).txt'
+```
+
+Now we can start the transfer. The command below is idempotent, and
+the number of jobs done by GNU Parallel should converge to zero. If it
+does not some repositories listed in all-repos-1234.txt may have been
+deleted/renamed before they could be copied.
+
+```
+# Omnibus
+sudo -u git sh -c '
+cat /var/opt/gitlab/transfer-logs/* | sort | uniq -u |\
+  /usr/bin/env JOBS=10 \
+  /opt/gitlab/embedded/service/gitlab-rails/bin/parallel-rsync-repos \
+    /var/opt/gitlab/transfer-logs/succes-$(date +%s).log \
+    /var/opt/gitlab/git-data/repositories \
+    /mnt/gitlab/repositories
+'
+
+# Source
+cd /home/git/gitlab
+sudo -u git -H sh -c '
+cat /home/git/transfer-logs/* | sort | uniq -u |\
+  /usr/bin/env JOBS=10 \
+  bin/parallel-rsync-repos \
+    /home/git/transfer-logs/succes-$(date +%s).log \
+    /home/git/repositories \
+    /mnt/gitlab/repositories
+`
+```
+
+### Parallel rsync only for repositories with recent activity
+
+Suppose you have already done one sync that started after 2015-10-1 12:00 UTC.
+Then you might only want to sync repositories that were changed via GitLab
+_after_ that time. You can use the 'SINCE' variable to tell 'rake
+gitlab:list_repos' to only print repositories with recent activity.
+
+```
+# Omnibus
+sudo gitlab-rake gitlab:list_repos SINCE='2015-10-1 12:00 UTC' |\
+  sudo -u git \
+  /usr/bin/env JOBS=10 \
+  /opt/gitlab/embedded/service/gitlab-rails/bin/parallel-rsync-repos \
+    succes-$(date +%s).log \
+    /var/opt/gitlab/git-data/repositories \
+    /mnt/gitlab/repositories
+
+# Source
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:list_repos SINCE='2015-10-1 12:00 UTC' |\
+  sudo -u git -H \
+  /usr/bin/env JOBS=10 \
+  bin/parallel-rsync-repos \
+    succes-$(date +%s).log \
+    /home/git/repositories \
+    /mnt/gitlab/repositories
+```
diff --git a/doc/raketasks/list_repos.md b/doc/raketasks/list_repos.md
new file mode 100644
index 0000000000000000000000000000000000000000..476428eb4f5db91c6bfb697669f920082f75572b
--- /dev/null
+++ b/doc/raketasks/list_repos.md
@@ -0,0 +1,30 @@
+# Listing repository directories
+
+You can print a list of all Git repositories on disk managed by
+GitLab with the following command:
+
+```
+# Omnibus
+sudo gitlab-rake gitlab:list_repos
+
+# Source
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:list_repos RAILS_ENV=production
+```
+
+If you only want to list projects with recent activity you can pass
+a date with the 'SINCE' environment variable.  The time you specify
+is parsed by the Rails [TimeZone#parse
+function](http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html#method-i-parse).
+
+```
+# Omnibus
+sudo gitlab-rake gitlab:list_repos SINCE='Sep 1 2015'
+
+# Source
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:list_repos RAILS_ENV=production SINCE='Sep 1 2015'
+```
+
+Note that the projects listed are NOT sorted by activity; they use
+the default ordering of the GitLab Rails application.
diff --git a/features/project/graph.feature b/features/project/graph.feature
index 2acd65aea5fc208e991de70690e0a189163ba043..63793d6f989190409987d206b25e7ccb66d679ab 100644
--- a/features/project/graph.feature
+++ b/features/project/graph.feature
@@ -18,3 +18,8 @@ Feature: Project Graph
     Given project "Shop" has CI enabled
     When I visit project "Shop" CI graph page
     Then page should have CI graphs
+
+  @javascript
+  Scenario: I should see project languages graphs
+    When I visit project "Shop" languages graph page
+    Then page should have languages graphs
diff --git a/features/project/source/browse_files.feature b/features/project/source/browse_files.feature
index e545ea63ca880efe84b78f94826df221ad421702..37f99b37619bfab07d2212696621de6c054b9a92 100644
--- a/features/project/source/browse_files.feature
+++ b/features/project/source/browse_files.feature
@@ -221,3 +221,9 @@ Feature: Project Source Browse Files
     Given I switch ref to fix
     And I visit the fix tree
     Then I see the commit data for a directory with a leading dot
+
+  Scenario: I browse LFS object
+    Given I click on "files/lfs/lfs_object.iso" file in repo
+    Then I should see download link and object size
+    And I should not see lfs pointer details
+    And I should see buttons for allowed commands
diff --git a/features/steps/project/graph.rb b/features/steps/project/graph.rb
index 98f31f3b76a194d854087e70264c45910dc5f24f..b09ec86e5dfa7af77c1334f9b12777f92b0086ac 100644
--- a/features/steps/project/graph.rb
+++ b/features/steps/project/graph.rb
@@ -14,6 +14,15 @@ class Spinach::Features::ProjectGraph < Spinach::FeatureSteps
     visit commits_namespace_project_graph_path(project.namespace, project, "master")
   end
 
+  step 'I visit project "Shop" languages graph page' do
+    visit languages_namespace_project_graph_path(project.namespace, project, "master")
+  end
+
+  step 'page should have languages graphs' do
+    expect(page).to have_content "Ruby 66.63 %"
+    expect(page).to have_content "JavaScript 22.96 %"
+  end
+
   step 'page should have commits graphs' do
     expect(page).to have_content "Commit statistics for master"
     expect(page).to have_content "Commits per day of month"
diff --git a/features/steps/project/source/browse_files.rb b/features/steps/project/source/browse_files.rb
index 05d1346d006993bc99c5927a14192e4950ca7f07..2792174cc93bc8aeab06ced3e1b5e40f9d79cf13 100644
--- a/features/steps/project/source/browse_files.rb
+++ b/features/steps/project/source/browse_files.rb
@@ -305,6 +305,33 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
     expect(page).not_to have_content('Loading commit data...')
   end
 
+  step 'I click on "files/lfs/lfs_object.iso" file in repo' do
+    visit namespace_project_tree_path(@project.namespace, @project, "lfs")
+    click_link 'files'
+    click_link "lfs"
+    click_link "lfs_object.iso"
+  end
+
+  step 'I should see download link and object size' do
+    expect(page).to have_content 'Download (1.5 MB)'
+  end
+
+  step 'I should not see lfs pointer details' do
+    expect(page).not_to have_content 'version https://git-lfs.github.com/spec/v1'
+    expect(page).not_to have_content 'oid sha256:91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897'
+    expect(page).not_to have_content 'size 1575078'
+  end
+
+  step 'I should see buttons for allowed commands' do
+    expect(page).to have_content 'Raw'
+    expect(page).to have_content 'History'
+    expect(page).to have_content 'Permalink'
+    expect(page).not_to have_content 'Edit'
+    expect(page).not_to have_content 'Blame'
+    expect(page).not_to have_content 'Delete'
+    expect(page).not_to have_content 'Replace'
+  end
+
   private
 
   def set_new_content
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index 024aeec2e14bde0d9eb41b052af7d18f5117e59c..1a14d870a4a396e51ea76c0792112913f1248498 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -65,6 +65,18 @@ module API
         DestroyGroupService.new(group, current_user).execute
       end
 
+      # Get a list of projects in this group
+      #
+      # Example Request:
+      #   GET /groups/:id/projects
+      get ":id/projects" do
+        group = find_group(params[:id])
+        projects = group.projects
+        projects = filter_projects(projects)
+        projects = paginate projects
+        present projects, with: Entities::Project
+      end
+
       # Transfer a project to the Group namespace
       #
       # Parameters:
diff --git a/lib/gitlab/ldap/access.rb b/lib/gitlab/ldap/access.rb
index 16ff03c38d4f21736d4429bc38dfbdf2a1487612..c438a3d167b8e1d1ac42d7c7403b0a5eb97f7595 100644
--- a/lib/gitlab/ldap/access.rb
+++ b/lib/gitlab/ldap/access.rb
@@ -37,13 +37,15 @@ module Gitlab
 
           # Block user in GitLab if he/she was blocked in AD
           if Gitlab::LDAP::Person.disabled_via_active_directory?(user.ldap_identity.extern_uid, adapter)
-            user.block unless user.blocked?
+            user.block
             false
           else
             user.activate if user.blocked? && !ldap_config.block_auto_created_users
             true
           end
         else
+          # Block the user if they no longer exist in LDAP/AD
+          user.block 
           false
         end
       rescue
diff --git a/lib/gitlab/lfs/response.rb b/lib/gitlab/lfs/response.rb
index 9be9a65671b2b6f37436eb3220220354cd20e4f8..9d9617761b3b2be1284e30554c4a9904296c87fd 100644
--- a/lib/gitlab/lfs/response.rb
+++ b/lib/gitlab/lfs/response.rb
@@ -220,7 +220,7 @@ module Gitlab
 
       def storage_project(project)
         if project.forked?
-          project.forked_from_project
+          storage_project(project.forked_from_project)
         else
           project
         end
diff --git a/lib/omni_auth/request_forgery_protection.rb b/lib/omni_auth/request_forgery_protection.rb
index 3557522d3c9eaa7e5e1fe8446bd71c9fae4c8861..69155131d8d72b837d68413270b6632f2cb9e4e0 100644
--- a/lib/omni_auth/request_forgery_protection.rb
+++ b/lib/omni_auth/request_forgery_protection.rb
@@ -1,66 +1,21 @@
 # Protects OmniAuth request phase against CSRF.
 
 module OmniAuth
-  # Based on ActionController::RequestForgeryProtection.
-  class RequestForgeryProtection
-    def initialize(env)
-      @env = env
-    end
-
-    def request
-      @request ||= ActionDispatch::Request.new(@env)
-    end
-
-    def session
-      request.session
-    end
-
-    def reset_session
-      request.reset_session
-    end
-
-    def params
-      request.params
-    end
-
-    def call
-      verify_authenticity_token
-    end
+  module RequestForgeryProtection
+    class Controller < ActionController::Base
+      protect_from_forgery with: :exception
 
-    def verify_authenticity_token
-      if !verified_request?
-        Rails.logger.warn "Can't verify CSRF token authenticity" if Rails.logger
-        handle_unverified_request
+      def index
+        head :ok
       end
     end
 
-    private
-
-    def protect_against_forgery?
-      ApplicationController.allow_forgery_protection
-    end
-
-    def request_forgery_protection_token
-      ApplicationController.request_forgery_protection_token
-    end
-
-    def forgery_protection_strategy
-      ApplicationController.forgery_protection_strategy
-    end
-
-    def verified_request?
-      !protect_against_forgery? || request.get? || request.head? ||
-        form_authenticity_token == params[request_forgery_protection_token] ||
-        form_authenticity_token == request.headers['X-CSRF-Token']
-    end
-
-    def handle_unverified_request
-      forgery_protection_strategy.new(self).handle_unverified_request
+    def self.app
+      @app ||= Controller.action(:index)
     end
 
-    # Sets the token value for the current session.
-    def form_authenticity_token
-      session[:_csrf_token] ||= SecureRandom.base64(32)
+    def self.call(env)
+      app.call(env)
     end
   end
 end
diff --git a/lib/tasks/gitlab/git.rake b/lib/tasks/gitlab/git.rake
new file mode 100644
index 0000000000000000000000000000000000000000..65ee430d550ff54c144cfd1d0532f5b74c689e64
--- /dev/null
+++ b/lib/tasks/gitlab/git.rake
@@ -0,0 +1,55 @@
+namespace :gitlab do
+  namespace :git do
+
+    desc "GitLab | Git | Repack"
+    task repack: :environment do
+      failures = perform_git_cmd(%W(git repack -a --quiet), "Repacking repo")
+      if failures.empty?
+        puts "Done".green
+      else
+        output_failures(failures)
+      end
+    end
+
+    desc "GitLab | Git | Run garbage collection on all repos"
+    task gc: :environment do
+      failures = perform_git_cmd(%W(git gc --auto --quiet), "Garbage Collecting")
+      if failures.empty?
+        puts "Done".green
+      else
+        output_failures(failures)
+      end
+    end
+    
+    desc "GitLab | Git | Prune all repos"
+    task prune: :environment do
+      failures = perform_git_cmd(%W(git prune), "Git Prune")
+      if failures.empty?
+        puts "Done".green
+      else
+        output_failures(failures)
+      end
+    end
+
+    def perform_git_cmd(cmd, message)
+      puts "Starting #{message} on all repositories"
+
+      failures = []
+      all_repos do |repo|
+        if system(*cmd, chdir: repo)
+          puts "Performed #{message} at #{repo}"
+        else
+          failures << repo
+        end
+      end
+
+      failures
+    end
+
+    def output_failures(failures)
+      puts "The following repositories reported errors:".red
+      failures.each { |f| puts "- #{f}" }
+    end
+
+  end
+end
diff --git a/lib/tasks/gitlab/import.rake b/lib/tasks/gitlab/import.rake
index c1ee271ae2b23ebeb5582e3c1fe6a2e0fc273966..1c04f47f08ffe2b5e8239b0218e4d148b2740711 100644
--- a/lib/tasks/gitlab/import.rake
+++ b/lib/tasks/gitlab/import.rake
@@ -64,6 +64,8 @@ namespace :gitlab do
 
           if project.persisted?
             puts " * Created #{project.name} (#{repo_path})".green
+            project.update_repository_size
+            project.update_commit_count
           else
             puts " * Failed trying to create #{project.name} (#{repo_path})".red
             puts "   Errors: #{project.errors.messages}".red
diff --git a/lib/tasks/gitlab/list_repos.rake b/lib/tasks/gitlab/list_repos.rake
new file mode 100644
index 0000000000000000000000000000000000000000..c7596e7abcb72d33b1403f84c37a4f43dcf8362c
--- /dev/null
+++ b/lib/tasks/gitlab/list_repos.rake
@@ -0,0 +1,17 @@
+namespace :gitlab do
+  task list_repos: :environment do
+    scope = Project
+    if ENV['SINCE']
+      date = Time.parse(ENV['SINCE'])
+      warn "Listing repositories with activity or changes since #{date}"
+      project_ids = Project.where('last_activity_at > ? OR updated_at > ?', date, date).pluck(:id).sort
+      namespace_ids = Namespace.where(['updated_at > ?', date]).pluck(:id).sort
+      scope = scope.where('id IN (?) OR namespace_id in (?)', project_ids, namespace_ids)
+    end
+    scope.find_each do |project|
+      base = File.join(Gitlab.config.gitlab_shell.repos_path, project.path_with_namespace)
+      puts base + '.git'
+      puts base + '.wiki.git'
+    end
+  end
+end
diff --git a/lib/tasks/gitlab/task_helpers.rake b/lib/tasks/gitlab/task_helpers.rake
index efb863a8764b40b5285832e418b79333c8540a46..ebe516ec879c71e67dff706a173d110ec926c91b 100644
--- a/lib/tasks/gitlab/task_helpers.rake
+++ b/lib/tasks/gitlab/task_helpers.rake
@@ -118,4 +118,12 @@ namespace :gitlab do
       false
     end
   end
+
+  def all_repos
+    IO.popen(%W(find #{Gitlab.config.gitlab_shell.repos_path} -mindepth 2 -maxdepth 2 -type d -name *.git)) do |find|
+      find.each_line do |path|
+        yield path.chomp
+      end
+    end
+  end
 end
diff --git a/spec/controllers/projects/raw_controller_spec.rb b/spec/controllers/projects/raw_controller_spec.rb
index c114f3420212fa740896077efc08fe9be501b3ec..1caa476d37d92c622bfa1d72f5af135e5051e881 100644
--- a/spec/controllers/projects/raw_controller_spec.rb
+++ b/spec/controllers/projects/raw_controller_spec.rb
@@ -33,5 +33,39 @@ describe Projects::RawController do
         expect(response.header['Content-Type']).to eq('image/jpeg')
       end
     end
+
+    context 'lfs object' do
+      let(:id) { 'be93687/files/lfs/lfs_object.iso' }
+      let!(:lfs_object) { create(:lfs_object, oid: '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', size: '1575078') }
+
+      context 'when project has access' do
+        before do
+          public_project.lfs_objects << lfs_object
+          allow_any_instance_of(LfsObjectUploader).to receive(:exists?).and_return(true)
+          allow(controller).to receive(:send_file) { controller.render nothing: true }
+        end
+
+        it 'serves the file' do
+          expect(controller).to receive(:send_file).with("#{Gitlab.config.shared.path}/lfs-objects/91/ef/f75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897", filename: "lfs_object.iso", disposition: 'attachment')
+          get(:show,
+              namespace_id: public_project.namespace.to_param,
+              project_id: public_project.to_param,
+              id: id)
+
+          expect(response.status).to eq(200)
+        end
+      end
+
+      context 'when project does not have access' do
+        it 'does not serve the file' do
+          get(:show,
+              namespace_id: public_project.namespace.to_param,
+              project_id: public_project.to_param,
+              id: id)
+
+          expect(response.status).to eq(404)
+        end
+      end
+    end
   end
 end
diff --git a/spec/features/builds_spec.rb b/spec/features/builds_spec.rb
index 5213ce1099fd0521bfffeac30ce81050aea5c985..1f99a808f8765a79298aee46aa64db7f8372a3a2 100644
--- a/spec/features/builds_spec.rb
+++ b/spec/features/builds_spec.rb
@@ -19,7 +19,7 @@ describe "Builds" do
       end
 
       it { expect(page).to have_content 'Running' }
-      it { expect(page).to have_content 'Cancel all' }
+      it { expect(page).to have_content 'Cancel running' }
       it { expect(page).to have_content @build.short_sha }
       it { expect(page).to have_content @build.ref }
       it { expect(page).to have_content @build.name }
@@ -32,7 +32,7 @@ describe "Builds" do
       end
 
       it { expect(page).to have_content 'No builds to show' }
-      it { expect(page).to have_content 'Cancel all' }
+      it { expect(page).to have_content 'Cancel running' }
     end
 
     context "All builds" do
@@ -45,7 +45,7 @@ describe "Builds" do
       it { expect(page).to have_content @build.short_sha }
       it { expect(page).to have_content @build.ref }
       it { expect(page).to have_content @build.name }
-      it { expect(page).to_not have_content 'Cancel all' }
+      it { expect(page).to_not have_content 'Cancel running' }
     end
   end
 
@@ -53,11 +53,11 @@ describe "Builds" do
     before do
       @build.run!
       visit namespace_project_builds_path(@gl_project.namespace, @gl_project)
-      click_link "Cancel all"
+      click_link "Cancel running"
     end
 
     it { expect(page).to have_content 'No builds to show' }
-    it { expect(page).to_not have_content 'Cancel all' }
+    it { expect(page).to_not have_content 'Cancel running' }
   end
 
   describe "GET /:project/builds/:id" do
diff --git a/spec/javascripts/fixtures/merge_request_tabs.html.haml b/spec/javascripts/fixtures/merge_request_tabs.html.haml
index 7624a713948aeea7de1a67e91b888727a275f9a2..68678c3d7e30396a5e71d6bdd520ba586dc9a661 100644
--- a/spec/javascripts/fixtures/merge_request_tabs.html.haml
+++ b/spec/javascripts/fixtures/merge_request_tabs.html.haml
@@ -1,12 +1,12 @@
 %ul.nav.nav-tabs.merge-request-tabs
   %li.notes-tab
-    %a{href: '/foo/bar/merge_requests/1', data: {target: '#notes', action: 'notes', toggle: 'tab'}}
+    %a{href: '/foo/bar/merge_requests/1', data: {target: 'div#notes', action: 'notes', toggle: 'tab'}}
       Discussion
   %li.commits-tab
-    %a{href: '/foo/bar/merge_requests/1/commits', data: {target: '#commits', action: 'commits', toggle: 'tab'}}
+    %a{href: '/foo/bar/merge_requests/1/commits', data: {target: 'div#commits', action: 'commits', toggle: 'tab'}}
       Commits
   %li.diffs-tab
-    %a{href: '/foo/bar/merge_requests/1/diffs', data: {target: '#diffs', action: 'diffs', toggle: 'tab'}}
+    %a{href: '/foo/bar/merge_requests/1/diffs', data: {target: 'div#diffs', action: 'diffs', toggle: 'tab'}}
       Diffs
 
 .tab-content
diff --git a/spec/lib/gitlab/ldap/access_spec.rb b/spec/lib/gitlab/ldap/access_spec.rb
index c38f212b405171114c8fe3411efde5867904036a..960547a0ad78db2fa0438a9955b6e99ba40ccd8d 100644
--- a/spec/lib/gitlab/ldap/access_spec.rb
+++ b/spec/lib/gitlab/ldap/access_spec.rb
@@ -13,6 +13,11 @@ describe Gitlab::LDAP::Access do
       end
 
       it { is_expected.to be_falsey }
+      
+      it 'should block user in GitLab' do
+        access.allowed?
+        expect(user).to be_blocked
+      end
     end
 
     context 'when the user is found' do
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index 13cced81875c59f7680a92082e72c9c89542a56d..4cfa49d15666d06deeee90d6ba0181acde3978c5 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -10,6 +10,8 @@ describe API::API, api: true  do
   let(:avatar_file_path) { File.join(Rails.root, 'spec', 'fixtures', 'banana_sample.gif') }
   let!(:group1) { create(:group, avatar: File.open(avatar_file_path)) }
   let!(:group2) { create(:group) }
+  let!(:project1) { create(:project, namespace: group1) }
+  let!(:project2) { create(:project, namespace: group2) }
 
   before do
     group1.add_owner(user1)
@@ -67,7 +69,7 @@ describe API::API, api: true  do
       it "should return any existing group" do
         get api("/groups/#{group2.id}", admin)
         expect(response.status).to eq(200)
-        json_response['name'] == group2.name
+        expect(json_response['name']).to eq(group2.name)
       end
 
       it "should not return a non existing group" do
@@ -80,7 +82,7 @@ describe API::API, api: true  do
       it 'should return any existing group' do
         get api("/groups/#{group1.path}", admin)
         expect(response.status).to eq(200)
-        json_response['name'] == group2.name
+        expect(json_response['name']).to eq(group1.name)
       end
 
       it 'should not return a non existing group' do
@@ -95,6 +97,59 @@ describe API::API, api: true  do
     end
   end
 
+  describe "GET /groups/:id/projects" do
+    context "when authenticated as user" do
+      it "should return the group's projects" do
+        get api("/groups/#{group1.id}/projects", user1)
+        expect(response.status).to eq(200)
+        expect(json_response.length).to eq(1)
+        expect(json_response.first['name']).to eq(project1.name)
+      end
+
+      it "should not return a non existing group" do
+        get api("/groups/1328/projects", user1)
+        expect(response.status).to eq(404)
+      end
+
+      it "should not return a group not attached to user1" do
+        get api("/groups/#{group2.id}/projects", user1)
+        expect(response.status).to eq(403)
+      end
+    end
+
+    context "when authenticated as admin" do
+      it "should return any existing group" do
+        get api("/groups/#{group2.id}/projects", admin)
+        expect(response.status).to eq(200)
+        expect(json_response.length).to eq(1)
+        expect(json_response.first['name']).to eq(project2.name)
+      end
+
+      it "should not return a non existing group" do
+        get api("/groups/1328/projects", admin)
+        expect(response.status).to eq(404)
+      end
+    end
+
+    context 'when using group path in URL' do
+      it 'should return any existing group' do
+        get api("/groups/#{group1.path}/projects", admin)
+        expect(response.status).to eq(200)
+        expect(json_response.first['name']).to eq(project1.name)
+      end
+
+      it 'should not return a non existing group' do
+        get api('/groups/unknown/projects', admin)
+        expect(response.status).to eq(404)
+      end
+
+      it 'should not return a group not attached to user1' do
+        get api("/groups/#{group2.path}/projects", user1)
+        expect(response.status).to eq(403)
+      end
+    end
+  end
+
   describe "POST /groups" do
     context "when authenticated as user without group permissions" do
       it "should not create group" do
diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb
index 78b9a0f42fa6dfb80594bba2778be67ac4e6c775..4f4743bff6d957d5232aa390962752e5996298b6 100644
--- a/spec/support/test_env.rb
+++ b/spec/support/test_env.rb
@@ -12,6 +12,7 @@ module TestEnv
     'fix'              => '48f0be4',
     'improve/awesome'  => '5937ac0',
     'markdown'         => '0ed8c6c',
+    'lfs'              => 'be93687',
     'master'           => '5937ac0',
     "'test'"           => 'e56497b',
   }