diff --git a/CHANGELOG b/CHANGELOG
index 2d05a51e77d8df5559a6c323e866e3124e5244e2..65344736e9c19fb53582decbc354d5de76a5cf66 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,10 @@
+v 5.0.0
+  - replaced gitolite with gitlab-shell
+
+v 4.2.0
+  - User show page. Via /u/username
+  - Show help contents on pages for better navigation
+
 v 4.1.0
   - Optional Sign-Up
   - Discussions
diff --git a/Gemfile b/Gemfile
index 96b5bb6a074f2b86d8748ff4072b51418c07133f..23adddced7569138fe9d5b13462202f5b374f4b6 100644
--- a/Gemfile
+++ b/Gemfile
@@ -32,9 +32,6 @@ gem 'gitlab_omniauth-ldap', '1.0.2', require: "omniauth-ldap"
 # Dump db to yml file. Mostly used to migrate from sqlite to mysql
 gem 'gitlab_yaml_db', '1.0.0', require: "yaml_db"
 
-# Gitolite client (for work with gitolite-admin repo)
-gem "gitolite", '1.1.0'
-
 # Syntax highlighter
 gem "pygments.rb",  git: "https://github.com/gitlabhq/pygments.rb.git", branch: "master"
 
diff --git a/Gemfile.lock b/Gemfile.lock
index 7bf31c95babd5aefafa42bc586678740f6993e40..d91dbf7e82624f2bc7f3e116e7fbd2773e9cf706 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -107,7 +107,6 @@ GEM
       coderay (>= 1.0.0)
       erubis (>= 2.7.0)
     binding_of_caller (0.6.8)
-    blankslate (3.1.2)
     bootstrap-sass (2.2.1.1)
       sass (~> 3.2)
     builder (3.0.4)
@@ -195,10 +194,6 @@ GEM
       pyu-ruby-sasl (~> 0.0.3.1)
       rubyntlm (~> 0.1.1)
     gitlab_yaml_db (1.0.0)
-    gitolite (1.1.0)
-      gratr19 (~> 0.4.4.1)
-      grit (~> 2.5.0)
-      hashery (~> 1.5.0)
     grape (0.2.2)
       activesupport
       hashie (~> 1.2)
@@ -208,7 +203,6 @@ GEM
       rack-accept
       rack-mount
       virtus
-    gratr19 (0.4.4.1)
     growl (1.0.3)
     guard (1.5.4)
       listen (>= 0.4.2)
@@ -227,8 +221,6 @@ GEM
       activesupport (>= 3.1, < 4.1)
       haml (~> 3.1)
       railties (>= 3.1, < 4.1)
-    hashery (1.5.0)
-      blankslate
     hashie (1.2.0)
     hike (1.2.1)
     http_parser.rb (0.5.3)
@@ -497,7 +489,6 @@ DEPENDENCIES
   gitlab_meta (= 4.0)
   gitlab_omniauth-ldap (= 1.0.2)
   gitlab_yaml_db (= 1.0.0)
-  gitolite (= 1.1.0)
   grack!
   grape (~> 0.2.1)
   grit!
diff --git a/Procfile b/Procfile
index 21dfade1d8a8c469aff48b4d779e722d2994a336..1a4145cc7d3b5a7d45a1a748d030cfc2c8553689 100644
--- a/Procfile
+++ b/Procfile
@@ -1,2 +1,2 @@
 web: bundle exec unicorn_rails -p $PORT
-worker: bundle exec sidekiq -q post_receive,mailer,system_hook,common,default
+worker: bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,common,default,gitolite
diff --git a/README.md b/README.md
index 1a43be134da284a96be9f02324fbf0f8daa482c5..ee029f9bfcb6875d8ccc96338c7b433c39323b5f 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
 
 GitLab is a free project and repository management application
 
-![CI](http://ci.gitlab.org/projects/1/status?ref=master)
+[![CI](http://ci.gitlab.org/projects/1/status?ref=master)](http://ci.gitlab.org/projects/1?ref=master)
 
 ## Application details
 
diff --git a/ROADMAP.md b/ROADMAP.md
index acfd2eded973edfa616f3022557db83d8839d6d4..d148b518b0ee34028fcbcaa96874a335d48c0dda 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -1,13 +1,12 @@
 ## GitLab Roadmap
 
-### v4.3 March 22
+### v5.0 March 22
 
-* Jenkins CI integration service
+* Replace gitolite with gitlab-shell 
 * Usability improvements
 * Notification improvements
 
 ### v4.2 February 22
 
-* Campfire integration service
 * Teams
 
diff --git a/VERSION b/VERSION
index 87db9036a822108fd68f9be0ad2186f2760e1155..0ceadf72ef75f83a2758b5be089772584a167cd2 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-4.1.0rc1
+5.0.0pre
diff --git a/app/assets/images/home_icon.PNG b/app/assets/images/home_icon.PNG
deleted file mode 100644
index b1d60d5935760d7f7c448a6ea3e7270fe405a664..0000000000000000000000000000000000000000
Binary files a/app/assets/images/home_icon.PNG and /dev/null differ
diff --git a/app/assets/images/icon-attachment.png b/app/assets/images/icon-attachment.png
deleted file mode 100644
index 168ad8dce3765ac98968def2101ba9f298e9f637..0000000000000000000000000000000000000000
Binary files a/app/assets/images/icon-attachment.png and /dev/null differ
diff --git a/app/assets/images/onion_skin_sprites.gif b/app/assets/images/onion_skin_sprites.gif
new file mode 100644
index 0000000000000000000000000000000000000000..85d20260edcad0f13825b8b70d930133c9e54beb
Binary files /dev/null and b/app/assets/images/onion_skin_sprites.gif differ
diff --git a/app/assets/images/swipemode_sprites.gif b/app/assets/images/swipemode_sprites.gif
new file mode 100644
index 0000000000000000000000000000000000000000..327b3c31ffd3547bbc0e4b9fa7c81c4bcfdfc59e
Binary files /dev/null and b/app/assets/images/swipemode_sprites.gif differ
diff --git a/app/assets/javascripts/commit/file.js.coffee b/app/assets/javascripts/commit/file.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..a45ee58d1b4924ce3c26ceabb43e066c677de4a5
--- /dev/null
+++ b/app/assets/javascripts/commit/file.js.coffee
@@ -0,0 +1,7 @@
+class CommitFile
+  
+  constructor: (file) ->
+    if $('.image', file).length
+      new ImageFile(file)
+        
+this.CommitFile = CommitFile
\ No newline at end of file
diff --git a/app/assets/javascripts/commit/image-file.js.coffee b/app/assets/javascripts/commit/image-file.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..f901a9e28ffeefebc42593bb07b1f9880efa8512
--- /dev/null
+++ b/app/assets/javascripts/commit/image-file.js.coffee
@@ -0,0 +1,128 @@
+class ImageFile
+
+  # Width where images must fits in, for 2-up this gets divided by 2
+  @availWidth = 900
+  @viewModes = ['two-up', 'swipe']
+
+  constructor: (@file) ->
+    # Determine if old and new file has same dimensions, if not show 'two-up' view
+    this.requestImageInfo $('.two-up.view .frame.deleted img', @file), (deletedWidth, deletedHeight) =>
+      this.requestImageInfo $('.two-up.view .frame.added img', @file), (width, height) =>
+        if width == deletedWidth && height == deletedHeight
+          this.initViewModes()
+        else
+          this.initView('two-up')
+
+  initViewModes: ->
+    viewMode = ImageFile.viewModes[0]
+
+    $('.view-modes', @file).removeClass 'hide'
+    $('.view-modes-menu', @file).on 'click', 'li', (event) =>
+      unless $(event.currentTarget).hasClass('active')
+        this.activateViewMode(event.currentTarget.className)
+
+    this.activateViewMode(viewMode)
+
+  activateViewMode: (viewMode) ->
+    $('.view-modes-menu li', @file)
+      .removeClass('active')
+      .filter(".#{viewMode}").addClass 'active'
+    $(".view:visible:not(.#{viewMode})", @file).fadeOut 200, =>
+      $(".view.#{viewMode}", @file).fadeIn(200)
+      this.initView viewMode
+
+  initView: (viewMode) ->
+    this.views[viewMode].call(this)
+
+  prepareFrames = (view) ->
+    maxWidth = 0
+    maxHeight = 0
+    $('.frame', view).each (index, frame) =>
+      width = $(frame).width()
+      height = $(frame).height()
+      maxWidth = if width > maxWidth then width else maxWidth
+      maxHeight = if height > maxHeight then height else maxHeight
+    .css
+      width: maxWidth
+      height: maxHeight
+    
+    [maxWidth, maxHeight]
+
+  views: 
+    'two-up': ->
+      $('.two-up.view .wrap', @file).each (index, wrap) =>
+        $('img', wrap).each ->
+          currentWidth = $(this).width()
+          if currentWidth > ImageFile.availWidth / 2
+            $(this).width ImageFile.availWidth / 2
+
+        this.requestImageInfo $('img', wrap), (width, height) ->
+          $('.image-info .meta-width', wrap).text "#{width}px"
+          $('.image-info .meta-height', wrap).text "#{height}px"
+          $('.image-info', wrap).removeClass('hide')
+
+    'swipe': ->
+      maxWidth = 0
+      maxHeight = 0
+
+      $('.swipe.view', @file).each (index, view) =>
+
+        [maxWidth, maxHeight] = prepareFrames(view)
+
+        $('.swipe-frame', view).css
+          width: maxWidth + 16
+          height: maxHeight + 28
+
+        $('.swipe-wrap', view).css
+          width: maxWidth + 1
+          height: maxHeight + 2
+
+        $('.swipe-bar', view).css
+          left: 0
+        .draggable
+          axis: 'x'
+          containment: 'parent'
+          drag: (event) ->
+            $('.swipe-wrap', view).width (maxWidth + 1) - $(this).position().left
+          stop: (event) ->
+            $('.swipe-wrap', view).width (maxWidth + 1) - $(this).position().left
+
+    'onion-skin': ->
+      maxWidth = 0
+      maxHeight = 0
+
+      dragTrackWidth = $('.drag-track', @file).width() - $('.dragger', @file).width()
+
+      $('.onion-skin.view', @file).each (index, view) =>
+
+        [maxWidth, maxHeight] = prepareFrames(view)
+
+        $('.onion-skin-frame', view).css
+          width: maxWidth + 16
+          height: maxHeight + 28
+
+        $('.swipe-wrap', view).css
+          width: maxWidth + 1
+          height: maxHeight + 2
+        
+        $('.dragger', view).css
+          left: dragTrackWidth
+        .draggable
+          axis: 'x'
+          containment: 'parent'
+          drag: (event) ->
+            $('.frame.added', view).css('opacity', $(this).position().left / dragTrackWidth)
+          stop: (event) ->
+            $('.frame.added', view).css('opacity', $(this).position().left / dragTrackWidth)
+        
+      
+
+  requestImageInfo: (img, callback) ->
+    domImg = img.get(0)
+    if domImg.complete
+      callback.call(this, domImg.naturalWidth, domImg.naturalHeight)
+    else
+      img.on 'load', =>
+        callback.call(this, domImg.naturalWidth, domImg.naturalHeight)
+
+this.ImageFile = ImageFile
\ No newline at end of file
diff --git a/app/assets/javascripts/commits.js b/app/assets/javascripts/commits.js
deleted file mode 100644
index b31fe485896865d09f0104af225fac248a144886..0000000000000000000000000000000000000000
--- a/app/assets/javascripts/commits.js
+++ /dev/null
@@ -1,59 +0,0 @@
-var CommitsList = {
-  ref:null,
-  limit:0,
-  offset:0,
-  disable:false,
-
-  init:
-    function(ref, limit) {
-      $(".day-commits-table li.commit").live('click', function(e){
-        if(e.target.nodeName != "A") {
-          location.href = $(this).attr("url");
-          e.stopPropagation();
-          return false;
-        }
-      });
-
-      this.ref=ref;
-      this.limit=limit;
-      this.offset=limit;
-      this.initLoadMore();
-      $('.loading').show();
-    },
-
-  getOld:
-    function() {
-      $('.loading').show();
-      $.ajax({
-        type: "GET",
-        url: location.href,
-        data: "limit=" + this.limit + "&offset=" + this.offset + "&ref=" + this.ref,
-        complete: function(){ $('.loading').hide()},
-        dataType: "script"});
-    },
-
-  append:
-    function(count, html) {
-      $("#commits_list").append(html);
-      if(count > 0) {
-        this.offset += count;
-      } else { 
-        this.disable = true;
-      }
-    },
-
-  initLoadMore:
-    function() {
-      $(document).endlessScroll({
-        bottomPixels: 400,
-        fireDelay: 1000,
-        fireOnce:true,
-        ceaseFire: function() { 
-          return CommitsList.disable;
-        },
-        callback: function(i) {
-          CommitsList.getOld();
-        }
-      });
-    }
-}
diff --git a/app/assets/javascripts/commits.js.coffee b/app/assets/javascripts/commits.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..47d6fcf80895f1df1b11512b92866fa2ebe4b3b9
--- /dev/null
+++ b/app/assets/javascripts/commits.js.coffee
@@ -0,0 +1,54 @@
+class CommitsList
+  @data =
+    ref: null
+    limit: 0
+    offset: 0
+  @disable = false
+  
+  @showProgress: ->
+    $('.loading').show()
+    
+  @hideProgress: ->
+    $('.loading').hide()
+  
+  @init: (ref, limit) ->
+    $(".day-commits-table li.commit").live 'click', (event) ->
+      if event.target.nodeName != "A"
+        location.href = $(this).attr("url")
+        e.stopPropagation()
+        return false
+
+    @data.ref = ref
+    @data.limit = limit
+    @data.offset = limit
+    
+    this.initLoadMore()
+    this.showProgress();
+
+  @getOld: ->
+    this.showProgress()
+    $.ajax
+      type: "GET"
+      url: location.href
+      data: @data
+      complete: this.hideProgress
+      dataType: "script"
+
+  @append: (count, html) ->
+    $("#commits-list").append(html)
+    if count > 0
+      @data.offset += count
+    else
+      @disable = true
+  
+  @initLoadMore: -> 
+    $(document).endlessScroll
+      bottomPixels: 400
+      fireDelay: 1000
+      fireOnce: true
+      ceaseFire: =>
+        @disable
+      callback: =>
+        this.getOld()
+
+this.CommitsList = CommitsList
\ No newline at end of file
diff --git a/app/assets/javascripts/dashboard.js.coffee b/app/assets/javascripts/dashboard.js.coffee
index f15d09dd475bbf900e4054d9d0df24a9f5a94f9e..6171e0d50fdc0fcc89641c5d95018c3d4b0b324e 100644
--- a/app/assets/javascripts/dashboard.js.coffee
+++ b/app/assets/javascripts/dashboard.js.coffee
@@ -4,11 +4,11 @@ window.dashboardPage = ->
     event.preventDefault()
     toggleFilter $(this)
     reloadActivities()
-    
+
 reloadActivities = ->
   $(".content_list").html ''
   Pager.init 20, true
-  
+
 toggleFilter = (sender) ->
   sender.parent().toggleClass "inactive"
   event_filters = $.cookie("event_filter")
@@ -17,11 +17,11 @@ toggleFilter = (sender) ->
     event_filters = event_filters.split(",")
   else
     event_filters = new Array()
-    
+
   index = event_filters.indexOf(filter)
   if index is -1
     event_filters.push filter
   else
     event_filters.splice index, 1
-  
+
   $.cookie "event_filter", event_filters.join(",")
diff --git a/app/assets/javascripts/merge_requests.js.coffee b/app/assets/javascripts/merge_requests.js.coffee
index 9c9cc6132b354d9d0220c6ecc1bb1102f9d12bca..65ed817c7c6ee0b76ec265eab10bdbff5ed30be7 100644
--- a/app/assets/javascripts/merge_requests.js.coffee
+++ b/app/assets/javascripts/merge_requests.js.coffee
@@ -1,6 +1,6 @@
 #
 # * Filter merge requests
-# 
+#
 @merge_requestsPage = ->
   $('#assignee_id').chosen()
   $('#milestone_id').chosen()
@@ -8,16 +8,16 @@
     $(this).closest('form').submit()
 
 class MergeRequest
-  
+
   constructor: (@opts) ->
     this.$el = $('.merge-request')
     @diffs_loaded = false
     @commits_loaded = false
-    
+
     this.activateTab(@opts.action)
-    
+
     this.bindEvents()
-    
+
     this.initMergeWidget()
     this.$('.show-all-commits').on 'click', =>
       this.showAllCommits()
@@ -28,7 +28,7 @@ class MergeRequest
 
   initMergeWidget: ->
     this.showState( @opts.current_state )
-    
+
     if this.$('.automerge_widget').length and @opts.check_enable
       $.get @opts.url_to_automerge_check, (data) =>
         this.showState( data.state )
@@ -42,12 +42,12 @@ class MergeRequest
   bindEvents: ->
     this.$('.nav-tabs').on 'click', 'a', (event) =>
       a = $(event.currentTarget)
-      
+
       href = a.attr('href')
       History.replaceState {path: href}, document.title, href
-      
+
       event.preventDefault()
-      
+
     this.$('.nav-tabs').on 'click', 'li', (event) =>
       this.activateTab($(event.currentTarget).data('action'))
 
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index 8a7e08dd0e8f30ce06968184679f865c3895cf01..919c6b7f4a2dcb3c4de41dc37d3099825e822f68 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -20,12 +20,12 @@ var NoteList = {
 
     if(NoteList.reversed) {
       var form = $(".js-main-target-form");
-      form.find(".buttons, .note_options").hide();
+      form.find(".note-form-actions").hide();
       var textarea = form.find(".js-note-text");
       textarea.css("height", "40px");
       textarea.on("focus", function(){
         textarea.css("height", "80px");
-        form.find(".buttons, .note_options").show();
+        form.find(".note-form-actions").show();
       });
     }
 
diff --git a/app/assets/javascripts/pager.js b/app/assets/javascripts/pager.js
deleted file mode 100644
index 7edd6bd61860aa29b0994c451e5c73bfcd848d92..0000000000000000000000000000000000000000
--- a/app/assets/javascripts/pager.js
+++ /dev/null
@@ -1,56 +0,0 @@
-var Pager = {
-  limit:0,
-  offset:0,
-  disable:false,
-
-  init:
-    function(limit, preload) {
-      this.limit=limit;
-
-      if(preload) { 
-        this.offset = 0;
-        this.getOld();
-      } else { 
-        this.offset = limit;
-      }
-
-      this.initLoadMore();
-    },
-
-  getOld:
-    function() {
-      $('.loading').show();
-      $.ajax({
-        type: "GET",
-        url: location.href,
-        data: "limit=" + this.limit + "&offset=" + this.offset,
-        complete: function(){ $('.loading').hide()},
-        dataType: "script"});
-    },
-
-  append:
-    function(count, html) {
-      $(".content_list").append(html);
-      if(count > 0) {
-        this.offset += count;
-      } else { 
-        this.disable = true;
-      }
-    },
-
-  initLoadMore:
-    function() {
-      $(document).endlessScroll({
-        bottomPixels: 400,
-        fireDelay: 1000,
-        fireOnce:true,
-        ceaseFire: function() { 
-          return Pager.disable;
-        },
-        callback: function(i) {
-          $('.loading').show();
-          Pager.getOld();
-        }
-     });
-    }
-}
diff --git a/app/assets/javascripts/pager.js.coffee b/app/assets/javascripts/pager.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..5f606acdf9cc523c8f47eb1a03ca0e58e3d9fc6f
--- /dev/null
+++ b/app/assets/javascripts/pager.js.coffee
@@ -0,0 +1,42 @@
+@Pager =
+  limit: 0
+  offset: 0
+  disable: false
+  init: (limit, preload) ->
+    @limit = limit
+    if preload
+      @offset = 0
+      @getOld()
+    else
+      @offset = limit
+    @initLoadMore()
+
+  getOld: ->
+    $(".loading").show()
+    $.ajax
+      type: "GET"
+      url: location.href
+      data: "limit=" + @limit + "&offset=" + @offset
+      complete: ->
+        $(".loading").hide()
+
+      dataType: "script"
+
+  append: (count, html) ->
+    $(".content_list").append html
+    if count > 0
+      @offset += count
+    else
+      @disable = true
+
+  initLoadMore: ->
+    $(document).endlessScroll
+      bottomPixels: 400
+      fireDelay: 1000
+      fireOnce: true
+      ceaseFire: ->
+        Pager.disable
+
+      callback: (i) ->
+        $(".loading").show()
+        Pager.getOld()
diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss
index db077048b6cf8283420984a9caf1acb8eaf7f7de..c9a11d0a1acf5efce28dc524998701cd7324218c 100644
--- a/app/assets/stylesheets/common.scss
+++ b/app/assets/stylesheets/common.scss
@@ -1,5 +1,5 @@
 html {
-  overflow-y: scroll; 
+  overflow-y: scroll;
 }
 
 /** LAYOUT **/
@@ -277,8 +277,20 @@ p.time {
   }
 }
 
+.search-holder {
+  label, input {
+     height: 30px;
+     padding: 0;
+     font-size: 14px;
+  }
+  label {
+    line-height: 30px;
+    color: #666;
+  }
+}
+
 .highlight_word {
-  background: #EEDC94;
+  border-bottom: 2px solid #F90;
 }
 
 .status_info {
@@ -326,10 +338,6 @@ li.note {
     li {
       border-bottom:none !important;
     }
-    .file {
-      padding-left: 20px;
-      background:url("icon-attachment.png") no-repeat left center;
-    }
   }
 }
 
diff --git a/app/assets/stylesheets/gitlab_bootstrap.scss b/app/assets/stylesheets/gitlab_bootstrap.scss
index f53e0e50bab2cb1343291e489a2dc82d3ca1f99d..2ad1bf944a94bdcaa170c412716893936fd79951 100644
--- a/app/assets/stylesheets/gitlab_bootstrap.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap.scss
@@ -17,6 +17,8 @@ $baseLineHeight: 18px !default;
 @import "gitlab_bootstrap/variables.scss";
 @import "gitlab_bootstrap/fonts.scss";
 @import "gitlab_bootstrap/mixins.scss";
+@import "gitlab_bootstrap/avatar.scss";
+@import "gitlab_bootstrap/nav.scss";
 @import "gitlab_bootstrap/common.scss";
 @import "gitlab_bootstrap/typography.scss";
 @import "gitlab_bootstrap/buttons.scss";
diff --git a/app/assets/stylesheets/gitlab_bootstrap/avatar.scss b/app/assets/stylesheets/gitlab_bootstrap/avatar.scss
new file mode 100644
index 0000000000000000000000000000000000000000..de1fb1551bf74da2c74f48044b6d5179acf4ffce
--- /dev/null
+++ b/app/assets/stylesheets/gitlab_bootstrap/avatar.scss
@@ -0,0 +1,8 @@
+/** AVATARS **/
+img.avatar { float: left; margin-right: 12px; width: 40px; border: 1px solid #ddd; padding: 1px; }
+img.avatar.s16 { width: 16px; height: 16px; margin-right: 6px; }
+img.avatar.s24 { width: 24px; height: 24px; margin-right: 8px; }
+img.avatar.s32 { width: 32px; height: 32px; margin-right: 10px; }
+img.avatar.s90 { width: 90px; height: 90px; margin-right: 15px; }
+img.lil_av { padding-left: 4px; padding-right: 3px; }
+img.small { width: 80px; }
diff --git a/app/assets/stylesheets/gitlab_bootstrap/blocks.scss b/app/assets/stylesheets/gitlab_bootstrap/blocks.scss
index 8cb1c045778ef3aa8b990c6fae0fc34fe4dbbbdd..4d1b64463629168abed98373526e8a5946afc12a 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/blocks.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/blocks.scss
@@ -95,7 +95,11 @@
 
     form {
       margin-bottom: 0;
-      margin-top: 3px;
+      margin-top: 0;
+    }
+
+    .btn-tiny {
+      @include box-shadow(0 0px 0px 1px #f1f1f1);
     }
 
     .nav-pills {
diff --git a/app/assets/stylesheets/gitlab_bootstrap/buttons.scss b/app/assets/stylesheets/gitlab_bootstrap/buttons.scss
index 674481e2cd243528a59ce04b2fcceaaa1e6584ae..03497e32d267c1c9dd4b4282dce7d59fdcd83a89 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/buttons.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/buttons.scss
@@ -1,17 +1,16 @@
 .btn {
-  @include linear-gradient(#f7f7f7, #d5d5d5);
+  @include linear-gradient(#f1f1f1, #e1e1e1);
+  text-shadow: 0 1px 1px #FFF;
   border-color: #BBB;
+
   &:hover {
-    @include bg-gray-gradient;
-    border-color: #bbb;
+    background: #f1f1f1;
+    @include linear-gradient(#fAfAfA, #f1f1f1);
+    border-color: #AAA;
     color: #333;
   }
 
-  &.btn-white {
-    background: #FFF;
-  }
-
-  &.primary {
+  &.btn-primary {
     background: #2a79A3;
     @include linear-gradient(#47A7b7, #2585b5);
     border-color: #2A79A3;
@@ -58,21 +57,18 @@
     }
   }
 
-  &.save-btn {
+  &.btn-create {
     @extend .wide;
-    @extend .primary;
+    @extend .success;
   }
 
-  &.cancel-btn {
-    float: right;
-  }
-
-  &.wide {
-    padding-left: 30px;
-    padding-right: 30px;
+  &.btn-save {
+    @extend .wide;
+    @extend .btn-primary;
   }
 
-  &.danger {
+  &.btn-close,
+  &.btn-remove {
     @extend .btn-danger;
     border-color: #BD362F;
 
@@ -82,8 +78,13 @@
     }
   }
 
-  &.danger {
-    @extend .btn-danger;
+  &.btn-cancel {
+    float: right;
+  }
+
+  &.wide {
+    padding-left: 20px;
+    padding-right: 20px;
   }
 
   &.small {
@@ -95,7 +96,7 @@
     background-color: #ccc;
   }
 
-  &.very_small {
+  &.btn-tiny {
     font-size: 11px;
     padding: 2px 6px;
     line-height: 16px;
diff --git a/app/assets/stylesheets/gitlab_bootstrap/common.scss b/app/assets/stylesheets/gitlab_bootstrap/common.scss
index 2b3d14abda8b9c39cc46d110a7a4052c396857d1..cb292bc711fa14123278a3e0bf3590752ebcd97b 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/common.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/common.scss
@@ -9,7 +9,6 @@
 
 /** COMMON CLASSES **/
 .left { float:left }
-.right { float:right!important }
 .append-bottom-10 { margin-bottom:10px }
 .append-bottom-20 { margin-bottom:20px }
 .prepend-top-10 { margin-top:10px }
@@ -22,79 +21,13 @@
 .light { color: #888 }
 .tiny { font-weight: normal }
 
-/** PILLS & TABS**/
-.nav-pills {
-  .active a {
-    background: $primary_color;
-  }
-
-  > li > a {
-    @include border-radius(0);
-  }
-  &.nav-stacked {
-    > li > a {
-      border-left: 4px solid #EEE;
-      padding: 12px;
-    }
-    > .active > a {
-      border-color: #29B;
-      border-radius: 0;
-      background: #F1F1F1;
-      color: $style_color;
-      font-weight: bold;
-    }
-  }
-}
-
-.nav-pills > .active > a > i[class^="icon-"] { background: inherit; }
-
-
-
-/**
- * nav-tabs
- *
- */
-.nav-tabs > li > a, .nav-pills > li > a { color: $style_color; }
-.nav.nav-tabs {
-  li {
-    > a {
-      padding: 8px 20px;
-      margin-right: 7px;
-      line-height: 20px;
-      border-color: #EEE;
-      color: #888;
-      border-bottom: 1px solid #ddd;
-      .badge {
-        background-color: #eee;
-        color: #888;
-        text-shadow: 0 1px 1px #fff;
-      }
-      i[class^="icon-"] {
-        line-height: 14px;
-      }
-    }
-    &.active {
-      > a {
-        border-color: #CCC;
-        border-bottom: 1px solid #fff;
-        color: #333;
-      }
-    }
-  }
-}
 
 /** ALERT MESSAGES **/
-.alert-message { @extend .alert; }
-.alert-messag.success { @extend .alert-success; }
-.alert-message.error { @extend .alert-error; }
-
-/** AVATARS **/
-img.avatar { float: left; margin-right: 12px; width: 40px; border: 1px solid #ddd; padding: 1px; }
-img.avatar.s16 { width: 16px; height: 16px; margin-right: 6px; }
-img.avatar.s24 { width: 24px; height: 24px; margin-right: 8px; }
-img.avatar.s32 { width: 32px; height: 32px; margin-right: 10px; }
-img.lil_av { padding-left: 4px; padding-right: 3px; }
-img.small { width: 80px; }
+.alert.alert-disabled {
+  background: #EEE;
+  color: #777;
+  border-color: #DDD;
+}
 
 /** HELPERS **/
 .nothing_here_message {
diff --git a/app/assets/stylesheets/gitlab_bootstrap/files.scss b/app/assets/stylesheets/gitlab_bootstrap/files.scss
index 865a10e1fd7a13f0121a32529d8da08721cf7fcb..279cfcd2103132c3dd6938090f3c640045d19957 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/files.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/files.scss
@@ -135,7 +135,7 @@
         pre {
           border: none;
           border-radius: 0;
-          font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
+          font-family: $monospace_font;
           font-size: 12px !important;
           line-height: 16px !important;
           margin: 0;
diff --git a/app/assets/stylesheets/gitlab_bootstrap/fonts.scss b/app/assets/stylesheets/gitlab_bootstrap/fonts.scss
index b4217fa9cfa7f2151790533d285a82b3519fe75b..a0c9a6c7b8aba9d7eeb6fa616bfe5a6bb21667c5 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/fonts.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/fonts.scss
@@ -4,4 +4,4 @@
 }
 
 /** Typo **/
-$monospace: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono', 'lucida console', monospace;
+$monospace_font: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono', 'lucida console', monospace;
diff --git a/app/assets/stylesheets/gitlab_bootstrap/nav.scss b/app/assets/stylesheets/gitlab_bootstrap/nav.scss
new file mode 100644
index 0000000000000000000000000000000000000000..2eaef61ca333bf7f9a8d3a39c7ccb76a05aaf944
--- /dev/null
+++ b/app/assets/stylesheets/gitlab_bootstrap/nav.scss
@@ -0,0 +1,65 @@
+/**
+ * nav-pills
+ *
+ */
+.nav-pills {
+  .active a {
+    background: $primary_color;
+  }
+
+  > li > a {
+    @include border-radius(0);
+  }
+  &.nav-stacked {
+    > li > a {
+      border-left: 4px solid #EEE;
+      padding: 12px;
+    }
+    > .active > a {
+      border-color: #29B;
+      border-radius: 0;
+      background: #F1F1F1;
+      color: $style_color;
+      font-weight: bold;
+    }
+  }
+}
+
+.nav-pills > .active > a > i[class^="icon-"] { background: inherit; }
+
+
+
+/**
+ * nav-tabs
+ *
+ */
+.nav-tabs > li > a, .nav-pills > li > a { color: $style_color; }
+.nav.nav-tabs {
+  li {
+    > a {
+      padding: 8px 20px;
+      margin-right: 7px;
+      line-height: 20px;
+      border-color: #EEE;
+      color: #888;
+      border-bottom: 1px solid #ddd;
+      .badge {
+        background-color: #eee;
+        color: #888;
+        text-shadow: 0 1px 1px #fff;
+      }
+      i[class^="icon-"] {
+        line-height: 14px;
+      }
+    }
+    &.active {
+      > a {
+        border-color: #CCC;
+        border-bottom: 1px solid #fff;
+        color: #333;
+      }
+    }
+  }
+
+  &.nav-small-tabs > li > a { padding: 6px 9px; }
+}
diff --git a/app/assets/stylesheets/gitlab_bootstrap/typography.scss b/app/assets/stylesheets/gitlab_bootstrap/typography.scss
index e74a0de125bedfe09942352c434df1bd193a11e1..781577c214754030f83d11b68794f024faa98d7d 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/typography.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/typography.scss
@@ -21,7 +21,7 @@ h6 {
 
 /** CODE **/
 pre {
-  font-family:'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
+  font-family: $monospace_font;
 
   &.dark {
     background: #333;
@@ -79,7 +79,7 @@ a:focus {
 }
 
 .monospace {
-  font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
+  font-family: $monospace_font;
 }
 
 /**
diff --git a/app/assets/stylesheets/gitlab_bootstrap/variables.scss b/app/assets/stylesheets/gitlab_bootstrap/variables.scss
index 869eb168c0dadfb02e1eeb1e09703cae3310cffb..aeabe7ad2e83be87ee201e6971e182ff27b4162e 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/variables.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/variables.scss
@@ -1,5 +1,13 @@
-/** Colors **/
+/**
+ * General Colors
+ */
 $primary_color: #2FA0BB;
 $link_color: #3A89A3;
 $style_color: #474D57;
 $hover: #D9EDF7;
+
+/**
+ * Commit Diff Colors
+ */
+$added: #63c363;
+$deleted: #f77;
diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss
index c60aae49eaa12c52c42cd878006a4d55af6f244c..8b93287ed1e25402b649f13d642b3abced087358 100644
--- a/app/assets/stylesheets/sections/commits.scss
+++ b/app/assets/stylesheets/sections/commits.scss
@@ -1,7 +1,5 @@
 /**
- *
- * COMMIT SHOw
- *
+ * Commit file
  */
 .commit-committer-link,
 .commit-author-link {
@@ -12,11 +10,11 @@
   }
 }
 
-.diff_file {
+.file {
   border: 1px solid #CCC;
   margin-bottom: 1em;
 
-  .diff_file_header {
+  .header {
     @extend .clearfix;
     padding: 5px 5px 5px 10px;
     color: #555;
@@ -28,32 +26,35 @@
     background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
     background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
 
+    a{
+      color: $style_color;
+    }
+    
     > span {
-      font-family: $monospace;
+      font-family: $monospace_font;
       font-size: 14px;
       line-height: 30px;
     }
 
-    a.view-commit{
+    a.view-file{
       font-weight: bold;
     }
 
     .commit-short-id{
-      font-family: $monospace;
+      font-family: $monospace_font;
       font-size: smaller;
     }
 
     .file-mode{
-      font-family: $monospace;
+      font-family: $monospace_font;
     }
   }
-  .diff_file_content {
+  .content {
     overflow: auto;
     overflow-y: hidden;
-    background: #fff;
+    background: #FFF;
     color: #333;
     font-size: 12px;
-    font-family: $monospace;
     .old{
       span.idiff{
         background-color: #FAA;
@@ -66,114 +67,274 @@
     }
 
     table {
+      font-family: $monospace_font;
+      border: none;
+      margin: 0px;
+      padding: 0px;
       td {
         line-height: 18px;
+        font-size: 12px;
+      }
+    }
+    .old_line, .new_line {
+      margin: 0px;
+      padding: 0px;
+      border: none;
+      background: #EEE;
+      color: #666;
+      padding: 0px 5px;
+      border-right: 1px solid #ccc;
+      text-align: right;
+      min-width: 35px;
+      max-width: 35px;
+      width: 35px;
+      @include user-select(none);
+      a {
+        float: left;
+        width: 35px;
+        font-weight: normal;
+        color: #666;
+        &:hover {
+          text-decoration: underline;
+        }
+      }
+    }
+    .line_content {
+      white-space: pre;
+      height: 14px;
+      margin: 0px;
+      padding: 0px;
+      border: none;
+      &.new {
+        background: #CFD;
+      }
+      &.old {
+        background: #FDD;
+      }
+      &.matched {
+        color: #ccc;
+        background: #fafafa;
       }
     }
   }
-  .diff_file_content_image {
-    background: #eee;
+  .image {
+    background: #ddd;
     text-align: center;
-    .image {
+    padding: 30px;
+    .wrap{
       display: inline-block;
-      margin: 50px;
-      max-width: 400px;
-
+    }
+    
+    .frame {
+      display: inline-block;
+      background-color: #fff;
+      line-height: 0;
       img{
+        border: 1px solid #FFF;
         background: url('trans_bg.gif');
       }
+      &.deleted {
+        border: 1px solid $deleted;
+      }
 
-      &.diff_removed {
-        img{
-          border: 1px solid #C00;
-        }
+      &.added {
+        border: 1px solid $added;
       }
+    }
+    .image-info{
+      font-size: 12px;
+      margin: 5px 0 0 0;
+      color: grey;
+    }
 
-      &.diff_added {
-        img{
-          border: 1px solid #0C0;
+    .view.swipe{
+      position: relative;
+      
+      .swipe-frame{
+        display: block;
+        margin: auto;
+        position: relative;
+      }
+      .swipe-wrap{
+        overflow: hidden;
+        border-left: 1px solid #999;
+        position: absolute;
+        display: block;
+        top: 13px;
+        right: 7px;
+      }
+      .frame{
+        top: 0;
+        right: 0;
+        position: absolute;
+        &.deleted{
+          margin: 0;
+          display: block;
+          top: 13px;
+          right: 7px;
         }
       }
-
-      .image-info{
-        margin: 5px 0 0 0;
+      .swipe-bar{
+        display: block;
+        height: 100%;
+        width: 15px;
+        z-index: 100;
+        position: absolute;
+        cursor: pointer;
+        &:hover{
+          .top-handle{
+            background-position: -15px 3px;
+          }
+          .bottom-handle{
+            background-position: -15px -11px;
+          }
+        };
+        .top-handle{
+          display: block;
+          height: 14px;
+          width: 15px;
+          position: absolute;
+          top: 0px;
+          background: url('swipemode_sprites.gif') 0 3px no-repeat;
+        }
+        .bottom-handle{
+          display: block;
+          height: 14px;
+          width: 15px;
+          position: absolute;
+          bottom: 0px;
+          background: url('swipemode_sprites.gif') 0 -11px no-repeat;
+        }
       }
-    }
-
-    &.img_compared {
-      .image {
-        max-width: 300px;
+    } //.view.swipe
+    .view.onion-skin{
+      .onion-skin-frame{
+        display: block;
+        margin: auto;
+        position: relative;
       }
-    }
+      .frame.added, .frame.deleted {
+        position: absolute;
+        display: block;
+        top: 0px;
+        left: 0px;
+      }
+      .controls{
+        display: block;
+        height: 14px;
+        width: 300px;
+        z-index: 100;
+        position: absolute;
+        bottom: 0px;
+        left: 50%;
+        margin-left: -150px;
+        
+        .drag-track{
+          display: block;
+          position: absolute;
+          left: 12px;
+          height: 10px;
+          width: 276px;
+          background: url('onion_skin_sprites.gif') -4px -20px repeat-x;
+        }
+        
+        .dragger {
+          display: block;
+          position: absolute;
+          left: 0px;
+          top: 0px;
+          height: 14px;
+          width: 14px;
+          background: url('onion_skin_sprites.gif') 0px -34px repeat-x;
+          cursor: pointer;
+        }
+        
+        .transparent {
+          display: block;
+          position: absolute;
+          top: 2px;
+          right: 0px;
+          height: 10px;
+          width: 10px;
+          background: url('onion_skin_sprites.gif') -2px 0px no-repeat;
+        }
+        
+        .opaque {
+          display: block;
+          position: absolute;
+          top: 2px;
+          left: 0px;
+          height: 10px;
+          width: 10px;
+          background: url('onion_skin_sprites.gif') -2px -10px no-repeat;
+        }
+      }
+    } //.view.onion-skin
   }
-}
+  .view-modes{
 
-.diff_file_content{
-  table {
-    border: none;
-    margin: 0px;
-    padding: 0px;
-    tr {
-      td {
-        font-size: 12px;
-      }
+    padding: 10px;
+    text-align: center;
+    
+    background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
+    background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
+    background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
+    background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
+    
+    ul, li{
+      list-style: none;
+      margin: 0;
+      padding: 0;
+      display: inline-block;
     }
-  }
-  .new_line,
-  .old_line,
-  .notes_line {
-    margin:0px;
-    padding:0px;
-    border:none;
-    background:#EEE;
-    color:#666;
-    padding: 0px 5px;
-    border-right: 1px solid #ccc;
-    text-align: right;
-    min-width: 35px;
-    max-width: 35px;
-    width: 35px;
-    moz-user-select: none;
-    -khtml-user-select: none;
-    user-select: none;
-
-    a {
-      float: left;
-      width: 35px;
-      font-weight: normal;
-      color: #666;
-      &:hover {
+    
+    li{
+      color: grey;
+      border-left: 1px solid #c1c1c1;
+      padding: 0 12px 0 16px;
+      cursor: pointer;
+      &:first-child{
+        border-left: none;
+      }
+      &:hover{
         text-decoration: underline;
       }
-    }
-  }
-  .line_content {
-    white-space: pre;
-    height: 14px;
-    margin: 0px;
-    padding: 0px;
-    border: none;
-    &.new {
-      background: #CFD;
-    }
-    &.old {
-      background: #FDD;
-    }
-    &.matched {
-      color: #ccc;
-      background: #fafafa;
+      &.active{
+        &:hover{
+          text-decoration: none;
+        }
+        cursor: default;
+        color: #333;
+      }
+      &.disabled{
+        display: none;
+      }
     }
   }
 }
 
 /** COMMIT BLOCK **/
-.commit-title{display: block;}
-.commit-title{margin-bottom: 10px}
-.commit-author, .commit-committer{display: block;color: #999; font-weight: normal; font-style: italic;}
-.commit-author strong, .commit-committer strong{font-weight: bold; font-style: normal;}
+.commit-title{
+  display: block;
+}
+.commit-title{
+  margin-bottom: 10px;
+}
+.commit-author, .commit-committer{
+  display: block;
+  color: #999; 
+  font-weight: normal; 
+  font-style: italic;
+}
+.commit-author strong, .commit-committer strong{
+  font-weight: bold; 
+  font-style: normal;
+}
 
 
-/** COMMIT ROW **/
+/**
+ * COMMIT ROW
+ */
 .commit {
   .browse_code_link_holder {
     @extend .span2;
@@ -199,11 +360,10 @@
     float: left;
     @extend .lined;
     min-width: 65px;
-    font-family: $monospace;
+    font-family: $monospace_font;
   }
 }
 
-.diff_file_header a,
 .file-stats a {
   color: $style_color;
 }
@@ -237,7 +397,7 @@
   font-size: 13px;
   background: #474D57;
   color: #fff;
-  font-family: $monospace;
+  font-family: $monospace_font;
 }
 
 
diff --git a/app/assets/stylesheets/sections/events.scss b/app/assets/stylesheets/sections/events.scss
index 7472cb093263e401b902ae5ec12af58657198663..ff8101471783b9f777a0b629c3c87257caa2cd92 100644
--- a/app/assets/stylesheets/sections/events.scss
+++ b/app/assets/stylesheets/sections/events.scss
@@ -127,7 +127,7 @@
   .btn-new-mr {
     @extend .btn-info;
     @extend .small;
-    @extend .right;
+    @extend .pull-right;
     margin: -3px;
   }
 }
diff --git a/app/assets/stylesheets/sections/header.scss b/app/assets/stylesheets/sections/header.scss
index 048a3ffcbb2ad5b3ad5dc8686de010289df4467f..5fe18131828b9e875eefabf51a84d0f432ac22cc 100644
--- a/app/assets/stylesheets/sections/header.scss
+++ b/app/assets/stylesheets/sections/header.scss
@@ -13,7 +13,7 @@ header {
         color: $style_color;
         text-shadow: 0 1px 0 #fff;
         font-size: 18px;
-        padding: 11px;
+        padding: 12px;
       }
 
       /** NAV block with links and profile **/
diff --git a/app/assets/stylesheets/sections/login.scss b/app/assets/stylesheets/sections/login.scss
index 7536abff44fc5e442f462f3da5ef2c589d3300b8..89b8f1c0055322316b26d48ec58f3d9d60bb1749 100644
--- a/app/assets/stylesheets/sections/login.scss
+++ b/app/assets/stylesheets/sections/login.scss
@@ -1,7 +1,7 @@
 /* Login Page */
-body.login-page{ 
-  padding-top: 10%;
-  background: #f1f1f1;
+body.login-page{
+  padding-top: 7%;
+  background: #666;
 }
 
 .login-box{
diff --git a/app/assets/stylesheets/sections/merge_requests.scss b/app/assets/stylesheets/sections/merge_requests.scss
index 5225a242726b7d0cd2a321daf9f2fd817f17fc49..ff715c0fd1810031274de39762062d7afcb28962 100644
--- a/app/assets/stylesheets/sections/merge_requests.scss
+++ b/app/assets/stylesheets/sections/merge_requests.scss
@@ -77,7 +77,7 @@ li.merge_request {
   font-size: 14px;
   background: #474D57;
   color: #fff;
-  font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
+  font-family: $monospace_font;
 }
 
 .mr_source_commit,
diff --git a/app/assets/stylesheets/sections/nav.scss b/app/assets/stylesheets/sections/nav.scss
index bc19bc75a6797d0a95a99e01696913ba4560f222..50091cd7365f7a37618bf3ccf5dbc8cf4eb924b5 100644
--- a/app/assets/stylesheets/sections/nav.scss
+++ b/app/assets/stylesheets/sections/nav.scss
@@ -6,8 +6,7 @@ ul.main_menu {
   margin: auto;
   margin: 30px 0;
   margin-top: 10px;
-  border-bottom: 1px solid #DDD;
-  height: 37px;
+  height: 38px;
   position: relative;
   overflow: hidden;
   .count {
@@ -33,6 +32,7 @@ ul.main_menu {
     margin: 0;
     display: table-cell;
     width: 1%;
+    border-bottom: 2px solid #EEE;
     &.active {
       border-bottom: 2px solid #474D57;
       a {
@@ -42,10 +42,8 @@ ul.main_menu {
 
     &.home {
       a {
-        background: url(home_icon.PNG) no-repeat center center;
-        text-indent:-9999px;
-        min-width: 20px;
-        img {
+        i {
+          font-size: 20px;
           position: relative;
           top: 4px;
         }
@@ -56,7 +54,7 @@ ul.main_menu {
     display: block;
     text-align: center;
     font-weight: normal;
-    height: 35px;
+    height: 36px;
     line-height: 36px;
     color: #777;
     text-shadow: 0 1px 1px white;
diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss
index a7fadd4f64103b3227666759a2ab866232278203..648cb210e9cbf4f772d9faaf97cd6253f78599c2 100644
--- a/app/assets/stylesheets/sections/notes.scss
+++ b/app/assets/stylesheets/sections/notes.scss
@@ -40,13 +40,13 @@ ul.notes {
     .discussion-body {
       margin-left: 50px;
 
-      .diff_file,
+      .file,
       .discussion-hidden,
       .notes {
         @extend .borders;
         background-color: #F9F9F9;
       }
-      .diff_file .notes {
+      .file .notes {
         /* reset */
         background: inherit;
         border: none;
@@ -81,14 +81,6 @@ ul.notes {
     .attachment {
       font-size: 14px;
       margin-top: -20px;
-
-      .icon-attachment {
-        @extend .icon-paper-clip;
-        font-size: 24px;
-        position: relative;
-        text-align: right;
-        top: 6px;
-      }
     }
     .note-body {
       margin-left: 45px;
@@ -109,7 +101,7 @@ ul.notes {
   }
 }
 
-.diff_file .notes_holder {
+.file .notes_holder {
   font-family: $sansFontFamily;
   font-size: 13px;
   line-height: 18px;
@@ -134,8 +126,6 @@ ul.notes {
   }
 }
 
-
-
 /**
  * Actions for Discussions/Notes
  */
@@ -171,7 +161,7 @@ ul.notes {
     }
   }
 }
-.diff_file .note .note-actions {
+.file .note .note-actions {
   right: 0;
   top: 0;
 }
@@ -182,7 +172,7 @@ ul.notes {
  * Line note button on the side of diffs
  */
 
-.diff_file tr.line_holder {
+.file tr.line_holder {
   .add-diff-note {
     background: url("diff_note_add.png") no-repeat left 0;
     height: 22px;
@@ -212,25 +202,25 @@ ul.notes {
   }
 }
 
-
-
 /**
  * Note Form
  */
 
-.comment-btn,
+.comment-btn {
+  @extend .btn-create;
+}
 .reply-btn {
-  @extend .save-btn;
+  @extend .btn-primary;
 }
-.diff_file,
+.file .content tr.line_holder:hover > td { background: $hover !important; }
+.file .content tr.line_holder:hover > td .line_note_link {
+  opacity: 1.0;
+  filter: alpha(opacity=100);
+}
+.file,
 .discussion {
   .new_note {
     margin: 8px 5px 8px 0;
-
-    .note_options {
-      // because of the smaller width and the extra "cancel" button
-      margin-top: 8px;
-    }
   }
 }
 .new_note {
@@ -243,37 +233,6 @@ ul.notes {
   .clearfix {
     margin-bottom: 0;
   }
-  .note_options {
-    h6 {
-      @extend .left;
-      line-height: 20px;
-      padding-right: 16px;
-      padding-bottom: 16px;
-    }
-    label {
-      padding: 0;
-    }
-
-    .attachment {
-      @extend .right;
-      position: relative;
-      width: 350px;
-      height: 50px;
-      margin:0 0 5px !important;
-
-      // hide the actual file field
-      input {
-        display: none;
-      }
-
-      .choose-btn {
-        float: right;
-      }
-    }
-    .notify_options {
-      @extend .right;
-    }
-  }
   .note_text_and_preview {
     // makes the "absolute" position for links relative to this
     position: relative;
@@ -312,3 +271,17 @@ ul.notes {
   @extend .thumbnail;
   margin-left: 45px;
 }
+
+
+.note-form-actions {
+  background: #F9F9F9;
+  height: 45px;
+  padding: 0 5px;
+
+  .note-form-option {
+    margin-top: 8px;
+    margin-left: 15px;
+    @extend .pull-left;
+    @extend .span4;
+  }
+}
diff --git a/app/assets/stylesheets/sections/projects.scss b/app/assets/stylesheets/sections/projects.scss
index 4bdc56d2884a62dd66d86b39f3d5550d1ea6373d..28df1b5ac28dfe6f3029d253f75f32033bc88158 100644
--- a/app/assets/stylesheets/sections/projects.scss
+++ b/app/assets/stylesheets/sections/projects.scss
@@ -4,9 +4,8 @@
   }
 
   .side {
-    @extend .right;
+    @extend .pull-right;
 
-    .groups_box,
     .projects_box {
       > .title {
         padding: 2px 15px;
diff --git a/app/contexts/projects/create_context.rb b/app/contexts/projects/create_context.rb
index e644d89a356d78f43845ccc1803f0fbb3196a354..915bd8be8b00626de649a32f49f3d96e3936c685 100644
--- a/app/contexts/projects/create_context.rb
+++ b/app/contexts/projects/create_context.rb
@@ -32,16 +32,10 @@ module Projects
         @project.namespace_id = current_user.namespace_id
       end
 
-      Project.transaction do
-        @project.creator = current_user
-        @project.save!
+      @project.creator = current_user
 
-        # Add user as project master
-        @project.users_projects.create!(project_access: UsersProject::MASTER, user: current_user)
-
-        # when project saved no team member exist so
-        # project repository should be updated after first user add
-        @project.update_repository
+      if @project.save
+        @project.users_projects.create(project_access: UsersProject::MASTER, user: current_user)
       end
 
       @project
diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin/application_controller.rb
similarity index 82%
rename from app/controllers/admin_controller.rb
rename to app/controllers/admin/application_controller.rb
index bce9f69238577379d926b3c53cfdf427234ebd72..6a8f20f60471fe3722bf630077b07ec5b6cf02e8 100644
--- a/app/controllers/admin_controller.rb
+++ b/app/controllers/admin/application_controller.rb
@@ -1,7 +1,7 @@
 # Provides a base class for Admin controllers to subclass
 #
 # Automatically sets the layout and ensures an administrator is logged in
-class AdminController < ApplicationController
+class Admin::ApplicationController < ApplicationController
   layout 'admin'
   before_filter :authenticate_admin!
 
diff --git a/app/controllers/admin/dashboard_controller.rb b/app/controllers/admin/dashboard_controller.rb
index f97c56b0b31e3e22291a1c31ce8b50d65d604f29..3c27b86180be91c5b45e62f4bedf8055d55a775d 100644
--- a/app/controllers/admin/dashboard_controller.rb
+++ b/app/controllers/admin/dashboard_controller.rb
@@ -1,4 +1,4 @@
-class Admin::DashboardController < AdminController
+class Admin::DashboardController < Admin::ApplicationController
   def index
     @projects = Project.order("created_at DESC").limit(10)
     @users = User.order("created_at DESC").limit(10)
diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb
index 90dbda3eeeafb33e2bb6458caed8e8e485326780..f552fb595b862dc625f0b6e4755e8bc1a39e4dfd 100644
--- a/app/controllers/admin/groups_controller.rb
+++ b/app/controllers/admin/groups_controller.rb
@@ -1,4 +1,4 @@
-class Admin::GroupsController < AdminController
+class Admin::GroupsController < Admin::ApplicationController
   before_filter :group, only: [:edit, :show, :update, :destroy, :project_update, :project_teams_update]
 
   def index
diff --git a/app/controllers/admin/hooks_controller.rb b/app/controllers/admin/hooks_controller.rb
index 91a1d633590df04c31611bdd73e42bc7f0d45812..c5bf76f8c39dabd76a181ed3fec971905a98b74b 100644
--- a/app/controllers/admin/hooks_controller.rb
+++ b/app/controllers/admin/hooks_controller.rb
@@ -1,4 +1,4 @@
-class Admin::HooksController < AdminController
+class Admin::HooksController < Admin::ApplicationController
   def index
     @hooks = SystemHook.all
     @hook = SystemHook.new
diff --git a/app/controllers/admin/logs_controller.rb b/app/controllers/admin/logs_controller.rb
index 28c321a9e5231aee09fab2ca653d913e1ac06e6a..b999018dde469e3f32187b94551077c56a56a174 100644
--- a/app/controllers/admin/logs_controller.rb
+++ b/app/controllers/admin/logs_controller.rb
@@ -1,2 +1,2 @@
-class Admin::LogsController < AdminController
+class Admin::LogsController < Admin::ApplicationController
 end
diff --git a/app/controllers/admin/projects/application_controller.rb b/app/controllers/admin/projects/application_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b3f1539f38760eb94d8c1c3da0372630c645083b
--- /dev/null
+++ b/app/controllers/admin/projects/application_controller.rb
@@ -0,0 +1,11 @@
+# Provides a base class for Admin controllers to subclass
+#
+# Automatically sets the layout and ensures an administrator is logged in
+class Admin::Projects::ApplicationController < Admin::ApplicationController
+
+  protected
+
+  def project
+    @project ||= Project.find_with_namespace(params[:project_id])
+  end
+end
diff --git a/app/controllers/admin/projects/members_controller.rb b/app/controllers/admin/projects/members_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d9c0d572bb1ec23c1f72e75ad9bf35a6918b8118
--- /dev/null
+++ b/app/controllers/admin/projects/members_controller.rb
@@ -0,0 +1,32 @@
+class Admin::Projects::MembersController < Admin::Projects::ApplicationController
+  def edit
+    @member = team_member
+    @project = project
+    @team_member_relation = team_member_relation
+  end
+
+  def update
+    if team_member_relation.update_attributes(params[:team_member])
+      redirect_to [:admin, project],  notice: 'Project Access was successfully updated.'
+    else
+      render action: "edit"
+    end
+  end
+
+  def destroy
+    team_member_relation.destroy
+
+    redirect_to :back
+  end
+
+  private
+
+  def team_member
+    @member ||= project.users.find_by_username(params[:id])
+  end
+
+  def team_member_relation
+    team_member.users_projects.find_by_project_id(project)
+  end
+
+end
diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb
index fc2793a72e7b5959fd1f1910b840b53d06240f27..711817395f1fac05f502de85d62f004b696d0218 100644
--- a/app/controllers/admin/projects_controller.rb
+++ b/app/controllers/admin/projects_controller.rb
@@ -1,4 +1,4 @@
-class Admin::ProjectsController < AdminController
+class Admin::ProjectsController < Admin::ApplicationController
   before_filter :project, only: [:edit, :show, :update, :destroy, :team_update]
 
   def index
@@ -29,7 +29,9 @@ class Admin::ProjectsController < AdminController
   end
 
   def update
-    status = Projects::UpdateContext.new(project, current_user, params).execute(:admin)
+    project.creator = current_user unless project.creator
+
+    status = ::Projects::UpdateContext.new(project, current_user, params).execute(:admin)
 
     if status
       redirect_to [:admin, @project], notice: 'Project was successfully updated.'
diff --git a/app/controllers/admin/resque_controller.rb b/app/controllers/admin/resque_controller.rb
index 9d8e7e3051f0520c288741ce497c49334933bd54..7d489ab4876f226b95800dd0c5390fc7a4f8c62f 100644
--- a/app/controllers/admin/resque_controller.rb
+++ b/app/controllers/admin/resque_controller.rb
@@ -1,4 +1,4 @@
-class Admin::ResqueController < AdminController
+class Admin::ResqueController < Admin::ApplicationController
   def show
   end
 end
diff --git a/app/controllers/admin/team_members_controller.rb b/app/controllers/admin/team_members_controller.rb
deleted file mode 100644
index 073208057cabce9a48206a9ada82ce1f0dd51284..0000000000000000000000000000000000000000
--- a/app/controllers/admin/team_members_controller.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-class Admin::TeamMembersController < AdminController
-  def edit
-    @admin_team_member = UsersProject.find(params[:id])
-  end
-
-  def update
-    @admin_team_member = UsersProject.find(params[:id])
-
-    if @admin_team_member.update_attributes(params[:team_member])
-      redirect_to [:admin, @admin_team_member.project],  notice: 'Project Access was successfully updated.'
-    else
-      render action: "edit"
-    end
-  end
-
-  def destroy
-    @admin_team_member = UsersProject.find(params[:id])
-    @admin_team_member.destroy
-
-    redirect_to :back
-  end
-end
diff --git a/app/controllers/admin/teams/application_controller.rb b/app/controllers/admin/teams/application_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..8710821454eaf3a6857893b4f548d410eccfdaa9
--- /dev/null
+++ b/app/controllers/admin/teams/application_controller.rb
@@ -0,0 +1,11 @@
+# Provides a base class for Admin controllers to subclass
+#
+# Automatically sets the layout and ensures an administrator is logged in
+class Admin::Teams::ApplicationController < Admin::ApplicationController
+
+  private
+
+  def user_team
+    @team = UserTeam.find_by_path(params[:team_id])
+  end
+end
diff --git a/app/controllers/admin/teams/members_controller.rb b/app/controllers/admin/teams/members_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e7dbcad568f66c4e304a73f9e07cc26c00d16537
--- /dev/null
+++ b/app/controllers/admin/teams/members_controller.rb
@@ -0,0 +1,41 @@
+class Admin::Teams::MembersController < Admin::Teams::ApplicationController
+  def new
+    @users = User.potential_team_members(user_team)
+    @users = UserDecorator.decorate @users
+  end
+
+  def create
+    unless params[:user_ids].blank?
+      user_ids = params[:user_ids]
+      access = params[:default_project_access]
+      is_admin = params[:group_admin]
+      user_team.add_members(user_ids, access, is_admin)
+    end
+
+    redirect_to admin_team_path(user_team), notice: 'Members was successfully added into Team of users.'
+  end
+
+  def edit
+    team_member
+  end
+
+  def update
+    options = {default_projects_access: params[:default_project_access], group_admin: params[:group_admin]}
+    if user_team.update_membership(team_member, options)
+      redirect_to admin_team_path(user_team), notice: "Membership for #{team_member.name} was successfully updated in Team of users."
+    else
+      render :edit
+    end
+  end
+
+  def destroy
+    user_team.remove_member(team_member)
+    redirect_to admin_team_path(user_team), notice: "Member #{team_member.name} was successfully removed from Team of users."
+  end
+
+  protected
+
+  def team_member
+    @member ||= user_team.members.find_by_username(params[:id])
+  end
+end
diff --git a/app/controllers/admin/teams/projects_controller.rb b/app/controllers/admin/teams/projects_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..8584a188b20275c8ebb8a24b7dd10f428ec14f13
--- /dev/null
+++ b/app/controllers/admin/teams/projects_controller.rb
@@ -0,0 +1,41 @@
+class Admin::Teams::ProjectsController < Admin::Teams::ApplicationController
+  def new
+    @projects = Project.scoped
+    @projects = @projects.without_team(user_team) if user_team.projects.any?
+    #@projects.reject!(&:empty_repo?)
+  end
+
+  def create
+    unless params[:project_ids].blank?
+      project_ids = params[:project_ids]
+      access = params[:greatest_project_access]
+      user_team.assign_to_projects(project_ids, access)
+    end
+
+    redirect_to admin_team_path(user_team), notice: 'Team of users was successfully assgned to projects.'
+  end
+
+  def edit
+    team_project
+  end
+
+  def update
+    if user_team.update_project_access(team_project, params[:greatest_project_access])
+      redirect_to admin_team_path(user_team), notice: 'Access was successfully updated.'
+    else
+      render :edit
+    end
+  end
+
+  def destroy
+    user_team.resign_from_project(team_project)
+    redirect_to admin_team_path(user_team), notice: 'Team of users was successfully reassigned from project.'
+  end
+
+  protected
+
+  def team_project
+    @project ||= user_team.projects.find_with_namespace(params[:id])
+  end
+
+end
diff --git a/app/controllers/admin/teams_controller.rb b/app/controllers/admin/teams_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..786957cbc594496706a3391001676d2bde27a475
--- /dev/null
+++ b/app/controllers/admin/teams_controller.rb
@@ -0,0 +1,59 @@
+class Admin::TeamsController < Admin::ApplicationController
+  def index
+    @teams = UserTeam.order('name ASC')
+    @teams = @teams.search(params[:name]) if params[:name].present?
+    @teams = @teams.page(params[:page]).per(20)
+  end
+
+  def show
+    user_team
+  end
+
+  def new
+    @team = UserTeam.new
+  end
+
+  def edit
+    user_team
+  end
+
+  def create
+    @team = UserTeam.new(params[:user_team])
+    @team.path = @team.name.dup.parameterize if @team.name
+    @team.owner = current_user
+
+    if @team.save
+      redirect_to admin_team_path(@team), notice: 'Team of users was successfully created.'
+    else
+      render action: "new"
+    end
+  end
+
+  def update
+    user_team_params = params[:user_team].dup
+    owner_id = user_team_params.delete(:owner_id)
+
+    if owner_id
+      user_team.owner = User.find(owner_id)
+    end
+
+    if user_team.update_attributes(user_team_params)
+      redirect_to admin_team_path(user_team), notice: 'Team of users was successfully updated.'
+    else
+      render action: "edit"
+    end
+  end
+
+  def destroy
+    user_team.destroy
+
+    redirect_to admin_teams_path, notice: 'Team of users was successfully deleted.'
+  end
+
+  protected
+
+  def user_team
+    @team ||= UserTeam.find_by_path(params[:id])
+  end
+
+end
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index 8669f5d1d38928dc575872512dfc19431a8da974..400e44e086ddca7622bf7ca6a65bc87cba65b658 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -1,4 +1,6 @@
-class Admin::UsersController < AdminController
+class Admin::UsersController < Admin::ApplicationController
+  before_filter :admin_user, only: [:show, :edit, :update, :destroy]
+
   def index
     @admin_users = User.scoped
     @admin_users = @admin_users.filter(params[:filter])
@@ -7,25 +9,18 @@ class Admin::UsersController < AdminController
   end
 
   def show
-    @admin_user = User.find(params[:id])
-
-    @projects = if @admin_user.authorized_projects.empty?
-               Project
-             else
-               Project.without_user(@admin_user)
-             end.all
+    @projects = Project.scoped
+    @projects = @projects.without_user(admin_user) if admin_user.authorized_projects.present?
   end
 
   def team_update
-    @admin_user = User.find(params[:id])
-
     UsersProject.add_users_into_projects(
       params[:project_ids],
-      [@admin_user.id],
+      [admin_user.id],
       params[:project_access]
     )
 
-    redirect_to [:admin, @admin_user], notice: 'Teams were successfully updated.'
+    redirect_to [:admin, admin_user], notice: 'Teams were successfully updated.'
   end
 
 
@@ -34,13 +29,11 @@ class Admin::UsersController < AdminController
   end
 
   def edit
-    @admin_user = User.find(params[:id])
+    admin_user
   end
 
   def block
-    @admin_user = User.find(params[:id])
-
-    if @admin_user.block
+    if admin_user.block
       redirect_to :back, alert: "Successfully blocked"
     else
       redirect_to :back, alert: "Error occured. User was not blocked"
@@ -48,9 +41,7 @@ class Admin::UsersController < AdminController
   end
 
   def unblock
-    @admin_user = User.find(params[:id])
-
-    if @admin_user.update_attribute(:blocked, false)
+    if admin_user.update_attribute(:blocked, false)
       redirect_to :back, alert: "Successfully unblocked"
     else
       redirect_to :back, alert: "Error occured. User was not unblocked"
@@ -82,30 +73,34 @@ class Admin::UsersController < AdminController
       params[:user].delete(:password_confirmation)
     end
 
-    @admin_user = User.find(params[:id])
-    @admin_user.admin = (admin && admin.to_i > 0)
+    admin_user.admin = (admin && admin.to_i > 0)
 
     respond_to do |format|
-      if @admin_user.update_attributes(params[:user], as: :admin)
-        format.html { redirect_to [:admin, @admin_user], notice: 'User was successfully updated.' }
+      if admin_user.update_attributes(params[:user], as: :admin)
+        format.html { redirect_to [:admin, admin_user], notice: 'User was successfully updated.' }
         format.json { head :ok }
       else
         format.html { render action: "edit" }
-        format.json { render json: @admin_user.errors, status: :unprocessable_entity }
+        format.json { render json: admin_user.errors, status: :unprocessable_entity }
       end
     end
   end
 
   def destroy
-    @admin_user = User.find(params[:id])
-    if @admin_user.personal_projects.count > 0
+    if admin_user.personal_projects.count > 0
       redirect_to admin_users_path, alert: "User is a project owner and can't be removed." and return
     end
-    @admin_user.destroy
+    admin_user.destroy
 
     respond_to do |format|
-      format.html { redirect_to admin_users_url }
+      format.html { redirect_to admin_users_path }
       format.json { head :ok }
     end
   end
+
+  protected
+
+  def admin_user
+    @admin_user ||= User.find_by_username!(params[:id])
+  end
 end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 3457a1ab1b4a14dd10e6e27d07a6dea884fe4fda..1f211bac9c220d34de02aa23901a23fa024fc89f 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -4,16 +4,12 @@ class ApplicationController < ActionController::Base
   before_filter :set_current_user_for_observers
   before_filter :add_abilities
   before_filter :dev_tools if Rails.env == 'development'
+  before_filter :default_headers
 
   protect_from_forgery
 
   helper_method :abilities, :can?
 
-  rescue_from Gitlab::Gitolite::AccessDenied do |exception|
-    log_exception(exception)
-    render "errors/gitolite", layout: "errors", status: 500
-  end
-
   rescue_from Encoding::CompatibilityError do |exception|
     log_exception(exception)
     render "errors/encoding", layout: "errors", status: 500
@@ -94,6 +90,18 @@ class ApplicationController < ActionController::Base
     return access_denied! unless can?(current_user, :download_code, project)
   end
 
+  def authorize_create_team!
+    return access_denied! unless can?(current_user, :create_team, nil)
+  end
+
+  def authorize_manage_user_team!
+    return access_denied! unless user_team.present? && can?(current_user, :manage_user_team, user_team)
+  end
+
+  def authorize_admin_user_team!
+    return access_denied! unless user_team.present? && can?(current_user, :admin_user_team, user_team)
+  end
+
   def access_denied!
     render "errors/access_denied", layout: "errors", status: 404
   end
@@ -135,4 +143,9 @@ class ApplicationController < ActionController::Base
   def dev_tools
     Rack::MiniProfiler.authorize_request
   end
+
+  def default_headers
+    headers['X-Frame-Options'] = 'DENY'
+    headers['X-XSS-Protection'] = '1; mode=block'
+  end
 end
diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
index c0ec4708e0aa1d1b8efb7fb78a9d16c43b224a56..f320e819e26d5f6c091f831c5f6a4016e4ff5095 100644
--- a/app/controllers/dashboard_controller.rb
+++ b/app/controllers/dashboard_controller.rb
@@ -1,24 +1,15 @@
 class DashboardController < ApplicationController
   respond_to :html
 
-  before_filter :projects
-  before_filter :event_filter, only: :index
+  before_filter :load_projects
+  before_filter :event_filter, only: :show
 
-  def index
+  def show
     @groups = current_user.authorized_groups
-
     @has_authorized_projects = @projects.count > 0
-
-    @projects = case params[:scope]
-                when 'personal' then
-                  @projects.personal(current_user)
-                when 'joined' then
-                  @projects.joined(current_user)
-                else
-                  @projects
-                end
-
-    @projects = @projects.page(params[:page]).per(30)
+    @teams = current_user.authorized_teams
+    @projects_count = @projects.count
+    @projects = @projects.limit(20)
 
     @events = Event.in_projects(current_user.authorized_projects.pluck(:id))
     @events = @event_filter.apply_filter(@events)
@@ -33,6 +24,19 @@ class DashboardController < ApplicationController
     end
   end
 
+  def projects
+    @projects = case params[:scope]
+                when 'personal' then
+                  @projects.personal(current_user)
+                when 'joined' then
+                  @projects.joined(current_user)
+                else
+                  @projects
+                end
+
+    @projects = @projects.page(params[:page]).per(30)
+  end
+
   # Get authored or assigned open merge requests
   def merge_requests
     @merge_requests = current_user.cared_merge_requests
@@ -55,7 +59,7 @@ class DashboardController < ApplicationController
 
   protected
 
-  def projects
+  def load_projects
     @projects = current_user.authorized_projects.sorted_by_activity
   end
 
diff --git a/app/controllers/graph_controller.rb b/app/controllers/graph_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..30ec5e89db2e99bee4695b546a4b4bd946f6667a
--- /dev/null
+++ b/app/controllers/graph_controller.rb
@@ -0,0 +1,18 @@
+class GraphController < ProjectResourceController
+  include ExtractsPath
+
+  # Authorize
+  before_filter :authorize_read_project!
+  before_filter :authorize_code_access!
+  before_filter :require_non_empty_project
+
+  def show
+    respond_to do |format|
+      format.html
+      format.json do
+        graph = Gitlab::Graph::JsonBuilder.new(project, @ref)
+        render :json => graph.to_json
+      end
+    end
+  end
+end
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index c25fc32a62c03c731e264af4e76b757a36265190..7b8649a6bdfc43914bb18563fbc9f764b1c290e7 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -1,12 +1,32 @@
 class GroupsController < ApplicationController
   respond_to :html
-  layout 'group'
+  layout 'group', except: [:new, :create]
 
-  before_filter :group
-  before_filter :projects
+  before_filter :group, except: [:new, :create]
 
   # Authorize
-  before_filter :authorize_read_group!
+  before_filter :authorize_read_group!, except: [:new, :create]
+  before_filter :authorize_admin_group!, only: [:edit, :update, :destroy]
+  before_filter :authorize_create_group!, only: [:new, :create]
+
+  # Load group projects
+  before_filter :projects, except: [:new, :create]
+
+  def new
+    @group = Group.new
+  end
+
+  def create
+    @group = Group.new(params[:group])
+    @group.path = @group.name.dup.parameterize if @group.name
+    @group.owner = current_user
+
+    if @group.save
+      redirect_to @group, notice: 'Group was successfully created.'
+    else
+      render action: "new"
+    end
+  end
 
   def show
     @events = Event.in_projects(project_ids).limit(20).offset(params[:offset] || 0)
@@ -65,6 +85,31 @@ class GroupsController < ApplicationController
     redirect_to people_group_path(@group), notice: 'Users was successfully added.'
   end
 
+  def edit
+  end
+
+  def update
+    group_params = params[:group].dup
+    owner_id =group_params.delete(:owner_id)
+
+    if owner_id
+      @group.owner = User.find(owner_id)
+    end
+
+    if @group.update_attributes(group_params)
+      redirect_to @group, notice: 'Group was successfully updated.'
+    else
+      render action: "edit"
+    end
+  end
+
+  def destroy
+    @group.truncate_teams
+    @group.destroy
+
+    redirect_to root_path, notice: 'Group was removed.'
+  end
+
   protected
 
   def group
@@ -85,4 +130,16 @@ class GroupsController < ApplicationController
       return render_404
     end
   end
+
+  def authorize_create_group!
+    unless can?(current_user, :create_group, nil)
+      return render_404
+    end
+  end
+
+  def authorize_admin_group!
+    unless can?(current_user, :manage_group, group)
+      return render_404
+    end
+  end
 end
diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7e4776d2d753d7a1f215e2f2e1f44cc29f2dae33
--- /dev/null
+++ b/app/controllers/projects/application_controller.rb
@@ -0,0 +1,11 @@
+class Projects::ApplicationController < ApplicationController
+
+  before_filter :authorize_admin_team_member!
+
+  protected
+
+  def user_team
+    @team ||= UserTeam.find_by_path(params[:id])
+  end
+
+end
diff --git a/app/controllers/projects/teams_controller.rb b/app/controllers/projects/teams_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..3ca724aaf4dc5dd7effcc5996791a0a73963ba79
--- /dev/null
+++ b/app/controllers/projects/teams_controller.rb
@@ -0,0 +1,27 @@
+class Projects::TeamsController < Projects::ApplicationController
+
+  def available
+    @teams = current_user.is_admin? ? UserTeam.scoped : current_user.user_teams
+    @teams = @teams.without_project(project)
+    unless @teams.any?
+      redirect_to project_team_index_path(project), notice: "No avaliable teams for assigment."
+    end
+  end
+
+  def assign
+    unless params[:team_id].blank?
+      team = UserTeam.find(params[:team_id])
+      access = params[:greatest_project_access]
+      team.assign_to_project(project, access)
+    end
+    redirect_to project_team_index_path(project)
+  end
+
+  def resign
+    team = project.user_teams.find_by_path(params[:id])
+    team.resign_from_project(project)
+
+    redirect_to project_team_index_path(project)
+  end
+
+end
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 368737d1e0b54d42256f48cf299cc2addceff2e9..7978ea6222c469a01bfa7633363058d941f92a1f 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -19,7 +19,7 @@ class ProjectsController < ProjectResourceController
   end
 
   def create
-    @project = Projects::CreateContext.new(current_user, params[:project]).execute
+    @project = ::Projects::CreateContext.new(current_user, params[:project]).execute
 
     respond_to do |format|
       flash[:notice] = 'Project was successfully created.' if @project.saved?
@@ -35,7 +35,7 @@ class ProjectsController < ProjectResourceController
   end
 
   def update
-    status = Projects::UpdateContext.new(project, current_user, params).execute
+    status = ::Projects::UpdateContext.new(project, current_user, params).execute
 
     respond_to do |format|
       if status
@@ -90,16 +90,6 @@ class ProjectsController < ProjectResourceController
     end
   end
 
-  def graph
-    respond_to do |format|
-      format.html
-      format.json do
-        graph = Gitlab::Graph::JsonBuilder.new(project)
-        render :json => graph.to_json
-      end
-    end
-  end
-
   def destroy
     return access_denied! unless can?(current_user, :remove_project, project)
 
diff --git a/app/controllers/refs_controller.rb b/app/controllers/refs_controller.rb
index 09d9eb51b8241ac01623643069a410396c0873a6..0e4dba3dc4b0074ae4d965b15a6979551aa69556 100644
--- a/app/controllers/refs_controller.rb
+++ b/app/controllers/refs_controller.rb
@@ -13,6 +13,8 @@ class RefsController < ProjectResourceController
       format.html do
         new_path = if params[:destination] == "tree"
                      project_tree_path(@project, (@ref + "/" + params[:path]))
+                   elsif params[:destination] == "graph"
+                     project_graph_path(@project, @ref)
                    else
                      project_commits_path(@project, @ref)
                    end
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index a23292396a015ec63c103bddc60136c7cc42d386..bbd67df6c704f63e1102fe63a756890f68e9955c 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -1,6 +1,18 @@
 class SearchController < ApplicationController
   def show
-    result = SearchContext.new(current_user.authorized_projects.map(&:id), params).execute
+    project_id = params[:project_id]
+    group_id = params[:group_id]
+
+    project_ids = current_user.authorized_projects.map(&:id)
+
+    if group_id.present?
+      group_project_ids = Group.find(group_id).projects.map(&:id)
+      project_ids.select! { |id| group_project_ids.include?(id)}
+    elsif project_id.present?
+      project_ids.select! { |id| id == project_id.to_i}
+    end
+
+    result = SearchContext.new(project_ids, params).execute
 
     @projects       = result[:projects]
     @merge_requests = result[:merge_requests]
diff --git a/app/controllers/team_members_controller.rb b/app/controllers/team_members_controller.rb
index 8378a8458ffa7193717eab782e117d36ce28ed98..18d4ae3ac96df8fde06d01d54aaa1bc72e59f26f 100644
--- a/app/controllers/team_members_controller.rb
+++ b/app/controllers/team_members_controller.rb
@@ -4,15 +4,16 @@ class TeamMembersController < ProjectResourceController
   before_filter :authorize_admin_project!, except: [:index, :show]
 
   def index
+    @teams = UserTeam.scoped
   end
 
   def show
-    @team_member = project.users_projects.find(params[:id])
-    @events = @team_member.user.recent_events.where(:project_id => @project.id).limit(7)
+    @user_project_relation = project.users_projects.find_by_user_id(member)
+    @events = member.recent_events.in_projects(project).limit(7)
   end
 
   def new
-    @team_member = project.users_projects.new
+    @user_project_relation = project.users_projects.new
   end
 
   def create
@@ -28,18 +29,18 @@ class TeamMembersController < ProjectResourceController
   end
 
   def update
-    @team_member = project.users_projects.find(params[:id])
-    @team_member.update_attributes(params[:team_member])
+    @user_project_relation = project.users_projects.find_by_user_id(member)
+    @user_project_relation.update_attributes(params[:team_member])
 
-    unless @team_member.valid?
+    unless @user_project_relation.valid?
       flash[:alert] = "User should have at least one role"
     end
     redirect_to project_team_index_path(@project)
   end
 
   def destroy
-    @team_member = project.users_projects.find(params[:id])
-    @team_member.destroy
+    @user_project_relation = project.users_projects.find_by_user_id(member)
+    @user_project_relation.destroy
 
     respond_to do |format|
       format.html { redirect_to project_team_index_path(@project) }
@@ -54,4 +55,10 @@ class TeamMembersController < ProjectResourceController
 
     redirect_to project_team_members_path(project), notice: notice
   end
+
+  protected
+
+  def member
+    @member ||= User.find_by_username(params[:id])
+  end
 end
diff --git a/app/controllers/teams/application_controller.rb b/app/controllers/teams/application_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..fc23202610c60cfb8ae27a658f1cec56b5617b41
--- /dev/null
+++ b/app/controllers/teams/application_controller.rb
@@ -0,0 +1,13 @@
+class Teams::ApplicationController < ApplicationController
+
+  layout 'user_team'
+
+  before_filter :authorize_manage_user_team!
+
+  protected
+
+  def user_team
+    @team ||= UserTeam.find_by_path(params[:team_id])
+  end
+
+end
diff --git a/app/controllers/teams/members_controller.rb b/app/controllers/teams/members_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..db218b8ca5e726aa97e87341f442e5001fed2273
--- /dev/null
+++ b/app/controllers/teams/members_controller.rb
@@ -0,0 +1,49 @@
+class Teams::MembersController < Teams::ApplicationController
+
+  skip_before_filter :authorize_manage_user_team!, only: [:index]
+
+  def index
+    @members = user_team.members
+  end
+
+  def new
+    @users = User.potential_team_members(user_team)
+    @users = UserDecorator.decorate @users
+  end
+
+  def create
+    unless params[:user_ids].blank?
+      user_ids = params[:user_ids]
+      access = params[:default_project_access]
+      is_admin = params[:group_admin]
+      user_team.add_members(user_ids, access, is_admin)
+    end
+
+    redirect_to team_members_path(user_team), notice: 'Members was successfully added into Team of users.'
+  end
+
+  def edit
+    team_member
+  end
+
+  def update
+    options = {default_projects_access: params[:default_project_access], group_admin: params[:group_admin]}
+    if user_team.update_membership(team_member, options)
+      redirect_to team_members_path(user_team), notice: "Membership for #{team_member.name} was successfully updated in Team of users."
+    else
+      render :edit
+    end
+  end
+
+  def destroy
+    user_team.remove_member(team_member)
+    redirect_to team_path(user_team), notice: "Member #{team_member.name} was successfully removed from Team of users."
+  end
+
+  protected
+
+  def team_member
+    @member ||= user_team.members.find_by_username(params[:id])
+  end
+
+end
diff --git a/app/controllers/teams/projects_controller.rb b/app/controllers/teams/projects_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e87889b4046324ba5373d99b893628c6da201e05
--- /dev/null
+++ b/app/controllers/teams/projects_controller.rb
@@ -0,0 +1,57 @@
+class Teams::ProjectsController < Teams::ApplicationController
+
+  skip_before_filter :authorize_manage_user_team!, only: [:index]
+
+  def index
+    @projects = user_team.projects
+    @avaliable_projects = current_user.admin? ? Project.without_team(user_team) : current_user.owned_projects.without_team(user_team)
+  end
+
+  def new
+    user_team
+    @avaliable_projects = current_user.owned_projects.scoped
+    @avaliable_projects = @avaliable_projects.without_team(user_team) if user_team.projects.any?
+
+    redirect_to team_projects_path(user_team), notice: "No avalible projects." unless @avaliable_projects.any?
+  end
+
+  def create
+    redirect_to :back if params[:project_ids].blank?
+
+    project_ids = params[:project_ids]
+    access = params[:greatest_project_access]
+
+    # Reject non-allowed projects
+    allowed_project_ids = current_user.owned_projects.map(&:id)
+    project_ids.select! { |id| allowed_project_ids.include?(id.to_i) }
+
+    # Assign projects to team
+    user_team.assign_to_projects(project_ids, access)
+
+    redirect_to team_projects_path(user_team), notice: 'Team of users was successfully assigned to projects.'
+  end
+
+  def edit
+    team_project
+  end
+
+  def update
+    if user_team.update_project_access(team_project, params[:greatest_project_access])
+      redirect_to team_projects_path(user_team), notice: 'Access was successfully updated.'
+    else
+      render :edit
+    end
+  end
+
+  def destroy
+    user_team.resign_from_project(team_project)
+    redirect_to team_projects_path(user_team), notice: 'Team of users was successfully reassigned from project.'
+  end
+
+  private
+
+  def team_project
+    @project ||= user_team.projects.find_with_namespace(params[:id])
+  end
+
+end
diff --git a/app/controllers/teams_controller.rb b/app/controllers/teams_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..ef66b77e23290d4f80cf92dd9607078a27647c7c
--- /dev/null
+++ b/app/controllers/teams_controller.rb
@@ -0,0 +1,76 @@
+class TeamsController < ApplicationController
+  # Authorize
+  before_filter :authorize_create_team!, only: [:new, :create]
+  before_filter :authorize_manage_user_team!, only: [:edit, :update]
+  before_filter :authorize_admin_user_team!, only: [:destroy]
+
+  before_filter :user_team, except: [:new, :create]
+
+  layout 'user_team', except: [:new, :create]
+
+  def show
+    user_team
+    projects
+    @events = Event.in_projects(user_team.project_ids).limit(20).offset(params[:offset] || 0)
+  end
+
+  def edit
+    user_team
+  end
+
+  def update
+    if user_team.update_attributes(params[:user_team])
+      redirect_to team_path(user_team)
+    else
+      render action: :edit
+    end
+  end
+
+  def destroy
+    user_team.destroy
+    redirect_to dashboard_path
+  end
+
+  def new
+    @team = UserTeam.new
+  end
+
+  def create
+    @team = UserTeam.new(params[:user_team])
+    @team.owner = current_user unless params[:owner]
+    @team.path = @team.name.dup.parameterize if @team.name
+
+    if @team.save
+      redirect_to team_path(@team)
+    else
+      render action: :new
+    end
+  end
+
+  # Get authored or assigned open merge requests
+  def merge_requests
+    projects
+    @merge_requests = MergeRequest.of_user_team(user_team)
+    @merge_requests = FilterContext.new(@merge_requests, params).execute
+    @merge_requests = @merge_requests.recent.page(params[:page]).per(20)
+  end
+
+  # Get only assigned issues
+  def issues
+    projects
+    @issues = Issue.of_user_team(user_team)
+    @issues = FilterContext.new(@issues, params).execute
+    @issues = @issues.recent.page(params[:page]).per(20)
+    @issues = @issues.includes(:author, :project)
+  end
+
+  protected
+
+  def projects
+    @projects ||= user_team.projects.sorted_by_activity
+  end
+
+  def user_team
+    @team ||= current_user.authorized_teams.find_by_path(params[:id])
+  end
+end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e027057fe65d920da683d7d6176b19ef7aa79937
--- /dev/null
+++ b/app/controllers/users_controller.rb
@@ -0,0 +1,7 @@
+class UsersController < ApplicationController
+  def show
+    @user = User.find_by_username!(params[:username])
+    @projects = @user.authorized_projects.where('projects.id in (?)', current_user.authorized_projects.map(&:id))
+    @events = @user.recent_events.where(project_id: @projects.map(&:id)).limit(20)
+  end
+end
diff --git a/app/decorators/user_decorator.rb b/app/decorators/user_decorator.rb
index af9c6a63e756147d0c59efa70de112e28a080f51..b781f237352c21fcf96e032df006ed5b6d1788c2 100644
--- a/app/decorators/user_decorator.rb
+++ b/app/decorators/user_decorator.rb
@@ -8,4 +8,8 @@ class UserDecorator < ApplicationDecorator
   def tm_of(project)
     project.team_member_by_id(self.id)
   end
+
+  def name_with_email
+    "#{name} (#{email})"
+  end
 end
diff --git a/app/helpers/admin/teams/members_helper.rb b/app/helpers/admin/teams/members_helper.rb
new file mode 100644
index 0000000000000000000000000000000000000000..58b9f1896c4a9fd9b190430148ea8f55a3e19bfc
--- /dev/null
+++ b/app/helpers/admin/teams/members_helper.rb
@@ -0,0 +1,5 @@
+module Admin::Teams::MembersHelper
+  def member_since(team, member)
+    team.user_team_user_relationships.find_by_user_id(member).created_at
+  end
+end
diff --git a/app/helpers/admin/teams/projects_helper.rb b/app/helpers/admin/teams/projects_helper.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b97cc403337266f1ea19700221047accaafaeb64
--- /dev/null
+++ b/app/helpers/admin/teams/projects_helper.rb
@@ -0,0 +1,5 @@
+module Admin::Teams::ProjectsHelper
+  def assigned_since(team, project)
+    team.user_team_project_relationships.find_by_project_id(project).created_at
+  end
+end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 6478982cdad3737a1a5957c7695f1225c98808fc..196105f011900ea89b815e6d751166c9df8510c2 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -72,8 +72,9 @@ module ApplicationHelper
   end
 
   def search_autocomplete_source
-    projects = current_user.authorized_projects.map { |p| { label: p.name_with_namespace, url: project_path(p) } }
-    groups = current_user.authorized_groups.map { |group| { label: "<group> #{group.name}", url: group_path(group) } }
+    projects = current_user.authorized_projects.map { |p| { label: "project: #{p.name_with_namespace}", url: project_path(p) } }
+    groups = current_user.authorized_groups.map { |group| { label: "group: #{group.name}", url: group_path(group) } }
+    teams = current_user.authorized_teams.map { |team| { label: "team: #{team.name}", url: team_path(team) } }
 
     default_nav = [
       { label: "My Profile", url: profile_path },
@@ -83,29 +84,29 @@ module ApplicationHelper
     ]
 
     help_nav = [
-      { label: "API Help", url: help_api_path },
-      { label: "Markdown Help", url: help_markdown_path },
-      { label: "Permissions Help", url: help_permissions_path },
-      { label: "Public Access Help", url: help_public_access_path },
-      { label: "Rake Tasks Help", url: help_raketasks_path },
-      { label: "SSH Keys Help", url: help_ssh_path },
-      { label: "System Hooks Help", url: help_system_hooks_path },
-      { label: "Web Hooks Help", url: help_web_hooks_path },
-      { label: "Workflow Help", url: help_workflow_path },
+      { label: "help: API Help", url: help_api_path },
+      { label: "help: Markdown Help", url: help_markdown_path },
+      { label: "help: Permissions Help", url: help_permissions_path },
+      { label: "help: Public Access Help", url: help_public_access_path },
+      { label: "help: Rake Tasks Help", url: help_raketasks_path },
+      { label: "help: SSH Keys Help", url: help_ssh_path },
+      { label: "help: System Hooks Help", url: help_system_hooks_path },
+      { label: "help: Web Hooks Help", url: help_web_hooks_path },
+      { label: "help: Workflow Help", url: help_workflow_path },
     ]
 
     project_nav = []
     if @project && @project.repository && @project.repository.root_ref
       project_nav = [
-        { label: "#{@project.name} Issues",   url: project_issues_path(@project) },
-        { label: "#{@project.name} Commits",  url: project_commits_path(@project, @ref || @project.repository.root_ref) },
-        { label: "#{@project.name} Merge Requests", url: project_merge_requests_path(@project) },
-        { label: "#{@project.name} Milestones", url: project_milestones_path(@project) },
-        { label: "#{@project.name} Snippets", url: project_snippets_path(@project) },
-        { label: "#{@project.name} Team",     url: project_team_index_path(@project) },
-        { label: "#{@project.name} Tree",     url: project_tree_path(@project, @ref || @project.repository.root_ref) },
-        { label: "#{@project.name} Wall",     url: wall_project_path(@project) },
-        { label: "#{@project.name} Wiki",     url: project_wikis_path(@project) },
+        { label: "#{@project.name_with_namespace} - Issues",   url: project_issues_path(@project) },
+        { label: "#{@project.name_with_namespace} - Commits",  url: project_commits_path(@project, @ref || @project.repository.root_ref) },
+        { label: "#{@project.name_with_namespace} - Merge Requests", url: project_merge_requests_path(@project) },
+        { label: "#{@project.name_with_namespace} - Milestones", url: project_milestones_path(@project) },
+        { label: "#{@project.name_with_namespace} - Snippets", url: project_snippets_path(@project) },
+        { label: "#{@project.name_with_namespace} - Team",     url: project_team_index_path(@project) },
+        { label: "#{@project.name_with_namespace} - Tree",     url: project_tree_path(@project, @ref || @project.repository.root_ref) },
+        { label: "#{@project.name_with_namespace} - Wall",     url: wall_project_path(@project) },
+        { label: "#{@project.name_with_namespace} - Wiki",     url: project_wikis_path(@project) },
       ]
     end
 
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index 4b5d8bd96a6fbcd45b68f6046e801b8a1cfd59c1..6d2ce2feea3082e5d258ab0e821df1a58f0b4a50 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -59,9 +59,9 @@ module CommitsHelper
 
   def image_diff_class(diff)
     if diff.deleted_file
-      "diff_removed"
+      "deleted"
     elsif diff.new_file
-      "diff_added"
+      "added"
     else
       nil
     end
diff --git a/app/helpers/dashboard_helper.rb b/app/helpers/dashboard_helper.rb
index 0baa5b4108ee3b049c944d375ac18102252e79c9..c759dffa16e1fcd501ad348dfc53509fdd594fa0 100644
--- a/app/helpers/dashboard_helper.rb
+++ b/app/helpers/dashboard_helper.rb
@@ -9,9 +9,9 @@ module DashboardHelper
 
     case entity
     when 'issue' then
-      dashboard_issues_path(options)
+      issues_dashboard_path(options)
     when 'merge_request'
-      dashboard_merge_requests_path(options)
+      merge_requests_dashboard_path(options)
     end
   end
 
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
index f4d9b17bce552d212bd490745fb7ddbf6cf563fd..38374e3394d97ef63d311b872f7d2a83b5851d53 100644
--- a/app/helpers/events_helper.rb
+++ b/app/helpers/events_helper.rb
@@ -1,10 +1,9 @@
 module EventsHelper
   def link_to_author(event)
-    project = event.project
-    tm = project.team_member_by_id(event.author_id) if project
+    author = event.author
 
-    if tm
-      link_to event.author_name, project_team_member_path(project, tm)
+    if author
+      link_to author.name, user_path(author.username)
     else
       event.author_name
     end
diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb
index 111982e9147ed5627ca4fda209f25d11263529ab..1a3d34eb886c672b4f66eb79a2e4e297582788c3 100644
--- a/app/helpers/gitlab_markdown_helper.rb
+++ b/app/helpers/gitlab_markdown_helper.rb
@@ -13,7 +13,13 @@ module GitlabMarkdownHelper
   def link_to_gfm(body, url, html_options = {})
     return "" if body.blank?
 
-    gfm_body = gfm(escape_once(body), html_options)
+    escaped_body = if body =~ /^\<img/
+                     body
+                   else
+                     escape_once(body)
+                   end
+
+    gfm_body = gfm(escaped_body, html_options)
 
     gfm_body.gsub!(%r{<a.*?>.*?</a>}m) do |match|
       "</a>#{match}#{link_to("", url, html_options)[0..-5]}" # "</a>".length +1
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 158925ba6c03737a7cfac1675d456cf5b37c2687..05303e86ae8977143a6730022007c09b48127119 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -3,8 +3,12 @@ module ProjectsHelper
     @project.users_projects.sort_by(&:project_access).reverse.group_by(&:project_access)
   end
 
-  def remove_from_team_message(project, member)
-    "You are going to remove #{member.user_name} from #{project.name}. Are you sure?"
+  def grouper_project_teams(project)
+    @project.user_team_project_relationships.sort_by(&:greatest_access).reverse.group_by(&:greatest_access)
+  end
+
+  def remove_from_project_team_message(project, user)
+    "You are going to remove #{user.name} from #{project.name} project team. Are you sure?"
   end
 
   def link_to_project project
@@ -39,7 +43,7 @@ module ProjectsHelper
     tm = project.team_member_by_id(author)
 
     if tm
-      link_to author_html, project_team_member_path(project, tm), class: "author_link"
+      link_to author_html, project_team_member_path(project, tm.user_username), class: "author_link"
     else
       author_html
     end.html_safe
@@ -51,7 +55,9 @@ module ProjectsHelper
 
   def project_title project
     if project.group
-      project.name_with_namespace
+      content_tag :span do
+        link_to(project.group.name, group_path(project.group)) + " / " + project.name
+      end
     else
       project.name
     end
diff --git a/app/helpers/tab_helper.rb b/app/helpers/tab_helper.rb
index d52d8af6641962da4f3255b3c5fa3e722d8d5d26..5bd6de896ee565f4601dc15a56f763df6d7aa44a 100644
--- a/app/helpers/tab_helper.rb
+++ b/app/helpers/tab_helper.rb
@@ -39,7 +39,12 @@ module TabHelper
   # Returns a list item element String
   def nav_link(options = {}, &block)
     if path = options.delete(:path)
-      c, a, _ = path.split('#')
+      if path.respond_to?(:each)
+        c = path.map { |p| p.split('#').first }
+        a = path.map { |p| p.split('#').last }
+      else
+        c, a, _ = path.split('#')
+      end
     else
       c = options.delete(:controller)
       a = options.delete(:action)
diff --git a/app/helpers/user_teams_helper.rb b/app/helpers/user_teams_helper.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2055bb3c8bcdc6625a58f2ff4c5ca56471189234
--- /dev/null
+++ b/app/helpers/user_teams_helper.rb
@@ -0,0 +1,26 @@
+module UserTeamsHelper
+  def team_filter_path(entity, options={})
+    exist_opts = {
+      status: params[:status],
+      project_id: params[:project_id],
+    }
+
+    options = exist_opts.merge(options)
+
+    case entity
+    when 'issue' then
+      issues_team_path(@team, options)
+    when 'merge_request'
+      merge_requests_team_path(@team, options)
+    end
+  end
+
+  def grouped_user_team_members(team)
+    team.user_team_user_relationships.sort_by(&:permission).reverse.group_by(&:permission)
+  end
+
+  def remove_from_user_team_message(team, member)
+    "You are going to remove #{member.name} from #{team.name}. Are you sure?"
+  end
+
+end
diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb
index 0ed06475fa8090fcfb2b5e10d90b03267ed7286c..08f7e01aab11c192ec46d6040283dfa42a635e2c 100644
--- a/app/mailers/notify.rb
+++ b/app/mailers/notify.rb
@@ -10,6 +10,10 @@ class Notify < ActionMailer::Base
 
   default from: Gitlab.config.gitlab.email_from
 
+  # Just send email with 3 seconds delay
+  def self.delay
+    delay_for(2.seconds)
+  end
 
 
   #
@@ -63,12 +67,12 @@ class Notify < ActionMailer::Base
   # Note
   #
 
-  def note_commit_email(commit_autor_email, note_id)
+  def note_commit_email(recipient_id, note_id)
     @note = Note.find(note_id)
     @commit = @note.noteable
     @commit = CommitDecorator.decorate(@commit)
     @project = @note.project
-    mail(to: commit_autor_email, subject: subject("note for commit #{@commit.short_id}", @commit.title))
+    mail(to: recipient(recipient_id), subject: subject("note for commit #{@commit.short_id}", @commit.title))
   end
 
   def note_issue_email(recipient_id, note_id)
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 9d33501fdbc57a0cb2c79b245a7396e8b9d77500..6d087a959a9320f9f744f217619b997fcbd8942c 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -1,15 +1,25 @@
 class Ability
   class << self
-    def allowed(object, subject)
+    def allowed(user, subject)
+      return [] unless user.kind_of?(User)
+
       case subject.class.name
-      when "Project" then project_abilities(object, subject)
-      when "Issue" then issue_abilities(object, subject)
-      when "Note" then note_abilities(object, subject)
-      when "Snippet" then snippet_abilities(object, subject)
-      when "MergeRequest" then merge_request_abilities(object, subject)
-      when "Group", "Namespace" then group_abilities(object, subject)
+      when "Project" then project_abilities(user, subject)
+      when "Issue" then issue_abilities(user, subject)
+      when "Note" then note_abilities(user, subject)
+      when "Snippet" then snippet_abilities(user, subject)
+      when "MergeRequest" then merge_request_abilities(user, subject)
+      when "Group", "Namespace" then group_abilities(user, subject)
+      when "UserTeam" then user_team_abilities(user, subject)
       else []
-      end
+      end.concat(global_abilities(user))
+    end
+
+    def global_abilities(user)
+      rules = []
+      rules << :create_group if user.can_create_group
+      rules << :create_team if user.can_create_team
+      rules
     end
 
     def project_abilities(user, project)
@@ -110,6 +120,22 @@ class Ability
       rules.flatten
     end
 
+    def user_team_abilities user, team
+      rules = []
+
+      # Only group owner and administrators can manage group
+      if team.owner == user || team.admin?(user) || user.admin?
+        rules << [ :manage_user_team ]
+      end
+
+      if team.owner == user || user.admin?
+        rules << [ :admin_user_team ]
+      end
+
+      rules.flatten
+    end
+
+
     [:issue, :note, :snippet, :merge_request].each do |name|
       define_method "#{name}_abilities" do |user, subject|
         if subject.author == user
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index d1717d3bbeef3dff620f486ab5f3b674a046a2a0..8872cf59a2cfa17fed8f461dc7e9037090911082 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -22,6 +22,7 @@ module Issuable
     scope :opened, where(closed: false)
     scope :closed, where(closed: true)
     scope :of_group, ->(group) { where(project_id: group.project_ids) }
+    scope :of_user_team, ->(team) { where(project_id: team.project_ids, assignee_id: team.member_ids) }
     scope :assigned, ->(u) { where(assignee_id: u.id)}
     scope :recent, order("created_at DESC")
 
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 40a6c01577d3b5477f3b4e4fe1818bae3a666efc..07c0401143c8050f35aad274ee2e71abdbf7a091 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -24,8 +24,6 @@ class Issue < ActiveRecord::Base
 
   acts_as_taggable_on :labels
 
-  validates :description, length: { within: 0..10000 }
-
   def self.open_for(user)
     opened.assigned(user)
   end
diff --git a/app/models/key.rb b/app/models/key.rb
index 2bf50f5656572122bb8bf0e47ac8d31efc7e9f34..895e8d6cb9ccbab7693ceb422fa19529286760b0 100644
--- a/app/models/key.rb
+++ b/app/models/key.rb
@@ -24,8 +24,8 @@ class Key < ActiveRecord::Base
   before_save :set_identifier
 
   validates :title, presence: true, length: { within: 0..255 }
-  validates :key, presence: true, length: { within: 0..5000 }, format: { :with => /ssh-.{3} / }
-  validate :unique_key, :fingerprintable_key
+  validates :key, presence: true, length: { within: 0..5000 }, format: { :with => /ssh-.{3} / }, uniqueness: true
+  validate :fingerprintable_key
 
   delegate :name, :email, to: :user, prefix: true
 
@@ -33,14 +33,6 @@ class Key < ActiveRecord::Base
     self.key = self.key.strip unless self.key.blank?
   end
 
-  def unique_key
-    query = Key.where(key: key)
-    query = query.where('(project_id IS NULL OR project_id = ?)', project_id) if project_id
-    if (query.count > 0)
-      errors.add :key, 'already exist.'
-    end
-  end
-
   def fingerprintable_key
     return true unless key # Don't test if there is no key.
     # `ssh-keygen -lf /dev/stdin <<< "#{key}"` errors with: redirection unexpected
@@ -65,7 +57,7 @@ class Key < ActiveRecord::Base
   end
 
   def is_deploy_key
-    true if project_id
+    !!project_id
   end
 
   # projects that has this key
@@ -77,7 +69,7 @@ class Key < ActiveRecord::Base
     end
   end
 
-  def last_deploy?
-    Key.where(identifier: identifier).count == 0
+  def shell_id
+    "key-#{self.id}"
   end
 end
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index ad04d0ef99b88045176cc6d3e7eec5c28e6e2249..f17d8f65183895cddf57189fe66c3a8ae725daba 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -27,7 +27,6 @@ class Namespace < ActiveRecord::Base
 
   after_create :ensure_dir_exist
   after_update :move_dir
-  after_commit :update_gitolite, on: :update, if: :require_update_gitolite
   after_destroy :rm_dir
 
   scope :root, where('type IS NULL')
@@ -89,11 +88,6 @@ class Namespace < ActiveRecord::Base
     end
   end
 
-  def update_gitolite
-    @require_update_gitolite = false
-    projects.each(&:update_repository)
-  end
-
   def rm_dir
     dir_path = File.join(Gitlab.config.gitolite.repos_path, path)
     FileUtils.rm_r( dir_path, force: true )
diff --git a/app/models/project.rb b/app/models/project.rb
index fa38093b7d5364e44cdc2d530fed762a4642d749..e6be2d2ce840fefcc406a77833c970fb969ea06b 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -8,7 +8,6 @@
 #  description            :text
 #  created_at             :datetime         not null
 #  updated_at             :datetime         not null
-#  private_flag           :boolean          default(TRUE), not null
 #  creator_id             :integer
 #  default_branch         :string(255)
 #  issues_enabled         :boolean          default(TRUE), not null
@@ -16,6 +15,7 @@
 #  merge_requests_enabled :boolean          default(TRUE), not null
 #  wiki_enabled           :boolean          default(TRUE), not null
 #  namespace_id           :integer
+#  public                 :boolean          default(FALSE), not null
 #
 
 require "grit"
@@ -33,28 +33,31 @@ class Project < ActiveRecord::Base
   attr_accessor :error_code
 
   # Relations
-  belongs_to :group, foreign_key: "namespace_id", conditions: "type = 'Group'"
+  belongs_to :creator,      foreign_key: "creator_id", class_name: "User"
+  belongs_to :group,        foreign_key: "namespace_id", conditions: "type = 'Group'"
   belongs_to :namespace
 
-  belongs_to :creator,
-    class_name: "User",
-    foreign_key: "creator_id"
-
-  has_many :users,          through: :users_projects
-  has_many :events,         dependent: :destroy
-  has_many :merge_requests, dependent: :destroy
-  has_many :issues,         dependent: :destroy, order: "closed, created_at DESC"
-  has_many :milestones,     dependent: :destroy
-  has_many :users_projects, dependent: :destroy
-  has_many :notes,          dependent: :destroy
-  has_many :snippets,       dependent: :destroy
-  has_many :deploy_keys,    dependent: :destroy, foreign_key: "project_id", class_name: "Key"
-  has_many :hooks,          dependent: :destroy, class_name: "ProjectHook"
-  has_many :wikis,          dependent: :destroy
-  has_many :protected_branches, dependent: :destroy
   has_one :last_event, class_name: 'Event', order: 'events.created_at DESC', foreign_key: 'project_id'
   has_one :gitlab_ci_service, dependent: :destroy
 
+  has_many :events,             dependent: :destroy
+  has_many :merge_requests,     dependent: :destroy
+  has_many :issues,             dependent: :destroy, order: "closed, created_at DESC"
+  has_many :milestones,         dependent: :destroy
+  has_many :users_projects,     dependent: :destroy
+  has_many :notes,              dependent: :destroy
+  has_many :snippets,           dependent: :destroy
+  has_many :deploy_keys,        dependent: :destroy, class_name: "Key", foreign_key: "project_id"
+  has_many :hooks,              dependent: :destroy, class_name: "ProjectHook"
+  has_many :wikis,              dependent: :destroy
+  has_many :protected_branches, dependent: :destroy
+  has_many :user_team_project_relationships, dependent: :destroy
+
+  has_many :users,          through: :users_projects
+  has_many :user_teams,     through: :user_team_project_relationships
+  has_many :user_team_user_relationships, through: :user_teams
+  has_many :user_teams_members, through: :user_team_user_relationships
+
   delegate :name, to: :owner, allow_nil: true, prefix: true
 
   # Validations
@@ -77,6 +80,8 @@ class Project < ActiveRecord::Base
   # Scopes
   scope :without_user, ->(user)  { where("id NOT IN (:ids)", ids: user.authorized_projects.map(&:id) ) }
   scope :not_in_group, ->(group) { where("id NOT IN (:ids)", ids: group.project_ids ) }
+  scope :without_team, ->(team) { team.projects.present? ? where("id NOT IN (:ids)", ids: team.projects.map(&:id)) : scoped  }
+  scope :in_team, ->(team) { where("id IN (:ids)", ids: team.projects.map(&:id)) }
   scope :in_namespace, ->(namespace) { where(namespace_id: namespace.id) }
   scope :sorted_by_activity, ->() { order("(SELECT max(events.created_at) FROM events WHERE events.project_id = projects.id) DESC") }
   scope :personal, ->(user) { where(namespace_id: user.namespace_id) }
@@ -122,7 +127,7 @@ class Project < ActiveRecord::Base
   end
 
   def team
-    @team ||= Team.new(self)
+    @team ||= ProjectTeam.new(self)
   end
 
   def repository
@@ -257,8 +262,6 @@ class Project < ActiveRecord::Base
 
       Gitlab::ProjectMover.new(self, old_dir, new_dir).execute
 
-      gitolite.move_repository(old_repo, self)
-
       save!
     end
   rescue Gitlab::ProjectMover::ProjectMoveError => ex
@@ -294,6 +297,9 @@ class Project < ActiveRecord::Base
   def trigger_post_receive(oldrev, newrev, ref, user)
     data = post_receive_data(oldrev, newrev, ref, user)
 
+    # Create satellite
+    self.satellite.create unless self.satellite.exists?
+
     # Create push event
     self.observe_push(data)
 
@@ -308,9 +314,6 @@ class Project < ActiveRecord::Base
       self.execute_services(data.dup)
     end
 
-    # Create satellite
-    self.satellite.create unless self.satellite.exists?
-
     # Discover the default branch, but only if it hasn't already been set to
     # something else
     if repository && default_branch.nil?
@@ -335,7 +338,7 @@ class Project < ActiveRecord::Base
   end
 
   def execute_hooks(data)
-    hooks.each { |hook| hook.execute(data) }
+    hooks.each { |hook| hook.async_execute(data) }
   end
 
   def execute_services(data)
@@ -454,14 +457,6 @@ class Project < ActiveRecord::Base
     namespace.try(:path) || ''
   end
 
-  def update_repository
-    gitolite.update_repository(self)
-  end
-
-  def destroy_repository
-    gitolite.remove_repository(self)
-  end
-
   def repo_exists?
     @repo_exists ||= (repository && repository.branches.present?)
   rescue
@@ -489,6 +484,11 @@ class Project < ActiveRecord::Base
     http_url = [Gitlab.config.gitlab.url, "/", path_with_namespace, ".git"].join('')
   end
 
+  def project_access_human(member)
+    project_user_relation = self.users_projects.find_by_user_id(member.id)
+    self.class.access_options.key(project_user_relation.project_access)
+  end
+
   # Check if current branch name is marked as protected in the system
   def protected_branch? branch_name
     protected_branches.map(&:name).include?(branch_name)
diff --git a/app/models/team.rb b/app/models/project_team.rb
similarity index 95%
rename from app/models/team.rb
rename to app/models/project_team.rb
index f235d20ebdbfc7285bd8d98db0aebcb907b0e3d1..c2cf83c0ca831177a54c85a26df30b0baeb32295 100644
--- a/app/models/team.rb
+++ b/app/models/project_team.rb
@@ -1,4 +1,4 @@
-class Team
+class ProjectTeam
   attr_accessor :project
 
   def initialize(project)
@@ -21,6 +21,10 @@ class Team
     end
   end
 
+  def get_tm user_id
+    project.users_projects.find_by_user_id(user_id)
+  end
+
   def add_user(user, access)
     add_users_ids([user.id], access)
   end
@@ -108,7 +112,6 @@ class Team
       source_team.each do |tm|
         tm.save
       end
-      target_project.update_repository
     end
 
     true
diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb
index 3308caf360a38e12cac1ab85e3bee63cdf09d40a..57229d507594cd1fa95d95479df6cfca2d57e662 100644
--- a/app/models/protected_branch.rb
+++ b/app/models/protected_branch.rb
@@ -18,13 +18,6 @@ class ProtectedBranch < ActiveRecord::Base
   validates :name, presence: true
   validates :project, presence: true
 
-  after_save :update_repository
-  after_destroy :update_repository
-
-  def update_repository
-    gitolite.update_repository(project)
-  end
-
   def commit
     project.repository.commit(self.name)
   end
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index 8d7eb788abb6e35f353c67ccd5efdc62d5499c22..806d346cf1084d0e4c3f2d96894ee62c084b1de2 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -28,7 +28,7 @@ class Snippet < ActiveRecord::Base
   validates :project, presence: true
   validates :title, presence: true, length: { within: 0..255 }
   validates :file_name, presence: true, length: { within: 0..255 }
-  validates :content, presence: true, length: { within: 0..10000 }
+  validates :content, presence: true
 
   # Scopes
   scope :fresh, order("created_at DESC")
diff --git a/app/models/user.rb b/app/models/user.rb
index 35a693fdb1c0beb4d58591af2685805fabfb4757..5b0df09a439780bbcc90ae731ffabb3e8af6bac6 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -31,6 +31,8 @@
 #  extern_uid             :string(255)
 #  provider               :string(255)
 #  username               :string(255)
+#  can_create_group       :boolean          default(TRUE), not null
+#  can_create_team        :boolean          default(TRUE), not null
 #
 
 class User < ActiveRecord::Base
@@ -40,23 +42,32 @@ class User < ActiveRecord::Base
   attr_accessible :email, :password, :password_confirmation, :remember_me, :bio, :name, :username,
                   :skype, :linkedin, :twitter, :dark_scheme, :theme_id, :force_random_password,
                   :extern_uid, :provider, as: [:default, :admin]
-  attr_accessible :projects_limit, as: :admin
+  attr_accessible :projects_limit, :can_create_team, :can_create_group, as: :admin
 
   attr_accessor :force_random_password
 
   # Namespace for personal projects
-  has_one :namespace, class_name: "Namespace", foreign_key: :owner_id, conditions: 'type IS NULL', dependent: :destroy
-  has_many :groups, class_name: "Group", foreign_key: :owner_id
-
-  has_many :keys, dependent: :destroy
-  has_many :users_projects, dependent: :destroy
-  has_many :issues, foreign_key: :author_id, dependent: :destroy
-  has_many :notes, foreign_key: :author_id, dependent: :destroy
-  has_many :merge_requests, foreign_key: :author_id, dependent: :destroy
-  has_many :events, class_name: "Event", foreign_key: :author_id, dependent: :destroy
-  has_many :recent_events, class_name: "Event", foreign_key: :author_id, order: "id DESC"
-  has_many :assigned_issues, class_name: "Issue", foreign_key: :assignee_id, dependent: :destroy
-  has_many :assigned_merge_requests, class_name: "MergeRequest", foreign_key: :assignee_id, dependent: :destroy
+  has_one :namespace,                 dependent: :destroy, foreign_key: :owner_id,    class_name: "Namespace", conditions: 'type IS NULL'
+
+  has_many :keys,                     dependent: :destroy
+  has_many :users_projects,           dependent: :destroy
+  has_many :issues,                   dependent: :destroy, foreign_key: :author_id
+  has_many :notes,                    dependent: :destroy, foreign_key: :author_id
+  has_many :merge_requests,           dependent: :destroy, foreign_key: :author_id
+  has_many :events,                   dependent: :destroy, foreign_key: :author_id,   class_name: "Event"
+  has_many :assigned_issues,          dependent: :destroy, foreign_key: :assignee_id, class_name: "Issue"
+  has_many :assigned_merge_requests,  dependent: :destroy, foreign_key: :assignee_id, class_name: "MergeRequest"
+
+  has_many :groups,         class_name: "Group", foreign_key: :owner_id
+  has_many :recent_events,  class_name: "Event", foreign_key: :author_id, order: "id DESC"
+
+  has_many :projects,       through: :users_projects
+
+  has_many :user_team_user_relationships, dependent: :destroy
+
+  has_many :user_teams,                      through: :user_team_user_relationships
+  has_many :user_team_project_relationships, through: :user_teams
+  has_many :team_projects,                   through: :user_team_project_relationships
 
   validates :name, presence: true
   validates :bio, length: { within: 0..255 }
@@ -80,6 +91,9 @@ class User < ActiveRecord::Base
   scope :blocked, where(blocked:  true)
   scope :active, where(blocked:  false)
   scope :alphabetically, order('name ASC')
+  scope :in_team, ->(team){ where(id: team.member_ids) }
+  scope :not_in_team, ->(team){ where('users.id NOT IN (:ids)', ids: team.member_ids) }
+  scope :potential_team_members, ->(team) { team.members.any? ? active.not_in_team(team) : active  }
 
   #
   # Class methods
@@ -131,6 +145,11 @@ class User < ActiveRecord::Base
   #
   # Instance methods
   #
+
+  def to_param
+    username
+  end
+
   def generate_password
     if self.force_random_password
       self.password = self.password_confirmation = Devise.friendly_token.first(8)
@@ -220,7 +239,7 @@ class User < ActiveRecord::Base
   end
 
   def can_create_group?
-    is_admin?
+    can?(:create_group, nil)
   end
 
   def abilities
@@ -283,4 +302,15 @@ class User < ActiveRecord::Base
   def namespace_id
     namespace.try :id
   end
+
+  def authorized_teams
+    @authorized_teams ||= begin
+                            ids = []
+                            ids << UserTeam.with_member(self).pluck('user_teams.id')
+                            ids << UserTeam.created_by(self).pluck('user_teams.id')
+                            ids.flatten
+
+                            UserTeam.where(id: ids)
+                          end
+  end
 end
diff --git a/app/models/user_team.rb b/app/models/user_team.rb
new file mode 100644
index 0000000000000000000000000000000000000000..dc8cf9eeb22dede1712ef000cd49f72544a99843
--- /dev/null
+++ b/app/models/user_team.rb
@@ -0,0 +1,109 @@
+# == Schema Information
+#
+# Table name: user_teams
+#
+#  id         :integer          not null, primary key
+#  name       :string(255)
+#  path       :string(255)
+#  owner_id   :integer
+#  created_at :datetime         not null
+#  updated_at :datetime         not null
+#
+
+class UserTeam < ActiveRecord::Base
+  attr_accessible :name, :owner_id, :path
+
+  belongs_to :owner, class_name: User
+
+  has_many :user_team_project_relationships, dependent: :destroy
+  has_many :user_team_user_relationships, dependent: :destroy
+
+  has_many :projects, through: :user_team_project_relationships
+  has_many :members,  through: :user_team_user_relationships, source: :user
+
+  validates :name, presence: true, uniqueness: true
+  validates :owner, presence: true
+  validates :path, uniqueness: true, presence: true, length: { within: 1..255 },
+            format: { with: Gitlab::Regex.path_regex,
+                      message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" }
+
+  scope :with_member, ->(user){ joins(:user_team_user_relationships).where(user_team_user_relationships: {user_id: user.id}) }
+  scope :with_project, ->(project){ joins(:user_team_project_relationships).where(user_team_project_relationships: {project_id: project})}
+  scope :without_project, ->(project){ where("user_teams.id NOT IN (:ids)", ids: (a = with_project(project); a.blank? ? 0 : a))}
+  scope :created_by, ->(user){ where(owner_id: user) }
+
+  class << self
+    def search query
+      where("name LIKE :query OR path LIKE :query", query: "%#{query}%")
+    end
+
+    def global_id
+      'GLN'
+    end
+
+    def access_roles
+      UsersProject.access_roles
+    end
+  end
+
+  def to_param
+    path
+  end
+
+  def assign_to_projects(projects, access)
+    projects.each do |project|
+      assign_to_project(project, access)
+    end
+  end
+
+  def assign_to_project(project, access)
+    Gitlab::UserTeamManager.assign(self, project, access)
+  end
+
+  def resign_from_project(project)
+    Gitlab::UserTeamManager.resign(self, project)
+  end
+
+  def add_members(users, access, group_admin)
+    users.each do |user|
+      add_member(user, access, group_admin)
+    end
+  end
+
+  def add_member(user, access, group_admin)
+    Gitlab::UserTeamManager.add_member_into_team(self, user, access, group_admin)
+  end
+
+  def remove_member(user)
+    Gitlab::UserTeamManager.remove_member_from_team(self, user)
+  end
+
+  def update_membership(user, options)
+    Gitlab::UserTeamManager.update_team_user_membership(self, user, options)
+  end
+
+  def update_project_access(project, permission)
+    Gitlab::UserTeamManager.update_project_greates_access(self, project, permission)
+  end
+
+  def max_project_access(project)
+    user_team_project_relationships.find_by_project_id(project).greatest_access
+  end
+
+  def human_max_project_access(project)
+    self.class.access_roles.invert[max_project_access(project)]
+  end
+
+  def default_projects_access(member)
+    user_team_user_relationships.find_by_user_id(member).permission
+  end
+
+  def human_default_projects_access(member)
+    self.class.access_roles.invert[default_projects_access(member)]
+  end
+
+  def admin?(member)
+    user_team_user_relationships.with_user(member).first.group_admin?
+  end
+
+end
diff --git a/app/models/user_team_project_relationship.rb b/app/models/user_team_project_relationship.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a7aa88970c77f5faeeed7534d4dc5ea48032d828
--- /dev/null
+++ b/app/models/user_team_project_relationship.rb
@@ -0,0 +1,40 @@
+# == Schema Information
+#
+# Table name: user_team_project_relationships
+#
+#  id              :integer          not null, primary key
+#  project_id      :integer
+#  user_team_id    :integer
+#  greatest_access :integer
+#  created_at      :datetime         not null
+#  updated_at      :datetime         not null
+#
+
+class UserTeamProjectRelationship < ActiveRecord::Base
+  attr_accessible :greatest_access, :project_id, :user_team_id
+
+  belongs_to :user_team
+  belongs_to :project
+
+  validates :project,   presence: true
+  validates :user_team, presence: true
+  validate :check_greatest_access
+
+  scope :with_project, ->(project){ where(project_id: project.id) }
+
+  def team_name
+    user_team.name
+  end
+
+  private
+
+  def check_greatest_access
+    errors.add(:base, :incorrect_access_code) unless correct_access?
+  end
+
+  def correct_access?
+    return false if greatest_access.blank?
+    return true if UsersProject.access_roles.has_value?(greatest_access)
+    false
+  end
+end
diff --git a/app/models/user_team_user_relationship.rb b/app/models/user_team_user_relationship.rb
new file mode 100644
index 0000000000000000000000000000000000000000..1f7e2625f5f4665472270932068b963521fa2846
--- /dev/null
+++ b/app/models/user_team_user_relationship.rb
@@ -0,0 +1,32 @@
+# == Schema Information
+#
+# Table name: user_team_user_relationships
+#
+#  id           :integer          not null, primary key
+#  user_id      :integer
+#  user_team_id :integer
+#  group_admin  :boolean
+#  permission   :integer
+#  created_at   :datetime         not null
+#  updated_at   :datetime         not null
+#
+
+class UserTeamUserRelationship < ActiveRecord::Base
+  attr_accessible :group_admin, :permission, :user_id, :user_team_id
+
+  belongs_to :user_team
+  belongs_to :user
+
+  validates :user_team, presence: true
+  validates :user,      presence: true
+
+  scope :with_user, ->(user) { where(user_id: user.id) }
+
+  def user_name
+    user.name
+  end
+
+  def access_human
+    UsersProject.access_roles.invert[permission]
+  end
+end
diff --git a/app/models/users_project.rb b/app/models/users_project.rb
index 79146289836cfd5bfd70b8721917b6c572fe0490..dd8ceb9da70e51ef7a16c548530948435c665d92 100644
--- a/app/models/users_project.rb
+++ b/app/models/users_project.rb
@@ -25,21 +25,21 @@ class UsersProject < ActiveRecord::Base
 
   attr_accessor :skip_git
 
-  after_save :update_repository, unless: :skip_git?
-  after_destroy :update_repository, unless: :skip_git?
-
   validates :user, presence: true
   validates :user_id, uniqueness: { scope: [:project_id], message: "already exists in project" }
   validates :project_access, inclusion: { in: [GUEST, REPORTER, DEVELOPER, MASTER] }, presence: true
   validates :project, presence: true
 
-  delegate :name, :email, to: :user, prefix: true
+  delegate :name, :username, :email, to: :user, prefix: true
 
   scope :guests, where(project_access: GUEST)
   scope :reporters, where(project_access: REPORTER)
   scope :developers, where(project_access: DEVELOPER)
   scope :masters, where(project_access: MASTER)
+
   scope :in_project, ->(project) { where(project_id: project.id) }
+  scope :in_projects, ->(projects) { where(project_id: project_ids) }
+  scope :with_user, ->(user) { where(user_id: user.id) }
 
   class << self
 
@@ -79,7 +79,6 @@ class UsersProject < ActiveRecord::Base
             users_project.save
           end
         end
-        Gitlab::Gitolite.new.update_repositories(Project.where(id: project_ids))
       end
 
       true
@@ -94,7 +93,6 @@ class UsersProject < ActiveRecord::Base
           users_project.skip_git = true
           users_project.destroy
         end
-        Gitlab::Gitolite.new.update_repositories(Project.where(id: project_ids))
       end
 
       true
@@ -125,10 +123,6 @@ class UsersProject < ActiveRecord::Base
     end
   end
 
-  def update_repository
-    gitolite.update_repository(project)
-  end
-
   def project_access_human
     Project.access_options.key(self.project_access)
   end
diff --git a/app/models/web_hook.rb b/app/models/web_hook.rb
index df58fa93b7e4d5c1a9f724f8ed7d30ff9184ddd1..efa27f31982d9faa16313271d7124169651668af 100644
--- a/app/models/web_hook.rb
+++ b/app/models/web_hook.rb
@@ -34,4 +34,8 @@ class WebHook < ActiveRecord::Base
                    basic_auth: {username: parsed_url.user, password: parsed_url.password})
     end
   end
+
+  def async_execute(data)
+    Sidekiq::Client.enqueue(ProjectWebHookWorker, id, data)
+  end
 end
diff --git a/app/observers/key_observer.rb b/app/observers/key_observer.rb
index bf5fa647647d9d628ef7bae009525246fd5261c8..4146216d82f16b96e96bc8640de6050905611165 100644
--- a/app/observers/key_observer.rb
+++ b/app/observers/key_observer.rb
@@ -2,11 +2,18 @@ class KeyObserver < ActiveRecord::Observer
   include Gitolited
 
   def after_save(key)
-    gitolite.set_key(key.identifier, key.key, key.projects)
+    GitoliteWorker.perform_async(
+      :add_key,
+      key.shell_id,
+      key.key
+    )
   end
 
   def after_destroy(key)
-    return if key.is_deploy_key && !key.last_deploy?
-    gitolite.remove_key(key.identifier, key.projects)
+    GitoliteWorker.perform_async(
+      :remove_key,
+      key.shell_id,
+      key.key,
+    )
   end
 end
diff --git a/app/observers/note_observer.rb b/app/observers/note_observer.rb
index 2ec644ef7c1f0e76f4af121b7653a9f5d85948a9..4ee9fadf4dad84d2ba2aa5aee2ceff339492d9c0 100644
--- a/app/observers/note_observer.rb
+++ b/app/observers/note_observer.rb
@@ -11,7 +11,9 @@ class NoteObserver < ActiveRecord::Observer
       notify_team(note)
     elsif note.notify_author
       # Notify only author of resource
-      Notify.delay.note_commit_email(note.noteable.author_email, note.id)
+      if note.commit_author
+        Notify.delay.note_commit_email(note.commit_author.id, note.id)
+      end
     else
       # Otherwise ignore it
       nil
diff --git a/app/observers/project_observer.rb b/app/observers/project_observer.rb
index b1c694569d7d4cd51bd2d299eb24d2810b776725..cc2a0224b722d2a9a59f5687fac11cac8b82327c 100644
--- a/app/observers/project_observer.rb
+++ b/app/observers/project_observer.rb
@@ -1,6 +1,11 @@
 class ProjectObserver < ActiveRecord::Observer
   def after_create(project)
-    project.update_repository
+    GitoliteWorker.perform_async(
+      :add_repository,
+      project.path_with_namespace
+    )
+
+    log_info("#{project.owner.name} created a new project \"#{project.name_with_namespace}\"")
   end
 
   def after_update(project)
@@ -8,13 +13,14 @@ class ProjectObserver < ActiveRecord::Observer
   end
 
   def after_destroy(project)
-    log_info("Project \"#{project.name}\" was removed")
+    GitoliteWorker.perform_async(
+      :remove_repository,
+      project.path_with_namespace
+    )
 
-    project.destroy_repository
-  end
+    project.satellite.destroy
 
-  def after_create project
-    log_info("#{project.owner.name} created a new project \"#{project.name}\"")
+    log_info("Project \"#{project.name}\" was removed")
   end
 
   protected
diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml
index 9a5e7edea0fd4281c2eb74fcafe487319b4e677c..46a876294ceb745f93098bfe2b8fdc147bcb2d51 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -6,7 +6,7 @@
         = link_to admin_projects_path do
           %h1= Project.count
         %hr
-        = link_to 'New Project', new_project_path, class: "btn small"
+        = link_to 'New Project', new_project_path, class: "btn btn-small"
   .span4
     .ui-box
       %h5.title Groups
@@ -14,7 +14,7 @@
         = link_to admin_groups_path do
           %h1= Group.count
         %hr
-        = link_to 'New Group', new_admin_group_path, class: "btn small"
+        = link_to 'New Group', new_admin_group_path, class: "btn btn-small"
   .span4
     .ui-box
       %h5.title Users
@@ -22,7 +22,7 @@
         = link_to admin_users_path do
           %h1= User.count
         %hr
-        = link_to 'New User', new_admin_user_path, class: "btn small"
+        = link_to 'New User', new_admin_user_path, class: "btn btn-small"
 
 .row
   .span4
@@ -31,7 +31,7 @@
     - @projects.each do |project|
       %p
         = link_to project.name_with_namespace, [:admin, project]
-        %span.light.right
+        %span.light.pull-right
           = time_ago_in_words project.created_at
           ago
 
@@ -42,7 +42,7 @@
       %p
         = link_to [:admin, user] do
           = user.name
-        %span.light.right
+        %span.light.pull-right
           = time_ago_in_words user.created_at
           ago
 
@@ -51,25 +51,25 @@
     %hr
     %p
       Issues
-      %span.light.right
+      %span.light.pull-right
         = Issue.count
     %p
       Merge Requests
-      %span.light.right
+      %span.light.pull-right
         = MergeRequest.count
     %p
       Notes
-      %span.light.right
+      %span.light.pull-right
         = Note.count
     %p
       Snippets
-      %span.light.right
+      %span.light.pull-right
         = Snippet.count
     %p
       SSH Keys
-      %span.light.right
+      %span.light.pull-right
         = Key.count
     %p
       Milestones
-      %span.light.right
+      %span.light.pull-right
         = Milestone.count
diff --git a/app/views/admin/groups/edit.html.haml b/app/views/admin/groups/edit.html.haml
index 901d07e74f36371212e4d97b49e5aa1a8cd5a9e1..dce044956c36558805fd007e125a70cbdb3acf75 100644
--- a/app/views/admin/groups/edit.html.haml
+++ b/app/views/admin/groups/edit.html.haml
@@ -2,7 +2,7 @@
 %hr
 = form_for [:admin, @group] do |f|
   - if @group.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %span= @group.errors.full_messages.first
   .clearfix.group_name_holder
     = f.label :name do
@@ -24,5 +24,5 @@
         %li It will change the git path to repositories under this group.
 
   .form-actions
-    = f.submit 'Rename group', class: "btn danger"
-    = link_to  'Cancel', admin_groups_path, class: "btn cancel-btn"
+    = f.submit 'Rename group', class: "btn btn-remove"
+    = link_to  'Cancel', admin_groups_path, class: "btn btn-cancel"
diff --git a/app/views/admin/groups/index.html.haml b/app/views/admin/groups/index.html.haml
index 49acedc8c79979413016533633ce36a5c90d45e0..25ce66575bfa79def312b6315fcfa9b0dbea7ce2 100644
--- a/app/views/admin/groups/index.html.haml
+++ b/app/views/admin/groups/index.html.haml
@@ -4,11 +4,11 @@
     allows you to keep projects organized.
     Use groups for uniting related projects.
 
-  = link_to 'New Group', new_admin_group_path, class: "btn small right"
+  = link_to 'New Group', new_admin_group_path, class: "btn btn-small pull-right"
 %br
 = form_tag admin_groups_path, method: :get, class: 'form-inline' do
   = text_field_tag :name, params[:name], class: "xlarge"
-  = submit_tag "Search", class: "btn submit primary"
+  = submit_tag "Search", class: "btn submit btn-primary"
 
 %table
   %thead
@@ -30,6 +30,6 @@
       %td
         = link_to group.owner_name, admin_user_path(group.owner_id)
       %td.bgred
-        = link_to 'Rename', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: "btn small"
-        = link_to 'Destroy', [:admin, group], confirm: "REMOVE #{group.name}? Are you sure?", method: :delete, class: "btn small danger"
+        = link_to 'Rename', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: "btn btn-small"
+        = link_to 'Destroy', [:admin, group], confirm: "REMOVE #{group.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove"
 = paginate @groups, theme: "admin"
diff --git a/app/views/admin/groups/new.html.haml b/app/views/admin/groups/new.html.haml
index 6ff0e781d1740461cbb40d9e9b6f0e8859a9edf8..60c6fa5ad090683891ccc8b4792f9fe607ce7496 100644
--- a/app/views/admin/groups/new.html.haml
+++ b/app/views/admin/groups/new.html.haml
@@ -2,7 +2,7 @@
 %hr
 = form_for [:admin, @group] do |f|
   - if @group.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %span= @group.errors.full_messages.first
   .clearfix
     = f.label :name do
@@ -10,7 +10,7 @@
     .input
       = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
       &nbsp;
-      = f.submit 'Create group', class: "btn primary"
+      = f.submit 'Create group', class: "btn btn-primary"
   %hr
   .padded
     %ul
diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml
index 0a25b125905365af537a9c8790e8ddf7d4ef58bf..6ae8a75d696992efd65e7e1cf812d50b5714e7a3 100644
--- a/app/views/admin/groups/show.html.haml
+++ b/app/views/admin/groups/show.html.haml
@@ -14,7 +14,7 @@
     %td
       = @group.name
       &nbsp;
-      = link_to edit_admin_group_path(@group), class: "btn btn-small right" do
+      = link_to edit_admin_group_path(@group), class: "btn btn-small pull-right" do
         %i.icon-edit
         Rename
   %tr
@@ -29,7 +29,7 @@
         Owner:
     %td
       = @group.owner_name
-      .right
+      .pull-right
         = link_to "#", class: "btn btn-small change-owner-link" do
           %i.icon-edit
           Change owner
@@ -42,7 +42,7 @@
       = form_for [:admin, @group] do |f|
         = f.select :owner_id, User.all.map { |user| [user.name, user.id] }, {}, {class: 'chosen'}
         %div
-          = f.submit 'Change Owner', class: "btn danger"
+          = f.submit 'Change Owner', class: "btn btn-remove"
           = link_to "Cancel", "#", class: "btn change-owner-cancel-link"
 
 - if @group.projects.any?
@@ -63,7 +63,7 @@
             %span.monospace= project.path_with_namespace + ".git"
           %td= project.users.count
           %td.bgred
-            = link_to 'Transfer project to global namespace', remove_project_admin_group_path(@group, project_id: project.id), confirm: 'Remove project from group and move to global namespace. Are you sure?', method: :delete, class: "btn danger small"
+            = link_to 'Transfer project to global namespace', remove_project_admin_group_path(@group, project_id: project.id), confirm: 'Remove project from group and move to global namespace. Are you sure?', method: :delete, class: "btn btn-remove small"
 
   = form_tag project_teams_update_admin_group_path(@group), id: "new_team_member", class: "bulk_import", method: :put  do
     %table.zebra-striped
@@ -72,22 +72,23 @@
           %th Users
           %th Project Access:
 
-      - @group.users.each do |u|
-        %tr{class: "user_#{u.id}"}
-          %td.name= link_to u.name, admin_user_path(u)
+      - @group.users.each do |user|
+        - next unless user
+        %tr{class: "user_#{user.id}"}
+          %td.name= link_to user.name, admin_user_path(user)
           %td.projects_access
-            - u.authorized_projects.in_namespace(@group).each do |project|
-              - u_p = u.users_projects.in_project(project).first
+            - user.authorized_projects.in_namespace(@group).each do |project|
+              - u_p = user.users_projects.in_project(project).first
               - next unless u_p
               %span
-                = project.name
-                = link_to "(#{ u_p.project_access_human })", edit_admin_team_member_path(u_p)
+                = project.name_with_namespace
+                = link_to "(#{ u_p.project_access_human })", edit_admin_project_member_path(project, user)
       %tr
         %td.input= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name), multiple: true, data: {placeholder: 'Select users'}, class: 'chosen span5'
         %td= select_tag :project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3"}
 
       %tr
-        %td= submit_tag 'Add user to projects in group', class: "btn primary"
+        %td= submit_tag 'Add user to projects in group', class: "btn btn-primary"
         %td
           Read more about project permissions
           %strong= link_to "here", help_permissions_path, class: "vlink"
@@ -109,7 +110,7 @@
       .input
         = select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name_with_namespace), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5'
     .form-actions
-      = submit_tag 'Add', class: "btn primary"
+      = submit_tag 'Add', class: "btn btn-primary"
 
 :javascript
   $(function(){
diff --git a/app/views/admin/hooks/index.html.haml b/app/views/admin/hooks/index.html.haml
index f17355fb2c2996f77851c7fa5704e50c454c52bb..acbf7a108b85d52168935a8fc33c689407ad619e 100644
--- a/app/views/admin/hooks/index.html.haml
+++ b/app/views/admin/hooks/index.html.haml
@@ -7,7 +7,7 @@
 
 = form_for @hook, as: :hook, url: admin_hooks_path, html: { class: 'form-inline' } do |f|
   -if @hook.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       - @hook.errors.full_messages.each do |msg|
         %p= msg
   .clearfix
@@ -15,7 +15,7 @@
     .input
       = f.text_field :url, class: "text_field xxlarge"
       &nbsp;
-      = f.submit "Add System Hook", class: "btn primary"
+      = f.submit "Add System Hook", class: "btn btn-primary"
 %hr
 
 -if @hooks.any?
@@ -33,7 +33,7 @@
         %td
           = link_to admin_hook_path(hook) do
             %strong= hook.url
-          = link_to 'Test Hook', admin_hook_test_path(hook), class: "btn small right"
+          = link_to 'Test Hook', admin_hook_test_path(hook), class: "btn btn-small pull-right"
         %td POST
         %td
-          = link_to 'Remove', admin_hook_path(hook), confirm: 'Are you sure?', method: :delete, class: "danger btn small right"
+          = link_to 'Remove', admin_hook_path(hook), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove btn-small pull-right"
diff --git a/app/views/admin/logs/show.html.haml b/app/views/admin/logs/show.html.haml
index c8be2ffa43cd923fd2c0206af7e16ab3e5a3ad6d..9ddd781c6ec4656e317c43cbb0f3be4d5e48bf88 100644
--- a/app/views/admin/logs/show.html.haml
+++ b/app/views/admin/logs/show.html.haml
@@ -15,7 +15,7 @@
       .file_title
         %i.icon-file
         githost.log
-        .right
+        .pull-right
           = link_to '#', class: 'log-bottom' do
             %i.icon-arrow-down
             Scroll down
@@ -29,7 +29,7 @@
       .file_title
         %i.icon-file
         application.log
-        .right
+        .pull-right
           = link_to '#', class: 'log-bottom' do
             %i.icon-arrow-down
             Scroll down
@@ -43,7 +43,7 @@
       .file_title
         %i.icon-file
         production.log
-        .right
+        .pull-right
           = link_to '#', class: 'log-bottom' do
             %i.icon-arrow-down
             Scroll down
@@ -57,7 +57,7 @@
       .file_title
         %i.icon-file
         sidekiq.log
-        .right
+        .pull-right
           = link_to '#', class: 'log-bottom' do
             %i.icon-arrow-down
             Scroll down
diff --git a/app/views/admin/projects/_form.html.haml b/app/views/admin/projects/_form.html.haml
index 0c7cf68ef439334b80834e96481eb842d978345a..ebf69924a2590e744d821c889cb4e94e3d22f653 100644
--- a/app/views/admin/projects/_form.html.haml
+++ b/app/views/admin/projects/_form.html.haml
@@ -1,6 +1,6 @@
 = form_for [:admin, project] do |f|
   -if project.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %ul
         - project.errors.full_messages.each do |msg|
           %li= msg
@@ -65,8 +65,8 @@
 
 
   .actions
-    = f.submit 'Save Project', class: "btn save-btn"
-    = link_to 'Cancel', admin_projects_path, class: "btn cancel-btn"
+    = f.submit 'Save Project', class: "btn btn-save"
+    = link_to 'Cancel', admin_projects_path, class: "btn btn-cancel"
 
 
 
diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml
index e47cda766369833b3867ef72fef4b95608ed6a90..15b2778252a367aa5e5f74b6062127cd3d8738c0 100644
--- a/app/views/admin/projects/index.html.haml
+++ b/app/views/admin/projects/index.html.haml
@@ -1,6 +1,6 @@
 %h3.page_title
   Projects
-  = link_to 'New Project', new_project_path, class: "btn small right"
+  = link_to 'New Project', new_project_path, class: "btn btn-small pull-right"
 
 %hr
 
@@ -37,7 +37,7 @@
 
 
         .form-actions
-          = submit_tag "Search", class: "btn submit primary"
+          = submit_tag "Search", class: "btn submit btn-primary"
           = link_to "Reset", admin_projects_path, class: "btn"
   .span8
     .ui-box
@@ -51,9 +51,9 @@
             - else
               %i.icon-lock.cgreen
             = link_to project.name_with_namespace, [:admin, project]
-            .right
-              = link_to 'Edit', edit_admin_project_path(project), id: "edit_#{dom_id(project)}", class: "btn small"
-              = link_to 'Destroy', [:admin, project], confirm: "REMOVE #{project.name}? Are you sure?", method: :delete, class: "btn small danger"
+            .pull-right
+              = link_to 'Edit', edit_admin_project_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small"
+              = link_to 'Destroy', [:admin, project], confirm: "REMOVE #{project.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove"
         - if @projects.blank?
           %p.nothing_here_message 0 projects matches
         - else
diff --git a/app/views/admin/projects/members/_form.html.haml b/app/views/admin/projects/members/_form.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..8041202980dabce7914b5b2dac95b7598637621a
--- /dev/null
+++ b/app/views/admin/projects/members/_form.html.haml
@@ -0,0 +1,16 @@
+= form_for @team_member_relation, as: :team_member, url: admin_project_member_path(@project, @member)  do |f|
+  -if @team_member_relation.errors.any?
+    .alert.alert-error
+      %ul
+        - @team_member_relation.errors.full_messages.each do |msg|
+          %li= msg
+
+  .clearfix
+    %label Project Access:
+    .input
+      = f.select :project_access, options_for_select(Project.access_options, @team_member_relation.project_access), {}, class: "project-access-select chosen span3"
+
+  %br
+  .actions
+    = f.submit 'Save', class: "btn btn-primary"
+    = link_to 'Cancel', :back, class: "btn"
diff --git a/app/views/admin/projects/members/edit.html.haml b/app/views/admin/projects/members/edit.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..2d76deb2aca195691d20e80b9524b5322e4d900c
--- /dev/null
+++ b/app/views/admin/projects/members/edit.html.haml
@@ -0,0 +1,8 @@
+%p.slead
+  Edit access for
+  = link_to @member.name, admin_user_path(@member)
+  in
+  = link_to @project.name_with_namespace, admin_project_path(@project)
+
+%hr
+= render 'form'
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index 8e0d82328dfb6e25265658407212cdfaf735dd9e..b9294bbafbe250e09eb558ff1b8a4542323cd44c 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -1,6 +1,6 @@
 %h3.page_title
   Project: #{@project.name_with_namespace}
-  = link_to edit_admin_project_path(@project), class: "btn right" do
+  = link_to edit_admin_project_path(@project), class: "btn pull-right" do
     %i.icon-edit
     Edit
 
@@ -114,9 +114,9 @@
 %h5
   Team
   %small
-    (#{@project.users_projects.count})
+    (#{@project.users.count})
 %br
-%table.zebra-striped
+%table.zebra-striped.team_members
   %thead
     %tr
       %th Name
@@ -124,13 +124,13 @@
       %th Repository Access
       %th
 
-  - @project.users_projects.each do |tm|
+  - @project.users.each do |tm|
     %tr
       %td
-        = link_to tm.user_name, admin_user_path(tm.user)
-      %td= tm.project_access_human
-      %td= link_to 'Edit Access', edit_admin_team_member_path(tm), class: "btn small"
-      %td= link_to 'Remove from team', admin_team_member_path(tm), confirm: 'Are you sure?', method: :delete, class: "btn danger small"
+        = link_to tm.name, admin_user_path(tm)
+      %td= @project.project_access_human(tm)
+      %td= link_to 'Edit Access', edit_admin_project_member_path(@project, tm), class: "btn btn-small"
+      %td= link_to 'Remove from team', admin_project_member_path(@project, tm), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove small"
 
 %br
 %h5 Add new team member
@@ -147,7 +147,7 @@
       %td= select_tag :project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3"}
 
     %tr
-      %td= submit_tag 'Add', class: "btn primary"
+      %td= submit_tag 'Add', class: "btn btn-primary"
       %td
         Read more about project permissions
         %strong= link_to "here", help_permissions_path, class: "vlink"
diff --git a/app/views/admin/team_members/_form.html.haml b/app/views/admin/team_members/_form.html.haml
deleted file mode 100644
index 9cd94fdd30f11e7cb40943b930f084031accd709..0000000000000000000000000000000000000000
--- a/app/views/admin/team_members/_form.html.haml
+++ /dev/null
@@ -1,16 +0,0 @@
-= form_for @admin_team_member, as: :team_member, url: admin_team_member_path(@admin_team_member)  do |f|
-  -if @admin_team_member.errors.any?
-    .alert-message.block-message.error
-      %ul
-        - @admin_team_member.errors.full_messages.each do |msg|
-          %li= msg
-
-  .clearfix
-    %label Project Access:
-    .input
-      = f.select :project_access, options_for_select(Project.access_options, @admin_team_member.project_access), {}, class: "project-access-select chosen span3"
-
-  %br
-  .actions
-    = f.submit 'Save', class: "btn primary"
-    = link_to 'Cancel', :back, class: "btn"
diff --git a/app/views/admin/team_members/edit.html.haml b/app/views/admin/team_members/edit.html.haml
deleted file mode 100644
index aea9bd70a79d29f6d658979a62976ac5f597beb2..0000000000000000000000000000000000000000
--- a/app/views/admin/team_members/edit.html.haml
+++ /dev/null
@@ -1,8 +0,0 @@
-%p.slead
-  Edit access for
-  = link_to @admin_team_member.user_name, admin_user_path(@admin_team_member)
-  in
-  = link_to @admin_team_member.project.name_with_namespace, admin_project_path(@admin_team_member)
-
-%hr
-= render 'form'
diff --git a/app/views/admin/teams/edit.html.haml b/app/views/admin/teams/edit.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..9282398ce5bfbfa4be6754ceaaf3277fa1c980a5
--- /dev/null
+++ b/app/views/admin/teams/edit.html.haml
@@ -0,0 +1,23 @@
+%h3.page_title Rename Team
+%hr
+= form_for @team, url: admin_team_path(@team), method: :put do |f|
+  - if @team.errors.any?
+    .alert.alert-error
+      %span= @team.errors.full_messages.first
+  .clearfix.team_name_holder
+    = f.label :name do
+      Team name is
+    .input
+      = f.text_field :name, placeholder: "Example Team", class: "xxlarge"
+
+  .clearfix.team_name_holder
+    = f.label :path do
+      %span.cred Team path is
+    .input
+      = f.text_field :path, placeholder: "example-team", class: "xxlarge danger"
+      %ul.cred
+        %li It will change web url for access team and team projects.
+
+  .form-actions
+    = f.submit 'Rename team', class: "btn btn-remove"
+    = link_to  'Cancel', admin_teams_path, class: "btn btn-cancel"
diff --git a/app/views/admin/teams/index.html.haml b/app/views/admin/teams/index.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..1f2f4763f76e4a2cd71ae6d346193177bbc4636a
--- /dev/null
+++ b/app/views/admin/teams/index.html.haml
@@ -0,0 +1,38 @@
+%h3.page_title
+  Teams
+  %small
+    simple Teams description
+
+  = link_to 'New Team', new_admin_team_path, class: "btn btn-small pull-right"
+  %br
+
+= form_tag admin_teams_path, method: :get, class: 'form-inline' do
+  = text_field_tag :name, params[:name], class: "xlarge"
+  = submit_tag "Search", class: "btn submit btn-primary"
+
+%table
+  %thead
+    %tr
+      %th
+        Name
+        %i.icon-sort-down
+      %th Path
+      %th Projects
+      %th Members
+      %th Owner
+      %th.cred Danger Zone!
+
+  - @teams.each do |team|
+    %tr
+      %td
+        %strong= link_to team.name, admin_team_path(team)
+      %td= team.path
+      %td= team.projects.count
+      %td= team.members.count
+      %td
+        = link_to team.owner.name, admin_user_path(team.owner_id)
+      %td.bgred
+        = link_to 'Rename', edit_admin_team_path(team), id: "edit_#{dom_id(team)}", class: "btn btn-small"
+        = link_to 'Destroy', admin_team_path(team), confirm: "REMOVE #{team.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove"
+
+= paginate @teams, theme: "admin"
diff --git a/app/views/admin/teams/members/_form.html.haml b/app/views/admin/teams/members/_form.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..f1388aab4bbf82cef500b5de5da583bb82df153d
--- /dev/null
+++ b/app/views/admin/teams/members/_form.html.haml
@@ -0,0 +1,20 @@
+= form_tag admin_team_member_path(@team, @member), method: :put do
+  -if @member.errors.any?
+    .alert.alert-error
+      %ul
+        - @member.errors.full_messages.each do |msg|
+          %li= msg
+
+  .clearfix
+    %label Default access for Team projects:
+    .input
+      = select_tag :default_project_access, options_for_select(UserTeam.access_roles, @team.default_projects_access(@member)), class: "project-access-select chosen span3"
+  .clearfix
+    %label Team admin?
+    .input
+      = check_box_tag :group_admin, true, @team.admin?(@member)
+
+  %br
+  .actions
+    = submit_tag 'Save', class: "btn btn-primary"
+    = link_to 'Cancel', :back, class: "btn"
diff --git a/app/views/admin/teams/members/edit.html.haml b/app/views/admin/teams/members/edit.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..a82847ee5f86a0492944193de17b72ca79e6b987
--- /dev/null
+++ b/app/views/admin/teams/members/edit.html.haml
@@ -0,0 +1,16 @@
+%h3
+  Edit access #{@member.name} in #{@team.name} team
+
+%hr
+%table.zebra-striped
+  %tr
+    %td User:
+    %td= @member.name
+  %tr
+    %td Team:
+    %td= @team.name
+  %tr
+    %td Since:
+    %td= member_since(@team, @member).stamp("Nov 11, 2010")
+
+= render 'form'
diff --git a/app/views/admin/teams/members/new.html.haml b/app/views/admin/teams/members/new.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..a37c941db5351b79603dfb7bf9c6d3d3929d885b
--- /dev/null
+++ b/app/views/admin/teams/members/new.html.haml
@@ -0,0 +1,29 @@
+%h3.page_title
+  Team: #{@team.name}
+
+%fieldset
+  %legend Members (#{@team.members.count})
+  = form_tag admin_team_members_path(@team), id: "team_members", class: "bulk_import", method: :post  do
+    %table#members_list
+      %thead
+        %tr
+          %th User name
+          %th Default project access
+          %th Team access
+          %th
+      - @team.members.each do |member|
+        %tr.member
+          %td
+            = link_to [:admin, member] do
+              = member.name
+              %small= "(#{member.email})"
+          %td= @team.human_default_projects_access(member)
+          %td= @team.admin?(member) ? "Admin" : "Member"
+          %td
+      %tr
+        %td= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name_with_email), multiple: true, data: {placeholder: 'Select users'}, class: 'chosen span5'
+        %td= select_tag :default_project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3" }
+        %td
+          %span= check_box_tag :group_admin
+          %span Admin?
+        %td= submit_tag 'Add', class: "btn btn-primary", id: :add_members_to_team
diff --git a/app/views/admin/teams/new.html.haml b/app/views/admin/teams/new.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..5d55a7975eecb477afb2e2612639b02c9730029e
--- /dev/null
+++ b/app/views/admin/teams/new.html.haml
@@ -0,0 +1,19 @@
+%h3.page_title New Team
+%hr
+= form_for @team, url: admin_teams_path do |f|
+  - if @team.errors.any?
+    .alert.alert-error
+      %span= @team.errors.full_messages.first
+  .clearfix
+    = f.label :name do
+      Team name is
+    .input
+      = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
+      &nbsp;
+      = f.submit 'Create team', class: "btn btn-primary"
+  %hr
+  .padded
+    %ul
+      %li All created teams are public (users can view who enter into team and which project are assigned for this team)
+      %li People within a team see only projects they have access to
+      %li You will be able to assign existing projects for team
diff --git a/app/views/admin/teams/projects/_form.html.haml b/app/views/admin/teams/projects/_form.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..5b79d518d42f24e9655b8485af1eb93f604518b2
--- /dev/null
+++ b/app/views/admin/teams/projects/_form.html.haml
@@ -0,0 +1,16 @@
+= form_tag admin_team_project_path(@team, @project), method: :put do
+  -if @project.errors.any?
+    .alert.alert-error
+      %ul
+        - @project.errors.full_messages.each do |msg|
+          %li= msg
+
+  .clearfix
+    %label Max access for Team members:
+    .input
+      = select_tag :greatest_project_access, options_for_select(UserTeam.access_roles, @team.max_project_access(@project)), class: "project-access-select chosen span3"
+
+  %br
+  .actions
+    = submit_tag 'Save', class: "btn btn-primary"
+    = link_to 'Cancel', :back, class: "btn"
diff --git a/app/views/admin/teams/projects/edit.html.haml b/app/views/admin/teams/projects/edit.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..b91a4982b81205f039d84f68eafeafbfe5f9281c
--- /dev/null
+++ b/app/views/admin/teams/projects/edit.html.haml
@@ -0,0 +1,16 @@
+%h3
+  Edit max access in #{@project.name} for #{@team.name} team
+
+%hr
+%table.zebra-striped
+  %tr
+    %td Project:
+    %td= @project.name
+  %tr
+    %td Team:
+    %td= @team.name
+  %tr
+    %td Since:
+    %td= assigned_since(@team, @project).stamp("Nov 11, 2010")
+
+= render 'form'
diff --git a/app/views/admin/teams/projects/new.html.haml b/app/views/admin/teams/projects/new.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..b60dad35214f9a793568f1166a8c5c0c8e9011af
--- /dev/null
+++ b/app/views/admin/teams/projects/new.html.haml
@@ -0,0 +1,23 @@
+%h3.page_title
+  Team: #{@team.name}
+
+%fieldset
+  %legend Projects (#{@team.projects.count})
+  = form_tag admin_team_projects_path(@team), id: "assign_projects", class: "bulk_import", method: :post  do
+    %table#projects_list
+      %thead
+        %tr
+          %th Project name
+          %th Max access
+          %th
+      - @team.projects.each do |project|
+        %tr.project
+          %td
+            = link_to project.name_with_namespace, [:admin, project]
+          %td
+            %span= @team.human_max_project_access(project)
+          %td
+      %tr
+        %td= select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name_with_namespace), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5'
+        %td= select_tag :greatest_project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3" }
+        %td= submit_tag 'Add', class: "btn btn-primary", id: :assign_projects_to_team
diff --git a/app/views/admin/teams/show.html.haml b/app/views/admin/teams/show.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..e5d079981c0f9b98d1c658ac09256e0144f2c21e
--- /dev/null
+++ b/app/views/admin/teams/show.html.haml
@@ -0,0 +1,101 @@
+%h3.page_title
+  Team: #{@team.name}
+
+%br
+%table.zebra-striped
+  %thead
+    %tr
+      %th Team
+      %th
+  %tr
+    %td
+      %b
+        Name:
+    %td
+      = @team.name
+      &nbsp;
+      = link_to edit_admin_team_path(@team), class: "btn btn-small pull-right" do
+        %i.icon-edit
+        Rename
+  %tr
+    %td
+      %b
+        Owner:
+    %td
+      = @team.owner.name
+      .pull-right
+        = link_to "#", class: "btn btn-small change-owner-link" do
+          %i.icon-edit
+          Change owner
+
+  %tr.change-owner-holder.hide
+    %td.bgred
+      %b.cred
+        New Owner:
+    %td.bgred
+      = form_for @team, url: admin_team_path(@team) do |f|
+        = f.select :owner_id, User.all.map { |user| [user.name, user.id] }, {}, {class: 'chosen'}
+        %div
+          = f.submit 'Change Owner', class: "btn btn-remove"
+          = link_to "Cancel", "#", class: "btn change-owner-cancel-link"
+
+%fieldset
+  %legend
+    Members (#{@team.members.count})
+    %span= link_to 'Add members', new_admin_team_member_path(@team), class: "btn btn-primary btn-small pull-right", id: :add_members_to_team
+  - if @team.members.any?
+    %table#members_list
+      %thead
+        %tr
+          %th User name
+          %th Default project access
+          %th Team access
+          %th.cred.span3 Danger Zone!
+      - @team.members.each do |member|
+        %tr.member{ class: "user_#{member.id}"}
+          %td
+            = link_to [:admin, member] do
+              = member.name
+              %small= "(#{member.email})"
+          %td= @team.human_default_projects_access(member)
+          %td= @team.admin?(member) ? "Admin" : "Member"
+          %td.bgred
+            = link_to 'Edit', edit_admin_team_member_path(@team, member), class: "btn btn-small"
+            &nbsp;
+            = link_to 'Remove', admin_team_member_path(@team, member), confirm: 'Remove member from team. Are you sure?', method: :delete, class: "btn btn-remove btn-small", id: "remove_member_#{member.id}"
+
+%fieldset
+  %legend
+    Projects (#{@team.projects.count})
+    %span= link_to 'Add projects', new_admin_team_project_path(@team), class: "btn btn-primary btn-small pull-right", id: :assign_projects_to_team
+  - if @team.projects.any?
+    %table#projects_list
+      %thead
+        %tr
+          %th Project name
+          %th Max access
+          %th.cred.span3 Danger Zone!
+      - @team.projects.each do |project|
+        %tr.project
+          %td
+            = link_to project.name_with_namespace, [:admin, project]
+          %td
+            %span= @team.human_max_project_access(project)
+          %td.bgred
+            = link_to 'Edit', edit_admin_team_project_path(@team, project), class: "btn btn-small"
+            &nbsp;
+            = link_to 'Relegate', admin_team_project_path(@team, project), confirm: 'Remove project from team. Are you sure?', method: :delete, class: "btn btn-remove small", id: "relegate_project_#{project.id}"
+
+:javascript
+  $(function(){
+    var modal = $('.change-owner-holder');
+    $('.change-owner-link').bind("click", function(){
+      $(this).hide();
+      modal.show();
+    });
+    $('.change-owner-cancel-link').bind("click", function(){
+      modal.hide();
+      $('.change-owner-link').show();
+    })
+  })
+
diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml
index 45195152cb707d3a83dbf5466f0d28b76b651523..51b05c05993cf647530ffeea93da4546b4ad017e 100644
--- a/app/views/admin/users/_form.html.haml
+++ b/app/views/admin/users/_form.html.haml
@@ -46,6 +46,14 @@
             = f.label :projects_limit
             .input= f.number_field :projects_limit
 
+          .clearfix
+            = f.label :can_create_group
+            .input= f.check_box :can_create_group
+
+          .clearfix
+            = f.label :can_create_team
+            .input= f.check_box :can_create_team
+
           .clearfix
             = f.label :admin do
               %strong.cred Administrator
@@ -55,10 +63,10 @@
             .alert.alert-error
               - if @admin_user.blocked
                 %p This user is blocked and is not able to login to GitLab
-                = link_to 'Unblock User', unblock_admin_user_path(@admin_user), method: :put, class: "btn small"
+                = link_to 'Unblock User', unblock_admin_user_path(@admin_user), method: :put, class: "btn btn-small"
               - else
                 %p Blocked users will be removed from all projects &amp; will not be able to login to GitLab.
-                = link_to 'Block User', block_admin_user_path(@admin_user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn small danger"
+                = link_to 'Block User', block_admin_user_path(@admin_user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn btn-small btn-remove"
     %fieldset
       %legend Profile
       .clearfix
@@ -72,8 +80,8 @@
         .input= f.text_field :twitter
 
     .actions
-      = f.submit 'Save', class: "btn save-btn"
+      = f.submit 'Save', class: "btn btn-save"
       - if @admin_user.new_record?
-        = link_to 'Cancel', admin_users_path, class: "btn cancel-btn"
+        = link_to 'Cancel', admin_users_path, class: "btn btn-cancel"
       - else
-        = link_to 'Cancel', admin_user_path(@admin_user), class: "btn cancel-btn"
+        = link_to 'Cancel', admin_user_path(@admin_user), class: "btn btn-cancel"
diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml
index 87290abe7a64ad14eb60575bf038938edc0de459..87d6309aefdfb8d1d1a2b45716e0c1e61c6baf65 100644
--- a/app/views/admin/users/index.html.haml
+++ b/app/views/admin/users/index.html.haml
@@ -1,11 +1,11 @@
 %h3.page_title
   Users
-  = link_to 'New User', new_admin_user_path, class: "btn small right"
+  = link_to 'New User', new_admin_user_path, class: "btn btn-small pull-right"
 %br
 
 = form_tag admin_users_path, method: :get, class: 'form-inline' do
   = text_field_tag :name, params[:name], class: "xlarge"
-  = submit_tag "Search", class: "btn submit primary"
+  = submit_tag "Search", class: "btn submit btn-primary"
 %ul.nav.nav-tabs
   %li{class: "#{'active' unless params[:filter]}"}
     = link_to admin_users_path do
@@ -44,15 +44,15 @@
       %td= user.username
       %td= user.email
       %td= user.users_projects.count
-      %td= link_to 'Edit', edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: "btn small"
+      %td= link_to 'Edit', edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: "btn btn-small"
       %td.bgred
         - if user == current_user
           %span.cred It's you!
         - else
           - if user.blocked
-            = link_to 'Unblock', unblock_admin_user_path(user), method: :put, class: "btn small success"
+            = link_to 'Unblock', unblock_admin_user_path(user), method: :put, class: "btn btn-small success"
           - else
-            = link_to 'Block', block_admin_user_path(user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn small danger"
-          = link_to 'Destroy', [:admin, user], confirm: "USER #{user.name} WILL BE REMOVED! Are you sure?", method: :delete, class: "btn small danger"
+            = link_to 'Block', block_admin_user_path(user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn btn-small btn-remove"
+          = link_to 'Destroy', [:admin, user], confirm: "USER #{user.name} WILL BE REMOVED! Are you sure?", method: :delete, class: "btn btn-small btn-remove"
 
 = paginate @admin_users, theme: "admin"
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index a3be6614136818f04a1b9c56d351b791f0c891d7..08201abd7d52b8a04e57cfb033b0f73352706e69 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -4,7 +4,7 @@
     %small Blocked
   - if @admin_user.admin
     %small Administrator
-  = link_to edit_admin_user_path(@admin_user), class: "btn right" do
+  = link_to edit_admin_user_path(@admin_user), class: "btn pull-right" do
     %i.icon-edit
     Edit
 
@@ -86,7 +86,7 @@
       %td= select_tag :project_access, options_for_select(Project.access_options), class: "project-access-select chosen span3"
 
     %tr
-      %td= submit_tag 'Add', class: "btn primary"
+      %td= submit_tag 'Add', class: "btn btn-primary"
       %td
         Read more about project permissions
         %strong= link_to "here", help_permissions_path, class: "vlink"
@@ -123,5 +123,5 @@
       %tr
         %td= link_to project.name_with_namespace, admin_project_path(project)
         %td= tm.project_access_human
-        %td= link_to 'Edit Access', edit_admin_team_member_path(tm), class: "btn small"
-        %td= link_to 'Remove from team', admin_team_member_path(tm), confirm: 'Are you sure?', method: :delete, class: "btn small danger"
+        %td= link_to 'Edit Access', edit_admin_project_member_path(project, tm.user), class: "btn btn-small"
+        %td= link_to 'Remove from team', admin_project_member_path(project, tm.user), confirm: 'Are you sure?', method: :delete, class: "btn btn-small btn-remove"
diff --git a/app/views/blame/_head.html.haml b/app/views/blame/_head.html.haml
index 85da18052b4aca1045b90c5f264fa060d4073299..ef9e6c9c53288280e7147b2f57b419ef3f150046 100644
--- a/app/views/blame/_head.html.haml
+++ b/app/views/blame/_head.html.haml
@@ -3,5 +3,5 @@
     = render partial: 'shared/ref_switcher', locals: {destination: 'tree', path: params[:path]}
   = nav_link(controller: :refs) do
     = link_to 'Source', project_tree_path(@project, @ref)
-  %li.right
+  %li.pull-right
     = render "shared/clone_panel"
diff --git a/app/views/commit/huge_commit.html.haml b/app/views/commit/huge_commit.html.haml
index ba97a7c572c79b234fd1978c0ed80476e72e30e3..7f0bcf380375a18ab529ff072aae5b2a612b3c6f 100644
--- a/app/views/commit/huge_commit.html.haml
+++ b/app/views/commit/huge_commit.html.haml
@@ -1,3 +1,3 @@
 = render "commits/commit_box"
-.alert-message.block-message.error
+.alert.alert-error
   %h4 Commit diffs are too big to be displayed
diff --git a/app/views/commit/show.html.haml b/app/views/commit/show.html.haml
index f920534e03a30aec6425576d29402e501892e9c1..485f2d1e67c6261e5a7ec27725cfca2d2e2ad464 100644
--- a/app/views/commit/show.html.haml
+++ b/app/views/commit/show.html.haml
@@ -1,6 +1,6 @@
 = render "commits/commit_box"
 
-%p.right.cgray
+%p.pull-right.cgray
   This commit has
   %span.cgreen #{@commit.stats.additions} additions
   and
@@ -11,19 +11,7 @@
 
 :javascript
   $(function(){
-    var w, h;
-    $('.diff_file').each(function(){
-      $('.image.diff_removed img', this).on('load', $.proxy(function(event){
-        var w = event.currentTarget.naturalWidth
-          , h = event.currentTarget.naturalHeight;
-        $('.image.diff_removed .image-info', this).append(' | <b>W:</b> ' + w + 'px | <b>H:</b> ' + h + 'px');
-      }, this));
-      $('.image.diff_added img', this).on('load', $.proxy(function(event){
-        var w = event.currentTarget.naturalWidth
-          , h = event.currentTarget.naturalHeight;
-        $('.image.diff_added .image-info', this).append(' | <b>W:</b> ' + w + 'px | <b>H:</b> ' + h + 'px');
-      }, this));
-
+    $('.files .file').each(function(){
+      new CommitFile(this);
     });
-
   });
diff --git a/app/views/commits/_commit_box.html.haml b/app/views/commits/_commit_box.html.haml
index 0544a1d10fee4a3f6bce9ecc37bd76b15bdca748..4c80c13ced14a481268f7e6ce4f839e154b46b9d 100644
--- a/app/views/commits/_commit_box.html.haml
+++ b/app/views/commits/_commit_box.html.haml
@@ -1,6 +1,6 @@
 .ui-box.ui-box-show
   .ui-box-head
-    .right
+    .pull-right
       - if @notes_count > 0
         %span.btn.disabled.grouped
           %i.icon-comment
@@ -13,7 +13,7 @@
         %ul.dropdown-menu
           %li= link_to "Email Patches", project_commit_path(@project, @commit, format: :patch)
           %li= link_to "Plain Diff",    project_commit_path(@project, @commit, format: :diff)
-      = link_to project_tree_path(@project, @commit), class: "btn primary grouped" do
+      = link_to project_tree_path(@project, @commit), class: "btn btn-primary grouped" do
         %span Browse Code »
     %h3.commit-title.page_title
       = gfm escape_once(@commit.title)
diff --git a/app/views/commits/_commits.html.haml b/app/views/commits/_commits.html.haml
index 0dc6664c1d6c078ae06db3f32c1843f2ae8836a3..191320933d35ee94b3faa6080b83375f6b71bae5 100644
--- a/app/views/commits/_commits.html.haml
+++ b/app/views/commits/_commits.html.haml
@@ -2,5 +2,5 @@
   %div.ui-box
     %h5.title
       %i.icon-calendar
-      = day.stamp("28 Aug, 2010")
+      %span= day.stamp("28 Aug, 2010")
     %ul.well-list= render commits
diff --git a/app/views/commits/_diffs.html.haml b/app/views/commits/_diffs.html.haml
index 7fe45aa25bc23149b9aacc29dfa4617b4ec40bf3..76f9f267b4166f350f8976155e50a04e4600fa3e 100644
--- a/app/views/commits/_diffs.html.haml
+++ b/app/views/commits/_diffs.html.haml
@@ -1,7 +1,7 @@
 - if @suppress_diff
-  .alert-message.block-message
+  .alert.alert-block
     %p
-      %strong Warning! Large commit with more then #{Commit::DIFF_SAFE_SIZE} files changed.
+      %strong Warning! Large commit with more than #{Commit::DIFF_SAFE_SIZE} files changed.
     %p To prevent performance issue we rejected diff information.
     %p
       But if you still want to see diff
@@ -12,50 +12,38 @@
 .file-stats
   = render "commits/diff_head", diffs: diffs
 
-- unless @suppress_diff
-  - diffs.each_with_index do |diff, i|
-    - next if diff.diff.empty?
-    - file = (@commit.tree / diff.new_path)
-    - file = (@commit.prev_commit.tree / diff.old_path) unless file
-    - next unless file
-    .diff_file{id: "diff-#{i}"}
-      .diff_file_header
-        - if diff.deleted_file
-          %span= diff.old_path
+.files
+  - unless @suppress_diff
+    - diffs.each_with_index do |diff, i|
+      - next if diff.diff.empty?
+      - file = (@commit.tree / diff.new_path)
+      - file = (@commit.prev_commit.tree / diff.old_path) unless file
+      - next unless file
+      .file{id: "diff-#{i}"}
+        .header
+          - if diff.deleted_file
+            %span= diff.old_path
 
-          - if @commit.prev_commit
-            = link_to project_tree_path(@project, tree_join(@commit.prev_commit_id, diff.new_path)), {:class => 'btn right view-commit'} do
+            - if @commit.prev_commit
+              = link_to project_tree_path(@project, tree_join(@commit.prev_commit_id, diff.new_path)), {:class => 'btn pull-right view-file'} do
+                View file @
+                %span.commit-short-id= @commit.short_id(6)
+          - else
+            %span= diff.new_path
+            - if diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode
+              %span.file-mode= "#{diff.a_mode} → #{diff.b_mode}"
+
+            = link_to project_tree_path(@project, tree_join(@commit.id, diff.new_path)), {:class => 'btn btn-tiny pull-right view-file'} do
               View file @
               %span.commit-short-id= @commit.short_id(6)
-        - else
-          %span= diff.new_path
-          - if diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode
-            %span.file-mode= "#{diff.a_mode} → #{diff.b_mode}"
-
-          = link_to project_tree_path(@project, tree_join(@commit.id, diff.new_path)), {:class => 'btn very_small right view-commit'} do
-            View file @
-            %span.commit-short-id= @commit.short_id(6)
 
-        %br/
-      .diff_file_content
-        -# Skip all non-supported blobs
-        - next unless file.respond_to?('text?')
-        - if file.text?
-          = render "commits/text_diff", diff: diff, index: i
-        - elsif file.image?
-          - old_file = (@commit.prev_commit.tree / diff.old_path) if !@commit.prev_commit.nil?
-          - if diff.renamed_file || diff.new_file || diff.deleted_file
-            .diff_file_content_image
-              .image{class: image_diff_class(diff)}
-                %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"}
-                %div.image-info= "#{number_to_human_size file.size}"
+        .content
+          -# Skipp all non non-supported blobs
+          - next unless file.respond_to?('text?')
+          - if file.text?
+            = render "commits/text_file", diff: diff, index: i
+          - elsif file.image?
+            - old_file = (@commit.prev_commit.tree / diff.old_path) if !@commit.prev_commit.nil?
+            = render "commits/image", diff: diff, old_file: old_file, file: file, index: i
           - else
-            .diff_file_content_image.img_compared
-              .image.diff_removed
-                %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(old_file.data)}"}
-                %div.image-info= "#{number_to_human_size file.size}"
-              .image.diff_added
-                %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"}
-                %div.image-info= "#{number_to_human_size file.size}"
-        - else
-          %p.nothing_here_message No preview for this file type
+            %p.nothing_here_message No preview for this file type
diff --git a/app/views/commits/_head.html.haml b/app/views/commits/_head.html.haml
index a5f3fdf5c5e47170a0040b14ff33c4773b4acf49..02debe426fefefa84886887b6d840d6bfedfd97c 100644
--- a/app/views/commits/_head.html.haml
+++ b/app/views/commits/_head.html.haml
@@ -22,7 +22,7 @@
 
 
   - if current_controller?(:commits) && current_user.private_token
-    %li.right
+    %li.pull-right
       %span.rss-icon
         = link_to project_commits_path(@project, @ref, {format: :atom, private_token: current_user.private_token}), title: "Feed" do
           = image_tag "rss_ui.png", title: "feed"
diff --git a/app/views/commits/_image.html.haml b/app/views/commits/_image.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..db02fa333b93779587b9414e406df83f10a6c902
--- /dev/null
+++ b/app/views/commits/_image.html.haml
@@ -0,0 +1,63 @@
+- if diff.renamed_file || diff.new_file || diff.deleted_file
+  .image
+    %span.wrap
+      .frame{class: image_diff_class(diff)}
+        %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"}
+      %p.image-info= "#{number_to_human_size file.size}"
+- else
+  .image
+    %div.two-up.view
+      %span.wrap
+        .frame.deleted
+          %a{href: project_tree_path(@project, tree_join(@commit.id, diff.old_path))}
+            %img{src: "data:#{old_file.mime_type};base64,#{Base64.encode64(old_file.data)}"}
+        %p.image-info.hide
+          %span.meta-filesize= "#{number_to_human_size old_file.size}"
+          |
+          %b W:
+          %span.meta-width 
+          |
+          %b H:
+          %span.meta-height
+      %span.wrap
+        .frame.added
+          %a{href: project_tree_path(@project, tree_join(@commit.id, diff.new_path))}
+            %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"}
+        %p.image-info.hide
+          %span.meta-filesize= "#{number_to_human_size file.size}"
+          |
+          %b W:
+          %span.meta-width 
+          |
+          %b H:
+          %span.meta-height
+
+    %div.swipe.view.hide
+      .swipe-frame
+        .frame.deleted
+          %img{src: "data:#{old_file.mime_type};base64,#{Base64.encode64(old_file.data)}"}
+        .swipe-wrap
+          .frame.added
+            %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"}
+        %span.swipe-bar
+          %span.top-handle
+          %span.bottom-handle
+
+    %div.onion-skin.view.hide
+      .onion-skin-frame
+        .frame.deleted
+          %img{src: "data:#{old_file.mime_type};base64,#{Base64.encode64(old_file.data)}"}
+        .frame.added
+          %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"}
+        .controls
+          .transparent
+          .drag-track
+            .dragger{:style => "left: 0px;"}
+          .opaque
+
+
+  .view-modes.hide
+    %ul.view-modes-menu
+      %li.two-up{data: {mode: 'two-up'}} 2-up
+      %li.swipe{data: {mode: 'swipe'}} Swipe
+      %li.onion-skin{data: {mode: 'onion-skin'}} Onion skin
\ No newline at end of file
diff --git a/app/views/commits/_text_diff.html.haml b/app/views/commits/_text_file.html.haml
similarity index 95%
rename from app/views/commits/_text_diff.html.haml
rename to app/views/commits/_text_file.html.haml
index 8afad96bde2702338c536f9199c315df87daea23..760fd07ed8b9f7175158de5acdd924d9e54eeb94 100644
--- a/app/views/commits/_text_diff.html.haml
+++ b/app/views/commits/_text_file.html.haml
@@ -2,7 +2,7 @@
 - if too_big
   %a.supp_diff_link Diff suppressed. Click to show
 
-%table{class: "#{'hide' if too_big}"}
+%table.text-file{class: "#{'hide' if too_big}"}
   - each_diff_line(diff, index) do |line, type, line_code, line_new, line_old|
     %tr.line_holder{ id: line_code }
       - if type == "match"
diff --git a/app/views/commits/show.html.haml b/app/views/commits/show.html.haml
index 9451a038df057692cd6ac6672d72305bf091d576..d180b8ec4260e9f07bad7a56c0354ebb4eb8f69a 100644
--- a/app/views/commits/show.html.haml
+++ b/app/views/commits/show.html.haml
@@ -5,7 +5,7 @@
     = breadcrumbs
 
 %div{id: dom_id(@project)}
-  #commits_list= render "commits"
+  #commits-list= render "commits"
 .clear
 .loading{ style: "display:none;"}
 
diff --git a/app/views/compare/_form.html.haml b/app/views/compare/_form.html.haml
index 0915782dddc70d637ecac033a0678dc9d1523c28..7c0688a2287b8732d1ba716ccda28ff09aa0b3b1 100644
--- a/app/views/compare/_form.html.haml
+++ b/app/views/compare/_form.html.haml
@@ -19,7 +19,7 @@
         = text_field_tag :to, params[:to], placeholder: "aa8b4ef", class: "xlarge"
       .pull-left
         &nbsp;
-        = submit_tag "Compare", class: "btn primary wide commits-compare-btn"
+        = submit_tag "Compare", class: "btn btn-primary wide commits-compare-btn"
     - if @refs_are_same
       .alert
         %span Refs are the same
diff --git a/app/views/dashboard/_filter.html.haml b/app/views/dashboard/_filter.html.haml
index 4624af799487e5486fa7a630a24776d7d74f4d88..82e679d5927c422c0284bdb99f116e917b2f4cbf 100644
--- a/app/views/dashboard/_filter.html.haml
+++ b/app/views/dashboard/_filter.html.haml
@@ -25,9 +25,9 @@
           %li{class: ("active" if params[:project_id] == project.id.to_s)}
             = link_to dashboard_filter_path(entity, project_id: project.id) do
               = project.name_with_namespace
-              %small.right= entities_per_project(project, entity)
+              %small.pull-right= entities_per_project(project, entity)
 
   %fieldset
     %hr
-    = link_to "Reset", dashboard_filter_path(entity), class: 'btn right'
+    = link_to "Reset", dashboard_filter_path(entity), class: 'btn pull-right'
 
diff --git a/app/views/dashboard/_groups.html.haml b/app/views/dashboard/_groups.html.haml
index 7f544406761afaf88de0c4a11e8aa960ad0c0764..ba8d3029eaf4f5949d6f832961dc092ba6b712f4 100644
--- a/app/views/dashboard/_groups.html.haml
+++ b/app/views/dashboard/_groups.html.haml
@@ -1,11 +1,11 @@
-.groups_box
+.ui-box
   %h5.title
     Groups
     %small
       (#{groups.count})
     - if current_user.can_create_group?
-      %span.right
-        = link_to new_admin_group_path, class: "btn very_small info" do
+      %span.pull-right
+        = link_to new_group_path, class: "btn btn-tiny info" do
           %i.icon-plus
           New Group
   %ul.well-list
@@ -13,8 +13,6 @@
       %li
         = link_to group_path(id: group.path), class: dom_class(group) do
           %strong.well-title= truncate(group.name, length: 35)
-          %span.arrow
-            &rarr;
-          %span.last_activity
-            %strong Projects:
-            %span= current_user.authorized_projects.where(namespace_id: group.id).count
+        %span.pull-right.light
+          - if group.owner == current_user
+            %i.icon-wrench
diff --git a/app/views/dashboard/_projects.html.haml b/app/views/dashboard/_projects.html.haml
index 6c1304ee4a852d187a6c3b7cd4d355e6e75e5108..30fb726801452d5fe9e9b6b24c1451c4f7b7f280 100644
--- a/app/views/dashboard/_projects.html.haml
+++ b/app/views/dashboard/_projects.html.haml
@@ -2,19 +2,12 @@
   %h5.title
     Projects
     %small
-      (#{projects.total_count})
+      (#{@projects_count})
     - if current_user.can_create_project?
-      %span.right
-        = link_to new_project_path, class: "btn very_small info" do
+      %span.pull-right
+        = link_to new_project_path, class: "btn btn-tiny info" do
           %i.icon-plus
           New Project
-  %ul.nav.nav-projects-tabs
-    = nav_tab :scope, nil do
-      = link_to "All", dashboard_path
-    = nav_tab :scope, 'personal' do
-      = link_to "Personal", dashboard_path(scope: 'personal')
-    = nav_tab :scope, 'joined' do
-      = link_to "Joined", dashboard_path(scope: 'joined')
 
   %ul.well-list
     - projects.each do |project|
@@ -33,4 +26,6 @@
     - if projects.blank?
       %li
         %h3.nothing_here_message There are no projects here.
-  .bottom= paginate projects, theme: "gitlab"
+    - if @projects_count > 20
+      %li.bottom
+        %strong= link_to "show all projects", projects_dashboard_path
diff --git a/app/views/dashboard/_sidebar.html.haml b/app/views/dashboard/_sidebar.html.haml
index 9830cdf4f6b85ee1d1d46116edd240a7945c02e3..7c6daf6ec311868e254dd795a96979ac84d93245 100644
--- a/app/views/dashboard/_sidebar.html.haml
+++ b/app/views/dashboard/_sidebar.html.haml
@@ -1,3 +1,5 @@
+- if @teams.present?
+  = render "teams", teams: @teams
 - if @groups.present?
   = render "groups", groups: @groups
 = render "projects", projects: @projects
diff --git a/app/views/dashboard/_teams.html.haml b/app/views/dashboard/_teams.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..f56115856a741f55afab3662c7ed93184255f2c5
--- /dev/null
+++ b/app/views/dashboard/_teams.html.haml
@@ -0,0 +1,20 @@
+.ui-box.teams-box
+  %h5.title
+    Teams
+    %small
+      (#{@teams.count})
+    %span.pull-right
+      = link_to new_team_path, class: "btn btn-tiny info" do
+        %i.icon-plus
+        New Team
+  %ul.well-list
+    - @teams.each do |team|
+      %li
+        = link_to team_path(id: team.path), class: dom_class(team) do
+          %strong.well-title= truncate(team.name, length: 35)
+        %span.pull-right.light
+          - if team.owner == current_user
+            %i.icon-wrench
+          - tm = current_user.user_team_user_relationships.find_by_user_team_id(team.id)
+          - if tm
+            = tm.access_human
diff --git a/app/views/dashboard/_zero_authorized_projects.html.haml b/app/views/dashboard/_zero_authorized_projects.html.haml
index d1676ed11fadc6d7ec51a788c413ea0db96457d0..4b0d0d6873d13a3ddc1d0186bd9d8debd090908c 100644
--- a/app/views/dashboard/_zero_authorized_projects.html.haml
+++ b/app/views/dashboard/_zero_authorized_projects.html.haml
@@ -6,7 +6,7 @@
     = current_user.projects_limit
     projects. Click on button below to add a new one
     .link_holder
-      = link_to new_project_path, class: "btn primary" do
+      = link_to new_project_path, class: "btn btn-primary" do
         New Project »
   - else
     If you will be added to project - it will be displayed here
diff --git a/app/views/dashboard/issues.atom.builder b/app/views/dashboard/issues.atom.builder
index 28bdc5ed814e8083c300f63d9c2d9d45403f3f11..0f0f3466e92dce54addf87855d1a39f993673f1c 100644
--- a/app/views/dashboard/issues.atom.builder
+++ b/app/views/dashboard/issues.atom.builder
@@ -1,9 +1,9 @@
 xml.instruct!
 xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do
   xml.title   "#{current_user.name} issues"
-  xml.link    :href => dashboard_issues_url(:atom, :private_token => current_user.private_token), :rel => "self", :type => "application/atom+xml"
-  xml.link    :href => dashboard_issues_url(:private_token => current_user.private_token), :rel => "alternate", :type => "text/html"
-  xml.id      dashboard_issues_url(:private_token => current_user.private_token)
+  xml.link    :href => issues_dashboard_url(:atom, :private_token => current_user.private_token), :rel => "self", :type => "application/atom+xml"
+  xml.link    :href => issues_dashboard_url(:private_token => current_user.private_token), :rel => "alternate", :type => "text/html"
+  xml.id      issues_dashboard_url(:private_token => current_user.private_token)
   xml.updated @issues.first.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") if @issues.any?
 
   @issues.each do |issue|
diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml
index 307d0d85ea3ab18f49dc82c8d0e9b0e81412bd30..affe01a7ef94fba499d04eedd928adc65e35ff9d 100644
--- a/app/views/dashboard/issues.html.haml
+++ b/app/views/dashboard/issues.html.haml
@@ -1,7 +1,7 @@
 %h3.page_title
   Issues
   %small (assigned to you)
-  %small.right #{@issues.total_count} issues
+  %small.pull-right #{@issues.total_count} issues
 
 %hr
 
diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml
index 0c4d6e0aadfbe30a6aa3984a88e3dd1558ea6821..a311729dd4d3386c3afa4f17e26729a98f3292c4 100644
--- a/app/views/dashboard/merge_requests.html.haml
+++ b/app/views/dashboard/merge_requests.html.haml
@@ -1,7 +1,7 @@
 %h3.page_title
   Merge Requests
   %small (authored by or assigned to you)
-  %small.right #{@merge_requests.total_count} merge requests
+  %small.pull-right #{@merge_requests.total_count} merge requests
 
 %hr
 .row
diff --git a/app/views/dashboard/projects.html.haml b/app/views/dashboard/projects.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..8e21b0c7e023e032be82d739187a1da933bd385b
--- /dev/null
+++ b/app/views/dashboard/projects.html.haml
@@ -0,0 +1,56 @@
+%h3.page_title
+  Projects
+  %span
+    (#{@projects.total_count})
+  - if current_user.can_create_project?
+    %span.pull-right
+      = link_to new_project_path, class: "btn btn-tiny info" do
+        %i.icon-plus
+        New Project
+
+
+%hr
+.row
+  .span3
+    %ul.nav.nav-pills.nav-stacked
+      = nav_tab :scope, nil do
+        = link_to "All", projects_dashboard_path
+      = nav_tab :scope, 'personal' do
+        = link_to "Personal", projects_dashboard_path(scope: 'personal')
+      = nav_tab :scope, 'joined' do
+        = link_to "Joined", projects_dashboard_path(scope: 'joined')
+
+  .span9
+    = form_tag projects_dashboard_path, method: 'get' do
+      %fieldset.dashboard-search-filter
+        = hidden_field_tag "scope", params[:scope]
+        = search_field_tag "search", params[:search], { placeholder: 'Search', class: 'left input-xxlarge' }
+        = button_tag type: 'submit', class: 'btn' do
+          %i.icon-search
+
+    %ul.well-list
+      - @projects.each do |project|
+        %li.clearfix
+          .left
+            = link_to project_path(project), class: dom_class(project) do
+              - if project.namespace
+                = project.namespace.human_name
+                \/
+              %strong.well-title
+                = truncate(project.name, length: 25)
+            %br
+            %small.light
+              %strong Last activity:
+              %span= project_last_activity(project)
+          .pull-right.light
+            - if project.owner == current_user
+              %i.icon-wrench
+            - tm = project.team.get_tm(current_user.id)
+            - if tm
+              = tm.project_access_human
+
+      - if @projects.blank?
+        %li
+          %h3.nothing_here_message There are no projects here.
+    .bottom= paginate @projects, theme: "gitlab"
+
diff --git a/app/views/dashboard/index.atom.builder b/app/views/dashboard/show.atom.builder
similarity index 100%
rename from app/views/dashboard/index.atom.builder
rename to app/views/dashboard/show.atom.builder
diff --git a/app/views/dashboard/index.html.haml b/app/views/dashboard/show.html.haml
similarity index 100%
rename from app/views/dashboard/index.html.haml
rename to app/views/dashboard/show.html.haml
diff --git a/app/views/dashboard/index.js.haml b/app/views/dashboard/show.js.haml
similarity index 100%
rename from app/views/dashboard/index.js.haml
rename to app/views/dashboard/show.js.haml
diff --git a/app/views/deploy_keys/_form.html.haml b/app/views/deploy_keys/_form.html.haml
index 6beba562a9508967fa429e3a30dafe00dbbf94f5..5fb83021dc08a94e1d1e8856162bc10e159a7161 100644
--- a/app/views/deploy_keys/_form.html.haml
+++ b/app/views/deploy_keys/_form.html.haml
@@ -1,7 +1,7 @@
 %div
   = form_for [@project, @key], url: project_deploy_keys_path do |f|
     -if @key.errors.any?
-      .alert-message.block-message.error
+      .alert.alert-error
         %ul
           - @key.errors.full_messages.each do |msg|
             %li= msg
@@ -18,6 +18,6 @@
           = link_to "here", help_ssh_path
 
     .actions
-      = f.submit 'Save', class: "save-btn btn"
-      = link_to "Cancel", project_deploy_keys_path(@project), class: "btn cancel-btn"
+      = f.submit 'Save', class: "btn-save btn"
+      = link_to "Cancel", project_deploy_keys_path(@project), class: "btn btn-cancel"
 
diff --git a/app/views/deploy_keys/_show.html.haml b/app/views/deploy_keys/_show.html.haml
index a5314ae92ade74b90fb77c1ed5e63dda373b22cb..635054350ecec96baa4fdf756e7f6f852c3a111d 100644
--- a/app/views/deploy_keys/_show.html.haml
+++ b/app/views/deploy_keys/_show.html.haml
@@ -8,5 +8,5 @@
       = time_ago_in_words(key.created_at)
       ago
   %td
-    = link_to 'Remove', project_deploy_key_path(key.project, key), confirm: 'Are you sure?', method: :delete, class: "danger btn delete-key small right"
+    = link_to 'Remove', project_deploy_key_path(key.project, key), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove delete-key btn-small pull-right"
 
diff --git a/app/views/deploy_keys/index.html.haml b/app/views/deploy_keys/index.html.haml
index b9c654a1abe5cbbc7d974f0f3ba66638e430daaf..db167f4e2f29b115c943ca139b17ca70065d9df8 100644
--- a/app/views/deploy_keys/index.html.haml
+++ b/app/views/deploy_keys/index.html.haml
@@ -4,7 +4,7 @@
   Deploy keys allow read-only access to repository. It matches perfectly for CI, staging or production servers.
 
   - if can? current_user, :admin_project, @project
-    = link_to new_project_deploy_key_path(@project), class: "btn small", title: "New Deploy Key" do
+    = link_to new_project_deploy_key_path(@project), class: "btn btn-small", title: "New Deploy Key" do
       Add Deploy Key
 - if @keys.any?
   %table
diff --git a/app/views/deploy_keys/show.html.haml b/app/views/deploy_keys/show.html.haml
index c94cf10dde09a62dd15258c9cad2ca5108d741b6..227afecb0619a60156a17359ea52df3caf5c680c 100644
--- a/app/views/deploy_keys/show.html.haml
+++ b/app/views/deploy_keys/show.html.haml
@@ -10,5 +10,5 @@
     &larr; To keys list
 %hr
 %pre= @key.key
-.right
-  = link_to 'Remove', project_deploy_key_path(@key.project, @key), confirm: 'Are you sure?', method: :delete, class: "danger btn delete-key"
+.pull-right
+  = link_to 'Remove', project_deploy_key_path(@key.project, @key), confirm: 'Are you sure?', method: :delete, class: "btn-remove btn delete-key"
diff --git a/app/views/devise/passwords/edit.html.haml b/app/views/devise/passwords/edit.html.haml
index 31d355673ab2b0c9f5f7cfe4a9157b219a83d6a4..e5800025c6de847e49120dba55e06a9b3e0d6cbf 100644
--- a/app/views/devise/passwords/edit.html.haml
+++ b/app/views/devise/passwords/edit.html.haml
@@ -8,5 +8,5 @@
   %div
     = f.password_field :password_confirmation, class: "text bottom", placeholder: "Confirm new password"
   %div
-    = f.submit "Change my password", class: "btn primary"
-    .right= render partial: "devise/shared/links"
+    = f.submit "Change my password", class: "btn btn-primary"
+    .pull-right= render partial: "devise/shared/links"
diff --git a/app/views/devise/passwords/new.html.erb b/app/views/devise/passwords/new.html.erb
index 860d67d19e7a9c8f5bd70d1a13115c70aabbf7e7..0e39f3187265d6c76327b9d45fa1574d1578516b 100644
--- a/app/views/devise/passwords/new.html.erb
+++ b/app/views/devise/passwords/new.html.erb
@@ -1,9 +1,9 @@
-<%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :class => "login-box", :method => :post }) do |f| %>
-  <%= image_tag "login-logo.png", :width => "304", :height => "66", :class => "login-logo", :alt => "Login Logo" %>
+<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { class: "login-box", method: :post }) do |f| %>
+  <%= image_tag "login-logo.png", width: "304", height: "66", class: "login-logo", alt: "Login Logo" %>
   <%= devise_error_messages! %>
-  <%= f.email_field :email, :placeholder => "Email",  :class => "text" %>
+  <%= f.email_field :email, placeholder: "Email",  class: "text" %>
   <br/>
   <br/>
-  <%= f.submit "Reset password", :class => "primary btn"  %>
-  <div class="right"> <%= link_to "Sign in", new_session_path(resource_name), :class => "btn" %><br /></div>
+  <%= f.submit "Reset password", class: "btn-primary btn"  %>
+  <div class="pull-right"> <%= link_to "Sign in", new_session_path(resource_name), class: "btn" %><br /></div>
 <% end %>
diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml
index 81eb26222615109a82fcf8beddfc5b07383be2d6..12b0438229b9d6071a0ed9ae45f04f48f6b5777f 100644
--- a/app/views/devise/registrations/new.html.haml
+++ b/app/views/devise/registrations/new.html.haml
@@ -1,19 +1,18 @@
-= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :class => "login-box" }) do |f|
-  = image_tag "login-logo.png", :width => "304", :height => "66", :class => "login-logo", :alt => "Login Logo"
+= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { class: "login-box" }) do |f|
+  = image_tag "login-logo.png", width: "304", height: "66", class: "login-logo", alt: "Login Logo"
   = devise_error_messages!
   %div
-    = f.text_field :name, :class => "text top", :placeholder => "Name", :required => true
+    = f.text_field :name, class: "text top", placeholder: "Name", required: true
   %div
-    = f.text_field :username, :class => "text middle", :placeholder => "Username", :required => true
+    = f.text_field :username, class: "text middle", placeholder: "Username", required: true
   %div
-    = f.email_field :email, :class => "text middle", :placeholder => "Email", :required => true
+    = f.email_field :email, class: "text middle", placeholder: "Email", required: true
   %div
-    = f.password_field :password, :class => "text middle", :placeholder => "Password", :required => true
+    = f.password_field :password, class: "text middle", placeholder: "Password", required: true
   %div
-    = f.password_field :password_confirmation, :class => "text bottom", :placeholder => "Confirm password", :required => true
+    = f.password_field :password_confirmation, class: "text bottom", placeholder: "Confirm password", required: true
   %div
-    = f.submit "Sign up", :class => "primary btn wide"
-  %br
+    = f.submit "Sign up", class: "btn-create btn"
   %hr
   = link_to "Sign in", new_session_path(resource_name)
-  = link_to "Forgot your password?", new_password_path(resource_name), :class => "right"
+  = link_to "Forgot your password?", new_password_path(resource_name), class: "pull-right"
diff --git a/app/views/devise/sessions/_new_ldap.html.haml b/app/views/devise/sessions/_new_ldap.html.haml
index 4233aa61ecb5d80bab88186b737bb3435670eba0..7968b0e9c9fdcb7a4222baacd4bf1cf128c7d027 100644
--- a/app/views/devise/sessions/_new_ldap.html.haml
+++ b/app/views/devise/sessions/_new_ldap.html.haml
@@ -3,11 +3,11 @@
   = text_field_tag :username, nil, {:class => "text top", :placeholder => "LDAP Login"}
   = password_field_tag :password, nil, {:class => "text bottom", :placeholder => "Password"}
   %br/
-  = submit_tag "LDAP Sign in", :class => "primary btn"
+  = submit_tag "LDAP Sign in", :class => "btn-primary btn"
   - if devise_mapping.omniauthable?
     - (resource_class.omniauth_providers - [:ldap]).each do |provider|
       %hr/
-      = link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider), :class => "btn primary"
+      = link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider), :class => "btn btn-primary"
       %br/
   %hr/
   %a#other_form_toggle{:href => "#", :onclick => "javascript:$('#new_user').toggle();"} Other Sign in
@@ -24,6 +24,6 @@
         = f.check_box :remember_me
         %span Remember me
   %br/
-  = f.submit "Sign in", :class => "primary btn"
-  .right
+  = f.submit "Sign in", :class => "btn-primary btn"
+  .pull-right
     = render :partial => "devise/shared/links"
diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml
index 0983f3157c4eeee3bd6690309e41acaa179825ae..d904e701b8ab25102483cbf08d26a4d876dd81f8 100644
--- a/app/views/devise/sessions/new.html.haml
+++ b/app/views/devise/sessions/new.html.haml
@@ -11,18 +11,18 @@
           = f.check_box :remember_me
           %span Remember me
     %br/
-    = f.submit "Sign in", :class => "primary btn wide"
-    .right
+    = f.submit "Sign in", :class => "btn-create btn"
+    .pull-right
       = link_to "Forgot your password?", new_password_path(resource_name), :class => "btn"
     %br/
-    %br/
     - if Gitlab.config.gitlab.signup_enabled
       %hr/
       Don't have an account?
       = link_to "Sign up", new_registration_path(resource_name)
-    .clearfix
     - if devise_mapping.omniauthable? && resource_class.omniauth_providers.present?
+      %hr
       %div
+        %span Sign in with: &nbsp;
         - resource_class.omniauth_providers.each do |provider|
           %span
             = link_to authbutton(provider, 32), omniauth_authorize_path(resource_name, provider)
diff --git a/app/views/events/_event.html.haml b/app/views/events/_event.html.haml
index 191aed0747e0b3c39cb1bf775a6683bf72401523..719f6c3787f982752d118d097001381e89772718 100644
--- a/app/views/events/_event.html.haml
+++ b/app/views/events/_event.html.haml
@@ -1,6 +1,6 @@
 - if event.proper?
   %div.event-item
-    %span.cgray.right
+    %span.cgray.pull-right
       #{time_ago_in_words(event.created_at)} ago.
 
     = image_tag gravatar_icon(event.author_email), class: "avatar s24"
diff --git a/app/views/projects/graph.html.haml b/app/views/graph/show.html.haml
similarity index 51%
rename from app/views/projects/graph.html.haml
rename to app/views/graph/show.html.haml
index 4e0b0e36c343afc6caf338217ed8c3c350e5268d..ca3a8706313ee75af30ccab845ae850aac356760 100644
--- a/app/views/projects/graph.html.haml
+++ b/app/views/graph/show.html.haml
@@ -1,5 +1,7 @@
 %h3.page_title Project Network Graph
 %br
+= render partial: 'shared/ref_switcher', locals: {destination: 'graph', path: @path}
+%br
 .graph_holder
   %h4
     %small You can move around the graph by using the arrow keys.
@@ -10,7 +12,8 @@
   var branch_graph;
   $(function(){
     branch_graph = new BranchGraph($("#holder"), {
-      url: '#{url_for controller: 'projects', action: 'graph', format: :json}',
-      commit_url: '#{url_for controller: 'projects', action: 'show'}/commits/%s'
+      url: '#{project_graph_path(@project, @ref, format: :json)}',
+      commit_url: '#{project_commit_path(@project, 'ae45ca32').gsub("ae45ca32", "%s")}',
+      ref: '#{@ref}'
     });
   });
diff --git a/app/views/groups/_filter.html.haml b/app/views/groups/_filter.html.haml
index c8b0ad0f4339c8772b67a64d07fbc3e8a68da8d2..c14fc8e5e4b725440a35f3a5e27d3266b8d4bd5c 100644
--- a/app/views/groups/_filter.html.haml
+++ b/app/views/groups/_filter.html.haml
@@ -25,9 +25,9 @@
           %li{class: ("active" if params[:project_id] == project.id.to_s)}
             = link_to group_filter_path(entity, project_id: project.id) do
               = project.name_with_namespace
-              %small.right= entities_per_project(project, entity)
+              %small.pull-right= entities_per_project(project, entity)
 
   %fieldset
     %hr
-    = link_to "Reset", group_filter_path(entity), class: 'btn right'
+    = link_to "Reset", group_filter_path(entity), class: 'btn pull-right'
 
diff --git a/app/views/groups/_new_group_member.html.haml b/app/views/groups/_new_group_member.html.haml
index 2d599816e2ac584be3447b7adbb048f018b69fcf..9cdbea60370ba69c13a201e941b6577bcc470145 100644
--- a/app/views/groups/_new_group_member.html.haml
+++ b/app/views/groups/_new_group_member.html.haml
@@ -14,5 +14,5 @@
 
     .form-actions
       = hidden_field_tag :redirect_to, people_group_path(@group)
-      = f.submit 'Add', class: "btn save-btn"
+      = f.submit 'Add', class: "btn btn-save"
 
diff --git a/app/views/groups/_new_member.html.haml b/app/views/groups/_new_member.html.haml
index 89ac05e774e760433e2ab000df3e94e928356f47..b3424b01bcb5ab54dc9e9202592a20a9035f0ea8 100644
--- a/app/views/groups/_new_member.html.haml
+++ b/app/views/groups/_new_member.html.haml
@@ -14,5 +14,5 @@
 
     .form-actions
       = hidden_field_tag :redirect_to, people_group_path(@group, project_id: @project.id)
-      = f.submit 'Add', class: "btn save-btn"
+      = f.submit 'Add', class: "btn btn-save"
 
diff --git a/app/views/groups/_people_filter.html.haml b/app/views/groups/_people_filter.html.haml
index 79a1b01a5faad5763ce877525c3b2a0b39598461..901a037adf32f46cb534887cf839284b6763fbbb 100644
--- a/app/views/groups/_people_filter.html.haml
+++ b/app/views/groups/_people_filter.html.haml
@@ -6,9 +6,9 @@
         %li{class: ("active" if params[:project_id] == project.id.to_s)}
           = link_to people_group_path(@group, project_id: project.id) do
             = project.name_with_namespace
-            %small.right= project.users.count
+            %small.pull-right= project.users.count
 
   %fieldset
     %hr
-    = link_to "Reset", people_group_path(@group), class: 'btn right'
+    = link_to "Reset", people_group_path(@group), class: 'btn pull-right'
 
diff --git a/app/views/groups/_projects.html.haml b/app/views/groups/_projects.html.haml
index 040d1ae94aae6a79f0da1817f4d1f9f368936873..4fa4a1779835cd8aeaaf2c25fbff7156628f6f66 100644
--- a/app/views/groups/_projects.html.haml
+++ b/app/views/groups/_projects.html.haml
@@ -4,8 +4,8 @@
     %small
       (#{projects.count})
     - if can? current_user, :manage_group, @group
-      %span.right
-        = link_to new_project_path(namespace_id: @group.id), class: "btn very_small info" do
+      %span.pull-right
+        = link_to new_project_path(namespace_id: @group.id), class: "btn btn-tiny info" do
           %i.icon-plus
           New Project
   %ul.well-list
diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..7202ef26c70af5f4a3f7f06f38d46e480bf7ab5d
--- /dev/null
+++ b/app/views/groups/edit.html.haml
@@ -0,0 +1,50 @@
+%h3.page_title Edit Group
+%hr
+= form_for @group do |f|
+  - if @group.errors.any?
+    .alert.alert-error
+      %span= @group.errors.full_messages.first
+  .clearfix
+    = f.label :name do
+      Group name is
+    .input
+      = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
+      &nbsp;
+      = f.submit 'Save group', class: "btn btn-save"
+%hr
+
+
+.row
+  .span7
+    .ui-box
+      %h5.title Projects
+      %ul.well-list
+        - @group.projects.each do |project|
+          %li
+            - if project.public
+              %i.icon-share
+            - else
+              %i.icon-lock.cgreen
+            = link_to project.name_with_namespace, project
+            .pull-right
+              = link_to 'Team', project_team_index_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small"
+              = link_to 'Edit', edit_project_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small"
+              = link_to 'Remove', project, confirm: "REMOVE #{project.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove"
+
+  .span5
+    .ui-box
+      %h5.title Transfer group
+      .padded
+        %p
+          Transferring group will cause loss of admin control over group and all child projects
+        = form_for @group do |f|
+          = f.select :owner_id, User.all.map { |user| [user.name, user.id] }, {}, {class: 'chosen'}
+          = f.submit 'Transfer group', class: "btn btn-small"
+    .ui-box
+      %h5.title Remove group
+      .padded.bgred
+        %p
+          Remove of group will cause removing all child projects and resources
+          %br
+          Removed group can not be restored!
+        = link_to 'Remove Group', @group, confirm: 'Removed group can not be restored! Are you sure?', method: :delete, class: "btn btn-remove btn-small"
diff --git a/app/views/groups/issues.atom.builder b/app/views/groups/issues.atom.builder
index 5bd07bcd89ff2352c63d43feb9c3d71cdad6e495..701747bdbc3242cfd894e95ed4666dc4b0331c16 100644
--- a/app/views/groups/issues.atom.builder
+++ b/app/views/groups/issues.atom.builder
@@ -1,9 +1,9 @@
 xml.instruct!
 xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do
   xml.title   "#{@user.name} issues"
-  xml.link    :href => dashboard_issues_url(:atom, :private_token => @user.private_token), :rel => "self", :type => "application/atom+xml"
-  xml.link    :href => dashboard_issues_url(:private_token => @user.private_token), :rel => "alternate", :type => "text/html"
-  xml.id      dashboard_issues_url(:private_token => @user.private_token)
+  xml.link    :href => issues_dashboard_url(:atom, :private_token => @user.private_token), :rel => "self", :type => "application/atom+xml"
+  xml.link    :href => issues_dashboard_url(:private_token => @user.private_token), :rel => "alternate", :type => "text/html"
+  xml.id      issues_dashboard_url(:private_token => @user.private_token)
   xml.updated @issues.first.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") if @issues.any?
 
   @issues.each do |issue|
diff --git a/app/views/groups/issues.html.haml b/app/views/groups/issues.html.haml
index 9e8642f3b2c6abb7c1003c6724db220640667ffe..94682bdd51e035611cef5b90fbcd72d70d8b00c6 100644
--- a/app/views/groups/issues.html.haml
+++ b/app/views/groups/issues.html.haml
@@ -1,7 +1,7 @@
 %h3.page_title
   Issues
   %small (assigned to you)
-  %small.right #{@issues.total_count} issues
+  %small.pull-right #{@issues.total_count} issues
 
 %hr
 .row
diff --git a/app/views/groups/merge_requests.html.haml b/app/views/groups/merge_requests.html.haml
index 0c4d6e0aadfbe30a6aa3984a88e3dd1558ea6821..a311729dd4d3386c3afa4f17e26729a98f3292c4 100644
--- a/app/views/groups/merge_requests.html.haml
+++ b/app/views/groups/merge_requests.html.haml
@@ -1,7 +1,7 @@
 %h3.page_title
   Merge Requests
   %small (authored by or assigned to you)
-  %small.right #{@merge_requests.total_count} merge requests
+  %small.pull-right #{@merge_requests.total_count} merge requests
 
 %hr
 .row
diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..73be474e2780821721906e49f9687231ae890abb
--- /dev/null
+++ b/app/views/groups/new.html.haml
@@ -0,0 +1,21 @@
+%h3.page_title New Group
+%hr
+= form_for @group do |f|
+  - if @group.errors.any?
+    .alert.alert-error
+      %span= @group.errors.full_messages.first
+  .clearfix
+    = f.label :name do
+      Group name is
+    .input
+      = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
+      &nbsp;
+      = f.submit 'Create group', class: "btn btn-create"
+  %hr
+  .padded
+    %ul
+      %li Group is kind of directory for several projects
+      %li All created groups are private
+      %li People within a group see only projects they have access to
+      %li All projects of group will be stored in group directory
+      %li You will be able to move existing projects into group
diff --git a/app/views/groups/people.html.haml b/app/views/groups/people.html.haml
index 0bceeaa3ceba6c37a24fb6812bcbb2b972114a57..3e4eb082f564b37b2992d4d6b03221862f4d62d0 100644
--- a/app/views/groups/people.html.haml
+++ b/app/views/groups/people.html.haml
@@ -16,5 +16,5 @@
             %strong= user.name
             %span.cgray= user.email
             - if @group.owner == user
-              %span.btn.btn-small.disabled.right Group Owner
+              %span.btn.btn-small.disabled.pull-right Group Owner
 
diff --git a/app/views/groups/search.html.haml b/app/views/groups/search.html.haml
index 1ba4707aa52d73d3569989485e0e79f4e2290552..f56bbadeac071cb911ab51df5d02e16f5ed4dc0f 100644
--- a/app/views/groups/search.html.haml
+++ b/app/views/groups/search.html.haml
@@ -4,6 +4,6 @@
       %strong Looking for
     .input
       = search_field_tag :search, params[:search], placeholder: "issue 143", class: "input-xxlarge search-text-input", id: "dashboard_search"
-      = submit_tag 'Search', class: "btn primary wide"
+      = submit_tag 'Search', class: "btn btn-primary wide"
 - if params[:search].present?
   = render 'search/result'
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index 84dd17c045deb11ca973a407578360e66e791ea1..a140b401b9d54048d7f092b5eb2dc0673cc50ff3 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -1,7 +1,7 @@
 .projects
   .activities.span8
     = render "events/event_last_push", event: @last_push
-    = link_to dashboard_path, class: 'btn very_small' do
+    = link_to dashboard_path, class: 'btn btn-tiny' do
       &larr; To dashboard
     &nbsp;
     %span.cgray You will only see events from projects in this group
diff --git a/app/views/help/_layout.html.haml b/app/views/help/_layout.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..fa5e3a30b2945fbcdad32825c028900593d28ca0
--- /dev/null
+++ b/app/views/help/_layout.html.haml
@@ -0,0 +1,34 @@
+.row
+  .span3{:"data-spy" => 'affix'}
+    .ui-box
+      .title
+        %h5 Help
+      %ul.well-list
+        %li
+          %strong= link_to "Workflow", help_workflow_path
+        %li
+          %strong= link_to "SSH keys", help_ssh_path
+
+        %li
+          %strong= link_to "GitLab Markdown", help_markdown_path
+
+        %li
+          %strong= link_to "Permissions", help_permissions_path
+
+        %li
+          %strong= link_to "API", help_api_path
+
+        %li
+          %strong= link_to "Web Hooks", help_web_hooks_path
+
+        %li
+          %strong= link_to "Rake Tasks", help_raketasks_path
+
+        %li
+          %strong= link_to "System Hooks", help_system_hooks_path
+
+        %li
+          %strong= link_to "Public Access", help_public_access_path
+
+  .span9.pull-right
+    = yield
diff --git a/app/views/help/api.html.haml b/app/views/help/api.html.haml
index 3f16637dd2e3538b96b6a41e4fc1ae394fc4d21f..d771f1e9f38109b9525f8a027823d71f217bb778 100644
--- a/app/views/help/api.html.haml
+++ b/app/views/help/api.html.haml
@@ -1,107 +1,105 @@
-%h3.page_title API
-.back_link
-  = link_to help_path do
-    &larr; to index
-%br
+= render layout: 'help/layout' do
+  %h3.page_title API
+  %br
 
-%ul.nav.nav-tabs.log-tabs
-  %li.active
-    = link_to "README", "#README", 'data-toggle' => 'tab'
-  %li
-    = link_to "Projects", "#projects", 'data-toggle' => 'tab'
-  %li
-    = link_to "Snippets", "#snippets", 'data-toggle' => 'tab'
-  %li
-    = link_to "Repositories", "#repositories", 'data-toggle' => 'tab'
-  %li
-    = link_to "Users", "#users", 'data-toggle' => 'tab'
-  %li
-    = link_to "Session", "#session", 'data-toggle' => 'tab'
-  %li
-    = link_to "Issues", "#issues", 'data-toggle' => 'tab'
-  %li
-    = link_to "Milestones", "#milestones", 'data-toggle' => 'tab'
-  %li
-    = link_to "Notes", "#notes", 'data-toggle' => 'tab'
+  %ul.nav.nav-tabs.log-tabs.nav-small-tabs
+    %li.active
+      = link_to "README", "#README", 'data-toggle' => 'tab'
+    %li
+      = link_to "Projects", "#projects", 'data-toggle' => 'tab'
+    %li
+      = link_to "Snippets", "#snippets", 'data-toggle' => 'tab'
+    %li
+      = link_to "Repositories", "#repositories", 'data-toggle' => 'tab'
+    %li
+      = link_to "Users", "#users", 'data-toggle' => 'tab'
+    %li
+      = link_to "Session", "#session", 'data-toggle' => 'tab'
+    %li
+      = link_to "Issues", "#issues", 'data-toggle' => 'tab'
+    %li
+      = link_to "Milestones", "#milestones", 'data-toggle' => 'tab'
+    %li
+      = link_to "Notes", "#notes", 'data-toggle' => 'tab'
 
-.tab-content
-  .tab-pane.active#README
-    .file_holder
-      .file_title
-        %i.icon-file
-        README
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "api", "README.md"))
+  .tab-content
+    .tab-pane.active#README
+      .file_holder
+        .file_title
+          %i.icon-file
+          README
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "api", "README.md"))
 
-  .tab-pane#projects
-    .file_holder
-      .file_title
-        %i.icon-file
-        Projects
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "api", "projects.md"))
+    .tab-pane#projects
+      .file_holder
+        .file_title
+          %i.icon-file
+          Projects
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "api", "projects.md"))
 
-  .tab-pane#snippets
-    .file_holder
-      .file_title
-        %i.icon-file
-        Projects Snippets
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "api", "snippets.md"))
+    .tab-pane#snippets
+      .file_holder
+        .file_title
+          %i.icon-file
+          Projects Snippets
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "api", "snippets.md"))
 
-  .tab-pane#repositories
-    .file_holder
-      .file_title
-        %i.icon-file
-        Projects
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "api", "repositories.md"))
+    .tab-pane#repositories
+      .file_holder
+        .file_title
+          %i.icon-file
+          Projects
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "api", "repositories.md"))
 
-  .tab-pane#users
-    .file_holder
-      .file_title
-        %i.icon-file
-        Users
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "api", "users.md"))
+    .tab-pane#users
+      .file_holder
+        .file_title
+          %i.icon-file
+          Users
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "api", "users.md"))
 
-  .tab-pane#session
-    .file_holder
-      .file_title
-        %i.icon-file
-        Session
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "api", "session.md"))
+    .tab-pane#session
+      .file_holder
+        .file_title
+          %i.icon-file
+          Session
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "api", "session.md"))
 
-  .tab-pane#issues
-    .file_holder
-      .file_title
-        %i.icon-file
-        Issues
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "api", "issues.md"))
+    .tab-pane#issues
+      .file_holder
+        .file_title
+          %i.icon-file
+          Issues
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "api", "issues.md"))
 
-  .tab-pane#milestones
-    .file_holder
-      .file_title
-        %i.icon-file
-        Milestones
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "api", "milestones.md"))
+    .tab-pane#milestones
+      .file_holder
+        .file_title
+          %i.icon-file
+          Milestones
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "api", "milestones.md"))
 
-  .tab-pane#notes
-    .file_holder
-      .file_title
-        %i.icon-file
-        Notes
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "api", "notes.md"))
+    .tab-pane#notes
+      .file_holder
+        .file_title
+          %i.icon-file
+          Notes
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "api", "notes.md"))
diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml
index 28791b321f1e1808b87a18ba06406ac3f3101b0e..1a4411c8f30e8393022188fbd82cfd66bb0f55c0 100644
--- a/app/views/help/index.html.haml
+++ b/app/views/help/index.html.haml
@@ -1,6 +1,6 @@
 %h3.page_title
   GITLAB
-  .right
+  .pull-right
     %span= Gitlab::Version
     %small= Gitlab::Revision
 %hr
diff --git a/app/views/help/markdown.html.haml b/app/views/help/markdown.html.haml
index 0419f7c131aa01e3debe2238c78e6e81c77a6b8a..92c1e49be49568233510a43ba756ca60b3aea305 100644
--- a/app/views/help/markdown.html.haml
+++ b/app/views/help/markdown.html.haml
@@ -1,129 +1,127 @@
-%h3.page_title GitLab Flavored Markdown
-.back_link
-  = link_to help_path do
-    &larr; to index
-%hr
-
-.row
-  .span8
-    %p
-      For GitLab we developed something we call "GitLab Flavored Markdown" (GFM).
-      It extends the standard Markdown in a few significant ways adds some useful functionality.
-
-    %p You can use GFM in:
-    %ul
-      %li commit messages
-      %li comments
-      %li wall posts
-      %li issues
-      %li merge requests
-      %li milestones
-      %li wiki pages
-
-  .span4
-    .alert.alert-info
+= render layout: 'help/layout' do
+  %h3.page_title GitLab Flavored Markdown
+  %br
+
+  .row
+    .span8
       %p
-        If you're not already familiar with Markdown, you should spend 15 minutes and go over the excellent
-        %strong= link_to "Markdown Syntax Guide", "http://daringfireball.net/projects/markdown/syntax"
-        at Daring Fireball.
+        For GitLab we developed something we call "GitLab Flavored Markdown" (GFM).
+        It extends the standard Markdown in a few significant ways adds some useful functionality.
+
+      %p You can use GFM in:
+      %ul
+        %li commit messages
+        %li comments
+        %li wall posts
+        %li issues
+        %li merge requests
+        %li milestones
+        %li wiki pages
+
+    .span4
+      .alert.alert-info
+        %p
+          If you're not already familiar with Markdown, you should spend 15 minutes and go over the excellent
+          %strong= link_to "Markdown Syntax Guide", "http://daringfireball.net/projects/markdown/syntax"
+          at Daring Fireball.
+
+  .row
+    .span8
+      %h3 Differences from traditional Markdown
+
+      %h4 Newlines
 
-.row
-  .span8
-    %h3 Differences from traditional Markdown
+      %p
+        The biggest difference that GFM introduces is in the handling of linebreaks.
+        With traditional Markdown you can hard wrap paragraphs of text and they will be combined into a single paragraph. We find this to be the cause of a huge number of unintentional formatting errors.
+        GFM treats newlines in paragraph-like content as real line breaks, which is probably what you intended.
 
-    %h4 Newlines
 
-    %p
-      The biggest difference that GFM introduces is in the handling of linebreaks.
-      With traditional Markdown you can hard wrap paragraphs of text and they will be combined into a single paragraph. We find this to be the cause of a huge number of unintentional formatting errors.
-      GFM treats newlines in paragraph-like content as real line breaks, which is probably what you intended.
+      %p The next paragraph contains two phrases separated by a single newline character:
+      %pre= "Roses are red\nViolets are blue"
+      %p becomes
+      = markdown "Roses are red\nViolets are blue"
 
+      %h4 Multiple underscores in words
 
-    %p The next paragraph contains two phrases separated by a single newline character:
-    %pre= "Roses are red\nViolets are blue"
-    %p becomes
-    = markdown "Roses are red\nViolets are blue"
+      %p
+        It is not reasonable to italicize just <em>part</em> of a word, especially when you're dealing with code and names often appear with multiple underscores.
+        Therefore, GFM ignores multiple underscores in words.
 
-    %h4 Multiple underscores in words
+      %pre= "perform_complicated_task\ndo_this_and_do_that_and_another_thing"
+      %p becomes
+      = markdown "perform_complicated_task\ndo_this_and_do_that_and_another_thing"
 
-    %p
-      It is not reasonable to italicize just <em>part</em> of a word, especially when you're dealing with code and names often appear with multiple underscores.
-      Therefore, GFM ignores multiple underscores in words.
+      %h4 URL autolinking
 
-    %pre= "perform_complicated_task\ndo_this_and_do_that_and_another_thing"
-    %p becomes
-    = markdown "perform_complicated_task\ndo_this_and_do_that_and_another_thing"
+      %p
+        GFM will autolink standard URLs you copy and paste into your text.
+        So if you want to link to a URL (instead of a textual link), you can simply put the URL in verbatim and it will be turned into a link to that URL.
 
-    %h4 URL autolinking
+      %h4 Fenced code blocks
 
-    %p
-      GFM will autolink standard URLs you copy and paste into your text.
-      So if you want to link to a URL (instead of a textual link), you can simply put the URL in verbatim and it will be turned into a link to that URL.
+      %p
+        Markdown converts text with four spaces at the front of each line to code blocks.
+        GFM supports that, but we also support fenced blocks.
+        Just wrap your code blocks in <code>```</code> and you won't need to indent manually to trigger a code block.
 
-    %h4 Fenced code blocks
+      %pre= %Q{```ruby\nrequire 'redcarpet'\nmarkdown = Redcarpet.new("Hello World!")\nputs markdown.to_html\n```}
+      %p becomes
+      = markdown %Q{```ruby\nrequire 'redcarpet'\nmarkdown = Redcarpet.new("Hello World!")\nputs markdown.to_html\n```}
 
-    %p
-      Markdown converts text with four spaces at the front of each line to code blocks.
-      GFM supports that, but we also support fenced blocks.
-      Just wrap your code blocks in <code>```</code> and you won't need to indent manually to trigger a code block.
+      %h4 Emoji
 
-    %pre= %Q{```ruby\nrequire 'redcarpet'\nmarkdown = Redcarpet.new("Hello World!")\nputs markdown.to_html\n```}
-    %p becomes
-    = markdown %Q{```ruby\nrequire 'redcarpet'\nmarkdown = Redcarpet.new("Hello World!")\nputs markdown.to_html\n```}
+  .row
+    .span8
+      :ruby
+        puts markdown %Q{Sometimes you want to be :cool: and add some :sparkles: to your :speech_balloon:. Well we have a :gift: for you:
 
-    %h4 Emoji
+          :exclamation: You can use emoji anywhere GFM is supported. :sunglasses:
 
-.row
-  .span8
-    :ruby
-      puts markdown %Q{Sometimes you want to be :cool: and add some :sparkles: to your :speech_balloon:. Well we have a :gift: for you:
+          You can use it to point out a :bug: or warn about :monkey:patches. And if someone improves your really :snail: code, send them a :bouquet: or some :candy:. People will :heart: you for that.
 
-        :exclamation: You can use emoji anywhere GFM is supported. :sunglasses:
+          If you are :new: to this, don't be :fearful:. You can easily join the emoji :circus_tent:. All you need to do is to :book: up on the supported codes.
+          }
 
-        You can use it to point out a :bug: or warn about :monkey:patches. And if someone improves your really :snail: code, send them a :bouquet: or some :candy:. People will :heart: you for that.
+    .span4
+      .alert.alert-info
+        %p
+          Consult the
+          %strong= link_to "Emoji Cheat Sheet", "http://www.emoji-cheat-sheet.com/"
+          for a list of all supported emoji codes.
 
-        If you are :new: to this, don't be :fearful:. You can easily join the emoji :circus_tent:. All you need to do is to :book: up on the supported codes.
-        }
+  .row
+    .span8
+      %h4 Special GitLab references
 
-  .span4
-    .alert.alert-info
       %p
-        Consult the
-        %strong= link_to "Emoji Cheat Sheet", "http://www.emoji-cheat-sheet.com/"
-        for a list of all supported emoji codes.
-
-.row
-  .span8
-    %h4 Special GitLab references
-
-    %p
-      GFM recognizes special references.
-      You can easily reference e.g. a team member, an issue or a commit within a project.
-      GFM will turn that reference into a link so you can navigate between them easily.
-
-    %p GFM will recognize the following references:
-    %ul
-      %li
-        %code @foo
-        for team members
-      %li
-        %code #123
-        for issues
-      %li
-        %code !123
-        for merge request
-      %li
-        %code $123
-        for snippets
-      %li
-        %code 1234567
-        for commits
-
-    -# this example will only be shown if the user has a project with at least one issue
-    - if @project = current_user.authorized_projects.first
-      - if issue = @project.issues.first
-        %p For example in your #{link_to @project.name, project_path(@project)} project, writing:
-        %pre= "This is related to ##{issue.id}. @#{current_user.name} is working on solving it."
-        %p becomes:
-        = markdown "This is related to ##{issue.id}. @#{current_user.name} is working on solving it."
-      - @project = nil # Prevent this from bubbling up to page title
+        GFM recognizes special references.
+        You can easily reference e.g. a team member, an issue or a commit within a project.
+        GFM will turn that reference into a link so you can navigate between them easily.
+
+      %p GFM will recognize the following references:
+      %ul
+        %li
+          %code @foo
+          for team members
+        %li
+          %code #123
+          for issues
+        %li
+          %code !123
+          for merge request
+        %li
+          %code $123
+          for snippets
+        %li
+          %code 1234567
+          for commits
+
+      -# this example will only be shown if the user has a project with at least one issue
+      - if @project = current_user.authorized_projects.first
+        - if issue = @project.issues.first
+          %p For example in your #{link_to @project.name, project_path(@project)} project, writing:
+          %pre= "This is related to ##{issue.id}. @#{current_user.username} is working on solving it."
+          %p becomes:
+          = markdown "This is related to ##{issue.id}. @#{current_user.username} is working on solving it."
+        - @project = nil # Prevent this from bubbling up to page title
diff --git a/app/views/help/permissions.html.haml b/app/views/help/permissions.html.haml
index b56251f35ebcddd2df84498d93258eff32b6c287..2075753e82a10b9d8b26d05cc4dbc42534b02371 100644
--- a/app/views/help/permissions.html.haml
+++ b/app/views/help/permissions.html.haml
@@ -1,68 +1,66 @@
-%h3.page_title Permissions
-.back_link
-  = link_to help_path do
-    &larr; to index
-%hr
+= render layout: 'help/layout' do
+  %h3.page_title Permissions
+  %br
 
-%fieldset
-  %legend Guest
-  %ul
-    %li Create new issue
-    %li Leave comments
-    %li Write on project wall
+  %fieldset
+    %legend Guest
+    %ul
+      %li Create new issue
+      %li Leave comments
+      %li Write on project wall
 
-%fieldset
-  %legend Reporter
-  %ul
-    %li Create new issue
-    %li Leave comments
-    %li Write on project wall
-    %li Pull project code
-    %li Download project
-    %li Create a code snippets
+  %fieldset
+    %legend Reporter
+    %ul
+      %li Create new issue
+      %li Leave comments
+      %li Write on project wall
+      %li Pull project code
+      %li Download project
+      %li Create a code snippets
 
 
-%fieldset
-  %legend Developer
-  %ul
-    %li Create new issue
-    %li Leave comments
-    %li Write on project wall
-    %li Pull project code
-    %li Download project
-    %li Create new merge request
-    %li Create a code snippets
-    %li Create new branches
-    %li Push to non-protected branches
-    %li Remove non-protected branches
-    %li Add tags
-    %li Write a wiki
+  %fieldset
+    %legend Developer
+    %ul
+      %li Create new issue
+      %li Leave comments
+      %li Write on project wall
+      %li Pull project code
+      %li Download project
+      %li Create new merge request
+      %li Create a code snippets
+      %li Create new branches
+      %li Push to non-protected branches
+      %li Remove non-protected branches
+      %li Add tags
+      %li Write a wiki
 
-%fieldset
-  %legend Master
-  %ul
-    %li Create new issue
-    %li Leave comments
-    %li Write on project wall
-    %li Pull project code
-    %li Download project
-    %li Create new merge request
-    %li Create a code snippets
-    %li Create new branches
-    %li Push to non-protected branches
-    %li Remove non-protected branches
-    %li Add tags
-    %li Write a wiki
-    %li Add new team members
-    %li Push to protected branches
-    %li Remove protected branches
-    %li Push with force option
-    %li Edit project
-    %li Add Deploy Keys to project
-    %li Configure Project Hooks
+  %fieldset
+    %legend Master
+    %ul
+      %li Create new issue
+      %li Leave comments
+      %li Write on project wall
+      %li Pull project code
+      %li Download project
+      %li Create new merge request
+      %li Create a code snippets
+      %li Create new branches
+      %li Push to non-protected branches
+      %li Remove non-protected branches
+      %li Add tags
+      %li Write a wiki
+      %li Add new team members
+      %li Push to protected branches
+      %li Remove protected branches
+      %li Push with force option
+      %li Edit project
+      %li Add Deploy Keys to project
+      %li Configure Project Hooks
 
-%fieldset
-  %legend Owner
-  %ul
-    %li Transfer project to another namespace
-    %li Remove project
+  %fieldset
+    %legend Owner
+    %ul
+      %li Transfer project to another namespace
+      %li Remove project
diff --git a/app/views/help/public_access.html.haml b/app/views/help/public_access.html.haml
index 60d8d59761773e42eca0b0252d0b2db7de13707a..66de17a34edc62819e82702005f0c5f8c3738e06 100644
--- a/app/views/help/public_access.html.haml
+++ b/app/views/help/public_access.html.haml
@@ -1,18 +1,16 @@
-%h3.page_title Public Access
-.back_link
-  = link_to help_path do
-    &larr; to index
-%hr
+= render layout: 'help/layout' do
+  %h3.page_title Public Access
+  %br
 
-%p
-  GitLab allows you to open selected projects to be accessed publicly.
-  These projects will be clonable
-  %em without any
-  authentication.
-  Also they will be listed on the #{link_to "public access directory", public_root_path}.
+  %p
+    GitLab allows you to open selected projects to be accessed publicly.
+    These projects will be clonable
+    %em without any
+    authentication.
+    Also they will be listed on the #{link_to "public access directory", public_root_path}.
 
-%ol
-  %li Go to your project dashboard
-  %li Click on the "Edit" tab
-  %li Select "Public clone access"
+  %ol
+    %li Go to your project dashboard
+    %li Click on the "Edit" tab
+    %li Select "Public clone access"
 
diff --git a/app/views/help/raketasks.html.haml b/app/views/help/raketasks.html.haml
index f015451a673d3288114e6f0eb207dd6ec78ad0b4..bcc874fc3902618778903d604e9e0706b812106b 100644
--- a/app/views/help/raketasks.html.haml
+++ b/app/views/help/raketasks.html.haml
@@ -1,66 +1,64 @@
-%h3.page_title GitLab Rake Tasks
-.back_link
-  = link_to help_path do
-    &larr; to index
-%hr
+= render layout: 'help/layout' do
+  %h3.page_title GitLab Rake Tasks
+  %br
 
-%p.slead
-  GitLab provides some specific rake tasks to enable special features or perform maintenance tasks.
+  %p.slead
+    GitLab provides some specific rake tasks to enable special features or perform maintenance tasks.
 
-%ul.nav.nav-tabs.log-tabs
-  %li.active
-    = link_to "Features", "#features", 'data-toggle' => 'tab'
-  %li
-    = link_to "Maintenance", "#maintenance", 'data-toggle' => 'tab'
-  %li
-    = link_to "User Management", "#user_management", 'data-toggle' => 'tab'
-  %li
-    = link_to "Backup & Restore", "#backup_restore", 'data-toggle' => 'tab'
-  %li
-    = link_to "Cleanup", "#cleanup", 'data-toggle' => 'tab'
+  %ul.nav.nav-tabs.log-tabs
+    %li.active
+      = link_to "Features", "#features", 'data-toggle' => 'tab'
+    %li
+      = link_to "Maintenance", "#maintenance", 'data-toggle' => 'tab'
+    %li
+      = link_to "User Management", "#user_management", 'data-toggle' => 'tab'
+    %li
+      = link_to "Backup & Restore", "#backup_restore", 'data-toggle' => 'tab'
+    %li
+      = link_to "Cleanup", "#cleanup", 'data-toggle' => 'tab'
 
-.tab-content
-  .tab-pane.active#features
-    .file_holder
-      .file_title
-        %i.icon-file
-        Features
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "raketasks", "features.md"))
+  .tab-content
+    .tab-pane.active#features
+      .file_holder
+        .file_title
+          %i.icon-file
+          Features
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "raketasks", "features.md"))
 
-  .tab-pane#maintenance
-    .file_holder
-      .file_title
-        %i.icon-file
-        Maintenance
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "raketasks", "maintenance.md"))
+    .tab-pane#maintenance
+      .file_holder
+        .file_title
+          %i.icon-file
+          Maintenance
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "raketasks", "maintenance.md"))
 
-  .tab-pane#user_management
-    .file_holder
-      .file_title
-        %i.icon-file
-        User Management
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "raketasks", "user_management.md"))
+    .tab-pane#user_management
+      .file_holder
+        .file_title
+          %i.icon-file
+          User Management
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "raketasks", "user_management.md"))
 
-  .tab-pane#cleanup
-    .file_holder
-      .file_title
-        %i.icon-file
-        Cleanup
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "raketasks", "cleanup.md"))
+    .tab-pane#cleanup
+      .file_holder
+        .file_title
+          %i.icon-file
+          Cleanup
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "raketasks", "cleanup.md"))
 
-  .tab-pane#backup_restore
-    .file_holder
-      .file_title
-        %i.icon-file
-        Backup & Restore
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "raketasks", "backup_restore.md"))
+    .tab-pane#backup_restore
+      .file_holder
+        .file_title
+          %i.icon-file
+          Backup & Restore
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "raketasks", "backup_restore.md"))
diff --git a/app/views/help/ssh.html.haml b/app/views/help/ssh.html.haml
index 3f082333a76303f10f3510c1ce25d304edd3c012..114415977b4e14a04b45a48957b66384550e9371 100644
--- a/app/views/help/ssh.html.haml
+++ b/app/views/help/ssh.html.haml
@@ -1,25 +1,23 @@
-%h3.page_title SSH Keys
-.back_link
-  = link_to help_path do
-    &larr; to index
-%hr
+= render layout: 'help/layout' do
+  %h3.page_title SSH Keys
+  %br
 
-%p.slead
-  SSH key allows you to establish a secure connection between your computer and GitLab
+  %p.slead
+    SSH key allows you to establish a secure connection between your computer and GitLab
 
-%p.slead
-  To generate a new SSH key just open your terminal and use code below.
+  %p.slead
+    To generate a new SSH key just open your terminal and use code below.
 
-%pre.dark
-  ssh-keygen -t rsa -C "#{current_user.email}"
+  %pre.dark
+    ssh-keygen -t rsa -C "#{current_user.email}"
 
-  \# Creates a new ssh key using the provided email
-  \# Generating public/private rsa key pair...
+    \# Creates a new ssh key using the provided email
+    \# Generating public/private rsa key pair...
 
-%p.slead
-  Next just use code below to dump your public key and add to GitLab SSH Keys
+  %p.slead
+    Next just use code below to dump your public key and add to GitLab SSH Keys
 
-%pre.dark
-  cat ~/.ssh/id_rsa.pub
+  %pre.dark
+    cat ~/.ssh/id_rsa.pub
 
-  \# ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6eNtGpNGwstc....
+    \# ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6eNtGpNGwstc....
diff --git a/app/views/help/system_hooks.html.haml b/app/views/help/system_hooks.html.haml
index c25b60deeb090ac1814485113ae42cfa115d0ecc..c49011a22698c89c23a81b10234fce1537660247 100644
--- a/app/views/help/system_hooks.html.haml
+++ b/app/views/help/system_hooks.html.haml
@@ -1,14 +1,12 @@
-%h3 System hooks
-.back_link
-  = link_to :back do
-    &larr; back
-%hr
-
-%p.slead
-  Your GitLab instance can perform HTTP POST requests on the following events: create_project, delete_project, create_user, delete_user, change_team_member.
-  %br
+= render layout: 'help/layout' do
+  %h3.page_title System hooks
   %br
-  System Hooks can be used, e.g. for logging or changing information in a LDAP server.
-  %br
-%h5 Hooks request example:
-= render "admin/hooks/data_ex"
+
+  %p.slead
+    Your GitLab instance can perform HTTP POST requests on the following events: create_project, delete_project, create_user, delete_user, change_team_member.
+    %br
+    %br
+    System Hooks can be used, e.g. for logging or changing information in a LDAP server.
+    %br
+  %h5 Hooks request example:
+  = render "admin/hooks/data_ex"
diff --git a/app/views/help/web_hooks.html.haml b/app/views/help/web_hooks.html.haml
index 65036613fa7474c53781dfa88a6c8b55f0cad2ac..09745f7361434d94580fdfdeb896dd86ba109002 100644
--- a/app/views/help/web_hooks.html.haml
+++ b/app/views/help/web_hooks.html.haml
@@ -1,15 +1,13 @@
-%h3.page_title Web hooks
-.back_link
-  = link_to help_path do
-    &larr; to index
-%hr
-
-%p.slead
-  Every GitLab project can trigger a web server whenever the repo is pushed to.
-  %br
-  Web Hooks can be used to update an external issue tracker, trigger CI builds, update a backup mirror, or even deploy to your production server.
+= render layout: 'help/layout' do
+  %h3.page_title Web hooks
   %br
-  GitLab will send POST request with commits information on every push.
-%h5 Hooks request example:
-= render "hooks/data_ex"
+
+  %p.slead
+    Every GitLab project can trigger a web server whenever the repo is pushed to.
+    %br
+    Web Hooks can be used to update an external issue tracker, trigger CI builds, update a backup mirror, or even deploy to your production server.
+    %br
+    GitLab will send POST request with commits information on every push.
+  %h5 Hooks request example:
+  = render "hooks/data_ex"
 
diff --git a/app/views/help/workflow.html.haml b/app/views/help/workflow.html.haml
index 6062ca091bd87b7d6be2598897567b424bbb34e3..495b7c6e6fc0955fa4bb966f2911640618378aee 100644
--- a/app/views/help/workflow.html.haml
+++ b/app/views/help/workflow.html.haml
@@ -1,40 +1,38 @@
-%h3.page_title Workflow
-.back_link
-  = link_to help_path do
-    &larr; to index
-%hr
-
-%ol.help
-  %li
-    %p Clone project
-    .bash
-      %pre.dark
-        git clone git@example.com:project-name.git
-
-  %li
-    %p Create branch with your feature
-    .bash
-      %pre.dark
-        git checkout -b $feature_name
-
-  %li
-    %p Write code. Commit changes
-    .bash
-      %pre.dark
-        git commit -am "My feature is ready"
-
-  %li
-    %p Push your branch to GitLab
-    .bash
-      %pre.dark
-        git push origin $feature_name
-
-  %li
-    %p Review your code on Commits page
-
-  %li
-    %p Create a merge request
-
-  %li
-    %p Your team lead will review code &amp; merge it to main branch
+= render layout: 'help/layout' do
+  %h3.page_title Workflow
+  %br
+
+  %ol.help
+    %li
+      %p Clone project
+      .bash
+        %pre.dark
+          git clone git@example.com:project-name.git
+
+    %li
+      %p Create branch with your feature
+      .bash
+        %pre.dark
+          git checkout -b $feature_name
+
+    %li
+      %p Write code. Commit changes
+      .bash
+        %pre.dark
+          git commit -am "My feature is ready"
+
+    %li
+      %p Push your branch to GitLab
+      .bash
+        %pre.dark
+          git push origin $feature_name
+
+    %li
+      %p Review your code on Commits page
+
+    %li
+      %p Create a merge request
+
+    %li
+      %p Your team lead will review code &amp; merge it to main branch
 
diff --git a/app/views/hooks/index.html.haml b/app/views/hooks/index.html.haml
index 1fcf6e1c57a6345cb0e888373c71b5e6d98a283c..88a5a7dcffe7939d357d3e0f85ea1bdbad779d1a 100644
--- a/app/views/hooks/index.html.haml
+++ b/app/views/hooks/index.html.haml
@@ -10,7 +10,7 @@
 
 = form_for [@project, @hook], as: :hook, url: project_hooks_path(@project), html: { class: 'form-inline' } do |f|
   -if @hook.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       - @hook.errors.full_messages.each do |msg|
         %p= msg
   .clearfix
@@ -18,7 +18,7 @@
     .input
       = f.text_field :url, class: "text_field xxlarge"
       &nbsp;
-      = f.submit "Add Web Hook", class: "btn primary"
+      = f.submit "Add Web Hook", class: "btn btn-primary"
 %hr
 
 -if @hooks.any?
@@ -37,6 +37,6 @@
           &rarr;
           %span.monospace= hook.url
         %td
-          .right
-            = link_to 'Test Hook', test_project_hook_path(@project, hook), class: "btn small grouped"
-            = link_to 'Remove', project_hook_path(@project, hook), confirm: 'Are you sure?', method: :delete, class: "danger btn small grouped"
+          .pull-right
+            = link_to 'Test Hook', test_project_hook_path(@project, hook), class: "btn btn-small grouped"
+            = link_to 'Remove', project_hook_path(@project, hook), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove btn-small grouped"
diff --git a/app/views/issues/_filter.html.haml b/app/views/issues/_filter.html.haml
index 779e55bb7af6670b0f2c1a389d21f5dec9b21b79..21efaa5357cbef9d5b1fe3282856539854af28b8 100644
--- a/app/views/issues/_filter.html.haml
+++ b/app/views/issues/_filter.html.haml
@@ -16,5 +16,5 @@
 
   %fieldset
     %hr
-    = link_to "Reset", project_issues_path(@project), class: 'btn right'
+    = link_to "Reset", project_issues_path(@project), class: 'btn pull-right'
 
diff --git a/app/views/issues/_form.html.haml b/app/views/issues/_form.html.haml
index bef235f2dea8a4d29239cf5021463f3cf142b204..6d7613a700dd67db93de5b058e9fb346cf5e8450 100644
--- a/app/views/issues/_form.html.haml
+++ b/app/views/issues/_form.html.haml
@@ -2,7 +2,7 @@
   %h3.page_title= @issue.new_record? ? "New Issue" : "Edit Issue ##{@issue.id}"
   = form_for [@project, @issue] do |f|
     -if @issue.errors.any?
-      .alert-message.block-message.error
+      .alert.alert-error
         - @issue.errors.full_messages.each do |msg|
           %span= msg
           %br
@@ -44,12 +44,12 @@
 
     .actions
       - if @issue.new_record?
-        = f.submit 'Submit new issue', class: "btn success"
+        = f.submit 'Submit new issue', class: "btn btn-create"
       -else
-        = f.submit 'Save changes', class: "save-btn btn"
+        = f.submit 'Save changes', class: "btn-save btn"
 
       - cancel_path = @issue.new_record? ? project_issues_path(@project) : project_issue_path(@project, @issue)
-      = link_to "Cancel", cancel_path, class: 'btn cancel-btn'
+      = link_to "Cancel", cancel_path, class: 'btn btn-cancel'
 
 
 
diff --git a/app/views/issues/_head.html.haml b/app/views/issues/_head.html.haml
index 4294503c211aaff062d43447e2900526b13f547a..7e0b2cde074ae8c484bc5736d18e90f8588e249c 100644
--- a/app/views/issues/_head.html.haml
+++ b/app/views/issues/_head.html.haml
@@ -5,7 +5,7 @@
     = link_to 'Milestones', project_milestones_path(@project), class: "tab"
   = nav_link(controller: :labels) do
     = link_to 'Labels', project_labels_path(@project), class: "tab"
-  %li.right
+  %li.pull-right
     %span.rss-icon
       = link_to project_issues_path(@project, :atom, { private_token: current_user.private_token }) do
         = image_tag "rss_ui.png", title: "feed"
diff --git a/app/views/issues/_issues.html.haml b/app/views/issues/_issues.html.haml
index 8821dbb8d9803af9fe0b70a1ba41bf1061529eb7..3bbd293dba2897aa41e93f739d0a89b9624fc730 100644
--- a/app/views/issues/_issues.html.haml
+++ b/app/views/issues/_issues.html.haml
@@ -4,7 +4,7 @@
 - if @issues.present?
   %li.bottom
     .left= paginate @issues, remote: true, theme: "gitlab"
-    .right
+    .pull-right
       %span.issue_counter #{@issues.total_count}
       issues for this filter
 - else
diff --git a/app/views/issues/_show.html.haml b/app/views/issues/_show.html.haml
index dcef901c15fe836accb8f1d51e233a2a20351265..fa888618066628be9e63596df8c7e6b766d3a50e 100644
--- a/app/views/issues/_show.html.haml
+++ b/app/views/issues/_show.html.haml
@@ -2,17 +2,17 @@
   - if controller.controller_name == 'issues'
     .issue_check
       = check_box_tag dom_id(issue,"selected"), nil, false, 'data-id' => issue.id, class: "selected_issue", disabled: !can?(current_user, :modify_issue, issue)
-  .right
+  .pull-right
     - if issue.notes.any?
-      %span.btn.small.disabled.grouped
+      %span.btn.btn-small.disabled.grouped
         %i.icon-comment
         = issue.notes.count
     - if can? current_user, :modify_issue, issue
       - if issue.closed
-        = link_to 'Reopen', project_issue_path(issue.project, issue, issue: {closed: false }, status_only: true), method: :put,  class: "btn small grouped reopen_issue", remote: true
+        = link_to 'Reopen', project_issue_path(issue.project, issue, issue: {closed: false }, status_only: true), method: :put,  class: "btn btn-small grouped reopen_issue", remote: true
       - else
-        = link_to 'Close', project_issue_path(issue.project, issue, issue: {closed: true }, status_only: true), method: :put, class: "btn small grouped close_issue", remote: true
-      = link_to edit_project_issue_path(issue.project, issue), class: "btn small edit-issue-link grouped" do
+        = link_to 'Close', project_issue_path(issue.project, issue, issue: {closed: true }, status_only: true), method: :put, class: "btn btn-small grouped close_issue", remote: true
+      = link_to edit_project_issue_path(issue.project, issue), class: "btn btn-small edit-issue-link grouped" do
         %i.icon-edit
         Edit
 
diff --git a/app/views/issues/index.html.haml b/app/views/issues/index.html.haml
index d5c29c780ce3423b6c326c8b1645a1de16406e6b..875f29e2600749d8ff788c22fd60dd95a4d1ee58 100644
--- a/app/views/issues/index.html.haml
+++ b/app/views/issues/index.html.haml
@@ -3,16 +3,16 @@
   %h3.page_title
     Issues
     %span (<span class=issue_counter>#{@issues.total_count}</span>)
-    .right
+    .pull-right
       .span5
         - if can? current_user, :write_issue, @project
-          = link_to new_project_issue_path(@project, issue: { assignee_id: params[:assignee_id], milestone_id: params[:milestone_id]}), class: "right btn primary", title: "New Issue", id: "new_issue_link" do
+          = link_to new_project_issue_path(@project, issue: { assignee_id: params[:assignee_id], milestone_id: params[:milestone_id]}), class: "btn btn-primary pull-right", title: "New Issue", id: "new_issue_link" do
             %i.icon-plus
             New Issue
-        = form_tag search_project_issues_path(@project), method: :get, remote: true, id: "issue_search_form", class: :right  do
+        = form_tag search_project_issues_path(@project), method: :get, remote: true, id: "issue_search_form", class: 'pull-right'  do
           = hidden_field_tag :project_id, @project.id, { id: 'project_id' }
           = hidden_field_tag :status, params[:status]
-          = search_field_tag :issue_search, nil, { placeholder: 'Search', class: 'issue_search span3 right neib search-text-input' }
+          = search_field_tag :issue_search, nil, { placeholder: 'Search', class: 'issue_search span3 pull-right neib search-text-input' }
 
   .clearfix
 
@@ -33,7 +33,7 @@
                 = select_tag('update[milestone_id]', options_from_collection_for_select(issues_active_milestones, "id", "title", params[:milestone_id]), prompt: "Milestone")
                 = hidden_field_tag 'update[issues_ids]', []
                 = hidden_field_tag :status, params[:status]
-              = button_tag "Save", class: "btn update_selected_issues btn-small save-btn"
+              = button_tag "Save", class: "btn update_selected_issues btn-small btn-save"
           .issues_filters
             = form_tag project_issues_path(@project), method: :get  do
               = select_tag(:label_name, options_for_select(issue_tags, params[:label_name]), prompt: "Labels")
diff --git a/app/views/issues/show.html.haml b/app/views/issues/show.html.haml
index 6bf789296997bdd647839839ac9144aec0a16d01..474955cc665c78d6620b25b329a40c52235bb800 100644
--- a/app/views/issues/show.html.haml
+++ b/app/views/issues/show.html.haml
@@ -5,7 +5,7 @@
     created at
     = @issue.created_at.stamp("Aug 21, 2011")
 
-  %span.right
+  %span.pull-right
     - if can?(current_user, :admin_project, @project) || @issue.author == current_user
       - if @issue.closed
         = link_to 'Reopen', project_issue_path(@project, @issue, issue: {closed: false }, status_only: true), method: :put,  class: "btn grouped reopen_issue"
@@ -16,7 +16,7 @@
         %i.icon-edit
         Edit
 
-.right
+.pull-right
   .span3#votes= render 'votes/votes_block', votable: @issue
 
 .back_link
@@ -42,7 +42,7 @@
       %cite.cgray and attached to milestone
       %strong= link_to_gfm truncate(milestone.title, length: 20), project_milestone_path(milestone.project, milestone)
 
-    .right
+    .pull-right
       - @issue.labels.each do |label|
         %span.label
           %i.icon-tag
diff --git a/app/views/keys/_form.html.haml b/app/views/keys/_form.html.haml
index 26700803e61247fbb76eab513cb2e575feb4cb92..fe26216b1d5acf17eefe9ce465d7aac32fd91fa4 100644
--- a/app/views/keys/_form.html.haml
+++ b/app/views/keys/_form.html.haml
@@ -1,7 +1,7 @@
 %div
   = form_for @key do |f|
     -if @key.errors.any?
-      .alert-message.block-message.error
+      .alert.alert-error
         %ul
           - @key.errors.full_messages.each do |msg|
             %li= msg
@@ -19,6 +19,6 @@
 
 
     .actions
-      = f.submit 'Save', class: "btn save-btn"
-      = link_to "Cancel", keys_path, class: "btn cancel-btn"
+      = f.submit 'Save', class: "btn btn-save"
+      = link_to "Cancel", keys_path, class: "btn btn-cancel"
 
diff --git a/app/views/keys/_show.html.haml b/app/views/keys/_show.html.haml
index 9d4485cf9a4bbd4982cbb7815a47c41cd790676b..52bbea6fc7bad85d3f63303fce3934edb3ee6234 100644
--- a/app/views/keys/_show.html.haml
+++ b/app/views/keys/_show.html.haml
@@ -8,5 +8,5 @@
       = time_ago_in_words(key.created_at)
       ago
   %td
-    = link_to 'Remove', key, confirm: 'Are you sure?', method: :delete, class: "btn small danger delete-key right"
+    = link_to 'Remove', key, confirm: 'Are you sure?', method: :delete, class: "btn btn-small btn-remove delete-key pull-right"
 
diff --git a/app/views/keys/index.html.haml b/app/views/keys/index.html.haml
index f5a8283a0ce3738e4e902e4ae3e787a1ac1bf5c1..7730b344a7db039935efaf5806883d907a187547 100644
--- a/app/views/keys/index.html.haml
+++ b/app/views/keys/index.html.haml
@@ -1,6 +1,6 @@
 %h3.page_title
   SSH Keys
-  = link_to "Add new", new_key_path, class: "btn right"
+  = link_to "Add new", new_key_path, class: "btn pull-right"
 
 %hr
 %p.slead
diff --git a/app/views/keys/show.html.haml b/app/views/keys/show.html.haml
index a8cba6c8f9ecfb1ba76d91aab8c6cadd65825398..059fe5e5806f705ab03b2b819693da699f4972f0 100644
--- a/app/views/keys/show.html.haml
+++ b/app/views/keys/show.html.haml
@@ -10,5 +10,5 @@
 %hr
 
 %pre= @key.key
-.right
-  = link_to 'Remove', @key, confirm: 'Are you sure?', method: :delete, class: "btn danger delete-key"
+.pull-right
+  = link_to 'Remove', @key, confirm: 'Are you sure?', method: :delete, class: "btn btn-remove delete-key"
diff --git a/app/views/labels/_label.html.haml b/app/views/labels/_label.html.haml
index 6e223e8e61d7f7b641f854da854a118d4d25dd76..027b041d58e91e8ae74c964b221394796f7151c0 100644
--- a/app/views/labels/_label.html.haml
+++ b/app/views/labels/_label.html.haml
@@ -2,7 +2,7 @@
   %strong
     %i.icon-tag
     = label.name
-  .right
+  .pull-right
     = link_to project_issues_path(label_name: label.name) do
       %strong
         = pluralize(label.count, 'issue')
diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml
index f4b2228a41babd38710f022486a7a406c4b46918..8f4f3d7815f31b7a00876ee6d973e2e0e4c5521c 100644
--- a/app/views/layouts/_head_panel.html.haml
+++ b/app/views/layouts/_head_panel.html.haml
@@ -17,7 +17,7 @@
             = link_to new_project_path, title: "Create New Project", class: 'has_bottom_tooltip', 'data-original-title' => 'New project'  do
               %i.icon-plus
         %li
-          = link_to profile_path, title: "Your Profile", class: 'has_bottom_tooltip', 'data-original-title' => 'Your profile'  do
+          = link_to profile_path, title: "My Profile", class: 'has_bottom_tooltip', 'data-original-title' => 'Your profile'  do
             %i.icon-user
         %li.separator
         %li
diff --git a/app/views/layouts/_search.html.haml b/app/views/layouts/_search.html.haml
index 7ea9079849a0d9c115c57d1cdc073dc7c5afe3a0..c484af04704e8503b6fa4507a985fe0ef75e1afb 100644
--- a/app/views/layouts/_search.html.haml
+++ b/app/views/layouts/_search.html.haml
@@ -1,6 +1,8 @@
 .search
   = form_tag search_path, method: :get, class: 'navbar-form pull-left' do |f|
     = text_field_tag "search", nil, placeholder: "Search", class: "search-input"
+    = hidden_field_tag :group_id, @group.try(:id)
+    = hidden_field_tag :project_id, @project.try(:id)
 
 :javascript
   $(function(){
diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml
index a60e7febe76ea70340a58ac16e57e2ac331f973e..a01886cdabf601cf3793784365edb6f1a2462c72 100644
--- a/app/views/layouts/admin.html.haml
+++ b/app/views/layouts/admin.html.haml
@@ -7,9 +7,12 @@
     .container
       %ul.main_menu
         = nav_link(controller: :dashboard, html_options: {class: 'home'}) do
-          = link_to "Stats", admin_root_path
+          = link_to admin_root_path, title: "Stats" do
+            %i.icon-home
         = nav_link(controller: :projects) do
           = link_to "Projects", admin_projects_path
+        = nav_link(controller: :teams) do
+          = link_to "Teams", admin_teams_path
         = nav_link(controller: :groups) do
           = link_to "Groups", admin_groups_path
         = nav_link(controller: :users) do
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index 88da5c98c78e0a5873d5a1d61ba71d2a44cd5595..7ee44238d10bd0e8f0ca4faeb33f9a3a8b2b53a8 100644
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -6,14 +6,18 @@
     = render "layouts/head_panel", title: "Dashboard"
     .container
       %ul.main_menu
-        = nav_link(path: 'dashboard#index', html_options: {class: 'home'}) do
-          = link_to "Home", root_path, title: "Home"
+        = nav_link(path: 'dashboard#show', html_options: {class: 'home'}) do
+          = link_to root_path, title: "Home" do
+            %i.icon-home
+        = nav_link(path: 'dashboard#projects') do
+          = link_to projects_dashboard_path do
+            Projects
         = nav_link(path: 'dashboard#issues') do
-          = link_to dashboard_issues_path do
+          = link_to issues_dashboard_path do
             Issues
             %span.count= current_user.assigned_issues.opened.count
         = nav_link(path: 'dashboard#merge_requests') do
-          = link_to dashboard_merge_requests_path do
+          = link_to merge_requests_dashboard_path do
             Merge Requests
             %span.count= current_user.cared_merge_requests.opened.count
         = nav_link(path: 'search#show') do
diff --git a/app/views/layouts/group.html.haml b/app/views/layouts/group.html.haml
index f47e8b3e9ff882c0fb32392608a1f1c9dad12034..9057ad50ce68620c314925bb9c943eb8291a2c06 100644
--- a/app/views/layouts/group.html.haml
+++ b/app/views/layouts/group.html.haml
@@ -3,11 +3,12 @@
   = render "layouts/head", title: "#{@group.name}"
   %body{class: "#{app_theme} application"}
     = render "layouts/flash"
-    = render "layouts/head_panel", title: "#{@group.name}"
+    = render "layouts/head_panel", title: "group: #{@group.name}"
     .container
       %ul.main_menu
         = nav_link(path: 'groups#show', html_options: {class: 'home'}) do
-          = link_to "Home", group_path(@group), title: "Home"
+          = link_to group_path(@group), title: "Home" do
+            %i.icon-home
         = nav_link(path: 'groups#issues') do
           = link_to issues_group_path(@group) do
             Issues
@@ -21,4 +22,10 @@
         = nav_link(path: 'groups#people') do
           = link_to "People", people_group_path(@group)
 
+        - if can?(current_user, :manage_group, @group)
+          = nav_link(path: 'groups#edit') do
+            = link_to edit_group_path(@group), class: "tab " do
+              %i.icon-edit
+              Edit Group
+
       .content= yield
diff --git a/app/views/layouts/profile.html.haml b/app/views/layouts/profile.html.haml
index 7852ed6f0e1380a88df9124abd0d064c56fae1c1..57f250c775bcd3b9d2ccd78c05040c0a6c99fcbc 100644
--- a/app/views/layouts/profile.html.haml
+++ b/app/views/layouts/profile.html.haml
@@ -7,7 +7,8 @@
     .container
       %ul.main_menu
         = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
-          = link_to "Profile", profile_path
+          = link_to profile_path, title: "Profile" do
+            %i.icon-home
         = nav_link(path: 'profiles#account') do
           = link_to "Account", account_profile_path
         = nav_link(controller: :keys) do
diff --git a/app/views/layouts/project_resource.html.haml b/app/views/layouts/project_resource.html.haml
index 14671c5ca70b116eb0066908653211618fbc5d5c..09ccb1d7b6a818027cbdf2f24179782b3b79658e 100644
--- a/app/views/layouts/project_resource.html.haml
+++ b/app/views/layouts/project_resource.html.haml
@@ -12,7 +12,8 @@
     .container
       %ul.main_menu
         = nav_link(html_options: {class: "home #{project_tab_class}"}) do
-          = link_to @project.path, project_path(@project), title: "Project"
+          = link_to project_path(@project), title: "Project" do
+            %i.icon-home
 
         - if @project.repo_exists?
           - if can? current_user, :download_code, @project
@@ -20,8 +21,8 @@
               = link_to 'Files', project_tree_path(@project, @ref || @repository.root_ref)
             = nav_link(controller: %w(commit commits compare repositories protected_branches)) do
               = link_to "Commits", project_commits_path(@project, @ref || @repository.root_ref)
-            = nav_link(path: 'projects#graph') do
-              = link_to "Network", graph_project_path(@project)
+            = nav_link(controller: %w(graph)) do
+              = link_to "Network", project_graph_path(@project, @ref || @repository.root_ref)
 
         - if @project.issues_enabled
           = nav_link(controller: %w(issues milestones labels)) do
diff --git a/app/views/layouts/user_team.html.haml b/app/views/layouts/user_team.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..19bbc373f46378d0575fb384725b53753070b972
--- /dev/null
+++ b/app/views/layouts/user_team.html.haml
@@ -0,0 +1,39 @@
+!!! 5
+%html{ lang: "en"}
+  = render "layouts/head", title: "#{@team.name}"
+  %body{class: "#{app_theme} application"}
+    = render "layouts/flash"
+    = render "layouts/head_panel", title: "team: #{@team.name}"
+    .container
+      %ul.main_menu
+        = nav_link(path: 'teams#show', html_options: {class: 'home'}) do
+          = link_to team_path(@team), title: "Home" do
+            %i.icon-home
+
+        = nav_link(path: 'teams#issues') do
+          = link_to issues_team_path(@team) do
+            Issues
+            %span.count= Issue.opened.of_user_team(@team).count
+
+        = nav_link(path: 'teams#merge_requests') do
+          = link_to merge_requests_team_path(@team) do
+            Merge Requests
+            %span.count= MergeRequest.opened.of_user_team(@team).count
+
+        = nav_link(controller: [:members]) do
+          = link_to team_members_path(@team), class: "team-tab tab" do
+            Members
+            %span.count= @team.members.count
+
+        - if can? current_user, :admin_user_team, @team
+          = nav_link(controller: [:projects]) do
+            = link_to team_projects_path(@team), class: "team-tab tab" do
+              Projects
+              %span.count= @team.projects.count
+
+          = nav_link(path: 'teams#edit') do
+            = link_to edit_team_path(@team), class: "stat-tab tab " do
+              %i.icon-edit
+              Edit Team
+
+      .content= yield
diff --git a/app/views/merge_requests/_filter.html.haml b/app/views/merge_requests/_filter.html.haml
index 86148fbcfee994da62090ded2a4937ffa0866051..4b48306ed0575bc8e8471610d4a71b8819f24fcf 100644
--- a/app/views/merge_requests/_filter.html.haml
+++ b/app/views/merge_requests/_filter.html.haml
@@ -16,5 +16,5 @@
 
   %fieldset
     %hr
-    = link_to "Reset", project_merge_requests_path(@project), class: 'btn right'
+    = link_to "Reset", project_merge_requests_path(@project), class: 'btn pull-right'
 
diff --git a/app/views/merge_requests/_form.html.haml b/app/views/merge_requests/_form.html.haml
index 9a4f0617a3a60210616083a11188263209308882..816c852d24bbffdec761d55d535935c06d8fc4e2 100644
--- a/app/views/merge_requests/_form.html.haml
+++ b/app/views/merge_requests/_form.html.haml
@@ -1,6 +1,6 @@
 = form_for [@project, @merge_request], html: { class: "#{controller.action_name}-merge-request form-horizontal" } do |f|
   -if @merge_request.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %ul
         - @merge_request.errors.full_messages.each do |msg|
           %li= msg
@@ -51,19 +51,19 @@
 
   .form-actions
     - if @merge_request.new_record?
-      = f.submit 'Submit merge request', class: "btn success"
+      = f.submit 'Submit merge request', class: "btn btn-create"
     -else
-      = f.submit 'Save changes', class: "save-btn btn"
+      = f.submit 'Save changes', class: "btn btn-save"
     - if @merge_request.new_record?
-      = link_to project_merge_requests_path(@project), class: "btn cancel-btn" do
+      = link_to project_merge_requests_path(@project), class: "btn btn-cancel" do
         Cancel
     - else
-      = link_to project_merge_request_path(@project, @merge_request), class: "btn cancel-btn" do
+      = link_to project_merge_request_path(@project, @merge_request), class: "btn btn-cancel" do
         Cancel
 
 :javascript
   $(function(){
-    disableButtonIfEmptyField("#merge_request_title", ".save-btn");
+    disableButtonIfEmptyField("#merge_request_title", ".btn-save");
 
     var source_branch = $("#merge_request_source_branch")
       , target_branch = $("#merge_request_target_branch");
diff --git a/app/views/merge_requests/_merge_request.html.haml b/app/views/merge_requests/_merge_request.html.haml
index 7369f3dd0619f67baae0e2572cf7b74d512aedcf..09c55d9846523ee6a512a9d0307d9242f58e7c14 100644
--- a/app/views/merge_requests/_merge_request.html.haml
+++ b/app/views/merge_requests/_merge_request.html.haml
@@ -1,20 +1,20 @@
 %li{ class: mr_css_classes(merge_request) }
-  .right
+  .pull-right
     .left
       - if merge_request.merged?
-        %span.btn.small.disabled.grouped
+        %span.btn.btn-small.disabled.grouped
           %strong
             %i.icon-ok
             = "MERGED"
       - if merge_request.notes.any?
-        %span.btn.small.disabled.grouped
+        %span.btn.btn-small.disabled.grouped
           %i.icon-comment
           = merge_request.mr_and_commit_notes.count
       - if merge_request.milestone_id?
-        %span.btn.small.disabled.grouped
+        %span.btn.btn-small.disabled.grouped
           %i.icon-time
           = merge_request.milestone.title
-      %span.btn.small.disabled.grouped
+      %span.btn.btn-small.disabled.grouped
         = merge_request.source_branch
         &rarr;
         = merge_request.target_branch
diff --git a/app/views/merge_requests/index.html.haml b/app/views/merge_requests/index.html.haml
index 61c32b533f6d7ef798f59958a8f883e7372badf7..3073c8f6bab447f57a9ea65320897b54caee26df 100644
--- a/app/views/merge_requests/index.html.haml
+++ b/app/views/merge_requests/index.html.haml
@@ -1,5 +1,5 @@
 - if can? current_user, :write_merge_request, @project
-  = link_to new_project_merge_request_path(@project), class: "right btn primary", title: "New Merge Request" do
+  = link_to new_project_merge_request_path(@project), class: "pull-right btn btn-primary", title: "New Merge Request" do
     %i.icon-plus
     New Merge Request
 %h3.page_title
@@ -28,8 +28,8 @@
         - if @merge_requests.present?
           %li.bottom
             .left= paginate @merge_requests, theme: "gitlab"
-            .right
-              %span.cgray.right #{@merge_requests.total_count} merge requests for this filter
+            .pull-right
+              %span.cgray.pull-right #{@merge_requests.total_count} merge requests for this filter
 
 :javascript
   $(merge_requestsPage);
diff --git a/app/views/merge_requests/show/_mr_accept.html.haml b/app/views/merge_requests/show/_mr_accept.html.haml
index 128ffe76782e9b0e01ef45d3705019179d8bd0f6..c2c04b863e7df72c52b5890d0f5517de53f6ed1e 100644
--- a/app/views/merge_requests/show/_mr_accept.html.haml
+++ b/app/views/merge_requests/show/_mr_accept.html.haml
@@ -1,5 +1,5 @@
 - unless can?(current_user, :accept_mr, @project)
-  .alert-message
+  .alert
     %strong Only masters can accept MR
 
 
@@ -29,14 +29,14 @@
         %strong This repository does not have satellite. Ask administrator to fix this issue
 
   .automerge_widget.cannot_be_merged{style: "display:none"}
-    .alert.alert-info
+    .alert.alert-disabled
       %span
-        = link_to "Show how to merge", "#", class: "how_to_merge_link btn small padded", title: "How To Merge"
+        = link_to "Show how to merge", "#", class: "how_to_merge_link btn btn-small padded", title: "How To Merge"
         &nbsp;
         %strong This request can't be merged with GitLab. You should do it manually
 
   .automerge_widget.unchecked
-    .alert-message
+    .alert
       %strong
         %i.icon-refresh
         Checking for ability to automatically merge…
diff --git a/app/views/merge_requests/show/_mr_ci.html.haml b/app/views/merge_requests/show/_mr_ci.html.haml
index d46b606ef7f8b4cfa125be781adee638faa212b4..dd1e78a020578711e84077773cdf5bf1f6f7cf91 100644
--- a/app/views/merge_requests/show/_mr_ci.html.haml
+++ b/app/views/merge_requests/show/_mr_ci.html.haml
@@ -23,7 +23,7 @@
         = link_to "Build page", ci_build_details_path(@merge_request)
 
   .ci_widget
-    .alert-message
+    .alert
       %strong
         %i.icon-refresh
         Checking for CI status for #{@merge_request.last_commit_short_sha}
diff --git a/app/views/merge_requests/show/_mr_title.html.haml b/app/views/merge_requests/show/_mr_title.html.haml
index c2ffe8e3770f1c89ab60b18f9d9222a64729f801..8119728dcb93588aeb595b127378145269dfdf85 100644
--- a/app/views/merge_requests/show/_mr_title.html.haml
+++ b/app/views/merge_requests/show/_mr_title.html.haml
@@ -5,7 +5,7 @@
   &rarr;
   %span.label_branch= @merge_request.target_branch
 
-  %span.right
+  %span.pull-right
     - if can?(current_user, :modify_merge_request, @merge_request)
       - if @merge_request.open?
         .left.btn-group
@@ -17,13 +17,13 @@
             %li= link_to "Email Patches", project_merge_request_path(@project, @merge_request, format: :patch)
             %li= link_to "Plain Diff",    project_merge_request_path(@project, @merge_request, format: :diff)
 
-        = link_to 'Close', project_merge_request_path(@project, @merge_request, merge_request: {closed: true }, status_only: true), method: :put, class: "btn grouped danger", title: "Close merge request"
+        = link_to 'Close', project_merge_request_path(@project, @merge_request, merge_request: {closed: true }, status_only: true), method: :put, class: "btn grouped btn-close", title: "Close merge request"
 
         = link_to edit_project_merge_request_path(@project, @merge_request), class: "btn grouped" do
           %i.icon-edit
           Edit
 
-.right
+.pull-right
   .span3#votes= render 'votes/votes_block', votable: @merge_request
 
 .back_link
diff --git a/app/views/milestones/_form.html.haml b/app/views/milestones/_form.html.haml
index 1c496a93e54137a29e7d2748629cd95a634d825e..fbaf64a305cdb559eb9420f865fcf5c1a94eb953 100644
--- a/app/views/milestones/_form.html.haml
+++ b/app/views/milestones/_form.html.haml
@@ -7,7 +7,7 @@
 
 = form_for [@project, @milestone], html: {class: "new_milestone form-horizontal"}  do |f|
   -if @milestone.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %ul
         - @milestone.errors.full_messages.each do |msg|
           %li= msg
@@ -32,16 +32,16 @@
 
   .form-actions
     - if @milestone.new_record?
-      = f.submit 'Create milestone', class: "save-btn btn"
-      = link_to "Cancel", project_milestones_path(@project), class: "btn cancel-btn"
+      = f.submit 'Create milestone', class: "btn-save btn"
+      = link_to "Cancel", project_milestones_path(@project), class: "btn btn-cancel"
     -else
-      = f.submit 'Save changes', class: "save-btn btn"
-      = link_to "Cancel", project_milestone_path(@project, @milestone), class: "btn cancel-btn"
+      = f.submit 'Save changes', class: "btn-save btn"
+      = link_to "Cancel", project_milestone_path(@project, @milestone), class: "btn btn-cancel"
 
 
 :javascript
   $(function() {
-    disableButtonIfEmptyField("#milestone_title", ".save-btn");
+    disableButtonIfEmptyField("#milestone_title", ".btn-save");
     $( ".datepicker" ).datepicker({
       dateFormat: "yy-mm-dd",
       onSelect: function(dateText, inst) { $("#milestone_due_date").val(dateText) }
diff --git a/app/views/milestones/_milestone.html.haml b/app/views/milestones/_milestone.html.haml
index 3864792f7e81995db1246d4a3964208dd1f21839..00e20117f36de3b6df691d7abcc32eb844e75278 100644
--- a/app/views/milestones/_milestone.html.haml
+++ b/app/views/milestones/_milestone.html.haml
@@ -1,7 +1,7 @@
 %li{class: "milestone milestone-#{milestone.closed ? 'closed' : 'open'}", id: dom_id(milestone) }
-  .right
+  .pull-right
     - if can?(current_user, :admin_milestone, milestone.project) and milestone.open?
-      = link_to edit_project_milestone_path(milestone.project, milestone), class: "btn small edit-milestone-link grouped" do
+      = link_to edit_project_milestone_path(milestone.project, milestone), class: "btn btn-small edit-milestone-link grouped" do
         %i.icon-edit
         Edit
   %h4
diff --git a/app/views/milestones/index.html.haml b/app/views/milestones/index.html.haml
index 3089595fe0b004298305882a4350f2d91a21fd12..b78f17053fd91e794ae7909ff3fede251d7c7436 100644
--- a/app/views/milestones/index.html.haml
+++ b/app/views/milestones/index.html.haml
@@ -3,7 +3,7 @@
   %h3.page_title
     Milestones
     - if can? current_user, :admin_milestone, @project
-      = link_to "New Milestone", new_project_milestone_path(@project), class: "right btn small", title: "New Milestone"
+      = link_to "New Milestone", new_project_milestone_path(@project), class: "pull-right btn btn-small", title: "New Milestone"
   %br
   %div.ui-box
     .title
diff --git a/app/views/milestones/show.html.haml b/app/views/milestones/show.html.haml
index fc7ae51f184328b41a87bb7e1bd008fe5a16e772..43d82a54dd64c654e9c608a761ec4c841e203b91 100644
--- a/app/views/milestones/show.html.haml
+++ b/app/views/milestones/show.html.haml
@@ -8,14 +8,14 @@
       = link_to project_milestones_path(@project) do
         &larr; To milestones list
   .span6
-    .right
+    .pull-right
       - unless  @milestone.closed
-        = link_to new_project_issue_path(@project, issue: { milestone_id: @milestone.id }), class: "btn small grouped", title: "New Issue" do
+        = link_to new_project_issue_path(@project, issue: { milestone_id: @milestone.id }), class: "btn btn-small grouped", title: "New Issue" do
           %i.icon-plus
           New Issue
         = link_to 'Browse Issues', project_issues_path(@milestone.project, milestone_id: @milestone.id), class: "btn edit-milestone-link small grouped"
         - if can?(current_user, :admin_milestone, @project)
-          = link_to edit_project_milestone_path(@project, @milestone), class: "btn small grouped" do
+          = link_to edit_project_milestone_path(@project, @milestone), class: "btn btn-small grouped" do
             %i.icon-edit
             Edit
 
@@ -25,7 +25,7 @@
   %hr
   %p
     %span All issues for this milestone are closed. You may close milestone now.
-    = link_to 'Close Milestone', project_milestone_path(@project, @milestone, milestone: {closed: true }), method: :put, class: "btn small danger"
+    = link_to 'Close Milestone', project_milestone_path(@project, @milestone, milestone: {closed: true }), method: :put, class: "btn btn-small btn-remove"
 
 .ui-box.ui-box-show
   .ui-box-head
@@ -43,7 +43,7 @@
       #{@milestone.closed_items_count} closed
       &ndash;
       #{@milestone.open_items_count} open
-      %span.right= @milestone.expires_at
+      %span.pull-right= @milestone.expires_at
     .progress.progress-info
       .bar{style: "width: #{@milestone.percent_complete}%;"}
 
diff --git a/app/views/notes/_discussion.html.haml b/app/views/notes/_discussion.html.haml
index a9a11fc2d7ebd303e0215af9e361754ba6c7a7f0..24cb422817445f186124a86743460a5d15c1ec09 100644
--- a/app/views/notes/_discussion.html.haml
+++ b/app/views/notes/_discussion.html.haml
@@ -38,7 +38,7 @@
     - if note.for_diff_line?
       - if note.diff
         .content
-          .diff_file= render "notes/discussion_diff", discussion_notes: discussion_notes, note: note
+          .file= render "notes/discussion_diff", discussion_notes: discussion_notes, note: note
       - else
         = link_to 'show outdated discussion', '#', class: 'js-show-outdated-discussion'
         %div.hide.outdated-discussion
diff --git a/app/views/notes/_discussion_diff.html.haml b/app/views/notes/_discussion_diff.html.haml
index 93ab59c72c501749bcf932e3d7f24992fd816973..790b77333d5c6b6eca9a878f22735b68e30ce61f 100644
--- a/app/views/notes/_discussion_diff.html.haml
+++ b/app/views/notes/_discussion_diff.html.haml
@@ -1,5 +1,5 @@
 - diff = note.diff
-.diff_file_header
+.header
   - if diff.deleted_file
     %span= diff.old_path
   - else
@@ -7,7 +7,7 @@
     - if diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode
       %span.file-mode= "#{diff.a_mode} → #{diff.b_mode}"
   %br/
-.diff_file_content
+.content
   %table
     - each_diff_line(diff, note.diff_file_index) do |line, type, line_code, line_new, line_old|
       %tr.line_holder{ id: line_code }
diff --git a/app/views/notes/_form.html.haml b/app/views/notes/_form.html.haml
index d094119a9da5ea209974de1c4b2c247de258466e..a154c31e5abeedbc565a621c316e941206d05c08 100644
--- a/app/views/notes/_form.html.haml
+++ b/app/views/notes/_form.html.haml
@@ -15,30 +15,30 @@
     = f.text_area :note, size: 255, class: 'note_text js-note-text js-gfm-input turn-on'
     .note_preview.js-note-preview.turn-off
 
-  .buttons
-    = f.submit 'Add Comment', class: "btn comment-btn grouped js-comment-button"
-    %a.btn.grouped.js-close-discussion-note-form Cancel
   .hint
-    .right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
+    .pull-right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
   .clearfix
 
-  .note_options
-    .attachment
-      %h6 Attachment:
-      .file_name.js-attachment-filename File name...
-      %a.choose-btn.btn.small.js-choose-note-attachment-button Choose File ...
-      .hint Any file up to 10 MB
+  .note-form-actions
+    .buttons
+      = f.submit 'Add Comment', class: "btn comment-btn grouped js-comment-button"
+      %a.btn.grouped.js-close-discussion-note-form Cancel
 
-      = f.file_field :attachment, class: "js-note-attachment-input"
-
-    .notify_options
-      %h6 Notify via email:
+    .note-form-option
       = label_tag :notify do
         = check_box_tag :notify, 1, !@note.for_commit?
-        Project team
+        %span.light Notify team via email
 
       .js-notify-commit-author
         = label_tag :notify_author do
           = check_box_tag :notify_author, 1 , @note.for_commit?
-          Commit author
-  .clearfix
+          %span.light Notify commit author
+    .note-form-option
+      %a.choose-btn.btn.btn-small.js-choose-note-attachment-button
+        %i.icon-paper-clip
+        %span Choose File ...
+      &nbsp;
+      %span.file_name.js-attachment-filename File name...
+      = f.file_field :attachment, class: "js-note-attachment-input hide"
+
+    .clearfix
diff --git a/app/views/notes/_note.html.haml b/app/views/notes/_note.html.haml
index 9efeb563e0a276bb49a2dfa2d4d317f4e466f516..4d3007a0ed1ddc8406bb5abeab33c054862b9afe 100644
--- a/app/views/notes/_note.html.haml
+++ b/app/views/notes/_note.html.haml
@@ -30,8 +30,8 @@
   - if note.attachment.url
     - if note.attachment.image?
       = image_tag note.attachment.url, class: 'note-image-attach'
-    .attachment.right
+    .attachment.pull-right
       = link_to note.attachment.url, target: "_blank" do
-        %i.icon-attachment
+        %i.icon-paper-clip
         = note.attachment_identifier
   .clear
diff --git a/app/views/profiles/account.html.haml b/app/views/profiles/account.html.haml
index 522e45e637a390a25a7a58e3d64c0291799b50be..2ad000b815bd86cf36e85478b511e87c98adaa00 100644
--- a/app/views/profiles/account.html.haml
+++ b/app/views/profiles/account.html.haml
@@ -12,7 +12,7 @@
 %fieldset
   %legend
     Private token
-    %span.cred.right
+    %span.cred.pull-right
       keep it secret!
   .padded
     = form_for @user, url: reset_private_token_profile_path, method: :put do |f|
@@ -24,7 +24,7 @@
         %p.cgray
           - if current_user.private_token
             = text_field_tag "token", current_user.private_token, class: "xxlarge large_text"
-            = f.submit 'Reset', confirm: "Are you sure?", class: "btn primary btn-build-token"
+            = f.submit 'Reset', confirm: "Are you sure?", class: "btn btn-primary btn-build-token"
           - else
             %span You don`t have one yet. Click generate to fix it.
             = f.submit 'Generate', class: "btn success btn-build-token"
@@ -35,7 +35,7 @@
     .padded
       %p.slead After successful password update you will be redirected to login page where you should login with new password
       -if @user.errors.any?
-        .alert-message.block-message.error
+        .alert.alert-error
           %ul
             - @user.errors.full_messages.each do |msg|
               %li= msg
@@ -49,14 +49,14 @@
           = f.password_field :password_confirmation, required: true
       .clearfix
         .input
-          = f.submit 'Save password', class: "btn save-btn"
+          = f.submit 'Save password', class: "btn btn-save"
 
 
 
 %fieldset.update-username
   %legend
     Username
-    %small.cred.right
+    %small.cred.pull-right
       Changing your username can have unintended side effects!
   = form_for @user, url: update_username_profile_path,  method: :put, remote: true do |f|
     .padded
@@ -75,6 +75,6 @@
           %li It will change web url for personal projects.
           %li It will change the git path to repositories for personal projects.
       .input
-        = f.submit 'Save username', class: "btn save-btn"
+        = f.submit 'Save username', class: "btn btn-save"
 
 
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index 687463b672cb731c8136803abb4198f72c044bdc..3cf6330cc3ccd9dcc97998111f48351009edbb8c 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -6,7 +6,7 @@
   %small
     = @user.email
 
-  .right
+  .pull-right
     = link_to destroy_user_session_path, class: "logout", method: :delete do
       %small
         %i.icon-signout
@@ -15,7 +15,7 @@
 
 = form_for @user, url: profile_path, method: :put, html: { class: "edit_user form-horizontal" }  do |f|
   -if @user.errors.any?
-    %div.alert-message.block-message.error
+    %div.alert.alert-error
       %ul
         - @user.errors.full_messages.each do |msg|
           %li= msg
@@ -31,8 +31,22 @@
         .controls
           = f.text_field :email, class: "input-xlarge", required: true
           %span.help-block We also use email for avatar detection.
+      .control-group
+        = f.label :skype, class: "control-label"
+        .controls= f.text_field :skype, class: "input-xlarge"
+      .control-group
+        = f.label :linkedin, class: "control-label"
+        .controls= f.text_field :linkedin, class: "input-xlarge"
+      .control-group
+        = f.label :twitter, class: "control-label"
+        .controls= f.text_field :twitter, class: "input-xlarge"
+      .control-group
+        = f.label :bio, class: "control-label"
+        .controls
+          = f.text_area :bio, rows: 6, class: "input-xlarge", maxlength: 250
+          %span.help-block Tell us about yourself in fewer than 250 characters.
 
-    .span5.right
+    .span5.pull-right
       %fieldset.tips
         %legend Tips:
         %ul
@@ -47,28 +61,22 @@
               %p
                 You can login through #{@user.provider.titleize}!
                 = link_to "click here to change", account_profile_path
-
-  .row
-    .span7
-      .control-group
-        = f.label :skype, class: "control-label"
-        .controls= f.text_field :skype, class: "input-xlarge"
-      .control-group
-        = f.label :linkedin, class: "control-label"
-        .controls= f.text_field :linkedin, class: "input-xlarge"
-      .control-group
-        = f.label :twitter, class: "control-label"
-        .controls= f.text_field :twitter, class: "input-xlarge"
-      .control-group
-        = f.label :bio, class: "control-label"
-        .controls
-          = f.text_area :bio, rows: 6, class: "input-xlarge", maxlength: 250
-          %span.help-block Tell us about yourself in fewer than 250 characters.
-    .span5.right
+          - if current_user.can_create_group?
+            %li
+              %p
+                Need a group for several dependent projects?
+                = link_to new_group_path, class: "btn btn-tiny" do
+                  Create a group
+          - if current_user.can_create_team?
+            %li
+              %p
+                Want to share a team between projects?
+                = link_to new_team_path, class: "btn btn-tiny" do
+                  Create a team
       %fieldset
         %legend
           Personal projects:
-          %small.right
+          %small.pull-right
             %span= current_user.personal_projects.count
             of
             %span= current_user.projects_limit
@@ -79,9 +87,10 @@
       %fieldset
         %legend
           SSH public keys:
-          %strong.right= link_to current_user.keys.count, keys_path
+          %span.pull-right
+            = link_to pluralize(current_user.keys.count, 'key'), keys_path
         .padded
-          = link_to "Add Public Key", new_key_path, class: "btn small"
+          = link_to "Add Public Key", new_key_path, class: "btn btn-small"
 
   .form-actions
-    = f.submit 'Save', class: "btn save-btn"
+    = f.submit 'Save', class: "btn btn-save"
diff --git a/app/views/projects/_clone_panel.html.haml b/app/views/projects/_clone_panel.html.haml
index 2962ad980b3bfd69ffc450f6afe8a4a02277cf81..e52df19be965aff530be022186c3071fcd52d35b 100644
--- a/app/views/projects/_clone_panel.html.haml
+++ b/app/views/projects/_clone_panel.html.haml
@@ -2,8 +2,8 @@
   .row
     .span7
       .form-horizontal= render "shared/clone_panel"
-    .span4.right
-      .right
+    .span4.pull-right
+      .pull-right
         - unless @project.empty_repo?
           - if can? current_user, :download_code, @project
             = link_to archive_project_repository_path(@project), class: "btn-small btn grouped" do
diff --git a/app/views/projects/_form.html.haml b/app/views/projects/_form.html.haml
index b582adc97a2ce84306cf2dbdd98b03bc0f0014e8..0336654dc698d488cea77bd2f209eab6c9143dbc 100644
--- a/app/views/projects/_form.html.haml
+++ b/app/views/projects/_form.html.haml
@@ -1,6 +1,6 @@
 = form_for(@project, remote: true) do |f|
   - if @project.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %ul
         - @project.errors.full_messages.each do |msg|
           %li= msg
@@ -42,7 +42,7 @@
         = f.check_box :wiki_enabled
         %span.descr Pages for project documentation
 
-  - if can? current_user, :change_public_mode, @project
+  - if can?(current_user, :change_public_mode, @project)
     %fieldset.features
       %legend
         %i.icon-share
@@ -77,9 +77,9 @@
   %br
 
   .actions
-    = f.submit 'Save', class: "btn save-btn"
+    = f.submit 'Save', class: "btn btn-save"
     = link_to 'Cancel', @project, class: "btn"
     - unless @project.new_record?
       - if can?(current_user, :remove_project, @project)
-        .right
-          = link_to 'Remove Project', @project, confirm: 'Removed project can not be restored! Are you sure?', method: :delete, class: "btn danger"
+        .pull-right
+          = link_to 'Remove Project', @project, confirm: 'Removed project can not be restored! Are you sure?', method: :delete, class: "btn btn-remove"
diff --git a/app/views/projects/_new_form.html.haml b/app/views/projects/_new_form.html.haml
index 131a4de42184218ede8675bc1a764c3b5288ae40..185164955fcd3271882bfec0b16501e48d60bd4c 100644
--- a/app/views/projects/_new_form.html.haml
+++ b/app/views/projects/_new_form.html.haml
@@ -1,13 +1,13 @@
 = form_for(@project, remote: true) do |f|
   - if @project.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %span= @project.errors.full_messages.first
   .clearfix.project_name_holder
     = f.label :name do
       Project name is
     .input
       = f.text_field :name, placeholder: "Example Project", class: "xxlarge"
-      = f.submit 'Create project', class: "btn success project-submit"
+      = f.submit 'Create project', class: "btn btn-create project-submit"
 
   - if current_user.can_select_namespace?
     .clearfix
@@ -15,6 +15,20 @@
         %span Namespace
       .input
         = f.select :namespace_id, namespaces_options(params[:namespace_id] || :current_user), {}, {class: 'chosen'}
-  %hr
+
   %p.padded
-    All created project are private. You choose who can see project and commit to repository.
+    New projects are private by default. You choose who can see the project and commit to repository.
+  %hr
+
+  - if current_user.can_create_group?
+    .clearfix
+      .input.light
+        Need a group for several dependent projects?
+        = link_to new_group_path, class: "btn btn-tiny" do
+          Create a group
+  - if current_user.can_create_team?
+    .clearfix
+      .input.light
+        Want to share a project between team?
+        = link_to new_team_path, class: "btn btn-tiny" do
+          Create a team
diff --git a/app/views/projects/_project_head.html.haml b/app/views/projects/_project_head.html.haml
index 94052650694b284251343ff63bd5eea4d1815131..b8c88853a620a53fba325044acdf4f088b93f694 100644
--- a/app/views/projects/_project_head.html.haml
+++ b/app/views/projects/_project_head.html.haml
@@ -3,7 +3,7 @@
     = link_to project_path(@project), class: "activities-tab tab" do
       %i.icon-home
       Show
-  = nav_link(controller: :team_members) do
+  = nav_link(controller: [:team_members, :teams]) do
     = link_to project_team_index_path(@project), class: "team-tab tab" do
       %i.icon-user
       Team
@@ -13,19 +13,19 @@
     = link_to 'Snippets', project_snippets_path(@project), class: "snippets-tab tab"
 
   - if can? current_user, :admin_project, @project
-    = nav_link(controller: :deploy_keys, html_options: {class: 'right'}) do
+    = nav_link(controller: :deploy_keys, html_options: {class: 'pull-right'}) do
       = link_to project_deploy_keys_path(@project) do
         %span
         Deploy Keys
-    = nav_link(controller: :hooks, html_options: {class: 'right'}) do
+    = nav_link(controller: :hooks, html_options: {class: 'pull-right'}) do
       = link_to project_hooks_path(@project) do
         %span
         Hooks
-    = nav_link(controller: :services, html_options: {class: 'right'}) do
+    = nav_link(controller: :services, html_options: {class: 'pull-right'}) do
       = link_to project_services_path(@project) do
         %span
         Services
-    = nav_link(path: 'projects#edit', html_options: {class: 'right'}) do
+    = nav_link(path: 'projects#edit', html_options: {class: 'pull-right'}) do
       = link_to edit_project_path(@project), class: "stat-tab tab " do
         %i.icon-edit
         Edit
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index 52dff687a3a70a775401632d35011c316e4077c3..9426517876ea8fc9fd5c5b67a1de5bf5907a4e14 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -31,4 +31,4 @@
 
   - if can? current_user, :remove_project, @project
     .prepend-top-20
-      = link_to 'Remove project', @project, confirm: 'Are you sure?', method: :delete, class: "btn danger right"
+      = link_to 'Remove project', @project, confirm: 'Are you sure?', method: :delete, class: "btn btn-remove pull-right"
diff --git a/app/views/projects/teams/available.html.haml b/app/views/projects/teams/available.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..da7823638b9741a7a84d199609437b0f2c6f0adc
--- /dev/null
+++ b/app/views/projects/teams/available.html.haml
@@ -0,0 +1,22 @@
+= render "projects/project_head"
+
+%h3.page_title
+  = "Assign project to team of users"
+%hr
+%p.slead
+  Read more about assign to team of users #{link_to "here", '#', class: 'vlink'}.
+= form_tag assign_project_teams_path(@project), method: 'post' do
+  %p.slead Choose Team of users you want to assign:
+  .padded
+    = label_tag :team_id, "Team"
+    .input= select_tag(:team_id, options_from_collection_for_select(@teams, :id, :name), prompt: "Select team", class: "chosen xxlarge", required: true)
+  %p.slead Choose greatest user acces in team you want to assign:
+  .padded
+    = label_tag :team_ids, "Permission"
+    .input= select_tag :greatest_project_access, options_for_select(UserTeam.access_roles), {class: "project-access-select chosen span3" }
+
+
+  .actions
+    = submit_tag 'Assign', class: "btn btn-create"
+    = link_to "Cancel", project_team_index_path(@project), class: "btn btn-cancel"
+
diff --git a/app/views/protected_branches/index.html.haml b/app/views/protected_branches/index.html.haml
index c1ecceda435a6f69fb80ef878627d277e6bdde45..15644de552f9246f4c1f4d006ae032d7a3bda96b 100644
--- a/app/views/protected_branches/index.html.haml
+++ b/app/views/protected_branches/index.html.haml
@@ -14,7 +14,7 @@
     - if can? current_user, :admin_project, @project
       = form_for [@project, @protected_branch] do |f|
         -if @protected_branch.errors.any?
-          .alert-message.block-message.error
+          .alert.alert-error
             %ul
               - @protected_branch.errors.full_messages.each do |msg|
                 %li= msg
@@ -24,7 +24,7 @@
           .span3
             = f.select(:name, @project.open_branches.map { |br| [br.name, br.name] } , {include_blank: "Select branch"}, {class: "chosen span3"})
           &nbsp;
-          = f.submit 'Protect', class: "primary btn"
+          = f.submit 'Protect', class: "btn-primary btn"
 
     - unless @branches.empty?
       %table
@@ -51,4 +51,4 @@
                   (branch was removed from repository)
               %td
                 - if can? current_user, :admin_project, @project
-                  = link_to 'Unprotect', [@project, branch], confirm: 'Are you sure?', method: :delete, class: "danger btn small"
+                  = link_to 'Unprotect', [@project, branch], confirm: 'Are you sure?', method: :delete, class: "btn btn-remove btn-small"
diff --git a/app/views/public/projects/index.html.haml b/app/views/public/projects/index.html.haml
index afdd4c5fd95150eab8dc3b9554a7f730a3ee9a0b..21e9d2e6029c93036f3d2a07ff5df988cd8447ab 100644
--- a/app/views/public/projects/index.html.haml
+++ b/app/views/public/projects/index.html.haml
@@ -9,7 +9,7 @@
       %h5
         %i.icon-share
         = project.name_with_namespace
-        .right
+        .pull-right
           %pre.dark.tiny git clone #{project.http_url_to_repo}
 
 
diff --git a/app/views/repositories/_feed.html.haml b/app/views/repositories/_feed.html.haml
index 443801337181bdbd7ea08c38cdd041592c62b842..eaf15ca77d63237da15022f7dfce7c139349131b 100644
--- a/app/views/repositories/_feed.html.haml
+++ b/app/views/repositories/_feed.html.haml
@@ -15,6 +15,6 @@
       = image_tag gravatar_icon(commit.author_email), class: "", width: 16
       = gfm escape_once(truncate(commit.title, length: 40))
   %td
-    %span.right.cgray
+    %span.pull-right.cgray
       = time_ago_in_words(commit.committed_date)
       ago
diff --git a/app/views/repositories/stats.html.haml b/app/views/repositories/stats.html.haml
index bdf047f1e989ee9c690b756cf5f1b45aa5fdd4ad..dde35ea38aa0b1d0f4600ea09165c94973a62358 100644
--- a/app/views/repositories/stats.html.haml
+++ b/app/views/repositories/stats.html.haml
@@ -23,7 +23,7 @@
           = image_tag gravatar_icon(author.email, 16), class: 'avatar s16'
           = author.name
           %small.light= author.email
-          .right
+          .pull-right
             = author.commits
 
 
diff --git a/app/views/search/_filter.html.haml b/app/views/search/_filter.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..3fe17dce8574ba8bee305f26fbb7bac86ab3e58f
--- /dev/null
+++ b/app/views/search/_filter.html.haml
@@ -0,0 +1,24 @@
+%fieldset
+  %legend Groups:
+  %ul.nav.nav-pills.nav-stacked
+    %li{class: ("active" if params[:group_id].blank?)}
+      = link_to search_path(group_id: nil, search: params[:search]) do
+        Any
+    - current_user.authorized_groups.each do |group|
+      %li{class: ("active" if params[:group_id] == group.id.to_s)}
+        = link_to search_path(group_id: group.id, search: params[:search]) do
+          = group.name
+
+%fieldset
+  %legend Projects:
+  %ul.nav.nav-pills.nav-stacked
+    %li{class: ("active" if params[:project_id].blank?)}
+      = link_to search_path(project_id: nil, search: params[:search]) do
+        Any
+    - current_user.authorized_projects.each do |project|
+      %li{class: ("active" if params[:project_id] == project.id.to_s)}
+        = link_to search_path(project_id: project.id, search: params[:search]) do
+          = project.name_with_namespace
+
+= hidden_field_tag :group_id, params[:group_id]
+= hidden_field_tag :project_id, params[:project_id]
diff --git a/app/views/search/_result.html.haml b/app/views/search/_result.html.haml
index 79bed4f737cdd9b64ade5ccfbd68ccbba04a0bdc..bfa46075baa3a2154328ba5ca355499ee4513a99 100644
--- a/app/views/search/_result.html.haml
+++ b/app/views/search/_result.html.haml
@@ -1,83 +1,38 @@
-%br
-%h3.page_title
-  Search results
-  %span.cgray (#{@projects.count + @merge_requests.count + @issues.count + @wiki_pages.count})
-%hr
+%fieldset
+  %legend
+    Search results
+    %span.cgray (#{@projects.count + @merge_requests.count + @issues.count + @wiki_pages.count})
 .search_results
-  .row
-    .span6
-      %table
-        %thead
-          %tr
-            %th Projects
-        %tbody
-          - @projects.each do |project|
-            %tr
-              %td
-                = link_to project do
-                  %strong.term= project.name_with_namespace
-                  %small.cgray
-                    last activity at
-                    = project.last_activity_date.stamp("Aug 25, 2011")
-          - if @projects.blank?
-            %tr
-              %td
-                %h4.nothing_here_message No Projects
-      %br
-      %table
-        %thead
-          %tr
-            %th Merge Requests
-        %tbody
-          - @merge_requests.each do |merge_request|
-            %tr
-              %td
-                = link_to [merge_request.project, merge_request] do
-                  %span.badge.badge-info ##{merge_request.id}
-                  &ndash;
-                  %strong.term= truncate merge_request.title, length: 50
-                  %strong.right
-                    %span.label= merge_request.project.name
-          - if @merge_requests.blank?
-            %tr
-              %td
-                %h4.nothing_here_message No Merge Requests
-    .span6
-      %table
-        %thead
-          %tr
-            %th Issues
-        %tbody
-          - @issues.each do |issue|
-            %tr
-              %td
-                = link_to [issue.project, issue] do
-                  %span.badge.badge-info ##{issue.id}
-                  &ndash;
-                  %strong.term= truncate issue.title, length: 40
-                %strong.right
-                  %span.label= issue.project.name
-          - if @issues.blank?
-            %tr
-              %td
-                %h4.nothing_here_message No Issues
-    .span6
-      %table
-        %thead
-          %tr
-            %th Wiki
-        %tbody
-          - @wiki_pages.each do |wiki_page|
-            %tr
-              %td
-                = link_to project_wiki_path(wiki_page.project, wiki_page) do
-                  %strong.term= truncate wiki_page.title, length: 40
-                %strong.right
-                  %span.label= wiki_page.project.name
-          - if @wiki_pages.blank?
-            %tr
-              %td
-                %h4.nothing_here_message No wiki pages
+  %ul.well-list
+    - @projects.each do |project|
+      %li
+        project:
+        = link_to project do
+          %strong.term= project.name_with_namespace
+    - @merge_requests.each do |merge_request|
+      %li
+        merge request:
+        = link_to [merge_request.project, merge_request] do
+          %span ##{merge_request.id}
+          %strong.term
+            = truncate merge_request.title, length: 50
+        %span.light (#{merge_request.project.name_with_namespace})
+    - @issues.each do |issue|
+      %li
+        issue:
+        = link_to [issue.project, issue] do
+          %span ##{issue.id}
+          %strong.term
+            = truncate issue.title, length: 50
+        %span.light (#{issue.project.name_with_namespace})
+    - @wiki_pages.each do |wiki_page|
+      %li
+        wiki:
+        = link_to project_wiki_path(wiki_page.project, wiki_page) do
+          %strong.term
+            = truncate wiki_page.title, length: 50
+        %span.light (#{wiki_page.project.name_with_namespace})
+
 :javascript
   $(function() {
     $(".search_results .term").highlight("#{escape_javascript(params[:search])}");
diff --git a/app/views/search/show.html.haml b/app/views/search/show.html.haml
index aa0d6d700d9cac5fc339cd57cc1ef743d26e8ead..5914c22df6ef951d442f7132b177247a83b82b70 100644
--- a/app/views/search/show.html.haml
+++ b/app/views/search/show.html.haml
@@ -1,9 +1,15 @@
 = form_tag search_path, method: :get, class: 'form-inline' do |f|
-  .padded
+  .search-holder
     = label_tag :search do
-      %strong Looking for
+      %span Looking for
     .input
       = search_field_tag :search, params[:search], placeholder: "issue 143", class: "input-xxlarge search-text-input", id: "dashboard_search"
-      = submit_tag 'Search', class: "btn primary wide"
-- if params[:search].present?
-  = render 'search/result'
+      = submit_tag 'Search', class: "btn btn-primary wide"
+  .clearfix
+  .row
+    .span3
+      = render 'filter', f: f
+    .span9
+      .results
+        - if params[:search].present?
+          = render 'search/result'
diff --git a/app/views/services/_gitlab_ci.html.haml b/app/views/services/_gitlab_ci.html.haml
index 649c5cc4c3c60212e57f7a927b7097c6a38538a9..dfde643849e3c2fffbfda69b55f5e20f20ebd41e 100644
--- a/app/views/services/_gitlab_ci.html.haml
+++ b/app/views/services/_gitlab_ci.html.haml
@@ -1,7 +1,7 @@
 %h3.page_title
   GitLab CI
   %small Continuous integration server from GitLab
-  .right
+  .pull-right
     - if @service.active
       %small.cgreen Enabled
     - else
@@ -16,7 +16,7 @@
 %hr
 = form_for(@service, :as => :service, :url => project_service_path(@project, :gitlab_ci), :method => :put) do |f|
   - if @service.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %ul
         - @service.errors.full_messages.each do |msg|
           %li= msg
@@ -40,7 +40,7 @@
 
 
   .form-actions
-    = f.submit 'Save', class: 'btn save-btn'
+    = f.submit 'Save', class: 'btn btn-save'
     &nbsp;
     - if @service.valid? && @service.active
       = link_to 'Test settings', test_project_service_path(@project), class: 'btn btn-small'
diff --git a/app/views/services/index.html.haml b/app/views/services/index.html.haml
index 2c94f965eec1f968a999d6613f2e7ec9ddc858c7..27dbf5025691bfb35ee8f631953048244504b59a 100644
--- a/app/views/services/index.html.haml
+++ b/app/views/services/index.html.haml
@@ -8,7 +8,7 @@
       = link_to edit_project_service_path(@project, :gitlab_ci) do
         GitLab CI
         %small Continuous integration server from GitLab
-      .right
+      .pull-right
         - if @gitlab_ci_service.try(:active)
           %small.cgreen
             %i.icon-ok
@@ -21,11 +21,11 @@
     %h4
       Jenkins CI
       %small An extendable open source continuous integration server
-      .right
+      .pull-right
         %small Not implemented yet
   %li.disabled
     %h4
       Campfire
       %small Web-based group chat tool
-      .right
+      .pull-right
         %small Not implemented yet
diff --git a/app/views/snippets/_blob.html.haml b/app/views/snippets/_blob.html.haml
index ed518300ac05615a7464406189c090c843df3101..017a33b34f343fdba99596bf6cdecaff8e8a2ca6 100644
--- a/app/views/snippets/_blob.html.haml
+++ b/app/views/snippets/_blob.html.haml
@@ -3,7 +3,7 @@
     %i.icon-file
     %strong= @snippet.file_name
     %span.options
-      = link_to "raw", raw_project_snippet_path(@project, @snippet), class: "btn very_small", target: "_blank"
+      = link_to "raw", raw_project_snippet_path(@project, @snippet), class: "btn btn-tiny", target: "_blank"
   .file_content.code
     - unless @snippet.content.empty?
       %div{class: user_color_scheme_class}
diff --git a/app/views/snippets/_form.html.haml b/app/views/snippets/_form.html.haml
index baef737b56524c8a42da9fa64184f23106f7c1d2..77162cdcde338beb2c54be39ac765e6961b31a15 100644
--- a/app/views/snippets/_form.html.haml
+++ b/app/views/snippets/_form.html.haml
@@ -4,7 +4,7 @@
 .snippet-form-holder
   = form_for [@project, @snippet] do |f|
     -if @snippet.errors.any?
-      .alert-message.block-message.error
+      .alert.alert-error
         %ul
           - @snippet.errors.full_messages.each do |msg|
             %li= msg
@@ -27,10 +27,10 @@
               = f.hidden_field :content, class: 'snippet-file-content'
 
     .form-actions
-      = f.submit 'Save', class: "save-btn btn"
+      = f.submit 'Save', class: "btn-save btn"
       = link_to "Cancel", project_snippets_path(@project), class: " btn"
       - unless @snippet.new_record?
-        .right= link_to 'Destroy', [@project, @snippet], confirm: 'Are you sure?', method: :delete, class: "btn right danger delete-snippet", id: "destroy_snippet_#{@snippet.id}"
+        .pull-right= link_to 'Destroy', [@project, @snippet], confirm: 'Are you sure?', method: :delete, class: "btn pull-right danger delete-snippet", id: "destroy_snippet_#{@snippet.id}"
 
 
 :javascript
diff --git a/app/views/snippets/index.html.haml b/app/views/snippets/index.html.haml
index 7b8f94de7dd5d3a25b79e8bb53444b51722ab8c4..28a533d238f3024428368b054419505c2ff8bd96 100644
--- a/app/views/snippets/index.html.haml
+++ b/app/views/snippets/index.html.haml
@@ -5,7 +5,7 @@
   %small share code pastes with others out of git repository
 
   - if can? current_user, :write_snippet, @project
-    = link_to new_project_snippet_path(@project), class: "btn small add_new right", title: "New Snippet" do
+    = link_to new_project_snippet_path(@project), class: "btn btn-small add_new pull-right", title: "New Snippet" do
       Add new snippet
 %br
 %table
diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml
index 02022185f9abded1d05ebb6cbabfc13a76bac008..e6bcd88f830e610f290e7827288076db26860f96 100644
--- a/app/views/snippets/show.html.haml
+++ b/app/views/snippets/show.html.haml
@@ -4,7 +4,7 @@
   = @snippet.title
   %small= @snippet.file_name
   - if can?(current_user, :admin_snippet, @project) || @snippet.author == current_user
-    = link_to "Edit", edit_project_snippet_path(@project, @snippet), class: "btn small right"
+    = link_to "Edit", edit_project_snippet_path(@project, @snippet), class: "btn btn-small pull-right"
 
 %br
 %div= render 'blob'
diff --git a/app/views/team_members/_form.html.haml b/app/views/team_members/_form.html.haml
index a963e462a7868fe990934f135d84463bbdf0641e..05bea2db87e91bbbe399b40882ca0fc1c0860db1 100644
--- a/app/views/team_members/_form.html.haml
+++ b/app/views/team_members/_form.html.haml
@@ -1,11 +1,11 @@
 %h3.page_title
   = "New Team member(s)"
 %hr
-= form_for @team_member, as: :team_member, url: project_team_members_path(@project, @team_member) do |f|
-  -if @team_member.errors.any?
-    .alert-message.block-message.error
+= form_for @user_project_relation, as: :team_member, url: project_team_members_path(@project) do |f|
+  -if @user_project_relation.errors.any?
+    .alert.alert-error
       %ul
-        - @team_member.errors.full_messages.each do |msg|
+        - @user_project_relation.errors.full_messages.each do |msg|
           %li= msg
 
   %h6 1. Choose people you want in the team
@@ -16,8 +16,8 @@
   %h6 2. Set access level for them
   .clearfix
     = f.label :project_access, "Project Access"
-    .input= select_tag :project_access, options_for_select(Project.access_options, @team_member.project_access), class: "project-access-select chosen"
+    .input= select_tag :project_access, options_for_select(Project.access_options, @user_project_relation.project_access), class: "project-access-select chosen"
 
   .actions
-    = f.submit 'Save', class: "btn save-btn"
-    = link_to "Cancel", project_team_index_path(@project), class: "btn cancel-btn"
+    = f.submit 'Add users', class: "btn btn-create"
+    = link_to "Cancel", project_team_index_path(@project), class: "btn btn-cancel"
diff --git a/app/views/team_members/_show.html.haml b/app/views/team_members/_show.html.haml
index 8082f47fca8b14f1dada1eb81d606f36f3993e97..3df2caed64a0cfbb65a6a1f00625ed918dc2c7b1 100644
--- a/app/views/team_members/_show.html.haml
+++ b/app/views/team_members/_show.html.haml
@@ -1,28 +1,28 @@
 - user = member.user
 - allow_admin = can? current_user, :admin_project, @project
-%li{id: dom_id(member), class: "team_member_row user_#{user.id}"}
+%li{id: dom_id(user), class: "team_member_row user_#{user.id}"}
   .row
     .span6
-      = link_to project_team_member_path(@project, member), title: user.name, class: "dark" do
+      = link_to project_team_member_path(@project, user), title: user.name, class: "dark" do
         = image_tag gravatar_icon(user.email, 40), class: "avatar s32"
-      = link_to project_team_member_path(@project, member), title: user.name, class: "dark" do
+      = link_to project_team_member_path(@project, user), title: user.name, class: "dark" do
         %strong= truncate(user.name, lenght: 40)
         %br
         %small.cgray= user.email
 
-    .span5.right
+    .span5.pull-right
       - if allow_admin
         .left
-          = form_for(member, as: :team_member, url: project_team_member_path(@project, member)) do |f|
+          = form_for(member, as: :team_member, url: project_team_member_path(@project, member.user)) do |f|
             = f.select :project_access, options_for_select(UsersProject.access_roles, member.project_access), {}, class: "medium project-access-select span2"
-      .right
+      .pull-right
         - if current_user == user
           %span.btn.disabled This is you!
         - if @project.namespace_owner == user
-          %span.btn.disabled.success Owner
+          %span.btn.disabled Owner
         - elsif user.blocked
           %span.btn.disabled.blocked Blocked
         - elsif allow_admin
-          = link_to project_team_member_path(project_id: @project, id: member.id), confirm: remove_from_team_message(@project, member), method: :delete, class: "very_small btn danger" do
+          = link_to project_team_member_path(@project, user), confirm: remove_from_project_team_message(@project, user), method: :delete, class: "btn-tiny btn btn-remove" do
             %i.icon-minus.icon-white
 
diff --git a/app/views/team_members/_show_team.html.haml b/app/views/team_members/_show_team.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..f1555f0b87b050a3a8070b5d4110f81f3545324c
--- /dev/null
+++ b/app/views/team_members/_show_team.html.haml
@@ -0,0 +1,15 @@
+- team = team_rel.user_team
+- allow_admin = can? current_user, :admin_team_member, @project
+%li{id: dom_id(team), class: "user_team_row team_#{team.id}"}
+  .row
+    .span6
+      %strong= link_to team.name, team_path(team), title: team.name, class: "dark"
+      %br
+      %small.cgray Members: #{team.members.count}
+
+    .span5.pull-right
+      .pull-right
+        - if allow_admin
+          .left
+            = link_to resign_project_team_path(@project, team), method: :delete, confirm: "Are you shure?", class: "btn btn-remove small" do
+              %i.icon-minus.icon-white
diff --git a/app/views/team_members/_teams.html.haml b/app/views/team_members/_teams.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..156fdd1befa13df95e66b40e15e2991e94e3fff8
--- /dev/null
+++ b/app/views/team_members/_teams.html.haml
@@ -0,0 +1,16 @@
+- grouper_project_teams(@project).each do |access, teams|
+  .ui-box
+    %h5.title
+      = UserTeam.access_roles.key(access).pluralize
+      %small= teams.size
+    %ul.well-list
+      - teams.sort_by(&:team_name).each do |tofr|
+        = render(partial: 'team_members/show_team', locals: {team_rel: tofr})
+
+
+:javascript
+  $(function(){
+    $('.repo-access-select, .project-access-select').live("change", function() {
+      $(this.form).submit();
+    });
+  })
diff --git a/app/views/team_members/create.js.haml b/app/views/team_members/create.js.haml
index d5ae5d0cc435582e285a7a0a6c1c050ac3d2079a..b7dff35a269a39287d6b8af50156bda82e2ce21b 100644
--- a/app/views/team_members/create.js.haml
+++ b/app/views/team_members/create.js.haml
@@ -1,4 +1,4 @@
-- if @team_member.valid?
+- if @user_project_relation.valid?
   :plain
     $("#new_team_member").hide("slide", { direction: "right" }, 150, function(){
       $("#team-table").show("slide", { direction: "left" }, 150, function() {
diff --git a/app/views/team_members/import.html.haml b/app/views/team_members/import.html.haml
index de82f4162481fa52af1923817a4225995f8392b2..d6c81befd08865726d99e1e997bf21e0c84e6fa1 100644
--- a/app/views/team_members/import.html.haml
+++ b/app/views/team_members/import.html.haml
@@ -4,7 +4,7 @@
   = "Import team from another project"
 %hr
 %p.slead
-  Read more about team import #{link_to "here", '#', class: 'vlink'}.
+  Read more about project team import #{link_to "here", '#', class: 'vlink'}.
 = form_tag apply_import_project_team_members_path(@project), method: 'post' do
   %p.slead Choose project you want to use as team source:
   .padded
@@ -12,6 +12,6 @@
     .input= select_tag(:source_project_id, options_from_collection_for_select(current_user.authorized_projects, :id, :name_with_namespace), prompt: "Select project", class: "chosen xxlarge", required: true)
 
   .actions
-    = submit_tag 'Import', class: "btn save-btn"
-    = link_to "Cancel", project_team_index_path(@project), class: "btn cancel-btn"
+    = submit_tag 'Import', class: "btn btn-save"
+    = link_to "Cancel", project_team_index_path(@project), class: "btn btn-cancel"
 
diff --git a/app/views/team_members/index.html.haml b/app/views/team_members/index.html.haml
index e413c81bb6c2fe2ee25bf8ba94c520319c5914d2..3264f58cb32d0bf1817924fcc39fb3bb19e2ac53 100644
--- a/app/views/team_members/index.html.haml
+++ b/app/views/team_members/index.html.haml
@@ -1,20 +1,33 @@
 = render "projects/project_head"
 %h3.page_title
   Team Members
-  (#{@project.users_projects.count})
+  (#{@project.users.count})
   %small
     Read more about project permissions
     %strong= link_to "here", help_permissions_path, class: "vlink"
 
   - if can? current_user, :admin_team_member, @project
-    %span.right
-      = link_to import_project_team_members_path(@project), class: "btn small grouped", title: "Import team from another project" do
+    %span.pull-right
+      = link_to import_project_team_members_path(@project), class: "btn btn-small grouped", title: "Import team from another project" do
         Import team from another project
-      = link_to new_project_team_member_path(@project), class: "btn success small grouped", title: "New Team Member" do
+      = link_to available_project_teams_path(@project), class: "btn btn-small grouped", title: "Assign project to team of users" do
+        Assign project to Team of users
+      = link_to new_project_team_member_path(@project), class: "btn btn-primary small grouped", title: "New Team Member" do
         New Team Member
-%hr
 
+%hr
 
 .clearfix
 %div.team-table
   = render partial: "team_members/team", locals: {project: @project}
+
+
+%h3.page_title
+  Assigned teams
+  (#{@project.user_teams.count})
+
+%hr
+
+.clearfix
+%div.team-table
+  = render partial: "team_members/teams", locals: {project: @project}
diff --git a/app/views/team_members/show.html.haml b/app/views/team_members/show.html.haml
index 4008e8bd23e6c17bbf2351be96ea5b1966fbe5ba..192948eff7da0134ff4aae79d9596f7458f03312 100644
--- a/app/views/team_members/show.html.haml
+++ b/app/views/team_members/show.html.haml
@@ -1,14 +1,13 @@
 - allow_admin = can? current_user, :admin_project, @project
-- user = @team_member.user
 
 .team_member_show
   - if can? current_user, :admin_project, @project
-    = link_to 'Remove from team', project_team_member_path(project_id: @project, id: @team_member.id), confirm: 'Are you sure?', method: :delete, class: "right btn danger"
+    = link_to 'Remove from team', project_team_member_path(@project, @member), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove pull-right"
   .profile_avatar_holder
-    = image_tag gravatar_icon(user.email, 60), class: "borders"
+    = image_tag gravatar_icon(@member.email, 60), class: "borders"
   %h3.page_title
-    = user.name
-    %small (@#{user.username})
+    = @member.name
+    %small (@#{@member.username})
 
   %hr
   .back_link
@@ -21,34 +20,34 @@
       %table.lite
         %tr
           %td Email
-          %td= mail_to user.email
+          %td= mail_to @member.email
         %tr
           %td Skype
-          %td= user.skype
-        - unless user.linkedin.blank?
+          %td= @member.skype
+        - unless @member.linkedin.blank?
           %tr
             %td LinkedIn
-            %td= user.linkedin
-        - unless user.twitter.blank?
+            %td= @member.linkedin
+        - unless @member.twitter.blank?
           %tr
             %td Twitter
-            %td= user.twitter
-        - unless user.bio.blank?
+            %td= @member.twitter
+        - unless @member.bio.blank?
           %tr
             %td Bio
-            %td= user.bio
+            %td= @member.bio
     .span6
       %table.lite
         %tr
           %td Member since
-          %td= @team_member.created_at.stamp("Aug 21, 2011")
+          %td= @user_project_relation.created_at.stamp("Aug 21, 2011")
         %tr
           %td
             Project Access:
             %small (#{link_to "read more", help_permissions_path, class: "vlink"})
           %td
-            = form_for(@team_member, as: :team_member, url: project_team_member_path(@project, @team_member)) do |f|
-              = f.select :project_access, options_for_select(Project.access_options, @team_member.project_access), {}, class: "project-access-select", disabled: !allow_admin
+            = form_for(@user_project_relation, as: :team_member, url: project_team_member_path(@project, @member)) do |f|
+              = f.select :project_access, options_for_select(Project.access_options, @user_project_relation.project_access), {}, class: "project-access-select", disabled: !allow_admin
   %hr
   = render @events
 :javascript
diff --git a/app/views/team_members/update.js.haml b/app/views/team_members/update.js.haml
index 6d7f88160deefa8e2a0c1c078f65fab9ab59112d..c68fe9574a2526a4fb136c22bd2d1428919aad4b 100644
--- a/app/views/team_members/update.js.haml
+++ b/app/views/team_members/update.js.haml
@@ -1,6 +1,6 @@
-- if @team_member.valid?
+- if @user_project_relation.valid?
   :plain
-    $("##{dom_id(@team_member)}").effect("highlight", {color: "#529214"}, 1000);;
+    $("##{dom_id(@user_project_relation)}").effect("highlight", {color: "#529214"}, 1000);;
 - else
   :plain
-    $("##{dom_id(@team_member)}").effect("highlight", {color: "#D12F19"}, 1000);;
+    $("##{dom_id(@user_project_relation)}").effect("highlight", {color: "#D12F19"}, 1000);;
diff --git a/app/views/teams/_filter.html.haml b/app/views/teams/_filter.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..f461fcad42e41dbb00faea920ef584103946f486
--- /dev/null
+++ b/app/views/teams/_filter.html.haml
@@ -0,0 +1,33 @@
+= form_tag team_filter_path(entity), method: 'get' do
+  %fieldset.dashboard-search-filter
+    = search_field_tag "search", params[:search], { placeholder: 'Search', class: 'search-text-input' }
+    = button_tag type: 'submit', class: 'btn' do
+      %i.icon-search
+
+  %fieldset
+    %legend Status:
+    %ul.nav.nav-pills.nav-stacked
+      %li{class: ("active" if !params[:status])}
+        = link_to team_filter_path(entity, status: nil) do
+          Open
+      %li{class: ("active" if params[:status] == 'closed')}
+        = link_to team_filter_path(entity, status: 'closed') do
+          Closed
+      %li{class: ("active" if params[:status] == 'all')}
+        = link_to team_filter_path(entity, status: 'all') do
+          All
+
+  %fieldset
+    %legend Projects:
+    %ul.nav.nav-pills.nav-stacked
+      - @projects.each do |project|
+        - unless entities_per_project(project, entity).zero?
+          %li{class: ("active" if params[:project_id] == project.id.to_s)}
+            = link_to team_filter_path(entity, project_id: project.id) do
+              = project.name_with_namespace
+              %small.pull-right= entities_per_project(project, entity)
+
+  %fieldset
+    %hr
+    = link_to "Reset", team_filter_path(entity), class: 'btn pull-right'
+
diff --git a/app/views/teams/_projects.html.haml b/app/views/teams/_projects.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..5677255b15be9b602671e7a0c862032481c096e1
--- /dev/null
+++ b/app/views/teams/_projects.html.haml
@@ -0,0 +1,22 @@
+.projects_box
+  %h5.title
+    Projects
+    %small
+      (#{projects.count})
+    - if can? current_user, :manage_user_team, @team
+      %span.pull-right
+        = link_to new_team_project_path(@team), class: "btn btn-tiny info" do
+          %i.icon-plus
+          Assign Project
+  %ul.well-list
+    - if projects.blank?
+      %p.nothing_here_message This team has no projects yet
+    - projects.each do |project|
+      %li
+        = link_to project_path(project), class: dom_class(project) do
+          %strong.well-title= truncate(project.name, length: 25)
+          %span.arrow
+            &rarr;
+          %span.last_activity
+            %strong Last activity:
+            %span= project_last_activity(project)
diff --git a/app/views/teams/edit.html.haml b/app/views/teams/edit.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..3435583600d2ccbe5f29f93e9f3f4a6e985b1a18
--- /dev/null
+++ b/app/views/teams/edit.html.haml
@@ -0,0 +1,20 @@
+%h3.page_title= "Edit Team #{@team.name}"
+%hr
+= form_for @team, url: team_path(@team) do |f|
+  - if @team.errors.any?
+    .alert.alert-error
+      %span= @team.errors.full_messages.first
+  .clearfix
+    = f.label :name do
+      Team name is
+    .input
+      = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
+
+  .clearfix
+    = f.label :path do
+      Team path is
+    .input
+      = f.text_field :path, placeholder: "opensource", class: "xxlarge left"
+  .form-actions
+    = f.submit 'Save team changes', class: "btn btn-primary"
+    = link_to 'Delete team', team_path(@team), method: :delete, confirm: "You are shure?", class: "btn btn-remove pull-right"
diff --git a/app/views/teams/issues.html.haml b/app/views/teams/issues.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..c6a68c37b9c9edeca02b441ae1019cf819030e47
--- /dev/null
+++ b/app/views/teams/issues.html.haml
@@ -0,0 +1,23 @@
+%h3.page_title
+  Issues
+  %small (in Team projects assigned to Team members)
+  %small.pull-right #{@issues.total_count} issues
+
+%hr
+.row
+  .span3
+    = render 'filter', entity: 'issue'
+  .span9
+    - if @issues.any?
+      - @issues.group_by(&:project).each do |group|
+        %div.ui-box
+          - @project = group[0]
+          %h5.title
+            = link_to_project @project
+          %ul.well-list.issues_table
+            - group[1].each do |issue|
+              = render(partial: 'issues/show', locals: {issue: issue})
+      %hr
+      = paginate @issues, theme: "gitlab"
+    - else
+      %p.nothing_here_message Nothing to show here
diff --git a/app/views/teams/members/_form.html.haml b/app/views/teams/members/_form.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..c22ee78305fab97f9ce5c48269d863269c85aa83
--- /dev/null
+++ b/app/views/teams/members/_form.html.haml
@@ -0,0 +1,20 @@
+= form_tag admin_team_member_path(@team, @member), method: :put do
+  -if @member.errors.any?
+    .alert.alert-error
+      %ul
+        - @member.errors.full_messages.each do |msg|
+          %li= msg
+
+  .clearfix
+    %label Default access for Team projects:
+    .input
+      = select_tag :default_project_access, options_for_select(UserTeam.access_roles, @team.default_projects_access(@member)), class: "project-access-select chosen span3"
+  .clearfix
+    %label Team admin?
+    .input
+      = check_box_tag :group_admin, true, @team.admin?(@member)
+
+  %br
+  .actions
+    = submit_tag 'Save', class: "btn btn-save"
+    = link_to 'Cancel', :back, class: "btn"
diff --git a/app/views/teams/members/_show.html.haml b/app/views/teams/members/_show.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..6cddb8e482663c34f9368bf0fcf1904954c0d74e
--- /dev/null
+++ b/app/views/teams/members/_show.html.haml
@@ -0,0 +1,31 @@
+- user = member.user
+- allow_admin = can? current_user, :manage_user_team, @team
+%li{id: dom_id(member), class: "team_member_row user_#{user.id}"}
+  .row
+    .span5
+      = link_to user_path(user.username), title: user.name, class: "dark" do
+        = image_tag gravatar_icon(user.email, 40), class: "avatar s32"
+      = link_to user_path(user.username), title: user.name, class: "dark" do
+        %strong= truncate(user.name, lenght: 40)
+        %br
+        %small.cgray= user.email
+
+    .span6.pull-right
+      - if allow_admin
+        .left.span2
+          = form_for(member, as: :team_member, url: team_member_path(@team, user)) do |f|
+            = f.select :permission, options_for_select(UsersProject.access_roles, @team.default_projects_access(user)), {}, class: "medium project-access-select span2"
+        .left.span2
+          %span
+            = check_box_tag :group_admin, true, @team.admin?(user)
+            Admin access
+      .pull-right
+        - if current_user == user
+          %span.btn.disabled This is you!
+        - if @team.owner == user
+          %span.btn.disabled.btn-success Owner
+        - elsif user.blocked
+          %span.btn.disabled.blocked Blocked
+        - elsif allow_admin
+          = link_to team_member_path(@team, user), confirm: remove_from_user_team_message(@team, user), method: :delete, class: "btn-tiny btn btn-remove" do
+            %i.icon-minus.icon-white
diff --git a/app/views/teams/members/_team.html.haml b/app/views/teams/members/_team.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..d8afc1fa3711e87b0d9400c561dbf20b06f69676
--- /dev/null
+++ b/app/views/teams/members/_team.html.haml
@@ -0,0 +1,16 @@
+- grouped_user_team_members(@team).each do |access, members|
+  .ui-box
+    %h5.title
+      = Project.access_options.key(access).pluralize
+      %small= members.size
+    %ul.well-list
+      - members.sort_by(&:user_name).each do |up|
+        = render(partial: 'teams/members/show', locals: {member: up})
+
+
+:javascript
+  $(function(){
+    $('.repo-access-select, .project-access-select').live("change", function() {
+      $(this.form).submit();
+    });
+  })
diff --git a/app/views/teams/members/edit.html.haml b/app/views/teams/members/edit.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..375880496abfaceb019f6b9b8908d6e1e0051a67
--- /dev/null
+++ b/app/views/teams/members/edit.html.haml
@@ -0,0 +1,16 @@
+%h3.page_title
+  Edit access #{@member.name} in #{@team.name} team
+
+%hr
+%table.zebra-striped
+  %tr
+    %td User:
+    %td= @member.name
+  %tr
+    %td Team:
+    %td= @team.name
+  %tr
+    %td Since:
+    %td= member_since(@team, @member).stamp("Nov 11, 2010")
+
+= render 'form'
diff --git a/app/views/teams/members/index.html.haml b/app/views/teams/members/index.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..87438266cfb75264bf268c3d7d7013a5f9bef5ae
--- /dev/null
+++ b/app/views/teams/members/index.html.haml
@@ -0,0 +1,17 @@
+%h3.page_title
+  Team Members
+  (#{@members.count})
+  %small
+    Read more about project permissions
+    %strong= link_to "here", help_permissions_path, class: "vlink"
+
+  - if can? current_user, :manage_user_team, @team
+    %span.pull-right
+      = link_to new_team_member_path(@team), class: "btn btn-primary small grouped", title: "New Team Member" do
+        New Team Member
+%hr
+
+
+.clearfix
+%div.team-table
+  = render partial: "teams/members/team", locals: {project: @team}
diff --git a/app/views/teams/members/new.html.haml b/app/views/teams/members/new.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..083e137e0ae0b6104188bac142f2a9d7487649ce
--- /dev/null
+++ b/app/views/teams/members/new.html.haml
@@ -0,0 +1,28 @@
+%h3.page_title
+  Team: #{@team.name}
+
+%fieldset
+  %legend Members (#{@team.members.count})
+  = form_tag team_members_path(@team), id: "team_members", class: "bulk_import", method: :post  do
+    %table#members_list
+      %thead
+        %tr
+          %th User name
+          %th Default project access
+          %th Team access
+          %th
+      - @team.members.each do |member|
+        %tr.member
+          %td
+            = member.name
+            %small= "(#{member.email})"
+          %td= @team.human_default_projects_access(member)
+          %td= @team.admin?(member) ? "Admin" : "Member"
+          %td
+      %tr
+        %td= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name_with_email), multiple: true, data: {placeholder: 'Select users'}, class: 'chosen span5'
+        %td= select_tag :default_project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3" }
+        %td
+          %span= check_box_tag :group_admin
+          %span Admin?
+        %td= submit_tag 'Add User', class: "btn btn-create", id: :add_members_to_team
diff --git a/app/views/teams/members/show.html.haml b/app/views/teams/members/show.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..f760c2dae3a2c405376acc73e29c5cb1d21450e8
--- /dev/null
+++ b/app/views/teams/members/show.html.haml
@@ -0,0 +1,60 @@
+- allow_admin = can? current_user, :admin_project, @project
+- user = @team_member.user
+
+.team_member_show
+  - if can? current_user, :admin_project, @project
+    = link_to 'Remove from team', project_team_member_path(project_id: @project, id: @team_member.id), confirm: 'Are you sure?', method: :delete, class: "pull-right btn btn-remove"
+  .profile_avatar_holder
+    = image_tag gravatar_icon(user.email, 60), class: "borders"
+  %h3.page_title
+    = user.name
+    %small (@#{user.username})
+
+  %hr
+  .back_link
+    %br
+    = link_to project_team_index_path(@project), class: "" do
+      &larr; To team list
+  %br
+  .row
+    .span6
+      %table.lite
+        %tr
+          %td Email
+          %td= mail_to user.email
+        %tr
+          %td Skype
+          %td= user.skype
+        - unless user.linkedin.blank?
+          %tr
+            %td LinkedIn
+            %td= user.linkedin
+        - unless user.twitter.blank?
+          %tr
+            %td Twitter
+            %td= user.twitter
+        - unless user.bio.blank?
+          %tr
+            %td Bio
+            %td= user.bio
+    .span6
+      %table.lite
+        %tr
+          %td Member since
+          %td= @team_member.created_at.stamp("Aug 21, 2011")
+        %tr
+          %td
+            Project Access:
+            %small (#{link_to "read more", help_permissions_path, class: "vlink"})
+          %td
+            = form_for(@team_member, as: :team_member, url: project_team_member_path(@project, @team_member)) do |f|
+              = f.select :project_access, options_for_select(Project.access_options, @team_member.project_access), {}, class: "project-access-select", disabled: !allow_admin
+  %hr
+  = render @events
+:javascript
+  $(function(){
+    $('.repo-access-select, .project-access-select').live("change", function() {
+      $(this.form).submit();
+    });
+  })
+
diff --git a/app/views/teams/merge_requests.html.haml b/app/views/teams/merge_requests.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..417d1aa604029e3d0e052f5bdb7902c55d0394b7
--- /dev/null
+++ b/app/views/teams/merge_requests.html.haml
@@ -0,0 +1,24 @@
+%h3.page_title
+  Merge Requests
+  %small (authored by or assigned to Team members)
+  %small.pull-right #{@merge_requests.total_count} merge requests
+
+%hr
+.row
+  .span3
+    = render 'filter', entity: 'merge_request'
+  .span9
+    - if @merge_requests.any?
+      - @merge_requests.group_by(&:project).each do |group|
+        .ui-box
+          - @project = group[0]
+          %h5.title
+            = link_to_project @project
+          %ul.well-list
+            - group[1].each do |merge_request|
+              = render(partial: 'merge_requests/merge_request', locals: {merge_request: merge_request})
+      %hr
+      = paginate @merge_requests, theme: "gitlab"
+
+    - else
+      %h3.nothing_here_message Nothing to show here
diff --git a/app/views/teams/new.html.haml b/app/views/teams/new.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..38f61c11c0cac08711fec3e092d980062e09fd58
--- /dev/null
+++ b/app/views/teams/new.html.haml
@@ -0,0 +1,19 @@
+%h3.page_title New Team
+%hr
+= form_for @team, url: teams_path do |f|
+  - if @team.errors.any?
+    .alert.alert-error
+      %span= @team.errors.full_messages.first
+  .clearfix
+    = f.label :name do
+      Team name is
+    .input
+      = f.text_field :name, placeholder: "Ex. Ruby Developers", class: "xxlarge left"
+      &nbsp;
+      = f.submit 'Create team', class: "btn btn-create"
+  %hr
+  .padded
+    %ul
+      %li All created teams are public (users can view who enter into team and which project are assigned for this team)
+      %li People within a team see only projects they have access to
+      %li You will be able to assign existing projects for team
diff --git a/app/views/teams/projects/_form.html.haml b/app/views/teams/projects/_form.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..d2c89b0c36bce601e58a7c535600acf5e5dbbe47
--- /dev/null
+++ b/app/views/teams/projects/_form.html.haml
@@ -0,0 +1,16 @@
+= form_tag team_project_path(@team, @project), method: :put do
+  -if @project.errors.any?
+    .alert.alert-error
+      %ul
+        - @project.errors.full_messages.each do |msg|
+          %li= msg
+
+  .clearfix
+    %label Max access for Team members:
+    .input
+      = select_tag :greatest_project_access, options_for_select(UserTeam.access_roles, @team.max_project_access(@project)), class: "project-access-select chosen span3"
+
+  %br
+  .actions
+    = submit_tag 'Save', class: "btn btn-save"
+    = link_to 'Cancel', :back, class: "btn btn-cancel"
diff --git a/app/views/teams/projects/edit.html.haml b/app/views/teams/projects/edit.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..82c7d734815d84de50dc50b37da0dbfa923af78b
--- /dev/null
+++ b/app/views/teams/projects/edit.html.haml
@@ -0,0 +1,6 @@
+%h3.page_title
+  Edit max access in #{link_to @project.name_with_namespace, @project} for #{link_to(@team.name, team_path(@team))} team
+
+%hr
+
+= render 'form'
diff --git a/app/views/teams/projects/index.html.haml b/app/views/teams/projects/index.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..696ee29c7786d7fed3ba43aeba2745916ad7bf93
--- /dev/null
+++ b/app/views/teams/projects/index.html.haml
@@ -0,0 +1,36 @@
+%h3.page_title
+  Assigned projects (#{@team.projects.count})
+  %small
+    Read more about project permissions
+    %strong= link_to "here", help_permissions_path, class: "vlink"
+
+  - if current_user.can?(:manage_user_team, @team) && @avaliable_projects.any?
+    %span.pull-right
+      = link_to new_team_project_path(@team), class: "btn btn-primary small grouped", title: "New Team Member" do
+        Assign project to Team
+
+%hr
+
+- if @team.projects.present?
+  %table.projects-table
+    %thead
+      %tr
+        %th Project name
+        %th Max access
+        - if current_user.can?(:admin_user_team, @team)
+          %th.span3
+
+    - @team.projects.each do |project|
+      %tr.project
+        %td
+          = link_to project.name_with_namespace, project_path(project)
+        %td
+          %span= @team.human_max_project_access(project)
+
+        - if current_user.can?(:admin_user_team, @team)
+          %td.bgred
+            = link_to 'Edit max access', edit_team_project_path(@team, project), class: "btn btn-small"
+            = link_to 'Relegate', team_project_path(@team, project), confirm: 'Remove project from team and move to global namespace. Are you sure?', method: :delete, class: "btn btn-remove small"
+
+- else
+  %p.nothing_here_message This team has no projects yet
diff --git a/app/views/teams/projects/new.html.haml b/app/views/teams/projects/new.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..3f3671aa0a47859c3376c0ad00397e472fffd9eb
--- /dev/null
+++ b/app/views/teams/projects/new.html.haml
@@ -0,0 +1,23 @@
+%h3.page_title
+  Team: #{@team.name}
+
+%fieldset
+  %legend Projects (#{@team.projects.count})
+  = form_tag team_projects_path(@team), id: "assign_projects", class: "bulk_import", method: :post  do
+    %table#projects_list
+      %thead
+        %tr
+          %th Project name
+          %th Max access
+          %th
+      - @team.projects.each do |project|
+        %tr.project
+          %td
+            = link_to project.name_with_namespace, team_project_path(@team, project)
+          %td
+            %span= @team.human_max_project_access(project)
+          %td
+      %tr
+        %td= select_tag :project_ids, options_from_collection_for_select(@avaliable_projects , :id, :name_with_namespace), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5'
+        %td= select_tag :greatest_project_access, options_for_select(UserTeam.access_roles), {class: "project-access-select chosen span3" }
+        %td= submit_tag 'Add Project', class: "btn btn-create", id: :assign_projects_to_team
diff --git a/app/views/teams/show.html.haml b/app/views/teams/show.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..d6e80e2a51e23e82e3e53e1a6876ec793fa5d364
--- /dev/null
+++ b/app/views/teams/show.html.haml
@@ -0,0 +1,28 @@
+.projects
+  .activities.span8
+    = link_to dashboard_path, class: 'btn btn-tiny' do
+      &larr; To dashboard
+    &nbsp;
+    %span.cgray Events and projects are filtered in scope of team
+    %hr
+    - if @events.any?
+      .content_list
+    - else
+      %p.nothing_here_message Projects activity will be displayed here
+    .loading.hide
+  .side.span4
+    = render "projects", projects: @projects
+    %div
+      %span.rss-icon
+        = link_to dashboard_path(:atom, { private_token: current_user.private_token }) do
+          = image_tag "rss_ui.png", title: "feed"
+          %strong News Feed
+
+    %hr
+    .gitlab-promo
+      = link_to "Homepage", "http://gitlabhq.com"
+      = link_to "Blog", "http://blog.gitlabhq.com"
+      = link_to "@gitlabhq", "https://twitter.com/gitlabhq"
+
+:javascript
+  $(function(){ Pager.init(20, true); });
diff --git a/app/views/tree/_blob_actions.html.haml b/app/views/tree/_blob_actions.html.haml
index 21334ea1f1652177d038209722ca404d8a45a2dd..0bde968d0e69610e41c3d9cb1bf7739b89a2b222 100644
--- a/app/views/tree/_blob_actions.html.haml
+++ b/app/views/tree/_blob_actions.html.haml
@@ -1,12 +1,12 @@
 .btn-group.tree-btn-group
   -# only show edit link for text files
   - if @tree.text?
-    = link_to "edit", edit_project_tree_path(@project, @id), class: "btn very_small", disabled: !allowed_tree_edit?
-  = link_to "raw", project_blob_path(@project, @id), class: "btn very_small", target: "_blank"
+    = link_to "edit", edit_project_tree_path(@project, @id), class: "btn btn-tiny", disabled: !allowed_tree_edit?
+  = link_to "raw", project_blob_path(@project, @id), class: "btn btn-tiny", target: "_blank"
   -# only show normal/blame view links for text files
   - if @tree.text?
     - if current_page? project_blame_path(@project, @id)
-      = link_to "normal view", project_tree_path(@project, @id), class: "btn very_small"
+      = link_to "normal view", project_tree_path(@project, @id), class: "btn btn-tiny"
     - else
-      = link_to "blame", project_blame_path(@project, @id), class: "btn very_small"
-  = link_to "history", project_commits_path(@project, @id), class: "btn very_small"
+      = link_to "blame", project_blame_path(@project, @id), class: "btn btn-tiny"
+  = link_to "history", project_commits_path(@project, @id), class: "btn btn-tiny"
diff --git a/app/views/tree/_head.html.haml b/app/views/tree/_head.html.haml
index f14526cf23a4dbb440c8cb2aa2dd32ea90952b5d..32c3882400eed8d0858d46be2e1c71c38bb6fee7 100644
--- a/app/views/tree/_head.html.haml
+++ b/app/views/tree/_head.html.haml
@@ -3,5 +3,5 @@
     = render partial: 'shared/ref_switcher', locals: {destination: 'tree', path: @path}
   = nav_link(controller: :tree) do
     = link_to 'Source', project_tree_path(@project, @ref)
-  %li.right
+  %li.pull-right
     = render "shared/clone_panel"
diff --git a/app/views/tree/_tree.html.haml b/app/views/tree/_tree.html.haml
index c284295951023e892ee3e69a3db1db2da3eeee56..29a2ed02d31a1398204205eef0db676148188f30 100644
--- a/app/views/tree/_tree.html.haml
+++ b/app/views/tree/_tree.html.haml
@@ -24,7 +24,7 @@
           %th Name
           %th Last Update
           %th Last Commit
-          %th= link_to "history", project_commits_path(@project, @id), class: "btn very_small right"
+          %th= link_to "history", project_commits_path(@project, @id), class: "btn btn-tiny pull-right"
 
       - if tree.up_dir?
         %tr.tree-item
diff --git a/app/views/tree/edit.html.haml b/app/views/tree/edit.html.haml
index adee68a00f8f8955b1f5b9c676714eb133308cb1..81918e509b83c96d1e7215c2d71c56768fdb2102 100644
--- a/app/views/tree/edit.html.haml
+++ b/app/views/tree/edit.html.haml
@@ -10,7 +10,7 @@
             %strong= @ref
         %span.options
           .btn-group.tree-btn-group
-            = link_to "Cancel", project_tree_path(@project, @id), class: "btn very_small cancel-btn", confirm: "Are you sure?"
+            = link_to "Cancel", project_tree_path(@project, @id), class: "btn btn-tiny btn-cancel", confirm: "Are you sure?"
       .file_content.code
         %pre#editor= @tree.data
 
@@ -27,7 +27,7 @@
         .message
           to branch
           %strong= @ref
-      = link_to "Cancel", project_tree_path(@project, @id), class: "btn cancel-btn", confirm: "Are you sure?"
+      = link_to "Cancel", project_tree_path(@project, @id), class: "btn btn-cancel", confirm: "Are you sure?"
 
 :javascript
   var ace_mode = "#{@tree.language.try(:ace_mode)}";
diff --git a/app/views/users/_profile.html.haml b/app/views/users/_profile.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..4981aaba0ac39ac0e9c5963606d08cabd5b5432f
--- /dev/null
+++ b/app/views/users/_profile.html.haml
@@ -0,0 +1,23 @@
+.ui-box
+  %h5.title
+    Profile
+  %ul.well-list
+    %li
+      %strong Email
+      %span.pull-right= mail_to @user.email
+    - unless @user.skype.blank?
+      %li
+        %strong Skype
+        %span.pull-right= @user.skype
+    - unless @user.linkedin.blank?
+      %li
+        %strong LinkedIn
+        %span.pull-right= @user.linkedin
+    - unless @user.twitter.blank?
+      %li
+        %strong Twitter
+        %span.pull-right= @user.twitter
+    - unless @user.bio.blank?
+      %li
+        %strong Bio
+        %span.pull-right= @user.bio
diff --git a/app/views/users/_projects.html.haml b/app/views/users/_projects.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..73f635f3a088f8beff8ec8895db70edee2b8d554
--- /dev/null
+++ b/app/views/users/_projects.html.haml
@@ -0,0 +1,20 @@
+.ui-box
+  %h5.title Projects
+  %ul.well-list
+    - @projects.each do |project|
+      %li
+        = link_to project_path(project), class: dom_class(project) do
+          - if project.namespace
+            = project.namespace.human_name
+            \/
+          %strong.well-title
+            = truncate(project.name, length: 45)
+          %span.pull-right.light
+            - if project.owner == @user
+              %i.icon-wrench
+            - tm = project.team.get_tm(@user.id)
+            - if tm
+              = tm.project_access_human
+%p.light
+  %i.icon-wrench
+  &ndash; user is a project owner
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..969fed9ce537f02d127f8838651ed82d8b7941f4
--- /dev/null
+++ b/app/views/users/show.html.haml
@@ -0,0 +1,21 @@
+.row
+  .span8
+    %h3.page_title
+      = image_tag gravatar_icon(@user.email, 90), class: "avatar s90"
+      = @user.name
+      - if @user == current_user
+        .pull-right
+          = link_to profile_path, class: 'btn btn-small' do
+            %i.icon-edit
+            Edit Profile
+      %br
+      %small @#{@user.username}
+      %br
+      %small member since #{@user.created_at.stamp("Nov 12, 2031")}
+    .clearfix
+    %hr
+    %h5 Recent events
+    = render @events
+  .span4
+    = render 'profile'
+    = render 'projects'
diff --git a/app/views/wikis/_form.html.haml b/app/views/wikis/_form.html.haml
index 9eb2a571fe5c0bef1cc77913c25c534adf3e58b9..7758b129b07aec99ac6a9b88e11f1ae487adb360 100644
--- a/app/views/wikis/_form.html.haml
+++ b/app/views/wikis/_form.html.haml
@@ -23,5 +23,5 @@
       = f.label :content
       .input= f.text_area :content, class: 'span8 js-gfm-input'
   .actions
-    = f.submit 'Save', class: "save-btn btn"
-    = link_to "Cancel", project_wiki_path(@project, :index), class: "btn cancel-btn"
+    = f.submit 'Save', class: "btn-save btn"
+    = link_to "Cancel", project_wiki_path(@project, :index), class: "btn btn-cancel"
diff --git a/app/views/wikis/edit.html.haml b/app/views/wikis/edit.html.haml
index 8f6b457f22a833f6716c148aaf357e03f1ceda95..9e221aba47dfcbb24c1ce8e2f8160c7126221cbe 100644
--- a/app/views/wikis/edit.html.haml
+++ b/app/views/wikis/edit.html.haml
@@ -2,7 +2,7 @@
 %hr
 = render 'form'
 
-.right
+.pull-right
   - if can? current_user, :admin_wiki, @project
-    = link_to project_wiki_path(@project, @wiki), confirm: "Are you sure you want to delete this page?", method: :delete, class: "btn small danger" do
+    = link_to project_wiki_path(@project, @wiki), confirm: "Are you sure you want to delete this page?", method: :delete, class: "btn btn-small btn-remove" do
       Delete this page
\ No newline at end of file
diff --git a/app/views/wikis/show.html.haml b/app/views/wikis/show.html.haml
index d3bd58bbeec2f46363627f95018b1bb5286fc429..7ff8b5cc01ec9e94faaee58d9f74bec4db998542 100644
--- a/app/views/wikis/show.html.haml
+++ b/app/views/wikis/show.html.haml
@@ -1,12 +1,12 @@
 %h3.page_title
   = @wiki.title
-  %span.right
-    = link_to pages_project_wikis_path(@project), class: "btn small grouped" do
+  %span.pull-right
+    = link_to pages_project_wikis_path(@project), class: "btn btn-small grouped" do
       Pages
     - if can? current_user, :write_wiki, @project
-      = link_to history_project_wiki_path(@project, @wiki), class: "btn small grouped" do
+      = link_to history_project_wiki_path(@project, @wiki), class: "btn btn-small grouped" do
         History
-      = link_to edit_project_wiki_path(@project, @wiki), class: "btn small grouped" do
+      = link_to edit_project_wiki_path(@project, @wiki), class: "btn btn-small grouped" do
         %i.icon-edit
         Edit
 %br
diff --git a/app/workers/gitolite_worker.rb b/app/workers/gitolite_worker.rb
new file mode 100644
index 0000000000000000000000000000000000000000..bff7a8c6a6f257a342112f43e9f75a8629617555
--- /dev/null
+++ b/app/workers/gitolite_worker.rb
@@ -0,0 +1,10 @@
+class GitoliteWorker
+  include Sidekiq::Worker
+  include Gitolited
+
+  sidekiq_options queue: :gitolite
+
+  def perform(action, *arg)
+    gitolite.send(action, *arg)
+  end
+end
diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb
index e74379a65dd367dea54d9e52ad4cee9ba0082c9a..6e2d0e7aba22b485c1f6402919a0044b9fdbdc52 100644
--- a/app/workers/post_receive.rb
+++ b/app/workers/post_receive.rb
@@ -4,23 +4,38 @@ class PostReceive
   sidekiq_options queue: :post_receive
 
   def perform(repo_path, oldrev, newrev, ref, identifier)
-    repo_path.gsub!(Gitlab.config.gitolite.repos_path.to_s, "")
+
+    if repo_path.start_with?(Gitlab.config.gitolite.repos_path.to_s)
+      repo_path.gsub!(Gitlab.config.gitolite.repos_path.to_s, "")
+    else
+      Gitlab::GitLogger.error("POST-RECEIVE: Check gitlab.yml config for correct gitolite.repos_path variable. \"#{Gitlab.config.gitolite.repos_path}\" does not match \"#{repo_path}\"")
+    end
+
     repo_path.gsub!(/.git$/, "")
     repo_path.gsub!(/^\//, "")
 
     project = Project.find_with_namespace(repo_path)
-    return false if project.nil?
+
+    if project.nil?
+      Gitlab::GitLogger.error("POST-RECEIVE: Triggered hook for non-existing project with full path \"#{repo_path} \"")
+      return false
+    end
 
     # Ignore push from non-gitlab users
     user = if identifier.eql? Gitlab.config.gitolite.admin_key
-      email = project.repository.commit(newrev).author.email rescue nil
-      User.find_by_email(email) if email
-    elsif /^[A-Z0-9._%a-z\-]+@(?:[A-Z0-9a-z\-]+\.)+[A-Za-z]{2,4}$/.match(identifier)
-      User.find_by_email(identifier)
-    else
-      Key.find_by_identifier(identifier).try(:user)
+             email = project.repository.commit(newrev).author.email rescue nil
+             User.find_by_email(email) if email
+           elsif /^[A-Z0-9._%a-z\-]+@(?:[A-Z0-9a-z\-]+\.)+[A-Za-z]{2,4}$/.match(identifier)
+             User.find_by_email(identifier)
+           elsif identifier =~ /key/
+             key_id = identifier.gsub("key-", "")
+             Key.find_by_id(key_id).try(:user)
+           end
+
+    unless user
+      Gitlab::GitLogger.error("POST-RECEIVE: Triggered hook for non-existing user \"#{identifier} \"")
+      return false
     end
-    return false unless user
 
     project.trigger_post_receive(oldrev, newrev, ref, user)
   end
diff --git a/app/workers/project_web_hook_worker.rb b/app/workers/project_web_hook_worker.rb
new file mode 100644
index 0000000000000000000000000000000000000000..9f9b9b1df5f672249af8397439d2c3eccc2f25c2
--- /dev/null
+++ b/app/workers/project_web_hook_worker.rb
@@ -0,0 +1,9 @@
+class ProjectWebHookWorker
+  include Sidekiq::Worker
+
+  sidekiq_options queue: :project_web_hook
+
+  def perform(hook_id, data)
+    WebHook.find(hook_id).execute data
+  end
+end
diff --git a/config/database.yml.postgresql b/config/database.yml.postgresql
index 0e873d2b8fb45ca5713caa5680f160d2dfd8d166..2bc0884f099beb374a2c20f280636bf093428fd3 100644
--- a/config/database.yml.postgresql
+++ b/config/database.yml.postgresql
@@ -6,7 +6,7 @@ production:
   encoding: unicode
   database: gitlabhq_production
   pool: 5
-  username: postgres
+  username: gitlab
   password:
   # host: localhost
   # port: 5432 
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index b2dccbe3d4c9a4062300d26a3b0ddd9aa3332d07..02118cbd9501ea2d8f59ca81c8799e379fc86a09 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -29,7 +29,7 @@ gitlab:
   # Email address used in the "From" field in mails sent by GitLab
   email_from: gitlab@localhost
 
-  # Email address of your support contanct (default: same as email_from)
+  # Email address of your support contact (default: same as email_from)
   support_email: support@localhost
 
   ## Project settings
@@ -96,7 +96,7 @@ omniauth:
 # GitLab Satellites
 satellites:
   # Relative paths are relative to Rails.root (default: tmp/repo_satellites/)
-  path: /home/gitlab/gitlab-satellites/
+  path: /home/git/gitlab-satellites/
 
 ## Backup settings
 backup:
@@ -105,8 +105,7 @@ backup:
 
 ## Gitolite settings
 gitolite:
-  admin_uri: git@localhost:gitolite-admin
-  # repos_path must not be a symlink
+  # REPOS_PATH MUST NOT BE A SYMLINK!!!
   repos_path: /home/git/repositories/
   hooks_path: /home/git/.gitolite/hooks/
   admin_key: gitlab
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index a1afa5b22c4f434b5fd1ff65ace51c387f7fa307..ebcbbf91636fa74221f409352f708cd68e3d69ad 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -51,7 +51,7 @@ Settings.gitlab['protocol']   ||= Settings.gitlab.https ? "https" : "http"
 Settings.gitlab['email_from'] ||= "gitlab@#{Settings.gitlab.host}"
 Settings.gitlab['support_email']  ||= Settings.gitlab.email_from
 Settings.gitlab['url']        ||= Settings.send(:build_gitlab_url)
-Settings.gitlab['user']       ||= 'gitlab'
+Settings.gitlab['user']       ||= 'git'
 Settings.gitlab['signup_enabled'] ||= false
 
 Settings['gravatar'] ||= Settingslogic.new({})
@@ -63,10 +63,10 @@ Settings['gitolite'] ||= Settingslogic.new({})
 Settings.gitolite['admin_key']    ||= 'gitlab'
 Settings.gitolite['admin_uri']    ||= 'git@localhost:gitolite-admin'
 Settings.gitolite['config_file']  ||= 'gitolite.conf'
-Settings.gitolite['hooks_path']   ||= '/home/git/share/gitolite/hooks/'
+Settings.gitolite['hooks_path']     = File.expand_path(Settings.gitolite['hooks_path'] || '/home/git/share/gitolite/hooks/', Rails.root)
 Settings.gitolite['receive_pack']   = true if Settings.gitolite['receive_pack'].nil?
 Settings.gitolite['upload_pack']    = true if Settings.gitolite['upload_pack'].nil?
-Settings.gitolite['repos_path']   ||= '/home/git/repositories/'
+Settings.gitolite['repos_path']     = File.expand_path(Settings.gitolite['repos_path'] || '/home/git/repositories/', Rails.root)
 Settings.gitolite['ssh_host']     ||= (Settings.gitlab.host || 'localhost')
 Settings.gitolite['ssh_port']     ||= 22
 Settings.gitolite['ssh_user']     ||= 'git'
diff --git a/config/initializers/5_backend.rb b/config/initializers/5_backend.rb
index 85f747ac334033ad1dd464dfc2cfbb60e3da1739..73436608c933aa0b82558f4d2c69d01513571740 100644
--- a/config/initializers/5_backend.rb
+++ b/config/initializers/5_backend.rb
@@ -1,5 +1,5 @@
 # GIT over HTTP
 require Rails.root.join("lib", "gitlab", "backend", "grack_auth")
 
-# GITOLITE backend
-require Rails.root.join("lib", "gitlab", "backend", "gitolite")
+# GIT over SSH
+require Rails.root.join("lib", "gitlab", "backend", "shell")
diff --git a/config/routes.rb b/config/routes.rb
index 00ff3f637521a792ab603588a3cc85ae545a080f..d6432b86007593f4c64199ea63b0bbe134c9474e 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -21,7 +21,7 @@ Gitlab::Application.routes.draw do
     project_root: Gitlab.config.gitolite.repos_path,
     upload_pack:  Gitlab.config.gitolite.upload_pack,
     receive_pack: Gitlab.config.gitolite.receive_pack
-  }), at: '/', constraints: lambda { |request| /[-\/\w\.-]+\.git\//.match(request.path_info) }
+  }), at: '/', constraints: lambda { |request| /[-\/\w\.]+\.git\//.match(request.path_info) }
 
   #
   # Help
@@ -49,13 +49,14 @@ Gitlab::Application.routes.draw do
   # Admin Area
   #
   namespace :admin do
-    resources :users do
+    resources :users, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ } do
       member do
         put :team_update
         put :block
         put :unblock
       end
     end
+
     resources :groups, constraints: { id: /[^\/]+/ } do
       member do
         put :project_update
@@ -63,18 +64,31 @@ Gitlab::Application.routes.draw do
         delete :remove_project
       end
     end
-    resources :projects, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ }, except: [:new, :create] do
-      member do
-        get :team
-        put :team_update
+
+    resources :teams, constraints: { id: /[^\/]+/ } do
+      scope module: :teams do
+        resources :members,   only: [:edit, :update, :destroy, :new, :create]
+        resources :projects,  only: [:edit, :update, :destroy, :new, :create], constraints: { id: /[a-zA-Z.\/0-9_\-]+/ }
       end
     end
-    resources :team_members, only: [:edit, :update, :destroy]
+
     resources :hooks, only: [:index, :create, :destroy] do
       get :test
     end
+
     resource :logs, only: [:show]
     resource :resque, controller: 'resque', only: [:show]
+
+    resources :projects, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ }, except: [:new, :create] do
+      member do
+        get :team
+        put :team_update
+      end
+      scope module: :projects, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ } do
+        resources :members, only: [:edit, :update, :destroy]
+      end
+    end
+
     root to: "dashboard#index"
   end
 
@@ -97,19 +111,25 @@ Gitlab::Application.routes.draw do
   end
 
   resources :keys
+  match "/u/:username" => "users#show", as: :user, constraints: { username: /.*/ }
+
+
 
   #
   # Dashboard Area
   #
-  get "dashboard"                => "dashboard#index"
-  get "dashboard/issues"         => "dashboard#issues"
-  get "dashboard/merge_requests" => "dashboard#merge_requests"
-
+  resource :dashboard, controller: "dashboard" do
+    member do
+      get :projects
+      get :issues
+      get :merge_requests
+    end
+  end
 
   #
   # Groups Area
   #
-  resources :groups, constraints: { id: /[^\/]+/ }, only: [:show] do
+  resources :groups, constraints: { id: /[^\/]+/ }  do
     member do
       get :issues
       get :merge_requests
@@ -119,6 +139,20 @@ Gitlab::Application.routes.draw do
     end
   end
 
+  #
+  # Teams Area
+  #
+  resources :teams, constraints: { id: /[^\/]+/ } do
+    member do
+      get :issues
+      get :merge_requests
+    end
+    scope module: :teams do
+      resources :members,   only: [:index, :new, :create, :edit, :update, :destroy]
+      resources :projects,  only: [:index, :new, :create, :edit, :update, :destroy], constraints: { id: /[a-zA-Z.0-9_\-\/]+/ }
+    end
+  end
+
   resources :projects, constraints: { id: /[^\/]+/ }, only: [:new, :create]
 
   devise_for :users, controllers: { omniauth_callbacks: :omniauth_callbacks, registrations: :registrations }
@@ -129,7 +163,6 @@ Gitlab::Application.routes.draw do
   resources :projects, constraints: { id: /[a-zA-Z.0-9_\-\/]+/ }, except: [:new, :create, :index], path: "/" do
     member do
       get "wall"
-      get "graph"
       get "files"
     end
 
@@ -139,6 +172,7 @@ Gitlab::Application.routes.draw do
     resources :compare, only: [:index, :create]
     resources :blame,   only: [:show], constraints: {id: /.+/}
     resources :blob,    only: [:show], constraints: {id: /.+/}
+    resources :graph,   only: [:show], constraints: {id: /.+/}
     match "/compare/:from...:to" => "compare#show", as: "compare",
                     :via => [:get, :post], constraints: {from: /.+/, to: /.+/}
 
@@ -235,6 +269,18 @@ Gitlab::Application.routes.draw do
       end
     end
 
+    scope module: :projects do
+      resources :teams, only: [] do
+        collection do
+          get :available
+          post :assign
+        end
+        member do
+          delete :resign
+        end
+      end
+    end
+
     resources :notes, only: [:index, :create, :destroy] do
       collection do
         post :preview
@@ -242,5 +288,5 @@ Gitlab::Application.routes.draw do
     end
   end
 
-  root to: "dashboard#index"
+  root to: "dashboard#show"
 end
diff --git a/config/unicorn.rb.example b/config/unicorn.rb.example
index 4852cd65daaddad1b2a8021e994656651bda3a2b..29b7146c7dff736bcf1e16498b4d9815194999c0 100644
--- a/config/unicorn.rb.example
+++ b/config/unicorn.rb.example
@@ -2,7 +2,7 @@
 # note that config/gitlab.yml web path should also be changed
 # ENV['RAILS_RELATIVE_URL_ROOT'] = "/gitlab"
 
-app_dir = "/home/gitlab/gitlab/"
+app_dir = "/home/git/gitlab/"
 worker_processes 2
 working_directory app_dir
 
diff --git a/db/migrate/20121219183753_create_user_teams.rb b/db/migrate/20121219183753_create_user_teams.rb
new file mode 100644
index 0000000000000000000000000000000000000000..65c4d053982cadce45061357bc18b95c89dbf541
--- /dev/null
+++ b/db/migrate/20121219183753_create_user_teams.rb
@@ -0,0 +1,11 @@
+class CreateUserTeams < ActiveRecord::Migration
+  def change
+    create_table :user_teams do |t|
+      t.string :name
+      t.string :path
+      t.integer :owner_id
+
+      t.timestamps
+    end
+  end
+end
diff --git a/db/migrate/20121220064104_create_user_team_project_relationships.rb b/db/migrate/20121220064104_create_user_team_project_relationships.rb
new file mode 100644
index 0000000000000000000000000000000000000000..8eb654c8728ba6d1a06308f2b3253d8b4df7a6c8
--- /dev/null
+++ b/db/migrate/20121220064104_create_user_team_project_relationships.rb
@@ -0,0 +1,11 @@
+class CreateUserTeamProjectRelationships < ActiveRecord::Migration
+  def change
+    create_table :user_team_project_relationships do |t|
+      t.integer :project_id
+      t.integer :user_team_id
+      t.integer :greatest_access
+
+      t.timestamps
+    end
+  end
+end
diff --git a/db/migrate/20121220064453_create_user_team_user_relationships.rb b/db/migrate/20121220064453_create_user_team_user_relationships.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7783b0ae4328ff8d1b1d7958f3708d0b6749a29b
--- /dev/null
+++ b/db/migrate/20121220064453_create_user_team_user_relationships.rb
@@ -0,0 +1,12 @@
+class CreateUserTeamUserRelationships < ActiveRecord::Migration
+  def change
+    create_table :user_team_user_relationships do |t|
+      t.integer :user_id
+      t.integer :user_team_id
+      t.boolean :group_admin
+      t.integer :permission
+
+      t.timestamps
+    end
+  end
+end
diff --git a/db/migrate/20130125090214_add_user_permissions.rb b/db/migrate/20130125090214_add_user_permissions.rb
new file mode 100644
index 0000000000000000000000000000000000000000..38b5f439a2d22687348aacc87ad919c51440ca6f
--- /dev/null
+++ b/db/migrate/20130125090214_add_user_permissions.rb
@@ -0,0 +1,11 @@
+class AddUserPermissions < ActiveRecord::Migration
+  def up
+    add_column :users, :can_create_group, :boolean, default: true, null: false
+    add_column :users, :can_create_team, :boolean, default: true, null: false
+  end
+
+  def down
+    remove_column :users, :can_create_group
+    remove_column :users, :can_create_team
+  end
+end
diff --git a/db/migrate/20130131070232_remove_private_flag_from_project.rb b/db/migrate/20130131070232_remove_private_flag_from_project.rb
new file mode 100644
index 0000000000000000000000000000000000000000..5754db115589d6442a1c5a1bc9991b68c2b8937c
--- /dev/null
+++ b/db/migrate/20130131070232_remove_private_flag_from_project.rb
@@ -0,0 +1,9 @@
+class RemovePrivateFlagFromProject < ActiveRecord::Migration
+  def up
+    remove_column :projects, :private_flag
+  end
+
+  def down
+    add_column :projects, :private_flag, :boolean, default: true, null: false
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 4b3a224360948f006c9ba83bda8cceda11171bb1..0f07d2bc8c54061a309b3b9cdf0a07016a6f62c1 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
 #
 # It's strongly recommended to check this file into your version control system.
 
-ActiveRecord::Schema.define(:version => 20130110172407) do
+ActiveRecord::Schema.define(:version => 20130131070232) do
 
   create_table "events", :force => true do |t|
     t.string   "target_type"
@@ -147,7 +147,6 @@ ActiveRecord::Schema.define(:version => 20130110172407) do
     t.text     "description"
     t.datetime "created_at",                                :null => false
     t.datetime "updated_at",                                :null => false
-    t.boolean  "private_flag",           :default => true,  :null => false
     t.integer  "creator_id"
     t.string   "default_branch"
     t.boolean  "issues_enabled",         :default => true,  :null => false
@@ -213,6 +212,31 @@ ActiveRecord::Schema.define(:version => 20130110172407) do
     t.string "name"
   end
 
+  create_table "user_team_project_relationships", :force => true do |t|
+    t.integer  "project_id"
+    t.integer  "user_team_id"
+    t.integer  "greatest_access"
+    t.datetime "created_at",      :null => false
+    t.datetime "updated_at",      :null => false
+  end
+
+  create_table "user_team_user_relationships", :force => true do |t|
+    t.integer  "user_id"
+    t.integer  "user_team_id"
+    t.boolean  "group_admin"
+    t.integer  "permission"
+    t.datetime "created_at",   :null => false
+    t.datetime "updated_at",   :null => false
+  end
+
+  create_table "user_teams", :force => true do |t|
+    t.string   "name"
+    t.string   "path"
+    t.integer  "owner_id"
+    t.datetime "created_at", :null => false
+    t.datetime "updated_at", :null => false
+  end
+
   create_table "users", :force => true do |t|
     t.string   "email",                  :default => "",    :null => false
     t.string   "encrypted_password",     :default => "",    :null => false
@@ -242,6 +266,8 @@ ActiveRecord::Schema.define(:version => 20130110172407) do
     t.string   "extern_uid"
     t.string   "provider"
     t.string   "username"
+    t.boolean  "can_create_group",       :default => true,  :null => false
+    t.boolean  "can_create_team",        :default => true,  :null => false
   end
 
   add_index "users", ["admin"], :name => "index_users_on_admin"
diff --git a/doc/api/README.md b/doc/api/README.md
index 477429c9fa09a64c8e1d9ef8cd3eddd9c4e139ad..0618db7e369b6e5c11428fce6672d696b05526f1 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -10,7 +10,7 @@ If no, or an invalid, `private_token` is provided then an error message will be
 }
 ```
 
-API requests should be prefixed with `api` and the API version. The API version is equal to the GitLab major version number, which is defined in `lib/api.rb`.
+API requests should be prefixed with `api` and the API version. The API version is defined in `lib/api.rb`.
 
 Example of a valid API request:
 
@@ -32,6 +32,7 @@ When listing resources you can pass the following parameters:
 + [Users](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/users.md)
 + [Session](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/session.md)
 + [Projects](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/projects.md)
++ [Groups](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/groups.md)
 + [Snippets](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/snippets.md)
 + [Repositories](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/repositories.md)
 + [Issues](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/issues.md)
diff --git a/doc/api/groups.md b/doc/api/groups.md
new file mode 100644
index 0000000000000000000000000000000000000000..00a7387c76fb29b9030a22b413f996c207bccdf8
--- /dev/null
+++ b/doc/api/groups.md
@@ -0,0 +1,45 @@
+## List project groups
+
+Get a list of groups. (As user: my groups, as admin: all groups)
+
+```
+GET /groups
+```
+
+```json
+[
+    {
+        "id": 1,
+        "name": "Foobar Group",
+        "path": "foo-bar",
+        "owner_id": 18
+    }
+]
+```
+
+## Details of group
+
+Get all details of a group.
+
+```
+GET /groups/:id
+```
+
+Parameters:
+
++ `id` (required) - The ID of a group
+
+## New group
+
+Create a new project group. Available only for admin
+
+```
+POST /groups
+```
+
+Parameters:
++ `name` (required)                  - Email
++ `path`                             - Password
+
+Will return created group with status `201 Created` on success, or `404 Not found` on fail.
+
diff --git a/doc/api/notes.md b/doc/api/notes.md
index bb33efb8c25dfdbb0f93384a2d4d34f27af5608b..a4ba282607643d6f324c9f8767cf337776c50705 100644
--- a/doc/api/notes.md
+++ b/doc/api/notes.md
@@ -30,6 +30,19 @@ Parameters:
 
 + `id` (required) - The ID of a project
 
+### List merge request notes
+
+Get a list of merge request notes.
+
+```
+GET /projects/:id/merge_requests/:merge_request_id/notes
+```
+
+Parameters:
+
++ `id` (required) - The ID of a project
++ `merge_request_id` (required) - The ID of an merge request
+
 ### List issue notes
 
 Get a list of issue notes.
diff --git a/doc/api/projects.md b/doc/api/projects.md
index 411286750f856b9dfa19425bf4bc0f6432d7e7af..82bb0c0d561068393849c36dcc7fc777f045fabc 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -22,6 +22,8 @@ GET /projects
       "created_at": "2012-05-23T08:00:58Z"
     },
     "private": true,
+    "path": "rails",
+    "path_with_namespace": "rails/rails",
     "issues_enabled": false,
     "merge_requests_enabled": false,
     "wall_enabled": true,
@@ -42,6 +44,8 @@ GET /projects
       "created_at": "2012-05-23T08:00:58Z"
     },
     "private": true,
+    "path": "gitlab",
+    "path_with_namespace": "randx/gitlab",
     "issues_enabled": true,
     "merge_requests_enabled": true,
     "wall_enabled": true,
@@ -78,6 +82,8 @@ Parameters:
     "created_at": "2012-05-23T08:00:58Z"
   },
   "private": true,
+  "path": "gitlab",
+  "path_with_namespace": "randx/gitlab",
   "issues_enabled": true,
   "merge_requests_enabled": true,
   "wall_enabled": true,
diff --git a/doc/api/repositories.md b/doc/api/repositories.md
index 685797ad78d7a71098f2a6c75b611c71f945c5ce..bc6ca70aa50064045cdd836797a07e1a7abbb50c 100644
--- a/doc/api/repositories.md
+++ b/doc/api/repositories.md
@@ -33,7 +33,8 @@ Parameters:
       },
       "authored_date": "2012-06-27T05:51:39-07:00",
       "committed_date": "2012-06-28T03:44:20-07:00"
-    }
+    },
+    "protected": true
   }
 ]
 ```
@@ -73,7 +74,88 @@ Parameters:
     },
     "authored_date": "2012-06-27T05:51:39-07:00",
     "committed_date": "2012-06-28T03:44:20-07:00"
-  }
+  },
+  "protected": true
+}
+```
+
+## Protect a project repository branch
+
+Protect a single project repository branch.
+
+```
+PUT /projects/:id/repository/branches/:branch/protect
+```
+
+Parameters:
+
++ `id` (required) - The ID of a project
++ `branch` (required) - The name of the branch
+
+```json
+{
+  "name": "master",
+  "commit": {
+    "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
+    "parents": [
+      {
+        "id": "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
+      }
+    ],
+    "tree": "46e82de44b1061621357f24c05515327f2795a95",
+    "message": "add projects API",
+    "author": {
+      "name": "John Smith",
+      "email": "john@example.com"
+    },
+    "committer": {
+      "name": "John Smith",
+      "email": "john@example.com"
+    },
+    "authored_date": "2012-06-27T05:51:39-07:00",
+    "committed_date": "2012-06-28T03:44:20-07:00"
+  },
+  "protected": true
+}
+```
+
+## Unprotect a project repository branch
+
+Unprotect a single project repository branch.
+
+```
+PUT /projects/:id/repository/branches/:branch/unprotect
+```
+
+Parameters:
+
++ `id` (required) - The ID of a project
++ `branch` (required) - The name of the branch
+
+```json
+{
+  "name": "master",
+  "commit": {
+    "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
+    "parents": [
+      {
+        "id": "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
+      }
+    ],
+    "tree": "46e82de44b1061621357f24c05515327f2795a95",
+    "message": "add projects API",
+    "author": {
+      "name": "John Smith",
+      "email": "john@example.com"
+    },
+    "committer": {
+      "name": "John Smith",
+      "email": "john@example.com"
+    },
+    "authored_date": "2012-06-27T05:51:39-07:00",
+    "committed_date": "2012-06-28T03:44:20-07:00"
+  },
+  "protected": false
 }
 ```
 
@@ -110,7 +192,8 @@ Parameters:
       },
       "authored_date": "2012-05-28T04:42:42-07:00",
       "committed_date": "2012-05-28T04:42:42-07:00"
-    }
+    },
+    "protected": null
   }
 ]
 ```
diff --git a/doc/api/users.md b/doc/api/users.md
index 200c0e06e0469cbccf76c19341be138619a75a07..b94d7c0f789d56a926b6cdb3f1d35b23af3539be 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -20,6 +20,8 @@ GET /users
     "linkedin": "",
     "twitter": "",
     "dark_scheme": false,
+    "extern_uid": "john.smith",
+    "provider": "provider_name",
     "theme_id": 1
   },
   {
@@ -34,6 +36,8 @@ GET /users
     "linkedin": "",
     "twitter": "",
     "dark_scheme": true,
+    "extern_uid": "jack.smith",
+    "provider": "provider_name",
     "theme_id": 1
   }
 ]
@@ -64,6 +68,8 @@ Parameters:
   "linkedin": "",
   "twitter": "",
   "dark_scheme": false,
+  "extern_uid": "john.smith",
+  "provider": "provider_name",
   "theme_id": 1
 }
 ```
@@ -84,10 +90,47 @@ Parameters:
 + `linkedin`                          - Linkedin
 + `twitter`                           - Twitter account
 + `projects_limit`                    - Number of projects user can create
++ `extern_uid`                        - External UID
++ `provider`                          - External provider name
++ `bio`                               - User's bio
 
 Will return created user with status `201 Created` on success, or `404 Not
 found` on fail.
 
+## User modification
+Modify user. Available only for admin
+
+```
+PUT /users/:id
+```
+
+Parameters:
++ `email`                             - Email
++ `username`                          - Username
++ `name`                              - Name
++ `password`                          - Password
++ `skype`                             - Skype ID
++ `linkedin`                          - Linkedin
++ `twitter`                           - Twitter account
++ `projects_limit`                    - Limit projects wich user can create
++ `extern_uid`                        - External UID
++ `provider`                          - External provider name
++ `bio`                               - User's bio
+
+
+Will return created user with status `200 OK` on success, or `404 Not
+found` on fail.
+
+## User deletion
+Delete user. Available only for admin
+
+```
+DELETE /users/:id
+```
+
+Will return deleted user with status `200 OK` on success, or `404 Not
+found` on fail.
+
 ## Current user
 
 Get currently authenticated user.
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 27c87ec825f737466cca9fe935229b6c7ab39dce..4e9818bcb9ee835204c5381af59e9d6c00917206 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -90,134 +90,75 @@ Install the Bundler Gem:
 
 # 3. System Users
 
-Create a user for Git and Gitolite:
+Create a `git` user for Gitlab:
 
-    sudo adduser \
-      --system \
-      --shell /bin/sh \
-      --gecos 'Git Version Control' \
-      --group \
-      --disabled-password \
-      --home /home/git \
-      git
+    sudo adduser --disabled-login --gecos 'GitLab' git
 
-Create a user for GitLab:
+# 4. GitLab shell
 
-    sudo adduser --disabled-login --gecos 'GitLab' gitlab
-
-    # Add it to the git group
-    sudo usermod -a -G git gitlab
-
-    # Generate the SSH key
-    sudo -u gitlab -H ssh-keygen -q -N '' -t rsa -f /home/gitlab/.ssh/id_rsa
-
-
-# 4. Gitolite
-
-Clone GitLab's fork of the Gitolite source code:
+    # login as git 
+    sudo su git
 
+    # go to home directory 
     cd /home/git
-    sudo -u git -H git clone -b gl-v320 https://github.com/gitlabhq/gitolite.git /home/git/gitolite
-
-Setup Gitolite with GitLab as its admin:
-
-**Important Note:**
-GitLab assumes *full and unshared* control over this Gitolite installation.
-
-    # Add Gitolite scripts to $PATH
-    sudo -u git -H mkdir /home/git/bin
-    sudo -u git -H sh -c 'printf "%b\n%b\n" "PATH=\$PATH:/home/git/bin" "export PATH" >> /home/git/.profile'
-    sudo -u git -H sh -c 'gitolite/install -ln /home/git/bin'
-
-    # Copy the gitlab user's (public) SSH key ...
-    sudo cp /home/gitlab/.ssh/id_rsa.pub /home/git/gitlab.pub
-    sudo chmod 0444 /home/git/gitlab.pub
-
-    # ... and use it as the admin key for the Gitolite setup
-    sudo -u git -H sh -c "PATH=/home/git/bin:$PATH; gitolite setup -pk /home/git/gitlab.pub"
-
-Fix the directory permissions for the configuration directory:
-
-    # Make sure the Gitolite config dir is owned by git
-    sudo chmod 750 /home/git/.gitolite/
-    sudo chown -R git:git /home/git/.gitolite/
 
-Fix the directory permissions for the repositories:
+    # clone gitlab shell
+    git clone https://dzaporozhets@dev.gitlab.org/gitlab/gitlab-shell.git
 
-    # Make sure the repositories dir is owned by git and it stays that way
-    sudo chmod -R ug+rwXs,o-rwx /home/git/repositories/
-    sudo chown -R git:git /home/git/repositories/
+    # setup
+    cd gitlab-shell
+    cp config.yml.example config.yml
+    ./bin/install 
 
 
-## Add domains to list to the list of known hosts
-
-    sudo -u gitlab -H ssh git@localhost
-    sudo -u gitlab -H ssh git@YOUR_DOMAIN_NAME
-    sudo -u gitlab -H ssh git@YOUR_GITOLITE_DOMAIN_NAME
-
-
-## Test if everything works so far
-
-    # Clone the admin repo so SSH adds localhost to known_hosts ...
-    # ... and to be sure your users have access to Gitolite
-    sudo -u gitlab -H git clone git@localhost:gitolite-admin.git /tmp/gitolite-admin
-
-    # If it succeeded without errors you can remove the cloned repo
-    sudo rm -rf /tmp/gitolite-admin
-
-**Important Note:**
-If you can't clone the `gitolite-admin` repository: **DO NOT PROCEED WITH INSTALLATION**!
-Check the [Trouble Shooting Guide](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Trouble-Shooting-Guide)
-and make sure you have followed all of the above steps carefully.
-
 
 # 5. Database
 
-See `doc/install/databases.md`
+To setup the MySQL/PostgreSQL database and dependencies please see [`doc/install/databases.md`](./databases.md) .
 
 
 # 6. GitLab
 
-    # We'll install GitLab into home directory of the user "gitlab"
-    cd /home/gitlab
+    # We'll install GitLab into home directory of the user "git"
+    cd /home/git
 
 ## Clone the Source
 
     # Clone GitLab repository
-    sudo -u gitlab -H git clone https://github.com/gitlabhq/gitlabhq.git gitlab
+    sudo -u git -H git clone https://github.com/gitlabhq/gitlabhq.git gitlab
 
     # Go to gitlab dir 
-    cd /home/gitlab/gitlab
+    cd /home/git/gitlab
    
     # Checkout to stable release
-    sudo -u gitlab -H git checkout 4-0-stable
+    sudo -u git -H git checkout 5-0-stable
 
 **Note:**
-You can change `4-0-stable` to `master` if you want the *bleeding edge* version, but
+You can change `5-0-stable` to `master` if you want the *bleeding edge* version, but
 do so with caution!
 
 ## Configure it
 
-    cd /home/gitlab/gitlab
+    cd /home/git/gitlab
 
     # Copy the example GitLab config
-    sudo -u gitlab -H cp config/gitlab.yml.example config/gitlab.yml
+    sudo -u git -H cp config/gitlab.yml.example config/gitlab.yml
 
     # Make sure to change "localhost" to the fully-qualified domain name of your
     # host serving GitLab where necessary
-    sudo -u gitlab -H vim config/gitlab.yml
+    sudo -u git -H vim config/gitlab.yml
 
     # Make sure GitLab can write to the log/ and tmp/ directories
-    sudo chown -R gitlab log/
-    sudo chown -R gitlab tmp/
+    sudo chown -R git log/
+    sudo chown -R git tmp/
     sudo chmod -R u+rwX  log/
     sudo chmod -R u+rwX  tmp/
 
     # Make directory for satellites
-    sudo -u gitlab -H mkdir /home/gitlab/gitlab-satellites
+    sudo -u git -H mkdir /home/git/gitlab-satellites
 
     # Copy the example Unicorn config
-    sudo -u gitlab -H cp config/unicorn.rb.example config/unicorn.rb
+    sudo -u git -H cp config/unicorn.rb.example config/unicorn.rb
 
 **Important Note:**
 Make sure to edit both files to match your setup.
@@ -225,42 +166,29 @@ Make sure to edit both files to match your setup.
 ## Configure GitLab DB settings
 
     # Mysql
-    sudo -u gitlab cp config/database.yml.mysql config/database.yml
+    sudo -u git cp config/database.yml.mysql config/database.yml
 
     # PostgreSQL
-    sudo -u gitlab cp config/database.yml.postgresql config/database.yml
+    sudo -u git cp config/database.yml.postgresql config/database.yml
 
 Make sure to update username/password in config/database.yml.
 
 ## Install Gems
 
-    cd /home/gitlab/gitlab
+    cd /home/git/gitlab
 
     sudo gem install charlock_holmes --version '0.6.9'
 
     # For MySQL (note, the option says "without")
-    sudo -u gitlab -H bundle install --deployment --without development test postgres
+    sudo -u git -H bundle install --deployment --without development test postgres
 
     # Or for PostgreSQL
-    sudo -u gitlab -H bundle install --deployment --without development test mysql
-
-## Configure Git
-
-GitLab needs to be able to commit and push changes to Gitolite. In order to do
-that Git requires a username and email. (We recommend using the same address
-used for the `email.from` setting in `config/gitlab.yml`)
-
-    sudo -u gitlab -H git config --global user.name "GitLab"
-    sudo -u gitlab -H git config --global user.email "gitlab@localhost"
-
-## Setup GitLab Hooks
+    sudo -u git -H bundle install --deployment --without development test mysql
 
-    sudo cp ./lib/hooks/post-receive /home/git/.gitolite/hooks/common/post-receive
-    sudo chown git:git /home/git/.gitolite/hooks/common/post-receive
 
 ## Initialise Database and Activate Advanced Features
 
-    sudo -u gitlab -H bundle exec rake gitlab:setup RAILS_ENV=production
+    sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production
 
 
 ## Install Init Script
@@ -279,11 +207,11 @@ Make GitLab start on boot:
 
 Check if GitLab and its environment is configured correctly:
 
-    sudo -u gitlab -H bundle exec rake gitlab:env:info RAILS_ENV=production
+    sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
 
 To make sure you didn't miss anything run a more thorough check with:
 
-    sudo -u gitlab -H bundle exec rake gitlab:check RAILS_ENV=production
+    sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
 
 If all items are green, then congratulations on successfully installing GitLab!
 However there are still a few steps left.
@@ -356,7 +284,7 @@ a different host, you can configure its connection string via the
 
 If you are running SSH on a non-standard port, you must change the gitlab user'S SSH config.
     
-    # Add to /home/gitlab/.ssh/config
+    # Add to /home/git/.ssh/config
     host localhost          # Give your setup a name (here: override localhost)
         user git            # Your remote git user
         port 2222           # Your port number
diff --git a/doc/install/structure.md b/doc/install/structure.md
index a67e12cc217d9aafb92e223b5452145731d8c985..f580ea159a2a461d5b7b852229caee786215c1ea 100644
--- a/doc/install/structure.md
+++ b/doc/install/structure.md
@@ -3,37 +3,23 @@
 This is the directory structure you will end up with following the instructions in the Installation Guide.
 
     |-- home
-    |   |-- gitlab
+    |   |-- git
     |       |-- .ssh
     |       |-- gitlab
     |       |-- gitlab-satellites
-    |   |-- git
-    |       |-- .gitolite
-    |       |-- .ssh
-    |       |-- bin
-    |       |-- gitolite
+    |       |-- gitlab-shell
     |       |-- repositories
 
 
-**/home/gitlab/.ssh**
-  Contains the Gitolite admin key GitLab uses to configure Gitolite.
+**/home/git/.ssh**
 
-**/home/gitlab/gitlab**
+**/home/git/gitlab**
   This is where GitLab lives.
 
-**/home/gitlab/gitlab-satellites**
+**/home/git/gitlab-satellites**
   Contains a copy of all repositories with a working tree.
   It's used for merge requests, editing files, etc.
 
-**/home/git/.ssh**
-  Contains the SSH access configuration managed by Gitolite.
-
-**/home/git/bin**
-  Contains Gitolite executables.
-
-**/home/git/gitolite**
-  This is where Gitolite lives.
-
 **/home/git/repositories**
   Holds all your repositories in bare format.
   This is the place Git uses when you pull/push to your projects.
diff --git a/doc/raketasks/maintenance.md b/doc/raketasks/maintenance.md
index ee5a8a3b5fba3fcba50df087526202c4d2f96fca..110dbd161f7b63aa07e3349ad6fdf14452a63e4e 100644
--- a/doc/raketasks/maintenance.md
+++ b/doc/raketasks/maintenance.md
@@ -81,7 +81,7 @@ Config directory owned by git:git? ... yes
 Config directory access is drwxr-x---? ... yes
 Repo base directory exists? ... yes
 Repo base owned by git:git? ... yes
-Repo base access is drwsrws---? ... yes
+Repo base access is drwxrws---? ... yes
 Can clone gitolite-admin? ... yes
 Can commit to gitolite-admin? ... yes
 post-receive hook exists? ... yes
diff --git a/features/admin/teams.feature b/features/admin/teams.feature
new file mode 100644
index 0000000000000000000000000000000000000000..6a15fddcdcc88641b22076cfb041fb54eeeed983
--- /dev/null
+++ b/features/admin/teams.feature
@@ -0,0 +1,70 @@
+Feature: Admin Teams
+  Background:
+    Given I sign in as an admin
+    And Create gitlab user "John"
+
+  Scenario: Create a team
+    When I visit admin teams page
+    And I click new team link
+    And submit form with new team info
+    Then I should be redirected to team page
+    And I should see newly created team
+
+  Scenario: Add user to team
+    When I visit admin teams page
+    When I have clean "HardCoders" team
+    And I visit "HardCoders" team page
+    When I click to "Add members" link
+    When I select user "John" from user list as "Developer"
+    And submit form with new team member info
+    Then I should see "John" in teams members list as "Developer"
+
+  Scenario: Assign team to existing project
+    When I visit admin teams page
+    When I have "HardCoders" team with "John" member with "Developer" role
+    When I have "Shop" project
+    And I visit "HardCoders" team page
+    Then I should see empty projects table
+    When I click to "Add projects" link
+    When I select project "Shop" with max access "Reporter"
+    And submit form with new team project info
+    Then I should see "Shop" project in projects list
+    When I visit "Shop" project admin page
+    Then I should see "John" user with role "Reporter" in team table
+
+  Scenario: Add user to team with ptojects
+    When I visit admin teams page
+    When I have "HardCoders" team with "John" member with "Developer" role
+    And "HardCoders" team assigned to "Shop" project with "Developer" max role access
+    When I have gitlab user "Jimm"
+    And I visit "HardCoders" team page
+    Then I should see members table without "Jimm" member
+    When I click to "Add members" link
+    When I select user "Jimm" ub team members list as "Master"
+    And submit form with new team member info
+    Then I should see "Jimm" in teams members list as "Master"
+
+  Scenario: Remove member from team
+    Given I have users team "HardCoders"
+    And gitlab user "John" is a member "HardCoders" team
+    And gitlab user "Jimm" is a member "HardCoders" team
+    And "HardCoders" team is assigned to "Shop" project
+    When I visit admin teams page
+    When I visit "HardCoders" team admin page
+    Then I shoould see "John" in members list
+    And I should see "Jimm" in members list
+    And I should see "Shop" in projects list
+    When I click on remove "Jimm" user link
+    Then I should be redirected to "HardCoders" team admin page
+    And I should not to see "Jimm" user in members list
+
+  Scenario: Remove project from team
+    Given I have users team "HardCoders"
+    And gitlab user "John" is a member "HardCoders" team
+    And gitlab user "Jimm" is a member "HardCoders" team
+    And "HardCoders" team is assigned to "Shop" project
+    When I visit admin teams page
+    When I visit "HardCoders" team admin page
+    Then I should see "Shop" project in projects list
+    When I click on "Relegate" link on "Shop" project
+    Then I should see projects liston team page without "Shop" project
diff --git a/features/dashboard/dashboard.feature b/features/dashboard/dashboard.feature
index 759843692b88402d0c3223a73d67e5eff94bd6bb..695148b5cdf4a65db0493df92ffa710db762fb4c 100644
--- a/features/dashboard/dashboard.feature
+++ b/features/dashboard/dashboard.feature
@@ -16,12 +16,6 @@ Feature: Dashboard
     And I visit dashboard page
     Then I should see groups list
 
-  Scenario: I should see correct projects count
-    Given I have group with projects
-    And group has a projects that does not belongs to me
-    When I visit dashboard page
-    Then I should see 1 project at group list
-
   Scenario: I should see last push widget
     Then I should see last push widget
     And I click "Create Merge Request" link
diff --git a/features/dashboard/projects.feature b/features/dashboard/projects.feature
new file mode 100644
index 0000000000000000000000000000000000000000..17022dab54fa58cddb341358265226f4557db854
--- /dev/null
+++ b/features/dashboard/projects.feature
@@ -0,0 +1,8 @@
+Feature: Dashboard
+  Background:
+    Given I sign in as a user
+    And I own project "Shop"
+    And I visit dashboard projects page
+
+  Scenario: I should see issues list
+    Then I should see projects list
diff --git a/features/group/create_group.feature b/features/group/create_group.feature
new file mode 100644
index 0000000000000000000000000000000000000000..b77f3599e6a20134bfbc0ff77c86f4287462011b
--- /dev/null
+++ b/features/group/create_group.feature
@@ -0,0 +1,11 @@
+Feature: Groups
+  Background:
+    Given I sign in as a user
+
+  Scenario: Create a group from dasboard
+    Given I have group with projects
+    And I visit dashboard page
+    When I click new group link
+    And submit form with new group info
+    Then I should be redirected to group page
+    And I should see newly created group
diff --git a/features/group/group.feature b/features/group/group.feature
index a4a55a7fc26e5f336ed9de887b99f3b5bff83d41..a48affe8e02ae94c27fe8bb27fc6b68017f370dc 100644
--- a/features/group/group.feature
+++ b/features/group/group.feature
@@ -24,3 +24,9 @@ Feature: Groups
     When I visit group people page
     And I select user "John" from list with role "Reporter"
     Then I should see user "John" in team list
+
+  Scenario: I should see edit group page
+    When I visit group settings page
+    And I change group name
+    Then I should see new group name
+
diff --git a/features/steps/admin/admin_active_tab.rb b/features/steps/admin/admin_active_tab.rb
index 48ec7bac0d648a9846f8283e1b447086878d3a0f..f14c5f396bedbb433e31452be5e6ded96f7e7941 100644
--- a/features/steps/admin/admin_active_tab.rb
+++ b/features/steps/admin/admin_active_tab.rb
@@ -4,7 +4,7 @@ class AdminActiveTab < Spinach::FeatureSteps
   include SharedActiveTab
 
   Then 'the active main tab should be Home' do
-    ensure_active_main_tab('Stats')
+    ensure_active_main_tab('Home')
   end
 
   Then 'the active main tab should be Projects' do
diff --git a/features/steps/admin/admin_teams.rb b/features/steps/admin/admin_teams.rb
new file mode 100644
index 0000000000000000000000000000000000000000..5c66b24bccf6c39776a1d94a56539b28a8ed61b0
--- /dev/null
+++ b/features/steps/admin/admin_teams.rb
@@ -0,0 +1,234 @@
+class AdminTeams < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedPaths
+  include SharedActiveTab
+  include SharedAdmin
+
+  And 'I have own project' do
+    create :project
+  end
+
+  And 'Create gitlab user "John"' do
+    @user = create(:user, :name => "John")
+  end
+
+  And 'I click new team link' do
+    click_link "New Team"
+  end
+
+  And 'submit form with new team info' do
+    fill_in 'user_team_name', with: 'gitlab'
+    click_button 'Create team'
+  end
+
+  Then 'I should be redirected to team page' do
+    current_path.should == admin_team_path(UserTeam.last)
+  end
+
+  And 'I should see newly created team' do
+    page.should have_content "Team: gitlab"
+  end
+
+  When 'I visit admin teams page' do
+    visit admin_teams_path
+  end
+
+  When 'I have clean "HardCoders" team' do
+    @team = create :user_team, name: "HardCoders", owner: current_user
+  end
+
+  And 'I visit "HardCoders" team page' do
+    visit admin_team_path(UserTeam.find_by_name("HardCoders"))
+  end
+
+  Then 'I should see only me in members table' do
+    members_list = find("#members_list .member")
+    members_list.should have_content(current_user.name)
+    members_list.should have_content(current_user.email)
+  end
+
+  When 'I select user "John" from user list as "Developer"' do
+    @user ||= User.find_by_name("John")
+    within "#team_members" do
+      select @user.name, :from => "user_ids"
+      select "Developer", :from => "default_project_access"
+    end
+  end
+
+  And 'submit form with new team member info' do
+    click_button 'add_members_to_team'
+  end
+
+  Then 'I should see "John" in teams members list as "Developer"' do
+    @user ||= User.find_by_name("John")
+    find_in_list("#members_list .member", @user).must_equal true
+  end
+
+  When 'I visit "John" user admin page' do
+    pending 'step not implemented'
+  end
+
+  Then 'I should see "HardCoders" team in teams table' do
+    pending 'step not implemented'
+  end
+
+  When 'I have "HardCoders" team with "John" member with "Developer" role' do
+    @team = create :user_team, name: "HardCoders", owner: current_user
+    @user ||= User.find_by_name("John")
+    @team.add_member(@user, UserTeam.access_roles["Developer"], group_admin: false)
+  end
+
+  When 'I have "Shop" project' do
+    @project = create :project, name: "Shop"
+  end
+
+  Then 'I should see empty projects table' do
+    page.has_no_css?("#projects_list").must_equal true
+  end
+
+  When 'I select project "Shop" with max access "Reporter"' do
+    @project ||= Project.find_by_name("Shop")
+    within "#assign_projects" do
+      select @project.name, :from => "project_ids"
+      select "Reporter", :from => "greatest_project_access"
+    end
+
+  end
+
+  And 'submit form with new team project info' do
+    click_button 'assign_projects_to_team'
+  end
+
+  Then 'I should see "Shop" project in projects list' do
+    project = Project.find_by_name("Shop")
+    find_in_list("#projects_list .project", project).must_equal true
+  end
+
+  When 'I visit "Shop" project admin page' do
+    project = Project.find_by_name("Shop")
+    visit admin_project_path(project)
+  end
+
+  And '"HardCoders" team assigned to "Shop" project with "Developer" max role access' do
+    @team = UserTeam.find_by_name("HardCoders")
+    @project = create :project, name: "Shop"
+    @team.assign_to_project(@project, UserTeam.access_roles["Developer"])
+  end
+
+  When 'I have gitlab user "Jimm"' do
+    create :user, name: "Jimm"
+  end
+
+  Then 'I should see members table without "Jimm" member' do
+    user = User.find_by_name("Jimm")
+    find_in_list("#members_list .member", user).must_equal false
+  end
+
+  When 'I select user "Jimm" ub team members list as "Master"' do
+    user = User.find_by_name("Jimm")
+    within "#team_members" do
+      select user.name, :from => "user_ids"
+      select "Developer", :from => "default_project_access"
+    end
+  end
+
+  Then 'I should see "Jimm" in teams members list as "Master"' do
+    user = User.find_by_name("Jimm")
+    find_in_list("#members_list .member", user).must_equal true
+  end
+
+  Given 'I have users team "HardCoders"' do
+    @team = create :user_team, name: "HardCoders"
+  end
+
+  And 'gitlab user "John" is a member "HardCoders" team' do
+    @team = UserTeam.find_by_name("HardCoders")
+    @user = User.find_by_name("John")
+    @user = create :user, name: "John" unless @user
+    @team.add_member(@user, UserTeam.access_roles["Master"], group_admin: false)
+  end
+
+  And 'gitlab user "Jimm" is a member "HardCoders" team' do
+    @team = UserTeam.find_by_name("HardCoders")
+    @user = User.find_by_name("Jimm")
+    @user = create :user, name: "Jimm" unless @user
+    @team.add_member(@user, UserTeam.access_roles["Master"], group_admin: false)
+  end
+
+  And '"HardCoders" team is assigned to "Shop" project' do
+    @team = UserTeam.find_by_name("HardCoders")
+    @project = create :project, name: "Shop"
+    @team.assign_to_project(@project, UserTeam.access_roles["Developer"])
+  end
+
+  When 'I visit "HardCoders" team admin page' do
+    visit admin_team_path(UserTeam.find_by_name("HardCoders"))
+  end
+
+  Then 'I shoould see "John" in members list' do
+    user = User.find_by_name("John")
+    find_in_list("#members_list .member", user).must_equal true
+  end
+
+  And 'I should see "Jimm" in members list' do
+    user = User.find_by_name("Jimm")
+    find_in_list("#members_list .member", user).must_equal true
+  end
+
+  And 'I should see "Shop" in projects list' do
+    project = Project.find_by_name("Shop")
+    find_in_list("#projects_list .project", project).must_equal true
+  end
+
+  When 'I click on remove "Jimm" user link' do
+    user = User.find_by_name("Jimm")
+    click_link "remove_member_#{user.id}"
+  end
+
+  Then 'I should be redirected to "HardCoders" team admin page' do
+    current_path.should == admin_team_path(UserTeam.find_by_name("HardCoders"))
+  end
+
+  And 'I should not to see "Jimm" user in members list' do
+    user = User.find_by_name("Jimm")
+    find_in_list("#members_list .member", user).must_equal false
+  end
+
+  When 'I click on "Relegate" link on "Shop" project' do
+    project = Project.find_by_name("Shop")
+    click_link "relegate_project_#{project.id}"
+  end
+
+  Then 'I should see projects liston team page without "Shop" project' do
+    project = Project.find_by_name("Shop")
+    find_in_list("#projects_list .project", project).must_equal false
+  end
+
+  Then 'I should see "John" user with role "Reporter" in team table' do
+    user = User.find_by_name("John")
+    find_in_list(".team_members", user).must_equal true
+  end
+
+  When 'I click to "Add members" link' do
+    click_link "Add members"
+  end
+
+  When 'I click to "Add projects" link' do
+    click_link "Add projects"
+  end
+
+  protected
+
+  def current_team
+    @team ||= Team.first
+  end
+
+  def find_in_list(selector, item)
+    members_list = all(selector)
+    entered = false
+    members_list.each do |member_item|
+      entered = true if member_item.has_content?(item.name)
+    end
+    entered
+  end
+end
diff --git a/features/steps/dashboard/dashboard.rb b/features/steps/dashboard/dashboard.rb
index 4bcefba76de71b925defd90fdff8f3314f167974..8c13ad0e151b57366c2cc7e144384a3d63cd5639 100644
--- a/features/steps/dashboard/dashboard.rb
+++ b/features/steps/dashboard/dashboard.rb
@@ -63,6 +63,12 @@ class Dashboard < Spinach::FeatureSteps
     @project.team << [current_user, :master]
   end
 
+  Then 'I should see projects list' do
+    @user.authorized_projects.all.each do |project|
+      page.should have_link project.name_with_namespace
+    end
+  end
+
   Then 'I should see groups list' do
     Group.all.each do |group|
       page.should have_link group.name
diff --git a/features/steps/group/group.rb b/features/steps/group/group.rb
index 04d8c874b3ecd59c08fd539f253fb8c75de1ca3c..5cfa4756ac35e4002176a70a3050853b9ae41283 100644
--- a/features/steps/group/group.rb
+++ b/features/steps/group/group.rb
@@ -64,6 +64,35 @@ class Groups < Spinach::FeatureSteps
       author: current_user
   end
 
+  When 'I click new group link' do
+    click_link "New Group"
+  end
+
+  And 'submit form with new group info' do
+    fill_in 'group_name', :with => 'Samurai'
+    click_button "Create group"
+  end
+
+  Then 'I should see newly created group' do
+    page.should have_content "Samurai"
+    page.should have_content "You will only see events from projects in this group"
+  end
+
+  Then 'I should be redirected to group page' do
+    current_path.should == group_path(Group.last)
+  end
+
+  And 'I change group name' do
+    fill_in 'group_name', :with => 'new-name'
+    click_button "Save group"
+  end
+
+  Then 'I should see new group name' do
+    within ".navbar-gitlab" do
+      page.should have_content "group: new-name"
+    end
+  end
+
   protected
 
   def current_group
diff --git a/features/steps/profile/profile_active_tab.rb b/features/steps/profile/profile_active_tab.rb
index 1924a6fa785bb24b3bd289423d598517fecc79e2..ee9f5f201cfca9509192c15dab16adf906f2baf7 100644
--- a/features/steps/profile/profile_active_tab.rb
+++ b/features/steps/profile/profile_active_tab.rb
@@ -4,7 +4,7 @@ class ProfileActiveTab < Spinach::FeatureSteps
   include SharedActiveTab
 
   Then 'the active main tab should be Home' do
-    ensure_active_main_tab('Profile')
+    ensure_active_main_tab('Home')
   end
 
   Then 'the active main tab should be Account' do
diff --git a/features/steps/project/project_active_tab.rb b/features/steps/project/project_active_tab.rb
index a5c80353862a7f313641f209fcf87b40148b9a6b..bce67c8296233634f54df21951998ebfc4c6d472 100644
--- a/features/steps/project/project_active_tab.rb
+++ b/features/steps/project/project_active_tab.rb
@@ -7,7 +7,7 @@ class ProjectActiveTab < Spinach::FeatureSteps
   # Main Tabs
 
   Then 'the active main tab should be Home' do
-    ensure_active_main_tab(@project.name)
+    ensure_active_main_tab('Home')
   end
 
   Then 'the active main tab should be Files' do
diff --git a/features/steps/project/project_network_graph.rb b/features/steps/project/project_network_graph.rb
index 77149bfe2c32231324a5f2cac7e8768b68f0565e..f26deff9367821611cc01f19cc68434495aa970e 100644
--- a/features/steps/project/project_network_graph.rb
+++ b/features/steps/project/project_network_graph.rb
@@ -14,6 +14,6 @@ class ProjectNetworkGraph < Spinach::FeatureSteps
     Gitlab::Graph::JsonBuilder.stub(max_count: 10)
 
     project = Project.find_by_name("Shop")
-    visit graph_project_path(project)
+    visit project_graph_path(project, "master")
   end
 end
diff --git a/features/steps/project/project_team_management.rb b/features/steps/project/project_team_management.rb
index 91b3ffeee9a85cd3391c740a846f1169e2d36c53..19352fe0ab8224018fe5856ccc2103cc2a81f6ef 100644
--- a/features/steps/project/project_team_management.rb
+++ b/features/steps/project/project_team_management.rb
@@ -24,7 +24,7 @@ class ProjectTeamManagement < Spinach::FeatureSteps
       select user.name, :from => "user_ids"
       select "Reporter", :from => "project_access"
     end
-    click_button "Save"
+    click_button "Add users"
   end
 
   Then 'I should see "Mike" in team list as "Reporter"' do
diff --git a/features/steps/shared/active_tab.rb b/features/steps/shared/active_tab.rb
index 884f2d5fb71b1c8b4cda68b6d589d2947bc11f97..446e3b9a8b3e6589dff7ab5f05e2d5c0e621d749 100644
--- a/features/steps/shared/active_tab.rb
+++ b/features/steps/shared/active_tab.rb
@@ -2,7 +2,11 @@ module SharedActiveTab
   include Spinach::DSL
 
   def ensure_active_main_tab(content)
-    page.find('ul.main_menu li.active').should have_content(content)
+    if content == "Home"
+      page.find('ul.main_menu li.active').should have_css('i.icon-home')
+    else
+      page.find('ul.main_menu li.active').should have_content(content)
+    end
   end
 
   def ensure_active_sub_tab(content)
diff --git a/features/steps/shared/diff_note.rb b/features/steps/shared/diff_note.rb
index 2ae0f1241b8e823b42f9b0f32f657bba44860e07..04862338026cb609c80ac426b1a52fb7fba58b92 100644
--- a/features/steps/shared/diff_note.rb
+++ b/features/steps/shared/diff_note.rb
@@ -2,27 +2,27 @@ module SharedDiffNote
   include Spinach::DSL
 
   Given 'I cancel the diff comment' do
-    within(".diff_file") do
+    within(".file") do
       find(".js-close-discussion-note-form").trigger("click")
     end
   end
 
   Given 'I delete a diff comment' do
     sleep 1
-    within(".diff_file") do
+    within(".file") do
       first(".js-note-delete").trigger("click")
     end
   end
 
   Given 'I haven\'t written any diff comment text' do
-    within(".diff_file") do
+    within(".file") do
       fill_in "note[note]", with: ""
     end
   end
 
   Given 'I leave a diff comment like "Typo, please fix"' do
     find("#586fb7c4e1add2d4d24e27566ed7064680098646_29_14.line_holder .js-add-diff-note-button").trigger("click")
-    within(".diff_file") do
+    within(".file") do
       fill_in "note[note]", with: "Typo, please fix"
       #click_button("Add Comment")
       find(".js-comment-button").trigger("click")
@@ -32,7 +32,7 @@ module SharedDiffNote
 
   Given 'I preview a diff comment text like "Should fix it :smile:"' do
     find("#586fb7c4e1add2d4d24e27566ed7064680098646_29_14.line_holder .js-add-diff-note-button").trigger("click")
-    within(".diff_file") do
+    within(".file") do
       fill_in "note[note]", with: "Should fix it :smile:"
       find(".js-note-preview-button").trigger("click")
     end
@@ -40,7 +40,7 @@ module SharedDiffNote
 
   Given 'I preview another diff comment text like "DRY this up"' do
     find("#586fb7c4e1add2d4d24e27566ed7064680098646_57_41.line_holder .js-add-diff-note-button").trigger("click")
-    within(".diff_file") do
+    within(".file") do
       fill_in "note[note]", with: "DRY this up"
       find(".js-note-preview-button").trigger("click")
     end
@@ -55,13 +55,13 @@ module SharedDiffNote
   end
 
   Given 'I write a diff comment like ":-1: I don\'t like this"' do
-    within(".diff_file") do
+    within(".file") do
       fill_in "note[note]", with: ":-1: I don\'t like this"
     end
   end
 
   Given 'I submit the diff comment' do
-    within(".diff_file") do
+    within(".file") do
       click_button("Add Comment")
     end
   end
@@ -69,49 +69,49 @@ module SharedDiffNote
 
 
   Then 'I should not see the diff comment form' do
-    within(".diff_file") do
+    within(".file") do
       page.should_not have_css("form.new_note")
     end
   end
 
   Then 'I should not see the diff comment preview button' do
-    within(".diff_file") do
+    within(".file") do
       page.should have_css(".js-note-preview-button", visible: false)
     end
   end
 
   Then 'I should not see the diff comment text field' do
-    within(".diff_file") do
+    within(".file") do
       page.should have_css(".js-note-text", visible: false)
     end
   end
 
   Then 'I should only see one diff form' do
-    within(".diff_file") do
+    within(".file") do
       page.should have_css("form.new_note", count: 1)
     end
   end
 
   Then 'I should see a diff comment form with ":-1: I don\'t like this"' do
-    within(".diff_file") do
+    within(".file") do
       page.should have_field("note[note]", with: ":-1: I don\'t like this")
     end
   end
 
   Then 'I should see a diff comment saying "Typo, please fix"' do
-    within(".diff_file .note") do
+    within(".file .note") do
       page.should have_content("Typo, please fix")
     end
   end
 
   Then 'I should see a discussion reply button' do
-    within(".diff_file") do
+    within(".file") do
       page.should have_link("Reply")
     end
   end
 
   Then 'I should see a temporary diff comment form' do
-    within(".diff_file") do
+    within(".file") do
       page.should have_css(".js-temp-notes-holder form.new_note")
     end
   end
@@ -121,37 +121,37 @@ module SharedDiffNote
   end
 
   Then 'I should see an empty diff comment form' do
-    within(".diff_file") do
+    within(".file") do
       page.should have_field("note[note]", with: "")
     end
   end
 
   Then 'I should see the cancel comment button' do
-    within(".diff_file form") do
+    within(".file form") do
       page.should have_css(".js-close-discussion-note-form", text: "Cancel")
     end
   end
 
   Then 'I should see the diff comment preview' do
-    within(".diff_file form") do
+    within(".file form") do
       page.should have_css(".js-note-preview", visible: false)
     end
   end
 
   Then 'I should see the diff comment edit button' do
-    within(".diff_file") do
+    within(".file") do
       page.should have_css(".js-note-edit-button", visible: true)
     end
   end
 
   Then 'I should see the diff comment preview button' do
-    within(".diff_file") do
+    within(".file") do
       page.should have_css(".js-note-preview-button", visible: true)
     end
   end
 
   Then 'I should see two separate previews' do
-    within(".diff_file") do
+    within(".file") do
       page.should have_css(".js-note-preview", visible: true, count: 2)
       page.should have_content("Should fix it")
       page.should have_content("DRY this up")
diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb
index c046c4e63e68f3100b0636bc351029026972f9d1..a8e68012d05adb10fe7ef83e43fdb8581403d8bd 100644
--- a/features/steps/shared/paths.rb
+++ b/features/steps/shared/paths.rb
@@ -25,6 +25,10 @@ module SharedPaths
     visit people_group_path(current_group)
   end
 
+  When 'I visit group settings page' do
+    visit edit_group_path(current_group)
+  end
+
   # ----------------------------------------
   # Dashboard
   # ----------------------------------------
@@ -33,12 +37,16 @@ module SharedPaths
     visit dashboard_path
   end
 
+  Given 'I visit dashboard projects page' do
+    visit projects_dashboard_path
+  end
+
   Given 'I visit dashboard issues page' do
-    visit dashboard_issues_path
+    visit issues_dashboard_path
   end
 
   Given 'I visit dashboard merge requests page' do
-    visit dashboard_merge_requests_path
+    visit merge_requests_dashboard_path
   end
 
   Given 'I visit dashboard search page' do
@@ -105,6 +113,10 @@ module SharedPaths
     visit admin_groups_path
   end
 
+  When 'I visit admin teams page' do
+    visit admin_teams_path
+  end
+
   # ----------------------------------------
   # Generic Project
   # ----------------------------------------
@@ -133,7 +145,7 @@ module SharedPaths
     # Stub Graph::JsonBuilder max_size to speed up test (10 commits vs. 650)
     Gitlab::Graph::JsonBuilder.stub(max_count: 10)
 
-    visit graph_project_path(@project)
+    visit project_graph_path(@project, root_ref)
   end
 
   Given "I visit my project's issues page" do
diff --git a/features/steps/userteams/userteams.rb b/features/steps/userteams/userteams.rb
new file mode 100644
index 0000000000000000000000000000000000000000..be83b4bac05ad9c9bfd0990cd6f385ee8cfa6cea
--- /dev/null
+++ b/features/steps/userteams/userteams.rb
@@ -0,0 +1,254 @@
+class Userteams < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedPaths
+  include SharedProject
+
+    When 'I do not have teams with me' do
+      UserTeam.with_member(current_user).destroy_all
+    end
+
+    Then 'I should see dashboard page without teams info block' do
+      page.has_no_css?(".teams-box").must_equal true
+    end
+
+    When 'I have teams with my membership' do
+      team = create :user_team, owner: current_user
+      team.add_member(current_user, UserTeam.access_roles["Master"], true)
+    end
+
+    Then 'I should see dashboard page with teams information block' do
+      page.should have_css(".teams-box")
+    end
+
+    When 'exist user teams' do
+      team = create :user_team
+      team.add_member(current_user, UserTeam.access_roles["Master"], true)
+    end
+
+    And 'I click on "All teams" link' do
+      click_link("All Teams")
+    end
+
+    Then 'I should see "All teams" page' do
+      current_path.should == teams_path
+    end
+
+    And 'I should see exist teams in teams list' do
+      team = UserTeam.last
+      find_in_list(".teams_list tr", team).must_equal true
+    end
+
+    When 'I click to "New team" link' do
+      click_link("New Team")
+    end
+
+    And 'I submit form with new team info' do
+      fill_in 'name', with: 'gitlab'
+      click_button 'Create team'
+    end
+
+    Then 'I should be redirected to new team page' do
+      team = UserTeam.last
+      current_path.should == team_path(team)
+    end
+
+    When 'I have teams with projects and members' do
+      team = create :user_team, owner: current_user
+      @project = create :project
+      team.add_member(current_user, UserTeam.access_roles["Master"], true)
+      team.assign_to_project(@project, UserTeam.access_roles["Master"])
+      @event = create(:closed_issue_event, project: @project)
+    end
+
+    When 'I visit team page' do
+      visit team_path(UserTeam.last)
+    end
+
+    Then 'I should see projects list' do
+      page.should have_css(".projects_box")
+      projects_box = find(".projects_box")
+      projects_box.should have_content(@project.name)
+    end
+
+    And 'project from team has issues assigned to me' do
+      team = UserTeam.last
+      team.projects.each do |project|
+        project.issues << create(:issue, assignee: current_user)
+      end
+    end
+
+    When 'I visit team issues page' do
+      team = UserTeam.last
+      visit issues_team_path(team)
+    end
+
+    Then 'I should see issues from this team assigned to me' do
+      team = UserTeam.last
+      team.projects.each do |project|
+        project.issues.assigned(current_user).each do |issue|
+          page.should have_content issue.title
+        end
+      end
+    end
+
+    Given 'I have team with projects and members' do
+      team = create :user_team, owner: current_user
+      project = create :project
+      user = create :user
+      team.add_member(current_user, UserTeam.access_roles["Master"], true)
+      team.add_member(user, UserTeam.access_roles["Developer"], false)
+      team.assign_to_project(project, UserTeam.access_roles["Master"])
+    end
+
+    Given 'project from team has issues assigned to teams members' do
+      team = UserTeam.last
+      team.projects.each do |project|
+        team.members.each do |member|
+          project.issues << create(:issue, assignee: member)
+        end
+      end
+    end
+
+    Then 'I should see issues from this team assigned to teams members' do
+      team = UserTeam.last
+      team.projects.each do |project|
+        team.members.each do |member|
+          project.issues.assigned(member).each do |issue|
+            page.should have_content issue.title
+          end
+        end
+      end
+    end
+
+    Given 'project from team has merge requests assigned to me' do
+      team = UserTeam.last
+      team.projects.each do |project|
+        team.members.each do |member|
+          3.times { project.merge_requests << create(:merge_request, assignee: member) }
+        end
+      end
+    end
+
+    When 'I visit team merge requests page' do
+      team = UserTeam.last
+      visit merge_requests_team_path(team)
+    end
+
+    Then 'I should see merge requests from this team assigned to me' do
+      team = UserTeam.last
+      team.projects.each do |project|
+        team.members.each do |member|
+          project.issues.assigned(member).each do |merge_request|
+            page.should have_content merge_request.title
+          end
+        end
+      end
+    end
+
+    Given 'project from team has merge requests assigned to team members' do
+      team = UserTeam.last
+      team.projects.each do |project|
+        team.members.each do |member|
+          3.times { project.merge_requests << create(:merge_request, assignee: member) }
+        end
+      end
+    end
+
+    Then 'I should see merge requests from this team assigned to me' do
+      team = UserTeam.last
+      team.projects.each do |project|
+        team.members.each do |member|
+          project.issues.assigned(member).each do |merge_request|
+            page.should have_content merge_request.title
+          end
+        end
+      end
+    end
+
+    Given 'I have new user "John"' do
+      create :user, name: "John"
+    end
+
+    When 'I visit team people page' do
+      team = UserTeam.last
+      visit team_members_path(team)
+    end
+
+    And 'I select user "John" from list with role "Reporter"' do
+      user = User.find_by_name("John")
+      within "#team_members" do
+        select user.name, :from => "user_ids"
+        select "Reporter", :from => "default_project_access"
+      end
+      click_button "Add"
+    end
+
+    Then 'I should see user "John" in team list' do
+      user = User.find_by_name("John")
+      team_members_list = find(".team-table")
+      team_members_list.should have_content user.name
+    end
+
+    And 'I have my own project without teams' do
+      @project = create :project, namespace: current_user.namespace
+    end
+
+    And 'I visit my team page' do
+      team = UserTeam.where(owner_id: current_user.id).last
+      visit team_path(team)
+    end
+
+    When 'I click on link "Projects"' do
+      click_link "Projects"
+    end
+
+    And 'I click link "Assign project to Team"' do
+      click_link "Assign project to Team"
+    end
+
+    Then 'I should see form with my own project in avaliable projects list' do
+      projects_select = find("#project_ids")
+      projects_select.should have_content(@project.name)
+    end
+
+    When 'I submit form with selected project and max access' do
+      within "#assign_projects" do
+        select @project.name_with_namespace, :from => "project_ids"
+        select "Reporter", :from => "greatest_project_access"
+      end
+      click_button "Add"
+    end
+
+    Then 'I should see my own project in team projects list' do
+      projects = find(".projects-table")
+      projects.should have_content(@project.name)
+    end
+
+    When 'I click link "New Team Member"' do
+      click_link "New Team Member"
+    end
+
+  protected
+
+  def current_team
+    @user_team ||= UserTeam.first
+  end
+
+  def project
+    current_team.projects.first
+  end
+
+  def assigned_to_user key, user
+    project.send(key).where(assignee_id: user)
+  end
+
+  def find_in_list(selector, item)
+    members_list = all(selector)
+    entered = false
+    members_list.each do |member_item|
+      entered = true if member_item.has_content?(item.name)
+    end
+    entered
+  end
+
+end
diff --git a/features/support/env.rb b/features/support/env.rb
index be10ad1b8b9806882fd607ea1384ee23b4f5fa25..c19ca3088cbb0496753710804bc61f96db9ba7c9 100644
--- a/features/support/env.rb
+++ b/features/support/env.rb
@@ -9,19 +9,13 @@ require 'spinach/capybara'
 require 'sidekiq/testing/inline'
 
 
-%w(gitolite_stub stubbed_repository valid_commit).each do |f|
+%w(stubbed_repository valid_commit).each do |f|
   require Rails.root.join('spec', 'support', f)
 end
 
 Dir["#{Rails.root}/features/steps/shared/*.rb"].each {|file| require file}
 
-#
-# Stub gitolite
-#
-include GitoliteStub
-
 WebMock.allow_net_connect!
-
 #
 # JS driver
 #
@@ -50,6 +44,4 @@ Spinach.hooks.before_run do
   RSpec::Mocks::setup self
 
   include FactoryGirl::Syntax::Methods
-
-  stub_gitolite!
 end
diff --git a/features/teams/team.feature b/features/teams/team.feature
new file mode 100644
index 0000000000000000000000000000000000000000..9255e0daadb42ebcd260776dcdc06dd4c2479317
--- /dev/null
+++ b/features/teams/team.feature
@@ -0,0 +1,69 @@
+Feature: UserTeams
+  Background:
+    Given I sign in as a user
+    And I own project "Shop"
+    And project "Shop" has push event
+
+  Scenario: No teams, no dashboard info block
+    When I do not have teams with me
+    And I visit dashboard page
+    Then I should see dashboard page without teams info block
+
+  Scenario: I should see teams info block
+    When I have teams with my membership
+    And I visit dashboard page
+    Then I should see dashboard page with teams information block
+
+  Scenario: I should can create new team
+    When I have teams with my membership
+    And I visit dashboard page
+    When I click to "New team" link
+    And I submit form with new team info
+    Then I should be redirected to new team page
+
+  Scenario: I should see team dashboard list
+    When I have teams with projects and members
+    When I visit team page
+    Then I should see projects list
+
+  Scenario: I should see team issues list
+    Given I have team with projects and members
+    And project from team has issues assigned to me
+    When I visit team issues page
+    Then I should see issues from this team assigned to me
+
+  Scenario: I should see teams members issues list
+    Given I have team with projects and members
+    Given project from team has issues assigned to teams members
+    When I visit team issues page
+    Then I should see issues from this team assigned to teams members
+
+  Scenario: I should see team merge requests list
+    Given I have team with projects and members
+    Given project from team has merge requests assigned to me
+    When I visit team merge requests page
+    Then I should see merge requests from this team assigned to me
+
+  Scenario: I should see teams members merge requests list
+    Given I have team with projects and members
+    Given project from team has merge requests assigned to team members
+    When I visit team merge requests page
+    Then I should see merge requests from this team assigned to me
+
+  Scenario: I should add user to projects in Team
+    Given I have team with projects and members
+    Given I have new user "John"
+    When I visit team people page
+    When I click link "New Team Member"
+    And I select user "John" from list with role "Reporter"
+    Then I should see user "John" in team list
+
+  Scenario: I should assign my team to my own project
+    Given I have team with projects and members
+    And I have my own project without teams
+    And I visit my team page
+    When I click on link "Projects"
+    And I click link "Assign project to Team"
+    Then I should see form with my own project in avaliable projects list
+    When I submit form with selected project and max access
+    Then I should see my own project in team projects list
diff --git a/lib/api.rb b/lib/api.rb
index f58b82ff98ebb99cfba84e027e573937ca3c4ca6..d9dce7c70ccb648f153e6db30cbe87681f11af3a 100644
--- a/lib/api.rb
+++ b/lib/api.rb
@@ -11,7 +11,8 @@ module Gitlab
     format :json
     error_format :json
     helpers APIHelpers
-
+    
+    mount Groups
     mount Users
     mount Projects
     mount Issues
@@ -19,5 +20,6 @@ module Gitlab
     mount Session
     mount MergeRequests
     mount Notes
+    mount Internal
   end
 end
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 80e2954a3448b5d34e8eda720f3fff7a1d88c9d5..c1873d87b55fc9216e6542c21133620fb8a9c65c 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -2,7 +2,7 @@ module Gitlab
   module Entities
     class User < Grape::Entity
       expose :id, :username, :email, :name, :bio, :skype, :linkedin, :twitter,
-             :dark_scheme, :theme_id, :blocked, :created_at
+             :dark_scheme, :theme_id, :blocked, :created_at, :extern_uid, :provider
     end
 
     class UserBasic < Grape::Entity
@@ -21,6 +21,7 @@ module Gitlab
       expose :id, :name, :description, :default_branch
       expose :owner, using: Entities::UserBasic
       expose :private_flag, as: :private
+      expose :path, :path_with_namespace
       expose :issues_enabled, :merge_requests_enabled, :wall_enabled, :wiki_enabled, :created_at
       expose :namespace
     end
@@ -31,8 +32,22 @@ module Gitlab
       end
     end
 
+    class Group < Grape::Entity
+      expose :id, :name, :path, :owner_id
+    end
+    
+    class GroupDetail < Group
+      expose :projects, using: Entities::Project
+    end
+
+    
     class RepoObject < Grape::Entity
       expose :name, :commit
+      expose :protected do |repo, options|
+        if options[:project]
+          options[:project].protected_branch? repo.name
+        end
+      end
     end
 
     class RepoCommit < Grape::Entity
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a67caef0bc56f7b348fc7af1e3f5238af49cfbfa
--- /dev/null
+++ b/lib/api/groups.rb
@@ -0,0 +1,56 @@
+module Gitlab
+  # groups API
+  class Groups < Grape::API
+    before { authenticate! }
+
+    resource :groups do
+      # Get a groups list
+      #
+      # Example Request:
+      #  GET /groups
+      get do
+        if current_user.admin
+          @groups = paginate Group
+        else
+          @groups = paginate current_user.groups
+        end
+        present @groups, with: Entities::Group
+      end
+
+      # Create group. Available only for admin
+      #
+      # Parameters:
+      #   name (required)                   - Name
+      #   path (required)                   - Path
+      # Example Request:
+      #   POST /groups
+      post do
+        authenticated_as_admin!
+        attrs = attributes_for_keys [:name, :path]
+        @group = Group.new(attrs)
+        @group.owner = current_user
+
+        if @group.save
+          present @group, with: Entities::Group
+        else
+          not_found!
+        end
+      end
+
+      # Get a single group, with containing projects
+      #
+      # Parameters:
+      #   id (required) - The ID of a group
+      # Example Request:
+      #   GET /groups/:id
+      get ":id" do
+        @group = Group.find(params[:id])
+        if current_user.admin or current_user.groups.include? @group
+          present @group, with: Entities::GroupDetail
+        else
+          not_found!
+        end
+      end
+    end
+  end
+end
diff --git a/lib/api/internal.rb b/lib/api/internal.rb
new file mode 100644
index 0000000000000000000000000000000000000000..3e5e3a478ba1d34176ac197ecd2007f73820b5ee
--- /dev/null
+++ b/lib/api/internal.rb
@@ -0,0 +1,49 @@
+module Gitlab
+  # Internal access API
+  class Internal < Grape::API
+    namespace 'internal' do
+      #
+      # Check if ssh key has access to project code
+      #
+      get "/allowed" do
+        key = Key.find(params[:key_id])
+        project = Project.find_with_namespace(params[:project])
+        git_cmd = params[:action]
+
+        if key.is_deploy_key
+          project == key.project && git_cmd == 'git-upload-pack'
+        else
+          user = key.user
+          action = case git_cmd
+                   when 'git-upload-pack'
+                     then :download_code
+                   when 'git-receive-pack'
+                     then
+                     if project.protected_branch?(params[:ref])
+                       :push_code_to_protected_branches
+                     else
+                       :push_code
+                     end
+                   end
+
+          user.can?(action, project)
+        end
+      end
+
+      #
+      # Discover user by ssh key
+      #
+      get "/discover" do
+        key = Key.find(params[:key_id])
+        present key.user, with: Entities::User
+      end
+
+      get "/check" do
+        {
+          api_version: '3'
+        }
+      end
+    end
+  end
+end
+
diff --git a/lib/api/notes.rb b/lib/api/notes.rb
index 4613db54578ad8de224297566c2b27bdd099a2ec..70344d6e3813a2098f14f9f30dd6428375491de8 100644
--- a/lib/api/notes.rb
+++ b/lib/api/notes.rb
@@ -3,7 +3,7 @@ module Gitlab
   class Notes < Grape::API
     before { authenticate! }
 
-    NOTEABLE_TYPES = [Issue, Snippet]
+    NOTEABLE_TYPES = [Issue, MergeRequest, Snippet]
 
     resource :projects do
       # Get a list of project wall notes
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index cbef1ed3b5071719134279616d0ef14ba3b0b602..a16243aa8228d34cbb69ad0ab9789b446e4ffb0d 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -218,7 +218,7 @@ module Gitlab
       # Example Request:
       #   GET /projects/:id/repository/branches
       get ":id/repository/branches" do
-        present user_project.repo.heads.sort_by(&:name), with: Entities::RepoObject
+        present user_project.repo.heads.sort_by(&:name), with: Entities::RepoObject, project: user_project
       end
 
       # Get a single branch
@@ -230,7 +230,43 @@ module Gitlab
       #   GET /projects/:id/repository/branches/:branch
       get ":id/repository/branches/:branch" do
         @branch = user_project.repo.heads.find { |item| item.name == params[:branch] }
-        present @branch, with: Entities::RepoObject
+        present @branch, with: Entities::RepoObject, project: user_project
+      end
+
+      # Protect a single branch
+      #
+      # Parameters:
+      #   id (required) - The ID of a project
+      #   branch (required) - The name of the branch
+      # Example Request:
+      #   PUT /projects/:id/repository/branches/:branch/protect
+      put ":id/repository/branches/:branch/protect" do
+        @branch = user_project.repo.heads.find { |item| item.name == params[:branch] }
+        protected = user_project.protected_branches.find_by_name(@branch.name)
+
+        unless protected
+          user_project.protected_branches.create(:name => @branch.name)
+        end
+
+        present @branch, with: Entities::RepoObject, project: user_project
+      end
+
+      # Unprotect a single branch
+      #
+      # Parameters:
+      #   id (required) - The ID of a project
+      #   branch (required) - The name of the branch
+      # Example Request:
+      #   PUT /projects/:id/repository/branches/:branch/unprotect
+      put ":id/repository/branches/:branch/unprotect" do
+        @branch = user_project.repo.heads.find { |item| item.name == params[:branch] }
+        protected = user_project.protected_branches.find_by_name(@branch.name)
+
+        if protected
+          protected.destroy
+        end
+
+        present @branch, with: Entities::RepoObject, project: user_project
       end
 
       # Get a project repository tags
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 140c20f6bd21cb8e6cb54e3d5852b8d409074aac..7ea90c75e9ee6732321c1e13b60e847edf98e211 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -34,11 +34,14 @@ module Gitlab
       #   linkedin                          - Linkedin
       #   twitter                           - Twitter account
       #   projects_limit                    - Number of projects user can create
+      #   extern_uid                        - External authentication provider UID
+      #   provider                          - External provider
+      #   bio                               - Bio
       # Example Request:
       #   POST /users
       post do
         authenticated_as_admin!
-        attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username]
+        attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio]
         user = User.new attrs, as: :admin
         if user.save
           present user, with: Entities::User
@@ -46,6 +49,48 @@ module Gitlab
           not_found!
         end
       end
+
+      # Update user. Available only for admin
+      #
+      # Parameters:
+      #   email                             - Email
+      #   name                              - Name
+      #   password                          - Password
+      #   skype                             - Skype ID
+      #   linkedin                          - Linkedin
+      #   twitter                           - Twitter account
+      #   projects_limit                    - Limit projects wich user can create
+      #   extern_uid                        - External authentication provider UID
+      #   provider                          - External provider
+      #   bio                               - Bio
+      # Example Request:
+      #   PUT /users/:id
+      put ":id" do
+        authenticated_as_admin!
+        attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio]
+        user = User.find_by_id(params[:id])
+
+        if user && user.update_attributes(attrs)
+          present user, with: Entities::User
+        else
+          not_found!
+        end
+      end
+
+      # Delete user. Available only for admin
+      #
+      # Example Request:
+      #   DELETE /users/:id
+      delete ":id" do
+        authenticated_as_admin!
+        user = User.find_by_id(params[:id])
+
+        if user
+          user.destroy
+        else
+          not_found!
+        end
+      end
     end
 
     resource :user do
diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb
index 270a0aaa87ac260df33655d76394af802a47948e..976ac01820429b285a215200e42e7e7641bfeae7 100644
--- a/lib/extracts_path.rb
+++ b/lib/extracts_path.rb
@@ -50,11 +50,14 @@ module ExtractsPath
 
     return pair unless @project
 
+    # Remove relative_url_root from path
+    input.gsub!(/^#{Gitlab.config.gitlab.relative_url_root}/, "")
     # Remove project, actions and all other staff from path
     input.gsub!(/^\/#{Regexp.escape(@project.path_with_namespace)}/, "")
-    input.gsub!(/^\/(tree|commits|blame|blob|refs)\//, "") # remove actions
+    input.gsub!(/^\/(tree|commits|blame|blob|refs|graph)\//, "") # remove actions
     input.gsub!(/\?.*$/, "") # remove stamps suffix
     input.gsub!(/.atom$/, "") # remove rss feed
+    input.gsub!(/.json$/, "") # remove json suffix
     input.gsub!(/\/edit$/, "") # remove edit route part
 
     if input.match(/^([[:alnum:]]{40})(.+)/)
diff --git a/lib/gitlab/backend/gitolite.rb b/lib/gitlab/backend/gitolite.rb
deleted file mode 100644
index 3b8a2090f737a072d1fe9c984e609a842bdaa836..0000000000000000000000000000000000000000
--- a/lib/gitlab/backend/gitolite.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-require_relative 'gitolite_config'
-
-module Gitlab
-  class Gitolite
-    class AccessDenied < StandardError; end
-
-    def config
-      Gitlab::GitoliteConfig.new
-    end
-
-    def set_key key_id, key_content, projects
-      config.apply do |config|
-        config.write_key(key_id, key_content)
-        config.update_projects(projects)
-      end
-    end
-
-    def remove_key key_id, projects
-      config.apply do |config|
-        config.rm_key(key_id)
-        config.update_projects(projects)
-      end
-    end
-
-    def update_repository project
-      config.update_project!(project)
-    end
-
-    def move_repository(old_repo, project)
-      config.apply do |config|
-        config.clean_repo(old_repo)
-        config.update_project(project)
-      end
-    end
-
-    def remove_repository project
-      config.destroy_project!(project)
-    end
-
-    def url_to_repo path
-      Gitlab.config.gitolite.ssh_path_prefix + "#{path}.git"
-    end
-
-    def enable_automerge
-      config.admin_all_repo!
-    end
-
-    def update_repositories projects
-      config.apply do |config|
-        config.update_projects(projects)
-      end
-    end
-
-    alias_method :create_repository, :update_repository
-  end
-end
diff --git a/lib/gitlab/backend/gitolite_config.rb b/lib/gitlab/backend/gitolite_config.rb
deleted file mode 100644
index 7d59ddae0c85bc74697866437d2c0f60b7082ff9..0000000000000000000000000000000000000000
--- a/lib/gitlab/backend/gitolite_config.rb
+++ /dev/null
@@ -1,242 +0,0 @@
-require 'gitolite'
-require 'timeout'
-require 'fileutils'
-
-module Gitlab
-  class GitoliteConfig
-    class PullError < StandardError; end
-    class PushError < StandardError; end
-    class BrokenGitolite < StandardError; end
-
-    attr_reader :config_tmp_dir, :ga_repo, :conf
-
-    def config_tmp_dir
-      @config_tmp_dir ||= Rails.root.join('tmp',"gitlabhq-gitolite-#{Time.now.to_i}")
-    end
-
-    def ga_repo
-      @ga_repo ||= ::Gitolite::GitoliteAdmin.new(
-        File.join(config_tmp_dir,'gitolite'),
-        conf: Gitlab.config.gitolite.config_file
-      )
-    end
-
-    def apply
-      Timeout::timeout(30) do
-        File.open(Rails.root.join('tmp', "gitlabhq-gitolite.lock"), "w+") do |f|
-          begin
-            # Set exclusive lock
-            # to prevent race condition
-            f.flock(File::LOCK_EX)
-
-            # Pull gitolite-admin repo
-            # in tmp dir before do any changes
-            pull(config_tmp_dir)
-
-            # Build ga_repo object and @conf
-            # to access gitolite-admin configuration
-            @conf = ga_repo.config
-
-            # Do any changes
-            # in gitolite-admin
-            # config here
-            yield(self)
-
-            # Save changes in
-            # gitolite-admin repo
-            # before push it
-            ga_repo.save
-
-            # Push gitolite-admin repo
-            # to apply all changes
-            push(config_tmp_dir)
-          ensure
-            # Remove tmp dir
-            # removing the gitolite folder first is important to avoid
-            # NFS issues.
-            FileUtils.rm_rf(File.join(config_tmp_dir, 'gitolite'))
-
-            # Remove parent tmp dir
-            FileUtils.rm_rf(config_tmp_dir)
-
-            # Unlock so other task can access
-            # gitolite configuration
-            f.flock(File::LOCK_UN)
-          end
-        end
-      end
-    rescue PullError => ex
-      log("Pull error ->  " + ex.message)
-      raise Gitolite::AccessDenied, ex.message
-
-    rescue PushError => ex
-      log("Push error ->  " + " " + ex.message)
-      raise Gitolite::AccessDenied, ex.message
-
-    rescue BrokenGitolite => ex
-      log("Gitolite error ->  " + " " + ex.message)
-      raise Gitolite::AccessDenied, ex.message
-
-    rescue Exception => ex
-      log(ex.class.name + " " + ex.message)
-      raise Gitolite::AccessDenied.new("gitolite timeout")
-    end
-
-    def log message
-      Gitlab::GitLogger.error(message)
-    end
-
-    def destroy_project(project)
-      FileUtils.rm_rf(project.repository.path_to_repo)
-      conf.rm_repo(project.path_with_namespace)
-    end
-
-    def clean_repo repo_name
-      conf.rm_repo(repo_name)
-    end
-
-    def destroy_project!(project)
-      apply do |config|
-        config.destroy_project(project)
-      end
-    end
-
-    def write_key(id, key)
-      File.open(File.join(config_tmp_dir, 'gitolite/keydir',"#{id}.pub"), 'w') do |f|
-        f.write(key.gsub(/\n/,''))
-      end
-    end
-
-    def rm_key(user)
-      key_path = File.join(config_tmp_dir, 'gitolite/keydir', "#{user}.pub")
-      ga_key = ::Gitolite::SSHKey.from_file(key_path)
-      ga_repo.rm_key(ga_key)
-    end
-
-    # update or create
-    def update_project(project)
-      repo = update_project_config(project, conf)
-      conf.add_repo(repo, true)
-    end
-
-    def update_project!( project)
-      apply do |config|
-        config.update_project(project)
-      end
-    end
-
-    # Updates many projects and uses project.path_with_namespace as the repo path
-    # An order of magnitude faster than update_project
-    def update_projects(projects)
-      projects.each do |project|
-        repo = update_project_config(project, conf)
-        conf.add_repo(repo, true)
-      end
-    end
-
-    def update_project_config(project, conf)
-      repo_name = project.path_with_namespace
-
-      repo = if conf.has_repo?(repo_name)
-               conf.get_repo(repo_name)
-             else
-               ::Gitolite::Config::Repo.new(repo_name)
-             end
-
-      name_readers = project.team.repository_readers
-      name_writers = project.team.repository_writers
-      name_masters = project.team.repository_masters
-
-      pr_br = project.protected_branches.map(&:name).join("$ ")
-
-      repo.clean_permissions
-
-      # Deny access to protected branches for writers
-      unless name_writers.blank? || pr_br.blank?
-        repo.add_permission("-", pr_br.strip + "$ ", name_writers)
-      end
-
-      # Add read permissions
-      repo.add_permission("R", "", name_readers) unless name_readers.blank?
-
-      # Add write permissions
-      repo.add_permission("RW+", "", name_writers) unless name_writers.blank?
-      repo.add_permission("RW+", "", name_masters) unless name_masters.blank?
-
-      # Add sharedRepository config
-      repo.set_git_config("core.sharedRepository", "0660")
-
-      repo
-    end
-
-    # Enable access to all repos for gitolite admin.
-    # We use it for accept merge request feature
-    def admin_all_repo
-      owner_name = Gitlab.config.gitolite.admin_key
-
-      # @ALL repos premission for gitolite owner
-      repo_name = "@all"
-      repo = if conf.has_repo?(repo_name)
-               conf.get_repo(repo_name)
-             else
-               ::Gitolite::Config::Repo.new(repo_name)
-             end
-
-      repo.add_permission("RW+", "", owner_name)
-      conf.add_repo(repo, true)
-    end
-
-    def admin_all_repo!
-      apply { |config| config.admin_all_repo }
-    end
-
-    private
-
-    def pull tmp_dir
-      Dir.mkdir tmp_dir
-      `git clone #{Gitlab.config.gitolite.admin_uri} #{tmp_dir}/gitolite`
-
-      unless File.exists?(File.join(tmp_dir, 'gitolite', 'conf', 'gitolite.conf'))
-        raise PullError, "unable to clone gitolite-admin repo"
-      end
-    end
-
-    def push tmp_dir
-      output, status = popen('git add -A')
-      raise "Git add failed." unless status.zero?
-
-      # git commit returns 0 on success, and 1 if there is nothing to commit
-      output, status = popen('git commit -m "GitLab"')
-      raise "Git add failed." unless [0,1].include?(status)
-
-      output, status = popen('git push')
-
-      if output =~ /remote\: FATAL/
-        raise BrokenGitolite, output
-      end
-
-      if status.zero? || output =~ /Everything up\-to\-date/
-        return true
-      else
-        raise PushError, "unable to push gitolite-admin repo"
-      end
-    end
-
-    def popen(cmd)
-      path = File.join(config_tmp_dir,'gitolite')
-      vars = { "PWD" => path }
-      options = { :chdir => path }
-
-      @cmd_output = ""
-      @cmd_status = 0
-      Open3.popen3(vars, cmd, options) do |stdin, stdout, stderr, wait_thr|
-        @cmd_status = wait_thr.value.exitstatus
-        @cmd_output << stdout.read
-        @cmd_output << stderr.read
-      end
-
-      return @cmd_output, @cmd_status
-    end
-  end
-end
-
diff --git a/lib/gitlab/backend/shell.rb b/lib/gitlab/backend/shell.rb
new file mode 100644
index 0000000000000000000000000000000000000000..50ebfc5b07c0c96c5b7769c149d7c5a84c077db0
--- /dev/null
+++ b/lib/gitlab/backend/shell.rb
@@ -0,0 +1,50 @@
+module Gitlab
+  class Shell
+    class AccessDenied < StandardError; end
+
+    # Init new repository
+    #
+    # name - project path with namespace
+    #
+    # Ex.
+    #   add_repository("gitlab/gitlab-ci")
+    #
+    def add_repository(name)
+      system("/home/git/gitlab-shell/bin/gitlab-projects add-project #{name}.git")
+    end
+
+    # Remove repository from file system
+    #
+    # name - project path with namespace
+    #
+    # Ex.
+    #   remove_repository("gitlab/gitlab-ci")
+    #
+    def remove_repository(name)
+      system("/home/git/gitlab-shell/bin/gitlab-projects rm-project #{name}.git")
+    end
+
+    # Add new key to gitlab-shell
+    #
+    # Ex.
+    #   add_key("key-42", "sha-rsa ...")
+    #
+    def add_key(key_id, key_content)
+      system("/home/git/gitlab-shell/bin/gitlab-keys add-key #{key_id} \"#{key_content}\"")
+    end
+
+    # Remove ssh key from gitlab shell
+    #
+    # Ex.
+    #   remove_key("key-342", "sha-rsa ...")
+    #
+    def remove_key(key_id, key_content)
+      system("/home/git/gitlab-shell/bin/gitlab-keys rm-key #{key_id} \"#{key_content}\"")
+    end
+
+
+    def url_to_repo path
+      Gitlab.config.gitolite.ssh_path_prefix + "#{path}.git"
+    end
+  end
+end
diff --git a/lib/gitlab/graph/commit.rb b/lib/gitlab/graph/commit.rb
index a6bf23a2381899c396895c7ee101bd4eb948aa49..13c8ebc9952b32b1f7f708f8490639e0be9ce3a8 100644
--- a/lib/gitlab/graph/commit.rb
+++ b/lib/gitlab/graph/commit.rb
@@ -5,12 +5,13 @@ module Gitlab
     class Commit
       include ActionView::Helpers::TagHelper
 
-      attr_accessor :time, :space, :refs
+      attr_accessor :time, :space, :refs, :parent_spaces
 
       def initialize(commit)
         @_commit = commit
         @time = -1
         @space = 0
+        @parent_spaces = []
       end
 
       def method_missing(m, *args, &block)
@@ -28,6 +29,7 @@ module Gitlab
         }
         h[:time]    = time
         h[:space]   = space
+        h[:parent_spaces]   = parent_spaces
         h[:refs]    = refs.collect{|r|r.name}.join(" ") unless refs.nil?
         h[:id]      = sha
         h[:date]    = date
diff --git a/lib/gitlab/graph/json_builder.rb b/lib/gitlab/graph/json_builder.rb
index 4a48b3b5675d4ce91fc8e90be88d50558088c649..4b3687e06c36f48abe9718c6daab736629544865 100644
--- a/lib/gitlab/graph/json_builder.rb
+++ b/lib/gitlab/graph/json_builder.rb
@@ -9,8 +9,9 @@ module Gitlab
         @max_count ||= 650
       end
 
-      def initialize project
+      def initialize project, ref
         @project = project
+        @ref = ref
         @repo = project.repo
         @ref_cache = {}
 
@@ -52,7 +53,7 @@ module Gitlab
       #
       # @return [Array<TimeDate>] list of commit dates corelated with time on commits
       def index_commits
-        days, heads = [], []
+        days, heads, times = [], [], []
         map = {}
 
         commits.reverse.each_with_index do |c,i|
@@ -60,14 +61,15 @@ module Gitlab
           days[i] = c.committed_date
           map[c.id] = c
           heads += c.refs unless c.refs.nil?
+          times[i] = c
         end
 
         heads.select!{|h| h.is_a? Grit::Head or h.is_a? Grit::Remote}
         # sort heads so the master is top and current branches are closer
         heads.sort! do |a,b|
-          if a.name == "master"
+          if a.name == @ref
             -1
-          elsif b.name == "master"
+          elsif b.name == @ref
             1
           else
             b.commit.committed_date <=> a.commit.committed_date
@@ -85,9 +87,62 @@ module Gitlab
           end
         end
 
+        # find parent spaces for not overlap lines
+        times.each do |c|
+          c.parent_spaces.concat(find_free_parent_spaces(c, map, times))
+        end
+
         days
       end
 
+      def find_free_parent_spaces(commit, map, times)
+        spaces = []
+
+        commit.parents.each do |p|
+          if map.include?(p.id) then
+            parent = map[p.id]
+
+            range = if commit.time < parent.time then
+                      commit.time..parent.time
+                    else
+                      parent.time..commit.time
+                    end
+
+            space = if commit.space >= parent.space then
+                      find_free_parent_space(range, parent.space, 1, commit.space, times)
+                    else
+                      find_free_parent_space(range, parent.space, -1, parent.space, times)
+                    end
+
+            mark_reserved(range, space)
+            spaces << space
+          end
+        end
+
+        spaces
+      end
+
+      def find_free_parent_space(range, space_base, space_step, space_default, times)
+        if is_overlap?(range, times, space_default) then
+          find_free_space(range, space_base, space_step)
+        else
+          space_default
+        end
+      end
+
+      def is_overlap?(range, times, overlap_space)
+        range.each do |i|
+          if i != range.first &&
+            i != range.last &&
+            times[i].space == overlap_space then
+
+            return true;
+          end
+        end
+
+        false
+      end
+
       # Add space mark on commit and its parents
       #
       # @param [Graph::Commit] the commit object.
@@ -97,10 +152,9 @@ module Gitlab
         if leaves.empty?
           return
         end
-        space = find_free_space(leaves, map)
-        leaves.each{|l| l.space = space}
         # and mark it as reserved
         min_time = leaves.last.time
+        max_space = 1
         parents = leaves.last.parents.collect
         parents.each do |p|
           if map.include? p.id
@@ -108,6 +162,9 @@ module Gitlab
             if parent.time < min_time
               min_time = parent.time
             end
+            if max_space < parent.space then
+              max_space = parent.space
+            end
           end
         end
         if parent_time.nil?
@@ -115,6 +172,11 @@ module Gitlab
         else
           max_time = parent_time - 1
         end
+
+        time_range = leaves.last.time..leaves.first.time
+        space = find_free_space(time_range, max_space, 2)
+        leaves.each{|l| l.space = space}
+
         mark_reserved(min_time..max_time, space)
 
         # Visit branching chains
@@ -132,27 +194,23 @@ module Gitlab
         end
       end
 
-      def find_free_space(leaves, map)
-        time_range = leaves.last.time..leaves.first.time
+      def find_free_space(time_range, space_base, space_step)
         reserved = []
         for day in time_range
           reserved += @_reserved[day]
         end
-        space = base_space(leaves, map)
-        while reserved.include? space do
-          space += 1
-        end
-        space
-      end
-
-      def base_space(leaves, map)
-        parents = []
-        leaves.each do |l|
-          parents.concat l.parents.collect.select{|p| map.include? p.id and map[p.id].space.nonzero?}
+        reserved.uniq!
+
+        space = space_base
+        while reserved.include?(space) do
+          space += space_step
+          if space <= 0 then
+            space_step *= -1
+            space = space_base + space_step
+          end
         end
 
-        space = parents.map{|p| map[p.id].space}.max || 0
-        space += 1
+        space
       end
 
       # Takes most left subtree branch of commits
diff --git a/lib/gitlab/popen.rb b/lib/gitlab/popen.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f2cfd8073e3c8b602d056330073fdef37b963542
--- /dev/null
+++ b/lib/gitlab/popen.rb
@@ -0,0 +1,18 @@
+module Gitlab
+  module Popen
+    def popen(cmd, path)
+      vars = { "PWD" => path }
+      options = { :chdir => path }
+
+      @cmd_output = ""
+      @cmd_status = 0
+      Open3.popen3(vars, cmd, options) do |stdin, stdout, stderr, wait_thr|
+        @cmd_status = wait_thr.value.exitstatus
+        @cmd_output << stdout.read
+        @cmd_output << stderr.read
+      end
+
+      return @cmd_output, @cmd_status
+    end
+  end
+end
diff --git a/lib/gitlab/satellite/logger.rb b/lib/gitlab/satellite/logger.rb
new file mode 100644
index 0000000000000000000000000000000000000000..6f3f8255aca11e5b9c77bf98bd968a299e3c9756
--- /dev/null
+++ b/lib/gitlab/satellite/logger.rb
@@ -0,0 +1,13 @@
+module Gitlab
+  module Satellite
+    class Logger < Gitlab::Logger
+      def self.file_name
+        'satellites.log'
+      end
+
+      def format_message(severity, timestamp, progname, msg)
+        "#{timestamp.to_s(:long)}: #{msg}\n"
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/satellite/satellite.rb b/lib/gitlab/satellite/satellite.rb
index 164af55d895842a3337aa3d96dcef3aa25b329aa..e7f7a7673b5410310350dc01675abfc75ddc1382 100644
--- a/lib/gitlab/satellite/satellite.rb
+++ b/lib/gitlab/satellite/satellite.rb
@@ -3,6 +3,8 @@ module Gitlab
 
   module Satellite
     class Satellite
+      include Gitlab::Popen
+
       PARKING_BRANCH = "__parking_branch"
 
       attr_accessor :project
@@ -11,6 +13,10 @@ module Gitlab
         @project = project
       end
 
+      def log message
+        Gitlab::Satellite::Logger.error(message)
+      end
+
       def raise_no_satellite
         raise SatelliteNotExistError.new("Satellite doesn't exist")
       end
@@ -24,11 +30,16 @@ module Gitlab
       end
 
       def create
-        create_cmd = "git clone #{project.url_to_repo} #{path}"
-        if system(create_cmd)
+        output, status = popen("git clone #{project.repository.path_to_repo} #{path}",
+                               Gitlab.config.satellites.path)
+
+        log("PID: #{project.id}: git clone #{project.repository.path_to_repo} #{path}")
+        log("PID: #{project.id}: -> #{output}")
+
+        if status.zero?
           true
         else
-          Gitlab::GitLogger.error("Failed to create satellite for #{project.name_with_namespace}")
+          log("Failed to create satellite for #{project.name_with_namespace}")
           false
         end
       end
@@ -66,6 +77,10 @@ module Gitlab
         @repo ||= Grit::Repo.new(path)
       end
 
+      def destroy
+        FileUtils.rm_rf(path)
+      end
+
       private
 
       # Clear the working directory
diff --git a/lib/gitlab/user_team_manager.rb b/lib/gitlab/user_team_manager.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a8ff4a3d94df296b23d0daed479c5d486fad45b1
--- /dev/null
+++ b/lib/gitlab/user_team_manager.rb
@@ -0,0 +1,135 @@
+# UserTeamManager class
+#
+# Used for manage User teams with project repositories
+module Gitlab
+  class UserTeamManager
+    class << self
+      def assign(team, project, access)
+        project = Project.find(project) unless project.is_a? Project
+        searched_project = team.user_team_project_relationships.find_by_project_id(project.id)
+
+        unless searched_project.present?
+          team.user_team_project_relationships.create(project_id: project.id, greatest_access: access)
+          update_team_users_access_in_project(team, project)
+        end
+      end
+
+      def resign(team, project)
+        project = Project.find(project) unless project.is_a? Project
+
+        team.user_team_project_relationships.with_project(project).destroy_all
+
+        update_team_users_access_in_project(team, project)
+      end
+
+      def update_team_user_membership(team, member, options)
+        updates = {}
+
+        if options[:default_projects_access] && options[:default_projects_access] != team.default_projects_access(member)
+          updates[:permission] = options[:default_projects_access]
+        end
+
+        if options[:group_admin].to_s != team.admin?(member).to_s
+          updates[:group_admin] = options[:group_admin].present?
+        end
+
+        unless updates.blank?
+          user_team_relationship = team.user_team_user_relationships.find_by_user_id(member)
+          if user_team_relationship.update_attributes(updates)
+            if updates[:permission]
+              rebuild_project_permissions_to_member(team, member)
+            end
+            true
+          else
+            false
+          end
+        else
+          true
+        end
+      end
+
+      def update_project_greates_access(team, project, permission)
+        project_relation = team.user_team_project_relationships.find_by_project_id(project)
+        if permission != team.max_project_access(project)
+          if project_relation.update_attributes(greatest_access: permission)
+            update_team_users_access_in_project(team, project)
+            true
+          else
+            false
+          end
+        else
+          true
+        end
+      end
+
+      def rebuild_project_permissions_to_member(team, member)
+        team.projects.each do |project|
+          update_team_user_access_in_project(team, member, project)
+        end
+      end
+
+      def update_team_users_access_in_project(team, project)
+        members = team.members
+        members.each do |member|
+          update_team_user_access_in_project(team, member, project)
+        end
+      end
+
+      def update_team_user_access_in_project(team, user, project)
+        granted_access = max_teams_member_permission_in_project(user, project)
+
+        project_team_user = UsersProject.find_by_user_id_and_project_id(user.id, project.id)
+        project_team_user.destroy if project_team_user.present?
+
+        # project_team_user.project_access != granted_access
+        project.team << [user, granted_access] if granted_access > 0
+      end
+
+      def max_teams_member_permission_in_project(user, project, teams = nil)
+        result_access = 0
+
+        user_teams = project.user_teams.with_member(user)
+
+        teams ||= user_teams
+
+        if teams.any?
+          teams.each do |team|
+            granted_access = max_team_member_permission_in_project(team, user, project)
+            result_access = [granted_access, result_access].max
+          end
+        end
+        result_access
+      end
+
+      def max_team_member_permission_in_project(team, user, project)
+        member_access = team.default_projects_access(user)
+        team_access = team.user_team_project_relationships.find_by_project_id(project.id).greatest_access
+
+        [team_access, member_access].min
+      end
+
+      def add_member_into_team(team, user, access, admin)
+        user = User.find(user) unless user.is_a? User
+
+        team.user_team_user_relationships.create(user_id: user.id, permission: access, group_admin: admin)
+        team.projects.each do |project|
+          update_team_user_access_in_project(team, user, project)
+        end
+      end
+
+      def remove_member_from_team(team, user)
+        user = User.find(user) unless user.is_a? User
+
+        team.user_team_user_relationships.with_user(user).destroy_all
+        other_teams = []
+        team.projects.each do |project|
+          other_teams << project.user_teams.with_member(user)
+        end
+        other_teams.uniq
+        unless other_teams.any?
+          UsersProject.in_projects(team.projects).with_user(user).destroy_all
+        end
+      end
+    end
+  end
+end
diff --git a/lib/gitolited.rb b/lib/gitolited.rb
index 68b9b6255253b0e4faeeac16045ee3d8235061b9..4911a473f05e1d42b0127cd1d98372775897df1c 100644
--- a/lib/gitolited.rb
+++ b/lib/gitolited.rb
@@ -6,6 +6,6 @@
 #
 module Gitolited
   def gitolite
-    Gitlab::Gitolite.new
+    Gitlab::Shell.new
   end
 end
diff --git a/lib/hooks/post-receive b/lib/hooks/post-receive
deleted file mode 100755
index 6944d3e3f72fddbc1ca6839ed0c331fab787dcc6..0000000000000000000000000000000000000000
--- a/lib/hooks/post-receive
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/env bash
-
-# Version 4.1
-# This file was placed here by GitLab. It makes sure that your pushed commits
-# will be processed properly.
-
-while read oldrev newrev ref
-do
-  # For every branch or tag that was pushed, create a Resque job in redis.
-  repo_path=`pwd`
-  env -i redis-cli rpush "resque:gitlab:queue:post_receive" "{\"class\":\"PostReceive\",\"args\":[\"$repo_path\",\"$oldrev\",\"$newrev\",\"$ref\",\"$GL_USER\"]}" > /dev/null 2>&1
-done
diff --git a/lib/support/rewrite-hooks.sh b/lib/support/rewrite-hooks.sh
deleted file mode 100755
index b8fd36b9a1e5e61ebc0b4620d33235cbbe27548f..0000000000000000000000000000000000000000
--- a/lib/support/rewrite-hooks.sh
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/bin/bash
-
-src="/home/git/repositories"
-
-for dir in `ls "$src/"`
-do
-  if [ -d "$src/$dir" ]; then
-
-    if [ "$dir" = "gitolite-admin.git" ]
-    then
-      continue 
-    fi
-
-    if [[ "$dir" =~ ^.*.git$ ]]
-    then
-      project_hook="$src/$dir/hooks/post-receive"
-      gitolite_hook="/home/git/.gitolite/hooks/common/post-receive"
-
-      ln -s -f $gitolite_hook $project_hook
-    else
-      for subdir in `ls "$src/$dir/"`
-      do
-        if [ -d "$src/$dir/$subdir" ] && [[ "$subdir" =~ ^.*.git$ ]]; then
-          project_hook="$src/$dir/$subdir/hooks/post-receive"
-          gitolite_hook="/home/git/.gitolite/hooks/common/post-receive"
-
-          ln -s -f $gitolite_hook $project_hook
-        fi
-      done
-    fi
-  fi
-done
diff --git a/lib/support/truncate_repositories.sh b/lib/support/truncate_repositories.sh
deleted file mode 100755
index 3b14e2ee362fb858b7ffa61d8da672866493e382..0000000000000000000000000000000000000000
--- a/lib/support/truncate_repositories.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash
-
-echo "Danger!!! Data Loss"
-while true; do
-  read -p "Do you wish to all directories except gitolite-admin.git from /home/git/repositories/ (y/n) ?:  " yn
-  case $yn in
-    [Yy]* ) sh -c "find /home/git/repositories/. -maxdepth 1  -not -name 'gitolite-admin.git' -not -name '.' | xargs sudo rm -rf"; break;;
-    [Nn]* ) exit;;
-    * ) echo "Please answer yes or no.";;
-  esac
-done
diff --git a/lib/tasks/gitlab/bulk_add_permission.rake b/lib/tasks/gitlab/bulk_add_permission.rake
index 36c51d060bc735a12bb203a1f189b943cd13d70c..eb1a7559dbda102f60cd9993df7305cc48e4b485 100644
--- a/lib/tasks/gitlab/bulk_add_permission.rake
+++ b/lib/tasks/gitlab/bulk_add_permission.rake
@@ -4,21 +4,21 @@ namespace :gitlab do
     task :all_users_to_all_projects => :environment  do |t, args|
       user_ids = User.where(:admin => false).pluck(:id)
       admin_ids = User.where(:admin => true).pluck(:id)
+      projects_ids = Project.pluck(:id)
 
-      Project.find_each do |project|
-        puts "Importing #{user_ids.size} users into #{project.code}"
-        UsersProject.bulk_import(project, user_ids, UsersProject::DEVELOPER)
-        puts "Importing #{admin_ids.size} admins into #{project.code}"
-        UsersProject.bulk_import(project, admin_ids, UsersProject::MASTER)
-      end
+      puts "Importing #{user_ids.size} users into #{projects_ids.size} projects"
+      UsersProject.add_users_into_projects(projects_ids, user_ids, UsersProject::DEVELOPER)
+
+      puts "Importing #{admin_ids.size} admins into #{projects_ids.size} projects"
+      UsersProject.add_users_into_projects(projects_ids, admin_ids, UsersProject::MASTER)
     end
 
     desc "GITLAB | Add a specific user to all projects (as a developer)"
     task :user_to_projects, [:email] => :environment  do |t, args|
       user = User.find_by_email args.email
       project_ids = Project.pluck(:id)
-
-      UsersProject.user_bulk_import(user, project_ids, UsersProject::DEVELOPER)
+      puts "Importing #{user.email} users into #{project_ids.size} projects"
+      UsersProject.add_users_into_projects(project_ids, Array.wrap(user.id), UsersProject::DEVELOPER)
     end
   end
 end
\ No newline at end of file
diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake
index 826b78ec5b1bc8ff175efa78704215aab5f773ba..b54e63acfbc6b31a7679c61e227ed2594064ceea 100644
--- a/lib/tasks/gitlab/check.rake
+++ b/lib/tasks/gitlab/check.rake
@@ -169,7 +169,7 @@ namespace :gitlab do
       else
         puts "no".red
         try_fixing_it(
-          sudo_gitlab("bundle exec rake db:migrate")
+          sudo_gitlab("bundle exec rake db:migrate RAILS_ENV=production")
         )
         fix_and_rerun
       end
@@ -194,7 +194,7 @@ namespace :gitlab do
         else
           puts "no".red
           try_fixing_it(
-            sudo_gitlab("bundle exec rake gitlab:satellites:create"),
+            sudo_gitlab("bundle exec rake gitlab:satellites:create RAILS_ENV=production"),
             "If necessary, remove the tmp/repo_satellites directory ...",
             "... and rerun the above command"
           )
@@ -716,7 +716,7 @@ namespace :gitlab do
     end
 
     def check_repo_base_permissions
-      print "Repo base access is drwsrws---? ... "
+      print "Repo base access is drwxrws---? ... "
 
       repo_base_path = Gitlab.config.gitolite.repos_path
       unless File.exists?(repo_base_path)
@@ -724,12 +724,14 @@ namespace :gitlab do
         return
       end
 
-      if File.stat(repo_base_path).mode.to_s(8).ends_with?("6770")
+      if File.stat(repo_base_path).mode.to_s(8).ends_with?("2770")
         puts "yes".green
       else
         puts "no".red
         try_fixing_it(
-          "sudo chmod -R ug+rwXs,o-rwx #{repo_base_path}"
+          "sudo chmod -R ug+rwX,o-rwx #{repo_base_path}",
+          "sudo chmod -R ug-s #{repo_base_path}",
+          "find #{repo_base_path} -type d -print0 | sudo xargs -0 chmod g+s"
         )
         for_more_information(
           see_installation_guide_section "Gitolite"
@@ -780,21 +782,25 @@ namespace :gitlab do
       Project.find_each(batch_size: 100) do |project|
         print "#{project.name_with_namespace.yellow} ... "
 
-        correct_options = options.map do |name, value|
-          run("git --git-dir=\"#{project.repository.path_to_repo}\" config --get #{name}").try(:chomp) == value
-        end
-
-        if correct_options.all?
-          puts "ok".green
+        if project.empty_repo?
+          puts "repository is empty".magenta
         else
-          puts "wrong or missing".red
-          try_fixing_it(
-            sudo_gitlab("bundle exec rake gitlab:gitolite:update_repos")
-          )
-          for_more_information(
-            "doc/raketasks/maintenance.md"
-          )
-          fix_and_rerun
+          correct_options = options.map do |name, value|
+            run("git --git-dir=\"#{project.repository.path_to_repo}\" config --get #{name}").try(:chomp) == value
+          end
+
+          if correct_options.all?
+            puts "ok".green
+          else
+            puts "wrong or missing".red
+            try_fixing_it(
+              sudo_gitlab("bundle exec rake gitlab:gitolite:update_repos RAILS_ENV=production")
+            )
+            for_more_information(
+              "doc/raketasks/maintenance.md"
+            )
+            fix_and_rerun
+          end
         end
       end
     end
@@ -820,32 +826,37 @@ namespace :gitlab do
 
       Project.find_each(batch_size: 100) do |project|
         print "#{project.name_with_namespace.yellow} ... "
-        project_hook_file = File.join(project.repository.path_to_repo, "hooks", hook_file)
 
-        unless File.exists?(project_hook_file)
-          puts "missing".red
-          try_fixing_it(
-            "sudo -u #{gitolite_ssh_user} ln -sf #{gitolite_hook_file} #{project_hook_file}"
-          )
-          for_more_information(
-            "lib/support/rewrite-hooks.sh"
-          )
-          fix_and_rerun
-          next
-        end
-
-        if File.lstat(project_hook_file).symlink? &&
-            File.realpath(project_hook_file) == File.realpath(gitolite_hook_file)
-          puts "ok".green
+        if project.empty_repo?
+          puts "repository is empty".magenta
         else
-          puts "not a link to Gitolite's hook".red
-          try_fixing_it(
-            "sudo -u #{gitolite_ssh_user} ln -sf #{gitolite_hook_file} #{project_hook_file}"
-          )
-          for_more_information(
-            "lib/support/rewrite-hooks.sh"
-          )
-          fix_and_rerun
+          project_hook_file = File.join(project.repository.path_to_repo, "hooks", hook_file)
+
+          unless File.exists?(project_hook_file)
+            puts "missing".red
+            try_fixing_it(
+              "sudo -u #{gitolite_ssh_user} ln -sf #{gitolite_hook_file} #{project_hook_file}"
+            )
+            for_more_information(
+              "lib/support/rewrite-hooks.sh"
+            )
+            fix_and_rerun
+            next
+          end
+
+          if File.lstat(project_hook_file).symlink? &&
+              File.realpath(project_hook_file) == File.realpath(gitolite_hook_file)
+            puts "ok".green
+          else
+            puts "not a link to Gitolite's hook".red
+            try_fixing_it(
+              "sudo -u #{gitolite_ssh_user} ln -sf #{gitolite_hook_file} #{project_hook_file}"
+            )
+            for_more_information(
+              "lib/support/rewrite-hooks.sh"
+            )
+            fix_and_rerun
+          end
         end
       end
     end
@@ -895,7 +906,7 @@ namespace :gitlab do
       else
         puts "no".red
         try_fixing_it(
-          sudo_gitlab("bundle exec rake sidekiq:start")
+          sudo_gitlab("bundle exec rake sidekiq:start RAILS_ENV=production")
         )
         for_more_information(
           see_installation_guide_section("Install Init Script"),
diff --git a/lib/tasks/gitlab/enable_automerge.rake b/lib/tasks/gitlab/enable_automerge.rake
index e92da81021f06a1f3a19daad21994e9fb3740332..a89c6eaa5c41291f2aae66ecb3a1cac289c2d1e4 100644
--- a/lib/tasks/gitlab/enable_automerge.rake
+++ b/lib/tasks/gitlab/enable_automerge.rake
@@ -3,11 +3,6 @@ namespace :gitlab do
   task :enable_automerge => :environment do
     warn_user_is_not_gitlab
 
-    puts "Updating repo permissions ..."
-    Gitlab::Gitolite.new.enable_automerge
-    puts "... #{"done".green}"
-    puts ""
-
     print "Creating satellites for ..."
     unless Project.count > 0
       puts "skipping, because you have no projects".magenta
diff --git a/lib/tasks/gitlab/import.rake b/lib/tasks/gitlab/import.rake
index 4bf9110508ed41a12ba25d6517364a45daa5f681..0ca652faa747949184370ee92fb9d317643a8276 100644
--- a/lib/tasks/gitlab/import.rake
+++ b/lib/tasks/gitlab/import.rake
@@ -44,7 +44,7 @@ namespace :gitlab do
             :name => path,
           }
 
-          project = Project.create_by_user(project_params, user)
+          project = Projects::CreateContext.new(user, project_params).execute
 
           if project.valid?
             puts " * Created #{project.name} (#{repo_name})".green
diff --git a/lib/tasks/gitlab/shell.rake b/lib/tasks/gitlab/shell.rake
new file mode 100644
index 0000000000000000000000000000000000000000..25713482ed81e0dff32cfdaadbb22fc2bfa38c8f
--- /dev/null
+++ b/lib/tasks/gitlab/shell.rake
@@ -0,0 +1,32 @@
+namespace :gitlab do
+  namespace :shell do
+    desc "GITLAB | Setup gitlab-shell"
+    task :setup => :environment do
+      setup
+    end
+  end
+
+  def setup
+    warn_user_is_not_gitlab
+
+    puts "This will rebuild an authorized_keys file."
+    puts "You will lose any data stored in /home/git/.ssh/authorized_keys."
+    ask_to_continue
+    puts ""
+
+    system("echo '# Managed by gitlab-shell' > /home/git/.ssh/authorized_keys")
+
+    Key.find_each(:batch_size => 1000) do |key|
+      if Gitlab::Shell.new.add_key(key.shell_id, key.key)
+        print '.'
+      else
+        print 'F'
+      end
+    end
+
+  rescue Gitlab::TaskAbortedByUserError
+    puts "Quitting...".red
+    exit 1
+  end
+end
+
diff --git a/lib/tasks/sidekiq.rake b/lib/tasks/sidekiq.rake
index 01da919d7f8ab22f97ddf5b0709b8761114c5659..e4eb0e6776f9637eff3980073d77ab057a73f515 100644
--- a/lib/tasks/sidekiq.rake
+++ b/lib/tasks/sidekiq.rake
@@ -6,7 +6,7 @@ namespace :sidekiq do
 
   desc "GITLAB | Start sidekiq"
   task :start do
-    run "nohup bundle exec sidekiq -q post_receive,mailer,system_hook,common,default -e #{Rails.env} -P #{pidfile} >> #{Rails.root.join("log", "sidekiq.log")} 2>&1 &"
+    run "nohup bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,gitolite,common,default -e #{Rails.env} -P #{pidfile} >> #{Rails.root.join("log", "sidekiq.log")} 2>&1 &"
   end
 
   def pidfile
diff --git a/public/deploy.html b/public/deploy.html
new file mode 100644
index 0000000000000000000000000000000000000000..d8c287809ea0ae0ed485aa81f57bca3e753065d0
--- /dev/null
+++ b/public/deploy.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Deploy in progress. Please try again in few minutes</title>
+    <link href="/static.css" media="screen" rel="stylesheet" type="text/css" />
+  </head>
+  <body>
+    <h1>Deploy in progress</h1>
+    <h3>Please try again in few minutes or contact your administrator.</h3>
+  </body>
+</html>
diff --git a/spec/factories.rb b/spec/factories.rb
index 593b8350fdaf8d229fc90b9d3989d9be7107f36a..0e0c04f98751ef17db30e5dd1d88b8a64f6b400b 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -12,7 +12,7 @@ FactoryGirl.define do
   factory :user, aliases: [:author, :assignee, :owner, :creator] do
     email { Faker::Internet.email }
     name
-    username { Faker::Internet.user_name }
+    sequence(:username) { |n| "#{Faker::Internet.user_name}#{n}" }
     password "123456"
     password_confirmation { password }
 
diff --git a/spec/factories/user_team_project_relationships.rb b/spec/factories/user_team_project_relationships.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e900d86c2e40f6cc8e5fa3c1678b01f153d3aa8f
--- /dev/null
+++ b/spec/factories/user_team_project_relationships.rb
@@ -0,0 +1,21 @@
+# == Schema Information
+#
+# Table name: user_team_project_relationships
+#
+#  id              :integer          not null, primary key
+#  project_id      :integer
+#  user_team_id    :integer
+#  greatest_access :integer
+#  created_at      :datetime         not null
+#  updated_at      :datetime         not null
+#
+
+# Read about factories at https://github.com/thoughtbot/factory_girl
+
+FactoryGirl.define do
+  factory :user_team_project_relationship do
+    project
+    user_team
+    greatest_access { UsersProject::MASTER }
+  end
+end
diff --git a/spec/factories/user_team_user_relationships.rb b/spec/factories/user_team_user_relationships.rb
new file mode 100644
index 0000000000000000000000000000000000000000..8c729dd875105524d5dea6874849e8948bc6b4d4
--- /dev/null
+++ b/spec/factories/user_team_user_relationships.rb
@@ -0,0 +1,23 @@
+# == Schema Information
+#
+# Table name: user_team_user_relationships
+#
+#  id           :integer          not null, primary key
+#  user_id      :integer
+#  user_team_id :integer
+#  group_admin  :boolean
+#  permission   :integer
+#  created_at   :datetime         not null
+#  updated_at   :datetime         not null
+#
+
+# Read about factories at https://github.com/thoughtbot/factory_girl
+
+FactoryGirl.define do
+  factory :user_team_user_relationship do
+    user
+    user_team
+    group_admin false
+    permission { UsersProject::MASTER }
+  end
+end
diff --git a/spec/factories/user_teams.rb b/spec/factories/user_teams.rb
new file mode 100644
index 0000000000000000000000000000000000000000..1a9ae8e885c3cf924219bef7ba49d893884d52cc
--- /dev/null
+++ b/spec/factories/user_teams.rb
@@ -0,0 +1,21 @@
+# == Schema Information
+#
+# Table name: user_teams
+#
+#  id         :integer          not null, primary key
+#  name       :string(255)
+#  path       :string(255)
+#  owner_id   :integer
+#  created_at :datetime         not null
+#  updated_at :datetime         not null
+#
+
+# Read about factories at https://github.com/thoughtbot/factory_girl
+
+FactoryGirl.define do
+  factory :user_team do
+    sequence(:name) { |n| "team#{n}" }
+    path { name.downcase.gsub(/\s/, '_') }
+    owner
+  end
+end
diff --git a/spec/lib/extracts_path_spec.rb b/spec/lib/extracts_path_spec.rb
index deb6499e00803707ed537f044ad2f3f9696dba07..ee20ae79809d4af3338416e2677a60ef96a818e2 100644
--- a/spec/lib/extracts_path_spec.rb
+++ b/spec/lib/extracts_path_spec.rb
@@ -73,5 +73,28 @@ describe ExtractsPath do
         extract_ref('/gitlab/gitlab-ci/tree/v2.0.0/CHANGELOG?_=12354435').should == ['v2.0.0', 'CHANGELOG']
       end
     end
+
+    context "with a fullpath and a relative_url_root" do
+      before do
+        Gitlab.config.gitlab.stub(relative_url_root: '/relative')
+      end
+
+      it "extracts a valid branch with relative_url_root" do
+        extract_ref('/relative/gitlab/gitlab-ci/tree/foo/bar/baz/CHANGELOG').should == ['foo/bar/baz', 'CHANGELOG']
+      end
+
+      it "extracts a valid tag" do
+        extract_ref('/relative/gitlab/gitlab-ci/tree/v2.0.0/CHANGELOG').should == ['v2.0.0', 'CHANGELOG']
+      end
+
+      it "extracts a valid commit SHA" do
+        extract_ref('/relative/gitlab/gitlab-ci/tree/f4b14494ef6abf3d144c28e4af0c20143383e062/CHANGELOG').should ==
+          ['f4b14494ef6abf3d144c28e4af0c20143383e062', 'CHANGELOG']
+      end
+
+      it "extracts a timestamp" do
+        extract_ref('/relative/gitlab/gitlab-ci/tree/v2.0.0/CHANGELOG?_=12354435').should == ['v2.0.0', 'CHANGELOG']
+      end
+    end
   end
 end
diff --git a/spec/lib/gitolite_config_spec.rb b/spec/lib/gitolite_config_spec.rb
deleted file mode 100644
index c3ce0db569aef71093eefac45a2acb61bc07b093..0000000000000000000000000000000000000000
--- a/spec/lib/gitolite_config_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::GitoliteConfig do
-  let(:gitolite) { Gitlab::GitoliteConfig.new }
-
-  it { should respond_to :write_key }
-  it { should respond_to :rm_key }
-  it { should respond_to :update_project }
-  it { should respond_to :update_project! }
-  it { should respond_to :update_projects }
-  it { should respond_to :destroy_project }
-  it { should respond_to :destroy_project! }
-  it { should respond_to :apply }
-  it { should respond_to :admin_all_repo }
-  it { should respond_to :admin_all_repo! }
-end
diff --git a/spec/lib/gitolite_spec.rb b/spec/lib/gitolite_spec.rb
deleted file mode 100644
index 8075b99ed99037ce637bcb510fbd66ec660f7a4d..0000000000000000000000000000000000000000
--- a/spec/lib/gitolite_spec.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Gitolite do
-  let(:project) { double('Project', path: 'diaspora') }
-  let(:gitolite_config) { double('Gitlab::GitoliteConfig') }
-  let(:gitolite) { Gitlab::Gitolite.new }
-
-  before do
-    gitolite.stub(config: gitolite_config)
-  end
-
-  it { should respond_to :set_key }
-  it { should respond_to :remove_key }
-
-  it { should respond_to :update_repository }
-  it { should respond_to :create_repository }
-  it { should respond_to :remove_repository }
-
-  it { gitolite.url_to_repo('diaspora').should == Gitlab.config.gitolite.ssh_path_prefix + "diaspora.git" }
-
-  it "should call config update" do
-    gitolite_config.should_receive(:update_project!)
-    gitolite.update_repository project
-  end
-end
diff --git a/spec/lib/shell_spec.rb b/spec/lib/shell_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..1c546e59235a7d1fcfc65c9a4c1057891dea5c2d
--- /dev/null
+++ b/spec/lib/shell_spec.rb
@@ -0,0 +1,17 @@
+require 'spec_helper'
+
+describe Gitlab::Shell do
+  let(:project) { double('Project', id: 7, path: 'diaspora') }
+  let(:gitolite) { Gitlab::Shell.new }
+
+  before do
+    Project.stub(find: project)
+  end
+
+  it { should respond_to :add_key }
+  it { should respond_to :remove_key }
+  it { should respond_to :add_repository }
+  it { should respond_to :remove_repository }
+
+  it { gitolite.url_to_repo('diaspora').should == Gitlab.config.gitolite.ssh_path_prefix + "diaspora.git" }
+end
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index d947f0e28822b0ca7cb158c5f11372c8518c5ed9..befc10594dba7aa152e17687967d92dcffed840a 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -266,7 +266,7 @@ describe Notify do
 
         before(:each) { note.stub(:noteable).and_return(commit) }
 
-        subject { Notify.note_commit_email(recipient.email, note.id) }
+        subject { Notify.note_commit_email(recipient.id, note.id) }
 
         it_behaves_like 'a note email'
 
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index 0816b3eed5a30dc0370b504787d0721f7de61455..10db53e07450862d9da1b66488c3ad8ed9b5ba89 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -28,10 +28,6 @@ describe Issue do
     it { should_not allow_mass_assignment_of(:project_id) }
   end
 
-  describe "Validation" do
-    it { should ensure_length_of(:description).is_within(0..10000) }
-  end
-
   describe 'modules' do
     it { should include_module(Issuable) }
   end
diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb
index 6d2310df5c025782cef8da8ecc472635b25a69e1..94b952cf932f58d0d26b4f21dcdbc6a247562a9e 100644
--- a/spec/models/key_spec.rb
+++ b/spec/models/key_spec.rb
@@ -46,9 +46,9 @@ describe Key do
         key.should_not be_valid
       end
 
-      it "does accept the same key for another project" do
+      it "does not accept the same key for another project" do
         key = build(:key, project_id: 0)
-        key.should be_valid
+        key.should_not be_valid
       end
     end
 
diff --git a/spec/models/project_hooks_spec.rb b/spec/models/project_hooks_spec.rb
index 60457e20c51425e8bc43d6befc5f6cfab2c8cce3..3559c72f6f0f785d07ef5685a233bd32e6757027 100644
--- a/spec/models/project_hooks_spec.rb
+++ b/spec/models/project_hooks_spec.rb
@@ -38,11 +38,14 @@ describe Project, "Hooks" do
         @project_hook = create(:project_hook)
         @project_hook_2 = create(:project_hook)
         project.hooks << [@project_hook, @project_hook_2]
+
+        stub_request(:post, @project_hook.url)
+        stub_request(:post, @project_hook_2.url)
       end
 
       it "executes multiple web hook" do
-        @project_hook.should_receive(:execute).once
-        @project_hook_2.should_receive(:execute).once
+        @project_hook.should_receive(:async_execute).once
+        @project_hook_2.should_receive(:async_execute).once
 
         project.trigger_post_receive('oldrev', 'newrev', 'refs/heads/master', @user)
       end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 17bc988bf059b49c56488084da8fcc844d97ed6d..3dccb482375c9d4d230a1ddd85e04da4931b11ea 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -8,7 +8,6 @@
 #  description            :text
 #  created_at             :datetime         not null
 #  updated_at             :datetime         not null
-#  private_flag           :boolean          default(TRUE), not null
 #  creator_id             :integer
 #  default_branch         :string(255)
 #  issues_enabled         :boolean          default(TRUE), not null
@@ -16,6 +15,7 @@
 #  merge_requests_enabled :boolean          default(TRUE), not null
 #  wiki_enabled           :boolean          default(TRUE), not null
 #  namespace_id           :integer
+#  public                 :boolean          default(FALSE), not null
 #
 
 require 'spec_helper'
@@ -42,7 +42,6 @@ describe Project do
   describe "Mass assignment" do
     it { should_not allow_mass_assignment_of(:namespace_id) }
     it { should_not allow_mass_assignment_of(:creator_id) }
-    it { should_not allow_mass_assignment_of(:private_flag) }
   end
 
   describe "Validation" do
@@ -78,8 +77,6 @@ describe Project do
     it { should respond_to(:url_to_repo) }
     it { should respond_to(:repo_exists?) }
     it { should respond_to(:satellite) }
-    it { should respond_to(:update_repository) }
-    it { should respond_to(:destroy_repository) }
     it { should respond_to(:observe_push) }
     it { should respond_to(:update_merge_requests) }
     it { should respond_to(:execute_hooks) }
diff --git a/spec/models/team_spec.rb b/spec/models/project_team_spec.rb
similarity index 94%
rename from spec/models/team_spec.rb
rename to spec/models/project_team_spec.rb
index 65ffe13b490c651f75d792e4fc483718a23afbcd..7803811f395a9778659ae7f910a1e202404fe5b6 100644
--- a/spec/models/team_spec.rb
+++ b/spec/models/project_team_spec.rb
@@ -1,6 +1,6 @@
 require "spec_helper"
 
-describe Team do
+describe ProjectTeam do
   let(:team) { create(:project).team }
 
   describe "Respond to" do
diff --git a/spec/models/protected_branch_spec.rb b/spec/models/protected_branch_spec.rb
index c4d2e2f49f515856ef3f2276f096fc0121adf863..6e830393e32e632fb4d57a10ab1824331c58c718 100644
--- a/spec/models/protected_branch_spec.rb
+++ b/spec/models/protected_branch_spec.rb
@@ -24,19 +24,4 @@ describe ProtectedBranch do
     it { should validate_presence_of(:project) }
     it { should validate_presence_of(:name) }
   end
-
-  describe 'Callbacks' do
-    let(:branch) { build(:protected_branch) }
-
-    it 'call update_repository after save' do
-      branch.should_receive(:update_repository)
-      branch.save
-    end
-
-    it 'call update_repository after destroy' do
-      branch.save
-      branch.should_receive(:update_repository)
-      branch.destroy
-    end
-  end
 end
diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb
index b474d88c9e27e070181a3fe78e5bee7be0a0fc85..e4d1934829f663f30462cfd5b52445fdd3d80eee 100644
--- a/spec/models/snippet_spec.rb
+++ b/spec/models/snippet_spec.rb
@@ -38,6 +38,5 @@ describe Snippet do
     it { should ensure_length_of(:title).is_within(0..255) }
 
     it { should validate_presence_of(:content) }
-    it { should ensure_length_of(:content).is_within(0..10_000) }
   end
 end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index f19c40b5fa6b9a760dc5bf643de6906faef72c13..8ab0a0343bbf385eb3b1b4cda9d1d285a10dff00 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -31,6 +31,8 @@
 #  extern_uid             :string(255)
 #  provider               :string(255)
 #  username               :string(255)
+#  can_create_group       :boolean          default(TRUE), not null
+#  can_create_team        :boolean          default(TRUE), not null
 #
 
 require 'spec_helper'
@@ -189,7 +191,7 @@ describe User do
 
     it { user.is_admin?.should be_false }
     it { user.require_ssh_key?.should be_true }
-    it { user.can_create_group?.should be_false }
+    it { user.can_create_group?.should be_true }
     it { user.can_create_project?.should be_true }
     it { user.first_name.should == 'John' }
   end
diff --git a/spec/models/user_team_project_relationship_spec.rb b/spec/models/user_team_project_relationship_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..86150cf305f31f0a5251ec5bf0892992f2f8973d
--- /dev/null
+++ b/spec/models/user_team_project_relationship_spec.rb
@@ -0,0 +1,17 @@
+# == Schema Information
+#
+# Table name: user_team_project_relationships
+#
+#  id              :integer          not null, primary key
+#  project_id      :integer
+#  user_team_id    :integer
+#  greatest_access :integer
+#  created_at      :datetime         not null
+#  updated_at      :datetime         not null
+#
+
+require 'spec_helper'
+
+describe UserTeamProjectRelationship do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/models/user_team_spec.rb b/spec/models/user_team_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..76d47f41498ca53f2be784b3ac9d7d8c7e52c9c3
--- /dev/null
+++ b/spec/models/user_team_spec.rb
@@ -0,0 +1,17 @@
+# == Schema Information
+#
+# Table name: user_teams
+#
+#  id         :integer          not null, primary key
+#  name       :string(255)
+#  path       :string(255)
+#  owner_id   :integer
+#  created_at :datetime         not null
+#  updated_at :datetime         not null
+#
+
+require 'spec_helper'
+
+describe UserTeam do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/models/user_team_user_relationship_spec.rb b/spec/models/user_team_user_relationship_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..981ad1e887313725922352f82ecdbbf64c8f5275
--- /dev/null
+++ b/spec/models/user_team_user_relationship_spec.rb
@@ -0,0 +1,18 @@
+# == Schema Information
+#
+# Table name: user_team_user_relationships
+#
+#  id           :integer          not null, primary key
+#  user_id      :integer
+#  user_team_id :integer
+#  group_admin  :boolean
+#  permission   :integer
+#  created_at   :datetime         not null
+#  updated_at   :datetime         not null
+#
+
+require 'spec_helper'
+
+describe UserTeamUserRelationship do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/observers/key_observer_spec.rb b/spec/observers/key_observer_spec.rb
index ae7b0f73e57ed413702807b49737a38d19a58073..0a886a57afdd79b030a3ee8be98bd161a2c4ba55 100644
--- a/spec/observers/key_observer_spec.rb
+++ b/spec/observers/key_observer_spec.rb
@@ -3,31 +3,25 @@ require 'spec_helper'
 describe KeyObserver do
   before do
     @key = double('Key',
-      identifier: 'admin_654654',
+      shell_id: 'key-32',
       key: '== a vaild ssh key',
       projects: [],
       is_deploy_key: false
     )
 
-    @gitolite = double('Gitlab::Gitolite',
-      set_key: true,
-      remove_key: true
-    )
-
     @observer = KeyObserver.instance
-    @observer.stub(gitolite: @gitolite)
   end
 
   context :after_save do
     it do
-      @gitolite.should_receive(:set_key).with(@key.identifier, @key.key, @key.projects)
+      GitoliteWorker.should_receive(:perform_async).with(:add_key, @key.shell_id, @key.key)
       @observer.after_save(@key)
     end
   end
 
   context :after_destroy do
     it do
-      @gitolite.should_receive(:remove_key).with(@key.identifier, @key.projects)
+      GitoliteWorker.should_receive(:perform_async).with(:remove_key, @key.shell_id, @key.key)
       @observer.after_destroy(@key)
     end
   end
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c39a4228408e6108d30084ca02846bd1349d2e12
--- /dev/null
+++ b/spec/requests/api/groups_spec.rb
@@ -0,0 +1,93 @@
+require 'spec_helper'
+
+describe Gitlab::API do
+  include ApiHelpers
+
+  let(:user1)  { create(:user) }
+  let(:user2)  { create(:user) }
+  let(:admin) { create(:admin) }
+  let!(:group1)  { create(:group, owner: user1) }
+  let!(:group2)  { create(:group, owner: user2) }
+
+  describe "GET /groups" do
+    context "when unauthenticated" do
+      it "should return authentication error" do
+        get api("/groups")
+        response.status.should == 401
+      end
+    end
+
+    context "when authenticated as user" do
+      it "normal user: should return an array of groups of user1" do
+        get api("/groups", user1)
+        response.status.should == 200
+        json_response.should be_an Array
+        json_response.length.should == 1
+        json_response.first['name'].should == group1.name
+      end
+    end
+    
+    context "when authenticated as  admin" do
+      it "admin: should return an array of all groups" do
+        get api("/groups", admin)
+        response.status.should == 200
+        json_response.should be_an Array
+        json_response.length.should == 2
+      end
+    end
+  end
+  
+  describe "GET /groups/:id" do
+    context "when authenticated as user" do
+      it "should return one of user1's groups" do
+        get api("/groups/#{group1.id}", user1)
+        response.status.should == 200
+        json_response['name'] == group1.name
+      end
+      
+      it "should not return a non existing group" do
+        get api("/groups/1328", user1)
+        response.status.should == 404
+      end
+      
+      it "should not return a group not attached to user1" do
+        get api("/groups/#{group2.id}", user1)
+        response.status.should == 404
+      end
+    end
+    
+    context "when authenticated as admin" do
+      it "should return any existing group" do
+        get api("/groups/#{group2.id}", admin)
+        response.status.should == 200
+        json_response['name'] == group2.name
+      end
+      
+      it "should not return a non existing group" do
+        get api("/groups/1328", admin)
+        response.status.should == 404
+      end
+    end
+  end
+  
+  describe "POST /groups" do
+    context "when authenticated as user" do
+      it "should not create group" do
+        post api("/groups", user1), attributes_for(:group)
+        response.status.should == 403
+      end
+    end
+    
+    context "when authenticated as admin" do
+      it "should create group" do
+        post api("/groups", admin), attributes_for(:group)
+        response.status.should == 201
+      end
+
+      it "should not create group, duplicate" do
+        post api("/groups", admin), {:name => "Duplicate Test", :path => group2.path}
+        response.status.should == 404
+      end
+    end
+  end
+end
diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb
index ae4fc111f636edea2174453b8601d43a171eb6c0..ee99d85df4d721aeb412ba84fc9af5f921e0b5ea 100644
--- a/spec/requests/api/notes_spec.rb
+++ b/spec/requests/api/notes_spec.rb
@@ -6,8 +6,10 @@ describe Gitlab::API do
   let(:user) { create(:user) }
   let!(:project) { create(:project, namespace: user.namespace ) }
   let!(:issue) { create(:issue, project: project, author: user) }
+  let!(:merge_request) { create(:merge_request, project: project, author: user) }
   let!(:snippet) { create(:snippet, project: project, author: user) }
   let!(:issue_note) { create(:note, noteable: issue, project: project, author: user) }
+  let!(:merge_request_note) { create(:note, noteable: merge_request, project: project, author: user) }
   let!(:snippet_note) { create(:note, noteable: snippet, project: project, author: user) }
   let!(:wall_note) { create(:note, project: project, author: user) }
   before { project.team << [user, :reporter] }
@@ -64,6 +66,15 @@ describe Gitlab::API do
         json_response.first['body'].should == snippet_note.note
       end
     end
+
+    context "when noteable is a Merge Request" do
+      it "should return an array of merge_requests notes" do
+        get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/notes", user)
+        response.status.should == 200
+        json_response.should be_an Array
+        json_response.first['body'].should == merge_request_note.note
+      end
+    end
   end
 
   describe "GET /projects/:id/noteable/:noteable_id/notes/:note_id" do
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index c2244210bcf29da26c977e2a06dda8b91516d989..d932fd9e74dc001ebe6f12955ff97cdd422844a5 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -107,6 +107,29 @@ describe Gitlab::API do
 
       json_response['name'].should == 'new_design'
       json_response['commit']['id'].should == '621491c677087aa243f165eab467bfdfbee00be1'
+      json_response['protected'].should == false
+    end
+  end
+
+  describe "PUT /projects/:id/repository/branches/:branch/protect" do
+    it "should protect a single branch" do
+      put api("/projects/#{project.id}/repository/branches/new_design/protect", user)
+      response.status.should == 200
+
+      json_response['name'].should == 'new_design'
+      json_response['commit']['id'].should == '621491c677087aa243f165eab467bfdfbee00be1'
+      json_response['protected'].should == true
+    end
+  end
+
+  describe "PUT /projects/:id/repository/branches/:branch/unprotect" do
+    it "should unprotect a single branch" do
+      put api("/projects/#{project.id}/repository/branches/new_design/unprotect", user)
+      response.status.should == 200
+
+      json_response['name'].should == 'new_design'
+      json_response['commit']['id'].should == '621491c677087aa243f165eab467bfdfbee00be1'
+      json_response['protected'].should == false
     end
   end
 
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index ee5f510aac5083d5496e36d2b9cdcd8540150e0d..1645117e231c01d62b55cbba90ff92ff92a682e9 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -83,6 +83,54 @@ describe Gitlab::API do
     end
   end
 
+  describe "PUT /users/:id" do
+    before { admin }
+
+    it "should update user" do
+      put api("/users/#{user.id}", admin), {bio: 'new test bio'}
+      response.status.should == 200
+      json_response['bio'].should == 'new test bio'
+      user.reload.bio.should == 'new test bio'
+    end
+
+    it "should not allow invalid update" do
+      put api("/users/#{user.id}", admin), {email: 'invalid email'}
+      response.status.should == 404
+      user.reload.email.should_not == 'invalid email'
+    end
+
+    it "shouldn't available for non admin users" do
+      put api("/users/#{user.id}", user), attributes_for(:user)
+      response.status.should == 403
+    end
+
+    it "should return 404 for non-existing user" do
+      put api("/users/999999", admin), {bio: 'update should fail'}
+      response.status.should == 404
+    end
+  end
+
+  describe "DELETE /users/:id" do
+    before { admin }
+
+    it "should delete user" do
+      delete api("/users/#{user.id}", admin)
+      response.status.should == 200
+      expect { User.find(user.id) }.to raise_error ActiveRecord::RecordNotFound
+      json_response['email'].should == user.email
+    end
+
+    it "shouldn't available for non admin users" do
+      delete api("/users/#{user.id}", user)
+      response.status.should == 403
+    end
+
+    it "should return 404 for non-existing user" do
+      delete api("/users/999999", admin)
+      response.status.should == 404
+    end
+  end
+
   describe "GET /user" do
     it "should return current user" do
       get api("/user", user)
diff --git a/spec/requests/atom/dashboard_issues_spec.rb b/spec/requests/atom/dashboard_issues_spec.rb
index 8ce64cd4c14a825d75fca86662932176e278fe64..6f5d51d16b6acb373f2eb0c1428fb115b2cc318a 100644
--- a/spec/requests/atom/dashboard_issues_spec.rb
+++ b/spec/requests/atom/dashboard_issues_spec.rb
@@ -10,7 +10,7 @@ describe "Dashboard Issues Feed" do
 
     describe "atom feed" do
       it "should render atom feed via private token" do
-        visit dashboard_issues_path(:atom, private_token: user.private_token)
+        visit issues_dashboard_path(:atom, private_token: user.private_token)
 
         page.response_headers['Content-Type'].should have_content("application/atom+xml")
         page.body.should have_selector("title", text: "#{user.name} issues")
diff --git a/spec/requests/notes_on_merge_requests_spec.rb b/spec/requests/notes_on_merge_requests_spec.rb
index 2b670359a49d7914069b6bb4658f787bf4202475..0111cf42ac7a7063acd6e776ef6d05b02d97694b 100644
--- a/spec/requests/notes_on_merge_requests_spec.rb
+++ b/spec/requests/notes_on_merge_requests_spec.rb
@@ -22,9 +22,9 @@ describe "On a merge request", js: true do
     it { within(".js-main-target-form") { should_not have_link("Cancel") } }
 
     # notifiactions
-    it { within(".js-main-target-form") { should have_checked_field("Project team") } }
-    it { within(".js-main-target-form") { should_not have_checked_field("Commit author") } }
-    it { within(".js-main-target-form") { should_not have_unchecked_field("Commit author") } }
+    it { within(".js-main-target-form") { should have_checked_field("Notify team via email") } }
+    it { within(".js-main-target-form") { should_not have_checked_field("Notify commit author") } }
+    it { within(".js-main-target-form") { should_not have_unchecked_field("Notify commit author") } }
 
     describe "without text" do
       it { within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: false) } }
@@ -125,7 +125,7 @@ describe "On a merge request diff", js: true, focus: true do
       it { should have_css(".js-close-discussion-note-form", text: "Cancel") }
 
       # notification options
-      it { should have_checked_field("Project team") }
+      it { should have_checked_field("Notify team via email") }
 
       it "shouldn't add a second form for same row" do
         find("#4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185.line_holder .js-add-diff-note-button").trigger("click")
diff --git a/spec/requests/notes_on_wall_spec.rb b/spec/requests/notes_on_wall_spec.rb
index 01673f997e935709dbd95a8799e3fb2d44d1c4d1..4adcf74e0b6a4cca6911b6364a5218dec8ef1644 100644
--- a/spec/requests/notes_on_wall_spec.rb
+++ b/spec/requests/notes_on_wall_spec.rb
@@ -21,9 +21,9 @@ describe "On the project wall", js: true do
     it { within(".js-main-target-form") { should_not have_link("Cancel") } }
 
     # notifiactions
-    it { within(".js-main-target-form") { should have_checked_field("Project team") } }
-    it { within(".js-main-target-form") { should_not have_checked_field("Commit author") } }
-    it { within(".js-main-target-form") { should_not have_unchecked_field("Commit author") } }
+    it { within(".js-main-target-form") { should have_checked_field("Notify team via email") } }
+    it { within(".js-main-target-form") { should_not have_checked_field("Notify commit author") } }
+    it { within(".js-main-target-form") { should_not have_unchecked_field("Notify commit author") } }
 
     describe "without text" do
       it { within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: false) } }
diff --git a/spec/routing/admin_routing_spec.rb b/spec/routing/admin_routing_spec.rb
index fb26bf98d0ff3631c7587deb01dd9f2c94565e63..3e0e4bb38838c4ab036c4cc57165a79e8af7a33c 100644
--- a/spec/routing/admin_routing_spec.rb
+++ b/spec/routing/admin_routing_spec.rb
@@ -95,20 +95,20 @@ describe Admin::ProjectsController, "routing" do
   end
 end
 
-# edit_admin_team_member GET    /admin/team_members/:id/edit(.:format) admin/team_members#edit
-#      admin_team_member PUT    /admin/team_members/:id(.:format)      admin/team_members#update
-#                        DELETE /admin/team_members/:id(.:format)      admin/team_members#destroy
-describe Admin::TeamMembersController, "routing" do
+# edit_admin_project_member GET      /admin/projects/:project_id/members/:id/edit(.:format)    admin/projects/members#edit {:id=>/[^\/]+/, :project_id=>/[^\/]+/}
+#      admin_project_member PUT      /admin/projects/:project_id/members/:id(.:format)         admin/projects/members#update {:id=>/[^\/]+/, :project_id=>/[^\/]+/}
+#                           DELETE   /admin/projects/:project_id/members/:id(.:format)         admin/projects/members#destroy {:id=>/[^\/]+/, :project_id=>/[^\/]+/}
+describe Admin::Projects::MembersController, "routing" do
   it "to #edit" do
-    get("/admin/team_members/1/edit").should route_to('admin/team_members#edit', id: '1')
+    get("/admin/projects/test/members/1/edit").should route_to('admin/projects/members#edit', project_id: 'test', id: '1')
   end
 
   it "to #update" do
-    put("/admin/team_members/1").should route_to('admin/team_members#update', id: '1')
+    put("/admin/projects/test/members/1").should route_to('admin/projects/members#update', project_id: 'test', id: '1')
   end
 
   it "to #destroy" do
-    delete("/admin/team_members/1").should route_to('admin/team_members#destroy', id: '1')
+    delete("/admin/projects/test/members/1").should route_to('admin/projects/members#destroy', project_id: 'test', id: '1')
   end
 end
 
diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb
index 6171141648c48ac9fb4477497f893f58adb0ad36..f94bedc79a1d1cb36edd6402cf32686c25da13e0 100644
--- a/spec/routing/project_routing_spec.rb
+++ b/spec/routing/project_routing_spec.rb
@@ -76,7 +76,7 @@ describe ProjectsController, "routing" do
   end
 
   it "to #graph" do
-    get("/gitlabhq/graph").should route_to('projects#graph', id: 'gitlabhq')
+    get("/gitlabhq/graph/master").should route_to('graph#show', project_id: 'gitlabhq', id: 'master')
   end
 
   it "to #files" do
diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb
index 57fd70e7497cd912e774b7a011c617f7ca7d5faa..5ad8165ecce1de76442b5f4c19394f13a7136634 100644
--- a/spec/routing/routing_spec.rb
+++ b/spec/routing/routing_spec.rb
@@ -146,14 +146,14 @@ describe KeysController, "routing" do
   end
 end
 
-#                dashboard GET    /dashboard(.:format)                dashboard#index
+#                dashboard GET    /dashboard(.:format)                dashboard#show
 #         dashboard_issues GET    /dashboard/issues(.:format)         dashboard#issues
 # dashboard_merge_requests GET    /dashboard/merge_requests(.:format) dashboard#merge_requests
-#                     root        /                                   dashboard#index
+#                     root        /                                   dashboard#show
 describe DashboardController, "routing" do
   it "to #index" do
-    get("/dashboard").should route_to('dashboard#index')
-    get("/").should route_to('dashboard#index')
+    get("/dashboard").should route_to('dashboard#show')
+    get("/").should route_to('dashboard#show')
   end
 
   it "to #issues" do
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index dbac3c549011f393de88c8d7e914e96d9d76e2f6..bb314e60eb7d47c5e822a721ce7e396905af2dda 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -24,7 +24,6 @@ RSpec.configure do |config|
   config.mock_with :rspec
 
   config.include LoginHelpers, type: :request
-  config.include GitoliteStub
   config.include FactoryGirl::Syntax::Methods
   config.include Devise::TestHelpers, type: :controller
 
@@ -34,8 +33,6 @@ RSpec.configure do |config|
   config.use_transactional_fixtures = false
 
   config.before do
-    stub_gitolite!
-
     # Use tmp dir for FS manipulations
     temp_repos_path = Rails.root.join('tmp', 'test-git-base-path')
     Gitlab.config.gitolite.stub(repos_path: temp_repos_path)
diff --git a/spec/support/gitolite_stub.rb b/spec/support/gitolite_stub.rb
deleted file mode 100644
index 574bb5a12a3f9e52d2f84be600523d0560fcd866..0000000000000000000000000000000000000000
--- a/spec/support/gitolite_stub.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-module GitoliteStub
-  def stub_gitolite!
-    stub_gitlab_gitolite
-    stub_gitolite_admin
-  end
-
-  def stub_gitolite_admin
-    gitolite_admin = double('Gitolite::GitoliteAdmin')
-    gitolite_admin.as_null_object
-
-    Gitolite::GitoliteAdmin.stub(new: gitolite_admin)
-  end
-
-  def stub_gitlab_gitolite
-    gitolite_config = double('Gitlab::GitoliteConfig')
-    gitolite_config.stub(apply: ->() { yield(self) })
-    gitolite_config.as_null_object
-
-    Gitlab::GitoliteConfig.stub(new: gitolite_config)
-  end
-end
diff --git a/spec/support/stubbed_repository.rb b/spec/support/stubbed_repository.rb
index e6e194d70f556b49933093795165988f455cb962..434cab6516e7ad539bb5817b2de45de2ae68a9b0 100644
--- a/spec/support/stubbed_repository.rb
+++ b/spec/support/stubbed_repository.rb
@@ -1,5 +1,6 @@
 require "repository"
 require "project"
+require "shell"
 
 # Stubs out all Git repository access done by models so that specs can run
 # against fake repositories without Grit complaining that they don't exist.
@@ -21,6 +22,10 @@ class Project
       true
     end
 
+    def destroy
+      true
+    end
+
     def create
       true
     end
@@ -32,3 +37,23 @@ class GitLabTestRepo < Repository
     @repo ||= Grit::Repo.new(Rails.root.join('tmp', 'repositories', 'gitlabhq'))
   end
 end
+
+module Gitlab
+  class Shell
+    def add_repository name
+      true
+    end
+
+    def remove_repository name
+      true
+    end
+
+    def add_key id, key
+      true
+    end
+
+    def remove_key id, key
+      true
+    end
+  end
+end
diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb
index f408c89afddf6c487516b8f3e14dbcbed8d746cb..f1a69b1b2e4c7ac5999c620fedb695f6c0090ce3 100644
--- a/spec/workers/post_receive_spec.rb
+++ b/spec/workers/post_receive_spec.rb
@@ -11,7 +11,7 @@ describe PostReceive do
   context "web hook" do
     let(:project) { create(:project) }
     let(:key) { create(:key, user: project.owner) }
-    let(:key_id) { key.identifier }
+    let(:key_id) { key.shell_id }
 
     it "fetches the correct project" do
       Project.should_receive(:find_with_namespace).with(project.path_with_namespace).and_return(project)
@@ -19,7 +19,7 @@ describe PostReceive do
     end
 
     it "does not run if the author is not in the project" do
-      Key.stub(find_by_identifier: nil)
+      Key.stub(find_by_id: nil)
 
       project.should_not_receive(:observe_push)
       project.should_not_receive(:execute_hooks)
diff --git a/vendor/assets/javascripts/branch-graph.js b/vendor/assets/javascripts/branch-graph.js
index 805423bc70d93bd02f2ae306d19f91db822a1b29..7929d3b2a14c867e607d71547883a25dfb452004 100644
--- a/vendor/assets/javascripts/branch-graph.js
+++ b/vendor/assets/javascripts/branch-graph.js
@@ -65,15 +65,16 @@
 
   BranchGraph.prototype.buildGraph = function(){
     var graphWidth = $(this.element).width()
-      , ch = this.mspace * 20 + 20
-      , cw = Math.max(graphWidth, this.mtime * 20 + 20)
+      , ch = this.mspace * 20 + 100
+      , cw = Math.max(graphWidth, this.mtime * 20 + 260)
       , r = Raphael(this.element.get(0), cw, ch)
       , top = r.set()
       , cuday = 0
       , cumonth = ""
       , offsetX = 20
       , offsetY = 60
-      , barWidth = Math.max(graphWidth, this.dayCount * 20 + 80);
+      , barWidth = Math.max(graphWidth, this.dayCount * 20 + 320)
+      , scrollLeft = cw;
     
     this.raphael = r;
     
@@ -103,8 +104,9 @@
     
     for (i = 0; i < this.commitCount; i++) {
       var x = offsetX + 20 * this.commits[i].time
-        , y = offsetY + 20 * this.commits[i].space
-        , c;
+        , y = offsetY + 10 * this.commits[i].space
+        , c
+        , ps;
       
       // Draw dot
       r.circle(x, y, 3).attr({
@@ -115,26 +117,40 @@
       // Draw lines
       for (var j = 0, jj = this.commits[i].parents.length; j < jj; j++) {
         c = this.preparedCommits[this.commits[i].parents[j][0]];
+        ps = this.commits[i].parent_spaces[j];
         if (c) {
           var cx = offsetX + 20 * c.time
-            , cy = offsetY + 20 * c.space;
-          if (c.space == this.commits[i].space) {
+            , cy = offsetY + 10 * c.space
+            , psy = offsetY + 10 * ps;
+          if (c.space == this.commits[i].space && c.space == ps) {
             r.path([
               "M", x, y,
-              "L", x - 20 * (c.time + 1), y
+              "L", cx, cy
             ]).attr({
               stroke: this.colors[c.space], 
               "stroke-width": 2
             });
 
           } else if (c.space < this.commits[i].space) {
-            r.path(["M", x - 5, y + .0001, "l-5-2,0,4,5,-2C", x - 5, y, x - 17, y + 2, x - 20, y - 5, "L", cx, y - 5, cx, cy])
+            r.path([
+                "M", x - 5, y,
+                "l-5-2,0,4,5,-2",
+                "L", x - 10, y,
+                "L", x - 15, psy,
+                "L", cx + 5, psy,
+                "L", cx, cy])
             .attr({
               stroke: this.colors[this.commits[i].space], 
               "stroke-width": 2
             });
           } else {
-            r.path(["M", x - 3, y + 6, "l-4,3,4,2,0,-5L", x - 10, y + 20, "L", x - 10, cy, cx, cy])
+            r.path([
+                "M", x - 3, y + 6,
+                "l-4,3,4,2,0,-5",
+                "L", x - 5, y + 10,
+                "L", x - 10, psy,
+                "L", cx + 5, psy,
+                "L", cx, cy])
             .attr({
               stroke: this.colors[c.space], 
               "stroke-width": 2
@@ -145,12 +161,18 @@
       
       if (this.commits[i].refs) {
         this.appendLabel(x, y, this.commits[i].refs);
+
+        // The main branch is displayed in the center.
+        re = new RegExp('(^| )' + this.options.ref + '( |$)');
+        if (this.commits[i].refs.match(re)) {
+          scrollLeft = x - graphWidth / 2;
+        }
       }
       
       this.appendAnchor(top, this.commits[i], x, y);
     }
     top.toFront();
-    this.element.scrollLeft(cw);
+    this.element.scrollLeft(scrollLeft);
     this.bindEvents();
   };
   
@@ -260,7 +282,7 @@
       cursor: "pointer"
     })
     .click(function(){
-      window.location = options.commit_url.replace('%s', commit.id);
+      window.open(options.commit_url.replace('%s', commit.id), '_blank');
     })
     .hover(function(){
       this.tooltip = r.commitTooltip(x, y + 5, commit);
@@ -351,4 +373,4 @@ function textWrap(t, width) {
   t.attr({
     "y": b.y + h
   });
-}
\ No newline at end of file
+}