diff --git a/.gitignore b/.gitignore
index 912d61a8f0ac12ed507c55094c34f8158b51d5a0..7e621d260fcc3d0cc3a4a4c1d220158d24b8ed0d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,7 +2,7 @@
 .rbx/
 db/*.sqlite3
 db/*.sqlite3-journal
-log/*.log
+log/*.log*
 tmp/
 .sass-cache/
 coverage/*
@@ -20,6 +20,7 @@ config/database.yml
 config/initializers/omniauth.rb
 config/unicorn.rb
 config/resque.yml
+config/aws.yml
 db/data.yml
 .idea
 .DS_Store
diff --git a/Gemfile b/Gemfile
index 01696152b622175d06ca4ac0d73d71514614f07b..4a7db0eb711abd4fdbb3ccadd9dd610b38dd6020 100644
--- a/Gemfile
+++ b/Gemfile
@@ -70,6 +70,9 @@ gem "github-markup", "~> 0.7.4", require: 'github/markup'
 # Servers
 gem "unicorn", "~> 4.4.0"
 
+# State machine
+gem "state_machine"
+
 # Issue tags
 gem "acts-as-taggable-on", "2.3.3"
 
diff --git a/Gemfile.lock b/Gemfile.lock
index 1bc7124fff4e0eb56ec7f712c3b02e8fd0ab3ab9..1b8c58373027054e39f6ae1203d7f32ea834a930 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -425,6 +425,7 @@ GEM
       rack (~> 1.0)
       tilt (~> 1.1, != 1.3.0)
     stamp (0.3.0)
+    state_machine (1.1.2)
     temple (0.5.5)
     test_after_commit (0.0.1)
     therubyracer (0.10.2)
@@ -536,6 +537,7 @@ DEPENDENCIES
   slim
   spinach-rails
   stamp
+  state_machine
   test_after_commit
   therubyracer
   thin
diff --git a/app/assets/javascripts/main.js.coffee b/app/assets/javascripts/main.js.coffee
index 5aaea50cf219592dd4880a1a5a8f1636881629b6..d789f54a4e6b32c4c718535870223331143a950b 100644
--- a/app/assets/javascripts/main.js.coffee
+++ b/app/assets/javascripts/main.js.coffee
@@ -49,6 +49,10 @@ $ ->
   # Bottom tooltip
   $('.has_bottom_tooltip').tooltip(placement: 'bottom')
 
+  # Form submitter
+  $('.trigger-submit').on 'change', ->
+    $(@).parents('form').submit()
+
   # Flash
   if (flash = $("#flash-container")).length > 0
     flash.click -> $(@).slideUp("slow")
diff --git a/app/assets/javascripts/merge_requests.js.coffee b/app/assets/javascripts/merge_requests.js.coffee
index 65ed817c7c6ee0b76ec265eab10bdbff5ed30be7..496da7316fdc7fb46f866263ca7f55df86382eb2 100644
--- a/app/assets/javascripts/merge_requests.js.coffee
+++ b/app/assets/javascripts/merge_requests.js.coffee
@@ -27,7 +27,7 @@ class MergeRequest
     this.$el.find(selector)
 
   initMergeWidget: ->
-    this.showState( @opts.current_state )
+    this.showState( @opts.current_status )
 
     if this.$('.automerge_widget').length and @opts.check_enable
       $.get @opts.url_to_automerge_check, (data) =>
diff --git a/app/assets/stylesheets/gitlab_bootstrap/mixins.scss b/app/assets/stylesheets/gitlab_bootstrap/mixins.scss
index 9b1e2f2c72805c9d1930d2cba213e09815730df5..c8cc9a706789714934f8a964f5e8cca17d48d84a 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/mixins.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/mixins.scss
@@ -63,7 +63,7 @@
   color: $style_color;
   text-shadow: 0 1px 1px #FFF;
   font-family: 'Yanone', sans-serif;
-  font-size: 26px;
-  line-height: 42px;
+  font-size: 24px;
+  line-height: 36px;
   font-weight: normal;
 }
diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss
index 8b93287ed1e25402b649f13d642b3abced087358..a389a9baa841914b0c5c42c415a90f0aed6f508c 100644
--- a/app/assets/stylesheets/sections/commits.scss
+++ b/app/assets/stylesheets/sections/commits.scss
@@ -29,7 +29,7 @@
     a{
       color: $style_color;
     }
-    
+
     > span {
       font-family: $monospace_font;
       font-size: 14px;
@@ -124,7 +124,7 @@
     .wrap{
       display: inline-block;
     }
-    
+
     .frame {
       display: inline-block;
       background-color: #fff;
@@ -149,7 +149,7 @@
 
     .view.swipe{
       position: relative;
-      
+
       .swipe-frame{
         display: block;
         margin: auto;
@@ -228,7 +228,7 @@
         bottom: 0px;
         left: 50%;
         margin-left: -150px;
-        
+
         .drag-track{
           display: block;
           position: absolute;
@@ -237,7 +237,7 @@
           width: 276px;
           background: url('onion_skin_sprites.gif') -4px -20px repeat-x;
         }
-        
+
         .dragger {
           display: block;
           position: absolute;
@@ -248,7 +248,7 @@
           background: url('onion_skin_sprites.gif') 0px -34px repeat-x;
           cursor: pointer;
         }
-        
+
         .transparent {
           display: block;
           position: absolute;
@@ -258,7 +258,7 @@
           width: 10px;
           background: url('onion_skin_sprites.gif') -2px 0px no-repeat;
         }
-        
+
         .opaque {
           display: block;
           position: absolute;
@@ -275,19 +275,19 @@
 
     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;
     }
-    
+
     li{
       color: grey;
       border-left: 1px solid #c1c1c1;
@@ -322,12 +322,12 @@
 }
 .commit-author, .commit-committer{
   display: block;
-  color: #999; 
-  font-weight: normal; 
+  color: #999;
+  font-weight: normal;
   font-style: italic;
 }
 .commit-author strong, .commit-committer strong{
-  font-weight: bold; 
+  font-weight: bold;
   font-style: normal;
 }
 
@@ -337,7 +337,6 @@
  */
 .commit {
   .browse_code_link_holder {
-    @extend .span2;
     float: right;
   }
 
diff --git a/app/assets/stylesheets/sections/header.scss b/app/assets/stylesheets/sections/header.scss
index 5fe18131828b9e875eefabf51a84d0f432ac22cc..05c077a867abb15edc461a6b662143c9c97bc398 100644
--- a/app/assets/stylesheets/sections/header.scss
+++ b/app/assets/stylesheets/sections/header.scss
@@ -5,15 +5,16 @@
 header {
   &.navbar-gitlab {
     .navbar-inner {
-      height: 45px;
-      padding: 5px;
+      height: 40px;
+      padding: 3px;
       background: #F1F1F1;
+      filter: none;
 
       .nav > li > a {
         color: $style_color;
         text-shadow: 0 1px 0 #fff;
-        font-size: 18px;
-        padding: 12px;
+        font-size: 16px;
+        padding: 10px;
       }
 
       /** NAV block with links and profile **/
@@ -25,7 +26,6 @@ header {
   }
 
   z-index: 10;
-  /*height: 60px;*/
 
   /**
    *
@@ -34,7 +34,7 @@ header {
    */
   .app_logo {
     float: left;
-    margin-right: 15px;
+    margin-right: 9px;
     position: relative;
     top: -5px;
     padding-top: 5px;
@@ -42,10 +42,10 @@ header {
     a {
       float: left;
       padding: 0px;
-      margin: 0 10px;
+      margin: 0 6px;
 
       h1 {
-        background: url('logo_dark.png') no-repeat 0px 2px;
+        background: url('logo_dark.png') no-repeat center 1px;
         float: left;
         height: 40px;
         width: 40px;
@@ -79,7 +79,6 @@ header {
   .search {
     margin-right: 45px;
     margin-left: 10px;
-    margin-top: 2px;
 
     .search-input {
       @extend .span2;
@@ -105,7 +104,7 @@ header {
   .account-box {
     position: absolute;
     right: 0;
-    top: 6px;
+    top: 4px;
     z-index: 10000;
     width: 128px;
     font-size: 11px;
@@ -228,6 +227,7 @@ header {
       .search-input {
         background-color: #D2D5DA;
         background-color: rgba(255, 255, 255, 0.5);
+        border: 1px solid #AAA;
 
         &:focus {
           background-color: white;
@@ -240,13 +240,16 @@ header {
     .app_logo {
       a {
         h1 {
-          background: url('logo_white.png') no-repeat center center;
+          background: url('logo_white.png') no-repeat center 1px;
           color: #fff;
           text-shadow: 0 1px 1px #111;
         }
       }
     }
     .project_name {
+      a {
+        color: #FFF;
+      }
       color: #fff;
       text-shadow: 0 1px 1px #111;
     }
@@ -261,11 +264,11 @@ header {
 
   .separator {
     float: left;
-    height: 60px;
+    height: 46px;
     width: 1px;
     background: white;
     border-left: 1px solid #DDD;
-    margin-top: -10px;
+    margin-top: -3px;
     margin-left: 10px;
     margin-right: 10px;
   }
diff --git a/app/assets/stylesheets/sections/projects.scss b/app/assets/stylesheets/sections/projects.scss
index 28df1b5ac28dfe6f3029d253f75f32033bc88158..b37830b138e24e590b1dc71e6dc20b0e6f07f123 100644
--- a/app/assets/stylesheets/sections/projects.scss
+++ b/app/assets/stylesheets/sections/projects.scss
@@ -115,3 +115,7 @@ ul.nav.nav-projects-tabs {
     }
   }
 }
+
+.team_member_row form {
+  margin: 0px;
+}
diff --git a/app/assets/stylesheets/themes/ui_mars.scss b/app/assets/stylesheets/themes/ui_mars.scss
index 0a78c5c09f572fcc4db1dea15d03aca1f6ebc5fc..a2b8c21ea11df88a8e0f97514806bd8273cf9481 100644
--- a/app/assets/stylesheets/themes/ui_mars.scss
+++ b/app/assets/stylesheets/themes/ui_mars.scss
@@ -8,66 +8,27 @@
  *
  */
 .ui_mars {
-
   /*
    *  Application Header
    *
    */
   header {
-
+    @extend .header-dark;
     &.navbar-gitlab {
       .navbar-inner {
-        background: #474D57 url('bg-header.png') repeat-x bottom;
-        border-bottom: 1px solid #444;
-
-        .nav > li > a {
-          color: #eee;
-          text-shadow: 0 1px 0 #444;
+        background: #474D57;
+        border-bottom: 1px solid #373D47;
+        .app_logo {
+          &:hover {
+            background-color: #373D47;
+          }
         }
       }
     }
 
-    .search {
-      float: right;
-      margin-right: 45px;
-      .search-input {
-        border: 1px solid rgba(0, 0, 0, 0.7);
-        background-color: #D2D5DA;
-        background-color: rgba(255, 255, 255, 0.5);
-
-        &:focus {
-          background-color: white;
-        }
-      }
-    }
-    .search-input::-webkit-input-placeholder {
-      color: #666;
-    }
-    .app_logo {
-      a {
-        h1 {
-          background: url('logo_white.png') no-repeat center center;
-          color: #eee;
-          text-shadow: 0 1px 1px #111;
-        }
-      }
-      &:hover {
-        background-color: #41464e;
-      }
-    }
-    .project_name {
-      color: #eee;
-      text-shadow: 0 1px 1px #111;
+    .separator {
+      background: #31363E;
+      border-left: 1px solid #666;
     }
   }
-
-  .separator {
-    background: #31363E;
-    border-left: 1px solid #666;
-  }
-
-  /*
-   *  End of Application Header
-   *
-   */
 }
diff --git a/app/contexts/merge_requests_load_context.rb b/app/contexts/merge_requests_load_context.rb
index 4ec66cd9b78a3fdf070e55f55bf746f251e0bd9d..683f4c83e77f4697af95b439d12003c69b4e50f0 100644
--- a/app/contexts/merge_requests_load_context.rb
+++ b/app/contexts/merge_requests_load_context.rb
@@ -14,7 +14,7 @@ class MergeRequestsLoadContext < BaseContext
                      end
 
     merge_requests = merge_requests.page(params[:page]).per(20)
-    merge_requests = merge_requests.includes(:author, :project).order("closed, created_at desc")
+    merge_requests = merge_requests.includes(:author, :project).order("state, created_at desc")
 
     # Filter by specific assignee_id (or lack thereof)?
     if params[:assignee_id].present?
diff --git a/app/contexts/projects/create_context.rb b/app/contexts/projects/create_context.rb
index 629c5294754cc842ead99314b55660d037949723..fe8dde8c954f737512c38b53e98bbb3a1c6fff8e 100644
--- a/app/contexts/projects/create_context.rb
+++ b/app/contexts/projects/create_context.rb
@@ -38,6 +38,8 @@ module Projects
       if @project.valid? && @project.import_url.present?
         shell = Gitlab::Shell.new
         if shell.import_repository(@project.path_with_namespace, @project.import_url)
+          # We should create satellite for imported repo
+          @project.satellite.create unless @project.satellite.exists?
           true
         else
           @project.errors.add(:import_url, 'cannot clone repo')
diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
index f320e819e26d5f6c091f831c5f6a4016e4ff5095..9fd477dcdb65c554f73a4716c76534bdd8f03814 100644
--- a/app/controllers/dashboard_controller.rb
+++ b/app/controllers/dashboard_controller.rb
@@ -5,7 +5,7 @@ class DashboardController < ApplicationController
   before_filter :event_filter, only: :show
 
   def show
-    @groups = current_user.authorized_groups
+    @groups = current_user.authorized_groups.sort_by(&:human_name)
     @has_authorized_projects = @projects.count > 0
     @teams = current_user.authorized_teams
     @projects_count = @projects.count
diff --git a/app/controllers/files_controller.rb b/app/controllers/files_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..3cd2e77322c318d954547092c40e37d6335bd349
--- /dev/null
+++ b/app/controllers/files_controller.rb
@@ -0,0 +1,13 @@
+class FilesController < ApplicationController
+  def download
+    note = Note.find(params[:id])
+
+    if can?(current_user, :read_project, note.project)
+      uploader = note.attachment
+      send_file uploader.file.path, disposition: 'attachment'
+    else
+      not_found!
+    end
+  end
+end
+
diff --git a/app/controllers/merge_requests_controller.rb b/app/controllers/merge_requests_controller.rb
index ab6bf595982bdb63092dd8e1cda3361fdeeaeceb..bf6652726d2260cf98f9bd1624bcd23922741abd 100644
--- a/app/controllers/merge_requests_controller.rb
+++ b/app/controllers/merge_requests_controller.rb
@@ -73,14 +73,14 @@ class MergeRequestsController < ProjectResourceController
     if @merge_request.unchecked?
       @merge_request.check_if_can_be_merged
     end
-    render json: {state: @merge_request.human_state}
+    render json: {merge_status: @merge_request.human_merge_status}
   rescue Gitlab::SatelliteNotExistError
-    render json: {state: :no_satellite}
+    render json: {merge_status: :no_satellite}
   end
 
   def automerge
     return access_denied! unless can?(current_user, :accept_mr, @project)
-    if @merge_request.open? && @merge_request.can_be_merged?
+    if @merge_request.opened? && @merge_request.can_be_merged?
       @merge_request.should_remove_source_branch = params[:should_remove_source_branch]
       @merge_request.automerge!(current_user)
       @status = true
diff --git a/app/controllers/milestones_controller.rb b/app/controllers/milestones_controller.rb
index a0c824e8abb0919006ab1c151a13b53ad25ac398..57f1e9e6bb341f965ff8d04889468a73c7c4fcdc 100644
--- a/app/controllers/milestones_controller.rb
+++ b/app/controllers/milestones_controller.rb
@@ -12,7 +12,7 @@ class MilestonesController < ProjectResourceController
 
   def index
     @milestones = case params[:f]
-                  when 'all'; @project.milestones.order("closed, due_date DESC")
+                  when 'all'; @project.milestones.order("state, due_date DESC")
                   when 'closed'; @project.milestones.closed.order("due_date DESC")
                   else @project.milestones.active.order("due_date ASC")
                   end
diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb
index 1d1efb16f042c0cef0c3200756b660715553b4bf..051a6664519c265e201fc00a244a9881211504ea 100644
--- a/app/controllers/profiles_controller.rb
+++ b/app/controllers/profiles_controller.rb
@@ -51,7 +51,9 @@ class ProfilesController < ApplicationController
   end
 
   def update_username
-    @user.update_attributes(username: params[:user][:username])
+    if @user.can_change_username?
+      @user.update_attributes(username: params[:user][:username])
+    end
 
     respond_to do |format|
       format.js
diff --git a/app/controllers/team_members_controller.rb b/app/controllers/team_members_controller.rb
index 18d4ae3ac96df8fde06d01d54aaa1bc72e59f26f..04348dc7977db927a96d6fa3761e099987869496 100644
--- a/app/controllers/team_members_controller.rb
+++ b/app/controllers/team_members_controller.rb
@@ -4,7 +4,11 @@ class TeamMembersController < ProjectResourceController
   before_filter :authorize_admin_project!, except: [:index, :show]
 
   def index
-    @teams = UserTeam.scoped
+    @team = @project.users_projects.scoped
+    @team = @team.send(params[:type]) if %w(masters developers reporters guests).include?(params[:type])
+    @team = @team.sort_by(&:project_access).reverse.group_by(&:project_access)
+
+    @assigned_teams = @project.user_team_project_relationships
   end
 
   def show
diff --git a/app/controllers/teams/members_controller.rb b/app/controllers/teams/members_controller.rb
index db218b8ca5e726aa97e87341f442e5001fed2273..ead62e13afac8a6f8f8790eaf088f49ffb01b417 100644
--- a/app/controllers/teams/members_controller.rb
+++ b/app/controllers/teams/members_controller.rb
@@ -27,7 +27,13 @@ class Teams::MembersController < Teams::ApplicationController
   end
 
   def update
-    options = {default_projects_access: params[:default_project_access], group_admin: params[:group_admin]}
+    member_params = params[:team_member]
+
+    options = {
+      default_projects_access: member_params[:permission],
+      group_admin: member_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
@@ -45,5 +51,4 @@ class Teams::MembersController < Teams::ApplicationController
   def team_member
     @member ||= user_team.members.find_by_username(params[:id])
   end
-
 end
diff --git a/app/controllers/teams_controller.rb b/app/controllers/teams_controller.rb
index ef66b77e23290d4f80cf92dd9607078a27647c7c..4861892d36e66306eeff190fa039a2f40446776a 100644
--- a/app/controllers/teams_controller.rb
+++ b/app/controllers/teams_controller.rb
@@ -9,13 +9,11 @@ class TeamsController < ApplicationController
   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
@@ -41,6 +39,9 @@ class TeamsController < ApplicationController
     @team.path = @team.name.dup.parameterize if @team.name
 
     if @team.save
+      # Add current user as Master to the team
+      @team.add_members([current_user.id], UsersProject::MASTER, true)
+
       redirect_to team_path(@team)
     else
       render action: :new
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 196105f011900ea89b815e6d751166c9df8510c2..d02130c5eb1056717ed5def41be0a956cb6b680a 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -73,8 +73,8 @@ module ApplicationHelper
 
   def search_autocomplete_source
     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) } }
+    groups = current_user.authorized_groups.map { |group| { label: "group: #{simple_sanitize(group.name)}", url: group_path(group) } }
+    teams = current_user.authorized_teams.map { |team| { label: "team: #{simple_sanitize(team.name)}", url: team_path(team) } }
 
     default_nav = [
       { label: "My Profile", url: profile_path },
@@ -159,8 +159,13 @@ module ApplicationHelper
               alt: "Sign in with #{provider.to_s.titleize}")
   end
 
+  def simple_sanitize str
+    sanitize(str, tags: %w(a span))
+  end
+
   def image_url(source)
     root_url + path_to_image(source)
   end
+
   alias_method :url_to_image, :image_url
 end
diff --git a/app/helpers/dashboard_helper.rb b/app/helpers/dashboard_helper.rb
index c759dffa16e1fcd501ad348dfc53509fdd594fa0..e3be07c9fe0a8da06e5bc6e150cd720c4dd2ee2e 100644
--- a/app/helpers/dashboard_helper.rb
+++ b/app/helpers/dashboard_helper.rb
@@ -27,6 +27,6 @@ module DashboardHelper
               items.opened
             end
 
-    items.where(assignee_id: current_user.id).count
+    items.cared(current_user).count
   end
 end
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index 2825787fd2f3c6cd2031e32801d2e6e90ce9ae17..ed7e3e869c0db739f90f69d0bc911fbe0cab1639 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -6,7 +6,7 @@ module IssuesHelper
 
   def issue_css_classes issue
     classes = "issue"
-    classes << " closed" if issue.closed
+    classes << " closed" if issue.closed?
     classes << " today" if issue.today?
     classes
   end
diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb
index ca0a89c374923ac203ba36b1709066bdd623e321..155d03d1147ee1ae58b91546b160d72b5f8bed69 100644
--- a/app/helpers/merge_requests_helper.rb
+++ b/app/helpers/merge_requests_helper.rb
@@ -12,7 +12,7 @@ module MergeRequestsHelper
 
   def mr_css_classes mr
     classes = "merge_request"
-    classes << " closed" if mr.closed
+    classes << " closed" if mr.closed?
     classes << " merged" if mr.merged?
     classes
   end
diff --git a/app/helpers/namespaces_helper.rb b/app/helpers/namespaces_helper.rb
index 6d0c6c981917dce72d8f5dc8f36efbd09f650e8b..a9a6c78654f2fcc499fb24120a425c20b46d249a 100644
--- a/app/helpers/namespaces_helper.rb
+++ b/app/helpers/namespaces_helper.rb
@@ -10,8 +10,8 @@ module NamespacesHelper
 
 
     global_opts = ["Global", [['/', Namespace.global_id]] ]
-    group_opts = ["Groups", groups.map {|g| [g.human_name, g.id]} ]
-    users_opts = [ "Users", users.map {|u| [u.human_name, u.id]} ]
+    group_opts = ["Groups", groups.sort_by(&:human_name).map {|g| [g.human_name, g.id]} ]
+    users_opts = [ "Users", users.sort_by(&:human_name).map {|u| [u.human_name, u.id]} ]
 
     options = []
     options << global_opts if current_user.admin
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 05303e86ae8977143a6730022007c09b48127119..2c7984c071e5f4231de8f2770ca911178fa3efb3 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -1,12 +1,4 @@
 module ProjectsHelper
-  def grouper_project_members(project)
-    @project.users_projects.sort_by(&:project_access).reverse.group_by(&:project_access)
-  end
-
-  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
@@ -56,7 +48,7 @@ module ProjectsHelper
   def project_title project
     if project.group
       content_tag :span do
-        link_to(project.group.name, group_path(project.group)) + " / " + project.name
+        link_to(simple_sanitize(project.group.name), group_path(project.group)) + " / " + project.name
       end
     else
       project.name
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 6d087a959a9320f9f744f217619b997fcbd8942c..6fda2e52c7c6fdfc50371c01b35db4394785efa1 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -123,7 +123,7 @@ class Ability
     def user_team_abilities user, team
       rules = []
 
-      # Only group owner and administrators can manage group
+      # Only group owner and administrators can manage team
       if team.owner == user || team.admin?(user) || user.admin?
         rules << [ :manage_user_team ]
       end
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index 645b35ec660506107683f23186c626c277b25ac9..85337583640b4db3ec1b50a633f8e0f0e07122fb 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -17,10 +17,9 @@ module Issuable
     validates :project, presence: true
     validates :author, presence: true
     validates :title, presence: true, length: { within: 0..255 }
-    validates :closed, inclusion: { in: [true, false] }
 
-    scope :opened, -> { where(closed: false) }
-    scope :closed, -> { where(closed: true) }
+    scope :opened, -> { with_state(:opened) }
+    scope :closed, -> { with_state(:closed) }
     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)}
@@ -62,14 +61,6 @@ module Issuable
     assignee_id_changed?
   end
 
-  def is_being_closed?
-    closed_changed? && closed
-  end
-
-  def is_being_reopened?
-    closed_changed? && !closed
-  end
-
   #
   # Votes
   #
diff --git a/app/models/event.rb b/app/models/event.rb
index 18422e192a4870c4bf3c54e55111df57dfeef572..ae14454c59a34ad0603cc5f73c2cdc4018733d0f 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -130,10 +130,6 @@ class Event < ActiveRecord::Base
     target if target_type == "MergeRequest"
   end
 
-  def author
-    @author ||= User.find(author_id)
-  end
-
   def action_name
     if closed?
       "closed"
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 07c0401143c8050f35aad274ee2e71abdbf7a091..112f43c4692b08dc0e1827010c94a10ff72b79ab 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -9,7 +9,7 @@
 #  project_id   :integer
 #  created_at   :datetime         not null
 #  updated_at   :datetime         not null
-#  closed       :boolean          default(FALSE), not null
+#  state        :string           default(FALSE), not null
 #  position     :integer          default(0)
 #  branch_name  :string(255)
 #  description  :text
@@ -19,12 +19,35 @@
 class Issue < ActiveRecord::Base
   include Issuable
 
-  attr_accessible :title, :assignee_id, :closed, :position, :description,
-                  :milestone_id, :label_list, :author_id_of_changes
+  attr_accessible :title, :assignee_id, :position, :description,
+                  :milestone_id, :label_list, :author_id_of_changes,
+                  :state_event
 
   acts_as_taggable_on :labels
 
-  def self.open_for(user)
-    opened.assigned(user)
+  class << self
+    def cared(user)
+      where('assignee_id = :user', user: user.id)
+    end
+
+    def open_for(user)
+      opened.assigned(user)
+    end
+  end
+
+  state_machine :state, initial: :opened do
+    event :close do
+      transition [:reopened, :opened] => :closed
+    end
+
+    event :reopen do
+      transition closed: :reopened
+    end
+
+    state :opened
+
+    state :reopened
+
+    state :closed
   end
 end
diff --git a/app/models/key.rb b/app/models/key.rb
index 895e8d6cb9ccbab7693ceb422fa19529286760b0..edb0bcd61fd237f8a3fe1a794af0feddcca77f64 100644
--- a/app/models/key.rb
+++ b/app/models/key.rb
@@ -35,7 +35,7 @@ class Key < ActiveRecord::Base
 
   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
+
     file = Tempfile.new('key_file')
     begin
       file.puts key
@@ -45,7 +45,7 @@ class Key < ActiveRecord::Base
       file.close
       file.unlink # deletes the temp file
     end
-    errors.add(:key, "can't be fingerprinted") if fingerprint_output.match("failed")
+    errors.add(:key, "can't be fingerprinted") if $?.exitstatus != 0
   end
 
   def set_identifier
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 345b8d6e07d53344a41587aa7e420dd23edf74e1..06aa9f3c9e02ad9e8d74bd9fbcfce36fb0699997 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -9,15 +9,14 @@
 #  author_id     :integer
 #  assignee_id   :integer
 #  title         :string(255)
-#  closed        :boolean          default(FALSE), not null
+#  state         :string(255)      not null
 #  created_at    :datetime         not null
 #  updated_at    :datetime         not null
 #  st_commits    :text(2147483647)
 #  st_diffs      :text(2147483647)
-#  merged        :boolean          default(FALSE), not null
-#  state         :integer          default(1), not null
-#  milestone_id  :integer
+#  merge_status  :integer          default(1), not null
 #
+#  milestone_id  :integer
 
 require Rails.root.join("app/models/commit")
 require Rails.root.join("lib/static_model")
@@ -25,11 +24,33 @@ require Rails.root.join("lib/static_model")
 class MergeRequest < ActiveRecord::Base
   include Issuable
 
-  attr_accessible :title, :assignee_id, :closed, :target_branch, :source_branch, :milestone_id,
-                  :author_id_of_changes
+  attr_accessible :title, :assignee_id, :target_branch, :source_branch, :milestone_id,
+                  :author_id_of_changes, :state_event
 
   attr_accessor :should_remove_source_branch
 
+  state_machine :state, initial: :opened do
+    event :close do
+      transition [:reopened, :opened] => :closed
+    end
+
+    event :merge do
+      transition [:reopened, :opened] => :merged
+    end
+
+    event :reopen do
+      transition closed: :reopened
+    end
+
+    state :opened
+
+    state :reopened
+
+    state :closed
+
+    state :merged
+  end
+
   BROKEN_DIFF = "--broken-diff"
 
   UNCHECKED = 1
@@ -43,21 +64,33 @@ class MergeRequest < ActiveRecord::Base
   validates :target_branch, presence: true
   validate :validate_branches
 
-  def self.find_all_by_branch(branch_name)
-    where("source_branch LIKE :branch OR target_branch LIKE :branch", branch: branch_name)
-  end
+  scope :merged, -> { with_state(:merged) }
 
-  def self.find_all_by_milestone(milestone)
-    where("milestone_id = :milestone_id", milestone_id: milestone)
+  class << self
+    def find_all_by_branch(branch_name)
+      where("source_branch LIKE :branch OR target_branch LIKE :branch", branch: branch_name)
+    end
+
+    def cared(user)
+      where('assignee_id = :user OR author_id = :user', user: user.id)
+    end
+
+    def find_all_by_branch(branch_name)
+      where("source_branch LIKE :branch OR target_branch LIKE :branch", branch: branch_name)
+    end
+
+    def find_all_by_milestone(milestone)
+      where("milestone_id = :milestone_id", milestone_id: milestone)
+    end
   end
 
-  def human_state
-    states = {
+  def human_merge_status
+    merge_statuses = {
       CAN_BE_MERGED =>  "can_be_merged",
       CANNOT_BE_MERGED => "cannot_be_merged",
       UNCHECKED => "unchecked"
     }
-    states[self.state]
+    merge_statuses[self.merge_status]
   end
 
   def validate_branches
@@ -72,20 +105,20 @@ class MergeRequest < ActiveRecord::Base
   end
 
   def unchecked?
-    state == UNCHECKED
+    merge_status == UNCHECKED
   end
 
   def mark_as_unchecked
-    self.state = UNCHECKED
+    self.merge_status = UNCHECKED
     self.save
   end
 
   def can_be_merged?
-    state == CAN_BE_MERGED
+    merge_status == CAN_BE_MERGED
   end
 
   def check_if_can_be_merged
-    self.state = if Gitlab::Satellite::MergeAction.new(self.author, self).can_be_merged?
+    self.merge_status = if Gitlab::Satellite::MergeAction.new(self.author, self).can_be_merged?
                    CAN_BE_MERGED
                  else
                    CANNOT_BE_MERGED
@@ -98,7 +131,7 @@ class MergeRequest < ActiveRecord::Base
   end
 
   def reloaded_diffs
-    if open? && unmerged_diffs.any?
+    if opened? && unmerged_diffs.any?
       self.st_diffs = unmerged_diffs
       self.save
     end
@@ -128,10 +161,6 @@ class MergeRequest < ActiveRecord::Base
     commits.first
   end
 
-  def merged?
-    merged && merge_event
-  end
-
   def merge_event
     self.project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::MERGED).last
   end
@@ -146,26 +175,16 @@ class MergeRequest < ActiveRecord::Base
 
   def probably_merged?
     unmerged_commits.empty? &&
-      commits.any? && open?
-  end
-
-  def open?
-    !closed
-  end
-
-  def mark_as_merged!
-    self.merged = true
-    self.closed = true
-    save
+      commits.any? && opened?
   end
 
   def mark_as_unmergable
-    self.state = CANNOT_BE_MERGED
+    self.merge_status = CANNOT_BE_MERGED
     self.save
   end
 
   def reloaded_commits
-    if open? && unmerged_commits.any?
+    if opened? && unmerged_commits.any?
       self.st_commits = unmerged_commits
       save
     end
@@ -181,7 +200,8 @@ class MergeRequest < ActiveRecord::Base
   end
 
   def merge!(user_id)
-    self.mark_as_merged!
+    self.merge
+
     Event.create(
       project: self.project,
       action: Event::MERGED,
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index 457fe18f35b9fb689e3fc27b3a0b5c7002745a71..d822a68dc7a3cee30fcab7b6fc51014a7197f1d8 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -13,19 +13,32 @@
 #
 
 class Milestone < ActiveRecord::Base
-  attr_accessible :title, :description, :due_date, :closed, :author_id_of_changes
+  attr_accessible :title, :description, :due_date, :state_event, :author_id_of_changes
   attr_accessor :author_id_of_changes
 
   belongs_to :project
   has_many :issues
   has_many :merge_requests
 
-  scope :active, -> { where(closed: false) }
-  scope :closed, -> { where(closed: true) }
+  scope :active, -> { with_state(:active) }
+  scope :closed, -> { with_state(:closed) }
 
   validates :title, presence: true
   validates :project, presence: true
-  validates :closed, inclusion: { in: [true, false] }
+
+  state_machine :state, initial: :active do
+    event :close do
+      transition active: :closed
+    end
+
+    event :activate do
+      transition closed: :active
+    end
+
+    state :closed
+
+    state :active
+  end
 
   def expired?
     if due_date
@@ -68,17 +81,13 @@ class Milestone < ActiveRecord::Base
   end
 
   def can_be_closed?
-    open? && issues.opened.count.zero?
+    active? && issues.opened.count.zero?
   end
 
   def is_empty?
     total_items_count.zero?
   end
 
-  def open?
-    !closed
-  end
-
   def author_id
     author_id_of_changes
   end
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 4e157839369bdab3ff6c41ce013e195aeb704ce6..385fa291b4800a5b9337c48ad1b953075631f093 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -17,11 +17,15 @@ class Namespace < ActiveRecord::Base
   has_many :projects, dependent: :destroy
   belongs_to :owner, class_name: "User"
 
-  validates :name, presence: true, uniqueness: true
+  validates :owner, presence: true
+  validates :name, presence: true, uniqueness: true,
+            length: { within: 0..255 },
+            format: { with: Gitlab::Regex.name_regex,
+                      message: "only letters, digits, spaces & '_' '-' '.' allowed." }
+
   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" }
-  validates :owner, presence: true
 
   delegate :name, to: :owner, allow_nil: true, prefix: true
 
diff --git a/app/models/project.rb b/app/models/project.rb
index 9c62e08fb82c339ff01ebacbe64e52c143233ddf..54bfb88e915840cb6cfc673f9bf896f084c16902 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -43,7 +43,7 @@ class Project < ActiveRecord::Base
 
   has_many :events,             dependent: :destroy
   has_many :merge_requests,     dependent: :destroy
-  has_many :issues,             dependent: :destroy, order: "closed, created_at DESC"
+  has_many :issues,             dependent: :destroy, order: "state, created_at DESC"
   has_many :milestones,         dependent: :destroy
   has_many :users_projects,     dependent: :destroy
   has_many :notes,              dependent: :destroy
@@ -146,7 +146,7 @@ class Project < ActiveRecord::Base
   end
 
   def saved?
-    id && valid?
+    id && persisted?
   end
 
   def import?
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 37431fe3b0ec0385cb5a88e3b95c20ade2489035..a5ca5533e086d21d4fca488a8f5505999dc69d75 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -132,16 +132,16 @@ class Repository
     return nil unless commit
 
     # Build file path
-    file_name = self.path_with_namespace + "-" + commit.id.to_s + ".tar.gz"
+    file_name = self.path_with_namespace.gsub("/","_") + "-" + commit.id.to_s + ".tar.gz"
     storage_path = Rails.root.join("tmp", "repositories")
-    file_path = File.join(storage_path, file_name)
+    file_path = File.join(storage_path, self.path_with_namespace, file_name)
 
     # Put files into a directory before archiving
     prefix = self.path_with_namespace + "/"
 
     # Create file if not exists
     unless File.exists?(file_path)
-      FileUtils.mkdir_p storage_path
+      FileUtils.mkdir_p File.dirname(file_path)
       file = self.repo.archive_to_file(ref, prefix,  file_path)
     end
 
diff --git a/app/models/user.rb b/app/models/user.rb
index 10af9b8c16599bc9acab6d9564f54ecc0bc73ce3..4ed31c7edce02e563a0c4ac0e02a7f60bc5e2cad 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -234,8 +234,12 @@ class User < ActiveRecord::Base
     keys.count == 0
   end
 
+  def can_change_username?
+    Gitlab.config.gitlab.username_changing_enabled
+  end
+
   def can_create_project?
-    projects_limit > personal_projects.count
+    projects_limit > owned_projects.count
   end
 
   def can_create_group?
@@ -263,7 +267,7 @@ class User < ActiveRecord::Base
   end
 
   def cared_merge_requests
-    MergeRequest.where("author_id = :id or assignee_id = :id", id: self.id)
+    MergeRequest.cared(self)
   end
 
   # Remove user from all projects and
diff --git a/app/models/user_team.rb b/app/models/user_team.rb
index dc8cf9eeb22dede1712ef000cd49f72544a99843..2f3091c2353ab5d5d81120b046e66ddc4773c0ea 100644
--- a/app/models/user_team.rb
+++ b/app/models/user_team.rb
@@ -21,8 +21,11 @@ class UserTeam < ActiveRecord::Base
   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 :name, presence: true, uniqueness: true,
+            length: { within: 0..255 },
+            format: { with: Gitlab::Regex.name_regex,
+                      message: "only letters, digits, spaces & '_' '-' '.' allowed." }
   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" }
diff --git a/app/models/user_team_project_relationship.rb b/app/models/user_team_project_relationship.rb
index a7aa88970c77f5faeeed7534d4dc5ea48032d828..991510be9368d6e2d13e5c8bb1cc8620d9665848 100644
--- a/app/models/user_team_project_relationship.rb
+++ b/app/models/user_team_project_relationship.rb
@@ -26,6 +26,10 @@ class UserTeamProjectRelationship < ActiveRecord::Base
     user_team.name
   end
 
+  def human_max_access
+    UserTeam.access_roles.key(greatest_access)
+  end
+
   private
 
   def check_greatest_access
diff --git a/app/observers/activity_observer.rb b/app/observers/activity_observer.rb
index b568bb6b763718b3c82b14a641b98972bf337734..9c72a6d33f9c9f604f6be1a740b7e6d15330657d 100644
--- a/app/observers/activity_observer.rb
+++ b/app/observers/activity_observer.rb
@@ -20,15 +20,23 @@ class ActivityObserver < ActiveRecord::Observer
     end
   end
 
-  def after_save(record)
-    if record.changed.include?("closed") && record.author_id_of_changes
+  def after_close(record, transition)
       Event.create(
         project: record.project,
         target_id: record.id,
         target_type: record.class.name,
-        action: (record.closed ? Event::CLOSED : Event::REOPENED),
+        action: Event::CLOSED,
+        author_id: record.author_id_of_changes
+      )
+  end
+
+  def after_reopen(record, transition)
+      Event.create(
+        project: record.project,
+        target_id: record.id,
+        target_type: record.class.name,
+        action: Event::REOPENED,
         author_id: record.author_id_of_changes
       )
-    end
   end
 end
diff --git a/app/observers/issue_observer.rb b/app/observers/issue_observer.rb
index 262d0f892c40e36fdc720a7e671824c650ddc2b0..592e2950f3785558013dc223cb8faa4dced3a057 100644
--- a/app/observers/issue_observer.rb
+++ b/app/observers/issue_observer.rb
@@ -7,22 +7,31 @@ class IssueObserver < ActiveRecord::Observer
     end
   end
 
-  def after_update(issue)
+  def after_close(issue, transition)
     send_reassigned_email(issue) if issue.is_being_reassigned?
 
-    status = nil
-    status = 'closed' if issue.is_being_closed?
-    status = 'reopened' if issue.is_being_reopened?
-    if status
-      Note.create_status_change_note(issue, current_user, status)
-      [issue.author, issue.assignee].compact.each do |recipient|
-        Notify.delay.issue_status_changed_email(recipient.id, issue.id, status, current_user.id)
-      end
-    end
+    create_note(issue)
+  end
+
+  def after_reopen(issue, transition)
+    send_reassigned_email(issue) if issue.is_being_reassigned?
+
+    create_note(issue)
+  end
+
+  def after_update(issue)
+    send_reassigned_email(issue) if issue.is_being_reassigned?
   end
 
   protected
 
+  def create_note(issue)
+    Note.create_status_change_note(issue, current_user, issue.state)
+    [issue.author, issue.assignee].compact.each do |recipient|
+      Notify.delay.issue_status_changed_email(recipient.id, issue.id, issue.state, current_user.id)
+    end
+  end
+
   def send_reassigned_email(issue)
     recipient_ids = [issue.assignee_id, issue.assignee_id_was].keep_if {|id| id && id != current_user.id }
 
diff --git a/app/observers/merge_request_observer.rb b/app/observers/merge_request_observer.rb
index 6d3c2bdd18638da3b11ce401091d3745b806e737..d89e7734c1ae63396186d063265f136f5a0317aa 100644
--- a/app/observers/merge_request_observer.rb
+++ b/app/observers/merge_request_observer.rb
@@ -7,15 +7,20 @@ class MergeRequestObserver < ActiveRecord::Observer
     end
   end
 
-  def after_update(merge_request)
+  def after_close(merge_request, transition)
     send_reassigned_email(merge_request) if merge_request.is_being_reassigned?
 
-    status = nil
-    status = 'closed' if merge_request.is_being_closed?
-    status = 'reopened' if merge_request.is_being_reopened?
-    if status
-      Note.create_status_change_note(merge_request, current_user, status)
-    end
+    Note.create_status_change_note(merge_request, current_user, merge_request.state)
+  end
+
+  def after_reopen(merge_request, transition)
+    send_reassigned_email(merge_request) if merge_request.is_being_reassigned?
+
+    Note.create_status_change_note(merge_request, current_user, merge_request.state)
+  end
+
+  def after_update(merge_request)
+    send_reassigned_email(merge_request) if merge_request.is_being_reassigned?
   end
 
   protected
diff --git a/app/uploaders/attachment_uploader.rb b/app/uploaders/attachment_uploader.rb
index 3dbf2860bd4477000a17304bd122eae38f5b321e..200700b8810935111e64d22c247a15ce0c3704a5 100644
--- a/app/uploaders/attachment_uploader.rb
+++ b/app/uploaders/attachment_uploader.rb
@@ -19,4 +19,12 @@ class AttachmentUploader < CarrierWave::Uploader::Base
   rescue
     false
   end
+
+  def secure_url
+    if self.class.storage == CarrierWave::Storage::File
+      "/files/#{model.class.to_s.underscore}/#{model.id}/#{file.filename}"
+    else
+      url
+    end
+  end
 end
diff --git a/app/views/admin/groups/index.html.haml b/app/views/admin/groups/index.html.haml
index 25ce66575bfa79def312b6315fcfa9b0dbea7ce2..6d5a293ef7ff45f7fa2f5e2c41c8c81de2a33e52 100644
--- a/app/views/admin/groups/index.html.haml
+++ b/app/views/admin/groups/index.html.haml
@@ -28,7 +28,7 @@
       %td= group.path
       %td= group.projects.count
       %td
-        = link_to group.owner_name, admin_user_path(group.owner_id)
+        = link_to group.owner_name, admin_user_path(group.owner)
       %td.bgred
         = 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"
diff --git a/app/views/admin/teams/index.html.haml b/app/views/admin/teams/index.html.haml
index 1f2f4763f76e4a2cd71ae6d346193177bbc4636a..bb0487d43e9c127d9bdd08f73fe6b02188d909e8 100644
--- a/app/views/admin/teams/index.html.haml
+++ b/app/views/admin/teams/index.html.haml
@@ -30,7 +30,7 @@
       %td= team.projects.count
       %td= team.members.count
       %td
-        = link_to team.owner.name, admin_user_path(team.owner_id)
+        = link_to team.owner.name, admin_user_path(team.owner)
       %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"
diff --git a/app/views/commits/_commit.html.haml b/app/views/commits/_commit.html.haml
index eb0312d01e1fc74822da0e041f181c5ad62482db..2f5ff130f03d1d47a993dcee9aaff4d10aa9fb5f 100644
--- a/app/views/commits/_commit.html.haml
+++ b/app/views/commits/_commit.html.haml
@@ -6,9 +6,9 @@
     = link_to commit.short_id(8), project_commit_path(@project, commit), class: "commit_short_id"
     = commit.author_link avatar: true, size: 24
     &nbsp;
-    = link_to_gfm truncate(commit.title, length: 50), project_commit_path(@project, commit.id), class: "row_title"
+    = link_to_gfm truncate(commit.title, length: 70), project_commit_path(@project, commit.id), class: "row_title"
 
-    %span.committed_ago
+    %time.committed_ago{ datetime: commit.committed_date, title: commit.committed_date.stamp("Aug 21, 2011 9:23pm") }
       = time_ago_in_words(commit.committed_date)
       ago
       &nbsp;
diff --git a/app/views/events/event/_note.html.haml b/app/views/events/event/_note.html.haml
index 20c3b927067938c151349a1d8fb37fe7cd8c2054..19665ce0aeaebace6b5bbb1bbb2e0bb23198bb5a 100644
--- a/app/views/events/event/_note.html.haml
+++ b/app/views/events/event/_note.html.haml
@@ -26,7 +26,7 @@
     = markdown truncate(event.target.note, length: 70)
     - note = event.target
     - if note.attachment.url
-      = link_to note.attachment.url, target: "_blank", class: 'note-file-attach' do
+      = link_to note.attachment.secure_url, target: "_blank", class: 'note-file-attach' do
         - if note.attachment.image?
           = image_tag note.attachment.url, class: 'note-image-attach'
         - else
diff --git a/app/views/groups/_filter.html.haml b/app/views/groups/_filter.html.haml
index c14fc8e5e4b725440a35f3a5e27d3266b8d4bd5c..5c66f97753137c89b32fb5e1901dfa3b7daca96f 100644
--- a/app/views/groups/_filter.html.haml
+++ b/app/views/groups/_filter.html.haml
@@ -26,6 +26,8 @@
             = link_to group_filter_path(entity, project_id: project.id) do
               = project.name_with_namespace
               %small.pull-right= entities_per_project(project, entity)
+      - if @projects.blank?
+        %p.nothing_here_message This group has no projects yet
 
   %fieldset
     %hr
diff --git a/app/views/groups/_people_filter.html.haml b/app/views/groups/_people_filter.html.haml
index 901a037adf32f46cb534887cf839284b6763fbbb..ee63743eb4fa95586ccbe7eb5667f2a77ae3f19b 100644
--- a/app/views/groups/_people_filter.html.haml
+++ b/app/views/groups/_people_filter.html.haml
@@ -7,6 +7,8 @@
           = link_to people_group_path(@group, project_id: project.id) do
             = project.name_with_namespace
             %small.pull-right= project.users.count
+      - if @projects.blank?
+        %p.nothing_here_message This group has no projects yet
 
   %fieldset
     %hr
diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml
index 7202ef26c70af5f4a3f7f06f38d46e480bf7ab5d..41ebf60698bab97f9c6c6a3d40c026795d3803b6 100644
--- a/app/views/groups/edit.html.haml
+++ b/app/views/groups/edit.html.haml
@@ -30,6 +30,8 @@
               = 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"
+        - if @group.projects.blank?
+          %p.nothing_here_message This group has no projects yet
 
   .span5
     .ui-box
diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml
index 1a4411c8f30e8393022188fbd82cfd66bb0f55c0..879a19fdfb4117e28460d85df509222e7b43c792 100644
--- a/app/views/help/index.html.haml
+++ b/app/views/help/index.html.haml
@@ -1,8 +1,8 @@
 %h3.page_title
   GITLAB
   .pull-right
-    %span= Gitlab::Version
-    %small= Gitlab::Revision
+    %span= Gitlab::VERSION
+    %small= Gitlab::REVISION
 %hr
 %p.lead
   Self Hosted Git Management
diff --git a/app/views/issues/_show.html.haml b/app/views/issues/_show.html.haml
index fa888618066628be9e63596df8c7e6b766d3a50e..3d1ecd438818207d0b79438f063a6c1514345590 100644
--- a/app/views/issues/_show.html.haml
+++ b/app/views/issues/_show.html.haml
@@ -8,10 +8,10 @@
         %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 btn-small grouped reopen_issue", remote: true
+      - if issue.closed?
+        = link_to 'Reopen', project_issue_path(issue.project, issue, issue: {state_event: :reopen }, 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 btn-small grouped close_issue", remote: true
+        = link_to 'Close', project_issue_path(issue.project, issue, issue: {state_event: :close }, 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/show.html.haml b/app/views/issues/show.html.haml
index 474955cc665c78d6620b25b329a40c52235bb800..f1a97e10913a27c4fb11501ed507157b7c0bcccd 100644
--- a/app/views/issues/show.html.haml
+++ b/app/views/issues/show.html.haml
@@ -7,10 +7,10 @@
 
   %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"
+      - if @issue.closed?
+        = link_to 'Reopen', project_issue_path(@project, @issue, issue: {state_event: :reopen }, status_only: true), method: :put,  class: "btn grouped reopen_issue"
       - else
-        = link_to 'Close', project_issue_path(@project, @issue, issue: {closed: true }, status_only: true), method: :put, class: "btn grouped close_issue", title: "Close Issue"
+        = link_to 'Close', project_issue_path(@project, @issue, issue: {state_event: :close }, status_only: true), method: :put, class: "btn grouped close_issue", title: "Close Issue"
     - if can?(current_user, :admin_project, @project) || @issue.author == current_user
       = link_to edit_project_issue_path(@project, @issue), class: "btn grouped" do
         %i.icon-edit
@@ -27,7 +27,7 @@
 .ui-box.ui-box-show
   .ui-box-head
     %h4.box-title
-      - if @issue.closed
+      - if @issue.closed?
         .error.status_info Closed
       = gfm escape_once(@issue.title)
 
diff --git a/app/views/merge_requests/_show.html.haml b/app/views/merge_requests/_show.html.haml
index cefd33c0cdf034b4464235dcdb70f302346405da..ae2cfe924ec9e5e80ee6b9dca859ab176f54c425 100644
--- a/app/views/merge_requests/_show.html.haml
+++ b/app/views/merge_requests/_show.html.haml
@@ -29,10 +29,10 @@
   $(function(){
     merge_request = new MergeRequest({
       url_to_automerge_check: "#{automerge_check_project_merge_request_path(@project, @merge_request)}",
-      check_enable: #{@merge_request.state == MergeRequest::UNCHECKED ? "true" : "false"},
+      check_enable: #{@merge_request.merge_status == MergeRequest::UNCHECKED ? "true" : "false"},
       url_to_ci_check: "#{ci_status_project_merge_request_path(@project, @merge_request)}",
       ci_enable: #{@project.gitlab_ci? ? "true" : "false"},
-      current_state: "#{@merge_request.human_state}",
+      current_status: "#{@merge_request.human_merge_status}",
       action: "#{controller.action_name}"
     });
   });
diff --git a/app/views/merge_requests/show/_mr_accept.html.haml b/app/views/merge_requests/show/_mr_accept.html.haml
index c2c04b863e7df72c52b5890d0f5517de53f6ed1e..64f25a5118c635cdb76f9b4b9fc039cb590d770a 100644
--- a/app/views/merge_requests/show/_mr_accept.html.haml
+++ b/app/views/merge_requests/show/_mr_accept.html.haml
@@ -3,7 +3,7 @@
     %strong Only masters can accept MR
 
 
-- if @merge_request.open? && @commits.any? && can?(current_user, :accept_mr, @project)
+- if @merge_request.opened? && @commits.any? && can?(current_user, :accept_mr, @project)
   .automerge_widget.can_be_merged{style: "display:none"}
     .alert.alert-success
       %span
diff --git a/app/views/merge_requests/show/_mr_box.html.haml b/app/views/merge_requests/show/_mr_box.html.haml
index 644d7fcc58e08667a8c33beae112445073765092..3b54f613f581482b7d2e38b73d34230876211d00 100644
--- a/app/views/merge_requests/show/_mr_box.html.haml
+++ b/app/views/merge_requests/show/_mr_box.html.haml
@@ -1,11 +1,11 @@
 .ui-box.ui-box-show
   .ui-box-head
     %h4.box-title
-      - if @merge_request.merged
+      - if @merge_request.merged?
         .error.status_info
           %i.icon-ok
           Merged
-      - elsif @merge_request.closed
+      - elsif @merge_request.closed?
         .error.status_info Closed
       = gfm escape_once(@merge_request.title)
 
@@ -21,14 +21,14 @@
         %strong= link_to_gfm truncate(milestone.title, length: 20), project_milestone_path(milestone.project, milestone)
 
 
-  - if @merge_request.closed
+  - if @merge_request.closed?
     .ui-box-bottom
-      - if @merge_request.merged?
-        %span
-          Merged by #{link_to_member(@project, @merge_request.merge_event.author)}
-          %small #{time_ago_in_words(@merge_request.merge_event.created_at)} ago.
-      - elsif @merge_request.closed_event
-        %span
-          Closed by #{link_to_member(@project, @merge_request.closed_event.author)}
-          %small #{time_ago_in_words(@merge_request.closed_event.created_at)} ago.
+      %span
+        Closed by #{link_to_member(@project, @merge_request.closed_event.author)}
+        %small #{time_ago_in_words(@merge_request.closed_event.created_at)} ago.
+  - if @merge_request.merged?
+    .ui-box-bottom
+      %span
+        Merged by #{link_to_member(@project, @merge_request.merge_event.author)}
+        %small #{time_ago_in_words(@merge_request.merge_event.created_at)} ago.
 
diff --git a/app/views/merge_requests/show/_mr_ci.html.haml b/app/views/merge_requests/show/_mr_ci.html.haml
index dd1e78a020578711e84077773cdf5bf1f6f7cf91..a8faa6ba6176549637dd672b480029af028eab58 100644
--- a/app/views/merge_requests/show/_mr_ci.html.haml
+++ b/app/views/merge_requests/show/_mr_ci.html.haml
@@ -1,4 +1,4 @@
-- if @merge_request.open? && @commits.any?
+- if @merge_request.opened? && @commits.any?
   .ci_widget.ci-success{style: "display:none"}
     .alert.alert-success
       %i.icon-ok
diff --git a/app/views/merge_requests/show/_mr_title.html.haml b/app/views/merge_requests/show/_mr_title.html.haml
index 8119728dcb93588aeb595b127378145269dfdf85..3df7e4b21c6b5dc87217b8dace4dfda7264649c3 100644
--- a/app/views/merge_requests/show/_mr_title.html.haml
+++ b/app/views/merge_requests/show/_mr_title.html.haml
@@ -7,7 +7,7 @@
 
   %span.pull-right
     - if can?(current_user, :modify_merge_request, @merge_request)
-      - if @merge_request.open?
+      - if @merge_request.opened?
         .left.btn-group
           %a.btn.grouped.dropdown-toggle{ data: {toggle: :dropdown} }
             %i.icon-download-alt
@@ -17,7 +17,7 @@
             %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 btn-close", title: "Close merge request"
+        = link_to 'Close', project_merge_request_path(@project, @merge_request, merge_request: {state_event: :close }), 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
diff --git a/app/views/milestones/_milestone.html.haml b/app/views/milestones/_milestone.html.haml
index 00e20117f36de3b6df691d7abcc32eb844e75278..8a3727c6f6a9a99ca6635f6f3fd30cdcd80c4165 100644
--- a/app/views/milestones/_milestone.html.haml
+++ b/app/views/milestones/_milestone.html.haml
@@ -1,12 +1,12 @@
-%li{class: "milestone milestone-#{milestone.closed ? 'closed' : 'open'}", id: dom_id(milestone) }
+%li{class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: dom_id(milestone) }
   .pull-right
-    - if can?(current_user, :admin_milestone, milestone.project) and milestone.open?
+    - if can?(current_user, :admin_milestone, milestone.project) and milestone.active?
       = link_to edit_project_milestone_path(milestone.project, milestone), class: "btn btn-small edit-milestone-link grouped" do
         %i.icon-edit
         Edit
   %h4
     = link_to_gfm truncate(milestone.title, length: 100), project_milestone_path(milestone.project, milestone)
-    - if milestone.expired? and not milestone.closed
+    - if milestone.expired? and not milestone.closed?
       %span.cred (Expired)
     %small
       = milestone.expires_at
diff --git a/app/views/milestones/show.html.haml b/app/views/milestones/show.html.haml
index 43d82a54dd64c654e9c608a761ec4c841e203b91..c2b095422462ee19e68985652044856a324472f1 100644
--- a/app/views/milestones/show.html.haml
+++ b/app/views/milestones/show.html.haml
@@ -9,7 +9,7 @@
         &larr; To milestones list
   .span6
     .pull-right
-      - unless  @milestone.closed
+      - unless  @milestone.closed?
         = 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
@@ -25,12 +25,12 @@
   %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 btn-small btn-remove"
+    = link_to 'Close Milestone', project_milestone_path(@project, @milestone, milestone: {state_event: :close }), method: :put, class: "btn btn-small btn-remove"
 
 .ui-box.ui-box-show
   .ui-box-head
     %h4.box-title
-      - if @milestone.closed
+      - if @milestone.closed?
         .error.status_info Closed
       - elsif @milestone.expired?
         .error.status_info Expired
@@ -63,7 +63,7 @@
           %li=link_to('All Issues', '#')
       %ul.well-list
         - @issues.each do |issue|
-          %li{data: {closed: issue.closed}}
+          %li{data: {closed: issue.closed?}}
             = link_to [@project, issue] do
               %span.badge.badge-info ##{issue.id}
             &ndash;
@@ -77,7 +77,7 @@
           %li=link_to('All Merge Requests', '#')
       %ul.well-list
         - @merge_requests.each do |merge_request|
-          %li{data: {closed: merge_request.closed}}
+          %li{data: {closed: merge_request.closed?}}
             = link_to [@project, merge_request] do
               %span.badge.badge-info ##{merge_request.id}
             &ndash;
diff --git a/app/views/notes/_note.html.haml b/app/views/notes/_note.html.haml
index 4d3007a0ed1ddc8406bb5abeab33c054862b9afe..b355e2a0bd4ef4f8cdf8c7c29b9befc1c124bff5 100644
--- a/app/views/notes/_note.html.haml
+++ b/app/views/notes/_note.html.haml
@@ -31,7 +31,7 @@
     - if note.attachment.image?
       = image_tag note.attachment.url, class: 'note-image-attach'
     .attachment.pull-right
-      = link_to note.attachment.url, target: "_blank" do
+      = link_to note.attachment.secure_url, target: "_blank" do
         %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 5465d1f96e9edc1c6f6c3ee6ae0672ebad346061..5b6c298df4aeed9c7fd258ad1c6be2e6bb4003dc 100644
--- a/app/views/profiles/account.html.haml
+++ b/app/views/profiles/account.html.haml
@@ -53,29 +53,30 @@
 
 
 
-%fieldset.update-username
-  %legend
-    Username
-    %small.cred.pull-right
-      Changing your username can have unintended side effects!
-  = form_for @user, url: update_username_profile_path,  method: :put, remote: true do |f|
-    .padded
-      = f.label :username
-      .input
-        = f.text_field :username, required: true
-        &nbsp;
-        %span.loading-gif.hide= image_tag "ajax_loader.gif"
-        %span.update-success.cgreen.hide
-          %i.icon-ok
-          Saved
-        %span.update-failed.cred.hide
-          %i.icon-remove
-          Failed
-        %ul.cred
-          %li 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 btn-save"
+- if current_user.can_change_username?
+  %fieldset.update-username
+    %legend
+      Username
+      %small.cred.pull-right
+        Changing your username can have unintended side effects!
+    = form_for @user, url: update_username_profile_path,  method: :put, remote: true do |f|
+      .padded
+        = f.label :username
+        .input
+          = f.text_field :username, required: true
+          &nbsp;
+          %span.loading-gif.hide= image_tag "ajax_loader.gif"
+          %span.update-success.cgreen.hide
+            %i.icon-ok
+            Saved
+          %span.update-failed.cred.hide
+            %i.icon-remove
+            Failed
+          %ul.cred
+            %li 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 btn-save"
 
 - if Gitlab.config.gitlab.signup_enabled
   %fieldset.remove-account
@@ -83,4 +84,4 @@
       Remove account
       %small.cred.pull-right
         Before removing the account you must remove all projects!
-    = link_to 'Delete account', user_registration_path, confirm: "REMOVE #{current_user.name}? Are you sure?", method: :delete, class: "btn btn-remove delete-key btn-small pull-right"
\ No newline at end of file
+    = link_to 'Delete account', user_registration_path, confirm: "REMOVE #{current_user.name}? Are you sure?", method: :delete, class: "btn btn-remove delete-key btn-small pull-right"
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index 3cf6330cc3ccd9dcc97998111f48351009edbb8c..9cab3ba525245b341659ec00cb870f36218748c3 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -77,7 +77,7 @@
         %legend
           Personal projects:
           %small.pull-right
-            %span= current_user.personal_projects.count
+            %span= current_user.owned_projects.count
             of
             %span= current_user.projects_limit
         .padded
diff --git a/app/views/projects/_new_form.html.haml b/app/views/projects/_new_form.html.haml
index ba3ccc421cd9a62fce479f4e5a97728b207ca4f9..b6503636890c1064e9a76e884ee72fe547c1026a 100644
--- a/app/views/projects/_new_form.html.haml
+++ b/app/views/projects/_new_form.html.haml
@@ -28,7 +28,7 @@
     .input
       = f.text_field :import_url, class: 'xlarge', placeholder: 'https://github.com/randx/six.git'
       .light
-        URL should be clonable
+        URL must be clonable
 
   %p.padded
     New projects are private by default. You choose who can see the project and commit to repository.
diff --git a/app/views/projects/files.html.haml b/app/views/projects/files.html.haml
index d108308318e6a8c05b9c325926fdd3da5f34645d..36948eff658bd2f1b6cee4ab00916731128f6da9 100644
--- a/app/views/projects/files.html.haml
+++ b/app/views/projects/files.html.haml
@@ -9,7 +9,7 @@
     - @notes.each do |note|
       %tr
         %td
-          %a{href: note.attachment.url}
+          = link_to note.attachment.secure_url, target: "_blank" do
             = image_tag gravatar_icon(note.author_email), class: "avatar s24"
             = note.attachment_identifier
         %td
diff --git a/app/views/team_members/_assigned_team.html.haml b/app/views/team_members/_assigned_team.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..1d512c44b26cc93ab654a1fd3a7667c14ff09fad
--- /dev/null
+++ b/app/views/team_members/_assigned_team.html.haml
@@ -0,0 +1,10 @@
+%li{id: dom_id(team), class: "user_team_row team_#{team.id}"}
+  .pull-right
+    - if can?(current_user, :admin_team_member, @project)
+      = link_to resign_project_team_path(@project, team), method: :delete, confirm: "Are you shure?", class: "btn btn-remove btn-tiny" do
+        %i.icon-minus.icon-white
+
+  %strong= link_to team.name, team_path(team), title: team.name, class: "dark"
+  %br
+  %small.cgray Members: #{team.members.count}
+  %small.cgray Max access: #{team_relation.human_max_access}
diff --git a/app/views/team_members/_assigned_teams.html.haml b/app/views/team_members/_assigned_teams.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..91c6d8f7157921336edae5e97436faf87560fd45
--- /dev/null
+++ b/app/views/team_members/_assigned_teams.html.haml
@@ -0,0 +1,4 @@
+.ui-box
+  %ul.well-list
+    - assigned_teams.sort_by(&:team_name).each do |team_relation|
+      = render "team_members/assigned_team", team_relation: team_relation, team: team_relation.user_team
diff --git a/app/views/team_members/_show_team.html.haml b/app/views/team_members/_show_team.html.haml
deleted file mode 100644
index f1555f0b87b050a3a8070b5d4110f81f3545324c..0000000000000000000000000000000000000000
--- a/app/views/team_members/_show_team.html.haml
+++ /dev/null
@@ -1,15 +0,0 @@
-- 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/_team.html.haml b/app/views/team_members/_team.html.haml
index 365d9b65942da06a0190af04ee263543cdb3dbdb..2ec8c1a84518bef632fc8241ff62e915c6b405e4 100644
--- a/app/views/team_members/_team.html.haml
+++ b/app/views/team_members/_team.html.haml
@@ -1,16 +1,8 @@
-- grouper_project_members(@project).each do |access, 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: 'team_members/show', locals: {member: up})
-
-
-:javascript
-  $(function(){
-    $('.repo-access-select, .project-access-select').live("change", function() {
-      $(this.form).submit();
-    });
-  })
+      - members.sort_by(&:user_name).each do |team_member|
+        = render 'team_members/team_member', member: team_member
diff --git a/app/views/team_members/_show.html.haml b/app/views/team_members/_team_member.html.haml
similarity index 86%
rename from app/views/team_members/_show.html.haml
rename to app/views/team_members/_team_member.html.haml
index 3df2caed64a0cfbb65a6a1f00625ed918dc2c7b1..e7cba0b349cb7c70230bdfd4c8067a18c42a7ad6 100644
--- a/app/views/team_members/_show.html.haml
+++ b/app/views/team_members/_team_member.html.haml
@@ -2,7 +2,7 @@
 - allow_admin = can? current_user, :admin_project, @project
 %li{id: dom_id(user), class: "team_member_row user_#{user.id}"}
   .row
-    .span6
+    .span4
       = 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, user), title: user.name, class: "dark" do
@@ -10,18 +10,18 @@
         %br
         %small.cgray= user.email
 
-    .span5.pull-right
+    .span4.pull-right
       - if allow_admin
         .left
           = 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"
+            = f.select :project_access, options_for_select(UsersProject.access_roles, member.project_access), {}, class: "medium project-access-select span2 trigger-submit"
       .pull-right
         - if current_user == user
-          %span.btn.disabled This is you!
+          %span.label This is you!
         - if @project.namespace_owner == user
-          %span.btn.disabled Owner
+          %span.label Owner
         - elsif user.blocked
-          %span.btn.disabled.blocked Blocked
+          %span.label Blocked
         - elsif allow_admin
           = 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/_teams.html.haml b/app/views/team_members/_teams.html.haml
deleted file mode 100644
index 156fdd1befa13df95e66b40e15e2991e94e3fff8..0000000000000000000000000000000000000000
--- a/app/views/team_members/_teams.html.haml
+++ /dev/null
@@ -1,16 +0,0 @@
-- 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/index.html.haml b/app/views/team_members/index.html.haml
index 3264f58cb32d0bf1817924fcc39fb3bb19e2ac53..6958ec4cfcc9a04485210523466499f702804ea0 100644
--- a/app/views/team_members/index.html.haml
+++ b/app/views/team_members/index.html.haml
@@ -18,16 +18,39 @@
 %hr
 
 .clearfix
-%div.team-table
-  = render partial: "team_members/team", locals: {project: @project}
+.row
+  .span3
+    %ul.nav.nav-pills.nav-stacked
+      %li{class: ("active" if !params[:type])}
+        = link_to project_team_members_path(type: nil) do
+          All
+      %li{class: ("active" if params[:type] == 'masters')}
+        = link_to project_team_members_path(type: 'masters') do
+          Masters
+          %span.pull-right= @project.users_projects.masters.count
+      %li{class: ("active" if params[:type] == 'developers')}
+        = link_to project_team_members_path(type: 'developers') do
+          Developers
+          %span.pull-right= @project.users_projects.developers.count
+      %li{class: ("active" if params[:type] == 'reporters')}
+        = link_to project_team_members_path(type: 'reporters') do
+          Reporters
+          %span.pull-right= @project.users_projects.reporters.count
+      %li{class: ("active" if params[:type] == 'guests')}
+        = link_to project_team_members_path(type: 'guests') do
+          Guests
+          %span.pull-right= @project.users_projects.guests.count
 
+    - if @assigned_teams.present?
+      %h5
+        Assigned teams
+        (#{@project.user_teams.count})
+      %div
+        = render "team_members/assigned_teams", assigned_teams: @assigned_teams
+
+  .span9
+    %div.team-table
+      = render "team_members/team", team: @team
 
-%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/teams/edit.html.haml b/app/views/teams/edit.html.haml
index 3435583600d2ccbe5f29f93e9f3f4a6e985b1a18..751fe94c6542fad9aff10572aa02916e1ef697b8 100644
--- a/app/views/teams/edit.html.haml
+++ b/app/views/teams/edit.html.haml
@@ -1,20 +1,29 @@
 %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"
+.row
+  .span7
+    = 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: "xlarge left"
+
+      .clearfix
+        = f.label :path do
+          Team path is
+        .input
+          = f.text_field :path, placeholder: "opensource", class: "xlarge left"
+      .form-actions
+        = f.submit 'Save team changes', class: "btn btn-save"
+  .span5
+    .ui-box
+      %h5.title Remove team
+      .padded.bgred
+        %p
+          Removed team can not be restored!
+        = link_to 'Remove team', team_path(@team), method: :delete, confirm: "You are sure?", class: "btn btn-remove btn-small"
 
-  .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/members/_show.html.haml b/app/views/teams/members/_show.html.haml
index 6cddb8e482663c34f9368bf0fcf1904954c0d74e..94d2fd50fe8e64d8e509f5b401d10e2a0611e00f 100644
--- a/app/views/teams/members/_show.html.haml
+++ b/app/views/teams/members/_show.html.haml
@@ -10,22 +10,21 @@
         %br
         %small.cgray= user.email
 
-    .span6.pull-right
+    .span4
       - 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
+        = 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 trigger-submit"
+          %br
+          = label_tag do
+            = f.check_box :group_admin, class: 'trigger-submit'
+            %span Admin access
+    .pull-right
+      - if current_user == user
+        %span.btn.disabled This is you!
+      - if @team.owner == user
+        %span.btn.disabled 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/new.html.haml b/app/views/teams/new.html.haml
index 38f61c11c0cac08711fec3e092d980062e09fd58..7089f7915586ae28307f85dba8d6fc00a03f0735 100644
--- a/app/views/teams/new.html.haml
+++ b/app/views/teams/new.html.haml
@@ -17,3 +17,17 @@
       %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
+  %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_project?
+    .clearfix
+      .input.light
+        Want to create a project?
+        = link_to new_project_path, class: "btn btn-tiny" do
+          Create a project
diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb
index e3f62d736ef48b57cc217cff76b4fbd89aa25e80..3ef6d5977cf29d864115f43c0e918dff5d56168f 100644
--- a/app/workers/post_receive.rb
+++ b/app/workers/post_receive.rb
@@ -21,14 +21,18 @@ class PostReceive
       return false
     end
 
-    # Ignore push from non-gitlab users
-    user = if identifier.nil?
-             raise identifier.inspect
+    user = if identifier.blank?
+             # Local push from gitlab
              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/
+
+           elsif identifier =~ /\Auser-\d+\Z/
+             # git push over http
+             user_id = identifier.gsub("user-", "")
+             User.find_by_id(user_id)
+
+           elsif identifier =~ /\Akey-\d+\Z/
+             # git push over ssh
              key_id = identifier.gsub("key-", "")
              Key.find_by_id(key_id).try(:user)
            end
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 72d85e89b37c08deb0c7258d132c01844676c909..62761c80cbbf3e89582620ea0b5dc18007b2e723 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -7,121 +7,132 @@
 # 2. Replace gitlab -> host with your domain
 # 3. Replace gitlab -> email_from
 
-#
-# 1. GitLab app settings
-# ==========================
-
-## GitLab settings
-gitlab:
-  ## Web server settings
-  host: localhost
-  port: 80
-  https: false
-  # Uncomment and customize to run in non-root path
-  # Note that ENV['RAILS_RELATIVE_URL_ROOT'] in config/unicorn.rb may need to be changed
-  # relative_url_root: /gitlab
-
-  # Uncomment and customize if you can't use the default user to run GitLab (default: 'git')
-  # user: git
-
-  ## Email settings
-  # Email address used in the "From" field in mails sent by GitLab
-  email_from: gitlab@localhost
-
-  # Email address of your support contact (default: same as email_from)
-  support_email: support@localhost
-
-  ## Project settings
-  default_projects_limit: 10
-  # signup_enabled: true          # default: false - Account passwords are not sent via the email if signup is enabled.
-
-## Gravatar
-gravatar:
-  enabled: true                 # Use user avatar images from Gravatar.com (default: true)
-  # plain_url: "http://..."     # default: http://www.gravatar.com/avatar/%{hash}?s=%{size}&d=mm
-  # ssl_url:   "https://..."    # default: https://secure.gravatar.com/avatar/%{hash}?s=%{size}&d=mm
-
-
-
-#
-# 2. Auth settings
-# ==========================
-
-## LDAP settings
-ldap:
-  enabled: false
-  host: '_your_ldap_server'
-  base: '_the_base_where_you_search_for_users'
-  port: 636
-  uid: 'sAMAccountName'
-  method: 'ssl' # "ssl" or "plain"
-  bind_dn: '_the_full_dn_of_the_user_you_will_bind_with'
-  password: '_the_password_of_the_bind_user'
-
-## Omniauth settings
-omniauth:
-  # Enable ability for users
-  # Allow logging in via Twitter, Google, etc. using Omniauth providers
-  enabled: false
-
+production: &base
+  #
+  # 1. GitLab app settings
+  # ==========================
+
+  ## GitLab settings
+  gitlab:
+    ## Web server settings
+    host: localhost
+    port: 80
+    https: false
+    # Uncomment and customize to run in non-root path
+    # Note that ENV['RAILS_RELATIVE_URL_ROOT'] in config/unicorn.rb may need to be changed
+    # relative_url_root: /gitlab
+
+    # Uncomment and customize if you can't use the default user to run GitLab (default: 'git')
+    # user: git
+
+    ## Email settings
+    # Email address used in the "From" field in mails sent by GitLab
+    email_from: gitlab@localhost
+
+    # Email address of your support contact (default: same as email_from)
+    support_email: support@localhost
+
+    ## Project settings
+    default_projects_limit: 10
+    # signup_enabled: true          # default: false - Account passwords are not sent via the email if signup is enabled.
+    # username_changing_enabled: false # default: true - User can change her username/namespace
+
+  ## Gravatar
+  gravatar:
+    enabled: true                 # Use user avatar images from Gravatar.com (default: true)
+    # plain_url: "http://..."     # default: http://www.gravatar.com/avatar/%{hash}?s=%{size}&d=mm
+    # ssl_url:   "https://..."    # default: https://secure.gravatar.com/avatar/%{hash}?s=%{size}&d=mm
+
+
+
+  #
+  # 2. Auth settings
+  # ==========================
+
+  ## LDAP settings
+  ldap:
+    enabled: false
+    host: '_your_ldap_server'
+    base: '_the_base_where_you_search_for_users'
+    port: 636
+    uid: 'sAMAccountName'
+    method: 'ssl' # "ssl" or "plain"
+    bind_dn: '_the_full_dn_of_the_user_you_will_bind_with'
+    password: '_the_password_of_the_bind_user'
+
+  ## Omniauth settings
+  omniauth:
+    # Enable ability for users
+    # Allow logging in via Twitter, Google, etc. using Omniauth providers
+    enabled: false
+
+    # CAUTION!
+    # This allows users to login without having a user account first (default: false)
+    # User accounts will be created automatically when authentication was successful.
+    allow_single_sign_on: false
+    # Locks down those users until they have been cleared by the admin (default: true)
+    block_auto_created_users: true
+
+    ## Auth providers
+    # Uncomment the lines and fill in the data of the auth provider you want to use
+    # If your favorite auth provider is not listed you can user others:
+    # see https://github.com/gitlabhq/gitlabhq/wiki/Using-Custom-Omniauth-Providers
+    # The 'app_id' and 'app_secret' parameters are always passed as the first two
+    # arguments, followed by optional 'args' which can be either a hash or an array.
+    providers:
+      # - { name: 'google_oauth2', app_id: 'YOUR APP ID',
+      #     app_secret: 'YOUR APP SECRET',
+      #     args: { access_type: 'offline', approval_prompt: '' } }
+      # - { name: 'twitter', app_id: 'YOUR APP ID',
+      #     app_secret: 'YOUR APP SECRET'}
+      # - { name: 'github', app_id: 'YOUR APP ID',
+      #     app_secret: 'YOUR APP SECRET' }
+
+
+
+  #
+  # 3. Advanced settings
+  # ==========================
+
+  # GitLab Satellites
+  satellites:
+    # Relative paths are relative to Rails.root (default: tmp/repo_satellites/)
+    path: /home/git/gitlab-satellites/
+
+  ## Backup settings
+  backup:
+    path: "tmp/backups"   # Relative paths are relative to Rails.root (default: tmp/backups/)
+    # keep_time: 604800   # default: 0 (forever) (in seconds)
+
+  ## GitLab Shell settings
+  gitlab_shell:
+    # REPOS_PATH MUST NOT BE A SYMLINK!!!
+    repos_path: /home/git/repositories/
+    hooks_path: /home/git/gitlab-shell/hooks/
+
+    # Git over HTTP
+    upload_pack: true
+    receive_pack: true
+
+    # If you use non-standart ssh port you need to specify it
+    # ssh_port: 22
+
+  ## Git settings
   # CAUTION!
-  # This allows users to login without having a user account first (default: false)
-  # User accounts will be created automatically when authentication was successful.
-  allow_single_sign_on: false
-  # Locks down those users until they have been cleared by the admin (default: true)
-  block_auto_created_users: true
-
-  ## Auth providers
-  # Uncomment the lines and fill in the data of the auth provider you want to use
-  # If your favorite auth provider is not listed you can user others:
-  # see https://github.com/gitlabhq/gitlabhq/wiki/Using-Custom-Omniauth-Providers
-  # The 'app_id' and 'app_secret' parameters are always passed as the first two
-  # arguments, followed by optional 'args' which can be either a hash or an array.
-  providers:
-    # - { name: 'google_oauth2', app_id: 'YOUR APP ID',
-    #     app_secret: 'YOUR APP SECRET',
-    #     args: { access_type: 'offline', approval_prompt: '' } }
-    # - { name: 'twitter', app_id: 'YOUR APP ID',
-    #     app_secret: 'YOUR APP SECRET'}
-    # - { name: 'github', app_id: 'YOUR APP ID',
-    #     app_secret: 'YOUR APP SECRET' }
-
-
-
-#
-# 3. Advanced settings
-# ==========================
-
-# GitLab Satellites
-satellites:
-  # Relative paths are relative to Rails.root (default: tmp/repo_satellites/)
-  path: /home/git/gitlab-satellites/
-
-## Backup settings
-backup:
-  path: "tmp/backups"   # Relative paths are relative to Rails.root (default: tmp/backups/)
-  # keep_time: 604800   # default: 0 (forever) (in seconds)
-
-## GitLab Shell settings
-gitlab_shell:
-  # REPOS_PATH MUST NOT BE A SYMLINK!!!
-  repos_path: /home/git/repositories/
-  hooks_path: /home/git/gitlab-shell/hooks/
-
-  # Git over HTTP
-  upload_pack: true
-  receive_pack: true
-
-  # If you use non-standart ssh port you need to specify it
-  # ssh_port: 22
-
-## Git settings
-# CAUTION!
-# Use the default values unless you really know what you are doing
-git:
-  bin_path: /usr/bin/git
-  # Max size of git object like commit, in bytes
-  # This value can be increased if you have a very large commits
-  max_size: 5242880 # 5.megabytes
-  # Git timeout to read commit, in seconds
-  timeout: 10
+  # Use the default values unless you really know what you are doing
+  git:
+    bin_path: /usr/bin/git
+    # Max size of git object like commit, in bytes
+    # This value can be increased if you have a very large commits
+    max_size: 5242880 # 5.megabytes
+    # Git timeout to read commit, in seconds
+    timeout: 10
+
+development:
+  <<: *base
+
+test:
+  <<: *base
+
+staging:
+  <<: *base
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index c1469530024b789bc6a3d80343766980565a8343..f7d18e671481e97e383d73ad957aad556b1594d5 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -1,5 +1,6 @@
 class Settings < Settingslogic
   source "#{Rails.root}/config/gitlab.yml"
+  namespace Rails.env
 
   class << self
     def gitlab_on_non_standard_port?
@@ -56,6 +57,7 @@ Settings.gitlab['support_email']  ||= Settings.gitlab.email_from
 Settings.gitlab['url']        ||= Settings.send(:build_gitlab_url)
 Settings.gitlab['user']       ||= 'git'
 Settings.gitlab['signup_enabled'] ||= false
+Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil?
 
 #
 # Gravatar
diff --git a/config/initializers/2_app.rb b/config/initializers/2_app.rb
index 748f15a11d9af85abf6b1ffda3771e549c63a101..27a0c0ffeb2cdd4a603e54f28a97f563c7059bd5 100644
--- a/config/initializers/2_app.rb
+++ b/config/initializers/2_app.rb
@@ -1,6 +1,6 @@
 module Gitlab
-  Version = File.read(Rails.root.join("VERSION"))
-  Revision = `git log --pretty=format:'%h' -n 1`
+  VERSION = File.read(Rails.root.join("VERSION")).strip
+  REVISION = `git log --pretty=format:'%h' -n 1`
 
   def self.config
     Settings
diff --git a/config/routes.rb b/config/routes.rb
index 125ec6bc5880b2982d4b4914556ea19e9c869a42..10536a6e5296ee4ecce39b5ee91eeba0c6d0ab67 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -46,6 +46,11 @@ Gitlab::Application.routes.draw do
     root to: "projects#index"
   end
 
+  #
+  # Attachments serving
+  #
+  get 'files/:type/:id/:filename' => 'files#download', constraints: { id: /\d+/, type: /[a-z]+/, filename: /[a-zA-Z.0-9_\-\+]+/ }
+
   #
   # Admin Area
   #
diff --git a/db/fixtures/development/02_source_code.rb b/db/fixtures/development/02_source_code.rb
index 4a9e5d0c2587f664a1ed3168d307a25a25a29b26..a0a46c9e927cb197379712e27638df15d2bc764b 100644
--- a/db/fixtures/development/02_source_code.rb
+++ b/db/fixtures/development/02_source_code.rb
@@ -1,4 +1,4 @@
-root = Gitlab.config.gitolite.repos_path
+root = Gitlab.config.gitlab_shell.repos_path
 
 projects = [
   { path: 'underscore.git',              git: 'https://github.com/documentcloud/underscore.git' },
diff --git a/db/fixtures/development/09_issues.rb b/db/fixtures/development/09_issues.rb
index 8978db4742b10d3db774eea198df42d9ca0e6e31..cd9b2b3e45618ecfe794db9986ff0dff95c37a9a 100644
--- a/db/fixtures/development/09_issues.rb
+++ b/db/fixtures/development/09_issues.rb
@@ -16,7 +16,7 @@ Gitlab::Seeder.quiet do
       project_id: project.id,
       author_id: user_id,
       assignee_id: user_id,
-      closed: [true, false].sample,
+      state: ['opened', 'closed'].sample,
       milestone: project.milestones.sample,
       title: Faker::Lorem.sentence(6)
     }])
diff --git a/db/fixtures/development/10_merge_requests.rb b/db/fixtures/development/10_merge_requests.rb
index 9904b4a150596d638c8a930bbefd603b1f7a9d8e..6d111b26c53428cfdeda17e67329e2cc2779b963 100644
--- a/db/fixtures/development/10_merge_requests.rb
+++ b/db/fixtures/development/10_merge_requests.rb
@@ -17,7 +17,7 @@ Gitlab::Seeder.quiet do
       project_id: project.id,
       author_id: user_id,
       assignee_id: user_id,
-      closed: [true, false].sample,
+      state: ['opened', 'closed'].sample,
       milestone: project.milestones.sample,
       title: Faker::Lorem.sentence(6)
     }])
diff --git a/db/migrate/20130214154045_rename_state_to_merge_status_in_milestone.rb b/db/migrate/20130214154045_rename_state_to_merge_status_in_milestone.rb
new file mode 100644
index 0000000000000000000000000000000000000000..23797fe1894750acf664bb81c5be985b0071204f
--- /dev/null
+++ b/db/migrate/20130214154045_rename_state_to_merge_status_in_milestone.rb
@@ -0,0 +1,5 @@
+class RenameStateToMergeStatusInMilestone < ActiveRecord::Migration
+  def change
+    rename_column :merge_requests, :state, :merge_status
+  end
+end
diff --git a/db/migrate/20130218140952_add_state_to_issue.rb b/db/migrate/20130218140952_add_state_to_issue.rb
new file mode 100644
index 0000000000000000000000000000000000000000..062103d0e3389f948b3539bbfc79d6ad820b4351
--- /dev/null
+++ b/db/migrate/20130218140952_add_state_to_issue.rb
@@ -0,0 +1,5 @@
+class AddStateToIssue < ActiveRecord::Migration
+  def change
+    add_column :issues, :state, :string
+  end
+end
diff --git a/db/migrate/20130218141038_add_state_to_merge_request.rb b/db/migrate/20130218141038_add_state_to_merge_request.rb
new file mode 100644
index 0000000000000000000000000000000000000000..ac4108ee311b5ef0854f2ee81ba1c026a0af8b38
--- /dev/null
+++ b/db/migrate/20130218141038_add_state_to_merge_request.rb
@@ -0,0 +1,5 @@
+class AddStateToMergeRequest < ActiveRecord::Migration
+  def change
+    add_column :merge_requests, :state, :string
+  end
+end
diff --git a/db/migrate/20130218141117_add_state_to_milestone.rb b/db/migrate/20130218141117_add_state_to_milestone.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c84039106bd9064a3825a65d21fbec38e248eed7
--- /dev/null
+++ b/db/migrate/20130218141117_add_state_to_milestone.rb
@@ -0,0 +1,5 @@
+class AddStateToMilestone < ActiveRecord::Migration
+  def change
+    add_column :milestones, :state, :string
+  end
+end
diff --git a/db/migrate/20130218141258_convert_closed_to_state_in_issue.rb b/db/migrate/20130218141258_convert_closed_to_state_in_issue.rb
new file mode 100644
index 0000000000000000000000000000000000000000..0614a5c00643109512443ac090eb42d15ce73e2d
--- /dev/null
+++ b/db/migrate/20130218141258_convert_closed_to_state_in_issue.rb
@@ -0,0 +1,14 @@
+class ConvertClosedToStateInIssue < ActiveRecord::Migration
+  def up
+    Issue.transaction do
+      Issue.where(closed: true).update_all("state = 'closed'")
+      Issue.where(closed: false).update_all("state = 'opened'")
+    end
+  end
+
+  def down
+    Issue.transaction do
+      Issue.where(state: :closed).update_all("closed = 1")
+    end
+  end
+end
diff --git a/db/migrate/20130218141327_convert_closed_to_state_in_merge_request.rb b/db/migrate/20130218141327_convert_closed_to_state_in_merge_request.rb
new file mode 100644
index 0000000000000000000000000000000000000000..4d5c6ee569d738a381b2f93f1c8379a8b46ed613
--- /dev/null
+++ b/db/migrate/20130218141327_convert_closed_to_state_in_merge_request.rb
@@ -0,0 +1,16 @@
+class ConvertClosedToStateInMergeRequest < ActiveRecord::Migration
+  def up
+    MergeRequest.transaction do
+      MergeRequest.where("closed = 1 AND merged = 1").update_all("state = 'merged'")
+      MergeRequest.where("closed = 1 AND merged = 0").update_all("state = 'closed'")
+      MergeRequest.where("closed = 0").update_all("state = 'opened'")
+    end
+  end
+
+  def down
+    MergeRequest.transaction do
+      MergeRequest.where(state: :closed).update_all("closed = 1")
+      MergeRequest.where(state: :merged).update_all("closed = 1, merged = 1")
+    end
+  end
+end
diff --git a/db/migrate/20130218141344_convert_closed_to_state_in_milestone.rb b/db/migrate/20130218141344_convert_closed_to_state_in_milestone.rb
new file mode 100644
index 0000000000000000000000000000000000000000..78096666393eb1ace606e3a10758d5e2b84be779
--- /dev/null
+++ b/db/migrate/20130218141344_convert_closed_to_state_in_milestone.rb
@@ -0,0 +1,14 @@
+class ConvertClosedToStateInMilestone < ActiveRecord::Migration
+  def up
+    Milestone.transaction do
+      Milestone.where(closed: false).update_all("state = 'opened'")
+      Milestone.where(closed: false).update_all("state = 'active'")
+    end
+  end
+
+  def down
+    Milestone.transaction do
+      Milestone.where(state: :closed).update_all("closed = 1")
+    end
+  end
+end
diff --git a/db/migrate/20130218141444_remove_merged_from_merge_request.rb b/db/migrate/20130218141444_remove_merged_from_merge_request.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a7bd82f500096e2d0a54080ff225cf636ff56532
--- /dev/null
+++ b/db/migrate/20130218141444_remove_merged_from_merge_request.rb
@@ -0,0 +1,9 @@
+class RemoveMergedFromMergeRequest < ActiveRecord::Migration
+  def up
+    remove_column :merge_requests, :merged
+  end
+
+  def down
+    add_column :merge_requests, :merged, :boolean, default: true, null: false
+  end
+end
diff --git a/db/migrate/20130218141507_remove_closed_from_issue.rb b/db/migrate/20130218141507_remove_closed_from_issue.rb
new file mode 100644
index 0000000000000000000000000000000000000000..95cc064252b8f603b5e7bcb9365ae74ea82600c0
--- /dev/null
+++ b/db/migrate/20130218141507_remove_closed_from_issue.rb
@@ -0,0 +1,9 @@
+class RemoveClosedFromIssue < ActiveRecord::Migration
+  def up
+    remove_column :issues, :closed
+  end
+
+  def down
+    add_column :issues, :closed, :boolean
+  end
+end
diff --git a/db/migrate/20130218141536_remove_closed_from_merge_request.rb b/db/migrate/20130218141536_remove_closed_from_merge_request.rb
new file mode 100644
index 0000000000000000000000000000000000000000..371835938b213308efc9ef18bba15b1958fb4e66
--- /dev/null
+++ b/db/migrate/20130218141536_remove_closed_from_merge_request.rb
@@ -0,0 +1,9 @@
+class RemoveClosedFromMergeRequest < ActiveRecord::Migration
+  def up
+    remove_column :merge_requests, :closed
+  end
+
+  def down
+    add_column :merge_requests, :closed, :boolean
+  end
+end
diff --git a/db/migrate/20130218141554_remove_closed_from_milestone.rb b/db/migrate/20130218141554_remove_closed_from_milestone.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e8dae4a19b1cb3fd235eb204ed46813e917c9810
--- /dev/null
+++ b/db/migrate/20130218141554_remove_closed_from_milestone.rb
@@ -0,0 +1,9 @@
+class RemoveClosedFromMilestone < ActiveRecord::Migration
+  def up
+    remove_column :milestones, :closed
+  end
+
+  def down
+    add_column :milestones, :closed, :boolean
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 0f07d2bc8c54061a309b3b9cdf0a07016a6f62c1..f837e6edf98daa2cf1987b1c5977cc9ab515b016 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 => 20130131070232) do
+ActiveRecord::Schema.define(:version => 20130218141554) do
 
   create_table "events", :force => true do |t|
     t.string   "target_type"
@@ -37,18 +37,17 @@ ActiveRecord::Schema.define(:version => 20130131070232) do
     t.integer  "assignee_id"
     t.integer  "author_id"
     t.integer  "project_id"
-    t.datetime "created_at",                      :null => false
-    t.datetime "updated_at",                      :null => false
-    t.boolean  "closed",       :default => false, :null => false
+    t.datetime "created_at",                  :null => false
+    t.datetime "updated_at",                  :null => false
     t.integer  "position",     :default => 0
     t.string   "branch_name"
     t.text     "description"
     t.integer  "milestone_id"
+    t.string   "state"
   end
 
   add_index "issues", ["assignee_id"], :name => "index_issues_on_assignee_id"
   add_index "issues", ["author_id"], :name => "index_issues_on_author_id"
-  add_index "issues", ["closed"], :name => "index_issues_on_closed"
   add_index "issues", ["created_at"], :name => "index_issues_on_created_at"
   add_index "issues", ["milestone_id"], :name => "index_issues_on_milestone_id"
   add_index "issues", ["project_id"], :name => "index_issues_on_project_id"
@@ -69,25 +68,23 @@ ActiveRecord::Schema.define(:version => 20130131070232) do
   add_index "keys", ["user_id"], :name => "index_keys_on_user_id"
 
   create_table "merge_requests", :force => true do |t|
-    t.string   "target_branch",                                          :null => false
-    t.string   "source_branch",                                          :null => false
-    t.integer  "project_id",                                             :null => false
+    t.string   "target_branch",                                      :null => false
+    t.string   "source_branch",                                      :null => false
+    t.integer  "project_id",                                         :null => false
     t.integer  "author_id"
     t.integer  "assignee_id"
     t.string   "title"
-    t.boolean  "closed",                              :default => false, :null => false
-    t.datetime "created_at",                                             :null => false
-    t.datetime "updated_at",                                             :null => false
+    t.datetime "created_at",                                         :null => false
+    t.datetime "updated_at",                                         :null => false
     t.text     "st_commits",    :limit => 2147483647
     t.text     "st_diffs",      :limit => 2147483647
-    t.boolean  "merged",                              :default => false, :null => false
-    t.integer  "state",                               :default => 1,     :null => false
+    t.integer  "merge_status",                        :default => 1, :null => false
     t.integer  "milestone_id"
+    t.string   "state"
   end
 
   add_index "merge_requests", ["assignee_id"], :name => "index_merge_requests_on_assignee_id"
   add_index "merge_requests", ["author_id"], :name => "index_merge_requests_on_author_id"
-  add_index "merge_requests", ["closed"], :name => "index_merge_requests_on_closed"
   add_index "merge_requests", ["created_at"], :name => "index_merge_requests_on_created_at"
   add_index "merge_requests", ["milestone_id"], :name => "index_merge_requests_on_milestone_id"
   add_index "merge_requests", ["project_id"], :name => "index_merge_requests_on_project_id"
@@ -96,13 +93,13 @@ ActiveRecord::Schema.define(:version => 20130131070232) do
   add_index "merge_requests", ["title"], :name => "index_merge_requests_on_title"
 
   create_table "milestones", :force => true do |t|
-    t.string   "title",                          :null => false
-    t.integer  "project_id",                     :null => false
+    t.string   "title",       :null => false
+    t.integer  "project_id",  :null => false
     t.text     "description"
     t.date     "due_date"
-    t.boolean  "closed",      :default => false, :null => false
-    t.datetime "created_at",                     :null => false
-    t.datetime "updated_at",                     :null => false
+    t.datetime "created_at",  :null => false
+    t.datetime "updated_at",  :null => false
+    t.string   "state"
   end
 
   add_index "milestones", ["due_date"], :name => "index_milestones_on_due_date"
diff --git a/doc/api/milestones.md b/doc/api/milestones.md
index b997e83901bb506e4fbc439c43eb94987039c3f8..73d29afc37ac36cf06dfb10170d6acacbb5f66f9 100644
--- a/doc/api/milestones.md
+++ b/doc/api/milestones.md
@@ -34,7 +34,6 @@ POST /projects/:id/milestones
 Parameters:
 
 + `id` (required) - The ID of a project
-+ `milestone_id` (required) - The ID of a project milestone
 + `title` (required) - The title of an milestone
 + `description` (optional) - The description of the milestone
 + `due_date` (optional) - The due date of the milestone
diff --git a/doc/api/projects.md b/doc/api/projects.md
index 16521917a7a48002094d20bdfb4e42aebc0ac7b3..cff4327a58c7337dfacdbeda437c6df9cbd3b4f6 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -23,7 +23,7 @@ GET /projects
       "blocked": false,
       "created_at": "2012-05-23T08:00:58Z"
     },
-    "private": true,
+    "public": true,
     "path": "rails",
     "path_with_namespace": "rails/rails",
     "issues_enabled": false,
@@ -45,7 +45,7 @@ GET /projects
       "blocked": false,
       "created_at": "2012-05-23T08:00:58Z"
     },
-    "private": true,
+    "public": true,
     "path": "gitlab",
     "path_with_namespace": "randx/gitlab",
     "issues_enabled": true,
@@ -89,7 +89,7 @@ Parameters:
     "blocked": false,
     "created_at": "2012-05-23T08:00:58Z"
   },
-  "private": true,
+  "public": true,
   "path": "gitlab",
   "path_with_namespace": "randx/gitlab",
   "issues_enabled": true,
diff --git a/doc/install/databases.md b/doc/install/databases.md
index 4c6c084d0b94852587d75e86566f23235a7d96c5..61882602bba3455fc41b293ca4a9a326ca25df50 100644
--- a/doc/install/databases.md
+++ b/doc/install/databases.md
@@ -27,7 +27,7 @@ GitLab supports the following databases:
     mysql> \q
 
     # Try connecting to the new database with the new user
-    sudo -u gitlab -H mysql -u gitlab -p -D gitlabhq_production
+    sudo -u git -H mysql -u gitlab -p -D gitlabhq_production
 
 ## PostgreSQL
 
@@ -47,5 +47,5 @@ GitLab supports the following databases:
     template1=# \q
 
     # Try connecting to the new database with the new user
-    sudo -u gitlab -H psql -d gitlabhq_production
+    sudo -u git -H psql -d gitlabhq_production
 
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 501ae6db87a51d9572ebcd5c4ee0855c0b761302..4d2ab63b2e93cfd12379833be8633a46a05598bc 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -1,6 +1,6 @@
 This installation guide was created for Debian/Ubuntu and tested on it.
 
-Please read `doc/install/requirements.md` for hardware and platform requirements.
+Please read [`doc/install/requirements.md`](./requirements.md) for hardware and platform requirements.
 
 
 **Important Note:**
@@ -8,12 +8,13 @@ The following steps have been known to work.
 If you deviate from this guide, do it with caution and make sure you don't
 violate any assumptions GitLab makes about its environment.
 For things like AWS installation scripts, init scripts or config files for
-alternative web server have a look at the "Advanced Setup Tips" section.
+alternative web server have a look at the [`Advanced Setup
+Tips`](./installation.md#advanced-setup-tips) section.
 
 
 **Important Note:**
 If you find a bug/error in this guide please submit an issue or pull request
-following the contribution guide (see `CONTRIBUTING.md`).
+following the [`contribution guide`](../../CONTRIBUTING.md).
 
 - - -
 
@@ -24,7 +25,7 @@ The GitLab installation consists of setting up the following components:
 1. Packages / Dependencies
 2. Ruby
 3. System Users
-4. Gitolite
+4. GitLab shell
 5. Database
 6. GitLab
 7. Nginx
@@ -32,16 +33,13 @@ The GitLab installation consists of setting up the following components:
 
 # 1. Packages / Dependencies
 
-`sudo` is not installed on Debian by default. If you don't have it you'll need
-to install it first.
+`sudo` is not installed on Debian by default. Make sure your system is
+up-to-date and install it.
 
     # run as root
-    apt-get update && apt-get upgrade && apt-get install sudo
-
-Make sure your system is up-to-date:
-
-    sudo apt-get update
-    sudo apt-get upgrade
+    apt-get update
+    apt-get upgrade
+    apt-get install sudo
 
 **Note:**
 Vim is an editor that is used here whenever there are files that need to be
@@ -96,25 +94,24 @@ Create a `git` user for Gitlab:
 
 # 4. GitLab shell
 
-    # login as git 
+    # Login as git 
     sudo su git
 
-    # go to home directory 
+    # Go to home directory 
     cd /home/git
 
-    # clone gitlab shell
+    # Clone gitlab shell
     git clone https://github.com/gitlabhq/gitlab-shell.git
 
-    # setup
+    # Setup
     cd gitlab-shell
     cp config.yml.example config.yml
     ./bin/install 
 
 
-
 # 5. Database
 
-To setup the MySQL/PostgreSQL database and dependencies please see [`doc/install/databases.md`](./databases.md) .
+To setup the MySQL/PostgreSQL database and dependencies please see [`doc/install/databases.md`](./databases.md).
 
 
 # 6. GitLab
@@ -154,9 +151,13 @@ do so with caution!
     sudo chmod -R u+rwX  log/
     sudo chmod -R u+rwX  tmp/
 
-    # Make directory for satellites
+    # Create directory for satellites
     sudo -u git -H mkdir /home/git/gitlab-satellites
 
+    # Create directory for pids and make sure GitLab can write to it
+    sudo -u git -H mkdir tmp/pids/
+    sudo chmod -R u+rwX  tmp/pids/
+ 
     # Copy the example Unicorn config
     sudo -u git -H cp config/unicorn.rb.example config/unicorn.rb
 
@@ -187,7 +188,9 @@ Make sure to update username/password in config/database.yml.
 
 
 ## Initialise Database and Activate Advanced Features
-
+    
+    sudo -u git -H bundle exec rake db:setup RAILS_ENV=production
+    sudo -u git -H bundle exec rake db:seed_fu RAILS_ENV=production
     sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production
 
 
@@ -205,7 +208,7 @@ Make GitLab start on boot:
 
 ## Check Application Status
 
-Check if GitLab and its environment is configured correctly:
+Check if GitLab and its environment are configured correctly:
 
     sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
 
@@ -227,7 +230,7 @@ However there are still a few steps left.
 
 **Note:**
 If you can't or don't want to use Nginx as your web server, have a look at the
-"Advanced Setup Tips" section.
+[`Advanced Setup Tips`](./installation.md#advanced-setup-tips) section.
 
 ## Installation
     sudo apt-get install nginx
@@ -244,11 +247,11 @@ Make sure to edit the config file to match your setup:
     # Change **YOUR_SERVER_IP** and **YOUR_SERVER_FQDN**
     # to the IP address and fully-qualified domain name
     # of your host serving GitLab
-    sudo vim /etc/nginx/sites-enabled/gitlab
+    sudo vim /etc/nginx/sites-available/gitlab
 
 ## Restart
 
-    sudo /etc/init.d/nginx restart
+    sudo service nginx restart
 
 
 # Done!
@@ -282,7 +285,7 @@ a different host, you can configure its connection string via the
 
 ## Custom SSH Connection
 
-If you are running SSH on a non-standard port, you must change the gitlab user'S SSH config.
+If you are running SSH on a non-standard port, you must change the gitlab user's SSH config.
     
     # Add to /home/git/.ssh/config
     host localhost          # Give your setup a name (here: override localhost)
diff --git a/features/steps/profile/profile_ssh_keys.rb b/features/steps/profile/profile_ssh_keys.rb
index 8ae1fa910257abe044d74162a415bc1732b4539b..fbb92077f0a3d6edb8e5f98dfdb26a8379cad602 100644
--- a/features/steps/profile/profile_ssh_keys.rb
+++ b/features/steps/profile/profile_ssh_keys.rb
@@ -43,6 +43,6 @@ class ProfileSshKeys < Spinach::FeatureSteps
   end
 
   And 'I have ssh key "ssh-rsa Work"' do
-    create(:key, :user => @user, :title => "ssh-rsa Work", :key => "jfKLJDFKSFJSHFJssh-rsa Work")
+    create(:key, :user => @user, :title => "ssh-rsa Work", :key => "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+L3TbFegm3k8QjejSwemk4HhlRh+DuN679Pc5ckqE/MPhVtE/+kZQDYCTB284GiT2aIoGzmZ8ee9TkaoejAsBwlA+Wz2Q3vhz65X6sMgalRwpdJx8kSEUYV8ZPV3MZvPo8KdNg993o4jL6G36GDW4BPIyO6FPZhfsawdf6liVD0Xo5kibIK7B9VoE178cdLQtLpS2YolRwf5yy6XR6hbbBGQR+6xrGOdP16eGZDb1CE2bMvvJijjloFqPscGktWOqW+nfh5txwFfBzlfARDTBsS8WZtg3Yoj1kn33kPsWRlgHfNutFRAIynDuDdQzQq8tTtVwm+Yi75RfcPHW8y3P Work")
   end
 end
diff --git a/features/steps/project/project_issues.rb b/features/steps/project/project_issues.rb
index 2103aeb17158c5140520912e1cb8934226f10dcd..7d54009988ff9ea5b5560dcd807627cad36e087d 100644
--- a/features/steps/project/project_issues.rb
+++ b/features/steps/project/project_issues.rb
@@ -122,10 +122,9 @@ class ProjectIssues < Spinach::FeatureSteps
 
   And 'project "Shop" have "Release 0.3" closed issue' do
     project = Project.find_by_name("Shop")
-    create(:issue,
+    create(:closed_issue,
            :title => "Release 0.3",
            :project => project,
-           :author => project.users.first,
-           :closed => true)
+           :author => project.users.first)
   end
 end
diff --git a/features/steps/project/project_merge_requests.rb b/features/steps/project/project_merge_requests.rb
index 329261add2a44e15d9ccb763e11b7494cfff0061..ff95a47d4cff35cacc68baaa5288d117b5775724 100644
--- a/features/steps/project/project_merge_requests.rb
+++ b/features/steps/project/project_merge_requests.rb
@@ -26,7 +26,7 @@ class ProjectMergeRequests < Spinach::FeatureSteps
 
   Then 'I should see closed merge request "Bug NS-04"' do
     mr = MergeRequest.find_by_title("Bug NS-04")
-    mr.closed.should be_true
+    mr.closed?.should be_true
     page.should have_content "Closed by"
   end
 
@@ -80,11 +80,10 @@ class ProjectMergeRequests < Spinach::FeatureSteps
 
   And 'project "Shop" have "Feature NS-03" closed merge request' do
     project = Project.find_by_name("Shop")
-    create(:merge_request,
+    create(:closed_merge_request,
            title: "Feature NS-03",
            project: project,
-           author: project.users.first,
-           closed: true)
+           author: project.users.first)
   end
 
   And 'I switch to the diff tab' do
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index c1873d87b55fc9216e6542c21133620fb8a9c65c..1cae1d337fee907756a37ee8dd237545ea72d827 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -20,7 +20,7 @@ module Gitlab
     class Project < Grape::Entity
       expose :id, :name, :description, :default_branch
       expose :owner, using: Entities::UserBasic
-      expose :private_flag, as: :private
+      expose :public
       expose :path, :path_with_namespace
       expose :issues_enabled, :merge_requests_enabled, :wall_enabled, :wiki_enabled, :created_at
       expose :namespace
@@ -35,12 +35,11 @@ module Gitlab
     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|
@@ -63,7 +62,7 @@ module Gitlab
     class Milestone < Grape::Entity
       expose :id
       expose (:project_id) {|milestone| milestone.project.id}
-      expose :title, :description, :due_date, :closed, :updated_at, :created_at
+      expose :title, :description, :due_date, :state, :updated_at, :created_at
     end
 
     class Issue < Grape::Entity
@@ -73,7 +72,7 @@ module Gitlab
       expose :label_list, as: :labels
       expose :milestone, using: Entities::Milestone
       expose :assignee, :author, using: Entities::UserBasic
-      expose :closed, :updated_at, :created_at
+      expose :state, :updated_at, :created_at
     end
 
     class SSHKey < Grape::Entity
@@ -81,7 +80,7 @@ module Gitlab
     end
 
     class MergeRequest < Grape::Entity
-      expose :id, :target_branch, :source_branch, :project_id, :title, :closed, :merged
+      expose :id, :target_branch, :source_branch, :project_id, :title, :state
       expose :author, :assignee, using: Entities::UserBasic
     end
 
diff --git a/lib/api/internal.rb b/lib/api/internal.rb
index 3e5e3a478ba1d34176ac197ecd2007f73820b5ee..5d74a761c05f6b3e6746ada51f0567a13c4eb890 100644
--- a/lib/api/internal.rb
+++ b/lib/api/internal.rb
@@ -40,7 +40,9 @@ module Gitlab
 
       get "/check" do
         {
-          api_version: '3'
+          api_version: Gitlab::API.version,
+          gitlab_version: Gitlab::VERSION,
+          gitlab_rev: Gitlab::REVISION,
         }
       end
     end
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index 4d832fbe59372707f1b1bb359351aab77975d341..70bbf47e72c05618ee78576d976c2afbd64305ff 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -69,14 +69,14 @@ module Gitlab
       #   assignee_id (optional) - The ID of a user to assign issue
       #   milestone_id (optional) - The ID of a milestone to assign issue
       #   labels (optional) - The labels of an issue
-      #   closed (optional) - The state of an issue (0 = false, 1 = true)
+      #   state (optional) - The state of an issue (close|reopen)
       # Example Request:
       #   PUT /projects/:id/issues/:issue_id
       put ":id/issues/:issue_id" do
         @issue = user_project.issues.find(params[:issue_id])
         authorize! :modify_issue, @issue
 
-        attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id, :closed]
+        attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id, :state_event]
         attrs[:label_list] = params[:labels] if params[:labels].present?
         IssueObserver.current_user = current_user
         if @issue.update_attributes attrs
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index 0c18ece382422f3953d2594d0bb2a583028ec68b..4b28094f1a4a83000eb929448ffd19da41d4ccb5 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -91,12 +91,12 @@ module Gitlab
       #   target_branch               - The target branch
       #   assignee_id                 - Assignee user ID
       #   title                       - Title of MR
-      #   closed                      - Status of MR. true - closed
+      #   state_event                 - Status of MR. (close|reopen|merge)
       # Example:
       #   PUT /projects/:id/merge_request/:merge_request_id
       #
       put ":id/merge_request/:merge_request_id" do
-        attrs = attributes_for_keys [:source_branch, :target_branch, :assignee_id, :title, :closed]
+        attrs = attributes_for_keys [:source_branch, :target_branch, :assignee_id, :title, :state_event]
         merge_request = user_project.merge_requests.find(params[:merge_request_id])
 
         authorize! :modify_merge_request, merge_request
diff --git a/lib/api/milestones.rb b/lib/api/milestones.rb
index cdb0e14690d1def451b5440dffe157ed2a526c0f..7f8fe053ba183d44ff0a1643f0f5f285d9669626 100644
--- a/lib/api/milestones.rb
+++ b/lib/api/milestones.rb
@@ -74,14 +74,14 @@ module Gitlab
       #   title (optional) - The title of a milestone
       #   description (optional) - The description of a milestone
       #   due_date (optional) - The due date of a milestone
-      #   closed (optional) - The status of the milestone
+      #   state (optional) - The status of the milestone (close|activate)
       # Example Request:
       #   PUT /projects/:id/milestones/:milestone_id
       put ":id/milestones/:milestone_id" do
         authorize! :admin_milestone, user_project
 
         @milestone = user_project.milestones.find(params[:milestone_id])
-        attrs = attributes_for_keys [:title, :description, :due_date, :closed]
+        attrs = attributes_for_keys [:title, :description, :due_date, :state_event]
         if @milestone.update_attributes attrs
           present @milestone, with: Entities::Milestone
         else
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index cf3e8257a776a2429b8a73b2c4da32c0c95c17fd..d171acc1ce1dc58857bf8c99f0eb03f8b54804f9 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -184,6 +184,7 @@ module Gitlab
       # Example Request:
       #   GET /projects/:id/hooks/:hook_id
       get ":id/hooks/:hook_id" do
+        authorize! :admin_project, user_project
         @hook = user_project.hooks.find(params[:hook_id])
         present @hook, with: Entities::Hook
       end
diff --git a/lib/gitlab/backend/grack_auth.rb b/lib/gitlab/backend/grack_auth.rb
index a2d15d5703445ec3ee2190071ef6daf429f9fcb9..abbee6132d34d11cadf3e10ad36528bc3594250a 100644
--- a/lib/gitlab/backend/grack_auth.rb
+++ b/lib/gitlab/backend/grack_auth.rb
@@ -1,3 +1,5 @@
+require_relative 'shell_env'
+
 module Grack
   class Auth < Rack::Auth::Basic
     attr_accessor :user, :project
@@ -7,9 +9,6 @@ module Grack
       @request = Rack::Request.new(env)
       @auth = Request.new(env)
 
-      # Pass Gitolite update hook
-      ENV['GL_BYPASS_UPDATE_HOOK'] = "true"
-
       # Need this patch due to the rails mount
       @env['PATH_INFO'] = @request.path
       @env['SCRIPT_NAME'] = ""
@@ -35,8 +34,7 @@ module Grack
         self.user = User.find_by_email(login) || User.find_by_username(login)
         return false unless user.try(:valid_password?, password)
 
-        # Set GL_USER env variable
-        ENV['GL_USER'] = user.email
+        Gitlab::ShellEnv.set_env(user)
       end
 
       # Git upload and receive
diff --git a/lib/gitlab/backend/shell.rb b/lib/gitlab/backend/shell.rb
index 85fa5bda0558ea2855d31729b59ee07beaa4a900..9ea08ccbdbf64576aefb3b9570ae1c5b6c72012c 100644
--- a/lib/gitlab/backend/shell.rb
+++ b/lib/gitlab/backend/shell.rb
@@ -10,7 +10,7 @@ module Gitlab
     #   add_repository("gitlab/gitlab-ci")
     #
     def add_repository(name)
-      system("/home/git/gitlab-shell/bin/gitlab-projects add-project #{name}.git")
+      system("#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-projects add-project #{name}.git")
     end
 
     # Import repository
@@ -21,7 +21,7 @@ module Gitlab
     #   import_repository("gitlab/gitlab-ci", "https://github.com/randx/six.git")
     #
     def import_repository(name, url)
-      system("/home/git/gitlab-shell/bin/gitlab-projects import-project #{name}.git #{url}")
+      system("#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-projects import-project #{name}.git #{url}")
     end
 
     # Remove repository from file system
@@ -32,7 +32,7 @@ module Gitlab
     #   remove_repository("gitlab/gitlab-ci")
     #
     def remove_repository(name)
-      system("/home/git/gitlab-shell/bin/gitlab-projects rm-project #{name}.git")
+      system("#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-projects rm-project #{name}.git")
     end
 
     # Add new key to gitlab-shell
@@ -41,7 +41,7 @@ module Gitlab
     #   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}\"")
+      system("#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-keys add-key #{key_id} \"#{key_content}\"")
     end
 
     # Remove ssh key from gitlab shell
@@ -50,12 +50,16 @@ module Gitlab
     #   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}\"")
+      system("#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-keys rm-key #{key_id} \"#{key_content}\"")
     end
 
-
     def url_to_repo path
       Gitlab.config.gitlab_shell.ssh_path_prefix + "#{path}.git"
     end
+   
+    def gitlab_shell_user_home
+      File.expand_path("~#{Gitlab.config.gitlab_shell.ssh_user}")
+    end
+
   end
 end
diff --git a/lib/gitlab/backend/shell_env.rb b/lib/gitlab/backend/shell_env.rb
new file mode 100644
index 0000000000000000000000000000000000000000..157218750938d341d1b644def73bea38c4b099a2
--- /dev/null
+++ b/lib/gitlab/backend/shell_env.rb
@@ -0,0 +1,17 @@
+module Gitlab
+  # This module provide 2 methods
+  # to set specific ENV variabled for GitLab Shell
+  module ShellEnv
+    extend self
+
+    def set_env(user)
+      # Set GL_ID env variable
+      ENV['GL_ID'] = "user-#{user.id}"
+    end
+
+    def reset_env
+      # Reset GL_ID env variable
+      ENV['GL_ID'] = nil
+    end
+  end
+end
diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb
index 483042205ead472aacd4634fe9539c618c43166d..5eeb7c801848d4a1bb8dc9c296bf89b1059c00d8 100644
--- a/lib/gitlab/regex.rb
+++ b/lib/gitlab/regex.rb
@@ -10,6 +10,10 @@ module Gitlab
       /\A[a-zA-Z][a-zA-Z0-9_\-\. ]*\z/
     end
 
+    def name_regex
+      /\A[a-zA-Z0-9_\-\. ]*\z/
+    end
+
     def path_regex
       default_regex
     end
diff --git a/lib/gitlab/satellite/action.rb b/lib/gitlab/satellite/action.rb
index ed2541f3998e45c0fd09345d0d37439c9d4ec89d..63303ca3de14c9d31a04f08b7630237e82d8c502 100644
--- a/lib/gitlab/satellite/action.rb
+++ b/lib/gitlab/satellite/action.rb
@@ -17,6 +17,8 @@ module Gitlab
       # * Locks the satellite repo
       # * Yields the prepared satellite repo
       def in_locked_and_timed_satellite
+        Gitlab::ShellEnv.set_env(user)
+
         Grit::Git.with_timeout(options[:git_timeout]) do
           project.satellite.lock do
             return yield project.satellite.repo
@@ -28,6 +30,8 @@ module Gitlab
       rescue Grit::Git::GitTimeout => ex
         Gitlab::GitLogger.error(ex.message)
         return false
+      ensure
+        Gitlab::ShellEnv.reset_env
       end
 
       # * Clears the satellite
diff --git a/lib/tasks/gitlab/info.rake b/lib/tasks/gitlab/info.rake
index c44016ef6e84bb95d5f89aa2dc72707332ffdbc2..091de6ee6d565819df784bc67787c8db5293293f 100644
--- a/lib/tasks/gitlab/info.rake
+++ b/lib/tasks/gitlab/info.rake
@@ -40,8 +40,8 @@ namespace :gitlab do
 
       puts ""
       puts "GitLab information".yellow
-      puts "Version:\t#{Gitlab::Version}"
-      puts "Revision:\t#{Gitlab::Revision}"
+      puts "Version:\t#{Gitlab::VERSION}"
+      puts "Revision:\t#{Gitlab::REVISION}"
       puts "Directory:\t#{Rails.root}"
       puts "DB Adapter:\t#{database_adapter}"
       puts "URL:\t\t#{Gitlab.config.gitlab.url}"
diff --git a/lib/tasks/gitlab/setup.rake b/lib/tasks/gitlab/setup.rake
index bc0742564d035a70d16ea309e1795b8490460571..8d4950cf396cc46af807ca879de77b0f4f9e5564 100644
--- a/lib/tasks/gitlab/setup.rake
+++ b/lib/tasks/gitlab/setup.rake
@@ -1,10 +1,10 @@
 namespace :gitlab do
   desc "GITLAB | Setup production application"
   task :setup => :environment do
-    setup
+    setup_db
   end
 
-  def setup
+  def setup_db
     warn_user_is_not_gitlab
 
     puts "This will create the necessary database tables and seed the database."
diff --git a/lib/tasks/gitlab/shell.rake b/lib/tasks/gitlab/shell.rake
index 0ab8df1d094093728158d124793c5dc0038c0422..ec5451dd47c5d13ecf9835c0ee092018d7fc6b23 100644
--- a/lib/tasks/gitlab/shell.rake
+++ b/lib/tasks/gitlab/shell.rake
@@ -25,12 +25,13 @@ namespace :gitlab do
   def setup
     warn_user_is_not_gitlab
 
+    gitlab_shell_authorized_keys = File.join(File.expand_path("~#{Gitlab.config.gitlab_shell.ssh_user}"),'.ssh/authorized_keys')
     puts "This will rebuild an authorized_keys file."
-    puts "You will lose any data stored in /home/git/.ssh/authorized_keys."
+    puts "You will lose any data stored in #{gitlab_shell_authorized_keys}."
     ask_to_continue
     puts ""
 
-    system("echo '# Managed by gitlab-shell' > /home/git/.ssh/authorized_keys")
+    system("echo '# Managed by gitlab-shell' > #{gitlab_shell_authorized_keys}")
 
     Key.find_each(batch_size: 1000) do |key|
       if Gitlab::Shell.new.add_key(key.shell_id, key.key)
diff --git a/lib/tasks/gitlab/task_helpers.rake b/lib/tasks/gitlab/task_helpers.rake
index d494125f76cc011eb0df44ac760c705047fe573b..cb4e34cc0d78b48ece2e71c1f9c014c1d380359e 100644
--- a/lib/tasks/gitlab/task_helpers.rake
+++ b/lib/tasks/gitlab/task_helpers.rake
@@ -77,8 +77,7 @@ namespace :gitlab do
   end
 
   def gid_for(group_name)
-    group_line = File.read("/etc/group").lines.select{|l| l.start_with?("#{group_name}:")}.first
-    group_line.split(":")[2].to_i
+    Etc.getgrnam(group_name).gid
   end
 
   def warn_user_is_not_gitlab
diff --git a/public/deploy.html b/public/deploy.html
index d8c287809ea0ae0ed485aa81f57bca3e753065d0..d9c4bb5c5833038732b13f7f69641978b09c512d 100644
--- a/public/deploy.html
+++ b/public/deploy.html
@@ -5,7 +5,7 @@
     <link href="/static.css" media="screen" rel="stylesheet" type="text/css" />
   </head>
   <body>
-    <h1>Deploy in progress</h1>
+    <h1><center><img src="/gitlab_logo.png"/></center>Deploy in progress</h1>
     <h3>Please try again in few minutes or contact your administrator.</h3>
   </body>
 </html>
diff --git a/public/gitlab_logo.png b/public/gitlab_logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..e3cda5978ab5ace1be801295eab4213d8853ef32
Binary files /dev/null and b/public/gitlab_logo.png differ
diff --git a/spec/factories.rb b/spec/factories.rb
index d2e9f48c47ba81ed31df1dd1da781d2b2f55d80a..b81984b5d5350cd603dbdbce9dc8aaafe64ab3f2 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -54,10 +54,15 @@ FactoryGirl.define do
     project
 
     trait :closed do
-      closed true
+      state :closed
+    end
+
+    trait :reopened do
+      state :reopened
     end
 
     factory :closed_issue, traits: [:closed]
+    factory :reopened_issue, traits: [:reopened]
   end
 
   factory :merge_request do
@@ -67,10 +72,6 @@ FactoryGirl.define do
     source_branch "master"
     target_branch "stable"
 
-    trait :closed do
-      closed true
-    end
-
     # pick 3 commits "at random" (from bcf03b5d~3 to bcf03b5d)
     trait :with_diffs do
       target_branch "master" # pretend bcf03b5d~3
@@ -85,7 +86,16 @@ FactoryGirl.define do
       end
     end
 
+    trait :closed do
+      state :closed
+    end
+
+    trait :reopened do
+      state :reopened
+    end
+
     factory :closed_merge_request, traits: [:closed]
+    factory :reopened_merge_request, traits: [:reopened]
     factory :merge_request_with_diffs, traits: [:with_diffs]
   end
 
@@ -148,11 +158,23 @@ FactoryGirl.define do
         "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa ++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
       end
     end
+
+    factory :invalid_key do
+      key do
+        "ssh-rsa this_is_invalid_key=="
+      end
+    end
   end
 
   factory :milestone do
     title
     project
+
+    trait :closed do
+      state :closed
+    end
+
+    factory :closed_milestone, traits: [:closed]
   end
 
   factory :system_hook do
diff --git a/spec/factories_spec.rb b/spec/factories_spec.rb
index 5ee7354688a606f625455fef76e9b9ce5f9578c9..8360477d8febf1cbeb1b4ec37c1f7f99e660df68 100644
--- a/spec/factories_spec.rb
+++ b/spec/factories_spec.rb
@@ -1,6 +1,9 @@
 require 'spec_helper'
 
-INVALID_FACTORIES = [:key_with_a_space_in_the_middle]
+INVALID_FACTORIES = [
+    :key_with_a_space_in_the_middle,
+    :invalid_key,
+]
 
 FactoryGirl.factories.map(&:name).each do |factory_name|
   next if INVALID_FACTORIES.include?(factory_name)
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index b5d4bd7b406e5d3cf1cc79fef9ced4ec2d4da688..551e1753be00cee13329d006541351d87ec655ee 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -15,7 +15,6 @@ describe Issue, "Issuable" do
     it { should validate_presence_of(:author) }
     it { should validate_presence_of(:title) }
     it { should ensure_length_of(:title).is_at_least(0).is_at_most(255) }
-    it { should ensure_inclusion_of(:closed).in_array([true, false]) }
   end
 
   describe "Scope" do
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index 10db53e07450862d9da1b66488c3ad8ed9b5ba89..99d9f65b0d7c5f00a4ef6140da1acd4d730bc150 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -9,7 +9,7 @@
 #  project_id   :integer
 #  created_at   :datetime         not null
 #  updated_at   :datetime         not null
-#  closed       :boolean          default(FALSE), not null
+#  state        :string           default(FALSE), not null
 #  position     :integer          default(0)
 #  branch_name  :string(255)
 #  description  :text
@@ -44,34 +44,15 @@ describe Issue do
     end
   end
 
-  describe '#is_being_closed?' do
-    it 'returns true if the closed attribute has changed and is now true' do
-      subject.closed = true
-      subject.is_being_closed?.should be_true
-    end
-    it 'returns false if the closed attribute has changed and is now false' do
-      issue = create(:closed_issue)
-      issue.closed = false
-      issue.is_being_closed?.should be_false
-    end
-    it 'returns false if the closed attribute has not changed' do
-      subject.is_being_closed?.should be_false
-    end
-  end
+  describe '#is_being_reassigned?' do
+    it 'returnes issues assigned to user' do
+      user = create :user
 
+      2.times do
+        issue = create :issue, assignee: user
+      end
 
-  describe '#is_being_reopened?' do
-    it 'returns true if the closed attribute has changed and is now false' do
-      issue = create(:closed_issue)
-      issue.closed = false
-      issue.is_being_reopened?.should be_true
-    end
-    it 'returns false if the closed attribute has changed and is now true' do
-      subject.closed = true
-      subject.is_being_reopened?.should be_false
-    end
-    it 'returns false if the closed attribute has not changed' do
-      subject.is_being_reopened?.should be_false
+      Issue.open_for(user).count.should eq 2
     end
   end
 end
diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb
index 94b952cf932f58d0d26b4f21dcdbc6a247562a9e..a9ab2f05a3411e3c8a4a54d748751926bf827bf8 100644
--- a/spec/models/key_spec.rb
+++ b/spec/models/key_spec.rb
@@ -73,8 +73,12 @@ describe Key do
       build(:key, user: user).should be_valid
     end
 
-    it "rejects the unfingerprintable key" do
+    it "rejects the unfingerprintable key (contains space in middle)" do
       build(:key_with_a_space_in_the_middle).should_not be_valid
     end
+
+    it "rejects the unfingerprintable key (not a key)" do
+      build(:invalid_key).should_not be_valid
+    end
   end
 end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 41f4ede5d89e3a752e0f9b4278d0d3262aa6d0e3..e61bf44ce53e8e512af12f3650ea81be68c362b1 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -15,7 +15,7 @@
 #  st_commits    :text(2147483647)
 #  st_diffs      :text(2147483647)
 #  merged        :boolean          default(FALSE), not null
-#  state         :integer          default(1), not null
+#  merge_status  :integer          default(1), not null
 #  milestone_id  :integer
 #
 
@@ -36,6 +36,10 @@ describe MergeRequest do
     it { should include_module(Issuable) }
   end
 
+  describe "#mr_and_commit_notes" do
+
+  end
+
   describe "#mr_and_commit_notes" do
     let!(:merge_request) { create(:merge_request) }
 
@@ -62,35 +66,4 @@ describe MergeRequest do
       subject.is_being_reassigned?.should be_false
     end
   end
-
-  describe '#is_being_closed?' do
-    it 'returns true if the closed attribute has changed and is now true' do
-      subject.closed = true
-      subject.is_being_closed?.should be_true
-    end
-    it 'returns false if the closed attribute has changed and is now false' do
-      merge_request = create(:closed_merge_request)
-      merge_request.closed = false
-      merge_request.is_being_closed?.should be_false
-    end
-    it 'returns false if the closed attribute has not changed' do
-      subject.is_being_closed?.should be_false
-    end
-  end
-
-
-  describe '#is_being_reopened?' do
-    it 'returns true if the closed attribute has changed and is now false' do
-      merge_request = create(:closed_merge_request)
-      merge_request.closed = false
-      merge_request.is_being_reopened?.should be_true
-    end
-    it 'returns false if the closed attribute has changed and is now true' do
-      subject.closed = true
-      subject.is_being_reopened?.should be_false
-    end
-    it 'returns false if the closed attribute has not changed' do
-      subject.is_being_reopened?.should be_false
-    end
-  end
 end
diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb
index 2ea2c56a6f738177c71bb12b16b95c1861ba5ed0..b473f8431465ac28677490121561346e91e60ced 100644
--- a/spec/models/milestone_spec.rb
+++ b/spec/models/milestone_spec.rb
@@ -7,7 +7,7 @@
 #  project_id  :integer          not null
 #  description :text
 #  due_date    :date
-#  closed      :boolean          default(FALSE), not null
+#  state       :string           default(FALSE), not null
 #  created_at  :datetime         not null
 #  updated_at  :datetime         not null
 #
@@ -27,7 +27,6 @@ describe Milestone do
   describe "Validation" do
     it { should validate_presence_of(:title) }
     it { should validate_presence_of(:project) }
-    it { should ensure_inclusion_of(:closed).in_array([true, false]) }
   end
 
   let(:milestone) { create(:milestone) }
@@ -41,7 +40,7 @@ describe Milestone do
 
     it "should count closed issues" do
       IssueObserver.current_user = issue.author
-      issue.update_attributes(closed: true)
+      issue.close
       milestone.issues << issue
       milestone.percent_complete.should == 100
     end
@@ -96,7 +95,7 @@ describe Milestone do
   describe :items_count do
     before do
       milestone.issues << create(:issue)
-      milestone.issues << create(:issue, closed: true)
+      milestone.issues << create(:closed_issue)
       milestone.merge_requests << create(:merge_request)
     end
 
@@ -110,7 +109,35 @@ describe Milestone do
     it { milestone.can_be_closed?.should be_true }
   end
 
-  describe :open? do
-    it { milestone.open?.should be_true }
+  describe :is_empty? do
+    before do
+      issue = create :closed_issue, milestone: milestone
+      merge_request = create :merge_request, milestone: milestone
+    end
+
+    it 'Should return total count of issues and merge requests assigned to milestone' do
+      milestone.total_items_count.should eq 2
+    end
+  end
+
+  describe :can_be_closed? do
+    before do
+      milestone = create :milestone
+      create :closed_issue, milestone: milestone
+
+      issue = create :issue
+    end
+
+    it 'should be true if milestone active and all nestied issues closed' do
+      milestone.can_be_closed?.should be_true
+    end
+
+    it 'should be false if milestone active and not all nestied issues closed' do
+      issue.milestone = milestone
+      issue.save 
+
+      milestone.can_be_closed?.should be_false
+    end
   end
+
 end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 4b620a2fa3efddcbfdfbffacabac798923cf1062..5c27f3634012907be52b94097f6b675c3ab32bfa 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -121,10 +121,7 @@ describe Project do
     let(:project) { create(:project) }
 
     before do
-      @merge_request = create(:merge_request,
-                              project: project,
-                              merged: false,
-                              closed: false)
+      @merge_request = create(:merge_request, project: project)
       @key = create(:key, user_id: project.owner.id)
     end
 
@@ -133,8 +130,7 @@ describe Project do
       @merge_request.last_commit.id.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a"
       project.update_merge_requests("8716fc78f3c65bbf7bcf7b574febd583bc5d2812", "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a", "refs/heads/stable", @key.user)
       @merge_request.reload
-      @merge_request.merged.should be_true
-      @merge_request.closed.should be_true
+      @merge_request.merged?.should be_true
     end
 
     it "should update merge request commits with new one if pushed to source branch" do
diff --git a/spec/observers/issue_observer_spec.rb b/spec/observers/issue_observer_spec.rb
index 700c9a3a69bc8d4e7049917c8b033150555faa0f..e4e66917e8a3ced69d95ad330e59fe759a04a7f8 100644
--- a/spec/observers/issue_observer_spec.rb
+++ b/spec/observers/issue_observer_spec.rb
@@ -1,10 +1,15 @@
 require 'spec_helper'
 
 describe IssueObserver do
-  let(:some_user) { double(:user, id: 1) }
-  let(:assignee) { double(:user, id: 2) }
-  let(:author) { double(:user, id: 3) }
-  let(:issue)    { double(:issue, id: 42, assignee: assignee, author: author) }
+  let(:some_user)      { create :user }
+  let(:assignee)       { create :user }
+  let(:author)         { create :user }
+  let(:mock_issue)     { double(:issue, id: 42, assignee: assignee, author: author) }
+  let(:assigned_issue)   { create(:issue, assignee: assignee, author: author) }
+  let(:unassigned_issue) { create(:issue, author: author) }
+  let(:closed_assigned_issue)   { create(:closed_issue, assignee: assignee, author: author) }
+  let(:closed_unassigned_issue) { create(:closed_issue, author: author) }
+
 
   before(:each) { subject.stub(:current_user).and_return(some_user) }
 
@@ -21,137 +26,91 @@ describe IssueObserver do
     end
 
     it 'sends an email to the assignee' do
-      Notify.should_receive(:new_issue_email).with(issue.id)
+      Notify.should_receive(:new_issue_email).with(mock_issue.id)
 
-      subject.after_create(issue)
+      subject.after_create(mock_issue)
     end
 
     it 'does not send an email to the assignee if assignee created the issue' do
       subject.stub(:current_user).and_return(assignee)
       Notify.should_not_receive(:new_issue_email)
 
-      subject.after_create(issue)
+      subject.after_create(mock_issue)
     end
   end
 
-  context '#after_update' do
-    before(:each) do
-      issue.stub(:is_being_reassigned?).and_return(false)
-      issue.stub(:is_being_closed?).and_return(false)
-      issue.stub(:is_being_reopened?).and_return(false)
-    end
-
-    it 'is called when an issue is changed' do
-      changed = create(:issue, project: create(:project))
-      subject.should_receive(:after_update)
-
-      Issue.observers.enable :issue_observer do
-        changed.description = 'I changed'
-        changed.save
-      end
-    end
-
-    context 'a reassigned email' do
-      it 'is sent if the issue is being reassigned' do
-        issue.should_receive(:is_being_reassigned?).and_return(true)
-        subject.should_receive(:send_reassigned_email).with(issue)
-
-        subject.after_update(issue)
-      end
-
-      it 'is not sent if the issue is not being reassigned' do
-        issue.should_receive(:is_being_reassigned?).and_return(false)
-        subject.should_not_receive(:send_reassigned_email)
-
-        subject.after_update(issue)
-      end
-    end
-
+  context '#after_close' do
     context 'a status "closed"' do
       it 'note is created if the issue is being closed' do
-        issue.should_receive(:is_being_closed?).and_return(true)
-        Notify.should_receive(:issue_status_changed_email).twice
-        Note.should_receive(:create_status_change_note).with(issue, some_user, 'closed')
-
-        subject.after_update(issue)
-      end
-
-      it 'note is not created if the issue is not being closed' do
-        issue.should_receive(:is_being_closed?).and_return(false)
-        Note.should_not_receive(:create_status_change_note).with(issue, some_user, 'closed')
+        Note.should_receive(:create_status_change_note).with(assigned_issue, some_user, 'closed')
 
-        subject.after_update(issue)
+        assigned_issue.close
       end
 
       it 'notification is delivered if the issue being closed' do
-        issue.stub(:is_being_closed?).and_return(true)
         Notify.should_receive(:issue_status_changed_email).twice
-        Note.should_receive(:create_status_change_note).with(issue, some_user, 'closed')
 
-        subject.after_update(issue)
-      end
-
-      it 'notification is not delivered if the issue not being closed' do
-        issue.stub(:is_being_closed?).and_return(false)
-        Notify.should_not_receive(:issue_status_changed_email)
-        Note.should_not_receive(:create_status_change_note).with(issue, some_user, 'closed')
-
-        subject.after_update(issue)
+        assigned_issue.close
       end
 
       it 'notification is delivered only to author if the issue being closed' do
-        issue_without_assignee = double(:issue, id: 42, author: author, assignee: nil)
-        issue_without_assignee.stub(:is_being_reassigned?).and_return(false)
-        issue_without_assignee.stub(:is_being_closed?).and_return(true)
-        issue_without_assignee.stub(:is_being_reopened?).and_return(false)
         Notify.should_receive(:issue_status_changed_email).once
-        Note.should_receive(:create_status_change_note).with(issue_without_assignee, some_user, 'closed')
+        Note.should_receive(:create_status_change_note).with(unassigned_issue, some_user, 'closed')
 
-        subject.after_update(issue_without_assignee)
+        unassigned_issue.close
       end
     end
 
     context 'a status "reopened"' do
       it 'note is created if the issue is being reopened' do
+        Note.should_receive(:create_status_change_note).with(closed_assigned_issue, some_user, 'reopened')
+
+        closed_assigned_issue.reopen
+      end
+
+      it 'notification is delivered if the issue being reopened' do
         Notify.should_receive(:issue_status_changed_email).twice
-        issue.should_receive(:is_being_reopened?).and_return(true)
-        Note.should_receive(:create_status_change_note).with(issue, some_user, 'reopened')
 
-        subject.after_update(issue)
+        closed_assigned_issue.reopen
       end
 
-      it 'note is not created if the issue is not being reopened' do
-        issue.should_receive(:is_being_reopened?).and_return(false)
-        Note.should_not_receive(:create_status_change_note).with(issue, some_user, 'reopened')
+      it 'notification is delivered only to author if the issue being reopened' do
+        Notify.should_receive(:issue_status_changed_email).once
+        Note.should_receive(:create_status_change_note).with(closed_unassigned_issue, some_user, 'reopened')
 
-        subject.after_update(issue)
+        closed_unassigned_issue.reopen
       end
+    end
+  end
 
-      it 'notification is delivered if the issue being reopened' do
-        issue.stub(:is_being_reopened?).and_return(true)
-        Notify.should_receive(:issue_status_changed_email).twice
-        Note.should_receive(:create_status_change_note).with(issue, some_user, 'reopened')
+  context '#after_update' do
+    before(:each) do
+      mock_issue.stub(:is_being_reassigned?).and_return(false)
+    end
+
+    it 'is called when an issue is changed' do
+      changed = create(:issue, project: create(:project))
+      subject.should_receive(:after_update)
 
-        subject.after_update(issue)
+      Issue.observers.enable :issue_observer do
+        changed.description = 'I changed'
+        changed.save
       end
+    end
 
-      it 'notification is not delivered if the issue not being reopened' do
-        issue.stub(:is_being_reopened?).and_return(false)
-        Notify.should_not_receive(:issue_status_changed_email)
-        Note.should_not_receive(:create_status_change_note).with(issue, some_user, 'reopened')
+    context 'a reassigned email' do
+      it 'is sent if the issue is being reassigned' do
+        mock_issue.should_receive(:is_being_reassigned?).and_return(true)
+        subject.should_receive(:send_reassigned_email).with(mock_issue)
 
-        subject.after_update(issue)
+        subject.after_update(mock_issue)
       end
 
-      it 'notification is delivered only to author if the issue being reopened' do
-        issue_without_assignee = double(:issue, id: 42, author: author, assignee: nil)
-        issue_without_assignee.stub(:is_being_reassigned?).and_return(false)
-        issue_without_assignee.stub(:is_being_closed?).and_return(false)
-        issue_without_assignee.stub(:is_being_reopened?).and_return(true)
-        Notify.should_receive(:issue_status_changed_email).once
-        Note.should_receive(:create_status_change_note).with(issue_without_assignee, some_user, 'reopened')
+      it 'is not sent if the issue is not being reassigned' do
+        mock_issue.should_receive(:is_being_reassigned?).and_return(false)
+        subject.should_not_receive(:send_reassigned_email)
 
-        subject.after_update(issue_without_assignee)
+        subject.after_update(mock_issue)
       end
     end
   end
@@ -160,23 +119,23 @@ describe IssueObserver do
     let(:previous_assignee) { double(:user, id: 3) }
 
     before(:each) do
-      issue.stub(:assignee_id).and_return(assignee.id)
-      issue.stub(:assignee_id_was).and_return(previous_assignee.id)
+      mock_issue.stub(:assignee_id).and_return(assignee.id)
+      mock_issue.stub(:assignee_id_was).and_return(previous_assignee.id)
     end
 
     def it_sends_a_reassigned_email_to(recipient)
-      Notify.should_receive(:reassigned_issue_email).with(recipient, issue.id, previous_assignee.id)
+      Notify.should_receive(:reassigned_issue_email).with(recipient, mock_issue.id, previous_assignee.id)
     end
 
     def it_does_not_send_a_reassigned_email_to(recipient)
-      Notify.should_not_receive(:reassigned_issue_email).with(recipient, issue.id, previous_assignee.id)
+      Notify.should_not_receive(:reassigned_issue_email).with(recipient, mock_issue.id, previous_assignee.id)
     end
 
     it 'sends a reassigned email to the previous and current assignees' do
       it_sends_a_reassigned_email_to assignee.id
       it_sends_a_reassigned_email_to previous_assignee.id
 
-      subject.send(:send_reassigned_email, issue)
+      subject.send(:send_reassigned_email, mock_issue)
     end
 
     context 'does not send an email to the user who made the reassignment' do
@@ -185,14 +144,14 @@ describe IssueObserver do
         it_sends_a_reassigned_email_to previous_assignee.id
         it_does_not_send_a_reassigned_email_to assignee.id
 
-        subject.send(:send_reassigned_email, issue)
+        subject.send(:send_reassigned_email, mock_issue)
       end
       it 'if the user is the previous assignee' do
         subject.stub(:current_user).and_return(previous_assignee)
         it_sends_a_reassigned_email_to assignee.id
         it_does_not_send_a_reassigned_email_to previous_assignee.id
 
-        subject.send(:send_reassigned_email, issue)
+        subject.send(:send_reassigned_email, mock_issue)
       end
     end
   end
diff --git a/spec/observers/merge_request_observer_spec.rb b/spec/observers/merge_request_observer_spec.rb
index 4841bf88fc54f5893d3e3f648237e19ebbd303e9..9d702107a895eb16e3970183eaddde7b536346c9 100644
--- a/spec/observers/merge_request_observer_spec.rb
+++ b/spec/observers/merge_request_observer_spec.rb
@@ -1,10 +1,14 @@
 require 'spec_helper'
 
 describe MergeRequestObserver do
-  let(:some_user) { double(:user, id: 1) }
-  let(:assignee) { double(:user, id: 2) }
-  let(:author) { double(:user, id: 3) }
-  let(:mr)    { double(:merge_request, id: 42, assignee: assignee, author: author) }
+  let(:some_user)      { create :user }
+  let(:assignee)       { create :user }
+  let(:author)         { create :user }
+  let(:mr_mock)    { double(:merge_request, id: 42, assignee: assignee, author: author) }
+  let(:assigned_mr)   { create(:merge_request, assignee: assignee, author: author) }
+  let(:unassigned_mr) { create(:merge_request, author: author) }
+  let(:closed_assigned_mr)   { create(:closed_merge_request, assignee: assignee, author: author) }
+  let(:closed_unassigned_mr) { create(:closed_merge_request, author: author) }
 
   before(:each) { subject.stub(:current_user).and_return(some_user) }
 
@@ -21,23 +25,21 @@ describe MergeRequestObserver do
     end
 
     it 'sends an email to the assignee' do
-      Notify.should_receive(:new_merge_request_email).with(mr.id)
-      subject.after_create(mr)
+      Notify.should_receive(:new_merge_request_email).with(mr_mock.id)
+      subject.after_create(mr_mock)
     end
 
     it 'does not send an email to the assignee if assignee created the merge request' do
       subject.stub(:current_user).and_return(assignee)
       Notify.should_not_receive(:new_merge_request_email)
 
-      subject.after_create(mr)
+      subject.after_create(mr_mock)
     end
   end
 
   context '#after_update' do
     before(:each) do
-      mr.stub(:is_being_reassigned?).and_return(false)
-      mr.stub(:is_being_closed?).and_return(false)
-      mr.stub(:is_being_reopened?).and_return(false)
+      mr_mock.stub(:is_being_reassigned?).and_return(false)
     end
 
     it 'is called when a merge request is changed' do
@@ -52,97 +54,50 @@ describe MergeRequestObserver do
 
     context 'a reassigned email' do
       it 'is sent if the merge request is being reassigned' do
-        mr.should_receive(:is_being_reassigned?).and_return(true)
-        subject.should_receive(:send_reassigned_email).with(mr)
+        mr_mock.should_receive(:is_being_reassigned?).and_return(true)
+        subject.should_receive(:send_reassigned_email).with(mr_mock)
 
-        subject.after_update(mr)
+        subject.after_update(mr_mock)
       end
 
       it 'is not sent if the merge request is not being reassigned' do
-        mr.should_receive(:is_being_reassigned?).and_return(false)
+        mr_mock.should_receive(:is_being_reassigned?).and_return(false)
         subject.should_not_receive(:send_reassigned_email)
 
-        subject.after_update(mr)
+        subject.after_update(mr_mock)
       end
     end
 
+  end
+
+  context '#after_close' do
     context 'a status "closed"' do
       it 'note is created if the merge request is being closed' do
-        mr.should_receive(:is_being_closed?).and_return(true)
-        Note.should_receive(:create_status_change_note).with(mr, some_user, 'closed')
-
-        subject.after_update(mr)
-      end
-
-      it 'note is not created if the merge request is not being closed' do
-        mr.should_receive(:is_being_closed?).and_return(false)
-        Note.should_not_receive(:create_status_change_note).with(mr, some_user, 'closed')
-
-        subject.after_update(mr)
-      end
-
-      it 'notification is delivered if the merge request being closed' do
-        mr.stub(:is_being_closed?).and_return(true)
-        Note.should_receive(:create_status_change_note).with(mr, some_user, 'closed')
-
-        subject.after_update(mr)
-      end
-
-      it 'notification is not delivered if the merge request not being closed' do
-        mr.stub(:is_being_closed?).and_return(false)
-        Note.should_not_receive(:create_status_change_note).with(mr, some_user, 'closed')
+        Note.should_receive(:create_status_change_note).with(assigned_mr, some_user, 'closed')
 
-        subject.after_update(mr)
+        assigned_mr.close
       end
 
       it 'notification is delivered only to author if the merge request is being closed' do
-        mr_without_assignee = double(:merge_request, id: 42, author: author, assignee: nil)
-        mr_without_assignee.stub(:is_being_reassigned?).and_return(false)
-        mr_without_assignee.stub(:is_being_closed?).and_return(true)
-        mr_without_assignee.stub(:is_being_reopened?).and_return(false)
-        Note.should_receive(:create_status_change_note).with(mr_without_assignee, some_user, 'closed')
+        Note.should_receive(:create_status_change_note).with(unassigned_mr, some_user, 'closed')
 
-        subject.after_update(mr_without_assignee)
+        unassigned_mr.close
       end
     end
+  end
 
+  context '#after_reopen' do
     context 'a status "reopened"' do
       it 'note is created if the merge request is being reopened' do
-        mr.should_receive(:is_being_reopened?).and_return(true)
-        Note.should_receive(:create_status_change_note).with(mr, some_user, 'reopened')
-
-        subject.after_update(mr)
-      end
-
-      it 'note is not created if the merge request is not being reopened' do
-        mr.should_receive(:is_being_reopened?).and_return(false)
-        Note.should_not_receive(:create_status_change_note).with(mr, some_user, 'reopened')
-
-        subject.after_update(mr)
-      end
-
-      it 'notification is delivered if the merge request being reopened' do
-        mr.stub(:is_being_reopened?).and_return(true)
-        Note.should_receive(:create_status_change_note).with(mr, some_user, 'reopened')
-
-        subject.after_update(mr)
-      end
-
-      it 'notification is not delivered if the merge request is not being reopened' do
-        mr.stub(:is_being_reopened?).and_return(false)
-        Note.should_not_receive(:create_status_change_note).with(mr, some_user, 'reopened')
+        Note.should_receive(:create_status_change_note).with(closed_assigned_mr, some_user, 'reopened')
 
-        subject.after_update(mr)
+        closed_assigned_mr.reopen
       end
 
       it 'notification is delivered only to author if the merge request is being reopened' do
-        mr_without_assignee = double(:merge_request, id: 42, author: author, assignee: nil)
-        mr_without_assignee.stub(:is_being_reassigned?).and_return(false)
-        mr_without_assignee.stub(:is_being_closed?).and_return(false)
-        mr_without_assignee.stub(:is_being_reopened?).and_return(true)
-        Note.should_receive(:create_status_change_note).with(mr_without_assignee, some_user, 'reopened')
+        Note.should_receive(:create_status_change_note).with(closed_unassigned_mr, some_user, 'reopened')
 
-        subject.after_update(mr_without_assignee)
+        closed_unassigned_mr.reopen
       end
     end
   end
@@ -151,23 +106,23 @@ describe MergeRequestObserver do
     let(:previous_assignee) { double(:user, id: 3) }
 
     before(:each) do
-      mr.stub(:assignee_id).and_return(assignee.id)
-      mr.stub(:assignee_id_was).and_return(previous_assignee.id)
+      mr_mock.stub(:assignee_id).and_return(assignee.id)
+      mr_mock.stub(:assignee_id_was).and_return(previous_assignee.id)
     end
 
     def it_sends_a_reassigned_email_to(recipient)
-      Notify.should_receive(:reassigned_merge_request_email).with(recipient, mr.id, previous_assignee.id)
+      Notify.should_receive(:reassigned_merge_request_email).with(recipient, mr_mock.id, previous_assignee.id)
     end
 
     def it_does_not_send_a_reassigned_email_to(recipient)
-      Notify.should_not_receive(:reassigned_merge_request_email).with(recipient, mr.id, previous_assignee.id)
+      Notify.should_not_receive(:reassigned_merge_request_email).with(recipient, mr_mock.id, previous_assignee.id)
     end
 
     it 'sends a reassigned email to the previous and current assignees' do
       it_sends_a_reassigned_email_to assignee.id
       it_sends_a_reassigned_email_to previous_assignee.id
 
-      subject.send(:send_reassigned_email, mr)
+      subject.send(:send_reassigned_email, mr_mock)
     end
 
     context 'does not send an email to the user who made the reassignment' do
@@ -176,14 +131,14 @@ describe MergeRequestObserver do
         it_sends_a_reassigned_email_to previous_assignee.id
         it_does_not_send_a_reassigned_email_to assignee.id
 
-        subject.send(:send_reassigned_email, mr)
+        subject.send(:send_reassigned_email, mr_mock)
       end
       it 'if the user is the previous assignee' do
         subject.stub(:current_user).and_return(previous_assignee)
         it_sends_a_reassigned_email_to assignee.id
         it_does_not_send_a_reassigned_email_to previous_assignee.id
 
-        subject.send(:send_reassigned_email, mr)
+        subject.send(:send_reassigned_email, mr_mock)
       end
     end
   end
diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb
index 781ebab026bcc7f9a4645673e6e7b149158fb4eb..630ac0f820a7a7068120e347253512586fd16b5c 100644
--- a/spec/requests/api/issues_spec.rb
+++ b/spec/requests/api/issues_spec.rb
@@ -54,14 +54,24 @@ describe Gitlab::API do
     end
   end
 
-  describe "PUT /projects/:id/issues/:issue_id" do
+  describe "PUT /projects/:id/issues/:issue_id to update only title" do
     it "should update a project issue" do
       put api("/projects/#{project.id}/issues/#{issue.id}", user),
-        title: 'updated title', labels: 'label2', closed: 1
+        title: 'updated title'
       response.status.should == 200
+
       json_response['title'].should == 'updated title'
+    end
+  end
+
+  describe "PUT /projects/:id/issues/:issue_id to update state and label" do
+    it "should update a project issue" do
+      put api("/projects/#{project.id}/issues/#{issue.id}", user),
+        labels: 'label2', state_event: "close"
+      response.status.should == 200
+
       json_response['labels'].should == ['label2']
-      json_response['closed'].should be_true
+      json_response['state'].should eq "closed"
     end
   end
 
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index 431aae7cc11c3beda2e78e7717dcd637b8e2028c..8de06c33394970882f063b8cc146351e464836d9 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -66,6 +66,23 @@ describe Gitlab::API do
     end
   end
 
+  describe "PUT /projects/:id/merge_request/:merge_request_id to close MR" do
+    it "should return merge_request" do
+      put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), state_event: "close"
+      response.status.should == 200
+      json_response['state'].should == 'closed'
+    end
+  end
+
+  describe "PUT /projects/:id/merge_request/:merge_request_id to merge MR" do
+    it "should return merge_request" do
+      put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), state_event: "merge"
+      response.status.should == 200
+      json_response['state'].should == 'merged'
+    end
+  end
+
+
   describe "PUT /projects/:id/merge_request/:merge_request_id" do
     it "should return merge_request" do
       put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), title: "New title"
diff --git a/spec/requests/api/milestones_spec.rb b/spec/requests/api/milestones_spec.rb
index 3cab63557a922014fa4a21cb9016a78f7350ed4b..00e800e8b91d350dddddaf60f1bcab0ee47ef0c4 100644
--- a/spec/requests/api/milestones_spec.rb
+++ b/spec/requests/api/milestones_spec.rb
@@ -68,4 +68,14 @@ describe Gitlab::API do
       response.status.should == 404
     end
   end
+
+  describe "PUT /projects/:id/milestones/:milestone_id to close milestone" do
+    it "should update a project milestone" do
+      put api("/projects/#{project.id}/milestones/#{milestone.id}", user),
+        state_event: 'close'
+      response.status.should == 200
+
+      json_response['state'].should == 'closed'
+    end
+  end
 end
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 486b63e74e548806511e0e140001862ce6325ef9..06ab0f5e6841fd43fea496a4fa89a29f14cb128e 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -33,6 +33,20 @@ describe Gitlab::API do
   end
 
   describe "POST /projects" do
+    context "maximum number of projects reached" do
+      before do
+        (1..user2.projects_limit).each do |project|
+          post api("/projects", user2), name: "foo#{project}"
+        end
+      end
+
+      it "should not create new project" do
+        expect {
+          post api("/projects", user2), name: 'foo'
+        }.to change {Project.count}.by(0)
+      end
+    end
+
     it "should create new project without path" do
       expect { post api("/projects", user), name: 'foo' }.to change {Project.count}.by(1)
     end
@@ -46,6 +60,12 @@ describe Gitlab::API do
       response.status.should == 400
     end
 
+    it "should create last project before reaching project limit" do
+      (1..user2.projects_limit-1).each { |p| post api("/projects", user2), name: "foo#{p}" }
+      post api("/projects", user2), name: "foo"
+      response.status.should == 201
+    end
+
     it "should respond with 201 on success" do
       post api("/projects", user), name: 'foo'
       response.status.should == 201
@@ -314,22 +334,44 @@ describe Gitlab::API do
   end
 
   describe "GET /projects/:id/hooks" do
-    it "should return project hooks" do
-      get api("/projects/#{project.id}/hooks", user)
+    context "authorized user" do
+      it "should return project hooks" do
+        get api("/projects/#{project.id}/hooks", user)
+        response.status.should == 200
 
-      response.status.should == 200
+        json_response.should be_an Array
+        json_response.count.should == 1
+        json_response.first['url'].should == "http://example.com"
+      end
+    end
 
-      json_response.should be_an Array
-      json_response.count.should == 1
-      json_response.first['url'].should == "http://example.com"
+    context "unauthorized user" do
+      it "should not access project hooks" do
+        get api("/projects/#{project.id}/hooks", user3)
+        response.status.should == 403
+      end
     end
   end
 
   describe "GET /projects/:id/hooks/:hook_id" do
-    it "should return a project hook" do
-      get api("/projects/#{project.id}/hooks/#{hook.id}", user)
-      response.status.should == 200
-      json_response['url'].should == hook.url
+    context "authorized user" do
+      it "should return a project hook" do
+        get api("/projects/#{project.id}/hooks/#{hook.id}", user)
+        response.status.should == 200
+        json_response['url'].should == hook.url
+      end
+
+      it "should return a 404 error if hook id is not available" do
+        get api("/projects/#{project.id}/hooks/1234", user)
+        response.status.should == 404
+      end
+    end
+
+    context "unauthorized user" do
+      it "should not access an existing hook" do
+        get api("/projects/#{project.id}/hooks/#{hook.id}", user3)
+        response.status.should == 403
+      end
     end
 
     it "should return a 404 error if hook id is not available" do
diff --git a/spec/requests/issues_spec.rb b/spec/requests/issues_spec.rb
index 2e94ffd0020f9350e219d3cc7f225914a89d428a..6fff59f036f5fa5c4531f9cbbb1803f3001483f9 100644
--- a/spec/requests/issues_spec.rb
+++ b/spec/requests/issues_spec.rb
@@ -58,8 +58,7 @@ describe "Issues" do
 
     it "should be able to search on different statuses" do
       issue = Issue.first # with title 'foobar'
-      issue.closed = true
-      issue.save
+      issue.close
 
       visit project_issues_path(project)
       click_link 'Closed'