From e954438a1d3a45addebf52ab04155459d7d84db0 Mon Sep 17 00:00:00 2001
From: Boyan Tabakov <boyan.tabakov@futurice.com>
Date: Tue, 18 Dec 2012 21:24:31 +0200
Subject: [PATCH 001/197] Extended users API to support updating and deleting
 users.

Also added tests.
---
 doc/api/users.md                | 43 +++++++++++++++++++++++++++++
 lib/api/entities.rb             |  2 +-
 lib/api/users.rb                | 47 +++++++++++++++++++++++++++++++-
 spec/requests/api/users_spec.rb | 48 +++++++++++++++++++++++++++++++++
 4 files changed, 138 insertions(+), 2 deletions(-)

diff --git a/doc/api/users.md b/doc/api/users.md
index 200c0e06e04..b94d7c0f789 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -20,6 +20,8 @@ GET /users
     "linkedin": "",
     "twitter": "",
     "dark_scheme": false,
+    "extern_uid": "john.smith",
+    "provider": "provider_name",
     "theme_id": 1
   },
   {
@@ -34,6 +36,8 @@ GET /users
     "linkedin": "",
     "twitter": "",
     "dark_scheme": true,
+    "extern_uid": "jack.smith",
+    "provider": "provider_name",
     "theme_id": 1
   }
 ]
@@ -64,6 +68,8 @@ Parameters:
   "linkedin": "",
   "twitter": "",
   "dark_scheme": false,
+  "extern_uid": "john.smith",
+  "provider": "provider_name",
   "theme_id": 1
 }
 ```
@@ -84,10 +90,47 @@ Parameters:
 + `linkedin`                          - Linkedin
 + `twitter`                           - Twitter account
 + `projects_limit`                    - Number of projects user can create
++ `extern_uid`                        - External UID
++ `provider`                          - External provider name
++ `bio`                               - User's bio
 
 Will return created user with status `201 Created` on success, or `404 Not
 found` on fail.
 
+## User modification
+Modify user. Available only for admin
+
+```
+PUT /users/:id
+```
+
+Parameters:
++ `email`                             - Email
++ `username`                          - Username
++ `name`                              - Name
++ `password`                          - Password
++ `skype`                             - Skype ID
++ `linkedin`                          - Linkedin
++ `twitter`                           - Twitter account
++ `projects_limit`                    - Limit projects wich user can create
++ `extern_uid`                        - External UID
++ `provider`                          - External provider name
++ `bio`                               - User's bio
+
+
+Will return created user with status `200 OK` on success, or `404 Not
+found` on fail.
+
+## User deletion
+Delete user. Available only for admin
+
+```
+DELETE /users/:id
+```
+
+Will return deleted user with status `200 OK` on success, or `404 Not
+found` on fail.
+
 ## Current user
 
 Get currently authenticated user.
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 070fbad27ed..bfb9093d61e 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -2,7 +2,7 @@ module Gitlab
   module Entities
     class User < Grape::Entity
       expose :id, :username, :email, :name, :bio, :skype, :linkedin, :twitter,
-             :dark_scheme, :theme_id, :blocked, :created_at
+             :dark_scheme, :theme_id, :blocked, :created_at, :extern_uid, :provider
     end
 
     class UserBasic < Grape::Entity
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 140c20f6bd2..7ea90c75e9e 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -34,11 +34,14 @@ module Gitlab
       #   linkedin                          - Linkedin
       #   twitter                           - Twitter account
       #   projects_limit                    - Number of projects user can create
+      #   extern_uid                        - External authentication provider UID
+      #   provider                          - External provider
+      #   bio                               - Bio
       # Example Request:
       #   POST /users
       post do
         authenticated_as_admin!
-        attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username]
+        attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio]
         user = User.new attrs, as: :admin
         if user.save
           present user, with: Entities::User
@@ -46,6 +49,48 @@ module Gitlab
           not_found!
         end
       end
+
+      # Update user. Available only for admin
+      #
+      # Parameters:
+      #   email                             - Email
+      #   name                              - Name
+      #   password                          - Password
+      #   skype                             - Skype ID
+      #   linkedin                          - Linkedin
+      #   twitter                           - Twitter account
+      #   projects_limit                    - Limit projects wich user can create
+      #   extern_uid                        - External authentication provider UID
+      #   provider                          - External provider
+      #   bio                               - Bio
+      # Example Request:
+      #   PUT /users/:id
+      put ":id" do
+        authenticated_as_admin!
+        attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio]
+        user = User.find_by_id(params[:id])
+
+        if user && user.update_attributes(attrs)
+          present user, with: Entities::User
+        else
+          not_found!
+        end
+      end
+
+      # Delete user. Available only for admin
+      #
+      # Example Request:
+      #   DELETE /users/:id
+      delete ":id" do
+        authenticated_as_admin!
+        user = User.find_by_id(params[:id])
+
+        if user
+          user.destroy
+        else
+          not_found!
+        end
+      end
     end
 
     resource :user do
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 4cfb4884e7c..108d1bf9458 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -53,6 +53,54 @@ describe Gitlab::API do
     end
   end
 
+  describe "PUT /users/:id" do
+    before { admin }
+
+    it "should update user" do
+      put api("/users/#{user.id}", admin), {bio: 'new test bio'}
+      response.status.should == 200
+      json_response['bio'].should == 'new test bio'
+      user.reload.bio.should == 'new test bio'
+    end
+
+    it "should not allow invalid update" do
+      put api("/users/#{user.id}", admin), {email: 'invalid email'}
+      response.status.should == 404
+      user.reload.email.should_not == 'invalid email'
+    end
+
+    it "shouldn't available for non admin users" do
+      put api("/users/#{user.id}", user), attributes_for(:user)
+      response.status.should == 403
+    end
+
+    it "should return 404 for non-existing user" do
+      put api("/users/999999", admin), {bio: 'update should fail'}
+      response.status.should == 404
+    end
+  end
+
+  describe "DELETE /users/:id" do
+    before { admin }
+
+    it "should delete user" do
+      delete api("/users/#{user.id}", admin)
+      response.status.should == 200
+      expect { User.find(user.id) }.to raise_error ActiveRecord::RecordNotFound
+      json_response['email'].should == user.email
+    end
+
+    it "shouldn't available for non admin users" do
+      delete api("/users/#{user.id}", user)
+      response.status.should == 403
+    end
+
+    it "should return 404 for non-existing user" do
+      delete api("/users/999999", admin)
+      response.status.should == 404
+    end
+  end
+
   describe "GET /user" do
     it "should return current user" do
       get api("/user", user)
-- 
GitLab


From 29baadf0c7f48c63867b839d4f990ff767b6dcc9 Mon Sep 17 00:00:00 2001
From: Kevin Lamontagne <kevin.lamontagne@libeo.com>
Date: Sun, 30 Dec 2012 21:15:31 -0500
Subject: [PATCH 002/197] Don't setuid the repositories on installation

---
 doc/install/installation.md | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/doc/install/installation.md b/doc/install/installation.md
index 7fb5e48cdc9..c499288ea5a 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -146,8 +146,9 @@ Fix the directory permissions for the configuration directory:
 Fix the directory permissions for the repositories:
 
     # Make sure the repositories dir is owned by git and it stays that way
-    sudo chmod -R ug+rwXs,o-rwx /home/git/repositories/
+    sudo chmod -R ug+rwX,o-rwx /home/git/repositories/
     sudo chown -R git:git /home/git/repositories/
+    find /home/git/repositories -type d -print0 | sudo xargs -0 chmod g+s 
 
 
 ## Disable StrictHostKeyChecking for localhost and your domain
-- 
GitLab


From c816dcc10513731f0ef0c1b247fef1ef1287dd7c Mon Sep 17 00:00:00 2001
From: Kevin Lamontagne <kevin.lamontagne@libeo.com>
Date: Sun, 30 Dec 2012 21:46:28 -0500
Subject: [PATCH 003/197] Don't setuid the repositories (Rake checks)

---
 doc/raketasks/maintenance.md | 2 +-
 lib/tasks/gitlab/check.rake  | 8 +++++---
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/doc/raketasks/maintenance.md b/doc/raketasks/maintenance.md
index bb8e1ed29f7..43df2ce9a4a 100644
--- a/doc/raketasks/maintenance.md
+++ b/doc/raketasks/maintenance.md
@@ -94,7 +94,7 @@ Config directory owned by git:git? ... yes
 Config directory access is drwxr-x---? ... yes
 Repo base directory exists? ... yes
 Repo base owned by git:git? ... yes
-Repo base access is drwsrws---? ... yes
+Repo base access is drwxrws---? ... yes
 Can clone gitolite-admin? ... yes
 Can commit to gitolite-admin? ... yes
 post-receive hook exists? ... yes
diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake
index 72111f87567..730a1fc5f2c 100644
--- a/lib/tasks/gitlab/check.rake
+++ b/lib/tasks/gitlab/check.rake
@@ -693,7 +693,7 @@ namespace :gitlab do
     end
 
     def check_repo_base_permissions
-      print "Repo base access is drwsrws---? ... "
+      print "Repo base access is drwxrws---? ... "
 
       repo_base_path = Gitlab.config.gitolite.repos_path
       unless File.exists?(repo_base_path)
@@ -701,13 +701,15 @@ namespace :gitlab do
         return
       end
 
-      if `stat --printf %a #{repo_base_path}` == "6770"
+      if `stat --printf %a #{repo_base_path}` == "2770"
         puts "yes".green
       else
         puts "no".red
         puts "#{repo_base_path} is not writable".red
         try_fixing_it(
-          "sudo chmod -R ug+rwXs,o-rwx #{repo_base_path}"
+          "sudo chmod -R ug+rwX,o-rwx #{repo_base_path}",
+          "sudo chmod -R u-s #{repo_base_path}",
+          "find -type d #{repo_base_path} -print0 | sudo xargs -0 chmod g+s"
         )
         for_more_information(
           see_installation_guide_section "Gitolite"
-- 
GitLab


From f4175219fb7a1cb93f7eed54bd6510a85345096e Mon Sep 17 00:00:00 2001
From: Kevin Lamontagne <kevin.lamontagne@libeo.com>
Date: Fri, 18 Jan 2013 14:13:38 -0500
Subject: [PATCH 004/197] Fix gitlab:check recommendation

Running the recommendation would give out:
GNU find: paths must precede expression
---
 lib/tasks/gitlab/check.rake | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake
index 730a1fc5f2c..ab95c823df7 100644
--- a/lib/tasks/gitlab/check.rake
+++ b/lib/tasks/gitlab/check.rake
@@ -709,7 +709,7 @@ namespace :gitlab do
         try_fixing_it(
           "sudo chmod -R ug+rwX,o-rwx #{repo_base_path}",
           "sudo chmod -R u-s #{repo_base_path}",
-          "find -type d #{repo_base_path} -print0 | sudo xargs -0 chmod g+s"
+          "find #{repo_base_path} -type d -print0 | sudo xargs -0 chmod g+s"
         )
         for_more_information(
           see_installation_guide_section "Gitolite"
-- 
GitLab


From 68fa988219d1ae3933bae5288f59e7f9f86f9a97 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 21 Jan 2013 16:36:55 +0200
Subject: [PATCH 005/197] done with 4.1. Version to 4.2.0pre :)

---
 VERSION                     | 2 +-
 doc/install/installation.md | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/VERSION b/VERSION
index 87db9036a82..b5d76fb80d8 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-4.1.0rc1
+4.2.0pre
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 27c87ec825f..0724bea9c3b 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -190,10 +190,10 @@ See `doc/install/databases.md`
     cd /home/gitlab/gitlab
    
     # Checkout to stable release
-    sudo -u gitlab -H git checkout 4-0-stable
+    sudo -u gitlab -H git checkout 4-1-stable
 
 **Note:**
-You can change `4-0-stable` to `master` if you want the *bleeding edge* version, but
+You can change `4-1-stable` to `master` if you want the *bleeding edge* version, but
 do so with caution!
 
 ## Configure it
-- 
GitLab


From d770714578cffe5423c6a1752367f7f545fa1f22 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 22 Jan 2013 10:35:58 +0200
Subject: [PATCH 006/197] Use subproccess instead subshell for git calls

---
 lib/gitlab/backend/gitolite_config.rb | 32 +++++++++++++++------------
 1 file changed, 18 insertions(+), 14 deletions(-)

diff --git a/lib/gitlab/backend/gitolite_config.rb b/lib/gitlab/backend/gitolite_config.rb
index 7d59ddae0c8..f12c10ce01c 100644
--- a/lib/gitlab/backend/gitolite_config.rb
+++ b/lib/gitlab/backend/gitolite_config.rb
@@ -8,10 +8,11 @@ module Gitlab
     class PushError < StandardError; end
     class BrokenGitolite < StandardError; end
 
-    attr_reader :config_tmp_dir, :ga_repo, :conf
+    attr_reader :config_tmp_dir, :tmp_dir, :ga_repo, :conf
 
-    def config_tmp_dir
-      @config_tmp_dir ||= Rails.root.join('tmp',"gitlabhq-gitolite-#{Time.now.to_i}")
+    def initialize
+      @tmp_dir = Rails.root.join("tmp").to_s
+      @config_tmp_dir = File.join(@tmp_dir,"gitlabhq-gitolite-#{Time.now.to_i}")
     end
 
     def ga_repo
@@ -23,7 +24,7 @@ module Gitlab
 
     def apply
       Timeout::timeout(30) do
-        File.open(Rails.root.join('tmp', "gitlabhq-gitolite.lock"), "w+") do |f|
+        File.open(File.join(tmp_dir, "gitlabhq-gitolite.lock"), "w+") do |f|
           begin
             # Set exclusive lock
             # to prevent race condition
@@ -31,7 +32,7 @@ module Gitlab
 
             # Pull gitolite-admin repo
             # in tmp dir before do any changes
-            pull(config_tmp_dir)
+            pull
 
             # Build ga_repo object and @conf
             # to access gitolite-admin configuration
@@ -49,7 +50,7 @@ module Gitlab
 
             # Push gitolite-admin repo
             # to apply all changes
-            push(config_tmp_dir)
+            push
           ensure
             # Remove tmp dir
             # removing the gitolite folder first is important to avoid
@@ -192,16 +193,20 @@ module Gitlab
 
     private
 
-    def pull tmp_dir
-      Dir.mkdir tmp_dir
-      `git clone #{Gitlab.config.gitolite.admin_uri} #{tmp_dir}/gitolite`
+    def pull
+      # Create config tmp dir like "RAILS_ROOT/tmp/gitlabhq-gitolite-132545"
+      Dir.mkdir config_tmp_dir
 
-      unless File.exists?(File.join(tmp_dir, 'gitolite', 'conf', 'gitolite.conf'))
+      # Clone gitolite-admin repo into tmp dir
+      popen("git clone #{Gitlab.config.gitolite.admin_uri} #{config_tmp_dir}/gitolite", tmp_dir)
+
+      # Ensure file with config presents after cloning
+      unless File.exists?(File.join(config_tmp_dir, 'gitolite', 'conf', 'gitolite.conf'))
         raise PullError, "unable to clone gitolite-admin repo"
       end
     end
 
-    def push tmp_dir
+    def push
       output, status = popen('git add -A')
       raise "Git add failed." unless status.zero?
 
@@ -222,8 +227,8 @@ module Gitlab
       end
     end
 
-    def popen(cmd)
-      path = File.join(config_tmp_dir,'gitolite')
+    def popen(cmd, path = nil)
+      path ||= File.join(config_tmp_dir,'gitolite')
       vars = { "PWD" => path }
       options = { :chdir => path }
 
@@ -239,4 +244,3 @@ module Gitlab
     end
   end
 end
-
-- 
GitLab


From 0ab906d5dec343562e0869d9a3fd9a47afe7a9e2 Mon Sep 17 00:00:00 2001
From: Erkan <erkan2005@gmail.com>
Date: Tue, 22 Jan 2013 10:04:02 +0100
Subject: [PATCH 007/197] Update config/gitlab.yml.example

---
 config/gitlab.yml.example | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index b2dccbe3d4c..4df8efa9c06 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -29,7 +29,7 @@ gitlab:
   # Email address used in the "From" field in mails sent by GitLab
   email_from: gitlab@localhost
 
-  # Email address of your support contanct (default: same as email_from)
+  # Email address of your support contact (default: same as email_from)
   support_email: support@localhost
 
   ## Project settings
-- 
GitLab


From 69ec189ad25000caa247aad944eda2398045b612 Mon Sep 17 00:00:00 2001
From: Valeriy Sizov <vsv2711@gmail.com>
Date: Tue, 22 Jan 2013 17:10:00 +0200
Subject: [PATCH 008/197] remove length of snippet content

---
 app/models/snippet.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index 8d7eb788abb..806d346cf10 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -28,7 +28,7 @@ class Snippet < ActiveRecord::Base
   validates :project, presence: true
   validates :title, presence: true, length: { within: 0..255 }
   validates :file_name, presence: true, length: { within: 0..255 }
-  validates :content, presence: true, length: { within: 0..10000 }
+  validates :content, presence: true
 
   # Scopes
   scope :fresh, order("created_at DESC")
-- 
GitLab


From 745c0dfa5768ffa5cb190d280127c8c5d1f6a5e4 Mon Sep 17 00:00:00 2001
From: Valeriy Sizov <vsv2711@gmail.com>
Date: Tue, 22 Jan 2013 17:15:22 +0200
Subject: [PATCH 009/197] remove length of issue content

according to #2677
---
 app/models/issue.rb | 2 --
 1 file changed, 2 deletions(-)

diff --git a/app/models/issue.rb b/app/models/issue.rb
index 40a6c01577d..07c0401143c 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -24,8 +24,6 @@ class Issue < ActiveRecord::Base
 
   acts_as_taggable_on :labels
 
-  validates :description, length: { within: 0..10000 }
-
   def self.open_for(user)
     opened.assigned(user)
   end
-- 
GitLab


From e982a9512e925f1534dfc893158f5654f97454f1 Mon Sep 17 00:00:00 2001
From: Valeriy Sizov <vsv2711@gmail.com>
Date: Tue, 22 Jan 2013 17:25:35 +0200
Subject: [PATCH 010/197] fix tests

---
 spec/models/issue_spec.rb   | 4 ----
 spec/models/snippet_spec.rb | 1 -
 2 files changed, 5 deletions(-)

diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index 0816b3eed5a..10db53e0745 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -28,10 +28,6 @@ describe Issue do
     it { should_not allow_mass_assignment_of(:project_id) }
   end
 
-  describe "Validation" do
-    it { should ensure_length_of(:description).is_within(0..10000) }
-  end
-
   describe 'modules' do
     it { should include_module(Issuable) }
   end
diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb
index b474d88c9e2..e4d1934829f 100644
--- a/spec/models/snippet_spec.rb
+++ b/spec/models/snippet_spec.rb
@@ -38,6 +38,5 @@ describe Snippet do
     it { should ensure_length_of(:title).is_within(0..255) }
 
     it { should validate_presence_of(:content) }
-    it { should ensure_length_of(:content).is_within(0..10_000) }
   end
 end
-- 
GitLab


From 2be107d0d9414d6de4df5bd5e3bea2fb1f1dbde5 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 22 Jan 2013 17:58:09 +0200
Subject: [PATCH 011/197] Help with index

---
 .../stylesheets/gitlab_bootstrap/common.scss  |   2 +
 app/views/help/_layout.html.haml              |  34 +++
 app/views/help/api.html.haml                  | 192 ++++++++--------
 app/views/help/markdown.html.haml             | 214 +++++++++---------
 app/views/help/permissions.html.haml          | 122 +++++-----
 app/views/help/public_access.html.haml        |  28 ++-
 app/views/help/raketasks.html.haml            | 116 +++++-----
 app/views/help/ssh.html.haml                  |  34 ++-
 app/views/help/system_hooks.html.haml         |  24 +-
 app/views/help/web_hooks.html.haml            |  24 +-
 app/views/help/workflow.html.haml             |  76 +++----
 11 files changed, 442 insertions(+), 424 deletions(-)
 create mode 100644 app/views/help/_layout.html.haml

diff --git a/app/assets/stylesheets/gitlab_bootstrap/common.scss b/app/assets/stylesheets/gitlab_bootstrap/common.scss
index 2b3d14abda8..6f439c9eaed 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/common.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/common.scss
@@ -81,6 +81,8 @@
       }
     }
   }
+
+  &.nav-small-tabs > li > a { padding: 6px 9px; }
 }
 
 /** ALERT MESSAGES **/
diff --git a/app/views/help/_layout.html.haml b/app/views/help/_layout.html.haml
new file mode 100644
index 00000000000..3839be2773c
--- /dev/null
+++ b/app/views/help/_layout.html.haml
@@ -0,0 +1,34 @@
+.row
+  .span3{:"data-spy" => 'affix'}
+    .ui-box
+      .title
+        %h5 Help
+      %ul.well-list
+        %li
+          %strong= link_to "Workflow", help_workflow_path
+        %li
+          %strong= link_to "SSH keys", help_ssh_path
+
+        %li
+          %strong= link_to "GitLab Markdown", help_markdown_path
+
+        %li
+          %strong= link_to "Permissions", help_permissions_path
+
+        %li
+          %strong= link_to "API", help_api_path
+
+        %li
+          %strong= link_to "Web Hooks", help_web_hooks_path
+
+        %li
+          %strong= link_to "Rake Tasks", help_raketasks_path
+
+        %li
+          %strong= link_to "System Hooks", help_system_hooks_path
+
+        %li
+          %strong= link_to "Public Access", help_public_access_path
+
+  .span9.right
+    = yield
diff --git a/app/views/help/api.html.haml b/app/views/help/api.html.haml
index 3f16637dd2e..d771f1e9f38 100644
--- a/app/views/help/api.html.haml
+++ b/app/views/help/api.html.haml
@@ -1,107 +1,105 @@
-%h3.page_title API
-.back_link
-  = link_to help_path do
-    &larr; to index
-%br
+= render layout: 'help/layout' do
+  %h3.page_title API
+  %br
 
-%ul.nav.nav-tabs.log-tabs
-  %li.active
-    = link_to "README", "#README", 'data-toggle' => 'tab'
-  %li
-    = link_to "Projects", "#projects", 'data-toggle' => 'tab'
-  %li
-    = link_to "Snippets", "#snippets", 'data-toggle' => 'tab'
-  %li
-    = link_to "Repositories", "#repositories", 'data-toggle' => 'tab'
-  %li
-    = link_to "Users", "#users", 'data-toggle' => 'tab'
-  %li
-    = link_to "Session", "#session", 'data-toggle' => 'tab'
-  %li
-    = link_to "Issues", "#issues", 'data-toggle' => 'tab'
-  %li
-    = link_to "Milestones", "#milestones", 'data-toggle' => 'tab'
-  %li
-    = link_to "Notes", "#notes", 'data-toggle' => 'tab'
+  %ul.nav.nav-tabs.log-tabs.nav-small-tabs
+    %li.active
+      = link_to "README", "#README", 'data-toggle' => 'tab'
+    %li
+      = link_to "Projects", "#projects", 'data-toggle' => 'tab'
+    %li
+      = link_to "Snippets", "#snippets", 'data-toggle' => 'tab'
+    %li
+      = link_to "Repositories", "#repositories", 'data-toggle' => 'tab'
+    %li
+      = link_to "Users", "#users", 'data-toggle' => 'tab'
+    %li
+      = link_to "Session", "#session", 'data-toggle' => 'tab'
+    %li
+      = link_to "Issues", "#issues", 'data-toggle' => 'tab'
+    %li
+      = link_to "Milestones", "#milestones", 'data-toggle' => 'tab'
+    %li
+      = link_to "Notes", "#notes", 'data-toggle' => 'tab'
 
-.tab-content
-  .tab-pane.active#README
-    .file_holder
-      .file_title
-        %i.icon-file
-        README
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "api", "README.md"))
+  .tab-content
+    .tab-pane.active#README
+      .file_holder
+        .file_title
+          %i.icon-file
+          README
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "api", "README.md"))
 
-  .tab-pane#projects
-    .file_holder
-      .file_title
-        %i.icon-file
-        Projects
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "api", "projects.md"))
+    .tab-pane#projects
+      .file_holder
+        .file_title
+          %i.icon-file
+          Projects
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "api", "projects.md"))
 
-  .tab-pane#snippets
-    .file_holder
-      .file_title
-        %i.icon-file
-        Projects Snippets
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "api", "snippets.md"))
+    .tab-pane#snippets
+      .file_holder
+        .file_title
+          %i.icon-file
+          Projects Snippets
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "api", "snippets.md"))
 
-  .tab-pane#repositories
-    .file_holder
-      .file_title
-        %i.icon-file
-        Projects
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "api", "repositories.md"))
+    .tab-pane#repositories
+      .file_holder
+        .file_title
+          %i.icon-file
+          Projects
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "api", "repositories.md"))
 
-  .tab-pane#users
-    .file_holder
-      .file_title
-        %i.icon-file
-        Users
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "api", "users.md"))
+    .tab-pane#users
+      .file_holder
+        .file_title
+          %i.icon-file
+          Users
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "api", "users.md"))
 
-  .tab-pane#session
-    .file_holder
-      .file_title
-        %i.icon-file
-        Session
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "api", "session.md"))
+    .tab-pane#session
+      .file_holder
+        .file_title
+          %i.icon-file
+          Session
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "api", "session.md"))
 
-  .tab-pane#issues
-    .file_holder
-      .file_title
-        %i.icon-file
-        Issues
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "api", "issues.md"))
+    .tab-pane#issues
+      .file_holder
+        .file_title
+          %i.icon-file
+          Issues
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "api", "issues.md"))
 
-  .tab-pane#milestones
-    .file_holder
-      .file_title
-        %i.icon-file
-        Milestones
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "api", "milestones.md"))
+    .tab-pane#milestones
+      .file_holder
+        .file_title
+          %i.icon-file
+          Milestones
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "api", "milestones.md"))
 
-  .tab-pane#notes
-    .file_holder
-      .file_title
-        %i.icon-file
-        Notes
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "api", "notes.md"))
+    .tab-pane#notes
+      .file_holder
+        .file_title
+          %i.icon-file
+          Notes
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "api", "notes.md"))
diff --git a/app/views/help/markdown.html.haml b/app/views/help/markdown.html.haml
index 0419f7c131a..46bcd895274 100644
--- a/app/views/help/markdown.html.haml
+++ b/app/views/help/markdown.html.haml
@@ -1,129 +1,127 @@
-%h3.page_title GitLab Flavored Markdown
-.back_link
-  = link_to help_path do
-    &larr; to index
-%hr
-
-.row
-  .span8
-    %p
-      For GitLab we developed something we call "GitLab Flavored Markdown" (GFM).
-      It extends the standard Markdown in a few significant ways adds some useful functionality.
-
-    %p You can use GFM in:
-    %ul
-      %li commit messages
-      %li comments
-      %li wall posts
-      %li issues
-      %li merge requests
-      %li milestones
-      %li wiki pages
-
-  .span4
-    .alert.alert-info
+= render layout: 'help/layout' do
+  %h3.page_title GitLab Flavored Markdown
+  %br
+
+  .row
+    .span8
       %p
-        If you're not already familiar with Markdown, you should spend 15 minutes and go over the excellent
-        %strong= link_to "Markdown Syntax Guide", "http://daringfireball.net/projects/markdown/syntax"
-        at Daring Fireball.
+        For GitLab we developed something we call "GitLab Flavored Markdown" (GFM).
+        It extends the standard Markdown in a few significant ways adds some useful functionality.
+
+      %p You can use GFM in:
+      %ul
+        %li commit messages
+        %li comments
+        %li wall posts
+        %li issues
+        %li merge requests
+        %li milestones
+        %li wiki pages
+
+    .span4
+      .alert.alert-info
+        %p
+          If you're not already familiar with Markdown, you should spend 15 minutes and go over the excellent
+          %strong= link_to "Markdown Syntax Guide", "http://daringfireball.net/projects/markdown/syntax"
+          at Daring Fireball.
+
+  .row
+    .span8
+      %h3 Differences from traditional Markdown
+
+      %h4 Newlines
 
-.row
-  .span8
-    %h3 Differences from traditional Markdown
+      %p
+        The biggest difference that GFM introduces is in the handling of linebreaks.
+        With traditional Markdown you can hard wrap paragraphs of text and they will be combined into a single paragraph. We find this to be the cause of a huge number of unintentional formatting errors.
+        GFM treats newlines in paragraph-like content as real line breaks, which is probably what you intended.
 
-    %h4 Newlines
 
-    %p
-      The biggest difference that GFM introduces is in the handling of linebreaks.
-      With traditional Markdown you can hard wrap paragraphs of text and they will be combined into a single paragraph. We find this to be the cause of a huge number of unintentional formatting errors.
-      GFM treats newlines in paragraph-like content as real line breaks, which is probably what you intended.
+      %p The next paragraph contains two phrases separated by a single newline character:
+      %pre= "Roses are red\nViolets are blue"
+      %p becomes
+      = markdown "Roses are red\nViolets are blue"
 
+      %h4 Multiple underscores in words
 
-    %p The next paragraph contains two phrases separated by a single newline character:
-    %pre= "Roses are red\nViolets are blue"
-    %p becomes
-    = markdown "Roses are red\nViolets are blue"
+      %p
+        It is not reasonable to italicize just <em>part</em> of a word, especially when you're dealing with code and names often appear with multiple underscores.
+        Therefore, GFM ignores multiple underscores in words.
 
-    %h4 Multiple underscores in words
+      %pre= "perform_complicated_task\ndo_this_and_do_that_and_another_thing"
+      %p becomes
+      = markdown "perform_complicated_task\ndo_this_and_do_that_and_another_thing"
 
-    %p
-      It is not reasonable to italicize just <em>part</em> of a word, especially when you're dealing with code and names often appear with multiple underscores.
-      Therefore, GFM ignores multiple underscores in words.
+      %h4 URL autolinking
 
-    %pre= "perform_complicated_task\ndo_this_and_do_that_and_another_thing"
-    %p becomes
-    = markdown "perform_complicated_task\ndo_this_and_do_that_and_another_thing"
+      %p
+        GFM will autolink standard URLs you copy and paste into your text.
+        So if you want to link to a URL (instead of a textual link), you can simply put the URL in verbatim and it will be turned into a link to that URL.
 
-    %h4 URL autolinking
+      %h4 Fenced code blocks
 
-    %p
-      GFM will autolink standard URLs you copy and paste into your text.
-      So if you want to link to a URL (instead of a textual link), you can simply put the URL in verbatim and it will be turned into a link to that URL.
+      %p
+        Markdown converts text with four spaces at the front of each line to code blocks.
+        GFM supports that, but we also support fenced blocks.
+        Just wrap your code blocks in <code>```</code> and you won't need to indent manually to trigger a code block.
 
-    %h4 Fenced code blocks
+      %pre= %Q{```ruby\nrequire 'redcarpet'\nmarkdown = Redcarpet.new("Hello World!")\nputs markdown.to_html\n```}
+      %p becomes
+      = markdown %Q{```ruby\nrequire 'redcarpet'\nmarkdown = Redcarpet.new("Hello World!")\nputs markdown.to_html\n```}
 
-    %p
-      Markdown converts text with four spaces at the front of each line to code blocks.
-      GFM supports that, but we also support fenced blocks.
-      Just wrap your code blocks in <code>```</code> and you won't need to indent manually to trigger a code block.
+      %h4 Emoji
 
-    %pre= %Q{```ruby\nrequire 'redcarpet'\nmarkdown = Redcarpet.new("Hello World!")\nputs markdown.to_html\n```}
-    %p becomes
-    = markdown %Q{```ruby\nrequire 'redcarpet'\nmarkdown = Redcarpet.new("Hello World!")\nputs markdown.to_html\n```}
+  .row
+    .span8
+      :ruby
+        puts markdown %Q{Sometimes you want to be :cool: and add some :sparkles: to your :speech_balloon:. Well we have a :gift: for you:
 
-    %h4 Emoji
+          :exclamation: You can use emoji anywhere GFM is supported. :sunglasses:
 
-.row
-  .span8
-    :ruby
-      puts markdown %Q{Sometimes you want to be :cool: and add some :sparkles: to your :speech_balloon:. Well we have a :gift: for you:
+          You can use it to point out a :bug: or warn about :monkey:patches. And if someone improves your really :snail: code, send them a :bouquet: or some :candy:. People will :heart: you for that.
 
-        :exclamation: You can use emoji anywhere GFM is supported. :sunglasses:
+          If you are :new: to this, don't be :fearful:. You can easily join the emoji :circus_tent:. All you need to do is to :book: up on the supported codes.
+          }
 
-        You can use it to point out a :bug: or warn about :monkey:patches. And if someone improves your really :snail: code, send them a :bouquet: or some :candy:. People will :heart: you for that.
+    .span4
+      .alert.alert-info
+        %p
+          Consult the
+          %strong= link_to "Emoji Cheat Sheet", "http://www.emoji-cheat-sheet.com/"
+          for a list of all supported emoji codes.
 
-        If you are :new: to this, don't be :fearful:. You can easily join the emoji :circus_tent:. All you need to do is to :book: up on the supported codes.
-        }
+  .row
+    .span8
+      %h4 Special GitLab references
 
-  .span4
-    .alert.alert-info
       %p
-        Consult the
-        %strong= link_to "Emoji Cheat Sheet", "http://www.emoji-cheat-sheet.com/"
-        for a list of all supported emoji codes.
-
-.row
-  .span8
-    %h4 Special GitLab references
-
-    %p
-      GFM recognizes special references.
-      You can easily reference e.g. a team member, an issue or a commit within a project.
-      GFM will turn that reference into a link so you can navigate between them easily.
-
-    %p GFM will recognize the following references:
-    %ul
-      %li
-        %code @foo
-        for team members
-      %li
-        %code #123
-        for issues
-      %li
-        %code !123
-        for merge request
-      %li
-        %code $123
-        for snippets
-      %li
-        %code 1234567
-        for commits
-
-    -# this example will only be shown if the user has a project with at least one issue
-    - if @project = current_user.authorized_projects.first
-      - if issue = @project.issues.first
-        %p For example in your #{link_to @project.name, project_path(@project)} project, writing:
-        %pre= "This is related to ##{issue.id}. @#{current_user.name} is working on solving it."
-        %p becomes:
-        = markdown "This is related to ##{issue.id}. @#{current_user.name} is working on solving it."
-      - @project = nil # Prevent this from bubbling up to page title
+        GFM recognizes special references.
+        You can easily reference e.g. a team member, an issue or a commit within a project.
+        GFM will turn that reference into a link so you can navigate between them easily.
+
+      %p GFM will recognize the following references:
+      %ul
+        %li
+          %code @foo
+          for team members
+        %li
+          %code #123
+          for issues
+        %li
+          %code !123
+          for merge request
+        %li
+          %code $123
+          for snippets
+        %li
+          %code 1234567
+          for commits
+
+      -# this example will only be shown if the user has a project with at least one issue
+      - if @project = current_user.authorized_projects.first
+        - if issue = @project.issues.first
+          %p For example in your #{link_to @project.name, project_path(@project)} project, writing:
+          %pre= "This is related to ##{issue.id}. @#{current_user.name} is working on solving it."
+          %p becomes:
+          = markdown "This is related to ##{issue.id}. @#{current_user.name} is working on solving it."
+        - @project = nil # Prevent this from bubbling up to page title
diff --git a/app/views/help/permissions.html.haml b/app/views/help/permissions.html.haml
index b56251f35eb..2075753e82a 100644
--- a/app/views/help/permissions.html.haml
+++ b/app/views/help/permissions.html.haml
@@ -1,68 +1,66 @@
-%h3.page_title Permissions
-.back_link
-  = link_to help_path do
-    &larr; to index
-%hr
+= render layout: 'help/layout' do
+  %h3.page_title Permissions
+  %br
 
-%fieldset
-  %legend Guest
-  %ul
-    %li Create new issue
-    %li Leave comments
-    %li Write on project wall
+  %fieldset
+    %legend Guest
+    %ul
+      %li Create new issue
+      %li Leave comments
+      %li Write on project wall
 
-%fieldset
-  %legend Reporter
-  %ul
-    %li Create new issue
-    %li Leave comments
-    %li Write on project wall
-    %li Pull project code
-    %li Download project
-    %li Create a code snippets
+  %fieldset
+    %legend Reporter
+    %ul
+      %li Create new issue
+      %li Leave comments
+      %li Write on project wall
+      %li Pull project code
+      %li Download project
+      %li Create a code snippets
 
 
-%fieldset
-  %legend Developer
-  %ul
-    %li Create new issue
-    %li Leave comments
-    %li Write on project wall
-    %li Pull project code
-    %li Download project
-    %li Create new merge request
-    %li Create a code snippets
-    %li Create new branches
-    %li Push to non-protected branches
-    %li Remove non-protected branches
-    %li Add tags
-    %li Write a wiki
+  %fieldset
+    %legend Developer
+    %ul
+      %li Create new issue
+      %li Leave comments
+      %li Write on project wall
+      %li Pull project code
+      %li Download project
+      %li Create new merge request
+      %li Create a code snippets
+      %li Create new branches
+      %li Push to non-protected branches
+      %li Remove non-protected branches
+      %li Add tags
+      %li Write a wiki
 
-%fieldset
-  %legend Master
-  %ul
-    %li Create new issue
-    %li Leave comments
-    %li Write on project wall
-    %li Pull project code
-    %li Download project
-    %li Create new merge request
-    %li Create a code snippets
-    %li Create new branches
-    %li Push to non-protected branches
-    %li Remove non-protected branches
-    %li Add tags
-    %li Write a wiki
-    %li Add new team members
-    %li Push to protected branches
-    %li Remove protected branches
-    %li Push with force option
-    %li Edit project
-    %li Add Deploy Keys to project
-    %li Configure Project Hooks
+  %fieldset
+    %legend Master
+    %ul
+      %li Create new issue
+      %li Leave comments
+      %li Write on project wall
+      %li Pull project code
+      %li Download project
+      %li Create new merge request
+      %li Create a code snippets
+      %li Create new branches
+      %li Push to non-protected branches
+      %li Remove non-protected branches
+      %li Add tags
+      %li Write a wiki
+      %li Add new team members
+      %li Push to protected branches
+      %li Remove protected branches
+      %li Push with force option
+      %li Edit project
+      %li Add Deploy Keys to project
+      %li Configure Project Hooks
 
-%fieldset
-  %legend Owner
-  %ul
-    %li Transfer project to another namespace
-    %li Remove project
+  %fieldset
+    %legend Owner
+    %ul
+      %li Transfer project to another namespace
+      %li Remove project
diff --git a/app/views/help/public_access.html.haml b/app/views/help/public_access.html.haml
index 60d8d597617..66de17a34ed 100644
--- a/app/views/help/public_access.html.haml
+++ b/app/views/help/public_access.html.haml
@@ -1,18 +1,16 @@
-%h3.page_title Public Access
-.back_link
-  = link_to help_path do
-    &larr; to index
-%hr
+= render layout: 'help/layout' do
+  %h3.page_title Public Access
+  %br
 
-%p
-  GitLab allows you to open selected projects to be accessed publicly.
-  These projects will be clonable
-  %em without any
-  authentication.
-  Also they will be listed on the #{link_to "public access directory", public_root_path}.
+  %p
+    GitLab allows you to open selected projects to be accessed publicly.
+    These projects will be clonable
+    %em without any
+    authentication.
+    Also they will be listed on the #{link_to "public access directory", public_root_path}.
 
-%ol
-  %li Go to your project dashboard
-  %li Click on the "Edit" tab
-  %li Select "Public clone access"
+  %ol
+    %li Go to your project dashboard
+    %li Click on the "Edit" tab
+    %li Select "Public clone access"
 
diff --git a/app/views/help/raketasks.html.haml b/app/views/help/raketasks.html.haml
index f015451a673..bcc874fc390 100644
--- a/app/views/help/raketasks.html.haml
+++ b/app/views/help/raketasks.html.haml
@@ -1,66 +1,64 @@
-%h3.page_title GitLab Rake Tasks
-.back_link
-  = link_to help_path do
-    &larr; to index
-%hr
+= render layout: 'help/layout' do
+  %h3.page_title GitLab Rake Tasks
+  %br
 
-%p.slead
-  GitLab provides some specific rake tasks to enable special features or perform maintenance tasks.
+  %p.slead
+    GitLab provides some specific rake tasks to enable special features or perform maintenance tasks.
 
-%ul.nav.nav-tabs.log-tabs
-  %li.active
-    = link_to "Features", "#features", 'data-toggle' => 'tab'
-  %li
-    = link_to "Maintenance", "#maintenance", 'data-toggle' => 'tab'
-  %li
-    = link_to "User Management", "#user_management", 'data-toggle' => 'tab'
-  %li
-    = link_to "Backup & Restore", "#backup_restore", 'data-toggle' => 'tab'
-  %li
-    = link_to "Cleanup", "#cleanup", 'data-toggle' => 'tab'
+  %ul.nav.nav-tabs.log-tabs
+    %li.active
+      = link_to "Features", "#features", 'data-toggle' => 'tab'
+    %li
+      = link_to "Maintenance", "#maintenance", 'data-toggle' => 'tab'
+    %li
+      = link_to "User Management", "#user_management", 'data-toggle' => 'tab'
+    %li
+      = link_to "Backup & Restore", "#backup_restore", 'data-toggle' => 'tab'
+    %li
+      = link_to "Cleanup", "#cleanup", 'data-toggle' => 'tab'
 
-.tab-content
-  .tab-pane.active#features
-    .file_holder
-      .file_title
-        %i.icon-file
-        Features
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "raketasks", "features.md"))
+  .tab-content
+    .tab-pane.active#features
+      .file_holder
+        .file_title
+          %i.icon-file
+          Features
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "raketasks", "features.md"))
 
-  .tab-pane#maintenance
-    .file_holder
-      .file_title
-        %i.icon-file
-        Maintenance
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "raketasks", "maintenance.md"))
+    .tab-pane#maintenance
+      .file_holder
+        .file_title
+          %i.icon-file
+          Maintenance
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "raketasks", "maintenance.md"))
 
-  .tab-pane#user_management
-    .file_holder
-      .file_title
-        %i.icon-file
-        User Management
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "raketasks", "user_management.md"))
+    .tab-pane#user_management
+      .file_holder
+        .file_title
+          %i.icon-file
+          User Management
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "raketasks", "user_management.md"))
 
-  .tab-pane#cleanup
-    .file_holder
-      .file_title
-        %i.icon-file
-        Cleanup
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "raketasks", "cleanup.md"))
+    .tab-pane#cleanup
+      .file_holder
+        .file_title
+          %i.icon-file
+          Cleanup
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "raketasks", "cleanup.md"))
 
-  .tab-pane#backup_restore
-    .file_holder
-      .file_title
-        %i.icon-file
-        Backup & Restore
-      .file_content.wiki
-        = preserve do
-          = markdown File.read(Rails.root.join("doc", "raketasks", "backup_restore.md"))
+    .tab-pane#backup_restore
+      .file_holder
+        .file_title
+          %i.icon-file
+          Backup & Restore
+        .file_content.wiki
+          = preserve do
+            = markdown File.read(Rails.root.join("doc", "raketasks", "backup_restore.md"))
diff --git a/app/views/help/ssh.html.haml b/app/views/help/ssh.html.haml
index 3f082333a76..114415977b4 100644
--- a/app/views/help/ssh.html.haml
+++ b/app/views/help/ssh.html.haml
@@ -1,25 +1,23 @@
-%h3.page_title SSH Keys
-.back_link
-  = link_to help_path do
-    &larr; to index
-%hr
+= render layout: 'help/layout' do
+  %h3.page_title SSH Keys
+  %br
 
-%p.slead
-  SSH key allows you to establish a secure connection between your computer and GitLab
+  %p.slead
+    SSH key allows you to establish a secure connection between your computer and GitLab
 
-%p.slead
-  To generate a new SSH key just open your terminal and use code below.
+  %p.slead
+    To generate a new SSH key just open your terminal and use code below.
 
-%pre.dark
-  ssh-keygen -t rsa -C "#{current_user.email}"
+  %pre.dark
+    ssh-keygen -t rsa -C "#{current_user.email}"
 
-  \# Creates a new ssh key using the provided email
-  \# Generating public/private rsa key pair...
+    \# Creates a new ssh key using the provided email
+    \# Generating public/private rsa key pair...
 
-%p.slead
-  Next just use code below to dump your public key and add to GitLab SSH Keys
+  %p.slead
+    Next just use code below to dump your public key and add to GitLab SSH Keys
 
-%pre.dark
-  cat ~/.ssh/id_rsa.pub
+  %pre.dark
+    cat ~/.ssh/id_rsa.pub
 
-  \# ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6eNtGpNGwstc....
+    \# ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6eNtGpNGwstc....
diff --git a/app/views/help/system_hooks.html.haml b/app/views/help/system_hooks.html.haml
index c25b60deeb0..c49011a2269 100644
--- a/app/views/help/system_hooks.html.haml
+++ b/app/views/help/system_hooks.html.haml
@@ -1,14 +1,12 @@
-%h3 System hooks
-.back_link
-  = link_to :back do
-    &larr; back
-%hr
-
-%p.slead
-  Your GitLab instance can perform HTTP POST requests on the following events: create_project, delete_project, create_user, delete_user, change_team_member.
-  %br
+= render layout: 'help/layout' do
+  %h3.page_title System hooks
   %br
-  System Hooks can be used, e.g. for logging or changing information in a LDAP server.
-  %br
-%h5 Hooks request example:
-= render "admin/hooks/data_ex"
+
+  %p.slead
+    Your GitLab instance can perform HTTP POST requests on the following events: create_project, delete_project, create_user, delete_user, change_team_member.
+    %br
+    %br
+    System Hooks can be used, e.g. for logging or changing information in a LDAP server.
+    %br
+  %h5 Hooks request example:
+  = render "admin/hooks/data_ex"
diff --git a/app/views/help/web_hooks.html.haml b/app/views/help/web_hooks.html.haml
index 65036613fa7..09745f73614 100644
--- a/app/views/help/web_hooks.html.haml
+++ b/app/views/help/web_hooks.html.haml
@@ -1,15 +1,13 @@
-%h3.page_title Web hooks
-.back_link
-  = link_to help_path do
-    &larr; to index
-%hr
-
-%p.slead
-  Every GitLab project can trigger a web server whenever the repo is pushed to.
-  %br
-  Web Hooks can be used to update an external issue tracker, trigger CI builds, update a backup mirror, or even deploy to your production server.
+= render layout: 'help/layout' do
+  %h3.page_title Web hooks
   %br
-  GitLab will send POST request with commits information on every push.
-%h5 Hooks request example:
-= render "hooks/data_ex"
+
+  %p.slead
+    Every GitLab project can trigger a web server whenever the repo is pushed to.
+    %br
+    Web Hooks can be used to update an external issue tracker, trigger CI builds, update a backup mirror, or even deploy to your production server.
+    %br
+    GitLab will send POST request with commits information on every push.
+  %h5 Hooks request example:
+  = render "hooks/data_ex"
 
diff --git a/app/views/help/workflow.html.haml b/app/views/help/workflow.html.haml
index 6062ca091bd..495b7c6e6fc 100644
--- a/app/views/help/workflow.html.haml
+++ b/app/views/help/workflow.html.haml
@@ -1,40 +1,38 @@
-%h3.page_title Workflow
-.back_link
-  = link_to help_path do
-    &larr; to index
-%hr
-
-%ol.help
-  %li
-    %p Clone project
-    .bash
-      %pre.dark
-        git clone git@example.com:project-name.git
-
-  %li
-    %p Create branch with your feature
-    .bash
-      %pre.dark
-        git checkout -b $feature_name
-
-  %li
-    %p Write code. Commit changes
-    .bash
-      %pre.dark
-        git commit -am "My feature is ready"
-
-  %li
-    %p Push your branch to GitLab
-    .bash
-      %pre.dark
-        git push origin $feature_name
-
-  %li
-    %p Review your code on Commits page
-
-  %li
-    %p Create a merge request
-
-  %li
-    %p Your team lead will review code &amp; merge it to main branch
+= render layout: 'help/layout' do
+  %h3.page_title Workflow
+  %br
+
+  %ol.help
+    %li
+      %p Clone project
+      .bash
+        %pre.dark
+          git clone git@example.com:project-name.git
+
+    %li
+      %p Create branch with your feature
+      .bash
+        %pre.dark
+          git checkout -b $feature_name
+
+    %li
+      %p Write code. Commit changes
+      .bash
+        %pre.dark
+          git commit -am "My feature is ready"
+
+    %li
+      %p Push your branch to GitLab
+      .bash
+        %pre.dark
+          git push origin $feature_name
+
+    %li
+      %p Review your code on Commits page
+
+    %li
+      %p Create a merge request
+
+    %li
+      %p Your team lead will review code &amp; merge it to main branch
 
-- 
GitLab


From 70690e1971f6d009da9a37782764ae7446f69636 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 22 Jan 2013 19:05:01 +0200
Subject: [PATCH 012/197] base implementation

---
 .../stylesheets/gitlab_bootstrap/common.scss  |  1 +
 app/assets/stylesheets/sections/header.scss   |  2 +-
 app/controllers/users_controller.rb           |  7 +++
 app/helpers/events_helper.rb                  |  7 ++-
 app/views/users/show.html.haml                | 44 +++++++++++++++++++
 config/routes.rb                              |  3 ++
 6 files changed, 59 insertions(+), 5 deletions(-)
 create mode 100644 app/controllers/users_controller.rb
 create mode 100644 app/views/users/show.html.haml

diff --git a/app/assets/stylesheets/gitlab_bootstrap/common.scss b/app/assets/stylesheets/gitlab_bootstrap/common.scss
index 6f439c9eaed..f6b4881658c 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/common.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/common.scss
@@ -95,6 +95,7 @@ img.avatar { float: left; margin-right: 12px; width: 40px; border: 1px solid #dd
 img.avatar.s16 { width: 16px; height: 16px; margin-right: 6px; }
 img.avatar.s24 { width: 24px; height: 24px; margin-right: 8px; }
 img.avatar.s32 { width: 32px; height: 32px; margin-right: 10px; }
+img.avatar.s90 { width: 90px; height: 90px; margin-right: 15px; }
 img.lil_av { padding-left: 4px; padding-right: 3px; }
 img.small { width: 80px; }
 
diff --git a/app/assets/stylesheets/sections/header.scss b/app/assets/stylesheets/sections/header.scss
index 048a3ffcbb2..5fe18131828 100644
--- a/app/assets/stylesheets/sections/header.scss
+++ b/app/assets/stylesheets/sections/header.scss
@@ -13,7 +13,7 @@ header {
         color: $style_color;
         text-shadow: 0 1px 0 #fff;
         font-size: 18px;
-        padding: 11px;
+        padding: 12px;
       }
 
       /** NAV block with links and profile **/
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
new file mode 100644
index 00000000000..4d106dc7a21
--- /dev/null
+++ b/app/controllers/users_controller.rb
@@ -0,0 +1,7 @@
+class UsersController < ApplicationController
+  def show
+    @user = User.find_by_username(params[:username])
+    @projects = @user.authorized_projects.where('projects.id in (?)', current_user.authorized_projects.map(&:id))
+    @events = @user.recent_events.where(project_id: @projects.map(&:id)).limit(20)
+  end
+end
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
index f4d9b17bce5..38374e3394d 100644
--- a/app/helpers/events_helper.rb
+++ b/app/helpers/events_helper.rb
@@ -1,10 +1,9 @@
 module EventsHelper
   def link_to_author(event)
-    project = event.project
-    tm = project.team_member_by_id(event.author_id) if project
+    author = event.author
 
-    if tm
-      link_to event.author_name, project_team_member_path(project, tm)
+    if author
+      link_to author.name, user_path(author.username)
     else
       event.author_name
     end
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
new file mode 100644
index 00000000000..613ff358a87
--- /dev/null
+++ b/app/views/users/show.html.haml
@@ -0,0 +1,44 @@
+.row
+  .span8
+    %h3.page_title
+      = image_tag gravatar_icon(@user.email, 90), class: "avatar s90"
+      = @user.name
+      %span.light (@#{@user.username})
+    .clearfix
+    %hr
+    %h5 Recent events
+    = render @events
+  .span4
+    .ui-box
+      %h5.title Profile
+      %ul.well-list
+        %li
+          %strong Email
+          %span.right= mail_to @user.email
+        - unless @user.skype.blank?
+          %li
+            %strong Skype
+            %span.right= @user.skype
+        - unless @user.linkedin.blank?
+          %li
+            %strong LinkedIn
+            %span.right= @user.linkedin
+        - unless @user.twitter.blank?
+          %li
+            %strong Twitter
+            %span.right= @user.twitter
+        - unless @user.bio.blank?
+          %li
+            %strong Bio
+            %span.right= @user.bio
+    .ui-box
+      %h5.title Projects
+      %ul.well-list
+        - @projects.each do |project|
+          %li
+            = link_to project_path(project), class: dom_class(project) do
+              - if project.namespace
+                = project.namespace.human_name
+                \/
+              %strong.well-title
+                = truncate(project.name, length: 45)
diff --git a/config/routes.rb b/config/routes.rb
index 00ff3f63752..c48d66a78e8 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -97,6 +97,9 @@ Gitlab::Application.routes.draw do
   end
 
   resources :keys
+  match "/u/:username" => "users#show", as: :user
+
+
 
   #
   # Dashboard Area
-- 
GitLab


From 96d97c4857cd2497108c8e5740ac8134cd439546 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 22 Jan 2013 19:45:13 +0200
Subject: [PATCH 013/197] Fix routing. Finalize user show page

---
 app/controllers/users_controller.rb |  2 +-
 app/models/team.rb                  |  4 ++++
 app/views/users/_projects.html.haml | 20 ++++++++++++++++++++
 app/views/users/show.html.haml      | 17 +++++------------
 config/routes.rb                    |  2 +-
 5 files changed, 31 insertions(+), 14 deletions(-)
 create mode 100644 app/views/users/_projects.html.haml

diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 4d106dc7a21..e027057fe65 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -1,6 +1,6 @@
 class UsersController < ApplicationController
   def show
-    @user = User.find_by_username(params[:username])
+    @user = User.find_by_username!(params[:username])
     @projects = @user.authorized_projects.where('projects.id in (?)', current_user.authorized_projects.map(&:id))
     @events = @user.recent_events.where(project_id: @projects.map(&:id)).limit(20)
   end
diff --git a/app/models/team.rb b/app/models/team.rb
index f235d20ebdb..51f4ff68d7b 100644
--- a/app/models/team.rb
+++ b/app/models/team.rb
@@ -21,6 +21,10 @@ class Team
     end
   end
 
+  def get_tm user_id
+    project.users_projects.find_by_user_id(user_id)
+  end
+
   def add_user(user, access)
     add_users_ids([user.id], access)
   end
diff --git a/app/views/users/_projects.html.haml b/app/views/users/_projects.html.haml
new file mode 100644
index 00000000000..f46a0ed1161
--- /dev/null
+++ b/app/views/users/_projects.html.haml
@@ -0,0 +1,20 @@
+.ui-box
+  %h5.title Projects
+  %ul.well-list
+    - @projects.each do |project|
+      %li
+        = link_to project_path(project), class: dom_class(project) do
+          - if project.namespace
+            = project.namespace.human_name
+            \/
+          %strong.well-title
+            = truncate(project.name, length: 45)
+          %span.right.light
+            - if project.owner == @user
+              %i.icon-wrench
+            - tm = project.team.get_tm(@user.id)
+            - if tm
+              = tm.project_access_human
+%p.light
+  %i.icon-wrench
+  &ndash; user is a project owner
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index 613ff358a87..2a77c6bfa3d 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -3,7 +3,10 @@
     %h3.page_title
       = image_tag gravatar_icon(@user.email, 90), class: "avatar s90"
       = @user.name
-      %span.light (@#{@user.username})
+      %br
+      %small @#{@user.username}
+      %br
+      %small member since #{@user.created_at.stamp("Nov 12, 2031")}
     .clearfix
     %hr
     %h5 Recent events
@@ -31,14 +34,4 @@
           %li
             %strong Bio
             %span.right= @user.bio
-    .ui-box
-      %h5.title Projects
-      %ul.well-list
-        - @projects.each do |project|
-          %li
-            = link_to project_path(project), class: dom_class(project) do
-              - if project.namespace
-                = project.namespace.human_name
-                \/
-              %strong.well-title
-                = truncate(project.name, length: 45)
+    = render 'projects'
diff --git a/config/routes.rb b/config/routes.rb
index c48d66a78e8..c7e81b6fe5a 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -97,7 +97,7 @@ Gitlab::Application.routes.draw do
   end
 
   resources :keys
-  match "/u/:username" => "users#show", as: :user
+  match "/u/:username" => "users#show", as: :user, constraints: { username: /.*/ }
 
 
 
-- 
GitLab


From 0ed7f32db3114ea3b0e07acdfff7054904057af5 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 22 Jan 2013 19:54:45 +0200
Subject: [PATCH 014/197] changelog

---
 CHANGELOG | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/CHANGELOG b/CHANGELOG
index 2d05a51e77d..4510b6d5cd9 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,7 @@
+v 4.2.0
+  - User show page. Via /u/username
+  - Show help contents on pages for better navigation
+
 v 4.1.0
   - Optional Sign-Up
   - Discussions
-- 
GitLab


From 621ca86b9edc9f4086f28ab469b3ca3d5b35b82a Mon Sep 17 00:00:00 2001
From: Erwan Arzur <earzur@runmyprocess.com>
Date: Tue, 22 Jan 2013 19:07:11 +0100
Subject: [PATCH 015/197] [import] - fix project import after refactoring

---
 lib/tasks/gitlab/import.rake | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/tasks/gitlab/import.rake b/lib/tasks/gitlab/import.rake
index 4bf9110508e..0ca652faa74 100644
--- a/lib/tasks/gitlab/import.rake
+++ b/lib/tasks/gitlab/import.rake
@@ -44,7 +44,7 @@ namespace :gitlab do
             :name => path,
           }
 
-          project = Project.create_by_user(project_params, user)
+          project = Projects::CreateContext.new(user, project_params).execute
 
           if project.valid?
             puts " * Created #{project.name} (#{repo_name})".green
-- 
GitLab


From 79b9249ff44c5ccbef44a8d9420a3fff369d932a Mon Sep 17 00:00:00 2001
From: Jun Futagawa <jfut@integ.jp>
Date: Wed, 23 Jan 2013 17:29:46 +0900
Subject: [PATCH 016/197] Remove relative_url_root from path. Fixes #2602

Files and Commits render a 404 when running with relative_url_root.
---
 lib/extracts_path.rb           |  2 ++
 spec/lib/extracts_path_spec.rb | 23 +++++++++++++++++++++++
 2 files changed, 25 insertions(+)

diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb
index 270a0aaa87a..12700e4f4ac 100644
--- a/lib/extracts_path.rb
+++ b/lib/extracts_path.rb
@@ -50,6 +50,8 @@ module ExtractsPath
 
     return pair unless @project
 
+    # Remove relative_url_root from path
+    input.gsub!(/^#{Gitlab.config.gitlab.relative_url_root}/, "")
     # Remove project, actions and all other staff from path
     input.gsub!(/^\/#{Regexp.escape(@project.path_with_namespace)}/, "")
     input.gsub!(/^\/(tree|commits|blame|blob|refs)\//, "") # remove actions
diff --git a/spec/lib/extracts_path_spec.rb b/spec/lib/extracts_path_spec.rb
index deb6499e008..ee20ae79809 100644
--- a/spec/lib/extracts_path_spec.rb
+++ b/spec/lib/extracts_path_spec.rb
@@ -73,5 +73,28 @@ describe ExtractsPath do
         extract_ref('/gitlab/gitlab-ci/tree/v2.0.0/CHANGELOG?_=12354435').should == ['v2.0.0', 'CHANGELOG']
       end
     end
+
+    context "with a fullpath and a relative_url_root" do
+      before do
+        Gitlab.config.gitlab.stub(relative_url_root: '/relative')
+      end
+
+      it "extracts a valid branch with relative_url_root" do
+        extract_ref('/relative/gitlab/gitlab-ci/tree/foo/bar/baz/CHANGELOG').should == ['foo/bar/baz', 'CHANGELOG']
+      end
+
+      it "extracts a valid tag" do
+        extract_ref('/relative/gitlab/gitlab-ci/tree/v2.0.0/CHANGELOG').should == ['v2.0.0', 'CHANGELOG']
+      end
+
+      it "extracts a valid commit SHA" do
+        extract_ref('/relative/gitlab/gitlab-ci/tree/f4b14494ef6abf3d144c28e4af0c20143383e062/CHANGELOG').should ==
+          ['f4b14494ef6abf3d144c28e4af0c20143383e062', 'CHANGELOG']
+      end
+
+      it "extracts a timestamp" do
+        extract_ref('/relative/gitlab/gitlab-ci/tree/v2.0.0/CHANGELOG?_=12354435').should == ['v2.0.0', 'CHANGELOG']
+      end
+    end
   end
 end
-- 
GitLab


From 70687cd5812a53ce574589f4f7ce6a6d683c2f07 Mon Sep 17 00:00:00 2001
From: Sato Hiroyuki <sathiroyuki@gmail.com>
Date: Wed, 23 Jan 2013 21:34:19 +0900
Subject: [PATCH 017/197] Improve network graph

---
 lib/gitlab/graph/json_builder.rb          | 10 ++++++----
 vendor/assets/javascripts/branch-graph.js |  4 ++--
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/lib/gitlab/graph/json_builder.rb b/lib/gitlab/graph/json_builder.rb
index 4a48b3b5675..a3157aa4b4d 100644
--- a/lib/gitlab/graph/json_builder.rb
+++ b/lib/gitlab/graph/json_builder.rb
@@ -16,6 +16,7 @@ module Gitlab
 
         @commits = collect_commits
         @days = index_commits
+        @space = 0
       end
 
       def to_json(*args)
@@ -97,8 +98,8 @@ module Gitlab
         if leaves.empty?
           return
         end
-        space = find_free_space(leaves, map)
-        leaves.each{|l| l.space = space}
+        @space = find_free_space(leaves, map)
+        leaves.each{|l| l.space = @space}
         # and mark it as reserved
         min_time = leaves.last.time
         parents = leaves.last.parents.collect
@@ -115,7 +116,7 @@ module Gitlab
         else
           max_time = parent_time - 1
         end
-        mark_reserved(min_time..max_time, space)
+        mark_reserved(min_time..max_time, @space)
 
         # Visit branching chains
         leaves.each do |l|
@@ -139,9 +140,10 @@ module Gitlab
           reserved += @_reserved[day]
         end
         space = base_space(leaves, map)
-        while reserved.include? space do
+        while (reserved.include? space) || (space == @space) do
           space += 1
         end
+
         space
       end
 
diff --git a/vendor/assets/javascripts/branch-graph.js b/vendor/assets/javascripts/branch-graph.js
index 805423bc70d..af3b572a4e3 100644
--- a/vendor/assets/javascripts/branch-graph.js
+++ b/vendor/assets/javascripts/branch-graph.js
@@ -121,7 +121,7 @@
           if (c.space == this.commits[i].space) {
             r.path([
               "M", x, y,
-              "L", x - 20 * (c.time + 1), y
+              "L", cx, cy
             ]).attr({
               stroke: this.colors[c.space], 
               "stroke-width": 2
@@ -351,4 +351,4 @@ function textWrap(t, width) {
   t.attr({
     "y": b.y + h
   });
-}
\ No newline at end of file
+}
-- 
GitLab


From b614e3b5cbff88b16b87ea8dc1b03ddc53146d15 Mon Sep 17 00:00:00 2001
From: fbehrens <fbehrens@gmail.com>
Date: Wed, 23 Jan 2013 15:32:31 +0100
Subject: [PATCH 018/197] Update config/database.yml.postgresql

This was necessary following the installation guide for ubuntu 10.4 with postgres
---
 config/database.yml.postgresql | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/config/database.yml.postgresql b/config/database.yml.postgresql
index 0e873d2b8fb..2bc0884f099 100644
--- a/config/database.yml.postgresql
+++ b/config/database.yml.postgresql
@@ -6,7 +6,7 @@ production:
   encoding: unicode
   database: gitlabhq_production
   pool: 5
-  username: postgres
+  username: gitlab
   password:
   # host: localhost
   # port: 5432 
-- 
GitLab


From d3c34ef8afa1018e9dae0a144227b399ba89adbf Mon Sep 17 00:00:00 2001
From: Austin Robertson <austinrobertson@gmail.com>
Date: Wed, 23 Jan 2013 08:47:19 -0600
Subject: [PATCH 019/197] Revise projects/new text

The previous text implied projects can only be private. Projects can now be private or public.
---
 app/views/projects/_new_form.html.haml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/views/projects/_new_form.html.haml b/app/views/projects/_new_form.html.haml
index 131a4de4218..2d5f3923e80 100644
--- a/app/views/projects/_new_form.html.haml
+++ b/app/views/projects/_new_form.html.haml
@@ -17,4 +17,4 @@
         = f.select :namespace_id, namespaces_options(params[:namespace_id] || :current_user), {}, {class: 'chosen'}
   %hr
   %p.padded
-    All created project are private. You choose who can see project and commit to repository.
+    New projects are private by default. You choose who can see the project and commit to repository.
-- 
GitLab


From 8ec36ca056cdae7ecd6b2b7dce215d7ef897e22d Mon Sep 17 00:00:00 2001
From: Chris Waguespack <cjwprostar@hotmail.com>
Date: Wed, 23 Jan 2013 09:58:38 -0600
Subject: [PATCH 020/197] Update Markdown example to use username

Update the Markdown example in the Help pages to use username instead of user.
---
 app/views/help/markdown.html.haml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/views/help/markdown.html.haml b/app/views/help/markdown.html.haml
index 46bcd895274..92c1e49be49 100644
--- a/app/views/help/markdown.html.haml
+++ b/app/views/help/markdown.html.haml
@@ -121,7 +121,7 @@
       - if @project = current_user.authorized_projects.first
         - if issue = @project.issues.first
           %p For example in your #{link_to @project.name, project_path(@project)} project, writing:
-          %pre= "This is related to ##{issue.id}. @#{current_user.name} is working on solving it."
+          %pre= "This is related to ##{issue.id}. @#{current_user.username} is working on solving it."
           %p becomes:
-          = markdown "This is related to ##{issue.id}. @#{current_user.name} is working on solving it."
+          = markdown "This is related to ##{issue.id}. @#{current_user.username} is working on solving it."
         - @project = nil # Prevent this from bubbling up to page title
-- 
GitLab


From f6c482c06f48449e7dcff34455b5bbdfbd8f6c7b Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 24 Jan 2013 17:47:09 +0200
Subject: [PATCH 021/197] User can create group

---
 app/controllers/groups_controller.rb    | 26 +++++++++++++++++++----
 app/helpers/tab_helper.rb               |  7 ++++++-
 app/models/user.rb                      |  2 +-
 app/views/dashboard/_groups.html.haml   |  2 +-
 app/views/groups/new.html.haml          | 21 +++++++++++++++++++
 app/views/layouts/_head_panel.html.haml |  2 +-
 app/views/projects/_new_form.html.haml  |  6 ++++++
 app/views/users/_profile.html.haml      | 23 ++++++++++++++++++++
 app/views/users/show.html.haml          | 28 ++++++-------------------
 config/routes.rb                        |  2 +-
 features/group/create_group.feature     | 11 ++++++++++
 features/steps/group/group.rb           | 18 ++++++++++++++++
 12 files changed, 117 insertions(+), 31 deletions(-)
 create mode 100644 app/views/groups/new.html.haml
 create mode 100644 app/views/users/_profile.html.haml
 create mode 100644 features/group/create_group.feature

diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index c25fc32a62c..f95db1af383 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -1,12 +1,30 @@
 class GroupsController < ApplicationController
   respond_to :html
-  layout 'group'
+  layout 'group', except: [:new, :create]
 
-  before_filter :group
-  before_filter :projects
+  before_filter :group, except: [:new, :create]
 
   # Authorize
-  before_filter :authorize_read_group!
+  before_filter :authorize_read_group!, except: [:new, :create]
+
+  # Load group projects
+  before_filter :projects, except: [:new, :create]
+
+  def new
+    @group = Group.new
+  end
+
+  def create
+    @group = Group.new(params[:group])
+    @group.path = @group.name.dup.parameterize if @group.name
+    @group.owner = current_user
+
+    if @group.save
+      redirect_to @group, notice: 'Group was successfully created.'
+    else
+      render action: "new"
+    end
+  end
 
   def show
     @events = Event.in_projects(project_ids).limit(20).offset(params[:offset] || 0)
diff --git a/app/helpers/tab_helper.rb b/app/helpers/tab_helper.rb
index d52d8af6641..5bd6de896ee 100644
--- a/app/helpers/tab_helper.rb
+++ b/app/helpers/tab_helper.rb
@@ -39,7 +39,12 @@ module TabHelper
   # Returns a list item element String
   def nav_link(options = {}, &block)
     if path = options.delete(:path)
-      c, a, _ = path.split('#')
+      if path.respond_to?(:each)
+        c = path.map { |p| p.split('#').first }
+        a = path.map { |p| p.split('#').last }
+      else
+        c, a, _ = path.split('#')
+      end
     else
       c = options.delete(:controller)
       a = options.delete(:action)
diff --git a/app/models/user.rb b/app/models/user.rb
index 35a693fdb1c..743d7523bdc 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -220,7 +220,7 @@ class User < ActiveRecord::Base
   end
 
   def can_create_group?
-    is_admin?
+    can_create_project?
   end
 
   def abilities
diff --git a/app/views/dashboard/_groups.html.haml b/app/views/dashboard/_groups.html.haml
index 7f544406761..dc50bffda80 100644
--- a/app/views/dashboard/_groups.html.haml
+++ b/app/views/dashboard/_groups.html.haml
@@ -5,7 +5,7 @@
       (#{groups.count})
     - if current_user.can_create_group?
       %span.right
-        = link_to new_admin_group_path, class: "btn very_small info" do
+        = link_to new_group_path, class: "btn very_small info" do
           %i.icon-plus
           New Group
   %ul.well-list
diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml
new file mode 100644
index 00000000000..b6d5f46507e
--- /dev/null
+++ b/app/views/groups/new.html.haml
@@ -0,0 +1,21 @@
+%h3.page_title New Group
+%hr
+= form_for @group do |f|
+  - if @group.errors.any?
+    .alert-message.block-message.error
+      %span= @group.errors.full_messages.first
+  .clearfix
+    = f.label :name do
+      Group name is
+    .input
+      = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
+      &nbsp;
+      = f.submit 'Create group', class: "btn primary"
+  %hr
+  .padded
+    %ul
+      %li Group is kind of directory for several projects
+      %li All created groups are private
+      %li People within a group see only projects they have access to
+      %li All projects of group will be stored in group directory
+      %li You will be able to move existing projects into group
diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml
index f4b2228a41b..8f4f3d7815f 100644
--- a/app/views/layouts/_head_panel.html.haml
+++ b/app/views/layouts/_head_panel.html.haml
@@ -17,7 +17,7 @@
             = link_to new_project_path, title: "Create New Project", class: 'has_bottom_tooltip', 'data-original-title' => 'New project'  do
               %i.icon-plus
         %li
-          = link_to profile_path, title: "Your Profile", class: 'has_bottom_tooltip', 'data-original-title' => 'Your profile'  do
+          = link_to profile_path, title: "My Profile", class: 'has_bottom_tooltip', 'data-original-title' => 'Your profile'  do
             %i.icon-user
         %li.separator
         %li
diff --git a/app/views/projects/_new_form.html.haml b/app/views/projects/_new_form.html.haml
index 2d5f3923e80..ba8f255558a 100644
--- a/app/views/projects/_new_form.html.haml
+++ b/app/views/projects/_new_form.html.haml
@@ -15,6 +15,12 @@
         %span Namespace
       .input
         = f.select :namespace_id, namespaces_options(params[:namespace_id] || :current_user), {}, {class: 'chosen'}
+  - elsif current_user.can_create_group?
+    .clearfix
+      .input.light
+        Need a group for several projects?
+        = link_to new_group_path, class: "btn very_small" do
+          Create a group
   %hr
   %p.padded
     New projects are private by default. You choose who can see the project and commit to repository.
diff --git a/app/views/users/_profile.html.haml b/app/views/users/_profile.html.haml
new file mode 100644
index 00000000000..ab6538f083b
--- /dev/null
+++ b/app/views/users/_profile.html.haml
@@ -0,0 +1,23 @@
+.ui-box
+  %h5.title
+    Profile
+  %ul.well-list
+    %li
+      %strong Email
+      %span.right= mail_to @user.email
+    - unless @user.skype.blank?
+      %li
+        %strong Skype
+        %span.right= @user.skype
+    - unless @user.linkedin.blank?
+      %li
+        %strong LinkedIn
+        %span.right= @user.linkedin
+    - unless @user.twitter.blank?
+      %li
+        %strong Twitter
+        %span.right= @user.twitter
+    - unless @user.bio.blank?
+      %li
+        %strong Bio
+        %span.right= @user.bio
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index 2a77c6bfa3d..644826282b8 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -3,6 +3,11 @@
     %h3.page_title
       = image_tag gravatar_icon(@user.email, 90), class: "avatar s90"
       = @user.name
+      - if @user == current_user
+        .right
+          = link_to profile_path, class: 'btn small' do
+            %i.icon-edit
+            Edit Profile
       %br
       %small @#{@user.username}
       %br
@@ -12,26 +17,5 @@
     %h5 Recent events
     = render @events
   .span4
-    .ui-box
-      %h5.title Profile
-      %ul.well-list
-        %li
-          %strong Email
-          %span.right= mail_to @user.email
-        - unless @user.skype.blank?
-          %li
-            %strong Skype
-            %span.right= @user.skype
-        - unless @user.linkedin.blank?
-          %li
-            %strong LinkedIn
-            %span.right= @user.linkedin
-        - unless @user.twitter.blank?
-          %li
-            %strong Twitter
-            %span.right= @user.twitter
-        - unless @user.bio.blank?
-          %li
-            %strong Bio
-            %span.right= @user.bio
+    = render 'profile'
     = render 'projects'
diff --git a/config/routes.rb b/config/routes.rb
index c7e81b6fe5a..6d7e615187d 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -112,7 +112,7 @@ Gitlab::Application.routes.draw do
   #
   # Groups Area
   #
-  resources :groups, constraints: { id: /[^\/]+/ }, only: [:show] do
+  resources :groups, constraints: { id: /[^\/]+/ }, only: [:show, :new, :create] do
     member do
       get :issues
       get :merge_requests
diff --git a/features/group/create_group.feature b/features/group/create_group.feature
new file mode 100644
index 00000000000..b77f3599e6a
--- /dev/null
+++ b/features/group/create_group.feature
@@ -0,0 +1,11 @@
+Feature: Groups
+  Background:
+    Given I sign in as a user
+
+  Scenario: Create a group from dasboard
+    Given I have group with projects
+    And I visit dashboard page
+    When I click new group link
+    And submit form with new group info
+    Then I should be redirected to group page
+    And I should see newly created group
diff --git a/features/steps/group/group.rb b/features/steps/group/group.rb
index 04d8c874b3e..c6c6b4b5e5b 100644
--- a/features/steps/group/group.rb
+++ b/features/steps/group/group.rb
@@ -64,6 +64,24 @@ class Groups < Spinach::FeatureSteps
       author: current_user
   end
 
+  When 'I click new group link' do
+    click_link "New Group"
+  end
+
+  And 'submit form with new group info' do
+    fill_in 'group_name', :with => 'Samurai'
+    click_button "Create group"
+  end
+
+  Then 'I should see newly created group' do
+    page.should have_content "Samurai"
+    page.should have_content "You will only see events from projects in this group"
+  end
+
+  Then 'I should be redirected to group page' do
+    current_path.should == group_path(Group.last)
+  end
+
   protected
 
   def current_group
-- 
GitLab


From 8a86fe7bb0785ea69e591fd287430eb5448ac64e Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Sat, 19 Jan 2013 21:06:50 +0400
Subject: [PATCH 022/197] Added UserTeam core models (team and m-t-m
 relationships) and updated other models

---
 app/models/concerns/issuable.rb               |  1 +
 app/models/project.rb                         | 39 +++++----
 app/models/user.rb                            | 35 +++++---
 app/models/user_team.rb                       | 87 +++++++++++++++++++
 app/models/user_team_project_relationship.rb  | 24 +++++
 app/models/user_team_user_relationship.rb     | 15 ++++
 app/models/users_project.rb                   |  3 +
 .../20121219183753_create_user_teams.rb       | 11 +++
 ..._create_user_team_project_relationships.rb | 11 +++
 ...453_create_user_team_user_relationships.rb | 12 +++
 db/schema.rb                                  | 25 ++++++
 .../user_team_project_relationship_spec.rb    |  5 ++
 spec/models/user_team_spec.rb                 |  5 ++
 .../user_team_user_relationship_spec.rb       |  5 ++
 14 files changed, 249 insertions(+), 29 deletions(-)
 create mode 100644 app/models/user_team.rb
 create mode 100644 app/models/user_team_project_relationship.rb
 create mode 100644 app/models/user_team_user_relationship.rb
 create mode 100644 db/migrate/20121219183753_create_user_teams.rb
 create mode 100644 db/migrate/20121220064104_create_user_team_project_relationships.rb
 create mode 100644 db/migrate/20121220064453_create_user_team_user_relationships.rb
 create mode 100644 spec/models/user_team_project_relationship_spec.rb
 create mode 100644 spec/models/user_team_spec.rb
 create mode 100644 spec/models/user_team_user_relationship_spec.rb

diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index d1717d3bbee..8872cf59a2c 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -22,6 +22,7 @@ module Issuable
     scope :opened, where(closed: false)
     scope :closed, where(closed: true)
     scope :of_group, ->(group) { where(project_id: group.project_ids) }
+    scope :of_user_team, ->(team) { where(project_id: team.project_ids, assignee_id: team.member_ids) }
     scope :assigned, ->(u) { where(assignee_id: u.id)}
     scope :recent, order("created_at DESC")
 
diff --git a/app/models/project.rb b/app/models/project.rb
index fa38093b7d5..fa314d9c5f0 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -33,28 +33,31 @@ class Project < ActiveRecord::Base
   attr_accessor :error_code
 
   # Relations
-  belongs_to :group, foreign_key: "namespace_id", conditions: "type = 'Group'"
+  belongs_to :creator,      foreign_key: "creator_id", class_name: "User"
+  belongs_to :group,        foreign_key: "namespace_id", conditions: "type = 'Group'"
   belongs_to :namespace
 
-  belongs_to :creator,
-    class_name: "User",
-    foreign_key: "creator_id"
-
-  has_many :users,          through: :users_projects
-  has_many :events,         dependent: :destroy
-  has_many :merge_requests, dependent: :destroy
-  has_many :issues,         dependent: :destroy, order: "closed, created_at DESC"
-  has_many :milestones,     dependent: :destroy
-  has_many :users_projects, dependent: :destroy
-  has_many :notes,          dependent: :destroy
-  has_many :snippets,       dependent: :destroy
-  has_many :deploy_keys,    dependent: :destroy, foreign_key: "project_id", class_name: "Key"
-  has_many :hooks,          dependent: :destroy, class_name: "ProjectHook"
-  has_many :wikis,          dependent: :destroy
-  has_many :protected_branches, dependent: :destroy
   has_one :last_event, class_name: 'Event', order: 'events.created_at DESC', foreign_key: 'project_id'
   has_one :gitlab_ci_service, dependent: :destroy
 
+  has_many :events,             dependent: :destroy
+  has_many :merge_requests,     dependent: :destroy
+  has_many :issues,             dependent: :destroy, order: "closed, created_at DESC"
+  has_many :milestones,         dependent: :destroy
+  has_many :users_projects,     dependent: :destroy
+  has_many :notes,              dependent: :destroy
+  has_many :snippets,           dependent: :destroy
+  has_many :deploy_keys,        dependent: :destroy, class_name: "Key", foreign_key: "project_id"
+  has_many :hooks,              dependent: :destroy, class_name: "ProjectHook"
+  has_many :wikis,              dependent: :destroy
+  has_many :protected_branches, dependent: :destroy
+  has_many :user_team_project_relationships, dependent: :destroy
+
+  has_many :users,          through: :users_projects
+  has_many :user_teams,     through: :user_team_project_relationships
+  has_many :user_team_user_relationships, through: :user_teams
+  has_many :user_teams_members, through: :user_team_user_relationships
+
   delegate :name, to: :owner, allow_nil: true, prefix: true
 
   # Validations
@@ -77,6 +80,8 @@ class Project < ActiveRecord::Base
   # Scopes
   scope :without_user, ->(user)  { where("id NOT IN (:ids)", ids: user.authorized_projects.map(&:id) ) }
   scope :not_in_group, ->(group) { where("id NOT IN (:ids)", ids: group.project_ids ) }
+  scope :without_team, ->(team) { where("id NOT IN (:ids)", ids: team.projects.map(&:id)) }
+  scope :in_team, ->(team) { where("id IN (:ids)", ids: team.projects.map(&:id)) }
   scope :in_namespace, ->(namespace) { where(namespace_id: namespace.id) }
   scope :sorted_by_activity, ->() { order("(SELECT max(events.created_at) FROM events WHERE events.project_id = projects.id) DESC") }
   scope :personal, ->(user) { where(namespace_id: user.namespace_id) }
diff --git a/app/models/user.rb b/app/models/user.rb
index 743d7523bdc..16e07e9ce3f 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -45,18 +45,27 @@ class User < ActiveRecord::Base
   attr_accessor :force_random_password
 
   # Namespace for personal projects
-  has_one :namespace, class_name: "Namespace", foreign_key: :owner_id, conditions: 'type IS NULL', dependent: :destroy
-  has_many :groups, class_name: "Group", foreign_key: :owner_id
-
-  has_many :keys, dependent: :destroy
-  has_many :users_projects, dependent: :destroy
-  has_many :issues, foreign_key: :author_id, dependent: :destroy
-  has_many :notes, foreign_key: :author_id, dependent: :destroy
-  has_many :merge_requests, foreign_key: :author_id, dependent: :destroy
-  has_many :events, class_name: "Event", foreign_key: :author_id, dependent: :destroy
-  has_many :recent_events, class_name: "Event", foreign_key: :author_id, order: "id DESC"
-  has_many :assigned_issues, class_name: "Issue", foreign_key: :assignee_id, dependent: :destroy
-  has_many :assigned_merge_requests, class_name: "MergeRequest", foreign_key: :assignee_id, dependent: :destroy
+  has_one :namespace,                 dependent: :destroy, foreign_key: :owner_id,    class_name: "Namespace", conditions: 'type IS NULL'
+
+  has_many :keys,                     dependent: :destroy
+  has_many :users_projects,           dependent: :destroy
+  has_many :issues,                   dependent: :destroy, foreign_key: :author_id
+  has_many :notes,                    dependent: :destroy, foreign_key: :author_id
+  has_many :merge_requests,           dependent: :destroy, foreign_key: :author_id
+  has_many :events,                   dependent: :destroy, foreign_key: :author_id,   class_name: "Event"
+  has_many :assigned_issues,          dependent: :destroy, foreign_key: :assignee_id, class_name: "Issue"
+  has_many :assigned_merge_requests,  dependent: :destroy, foreign_key: :assignee_id, class_name: "MergeRequest"
+
+  has_many :groups,         class_name: "Group", foreign_key: :owner_id
+  has_many :recent_events,  class_name: "Event", foreign_key: :author_id, order: "id DESC"
+
+  has_many :projects,       through: :users_projects
+
+  has_many :user_team_user_relationships, dependent: :destroy
+
+  has_many :user_teams,                      through: :user_team_user_relationships
+  has_many :user_team_project_relationships, through: :user_teams
+  has_many :team_projects,                   through: :user_team_project_relationships
 
   validates :name, presence: true
   validates :bio, length: { within: 0..255 }
@@ -80,6 +89,8 @@ class User < ActiveRecord::Base
   scope :blocked, where(blocked:  true)
   scope :active, where(blocked:  false)
   scope :alphabetically, order('name ASC')
+  scope :in_team, ->(team){ where(id: team.member_ids) }
+  scope :not_in_team, ->(team){ where('users.id NOT IN (:ids)', ids: team.member_ids) }
 
   #
   # Class methods
diff --git a/app/models/user_team.rb b/app/models/user_team.rb
new file mode 100644
index 00000000000..d402fd22ea3
--- /dev/null
+++ b/app/models/user_team.rb
@@ -0,0 +1,87 @@
+class UserTeam < ActiveRecord::Base
+  attr_accessible :name, :owner_id, :path
+
+  belongs_to :owner, class_name: User
+
+  has_many :user_team_project_relationships, dependent: :destroy
+  has_many :user_team_user_relationships, dependent: :destroy
+
+  has_many :projects, through: :user_team_project_relationships
+  has_many :members,  through: :user_team_user_relationships, source: :user
+
+  validates :name, presence: true, uniqueness: true
+  validates :owner, presence: true
+  validates :path, uniqueness: true, presence: true, length: { within: 1..255 },
+            format: { with: Gitlab::Regex.path_regex,
+                      message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" }
+
+  scope :with_member, ->(user){ joins(:user_team_user_relationships).where(user_team_user_relationships: {user_id: user.id}) }
+  scope :created_by, ->(user){ where(owner_id: user) }
+
+  class << self
+    def search query
+      where("name LIKE :query OR path LIKE :query", query: "%#{query}%")
+    end
+
+    def global_id
+      'GLN'
+    end
+
+    def access_roles
+      UsersProject.access_roles
+    end
+  end
+
+  def to_param
+    path
+  end
+
+  def assign_to_projects(projects, access)
+    projects.each do |project|
+      assign_to_project(project, access)
+    end
+  end
+
+  def assign_to_project(project, access)
+    Gitlab::UserTeamManager.assign(self, project, access)
+  end
+
+  def resign_from_project(project)
+    Gitlab::UserTeamManager.resign(self, project)
+  end
+
+  def add_members(users, access, group_admin)
+    users.each do |user|
+      add_member(user, access, group_admin)
+    end
+  end
+
+  def add_member(user, access, group_admin)
+    Gitlab::UserTeamManager.add_member_into_team(self, user, access, group_admin)
+  end
+
+  def remove_member(user)
+    Gitlab::UserTeamManager.remove_member_from_team(self, user)
+  end
+
+  def max_project_access(project)
+    user_team_project_relationships.find_by_project_id(project).greatest_access
+  end
+
+  def human_max_project_access(project)
+    self.class.access_roles.invert[max_project_access(project)]
+  end
+
+  def default_projects_access(member)
+    user_team_user_relationships.find_by_user_id(member).permission
+  end
+
+  def human_default_projects_access(member)
+    self.class.access_roles.invert[default_projects_access(member)]
+  end
+
+  def admin?(member)
+    user_team_user_relationships.with_user(member).first.group_admin?
+  end
+
+end
diff --git a/app/models/user_team_project_relationship.rb b/app/models/user_team_project_relationship.rb
new file mode 100644
index 00000000000..4413c492a6d
--- /dev/null
+++ b/app/models/user_team_project_relationship.rb
@@ -0,0 +1,24 @@
+class UserTeamProjectRelationship < ActiveRecord::Base
+  attr_accessible :greatest_access, :project_id, :user_team_id
+
+  belongs_to :user_team
+  belongs_to :project
+
+  validates :project,   presence: true
+  validates :user_team, presence: true
+  validate :check_greatest_access
+
+  scope :with_project, ->(project){ where(project_id: project.id) }
+
+  private
+
+  def check_greatest_access
+    errors.add(:base, :incorrect_access_code) unless correct_access?
+  end
+
+  def correct_access?
+    return false if greatest_access.blank?
+    return true if UsersProject.access_roles.has_value?(greatest_access)
+    false
+  end
+end
diff --git a/app/models/user_team_user_relationship.rb b/app/models/user_team_user_relationship.rb
new file mode 100644
index 00000000000..00d12ebf607
--- /dev/null
+++ b/app/models/user_team_user_relationship.rb
@@ -0,0 +1,15 @@
+class UserTeamUserRelationship < ActiveRecord::Base
+  attr_accessible :group_admin, :permission, :user_id, :user_team_id
+
+  belongs_to :user_team
+  belongs_to :user
+
+  validates :user_team, presence: true
+  validates :user,      presence: true
+
+  scope :with_user, ->(user) { where(user_id: user.id) }
+
+  def user_name
+    user.name
+  end
+end
diff --git a/app/models/users_project.rb b/app/models/users_project.rb
index 79146289836..d282b2acbfc 100644
--- a/app/models/users_project.rb
+++ b/app/models/users_project.rb
@@ -39,7 +39,10 @@ class UsersProject < ActiveRecord::Base
   scope :reporters, where(project_access: REPORTER)
   scope :developers, where(project_access: DEVELOPER)
   scope :masters, where(project_access: MASTER)
+
   scope :in_project, ->(project) { where(project_id: project.id) }
+  scope :in_projects, ->(projects) { where(project_id: projects.map(&:id)) }
+  scope :with_user, ->(user) { where(user_id: user.id) }
 
   class << self
 
diff --git a/db/migrate/20121219183753_create_user_teams.rb b/db/migrate/20121219183753_create_user_teams.rb
new file mode 100644
index 00000000000..65c4d053982
--- /dev/null
+++ b/db/migrate/20121219183753_create_user_teams.rb
@@ -0,0 +1,11 @@
+class CreateUserTeams < ActiveRecord::Migration
+  def change
+    create_table :user_teams do |t|
+      t.string :name
+      t.string :path
+      t.integer :owner_id
+
+      t.timestamps
+    end
+  end
+end
diff --git a/db/migrate/20121220064104_create_user_team_project_relationships.rb b/db/migrate/20121220064104_create_user_team_project_relationships.rb
new file mode 100644
index 00000000000..8eb654c8728
--- /dev/null
+++ b/db/migrate/20121220064104_create_user_team_project_relationships.rb
@@ -0,0 +1,11 @@
+class CreateUserTeamProjectRelationships < ActiveRecord::Migration
+  def change
+    create_table :user_team_project_relationships do |t|
+      t.integer :project_id
+      t.integer :user_team_id
+      t.integer :greatest_access
+
+      t.timestamps
+    end
+  end
+end
diff --git a/db/migrate/20121220064453_create_user_team_user_relationships.rb b/db/migrate/20121220064453_create_user_team_user_relationships.rb
new file mode 100644
index 00000000000..7783b0ae432
--- /dev/null
+++ b/db/migrate/20121220064453_create_user_team_user_relationships.rb
@@ -0,0 +1,12 @@
+class CreateUserTeamUserRelationships < ActiveRecord::Migration
+  def change
+    create_table :user_team_user_relationships do |t|
+      t.integer :user_id
+      t.integer :user_team_id
+      t.boolean :group_admin
+      t.integer :permission
+
+      t.timestamps
+    end
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 4b3a2243609..88849872ab2 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -213,6 +213,31 @@ ActiveRecord::Schema.define(:version => 20130110172407) do
     t.string "name"
   end
 
+  create_table "user_team_project_relationships", :force => true do |t|
+    t.integer  "project_id"
+    t.integer  "user_team_id"
+    t.integer  "greatest_access"
+    t.datetime "created_at",      :null => false
+    t.datetime "updated_at",      :null => false
+  end
+
+  create_table "user_team_user_relationships", :force => true do |t|
+    t.integer  "user_id"
+    t.integer  "user_team_id"
+    t.boolean  "group_admin"
+    t.integer  "permission"
+    t.datetime "created_at",   :null => false
+    t.datetime "updated_at",   :null => false
+  end
+
+  create_table "user_teams", :force => true do |t|
+    t.string   "name"
+    t.string   "path"
+    t.integer  "owner_id"
+    t.datetime "created_at", :null => false
+    t.datetime "updated_at", :null => false
+  end
+
   create_table "users", :force => true do |t|
     t.string   "email",                  :default => "",    :null => false
     t.string   "encrypted_password",     :default => "",    :null => false
diff --git a/spec/models/user_team_project_relationship_spec.rb b/spec/models/user_team_project_relationship_spec.rb
new file mode 100644
index 00000000000..81051d59971
--- /dev/null
+++ b/spec/models/user_team_project_relationship_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe UserTeamProjectRelationship do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/models/user_team_spec.rb b/spec/models/user_team_spec.rb
new file mode 100644
index 00000000000..2d1b99db6f8
--- /dev/null
+++ b/spec/models/user_team_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe UserTeam do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/models/user_team_user_relationship_spec.rb b/spec/models/user_team_user_relationship_spec.rb
new file mode 100644
index 00000000000..309f1975e51
--- /dev/null
+++ b/spec/models/user_team_user_relationship_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe UserTeamUserRelationship do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
-- 
GitLab


From 82499a4cbfdd9605312322fea80b76f034230b1b Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Sat, 19 Jan 2013 21:11:11 +0400
Subject: [PATCH 023/197] Admin teams section added

---
 app/controllers/admin/teams_controller.rb | 104 ++++++++++
 app/views/admin/teams/edit.html.haml      |  28 +++
 app/views/admin/teams/index.html.haml     |  37 ++++
 app/views/admin/teams/new.html.haml       |  21 ++
 app/views/admin/teams/show.html.haml      | 104 ++++++++++
 app/views/layouts/admin.html.haml         |   2 +
 config/routes.rb                          |   8 +
 features/admin/teams.feature              |  73 +++++++
 features/steps/admin/admin_teams.rb       | 222 ++++++++++++++++++++++
 features/steps/shared/paths.rb            |   4 +
 10 files changed, 603 insertions(+)
 create mode 100644 app/controllers/admin/teams_controller.rb
 create mode 100644 app/views/admin/teams/edit.html.haml
 create mode 100644 app/views/admin/teams/index.html.haml
 create mode 100644 app/views/admin/teams/new.html.haml
 create mode 100644 app/views/admin/teams/show.html.haml
 create mode 100644 features/admin/teams.feature
 create mode 100644 features/steps/admin/admin_teams.rb

diff --git a/app/controllers/admin/teams_controller.rb b/app/controllers/admin/teams_controller.rb
new file mode 100644
index 00000000000..fd25d3fe219
--- /dev/null
+++ b/app/controllers/admin/teams_controller.rb
@@ -0,0 +1,104 @@
+class Admin::TeamsController < AdminController
+  before_filter :user_team,
+                only: [ :edit, :show, :update, :destroy,
+                        :delegate_projects, :relegate_project,
+                        :add_members, :remove_member ]
+
+  def index
+    @teams = UserTeam.order('name ASC')
+    @teams = @teams.search(params[:name]) if params[:name].present?
+    @teams = @teams.page(params[:page]).per(20)
+  end
+
+  def show
+    @projects = Project.scoped
+    @projects = @projects.without_team(@team) if @team.projects.any?
+    #@projects.reject!(&:empty_repo?)
+
+    @users = User.active
+    @users = @users.not_in_team(@team) if @team.members.any?
+    @users = UserDecorator.decorate @users
+  end
+
+  def new
+    @team = UserTeam.new
+  end
+
+  def edit
+  end
+
+  def create
+    @team = UserTeam.new(params[:user_team])
+    @team.path = @team.name.dup.parameterize if @team.name
+    @team.owner = current_user
+
+    if @team.save
+      redirect_to admin_team_path(@team), notice: 'UserTeam was successfully created.'
+    else
+      render action: "new"
+    end
+  end
+
+  def update
+    user_team_params = params[:user_team].dup
+    owner_id = user_team_params.delete(:owner_id)
+
+    if owner_id
+      @team.owner = User.find(owner_id)
+    end
+
+    if @team.update_attributes(user_team_params)
+      redirect_to admin_team_path(@team), notice: 'UserTeam was successfully updated.'
+    else
+      render action: "edit"
+    end
+  end
+
+  def destroy
+    @team.destroy
+
+    redirect_to admin_user_teams_path, notice: 'UserTeam was successfully deleted.'
+  end
+
+  def delegate_projects
+    unless params[:project_ids].blank?
+      project_ids = params[:project_ids]
+      access = params[:greatest_project_access]
+      @team.assign_to_projects(project_ids, access)
+    end
+
+    redirect_to admin_team_path(@team), notice: 'Projects was successfully added.'
+  end
+
+  def relegate_project
+    project = params[:project_id]
+    @team.resign_from_project(project)
+
+    redirect_to admin_team_path(@team), notice: 'Project was successfully removed.'
+  end
+
+  def add_members
+    unless params[:user_ids].blank?
+      user_ids = params[:user_ids]
+      access = params[:default_project_access]
+      is_admin = params[:group_admin]
+      @team.add_members(user_ids, access, is_admin)
+    end
+
+    redirect_to admin_team_path(@team), notice: 'Members was successfully added.'
+  end
+
+  def remove_member
+    member = params[:member_id]
+    @team.remove_member(member)
+
+    redirect_to admin_team_path(@team), notice: 'Member was successfully removed.'
+  end
+
+  private
+
+  def user_team
+    @team = UserTeam.find_by_path(params[:id])
+  end
+
+end
diff --git a/app/views/admin/teams/edit.html.haml b/app/views/admin/teams/edit.html.haml
new file mode 100644
index 00000000000..15ec267f45f
--- /dev/null
+++ b/app/views/admin/teams/edit.html.haml
@@ -0,0 +1,28 @@
+%h3.page_title Rename Team
+%hr
+= form_for [:admin, @team] do |f|
+  - if @team.errors.any?
+    .alert-message.block-message.error
+      %span= @team.errors.full_messages.first
+  .clearfix.team_name_holder
+    = f.label :name do
+      Team name is
+    .input
+      = f.text_field :name, placeholder: "Example Team", class: "xxlarge"
+
+
+
+  .clearfix.team_name_holder
+    = f.label :path do
+      %span.cred Team path is
+    .input
+      = f.text_field :path, placeholder: "example-team", class: "xxlarge danger"
+      %ul.cred
+        %li Changing team path can have unintended side effects.
+        %li Renaming team path will rename directory for all related projects
+        %li It will change web url for access team and team projects.
+        %li It will change the git path to repositories under this team.
+
+  .form-actions
+    = f.submit 'Rename team', class: "btn danger"
+    = link_to  'Cancel', admin_teams_path, class: "btn cancel-btn"
diff --git a/app/views/admin/teams/index.html.haml b/app/views/admin/teams/index.html.haml
new file mode 100644
index 00000000000..8b6928e906e
--- /dev/null
+++ b/app/views/admin/teams/index.html.haml
@@ -0,0 +1,37 @@
+%h3.page_title
+  Teams
+  %small
+    simple Teams description
+
+  = link_to 'New Team', new_admin_team_path, class: "btn small right"
+  %br
+
+= form_tag admin_teams_path, method: :get, class: 'form-inline' do
+  = text_field_tag :name, params[:name], class: "xlarge"
+  = submit_tag "Search", class: "btn submit primary"
+
+%table
+  %thead
+    %tr
+      %th
+        Name
+        %i.icon-sort-down
+      %th Path
+      %th Projects
+      %th Members
+      %th Owner
+      %th.cred Danger Zone!
+
+  - @teams.each do |team|
+    %tr
+      %td
+        %strong= link_to team.name, admin_team_path(team)
+      %td= team.path
+      %td= team.projects.count
+      %td= team.members.count
+      %td
+        = link_to team.owner.name, admin_user_path(team.owner_id)
+      %td.bgred
+        = link_to 'Rename', edit_admin_team_path(team), id: "edit_#{dom_id(team)}", class: "btn small"
+        = link_to 'Destroy', admin_team_path(team), confirm: "REMOVE #{team.name}? Are you sure?", method: :delete, class: "btn small danger"
+= paginate @teams, theme: "admin"
diff --git a/app/views/admin/teams/new.html.haml b/app/views/admin/teams/new.html.haml
new file mode 100644
index 00000000000..c936b66b32e
--- /dev/null
+++ b/app/views/admin/teams/new.html.haml
@@ -0,0 +1,21 @@
+%h3.page_title New Team
+%hr
+= form_for @team, url: admin_teams_path do |f|
+  - if @team.errors.any?
+    .alert-message.block-message.error
+      %span= @team.errors.full_messages.first
+  .clearfix
+    = f.label :name do
+      Team name is
+    .input
+      = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
+      &nbsp;
+      = f.submit 'Create team', class: "btn primary"
+  %hr
+  .padded
+    %ul
+      %li Team is kind of directory for several projects
+      %li All created teams are private
+      %li People within a team see only projects they have access to
+      %li All projects of team will be stored in team directory
+      %li You will be able to move existing projects into team
diff --git a/app/views/admin/teams/show.html.haml b/app/views/admin/teams/show.html.haml
new file mode 100644
index 00000000000..0f47717ae0e
--- /dev/null
+++ b/app/views/admin/teams/show.html.haml
@@ -0,0 +1,104 @@
+%h3.page_title
+  Team: #{@team.name}
+
+%br
+%table.zebra-striped
+  %thead
+    %tr
+      %th Team
+      %th
+  %tr
+    %td
+      %b
+        Name:
+    %td
+      = @team.name
+      &nbsp;
+      = link_to edit_admin_team_path(@team), class: "btn btn-small right" do
+        %i.icon-edit
+        Rename
+  %tr
+    %td
+      %b
+        Owner:
+    %td
+      = @team.owner.name
+      .right
+        = link_to "#", class: "btn btn-small change-owner-link" do
+          %i.icon-edit
+          Change owner
+
+  %tr.change-owner-holder.hide
+    %td.bgred
+      %b.cred
+        New Owner:
+    %td.bgred
+      = form_for @team, url: admin_team_path(@team) do |f|
+        = f.select :owner_id, User.all.map { |user| [user.name, user.id] }, {}, {class: 'chosen'}
+        %div
+          = f.submit 'Change Owner', class: "btn danger"
+          = link_to "Cancel", "#", class: "btn change-owner-cancel-link"
+
+%fieldset
+  %legend Members (#{@team.members.count})
+  = form_tag add_members_admin_team_path(@team), id: "team_members", class: "bulk_import", method: :post  do
+    %table#members_list
+      %thead
+        %tr
+          %th User name
+          %th Default project access
+          %th Team access
+          %th.cred Danger Zone!
+      - @team.members.each do |member|
+        %tr.member
+          %td
+            = link_to [:admin, member] do
+              = member.name
+              %small= "(#{member.email})"
+          %td= @team.human_default_projects_access(member)
+          %td= @team.admin?(member) ? "Admin" : "Member"
+          %td.bgred
+            = link_to 'Remove', remove_member_admin_team_path(@team, member_id: member.id), confirm: 'Remove project from team and move to global namespace. Are you sure?', method: :delete, class: "btn danger small"
+      %tr
+        %td= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name_with_email), multiple: true, data: {placeholder: 'Select users'}, class: 'chosen span5'
+        %td= select_tag :default_project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3" }
+        %td
+          %span= check_box_tag :group_admin
+          %span Admin?
+        %td= submit_tag 'Add', class: "btn primary", id: :add_members_to_team
+
+%fieldset
+  %legend Projects (#{@team.projects.count})
+  = form_tag delegate_projects_admin_team_path(@team), id: "assign_projects", class: "bulk_import", method: :post  do
+    %table#projects_list
+      %thead
+        %tr
+          %th Project name
+          %th Max access
+          %th.cred Danger Zone!
+      - @team.projects.each do |project|
+        %tr.project
+          %td
+            = link_to project.name_with_namespace, [:admin, project]
+          %td
+            %span= @team.human_max_project_access(project)
+          %td.bgred
+            = link_to 'Relegate', relegate_project_admin_team_path(@team, project_id: project.id), confirm: 'Remove project from team and move to global namespace. Are you sure?', method: :delete, class: "btn danger small"
+      %tr
+        %td= select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name_with_namespace), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5'
+        %td= select_tag :greatest_project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3" }
+        %td= submit_tag 'Add', class: "btn primary", id: :assign_projects_to_team
+
+:javascript
+  $(function(){
+    var modal = $('.change-owner-holder');
+    $('.change-owner-link').bind("click", function(){
+      $(this).hide();
+      modal.show();
+    });
+    $('.change-owner-cancel-link').bind("click", function(){
+      modal.hide();
+      $('.change-owner-link').show();
+    })
+  })
+
diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml
index a60e7febe76..28626b9c682 100644
--- a/app/views/layouts/admin.html.haml
+++ b/app/views/layouts/admin.html.haml
@@ -10,6 +10,8 @@
           = link_to "Stats", admin_root_path
         = nav_link(controller: :projects) do
           = link_to "Projects", admin_projects_path
+        = nav_link(controller: :teams) do
+          = link_to "Teams", admin_teams_path
         = nav_link(controller: :groups) do
           = link_to "Groups", admin_groups_path
         = nav_link(controller: :users) do
diff --git a/config/routes.rb b/config/routes.rb
index 6d7e615187d..d364f80551e 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -69,6 +69,14 @@ Gitlab::Application.routes.draw do
         put :team_update
       end
     end
+    resources :teams do #, constraints: { id: /[^\/]+/ } do end
+      member do
+        post :delegate_projects
+        delete :relegate_project
+        post :add_members
+        delete :remove_member
+      end
+    end
     resources :team_members, only: [:edit, :update, :destroy]
     resources :hooks, only: [:index, :create, :destroy] do
       get :test
diff --git a/features/admin/teams.feature b/features/admin/teams.feature
new file mode 100644
index 00000000000..e070a90ae02
--- /dev/null
+++ b/features/admin/teams.feature
@@ -0,0 +1,73 @@
+Feature: Admin Teams
+  Background:
+    Given I sign in as an admin
+    #And there are projects in system
+    #And system has users
+    #And I have own project
+    And Create gitlab user "John"
+
+  Scenario: Create a team
+    When I visit admin teams page
+    And I click new team link
+    And submit form with new team info
+    Then I should be redirected to team page
+    And I should see newly created team
+
+  Scenario: Add user to team
+    When I visit admin teams page
+    When I have clean "HardCoders" team
+    And I visit "HardCoders" team page
+    #Then I should see only me in members table
+    When I select user "John" from user list as "Developer"
+    And submit form with new team member info
+    Then I should see "John" in teams members list as "Developer"
+    When I visit "John" user admin page
+    Then I should see "HardCoders" team in teams table
+
+  Scenario: Assign team to existing project
+    When I visit admin teams page
+    When I have "HardCoders" team with "John" member with "Developer" role
+    When I have "Shop" project
+    And I visit "HardCoders" team page
+    Then I should see empty projects table
+    When I select project "Shop" with max access "Reporter"
+    And submit form with new team project info
+    Then I should see "Shop" project in projects list
+    When I visit "Shop" project admin page
+    Then I should see "John" user with role "Reporter" in team table
+
+  Scenario: Add user to team with ptojects
+    When I visit admin teams page
+    When I have "HardCoders" team with "John" member with "Developer" role
+    And "HardCoders" team assigned to "Shop" project with "Developer" max role access
+    When I have gitlab user "Jimm"
+    And I visit "HardCoders" team page
+    Then I should see members table without "Jimm" member
+    When I select user "Jimm" ub team members list as "Master"
+    And submit form with new team member info
+    Then I should see "Jimm" in teams members list as "Master"
+
+  Scenario: Remove member from team
+    Given I have users team "HardCoders"
+    And gitlab user "John" is a member "HardCoders" team
+    And gitlab user "Jimm" is a member "HardCoders" team
+    And "HardCoders" team is assigned to "Shop" project
+    When I visit admin teams page
+    When I visit "HardCoders" team admin page
+    Then I shoould see "John" in members list
+    And I should see "Jimm" in members list
+    And I should see "Shop" in projects list
+    When I click on remove "Jimm" user link
+    Then I should be redirected to "HardCoders" team admin page
+    And I should not to see "Jimm" user in members list
+
+  Scenario: Remove project from team
+    Given I have users team "HardCoders"
+    And gitlab user "John" is a member "HardCoders" team
+    And gitlab user "Jimm" is a member "HardCoders" team
+    And "HardCoders" team is assigned to "Shop" project
+    When I visit admin teams page
+    When I visit "HardCoders" team admin page
+    Then I should see "Shop" project in projects list
+    When I click on "Relegate" link on "Shop" project
+    Then I should see projects liston team page without "Shop" project
diff --git a/features/steps/admin/admin_teams.rb b/features/steps/admin/admin_teams.rb
new file mode 100644
index 00000000000..7bb1dacabcb
--- /dev/null
+++ b/features/steps/admin/admin_teams.rb
@@ -0,0 +1,222 @@
+class AdminTeams < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedPaths
+  include SharedActiveTab
+  include SharedAdmin
+
+  And 'I have own project' do
+    create :project
+  end
+
+  And 'Create gitlab user "John"' do
+    @user = create(:user, :name => "John")
+  end
+
+  And 'I click new team link' do
+    click_link "New Team"
+  end
+
+  And 'submit form with new team info' do
+    fill_in 'user_team_name', with: 'gitlab'
+    click_button 'Create team'
+  end
+
+  Then 'I should be redirected to team page' do
+    current_path.should == admin_team_path(UserTeam.last)
+  end
+
+  And 'I should see newly created team' do
+    page.should have_content "Team: gitlab"
+  end
+
+  When 'I visit admin teams page' do
+    visit admin_teams_path
+  end
+
+  When 'I have clean "HardCoders" team' do
+    @team = create :user_team, name: "HardCoders", owner: current_user
+  end
+
+  And 'I visit "HardCoders" team page' do
+    visit admin_team_path(UserTeam.find_by_name("HardCoders"))
+  end
+
+  Then 'I should see only me in members table' do
+    members_list = find("#members_list .member")
+    members_list.should have_content(current_user.name)
+    members_list.should have_content(current_user.email)
+  end
+
+  When 'I select user "John" from user list as "Developer"' do
+    @user ||= User.find_by_name("John")
+    within "#team_members" do
+      select user.name, :from => "user_ids"
+      select "Developer", :from => "default_project_access"
+    end
+  end
+
+  And 'submit form with new team member info' do
+    click_button 'add_members_to_team'
+  end
+
+  Then 'I should see "John" in teams members list as "Developer"' do
+    @user ||= User.find_by_name("John")
+    find_in_list("#members_list .member", user).must_equal true
+  end
+
+  When 'I visit "John" user admin page' do
+    pending 'step not implemented'
+  end
+
+  Then 'I should see "HardCoders" team in teams table' do
+    pending 'step not implemented'
+  end
+
+  When 'I have "HardCoders" team with "John" member with "Developer" role' do
+    @team = create :user_team, name: "HardCoders", owner: current_user
+    @user ||= User.find_by_name("John")
+    @team.add_member(@user, UserTeam.access_roles["Developer"], group_admin: false)
+  end
+
+  When 'I have "Shop" project' do
+    @project = create :project, name: "Shop"
+  end
+
+  Then 'I should see empty projects table' do
+    projects_list = find("#projects_list")
+    projects_list.has_content?("Relegate").must_equal false
+  end
+
+  When 'I select project "Shop" with max access "Reporter"' do
+    @project ||= Project.find_by_name("Shop")
+    within "#assign_projects" do
+      select @project.name, :from => "project_ids"
+      select "Reporter", :from => "greatest_project_access"
+    end
+
+  end
+
+  And 'submit form with new team project info' do
+    click_button 'assign_projects_to_team'
+  end
+
+  Then 'I should see "Shop" project in projects list' do
+    project = Project.find_by_name("Shop")
+    find_in_list("#projects_list .project", project).must_equal true
+  end
+
+  When 'I visit "Shop" project admin page' do
+    project = Project.find_by_name("Shop")
+    visit admin_project_path(project)
+  end
+
+  And '"HardCoders" team assigned to "Shop" project with "Developer" max role access' do
+    @team = UserTeam.find_by_name("HardCoders")
+    @project = create :project, name: "Shop"
+    @team.assign_to_project(@project, UserTeam.access_roles["Developer"])
+  end
+
+  When 'I have gitlab user "Jimm"' do
+    create :user, name: "Jimm"
+  end
+
+  Then 'I should see members table without "Jimm" member' do
+    user = User.find_by_name("Jimm")
+    find_in_list("#members_list .member", user).must_equal false
+  end
+
+  When 'I select user "Jimm" ub team members list as "Master"' do
+    user = User.find_by_name("Jimm")
+    within "#team_members" do
+      select user.name, :from => "user_ids"
+      select "Developer", :from => "default_project_access"
+    end
+  end
+
+  Then 'I should see "Jimm" in teams members list as "Master"' do
+    user = User.find_by_name("Jimm")
+    find_in_list("#members_list .member", user).must_equal true
+  end
+
+  Given 'I have users team "HardCoders"' do
+    @team = create :user_team, name: "HardCoders"
+  end
+
+  And 'gitlab user "John" is a member "HardCoders" team' do
+    @team = UserTeam.find_by_name("HardCoders")
+    @user = User.find_by_name("John")
+    @user = create :user, name: "John" unless @user
+    @team.add_member(@user, UserTeam.access_roles["Master"], group_admin: false)
+  end
+
+  And 'gitlab user "Jimm" is a member "HardCoders" team' do
+    @team = UserTeam.find_by_name("HardCoders")
+    @user = User.find_by_name("Jimm")
+    @user = create :user, name: "Jimm" unless @user
+    @team.add_member(@user, UserTeam.access_roles["Master"], group_admin: false)
+  end
+
+  And '"HardCoders" team is assigned to "Shop" project' do
+    @team = UserTeam.find_by_name("HardCoders")
+    @project = create :project, name: "Shop"
+    @team.assign_to_project(@project, UserTeam.access_roles["Developer"])
+  end
+
+  When 'I visit "HardCoders" team admin page' do
+    visit admin_team_path(UserTeam.find_by_name("HardCoders"))
+  end
+
+  Then 'I shoould see "John" in members list' do
+    user = User.find_by_name("John")
+    find_in_list("#members_list .member", user).must_equal true
+  end
+
+  And 'I should see "Jimm" in members list' do
+    user = User.find_by_name("Jimm")
+    find_in_list("#members_list .member", user).must_equal true
+  end
+
+  And 'I should see "Shop" in projects list' do
+
+  end
+
+  When 'I click on remove "Jimm" user link' do
+
+  end
+
+  Then 'I should be redirected to "HardCoders" team admin page' do
+    current_path.should admin_team_peth(UserTeam.find_by_name("HardCoders"))
+  end
+
+  And 'I should not to see "Jimm" user in members list' do
+
+  end
+
+  When 'I click on "Relegate" link on "Shop" project' do
+
+  end
+
+  Then 'I should see projects liston team page without "Shop" project' do
+
+  end
+
+  Then 'I should see "John" user with role "Reporter" in team table' do
+    user = User.find_by_name("John")
+    find_in_list(".team_members", user).must_equal true
+  end
+
+  protected
+
+  def current_team
+    @team ||= Team.first
+  end
+
+  def find_in_list(selector, item)
+    members_list = all(selector)
+    entered = false
+    members_list.each do |member_item|
+      entered = true if member_item.has_content?(item.name)
+    end
+    entered
+  end
+end
diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb
index c046c4e63e6..e397ff87f41 100644
--- a/features/steps/shared/paths.rb
+++ b/features/steps/shared/paths.rb
@@ -105,6 +105,10 @@ module SharedPaths
     visit admin_groups_path
   end
 
+  When 'I visit admin teams page' do
+    visit admin_teams_path
+  end
+
   # ----------------------------------------
   # Generic Project
   # ----------------------------------------
-- 
GitLab


From 695becc4cb017d76329efb55aae7ddb9a208895b Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Sat, 19 Jan 2013 21:32:09 +0400
Subject: [PATCH 024/197] Add teams into Public sections

---
 app/controllers/teams_controller.rb      | 113 ++++++++++
 app/views/teams/_filter.html.haml        |  33 +++
 app/views/teams/_projects.html.haml      |  22 ++
 app/views/teams/_team_head.html.haml     |  19 ++
 app/views/teams/edit.html.haml           |  32 +++
 app/views/teams/index.html.haml          |  37 ++++
 app/views/teams/issues.html.haml         |  25 +++
 app/views/teams/merge_requests.html.haml |  24 +++
 app/views/teams/new.html.haml            |  21 ++
 app/views/teams/search.html.haml         |  11 +
 app/views/teams/show.html.haml           |  30 +++
 config/routes.rb                         |  14 ++
 features/steps/userteams/userteams.rb    | 250 +++++++++++++++++++++++
 features/teams/team.feature              |  75 +++++++
 14 files changed, 706 insertions(+)
 create mode 100644 app/controllers/teams_controller.rb
 create mode 100644 app/views/teams/_filter.html.haml
 create mode 100644 app/views/teams/_projects.html.haml
 create mode 100644 app/views/teams/_team_head.html.haml
 create mode 100644 app/views/teams/edit.html.haml
 create mode 100644 app/views/teams/index.html.haml
 create mode 100644 app/views/teams/issues.html.haml
 create mode 100644 app/views/teams/merge_requests.html.haml
 create mode 100644 app/views/teams/new.html.haml
 create mode 100644 app/views/teams/search.html.haml
 create mode 100644 app/views/teams/show.html.haml
 create mode 100644 features/steps/userteams/userteams.rb
 create mode 100644 features/teams/team.feature

diff --git a/app/controllers/teams_controller.rb b/app/controllers/teams_controller.rb
new file mode 100644
index 00000000000..4e3703d72d4
--- /dev/null
+++ b/app/controllers/teams_controller.rb
@@ -0,0 +1,113 @@
+class TeamsController < ApplicationController
+  respond_to :html
+  layout 'user_team',       only: [:show, :edit, :update, :destroy, :issues, :merge_requests, :search]
+
+  before_filter :user_team, only: [:show, :edit, :update, :destroy, :issues, :merge_requests, :search]
+  before_filter :projects,  only: [:show, :edit, :update, :destroy, :issues, :merge_requests, :search]
+
+  # Authorize
+  before_filter :authorize_manage_user_team!, only: [:edit, :update]
+  before_filter :authorize_admin_user_team!, only: [:destroy]
+
+  def index
+    @teams = UserTeam.all
+  end
+
+  def show
+    @events = Event.in_projects(project_ids).limit(20).offset(params[:offset] || 0)
+
+    respond_to do |format|
+      format.html
+      format.js
+      format.atom { render layout: false }
+    end
+  end
+
+  def edit
+
+  end
+
+  def update
+    if user_team.update_attributes(params[:user_team])
+      redirect_to team_path(user_team)
+    else
+      render action: :edit
+    end
+  end
+
+  def destroy
+    user_team.destroy
+    redirect_to teams_path
+  end
+
+  def new
+    @team = UserTeam.new
+  end
+
+  def create
+    @team = UserTeam.new(params[:user_team])
+    @team.owner = current_user unless params[:owner]
+    @team.path = @team.name.dup.parameterize if @team.name
+
+    if @team.save
+      redirect_to team_path(@team)
+    else
+      render action: :new
+    end
+  end
+
+  # Get authored or assigned open merge requests
+  def merge_requests
+    @merge_requests = MergeRequest.of_user_team(@user_team)
+    @merge_requests = FilterContext.new(@merge_requests, params).execute
+    @merge_requests = @merge_requests.recent.page(params[:page]).per(20)
+  end
+
+  # Get only assigned issues
+  def issues
+    @issues = Issue.of_user_team(@user_team)
+    @issues = FilterContext.new(@issues, params).execute
+    @issues = @issues.recent.page(params[:page]).per(20)
+    @issues = @issues.includes(:author, :project)
+
+    respond_to do |format|
+      format.html
+      format.atom { render layout: false }
+    end
+  end
+
+  def search
+    result = SearchContext.new(project_ids, params).execute
+
+    @projects       = result[:projects]
+    @merge_requests = result[:merge_requests]
+    @issues         = result[:issues]
+    @wiki_pages     = result[:wiki_pages]
+  end
+
+  protected
+
+  def user_team
+    @user_team ||= UserTeam.find_by_path(params[:id])
+  end
+
+  def projects
+    @projects ||= user_team.projects.sorted_by_activity
+  end
+
+  def project_ids
+    projects.map(&:id)
+  end
+
+  def authorize_manage_user_team!
+    unless user_team.present? or can?(current_user, :manage_user_team, user_team)
+      return render_404
+    end
+  end
+
+  def authorize_admin_user_team!
+    unless user_team.owner == current_user || current_user.admin?
+      return render_404
+    end
+  end
+end
diff --git a/app/views/teams/_filter.html.haml b/app/views/teams/_filter.html.haml
new file mode 100644
index 00000000000..8e358319651
--- /dev/null
+++ b/app/views/teams/_filter.html.haml
@@ -0,0 +1,33 @@
+= form_tag team_filter_path(entity), method: 'get' do
+  %fieldset.dashboard-search-filter
+    = search_field_tag "search", params[:search], { placeholder: 'Search', class: 'search-text-input' }
+    = button_tag type: 'submit', class: 'btn' do
+      %i.icon-search
+
+  %fieldset
+    %legend Status:
+    %ul.nav.nav-pills.nav-stacked
+      %li{class: ("active" if !params[:status])}
+        = link_to team_filter_path(entity, status: nil) do
+          Open
+      %li{class: ("active" if params[:status] == 'closed')}
+        = link_to team_filter_path(entity, status: 'closed') do
+          Closed
+      %li{class: ("active" if params[:status] == 'all')}
+        = link_to team_filter_path(entity, status: 'all') do
+          All
+
+  %fieldset
+    %legend Projects:
+    %ul.nav.nav-pills.nav-stacked
+      - @projects.each do |project|
+        - unless entities_per_project(project, entity).zero?
+          %li{class: ("active" if params[:project_id] == project.id.to_s)}
+            = link_to team_filter_path(entity, project_id: project.id) do
+              = project.name_with_namespace
+              %small.right= entities_per_project(project, entity)
+
+  %fieldset
+    %hr
+    = link_to "Reset", team_filter_path(entity), class: 'btn right'
+
diff --git a/app/views/teams/_projects.html.haml b/app/views/teams/_projects.html.haml
new file mode 100644
index 00000000000..040d1ae94aa
--- /dev/null
+++ b/app/views/teams/_projects.html.haml
@@ -0,0 +1,22 @@
+.projects_box
+  %h5.title
+    Projects
+    %small
+      (#{projects.count})
+    - if can? current_user, :manage_group, @group
+      %span.right
+        = link_to new_project_path(namespace_id: @group.id), class: "btn very_small info" do
+          %i.icon-plus
+          New Project
+  %ul.well-list
+    - if projects.blank?
+      %p.nothing_here_message This groups has no projects yet
+    - projects.each do |project|
+      %li
+        = link_to project_path(project), class: dom_class(project) do
+          %strong.well-title= truncate(project.name, length: 25)
+          %span.arrow
+            &rarr;
+          %span.last_activity
+            %strong Last activity:
+            %span= project_last_activity(project)
diff --git a/app/views/teams/_team_head.html.haml b/app/views/teams/_team_head.html.haml
new file mode 100644
index 00000000000..53796623de1
--- /dev/null
+++ b/app/views/teams/_team_head.html.haml
@@ -0,0 +1,19 @@
+%ul.nav.nav-tabs
+  = nav_link(path: 'teams#show') do
+    = link_to team_path(@user_team), class: "activities-tab tab" do
+      %i.icon-home
+      Show
+  = nav_link(controller: [:members]) do
+    = link_to team_members_path(@user_team), class: "team-tab tab" do
+      %i.icon-user
+      Members
+  = nav_link(controller: [:projects]) do
+    = link_to team_projects_path(@user_team), class: "team-tab tab" do
+      %i.icon-briefcase
+      Projects
+
+  - if can? current_user, :manage_user_team, @user_team
+    = nav_link(path: 'teams#edit', html_options: {class: 'right'}) do
+      = link_to edit_team_path(@user_team), class: "stat-tab tab " do
+        %i.icon-edit
+        Edit
diff --git a/app/views/teams/edit.html.haml b/app/views/teams/edit.html.haml
new file mode 100644
index 00000000000..4c239e8fa41
--- /dev/null
+++ b/app/views/teams/edit.html.haml
@@ -0,0 +1,32 @@
+= render "team_head"
+
+%h3.page_title= "Edit Team #{@user_team.name}"
+%hr
+= form_for @user_team, url: teams_path do |f|
+  - if @user_team.errors.any?
+    .alert-message.block-message.error
+      %span= @user_team.errors.full_messages.first
+  .clearfix
+    = f.label :name do
+      Team name is
+    .input
+      = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
+
+  .clearfix
+    = f.label :path do
+      Team path is
+    .input
+      = f.text_field :path, placeholder: "opensource", class: "xxlarge left"
+  .clearfix
+    .input.span3.center
+      = f.submit 'Save team changes', class: "btn primary"
+    .input.span3.center
+      = link_to 'Delete team', team_path(@user_team), method: :delete, confirm: "You are shure?", class: "btn danger"
+  %hr
+  .padded
+    %ul
+      %li Team is kind of directory for several projects
+      %li All created teams are private
+      %li People within a team see only projects they have access to
+      %li All projects of team will be stored in team directory
+      %li You will be able to move existing projects into team
diff --git a/app/views/teams/index.html.haml b/app/views/teams/index.html.haml
new file mode 100644
index 00000000000..9ac54594521
--- /dev/null
+++ b/app/views/teams/index.html.haml
@@ -0,0 +1,37 @@
+%h3.page_title
+  Teams
+  %small
+    list of all teams
+
+  = link_to 'New Team', new_team_path, class: "btn small right"
+  %br
+
+= form_tag search_teams_path, method: :get, class: 'form-inline' do
+  = text_field_tag :name, params[:name], class: "xlarge"
+  = submit_tag "Search", class: "btn submit primary"
+
+%table.teams_list
+  %thead
+    %tr
+      %th
+        Name
+        %i.icon-sort-down
+      %th Path
+      %th Projects
+      %th Members
+      %th Owner
+      %th
+
+  - @teams.each do |team|
+    %tr
+      %td
+        %strong= link_to team.name, team_path(team)
+      %td= team.path
+      %td= link_to team.projects.count, team_projects_path(team)
+      %td= link_to team.members.count, team_members_path(team)
+      %td= link_to team.owner.name, team_member_path(team, team.owner)
+      %td
+        - if current_user.can?(:manage_user_team, team)
+          - if team.owner == current_user
+            = link_to "Destroy", team_path(team), method: :delete, confirm: "You are shure?", class: "danger btn small right"
+          = link_to "Edit", edit_team_path(team), class: "btn small right"
diff --git a/app/views/teams/issues.html.haml b/app/views/teams/issues.html.haml
new file mode 100644
index 00000000000..3c17e85a115
--- /dev/null
+++ b/app/views/teams/issues.html.haml
@@ -0,0 +1,25 @@
+= render "team_head"
+
+%h3.page_title
+  Issues
+  %small (in Team projects assigned to Team members)
+  %small.right #{@issues.total_count} issues
+
+%hr
+.row
+  .span3
+    = render 'filter', entity: 'issue'
+  .span9
+    - if @issues.any?
+      - @issues.group_by(&:project).each do |group|
+        %div.ui-box
+          - @project = group[0]
+          %h5.title
+            = link_to_project @project
+          %ul.well-list.issues_table
+            - group[1].each do |issue|
+              = render(partial: 'issues/show', locals: {issue: issue})
+      %hr
+      = paginate @issues, theme: "gitlab"
+    - else
+      %p.nothing_here_message Nothing to show here
diff --git a/app/views/teams/merge_requests.html.haml b/app/views/teams/merge_requests.html.haml
new file mode 100644
index 00000000000..c9af529e113
--- /dev/null
+++ b/app/views/teams/merge_requests.html.haml
@@ -0,0 +1,24 @@
+%h3.page_title
+  Merge Requests
+  %small (authored by or assigned to Team members)
+  %small.right #{@merge_requests.total_count} merge requests
+
+%hr
+.row
+  .span3
+    = render 'filter', entity: 'merge_request'
+  .span9
+    - if @merge_requests.any?
+      - @merge_requests.group_by(&:project).each do |group|
+        .ui-box
+          - @project = group[0]
+          %h5.title
+            = link_to_project @project
+          %ul.well-list
+            - group[1].each do |merge_request|
+              = render(partial: 'merge_requests/merge_request', locals: {merge_request: merge_request})
+      %hr
+      = paginate @merge_requests, theme: "gitlab"
+
+    - else
+      %h3.nothing_here_message Nothing to show here
diff --git a/app/views/teams/new.html.haml b/app/views/teams/new.html.haml
new file mode 100644
index 00000000000..d8312e0e913
--- /dev/null
+++ b/app/views/teams/new.html.haml
@@ -0,0 +1,21 @@
+%h3.page_title New Team
+%hr
+= form_for @team, url: teams_path do |f|
+  - if @team.errors.any?
+    .alert-message.block-message.error
+      %span= @team.errors.full_messages.first
+  .clearfix
+    = f.label :name do
+      Team name is
+    .input
+      = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
+      &nbsp;
+      = f.submit 'Create team', class: "btn primary"
+  %hr
+  .padded
+    %ul
+      %li Team is kind of directory for several projects
+      %li All created teams are private
+      %li People within a team see only projects they have access to
+      %li All projects of team will be stored in team directory
+      %li You will be able to move existing projects into team
diff --git a/app/views/teams/search.html.haml b/app/views/teams/search.html.haml
new file mode 100644
index 00000000000..601f2d57c8b
--- /dev/null
+++ b/app/views/teams/search.html.haml
@@ -0,0 +1,11 @@
+= render "team_head"
+
+= form_tag search_team_path(@user_team), method: :get, class: 'form-inline' do |f|
+  .padded
+    = label_tag :search do
+      %strong Looking for
+    .input
+      = search_field_tag :search, params[:search], placeholder: "issue 143", class: "input-xxlarge search-text-input", id: "dashboard_search"
+      = submit_tag 'Search', class: "btn primary wide"
+- if params[:search].present?
+  = render 'search/result'
diff --git a/app/views/teams/show.html.haml b/app/views/teams/show.html.haml
new file mode 100644
index 00000000000..9acbf3e1ecf
--- /dev/null
+++ b/app/views/teams/show.html.haml
@@ -0,0 +1,30 @@
+= render "team_head"
+
+.projects
+  .activities.span8
+    = link_to dashboard_path, class: 'btn very_small' do
+      &larr; To dashboard
+    &nbsp;
+    %span.cgray Events and projects are filtered in scope of team
+    %hr
+    - if @events.any?
+      .content_list
+    - else
+      %p.nothing_here_message Projects activity will be displayed here
+    .loading.hide
+  .side.span4
+    = render "projects", projects: @projects
+    %div
+      %span.rss-icon
+        = link_to dashboard_path(:atom, { private_token: current_user.private_token }) do
+          = image_tag "rss_ui.png", title: "feed"
+          %strong News Feed
+
+    %hr
+    .gitlab-promo
+      = link_to "Homepage", "http://gitlabhq.com"
+      = link_to "Blog", "http://blog.gitlabhq.com"
+      = link_to "@gitlabhq", "https://twitter.com/gitlabhq"
+
+:javascript
+  $(function(){ Pager.init(20, true); });
diff --git a/config/routes.rb b/config/routes.rb
index d364f80551e..4a6b0d0b74d 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -130,6 +130,20 @@ Gitlab::Application.routes.draw do
     end
   end
 
+  resources :teams do
+    member do
+      get :issues
+      get :merge_requests
+      get :search
+      post :delegate_projects
+      delete :relegate_project
+      put :update_access
+    end
+    collection do
+      get :search
+    end
+  end
+
   resources :projects, constraints: { id: /[^\/]+/ }, only: [:new, :create]
 
   devise_for :users, controllers: { omniauth_callbacks: :omniauth_callbacks, registrations: :registrations }
diff --git a/features/steps/userteams/userteams.rb b/features/steps/userteams/userteams.rb
new file mode 100644
index 00000000000..59ec3d2de6e
--- /dev/null
+++ b/features/steps/userteams/userteams.rb
@@ -0,0 +1,250 @@
+class Userteams < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedPaths
+  include SharedProject
+
+    When 'I do not have teams with me' do
+      UserTeam.with_member(current_user).destroy_all
+    end
+
+    Then 'I should see dashboard page without teams info block' do
+      page.has_no_css?(".teams_box").must_equal true
+    end
+
+    When 'I have teams with my membership' do
+      team = create :user_team
+      team.add_member(current_user, UserTeam.access_roles["Master"], true)
+    end
+
+    Then 'I should see dashboard page with teams information block' do
+      page.should have_css(".teams_box")
+    end
+
+    When 'exist user teams' do
+      team = create :user_team
+      team.add_member(current_user, UserTeam.access_roles["Master"], true)
+    end
+
+    And 'I click on "All teams" link' do
+      click_link("All Teams")
+    end
+
+    Then 'I should see "All teams" page' do
+      current_path.should == teams_path
+    end
+
+    And 'I should see exist teams in teams list' do
+      team = UserTeam.last
+      find_in_list(".teams_list tr", team).must_equal true
+    end
+
+    When 'I click to "New team" link' do
+      click_link("New Team")
+    end
+
+    And 'I submit form with new team info' do
+      fill_in 'name', with: 'gitlab'
+      click_button 'Create team'
+    end
+
+    Then 'I should be redirected to new team page' do
+      team = UserTeam.last
+      current_path.should == team_path(team)
+    end
+
+    When 'I have teams with projects and members' do
+      team = create :user_team
+      @project = create :project
+      team.add_member(current_user, UserTeam.access_roles["Master"], true)
+      team.assign_to_project(@project, UserTeam.access_roles["Master"])
+      @event = create(:closed_issue_event, project: @project)
+    end
+
+    When 'I visit team page' do
+      visit team_path(UserTeam.last)
+    end
+
+    Then 'I should see projects list' do
+      page.should have_css(".projects_box")
+      projects_box = find(".projects_box")
+      projects_box.should have_content(@project.name)
+    end
+
+    And 'project from team has issues assigned to me' do
+      team = UserTeam.last
+      team.projects.each do |project|
+        project.issues << create(:issue, assignee: current_user)
+      end
+    end
+
+    When 'I visit team issues page' do
+      team = UserTeam.last
+      visit issues_team_path(team)
+    end
+
+    Then 'I should see issues from this team assigned to me' do
+      team = UserTeam.last
+      team.projects.each do |project|
+        project.issues.assigned(current_user).each do |issue|
+          page.should have_content issue.title
+        end
+      end
+    end
+
+    Given 'I have team with projects and members' do
+      team = create :user_team
+      project = create :project
+      user = create :user
+      team.add_member(current_user, UserTeam.access_roles["Master"], true)
+      team.add_member(user, UserTeam.access_roles["Developer"], false)
+      team.assign_to_project(project, UserTeam.access_roles["Master"])
+    end
+
+    Given 'project from team has issues assigned to teams members' do
+      team = UserTeam.last
+      team.projects.each do |project|
+        team.members.each do |member|
+          project.issues << create(:issue, assignee: member)
+        end
+      end
+    end
+
+    Then 'I should see issues from this team assigned to teams members' do
+      team = UserTeam.last
+      team.projects.each do |project|
+        team.members.each do |member|
+          project.issues.assigned(member).each do |issue|
+            page.should have_content issue.title
+          end
+        end
+      end
+    end
+
+    Given 'project from team has merge requests assigned to me' do
+      team = UserTeam.last
+      team.projects.each do |project|
+        team.members.each do |member|
+          3.times { project.merge_requests << create(:merge_request, assignee: member) }
+        end
+      end
+    end
+
+    When 'I visit team merge requests page' do
+      team = UserTeam.last
+      visit merge_requests_team_path(team)
+    end
+
+    Then 'I should see merge requests from this team assigned to me' do
+      team = UserTeam.last
+      team.projects.each do |project|
+        team.members.each do |member|
+          project.issues.assigned(member).each do |merge_request|
+            page.should have_content merge_request.title
+          end
+        end
+      end
+    end
+
+    Given 'project from team has merge requests assigned to team members' do
+      team = UserTeam.last
+      team.projects.each do |project|
+        team.members.each do |member|
+          3.times { project.merge_requests << create(:merge_request, assignee: member) }
+        end
+      end
+    end
+
+    Then 'I should see merge requests from this team assigned to me' do
+      team = UserTeam.last
+      team.projects.each do |project|
+        team.members.each do |member|
+          project.issues.assigned(member).each do |merge_request|
+            page.should have_content merge_request.title
+          end
+        end
+      end
+    end
+
+    Given 'I have new user "John"' do
+      create :user, name: "John"
+    end
+
+    When 'I visit team people page' do
+      team = UserTeam.last
+      visit team_members_path(team)
+    end
+
+    And 'I select user "John" from list with role "Reporter"' do
+      pending 'step not implemented'
+    end
+
+    Then 'I should see user "John" in team list' do
+      user = User.find_by_name("John")
+      team_members_list = find(".team-table")
+      team_members_list.should have_content user.name
+    end
+
+    And 'I have my own project without teams' do
+      project = create :project, creator: current_user
+    end
+
+    And 'I visit my team page' do
+      team = UserTeam.last
+      visit team_path(team)
+    end
+
+    When 'I click on link "Projects"' do
+      click_link "Projects"
+    end
+
+    Then 'I should see form with my own project in avaliable projects list' do
+      project = current_user.projects.first
+      projects_select = find("#project_ids")
+      projects_select.should have_content(project.name)
+    end
+
+    When 'I submit form with selected project and max access' do
+      project = current_user.projects.first
+      within "#team_projects" do
+        select project.name, :from => "project_ids"
+        select "Reporter", :from => "greatest_project_access"
+      end
+      click_button "Add"
+    end
+
+    Then 'I should see my own project in team projects list' do
+      project = current_user.projects.first
+      projects = all("table .project")
+      projects.each do |project_row|
+        project_row.should have_content(project.name)
+      end
+    end
+
+    When 'I click link "New Team Member"' do
+      click_link "New Team Member"
+    end
+
+  protected
+
+  def current_team
+    @user_team ||= Team.first
+  end
+
+  def project
+    current_team.projects.first
+  end
+
+  def assigned_to_user key, user
+    project.send(key).where(assignee_id: user)
+  end
+
+  def find_in_list(selector, item)
+    members_list = all(selector)
+    entered = false
+    members_list.each do |member_item|
+      entered = true if member_item.has_content?(item.name)
+    end
+    entered
+  end
+
+end
diff --git a/features/teams/team.feature b/features/teams/team.feature
new file mode 100644
index 00000000000..d914313efb6
--- /dev/null
+++ b/features/teams/team.feature
@@ -0,0 +1,75 @@
+Feature: UserTeams
+  Background:
+    Given I sign in as a user
+    And I own project "Shop"
+    And project "Shop" has push event
+
+  Scenario: No teams, no dashboard info block
+    When I do not have teams with me
+    And I visit dashboard page
+    Then I should see dashboard page without teams info block
+
+  Scenario: I should see teams info block
+    When I have teams with my membership
+    And I visit dashboard page
+    Then I should see dashboard page with teams information block
+
+  Scenario: I should see all teams list
+    When exist user teams
+    And I visit dashboard page
+    And I click on "All teams" link
+    Then I should see "All teams" page
+    And I should see exist teams in teams list
+
+  Scenario: I should can create new team
+    When I have teams with my membership
+    And I visit dashboard page
+    When I click to "New team" link
+    And I submit form with new team info
+    Then I should be redirected to new team page
+
+  Scenario: I should see team dashboard list
+    When I have teams with projects and members
+    When I visit team page
+    Then I should see projects list
+
+  Scenario: I should see team issues list
+    Given I have team with projects and members
+    And project from team has issues assigned to me
+    When I visit team issues page
+    Then I should see issues from this team assigned to me
+
+  Scenario: I should see teams members issues list
+    Given I have team with projects and members
+    Given project from team has issues assigned to teams members
+    When I visit team issues page
+    Then I should see issues from this team assigned to teams members
+
+  Scenario: I should see team merge requests list
+    Given I have team with projects and members
+    Given project from team has merge requests assigned to me
+    When I visit team merge requests page
+    Then I should see merge requests from this team assigned to me
+
+  Scenario: I should see teams members merge requests list
+    Given I have team with projects and members
+    Given project from team has merge requests assigned to team members
+    When I visit team merge requests page
+    Then I should see merge requests from this team assigned to me
+
+  Scenario: I should add user to projects in Team
+    Given I have team with projects and members
+    Given I have new user "John"
+    When I visit team people page
+    When I click link "New Team Member"
+    And I select user "John" from list with role "Reporter"
+    Then I should see user "John" in team list
+
+  Scenario: I should assign my team to my own project
+    Given I have team with projects and members
+    And I have my own project without teams
+    And I visit my team page
+    When I click on link "Projects"
+    Then I should see form with my own project in avaliable projects list
+    When I submit form with selected project and max access
+    Then I should see my own project in team projects list
-- 
GitLab


From 7d3efec7d190948423d7e40a3f87e2d62b4ea808 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Sat, 19 Jan 2013 21:32:55 +0400
Subject: [PATCH 025/197] Add ability to teams

---
 app/models/ability.rb | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/app/models/ability.rb b/app/models/ability.rb
index 9d33501fdbc..63d720164a1 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -8,6 +8,7 @@ class Ability
       when "Snippet" then snippet_abilities(object, subject)
       when "MergeRequest" then merge_request_abilities(object, subject)
       when "Group", "Namespace" then group_abilities(object, subject)
+      when "UserTeam" then user_team_abilities(object, subject)
       else []
       end
     end
@@ -110,6 +111,22 @@ class Ability
       rules.flatten
     end
 
+    def user_team_abilities user, team
+      rules = []
+
+      # Only group owner and administrators can manage group
+      if team.owner == user || team.admin?(user) || user.admin?
+        rules << [ :manage_user_team ]
+      end
+
+      if team.owner == user || user.admin?
+        rules << [ :admin_user_team ]
+      end
+
+      rules.flatten
+    end
+
+
     [:issue, :note, :snippet, :merge_request].each do |name|
       define_method "#{name}_abilities" do |user, subject|
         if subject.author == user
-- 
GitLab


From 911f6eb1067f27606c9f6f1f8e554fba0cf02d19 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Sat, 19 Jan 2013 21:33:38 +0400
Subject: [PATCH 026/197] merge into public

---
 app/views/dashboard/_teams.html.haml  | 23 +++++++++++++++++++++++
 app/views/layouts/user_team.html.haml | 22 ++++++++++++++++++++++
 2 files changed, 45 insertions(+)
 create mode 100644 app/views/dashboard/_teams.html.haml
 create mode 100644 app/views/layouts/user_team.html.haml

diff --git a/app/views/dashboard/_teams.html.haml b/app/views/dashboard/_teams.html.haml
new file mode 100644
index 00000000000..cbf97b93097
--- /dev/null
+++ b/app/views/dashboard/_teams.html.haml
@@ -0,0 +1,23 @@
+.teams_box
+  %h5.title
+    My Teams
+    %small
+      (#{teams.count})
+    %span.right
+      = link_to new_team_path, class: "btn very_small info" do
+        %i.icon-plus
+        New Team
+    %span.right
+      = link_to teams_path, class: "btn very_small info" do
+        %i.icon-user
+        All Teams
+  %ul.well-list
+    - teams.each do |team|
+      %li
+        = link_to team_path(id: team.path), class: dom_class(team) do
+          %strong.well-title= truncate(team.name, length: 35)
+          %span.arrow
+            &rarr;
+          %span.last_activity
+            %strong Projects:
+            %span= current_user.authorized_projects.in_team(team).count
diff --git a/app/views/layouts/user_team.html.haml b/app/views/layouts/user_team.html.haml
new file mode 100644
index 00000000000..bd3dfe0d418
--- /dev/null
+++ b/app/views/layouts/user_team.html.haml
@@ -0,0 +1,22 @@
+!!! 5
+%html{ lang: "en"}
+  = render "layouts/head", title: "#{@user_team.name}"
+  %body{class: "#{app_theme} application"}
+    = render "layouts/flash"
+    = render "layouts/head_panel", title: "#{@user_team.name}"
+    .container
+      %ul.main_menu
+        = nav_link(path: 'teams#show', html_options: {class: 'home'}) do
+          = link_to "Home", team_path(@user_team), title: "Home"
+        = nav_link(path: 'teams#issues') do
+          = link_to issues_team_path(@user_team) do
+            Issues
+            %span.count= Issue.opened.of_user_team(@user_team).count
+        = nav_link(path: 'teams#merge_requests') do
+          = link_to merge_requests_team_path(@user_team) do
+            Merge Requests
+            %span.count= MergeRequest.opened.of_user_team(@user_team).count
+        = nav_link(path: 'teams#search') do
+          = link_to "Search", search_team_path(@user_team)
+
+      .content= yield
-- 
GitLab


From 360aa1b4075ba6ffa9927971c580db0059ab4842 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Sat, 19 Jan 2013 21:43:07 +0400
Subject: [PATCH 027/197] Team core management

---
 lib/gitlab/user_team_manager.rb | 93 +++++++++++++++++++++++++++++++++
 1 file changed, 93 insertions(+)
 create mode 100644 lib/gitlab/user_team_manager.rb

diff --git a/lib/gitlab/user_team_manager.rb b/lib/gitlab/user_team_manager.rb
new file mode 100644
index 00000000000..d010c79223e
--- /dev/null
+++ b/lib/gitlab/user_team_manager.rb
@@ -0,0 +1,93 @@
+# UserTeamManager class
+#
+# Used for manage User teams with project repositories
+module Gitlab
+  class UserTeamManager
+    class << self
+      def assign(team, project, access)
+        project = Project.find(project) unless project.is_a? Project
+        searched_project = team.user_team_project_relationships.find_by_project_id(project.id)
+
+        unless searched_project.present?
+          team.user_team_project_relationships.create(project_id: project.id, greatest_access: access)
+          update_team_users_access_in_project(team, project)
+        end
+      end
+
+      def resign(team, project)
+        project = Project.find(project) unless project.is_a? Project
+
+        team.user_team_project_relationships.with_project(project).destroy_all
+
+        update_team_users_access_in_project(team, project)
+      end
+
+      def update_team_users_access_in_project(team, project)
+        members = team.members
+        members.each do |member|
+          update_team_user_access_in_project(team, member, project)
+        end
+      end
+
+      def update_team_user_access_in_project(team, user, project)
+        granted_access = max_teams_member_permission_in_project(user, project)
+
+        project_team_user = UsersProject.find_by_user_id_and_project_id(user.id, project.id)
+
+        if project_team_user.present?
+          project_team_user.destroy
+        end
+
+        if project_team_user.blank? && granted_access > 0
+          UsersProject.add_users_into_projects([project.id], [user.id], granted_access)
+        end
+      end
+
+      def max_teams_member_permission_in_project(user, project, teams = nil)
+        result_access = 0
+
+        user_teams = project.user_teams.with_member(user)
+
+        teams ||= user_teams
+
+        if teams.any?
+          teams.each do |team|
+            granted_access = max_team_member_permission_in_project(team, user, project)
+            result_access = [granted_access, result_access].max
+          end
+        end
+        result_access
+      end
+
+      def max_team_member_permission_in_project(team, user, project)
+        member_access = team.default_projects_access(user)
+        team_access = team.user_team_project_relationships.find_by_project_id(project.id).greatest_access
+
+        [team_access, member_access].min
+      end
+
+      def add_member_into_team(team, user, access, admin)
+        user = User.find(user) unless user.is_a? User
+
+        team.user_team_user_relationships.create(user_id: user.id, permission: access, group_admin: admin)
+        team.projects.each do |project|
+          update_team_user_access_in_project(team, user, project)
+        end
+      end
+
+      def remove_member_from_team(team, user)
+        user = User.find(user) unless user.is_a? User
+
+        team.user_team_user_relationships.with_user(user).destroy_all
+        other_teams = []
+        team.projects.each do |project|
+          other_teams << project.user_teams.with_member(user)
+        end
+        other_teams.uniq
+        unless other_teams.any?
+          UsersProject.in_projects(team.projects).with_user(user).destroy_all
+        end
+      end
+    end
+  end
+end
-- 
GitLab


From ea6f46cb87c7ba8c0c620a8ff954f203b3276a7c Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Sat, 19 Jan 2013 21:47:08 +0400
Subject: [PATCH 028/197] Team members public section

---
 app/controllers/teams/members_controller.rb | 58 ++++++++++++++++++++
 app/views/teams/members/_form.html.haml     | 23 ++++++++
 app/views/teams/members/_show.html.haml     | 31 +++++++++++
 app/views/teams/members/_team.html.haml     | 16 ++++++
 app/views/teams/members/index.html.haml     | 18 +++++++
 app/views/teams/members/new.html.haml       |  2 +
 app/views/teams/members/show.html.haml      | 60 +++++++++++++++++++++
 config/routes.rb                            |  4 ++
 8 files changed, 212 insertions(+)
 create mode 100644 app/controllers/teams/members_controller.rb
 create mode 100644 app/views/teams/members/_form.html.haml
 create mode 100644 app/views/teams/members/_show.html.haml
 create mode 100644 app/views/teams/members/_team.html.haml
 create mode 100644 app/views/teams/members/index.html.haml
 create mode 100644 app/views/teams/members/new.html.haml
 create mode 100644 app/views/teams/members/show.html.haml

diff --git a/app/controllers/teams/members_controller.rb b/app/controllers/teams/members_controller.rb
new file mode 100644
index 00000000000..ab1c2878331
--- /dev/null
+++ b/app/controllers/teams/members_controller.rb
@@ -0,0 +1,58 @@
+class Teams::MembersController < Teams::ApplicationController
+  # Authorize
+  before_filter :authorize_manage_user_team!, only: [:new, :edit]
+
+  def index
+    @members = @user_team.members
+  end
+
+  def show
+    @team_member = @user_team.members.find(params[:id])
+    @events = @team_member.recent_events.limit(7)
+  end
+
+  def new
+    @team_member = @user_team.members.new
+  end
+
+  def create
+    users = User.where(id: params[:user_ids])
+
+    @project.team << [users, params[:default_project_access]]
+
+    if params[:redirect_to]
+      redirect_to params[:redirect_to]
+    else
+      redirect_to project_team_index_path(@project)
+    end
+  end
+
+  def update
+    @team_member = @user_team.members.find(params[:id])
+    @team_member.update_attributes(params[:team_member])
+
+    unless @team_member.valid?
+      flash[:alert] = "User should have at least one role"
+    end
+    redirect_to team_member_path(@project)
+  end
+
+  def destroy
+    @team_member = project.users_projects.find(params[:id])
+    @team_member.destroy
+
+    respond_to do |format|
+      format.html { redirect_to project_team_index_path(@project) }
+      format.js { render nothing: true }
+    end
+  end
+
+  def apply_import
+    giver = Project.find(params[:source_project_id])
+    status = @project.team.import(giver)
+    notice = status ? "Succesfully imported" : "Import failed"
+
+    redirect_to project_team_members_path(project), notice: notice
+  end
+
+end
diff --git a/app/views/teams/members/_form.html.haml b/app/views/teams/members/_form.html.haml
new file mode 100644
index 00000000000..a963e462a78
--- /dev/null
+++ b/app/views/teams/members/_form.html.haml
@@ -0,0 +1,23 @@
+%h3.page_title
+  = "New Team member(s)"
+%hr
+= form_for @team_member, as: :team_member, url: project_team_members_path(@project, @team_member) do |f|
+  -if @team_member.errors.any?
+    .alert-message.block-message.error
+      %ul
+        - @team_member.errors.full_messages.each do |msg|
+          %li= msg
+
+  %h6 1. Choose people you want in the team
+  .clearfix
+    = f.label :user_ids, "People"
+    .input= select_tag(:user_ids, options_from_collection_for_select(User.active.not_in_project(@project).alphabetically, :id, :name), {data: {placeholder: "Select users"}, class: "chosen xxlarge", multiple: true})
+
+  %h6 2. Set access level for them
+  .clearfix
+    = f.label :project_access, "Project Access"
+    .input= select_tag :project_access, options_for_select(Project.access_options, @team_member.project_access), class: "project-access-select chosen"
+
+  .actions
+    = f.submit 'Save', class: "btn save-btn"
+    = link_to "Cancel", project_team_index_path(@project), class: "btn cancel-btn"
diff --git a/app/views/teams/members/_show.html.haml b/app/views/teams/members/_show.html.haml
new file mode 100644
index 00000000000..dfe73c77652
--- /dev/null
+++ b/app/views/teams/members/_show.html.haml
@@ -0,0 +1,31 @@
+- user = member.user
+- allow_admin = can? current_user, :manage_user_team, @user_team
+%li{id: dom_id(member), class: "team_member_row user_#{user.id}"}
+  .row
+    .span5
+      = link_to team_member_path(@user_team, user), title: user.name, class: "dark" do
+        = image_tag gravatar_icon(user.email, 40), class: "avatar s32"
+      = link_to team_member_path(@user_team, user), title: user.name, class: "dark" do
+        %strong= truncate(user.name, lenght: 40)
+        %br
+        %small.cgray= user.email
+
+    .span6.right
+      - if allow_admin
+        .left.span2
+          = form_for(member, as: :team_member, url: team_member_path(@user_team, user)) do |f|
+            = f.select :permission, options_for_select(UsersProject.access_roles, @user_team.default_projects_access(user)), {}, class: "medium project-access-select span2"
+        .left.span2
+          %span
+            Admin access
+            = check_box_tag :group_admin
+      .right
+        - if current_user == user
+          %span.btn.disabled This is you!
+        - if @user_team.owner == user
+          %span.btn.disabled.success Owner
+        - elsif user.blocked
+          %span.btn.disabled.blocked Blocked
+        - elsif allow_admin
+          = link_to team_member_path(@user_team, user), confirm: remove_from_team_message(@user_team, user), method: :delete, class: "very_small btn danger" do
+            %i.icon-minus.icon-white
diff --git a/app/views/teams/members/_team.html.haml b/app/views/teams/members/_team.html.haml
new file mode 100644
index 00000000000..e1fbf6d1e75
--- /dev/null
+++ b/app/views/teams/members/_team.html.haml
@@ -0,0 +1,16 @@
+- grouped_user_team_members(@user_team).each do |access, members|
+  .ui-box
+    %h5.title
+      = Project.access_options.key(access).pluralize
+      %small= members.size
+    %ul.well-list
+      - members.sort_by(&:user_name).each do |up|
+        = render(partial: 'teams/members/show', locals: {member: up})
+
+
+:javascript
+  $(function(){
+    $('.repo-access-select, .project-access-select').live("change", function() {
+      $(this.form).submit();
+    });
+  })
diff --git a/app/views/teams/members/index.html.haml b/app/views/teams/members/index.html.haml
new file mode 100644
index 00000000000..5b125b32769
--- /dev/null
+++ b/app/views/teams/members/index.html.haml
@@ -0,0 +1,18 @@
+= render "teams/team_head"
+%h3.page_title
+  Team Members
+  (#{@members.count})
+  %small
+    Read more about project permissions
+    %strong= link_to "here", help_permissions_path, class: "vlink"
+
+  - if can? current_user, :manage_user_team, @user_team
+    %span.right
+      = link_to new_team_member_path(@user_team), class: "btn success small grouped", title: "New Team Member" do
+        New Team Member
+%hr
+
+
+.clearfix
+%div.team-table
+  = render partial: "teams/members/team", locals: {project: @user_team}
diff --git a/app/views/teams/members/new.html.haml b/app/views/teams/members/new.html.haml
new file mode 100644
index 00000000000..40eb4cebf08
--- /dev/null
+++ b/app/views/teams/members/new.html.haml
@@ -0,0 +1,2 @@
+= render "projects/project_head"
+= render "team_members/form"
diff --git a/app/views/teams/members/show.html.haml b/app/views/teams/members/show.html.haml
new file mode 100644
index 00000000000..4008e8bd23e
--- /dev/null
+++ b/app/views/teams/members/show.html.haml
@@ -0,0 +1,60 @@
+- allow_admin = can? current_user, :admin_project, @project
+- user = @team_member.user
+
+.team_member_show
+  - if can? current_user, :admin_project, @project
+    = link_to 'Remove from team', project_team_member_path(project_id: @project, id: @team_member.id), confirm: 'Are you sure?', method: :delete, class: "right btn danger"
+  .profile_avatar_holder
+    = image_tag gravatar_icon(user.email, 60), class: "borders"
+  %h3.page_title
+    = user.name
+    %small (@#{user.username})
+
+  %hr
+  .back_link
+    %br
+    = link_to project_team_index_path(@project), class: "" do
+      &larr; To team list
+  %br
+  .row
+    .span6
+      %table.lite
+        %tr
+          %td Email
+          %td= mail_to user.email
+        %tr
+          %td Skype
+          %td= user.skype
+        - unless user.linkedin.blank?
+          %tr
+            %td LinkedIn
+            %td= user.linkedin
+        - unless user.twitter.blank?
+          %tr
+            %td Twitter
+            %td= user.twitter
+        - unless user.bio.blank?
+          %tr
+            %td Bio
+            %td= user.bio
+    .span6
+      %table.lite
+        %tr
+          %td Member since
+          %td= @team_member.created_at.stamp("Aug 21, 2011")
+        %tr
+          %td
+            Project Access:
+            %small (#{link_to "read more", help_permissions_path, class: "vlink"})
+          %td
+            = form_for(@team_member, as: :team_member, url: project_team_member_path(@project, @team_member)) do |f|
+              = f.select :project_access, options_for_select(Project.access_options, @team_member.project_access), {}, class: "project-access-select", disabled: !allow_admin
+  %hr
+  = render @events
+:javascript
+  $(function(){
+    $('.repo-access-select, .project-access-select').live("change", function() {
+      $(this.form).submit();
+    });
+  })
+
diff --git a/config/routes.rb b/config/routes.rb
index 4a6b0d0b74d..44678ca0266 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -139,6 +139,10 @@ Gitlab::Application.routes.draw do
       delete :relegate_project
       put :update_access
     end
+    scope module: :teams do
+      resources :members
+      end
+    end
     collection do
       get :search
     end
-- 
GitLab


From a96cf3ad09c06fb5bfe668a77edc5d7adb2d092f Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Sat, 19 Jan 2013 21:48:05 +0400
Subject: [PATCH 029/197] Team projects public section

---
 app/controllers/teams/projects_controller.rb | 21 ++++++++++++
 app/views/teams/projects/edit.html.haml      |  4 +++
 app/views/teams/projects/index.html.haml     | 34 ++++++++++++++++++++
 app/views/teams/projects/new.html.haml       |  4 +++
 app/views/teams/projects/show.html.haml      |  4 +++
 config/routes.rb                             |  2 ++
 6 files changed, 69 insertions(+)
 create mode 100644 app/controllers/teams/projects_controller.rb
 create mode 100644 app/views/teams/projects/edit.html.haml
 create mode 100644 app/views/teams/projects/index.html.haml
 create mode 100644 app/views/teams/projects/new.html.haml
 create mode 100644 app/views/teams/projects/show.html.haml

diff --git a/app/controllers/teams/projects_controller.rb b/app/controllers/teams/projects_controller.rb
new file mode 100644
index 00000000000..796f37f6d5d
--- /dev/null
+++ b/app/controllers/teams/projects_controller.rb
@@ -0,0 +1,21 @@
+class Teams::ProjectsController < Teams::ApplicationController
+  def index
+    @projects = @user_team.projects
+    @avaliable_projects = current_user.admin? ? Project.without_team(@user_team) : (Project.personal(current_user) + current_user.projects).uniq
+  end
+
+  def new
+  end
+
+  def create
+  end
+
+  def edit
+  end
+
+  def update
+  end
+
+  def destroy
+  end
+end
diff --git a/app/views/teams/projects/edit.html.haml b/app/views/teams/projects/edit.html.haml
new file mode 100644
index 00000000000..66c9f0671ff
--- /dev/null
+++ b/app/views/teams/projects/edit.html.haml
@@ -0,0 +1,4 @@
+= render "teams/team_head"
+
+%h1 Teams::Projects#edit
+%p Find me in app/views/teams/projects/edit.html.haml
diff --git a/app/views/teams/projects/index.html.haml b/app/views/teams/projects/index.html.haml
new file mode 100644
index 00000000000..66cb12a8421
--- /dev/null
+++ b/app/views/teams/projects/index.html.haml
@@ -0,0 +1,34 @@
+= render "teams/team_head"
+
+%fieldset
+  %legend Projects (#{@user_team.projects.count})
+  = form_tag delegate_projects_team_path(@user_team), id: "team_projects", class: "bulk_import", method: :post  do
+    %table
+      %thead
+        %tr
+          %th Project name
+          %th Max access
+          %th
+      - @user_team.projects.each do |project|
+        %tr.project
+          %td
+            = link_to project.name_with_namespace, project
+          %td
+            %span= @user_team.human_max_project_access(project)
+            -# if current_user.can?(:manage_user_team, @user_team)
+              - relation = project.user_team_project_relationships.find_by_user_team_id(@user_team)
+              = form_for(relation, as: :project, url: team_project_path(@user_team, project)) do |f|
+                = f.select :greatest_access, options_for_select(UsersProject.access_roles, @user_team.max_project_access(project)), {}, class: "medium project-access-select span2"
+
+          - if current_user.can?(:admin_user_team, @user_team)
+            %td.bgred
+              -#= link_to 'Edit max access', edit_project_team_path(@user_team, project), class: "btn small"
+              = link_to 'Relegate', relegate_project_team_path(@user_team, project_id: project.id), confirm: 'Remove project from team and move to global namespace. Are you sure?', method: :delete, class: "btn danger small"
+          - else
+            %td
+
+      - if @avaliable_projects.any?
+        %tr
+          %td= select_tag :project_ids, options_from_collection_for_select(@avaliable_projects , :id, :name_with_namespace), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5'
+          %td= select_tag :greatest_project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3" }
+          %td= submit_tag 'Add', class: "btn primary"
diff --git a/app/views/teams/projects/new.html.haml b/app/views/teams/projects/new.html.haml
new file mode 100644
index 00000000000..24d2d4c34ca
--- /dev/null
+++ b/app/views/teams/projects/new.html.haml
@@ -0,0 +1,4 @@
+= render "teams/team_head"
+
+%h1 Teams::Projects#new
+%p Find me in app/views/teams/projects/new.html.haml
diff --git a/app/views/teams/projects/show.html.haml b/app/views/teams/projects/show.html.haml
new file mode 100644
index 00000000000..66c9f0671ff
--- /dev/null
+++ b/app/views/teams/projects/show.html.haml
@@ -0,0 +1,4 @@
+= render "teams/team_head"
+
+%h1 Teams::Projects#edit
+%p Find me in app/views/teams/projects/edit.html.haml
diff --git a/config/routes.rb b/config/routes.rb
index 44678ca0266..69ad2e68642 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,6 +1,7 @@
 require 'sidekiq/web'
 
 Gitlab::Application.routes.draw do
+
   #
   # Search
   #
@@ -141,6 +142,7 @@ Gitlab::Application.routes.draw do
     end
     scope module: :teams do
       resources :members
+      resources :projects, only: [:index, :show] do
       end
     end
     collection do
-- 
GitLab


From 3c6e144608b655ff1b43ec33baf020d19d460ba8 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Sat, 19 Jan 2013 21:48:46 +0400
Subject: [PATCH 030/197] add dashboard teams block

---
 app/controllers/dashboard_controller.rb | 2 ++
 app/views/dashboard/_sidebar.html.haml  | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
index c0ec4708e0a..1322973489c 100644
--- a/app/controllers/dashboard_controller.rb
+++ b/app/controllers/dashboard_controller.rb
@@ -18,6 +18,8 @@ class DashboardController < ApplicationController
                   @projects
                 end
 
+    @teams = (UserTeam.with_member(current_user) + UserTeam.created_by(current_user)).uniq
+
     @projects = @projects.page(params[:page]).per(30)
 
     @events = Event.in_projects(current_user.authorized_projects.pluck(:id))
diff --git a/app/views/dashboard/_sidebar.html.haml b/app/views/dashboard/_sidebar.html.haml
index 9830cdf4f6b..7c6daf6ec31 100644
--- a/app/views/dashboard/_sidebar.html.haml
+++ b/app/views/dashboard/_sidebar.html.haml
@@ -1,3 +1,5 @@
+- if @teams.present?
+  = render "teams", teams: @teams
 - if @groups.present?
   = render "groups", groups: @groups
 = render "projects", projects: @projects
-- 
GitLab


From b9a7bcb6a45c343f51aea49bccf38722e49c949c Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Sat, 19 Jan 2013 21:49:15 +0400
Subject: [PATCH 031/197] add teams application controller

---
 app/controllers/teams/application_controller.rb | 10 ++++++++++
 1 file changed, 10 insertions(+)
 create mode 100644 app/controllers/teams/application_controller.rb

diff --git a/app/controllers/teams/application_controller.rb b/app/controllers/teams/application_controller.rb
new file mode 100644
index 00000000000..1cfb0e0991a
--- /dev/null
+++ b/app/controllers/teams/application_controller.rb
@@ -0,0 +1,10 @@
+class Teams::ApplicationController < ApplicationController
+  before_filter :user_team, only: [:index, :show, :edit, :update, :destroy, :issues, :merge_requests, :search, :members]
+
+  protected
+
+  def user_team
+    @user_team ||= UserTeam.find_by_path(params[:team_id])
+  end
+
+end
-- 
GitLab


From c098ac64309b2eb75195324fec08f552c839cf32 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Sat, 19 Jan 2013 21:50:03 +0400
Subject: [PATCH 032/197] update stylesheets (for teams block)

---
 app/assets/stylesheets/sections/projects.scss | 1 +
 1 file changed, 1 insertion(+)

diff --git a/app/assets/stylesheets/sections/projects.scss b/app/assets/stylesheets/sections/projects.scss
index 4bdc56d2884..ee2c379f2ab 100644
--- a/app/assets/stylesheets/sections/projects.scss
+++ b/app/assets/stylesheets/sections/projects.scss
@@ -7,6 +7,7 @@
     @extend .right;
 
     .groups_box,
+    .teams_box,
     .projects_box {
       > .title {
         padding: 2px 15px;
-- 
GitLab


From b6458ae3b3afd872720e1abbd5e0a284752c2323 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Sat, 19 Jan 2013 21:51:01 +0400
Subject: [PATCH 033/197] add into user decorator (presenter) to full user name

---
 app/decorators/user_decorator.rb | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/app/decorators/user_decorator.rb b/app/decorators/user_decorator.rb
index af9c6a63e75..b781f237352 100644
--- a/app/decorators/user_decorator.rb
+++ b/app/decorators/user_decorator.rb
@@ -8,4 +8,8 @@ class UserDecorator < ApplicationDecorator
   def tm_of(project)
     project.team_member_by_id(self.id)
   end
+
+  def name_with_email
+    "#{name} (#{email})"
+  end
 end
-- 
GitLab


From 3a0d4865f63fd078b54436864c201a7c41a9ddf9 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Sat, 19 Jan 2013 21:51:42 +0400
Subject: [PATCH 034/197] update projects show css selector

---
 app/views/admin/projects/show.html.haml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index 8e0d82328df..12cad07c9c4 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -116,7 +116,7 @@
   %small
     (#{@project.users_projects.count})
 %br
-%table.zebra-striped
+%table.zebra-striped.team_members
   %thead
     %tr
       %th Name
-- 
GitLab


From 17e9207dff39374ae33574b19123d1a1320fff4c Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Sat, 19 Jan 2013 21:53:03 +0400
Subject: [PATCH 035/197] add user team factories

---
 spec/factories/user_team_project_relationships.rb |  9 +++++++++
 spec/factories/user_team_user_relationships.rb    | 10 ++++++++++
 spec/factories/user_teams.rb                      |  9 +++++++++
 3 files changed, 28 insertions(+)
 create mode 100644 spec/factories/user_team_project_relationships.rb
 create mode 100644 spec/factories/user_team_user_relationships.rb
 create mode 100644 spec/factories/user_teams.rb

diff --git a/spec/factories/user_team_project_relationships.rb b/spec/factories/user_team_project_relationships.rb
new file mode 100644
index 00000000000..fa0f26e7455
--- /dev/null
+++ b/spec/factories/user_team_project_relationships.rb
@@ -0,0 +1,9 @@
+# Read about factories at https://github.com/thoughtbot/factory_girl
+
+FactoryGirl.define do
+  factory :user_team_project_relationship do
+    project_id 1
+    user_team_id 1
+    greatest_access 1
+  end
+end
diff --git a/spec/factories/user_team_user_relationships.rb b/spec/factories/user_team_user_relationships.rb
new file mode 100644
index 00000000000..9b655e00686
--- /dev/null
+++ b/spec/factories/user_team_user_relationships.rb
@@ -0,0 +1,10 @@
+# Read about factories at https://github.com/thoughtbot/factory_girl
+
+FactoryGirl.define do
+  factory :user_team_user_relationship do
+    user_id 1
+    user_team_id 1
+    group_admin false
+    permission 1
+  end
+end
diff --git a/spec/factories/user_teams.rb b/spec/factories/user_teams.rb
new file mode 100644
index 00000000000..f4fe45cbb8a
--- /dev/null
+++ b/spec/factories/user_teams.rb
@@ -0,0 +1,9 @@
+# Read about factories at https://github.com/thoughtbot/factory_girl
+
+FactoryGirl.define do
+  factory :user_team do
+    sequence(:name) { |n| "team#{n}" }
+    path { name.downcase.gsub(/\s/, '_') }
+    owner
+  end
+end
-- 
GitLab


From a987f1469e2480559b675c251d49509f6200112f Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Sat, 19 Jan 2013 21:55:59 +0400
Subject: [PATCH 036/197] commit user team helper

---
 app/helpers/user_teams_helper.rb | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
 create mode 100644 app/helpers/user_teams_helper.rb

diff --git a/app/helpers/user_teams_helper.rb b/app/helpers/user_teams_helper.rb
new file mode 100644
index 00000000000..01e10de52fb
--- /dev/null
+++ b/app/helpers/user_teams_helper.rb
@@ -0,0 +1,26 @@
+module UserTeamsHelper
+  def team_filter_path(entity, options={})
+    exist_opts = {
+      status: params[:status],
+      project_id: params[:project_id],
+    }
+
+    options = exist_opts.merge(options)
+
+    case entity
+    when 'issue' then
+      issues_team_path(@user_team, options)
+    when 'merge_request'
+      merge_requests_team_path(@user_team, options)
+    end
+  end
+
+  def grouped_user_team_members(team)
+    team.user_team_user_relationships.sort_by(&:permission).reverse.group_by(&:permission)
+  end
+
+  def remove_from_team_message(team, member)
+    "You are going to remove #{member.name} from #{team.name}. Are you sure?"
+  end
+
+end
-- 
GitLab


From c5f427b0a499136568bcf3cc738e5f1a8575e358 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Sat, 19 Jan 2013 21:58:13 +0400
Subject: [PATCH 037/197] save commit

---
 app/views/teams/members/edit.html.haml        |  2 +
 app/views/teams/members/import.html.haml      | 17 ++++++
 .../admin/teams_controller_spec.rb            | 47 ++++++++++++++++
 .../teams/members_controller_spec.rb          | 47 ++++++++++++++++
 .../teams/projects_controller_spec.rb         | 47 ++++++++++++++++
 spec/controllers/teams_controller_spec.rb     | 54 +++++++++++++++++++
 spec/helpers/admin/teams_helper_spec.rb       | 15 ++++++
 spec/helpers/teams/members_helper_spec.rb     | 15 ++++++
 spec/helpers/teams/projects_helper_spec.rb    | 15 ++++++
 spec/helpers/teams_helper_spec.rb             | 15 ++++++
 .../admin/teams/create.html.haml_spec.rb      |  5 ++
 .../admin/teams/destroy.html.haml_spec.rb     |  5 ++
 spec/views/admin/teams/edit.html.haml_spec.rb |  5 ++
 .../views/admin/teams/index.html.haml_spec.rb |  5 ++
 spec/views/admin/teams/show.html.haml_spec.rb |  5 ++
 .../admin/teams/update.html.haml_spec.rb      |  5 ++
 spec/views/teams/create.html.haml_spec.rb     |  5 ++
 spec/views/teams/destroy.html.haml_spec.rb    |  5 ++
 spec/views/teams/edit.html.haml_spec.rb       |  5 ++
 spec/views/teams/index.html.haml_spec.rb      |  5 ++
 .../teams/members/create.html.haml_spec.rb    |  5 ++
 .../teams/members/destroy.html.haml_spec.rb   |  5 ++
 .../teams/members/edit.html.haml_spec.rb      |  5 ++
 .../teams/members/index.html.haml_spec.rb     |  5 ++
 .../views/teams/members/new.html.haml_spec.rb |  5 ++
 .../teams/members/update.html.haml_spec.rb    |  5 ++
 spec/views/teams/new.html.haml_spec.rb        |  5 ++
 .../teams/projects/create.html.haml_spec.rb   |  5 ++
 .../teams/projects/destroy.html.haml_spec.rb  |  5 ++
 .../teams/projects/edit.html.haml_spec.rb     |  5 ++
 .../teams/projects/index.html.haml_spec.rb    |  5 ++
 .../teams/projects/new.html.haml_spec.rb      |  5 ++
 .../teams/projects/update.html.haml_spec.rb   |  5 ++
 spec/views/teams/show.html.haml_spec.rb       |  5 ++
 spec/views/teams/update.html.haml_spec.rb     |  5 ++
 35 files changed, 399 insertions(+)
 create mode 100644 app/views/teams/members/edit.html.haml
 create mode 100644 app/views/teams/members/import.html.haml
 create mode 100644 spec/controllers/admin/teams_controller_spec.rb
 create mode 100644 spec/controllers/teams/members_controller_spec.rb
 create mode 100644 spec/controllers/teams/projects_controller_spec.rb
 create mode 100644 spec/controllers/teams_controller_spec.rb
 create mode 100644 spec/helpers/admin/teams_helper_spec.rb
 create mode 100644 spec/helpers/teams/members_helper_spec.rb
 create mode 100644 spec/helpers/teams/projects_helper_spec.rb
 create mode 100644 spec/helpers/teams_helper_spec.rb
 create mode 100644 spec/views/admin/teams/create.html.haml_spec.rb
 create mode 100644 spec/views/admin/teams/destroy.html.haml_spec.rb
 create mode 100644 spec/views/admin/teams/edit.html.haml_spec.rb
 create mode 100644 spec/views/admin/teams/index.html.haml_spec.rb
 create mode 100644 spec/views/admin/teams/show.html.haml_spec.rb
 create mode 100644 spec/views/admin/teams/update.html.haml_spec.rb
 create mode 100644 spec/views/teams/create.html.haml_spec.rb
 create mode 100644 spec/views/teams/destroy.html.haml_spec.rb
 create mode 100644 spec/views/teams/edit.html.haml_spec.rb
 create mode 100644 spec/views/teams/index.html.haml_spec.rb
 create mode 100644 spec/views/teams/members/create.html.haml_spec.rb
 create mode 100644 spec/views/teams/members/destroy.html.haml_spec.rb
 create mode 100644 spec/views/teams/members/edit.html.haml_spec.rb
 create mode 100644 spec/views/teams/members/index.html.haml_spec.rb
 create mode 100644 spec/views/teams/members/new.html.haml_spec.rb
 create mode 100644 spec/views/teams/members/update.html.haml_spec.rb
 create mode 100644 spec/views/teams/new.html.haml_spec.rb
 create mode 100644 spec/views/teams/projects/create.html.haml_spec.rb
 create mode 100644 spec/views/teams/projects/destroy.html.haml_spec.rb
 create mode 100644 spec/views/teams/projects/edit.html.haml_spec.rb
 create mode 100644 spec/views/teams/projects/index.html.haml_spec.rb
 create mode 100644 spec/views/teams/projects/new.html.haml_spec.rb
 create mode 100644 spec/views/teams/projects/update.html.haml_spec.rb
 create mode 100644 spec/views/teams/show.html.haml_spec.rb
 create mode 100644 spec/views/teams/update.html.haml_spec.rb

diff --git a/app/views/teams/members/edit.html.haml b/app/views/teams/members/edit.html.haml
new file mode 100644
index 00000000000..a2742977717
--- /dev/null
+++ b/app/views/teams/members/edit.html.haml
@@ -0,0 +1,2 @@
+%h1 Teams::Members#edit
+%p Find me in app/views/teams/members/edit.html.haml
\ No newline at end of file
diff --git a/app/views/teams/members/import.html.haml b/app/views/teams/members/import.html.haml
new file mode 100644
index 00000000000..de82f416248
--- /dev/null
+++ b/app/views/teams/members/import.html.haml
@@ -0,0 +1,17 @@
+= render "projects/project_head"
+
+%h3.page_title
+  = "Import team from another project"
+%hr
+%p.slead
+  Read more about team import #{link_to "here", '#', class: 'vlink'}.
+= form_tag apply_import_project_team_members_path(@project), method: 'post' do
+  %p.slead Choose project you want to use as team source:
+  .padded
+    = label_tag :source_project_id, "Project"
+    .input= select_tag(:source_project_id, options_from_collection_for_select(current_user.authorized_projects, :id, :name_with_namespace), prompt: "Select project", class: "chosen xxlarge", required: true)
+
+  .actions
+    = submit_tag 'Import', class: "btn save-btn"
+    = link_to "Cancel", project_team_index_path(@project), class: "btn cancel-btn"
+
diff --git a/spec/controllers/admin/teams_controller_spec.rb b/spec/controllers/admin/teams_controller_spec.rb
new file mode 100644
index 00000000000..02d8f86a79d
--- /dev/null
+++ b/spec/controllers/admin/teams_controller_spec.rb
@@ -0,0 +1,47 @@
+require 'spec_helper'
+
+describe Admin::TeamsController do
+
+  describe "GET 'index'" do
+    it "returns http success" do
+      get 'index'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'show'" do
+    it "returns http success" do
+      get 'show'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'create'" do
+    it "returns http success" do
+      get 'create'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'edit'" do
+    it "returns http success" do
+      get 'edit'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'update'" do
+    it "returns http success" do
+      get 'update'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'destroy'" do
+    it "returns http success" do
+      get 'destroy'
+      response.should be_success
+    end
+  end
+
+end
diff --git a/spec/controllers/teams/members_controller_spec.rb b/spec/controllers/teams/members_controller_spec.rb
new file mode 100644
index 00000000000..e1ac558a6cd
--- /dev/null
+++ b/spec/controllers/teams/members_controller_spec.rb
@@ -0,0 +1,47 @@
+require 'spec_helper'
+
+describe Teams::MembersController do
+
+  describe "GET 'index'" do
+    it "returns http success" do
+      get 'index'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'new'" do
+    it "returns http success" do
+      get 'new'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'create'" do
+    it "returns http success" do
+      get 'create'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'edit'" do
+    it "returns http success" do
+      get 'edit'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'update'" do
+    it "returns http success" do
+      get 'update'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'destroy'" do
+    it "returns http success" do
+      get 'destroy'
+      response.should be_success
+    end
+  end
+
+end
diff --git a/spec/controllers/teams/projects_controller_spec.rb b/spec/controllers/teams/projects_controller_spec.rb
new file mode 100644
index 00000000000..b379c3721bb
--- /dev/null
+++ b/spec/controllers/teams/projects_controller_spec.rb
@@ -0,0 +1,47 @@
+require 'spec_helper'
+
+describe Teams::ProjectsController do
+
+  describe "GET 'index'" do
+    it "returns http success" do
+      get 'index'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'new'" do
+    it "returns http success" do
+      get 'new'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'create'" do
+    it "returns http success" do
+      get 'create'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'edit'" do
+    it "returns http success" do
+      get 'edit'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'update'" do
+    it "returns http success" do
+      get 'update'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'destroy'" do
+    it "returns http success" do
+      get 'destroy'
+      response.should be_success
+    end
+  end
+
+end
diff --git a/spec/controllers/teams_controller_spec.rb b/spec/controllers/teams_controller_spec.rb
new file mode 100644
index 00000000000..923261fce9c
--- /dev/null
+++ b/spec/controllers/teams_controller_spec.rb
@@ -0,0 +1,54 @@
+require 'spec_helper'
+
+describe TeamsController do
+
+  describe "GET 'index'" do
+    it "returns http success" do
+      get 'index'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'show'" do
+    it "returns http success" do
+      get 'show'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'new'" do
+    it "returns http success" do
+      get 'new'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'edit'" do
+    it "returns http success" do
+      get 'edit'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'update'" do
+    it "returns http success" do
+      get 'update'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'create'" do
+    it "returns http success" do
+      get 'create'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'destroy'" do
+    it "returns http success" do
+      get 'destroy'
+      response.should be_success
+    end
+  end
+
+end
diff --git a/spec/helpers/admin/teams_helper_spec.rb b/spec/helpers/admin/teams_helper_spec.rb
new file mode 100644
index 00000000000..5ed6073297b
--- /dev/null
+++ b/spec/helpers/admin/teams_helper_spec.rb
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+# Specs in this file have access to a helper object that includes
+# the Admin::TeamsHelper. For example:
+#
+# describe Admin::TeamsHelper do
+#   describe "string concat" do
+#     it "concats two strings with spaces" do
+#       helper.concat_strings("this","that").should == "this that"
+#     end
+#   end
+# end
+describe Admin::TeamsHelper do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/helpers/teams/members_helper_spec.rb b/spec/helpers/teams/members_helper_spec.rb
new file mode 100644
index 00000000000..a8e227aa063
--- /dev/null
+++ b/spec/helpers/teams/members_helper_spec.rb
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+# Specs in this file have access to a helper object that includes
+# the Teams::MembersHelper. For example:
+#
+# describe Teams::MembersHelper do
+#   describe "string concat" do
+#     it "concats two strings with spaces" do
+#       helper.concat_strings("this","that").should == "this that"
+#     end
+#   end
+# end
+describe Teams::MembersHelper do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/helpers/teams/projects_helper_spec.rb b/spec/helpers/teams/projects_helper_spec.rb
new file mode 100644
index 00000000000..836d1dca018
--- /dev/null
+++ b/spec/helpers/teams/projects_helper_spec.rb
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+# Specs in this file have access to a helper object that includes
+# the Teams::ProjectsHelper. For example:
+#
+# describe Teams::ProjectsHelper do
+#   describe "string concat" do
+#     it "concats two strings with spaces" do
+#       helper.concat_strings("this","that").should == "this that"
+#     end
+#   end
+# end
+describe Teams::ProjectsHelper do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/helpers/teams_helper_spec.rb b/spec/helpers/teams_helper_spec.rb
new file mode 100644
index 00000000000..95726163e35
--- /dev/null
+++ b/spec/helpers/teams_helper_spec.rb
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+# Specs in this file have access to a helper object that includes
+# the TeamsHelper. For example:
+#
+# describe TeamsHelper do
+#   describe "string concat" do
+#     it "concats two strings with spaces" do
+#       helper.concat_strings("this","that").should == "this that"
+#     end
+#   end
+# end
+describe TeamsHelper do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/admin/teams/create.html.haml_spec.rb b/spec/views/admin/teams/create.html.haml_spec.rb
new file mode 100644
index 00000000000..27f57d89693
--- /dev/null
+++ b/spec/views/admin/teams/create.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "teams/create.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/admin/teams/destroy.html.haml_spec.rb b/spec/views/admin/teams/destroy.html.haml_spec.rb
new file mode 100644
index 00000000000..87670e4dc66
--- /dev/null
+++ b/spec/views/admin/teams/destroy.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "teams/destroy.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/admin/teams/edit.html.haml_spec.rb b/spec/views/admin/teams/edit.html.haml_spec.rb
new file mode 100644
index 00000000000..5180d713f7f
--- /dev/null
+++ b/spec/views/admin/teams/edit.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "teams/edit.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/admin/teams/index.html.haml_spec.rb b/spec/views/admin/teams/index.html.haml_spec.rb
new file mode 100644
index 00000000000..7a0d69bd316
--- /dev/null
+++ b/spec/views/admin/teams/index.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "teams/index.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/admin/teams/show.html.haml_spec.rb b/spec/views/admin/teams/show.html.haml_spec.rb
new file mode 100644
index 00000000000..b7f7b669c2e
--- /dev/null
+++ b/spec/views/admin/teams/show.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "teams/show.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/admin/teams/update.html.haml_spec.rb b/spec/views/admin/teams/update.html.haml_spec.rb
new file mode 100644
index 00000000000..b28cfa4f699
--- /dev/null
+++ b/spec/views/admin/teams/update.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "teams/update.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/teams/create.html.haml_spec.rb b/spec/views/teams/create.html.haml_spec.rb
new file mode 100644
index 00000000000..27f57d89693
--- /dev/null
+++ b/spec/views/teams/create.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "teams/create.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/teams/destroy.html.haml_spec.rb b/spec/views/teams/destroy.html.haml_spec.rb
new file mode 100644
index 00000000000..87670e4dc66
--- /dev/null
+++ b/spec/views/teams/destroy.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "teams/destroy.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/teams/edit.html.haml_spec.rb b/spec/views/teams/edit.html.haml_spec.rb
new file mode 100644
index 00000000000..5180d713f7f
--- /dev/null
+++ b/spec/views/teams/edit.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "teams/edit.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/teams/index.html.haml_spec.rb b/spec/views/teams/index.html.haml_spec.rb
new file mode 100644
index 00000000000..7a0d69bd316
--- /dev/null
+++ b/spec/views/teams/index.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "teams/index.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/teams/members/create.html.haml_spec.rb b/spec/views/teams/members/create.html.haml_spec.rb
new file mode 100644
index 00000000000..b6f817617e4
--- /dev/null
+++ b/spec/views/teams/members/create.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "members/create.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/teams/members/destroy.html.haml_spec.rb b/spec/views/teams/members/destroy.html.haml_spec.rb
new file mode 100644
index 00000000000..3ff1634461c
--- /dev/null
+++ b/spec/views/teams/members/destroy.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "members/destroy.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/teams/members/edit.html.haml_spec.rb b/spec/views/teams/members/edit.html.haml_spec.rb
new file mode 100644
index 00000000000..3e952e898a9
--- /dev/null
+++ b/spec/views/teams/members/edit.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "members/edit.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/teams/members/index.html.haml_spec.rb b/spec/views/teams/members/index.html.haml_spec.rb
new file mode 100644
index 00000000000..363430d769f
--- /dev/null
+++ b/spec/views/teams/members/index.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "members/index.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/teams/members/new.html.haml_spec.rb b/spec/views/teams/members/new.html.haml_spec.rb
new file mode 100644
index 00000000000..f03eed1f29f
--- /dev/null
+++ b/spec/views/teams/members/new.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "members/new.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/teams/members/update.html.haml_spec.rb b/spec/views/teams/members/update.html.haml_spec.rb
new file mode 100644
index 00000000000..43b84bad99b
--- /dev/null
+++ b/spec/views/teams/members/update.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "members/update.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/teams/new.html.haml_spec.rb b/spec/views/teams/new.html.haml_spec.rb
new file mode 100644
index 00000000000..8ef621b708f
--- /dev/null
+++ b/spec/views/teams/new.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "teams/new.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/teams/projects/create.html.haml_spec.rb b/spec/views/teams/projects/create.html.haml_spec.rb
new file mode 100644
index 00000000000..74c4ee2d837
--- /dev/null
+++ b/spec/views/teams/projects/create.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "projects/create.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/teams/projects/destroy.html.haml_spec.rb b/spec/views/teams/projects/destroy.html.haml_spec.rb
new file mode 100644
index 00000000000..b3eee48f38b
--- /dev/null
+++ b/spec/views/teams/projects/destroy.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "projects/destroy.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/teams/projects/edit.html.haml_spec.rb b/spec/views/teams/projects/edit.html.haml_spec.rb
new file mode 100644
index 00000000000..ef41b7b0814
--- /dev/null
+++ b/spec/views/teams/projects/edit.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "projects/edit.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/teams/projects/index.html.haml_spec.rb b/spec/views/teams/projects/index.html.haml_spec.rb
new file mode 100644
index 00000000000..8cf0dbcd954
--- /dev/null
+++ b/spec/views/teams/projects/index.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "projects/index.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/teams/projects/new.html.haml_spec.rb b/spec/views/teams/projects/new.html.haml_spec.rb
new file mode 100644
index 00000000000..9ee68e5ae05
--- /dev/null
+++ b/spec/views/teams/projects/new.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "projects/new.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/teams/projects/update.html.haml_spec.rb b/spec/views/teams/projects/update.html.haml_spec.rb
new file mode 100644
index 00000000000..fdaafd3924b
--- /dev/null
+++ b/spec/views/teams/projects/update.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "projects/update.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/teams/show.html.haml_spec.rb b/spec/views/teams/show.html.haml_spec.rb
new file mode 100644
index 00000000000..b7f7b669c2e
--- /dev/null
+++ b/spec/views/teams/show.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "teams/show.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/teams/update.html.haml_spec.rb b/spec/views/teams/update.html.haml_spec.rb
new file mode 100644
index 00000000000..b28cfa4f699
--- /dev/null
+++ b/spec/views/teams/update.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "teams/update.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
-- 
GitLab


From 6d1c566ec9f8506500f997c5ab33915e98826f3f Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Sat, 19 Jan 2013 22:52:55 +0400
Subject: [PATCH 038/197] Rename Team class to ProjectTeam

---
 app/models/project.rb                   | 2 +-
 app/models/{team.rb => project_team.rb} | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
 rename app/models/{team.rb => project_team.rb} (99%)

diff --git a/app/models/project.rb b/app/models/project.rb
index fa314d9c5f0..a21cc3f6f40 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -127,7 +127,7 @@ class Project < ActiveRecord::Base
   end
 
   def team
-    @team ||= Team.new(self)
+    @team ||= ProjectTeam.new(self)
   end
 
   def repository
diff --git a/app/models/team.rb b/app/models/project_team.rb
similarity index 99%
rename from app/models/team.rb
rename to app/models/project_team.rb
index 51f4ff68d7b..2cc76974987 100644
--- a/app/models/team.rb
+++ b/app/models/project_team.rb
@@ -1,4 +1,4 @@
-class Team
+class ProjectTeam
   attr_accessor :project
 
   def initialize(project)
-- 
GitLab


From 845f146518783e7122d5ff9c593ffe3c6a59cecf Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Sun, 20 Jan 2013 11:46:15 +0400
Subject: [PATCH 039/197] fix simples errors in tests

---
 features/steps/admin/admin_teams.rb | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/features/steps/admin/admin_teams.rb b/features/steps/admin/admin_teams.rb
index 7bb1dacabcb..bba60ec496b 100644
--- a/features/steps/admin/admin_teams.rb
+++ b/features/steps/admin/admin_teams.rb
@@ -50,7 +50,7 @@ class AdminTeams < Spinach::FeatureSteps
   When 'I select user "John" from user list as "Developer"' do
     @user ||= User.find_by_name("John")
     within "#team_members" do
-      select user.name, :from => "user_ids"
+      select @user.name, :from => "user_ids"
       select "Developer", :from => "default_project_access"
     end
   end
@@ -61,7 +61,7 @@ class AdminTeams < Spinach::FeatureSteps
 
   Then 'I should see "John" in teams members list as "Developer"' do
     @user ||= User.find_by_name("John")
-    find_in_list("#members_list .member", user).must_equal true
+    find_in_list("#members_list .member", @user).must_equal true
   end
 
   When 'I visit "John" user admin page' do
@@ -185,7 +185,7 @@ class AdminTeams < Spinach::FeatureSteps
   end
 
   Then 'I should be redirected to "HardCoders" team admin page' do
-    current_path.should admin_team_peth(UserTeam.find_by_name("HardCoders"))
+    current_path.should == admin_team_path(UserTeam.find_by_name("HardCoders"))
   end
 
   And 'I should not to see "Jimm" user in members list' do
-- 
GitLab


From 2984716870a26b704a04e4ac4e72bfbc05750f73 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Sun, 20 Jan 2013 12:08:46 +0400
Subject: [PATCH 040/197] Admin rename team page is fixed

---
 app/views/admin/teams/edit.html.haml | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/app/views/admin/teams/edit.html.haml b/app/views/admin/teams/edit.html.haml
index 15ec267f45f..b2499ef6b8b 100644
--- a/app/views/admin/teams/edit.html.haml
+++ b/app/views/admin/teams/edit.html.haml
@@ -1,6 +1,6 @@
 %h3.page_title Rename Team
 %hr
-= form_for [:admin, @team] do |f|
+= form_for @team, url: admin_team_path(@team), method: :put do |f|
   - if @team.errors.any?
     .alert-message.block-message.error
       %span= @team.errors.full_messages.first
@@ -10,18 +10,13 @@
     .input
       = f.text_field :name, placeholder: "Example Team", class: "xxlarge"
 
-
-
   .clearfix.team_name_holder
     = f.label :path do
       %span.cred Team path is
     .input
       = f.text_field :path, placeholder: "example-team", class: "xxlarge danger"
       %ul.cred
-        %li Changing team path can have unintended side effects.
-        %li Renaming team path will rename directory for all related projects
         %li It will change web url for access team and team projects.
-        %li It will change the git path to repositories under this team.
 
   .form-actions
     = f.submit 'Rename team', class: "btn danger"
-- 
GitLab


From 9d318db48f4d76b8493aefa80e7b29c2ea3cc1cf Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Sun, 20 Jan 2013 15:20:50 +0400
Subject: [PATCH 041/197] Added the correct hierarchy of controllers for the
 administrative part

---
 .../{admin_controller.rb => admin/application_controller.rb}    | 2 +-
 app/controllers/admin/dashboard_controller.rb                   | 2 +-
 app/controllers/admin/groups_controller.rb                      | 2 +-
 app/controllers/admin/hooks_controller.rb                       | 2 +-
 app/controllers/admin/logs_controller.rb                        | 2 +-
 app/controllers/admin/projects_controller.rb                    | 2 +-
 app/controllers/admin/resque_controller.rb                      | 2 +-
 app/controllers/admin/team_members_controller.rb                | 2 +-
 app/controllers/admin/teams_controller.rb                       | 2 +-
 app/controllers/admin/users_controller.rb                       | 2 +-
 10 files changed, 10 insertions(+), 10 deletions(-)
 rename app/controllers/{admin_controller.rb => admin/application_controller.rb} (82%)

diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin/application_controller.rb
similarity index 82%
rename from app/controllers/admin_controller.rb
rename to app/controllers/admin/application_controller.rb
index bce9f692385..6a8f20f6047 100644
--- a/app/controllers/admin_controller.rb
+++ b/app/controllers/admin/application_controller.rb
@@ -1,7 +1,7 @@
 # Provides a base class for Admin controllers to subclass
 #
 # Automatically sets the layout and ensures an administrator is logged in
-class AdminController < ApplicationController
+class Admin::ApplicationController < ApplicationController
   layout 'admin'
   before_filter :authenticate_admin!
 
diff --git a/app/controllers/admin/dashboard_controller.rb b/app/controllers/admin/dashboard_controller.rb
index f97c56b0b31..3c27b86180b 100644
--- a/app/controllers/admin/dashboard_controller.rb
+++ b/app/controllers/admin/dashboard_controller.rb
@@ -1,4 +1,4 @@
-class Admin::DashboardController < AdminController
+class Admin::DashboardController < Admin::ApplicationController
   def index
     @projects = Project.order("created_at DESC").limit(10)
     @users = User.order("created_at DESC").limit(10)
diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb
index 90dbda3eeea..f552fb595b8 100644
--- a/app/controllers/admin/groups_controller.rb
+++ b/app/controllers/admin/groups_controller.rb
@@ -1,4 +1,4 @@
-class Admin::GroupsController < AdminController
+class Admin::GroupsController < Admin::ApplicationController
   before_filter :group, only: [:edit, :show, :update, :destroy, :project_update, :project_teams_update]
 
   def index
diff --git a/app/controllers/admin/hooks_controller.rb b/app/controllers/admin/hooks_controller.rb
index 91a1d633590..c5bf76f8c39 100644
--- a/app/controllers/admin/hooks_controller.rb
+++ b/app/controllers/admin/hooks_controller.rb
@@ -1,4 +1,4 @@
-class Admin::HooksController < AdminController
+class Admin::HooksController < Admin::ApplicationController
   def index
     @hooks = SystemHook.all
     @hook = SystemHook.new
diff --git a/app/controllers/admin/logs_controller.rb b/app/controllers/admin/logs_controller.rb
index 28c321a9e52..b999018dde4 100644
--- a/app/controllers/admin/logs_controller.rb
+++ b/app/controllers/admin/logs_controller.rb
@@ -1,2 +1,2 @@
-class Admin::LogsController < AdminController
+class Admin::LogsController < Admin::ApplicationController
 end
diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb
index fc2793a72e7..28d9bf01cce 100644
--- a/app/controllers/admin/projects_controller.rb
+++ b/app/controllers/admin/projects_controller.rb
@@ -1,4 +1,4 @@
-class Admin::ProjectsController < AdminController
+class Admin::ProjectsController < Admin::ApplicationController
   before_filter :project, only: [:edit, :show, :update, :destroy, :team_update]
 
   def index
diff --git a/app/controllers/admin/resque_controller.rb b/app/controllers/admin/resque_controller.rb
index 9d8e7e3051f..7d489ab4876 100644
--- a/app/controllers/admin/resque_controller.rb
+++ b/app/controllers/admin/resque_controller.rb
@@ -1,4 +1,4 @@
-class Admin::ResqueController < AdminController
+class Admin::ResqueController < Admin::ApplicationController
   def show
   end
 end
diff --git a/app/controllers/admin/team_members_controller.rb b/app/controllers/admin/team_members_controller.rb
index 073208057ca..3c85681cf66 100644
--- a/app/controllers/admin/team_members_controller.rb
+++ b/app/controllers/admin/team_members_controller.rb
@@ -1,4 +1,4 @@
-class Admin::TeamMembersController < AdminController
+class Admin::TeamMembersController < Admin::ApplicationController
   def edit
     @admin_team_member = UsersProject.find(params[:id])
   end
diff --git a/app/controllers/admin/teams_controller.rb b/app/controllers/admin/teams_controller.rb
index fd25d3fe219..5d9356e9095 100644
--- a/app/controllers/admin/teams_controller.rb
+++ b/app/controllers/admin/teams_controller.rb
@@ -1,4 +1,4 @@
-class Admin::TeamsController < AdminController
+class Admin::TeamsController < Admin::ApplicationController
   before_filter :user_team,
                 only: [ :edit, :show, :update, :destroy,
                         :delegate_projects, :relegate_project,
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index 8669f5d1d38..659dd2f2ab0 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -1,4 +1,4 @@
-class Admin::UsersController < AdminController
+class Admin::UsersController < Admin::ApplicationController
   def index
     @admin_users = User.scoped
     @admin_users = @admin_users.filter(params[:filter])
-- 
GitLab


From 9804b7df68a0ba4a1b144bc652351ad77a38fc3f Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Sun, 20 Jan 2013 15:25:16 +0400
Subject: [PATCH 042/197] Move admin team members management to own controller

---
 .../admin/teams/application_controller.rb     | 12 +++++
 .../admin/teams/members_controller.rb         | 35 +++++++++++++++
 app/models/user_team.rb                       |  4 ++
 app/views/admin/teams/members/_form.html.haml | 20 +++++++++
 app/views/admin/teams/members/edit.html.haml  | 16 +++++++
 app/views/admin/teams/members/new.html.haml   | 29 ++++++++++++
 app/views/admin/teams/show.html.haml          | 45 +++++++++----------
 config/routes.rb                              |  3 ++
 lib/gitlab/user_team_manager.rb               | 32 +++++++++++++
 9 files changed, 173 insertions(+), 23 deletions(-)
 create mode 100644 app/controllers/admin/teams/application_controller.rb
 create mode 100644 app/controllers/admin/teams/members_controller.rb
 create mode 100644 app/views/admin/teams/members/_form.html.haml
 create mode 100644 app/views/admin/teams/members/edit.html.haml
 create mode 100644 app/views/admin/teams/members/new.html.haml

diff --git a/app/controllers/admin/teams/application_controller.rb b/app/controllers/admin/teams/application_controller.rb
new file mode 100644
index 00000000000..a2920b626b5
--- /dev/null
+++ b/app/controllers/admin/teams/application_controller.rb
@@ -0,0 +1,12 @@
+# Provides a base class for Admin controllers to subclass
+#
+# Automatically sets the layout and ensures an administrator is logged in
+class Admin::Teams::ApplicationController < Admin::ApplicationController
+  before_filter :user_team
+
+  private
+
+  def user_team
+    @team = UserTeam.find_by_path(params[:team_id])
+  end
+end
diff --git a/app/controllers/admin/teams/members_controller.rb b/app/controllers/admin/teams/members_controller.rb
new file mode 100644
index 00000000000..4037bff510e
--- /dev/null
+++ b/app/controllers/admin/teams/members_controller.rb
@@ -0,0 +1,35 @@
+class Admin::Teams::MembersController < Admin::Teams::ApplicationController
+  def new
+    @users = User.active
+    @users = @users.not_in_team(@team) if @team.members.any?
+    @users = UserDecorator.decorate @users
+  end
+
+  def create
+    unless params[:user_ids].blank?
+      user_ids = params[:user_ids]
+      access = params[:default_project_access]
+      is_admin = params[:group_admin]
+      @team.add_members(user_ids, access, is_admin)
+    end
+
+    redirect_to admin_team_path(@team), notice: 'Members was successfully added.'
+  end
+
+  def edit
+    @member = @team.members.find(params[:id])
+  end
+
+  def update
+    @member = @team.members.find(params[:id])
+    options = {default_projects_access: params[:default_project_access], group_admin: params[:group_admin]}
+    if @team.update_membership(@member, options)
+      redirect_to admin_team_path(@team), notice: 'Membership was successfully updated.'
+    else
+      render :edit
+    end
+  end
+
+  def destroy
+  end
+end
diff --git a/app/models/user_team.rb b/app/models/user_team.rb
index d402fd22ea3..c9dfd671efc 100644
--- a/app/models/user_team.rb
+++ b/app/models/user_team.rb
@@ -64,6 +64,10 @@ class UserTeam < ActiveRecord::Base
     Gitlab::UserTeamManager.remove_member_from_team(self, user)
   end
 
+  def update_membership(user, options)
+    Gitlab::UserTeamManager.update_team_user_membership(self, user, options)
+  end
+
   def max_project_access(project)
     user_team_project_relationships.find_by_project_id(project).greatest_access
   end
diff --git a/app/views/admin/teams/members/_form.html.haml b/app/views/admin/teams/members/_form.html.haml
new file mode 100644
index 00000000000..b75d788a94a
--- /dev/null
+++ b/app/views/admin/teams/members/_form.html.haml
@@ -0,0 +1,20 @@
+= form_tag admin_team_member_path(@team, @member), method: :put do
+  -if @member.errors.any?
+    .alert-message.block-message.error
+      %ul
+        - @member.errors.full_messages.each do |msg|
+          %li= msg
+
+  .clearfix
+    %label Default access for Team projects:
+    .input
+      = select_tag :default_project_access, options_for_select(UserTeam.access_roles, @team.default_projects_access(@member)), class: "project-access-select chosen span3"
+  .clearfix
+    %label Team admin?
+    .input
+      = check_box_tag :group_admin, true, @team.admin?(@member)
+
+  %br
+  .actions
+    = submit_tag 'Save', class: "btn primary"
+    = link_to 'Cancel', :back, class: "btn"
diff --git a/app/views/admin/teams/members/edit.html.haml b/app/views/admin/teams/members/edit.html.haml
new file mode 100644
index 00000000000..a82847ee5f8
--- /dev/null
+++ b/app/views/admin/teams/members/edit.html.haml
@@ -0,0 +1,16 @@
+%h3
+  Edit access #{@member.name} in #{@team.name} team
+
+%hr
+%table.zebra-striped
+  %tr
+    %td User:
+    %td= @member.name
+  %tr
+    %td Team:
+    %td= @team.name
+  %tr
+    %td Since:
+    %td= member_since(@team, @member).stamp("Nov 11, 2010")
+
+= render 'form'
diff --git a/app/views/admin/teams/members/new.html.haml b/app/views/admin/teams/members/new.html.haml
new file mode 100644
index 00000000000..5cdf07359c8
--- /dev/null
+++ b/app/views/admin/teams/members/new.html.haml
@@ -0,0 +1,29 @@
+%h3.page_title
+  Team: #{@team.name}
+
+%fieldset
+  %legend Members (#{@team.members.count})
+  = form_tag add_members_admin_team_path(@team), id: "team_members", class: "bulk_import", method: :post  do
+    %table#members_list
+      %thead
+        %tr
+          %th User name
+          %th Default project access
+          %th Team access
+          %th
+      - @team.members.each do |member|
+        %tr.member
+          %td
+            = link_to [:admin, member] do
+              = member.name
+              %small= "(#{member.email})"
+          %td= @team.human_default_projects_access(member)
+          %td= @team.admin?(member) ? "Admin" : "Member"
+          %td
+      %tr
+        %td= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name_with_email), multiple: true, data: {placeholder: 'Select users'}, class: 'chosen span5'
+        %td= select_tag :default_project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3" }
+        %td
+          %span= check_box_tag :group_admin
+          %span Admin?
+        %td= submit_tag 'Add', class: "btn primary", id: :add_members_to_team
diff --git a/app/views/admin/teams/show.html.haml b/app/views/admin/teams/show.html.haml
index 0f47717ae0e..05a3a1d3e16 100644
--- a/app/views/admin/teams/show.html.haml
+++ b/app/views/admin/teams/show.html.haml
@@ -41,31 +41,30 @@
 
 %fieldset
   %legend Members (#{@team.members.count})
-  = form_tag add_members_admin_team_path(@team), id: "team_members", class: "bulk_import", method: :post  do
-    %table#members_list
-      %thead
-        %tr
-          %th User name
-          %th Default project access
-          %th Team access
-          %th.cred Danger Zone!
-      - @team.members.each do |member|
-        %tr.member
-          %td
-            = link_to [:admin, member] do
-              = member.name
-              %small= "(#{member.email})"
-          %td= @team.human_default_projects_access(member)
-          %td= @team.admin?(member) ? "Admin" : "Member"
-          %td.bgred
-            = link_to 'Remove', remove_member_admin_team_path(@team, member_id: member.id), confirm: 'Remove project from team and move to global namespace. Are you sure?', method: :delete, class: "btn danger small"
+  %table#members_list
+    %thead
       %tr
-        %td= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name_with_email), multiple: true, data: {placeholder: 'Select users'}, class: 'chosen span5'
-        %td= select_tag :default_project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3" }
+        %th User name
+        %th Default project access
+        %th Team access
+        %th.cred Danger Zone!
+    - @team.members.each do |member|
+      %tr.member
         %td
-          %span= check_box_tag :group_admin
-          %span Admin?
-        %td= submit_tag 'Add', class: "btn primary", id: :add_members_to_team
+          = link_to [:admin, member] do
+            = member.name
+            %small= "(#{member.email})"
+        %td= @team.human_default_projects_access(member)
+        %td= @team.admin?(member) ? "Admin" : "Member"
+        %td.bgred
+          = link_to 'Edit', edit_admin_team_member_path(@team, member), class: "btn small"
+          &nbsp;
+          = link_to 'Remove', admin_team_member_path(@team, member), confirm: 'Remove member from team. Are you sure?', method: :delete, class: "btn danger small"
+    %tr
+      %td
+      %td
+      %td
+      %td= link_to 'Add members', new_admin_team_member_path(@team), class: "btn primary", id: :add_members_to_team
 
 %fieldset
   %legend Projects (#{@team.projects.count})
diff --git a/config/routes.rb b/config/routes.rb
index 69ad2e68642..b15431e3455 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -77,6 +77,9 @@ Gitlab::Application.routes.draw do
         post :add_members
         delete :remove_member
       end
+      scope module: :teams do
+        resources :members, only: [:edit, :update, :destroy, :new, :create]
+      end
     end
     resources :team_members, only: [:edit, :update, :destroy]
     resources :hooks, only: [:index, :create, :destroy] do
diff --git a/lib/gitlab/user_team_manager.rb b/lib/gitlab/user_team_manager.rb
index d010c79223e..753081ea718 100644
--- a/lib/gitlab/user_team_manager.rb
+++ b/lib/gitlab/user_team_manager.rb
@@ -22,6 +22,38 @@ module Gitlab
         update_team_users_access_in_project(team, project)
       end
 
+      def update_team_user_membership(team, member, options)
+        updates = {}
+
+        if options[:default_projects_access] && options[:default_projects_access] != team.default_projects_access(member)
+          updates[:permission] = options[:default_projects_access]
+        end
+
+        if options[:group_admin].to_s != team.admin?(member).to_s
+          updates[:group_admin] = options[:group_admin].present?
+        end
+
+        unless updates.blank?
+          user_team_relationship = team.user_team_user_relationships.find_by_user_id(member)
+          if user_team_relationship.update_attributes(updates)
+            if updates[:permission]
+              rebuild_project_permissions_to_member(team, member)
+            end
+            true
+          else
+            false
+          end
+        else
+          true
+        end
+      end
+
+      def rebuild_project_permissions_to_member(team, member)
+        team.projects.each do |project|
+          update_team_user_access_in_project(team, member, project)
+        end
+      end
+
       def update_team_users_access_in_project(team, project)
         members = team.members
         members.each do |member|
-- 
GitLab


From cca993597013e1359d84230b0f69a2e02edb8e97 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Sun, 20 Jan 2013 15:25:45 +0400
Subject: [PATCH 043/197] save generated files

---
 .../javascripts/admin/teams/members.js.coffee |  3 ++
 .../stylesheets/admin/teams/members.css.scss  |  3 ++
 app/helpers/admin/teams/members_helper.rb     |  5 +++
 config/routes.rb                              |  1 -
 .../admin/teams/members_controller_spec.rb    | 40 +++++++++++++++++++
 .../admin/teams/members_helper_spec.rb        | 15 +++++++
 .../teams/members/create.html.haml_spec.rb    |  5 +++
 .../teams/members/destroy.html.haml_spec.rb   |  5 +++
 .../teams/members/edit.html.haml_spec.rb      |  5 +++
 .../admin/teams/members/new.html.haml_spec.rb |  5 +++
 .../teams/members/update.html.haml_spec.rb    |  5 +++
 11 files changed, 91 insertions(+), 1 deletion(-)
 create mode 100644 app/assets/javascripts/admin/teams/members.js.coffee
 create mode 100644 app/assets/stylesheets/admin/teams/members.css.scss
 create mode 100644 app/helpers/admin/teams/members_helper.rb
 create mode 100644 spec/controllers/admin/teams/members_controller_spec.rb
 create mode 100644 spec/helpers/admin/teams/members_helper_spec.rb
 create mode 100644 spec/views/admin/teams/members/create.html.haml_spec.rb
 create mode 100644 spec/views/admin/teams/members/destroy.html.haml_spec.rb
 create mode 100644 spec/views/admin/teams/members/edit.html.haml_spec.rb
 create mode 100644 spec/views/admin/teams/members/new.html.haml_spec.rb
 create mode 100644 spec/views/admin/teams/members/update.html.haml_spec.rb

diff --git a/app/assets/javascripts/admin/teams/members.js.coffee b/app/assets/javascripts/admin/teams/members.js.coffee
new file mode 100644
index 00000000000..761567942fc
--- /dev/null
+++ b/app/assets/javascripts/admin/teams/members.js.coffee
@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
diff --git a/app/assets/stylesheets/admin/teams/members.css.scss b/app/assets/stylesheets/admin/teams/members.css.scss
new file mode 100644
index 00000000000..47c2273c1c2
--- /dev/null
+++ b/app/assets/stylesheets/admin/teams/members.css.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the Admin::Teams::Members controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/app/helpers/admin/teams/members_helper.rb b/app/helpers/admin/teams/members_helper.rb
new file mode 100644
index 00000000000..58b9f1896c4
--- /dev/null
+++ b/app/helpers/admin/teams/members_helper.rb
@@ -0,0 +1,5 @@
+module Admin::Teams::MembersHelper
+  def member_since(team, member)
+    team.user_team_user_relationships.find_by_user_id(member).created_at
+  end
+end
diff --git a/config/routes.rb b/config/routes.rb
index b15431e3455..a31d0e7797d 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,7 +1,6 @@
 require 'sidekiq/web'
 
 Gitlab::Application.routes.draw do
-
   #
   # Search
   #
diff --git a/spec/controllers/admin/teams/members_controller_spec.rb b/spec/controllers/admin/teams/members_controller_spec.rb
new file mode 100644
index 00000000000..a9e41be59f7
--- /dev/null
+++ b/spec/controllers/admin/teams/members_controller_spec.rb
@@ -0,0 +1,40 @@
+require 'spec_helper'
+
+describe Admin::Teams::MembersController do
+
+  describe "GET 'new'" do
+    it "returns http success" do
+      get 'new'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'create'" do
+    it "returns http success" do
+      get 'create'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'edit'" do
+    it "returns http success" do
+      get 'edit'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'update'" do
+    it "returns http success" do
+      get 'update'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'destroy'" do
+    it "returns http success" do
+      get 'destroy'
+      response.should be_success
+    end
+  end
+
+end
diff --git a/spec/helpers/admin/teams/members_helper_spec.rb b/spec/helpers/admin/teams/members_helper_spec.rb
new file mode 100644
index 00000000000..ceef71c0be6
--- /dev/null
+++ b/spec/helpers/admin/teams/members_helper_spec.rb
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+# Specs in this file have access to a helper object that includes
+# the Admin::Teams::MembersHelper. For example:
+#
+# describe Admin::Teams::MembersHelper do
+#   describe "string concat" do
+#     it "concats two strings with spaces" do
+#       helper.concat_strings("this","that").should == "this that"
+#     end
+#   end
+# end
+describe Admin::Teams::MembersHelper do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/admin/teams/members/create.html.haml_spec.rb b/spec/views/admin/teams/members/create.html.haml_spec.rb
new file mode 100644
index 00000000000..b6f817617e4
--- /dev/null
+++ b/spec/views/admin/teams/members/create.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "members/create.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/admin/teams/members/destroy.html.haml_spec.rb b/spec/views/admin/teams/members/destroy.html.haml_spec.rb
new file mode 100644
index 00000000000..3ff1634461c
--- /dev/null
+++ b/spec/views/admin/teams/members/destroy.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "members/destroy.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/admin/teams/members/edit.html.haml_spec.rb b/spec/views/admin/teams/members/edit.html.haml_spec.rb
new file mode 100644
index 00000000000..3e952e898a9
--- /dev/null
+++ b/spec/views/admin/teams/members/edit.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "members/edit.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/admin/teams/members/new.html.haml_spec.rb b/spec/views/admin/teams/members/new.html.haml_spec.rb
new file mode 100644
index 00000000000..f03eed1f29f
--- /dev/null
+++ b/spec/views/admin/teams/members/new.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "members/new.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/admin/teams/members/update.html.haml_spec.rb b/spec/views/admin/teams/members/update.html.haml_spec.rb
new file mode 100644
index 00000000000..43b84bad99b
--- /dev/null
+++ b/spec/views/admin/teams/members/update.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "members/update.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
-- 
GitLab


From b7470440ffbc9cb9f58f9de4b3064760670a20a4 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Mon, 21 Jan 2013 01:03:29 +0400
Subject: [PATCH 044/197] Move team project management to own controller

---
 .../admin/teams/projects_controller.rb        | 42 +++++++++++++++++++
 app/helpers/admin/teams/projects_helper.rb    |  5 +++
 app/models/user_team.rb                       |  4 ++
 .../admin/teams/projects/_form.html.haml      | 16 +++++++
 app/views/admin/teams/projects/edit.html.haml | 16 +++++++
 app/views/admin/teams/projects/new.html.haml  | 23 ++++++++++
 config/routes.rb                              |  1 +
 lib/gitlab/user_team_manager.rb               | 14 +++++++
 8 files changed, 121 insertions(+)
 create mode 100644 app/controllers/admin/teams/projects_controller.rb
 create mode 100644 app/helpers/admin/teams/projects_helper.rb
 create mode 100644 app/views/admin/teams/projects/_form.html.haml
 create mode 100644 app/views/admin/teams/projects/edit.html.haml
 create mode 100644 app/views/admin/teams/projects/new.html.haml

diff --git a/app/controllers/admin/teams/projects_controller.rb b/app/controllers/admin/teams/projects_controller.rb
new file mode 100644
index 00000000000..74e566191b1
--- /dev/null
+++ b/app/controllers/admin/teams/projects_controller.rb
@@ -0,0 +1,42 @@
+class Admin::Teams::ProjectsController < Admin::Teams::ApplicationController
+  before_filter :team_project, only: [:edit, :destroy, :update]
+
+  def new
+    @projects = Project.scoped
+    @projects = @projects.without_team(@team) if @team.projects.any?
+    #@projects.reject!(&:empty_repo?)
+  end
+
+  def create
+    unless params[:project_ids].blank?
+      project_ids = params[:project_ids]
+      access = params[:greatest_project_access]
+      @team.assign_to_projects(project_ids, access)
+    end
+
+    redirect_to admin_team_path(@team), notice: 'Projects was successfully added.'
+  end
+
+  def edit
+  end
+
+  def update
+    if @team.update_project_access(@project, params[:greatest_project_access])
+      redirect_to admin_team_path(@team), notice: 'Membership was successfully updated.'
+    else
+      render :edit
+    end
+  end
+
+  def destroy
+    @team.resign_from_project(@project)
+    redirect_to admin_team_path(@team), notice: 'Project was successfully removed.'
+  end
+
+  private
+
+  def team_project
+    @project = @team.projects.find_by_path(params[:id])
+  end
+
+end
diff --git a/app/helpers/admin/teams/projects_helper.rb b/app/helpers/admin/teams/projects_helper.rb
new file mode 100644
index 00000000000..b97cc403337
--- /dev/null
+++ b/app/helpers/admin/teams/projects_helper.rb
@@ -0,0 +1,5 @@
+module Admin::Teams::ProjectsHelper
+  def assigned_since(team, project)
+    team.user_team_project_relationships.find_by_project_id(project).created_at
+  end
+end
diff --git a/app/models/user_team.rb b/app/models/user_team.rb
index c9dfd671efc..2e2f75060c3 100644
--- a/app/models/user_team.rb
+++ b/app/models/user_team.rb
@@ -68,6 +68,10 @@ class UserTeam < ActiveRecord::Base
     Gitlab::UserTeamManager.update_team_user_membership(self, user, options)
   end
 
+  def update_project_access(project, permission)
+    Gitlab::UserTeamManager.update_project_greates_access(self, project, permission)
+  end
+
   def max_project_access(project)
     user_team_project_relationships.find_by_project_id(project).greatest_access
   end
diff --git a/app/views/admin/teams/projects/_form.html.haml b/app/views/admin/teams/projects/_form.html.haml
new file mode 100644
index 00000000000..db4fe85b000
--- /dev/null
+++ b/app/views/admin/teams/projects/_form.html.haml
@@ -0,0 +1,16 @@
+= form_tag admin_team_project_path(@team, @project), method: :put do
+  -if @project.errors.any?
+    .alert-message.block-message.error
+      %ul
+        - @project.errors.full_messages.each do |msg|
+          %li= msg
+
+  .clearfix
+    %label Max access for Team members:
+    .input
+      = select_tag :greatest_project_access, options_for_select(UserTeam.access_roles, @team.max_project_access(@project)), class: "project-access-select chosen span3"
+
+  %br
+  .actions
+    = submit_tag 'Save', class: "btn primary"
+    = link_to 'Cancel', :back, class: "btn"
diff --git a/app/views/admin/teams/projects/edit.html.haml b/app/views/admin/teams/projects/edit.html.haml
new file mode 100644
index 00000000000..b91a4982b81
--- /dev/null
+++ b/app/views/admin/teams/projects/edit.html.haml
@@ -0,0 +1,16 @@
+%h3
+  Edit max access in #{@project.name} for #{@team.name} team
+
+%hr
+%table.zebra-striped
+  %tr
+    %td Project:
+    %td= @project.name
+  %tr
+    %td Team:
+    %td= @team.name
+  %tr
+    %td Since:
+    %td= assigned_since(@team, @project).stamp("Nov 11, 2010")
+
+= render 'form'
diff --git a/app/views/admin/teams/projects/new.html.haml b/app/views/admin/teams/projects/new.html.haml
new file mode 100644
index 00000000000..8a0a18a48c0
--- /dev/null
+++ b/app/views/admin/teams/projects/new.html.haml
@@ -0,0 +1,23 @@
+%h3.page_title
+  Team: #{@team.name}
+
+%fieldset
+  %legend Projects (#{@team.projects.count})
+  = form_tag admin_team_projects_path(@team), id: "assign_projects", class: "bulk_import", method: :post  do
+    %table#projects_list
+      %thead
+        %tr
+          %th Project name
+          %th Max access
+          %th
+      - @team.projects.each do |project|
+        %tr.project
+          %td
+            = link_to project.name_with_namespace, [:admin, project]
+          %td
+            %span= @team.human_max_project_access(project)
+          %td
+      %tr
+        %td= select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name_with_namespace), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5'
+        %td= select_tag :greatest_project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3" }
+        %td= submit_tag 'Add', class: "btn primary", id: :assign_projects_to_team
diff --git a/config/routes.rb b/config/routes.rb
index a31d0e7797d..3132c310c99 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -78,6 +78,7 @@ Gitlab::Application.routes.draw do
       end
       scope module: :teams do
         resources :members, only: [:edit, :update, :destroy, :new, :create]
+        resources :projects, only: [:edit, :update, :destroy, :new, :create]
       end
     end
     resources :team_members, only: [:edit, :update, :destroy]
diff --git a/lib/gitlab/user_team_manager.rb b/lib/gitlab/user_team_manager.rb
index 753081ea718..7d9a9bdf3f5 100644
--- a/lib/gitlab/user_team_manager.rb
+++ b/lib/gitlab/user_team_manager.rb
@@ -48,6 +48,20 @@ module Gitlab
         end
       end
 
+      def update_project_greates_access(team, project, permission)
+        project_relation = team.user_team_project_relationships.find_by_project_id(project)
+        if permission != team.max_project_access(project)
+          if project_relation.update_attributes(greatest_access: permission)
+            update_team_users_access_in_project(team, project)
+            true
+          else
+            false
+          end
+        else
+          true
+        end
+      end
+
       def rebuild_project_permissions_to_member(team, member)
         team.projects.each do |project|
           update_team_user_access_in_project(team, member, project)
-- 
GitLab


From a7667ffc14017732228058e34e1f724be08bf9a0 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Mon, 21 Jan 2013 01:04:53 +0400
Subject: [PATCH 045/197] Repair members management of teams

---
 .../admin/teams/members_controller.rb         | 15 +++++++-
 app/views/admin/teams/members/new.html.haml   |  2 +-
 app/views/admin/teams/show.html.haml          | 37 ++++++++++---------
 3 files changed, 33 insertions(+), 21 deletions(-)

diff --git a/app/controllers/admin/teams/members_controller.rb b/app/controllers/admin/teams/members_controller.rb
index 4037bff510e..6795a520bb3 100644
--- a/app/controllers/admin/teams/members_controller.rb
+++ b/app/controllers/admin/teams/members_controller.rb
@@ -1,4 +1,6 @@
 class Admin::Teams::MembersController < Admin::Teams::ApplicationController
+  before_filter :team_member, only: [:edit, :destroy, :update]
+
   def new
     @users = User.active
     @users = @users.not_in_team(@team) if @team.members.any?
@@ -17,11 +19,9 @@ class Admin::Teams::MembersController < Admin::Teams::ApplicationController
   end
 
   def edit
-    @member = @team.members.find(params[:id])
   end
 
   def update
-    @member = @team.members.find(params[:id])
     options = {default_projects_access: params[:default_project_access], group_admin: params[:group_admin]}
     if @team.update_membership(@member, options)
       redirect_to admin_team_path(@team), notice: 'Membership was successfully updated.'
@@ -31,5 +31,16 @@ class Admin::Teams::MembersController < Admin::Teams::ApplicationController
   end
 
   def destroy
+    if @team.remove_member(@member)
+      redirect_to admin_team_path(@team), notice: "Member was successfully removed from team."
+    else
+      redirect_to admin_team_members(@team), notice: "Something wrong."
+    end
+  end
+
+  private
+
+  def team_member
+    @member = @team.members.find(params[:id])
   end
 end
diff --git a/app/views/admin/teams/members/new.html.haml b/app/views/admin/teams/members/new.html.haml
index 5cdf07359c8..066ab19fd08 100644
--- a/app/views/admin/teams/members/new.html.haml
+++ b/app/views/admin/teams/members/new.html.haml
@@ -3,7 +3,7 @@
 
 %fieldset
   %legend Members (#{@team.members.count})
-  = form_tag add_members_admin_team_path(@team), id: "team_members", class: "bulk_import", method: :post  do
+  = form_tag admin_team_members_path(@team), id: "team_members", class: "bulk_import", method: :post  do
     %table#members_list
       %thead
         %tr
diff --git a/app/views/admin/teams/show.html.haml b/app/views/admin/teams/show.html.haml
index 05a3a1d3e16..2bb9c02af7e 100644
--- a/app/views/admin/teams/show.html.haml
+++ b/app/views/admin/teams/show.html.haml
@@ -68,25 +68,26 @@
 
 %fieldset
   %legend Projects (#{@team.projects.count})
-  = form_tag delegate_projects_admin_team_path(@team), id: "assign_projects", class: "bulk_import", method: :post  do
-    %table#projects_list
-      %thead
-        %tr
-          %th Project name
-          %th Max access
-          %th.cred Danger Zone!
-      - @team.projects.each do |project|
-        %tr.project
-          %td
-            = link_to project.name_with_namespace, [:admin, project]
-          %td
-            %span= @team.human_max_project_access(project)
-          %td.bgred
-            = link_to 'Relegate', relegate_project_admin_team_path(@team, project_id: project.id), confirm: 'Remove project from team and move to global namespace. Are you sure?', method: :delete, class: "btn danger small"
+  %table#projects_list
+    %thead
       %tr
-        %td= select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name_with_namespace), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5'
-        %td= select_tag :greatest_project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3" }
-        %td= submit_tag 'Add', class: "btn primary", id: :assign_projects_to_team
+        %th Project name
+        %th Max access
+        %th.cred Danger Zone!
+    - @team.projects.each do |project|
+      %tr.project
+        %td
+          = link_to project.name_with_namespace, [:admin, project]
+        %td
+          %span= @team.human_max_project_access(project)
+        %td.bgred
+          = link_to 'Edit', edit_admin_team_project_path(@team, project), class: "btn small"
+          &nbsp;
+          = link_to 'Relegate', admin_team_project_path(@team, project), confirm: 'Remove project from team. Are you sure?', method: :delete, class: "btn danger small"
+    %tr
+      %td
+      %td
+      %td= link_to 'Add projects', new_admin_team_project_path(@team), class: "btn primary", id: :assign_projects_to_team
 
 :javascript
   $(function(){
-- 
GitLab


From 17a8ee57fe7a2c2b7c18c59f88828be9d5a455a0 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Mon, 21 Jan 2013 01:05:51 +0400
Subject: [PATCH 046/197] Remove old data

---
 app/controllers/admin/teams_controller.rb | 35 -----------------------
 app/models/users_project.rb               |  2 +-
 config/routes.rb                          |  6 ----
 3 files changed, 1 insertion(+), 42 deletions(-)

diff --git a/app/controllers/admin/teams_controller.rb b/app/controllers/admin/teams_controller.rb
index 5d9356e9095..ee9141e371c 100644
--- a/app/controllers/admin/teams_controller.rb
+++ b/app/controllers/admin/teams_controller.rb
@@ -60,41 +60,6 @@ class Admin::TeamsController < Admin::ApplicationController
     redirect_to admin_user_teams_path, notice: 'UserTeam was successfully deleted.'
   end
 
-  def delegate_projects
-    unless params[:project_ids].blank?
-      project_ids = params[:project_ids]
-      access = params[:greatest_project_access]
-      @team.assign_to_projects(project_ids, access)
-    end
-
-    redirect_to admin_team_path(@team), notice: 'Projects was successfully added.'
-  end
-
-  def relegate_project
-    project = params[:project_id]
-    @team.resign_from_project(project)
-
-    redirect_to admin_team_path(@team), notice: 'Project was successfully removed.'
-  end
-
-  def add_members
-    unless params[:user_ids].blank?
-      user_ids = params[:user_ids]
-      access = params[:default_project_access]
-      is_admin = params[:group_admin]
-      @team.add_members(user_ids, access, is_admin)
-    end
-
-    redirect_to admin_team_path(@team), notice: 'Members was successfully added.'
-  end
-
-  def remove_member
-    member = params[:member_id]
-    @team.remove_member(member)
-
-    redirect_to admin_team_path(@team), notice: 'Member was successfully removed.'
-  end
-
   private
 
   def user_team
diff --git a/app/models/users_project.rb b/app/models/users_project.rb
index d282b2acbfc..ca5048ca7d4 100644
--- a/app/models/users_project.rb
+++ b/app/models/users_project.rb
@@ -41,7 +41,7 @@ class UsersProject < ActiveRecord::Base
   scope :masters, where(project_access: MASTER)
 
   scope :in_project, ->(project) { where(project_id: project.id) }
-  scope :in_projects, ->(projects) { where(project_id: projects.map(&:id)) }
+  scope :in_projects, ->(projects) { where(project_id: project_ids) }
   scope :with_user, ->(user) { where(user_id: user.id) }
 
   class << self
diff --git a/config/routes.rb b/config/routes.rb
index 3132c310c99..21bfc89c24c 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -70,12 +70,6 @@ Gitlab::Application.routes.draw do
       end
     end
     resources :teams do #, constraints: { id: /[^\/]+/ } do end
-      member do
-        post :delegate_projects
-        delete :relegate_project
-        post :add_members
-        delete :remove_member
-      end
       scope module: :teams do
         resources :members, only: [:edit, :update, :destroy, :new, :create]
         resources :projects, only: [:edit, :update, :destroy, :new, :create]
-- 
GitLab


From 13fb3fdcf20f505b2591cfe3fc1a1e74242a932c Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Mon, 21 Jan 2013 01:06:11 +0400
Subject: [PATCH 047/197] Repair admin section tests

---
 features/admin/teams.feature        | 4 +++-
 features/steps/admin/admin_teams.rb | 8 ++++++++
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/features/admin/teams.feature b/features/admin/teams.feature
index e070a90ae02..6ca7c4cbe02 100644
--- a/features/admin/teams.feature
+++ b/features/admin/teams.feature
@@ -17,7 +17,7 @@ Feature: Admin Teams
     When I visit admin teams page
     When I have clean "HardCoders" team
     And I visit "HardCoders" team page
-    #Then I should see only me in members table
+    When I click to "Add members" link
     When I select user "John" from user list as "Developer"
     And submit form with new team member info
     Then I should see "John" in teams members list as "Developer"
@@ -30,6 +30,7 @@ Feature: Admin Teams
     When I have "Shop" project
     And I visit "HardCoders" team page
     Then I should see empty projects table
+    When I click to "Add projects" link
     When I select project "Shop" with max access "Reporter"
     And submit form with new team project info
     Then I should see "Shop" project in projects list
@@ -43,6 +44,7 @@ Feature: Admin Teams
     When I have gitlab user "Jimm"
     And I visit "HardCoders" team page
     Then I should see members table without "Jimm" member
+    When I click to "Add members" link
     When I select user "Jimm" ub team members list as "Master"
     And submit form with new team member info
     Then I should see "Jimm" in teams members list as "Master"
diff --git a/features/steps/admin/admin_teams.rb b/features/steps/admin/admin_teams.rb
index bba60ec496b..a1221cd1a8c 100644
--- a/features/steps/admin/admin_teams.rb
+++ b/features/steps/admin/admin_teams.rb
@@ -205,6 +205,14 @@ class AdminTeams < Spinach::FeatureSteps
     find_in_list(".team_members", user).must_equal true
   end
 
+  When 'I click to "Add members" link' do
+    click_link "Add members"
+  end
+
+  When 'I click to "Add projects" link' do
+    click_link "Add projects"
+  end
+
   protected
 
   def current_team
-- 
GitLab


From b8dadd6427e50aa6d4f8f5dee113518340495550 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Mon, 21 Jan 2013 01:07:17 +0400
Subject: [PATCH 048/197] repair rspec (remove and rename files)

---
 spec/helpers/admin/teams_helper_spec.rb           | 15 ---------------
 spec/helpers/teams/members_helper_spec.rb         | 15 ---------------
 spec/helpers/teams/projects_helper_spec.rb        | 15 ---------------
 spec/helpers/teams_helper_spec.rb                 | 15 ---------------
 .../models/{team_spec.rb => project_team_spec.rb} |  2 +-
 5 files changed, 1 insertion(+), 61 deletions(-)
 delete mode 100644 spec/helpers/admin/teams_helper_spec.rb
 delete mode 100644 spec/helpers/teams/members_helper_spec.rb
 delete mode 100644 spec/helpers/teams/projects_helper_spec.rb
 delete mode 100644 spec/helpers/teams_helper_spec.rb
 rename spec/models/{team_spec.rb => project_team_spec.rb} (94%)

diff --git a/spec/helpers/admin/teams_helper_spec.rb b/spec/helpers/admin/teams_helper_spec.rb
deleted file mode 100644
index 5ed6073297b..00000000000
--- a/spec/helpers/admin/teams_helper_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-require 'spec_helper'
-
-# Specs in this file have access to a helper object that includes
-# the Admin::TeamsHelper. For example:
-#
-# describe Admin::TeamsHelper do
-#   describe "string concat" do
-#     it "concats two strings with spaces" do
-#       helper.concat_strings("this","that").should == "this that"
-#     end
-#   end
-# end
-describe Admin::TeamsHelper do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/helpers/teams/members_helper_spec.rb b/spec/helpers/teams/members_helper_spec.rb
deleted file mode 100644
index a8e227aa063..00000000000
--- a/spec/helpers/teams/members_helper_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-require 'spec_helper'
-
-# Specs in this file have access to a helper object that includes
-# the Teams::MembersHelper. For example:
-#
-# describe Teams::MembersHelper do
-#   describe "string concat" do
-#     it "concats two strings with spaces" do
-#       helper.concat_strings("this","that").should == "this that"
-#     end
-#   end
-# end
-describe Teams::MembersHelper do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/helpers/teams/projects_helper_spec.rb b/spec/helpers/teams/projects_helper_spec.rb
deleted file mode 100644
index 836d1dca018..00000000000
--- a/spec/helpers/teams/projects_helper_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-require 'spec_helper'
-
-# Specs in this file have access to a helper object that includes
-# the Teams::ProjectsHelper. For example:
-#
-# describe Teams::ProjectsHelper do
-#   describe "string concat" do
-#     it "concats two strings with spaces" do
-#       helper.concat_strings("this","that").should == "this that"
-#     end
-#   end
-# end
-describe Teams::ProjectsHelper do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/helpers/teams_helper_spec.rb b/spec/helpers/teams_helper_spec.rb
deleted file mode 100644
index 95726163e35..00000000000
--- a/spec/helpers/teams_helper_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-require 'spec_helper'
-
-# Specs in this file have access to a helper object that includes
-# the TeamsHelper. For example:
-#
-# describe TeamsHelper do
-#   describe "string concat" do
-#     it "concats two strings with spaces" do
-#       helper.concat_strings("this","that").should == "this that"
-#     end
-#   end
-# end
-describe TeamsHelper do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/models/team_spec.rb b/spec/models/project_team_spec.rb
similarity index 94%
rename from spec/models/team_spec.rb
rename to spec/models/project_team_spec.rb
index 65ffe13b490..7803811f395 100644
--- a/spec/models/team_spec.rb
+++ b/spec/models/project_team_spec.rb
@@ -1,6 +1,6 @@
 require "spec_helper"
 
-describe Team do
+describe ProjectTeam do
   let(:team) { create(:project).team }
 
   describe "Respond to" do
-- 
GitLab


From 497f7ab5ba11bcb9d663c86e74326d8116125e18 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Mon, 21 Jan 2013 01:07:28 +0400
Subject: [PATCH 049/197] save autogenerated files

---
 .../admin/teams/projects.js.coffee            |  3 ++
 .../stylesheets/admin/teams/projects.css.scss |  3 ++
 .../admin/teams/projects_controller_spec.rb   | 40 +++++++++++++++++++
 .../admin/teams/projects_helper_spec.rb       | 15 +++++++
 .../teams/projects/create.html.haml_spec.rb   |  5 +++
 .../teams/projects/destroy.html.haml_spec.rb  |  5 +++
 .../teams/projects/edit.html.haml_spec.rb     |  5 +++
 .../teams/projects/new.html.haml_spec.rb      |  5 +++
 .../teams/projects/update.html.haml_spec.rb   |  5 +++
 9 files changed, 86 insertions(+)
 create mode 100644 app/assets/javascripts/admin/teams/projects.js.coffee
 create mode 100644 app/assets/stylesheets/admin/teams/projects.css.scss
 create mode 100644 spec/controllers/admin/teams/projects_controller_spec.rb
 create mode 100644 spec/helpers/admin/teams/projects_helper_spec.rb
 create mode 100644 spec/views/admin/teams/projects/create.html.haml_spec.rb
 create mode 100644 spec/views/admin/teams/projects/destroy.html.haml_spec.rb
 create mode 100644 spec/views/admin/teams/projects/edit.html.haml_spec.rb
 create mode 100644 spec/views/admin/teams/projects/new.html.haml_spec.rb
 create mode 100644 spec/views/admin/teams/projects/update.html.haml_spec.rb

diff --git a/app/assets/javascripts/admin/teams/projects.js.coffee b/app/assets/javascripts/admin/teams/projects.js.coffee
new file mode 100644
index 00000000000..761567942fc
--- /dev/null
+++ b/app/assets/javascripts/admin/teams/projects.js.coffee
@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
diff --git a/app/assets/stylesheets/admin/teams/projects.css.scss b/app/assets/stylesheets/admin/teams/projects.css.scss
new file mode 100644
index 00000000000..e6a6ec39043
--- /dev/null
+++ b/app/assets/stylesheets/admin/teams/projects.css.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the Admin::Teams::Projects controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/spec/controllers/admin/teams/projects_controller_spec.rb b/spec/controllers/admin/teams/projects_controller_spec.rb
new file mode 100644
index 00000000000..7fe6ee0ca26
--- /dev/null
+++ b/spec/controllers/admin/teams/projects_controller_spec.rb
@@ -0,0 +1,40 @@
+require 'spec_helper'
+
+describe Admin::Teams::ProjectsController do
+
+  describe "GET 'new'" do
+    it "returns http success" do
+      get 'new'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'create'" do
+    it "returns http success" do
+      get 'create'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'edit'" do
+    it "returns http success" do
+      get 'edit'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'update'" do
+    it "returns http success" do
+      get 'update'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'destroy'" do
+    it "returns http success" do
+      get 'destroy'
+      response.should be_success
+    end
+  end
+
+end
diff --git a/spec/helpers/admin/teams/projects_helper_spec.rb b/spec/helpers/admin/teams/projects_helper_spec.rb
new file mode 100644
index 00000000000..1c98d23cdb7
--- /dev/null
+++ b/spec/helpers/admin/teams/projects_helper_spec.rb
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+# Specs in this file have access to a helper object that includes
+# the Admin::Teams::ProjectsHelper. For example:
+#
+# describe Admin::Teams::ProjectsHelper do
+#   describe "string concat" do
+#     it "concats two strings with spaces" do
+#       helper.concat_strings("this","that").should == "this that"
+#     end
+#   end
+# end
+describe Admin::Teams::ProjectsHelper do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/admin/teams/projects/create.html.haml_spec.rb b/spec/views/admin/teams/projects/create.html.haml_spec.rb
new file mode 100644
index 00000000000..74c4ee2d837
--- /dev/null
+++ b/spec/views/admin/teams/projects/create.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "projects/create.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/admin/teams/projects/destroy.html.haml_spec.rb b/spec/views/admin/teams/projects/destroy.html.haml_spec.rb
new file mode 100644
index 00000000000..b3eee48f38b
--- /dev/null
+++ b/spec/views/admin/teams/projects/destroy.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "projects/destroy.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/admin/teams/projects/edit.html.haml_spec.rb b/spec/views/admin/teams/projects/edit.html.haml_spec.rb
new file mode 100644
index 00000000000..ef41b7b0814
--- /dev/null
+++ b/spec/views/admin/teams/projects/edit.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "projects/edit.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/admin/teams/projects/new.html.haml_spec.rb b/spec/views/admin/teams/projects/new.html.haml_spec.rb
new file mode 100644
index 00000000000..9ee68e5ae05
--- /dev/null
+++ b/spec/views/admin/teams/projects/new.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "projects/new.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/views/admin/teams/projects/update.html.haml_spec.rb b/spec/views/admin/teams/projects/update.html.haml_spec.rb
new file mode 100644
index 00000000000..fdaafd3924b
--- /dev/null
+++ b/spec/views/admin/teams/projects/update.html.haml_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe "projects/update.html.haml" do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
-- 
GitLab


From 1dd0feacc7ba885c53da74028ee081a5a08e05ca Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Mon, 21 Jan 2013 23:55:55 +0400
Subject: [PATCH 050/197] move Team_members controller into project (conflicts
 with team/members controller)

---
 .../admin/projects/application_controller.rb  | 11 +++++++
 .../admin/projects/members_controller.rb      | 32 +++++++++++++++++++
 .../admin/team_members_controller.rb          | 22 -------------
 app/models/project.rb                         |  5 +++
 .../admin/projects/members/_form.html.haml    | 16 ++++++++++
 .../admin/projects/members/edit.html.haml     |  8 +++++
 app/views/admin/projects/show.html.haml       | 12 +++----
 app/views/admin/team_members/_form.html.haml  | 16 ----------
 app/views/admin/team_members/edit.html.haml   |  8 -----
 config/routes.rb                              |  4 ++-
 .../admin/projects/members_controller_spec.rb | 26 +++++++++++++++
 11 files changed, 107 insertions(+), 53 deletions(-)
 create mode 100644 app/controllers/admin/projects/application_controller.rb
 create mode 100644 app/controllers/admin/projects/members_controller.rb
 delete mode 100644 app/controllers/admin/team_members_controller.rb
 create mode 100644 app/views/admin/projects/members/_form.html.haml
 create mode 100644 app/views/admin/projects/members/edit.html.haml
 delete mode 100644 app/views/admin/team_members/_form.html.haml
 delete mode 100644 app/views/admin/team_members/edit.html.haml
 create mode 100644 spec/controllers/admin/projects/members_controller_spec.rb

diff --git a/app/controllers/admin/projects/application_controller.rb b/app/controllers/admin/projects/application_controller.rb
new file mode 100644
index 00000000000..0f3da998666
--- /dev/null
+++ b/app/controllers/admin/projects/application_controller.rb
@@ -0,0 +1,11 @@
+# Provides a base class for Admin controllers to subclass
+#
+# Automatically sets the layout and ensures an administrator is logged in
+class Admin::Projects::ApplicationController < Admin::ApplicationController
+
+  protected
+
+  def project
+    @project ||= Project.find_by_path(params[:project_id])
+  end
+end
diff --git a/app/controllers/admin/projects/members_controller.rb b/app/controllers/admin/projects/members_controller.rb
new file mode 100644
index 00000000000..5c20c0717ed
--- /dev/null
+++ b/app/controllers/admin/projects/members_controller.rb
@@ -0,0 +1,32 @@
+class Admin::Projects::MembersController < Admin::Projects::ApplicationController
+  def edit
+    @member = team_member
+    @project = project
+    @team_member_relation = team_member_relation
+  end
+
+  def update
+    if team_member_relation.update_attributes(params[:team_member])
+      redirect_to [:admin, project],  notice: 'Project Access was successfully updated.'
+    else
+      render action: "edit"
+    end
+  end
+
+  def destroy
+    team_member_relation.destroy
+
+    redirect_to :back
+  end
+
+  private
+
+  def team_member
+    @member ||= project.users.find(params[:id])
+  end
+
+  def team_member_relation
+    team_member.users_projects.find_by_project_id(project)
+  end
+
+end
diff --git a/app/controllers/admin/team_members_controller.rb b/app/controllers/admin/team_members_controller.rb
deleted file mode 100644
index 3c85681cf66..00000000000
--- a/app/controllers/admin/team_members_controller.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-class Admin::TeamMembersController < Admin::ApplicationController
-  def edit
-    @admin_team_member = UsersProject.find(params[:id])
-  end
-
-  def update
-    @admin_team_member = UsersProject.find(params[:id])
-
-    if @admin_team_member.update_attributes(params[:team_member])
-      redirect_to [:admin, @admin_team_member.project],  notice: 'Project Access was successfully updated.'
-    else
-      render action: "edit"
-    end
-  end
-
-  def destroy
-    @admin_team_member = UsersProject.find(params[:id])
-    @admin_team_member.destroy
-
-    redirect_to :back
-  end
-end
diff --git a/app/models/project.rb b/app/models/project.rb
index a21cc3f6f40..ba46fea2864 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -494,6 +494,11 @@ class Project < ActiveRecord::Base
     http_url = [Gitlab.config.gitlab.url, "/", path_with_namespace, ".git"].join('')
   end
 
+  def project_access_human(member)
+    project_user_relation = self.users_projects.find_by_user_id(member.id)
+    self.class.access_options.key(project_user_relation.project_access)
+  end
+
   # Check if current branch name is marked as protected in the system
   def protected_branch? branch_name
     protected_branches.map(&:name).include?(branch_name)
diff --git a/app/views/admin/projects/members/_form.html.haml b/app/views/admin/projects/members/_form.html.haml
new file mode 100644
index 00000000000..f1bb6cfa226
--- /dev/null
+++ b/app/views/admin/projects/members/_form.html.haml
@@ -0,0 +1,16 @@
+= form_for @team_member_relation, as: :team_member, url: admin_project_member_path(@project, @member)  do |f|
+  -if @team_member_relation.errors.any?
+    .alert-message.block-message.error
+      %ul
+        - @team_member_relation.errors.full_messages.each do |msg|
+          %li= msg
+
+  .clearfix
+    %label Project Access:
+    .input
+      = f.select :project_access, options_for_select(Project.access_options, @team_member_relation.project_access), {}, class: "project-access-select chosen span3"
+
+  %br
+  .actions
+    = f.submit 'Save', class: "btn primary"
+    = link_to 'Cancel', :back, class: "btn"
diff --git a/app/views/admin/projects/members/edit.html.haml b/app/views/admin/projects/members/edit.html.haml
new file mode 100644
index 00000000000..2d76deb2aca
--- /dev/null
+++ b/app/views/admin/projects/members/edit.html.haml
@@ -0,0 +1,8 @@
+%p.slead
+  Edit access for
+  = link_to @member.name, admin_user_path(@member)
+  in
+  = link_to @project.name_with_namespace, admin_project_path(@project)
+
+%hr
+= render 'form'
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index 12cad07c9c4..a213c09d456 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -114,7 +114,7 @@
 %h5
   Team
   %small
-    (#{@project.users_projects.count})
+    (#{@project.users.count})
 %br
 %table.zebra-striped.team_members
   %thead
@@ -124,13 +124,13 @@
       %th Repository Access
       %th
 
-  - @project.users_projects.each do |tm|
+  - @project.users.each do |tm|
     %tr
       %td
-        = link_to tm.user_name, admin_user_path(tm.user)
-      %td= tm.project_access_human
-      %td= link_to 'Edit Access', edit_admin_team_member_path(tm), class: "btn small"
-      %td= link_to 'Remove from team', admin_team_member_path(tm), confirm: 'Are you sure?', method: :delete, class: "btn danger small"
+        = link_to tm.name, admin_user_path(tm)
+      %td= @project.project_access_human(tm)
+      %td= link_to 'Edit Access', edit_admin_project_member_path(@project, tm), class: "btn small"
+      %td= link_to 'Remove from team', admin_project_member_path(@project, tm), confirm: 'Are you sure?', method: :delete, class: "btn danger small"
 
 %br
 %h5 Add new team member
diff --git a/app/views/admin/team_members/_form.html.haml b/app/views/admin/team_members/_form.html.haml
deleted file mode 100644
index 9cd94fdd30f..00000000000
--- a/app/views/admin/team_members/_form.html.haml
+++ /dev/null
@@ -1,16 +0,0 @@
-= form_for @admin_team_member, as: :team_member, url: admin_team_member_path(@admin_team_member)  do |f|
-  -if @admin_team_member.errors.any?
-    .alert-message.block-message.error
-      %ul
-        - @admin_team_member.errors.full_messages.each do |msg|
-          %li= msg
-
-  .clearfix
-    %label Project Access:
-    .input
-      = f.select :project_access, options_for_select(Project.access_options, @admin_team_member.project_access), {}, class: "project-access-select chosen span3"
-
-  %br
-  .actions
-    = f.submit 'Save', class: "btn primary"
-    = link_to 'Cancel', :back, class: "btn"
diff --git a/app/views/admin/team_members/edit.html.haml b/app/views/admin/team_members/edit.html.haml
deleted file mode 100644
index aea9bd70a79..00000000000
--- a/app/views/admin/team_members/edit.html.haml
+++ /dev/null
@@ -1,8 +0,0 @@
-%p.slead
-  Edit access for
-  = link_to @admin_team_member.user_name, admin_user_path(@admin_team_member)
-  in
-  = link_to @admin_team_member.project.name_with_namespace, admin_project_path(@admin_team_member)
-
-%hr
-= render 'form'
diff --git a/config/routes.rb b/config/routes.rb
index 21bfc89c24c..69ac18127d4 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -68,6 +68,9 @@ Gitlab::Application.routes.draw do
         get :team
         put :team_update
       end
+      scope module: :projects do
+        resources :members, only: [:edit, :update, :destroy]
+      end
     end
     resources :teams do #, constraints: { id: /[^\/]+/ } do end
       scope module: :teams do
@@ -75,7 +78,6 @@ Gitlab::Application.routes.draw do
         resources :projects, only: [:edit, :update, :destroy, :new, :create]
       end
     end
-    resources :team_members, only: [:edit, :update, :destroy]
     resources :hooks, only: [:index, :create, :destroy] do
       get :test
     end
diff --git a/spec/controllers/admin/projects/members_controller_spec.rb b/spec/controllers/admin/projects/members_controller_spec.rb
new file mode 100644
index 00000000000..73625e33d70
--- /dev/null
+++ b/spec/controllers/admin/projects/members_controller_spec.rb
@@ -0,0 +1,26 @@
+require 'spec_helper'
+
+describe Admin::Projects::MembersController do
+
+  describe "GET 'edit'" do
+    it "returns http success" do
+      get 'edit'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'update'" do
+    it "returns http success" do
+      get 'update'
+      response.should be_success
+    end
+  end
+
+  describe "GET 'destroy'" do
+    it "returns http success" do
+      get 'destroy'
+      response.should be_success
+    end
+  end
+
+end
-- 
GitLab


From 4ce715a360b089f95bf8e2b37cf87ec237492fcc Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Tue, 22 Jan 2013 21:14:00 +0400
Subject: [PATCH 051/197] Fix using context of Projects::UpdateContext (in
 admin section error, in public section - to next step if moving controlers)

---
 app/controllers/admin/projects_controller.rb | 2 +-
 app/controllers/projects_controller.rb       | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb
index 28d9bf01cce..7f88652cdab 100644
--- a/app/controllers/admin/projects_controller.rb
+++ b/app/controllers/admin/projects_controller.rb
@@ -29,7 +29,7 @@ class Admin::ProjectsController < Admin::ApplicationController
   end
 
   def update
-    status = Projects::UpdateContext.new(project, current_user, params).execute(:admin)
+    status = ::Projects::UpdateContext.new(project, current_user, params).execute(:admin)
 
     if status
       redirect_to [:admin, @project], notice: 'Project was successfully updated.'
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 368737d1e0b..6e5e1f91381 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -19,7 +19,7 @@ class ProjectsController < ProjectResourceController
   end
 
   def create
-    @project = Projects::CreateContext.new(current_user, params[:project]).execute
+    @project = ::Projects::CreateContext.new(current_user, params[:project]).execute
 
     respond_to do |format|
       flash[:notice] = 'Project was successfully created.' if @project.saved?
@@ -35,7 +35,7 @@ class ProjectsController < ProjectResourceController
   end
 
   def update
-    status = Projects::UpdateContext.new(project, current_user, params).execute
+    status = ::Projects::UpdateContext.new(project, current_user, params).execute
 
     respond_to do |format|
       if status
-- 
GitLab


From ccf8fa4fa23c9d48350bd2ed53f4a86afcfd6655 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Tue, 22 Jan 2013 21:15:05 +0400
Subject: [PATCH 052/197] if project creator was remowed from Gitlab - creator
 is next admin, who edit this project

---
 app/controllers/admin/projects_controller.rb | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb
index 7f88652cdab..711817395f1 100644
--- a/app/controllers/admin/projects_controller.rb
+++ b/app/controllers/admin/projects_controller.rb
@@ -29,6 +29,8 @@ class Admin::ProjectsController < Admin::ApplicationController
   end
 
   def update
+    project.creator = current_user unless project.creator
+
     status = ::Projects::UpdateContext.new(project, current_user, params).execute(:admin)
 
     if status
-- 
GitLab


From f6f414ce3b8c252779e78cfd1a6470dc03e2e374 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Tue, 22 Jan 2013 21:20:39 +0400
Subject: [PATCH 053/197] refactoring project team members controller
 (corresponding mental model)

---
 app/controllers/team_members_controller.rb | 22 +++++++++------
 app/helpers/projects_helper.rb             |  4 +--
 app/views/team_members/_form.html.haml     |  8 +++---
 app/views/team_members/_show.html.haml     | 10 +++----
 app/views/team_members/create.js.haml      |  2 +-
 app/views/team_members/index.html.haml     |  2 +-
 app/views/team_members/show.html.haml      | 31 +++++++++++-----------
 app/views/team_members/update.js.haml      |  6 ++---
 8 files changed, 45 insertions(+), 40 deletions(-)

diff --git a/app/controllers/team_members_controller.rb b/app/controllers/team_members_controller.rb
index 8378a8458ff..2b48e29ed7d 100644
--- a/app/controllers/team_members_controller.rb
+++ b/app/controllers/team_members_controller.rb
@@ -7,12 +7,12 @@ class TeamMembersController < ProjectResourceController
   end
 
   def show
-    @team_member = project.users_projects.find(params[:id])
-    @events = @team_member.user.recent_events.where(:project_id => @project.id).limit(7)
+    @user_project_relation = project.users_projects.find_by_user_id(member)
+    @events = member.recent_events.in_projects(project).limit(7)
   end
 
   def new
-    @team_member = project.users_projects.new
+    @user_project_relation = project.users_projects.new
   end
 
   def create
@@ -28,18 +28,18 @@ class TeamMembersController < ProjectResourceController
   end
 
   def update
-    @team_member = project.users_projects.find(params[:id])
-    @team_member.update_attributes(params[:team_member])
+    @user_project_relation = project.users_projects.find_by_user_id(member)
+    @user_project_relation.update_attributes(params[:team_member])
 
-    unless @team_member.valid?
+    unless @user_project_relation.valid?
       flash[:alert] = "User should have at least one role"
     end
     redirect_to project_team_index_path(@project)
   end
 
   def destroy
-    @team_member = project.users_projects.find(params[:id])
-    @team_member.destroy
+    @user_project_relation = project.users_projects.find_by_user_id(params[:id])
+    @user_project_relation.destroy
 
     respond_to do |format|
       format.html { redirect_to project_team_index_path(@project) }
@@ -54,4 +54,10 @@ class TeamMembersController < ProjectResourceController
 
     redirect_to project_team_members_path(project), notice: notice
   end
+
+  protected
+
+  def member
+    @member ||= User.find(params[:id])
+  end
 end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 158925ba6c0..dbd47998eb1 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -3,8 +3,8 @@ module ProjectsHelper
     @project.users_projects.sort_by(&:project_access).reverse.group_by(&:project_access)
   end
 
-  def remove_from_team_message(project, member)
-    "You are going to remove #{member.user_name} from #{project.name}. Are you sure?"
+  def remove_from_project_team_message(project, user)
+    "You are going to remove #{user.name} from #{project.name} project team. Are you sure?"
   end
 
   def link_to_project project
diff --git a/app/views/team_members/_form.html.haml b/app/views/team_members/_form.html.haml
index a963e462a78..f9ee49dbdeb 100644
--- a/app/views/team_members/_form.html.haml
+++ b/app/views/team_members/_form.html.haml
@@ -1,11 +1,11 @@
 %h3.page_title
   = "New Team member(s)"
 %hr
-= form_for @team_member, as: :team_member, url: project_team_members_path(@project, @team_member) do |f|
-  -if @team_member.errors.any?
+= form_for @user_project_relation, as: :team_member, url: project_team_members_path(@project) do |f|
+  -if @user_project_relation.errors.any?
     .alert-message.block-message.error
       %ul
-        - @team_member.errors.full_messages.each do |msg|
+        - @user_project_relation.errors.full_messages.each do |msg|
           %li= msg
 
   %h6 1. Choose people you want in the team
@@ -16,7 +16,7 @@
   %h6 2. Set access level for them
   .clearfix
     = f.label :project_access, "Project Access"
-    .input= select_tag :project_access, options_for_select(Project.access_options, @team_member.project_access), class: "project-access-select chosen"
+    .input= select_tag :project_access, options_for_select(Project.access_options, @user_project_relation.project_access), class: "project-access-select chosen"
 
   .actions
     = f.submit 'Save', class: "btn save-btn"
diff --git a/app/views/team_members/_show.html.haml b/app/views/team_members/_show.html.haml
index 8082f47fca8..52992033805 100644
--- a/app/views/team_members/_show.html.haml
+++ b/app/views/team_members/_show.html.haml
@@ -1,11 +1,11 @@
 - user = member.user
 - allow_admin = can? current_user, :admin_project, @project
-%li{id: dom_id(member), class: "team_member_row user_#{user.id}"}
+%li{id: dom_id(user), class: "team_member_row user_#{user.id}"}
   .row
     .span6
-      = link_to project_team_member_path(@project, member), title: user.name, class: "dark" do
+      = link_to project_team_member_path(@project, user), title: user.name, class: "dark" do
         = image_tag gravatar_icon(user.email, 40), class: "avatar s32"
-      = link_to project_team_member_path(@project, member), title: user.name, class: "dark" do
+      = link_to project_team_member_path(@project, user), title: user.name, class: "dark" do
         %strong= truncate(user.name, lenght: 40)
         %br
         %small.cgray= user.email
@@ -13,7 +13,7 @@
     .span5.right
       - if allow_admin
         .left
-          = form_for(member, as: :team_member, url: project_team_member_path(@project, member)) do |f|
+          = form_for(member, as: :team_member, url: project_team_member_path(@project, member.user)) do |f|
             = f.select :project_access, options_for_select(UsersProject.access_roles, member.project_access), {}, class: "medium project-access-select span2"
       .right
         - if current_user == user
@@ -23,6 +23,6 @@
         - elsif user.blocked
           %span.btn.disabled.blocked Blocked
         - elsif allow_admin
-          = link_to project_team_member_path(project_id: @project, id: member.id), confirm: remove_from_team_message(@project, member), method: :delete, class: "very_small btn danger" do
+          = link_to project_team_member_path(@project, user), confirm: remove_from_project_team_message(@project, user), method: :delete, class: "very_small btn danger" do
             %i.icon-minus.icon-white
 
diff --git a/app/views/team_members/create.js.haml b/app/views/team_members/create.js.haml
index d5ae5d0cc43..b7dff35a269 100644
--- a/app/views/team_members/create.js.haml
+++ b/app/views/team_members/create.js.haml
@@ -1,4 +1,4 @@
-- if @team_member.valid?
+- if @user_project_relation.valid?
   :plain
     $("#new_team_member").hide("slide", { direction: "right" }, 150, function(){
       $("#team-table").show("slide", { direction: "left" }, 150, function() {
diff --git a/app/views/team_members/index.html.haml b/app/views/team_members/index.html.haml
index e413c81bb6c..8ba13939a30 100644
--- a/app/views/team_members/index.html.haml
+++ b/app/views/team_members/index.html.haml
@@ -1,7 +1,7 @@
 = render "projects/project_head"
 %h3.page_title
   Team Members
-  (#{@project.users_projects.count})
+  (#{@project.users.count})
   %small
     Read more about project permissions
     %strong= link_to "here", help_permissions_path, class: "vlink"
diff --git a/app/views/team_members/show.html.haml b/app/views/team_members/show.html.haml
index 4008e8bd23e..a6a7152e92a 100644
--- a/app/views/team_members/show.html.haml
+++ b/app/views/team_members/show.html.haml
@@ -1,14 +1,13 @@
 - allow_admin = can? current_user, :admin_project, @project
-- user = @team_member.user
 
 .team_member_show
   - if can? current_user, :admin_project, @project
-    = link_to 'Remove from team', project_team_member_path(project_id: @project, id: @team_member.id), confirm: 'Are you sure?', method: :delete, class: "right btn danger"
+    = link_to 'Remove from team', project_team_member_path(@project, @member), confirm: 'Are you sure?', method: :delete, class: "right btn danger"
   .profile_avatar_holder
-    = image_tag gravatar_icon(user.email, 60), class: "borders"
+    = image_tag gravatar_icon(@member.email, 60), class: "borders"
   %h3.page_title
-    = user.name
-    %small (@#{user.username})
+    = @member.name
+    %small (@#{@member.username})
 
   %hr
   .back_link
@@ -21,34 +20,34 @@
       %table.lite
         %tr
           %td Email
-          %td= mail_to user.email
+          %td= mail_to @member.email
         %tr
           %td Skype
-          %td= user.skype
-        - unless user.linkedin.blank?
+          %td= @member.skype
+        - unless @member.linkedin.blank?
           %tr
             %td LinkedIn
-            %td= user.linkedin
-        - unless user.twitter.blank?
+            %td= @member.linkedin
+        - unless @member.twitter.blank?
           %tr
             %td Twitter
-            %td= user.twitter
-        - unless user.bio.blank?
+            %td= @member.twitter
+        - unless @member.bio.blank?
           %tr
             %td Bio
-            %td= user.bio
+            %td= @member.bio
     .span6
       %table.lite
         %tr
           %td Member since
-          %td= @team_member.created_at.stamp("Aug 21, 2011")
+          %td= @user_project_relation.created_at.stamp("Aug 21, 2011")
         %tr
           %td
             Project Access:
             %small (#{link_to "read more", help_permissions_path, class: "vlink"})
           %td
-            = form_for(@team_member, as: :team_member, url: project_team_member_path(@project, @team_member)) do |f|
-              = f.select :project_access, options_for_select(Project.access_options, @team_member.project_access), {}, class: "project-access-select", disabled: !allow_admin
+            = form_for(@user_project_relation, as: :team_member, url: project_team_member_path(@project, @member)) do |f|
+              = f.select :project_access, options_for_select(Project.access_options, @user_project_relation.project_access), {}, class: "project-access-select", disabled: !allow_admin
   %hr
   = render @events
 :javascript
diff --git a/app/views/team_members/update.js.haml b/app/views/team_members/update.js.haml
index 6d7f88160de..c68fe9574a2 100644
--- a/app/views/team_members/update.js.haml
+++ b/app/views/team_members/update.js.haml
@@ -1,6 +1,6 @@
-- if @team_member.valid?
+- if @user_project_relation.valid?
   :plain
-    $("##{dom_id(@team_member)}").effect("highlight", {color: "#529214"}, 1000);;
+    $("##{dom_id(@user_project_relation)}").effect("highlight", {color: "#529214"}, 1000);;
 - else
   :plain
-    $("##{dom_id(@team_member)}").effect("highlight", {color: "#D12F19"}, 1000);;
+    $("##{dom_id(@user_project_relation)}").effect("highlight", {color: "#D12F19"}, 1000);;
-- 
GitLab


From f87b76a805e8ac2d6a77747be171714e2289281a Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Tue, 22 Jan 2013 21:21:07 +0400
Subject: [PATCH 054/197] refactoring user team in public section

---
 .../teams/application_controller.rb           |  2 --
 app/controllers/teams/projects_controller.rb  | 22 +++++++++++++++++--
 app/helpers/user_teams_helper.rb              |  2 +-
 app/views/teams/members/_show.html.haml       |  2 +-
 4 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/app/controllers/teams/application_controller.rb b/app/controllers/teams/application_controller.rb
index 1cfb0e0991a..f1ecb5b2ce8 100644
--- a/app/controllers/teams/application_controller.rb
+++ b/app/controllers/teams/application_controller.rb
@@ -1,6 +1,4 @@
 class Teams::ApplicationController < ApplicationController
-  before_filter :user_team, only: [:index, :show, :edit, :update, :destroy, :issues, :merge_requests, :search, :members]
-
   protected
 
   def user_team
diff --git a/app/controllers/teams/projects_controller.rb b/app/controllers/teams/projects_controller.rb
index 796f37f6d5d..84de96861fb 100644
--- a/app/controllers/teams/projects_controller.rb
+++ b/app/controllers/teams/projects_controller.rb
@@ -1,21 +1,39 @@
 class Teams::ProjectsController < Teams::ApplicationController
   def index
-    @projects = @user_team.projects
-    @avaliable_projects = current_user.admin? ? Project.without_team(@user_team) : (Project.personal(current_user) + current_user.projects).uniq
+    @projects = user_team.projects
+    @avaliable_projects = current_user.admin? ? Project.without_team(user_team) : (Project.personal(current_user) + current_user.projects).uniq
   end
 
   def new
+    @projects = Project.scoped
+    @projects = @projects.without_team(user_team) if user_team.projects.any?
+    #@projects.reject!(&:empty_repo?)
   end
 
   def create
+    unless params[:project_ids].blank?
+      project_ids = params[:project_ids]
+      access = params[:greatest_project_access]
+      user_team.assign_to_projects(project_ids, access)
+    end
+
+    redirect_to admin_team_path(user_team), notice: 'Projects was successfully added.'
   end
 
   def edit
+    @user_team = user_team
   end
 
   def update
+    if user_team.update_project_access(project, params[:greatest_project_access])
+      redirect_to admin_team_path(user_team), notice: 'Membership was successfully updated.'
+    else
+      render :edit
+    end
   end
 
   def destroy
+    user_team.resign_from_project(project)
+    redirect_to admin_team_path(user_team), notice: 'Project was successfully removed.'
   end
 end
diff --git a/app/helpers/user_teams_helper.rb b/app/helpers/user_teams_helper.rb
index 01e10de52fb..60deb9e09e5 100644
--- a/app/helpers/user_teams_helper.rb
+++ b/app/helpers/user_teams_helper.rb
@@ -19,7 +19,7 @@ module UserTeamsHelper
     team.user_team_user_relationships.sort_by(&:permission).reverse.group_by(&:permission)
   end
 
-  def remove_from_team_message(team, member)
+  def remove_from_user_team_message(team, member)
     "You are going to remove #{member.name} from #{team.name}. Are you sure?"
   end
 
diff --git a/app/views/teams/members/_show.html.haml b/app/views/teams/members/_show.html.haml
index dfe73c77652..a06d269ac00 100644
--- a/app/views/teams/members/_show.html.haml
+++ b/app/views/teams/members/_show.html.haml
@@ -27,5 +27,5 @@
         - elsif user.blocked
           %span.btn.disabled.blocked Blocked
         - elsif allow_admin
-          = link_to team_member_path(@user_team, user), confirm: remove_from_team_message(@user_team, user), method: :delete, class: "very_small btn danger" do
+          = link_to team_member_path(@user_team, user), confirm: remove_from_user_team_message(@user_team, user), method: :delete, class: "very_small btn danger" do
             %i.icon-minus.icon-white
-- 
GitLab


From dcea52203ddc93c1d073e7615d98725cc3584d2f Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Tue, 22 Jan 2013 21:29:19 +0400
Subject: [PATCH 055/197] remove before_filter from controllers

---
 .../admin/teams/members_controller.rb         | 11 +++----
 .../admin/teams/projects_controller.rb        | 11 +++----
 app/controllers/admin/teams_controller.rb     | 32 ++++++++-----------
 app/controllers/teams/projects_controller.rb  | 13 ++++++--
 4 files changed, 34 insertions(+), 33 deletions(-)

diff --git a/app/controllers/admin/teams/members_controller.rb b/app/controllers/admin/teams/members_controller.rb
index 6795a520bb3..a6dbf6b5049 100644
--- a/app/controllers/admin/teams/members_controller.rb
+++ b/app/controllers/admin/teams/members_controller.rb
@@ -1,6 +1,4 @@
 class Admin::Teams::MembersController < Admin::Teams::ApplicationController
-  before_filter :team_member, only: [:edit, :destroy, :update]
-
   def new
     @users = User.active
     @users = @users.not_in_team(@team) if @team.members.any?
@@ -19,11 +17,12 @@ class Admin::Teams::MembersController < Admin::Teams::ApplicationController
   end
 
   def edit
+    team_member
   end
 
   def update
     options = {default_projects_access: params[:default_project_access], group_admin: params[:group_admin]}
-    if @team.update_membership(@member, options)
+    if @team.update_membership(team_member, options)
       redirect_to admin_team_path(@team), notice: 'Membership was successfully updated.'
     else
       render :edit
@@ -31,16 +30,16 @@ class Admin::Teams::MembersController < Admin::Teams::ApplicationController
   end
 
   def destroy
-    if @team.remove_member(@member)
+    if @team.remove_member(team_member)
       redirect_to admin_team_path(@team), notice: "Member was successfully removed from team."
     else
       redirect_to admin_team_members(@team), notice: "Something wrong."
     end
   end
 
-  private
+  protected
 
   def team_member
-    @member = @team.members.find(params[:id])
+    @member ||= @team.members.find(params[:id])
   end
 end
diff --git a/app/controllers/admin/teams/projects_controller.rb b/app/controllers/admin/teams/projects_controller.rb
index 74e566191b1..f255b8448ab 100644
--- a/app/controllers/admin/teams/projects_controller.rb
+++ b/app/controllers/admin/teams/projects_controller.rb
@@ -1,6 +1,4 @@
 class Admin::Teams::ProjectsController < Admin::Teams::ApplicationController
-  before_filter :team_project, only: [:edit, :destroy, :update]
-
   def new
     @projects = Project.scoped
     @projects = @projects.without_team(@team) if @team.projects.any?
@@ -18,10 +16,11 @@ class Admin::Teams::ProjectsController < Admin::Teams::ApplicationController
   end
 
   def edit
+    team_project
   end
 
   def update
-    if @team.update_project_access(@project, params[:greatest_project_access])
+    if @team.update_project_access(team_project, params[:greatest_project_access])
       redirect_to admin_team_path(@team), notice: 'Membership was successfully updated.'
     else
       render :edit
@@ -29,14 +28,14 @@ class Admin::Teams::ProjectsController < Admin::Teams::ApplicationController
   end
 
   def destroy
-    @team.resign_from_project(@project)
+    @team.resign_from_project(team_project)
     redirect_to admin_team_path(@team), notice: 'Project was successfully removed.'
   end
 
-  private
+  protected
 
   def team_project
-    @project = @team.projects.find_by_path(params[:id])
+    @project ||= @team.projects.find_by_path(params[:id])
   end
 
 end
diff --git a/app/controllers/admin/teams_controller.rb b/app/controllers/admin/teams_controller.rb
index ee9141e371c..f42ec10585b 100644
--- a/app/controllers/admin/teams_controller.rb
+++ b/app/controllers/admin/teams_controller.rb
@@ -1,9 +1,4 @@
 class Admin::TeamsController < Admin::ApplicationController
-  before_filter :user_team,
-                only: [ :edit, :show, :update, :destroy,
-                        :delegate_projects, :relegate_project,
-                        :add_members, :remove_member ]
-
   def index
     @teams = UserTeam.order('name ASC')
     @teams = @teams.search(params[:name]) if params[:name].present?
@@ -12,11 +7,11 @@ class Admin::TeamsController < Admin::ApplicationController
 
   def show
     @projects = Project.scoped
-    @projects = @projects.without_team(@team) if @team.projects.any?
+    @projects = @projects.without_team(user_team) if user_team.projects.any?
     #@projects.reject!(&:empty_repo?)
 
     @users = User.active
-    @users = @users.not_in_team(@team) if @team.members.any?
+    @users = @users.not_in_team(user_team) if user_team.members.any?
     @users = UserDecorator.decorate @users
   end
 
@@ -25,15 +20,16 @@ class Admin::TeamsController < Admin::ApplicationController
   end
 
   def edit
+    user_team
   end
 
   def create
-    @team = UserTeam.new(params[:user_team])
-    @team.path = @team.name.dup.parameterize if @team.name
-    @team.owner = current_user
+    user_team = UserTeam.new(params[:user_team])
+    user_team.path = user_team.name.dup.parameterize if user_team.name
+    user_team.owner = current_user
 
-    if @team.save
-      redirect_to admin_team_path(@team), notice: 'UserTeam was successfully created.'
+    if user_team.save
+      redirect_to admin_team_path(user_team), notice: 'UserTeam was successfully created.'
     else
       render action: "new"
     end
@@ -44,26 +40,26 @@ class Admin::TeamsController < Admin::ApplicationController
     owner_id = user_team_params.delete(:owner_id)
 
     if owner_id
-      @team.owner = User.find(owner_id)
+      user_team.owner = User.find(owner_id)
     end
 
-    if @team.update_attributes(user_team_params)
-      redirect_to admin_team_path(@team), notice: 'UserTeam was successfully updated.'
+    if user_team.update_attributes(user_team_params)
+      redirect_to admin_team_path(user_team), notice: 'UserTeam was successfully updated.'
     else
       render action: "edit"
     end
   end
 
   def destroy
-    @team.destroy
+    user_team.destroy
 
     redirect_to admin_user_teams_path, notice: 'UserTeam was successfully deleted.'
   end
 
-  private
+  protected
 
   def user_team
-    @team = UserTeam.find_by_path(params[:id])
+    @team ||= UserTeam.find_by_path(params[:id])
   end
 
 end
diff --git a/app/controllers/teams/projects_controller.rb b/app/controllers/teams/projects_controller.rb
index 84de96861fb..1e65c0ce35e 100644
--- a/app/controllers/teams/projects_controller.rb
+++ b/app/controllers/teams/projects_controller.rb
@@ -21,11 +21,11 @@ class Teams::ProjectsController < Teams::ApplicationController
   end
 
   def edit
-    @user_team = user_team
+    team_project
   end
 
   def update
-    if user_team.update_project_access(project, params[:greatest_project_access])
+    if user_team.update_project_access(team_project, params[:greatest_project_access])
       redirect_to admin_team_path(user_team), notice: 'Membership was successfully updated.'
     else
       render :edit
@@ -33,7 +33,14 @@ class Teams::ProjectsController < Teams::ApplicationController
   end
 
   def destroy
-    user_team.resign_from_project(project)
+    user_team.resign_from_project(team_project)
     redirect_to admin_team_path(user_team), notice: 'Project was successfully removed.'
   end
+
+  private
+
+  def team_project
+    @project ||= @team.projects.find_by_path(params[:id])
+  end
+
 end
-- 
GitLab


From 7534154b44f920005e6732bbcc9e9af391b81546 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Wed, 23 Jan 2013 00:58:44 +0400
Subject: [PATCH 056/197] Add access control in public section to users teams

---
 app/controllers/teams/application_controller.rb | 7 +++++++
 app/controllers/teams/members_controller.rb     | 2 +-
 app/controllers/teams/projects_controller.rb    | 3 +++
 3 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/app/controllers/teams/application_controller.rb b/app/controllers/teams/application_controller.rb
index f1ecb5b2ce8..ff73f6b4eb0 100644
--- a/app/controllers/teams/application_controller.rb
+++ b/app/controllers/teams/application_controller.rb
@@ -1,8 +1,15 @@
 class Teams::ApplicationController < ApplicationController
+
+  before_filter :authorize_manage_user_team!
+
   protected
 
   def user_team
     @user_team ||= UserTeam.find_by_path(params[:team_id])
   end
 
+  def authorize_manage_user_team!
+    return access_denied! unless can?(current_user, :manage_user_team, user_team)
+  end
+
 end
diff --git a/app/controllers/teams/members_controller.rb b/app/controllers/teams/members_controller.rb
index ab1c2878331..111ad5c2f3d 100644
--- a/app/controllers/teams/members_controller.rb
+++ b/app/controllers/teams/members_controller.rb
@@ -1,6 +1,6 @@
 class Teams::MembersController < Teams::ApplicationController
   # Authorize
-  before_filter :authorize_manage_user_team!, only: [:new, :edit]
+  skip_before_filter :authorize_manage_user_team!, only: [:index]
 
   def index
     @members = @user_team.members
diff --git a/app/controllers/teams/projects_controller.rb b/app/controllers/teams/projects_controller.rb
index 1e65c0ce35e..6255853f8c9 100644
--- a/app/controllers/teams/projects_controller.rb
+++ b/app/controllers/teams/projects_controller.rb
@@ -1,4 +1,7 @@
 class Teams::ProjectsController < Teams::ApplicationController
+
+  skip_before_filter :authorize_manage_user_team!, only: [:index]
+
   def index
     @projects = user_team.projects
     @avaliable_projects = current_user.admin? ? Project.without_team(user_team) : (Project.personal(current_user) + current_user.projects).uniq
-- 
GitLab


From 7658f8c151b22680cf594d028e180a8a859fc9b8 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Wed, 23 Jan 2013 01:03:52 +0400
Subject: [PATCH 057/197] update routes

---
 config/routes.rb | 44 ++++++++++++++++++++++++--------------------
 1 file changed, 24 insertions(+), 20 deletions(-)

diff --git a/config/routes.rb b/config/routes.rb
index 69ac18127d4..e8af16387bc 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -56,6 +56,7 @@ Gitlab::Application.routes.draw do
         put :unblock
       end
     end
+
     resources :groups, constraints: { id: /[^\/]+/ } do
       member do
         put :project_update
@@ -63,26 +64,31 @@ Gitlab::Application.routes.draw do
         delete :remove_project
       end
     end
-    resources :projects, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ }, except: [:new, :create] do
-      member do
-        get :team
-        put :team_update
-      end
-      scope module: :projects do
-        resources :members, only: [:edit, :update, :destroy]
-      end
-    end
-    resources :teams do #, constraints: { id: /[^\/]+/ } do end
+
+    resources :teams, constraints: { id: /[^\/]+/ } do
       scope module: :teams do
-        resources :members, only: [:edit, :update, :destroy, :new, :create]
-        resources :projects, only: [:edit, :update, :destroy, :new, :create]
+        resources :members,   only: [:edit, :update, :destroy, :new, :create]
+        resources :projects,  only: [:edit, :update, :destroy, :new, :create], constraints: { id: /[a-zA-Z.\/0-9_\-]+/ }
       end
     end
+
     resources :hooks, only: [:index, :create, :destroy] do
       get :test
     end
+
     resource :logs, only: [:show]
     resource :resque, controller: 'resque', only: [:show]
+
+    resources :projects, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ }, except: [:new, :create] do
+      member do
+        get :team
+        put :team_update
+      end
+      scope module: :projects, constraints: { id: /[^\/]+/ } do
+        resources :members, only: [:edit, :update, :destroy]
+      end
+    end
+
     root to: "dashboard#index"
   end
 
@@ -116,7 +122,6 @@ Gitlab::Application.routes.draw do
   get "dashboard/issues"         => "dashboard#issues"
   get "dashboard/merge_requests" => "dashboard#merge_requests"
 
-
   #
   # Groups Area
   #
@@ -130,19 +135,18 @@ Gitlab::Application.routes.draw do
     end
   end
 
-  resources :teams do
+  #
+  # Teams Area
+  #
+  resources :teams, constraints: { id: /[^\/]+/ } do
     member do
       get :issues
       get :merge_requests
       get :search
-      post :delegate_projects
-      delete :relegate_project
-      put :update_access
     end
     scope module: :teams do
-      resources :members
-      resources :projects, only: [:index, :show] do
-      end
+      resources :members,   only: [:index, :new, :create, :edit, :update, :destroy]
+      resources :projects,  only: [:index, :new, :create, :edit, :update, :destroy], constraints: { id: /[a-zA-Z.0-9_\-\/]+/ }
     end
     collection do
       get :search
-- 
GitLab


From 18bd1c9d30e16783d750c7786cbcc7d350f4d0aa Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Wed, 23 Jan 2013 02:20:27 +0400
Subject: [PATCH 058/197] update all teams code. refactoring and some
 corrections

---
 .../admin/teams/application_controller.rb     |  1 -
 .../admin/teams/members_controller.rb         | 18 ++--
 .../admin/teams/projects_controller.rb        | 16 ++--
 app/controllers/admin/teams_controller.rb     | 14 +--
 app/controllers/application_controller.rb     |  9 ++
 app/controllers/team_members_controller.rb    |  1 +
 .../teams/application_controller.rb           |  6 +-
 app/controllers/teams/members_controller.rb   | 59 ++++++------
 app/controllers/teams/projects_controller.rb  | 15 ++--
 app/controllers/teams_controller.rb           | 59 ++++--------
 app/views/admin/teams/index.html.haml         |  1 +
 app/views/admin/teams/new.html.haml           |  6 +-
 app/views/admin/teams/show.html.haml          | 89 +++++++++----------
 app/views/dashboard/_teams.html.haml          |  9 +-
 app/views/layouts/_head_panel.html.haml       |  3 +
 app/views/layouts/user_team.html.haml         | 16 ++--
 app/views/teams/_team_head.html.haml          | 12 +--
 app/views/teams/edit.html.haml                | 18 ++--
 app/views/teams/index.html.haml               |  5 +-
 app/views/teams/members/_form.html.haml       | 27 +++---
 app/views/teams/members/_show.html.haml       | 14 +--
 app/views/teams/members/_team.html.haml       |  2 +-
 app/views/teams/members/edit.html.haml        | 20 ++++-
 app/views/teams/members/import.html.haml      | 17 ----
 app/views/teams/members/index.html.haml       |  7 +-
 app/views/teams/members/new.html.haml         | 32 ++++++-
 app/views/teams/members/show.html.haml        |  2 +
 app/views/teams/merge_requests.html.haml      |  2 +
 app/views/teams/new.html.haml                 |  6 +-
 app/views/teams/projects/_form.html.haml      | 16 ++++
 app/views/teams/projects/edit.html.haml       | 18 +++-
 app/views/teams/projects/index.html.haml      | 60 ++++++-------
 app/views/teams/projects/new.html.haml        | 25 +++++-
 app/views/teams/projects/show.html.haml       |  4 -
 app/views/teams/search.html.haml              |  2 +-
 35 files changed, 330 insertions(+), 281 deletions(-)
 delete mode 100644 app/views/teams/members/import.html.haml
 create mode 100644 app/views/teams/projects/_form.html.haml
 delete mode 100644 app/views/teams/projects/show.html.haml

diff --git a/app/controllers/admin/teams/application_controller.rb b/app/controllers/admin/teams/application_controller.rb
index a2920b626b5..8710821454e 100644
--- a/app/controllers/admin/teams/application_controller.rb
+++ b/app/controllers/admin/teams/application_controller.rb
@@ -2,7 +2,6 @@
 #
 # Automatically sets the layout and ensures an administrator is logged in
 class Admin::Teams::ApplicationController < Admin::ApplicationController
-  before_filter :user_team
 
   private
 
diff --git a/app/controllers/admin/teams/members_controller.rb b/app/controllers/admin/teams/members_controller.rb
index a6dbf6b5049..cdcc96c0aef 100644
--- a/app/controllers/admin/teams/members_controller.rb
+++ b/app/controllers/admin/teams/members_controller.rb
@@ -1,7 +1,7 @@
 class Admin::Teams::MembersController < Admin::Teams::ApplicationController
   def new
     @users = User.active
-    @users = @users.not_in_team(@team) if @team.members.any?
+    @users = @users.not_in_team(user_team) if user_team.members.any?
     @users = UserDecorator.decorate @users
   end
 
@@ -10,10 +10,10 @@ class Admin::Teams::MembersController < Admin::Teams::ApplicationController
       user_ids = params[:user_ids]
       access = params[:default_project_access]
       is_admin = params[:group_admin]
-      @team.add_members(user_ids, access, is_admin)
+      user_team.add_members(user_ids, access, is_admin)
     end
 
-    redirect_to admin_team_path(@team), notice: 'Members was successfully added.'
+    redirect_to admin_team_path(user_team), notice: 'Members was successfully added into Team of users.'
   end
 
   def edit
@@ -22,24 +22,24 @@ class Admin::Teams::MembersController < Admin::Teams::ApplicationController
 
   def update
     options = {default_projects_access: params[:default_project_access], group_admin: params[:group_admin]}
-    if @team.update_membership(team_member, options)
-      redirect_to admin_team_path(@team), notice: 'Membership was successfully updated.'
+    if user_team.update_membership(team_member, options)
+      redirect_to admin_team_path(user_team), notice: "Membership for #{team_member.name} was successfully updated in Team of users."
     else
       render :edit
     end
   end
 
   def destroy
-    if @team.remove_member(team_member)
-      redirect_to admin_team_path(@team), notice: "Member was successfully removed from team."
+    if user_team.remove_member(team_member)
+      redirect_to admin_team_path(user_team), notice: "Member #{team_member.name} was successfully removed from Team of users."
     else
-      redirect_to admin_team_members(@team), notice: "Something wrong."
+      redirect_to admin_team_members(user_team), notice: "Something is wrong."
     end
   end
 
   protected
 
   def team_member
-    @member ||= @team.members.find(params[:id])
+    @member ||= user_team.members.find(params[:id])
   end
 end
diff --git a/app/controllers/admin/teams/projects_controller.rb b/app/controllers/admin/teams/projects_controller.rb
index f255b8448ab..8584a188b20 100644
--- a/app/controllers/admin/teams/projects_controller.rb
+++ b/app/controllers/admin/teams/projects_controller.rb
@@ -1,7 +1,7 @@
 class Admin::Teams::ProjectsController < Admin::Teams::ApplicationController
   def new
     @projects = Project.scoped
-    @projects = @projects.without_team(@team) if @team.projects.any?
+    @projects = @projects.without_team(user_team) if user_team.projects.any?
     #@projects.reject!(&:empty_repo?)
   end
 
@@ -9,10 +9,10 @@ class Admin::Teams::ProjectsController < Admin::Teams::ApplicationController
     unless params[:project_ids].blank?
       project_ids = params[:project_ids]
       access = params[:greatest_project_access]
-      @team.assign_to_projects(project_ids, access)
+      user_team.assign_to_projects(project_ids, access)
     end
 
-    redirect_to admin_team_path(@team), notice: 'Projects was successfully added.'
+    redirect_to admin_team_path(user_team), notice: 'Team of users was successfully assgned to projects.'
   end
 
   def edit
@@ -20,22 +20,22 @@ class Admin::Teams::ProjectsController < Admin::Teams::ApplicationController
   end
 
   def update
-    if @team.update_project_access(team_project, params[:greatest_project_access])
-      redirect_to admin_team_path(@team), notice: 'Membership was successfully updated.'
+    if user_team.update_project_access(team_project, params[:greatest_project_access])
+      redirect_to admin_team_path(user_team), notice: 'Access was successfully updated.'
     else
       render :edit
     end
   end
 
   def destroy
-    @team.resign_from_project(team_project)
-    redirect_to admin_team_path(@team), notice: 'Project was successfully removed.'
+    user_team.resign_from_project(team_project)
+    redirect_to admin_team_path(user_team), notice: 'Team of users was successfully reassigned from project.'
   end
 
   protected
 
   def team_project
-    @project ||= @team.projects.find_by_path(params[:id])
+    @project ||= user_team.projects.find_with_namespace(params[:id])
   end
 
 end
diff --git a/app/controllers/admin/teams_controller.rb b/app/controllers/admin/teams_controller.rb
index f42ec10585b..7371f4a446c 100644
--- a/app/controllers/admin/teams_controller.rb
+++ b/app/controllers/admin/teams_controller.rb
@@ -24,12 +24,12 @@ class Admin::TeamsController < Admin::ApplicationController
   end
 
   def create
-    user_team = UserTeam.new(params[:user_team])
-    user_team.path = user_team.name.dup.parameterize if user_team.name
-    user_team.owner = current_user
+    @team = UserTeam.new(params[:user_team])
+    @team.path = @team.name.dup.parameterize if @team.name
+    @team.owner = current_user
 
-    if user_team.save
-      redirect_to admin_team_path(user_team), notice: 'UserTeam was successfully created.'
+    if @team.save
+      redirect_to admin_team_path(@team), notice: 'Team of users was successfully created.'
     else
       render action: "new"
     end
@@ -44,7 +44,7 @@ class Admin::TeamsController < Admin::ApplicationController
     end
 
     if user_team.update_attributes(user_team_params)
-      redirect_to admin_team_path(user_team), notice: 'UserTeam was successfully updated.'
+      redirect_to admin_team_path(user_team), notice: 'Team of users was successfully updated.'
     else
       render action: "edit"
     end
@@ -53,7 +53,7 @@ class Admin::TeamsController < Admin::ApplicationController
   def destroy
     user_team.destroy
 
-    redirect_to admin_user_teams_path, notice: 'UserTeam was successfully deleted.'
+    redirect_to admin_user_teams_path, notice: 'Team of users was successfully deleted.'
   end
 
   protected
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 3457a1ab1b4..f903c7fdd62 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -94,6 +94,14 @@ class ApplicationController < ActionController::Base
     return access_denied! unless can?(current_user, :download_code, project)
   end
 
+  def authorize_manage_user_team!
+    return access_denied! unless user_team.present? && can?(current_user, :manage_user_team, user_team)
+  end
+
+  def authorize_admin_user_team!
+    return access_denied! unless user_team.present? && can?(current_user, :admin_user_team, user_team)
+  end
+
   def access_denied!
     render "errors/access_denied", layout: "errors", status: 404
   end
@@ -135,4 +143,5 @@ class ApplicationController < ActionController::Base
   def dev_tools
     Rack::MiniProfiler.authorize_request
   end
+
 end
diff --git a/app/controllers/team_members_controller.rb b/app/controllers/team_members_controller.rb
index 2b48e29ed7d..7e4c8792b50 100644
--- a/app/controllers/team_members_controller.rb
+++ b/app/controllers/team_members_controller.rb
@@ -4,6 +4,7 @@ class TeamMembersController < ProjectResourceController
   before_filter :authorize_admin_project!, except: [:index, :show]
 
   def index
+    @teams = UserTeam.scoped
   end
 
   def show
diff --git a/app/controllers/teams/application_controller.rb b/app/controllers/teams/application_controller.rb
index ff73f6b4eb0..2c1583d943e 100644
--- a/app/controllers/teams/application_controller.rb
+++ b/app/controllers/teams/application_controller.rb
@@ -5,11 +5,7 @@ class Teams::ApplicationController < ApplicationController
   protected
 
   def user_team
-    @user_team ||= UserTeam.find_by_path(params[:team_id])
-  end
-
-  def authorize_manage_user_team!
-    return access_denied! unless can?(current_user, :manage_user_team, user_team)
+    @team ||= UserTeam.find_by_path(params[:team_id])
   end
 
 end
diff --git a/app/controllers/teams/members_controller.rb b/app/controllers/teams/members_controller.rb
index 111ad5c2f3d..95b8de1861b 100644
--- a/app/controllers/teams/members_controller.rb
+++ b/app/controllers/teams/members_controller.rb
@@ -1,58 +1,53 @@
 class Teams::MembersController < Teams::ApplicationController
-  # Authorize
+
   skip_before_filter :authorize_manage_user_team!, only: [:index]
 
   def index
-    @members = @user_team.members
-  end
-
-  def show
-    @team_member = @user_team.members.find(params[:id])
-    @events = @team_member.recent_events.limit(7)
+    @members = user_team.members
   end
 
   def new
-    @team_member = @user_team.members.new
+    @users = User.active
+    @users = @users.not_in_team(user_team) if user_team.members.any?
+    @users = UserDecorator.decorate @users
   end
 
   def create
-    users = User.where(id: params[:user_ids])
+    unless params[:user_ids].blank?
+      user_ids = params[:user_ids]
+      access = params[:default_project_access]
+      is_admin = params[:group_admin]
+      user_team.add_members(user_ids, access, is_admin)
+    end
 
-    @project.team << [users, params[:default_project_access]]
+    redirect_to team_path(user_team), notice: 'Members was successfully added into Team of users.'
+  end
 
-    if params[:redirect_to]
-      redirect_to params[:redirect_to]
-    else
-      redirect_to project_team_index_path(@project)
-    end
+  def edit
+    team_member
   end
 
   def update
-    @team_member = @user_team.members.find(params[:id])
-    @team_member.update_attributes(params[:team_member])
-
-    unless @team_member.valid?
-      flash[:alert] = "User should have at least one role"
+    options = {default_projects_access: params[:default_project_access], group_admin: params[:group_admin]}
+    if user_team.update_membership(team_member, options)
+      redirect_to team_path(user_team), notice: "Membership for #{team_member.name} was successfully updated in Team of users."
+    else
+      render :edit
     end
-    redirect_to team_member_path(@project)
   end
 
   def destroy
-    @team_member = project.users_projects.find(params[:id])
-    @team_member.destroy
-
-    respond_to do |format|
-      format.html { redirect_to project_team_index_path(@project) }
-      format.js { render nothing: true }
+    if user_team.remove_member(team_member)
+      redirect_to team_path(user_team), notice: "Member #{team_member.name} was successfully removed from Team of users."
+    else
+      redirect_to team_members(user_team), notice: "Something is wrong."
     end
   end
 
-  def apply_import
-    giver = Project.find(params[:source_project_id])
-    status = @project.team.import(giver)
-    notice = status ? "Succesfully imported" : "Import failed"
+  protected
 
-    redirect_to project_team_members_path(project), notice: notice
+  def team_member
+    @member ||= user_team.members.find(params[:id])
   end
 
 end
diff --git a/app/controllers/teams/projects_controller.rb b/app/controllers/teams/projects_controller.rb
index 6255853f8c9..21ddba865f3 100644
--- a/app/controllers/teams/projects_controller.rb
+++ b/app/controllers/teams/projects_controller.rb
@@ -8,9 +8,12 @@ class Teams::ProjectsController < Teams::ApplicationController
   end
 
   def new
-    @projects = Project.scoped
-    @projects = @projects.without_team(user_team) if user_team.projects.any?
+    user_team
+    @avaliable_projects = Project.scoped
+    @avaliable_projects = @avaliable_projects.without_team(user_team) if user_team.projects.any?
     #@projects.reject!(&:empty_repo?)
+
+    redirect_to team_projects_path(user_team), notice: "No avalible projects." unless @avaliable_projects.any?
   end
 
   def create
@@ -20,7 +23,7 @@ class Teams::ProjectsController < Teams::ApplicationController
       user_team.assign_to_projects(project_ids, access)
     end
 
-    redirect_to admin_team_path(user_team), notice: 'Projects was successfully added.'
+    redirect_to team_projects_path(user_team), notice: 'Team of users was successfully assgned to projects.'
   end
 
   def edit
@@ -29,7 +32,7 @@ class Teams::ProjectsController < Teams::ApplicationController
 
   def update
     if user_team.update_project_access(team_project, params[:greatest_project_access])
-      redirect_to admin_team_path(user_team), notice: 'Membership was successfully updated.'
+      redirect_to team_projects_path(user_team), notice: 'Access was successfully updated.'
     else
       render :edit
     end
@@ -37,13 +40,13 @@ class Teams::ProjectsController < Teams::ApplicationController
 
   def destroy
     user_team.resign_from_project(team_project)
-    redirect_to admin_team_path(user_team), notice: 'Project was successfully removed.'
+    redirect_to team_projects_path(user_team), notice: 'Team of users was successfully reassigned from project.'
   end
 
   private
 
   def team_project
-    @project ||= @team.projects.find_by_path(params[:id])
+    @project ||= user_team.projects.find_with_namespace(params[:id])
   end
 
 end
diff --git a/app/controllers/teams_controller.rb b/app/controllers/teams_controller.rb
index 4e3703d72d4..169ee34f4ec 100644
--- a/app/controllers/teams_controller.rb
+++ b/app/controllers/teams_controller.rb
@@ -1,30 +1,26 @@
 class TeamsController < ApplicationController
-  respond_to :html
-  layout 'user_team',       only: [:show, :edit, :update, :destroy, :issues, :merge_requests, :search]
+  # Authorize
+  before_filter :authorize_manage_user_team!
+  before_filter :authorize_admin_user_team!
 
-  before_filter :user_team, only: [:show, :edit, :update, :destroy, :issues, :merge_requests, :search]
-  before_filter :projects,  only: [:show, :edit, :update, :destroy, :issues, :merge_requests, :search]
+  # Skip access control on public section
+  skip_before_filter :authorize_manage_user_team!, only: [:index, :show, :new, :destroy, :create, :search, :issues, :merge_requests]
+  skip_before_filter :authorize_admin_user_team!, only: [:index, :show, :new, :create, :search, :issues, :merge_requests]
 
-  # Authorize
-  before_filter :authorize_manage_user_team!, only: [:edit, :update]
-  before_filter :authorize_admin_user_team!, only: [:destroy]
+  layout 'user_team',       only: [:show, :edit, :update, :destroy, :issues, :merge_requests, :search]
 
   def index
-    @teams = UserTeam.all
+    @teams = UserTeam.order('name ASC')
   end
 
   def show
-    @events = Event.in_projects(project_ids).limit(20).offset(params[:offset] || 0)
-
-    respond_to do |format|
-      format.html
-      format.js
-      format.atom { render layout: false }
-    end
+    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
@@ -58,56 +54,37 @@ class TeamsController < ApplicationController
 
   # Get authored or assigned open merge requests
   def merge_requests
-    @merge_requests = MergeRequest.of_user_team(@user_team)
+    @merge_requests = MergeRequest.of_user_team(user_team)
     @merge_requests = FilterContext.new(@merge_requests, params).execute
     @merge_requests = @merge_requests.recent.page(params[:page]).per(20)
   end
 
   # Get only assigned issues
   def issues
-    @issues = Issue.of_user_team(@user_team)
+    @issues = Issue.of_user_team(user_team)
     @issues = FilterContext.new(@issues, params).execute
     @issues = @issues.recent.page(params[:page]).per(20)
     @issues = @issues.includes(:author, :project)
-
-    respond_to do |format|
-      format.html
-      format.atom { render layout: false }
-    end
   end
 
   def search
-    result = SearchContext.new(project_ids, params).execute
+    result = SearchContext.new(user_team.project_ids, params).execute
 
     @projects       = result[:projects]
     @merge_requests = result[:merge_requests]
     @issues         = result[:issues]
     @wiki_pages     = result[:wiki_pages]
+    @teams          = result[:teams]
   end
 
   protected
 
-  def user_team
-    @user_team ||= UserTeam.find_by_path(params[:id])
-  end
-
   def projects
     @projects ||= user_team.projects.sorted_by_activity
   end
 
-  def project_ids
-    projects.map(&:id)
-  end
-
-  def authorize_manage_user_team!
-    unless user_team.present? or can?(current_user, :manage_user_team, user_team)
-      return render_404
-    end
+  def user_team
+    @team ||= UserTeam.find_by_path(params[:id])
   end
 
-  def authorize_admin_user_team!
-    unless user_team.owner == current_user || current_user.admin?
-      return render_404
-    end
-  end
 end
diff --git a/app/views/admin/teams/index.html.haml b/app/views/admin/teams/index.html.haml
index 8b6928e906e..3ab57448ab2 100644
--- a/app/views/admin/teams/index.html.haml
+++ b/app/views/admin/teams/index.html.haml
@@ -34,4 +34,5 @@
       %td.bgred
         = link_to 'Rename', edit_admin_team_path(team), id: "edit_#{dom_id(team)}", class: "btn small"
         = link_to 'Destroy', admin_team_path(team), confirm: "REMOVE #{team.name}? Are you sure?", method: :delete, class: "btn small danger"
+
 = paginate @teams, theme: "admin"
diff --git a/app/views/admin/teams/new.html.haml b/app/views/admin/teams/new.html.haml
index c936b66b32e..a40a2c4ebf9 100644
--- a/app/views/admin/teams/new.html.haml
+++ b/app/views/admin/teams/new.html.haml
@@ -14,8 +14,6 @@
   %hr
   .padded
     %ul
-      %li Team is kind of directory for several projects
-      %li All created teams are private
+      %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 All projects of team will be stored in team directory
-      %li You will be able to move existing projects into team
+      %li You will be able to assign existing projects for team
diff --git a/app/views/admin/teams/show.html.haml b/app/views/admin/teams/show.html.haml
index 2bb9c02af7e..a7470c2d6e0 100644
--- a/app/views/admin/teams/show.html.haml
+++ b/app/views/admin/teams/show.html.haml
@@ -40,54 +40,51 @@
           = link_to "Cancel", "#", class: "btn change-owner-cancel-link"
 
 %fieldset
-  %legend Members (#{@team.members.count})
-  %table#members_list
-    %thead
-      %tr
-        %th User name
-        %th Default project access
-        %th Team access
-        %th.cred Danger Zone!
-    - @team.members.each do |member|
-      %tr.member
-        %td
-          = link_to [:admin, member] do
-            = member.name
-            %small= "(#{member.email})"
-        %td= @team.human_default_projects_access(member)
-        %td= @team.admin?(member) ? "Admin" : "Member"
-        %td.bgred
-          = link_to 'Edit', edit_admin_team_member_path(@team, member), class: "btn small"
-          &nbsp;
-          = link_to 'Remove', admin_team_member_path(@team, member), confirm: 'Remove member from team. Are you sure?', method: :delete, class: "btn danger small"
-    %tr
-      %td
-      %td
-      %td
-      %td= link_to 'Add members', new_admin_team_member_path(@team), class: "btn primary", id: :add_members_to_team
+  %legend
+    Members (#{@team.members.count})
+    %span= link_to 'Add members', new_admin_team_member_path(@team), class: "btn success small right", id: :add_members_to_team
+  - if @team.members.any?
+    %table#members_list
+      %thead
+        %tr
+          %th User name
+          %th Default project access
+          %th Team access
+          %th.cred.span3 Danger Zone!
+      - @team.members.each do |member|
+        %tr.member
+          %td
+            = link_to [:admin, member] do
+              = member.name
+              %small= "(#{member.email})"
+          %td= @team.human_default_projects_access(member)
+          %td= @team.admin?(member) ? "Admin" : "Member"
+          %td.bgred
+            = link_to 'Edit', edit_admin_team_member_path(@team, member), class: "btn small"
+            &nbsp;
+            = link_to 'Remove', admin_team_member_path(@team, member), confirm: 'Remove member from team. Are you sure?', method: :delete, class: "btn danger small"
 
 %fieldset
-  %legend Projects (#{@team.projects.count})
-  %table#projects_list
-    %thead
-      %tr
-        %th Project name
-        %th Max access
-        %th.cred Danger Zone!
-    - @team.projects.each do |project|
-      %tr.project
-        %td
-          = link_to project.name_with_namespace, [:admin, project]
-        %td
-          %span= @team.human_max_project_access(project)
-        %td.bgred
-          = link_to 'Edit', edit_admin_team_project_path(@team, project), class: "btn small"
-          &nbsp;
-          = link_to 'Relegate', admin_team_project_path(@team, project), confirm: 'Remove project from team. Are you sure?', method: :delete, class: "btn danger small"
-    %tr
-      %td
-      %td
-      %td= link_to 'Add projects', new_admin_team_project_path(@team), class: "btn primary", id: :assign_projects_to_team
+  %legend
+    Projects (#{@team.projects.count})
+    %span= link_to 'Add projects', new_admin_team_project_path(@team), class: "btn success small right", id: :assign_projects_to_team
+  - if @team.projects.any?
+    %table#projects_list
+      %thead
+        %tr
+          %th Project name
+          %th Max access
+          %th.cred.span3 Danger Zone!
+      - @team.projects.each do |project|
+        %tr.project
+          %td
+            = link_to project.name_with_namespace, [:admin, project]
+          %td
+            %span= @team.human_max_project_access(project)
+          %td.bgred
+            = link_to 'Edit', edit_admin_team_project_path(@team, project), class: "btn small"
+            &nbsp;
+            = link_to 'Relegate', admin_team_project_path(@team, project), confirm: 'Remove project from team. Are you sure?', method: :delete, class: "btn danger small"
 
 :javascript
   $(function(){
diff --git a/app/views/dashboard/_teams.html.haml b/app/views/dashboard/_teams.html.haml
index cbf97b93097..414bb12a945 100644
--- a/app/views/dashboard/_teams.html.haml
+++ b/app/views/dashboard/_teams.html.haml
@@ -2,7 +2,7 @@
   %h5.title
     My Teams
     %small
-      (#{teams.count})
+      (#{@teams.count})
     %span.right
       = link_to new_team_path, class: "btn very_small info" do
         %i.icon-plus
@@ -12,7 +12,7 @@
         %i.icon-user
         All Teams
   %ul.well-list
-    - teams.each do |team|
+    - @teams.each do |team|
       %li
         = link_to team_path(id: team.path), class: dom_class(team) do
           %strong.well-title= truncate(team.name, length: 35)
@@ -20,4 +20,7 @@
             &rarr;
           %span.last_activity
             %strong Projects:
-            %span= current_user.authorized_projects.in_team(team).count
+            %span= team.projects.count
+          %span.last_activity
+            %strong Members:
+            %span= team.members.count
diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml
index 8f4f3d7815f..945500d4b6c 100644
--- a/app/views/layouts/_head_panel.html.haml
+++ b/app/views/layouts/_head_panel.html.haml
@@ -8,6 +8,9 @@
         %span.separator
       %h1.project_name= title
       %ul.nav
+        %li
+          = link_to teams_path, title: "Teams of users", class: 'has_bottom_tooltip', 'data-original-title' => 'Teams list'  do
+            %i.icon-globe
         - if current_user.is_admin?
           %li
             = link_to admin_root_path, title: "Admin area", class: 'has_bottom_tooltip', 'data-original-title' => 'Admin area' do
diff --git a/app/views/layouts/user_team.html.haml b/app/views/layouts/user_team.html.haml
index bd3dfe0d418..aa613d71f90 100644
--- a/app/views/layouts/user_team.html.haml
+++ b/app/views/layouts/user_team.html.haml
@@ -1,22 +1,22 @@
 !!! 5
 %html{ lang: "en"}
-  = render "layouts/head", title: "#{@user_team.name}"
+  = render "layouts/head", title: "#{@team.name}"
   %body{class: "#{app_theme} application"}
     = render "layouts/flash"
-    = render "layouts/head_panel", title: "#{@user_team.name}"
+    = render "layouts/head_panel", title: "#{@team.name}"
     .container
       %ul.main_menu
         = nav_link(path: 'teams#show', html_options: {class: 'home'}) do
-          = link_to "Home", team_path(@user_team), title: "Home"
+          = link_to "Home", team_path(@team), title: "Home"
         = nav_link(path: 'teams#issues') do
-          = link_to issues_team_path(@user_team) do
+          = link_to issues_team_path(@team) do
             Issues
-            %span.count= Issue.opened.of_user_team(@user_team).count
+            %span.count= Issue.opened.of_user_team(@team).count
         = nav_link(path: 'teams#merge_requests') do
-          = link_to merge_requests_team_path(@user_team) do
+          = link_to merge_requests_team_path(@team) do
             Merge Requests
-            %span.count= MergeRequest.opened.of_user_team(@user_team).count
+            %span.count= MergeRequest.opened.of_user_team(@team).count
         = nav_link(path: 'teams#search') do
-          = link_to "Search", search_team_path(@user_team)
+          = link_to "Search", search_team_path(@team)
 
       .content= yield
diff --git a/app/views/teams/_team_head.html.haml b/app/views/teams/_team_head.html.haml
index 53796623de1..cb5c9567ba6 100644
--- a/app/views/teams/_team_head.html.haml
+++ b/app/views/teams/_team_head.html.haml
@@ -1,19 +1,19 @@
 %ul.nav.nav-tabs
   = nav_link(path: 'teams#show') do
-    = link_to team_path(@user_team), class: "activities-tab tab" do
+    = link_to team_path(@team), class: "activities-tab tab" do
       %i.icon-home
       Show
   = nav_link(controller: [:members]) do
-    = link_to team_members_path(@user_team), class: "team-tab tab" do
+    = link_to team_members_path(@team), class: "team-tab tab" do
       %i.icon-user
       Members
   = nav_link(controller: [:projects]) do
-    = link_to team_projects_path(@user_team), class: "team-tab tab" do
+    = link_to team_projects_path(@team), class: "team-tab tab" do
       %i.icon-briefcase
       Projects
 
-  - if can? current_user, :manage_user_team, @user_team
+  - if can? current_user, :admin_user_team, @team
     = nav_link(path: 'teams#edit', html_options: {class: 'right'}) do
-      = link_to edit_team_path(@user_team), class: "stat-tab tab " do
+      = link_to edit_team_path(@team), class: "stat-tab tab " do
         %i.icon-edit
-        Edit
+        Edit Team
diff --git a/app/views/teams/edit.html.haml b/app/views/teams/edit.html.haml
index 4c239e8fa41..b2ceb2bdb21 100644
--- a/app/views/teams/edit.html.haml
+++ b/app/views/teams/edit.html.haml
@@ -1,11 +1,11 @@
 = render "team_head"
 
-%h3.page_title= "Edit Team #{@user_team.name}"
+%h3.page_title= "Edit Team #{@team.name}"
 %hr
-= form_for @user_team, url: teams_path do |f|
-  - if @user_team.errors.any?
+= form_for @team, url: teams_path do |f|
+  - if @team.errors.any?
     .alert-message.block-message.error
-      %span= @user_team.errors.full_messages.first
+      %span= @team.errors.full_messages.first
   .clearfix
     = f.label :name do
       Team name is
@@ -21,12 +21,4 @@
     .input.span3.center
       = f.submit 'Save team changes', class: "btn primary"
     .input.span3.center
-      = link_to 'Delete team', team_path(@user_team), method: :delete, confirm: "You are shure?", class: "btn danger"
-  %hr
-  .padded
-    %ul
-      %li Team is kind of directory for several projects
-      %li All created teams are private
-      %li People within a team see only projects they have access to
-      %li All projects of team will be stored in team directory
-      %li You will be able to move existing projects into team
+      = link_to 'Delete team', team_path(@team), method: :delete, confirm: "You are shure?", class: "btn danger"
diff --git a/app/views/teams/index.html.haml b/app/views/teams/index.html.haml
index 9ac54594521..8f8874328fc 100644
--- a/app/views/teams/index.html.haml
+++ b/app/views/teams/index.html.haml
@@ -3,7 +3,7 @@
   %small
     list of all teams
 
-  = link_to 'New Team', new_team_path, class: "btn small right"
+  = link_to 'New Team', new_team_path, class: "btn success small right"
   %br
 
 = form_tag search_teams_path, method: :get, class: 'form-inline' do
@@ -32,6 +32,7 @@
       %td= link_to team.owner.name, team_member_path(team, team.owner)
       %td
         - if current_user.can?(:manage_user_team, team)
-          - if team.owner == current_user
+          - if current_user.can?(:admin_user_team, team)
             = link_to "Destroy", team_path(team), method: :delete, confirm: "You are shure?", class: "danger btn small right"
+            &nbsp;
           = link_to "Edit", edit_team_path(team), class: "btn small right"
diff --git a/app/views/teams/members/_form.html.haml b/app/views/teams/members/_form.html.haml
index a963e462a78..b75d788a94a 100644
--- a/app/views/teams/members/_form.html.haml
+++ b/app/views/teams/members/_form.html.haml
@@ -1,23 +1,20 @@
-%h3.page_title
-  = "New Team member(s)"
-%hr
-= form_for @team_member, as: :team_member, url: project_team_members_path(@project, @team_member) do |f|
-  -if @team_member.errors.any?
+= form_tag admin_team_member_path(@team, @member), method: :put do
+  -if @member.errors.any?
     .alert-message.block-message.error
       %ul
-        - @team_member.errors.full_messages.each do |msg|
+        - @member.errors.full_messages.each do |msg|
           %li= msg
 
-  %h6 1. Choose people you want in the team
   .clearfix
-    = f.label :user_ids, "People"
-    .input= select_tag(:user_ids, options_from_collection_for_select(User.active.not_in_project(@project).alphabetically, :id, :name), {data: {placeholder: "Select users"}, class: "chosen xxlarge", multiple: true})
-
-  %h6 2. Set access level for them
+    %label Default access for Team projects:
+    .input
+      = select_tag :default_project_access, options_for_select(UserTeam.access_roles, @team.default_projects_access(@member)), class: "project-access-select chosen span3"
   .clearfix
-    = f.label :project_access, "Project Access"
-    .input= select_tag :project_access, options_for_select(Project.access_options, @team_member.project_access), class: "project-access-select chosen"
+    %label Team admin?
+    .input
+      = check_box_tag :group_admin, true, @team.admin?(@member)
 
+  %br
   .actions
-    = f.submit 'Save', class: "btn save-btn"
-    = link_to "Cancel", project_team_index_path(@project), class: "btn cancel-btn"
+    = submit_tag 'Save', class: "btn primary"
+    = link_to 'Cancel', :back, class: "btn"
diff --git a/app/views/teams/members/_show.html.haml b/app/views/teams/members/_show.html.haml
index a06d269ac00..ec4728787cf 100644
--- a/app/views/teams/members/_show.html.haml
+++ b/app/views/teams/members/_show.html.haml
@@ -1,11 +1,11 @@
 - user = member.user
-- allow_admin = can? current_user, :manage_user_team, @user_team
+- allow_admin = can? current_user, :manage_user_team, @team
 %li{id: dom_id(member), class: "team_member_row user_#{user.id}"}
   .row
     .span5
-      = link_to team_member_path(@user_team, user), title: user.name, class: "dark" do
+      = link_to team_member_path(@team, user), title: user.name, class: "dark" do
         = image_tag gravatar_icon(user.email, 40), class: "avatar s32"
-      = link_to team_member_path(@user_team, user), title: user.name, class: "dark" do
+      = link_to team_member_path(@team, user), title: user.name, class: "dark" do
         %strong= truncate(user.name, lenght: 40)
         %br
         %small.cgray= user.email
@@ -13,8 +13,8 @@
     .span6.right
       - if allow_admin
         .left.span2
-          = form_for(member, as: :team_member, url: team_member_path(@user_team, user)) do |f|
-            = f.select :permission, options_for_select(UsersProject.access_roles, @user_team.default_projects_access(user)), {}, class: "medium project-access-select 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
             Admin access
@@ -22,10 +22,10 @@
       .right
         - if current_user == user
           %span.btn.disabled This is you!
-        - if @user_team.owner == user
+        - if @team.owner == user
           %span.btn.disabled.success Owner
         - elsif user.blocked
           %span.btn.disabled.blocked Blocked
         - elsif allow_admin
-          = link_to team_member_path(@user_team, user), confirm: remove_from_user_team_message(@user_team, user), method: :delete, class: "very_small btn danger" do
+          = link_to team_member_path(@team, user), confirm: remove_from_user_team_message(@team, user), method: :delete, class: "very_small btn danger" do
             %i.icon-minus.icon-white
diff --git a/app/views/teams/members/_team.html.haml b/app/views/teams/members/_team.html.haml
index e1fbf6d1e75..d8afc1fa371 100644
--- a/app/views/teams/members/_team.html.haml
+++ b/app/views/teams/members/_team.html.haml
@@ -1,4 +1,4 @@
-- grouped_user_team_members(@user_team).each do |access, members|
+- grouped_user_team_members(@team).each do |access, members|
   .ui-box
     %h5.title
       = Project.access_options.key(access).pluralize
diff --git a/app/views/teams/members/edit.html.haml b/app/views/teams/members/edit.html.haml
index a2742977717..9caff799552 100644
--- a/app/views/teams/members/edit.html.haml
+++ b/app/views/teams/members/edit.html.haml
@@ -1,2 +1,18 @@
-%h1 Teams::Members#edit
-%p Find me in app/views/teams/members/edit.html.haml
\ No newline at end of file
+= render "teams/team_head"
+
+%h3
+  Edit access #{@member.name} in #{@team.name} team
+
+%hr
+%table.zebra-striped
+  %tr
+    %td User:
+    %td= @member.name
+  %tr
+    %td Team:
+    %td= @team.name
+  %tr
+    %td Since:
+    %td= member_since(@team, @member).stamp("Nov 11, 2010")
+
+= render 'form'
diff --git a/app/views/teams/members/import.html.haml b/app/views/teams/members/import.html.haml
deleted file mode 100644
index de82f416248..00000000000
--- a/app/views/teams/members/import.html.haml
+++ /dev/null
@@ -1,17 +0,0 @@
-= render "projects/project_head"
-
-%h3.page_title
-  = "Import team from another project"
-%hr
-%p.slead
-  Read more about team import #{link_to "here", '#', class: 'vlink'}.
-= form_tag apply_import_project_team_members_path(@project), method: 'post' do
-  %p.slead Choose project you want to use as team source:
-  .padded
-    = label_tag :source_project_id, "Project"
-    .input= select_tag(:source_project_id, options_from_collection_for_select(current_user.authorized_projects, :id, :name_with_namespace), prompt: "Select project", class: "chosen xxlarge", required: true)
-
-  .actions
-    = submit_tag 'Import', class: "btn save-btn"
-    = link_to "Cancel", project_team_index_path(@project), class: "btn cancel-btn"
-
diff --git a/app/views/teams/members/index.html.haml b/app/views/teams/members/index.html.haml
index 5b125b32769..1628237ede0 100644
--- a/app/views/teams/members/index.html.haml
+++ b/app/views/teams/members/index.html.haml
@@ -1,4 +1,5 @@
 = render "teams/team_head"
+
 %h3.page_title
   Team Members
   (#{@members.count})
@@ -6,13 +7,13 @@
     Read more about project permissions
     %strong= link_to "here", help_permissions_path, class: "vlink"
 
-  - if can? current_user, :manage_user_team, @user_team
+  - if can? current_user, :manage_user_team, @team
     %span.right
-      = link_to new_team_member_path(@user_team), class: "btn success small grouped", title: "New Team Member" do
+      = link_to new_team_member_path(@team), class: "btn success small grouped", title: "New Team Member" do
         New Team Member
 %hr
 
 
 .clearfix
 %div.team-table
-  = render partial: "teams/members/team", locals: {project: @user_team}
+  = render partial: "teams/members/team", locals: {project: @team}
diff --git a/app/views/teams/members/new.html.haml b/app/views/teams/members/new.html.haml
index 40eb4cebf08..43f7c5d7b6f 100644
--- a/app/views/teams/members/new.html.haml
+++ b/app/views/teams/members/new.html.haml
@@ -1,2 +1,30 @@
-= render "projects/project_head"
-= render "team_members/form"
+= render "teams/team_head"
+
+%h3.page_title
+  Team: #{@team.name}
+
+%fieldset
+  %legend Members (#{@team.members.count})
+  = form_tag team_members_path(@team), id: "team_members", class: "bulk_import", method: :post  do
+    %table#members_list
+      %thead
+        %tr
+          %th User name
+          %th Default project access
+          %th Team access
+          %th
+      - @team.members.each do |member|
+        %tr.member
+          %td
+            = member.name
+            %small= "(#{member.email})"
+          %td= @team.human_default_projects_access(member)
+          %td= @team.admin?(member) ? "Admin" : "Member"
+          %td
+      %tr
+        %td= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name_with_email), multiple: true, data: {placeholder: 'Select users'}, class: 'chosen span5'
+        %td= select_tag :default_project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3" }
+        %td
+          %span= check_box_tag :group_admin
+          %span Admin?
+        %td= submit_tag 'Add', class: "btn primary", id: :add_members_to_team
diff --git a/app/views/teams/members/show.html.haml b/app/views/teams/members/show.html.haml
index 4008e8bd23e..03ef21be7a6 100644
--- a/app/views/teams/members/show.html.haml
+++ b/app/views/teams/members/show.html.haml
@@ -1,3 +1,5 @@
+= render "teams/team_head"
+
 - allow_admin = can? current_user, :admin_project, @project
 - user = @team_member.user
 
diff --git a/app/views/teams/merge_requests.html.haml b/app/views/teams/merge_requests.html.haml
index c9af529e113..f16331e1cdd 100644
--- a/app/views/teams/merge_requests.html.haml
+++ b/app/views/teams/merge_requests.html.haml
@@ -1,3 +1,5 @@
+= render "team_head"
+
 %h3.page_title
   Merge Requests
   %small (authored by or assigned to Team members)
diff --git a/app/views/teams/new.html.haml b/app/views/teams/new.html.haml
index d8312e0e913..a068c51e6ab 100644
--- a/app/views/teams/new.html.haml
+++ b/app/views/teams/new.html.haml
@@ -14,8 +14,6 @@
   %hr
   .padded
     %ul
-      %li Team is kind of directory for several projects
-      %li All created teams are private
+      %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 All projects of team will be stored in team directory
-      %li You will be able to move existing projects into team
+      %li You will be able to assign existing projects for team
diff --git a/app/views/teams/projects/_form.html.haml b/app/views/teams/projects/_form.html.haml
new file mode 100644
index 00000000000..3749dbc4f99
--- /dev/null
+++ b/app/views/teams/projects/_form.html.haml
@@ -0,0 +1,16 @@
+= form_tag team_project_path(@team, @project), method: :put do
+  -if @project.errors.any?
+    .alert-message.block-message.error
+      %ul
+        - @project.errors.full_messages.each do |msg|
+          %li= msg
+
+  .clearfix
+    %label Max access for Team members:
+    .input
+      = select_tag :greatest_project_access, options_for_select(UserTeam.access_roles, @team.max_project_access(@project)), class: "project-access-select chosen span3"
+
+  %br
+  .actions
+    = submit_tag 'Save', class: "btn primary"
+    = link_to 'Cancel', :back, class: "btn"
diff --git a/app/views/teams/projects/edit.html.haml b/app/views/teams/projects/edit.html.haml
index 66c9f0671ff..056ee6852c1 100644
--- a/app/views/teams/projects/edit.html.haml
+++ b/app/views/teams/projects/edit.html.haml
@@ -1,4 +1,18 @@
 = render "teams/team_head"
 
-%h1 Teams::Projects#edit
-%p Find me in app/views/teams/projects/edit.html.haml
+%h3
+  Edit max access in #{@project.name} for #{@team.name} team
+
+%hr
+%table.zebra-striped
+  %tr
+    %td Project:
+    %td= @project.name
+  %tr
+    %td Team:
+    %td= @team.name
+  %tr
+    %td Since:
+    %td= assigned_since(@team, @project).stamp("Nov 11, 2010")
+
+= render 'form'
diff --git a/app/views/teams/projects/index.html.haml b/app/views/teams/projects/index.html.haml
index 66cb12a8421..b0a50e594cf 100644
--- a/app/views/teams/projects/index.html.haml
+++ b/app/views/teams/projects/index.html.haml
@@ -1,34 +1,34 @@
 = render "teams/team_head"
 
-%fieldset
-  %legend Projects (#{@user_team.projects.count})
-  = form_tag delegate_projects_team_path(@user_team), id: "team_projects", class: "bulk_import", method: :post  do
-    %table
-      %thead
-        %tr
-          %th Project name
-          %th Max access
-          %th
-      - @user_team.projects.each do |project|
-        %tr.project
-          %td
-            = link_to project.name_with_namespace, project
-          %td
-            %span= @user_team.human_max_project_access(project)
-            -# if current_user.can?(:manage_user_team, @user_team)
-              - relation = project.user_team_project_relationships.find_by_user_team_id(@user_team)
-              = form_for(relation, as: :project, url: team_project_path(@user_team, project)) do |f|
-                = f.select :greatest_access, options_for_select(UsersProject.access_roles, @user_team.max_project_access(project)), {}, class: "medium project-access-select span2"
+%h3.page_title
+  Assigned projects (#{@team.projects.count})
+  %small
+    Read more about project permissions
+    %strong= link_to "here", help_permissions_path, class: "vlink"
 
-          - if current_user.can?(:admin_user_team, @user_team)
-            %td.bgred
-              -#= link_to 'Edit max access', edit_project_team_path(@user_team, project), class: "btn small"
-              = link_to 'Relegate', relegate_project_team_path(@user_team, project_id: project.id), confirm: 'Remove project from team and move to global namespace. Are you sure?', method: :delete, class: "btn danger small"
-          - else
-            %td
+  - if current_user.can?(:manage_user_team, @team) && @avaliable_projects.any?
+    %span.right
+      = link_to new_team_project_path(@team), class: "btn success small grouped", title: "New Team Member" do
+        Assign project to Team
 
-      - if @avaliable_projects.any?
-        %tr
-          %td= select_tag :project_ids, options_from_collection_for_select(@avaliable_projects , :id, :name_with_namespace), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5'
-          %td= select_tag :greatest_project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3" }
-          %td= submit_tag 'Add', class: "btn primary"
+%hr
+
+%table
+  %thead
+    %tr
+      %th Project name
+      %th Max access
+      - if current_user.can?(:admin_user_team, @team)
+        %th.span3
+
+  - @team.projects.each do |project|
+    %tr.project
+      %td
+        = link_to project.name_with_namespace, project_path(project)
+      %td
+        %span= @team.human_max_project_access(project)
+
+      - if current_user.can?(:admin_user_team, @team)
+        %td.bgred
+          = link_to 'Edit max access', edit_team_project_path(@team, project), class: "btn small"
+          = link_to 'Relegate', team_project_path(@team, project), confirm: 'Remove project from team and move to global namespace. Are you sure?', method: :delete, class: "btn danger small"
diff --git a/app/views/teams/projects/new.html.haml b/app/views/teams/projects/new.html.haml
index 24d2d4c34ca..000f62bb643 100644
--- a/app/views/teams/projects/new.html.haml
+++ b/app/views/teams/projects/new.html.haml
@@ -1,4 +1,25 @@
 = render "teams/team_head"
 
-%h1 Teams::Projects#new
-%p Find me in app/views/teams/projects/new.html.haml
+%h3.page_title
+  Team: #{@team.name}
+
+%fieldset
+  %legend Projects (#{@team.projects.count})
+  = form_tag team_projects_path(@team), id: "assign_projects", class: "bulk_import", method: :post  do
+    %table#projects_list
+      %thead
+        %tr
+          %th Project name
+          %th Max access
+          %th
+      - @team.projects.each do |project|
+        %tr.project
+          %td
+            = link_to project.name_with_namespace, team_project_path(@team, project)
+          %td
+            %span= @team.human_max_project_access(project)
+          %td
+      %tr
+        %td= select_tag :project_ids, options_from_collection_for_select(@avaliable_projects , :id, :name_with_namespace), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5'
+        %td= select_tag :greatest_project_access, options_for_select(UserTeam.access_roles), {class: "project-access-select chosen span3" }
+        %td= submit_tag 'Add', class: "btn primary", id: :assign_projects_to_team
diff --git a/app/views/teams/projects/show.html.haml b/app/views/teams/projects/show.html.haml
deleted file mode 100644
index 66c9f0671ff..00000000000
--- a/app/views/teams/projects/show.html.haml
+++ /dev/null
@@ -1,4 +0,0 @@
-= render "teams/team_head"
-
-%h1 Teams::Projects#edit
-%p Find me in app/views/teams/projects/edit.html.haml
diff --git a/app/views/teams/search.html.haml b/app/views/teams/search.html.haml
index 601f2d57c8b..5c357c5cfcb 100644
--- a/app/views/teams/search.html.haml
+++ b/app/views/teams/search.html.haml
@@ -1,6 +1,6 @@
 = render "team_head"
 
-= form_tag search_team_path(@user_team), method: :get, class: 'form-inline' do |f|
+= form_tag search_team_path(@team), method: :get, class: 'form-inline' do |f|
   .padded
     = label_tag :search do
       %strong Looking for
-- 
GitLab


From 31d84d71d3659dc815875f39f466cdcf81d97aaf Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Wed, 23 Jan 2013 18:14:20 +0400
Subject: [PATCH 059/197] assign team to project from project page in public
 section

---
 .../projects/application_controller.rb        | 11 ++++++++
 app/controllers/projects/teams_controller.rb  | 27 +++++++++++++++++++
 app/helpers/projects_helper.rb                |  4 +++
 app/models/user_team.rb                       |  2 ++
 app/models/user_team_project_relationship.rb  |  4 +++
 app/views/projects/_project_head.html.haml    |  2 +-
 app/views/projects/teams/avaliable.html.haml  | 22 +++++++++++++++
 app/views/team_members/_show_team.html.haml   | 15 +++++++++++
 app/views/team_members/_teams.html.haml       | 16 +++++++++++
 app/views/team_members/import.html.haml       |  2 +-
 app/views/team_members/index.html.haml        | 15 ++++++++++-
 config/routes.rb                              | 12 +++++++++
 12 files changed, 129 insertions(+), 3 deletions(-)
 create mode 100644 app/controllers/projects/application_controller.rb
 create mode 100644 app/controllers/projects/teams_controller.rb
 create mode 100644 app/views/projects/teams/avaliable.html.haml
 create mode 100644 app/views/team_members/_show_team.html.haml
 create mode 100644 app/views/team_members/_teams.html.haml

diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb
new file mode 100644
index 00000000000..7e4776d2d75
--- /dev/null
+++ b/app/controllers/projects/application_controller.rb
@@ -0,0 +1,11 @@
+class Projects::ApplicationController < ApplicationController
+
+  before_filter :authorize_admin_team_member!
+
+  protected
+
+  def user_team
+    @team ||= UserTeam.find_by_path(params[:id])
+  end
+
+end
diff --git a/app/controllers/projects/teams_controller.rb b/app/controllers/projects/teams_controller.rb
new file mode 100644
index 00000000000..c04835ed153
--- /dev/null
+++ b/app/controllers/projects/teams_controller.rb
@@ -0,0 +1,27 @@
+class Projects::TeamsController < Projects::ApplicationController
+
+  def avaliable
+    @teams = current_user.is_admin? ? UserTeam.scoped : current_user.user_teams
+    @teams = @teams.without_project(project)
+    unless @teams.any?
+      redirect_to project_team_index_path(project), notice: "No avaliable teams for assigment."
+    end
+  end
+
+  def assign
+    unless params[:team_id].blank?
+      team = UserTeam.find(params[:team_id])
+      access = params[:greatest_project_access]
+      team.assign_to_project(project, access)
+    end
+    redirect_to project_team_index_path(project)
+  end
+
+  def resign
+    team = project.user_teams.find_by_path(params[:id])
+    team.resign_from_project(project)
+
+    redirect_to project_team_index_path(project)
+  end
+
+end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index dbd47998eb1..c6cb9129499 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -3,6 +3,10 @@ module ProjectsHelper
     @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
diff --git a/app/models/user_team.rb b/app/models/user_team.rb
index 2e2f75060c3..0442123fc24 100644
--- a/app/models/user_team.rb
+++ b/app/models/user_team.rb
@@ -16,6 +16,8 @@ class UserTeam < ActiveRecord::Base
                       message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" }
 
   scope :with_member, ->(user){ joins(:user_team_user_relationships).where(user_team_user_relationships: {user_id: user.id}) }
+  scope :with_project, ->(project){ joins(:user_team_project_relationships).where(user_team_project_relationships: {project_id: project})}
+  scope :without_project, ->(project){ where("id NOT IN (:ids)", ids: with_project(project))}
   scope :created_by, ->(user){ where(owner_id: user) }
 
   class << self
diff --git a/app/models/user_team_project_relationship.rb b/app/models/user_team_project_relationship.rb
index 4413c492a6d..1b0368c7ecc 100644
--- a/app/models/user_team_project_relationship.rb
+++ b/app/models/user_team_project_relationship.rb
@@ -10,6 +10,10 @@ class UserTeamProjectRelationship < ActiveRecord::Base
 
   scope :with_project, ->(project){ where(project_id: project.id) }
 
+  def team_name
+    user_team.name
+  end
+
   private
 
   def check_greatest_access
diff --git a/app/views/projects/_project_head.html.haml b/app/views/projects/_project_head.html.haml
index 94052650694..cc215502859 100644
--- a/app/views/projects/_project_head.html.haml
+++ b/app/views/projects/_project_head.html.haml
@@ -3,7 +3,7 @@
     = link_to project_path(@project), class: "activities-tab tab" do
       %i.icon-home
       Show
-  = nav_link(controller: :team_members) do
+  = nav_link(controller: [:team_members, :teams]) do
     = link_to project_team_index_path(@project), class: "team-tab tab" do
       %i.icon-user
       Team
diff --git a/app/views/projects/teams/avaliable.html.haml b/app/views/projects/teams/avaliable.html.haml
new file mode 100644
index 00000000000..814e216d6ad
--- /dev/null
+++ b/app/views/projects/teams/avaliable.html.haml
@@ -0,0 +1,22 @@
+= render "projects/project_head"
+
+%h3.page_title
+  = "Assign project to team of users"
+%hr
+%p.slead
+  Read more about assign to team of users #{link_to "here", '#', class: 'vlink'}.
+= form_tag assign_project_teams_path(@project), method: 'post' do
+  %p.slead Choose Team of users you want to assign:
+  .padded
+    = label_tag :team_id, "Team"
+    .input= select_tag(:team_id, options_from_collection_for_select(@teams, :id, :name), prompt: "Select team", class: "chosen xxlarge", required: true)
+  %p.slead Choose greatest user acces in team you want to assign:
+  .padded
+    = label_tag :team_ids, "Permission"
+    .input= select_tag :greatest_project_access, options_for_select(UserTeam.access_roles), {class: "project-access-select chosen span3" }
+
+
+  .actions
+    = submit_tag 'Assign', class: "btn save-btn"
+    = link_to "Cancel", project_team_index_path(@project), class: "btn cancel-btn"
+
diff --git a/app/views/team_members/_show_team.html.haml b/app/views/team_members/_show_team.html.haml
new file mode 100644
index 00000000000..da0262efda5
--- /dev/null
+++ b/app/views/team_members/_show_team.html.haml
@@ -0,0 +1,15 @@
+- team = team_rel.user_team
+- allow_admin = can? current_user, :admin_team_member, @project
+%li{id: dom_id(team), class: "user_team_row team_#{team.id}"}
+  .row
+    .span6
+      %strong= link_to team.name, team_path(team), title: team.name, class: "dark"
+      %br
+      %small.cgray Members: #{team.members.count}
+
+    .span5.right
+      .right
+        - if allow_admin
+          .left
+            = link_to resign_project_team_path(@project, team), method: :delete, confirm: "Are you shure?", class: "btn danger small" do
+              %i.icon-minus.icon-white
diff --git a/app/views/team_members/_teams.html.haml b/app/views/team_members/_teams.html.haml
new file mode 100644
index 00000000000..156fdd1befa
--- /dev/null
+++ b/app/views/team_members/_teams.html.haml
@@ -0,0 +1,16 @@
+- grouper_project_teams(@project).each do |access, teams|
+  .ui-box
+    %h5.title
+      = UserTeam.access_roles.key(access).pluralize
+      %small= teams.size
+    %ul.well-list
+      - teams.sort_by(&:team_name).each do |tofr|
+        = render(partial: 'team_members/show_team', locals: {team_rel: tofr})
+
+
+:javascript
+  $(function(){
+    $('.repo-access-select, .project-access-select').live("change", function() {
+      $(this.form).submit();
+    });
+  })
diff --git a/app/views/team_members/import.html.haml b/app/views/team_members/import.html.haml
index de82f416248..135db946041 100644
--- a/app/views/team_members/import.html.haml
+++ b/app/views/team_members/import.html.haml
@@ -4,7 +4,7 @@
   = "Import team from another project"
 %hr
 %p.slead
-  Read more about team import #{link_to "here", '#', class: 'vlink'}.
+  Read more about project team import #{link_to "here", '#', class: 'vlink'}.
 = form_tag apply_import_project_team_members_path(@project), method: 'post' do
   %p.slead Choose project you want to use as team source:
   .padded
diff --git a/app/views/team_members/index.html.haml b/app/views/team_members/index.html.haml
index 8ba13939a30..f694ccbca93 100644
--- a/app/views/team_members/index.html.haml
+++ b/app/views/team_members/index.html.haml
@@ -10,11 +10,24 @@
     %span.right
       = link_to import_project_team_members_path(@project), class: "btn small grouped", title: "Import team from another project" do
         Import team from another project
+      = link_to avaliable_project_teams_path(@project), class: "btn small grouped", title: "Assign project to team of users" do
+        Assign project to Team of users
       = link_to new_project_team_member_path(@project), class: "btn success small grouped", title: "New Team Member" do
         New Team Member
-%hr
 
+%hr
 
 .clearfix
 %div.team-table
   = render partial: "team_members/team", locals: {project: @project}
+
+
+%h3.page_title
+  Assigned teams
+  (#{@project.user_teams.count})
+
+%hr
+
+.clearfix
+%div.team-table
+  = render partial: "team_members/teams", locals: {project: @project}
diff --git a/config/routes.rb b/config/routes.rb
index e8af16387bc..a19ab14f605 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -269,6 +269,18 @@ Gitlab::Application.routes.draw do
       end
     end
 
+    scope module: :projects do
+      resources :teams, only: [] do
+        collection do
+          get :avaliable
+          post :assign
+        end
+        member do
+          delete :resign
+        end
+      end
+    end
+
     resources :notes, only: [:index, :create, :destroy] do
       collection do
         post :preview
-- 
GitLab


From d721863382b3e2cedae03e8f235809eb409224c0 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Wed, 23 Jan 2013 18:14:53 +0400
Subject: [PATCH 060/197] Fix little bugs

---
 app/controllers/teams_controller.rb | 2 ++
 app/helpers/user_teams_helper.rb    | 4 ++--
 config/routes.rb                    | 2 +-
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/app/controllers/teams_controller.rb b/app/controllers/teams_controller.rb
index 169ee34f4ec..ea060b3a44d 100644
--- a/app/controllers/teams_controller.rb
+++ b/app/controllers/teams_controller.rb
@@ -54,6 +54,7 @@ class TeamsController < ApplicationController
 
   # Get authored or assigned open merge requests
   def merge_requests
+    projects
     @merge_requests = MergeRequest.of_user_team(user_team)
     @merge_requests = FilterContext.new(@merge_requests, params).execute
     @merge_requests = @merge_requests.recent.page(params[:page]).per(20)
@@ -61,6 +62,7 @@ class TeamsController < ApplicationController
 
   # Get only assigned issues
   def issues
+    projects
     @issues = Issue.of_user_team(user_team)
     @issues = FilterContext.new(@issues, params).execute
     @issues = @issues.recent.page(params[:page]).per(20)
diff --git a/app/helpers/user_teams_helper.rb b/app/helpers/user_teams_helper.rb
index 60deb9e09e5..2055bb3c8bc 100644
--- a/app/helpers/user_teams_helper.rb
+++ b/app/helpers/user_teams_helper.rb
@@ -9,9 +9,9 @@ module UserTeamsHelper
 
     case entity
     when 'issue' then
-      issues_team_path(@user_team, options)
+      issues_team_path(@team, options)
     when 'merge_request'
-      merge_requests_team_path(@user_team, options)
+      merge_requests_team_path(@team, options)
     end
   end
 
diff --git a/config/routes.rb b/config/routes.rb
index a19ab14f605..387f94ba025 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -21,7 +21,7 @@ Gitlab::Application.routes.draw do
     project_root: Gitlab.config.gitolite.repos_path,
     upload_pack:  Gitlab.config.gitolite.upload_pack,
     receive_pack: Gitlab.config.gitolite.receive_pack
-  }), at: '/', constraints: lambda { |request| /[-\/\w\.-]+\.git\//.match(request.path_info) }
+  }), at: '/', constraints: lambda { |request| /[-\/\w\.]+\.git\//.match(request.path_info) }
 
   #
   # Help
-- 
GitLab


From a5ce8696a6aa5a3a588fc618d8c959ce6c687310 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Wed, 23 Jan 2013 20:42:38 +0400
Subject: [PATCH 061/197] remove unused autogenerated files

---
 .../javascripts/admin/teams/members.js.coffee |  3 --
 .../admin/teams/projects.js.coffee            |  3 --
 .../stylesheets/admin/teams/members.css.scss  |  3 --
 .../stylesheets/admin/teams/projects.css.scss |  3 --
 .../admin/projects/members_controller_spec.rb | 26 ---------
 .../admin/teams/members_controller_spec.rb    | 40 --------------
 .../admin/teams/projects_controller_spec.rb   | 40 --------------
 .../admin/teams_controller_spec.rb            | 47 ----------------
 .../teams/members_controller_spec.rb          | 47 ----------------
 .../teams/projects_controller_spec.rb         | 47 ----------------
 spec/controllers/teams_controller_spec.rb     | 54 -------------------
 .../admin/teams/members_helper_spec.rb        | 15 ------
 .../admin/teams/projects_helper_spec.rb       | 15 ------
 .../admin/teams/create.html.haml_spec.rb      |  5 --
 .../admin/teams/destroy.html.haml_spec.rb     |  5 --
 spec/views/admin/teams/edit.html.haml_spec.rb |  5 --
 .../views/admin/teams/index.html.haml_spec.rb |  5 --
 .../teams/members/create.html.haml_spec.rb    |  5 --
 .../teams/members/destroy.html.haml_spec.rb   |  5 --
 .../teams/members/edit.html.haml_spec.rb      |  5 --
 .../admin/teams/members/new.html.haml_spec.rb |  5 --
 .../teams/members/update.html.haml_spec.rb    |  5 --
 .../teams/projects/create.html.haml_spec.rb   |  5 --
 .../teams/projects/destroy.html.haml_spec.rb  |  5 --
 .../teams/projects/edit.html.haml_spec.rb     |  5 --
 .../teams/projects/new.html.haml_spec.rb      |  5 --
 .../teams/projects/update.html.haml_spec.rb   |  5 --
 spec/views/admin/teams/show.html.haml_spec.rb |  5 --
 .../admin/teams/update.html.haml_spec.rb      |  5 --
 spec/views/teams/create.html.haml_spec.rb     |  5 --
 spec/views/teams/destroy.html.haml_spec.rb    |  5 --
 spec/views/teams/edit.html.haml_spec.rb       |  5 --
 spec/views/teams/index.html.haml_spec.rb      |  5 --
 .../teams/members/create.html.haml_spec.rb    |  5 --
 .../teams/members/destroy.html.haml_spec.rb   |  5 --
 .../teams/members/edit.html.haml_spec.rb      |  5 --
 .../teams/members/index.html.haml_spec.rb     |  5 --
 .../views/teams/members/new.html.haml_spec.rb |  5 --
 .../teams/members/update.html.haml_spec.rb    |  5 --
 spec/views/teams/new.html.haml_spec.rb        |  5 --
 .../teams/projects/create.html.haml_spec.rb   |  5 --
 .../teams/projects/destroy.html.haml_spec.rb  |  5 --
 .../teams/projects/edit.html.haml_spec.rb     |  5 --
 .../teams/projects/index.html.haml_spec.rb    |  5 --
 .../teams/projects/new.html.haml_spec.rb      |  5 --
 .../teams/projects/update.html.haml_spec.rb   |  5 --
 spec/views/teams/show.html.haml_spec.rb       |  5 --
 spec/views/teams/update.html.haml_spec.rb     |  5 --
 48 files changed, 518 deletions(-)
 delete mode 100644 app/assets/javascripts/admin/teams/members.js.coffee
 delete mode 100644 app/assets/javascripts/admin/teams/projects.js.coffee
 delete mode 100644 app/assets/stylesheets/admin/teams/members.css.scss
 delete mode 100644 app/assets/stylesheets/admin/teams/projects.css.scss
 delete mode 100644 spec/controllers/admin/projects/members_controller_spec.rb
 delete mode 100644 spec/controllers/admin/teams/members_controller_spec.rb
 delete mode 100644 spec/controllers/admin/teams/projects_controller_spec.rb
 delete mode 100644 spec/controllers/admin/teams_controller_spec.rb
 delete mode 100644 spec/controllers/teams/members_controller_spec.rb
 delete mode 100644 spec/controllers/teams/projects_controller_spec.rb
 delete mode 100644 spec/controllers/teams_controller_spec.rb
 delete mode 100644 spec/helpers/admin/teams/members_helper_spec.rb
 delete mode 100644 spec/helpers/admin/teams/projects_helper_spec.rb
 delete mode 100644 spec/views/admin/teams/create.html.haml_spec.rb
 delete mode 100644 spec/views/admin/teams/destroy.html.haml_spec.rb
 delete mode 100644 spec/views/admin/teams/edit.html.haml_spec.rb
 delete mode 100644 spec/views/admin/teams/index.html.haml_spec.rb
 delete mode 100644 spec/views/admin/teams/members/create.html.haml_spec.rb
 delete mode 100644 spec/views/admin/teams/members/destroy.html.haml_spec.rb
 delete mode 100644 spec/views/admin/teams/members/edit.html.haml_spec.rb
 delete mode 100644 spec/views/admin/teams/members/new.html.haml_spec.rb
 delete mode 100644 spec/views/admin/teams/members/update.html.haml_spec.rb
 delete mode 100644 spec/views/admin/teams/projects/create.html.haml_spec.rb
 delete mode 100644 spec/views/admin/teams/projects/destroy.html.haml_spec.rb
 delete mode 100644 spec/views/admin/teams/projects/edit.html.haml_spec.rb
 delete mode 100644 spec/views/admin/teams/projects/new.html.haml_spec.rb
 delete mode 100644 spec/views/admin/teams/projects/update.html.haml_spec.rb
 delete mode 100644 spec/views/admin/teams/show.html.haml_spec.rb
 delete mode 100644 spec/views/admin/teams/update.html.haml_spec.rb
 delete mode 100644 spec/views/teams/create.html.haml_spec.rb
 delete mode 100644 spec/views/teams/destroy.html.haml_spec.rb
 delete mode 100644 spec/views/teams/edit.html.haml_spec.rb
 delete mode 100644 spec/views/teams/index.html.haml_spec.rb
 delete mode 100644 spec/views/teams/members/create.html.haml_spec.rb
 delete mode 100644 spec/views/teams/members/destroy.html.haml_spec.rb
 delete mode 100644 spec/views/teams/members/edit.html.haml_spec.rb
 delete mode 100644 spec/views/teams/members/index.html.haml_spec.rb
 delete mode 100644 spec/views/teams/members/new.html.haml_spec.rb
 delete mode 100644 spec/views/teams/members/update.html.haml_spec.rb
 delete mode 100644 spec/views/teams/new.html.haml_spec.rb
 delete mode 100644 spec/views/teams/projects/create.html.haml_spec.rb
 delete mode 100644 spec/views/teams/projects/destroy.html.haml_spec.rb
 delete mode 100644 spec/views/teams/projects/edit.html.haml_spec.rb
 delete mode 100644 spec/views/teams/projects/index.html.haml_spec.rb
 delete mode 100644 spec/views/teams/projects/new.html.haml_spec.rb
 delete mode 100644 spec/views/teams/projects/update.html.haml_spec.rb
 delete mode 100644 spec/views/teams/show.html.haml_spec.rb
 delete mode 100644 spec/views/teams/update.html.haml_spec.rb

diff --git a/app/assets/javascripts/admin/teams/members.js.coffee b/app/assets/javascripts/admin/teams/members.js.coffee
deleted file mode 100644
index 761567942fc..00000000000
--- a/app/assets/javascripts/admin/teams/members.js.coffee
+++ /dev/null
@@ -1,3 +0,0 @@
-# Place all the behaviors and hooks related to the matching controller here.
-# All this logic will automatically be available in application.js.
-# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
diff --git a/app/assets/javascripts/admin/teams/projects.js.coffee b/app/assets/javascripts/admin/teams/projects.js.coffee
deleted file mode 100644
index 761567942fc..00000000000
--- a/app/assets/javascripts/admin/teams/projects.js.coffee
+++ /dev/null
@@ -1,3 +0,0 @@
-# Place all the behaviors and hooks related to the matching controller here.
-# All this logic will automatically be available in application.js.
-# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
diff --git a/app/assets/stylesheets/admin/teams/members.css.scss b/app/assets/stylesheets/admin/teams/members.css.scss
deleted file mode 100644
index 47c2273c1c2..00000000000
--- a/app/assets/stylesheets/admin/teams/members.css.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-// Place all the styles related to the Admin::Teams::Members controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/app/assets/stylesheets/admin/teams/projects.css.scss b/app/assets/stylesheets/admin/teams/projects.css.scss
deleted file mode 100644
index e6a6ec39043..00000000000
--- a/app/assets/stylesheets/admin/teams/projects.css.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-// Place all the styles related to the Admin::Teams::Projects controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/spec/controllers/admin/projects/members_controller_spec.rb b/spec/controllers/admin/projects/members_controller_spec.rb
deleted file mode 100644
index 73625e33d70..00000000000
--- a/spec/controllers/admin/projects/members_controller_spec.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-require 'spec_helper'
-
-describe Admin::Projects::MembersController do
-
-  describe "GET 'edit'" do
-    it "returns http success" do
-      get 'edit'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'update'" do
-    it "returns http success" do
-      get 'update'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'destroy'" do
-    it "returns http success" do
-      get 'destroy'
-      response.should be_success
-    end
-  end
-
-end
diff --git a/spec/controllers/admin/teams/members_controller_spec.rb b/spec/controllers/admin/teams/members_controller_spec.rb
deleted file mode 100644
index a9e41be59f7..00000000000
--- a/spec/controllers/admin/teams/members_controller_spec.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-require 'spec_helper'
-
-describe Admin::Teams::MembersController do
-
-  describe "GET 'new'" do
-    it "returns http success" do
-      get 'new'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'create'" do
-    it "returns http success" do
-      get 'create'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'edit'" do
-    it "returns http success" do
-      get 'edit'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'update'" do
-    it "returns http success" do
-      get 'update'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'destroy'" do
-    it "returns http success" do
-      get 'destroy'
-      response.should be_success
-    end
-  end
-
-end
diff --git a/spec/controllers/admin/teams/projects_controller_spec.rb b/spec/controllers/admin/teams/projects_controller_spec.rb
deleted file mode 100644
index 7fe6ee0ca26..00000000000
--- a/spec/controllers/admin/teams/projects_controller_spec.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-require 'spec_helper'
-
-describe Admin::Teams::ProjectsController do
-
-  describe "GET 'new'" do
-    it "returns http success" do
-      get 'new'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'create'" do
-    it "returns http success" do
-      get 'create'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'edit'" do
-    it "returns http success" do
-      get 'edit'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'update'" do
-    it "returns http success" do
-      get 'update'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'destroy'" do
-    it "returns http success" do
-      get 'destroy'
-      response.should be_success
-    end
-  end
-
-end
diff --git a/spec/controllers/admin/teams_controller_spec.rb b/spec/controllers/admin/teams_controller_spec.rb
deleted file mode 100644
index 02d8f86a79d..00000000000
--- a/spec/controllers/admin/teams_controller_spec.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-require 'spec_helper'
-
-describe Admin::TeamsController do
-
-  describe "GET 'index'" do
-    it "returns http success" do
-      get 'index'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'show'" do
-    it "returns http success" do
-      get 'show'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'create'" do
-    it "returns http success" do
-      get 'create'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'edit'" do
-    it "returns http success" do
-      get 'edit'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'update'" do
-    it "returns http success" do
-      get 'update'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'destroy'" do
-    it "returns http success" do
-      get 'destroy'
-      response.should be_success
-    end
-  end
-
-end
diff --git a/spec/controllers/teams/members_controller_spec.rb b/spec/controllers/teams/members_controller_spec.rb
deleted file mode 100644
index e1ac558a6cd..00000000000
--- a/spec/controllers/teams/members_controller_spec.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-require 'spec_helper'
-
-describe Teams::MembersController do
-
-  describe "GET 'index'" do
-    it "returns http success" do
-      get 'index'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'new'" do
-    it "returns http success" do
-      get 'new'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'create'" do
-    it "returns http success" do
-      get 'create'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'edit'" do
-    it "returns http success" do
-      get 'edit'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'update'" do
-    it "returns http success" do
-      get 'update'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'destroy'" do
-    it "returns http success" do
-      get 'destroy'
-      response.should be_success
-    end
-  end
-
-end
diff --git a/spec/controllers/teams/projects_controller_spec.rb b/spec/controllers/teams/projects_controller_spec.rb
deleted file mode 100644
index b379c3721bb..00000000000
--- a/spec/controllers/teams/projects_controller_spec.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-require 'spec_helper'
-
-describe Teams::ProjectsController do
-
-  describe "GET 'index'" do
-    it "returns http success" do
-      get 'index'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'new'" do
-    it "returns http success" do
-      get 'new'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'create'" do
-    it "returns http success" do
-      get 'create'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'edit'" do
-    it "returns http success" do
-      get 'edit'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'update'" do
-    it "returns http success" do
-      get 'update'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'destroy'" do
-    it "returns http success" do
-      get 'destroy'
-      response.should be_success
-    end
-  end
-
-end
diff --git a/spec/controllers/teams_controller_spec.rb b/spec/controllers/teams_controller_spec.rb
deleted file mode 100644
index 923261fce9c..00000000000
--- a/spec/controllers/teams_controller_spec.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-require 'spec_helper'
-
-describe TeamsController do
-
-  describe "GET 'index'" do
-    it "returns http success" do
-      get 'index'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'show'" do
-    it "returns http success" do
-      get 'show'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'new'" do
-    it "returns http success" do
-      get 'new'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'edit'" do
-    it "returns http success" do
-      get 'edit'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'update'" do
-    it "returns http success" do
-      get 'update'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'create'" do
-    it "returns http success" do
-      get 'create'
-      response.should be_success
-    end
-  end
-
-  describe "GET 'destroy'" do
-    it "returns http success" do
-      get 'destroy'
-      response.should be_success
-    end
-  end
-
-end
diff --git a/spec/helpers/admin/teams/members_helper_spec.rb b/spec/helpers/admin/teams/members_helper_spec.rb
deleted file mode 100644
index ceef71c0be6..00000000000
--- a/spec/helpers/admin/teams/members_helper_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-require 'spec_helper'
-
-# Specs in this file have access to a helper object that includes
-# the Admin::Teams::MembersHelper. For example:
-#
-# describe Admin::Teams::MembersHelper do
-#   describe "string concat" do
-#     it "concats two strings with spaces" do
-#       helper.concat_strings("this","that").should == "this that"
-#     end
-#   end
-# end
-describe Admin::Teams::MembersHelper do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/helpers/admin/teams/projects_helper_spec.rb b/spec/helpers/admin/teams/projects_helper_spec.rb
deleted file mode 100644
index 1c98d23cdb7..00000000000
--- a/spec/helpers/admin/teams/projects_helper_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-require 'spec_helper'
-
-# Specs in this file have access to a helper object that includes
-# the Admin::Teams::ProjectsHelper. For example:
-#
-# describe Admin::Teams::ProjectsHelper do
-#   describe "string concat" do
-#     it "concats two strings with spaces" do
-#       helper.concat_strings("this","that").should == "this that"
-#     end
-#   end
-# end
-describe Admin::Teams::ProjectsHelper do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/admin/teams/create.html.haml_spec.rb b/spec/views/admin/teams/create.html.haml_spec.rb
deleted file mode 100644
index 27f57d89693..00000000000
--- a/spec/views/admin/teams/create.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "teams/create.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/admin/teams/destroy.html.haml_spec.rb b/spec/views/admin/teams/destroy.html.haml_spec.rb
deleted file mode 100644
index 87670e4dc66..00000000000
--- a/spec/views/admin/teams/destroy.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "teams/destroy.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/admin/teams/edit.html.haml_spec.rb b/spec/views/admin/teams/edit.html.haml_spec.rb
deleted file mode 100644
index 5180d713f7f..00000000000
--- a/spec/views/admin/teams/edit.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "teams/edit.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/admin/teams/index.html.haml_spec.rb b/spec/views/admin/teams/index.html.haml_spec.rb
deleted file mode 100644
index 7a0d69bd316..00000000000
--- a/spec/views/admin/teams/index.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "teams/index.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/admin/teams/members/create.html.haml_spec.rb b/spec/views/admin/teams/members/create.html.haml_spec.rb
deleted file mode 100644
index b6f817617e4..00000000000
--- a/spec/views/admin/teams/members/create.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "members/create.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/admin/teams/members/destroy.html.haml_spec.rb b/spec/views/admin/teams/members/destroy.html.haml_spec.rb
deleted file mode 100644
index 3ff1634461c..00000000000
--- a/spec/views/admin/teams/members/destroy.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "members/destroy.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/admin/teams/members/edit.html.haml_spec.rb b/spec/views/admin/teams/members/edit.html.haml_spec.rb
deleted file mode 100644
index 3e952e898a9..00000000000
--- a/spec/views/admin/teams/members/edit.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "members/edit.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/admin/teams/members/new.html.haml_spec.rb b/spec/views/admin/teams/members/new.html.haml_spec.rb
deleted file mode 100644
index f03eed1f29f..00000000000
--- a/spec/views/admin/teams/members/new.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "members/new.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/admin/teams/members/update.html.haml_spec.rb b/spec/views/admin/teams/members/update.html.haml_spec.rb
deleted file mode 100644
index 43b84bad99b..00000000000
--- a/spec/views/admin/teams/members/update.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "members/update.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/admin/teams/projects/create.html.haml_spec.rb b/spec/views/admin/teams/projects/create.html.haml_spec.rb
deleted file mode 100644
index 74c4ee2d837..00000000000
--- a/spec/views/admin/teams/projects/create.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "projects/create.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/admin/teams/projects/destroy.html.haml_spec.rb b/spec/views/admin/teams/projects/destroy.html.haml_spec.rb
deleted file mode 100644
index b3eee48f38b..00000000000
--- a/spec/views/admin/teams/projects/destroy.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "projects/destroy.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/admin/teams/projects/edit.html.haml_spec.rb b/spec/views/admin/teams/projects/edit.html.haml_spec.rb
deleted file mode 100644
index ef41b7b0814..00000000000
--- a/spec/views/admin/teams/projects/edit.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "projects/edit.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/admin/teams/projects/new.html.haml_spec.rb b/spec/views/admin/teams/projects/new.html.haml_spec.rb
deleted file mode 100644
index 9ee68e5ae05..00000000000
--- a/spec/views/admin/teams/projects/new.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "projects/new.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/admin/teams/projects/update.html.haml_spec.rb b/spec/views/admin/teams/projects/update.html.haml_spec.rb
deleted file mode 100644
index fdaafd3924b..00000000000
--- a/spec/views/admin/teams/projects/update.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "projects/update.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/admin/teams/show.html.haml_spec.rb b/spec/views/admin/teams/show.html.haml_spec.rb
deleted file mode 100644
index b7f7b669c2e..00000000000
--- a/spec/views/admin/teams/show.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "teams/show.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/admin/teams/update.html.haml_spec.rb b/spec/views/admin/teams/update.html.haml_spec.rb
deleted file mode 100644
index b28cfa4f699..00000000000
--- a/spec/views/admin/teams/update.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "teams/update.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/teams/create.html.haml_spec.rb b/spec/views/teams/create.html.haml_spec.rb
deleted file mode 100644
index 27f57d89693..00000000000
--- a/spec/views/teams/create.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "teams/create.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/teams/destroy.html.haml_spec.rb b/spec/views/teams/destroy.html.haml_spec.rb
deleted file mode 100644
index 87670e4dc66..00000000000
--- a/spec/views/teams/destroy.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "teams/destroy.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/teams/edit.html.haml_spec.rb b/spec/views/teams/edit.html.haml_spec.rb
deleted file mode 100644
index 5180d713f7f..00000000000
--- a/spec/views/teams/edit.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "teams/edit.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/teams/index.html.haml_spec.rb b/spec/views/teams/index.html.haml_spec.rb
deleted file mode 100644
index 7a0d69bd316..00000000000
--- a/spec/views/teams/index.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "teams/index.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/teams/members/create.html.haml_spec.rb b/spec/views/teams/members/create.html.haml_spec.rb
deleted file mode 100644
index b6f817617e4..00000000000
--- a/spec/views/teams/members/create.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "members/create.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/teams/members/destroy.html.haml_spec.rb b/spec/views/teams/members/destroy.html.haml_spec.rb
deleted file mode 100644
index 3ff1634461c..00000000000
--- a/spec/views/teams/members/destroy.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "members/destroy.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/teams/members/edit.html.haml_spec.rb b/spec/views/teams/members/edit.html.haml_spec.rb
deleted file mode 100644
index 3e952e898a9..00000000000
--- a/spec/views/teams/members/edit.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "members/edit.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/teams/members/index.html.haml_spec.rb b/spec/views/teams/members/index.html.haml_spec.rb
deleted file mode 100644
index 363430d769f..00000000000
--- a/spec/views/teams/members/index.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "members/index.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/teams/members/new.html.haml_spec.rb b/spec/views/teams/members/new.html.haml_spec.rb
deleted file mode 100644
index f03eed1f29f..00000000000
--- a/spec/views/teams/members/new.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "members/new.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/teams/members/update.html.haml_spec.rb b/spec/views/teams/members/update.html.haml_spec.rb
deleted file mode 100644
index 43b84bad99b..00000000000
--- a/spec/views/teams/members/update.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "members/update.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/teams/new.html.haml_spec.rb b/spec/views/teams/new.html.haml_spec.rb
deleted file mode 100644
index 8ef621b708f..00000000000
--- a/spec/views/teams/new.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "teams/new.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/teams/projects/create.html.haml_spec.rb b/spec/views/teams/projects/create.html.haml_spec.rb
deleted file mode 100644
index 74c4ee2d837..00000000000
--- a/spec/views/teams/projects/create.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "projects/create.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/teams/projects/destroy.html.haml_spec.rb b/spec/views/teams/projects/destroy.html.haml_spec.rb
deleted file mode 100644
index b3eee48f38b..00000000000
--- a/spec/views/teams/projects/destroy.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "projects/destroy.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/teams/projects/edit.html.haml_spec.rb b/spec/views/teams/projects/edit.html.haml_spec.rb
deleted file mode 100644
index ef41b7b0814..00000000000
--- a/spec/views/teams/projects/edit.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "projects/edit.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/teams/projects/index.html.haml_spec.rb b/spec/views/teams/projects/index.html.haml_spec.rb
deleted file mode 100644
index 8cf0dbcd954..00000000000
--- a/spec/views/teams/projects/index.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "projects/index.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/teams/projects/new.html.haml_spec.rb b/spec/views/teams/projects/new.html.haml_spec.rb
deleted file mode 100644
index 9ee68e5ae05..00000000000
--- a/spec/views/teams/projects/new.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "projects/new.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/teams/projects/update.html.haml_spec.rb b/spec/views/teams/projects/update.html.haml_spec.rb
deleted file mode 100644
index fdaafd3924b..00000000000
--- a/spec/views/teams/projects/update.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "projects/update.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/teams/show.html.haml_spec.rb b/spec/views/teams/show.html.haml_spec.rb
deleted file mode 100644
index b7f7b669c2e..00000000000
--- a/spec/views/teams/show.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "teams/show.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/views/teams/update.html.haml_spec.rb b/spec/views/teams/update.html.haml_spec.rb
deleted file mode 100644
index b28cfa4f699..00000000000
--- a/spec/views/teams/update.html.haml_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe "teams/update.html.haml" do
-  pending "add some examples to (or delete) #{__FILE__}"
-end
-- 
GitLab


From eb99feb4a7e01c4e83203ec014c082205b77ad02 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Wed, 23 Jan 2013 20:43:23 +0400
Subject: [PATCH 062/197] simple refactoring

---
 app/assets/javascripts/dashboard.js.coffee     |  8 ++++----
 .../javascripts/merge_requests.js.coffee       | 18 +++++++++---------
 .../user_team_project_relationships.rb         |  6 +++---
 spec/factories/user_team_user_relationships.rb |  6 +++---
 4 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/app/assets/javascripts/dashboard.js.coffee b/app/assets/javascripts/dashboard.js.coffee
index f15d09dd475..6171e0d50fd 100644
--- a/app/assets/javascripts/dashboard.js.coffee
+++ b/app/assets/javascripts/dashboard.js.coffee
@@ -4,11 +4,11 @@ window.dashboardPage = ->
     event.preventDefault()
     toggleFilter $(this)
     reloadActivities()
-    
+
 reloadActivities = ->
   $(".content_list").html ''
   Pager.init 20, true
-  
+
 toggleFilter = (sender) ->
   sender.parent().toggleClass "inactive"
   event_filters = $.cookie("event_filter")
@@ -17,11 +17,11 @@ toggleFilter = (sender) ->
     event_filters = event_filters.split(",")
   else
     event_filters = new Array()
-    
+
   index = event_filters.indexOf(filter)
   if index is -1
     event_filters.push filter
   else
     event_filters.splice index, 1
-  
+
   $.cookie "event_filter", event_filters.join(",")
diff --git a/app/assets/javascripts/merge_requests.js.coffee b/app/assets/javascripts/merge_requests.js.coffee
index 9c9cc6132b3..65ed817c7c6 100644
--- a/app/assets/javascripts/merge_requests.js.coffee
+++ b/app/assets/javascripts/merge_requests.js.coffee
@@ -1,6 +1,6 @@
 #
 # * Filter merge requests
-# 
+#
 @merge_requestsPage = ->
   $('#assignee_id').chosen()
   $('#milestone_id').chosen()
@@ -8,16 +8,16 @@
     $(this).closest('form').submit()
 
 class MergeRequest
-  
+
   constructor: (@opts) ->
     this.$el = $('.merge-request')
     @diffs_loaded = false
     @commits_loaded = false
-    
+
     this.activateTab(@opts.action)
-    
+
     this.bindEvents()
-    
+
     this.initMergeWidget()
     this.$('.show-all-commits').on 'click', =>
       this.showAllCommits()
@@ -28,7 +28,7 @@ class MergeRequest
 
   initMergeWidget: ->
     this.showState( @opts.current_state )
-    
+
     if this.$('.automerge_widget').length and @opts.check_enable
       $.get @opts.url_to_automerge_check, (data) =>
         this.showState( data.state )
@@ -42,12 +42,12 @@ class MergeRequest
   bindEvents: ->
     this.$('.nav-tabs').on 'click', 'a', (event) =>
       a = $(event.currentTarget)
-      
+
       href = a.attr('href')
       History.replaceState {path: href}, document.title, href
-      
+
       event.preventDefault()
-      
+
     this.$('.nav-tabs').on 'click', 'li', (event) =>
       this.activateTab($(event.currentTarget).data('action'))
 
diff --git a/spec/factories/user_team_project_relationships.rb b/spec/factories/user_team_project_relationships.rb
index fa0f26e7455..93c7b57d0fa 100644
--- a/spec/factories/user_team_project_relationships.rb
+++ b/spec/factories/user_team_project_relationships.rb
@@ -2,8 +2,8 @@
 
 FactoryGirl.define do
   factory :user_team_project_relationship do
-    project_id 1
-    user_team_id 1
-    greatest_access 1
+    project
+    user_team
+    greatest_access { UsersProject::MASTER }
   end
 end
diff --git a/spec/factories/user_team_user_relationships.rb b/spec/factories/user_team_user_relationships.rb
index 9b655e00686..55179f9a45b 100644
--- a/spec/factories/user_team_user_relationships.rb
+++ b/spec/factories/user_team_user_relationships.rb
@@ -2,9 +2,9 @@
 
 FactoryGirl.define do
   factory :user_team_user_relationship do
-    user_id 1
-    user_team_id 1
+    user
+    user_team
     group_admin false
-    permission 1
+    permission { UsersProject::MASTER }
   end
 end
-- 
GitLab


From 690db9693fcee3beedc467b48fd9e4bd42ee936d Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Wed, 23 Jan 2013 23:39:47 +0400
Subject: [PATCH 063/197] fix tests

---
 .../admin/teams/members_controller.rb         |  7 ++---
 app/controllers/teams/members_controller.rb   | 11 +++----
 app/views/admin/teams/show.html.haml          |  6 ++--
 app/views/teams/projects/index.html.haml      |  2 +-
 features/admin/teams.feature                  |  3 --
 features/steps/admin/admin_teams.rb           | 18 ++++++-----
 features/steps/userteams/userteams.rb         | 30 +++++++++++--------
 features/support/env.rb                       |  2 +-
 features/teams/team.feature                   |  1 +
 spec/routing/admin_routing_spec.rb            | 14 ++++-----
 10 files changed, 47 insertions(+), 47 deletions(-)

diff --git a/app/controllers/admin/teams/members_controller.rb b/app/controllers/admin/teams/members_controller.rb
index cdcc96c0aef..7fd777dc72f 100644
--- a/app/controllers/admin/teams/members_controller.rb
+++ b/app/controllers/admin/teams/members_controller.rb
@@ -30,11 +30,8 @@ class Admin::Teams::MembersController < Admin::Teams::ApplicationController
   end
 
   def destroy
-    if user_team.remove_member(team_member)
-      redirect_to admin_team_path(user_team), notice: "Member #{team_member.name} was successfully removed from Team of users."
-    else
-      redirect_to admin_team_members(user_team), notice: "Something is wrong."
-    end
+    user_team.remove_member(team_member)
+    redirect_to admin_team_path(user_team), notice: "Member #{team_member.name} was successfully removed from Team of users."
   end
 
   protected
diff --git a/app/controllers/teams/members_controller.rb b/app/controllers/teams/members_controller.rb
index 95b8de1861b..56e952a3d40 100644
--- a/app/controllers/teams/members_controller.rb
+++ b/app/controllers/teams/members_controller.rb
@@ -20,7 +20,7 @@ class Teams::MembersController < Teams::ApplicationController
       user_team.add_members(user_ids, access, is_admin)
     end
 
-    redirect_to team_path(user_team), notice: 'Members was successfully added into Team of users.'
+    redirect_to team_members_path(user_team), notice: 'Members was successfully added into Team of users.'
   end
 
   def edit
@@ -30,18 +30,15 @@ class Teams::MembersController < Teams::ApplicationController
   def update
     options = {default_projects_access: params[:default_project_access], group_admin: params[:group_admin]}
     if user_team.update_membership(team_member, options)
-      redirect_to team_path(user_team), notice: "Membership for #{team_member.name} was successfully updated in Team of users."
+      redirect_to team_members_path(user_team), notice: "Membership for #{team_member.name} was successfully updated in Team of users."
     else
       render :edit
     end
   end
 
   def destroy
-    if user_team.remove_member(team_member)
-      redirect_to team_path(user_team), notice: "Member #{team_member.name} was successfully removed from Team of users."
-    else
-      redirect_to team_members(user_team), notice: "Something is wrong."
-    end
+    user_team.remove_member(team_member)
+    redirect_to team_path(user_team), notice: "Member #{team_member.name} was successfully removed from Team of users."
   end
 
   protected
diff --git a/app/views/admin/teams/show.html.haml b/app/views/admin/teams/show.html.haml
index a7470c2d6e0..6a1deaff989 100644
--- a/app/views/admin/teams/show.html.haml
+++ b/app/views/admin/teams/show.html.haml
@@ -52,7 +52,7 @@
           %th Team access
           %th.cred.span3 Danger Zone!
       - @team.members.each do |member|
-        %tr.member
+        %tr.member{ class: "user_#{member.id}"}
           %td
             = link_to [:admin, member] do
               = member.name
@@ -62,7 +62,7 @@
           %td.bgred
             = link_to 'Edit', edit_admin_team_member_path(@team, member), class: "btn small"
             &nbsp;
-            = link_to 'Remove', admin_team_member_path(@team, member), confirm: 'Remove member from team. Are you sure?', method: :delete, class: "btn danger small"
+            = link_to 'Remove', admin_team_member_path(@team, member), confirm: 'Remove member from team. Are you sure?', method: :delete, class: "btn danger small", id: "remove_member_#{member.id}"
 
 %fieldset
   %legend
@@ -84,7 +84,7 @@
           %td.bgred
             = link_to 'Edit', edit_admin_team_project_path(@team, project), class: "btn small"
             &nbsp;
-            = link_to 'Relegate', admin_team_project_path(@team, project), confirm: 'Remove project from team. Are you sure?', method: :delete, class: "btn danger small"
+            = link_to 'Relegate', admin_team_project_path(@team, project), confirm: 'Remove project from team. Are you sure?', method: :delete, class: "btn danger small", id: "relegate_project_#{project.id}"
 
 :javascript
   $(function(){
diff --git a/app/views/teams/projects/index.html.haml b/app/views/teams/projects/index.html.haml
index b0a50e594cf..af6ffe5f3a4 100644
--- a/app/views/teams/projects/index.html.haml
+++ b/app/views/teams/projects/index.html.haml
@@ -13,7 +13,7 @@
 
 %hr
 
-%table
+%table.projects-table
   %thead
     %tr
       %th Project name
diff --git a/features/admin/teams.feature b/features/admin/teams.feature
index 6ca7c4cbe02..b38a71e07b3 100644
--- a/features/admin/teams.feature
+++ b/features/admin/teams.feature
@@ -1,9 +1,6 @@
 Feature: Admin Teams
   Background:
     Given I sign in as an admin
-    #And there are projects in system
-    #And system has users
-    #And I have own project
     And Create gitlab user "John"
 
   Scenario: Create a team
diff --git a/features/steps/admin/admin_teams.rb b/features/steps/admin/admin_teams.rb
index a1221cd1a8c..5c66b24bccf 100644
--- a/features/steps/admin/admin_teams.rb
+++ b/features/steps/admin/admin_teams.rb
@@ -83,8 +83,7 @@ class AdminTeams < Spinach::FeatureSteps
   end
 
   Then 'I should see empty projects table' do
-    projects_list = find("#projects_list")
-    projects_list.has_content?("Relegate").must_equal false
+    page.has_no_css?("#projects_list").must_equal true
   end
 
   When 'I select project "Shop" with max access "Reporter"' do
@@ -177,11 +176,13 @@ class AdminTeams < Spinach::FeatureSteps
   end
 
   And 'I should see "Shop" in projects list' do
-
+    project = Project.find_by_name("Shop")
+    find_in_list("#projects_list .project", project).must_equal true
   end
 
   When 'I click on remove "Jimm" user link' do
-
+    user = User.find_by_name("Jimm")
+    click_link "remove_member_#{user.id}"
   end
 
   Then 'I should be redirected to "HardCoders" team admin page' do
@@ -189,15 +190,18 @@ class AdminTeams < Spinach::FeatureSteps
   end
 
   And 'I should not to see "Jimm" user in members list' do
-
+    user = User.find_by_name("Jimm")
+    find_in_list("#members_list .member", user).must_equal false
   end
 
   When 'I click on "Relegate" link on "Shop" project' do
-
+    project = Project.find_by_name("Shop")
+    click_link "relegate_project_#{project.id}"
   end
 
   Then 'I should see projects liston team page without "Shop" project' do
-
+    project = Project.find_by_name("Shop")
+    find_in_list("#projects_list .project", project).must_equal false
   end
 
   Then 'I should see "John" user with role "Reporter" in team table' do
diff --git a/features/steps/userteams/userteams.rb b/features/steps/userteams/userteams.rb
index 59ec3d2de6e..39a2588ec92 100644
--- a/features/steps/userteams/userteams.rb
+++ b/features/steps/userteams/userteams.rb
@@ -175,7 +175,12 @@ class Userteams < Spinach::FeatureSteps
     end
 
     And 'I select user "John" from list with role "Reporter"' do
-      pending 'step not implemented'
+      user = User.find_by_name("John")
+      within "#team_members" do
+        select user.name, :from => "user_ids"
+        select "Reporter", :from => "default_project_access"
+      end
+      click_button "Add"
     end
 
     Then 'I should see user "John" in team list' do
@@ -185,7 +190,7 @@ class Userteams < Spinach::FeatureSteps
     end
 
     And 'I have my own project without teams' do
-      project = create :project, creator: current_user
+      @project = create :project, creator: current_user
     end
 
     And 'I visit my team page' do
@@ -197,27 +202,26 @@ class Userteams < Spinach::FeatureSteps
       click_link "Projects"
     end
 
+    And 'I click link "Assign project to Team"' do
+      click_link "Assign project to Team"
+    end
+
     Then 'I should see form with my own project in avaliable projects list' do
-      project = current_user.projects.first
       projects_select = find("#project_ids")
-      projects_select.should have_content(project.name)
+      projects_select.should have_content(@project.name)
     end
 
     When 'I submit form with selected project and max access' do
-      project = current_user.projects.first
-      within "#team_projects" do
-        select project.name, :from => "project_ids"
+      within "#assign_projects" do
+        select @project.name, :from => "project_ids"
         select "Reporter", :from => "greatest_project_access"
       end
       click_button "Add"
     end
 
     Then 'I should see my own project in team projects list' do
-      project = current_user.projects.first
-      projects = all("table .project")
-      projects.each do |project_row|
-        project_row.should have_content(project.name)
-      end
+      projects = find(".projects-table")
+      projects.should have_content(@project.name)
     end
 
     When 'I click link "New Team Member"' do
@@ -227,7 +231,7 @@ class Userteams < Spinach::FeatureSteps
   protected
 
   def current_team
-    @user_team ||= Team.first
+    @user_team ||= UserTeam.first
   end
 
   def project
diff --git a/features/support/env.rb b/features/support/env.rb
index be10ad1b8b9..5651c4a09ba 100644
--- a/features/support/env.rb
+++ b/features/support/env.rb
@@ -21,7 +21,7 @@ Dir["#{Rails.root}/features/steps/shared/*.rb"].each {|file| require file}
 include GitoliteStub
 
 WebMock.allow_net_connect!
-
+Spinach.config.save_and_open_page_on_failure = true
 #
 # JS driver
 #
diff --git a/features/teams/team.feature b/features/teams/team.feature
index d914313efb6..b62d230fd56 100644
--- a/features/teams/team.feature
+++ b/features/teams/team.feature
@@ -70,6 +70,7 @@ Feature: UserTeams
     And I have my own project without teams
     And I visit my team page
     When I click on link "Projects"
+    And I click link "Assign project to Team"
     Then I should see form with my own project in avaliable projects list
     When I submit form with selected project and max access
     Then I should see my own project in team projects list
diff --git a/spec/routing/admin_routing_spec.rb b/spec/routing/admin_routing_spec.rb
index fb26bf98d0f..3e0e4bb3883 100644
--- a/spec/routing/admin_routing_spec.rb
+++ b/spec/routing/admin_routing_spec.rb
@@ -95,20 +95,20 @@ describe Admin::ProjectsController, "routing" do
   end
 end
 
-# edit_admin_team_member GET    /admin/team_members/:id/edit(.:format) admin/team_members#edit
-#      admin_team_member PUT    /admin/team_members/:id(.:format)      admin/team_members#update
-#                        DELETE /admin/team_members/:id(.:format)      admin/team_members#destroy
-describe Admin::TeamMembersController, "routing" do
+# edit_admin_project_member GET      /admin/projects/:project_id/members/:id/edit(.:format)    admin/projects/members#edit {:id=>/[^\/]+/, :project_id=>/[^\/]+/}
+#      admin_project_member PUT      /admin/projects/:project_id/members/:id(.:format)         admin/projects/members#update {:id=>/[^\/]+/, :project_id=>/[^\/]+/}
+#                           DELETE   /admin/projects/:project_id/members/:id(.:format)         admin/projects/members#destroy {:id=>/[^\/]+/, :project_id=>/[^\/]+/}
+describe Admin::Projects::MembersController, "routing" do
   it "to #edit" do
-    get("/admin/team_members/1/edit").should route_to('admin/team_members#edit', id: '1')
+    get("/admin/projects/test/members/1/edit").should route_to('admin/projects/members#edit', project_id: 'test', id: '1')
   end
 
   it "to #update" do
-    put("/admin/team_members/1").should route_to('admin/team_members#update', id: '1')
+    put("/admin/projects/test/members/1").should route_to('admin/projects/members#update', project_id: 'test', id: '1')
   end
 
   it "to #destroy" do
-    delete("/admin/team_members/1").should route_to('admin/team_members#destroy', id: '1')
+    delete("/admin/projects/test/members/1").should route_to('admin/projects/members#destroy', project_id: 'test', id: '1')
   end
 end
 
-- 
GitLab


From 9a604eb6798a2cc26df09ef9470273093acdb853 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Thu, 24 Jan 2013 00:06:48 +0400
Subject: [PATCH 064/197] Remove pending steps (no functional - no tests)

---
 features/admin/teams.feature | 2 --
 1 file changed, 2 deletions(-)

diff --git a/features/admin/teams.feature b/features/admin/teams.feature
index b38a71e07b3..6a15fddcdcc 100644
--- a/features/admin/teams.feature
+++ b/features/admin/teams.feature
@@ -18,8 +18,6 @@ Feature: Admin Teams
     When I select user "John" from user list as "Developer"
     And submit form with new team member info
     Then I should see "John" in teams members list as "Developer"
-    When I visit "John" user admin page
-    Then I should see "HardCoders" team in teams table
 
   Scenario: Assign team to existing project
     When I visit admin teams page
-- 
GitLab


From b695db4af4c9fe0dc27f78e549a6a785bf936731 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Thu, 24 Jan 2013 01:40:45 +0400
Subject: [PATCH 065/197] Remove save files with failed test %)

---
 features/support/env.rb | 1 -
 1 file changed, 1 deletion(-)

diff --git a/features/support/env.rb b/features/support/env.rb
index 5651c4a09ba..a08aa0de9f8 100644
--- a/features/support/env.rb
+++ b/features/support/env.rb
@@ -21,7 +21,6 @@ Dir["#{Rails.root}/features/steps/shared/*.rb"].each {|file| require file}
 include GitoliteStub
 
 WebMock.allow_net_connect!
-Spinach.config.save_and_open_page_on_failure = true
 #
 # JS driver
 #
-- 
GitLab


From 2befa8fe30bd5f3512e67d671e25df6f128389f0 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Thu, 24 Jan 2013 03:00:56 +0400
Subject: [PATCH 066/197] Switch user link to profile link

---
 app/views/teams/members/_show.html.haml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/views/teams/members/_show.html.haml b/app/views/teams/members/_show.html.haml
index ec4728787cf..dbbb382d97f 100644
--- a/app/views/teams/members/_show.html.haml
+++ b/app/views/teams/members/_show.html.haml
@@ -3,9 +3,9 @@
 %li{id: dom_id(member), class: "team_member_row user_#{user.id}"}
   .row
     .span5
-      = link_to team_member_path(@team, user), title: user.name, class: "dark" do
+      = link_to user_path(user.username), title: user.name, class: "dark" do
         = image_tag gravatar_icon(user.email, 40), class: "avatar s32"
-      = link_to team_member_path(@team, user), title: user.name, class: "dark" do
+      = link_to user_path(user.username), title: user.name, class: "dark" do
         %strong= truncate(user.name, lenght: 40)
         %br
         %small.cgray= user.email
-- 
GitLab


From 1a917bc954f7e2b0c7233288c73476f572cad8d6 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Thu, 24 Jan 2013 03:18:07 +0400
Subject: [PATCH 067/197] fix scope to empty relation

---
 app/models/user_team.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/models/user_team.rb b/app/models/user_team.rb
index 0442123fc24..e3037bcd1aa 100644
--- a/app/models/user_team.rb
+++ b/app/models/user_team.rb
@@ -17,7 +17,7 @@ class UserTeam < ActiveRecord::Base
 
   scope :with_member, ->(user){ joins(:user_team_user_relationships).where(user_team_user_relationships: {user_id: user.id}) }
   scope :with_project, ->(project){ joins(:user_team_project_relationships).where(user_team_project_relationships: {project_id: project})}
-  scope :without_project, ->(project){ where("id NOT IN (:ids)", ids: with_project(project))}
+  scope :without_project, ->(project){ where("id NOT IN (:ids)", ids: (a = with_project(project); a.blank? ? 0 : a))}
   scope :created_by, ->(user){ where(owner_id: user) }
 
   class << self
-- 
GitLab


From 645f9604752ae258ab3f125c8fa98adf3b81c127 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 24 Jan 2013 10:16:03 +0200
Subject: [PATCH 068/197] Few UI improvements

---
 app/controllers/teams/application_controller.rb | 2 ++
 app/views/dashboard/_teams.html.haml            | 3 +--
 app/views/layouts/_head_panel.html.haml         | 2 +-
 app/views/layouts/group.html.haml               | 2 +-
 app/views/layouts/user_team.html.haml           | 2 +-
 app/views/teams/_projects.html.haml             | 2 +-
 app/views/teams/index.html.haml                 | 8 ++++----
 7 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/app/controllers/teams/application_controller.rb b/app/controllers/teams/application_controller.rb
index 2c1583d943e..fc23202610c 100644
--- a/app/controllers/teams/application_controller.rb
+++ b/app/controllers/teams/application_controller.rb
@@ -1,5 +1,7 @@
 class Teams::ApplicationController < ApplicationController
 
+  layout 'user_team'
+
   before_filter :authorize_manage_user_team!
 
   protected
diff --git a/app/views/dashboard/_teams.html.haml b/app/views/dashboard/_teams.html.haml
index 414bb12a945..4250faac685 100644
--- a/app/views/dashboard/_teams.html.haml
+++ b/app/views/dashboard/_teams.html.haml
@@ -20,7 +20,6 @@
             &rarr;
           %span.last_activity
             %strong Projects:
-            %span= team.projects.count
-          %span.last_activity
+            %span= "#{team.projects.count}, "
             %strong Members:
             %span= team.members.count
diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml
index 945500d4b6c..de4117ae296 100644
--- a/app/views/layouts/_head_panel.html.haml
+++ b/app/views/layouts/_head_panel.html.haml
@@ -10,7 +10,7 @@
       %ul.nav
         %li
           = link_to teams_path, title: "Teams of users", class: 'has_bottom_tooltip', 'data-original-title' => 'Teams list'  do
-            %i.icon-globe
+            %i.icon-group
         - if current_user.is_admin?
           %li
             = link_to admin_root_path, title: "Admin area", class: 'has_bottom_tooltip', 'data-original-title' => 'Admin area' do
diff --git a/app/views/layouts/group.html.haml b/app/views/layouts/group.html.haml
index f47e8b3e9ff..46bc9ef1457 100644
--- a/app/views/layouts/group.html.haml
+++ b/app/views/layouts/group.html.haml
@@ -3,7 +3,7 @@
   = render "layouts/head", title: "#{@group.name}"
   %body{class: "#{app_theme} application"}
     = render "layouts/flash"
-    = render "layouts/head_panel", title: "#{@group.name}"
+    = render "layouts/head_panel", title: "group: #{@group.name}"
     .container
       %ul.main_menu
         = nav_link(path: 'groups#show', html_options: {class: 'home'}) do
diff --git a/app/views/layouts/user_team.html.haml b/app/views/layouts/user_team.html.haml
index aa613d71f90..769fc3b78c3 100644
--- a/app/views/layouts/user_team.html.haml
+++ b/app/views/layouts/user_team.html.haml
@@ -3,7 +3,7 @@
   = render "layouts/head", title: "#{@team.name}"
   %body{class: "#{app_theme} application"}
     = render "layouts/flash"
-    = render "layouts/head_panel", title: "#{@team.name}"
+    = render "layouts/head_panel", title: "team: #{@team.name}"
     .container
       %ul.main_menu
         = nav_link(path: 'teams#show', html_options: {class: 'home'}) do
diff --git a/app/views/teams/_projects.html.haml b/app/views/teams/_projects.html.haml
index 040d1ae94aa..95202bc6ee5 100644
--- a/app/views/teams/_projects.html.haml
+++ b/app/views/teams/_projects.html.haml
@@ -10,7 +10,7 @@
           New Project
   %ul.well-list
     - if projects.blank?
-      %p.nothing_here_message This groups has no projects yet
+      %p.nothing_here_message This team has no projects yet
     - projects.each do |project|
       %li
         = link_to project_path(project), class: dom_class(project) do
diff --git a/app/views/teams/index.html.haml b/app/views/teams/index.html.haml
index 8f8874328fc..6610cdbd76e 100644
--- a/app/views/teams/index.html.haml
+++ b/app/views/teams/index.html.haml
@@ -20,7 +20,7 @@
       %th Projects
       %th Members
       %th Owner
-      %th
+      %th.cred Danger Zone!
 
   - @teams.each do |team|
     %tr
@@ -30,9 +30,9 @@
       %td= link_to team.projects.count, team_projects_path(team)
       %td= link_to team.members.count, team_members_path(team)
       %td= link_to team.owner.name, team_member_path(team, team.owner)
-      %td
+      %td.bgred
         - if current_user.can?(:manage_user_team, team)
+          = link_to "Edit", edit_team_path(team), class: "btn small"
           - if current_user.can?(:admin_user_team, team)
-            = link_to "Destroy", team_path(team), method: :delete, confirm: "You are shure?", class: "danger btn small right"
+            = link_to "Destroy", team_path(team), method: :delete, confirm: "You are shure?", class: "danger btn small"
             &nbsp;
-          = link_to "Edit", edit_team_path(team), class: "btn small right"
-- 
GitLab


From ca105d0462090b1650019890feeeef3fdd356209 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 24 Jan 2013 10:39:16 +0200
Subject: [PATCH 069/197] Show only teams we have access to

---
 app/controllers/teams_controller.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/controllers/teams_controller.rb b/app/controllers/teams_controller.rb
index ea060b3a44d..7de094214d4 100644
--- a/app/controllers/teams_controller.rb
+++ b/app/controllers/teams_controller.rb
@@ -10,7 +10,7 @@ class TeamsController < ApplicationController
   layout 'user_team',       only: [:show, :edit, :update, :destroy, :issues, :merge_requests, :search]
 
   def index
-    @teams = UserTeam.order('name ASC')
+    @teams = current_user.user_teams.order('name ASC')
   end
 
   def show
-- 
GitLab


From ca752e64fbf1cd03ff3eff1ada80a1cfbcd9b2b4 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 24 Jan 2013 11:19:09 +0200
Subject: [PATCH 070/197] Fix mispelling and ambiguous id  in
 UserTeam.without_project

---
 app/controllers/projects/teams_controller.rb                | 2 +-
 app/models/user_team.rb                                     | 2 +-
 app/views/dashboard/_teams.html.haml                        | 6 +-----
 app/views/layouts/_head_panel.html.haml                     | 3 ---
 .../teams/{avaliable.html.haml => available.html.haml}      | 0
 app/views/team_members/index.html.haml                      | 2 +-
 app/views/teams/new.html.haml                               | 2 +-
 config/routes.rb                                            | 2 +-
 8 files changed, 6 insertions(+), 13 deletions(-)
 rename app/views/projects/teams/{avaliable.html.haml => available.html.haml} (100%)

diff --git a/app/controllers/projects/teams_controller.rb b/app/controllers/projects/teams_controller.rb
index c04835ed153..3ca724aaf4d 100644
--- a/app/controllers/projects/teams_controller.rb
+++ b/app/controllers/projects/teams_controller.rb
@@ -1,6 +1,6 @@
 class Projects::TeamsController < Projects::ApplicationController
 
-  def avaliable
+  def available
     @teams = current_user.is_admin? ? UserTeam.scoped : current_user.user_teams
     @teams = @teams.without_project(project)
     unless @teams.any?
diff --git a/app/models/user_team.rb b/app/models/user_team.rb
index e3037bcd1aa..b28a6a041ac 100644
--- a/app/models/user_team.rb
+++ b/app/models/user_team.rb
@@ -17,7 +17,7 @@ class UserTeam < ActiveRecord::Base
 
   scope :with_member, ->(user){ joins(:user_team_user_relationships).where(user_team_user_relationships: {user_id: user.id}) }
   scope :with_project, ->(project){ joins(:user_team_project_relationships).where(user_team_project_relationships: {project_id: project})}
-  scope :without_project, ->(project){ where("id NOT IN (:ids)", ids: (a = with_project(project); a.blank? ? 0 : a))}
+  scope :without_project, ->(project){ where("user_teams.id NOT IN (:ids)", ids: (a = with_project(project); a.blank? ? 0 : a))}
   scope :created_by, ->(user){ where(owner_id: user) }
 
   class << self
diff --git a/app/views/dashboard/_teams.html.haml b/app/views/dashboard/_teams.html.haml
index 4250faac685..b047acf8d4a 100644
--- a/app/views/dashboard/_teams.html.haml
+++ b/app/views/dashboard/_teams.html.haml
@@ -1,16 +1,12 @@
 .teams_box
   %h5.title
-    My Teams
+    Teams
     %small
       (#{@teams.count})
     %span.right
       = link_to new_team_path, class: "btn very_small info" do
         %i.icon-plus
         New Team
-    %span.right
-      = link_to teams_path, class: "btn very_small info" do
-        %i.icon-user
-        All Teams
   %ul.well-list
     - @teams.each do |team|
       %li
diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml
index de4117ae296..8f4f3d7815f 100644
--- a/app/views/layouts/_head_panel.html.haml
+++ b/app/views/layouts/_head_panel.html.haml
@@ -8,9 +8,6 @@
         %span.separator
       %h1.project_name= title
       %ul.nav
-        %li
-          = link_to teams_path, title: "Teams of users", class: 'has_bottom_tooltip', 'data-original-title' => 'Teams list'  do
-            %i.icon-group
         - if current_user.is_admin?
           %li
             = link_to admin_root_path, title: "Admin area", class: 'has_bottom_tooltip', 'data-original-title' => 'Admin area' do
diff --git a/app/views/projects/teams/avaliable.html.haml b/app/views/projects/teams/available.html.haml
similarity index 100%
rename from app/views/projects/teams/avaliable.html.haml
rename to app/views/projects/teams/available.html.haml
diff --git a/app/views/team_members/index.html.haml b/app/views/team_members/index.html.haml
index f694ccbca93..6425302b83b 100644
--- a/app/views/team_members/index.html.haml
+++ b/app/views/team_members/index.html.haml
@@ -10,7 +10,7 @@
     %span.right
       = link_to import_project_team_members_path(@project), class: "btn small grouped", title: "Import team from another project" do
         Import team from another project
-      = link_to avaliable_project_teams_path(@project), class: "btn small grouped", title: "Assign project to team of users" do
+      = link_to available_project_teams_path(@project), class: "btn small grouped", title: "Assign project to team of users" do
         Assign project to Team of users
       = link_to new_project_team_member_path(@project), class: "btn success small grouped", title: "New Team Member" do
         New Team Member
diff --git a/app/views/teams/new.html.haml b/app/views/teams/new.html.haml
index a068c51e6ab..12695f2b5ae 100644
--- a/app/views/teams/new.html.haml
+++ b/app/views/teams/new.html.haml
@@ -8,7 +8,7 @@
     = f.label :name do
       Team name is
     .input
-      = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
+      = f.text_field :name, placeholder: "Ex. Ruby Developers", class: "xxlarge left"
       &nbsp;
       = f.submit 'Create team', class: "btn primary"
   %hr
diff --git a/config/routes.rb b/config/routes.rb
index 387f94ba025..ba350a70bfa 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -272,7 +272,7 @@ Gitlab::Application.routes.draw do
     scope module: :projects do
       resources :teams, only: [] do
         collection do
-          get :avaliable
+          get :available
           post :assign
         end
         member do
-- 
GitLab


From b5dd9e6775e2da52a9efb07bbeedd7cd56230c1d Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 24 Jan 2013 11:43:09 +0200
Subject: [PATCH 071/197] Make a team and group boxes smaller on dashboard

---
 app/models/user_team_user_relationship.rb |  4 ++++
 app/views/dashboard/_groups.html.haml     | 10 ++++------
 app/views/dashboard/_teams.html.haml      | 15 +++++++--------
 3 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/app/models/user_team_user_relationship.rb b/app/models/user_team_user_relationship.rb
index 00d12ebf607..63bdc49e5b6 100644
--- a/app/models/user_team_user_relationship.rb
+++ b/app/models/user_team_user_relationship.rb
@@ -12,4 +12,8 @@ class UserTeamUserRelationship < ActiveRecord::Base
   def user_name
     user.name
   end
+
+  def access_human
+    UsersProject.access_roles.invert[permission]
+  end
 end
diff --git a/app/views/dashboard/_groups.html.haml b/app/views/dashboard/_groups.html.haml
index dc50bffda80..f9774669d9a 100644
--- a/app/views/dashboard/_groups.html.haml
+++ b/app/views/dashboard/_groups.html.haml
@@ -1,4 +1,4 @@
-.groups_box
+.ui-box
   %h5.title
     Groups
     %small
@@ -13,8 +13,6 @@
       %li
         = link_to group_path(id: group.path), class: dom_class(group) do
           %strong.well-title= truncate(group.name, length: 35)
-          %span.arrow
-            &rarr;
-          %span.last_activity
-            %strong Projects:
-            %span= current_user.authorized_projects.where(namespace_id: group.id).count
+        %span.right.light
+          - if group.owner == current_user
+            %i.icon-wrench
diff --git a/app/views/dashboard/_teams.html.haml b/app/views/dashboard/_teams.html.haml
index b047acf8d4a..7912175b760 100644
--- a/app/views/dashboard/_teams.html.haml
+++ b/app/views/dashboard/_teams.html.haml
@@ -1,4 +1,4 @@
-.teams_box
+.ui-box
   %h5.title
     Teams
     %small
@@ -12,10 +12,9 @@
       %li
         = link_to team_path(id: team.path), class: dom_class(team) do
           %strong.well-title= truncate(team.name, length: 35)
-          %span.arrow
-            &rarr;
-          %span.last_activity
-            %strong Projects:
-            %span= "#{team.projects.count}, "
-            %strong Members:
-            %span= team.members.count
+        %span.right.light
+          - if team.owner == current_user
+            %i.icon-wrench
+          - tm = current_user.user_team_user_relationships.find_by_user_team_id(team.id)
+          - if tm
+            = tm.access_human
-- 
GitLab


From 11b7b93cf7a0329ce9c012ef866c975acc42d9b4 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 24 Jan 2013 13:39:00 +0200
Subject: [PATCH 072/197] move team navs to upper nav

---
 app/views/layouts/user_team.html.haml | 18 ++++++++++++++++++
 app/views/teams/_team_head.html.haml  | 19 -------------------
 2 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/app/views/layouts/user_team.html.haml b/app/views/layouts/user_team.html.haml
index 769fc3b78c3..12fce837238 100644
--- a/app/views/layouts/user_team.html.haml
+++ b/app/views/layouts/user_team.html.haml
@@ -8,15 +8,33 @@
       %ul.main_menu
         = nav_link(path: 'teams#show', html_options: {class: 'home'}) do
           = link_to "Home", team_path(@team), title: "Home"
+
         = nav_link(path: 'teams#issues') do
           = link_to issues_team_path(@team) do
             Issues
             %span.count= Issue.opened.of_user_team(@team).count
+
         = nav_link(path: 'teams#merge_requests') do
           = link_to merge_requests_team_path(@team) do
             Merge Requests
             %span.count= MergeRequest.opened.of_user_team(@team).count
+
         = nav_link(path: 'teams#search') do
           = link_to "Search", search_team_path(@team)
 
+        = nav_link(controller: [:members]) do
+          = link_to team_members_path(@team), class: "team-tab tab" do
+            Members
+
+        - if can? current_user, :admin_user_team, @team
+          = nav_link(controller: [:projects]) do
+            = link_to team_projects_path(@team), class: "team-tab tab" do
+              %i.icon-briefcase
+              Projects
+
+          = nav_link(path: 'teams#edit') do
+            = link_to edit_team_path(@team), class: "stat-tab tab " do
+              %i.icon-edit
+              Edit Team
+
       .content= yield
diff --git a/app/views/teams/_team_head.html.haml b/app/views/teams/_team_head.html.haml
index cb5c9567ba6..e69de29bb2d 100644
--- a/app/views/teams/_team_head.html.haml
+++ b/app/views/teams/_team_head.html.haml
@@ -1,19 +0,0 @@
-%ul.nav.nav-tabs
-  = nav_link(path: 'teams#show') do
-    = link_to team_path(@team), class: "activities-tab tab" do
-      %i.icon-home
-      Show
-  = nav_link(controller: [:members]) do
-    = link_to team_members_path(@team), class: "team-tab tab" do
-      %i.icon-user
-      Members
-  = nav_link(controller: [:projects]) do
-    = link_to team_projects_path(@team), class: "team-tab tab" do
-      %i.icon-briefcase
-      Projects
-
-  - if can? current_user, :admin_user_team, @team
-    = nav_link(path: 'teams#edit', html_options: {class: 'right'}) do
-      = link_to edit_team_path(@team), class: "stat-tab tab " do
-        %i.icon-edit
-        Edit Team
-- 
GitLab


From b4967b3703e1d520dd520f4bb7196ba3ecc302e9 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 24 Jan 2013 14:10:17 +0200
Subject: [PATCH 073/197] Dont allow to select a project you have no right to
 assign

---
 app/controllers/teams/projects_controller.rb | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/app/controllers/teams/projects_controller.rb b/app/controllers/teams/projects_controller.rb
index 21ddba865f3..9e9cd9f5f57 100644
--- a/app/controllers/teams/projects_controller.rb
+++ b/app/controllers/teams/projects_controller.rb
@@ -9,9 +9,8 @@ class Teams::ProjectsController < Teams::ApplicationController
 
   def new
     user_team
-    @avaliable_projects = Project.scoped
+    @avaliable_projects = current_user.owned_projects.scoped
     @avaliable_projects = @avaliable_projects.without_team(user_team) if user_team.projects.any?
-    #@projects.reject!(&:empty_repo?)
 
     redirect_to team_projects_path(user_team), notice: "No avalible projects." unless @avaliable_projects.any?
   end
-- 
GitLab


From 7403afea9748316b78242ecb250f619fe1a15b36 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 24 Jan 2013 14:15:14 +0200
Subject: [PATCH 074/197] Reject non-owned projects to assign to teams

---
 app/controllers/teams/projects_controller.rb | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/app/controllers/teams/projects_controller.rb b/app/controllers/teams/projects_controller.rb
index 9e9cd9f5f57..f5729351508 100644
--- a/app/controllers/teams/projects_controller.rb
+++ b/app/controllers/teams/projects_controller.rb
@@ -16,13 +16,19 @@ class Teams::ProjectsController < Teams::ApplicationController
   end
 
   def create
-    unless params[:project_ids].blank?
-      project_ids = params[:project_ids]
-      access = params[:greatest_project_access]
-      user_team.assign_to_projects(project_ids, access)
-    end
+    redirect_to :back if params[:project_ids].blank?
+
+    project_ids = params[:project_ids]
+    access = params[:greatest_project_access]
+
+    # Reject non-allowed projects
+    allowed_project_ids = current_user.owned_projects.map(&:id)
+    project_ids.select! { |id| allowed_project_ids.include?(id) }
+
+    # Assign projects to team
+    user_team.assign_to_projects(project_ids, access)
 
-    redirect_to team_projects_path(user_team), notice: 'Team of users was successfully assgned to projects.'
+    redirect_to team_projects_path(user_team), notice: 'Team of users was successfully assigned to projects.'
   end
 
   def edit
-- 
GitLab


From 6d713e84e185f60b00c38e792d11df27ed110605 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Thu, 24 Jan 2013 22:18:43 +0400
Subject: [PATCH 075/197] remove unused code

---
 app/controllers/admin/teams_controller.rb | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/app/controllers/admin/teams_controller.rb b/app/controllers/admin/teams_controller.rb
index 7371f4a446c..335add0f57d 100644
--- a/app/controllers/admin/teams_controller.rb
+++ b/app/controllers/admin/teams_controller.rb
@@ -6,13 +6,7 @@ class Admin::TeamsController < Admin::ApplicationController
   end
 
   def show
-    @projects = Project.scoped
-    @projects = @projects.without_team(user_team) if user_team.projects.any?
-    #@projects.reject!(&:empty_repo?)
-
-    @users = User.active
-    @users = @users.not_in_team(user_team) if user_team.members.any?
-    @users = UserDecorator.decorate @users
+    user_team
   end
 
   def new
-- 
GitLab


From e52fec9cd9812e6fd8a7700c2188dbbf6e022c81 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Thu, 24 Jan 2013 22:19:18 +0400
Subject: [PATCH 076/197] Update check If user can assign project to team

---
 app/controllers/teams/projects_controller.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/controllers/teams/projects_controller.rb b/app/controllers/teams/projects_controller.rb
index f5729351508..27dc934452f 100644
--- a/app/controllers/teams/projects_controller.rb
+++ b/app/controllers/teams/projects_controller.rb
@@ -4,7 +4,7 @@ class Teams::ProjectsController < Teams::ApplicationController
 
   def index
     @projects = user_team.projects
-    @avaliable_projects = current_user.admin? ? Project.without_team(user_team) : (Project.personal(current_user) + current_user.projects).uniq
+    @avaliable_projects = current_user.admin? ? Project.without_team(user_team) : current_user.owned_projects.without_team(user_team)
   end
 
   def new
-- 
GitLab


From d839f6c52571e3b873a05779b1131f7b00670b31 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Thu, 24 Jan 2013 22:31:28 +0400
Subject: [PATCH 077/197] Remove simple code duplication in members controllers

---
 app/controllers/admin/teams/members_controller.rb | 3 +--
 app/controllers/teams/members_controller.rb       | 3 +--
 app/models/user.rb                                | 1 +
 3 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/app/controllers/admin/teams/members_controller.rb b/app/controllers/admin/teams/members_controller.rb
index 7fd777dc72f..139b82ab66c 100644
--- a/app/controllers/admin/teams/members_controller.rb
+++ b/app/controllers/admin/teams/members_controller.rb
@@ -1,7 +1,6 @@
 class Admin::Teams::MembersController < Admin::Teams::ApplicationController
   def new
-    @users = User.active
-    @users = @users.not_in_team(user_team) if user_team.members.any?
+    @users = User.potential_team_members(user_team)
     @users = UserDecorator.decorate @users
   end
 
diff --git a/app/controllers/teams/members_controller.rb b/app/controllers/teams/members_controller.rb
index 56e952a3d40..c41d5d7abe6 100644
--- a/app/controllers/teams/members_controller.rb
+++ b/app/controllers/teams/members_controller.rb
@@ -7,8 +7,7 @@ class Teams::MembersController < Teams::ApplicationController
   end
 
   def new
-    @users = User.active
-    @users = @users.not_in_team(user_team) if user_team.members.any?
+    @users = User.potential_team_members(user_team)
     @users = UserDecorator.decorate @users
   end
 
diff --git a/app/models/user.rb b/app/models/user.rb
index 16e07e9ce3f..b61d2cb0d83 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -91,6 +91,7 @@ class User < ActiveRecord::Base
   scope :alphabetically, order('name ASC')
   scope :in_team, ->(team){ where(id: team.member_ids) }
   scope :not_in_team, ->(team){ where('users.id NOT IN (:ids)', ids: team.member_ids) }
+  scope :potential_team_members, ->(team) { team.members.any? ? active : active.not_in_team(team) }
 
   #
   # Class methods
-- 
GitLab


From ac8247b46df8eb8c475436fc276a3648379ae7a0 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Fri, 25 Jan 2013 10:07:21 +0200
Subject: [PATCH 078/197] Improved search. added filters

---
 app/assets/stylesheets/common.scss   |  16 +++-
 app/controllers/search_controller.rb |  14 +++-
 app/helpers/application_helper.rb    |  40 +++++-----
 app/views/layouts/_search.html.haml  |   2 +
 app/views/search/_filter.html.haml   |  24 ++++++
 app/views/search/_result.html.haml   | 113 ++++++++-------------------
 app/views/search/show.html.haml      |  14 +++-
 7 files changed, 117 insertions(+), 106 deletions(-)
 create mode 100644 app/views/search/_filter.html.haml

diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss
index db077048b6c..0d25b104bb5 100644
--- a/app/assets/stylesheets/common.scss
+++ b/app/assets/stylesheets/common.scss
@@ -1,5 +1,5 @@
 html {
-  overflow-y: scroll; 
+  overflow-y: scroll;
 }
 
 /** LAYOUT **/
@@ -277,8 +277,20 @@ p.time {
   }
 }
 
+.search-holder {
+  label, input {
+     height: 30px;
+     padding: 0;
+     font-size: 14px;
+  }
+  label {
+    line-height: 30px;
+    color: #666;
+  }
+}
+
 .highlight_word {
-  background: #EEDC94;
+  border-bottom: 2px solid #F90;
 }
 
 .status_info {
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index a23292396a0..bbd67df6c70 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -1,6 +1,18 @@
 class SearchController < ApplicationController
   def show
-    result = SearchContext.new(current_user.authorized_projects.map(&:id), params).execute
+    project_id = params[:project_id]
+    group_id = params[:group_id]
+
+    project_ids = current_user.authorized_projects.map(&:id)
+
+    if group_id.present?
+      group_project_ids = Group.find(group_id).projects.map(&:id)
+      project_ids.select! { |id| group_project_ids.include?(id)}
+    elsif project_id.present?
+      project_ids.select! { |id| id == project_id.to_i}
+    end
+
+    result = SearchContext.new(project_ids, params).execute
 
     @projects       = result[:projects]
     @merge_requests = result[:merge_requests]
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 6478982cdad..9aafce57e60 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -72,8 +72,8 @@ module ApplicationHelper
   end
 
   def search_autocomplete_source
-    projects = current_user.authorized_projects.map { |p| { label: p.name_with_namespace, url: project_path(p) } }
-    groups = current_user.authorized_groups.map { |group| { label: "<group> #{group.name}", url: group_path(group) } }
+    projects = current_user.authorized_projects.map { |p| { label: "project: #{p.name_with_namespace}", url: project_path(p) } }
+    groups = current_user.authorized_groups.map { |group| { label: "group: #{group.name}", url: group_path(group) } }
 
     default_nav = [
       { label: "My Profile", url: profile_path },
@@ -83,29 +83,29 @@ module ApplicationHelper
     ]
 
     help_nav = [
-      { label: "API Help", url: help_api_path },
-      { label: "Markdown Help", url: help_markdown_path },
-      { label: "Permissions Help", url: help_permissions_path },
-      { label: "Public Access Help", url: help_public_access_path },
-      { label: "Rake Tasks Help", url: help_raketasks_path },
-      { label: "SSH Keys Help", url: help_ssh_path },
-      { label: "System Hooks Help", url: help_system_hooks_path },
-      { label: "Web Hooks Help", url: help_web_hooks_path },
-      { label: "Workflow Help", url: help_workflow_path },
+      { label: "help: API Help", url: help_api_path },
+      { label: "help: Markdown Help", url: help_markdown_path },
+      { label: "help: Permissions Help", url: help_permissions_path },
+      { label: "help: Public Access Help", url: help_public_access_path },
+      { label: "help: Rake Tasks Help", url: help_raketasks_path },
+      { label: "help: SSH Keys Help", url: help_ssh_path },
+      { label: "help: System Hooks Help", url: help_system_hooks_path },
+      { label: "help: Web Hooks Help", url: help_web_hooks_path },
+      { label: "help: Workflow Help", url: help_workflow_path },
     ]
 
     project_nav = []
     if @project && @project.repository && @project.repository.root_ref
       project_nav = [
-        { label: "#{@project.name} Issues",   url: project_issues_path(@project) },
-        { label: "#{@project.name} Commits",  url: project_commits_path(@project, @ref || @project.repository.root_ref) },
-        { label: "#{@project.name} Merge Requests", url: project_merge_requests_path(@project) },
-        { label: "#{@project.name} Milestones", url: project_milestones_path(@project) },
-        { label: "#{@project.name} Snippets", url: project_snippets_path(@project) },
-        { label: "#{@project.name} Team",     url: project_team_index_path(@project) },
-        { label: "#{@project.name} Tree",     url: project_tree_path(@project, @ref || @project.repository.root_ref) },
-        { label: "#{@project.name} Wall",     url: wall_project_path(@project) },
-        { label: "#{@project.name} Wiki",     url: project_wikis_path(@project) },
+        { label: "#{@project.name_with_namespace} - Issues",   url: project_issues_path(@project) },
+        { label: "#{@project.name_with_namespace} - Commits",  url: project_commits_path(@project, @ref || @project.repository.root_ref) },
+        { label: "#{@project.name_with_namespace} - Merge Requests", url: project_merge_requests_path(@project) },
+        { label: "#{@project.name_with_namespace} - Milestones", url: project_milestones_path(@project) },
+        { label: "#{@project.name_with_namespace} - Snippets", url: project_snippets_path(@project) },
+        { label: "#{@project.name_with_namespace} - Team",     url: project_team_index_path(@project) },
+        { label: "#{@project.name_with_namespace} - Tree",     url: project_tree_path(@project, @ref || @project.repository.root_ref) },
+        { label: "#{@project.name_with_namespace} - Wall",     url: wall_project_path(@project) },
+        { label: "#{@project.name_with_namespace} - Wiki",     url: project_wikis_path(@project) },
       ]
     end
 
diff --git a/app/views/layouts/_search.html.haml b/app/views/layouts/_search.html.haml
index 7ea9079849a..c484af04704 100644
--- a/app/views/layouts/_search.html.haml
+++ b/app/views/layouts/_search.html.haml
@@ -1,6 +1,8 @@
 .search
   = form_tag search_path, method: :get, class: 'navbar-form pull-left' do |f|
     = text_field_tag "search", nil, placeholder: "Search", class: "search-input"
+    = hidden_field_tag :group_id, @group.try(:id)
+    = hidden_field_tag :project_id, @project.try(:id)
 
 :javascript
   $(function(){
diff --git a/app/views/search/_filter.html.haml b/app/views/search/_filter.html.haml
new file mode 100644
index 00000000000..3fe17dce857
--- /dev/null
+++ b/app/views/search/_filter.html.haml
@@ -0,0 +1,24 @@
+%fieldset
+  %legend Groups:
+  %ul.nav.nav-pills.nav-stacked
+    %li{class: ("active" if params[:group_id].blank?)}
+      = link_to search_path(group_id: nil, search: params[:search]) do
+        Any
+    - current_user.authorized_groups.each do |group|
+      %li{class: ("active" if params[:group_id] == group.id.to_s)}
+        = link_to search_path(group_id: group.id, search: params[:search]) do
+          = group.name
+
+%fieldset
+  %legend Projects:
+  %ul.nav.nav-pills.nav-stacked
+    %li{class: ("active" if params[:project_id].blank?)}
+      = link_to search_path(project_id: nil, search: params[:search]) do
+        Any
+    - current_user.authorized_projects.each do |project|
+      %li{class: ("active" if params[:project_id] == project.id.to_s)}
+        = link_to search_path(project_id: project.id, search: params[:search]) do
+          = project.name_with_namespace
+
+= hidden_field_tag :group_id, params[:group_id]
+= hidden_field_tag :project_id, params[:project_id]
diff --git a/app/views/search/_result.html.haml b/app/views/search/_result.html.haml
index 79bed4f737c..bfa46075baa 100644
--- a/app/views/search/_result.html.haml
+++ b/app/views/search/_result.html.haml
@@ -1,83 +1,38 @@
-%br
-%h3.page_title
-  Search results
-  %span.cgray (#{@projects.count + @merge_requests.count + @issues.count + @wiki_pages.count})
-%hr
+%fieldset
+  %legend
+    Search results
+    %span.cgray (#{@projects.count + @merge_requests.count + @issues.count + @wiki_pages.count})
 .search_results
-  .row
-    .span6
-      %table
-        %thead
-          %tr
-            %th Projects
-        %tbody
-          - @projects.each do |project|
-            %tr
-              %td
-                = link_to project do
-                  %strong.term= project.name_with_namespace
-                  %small.cgray
-                    last activity at
-                    = project.last_activity_date.stamp("Aug 25, 2011")
-          - if @projects.blank?
-            %tr
-              %td
-                %h4.nothing_here_message No Projects
-      %br
-      %table
-        %thead
-          %tr
-            %th Merge Requests
-        %tbody
-          - @merge_requests.each do |merge_request|
-            %tr
-              %td
-                = link_to [merge_request.project, merge_request] do
-                  %span.badge.badge-info ##{merge_request.id}
-                  &ndash;
-                  %strong.term= truncate merge_request.title, length: 50
-                  %strong.right
-                    %span.label= merge_request.project.name
-          - if @merge_requests.blank?
-            %tr
-              %td
-                %h4.nothing_here_message No Merge Requests
-    .span6
-      %table
-        %thead
-          %tr
-            %th Issues
-        %tbody
-          - @issues.each do |issue|
-            %tr
-              %td
-                = link_to [issue.project, issue] do
-                  %span.badge.badge-info ##{issue.id}
-                  &ndash;
-                  %strong.term= truncate issue.title, length: 40
-                %strong.right
-                  %span.label= issue.project.name
-          - if @issues.blank?
-            %tr
-              %td
-                %h4.nothing_here_message No Issues
-    .span6
-      %table
-        %thead
-          %tr
-            %th Wiki
-        %tbody
-          - @wiki_pages.each do |wiki_page|
-            %tr
-              %td
-                = link_to project_wiki_path(wiki_page.project, wiki_page) do
-                  %strong.term= truncate wiki_page.title, length: 40
-                %strong.right
-                  %span.label= wiki_page.project.name
-          - if @wiki_pages.blank?
-            %tr
-              %td
-                %h4.nothing_here_message No wiki pages
+  %ul.well-list
+    - @projects.each do |project|
+      %li
+        project:
+        = link_to project do
+          %strong.term= project.name_with_namespace
+    - @merge_requests.each do |merge_request|
+      %li
+        merge request:
+        = link_to [merge_request.project, merge_request] do
+          %span ##{merge_request.id}
+          %strong.term
+            = truncate merge_request.title, length: 50
+        %span.light (#{merge_request.project.name_with_namespace})
+    - @issues.each do |issue|
+      %li
+        issue:
+        = link_to [issue.project, issue] do
+          %span ##{issue.id}
+          %strong.term
+            = truncate issue.title, length: 50
+        %span.light (#{issue.project.name_with_namespace})
+    - @wiki_pages.each do |wiki_page|
+      %li
+        wiki:
+        = link_to project_wiki_path(wiki_page.project, wiki_page) do
+          %strong.term
+            = truncate wiki_page.title, length: 50
+        %span.light (#{wiki_page.project.name_with_namespace})
+
 :javascript
   $(function() {
     $(".search_results .term").highlight("#{escape_javascript(params[:search])}");
diff --git a/app/views/search/show.html.haml b/app/views/search/show.html.haml
index aa0d6d700d9..22e1ae50df1 100644
--- a/app/views/search/show.html.haml
+++ b/app/views/search/show.html.haml
@@ -1,9 +1,15 @@
 = form_tag search_path, method: :get, class: 'form-inline' do |f|
-  .padded
+  .search-holder
     = label_tag :search do
-      %strong Looking for
+      %span Looking for
     .input
       = search_field_tag :search, params[:search], placeholder: "issue 143", class: "input-xxlarge search-text-input", id: "dashboard_search"
       = submit_tag 'Search', class: "btn primary wide"
-- if params[:search].present?
-  = render 'search/result'
+  .clearfix
+  .row
+    .span3
+      = render 'filter', f: f
+    .span9
+      .results
+        - if params[:search].present?
+          = render 'search/result'
-- 
GitLab


From 3ce79e06580c0efb0abeba0263bdc3ea10670e2d Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Fri, 25 Jan 2013 10:10:12 +0200
Subject: [PATCH 079/197] fix spec

---
 spec/models/user_spec.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index f19c40b5fa6..2ca82edf74e 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -189,7 +189,7 @@ describe User do
 
     it { user.is_admin?.should be_false }
     it { user.require_ssh_key?.should be_true }
-    it { user.can_create_group?.should be_false }
+    it { user.can_create_group?.should be_true }
     it { user.can_create_project?.should be_true }
     it { user.first_name.should == 'John' }
   end
-- 
GitLab


From 097e6053efd973c70c4995784a1abc30e9384008 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Fri, 25 Jan 2013 10:16:20 +0200
Subject: [PATCH 080/197] Fix for broken commit_url in graph

---
 app/views/projects/graph.html.haml | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/app/views/projects/graph.html.haml b/app/views/projects/graph.html.haml
index 4e0b0e36c34..72d9cb5ef15 100644
--- a/app/views/projects/graph.html.haml
+++ b/app/views/projects/graph.html.haml
@@ -1,5 +1,6 @@
 %h3.page_title Project Network Graph
 %br
+
 .graph_holder
   %h4
     %small You can move around the graph by using the arrow keys.
@@ -11,6 +12,6 @@
   $(function(){
     branch_graph = new BranchGraph($("#holder"), {
       url: '#{url_for controller: 'projects', action: 'graph', format: :json}',
-      commit_url: '#{url_for controller: 'projects', action: 'show'}/commits/%s'
+      commit_url: '#{project_commit_path(@project, 'ae45ca32').gsub("ae45ca32", "%s")}'
     });
   });
-- 
GitLab


From 585a53c4158e098c7c916cca6b252efbe06a6334 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Fri, 25 Jan 2013 11:08:22 +0200
Subject: [PATCH 081/197] can_create_group, can_create_team boolean fields for
 user

---
 db/migrate/20130125090214_add_user_permissions.rb | 11 +++++++++++
 db/schema.rb                                      |  4 +++-
 2 files changed, 14 insertions(+), 1 deletion(-)
 create mode 100644 db/migrate/20130125090214_add_user_permissions.rb

diff --git a/db/migrate/20130125090214_add_user_permissions.rb b/db/migrate/20130125090214_add_user_permissions.rb
new file mode 100644
index 00000000000..38b5f439a2d
--- /dev/null
+++ b/db/migrate/20130125090214_add_user_permissions.rb
@@ -0,0 +1,11 @@
+class AddUserPermissions < ActiveRecord::Migration
+  def up
+    add_column :users, :can_create_group, :boolean, default: true, null: false
+    add_column :users, :can_create_team, :boolean, default: true, null: false
+  end
+
+  def down
+    remove_column :users, :can_create_group
+    remove_column :users, :can_create_team
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 88849872ab2..144f4a57036 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
 #
 # It's strongly recommended to check this file into your version control system.
 
-ActiveRecord::Schema.define(:version => 20130110172407) do
+ActiveRecord::Schema.define(:version => 20130125090214) do
 
   create_table "events", :force => true do |t|
     t.string   "target_type"
@@ -267,6 +267,8 @@ ActiveRecord::Schema.define(:version => 20130110172407) do
     t.string   "extern_uid"
     t.string   "provider"
     t.string   "username"
+    t.boolean  "can_create_group",       :default => true,  :null => false
+    t.boolean  "can_create_team",        :default => true,  :null => false
   end
 
   add_index "users", ["admin"], :name => "index_users_on_admin"
-- 
GitLab


From 00e4a479d3732a528745513e4150fe28fee178e2 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Fri, 25 Jan 2013 11:30:49 +0200
Subject: [PATCH 082/197] allow/deny user to create group/team

---
 app/controllers/groups_controller.rb  |  5 +++++
 app/models/ability.rb                 | 27 ++++++++++++++++++---------
 app/models/user.rb                    |  2 +-
 app/views/admin/users/_form.html.haml |  8 ++++++++
 4 files changed, 32 insertions(+), 10 deletions(-)

diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index f95db1af383..72df170f1fd 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -6,6 +6,7 @@ class GroupsController < ApplicationController
 
   # Authorize
   before_filter :authorize_read_group!, except: [:new, :create]
+  before_filter :authorize_create_group!, only: [:new, :create]
 
   # Load group projects
   before_filter :projects, except: [:new, :create]
@@ -103,4 +104,8 @@ class GroupsController < ApplicationController
       return render_404
     end
   end
+
+  def authorize_create_group!
+    can?(current_user, :create_group, nil)
+  end
 end
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 63d720164a1..6d087a959a9 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -1,16 +1,25 @@
 class Ability
   class << self
-    def allowed(object, subject)
+    def allowed(user, subject)
+      return [] unless user.kind_of?(User)
+
       case subject.class.name
-      when "Project" then project_abilities(object, subject)
-      when "Issue" then issue_abilities(object, subject)
-      when "Note" then note_abilities(object, subject)
-      when "Snippet" then snippet_abilities(object, subject)
-      when "MergeRequest" then merge_request_abilities(object, subject)
-      when "Group", "Namespace" then group_abilities(object, subject)
-      when "UserTeam" then user_team_abilities(object, subject)
+      when "Project" then project_abilities(user, subject)
+      when "Issue" then issue_abilities(user, subject)
+      when "Note" then note_abilities(user, subject)
+      when "Snippet" then snippet_abilities(user, subject)
+      when "MergeRequest" then merge_request_abilities(user, subject)
+      when "Group", "Namespace" then group_abilities(user, subject)
+      when "UserTeam" then user_team_abilities(user, subject)
       else []
-      end
+      end.concat(global_abilities(user))
+    end
+
+    def global_abilities(user)
+      rules = []
+      rules << :create_group if user.can_create_group
+      rules << :create_team if user.can_create_team
+      rules
     end
 
     def project_abilities(user, project)
diff --git a/app/models/user.rb b/app/models/user.rb
index b61d2cb0d83..469436e9e3f 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -232,7 +232,7 @@ class User < ActiveRecord::Base
   end
 
   def can_create_group?
-    can_create_project?
+    can?(:create_group, nil)
   end
 
   def abilities
diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml
index 45195152cb7..465568ade9e 100644
--- a/app/views/admin/users/_form.html.haml
+++ b/app/views/admin/users/_form.html.haml
@@ -46,6 +46,14 @@
             = f.label :projects_limit
             .input= f.number_field :projects_limit
 
+          .clearfix
+            = f.label :can_create_group
+            .input= f.check_box :can_create_group
+
+          .clearfix
+            = f.label :can_create_team
+            .input= f.check_box :can_create_team
+
           .clearfix
             = f.label :admin do
               %strong.cred Administrator
-- 
GitLab


From 20a4742efdc9ed96da4ba3cbf6f513aff75c7ab1 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Fri, 25 Jan 2013 11:36:15 +0200
Subject: [PATCH 083/197] Fixing team tests

---
 app/assets/stylesheets/sections/projects.scss |  2 --
 app/views/dashboard/_teams.html.haml          |  2 +-
 features/dashboard/dashboard.feature          |  6 ------
 features/steps/userteams/userteams.rb         | 16 ++++++++--------
 features/teams/team.feature                   |  7 -------
 5 files changed, 9 insertions(+), 24 deletions(-)

diff --git a/app/assets/stylesheets/sections/projects.scss b/app/assets/stylesheets/sections/projects.scss
index ee2c379f2ab..b6db65adff1 100644
--- a/app/assets/stylesheets/sections/projects.scss
+++ b/app/assets/stylesheets/sections/projects.scss
@@ -6,8 +6,6 @@
   .side {
     @extend .right;
 
-    .groups_box,
-    .teams_box,
     .projects_box {
       > .title {
         padding: 2px 15px;
diff --git a/app/views/dashboard/_teams.html.haml b/app/views/dashboard/_teams.html.haml
index 7912175b760..5b2ea7a2384 100644
--- a/app/views/dashboard/_teams.html.haml
+++ b/app/views/dashboard/_teams.html.haml
@@ -1,4 +1,4 @@
-.ui-box
+.ui-box.teams-box
   %h5.title
     Teams
     %small
diff --git a/features/dashboard/dashboard.feature b/features/dashboard/dashboard.feature
index 759843692b8..695148b5cdf 100644
--- a/features/dashboard/dashboard.feature
+++ b/features/dashboard/dashboard.feature
@@ -16,12 +16,6 @@ Feature: Dashboard
     And I visit dashboard page
     Then I should see groups list
 
-  Scenario: I should see correct projects count
-    Given I have group with projects
-    And group has a projects that does not belongs to me
-    When I visit dashboard page
-    Then I should see 1 project at group list
-
   Scenario: I should see last push widget
     Then I should see last push widget
     And I click "Create Merge Request" link
diff --git a/features/steps/userteams/userteams.rb b/features/steps/userteams/userteams.rb
index 39a2588ec92..be83b4bac05 100644
--- a/features/steps/userteams/userteams.rb
+++ b/features/steps/userteams/userteams.rb
@@ -8,16 +8,16 @@ class Userteams < Spinach::FeatureSteps
     end
 
     Then 'I should see dashboard page without teams info block' do
-      page.has_no_css?(".teams_box").must_equal true
+      page.has_no_css?(".teams-box").must_equal true
     end
 
     When 'I have teams with my membership' do
-      team = create :user_team
+      team = create :user_team, owner: current_user
       team.add_member(current_user, UserTeam.access_roles["Master"], true)
     end
 
     Then 'I should see dashboard page with teams information block' do
-      page.should have_css(".teams_box")
+      page.should have_css(".teams-box")
     end
 
     When 'exist user teams' do
@@ -53,7 +53,7 @@ class Userteams < Spinach::FeatureSteps
     end
 
     When 'I have teams with projects and members' do
-      team = create :user_team
+      team = create :user_team, owner: current_user
       @project = create :project
       team.add_member(current_user, UserTeam.access_roles["Master"], true)
       team.assign_to_project(@project, UserTeam.access_roles["Master"])
@@ -92,7 +92,7 @@ class Userteams < Spinach::FeatureSteps
     end
 
     Given 'I have team with projects and members' do
-      team = create :user_team
+      team = create :user_team, owner: current_user
       project = create :project
       user = create :user
       team.add_member(current_user, UserTeam.access_roles["Master"], true)
@@ -190,11 +190,11 @@ class Userteams < Spinach::FeatureSteps
     end
 
     And 'I have my own project without teams' do
-      @project = create :project, creator: current_user
+      @project = create :project, namespace: current_user.namespace
     end
 
     And 'I visit my team page' do
-      team = UserTeam.last
+      team = UserTeam.where(owner_id: current_user.id).last
       visit team_path(team)
     end
 
@@ -213,7 +213,7 @@ class Userteams < Spinach::FeatureSteps
 
     When 'I submit form with selected project and max access' do
       within "#assign_projects" do
-        select @project.name, :from => "project_ids"
+        select @project.name_with_namespace, :from => "project_ids"
         select "Reporter", :from => "greatest_project_access"
       end
       click_button "Add"
diff --git a/features/teams/team.feature b/features/teams/team.feature
index b62d230fd56..9255e0daadb 100644
--- a/features/teams/team.feature
+++ b/features/teams/team.feature
@@ -14,13 +14,6 @@ Feature: UserTeams
     And I visit dashboard page
     Then I should see dashboard page with teams information block
 
-  Scenario: I should see all teams list
-    When exist user teams
-    And I visit dashboard page
-    And I click on "All teams" link
-    Then I should see "All teams" page
-    And I should see exist teams in teams list
-
   Scenario: I should can create new team
     When I have teams with my membership
     And I visit dashboard page
-- 
GitLab


From 2812e6f1f5a15a5f56ee61001e4a46cd922e827b Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Fri, 25 Jan 2013 13:47:54 +0200
Subject: [PATCH 084/197] Fix removeing project if repo not exists

---
 lib/gitlab/backend/gitolite_config.rb | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/lib/gitlab/backend/gitolite_config.rb b/lib/gitlab/backend/gitolite_config.rb
index f12c10ce01c..e4ebd595a93 100644
--- a/lib/gitlab/backend/gitolite_config.rb
+++ b/lib/gitlab/backend/gitolite_config.rb
@@ -88,7 +88,10 @@ module Gitlab
     end
 
     def destroy_project(project)
-      FileUtils.rm_rf(project.repository.path_to_repo)
+      # do rm-rf only if repository exists
+      if project.repository
+        FileUtils.rm_rf(project.repository.path_to_repo)
+      end
       conf.rm_repo(project.path_with_namespace)
     end
 
-- 
GitLab


From 5aca1d64e0b8ca2c58c961eb9e04e5d8629ed8ab Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Fri, 25 Jan 2013 13:56:04 +0200
Subject: [PATCH 085/197] Fix project adding to team

---
 app/controllers/teams/projects_controller.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/controllers/teams/projects_controller.rb b/app/controllers/teams/projects_controller.rb
index 27dc934452f..e87889b4046 100644
--- a/app/controllers/teams/projects_controller.rb
+++ b/app/controllers/teams/projects_controller.rb
@@ -23,7 +23,7 @@ class Teams::ProjectsController < Teams::ApplicationController
 
     # Reject non-allowed projects
     allowed_project_ids = current_user.owned_projects.map(&:id)
-    project_ids.select! { |id| allowed_project_ids.include?(id) }
+    project_ids.select! { |id| allowed_project_ids.include?(id.to_i) }
 
     # Assign projects to team
     user_team.assign_to_projects(project_ids, access)
-- 
GitLab


From 8016a7bd33d6d488a2d180af1d4ac12ef3421e00 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Fri, 25 Jan 2013 14:18:23 +0200
Subject: [PATCH 086/197] fix 1145

---
 app/views/commits/_commits.html.haml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/views/commits/_commits.html.haml b/app/views/commits/_commits.html.haml
index 0dc6664c1d6..191320933d3 100644
--- a/app/views/commits/_commits.html.haml
+++ b/app/views/commits/_commits.html.haml
@@ -2,5 +2,5 @@
   %div.ui-box
     %h5.title
       %i.icon-calendar
-      = day.stamp("28 Aug, 2010")
+      %span= day.stamp("28 Aug, 2010")
     %ul.well-list= render commits
-- 
GitLab


From 70e05801b196a460ec2b1d6f6f096f44d32b7928 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Fri, 25 Jan 2013 15:36:10 +0200
Subject: [PATCH 087/197] fix User.potential_team_members

---
 app/models/user.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/models/user.rb b/app/models/user.rb
index 469436e9e3f..8ef8ecda797 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -91,7 +91,7 @@ class User < ActiveRecord::Base
   scope :alphabetically, order('name ASC')
   scope :in_team, ->(team){ where(id: team.member_ids) }
   scope :not_in_team, ->(team){ where('users.id NOT IN (:ids)', ids: team.member_ids) }
-  scope :potential_team_members, ->(team) { team.members.any? ? active : active.not_in_team(team) }
+  scope :potential_team_members, ->(team) { team.members.any? ? active.not_in_team(team) : active  }
 
   #
   # Class methods
-- 
GitLab


From 3ddd9f753c0a6a57313ea4860bf7167f98f53cd2 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Fri, 25 Jan 2013 15:42:41 +0200
Subject: [PATCH 088/197] Fix mass-assignment. Dont allow users w/o access to
 create team

---
 app/controllers/application_controller.rb |  4 ++++
 app/controllers/teams_controller.rb       | 11 ++++-------
 app/models/user.rb                        |  2 +-
 3 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index f903c7fdd62..74125e3308a 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -94,6 +94,10 @@ class ApplicationController < ActionController::Base
     return access_denied! unless can?(current_user, :download_code, project)
   end
 
+  def authorize_create_team!
+    return access_denied! unless can?(current_user, :create_team, nil)
+  end
+
   def authorize_manage_user_team!
     return access_denied! unless user_team.present? && can?(current_user, :manage_user_team, user_team)
   end
diff --git a/app/controllers/teams_controller.rb b/app/controllers/teams_controller.rb
index 7de094214d4..828bdeb80ab 100644
--- a/app/controllers/teams_controller.rb
+++ b/app/controllers/teams_controller.rb
@@ -1,13 +1,10 @@
 class TeamsController < ApplicationController
   # Authorize
-  before_filter :authorize_manage_user_team!
-  before_filter :authorize_admin_user_team!
+  before_filter :authorize_create_team!, only: [:new, :create]
+  before_filter :authorize_manage_user_team!, only: [:edit, :update]
+  before_filter :authorize_admin_user_team!, only: [:destroy]
 
-  # Skip access control on public section
-  skip_before_filter :authorize_manage_user_team!, only: [:index, :show, :new, :destroy, :create, :search, :issues, :merge_requests]
-  skip_before_filter :authorize_admin_user_team!, only: [:index, :show, :new, :create, :search, :issues, :merge_requests]
-
-  layout 'user_team',       only: [:show, :edit, :update, :destroy, :issues, :merge_requests, :search]
+  layout 'user_team', except: [:new, :create]
 
   def index
     @teams = current_user.user_teams.order('name ASC')
diff --git a/app/models/user.rb b/app/models/user.rb
index 8ef8ecda797..7a0d66453f8 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -40,7 +40,7 @@ class User < ActiveRecord::Base
   attr_accessible :email, :password, :password_confirmation, :remember_me, :bio, :name, :username,
                   :skype, :linkedin, :twitter, :dark_scheme, :theme_id, :force_random_password,
                   :extern_uid, :provider, as: [:default, :admin]
-  attr_accessible :projects_limit, as: :admin
+  attr_accessible :projects_limit, :can_create_team, :can_create_group, as: :admin
 
   attr_accessor :force_random_password
 
-- 
GitLab


From 6350b32a3dddf70a28526c4f95c652072411e9c7 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Fri, 25 Jan 2013 15:51:45 +0200
Subject: [PATCH 089/197] Fix security issues with teams

---
 app/controllers/dashboard_controller.rb |  2 +-
 app/controllers/teams_controller.rb     |  9 +++------
 app/helpers/application_helper.rb       |  1 +
 app/models/user.rb                      | 11 +++++++++++
 4 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
index 1322973489c..13b7f02fdb8 100644
--- a/app/controllers/dashboard_controller.rb
+++ b/app/controllers/dashboard_controller.rb
@@ -18,7 +18,7 @@ class DashboardController < ApplicationController
                   @projects
                 end
 
-    @teams = (UserTeam.with_member(current_user) + UserTeam.created_by(current_user)).uniq
+    @teams = current_user.authorized_teams
 
     @projects = @projects.page(params[:page]).per(30)
 
diff --git a/app/controllers/teams_controller.rb b/app/controllers/teams_controller.rb
index 828bdeb80ab..e69a092c507 100644
--- a/app/controllers/teams_controller.rb
+++ b/app/controllers/teams_controller.rb
@@ -4,11 +4,9 @@ class TeamsController < ApplicationController
   before_filter :authorize_manage_user_team!, only: [:edit, :update]
   before_filter :authorize_admin_user_team!, only: [:destroy]
 
-  layout 'user_team', except: [:new, :create]
+  before_filter :user_team, except: [:new, :create]
 
-  def index
-    @teams = current_user.user_teams.order('name ASC')
-  end
+  layout 'user_team', except: [:new, :create]
 
   def show
     user_team
@@ -83,7 +81,6 @@ class TeamsController < ApplicationController
   end
 
   def user_team
-    @team ||= UserTeam.find_by_path(params[:id])
+    @team ||= current_user.authorized_teams.find_by_path(params[:id])
   end
-
 end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 9aafce57e60..196105f0119 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -74,6 +74,7 @@ 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) } }
 
     default_nav = [
       { label: "My Profile", url: profile_path },
diff --git a/app/models/user.rb b/app/models/user.rb
index 7a0d66453f8..29f262968d5 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -295,4 +295,15 @@ class User < ActiveRecord::Base
   def namespace_id
     namespace.try :id
   end
+
+  def authorized_teams
+    @authorized_teams ||= begin
+                            ids = []
+                            ids << UserTeam.with_member(self).pluck('user_teams.id')
+                            ids << UserTeam.created_by(self).pluck('user_teams.id')
+                            ids.flatten
+
+                            UserTeam.where(id: ids)
+                          end
+  end
 end
-- 
GitLab


From 6743ecec597000315007b51bc3e45ea9c58cbaa7 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Fri, 25 Jan 2013 16:18:37 +0200
Subject: [PATCH 090/197] Fix redirects. Add link to new team and new group

---
 app/controllers/admin/teams_controller.rb |  2 +-
 app/controllers/teams_controller.rb       |  2 +-
 app/views/projects/_new_form.html.haml    | 18 +++++++++++++-----
 3 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/app/controllers/admin/teams_controller.rb b/app/controllers/admin/teams_controller.rb
index 335add0f57d..786957cbc59 100644
--- a/app/controllers/admin/teams_controller.rb
+++ b/app/controllers/admin/teams_controller.rb
@@ -47,7 +47,7 @@ class Admin::TeamsController < Admin::ApplicationController
   def destroy
     user_team.destroy
 
-    redirect_to admin_user_teams_path, notice: 'Team of users was successfully deleted.'
+    redirect_to admin_teams_path, notice: 'Team of users was successfully deleted.'
   end
 
   protected
diff --git a/app/controllers/teams_controller.rb b/app/controllers/teams_controller.rb
index e69a092c507..1ac0d5696b6 100644
--- a/app/controllers/teams_controller.rb
+++ b/app/controllers/teams_controller.rb
@@ -28,7 +28,7 @@ class TeamsController < ApplicationController
 
   def destroy
     user_team.destroy
-    redirect_to teams_path
+    redirect_to dashboard_path
   end
 
   def new
diff --git a/app/views/projects/_new_form.html.haml b/app/views/projects/_new_form.html.haml
index ba8f255558a..41a602147ca 100644
--- a/app/views/projects/_new_form.html.haml
+++ b/app/views/projects/_new_form.html.haml
@@ -15,12 +15,20 @@
         %span Namespace
       .input
         = f.select :namespace_id, namespaces_options(params[:namespace_id] || :current_user), {}, {class: 'chosen'}
-  - elsif current_user.can_create_group?
+
+  %p.padded
+    New projects are private by default. You choose who can see the project and commit to repository.
+  %hr
+
+  - if current_user.can_create_group?
     .clearfix
       .input.light
-        Need a group for several projects?
+        Need a group for several dependent projects?
         = link_to new_group_path, class: "btn very_small" do
           Create a group
-  %hr
-  %p.padded
-    New projects are private by default. You choose who can see the project and commit to repository.
+  - if current_user.can_create_team?
+    .clearfix
+      .input.light
+        Want to share a team between projects?
+        = link_to new_team_path, class: "btn very_small" do
+          Create a team
-- 
GitLab


From 1c88fbb3915e6d2efcac5cc2edb8d480f1112c75 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Fri, 25 Jan 2013 16:25:43 +0200
Subject: [PATCH 091/197] show new group, new team links in profile

---
 app/views/profiles/show.html.haml | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index 687463b672c..4e55922ef8d 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -47,6 +47,18 @@
               %p
                 You can login through #{@user.provider.titleize}!
                 = link_to "click here to change", account_profile_path
+          - if current_user.can_create_group?
+            %li
+              %p
+                Need a group for several dependent projects?
+                = link_to new_group_path, class: "btn very_small" do
+                  Create a group
+          - if current_user.can_create_team?
+            %li
+              %p
+                Want to share a team between projects?
+                = link_to new_team_path, class: "btn very_small" do
+                  Create a team
 
   .row
     .span7
@@ -79,7 +91,8 @@
       %fieldset
         %legend
           SSH public keys:
-          %strong.right= link_to current_user.keys.count, keys_path
+          %span.right
+            = link_to pluralize(current_user.keys.count, 'key'), keys_path
         .padded
           = link_to "Add Public Key", new_key_path, class: "btn small"
 
-- 
GitLab


From 74e329064abc1306132dd73dcb2e25221379f568 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Fri, 25 Jan 2013 16:36:14 +0200
Subject: [PATCH 092/197] teams refactoring and cleanup pt.1

---
 app/controllers/teams_controller.rb      | 10 ------
 app/models/project.rb                    |  2 +-
 app/views/layouts/user_team.html.haml    |  6 ++--
 app/views/profiles/show.html.haml        | 32 +++++++++----------
 app/views/teams/_team_head.html.haml     |  0
 app/views/teams/edit.html.haml           |  2 --
 app/views/teams/index.html.haml          | 38 ----------------------
 app/views/teams/issues.html.haml         |  2 --
 app/views/teams/members/edit.html.haml   |  4 +--
 app/views/teams/members/index.html.haml  |  2 --
 app/views/teams/members/new.html.haml    |  2 --
 app/views/teams/members/show.html.haml   |  2 --
 app/views/teams/merge_requests.html.haml |  2 --
 app/views/teams/projects/edit.html.haml  |  2 --
 app/views/teams/projects/index.html.haml | 40 +++++++++++++-----------
 app/views/teams/projects/new.html.haml   |  2 --
 app/views/teams/search.html.haml         | 11 -------
 app/views/teams/show.html.haml           |  2 --
 config/routes.rb                         |  4 ---
 19 files changed, 39 insertions(+), 126 deletions(-)
 delete mode 100644 app/views/teams/_team_head.html.haml
 delete mode 100644 app/views/teams/index.html.haml
 delete mode 100644 app/views/teams/search.html.haml

diff --git a/app/controllers/teams_controller.rb b/app/controllers/teams_controller.rb
index 1ac0d5696b6..ef66b77e232 100644
--- a/app/controllers/teams_controller.rb
+++ b/app/controllers/teams_controller.rb
@@ -64,16 +64,6 @@ class TeamsController < ApplicationController
     @issues = @issues.includes(:author, :project)
   end
 
-  def search
-    result = SearchContext.new(user_team.project_ids, params).execute
-
-    @projects       = result[:projects]
-    @merge_requests = result[:merge_requests]
-    @issues         = result[:issues]
-    @wiki_pages     = result[:wiki_pages]
-    @teams          = result[:teams]
-  end
-
   protected
 
   def projects
diff --git a/app/models/project.rb b/app/models/project.rb
index ba46fea2864..e521dfc93da 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -80,7 +80,7 @@ class Project < ActiveRecord::Base
   # Scopes
   scope :without_user, ->(user)  { where("id NOT IN (:ids)", ids: user.authorized_projects.map(&:id) ) }
   scope :not_in_group, ->(group) { where("id NOT IN (:ids)", ids: group.project_ids ) }
-  scope :without_team, ->(team) { where("id NOT IN (:ids)", ids: team.projects.map(&:id)) }
+  scope :without_team, ->(team) { team.projects.present? ? where("id NOT IN (:ids)", ids: team.projects.map(&:id)) : scoped  }
   scope :in_team, ->(team) { where("id IN (:ids)", ids: team.projects.map(&:id)) }
   scope :in_namespace, ->(namespace) { where(namespace_id: namespace.id) }
   scope :sorted_by_activity, ->() { order("(SELECT max(events.created_at) FROM events WHERE events.project_id = projects.id) DESC") }
diff --git a/app/views/layouts/user_team.html.haml b/app/views/layouts/user_team.html.haml
index 12fce837238..2d397e80905 100644
--- a/app/views/layouts/user_team.html.haml
+++ b/app/views/layouts/user_team.html.haml
@@ -19,18 +19,16 @@
             Merge Requests
             %span.count= MergeRequest.opened.of_user_team(@team).count
 
-        = nav_link(path: 'teams#search') do
-          = link_to "Search", search_team_path(@team)
-
         = nav_link(controller: [:members]) do
           = link_to team_members_path(@team), class: "team-tab tab" do
             Members
+            %span.count= @team.members.count
 
         - if can? current_user, :admin_user_team, @team
           = nav_link(controller: [:projects]) do
             = link_to team_projects_path(@team), class: "team-tab tab" do
-              %i.icon-briefcase
               Projects
+              %span.count= @team.projects.count
 
           = nav_link(path: 'teams#edit') do
             = link_to edit_team_path(@team), class: "stat-tab tab " do
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index 4e55922ef8d..7a3177f0efc 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -31,6 +31,20 @@
         .controls
           = f.text_field :email, class: "input-xlarge", required: true
           %span.help-block We also use email for avatar detection.
+      .control-group
+        = f.label :skype, class: "control-label"
+        .controls= f.text_field :skype, class: "input-xlarge"
+      .control-group
+        = f.label :linkedin, class: "control-label"
+        .controls= f.text_field :linkedin, class: "input-xlarge"
+      .control-group
+        = f.label :twitter, class: "control-label"
+        .controls= f.text_field :twitter, class: "input-xlarge"
+      .control-group
+        = f.label :bio, class: "control-label"
+        .controls
+          = f.text_area :bio, rows: 6, class: "input-xlarge", maxlength: 250
+          %span.help-block Tell us about yourself in fewer than 250 characters.
 
     .span5.right
       %fieldset.tips
@@ -59,24 +73,6 @@
                 Want to share a team between projects?
                 = link_to new_team_path, class: "btn very_small" do
                   Create a team
-
-  .row
-    .span7
-      .control-group
-        = f.label :skype, class: "control-label"
-        .controls= f.text_field :skype, class: "input-xlarge"
-      .control-group
-        = f.label :linkedin, class: "control-label"
-        .controls= f.text_field :linkedin, class: "input-xlarge"
-      .control-group
-        = f.label :twitter, class: "control-label"
-        .controls= f.text_field :twitter, class: "input-xlarge"
-      .control-group
-        = f.label :bio, class: "control-label"
-        .controls
-          = f.text_area :bio, rows: 6, class: "input-xlarge", maxlength: 250
-          %span.help-block Tell us about yourself in fewer than 250 characters.
-    .span5.right
       %fieldset
         %legend
           Personal projects:
diff --git a/app/views/teams/_team_head.html.haml b/app/views/teams/_team_head.html.haml
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/app/views/teams/edit.html.haml b/app/views/teams/edit.html.haml
index b2ceb2bdb21..60535330c4a 100644
--- a/app/views/teams/edit.html.haml
+++ b/app/views/teams/edit.html.haml
@@ -1,5 +1,3 @@
-= render "team_head"
-
 %h3.page_title= "Edit Team #{@team.name}"
 %hr
 = form_for @team, url: teams_path do |f|
diff --git a/app/views/teams/index.html.haml b/app/views/teams/index.html.haml
deleted file mode 100644
index 6610cdbd76e..00000000000
--- a/app/views/teams/index.html.haml
+++ /dev/null
@@ -1,38 +0,0 @@
-%h3.page_title
-  Teams
-  %small
-    list of all teams
-
-  = link_to 'New Team', new_team_path, class: "btn success small right"
-  %br
-
-= form_tag search_teams_path, method: :get, class: 'form-inline' do
-  = text_field_tag :name, params[:name], class: "xlarge"
-  = submit_tag "Search", class: "btn submit primary"
-
-%table.teams_list
-  %thead
-    %tr
-      %th
-        Name
-        %i.icon-sort-down
-      %th Path
-      %th Projects
-      %th Members
-      %th Owner
-      %th.cred Danger Zone!
-
-  - @teams.each do |team|
-    %tr
-      %td
-        %strong= link_to team.name, team_path(team)
-      %td= team.path
-      %td= link_to team.projects.count, team_projects_path(team)
-      %td= link_to team.members.count, team_members_path(team)
-      %td= link_to team.owner.name, team_member_path(team, team.owner)
-      %td.bgred
-        - if current_user.can?(:manage_user_team, team)
-          = link_to "Edit", edit_team_path(team), class: "btn small"
-          - if current_user.can?(:admin_user_team, team)
-            = link_to "Destroy", team_path(team), method: :delete, confirm: "You are shure?", class: "danger btn small"
-            &nbsp;
diff --git a/app/views/teams/issues.html.haml b/app/views/teams/issues.html.haml
index 3c17e85a115..4481e2eaa03 100644
--- a/app/views/teams/issues.html.haml
+++ b/app/views/teams/issues.html.haml
@@ -1,5 +1,3 @@
-= render "team_head"
-
 %h3.page_title
   Issues
   %small (in Team projects assigned to Team members)
diff --git a/app/views/teams/members/edit.html.haml b/app/views/teams/members/edit.html.haml
index 9caff799552..375880496ab 100644
--- a/app/views/teams/members/edit.html.haml
+++ b/app/views/teams/members/edit.html.haml
@@ -1,6 +1,4 @@
-= render "teams/team_head"
-
-%h3
+%h3.page_title
   Edit access #{@member.name} in #{@team.name} team
 
 %hr
diff --git a/app/views/teams/members/index.html.haml b/app/views/teams/members/index.html.haml
index 1628237ede0..90fa0aef35c 100644
--- a/app/views/teams/members/index.html.haml
+++ b/app/views/teams/members/index.html.haml
@@ -1,5 +1,3 @@
-= render "teams/team_head"
-
 %h3.page_title
   Team Members
   (#{@members.count})
diff --git a/app/views/teams/members/new.html.haml b/app/views/teams/members/new.html.haml
index 43f7c5d7b6f..274cdbadf29 100644
--- a/app/views/teams/members/new.html.haml
+++ b/app/views/teams/members/new.html.haml
@@ -1,5 +1,3 @@
-= render "teams/team_head"
-
 %h3.page_title
   Team: #{@team.name}
 
diff --git a/app/views/teams/members/show.html.haml b/app/views/teams/members/show.html.haml
index 03ef21be7a6..4008e8bd23e 100644
--- a/app/views/teams/members/show.html.haml
+++ b/app/views/teams/members/show.html.haml
@@ -1,5 +1,3 @@
-= render "teams/team_head"
-
 - allow_admin = can? current_user, :admin_project, @project
 - user = @team_member.user
 
diff --git a/app/views/teams/merge_requests.html.haml b/app/views/teams/merge_requests.html.haml
index f16331e1cdd..c9af529e113 100644
--- a/app/views/teams/merge_requests.html.haml
+++ b/app/views/teams/merge_requests.html.haml
@@ -1,5 +1,3 @@
-= render "team_head"
-
 %h3.page_title
   Merge Requests
   %small (authored by or assigned to Team members)
diff --git a/app/views/teams/projects/edit.html.haml b/app/views/teams/projects/edit.html.haml
index 056ee6852c1..b91a4982b81 100644
--- a/app/views/teams/projects/edit.html.haml
+++ b/app/views/teams/projects/edit.html.haml
@@ -1,5 +1,3 @@
-= render "teams/team_head"
-
 %h3
   Edit max access in #{@project.name} for #{@team.name} team
 
diff --git a/app/views/teams/projects/index.html.haml b/app/views/teams/projects/index.html.haml
index af6ffe5f3a4..493fc2c5c9e 100644
--- a/app/views/teams/projects/index.html.haml
+++ b/app/views/teams/projects/index.html.haml
@@ -1,5 +1,3 @@
-= render "teams/team_head"
-
 %h3.page_title
   Assigned projects (#{@team.projects.count})
   %small
@@ -13,22 +11,26 @@
 
 %hr
 
-%table.projects-table
-  %thead
-    %tr
-      %th Project name
-      %th Max access
-      - if current_user.can?(:admin_user_team, @team)
-        %th.span3
+- if @team.projects.present?
+  %table.projects-table
+    %thead
+      %tr
+        %th Project name
+        %th Max access
+        - if current_user.can?(:admin_user_team, @team)
+          %th.span3
+
+    - @team.projects.each do |project|
+      %tr.project
+        %td
+          = link_to project.name_with_namespace, project_path(project)
+        %td
+          %span= @team.human_max_project_access(project)
 
-  - @team.projects.each do |project|
-    %tr.project
-      %td
-        = link_to project.name_with_namespace, project_path(project)
-      %td
-        %span= @team.human_max_project_access(project)
+        - if current_user.can?(:admin_user_team, @team)
+          %td.bgred
+            = link_to 'Edit max access', edit_team_project_path(@team, project), class: "btn small"
+            = link_to 'Relegate', team_project_path(@team, project), confirm: 'Remove project from team and move to global namespace. Are you sure?', method: :delete, class: "btn danger small"
 
-      - if current_user.can?(:admin_user_team, @team)
-        %td.bgred
-          = link_to 'Edit max access', edit_team_project_path(@team, project), class: "btn small"
-          = link_to 'Relegate', team_project_path(@team, project), confirm: 'Remove project from team and move to global namespace. Are you sure?', method: :delete, class: "btn danger small"
+- else
+  %p.nothing_here_message This team has no projects yet
diff --git a/app/views/teams/projects/new.html.haml b/app/views/teams/projects/new.html.haml
index 000f62bb643..d57f56b2fee 100644
--- a/app/views/teams/projects/new.html.haml
+++ b/app/views/teams/projects/new.html.haml
@@ -1,5 +1,3 @@
-= render "teams/team_head"
-
 %h3.page_title
   Team: #{@team.name}
 
diff --git a/app/views/teams/search.html.haml b/app/views/teams/search.html.haml
deleted file mode 100644
index 5c357c5cfcb..00000000000
--- a/app/views/teams/search.html.haml
+++ /dev/null
@@ -1,11 +0,0 @@
-= render "team_head"
-
-= form_tag search_team_path(@team), method: :get, class: 'form-inline' do |f|
-  .padded
-    = label_tag :search do
-      %strong Looking for
-    .input
-      = search_field_tag :search, params[:search], placeholder: "issue 143", class: "input-xxlarge search-text-input", id: "dashboard_search"
-      = submit_tag 'Search', class: "btn primary wide"
-- if params[:search].present?
-  = render 'search/result'
diff --git a/app/views/teams/show.html.haml b/app/views/teams/show.html.haml
index 9acbf3e1ecf..d9257ab090c 100644
--- a/app/views/teams/show.html.haml
+++ b/app/views/teams/show.html.haml
@@ -1,5 +1,3 @@
-= render "team_head"
-
 .projects
   .activities.span8
     = link_to dashboard_path, class: 'btn very_small' do
diff --git a/config/routes.rb b/config/routes.rb
index ba350a70bfa..d67f0a47a00 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -142,15 +142,11 @@ Gitlab::Application.routes.draw do
     member do
       get :issues
       get :merge_requests
-      get :search
     end
     scope module: :teams do
       resources :members,   only: [:index, :new, :create, :edit, :update, :destroy]
       resources :projects,  only: [:index, :new, :create, :edit, :update, :destroy], constraints: { id: /[a-zA-Z.0-9_\-\/]+/ }
     end
-    collection do
-      get :search
-    end
   end
 
   resources :projects, constraints: { id: /[^\/]+/ }, only: [:new, :create]
-- 
GitLab


From 5f3df89c64f9b93ce9b8f6a791c6d6d51fd18624 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Fri, 25 Jan 2013 17:18:27 +0200
Subject: [PATCH 093/197] Fix teams + gitolite access

---
 lib/gitlab/user_team_manager.rb | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/lib/gitlab/user_team_manager.rb b/lib/gitlab/user_team_manager.rb
index 7d9a9bdf3f5..82bb5a05879 100644
--- a/lib/gitlab/user_team_manager.rb
+++ b/lib/gitlab/user_team_manager.rb
@@ -79,12 +79,10 @@ module Gitlab
         granted_access = max_teams_member_permission_in_project(user, project)
 
         project_team_user = UsersProject.find_by_user_id_and_project_id(user.id, project.id)
+        project_team_user.destroy if project_team_user.present?
 
-        if project_team_user.present?
-          project_team_user.destroy
-        end
-
-        if project_team_user.blank? && granted_access > 0
+        # project_team_user.project_access != granted_access
+        if granted_access > 0
           UsersProject.add_users_into_projects([project.id], [user.id], granted_access)
         end
       end
-- 
GitLab


From 639b0a8715074a166eb9ef4252e4f2b5ae5e2c84 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Fri, 25 Jan 2013 17:26:00 +0200
Subject: [PATCH 094/197] refactor add to team

---
 lib/gitlab/user_team_manager.rb | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/lib/gitlab/user_team_manager.rb b/lib/gitlab/user_team_manager.rb
index 82bb5a05879..a8ff4a3d94d 100644
--- a/lib/gitlab/user_team_manager.rb
+++ b/lib/gitlab/user_team_manager.rb
@@ -82,9 +82,7 @@ module Gitlab
         project_team_user.destroy if project_team_user.present?
 
         # project_team_user.project_access != granted_access
-        if granted_access > 0
-          UsersProject.add_users_into_projects([project.id], [user.id], granted_access)
-        end
+        project.team << [user, granted_access] if granted_access > 0
       end
 
       def max_teams_member_permission_in_project(user, project, teams = nil)
-- 
GitLab


From 8a65229b3548a421ca6e7c41a819b40d50f7e162 Mon Sep 17 00:00:00 2001
From: Ryan LaNeve <ryan.laneve@aciss.com>
Date: Thu, 24 Jan 2013 15:15:24 -0500
Subject: [PATCH 095/197] Updates project to process web hooks async via
 sidekiq.

A new queue of "project_web_hook" is used to process web hooks asynchronously, allowing each to succeed/fail (and be retried) independently.

(Basically, project web hooks now process the same as system hooks.)
---
 Procfile                               | 2 +-
 app/models/project.rb                  | 2 +-
 app/models/web_hook.rb                 | 4 ++++
 app/workers/project_web_hook_worker.rb | 9 +++++++++
 lib/tasks/sidekiq.rake                 | 2 +-
 5 files changed, 16 insertions(+), 3 deletions(-)
 create mode 100644 app/workers/project_web_hook_worker.rb

diff --git a/Procfile b/Procfile
index 21dfade1d8a..28a97ddafd7 100644
--- a/Procfile
+++ b/Procfile
@@ -1,2 +1,2 @@
 web: bundle exec unicorn_rails -p $PORT
-worker: bundle exec sidekiq -q post_receive,mailer,system_hook,common,default
+worker: bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,common,default
diff --git a/app/models/project.rb b/app/models/project.rb
index e521dfc93da..cb6986ce43d 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -340,7 +340,7 @@ class Project < ActiveRecord::Base
   end
 
   def execute_hooks(data)
-    hooks.each { |hook| hook.execute(data) }
+    hooks.each { |hook| hook.async_execute(data) }
   end
 
   def execute_services(data)
diff --git a/app/models/web_hook.rb b/app/models/web_hook.rb
index df58fa93b7e..efa27f31982 100644
--- a/app/models/web_hook.rb
+++ b/app/models/web_hook.rb
@@ -34,4 +34,8 @@ class WebHook < ActiveRecord::Base
                    basic_auth: {username: parsed_url.user, password: parsed_url.password})
     end
   end
+
+  def async_execute(data)
+    Sidekiq::Client.enqueue(ProjectWebHookWorker, id, data)
+  end
 end
diff --git a/app/workers/project_web_hook_worker.rb b/app/workers/project_web_hook_worker.rb
new file mode 100644
index 00000000000..9f9b9b1df5f
--- /dev/null
+++ b/app/workers/project_web_hook_worker.rb
@@ -0,0 +1,9 @@
+class ProjectWebHookWorker
+  include Sidekiq::Worker
+
+  sidekiq_options queue: :project_web_hook
+
+  def perform(hook_id, data)
+    WebHook.find(hook_id).execute data
+  end
+end
diff --git a/lib/tasks/sidekiq.rake b/lib/tasks/sidekiq.rake
index 01da919d7f8..0d2ec6f332c 100644
--- a/lib/tasks/sidekiq.rake
+++ b/lib/tasks/sidekiq.rake
@@ -6,7 +6,7 @@ namespace :sidekiq do
 
   desc "GITLAB | Start sidekiq"
   task :start do
-    run "nohup bundle exec sidekiq -q post_receive,mailer,system_hook,common,default -e #{Rails.env} -P #{pidfile} >> #{Rails.root.join("log", "sidekiq.log")} 2>&1 &"
+    run "nohup bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,common,default -e #{Rails.env} -P #{pidfile} >> #{Rails.root.join("log", "sidekiq.log")} 2>&1 &"
   end
 
   def pidfile
-- 
GitLab


From 561a0e3a4a53030ef465c1ce729aba2e5def9964 Mon Sep 17 00:00:00 2001
From: Sato Hiroyuki <sathiroyuki@gmail.com>
Date: Sat, 26 Jan 2013 00:52:11 +0900
Subject: [PATCH 096/197] Fix not showing tooltip on network graph

---
 vendor/assets/javascripts/branch-graph.js | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/vendor/assets/javascripts/branch-graph.js b/vendor/assets/javascripts/branch-graph.js
index af3b572a4e3..93849c79e80 100644
--- a/vendor/assets/javascripts/branch-graph.js
+++ b/vendor/assets/javascripts/branch-graph.js
@@ -65,15 +65,15 @@
 
   BranchGraph.prototype.buildGraph = function(){
     var graphWidth = $(this.element).width()
-      , ch = this.mspace * 20 + 20
-      , cw = Math.max(graphWidth, this.mtime * 20 + 20)
+      , ch = this.mspace * 20 + 100
+      , cw = Math.max(graphWidth, this.mtime * 20 + 260)
       , r = Raphael(this.element.get(0), cw, ch)
       , top = r.set()
       , cuday = 0
       , cumonth = ""
       , offsetX = 20
       , offsetY = 60
-      , barWidth = Math.max(graphWidth, this.dayCount * 20 + 80);
+      , barWidth = Math.max(graphWidth, this.dayCount * 20 + 320);
     
     this.raphael = r;
     
-- 
GitLab


From 6efda51cc5caad07b6a01d293daf913eec01901f Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Fri, 25 Jan 2013 21:20:15 +0400
Subject: [PATCH 097/197] fix edit project members access link and page fixes
 refs #2745

---
 app/controllers/admin/projects/application_controller.rb | 2 +-
 app/controllers/admin/projects/members_controller.rb     | 2 +-
 app/views/admin/users/show.html.haml                     | 4 ++--
 config/routes.rb                                         | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/app/controllers/admin/projects/application_controller.rb b/app/controllers/admin/projects/application_controller.rb
index 0f3da998666..b3f1539f387 100644
--- a/app/controllers/admin/projects/application_controller.rb
+++ b/app/controllers/admin/projects/application_controller.rb
@@ -6,6 +6,6 @@ class Admin::Projects::ApplicationController < Admin::ApplicationController
   protected
 
   def project
-    @project ||= Project.find_by_path(params[:project_id])
+    @project ||= Project.find_with_namespace(params[:project_id])
   end
 end
diff --git a/app/controllers/admin/projects/members_controller.rb b/app/controllers/admin/projects/members_controller.rb
index 5c20c0717ed..d9c0d572bb1 100644
--- a/app/controllers/admin/projects/members_controller.rb
+++ b/app/controllers/admin/projects/members_controller.rb
@@ -22,7 +22,7 @@ class Admin::Projects::MembersController < Admin::Projects::ApplicationControlle
   private
 
   def team_member
-    @member ||= project.users.find(params[:id])
+    @member ||= project.users.find_by_username(params[:id])
   end
 
   def team_member_relation
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index a3be6614136..a69a8ca9afe 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -123,5 +123,5 @@
       %tr
         %td= link_to project.name_with_namespace, admin_project_path(project)
         %td= tm.project_access_human
-        %td= link_to 'Edit Access', edit_admin_team_member_path(tm), class: "btn small"
-        %td= link_to 'Remove from team', admin_team_member_path(tm), confirm: 'Are you sure?', method: :delete, class: "btn small danger"
+        %td= link_to 'Edit Access', edit_admin_project_member_path(project.path_with_namespace, tm.user.username), class: "btn small"
+        %td= link_to 'Remove from team', admin_project_member_path(project.path_with_namespace, tm.user.username), confirm: 'Are you sure?', method: :delete, class: "btn small danger"
diff --git a/config/routes.rb b/config/routes.rb
index d67f0a47a00..4a66e9f11bf 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -84,7 +84,7 @@ Gitlab::Application.routes.draw do
         get :team
         put :team_update
       end
-      scope module: :projects, constraints: { id: /[^\/]+/ } do
+      scope module: :projects, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ } do
         resources :members, only: [:edit, :update, :destroy]
       end
     end
-- 
GitLab


From f225ff86743fca4c6957790d78b66ba663d5b40d Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Fri, 25 Jan 2013 22:33:49 +0400
Subject: [PATCH 098/197] Update user finding (by username) in admin teams
 members controller

---
 app/controllers/admin/teams/members_controller.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/controllers/admin/teams/members_controller.rb b/app/controllers/admin/teams/members_controller.rb
index 139b82ab66c..e7dbcad568f 100644
--- a/app/controllers/admin/teams/members_controller.rb
+++ b/app/controllers/admin/teams/members_controller.rb
@@ -36,6 +36,6 @@ class Admin::Teams::MembersController < Admin::Teams::ApplicationController
   protected
 
   def team_member
-    @member ||= user_team.members.find(params[:id])
+    @member ||= user_team.members.find_by_username(params[:id])
   end
 end
-- 
GitLab


From e1679d20c7f3e51ef63a5730543914bc9e1f1ae2 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Fri, 25 Jan 2013 22:34:49 +0400
Subject: [PATCH 099/197] Update user finding (by username) in teams_members
 (project team) controller

---
 app/controllers/team_members_controller.rb | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/controllers/team_members_controller.rb b/app/controllers/team_members_controller.rb
index 7e4c8792b50..18d4ae3ac96 100644
--- a/app/controllers/team_members_controller.rb
+++ b/app/controllers/team_members_controller.rb
@@ -39,7 +39,7 @@ class TeamMembersController < ProjectResourceController
   end
 
   def destroy
-    @user_project_relation = project.users_projects.find_by_user_id(params[:id])
+    @user_project_relation = project.users_projects.find_by_user_id(member)
     @user_project_relation.destroy
 
     respond_to do |format|
@@ -59,6 +59,6 @@ class TeamMembersController < ProjectResourceController
   protected
 
   def member
-    @member ||= User.find(params[:id])
+    @member ||= User.find_by_username(params[:id])
   end
 end
-- 
GitLab


From df64bdffdf274d0e4d96ea8c58046370b201f1e2 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Fri, 25 Jan 2013 22:35:31 +0400
Subject: [PATCH 100/197] Update user finding (by username) in teams members
 (team of users) controller

---
 app/controllers/teams/members_controller.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/controllers/teams/members_controller.rb b/app/controllers/teams/members_controller.rb
index c41d5d7abe6..db218b8ca5e 100644
--- a/app/controllers/teams/members_controller.rb
+++ b/app/controllers/teams/members_controller.rb
@@ -43,7 +43,7 @@ class Teams::MembersController < Teams::ApplicationController
   protected
 
   def team_member
-    @member ||= user_team.members.find(params[:id])
+    @member ||= user_team.members.find_by_username(params[:id])
   end
 
 end
-- 
GitLab


From 916165dfc4591145ebddee063857e85414b813f6 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Fri, 25 Jan 2013 22:35:58 +0400
Subject: [PATCH 101/197] username is default param to User

---
 app/models/user.rb | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/app/models/user.rb b/app/models/user.rb
index 29f262968d5..5a95deec53d 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -143,6 +143,11 @@ class User < ActiveRecord::Base
   #
   # Instance methods
   #
+
+  def to_param
+    username
+  end
+
   def generate_password
     if self.force_random_password
       self.password = self.password_confirmation = Devise.friendly_token.first(8)
-- 
GitLab


From ef85202f71facf1cf84b07d719ac7ab6d0071cbc Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Fri, 25 Jan 2013 22:37:38 +0400
Subject: [PATCH 102/197] fix links in admin group view page (user links)

---
 app/views/admin/groups/show.html.haml | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml
index 0a25b125905..e347f916c4f 100644
--- a/app/views/admin/groups/show.html.haml
+++ b/app/views/admin/groups/show.html.haml
@@ -72,16 +72,17 @@
           %th Users
           %th Project Access:
 
-      - @group.users.each do |u|
-        %tr{class: "user_#{u.id}"}
-          %td.name= link_to u.name, admin_user_path(u)
+      - @group.users.each do |user|
+        - next unless user
+        %tr{class: "user_#{user.id}"}
+          %td.name= link_to user.name, admin_user_path(user)
           %td.projects_access
-            - u.authorized_projects.in_namespace(@group).each do |project|
-              - u_p = u.users_projects.in_project(project).first
+            - user.authorized_projects.in_namespace(@group).each do |project|
+              - u_p = user.users_projects.in_project(project).first
               - next unless u_p
               %span
-                = project.name
-                = link_to "(#{ u_p.project_access_human })", edit_admin_team_member_path(u_p)
+                = project.name_with_namespace
+                = link_to "(#{ u_p.project_access_human })", edit_admin_project_member_path(project, user)
       %tr
         %td.input= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name), multiple: true, data: {placeholder: 'Select users'}, class: 'chosen span5'
         %td= select_tag :project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3"}
-- 
GitLab


From c5cbbea82e5f1ce07d5928e409fe78a80b1b7094 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Fri, 25 Jan 2013 22:38:24 +0400
Subject: [PATCH 103/197] rewrite admin users controller (use 1 variable and
 find by username)

---
 app/controllers/admin/users_controller.rb | 44 +++++++++++------------
 1 file changed, 20 insertions(+), 24 deletions(-)

diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index 659dd2f2ab0..0c7f97dd72c 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -7,25 +7,21 @@ class Admin::UsersController < Admin::ApplicationController
   end
 
   def show
-    @admin_user = User.find(params[:id])
-
-    @projects = if @admin_user.authorized_projects.empty?
+    projects = if admin_user.authorized_projects.empty?
                Project
              else
-               Project.without_user(@admin_user)
+               Project.without_user(admin_user)
              end.all
   end
 
   def team_update
-    @admin_user = User.find(params[:id])
-
     UsersProject.add_users_into_projects(
       params[:project_ids],
-      [@admin_user.id],
+      [admin_user.id],
       params[:project_access]
     )
 
-    redirect_to [:admin, @admin_user], notice: 'Teams were successfully updated.'
+    redirect_to [:admin, admin_user], notice: 'Teams were successfully updated.'
   end
 
 
@@ -34,13 +30,11 @@ class Admin::UsersController < Admin::ApplicationController
   end
 
   def edit
-    @admin_user = User.find(params[:id])
+    admin_user
   end
 
   def block
-    @admin_user = User.find(params[:id])
-
-    if @admin_user.block
+    if admin_user.block
       redirect_to :back, alert: "Successfully blocked"
     else
       redirect_to :back, alert: "Error occured. User was not blocked"
@@ -48,9 +42,7 @@ class Admin::UsersController < Admin::ApplicationController
   end
 
   def unblock
-    @admin_user = User.find(params[:id])
-
-    if @admin_user.update_attribute(:blocked, false)
+    if admin_user.update_attribute(:blocked, false)
       redirect_to :back, alert: "Successfully unblocked"
     else
       redirect_to :back, alert: "Error occured. User was not unblocked"
@@ -82,30 +74,34 @@ class Admin::UsersController < Admin::ApplicationController
       params[:user].delete(:password_confirmation)
     end
 
-    @admin_user = User.find(params[:id])
-    @admin_user.admin = (admin && admin.to_i > 0)
+    admin_user.admin = (admin && admin.to_i > 0)
 
     respond_to do |format|
-      if @admin_user.update_attributes(params[:user], as: :admin)
-        format.html { redirect_to [:admin, @admin_user], notice: 'User was successfully updated.' }
+      if admin_user.update_attributes(params[:user], as: :admin)
+        format.html { redirect_to [:admin, admin_user], notice: 'User was successfully updated.' }
         format.json { head :ok }
       else
         format.html { render action: "edit" }
-        format.json { render json: @admin_user.errors, status: :unprocessable_entity }
+        format.json { render json: admin_user.errors, status: :unprocessable_entity }
       end
     end
   end
 
   def destroy
-    @admin_user = User.find(params[:id])
-    if @admin_user.personal_projects.count > 0
+    if admin_user.personal_projects.count > 0
       redirect_to admin_users_path, alert: "User is a project owner and can't be removed." and return
     end
-    @admin_user.destroy
+    admin_user.destroy
 
     respond_to do |format|
-      format.html { redirect_to admin_users_url }
+      format.html { redirect_to admin_users_path }
       format.json { head :ok }
     end
   end
+
+  protected
+
+  def admin_user
+    @admin_user ||= User.find_by_username(params[:id])
+  end
 end
-- 
GitLab


From 75a02e090a436aac2a182f2b56dfda4719cbd5b8 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Fri, 25 Jan 2013 23:19:31 +0400
Subject: [PATCH 104/197] simple cleanup code %)

---
 app/views/admin/users/show.html.haml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index a69a8ca9afe..d9d720dad76 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -123,5 +123,5 @@
       %tr
         %td= link_to project.name_with_namespace, admin_project_path(project)
         %td= tm.project_access_human
-        %td= link_to 'Edit Access', edit_admin_project_member_path(project.path_with_namespace, tm.user.username), class: "btn small"
-        %td= link_to 'Remove from team', admin_project_member_path(project.path_with_namespace, tm.user.username), confirm: 'Are you sure?', method: :delete, class: "btn small danger"
+        %td= link_to 'Edit Access', edit_admin_project_member_path(project, tm.user), class: "btn small"
+        %td= link_to 'Remove from team', admin_project_member_path(project, tm.user), confirm: 'Are you sure?', method: :delete, class: "btn small danger"
-- 
GitLab


From 45917935ef38cdb35b152dc8a04b37efb92f33f0 Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Sat, 26 Jan 2013 00:37:55 +0400
Subject: [PATCH 105/197] fix copied code. Add assign projects button.

---
 app/views/teams/_projects.html.haml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/app/views/teams/_projects.html.haml b/app/views/teams/_projects.html.haml
index 95202bc6ee5..4d99d5c259b 100644
--- a/app/views/teams/_projects.html.haml
+++ b/app/views/teams/_projects.html.haml
@@ -3,11 +3,11 @@
     Projects
     %small
       (#{projects.count})
-    - if can? current_user, :manage_group, @group
+    - if can? current_user, :manage_user_team, @team
       %span.right
-        = link_to new_project_path(namespace_id: @group.id), class: "btn very_small info" do
+        = link_to new_team_project_path(@team), class: "btn very_small info" do
           %i.icon-plus
-          New Project
+          Assign Project
   %ul.well-list
     - if projects.blank?
       %p.nothing_here_message This team has no projects yet
-- 
GitLab


From b280c2f361ab2c22166523a3123c378d69fdf4df Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Sat, 26 Jan 2013 00:38:21 +0400
Subject: [PATCH 106/197] Edit create new team text

---
 app/views/projects/_new_form.html.haml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/views/projects/_new_form.html.haml b/app/views/projects/_new_form.html.haml
index 41a602147ca..5f7348d47a1 100644
--- a/app/views/projects/_new_form.html.haml
+++ b/app/views/projects/_new_form.html.haml
@@ -29,6 +29,6 @@
   - if current_user.can_create_team?
     .clearfix
       .input.light
-        Want to share a team between projects?
+        Want to share a project between team?
         = link_to new_team_path, class: "btn very_small" do
           Create a team
-- 
GitLab


From 890e774ddc7bea953daddcce9f5677fafc30896a Mon Sep 17 00:00:00 2001
From: Andrey Kumanyaev <me@zzet.org>
Date: Sat, 26 Jan 2013 01:14:36 +0400
Subject: [PATCH 107/197] Display actual user role (admin or not) in team
 members list

---
 app/views/teams/members/_show.html.haml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/views/teams/members/_show.html.haml b/app/views/teams/members/_show.html.haml
index dbbb382d97f..740d5a498c0 100644
--- a/app/views/teams/members/_show.html.haml
+++ b/app/views/teams/members/_show.html.haml
@@ -18,7 +18,7 @@
         .left.span2
           %span
             Admin access
-            = check_box_tag :group_admin
+            = check_box_tag :group_admin, true, @team.admin?(user)
       .right
         - if current_user == user
           %span.btn.disabled This is you!
-- 
GitLab


From 0125b74b3cbdb7df3b029cd2373b96ca3905c16a Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sat, 26 Jan 2013 12:08:34 +0200
Subject: [PATCH 108/197] Fix application crashes after #2772

---
 app/controllers/admin/users_controller.rb | 11 +++++------
 config/routes.rb                          |  2 +-
 2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index 0c7f97dd72c..ed421624295 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -1,4 +1,6 @@
 class Admin::UsersController < Admin::ApplicationController
+  before_filter :admin_user, only: [:show, :edit, :update, :destroy]
+
   def index
     @admin_users = User.scoped
     @admin_users = @admin_users.filter(params[:filter])
@@ -7,11 +9,8 @@ class Admin::UsersController < Admin::ApplicationController
   end
 
   def show
-    projects = if admin_user.authorized_projects.empty?
-               Project
-             else
-               Project.without_user(admin_user)
-             end.all
+    @projects = Project.scoped
+    @projects = @projects.without_user(admin_user) if admin_user.authorized_projects.empty?
   end
 
   def team_update
@@ -102,6 +101,6 @@ class Admin::UsersController < Admin::ApplicationController
   protected
 
   def admin_user
-    @admin_user ||= User.find_by_username(params[:id])
+    @admin_user ||= User.find_by_username!(params[:id])
   end
 end
diff --git a/config/routes.rb b/config/routes.rb
index 4a66e9f11bf..5ae4c8087c7 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -49,7 +49,7 @@ Gitlab::Application.routes.draw do
   # Admin Area
   #
   namespace :admin do
-    resources :users do
+    resources :users, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ } do
       member do
         put :team_update
         put :block
-- 
GitLab


From b68bba441eaa9baf76dc2c0f9532615aaec3137b Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sat, 26 Jan 2013 12:15:38 +0200
Subject: [PATCH 109/197] Fix projects in admin -> user -> show

---
 app/controllers/admin/users_controller.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index ed421624295..400e44e086d 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -10,7 +10,7 @@ class Admin::UsersController < Admin::ApplicationController
 
   def show
     @projects = Project.scoped
-    @projects = @projects.without_user(admin_user) if admin_user.authorized_projects.empty?
+    @projects = @projects.without_user(admin_user) if admin_user.authorized_projects.present?
   end
 
   def team_update
-- 
GitLab


From 6ab6c55de5516ac636b5ca1147c1d1f81831c599 Mon Sep 17 00:00:00 2001
From: Alex Denisov <1101.debian@gmail.com>
Date: Sat, 26 Jan 2013 14:22:48 +0000
Subject: [PATCH 110/197] Missed environment added to 'Try fixing it' block

---
 lib/tasks/gitlab/check.rake | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake
index 826b78ec5b1..1ca723f271a 100644
--- a/lib/tasks/gitlab/check.rake
+++ b/lib/tasks/gitlab/check.rake
@@ -169,7 +169,7 @@ namespace :gitlab do
       else
         puts "no".red
         try_fixing_it(
-          sudo_gitlab("bundle exec rake db:migrate")
+          sudo_gitlab("bundle exec rake db:migrate RAILS_ENV=production")
         )
         fix_and_rerun
       end
@@ -194,7 +194,7 @@ namespace :gitlab do
         else
           puts "no".red
           try_fixing_it(
-            sudo_gitlab("bundle exec rake gitlab:satellites:create"),
+            sudo_gitlab("bundle exec rake gitlab:satellites:create RAILS_ENV=production"),
             "If necessary, remove the tmp/repo_satellites directory ...",
             "... and rerun the above command"
           )
@@ -789,7 +789,7 @@ namespace :gitlab do
         else
           puts "wrong or missing".red
           try_fixing_it(
-            sudo_gitlab("bundle exec rake gitlab:gitolite:update_repos")
+            sudo_gitlab("bundle exec rake gitlab:gitolite:update_repos RAILS_ENV=production")
           )
           for_more_information(
             "doc/raketasks/maintenance.md"
@@ -895,7 +895,7 @@ namespace :gitlab do
       else
         puts "no".red
         try_fixing_it(
-          sudo_gitlab("bundle exec rake sidekiq:start")
+          sudo_gitlab("bundle exec rake sidekiq:start RAILS_ENV=production")
         )
         for_more_information(
           see_installation_guide_section("Install Init Script"),
-- 
GitLab


From bd3b677b86d7c76788420e94862836343ac5c841 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sun, 27 Jan 2013 12:34:27 +0200
Subject: [PATCH 111/197] Add projects page to dashboard. Remove projects
 pagination on dashboard

---
 app/controllers/dashboard_controller.rb | 32 +++++++++--------
 app/views/dashboard/_projects.html.haml | 13 +++----
 app/views/dashboard/projects.html.haml  | 46 +++++++++++++++++++++++++
 app/views/layouts/application.html.haml |  3 ++
 config/routes.rb                        |  1 +
 5 files changed, 71 insertions(+), 24 deletions(-)
 create mode 100644 app/views/dashboard/projects.html.haml

diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
index 13b7f02fdb8..13d8000873b 100644
--- a/app/controllers/dashboard_controller.rb
+++ b/app/controllers/dashboard_controller.rb
@@ -1,26 +1,15 @@
 class DashboardController < ApplicationController
   respond_to :html
 
-  before_filter :projects
+  before_filter :load_projects
   before_filter :event_filter, only: :index
 
   def index
     @groups = current_user.authorized_groups
-
     @has_authorized_projects = @projects.count > 0
-
-    @projects = case params[:scope]
-                when 'personal' then
-                  @projects.personal(current_user)
-                when 'joined' then
-                  @projects.joined(current_user)
-                else
-                  @projects
-                end
-
     @teams = current_user.authorized_teams
-
-    @projects = @projects.page(params[:page]).per(30)
+    @projects_count = @projects.count
+    @projects = @projects.limit(20)
 
     @events = Event.in_projects(current_user.authorized_projects.pluck(:id))
     @events = @event_filter.apply_filter(@events)
@@ -35,6 +24,19 @@ class DashboardController < ApplicationController
     end
   end
 
+  def projects
+    @projects = case params[:scope]
+                when 'personal' then
+                  @projects.personal(current_user)
+                when 'joined' then
+                  @projects.joined(current_user)
+                else
+                  @projects
+                end
+
+    @projects = @projects.page(params[:page]).per(30)
+  end
+
   # Get authored or assigned open merge requests
   def merge_requests
     @merge_requests = current_user.cared_merge_requests
@@ -57,7 +59,7 @@ class DashboardController < ApplicationController
 
   protected
 
-  def projects
+  def load_projects
     @projects = current_user.authorized_projects.sorted_by_activity
   end
 
diff --git a/app/views/dashboard/_projects.html.haml b/app/views/dashboard/_projects.html.haml
index 6c1304ee4a8..d7273fdca34 100644
--- a/app/views/dashboard/_projects.html.haml
+++ b/app/views/dashboard/_projects.html.haml
@@ -2,19 +2,12 @@
   %h5.title
     Projects
     %small
-      (#{projects.total_count})
+      (#{@projects_count})
     - if current_user.can_create_project?
       %span.right
         = link_to new_project_path, class: "btn very_small info" do
           %i.icon-plus
           New Project
-  %ul.nav.nav-projects-tabs
-    = nav_tab :scope, nil do
-      = link_to "All", dashboard_path
-    = nav_tab :scope, 'personal' do
-      = link_to "Personal", dashboard_path(scope: 'personal')
-    = nav_tab :scope, 'joined' do
-      = link_to "Joined", dashboard_path(scope: 'joined')
 
   %ul.well-list
     - projects.each do |project|
@@ -33,4 +26,6 @@
     - if projects.blank?
       %li
         %h3.nothing_here_message There are no projects here.
-  .bottom= paginate projects, theme: "gitlab"
+    - if @projects_count > 20
+      %li.bottom
+        %strong= link_to "show all projects", dashboard_projects_path
diff --git a/app/views/dashboard/projects.html.haml b/app/views/dashboard/projects.html.haml
new file mode 100644
index 00000000000..cfbb332a91a
--- /dev/null
+++ b/app/views/dashboard/projects.html.haml
@@ -0,0 +1,46 @@
+%h3.page_title
+  Projects
+  %span
+    (#{@projects.total_count})
+  - if current_user.can_create_project?
+    %span.right
+      = link_to new_project_path, class: "btn very_small info" do
+        %i.icon-plus
+        New Project
+
+%hr
+.row
+  .span3
+    %ul.nav.nav-pills.nav-stacked
+      = nav_tab :scope, nil do
+        = link_to "All", dashboard_projects_path
+      = nav_tab :scope, 'personal' do
+        = link_to "Personal", dashboard_projects_path(scope: 'personal')
+      = nav_tab :scope, 'joined' do
+        = link_to "Joined", dashboard_projects_path(scope: 'joined')
+
+  .span9
+    = form_tag dashboard_projects_path, method: 'get' do
+      %fieldset.dashboard-search-filter
+        = hidden_field_tag "scope", params[:scope]
+        = search_field_tag "search", params[:search], { placeholder: 'Search', class: 'left input-xxlarge' }
+        = button_tag type: 'submit', class: 'btn' do
+          %i.icon-search
+
+    %ul.well-list
+      - @projects.each do |project|
+        %li
+          = link_to project_path(project), class: dom_class(project) do
+            - if project.namespace
+              = project.namespace.human_name
+              \/
+            %strong.well-title
+              = truncate(project.name, length: 25)
+            %span.right.light
+              %strong Last activity:
+              %span= project_last_activity(project)
+      - if @projects.blank?
+        %li
+          %h3.nothing_here_message There are no projects here.
+    .bottom= paginate @projects, theme: "gitlab"
+
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index 88da5c98c78..0a83be3fd2e 100644
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -8,6 +8,9 @@
       %ul.main_menu
         = nav_link(path: 'dashboard#index', html_options: {class: 'home'}) do
           = link_to "Home", root_path, title: "Home"
+        = nav_link(path: 'dashboard#projects') do
+          = link_to dashboard_projects_path do
+            Projects
         = nav_link(path: 'dashboard#issues') do
           = link_to dashboard_issues_path do
             Issues
diff --git a/config/routes.rb b/config/routes.rb
index 5ae4c8087c7..6bbcf49ab5c 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -119,6 +119,7 @@ Gitlab::Application.routes.draw do
   # Dashboard Area
   #
   get "dashboard"                => "dashboard#index"
+  get "dashboard/projects"       => "dashboard#projects"
   get "dashboard/issues"         => "dashboard#issues"
   get "dashboard/merge_requests" => "dashboard#merge_requests"
 
-- 
GitLab


From 6b01196fb238cb921056ecd8d1572ff2874bf912 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sun, 27 Jan 2013 12:56:20 +0200
Subject: [PATCH 112/197] Dashboard to resource

---
 app/controllers/dashboard_controller.rb       |  4 +--
 app/helpers/dashboard_helper.rb               |  4 +--
 app/views/dashboard/_projects.html.haml       |  2 +-
 app/views/dashboard/issues.atom.builder       |  6 ++--
 app/views/dashboard/projects.html.haml        | 34 ++++++++++++-------
 .../{index.atom.builder => show.atom.builder} |  0
 .../{index.html.haml => show.html.haml}       |  0
 .../dashboard/{index.js.haml => show.js.haml} |  0
 app/views/groups/issues.atom.builder          |  6 ++--
 app/views/layouts/application.html.haml       |  8 ++---
 config/routes.rb                              | 13 ++++---
 11 files changed, 45 insertions(+), 32 deletions(-)
 rename app/views/dashboard/{index.atom.builder => show.atom.builder} (100%)
 rename app/views/dashboard/{index.html.haml => show.html.haml} (100%)
 rename app/views/dashboard/{index.js.haml => show.js.haml} (100%)

diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
index 13d8000873b..f320e819e26 100644
--- a/app/controllers/dashboard_controller.rb
+++ b/app/controllers/dashboard_controller.rb
@@ -2,9 +2,9 @@ class DashboardController < ApplicationController
   respond_to :html
 
   before_filter :load_projects
-  before_filter :event_filter, only: :index
+  before_filter :event_filter, only: :show
 
-  def index
+  def show
     @groups = current_user.authorized_groups
     @has_authorized_projects = @projects.count > 0
     @teams = current_user.authorized_teams
diff --git a/app/helpers/dashboard_helper.rb b/app/helpers/dashboard_helper.rb
index 0baa5b4108e..c759dffa16e 100644
--- a/app/helpers/dashboard_helper.rb
+++ b/app/helpers/dashboard_helper.rb
@@ -9,9 +9,9 @@ module DashboardHelper
 
     case entity
     when 'issue' then
-      dashboard_issues_path(options)
+      issues_dashboard_path(options)
     when 'merge_request'
-      dashboard_merge_requests_path(options)
+      merge_requests_dashboard_path(options)
     end
   end
 
diff --git a/app/views/dashboard/_projects.html.haml b/app/views/dashboard/_projects.html.haml
index d7273fdca34..f2acd2b0b0c 100644
--- a/app/views/dashboard/_projects.html.haml
+++ b/app/views/dashboard/_projects.html.haml
@@ -28,4 +28,4 @@
         %h3.nothing_here_message There are no projects here.
     - if @projects_count > 20
       %li.bottom
-        %strong= link_to "show all projects", dashboard_projects_path
+        %strong= link_to "show all projects", projects_dashboard_path
diff --git a/app/views/dashboard/issues.atom.builder b/app/views/dashboard/issues.atom.builder
index 28bdc5ed814..0f0f3466e92 100644
--- a/app/views/dashboard/issues.atom.builder
+++ b/app/views/dashboard/issues.atom.builder
@@ -1,9 +1,9 @@
 xml.instruct!
 xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do
   xml.title   "#{current_user.name} issues"
-  xml.link    :href => dashboard_issues_url(:atom, :private_token => current_user.private_token), :rel => "self", :type => "application/atom+xml"
-  xml.link    :href => dashboard_issues_url(:private_token => current_user.private_token), :rel => "alternate", :type => "text/html"
-  xml.id      dashboard_issues_url(:private_token => current_user.private_token)
+  xml.link    :href => issues_dashboard_url(:atom, :private_token => current_user.private_token), :rel => "self", :type => "application/atom+xml"
+  xml.link    :href => issues_dashboard_url(:private_token => current_user.private_token), :rel => "alternate", :type => "text/html"
+  xml.id      issues_dashboard_url(:private_token => current_user.private_token)
   xml.updated @issues.first.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") if @issues.any?
 
   @issues.each do |issue|
diff --git a/app/views/dashboard/projects.html.haml b/app/views/dashboard/projects.html.haml
index cfbb332a91a..e6c710e68e9 100644
--- a/app/views/dashboard/projects.html.haml
+++ b/app/views/dashboard/projects.html.haml
@@ -8,19 +8,20 @@
         %i.icon-plus
         New Project
 
+
 %hr
 .row
   .span3
     %ul.nav.nav-pills.nav-stacked
       = nav_tab :scope, nil do
-        = link_to "All", dashboard_projects_path
+        = link_to "All", projects_dashboard_path
       = nav_tab :scope, 'personal' do
-        = link_to "Personal", dashboard_projects_path(scope: 'personal')
+        = link_to "Personal", projects_dashboard_path(scope: 'personal')
       = nav_tab :scope, 'joined' do
-        = link_to "Joined", dashboard_projects_path(scope: 'joined')
+        = link_to "Joined", projects_dashboard_path(scope: 'joined')
 
   .span9
-    = form_tag dashboard_projects_path, method: 'get' do
+    = form_tag projects_dashboard_path, method: 'get' do
       %fieldset.dashboard-search-filter
         = hidden_field_tag "scope", params[:scope]
         = search_field_tag "search", params[:search], { placeholder: 'Search', class: 'left input-xxlarge' }
@@ -29,16 +30,25 @@
 
     %ul.well-list
       - @projects.each do |project|
-        %li
-          = link_to project_path(project), class: dom_class(project) do
-            - if project.namespace
-              = project.namespace.human_name
-              \/
-            %strong.well-title
-              = truncate(project.name, length: 25)
-            %span.right.light
+        %li.clearfix
+          .left
+            = link_to project_path(project), class: dom_class(project) do
+              - if project.namespace
+                = project.namespace.human_name
+                \/
+              %strong.well-title
+                = truncate(project.name, length: 25)
+            %br
+            %small.light
               %strong Last activity:
               %span= project_last_activity(project)
+          .right.light
+            - if project.owner == current_user
+              %i.icon-wrench
+            - tm = project.team.get_tm(current_user.id)
+            - if tm
+              = tm.project_access_human
+
       - if @projects.blank?
         %li
           %h3.nothing_here_message There are no projects here.
diff --git a/app/views/dashboard/index.atom.builder b/app/views/dashboard/show.atom.builder
similarity index 100%
rename from app/views/dashboard/index.atom.builder
rename to app/views/dashboard/show.atom.builder
diff --git a/app/views/dashboard/index.html.haml b/app/views/dashboard/show.html.haml
similarity index 100%
rename from app/views/dashboard/index.html.haml
rename to app/views/dashboard/show.html.haml
diff --git a/app/views/dashboard/index.js.haml b/app/views/dashboard/show.js.haml
similarity index 100%
rename from app/views/dashboard/index.js.haml
rename to app/views/dashboard/show.js.haml
diff --git a/app/views/groups/issues.atom.builder b/app/views/groups/issues.atom.builder
index 5bd07bcd89f..701747bdbc3 100644
--- a/app/views/groups/issues.atom.builder
+++ b/app/views/groups/issues.atom.builder
@@ -1,9 +1,9 @@
 xml.instruct!
 xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do
   xml.title   "#{@user.name} issues"
-  xml.link    :href => dashboard_issues_url(:atom, :private_token => @user.private_token), :rel => "self", :type => "application/atom+xml"
-  xml.link    :href => dashboard_issues_url(:private_token => @user.private_token), :rel => "alternate", :type => "text/html"
-  xml.id      dashboard_issues_url(:private_token => @user.private_token)
+  xml.link    :href => issues_dashboard_url(:atom, :private_token => @user.private_token), :rel => "self", :type => "application/atom+xml"
+  xml.link    :href => issues_dashboard_url(:private_token => @user.private_token), :rel => "alternate", :type => "text/html"
+  xml.id      issues_dashboard_url(:private_token => @user.private_token)
   xml.updated @issues.first.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") if @issues.any?
 
   @issues.each do |issue|
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index 0a83be3fd2e..261a8608ca4 100644
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -6,17 +6,17 @@
     = render "layouts/head_panel", title: "Dashboard"
     .container
       %ul.main_menu
-        = nav_link(path: 'dashboard#index', html_options: {class: 'home'}) do
+        = nav_link(path: 'dashboard#show', html_options: {class: 'home'}) do
           = link_to "Home", root_path, title: "Home"
         = nav_link(path: 'dashboard#projects') do
-          = link_to dashboard_projects_path do
+          = link_to projects_dashboard_path do
             Projects
         = nav_link(path: 'dashboard#issues') do
-          = link_to dashboard_issues_path do
+          = link_to issues_dashboard_path do
             Issues
             %span.count= current_user.assigned_issues.opened.count
         = nav_link(path: 'dashboard#merge_requests') do
-          = link_to dashboard_merge_requests_path do
+          = link_to merge_requests_dashboard_path do
             Merge Requests
             %span.count= current_user.cared_merge_requests.opened.count
         = nav_link(path: 'search#show') do
diff --git a/config/routes.rb b/config/routes.rb
index 6bbcf49ab5c..7ffa081ac32 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -118,10 +118,13 @@ Gitlab::Application.routes.draw do
   #
   # Dashboard Area
   #
-  get "dashboard"                => "dashboard#index"
-  get "dashboard/projects"       => "dashboard#projects"
-  get "dashboard/issues"         => "dashboard#issues"
-  get "dashboard/merge_requests" => "dashboard#merge_requests"
+  resource :dashboard, controller: "dashboard" do
+    member do
+      get :projects
+      get :issues
+      get :merge_requests
+    end
+  end
 
   #
   # Groups Area
@@ -285,5 +288,5 @@ Gitlab::Application.routes.draw do
     end
   end
 
-  root to: "dashboard#index"
+  root to: "dashboard#show"
 end
-- 
GitLab


From 070f49fdc550654e538977f4fe6ce4a609521696 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sun, 27 Jan 2013 13:12:30 +0200
Subject: [PATCH 113/197] Make group name a link at header

---
 app/helpers/projects_helper.rb | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index c6cb9129499..4f0a80710cb 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -55,7 +55,9 @@ module ProjectsHelper
 
   def project_title project
     if project.group
-      project.name_with_namespace
+      content_tag :span do
+        link_to(project.group.name, group_path(project.group)) + " / " + project.name
+      end
     else
       project.name
     end
-- 
GitLab


From 7175b6a7695cf5c14185deccb8850d988f0dba95 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sun, 27 Jan 2013 13:20:23 +0200
Subject: [PATCH 114/197] Fixed dashboard show specs

---
 spec/requests/atom/dashboard_issues_spec.rb | 2 +-
 spec/routing/routing_spec.rb                | 8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/spec/requests/atom/dashboard_issues_spec.rb b/spec/requests/atom/dashboard_issues_spec.rb
index 8ce64cd4c14..6f5d51d16b6 100644
--- a/spec/requests/atom/dashboard_issues_spec.rb
+++ b/spec/requests/atom/dashboard_issues_spec.rb
@@ -10,7 +10,7 @@ describe "Dashboard Issues Feed" do
 
     describe "atom feed" do
       it "should render atom feed via private token" do
-        visit dashboard_issues_path(:atom, private_token: user.private_token)
+        visit issues_dashboard_path(:atom, private_token: user.private_token)
 
         page.response_headers['Content-Type'].should have_content("application/atom+xml")
         page.body.should have_selector("title", text: "#{user.name} issues")
diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb
index 57fd70e7497..5ad8165ecce 100644
--- a/spec/routing/routing_spec.rb
+++ b/spec/routing/routing_spec.rb
@@ -146,14 +146,14 @@ describe KeysController, "routing" do
   end
 end
 
-#                dashboard GET    /dashboard(.:format)                dashboard#index
+#                dashboard GET    /dashboard(.:format)                dashboard#show
 #         dashboard_issues GET    /dashboard/issues(.:format)         dashboard#issues
 # dashboard_merge_requests GET    /dashboard/merge_requests(.:format) dashboard#merge_requests
-#                     root        /                                   dashboard#index
+#                     root        /                                   dashboard#show
 describe DashboardController, "routing" do
   it "to #index" do
-    get("/dashboard").should route_to('dashboard#index')
-    get("/").should route_to('dashboard#index')
+    get("/dashboard").should route_to('dashboard#show')
+    get("/").should route_to('dashboard#show')
   end
 
   it "to #issues" do
-- 
GitLab


From cd47e625f0f6b564dff9a5e5fa51f3d88db2b530 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sun, 27 Jan 2013 14:10:42 +0200
Subject: [PATCH 115/197] Fix features

---
 features/steps/shared/paths.rb | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb
index e397ff87f41..0cfadfdffc4 100644
--- a/features/steps/shared/paths.rb
+++ b/features/steps/shared/paths.rb
@@ -34,11 +34,11 @@ module SharedPaths
   end
 
   Given 'I visit dashboard issues page' do
-    visit dashboard_issues_path
+    visit issues_dashboard_path
   end
 
   Given 'I visit dashboard merge requests page' do
-    visit dashboard_merge_requests_path
+    visit merge_requests_dashboard_path
   end
 
   Given 'I visit dashboard search page' do
-- 
GitLab


From d24fd32aa5090e1f26f028921048e15f09f82323 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sun, 27 Jan 2013 15:41:35 +0200
Subject: [PATCH 116/197] feature tests

---
 features/dashboard/projects.feature   | 8 ++++++++
 features/steps/dashboard/dashboard.rb | 6 ++++++
 features/steps/shared/paths.rb        | 4 ++++
 3 files changed, 18 insertions(+)
 create mode 100644 features/dashboard/projects.feature

diff --git a/features/dashboard/projects.feature b/features/dashboard/projects.feature
new file mode 100644
index 00000000000..17022dab54f
--- /dev/null
+++ b/features/dashboard/projects.feature
@@ -0,0 +1,8 @@
+Feature: Dashboard
+  Background:
+    Given I sign in as a user
+    And I own project "Shop"
+    And I visit dashboard projects page
+
+  Scenario: I should see issues list
+    Then I should see projects list
diff --git a/features/steps/dashboard/dashboard.rb b/features/steps/dashboard/dashboard.rb
index 4bcefba76de..8c13ad0e151 100644
--- a/features/steps/dashboard/dashboard.rb
+++ b/features/steps/dashboard/dashboard.rb
@@ -63,6 +63,12 @@ class Dashboard < Spinach::FeatureSteps
     @project.team << [current_user, :master]
   end
 
+  Then 'I should see projects list' do
+    @user.authorized_projects.all.each do |project|
+      page.should have_link project.name_with_namespace
+    end
+  end
+
   Then 'I should see groups list' do
     Group.all.each do |group|
       page.should have_link group.name
diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb
index 0cfadfdffc4..42ef40d6b95 100644
--- a/features/steps/shared/paths.rb
+++ b/features/steps/shared/paths.rb
@@ -33,6 +33,10 @@ module SharedPaths
     visit dashboard_path
   end
 
+  Given 'I visit dashboard projects page' do
+    visit projects_dashboard_path
+  end
+
   Given 'I visit dashboard issues page' do
     visit issues_dashboard_path
   end
-- 
GitLab


From ce0ec05c6371e055e9cc90e6239cafc015a6a69b Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sun, 27 Jan 2013 18:47:19 +0200
Subject: [PATCH 117/197] Pager.js to coffee

---
 app/assets/javascripts/pager.js        | 56 --------------------------
 app/assets/javascripts/pager.js.coffee | 42 +++++++++++++++++++
 2 files changed, 42 insertions(+), 56 deletions(-)
 delete mode 100644 app/assets/javascripts/pager.js
 create mode 100644 app/assets/javascripts/pager.js.coffee

diff --git a/app/assets/javascripts/pager.js b/app/assets/javascripts/pager.js
deleted file mode 100644
index 7edd6bd6186..00000000000
--- a/app/assets/javascripts/pager.js
+++ /dev/null
@@ -1,56 +0,0 @@
-var Pager = {
-  limit:0,
-  offset:0,
-  disable:false,
-
-  init:
-    function(limit, preload) {
-      this.limit=limit;
-
-      if(preload) { 
-        this.offset = 0;
-        this.getOld();
-      } else { 
-        this.offset = limit;
-      }
-
-      this.initLoadMore();
-    },
-
-  getOld:
-    function() {
-      $('.loading').show();
-      $.ajax({
-        type: "GET",
-        url: location.href,
-        data: "limit=" + this.limit + "&offset=" + this.offset,
-        complete: function(){ $('.loading').hide()},
-        dataType: "script"});
-    },
-
-  append:
-    function(count, html) {
-      $(".content_list").append(html);
-      if(count > 0) {
-        this.offset += count;
-      } else { 
-        this.disable = true;
-      }
-    },
-
-  initLoadMore:
-    function() {
-      $(document).endlessScroll({
-        bottomPixels: 400,
-        fireDelay: 1000,
-        fireOnce:true,
-        ceaseFire: function() { 
-          return Pager.disable;
-        },
-        callback: function(i) {
-          $('.loading').show();
-          Pager.getOld();
-        }
-     });
-    }
-}
diff --git a/app/assets/javascripts/pager.js.coffee b/app/assets/javascripts/pager.js.coffee
new file mode 100644
index 00000000000..5f606acdf9c
--- /dev/null
+++ b/app/assets/javascripts/pager.js.coffee
@@ -0,0 +1,42 @@
+@Pager =
+  limit: 0
+  offset: 0
+  disable: false
+  init: (limit, preload) ->
+    @limit = limit
+    if preload
+      @offset = 0
+      @getOld()
+    else
+      @offset = limit
+    @initLoadMore()
+
+  getOld: ->
+    $(".loading").show()
+    $.ajax
+      type: "GET"
+      url: location.href
+      data: "limit=" + @limit + "&offset=" + @offset
+      complete: ->
+        $(".loading").hide()
+
+      dataType: "script"
+
+  append: (count, html) ->
+    $(".content_list").append html
+    if count > 0
+      @offset += count
+    else
+      @disable = true
+
+  initLoadMore: ->
+    $(document).endlessScroll
+      bottomPixels: 400
+      fireDelay: 1000
+      fireOnce: true
+      ceaseFire: ->
+        Pager.disable
+
+      callback: (i) ->
+        $(".loading").show()
+        Pager.getOld()
-- 
GitLab


From 558369731fc95eb0690ce02fd3c38b7f4cf6921b Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sun, 27 Jan 2013 19:09:40 +0200
Subject: [PATCH 118/197] Add deploy.html for symlink if maintaince

---
 public/deploy.html | 11 +++++++++++
 1 file changed, 11 insertions(+)
 create mode 100644 public/deploy.html

diff --git a/public/deploy.html b/public/deploy.html
new file mode 100644
index 00000000000..d8c287809ea
--- /dev/null
+++ b/public/deploy.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Deploy in progress. Please try again in few minutes</title>
+    <link href="/static.css" media="screen" rel="stylesheet" type="text/css" />
+  </head>
+  <body>
+    <h1>Deploy in progress</h1>
+    <h3>Please try again in few minutes or contact your administrator.</h3>
+  </body>
+</html>
-- 
GitLab


From e33debc2147966525246bad999d0cacc4e676585 Mon Sep 17 00:00:00 2001
From: Koen Punt <koen@koenpunt.nl>
Date: Sat, 1 Dec 2012 13:49:21 +0100
Subject: [PATCH 119/197] Updated commit diff view with some minor visual
 modifications Prepared diff view for multiple view modes

Converted commits.js to coffeescript
image info in separate coffeescript file

Added swipe view mode

Added onion skin viewMode
---
 app/assets/images/onion_skin_sprites.gif      | Bin 0 -> 1584 bytes
 app/assets/images/swipemode_sprites.gif       | Bin 0 -> 1540 bytes
 app/assets/javascripts/commit/file.js.coffee  |   7 +
 .../javascripts/commit/image-file.js.coffee   | 128 +++++++
 app/assets/javascripts/commits.js             |  59 ---
 app/assets/javascripts/commits.js.coffee      |  54 +++
 app/assets/stylesheets/common.scss            |   2 +-
 .../stylesheets/gitlab_bootstrap/files.scss   |   2 +-
 .../stylesheets/gitlab_bootstrap/fonts.scss   |   2 +-
 .../gitlab_bootstrap/typography.scss          |   4 +-
 .../gitlab_bootstrap/variables.scss           |  10 +-
 app/assets/stylesheets/sections/commits.scss  | 348 +++++++++++++-----
 .../stylesheets/sections/merge_requests.scss  |   2 +-
 app/assets/stylesheets/sections/notes.scss    |  21 +-
 app/helpers/commits_helper.rb                 |   4 +-
 app/views/commit/show.html.haml               |  16 +-
 app/views/commits/_diffs.html.haml            |  72 ++--
 app/views/commits/_image.html.haml            |  63 ++++
 ...xt_diff.html.haml => _text_file.html.haml} |   2 +-
 app/views/commits/show.html.haml              |   2 +-
 app/views/notes/_discussion.html.haml         |   2 +-
 app/views/notes/_discussion_diff.html.haml    |   4 +-
 features/steps/shared/diff_note.rb            |  44 +--
 23 files changed, 593 insertions(+), 255 deletions(-)
 create mode 100644 app/assets/images/onion_skin_sprites.gif
 create mode 100644 app/assets/images/swipemode_sprites.gif
 create mode 100644 app/assets/javascripts/commit/file.js.coffee
 create mode 100644 app/assets/javascripts/commit/image-file.js.coffee
 delete mode 100644 app/assets/javascripts/commits.js
 create mode 100644 app/assets/javascripts/commits.js.coffee
 create mode 100644 app/views/commits/_image.html.haml
 rename app/views/commits/{_text_diff.html.haml => _text_file.html.haml} (95%)

diff --git a/app/assets/images/onion_skin_sprites.gif b/app/assets/images/onion_skin_sprites.gif
new file mode 100644
index 0000000000000000000000000000000000000000..85d20260edcad0f13825b8b70d930133c9e54beb
GIT binary patch
literal 1584
zcmZ?wbhEHb<YTa7xN5@i;>C+QckY}xaUw4-@ABo#t5>g{H*emiO`9%Wym;iuk*=<;
zi4!LtJ$iKW=FRKYt(!l8{^`@FOG-+bo13p(xpMpV?Xzdk?%cWa`Sa)J&!1ngV8Nk7
zhYAY|&z(EBYSpUZ;^Ku17al);eD2)2t*xy$Z{Ez!&E39z``Wc@3knJjA3l8Gz=4jA
zjx}r6Y}l}&t*!0ZvuFSR|DQQ?=9x2R($doIf&l{|p!lCV!Z$#{C9xzCNZZ&~6eK2R
zr<N!rrKV@**($x?y<bToGsRXZ+|<{=x4=0yBh#a*C^fjsFC@7tJJ~Wt$=*)EroyTs
zw;(sQBvGLvHz%*ys=`(&F(p4K)e6W43F|8<fR&VF+bTJNBosh)I_DRqDwygS=q4MO
z87P<;>KPiFn46pHC>R+S8t5As=^Gm98k$=f8(A3`C_sS{(6*wKG^-#NH>h1eo~=?w
zNlAf~zJ7Umxn8-kUVc%!zM-Y1CCCgTBVC{h-Qvo;lEez#ykcdT2`;I{$wiq3C7Jno
z3Lp~`lk!VTY?Xj6g?J&iz}FXUa9*(<*h6~B`MLTPi3R$GdItKrxgdXmRTq~8r6Qbx
zRdsPlWkITbP-=00X;E@2P`NTpGcfG%TLe-Fbd8mNQ6?}_5_4SglS^|`^GZBjY?XjA
zdMTMHR&M6zZia^DCI;q424)t9h89Lfj;<zVKxAUzVqj?kGXtAmS2I^PCpQyU6H8}j
zLqk^sOE(t-CnGaga|2ULGfNY5m|oAk;*!L?<W!iwnLvA;ES(*VT!8jiI$7e>Yvo*&
znpl!w6q28x14{t`8Tlpo#Toep3eLf%3ciWSnRy^SD0(2ibxAGCEK5ysE6UGR0Ee$t
zCKmfK{B7ZE=ICbR>}=xVW@zdPbUQ?E3OQk>4|I$^C~+Vq7MKt)1%jCHqz~l4Gf!$B
zFvk=Dvj*e;e}Dh{{`K?6_itaneE#(D!~1t{-@JbH^2PIKPoF$~^zgy`dw1{LzIF4)
z^=ntJT)uSi!ufM&&zwGW^2G6DM~@snbnw9beS7!p-nDbb_HA3YY~HkS!}@h=*Q{Q(
za>epxOP4HOv~a=vd2{E?o;7pE^l4M4OrA7xLVsUxPj^>mM|)dqOLJ3WLw#LsO?6de
zMR{3iNpVqOL4ICtPIgviMtWLmN^(+SLVR3oOmtLaM0i+eNN`YKfWM!wkGGenhr64r
zi?frXgT0-tjkT4fg}IrjiLntdTk7fRXlrR|sH>@}C@U!{$jiyfNJ~jdh>MAe2nz`c
z@bmHVaC32Tu(PqUFf%bSFev_H0g@&RI-r6GRAw@;y>*b%b<>e*Jv1ZdWX!P%htocH
zhIq{lcs*6CC1&H*^*z#mCvCm7xo~c*{Oa{TPP>-Refs%VY~1$rkG1Kw6-}irk<CS|
zCGDYkt^pG#O`bA!+VmMSo%^#z8RjooxIlc?(q+q61Q@Sgvv%G34eMEiH?EdqGce%i
z*`T>|zX9hu5yhR_tUKiy*GlYUU(L6ZV=c$I3zyb1?l54L-6?r`t;T_!OdEJ^^DAsM
zW?^~r;p3;z8x3XNs4;u1^KM`bKOfbru+gQpLsjt5TCWW$2enwe&ukRB@FDR?&aad$
f6E+-aJ`}36E~4S8!s9lfHws4<9G?^_z+epkWwdW0

literal 0
HcmV?d00001

diff --git a/app/assets/images/swipemode_sprites.gif b/app/assets/images/swipemode_sprites.gif
new file mode 100644
index 0000000000000000000000000000000000000000..327b3c31ffd3547bbc0e4b9fa7c81c4bcfdfc59e
GIT binary patch
literal 1540
zcmZ?wbhEHblw%NMxT?l*>(;H?w{LfKb*)>sE;l!K?%cWi_wQf4cyW1o`TF(imo8m;
z{P^*C^X4sIzP!G^J})n?xw(1u>ebt}ZQHwd@5+@cSFKvr)6=tT*|Gx%4y;(QV&A@f
zO-)UinVE+VAHIJ5`s~@WFJHdAVZ(;IckkZ0b7$tvnQ3Wh|NsAIpdL{C&mG|#px}~N
zk_e=2>?;Zqle1Gx6p~WYGxKbf-tXS8q>!0ns}yePYv5bpoSKp8QB{;0T;&&%T$P<{
znWAKGr(jcIRgqhen_7~nP?4LHS8P>btCX0MpOk6^WP^nDl@!2AO0sR096=HaAUmD&
zi&7O#^^A3s4Gawx%*^x*O-#+q40RNY3=EC*4S>i@*U-eu)Xd7rTmcG{fVLH-q*(>I
zxIyg#@@$ndN=gc>^!0&(u2*iXmtT~wZ)j<02{OaTNEfI=x41H|B(Xv_uUHvof=g;~
za#3bMNoIbY0?5R~r2NtnTP2`NAzsKWfE$}vtOxdvUUGh}ennz|zM-B0$V)JVzP|XC
z=H|jx7ncO3BHWAB;Np<Vf>iyW)Z+ZoqU2Pda%GTJ1y;^Qsfi`|MIrh5Ij~R+$jC3r
zFV4s>P;d@5Q_%2DOwP;$321_K`1)FT<`tJD<|U_ky4WfK&CtutOtEsbbg?uuH*hvK
zadkB`bTx8xbar%dvM_NqHgz_2F>!+Fb;(aI%}vcKf$2>_=yk!V7nB%s3xGDeq!wkC
zrKY$Q<>xAZJ#CeV+bxbb&4cPq!R;0&oO<<vj?o82EmBm&gn;P>#DphYAP1iGQ}cl7
zy$G1F8UO$L`{(zspFh5T`}*bcr;i`rzkB=U^{baJo<Do~<ng125ANT)d*}A8n>Vgs
zyL#pFrHdENpF4Zz^r@34jvqUE<nW<`2lnsVyJz>VojbN~+qz}*ri~lcuUorj^{SOC
zmM>enWbvYf3+B(8J7@N+nKPzOn>uCkq=^&y`+9r2yE;4C+ge+in;IMH>uPJNt12tX
z%Sua%iwX<!^Kx^tvobT%(^6BClM)l+<6>i?qaq{1!$L!Xg8~Em{d|4Ay*xeK-CSLq
zog5wP?QCtVtt>6f%}h;<jSLO+^>lT#wKO%<)l^lKl@t}^<z!`~r6eW9#Y9Dfg#-oo
z`FMG_xi~r4*;rYanHU)u6o0Y+Ni_x?P=Ny~@fg_tJ50V{Vr0U_dpP5SN}3Fdd)iHv
zFpr3w)>AT$UI_**)^k$qZ+eCbK5G%Z%3P)xmB1g$5}`DyK`@j@g;lAQRfQ*%UzMd*
ziA9w^R3t)5PAWnqR60RiK|Db^R3dVzM5timD#1`?&ZR1xDNf2_t5n4{J25gxGBbuc
zF)$@EF&x~zcmIh)M~<D@EqlS4LGkj%>uOi8?@>8@=CJDd6L%x-hdxYr?7MEmrnTEv
z?OePeV!7|i?W${hr>IPu;gOMbXl09ffU1kBpvwsXCD$Gq$4OUQ_&BY~JRW2&TFxSG
vugYL**v!f+X6k#Rp^%x4Z@2c+ZCidV%JSKu<UZ-eqOU5aM3~ha85pbqiK8m>

literal 0
HcmV?d00001

diff --git a/app/assets/javascripts/commit/file.js.coffee b/app/assets/javascripts/commit/file.js.coffee
new file mode 100644
index 00000000000..a45ee58d1b4
--- /dev/null
+++ b/app/assets/javascripts/commit/file.js.coffee
@@ -0,0 +1,7 @@
+class CommitFile
+  
+  constructor: (file) ->
+    if $('.image', file).length
+      new ImageFile(file)
+        
+this.CommitFile = CommitFile
\ No newline at end of file
diff --git a/app/assets/javascripts/commit/image-file.js.coffee b/app/assets/javascripts/commit/image-file.js.coffee
new file mode 100644
index 00000000000..f901a9e28ff
--- /dev/null
+++ b/app/assets/javascripts/commit/image-file.js.coffee
@@ -0,0 +1,128 @@
+class ImageFile
+
+  # Width where images must fits in, for 2-up this gets divided by 2
+  @availWidth = 900
+  @viewModes = ['two-up', 'swipe']
+
+  constructor: (@file) ->
+    # Determine if old and new file has same dimensions, if not show 'two-up' view
+    this.requestImageInfo $('.two-up.view .frame.deleted img', @file), (deletedWidth, deletedHeight) =>
+      this.requestImageInfo $('.two-up.view .frame.added img', @file), (width, height) =>
+        if width == deletedWidth && height == deletedHeight
+          this.initViewModes()
+        else
+          this.initView('two-up')
+
+  initViewModes: ->
+    viewMode = ImageFile.viewModes[0]
+
+    $('.view-modes', @file).removeClass 'hide'
+    $('.view-modes-menu', @file).on 'click', 'li', (event) =>
+      unless $(event.currentTarget).hasClass('active')
+        this.activateViewMode(event.currentTarget.className)
+
+    this.activateViewMode(viewMode)
+
+  activateViewMode: (viewMode) ->
+    $('.view-modes-menu li', @file)
+      .removeClass('active')
+      .filter(".#{viewMode}").addClass 'active'
+    $(".view:visible:not(.#{viewMode})", @file).fadeOut 200, =>
+      $(".view.#{viewMode}", @file).fadeIn(200)
+      this.initView viewMode
+
+  initView: (viewMode) ->
+    this.views[viewMode].call(this)
+
+  prepareFrames = (view) ->
+    maxWidth = 0
+    maxHeight = 0
+    $('.frame', view).each (index, frame) =>
+      width = $(frame).width()
+      height = $(frame).height()
+      maxWidth = if width > maxWidth then width else maxWidth
+      maxHeight = if height > maxHeight then height else maxHeight
+    .css
+      width: maxWidth
+      height: maxHeight
+    
+    [maxWidth, maxHeight]
+
+  views: 
+    'two-up': ->
+      $('.two-up.view .wrap', @file).each (index, wrap) =>
+        $('img', wrap).each ->
+          currentWidth = $(this).width()
+          if currentWidth > ImageFile.availWidth / 2
+            $(this).width ImageFile.availWidth / 2
+
+        this.requestImageInfo $('img', wrap), (width, height) ->
+          $('.image-info .meta-width', wrap).text "#{width}px"
+          $('.image-info .meta-height', wrap).text "#{height}px"
+          $('.image-info', wrap).removeClass('hide')
+
+    'swipe': ->
+      maxWidth = 0
+      maxHeight = 0
+
+      $('.swipe.view', @file).each (index, view) =>
+
+        [maxWidth, maxHeight] = prepareFrames(view)
+
+        $('.swipe-frame', view).css
+          width: maxWidth + 16
+          height: maxHeight + 28
+
+        $('.swipe-wrap', view).css
+          width: maxWidth + 1
+          height: maxHeight + 2
+
+        $('.swipe-bar', view).css
+          left: 0
+        .draggable
+          axis: 'x'
+          containment: 'parent'
+          drag: (event) ->
+            $('.swipe-wrap', view).width (maxWidth + 1) - $(this).position().left
+          stop: (event) ->
+            $('.swipe-wrap', view).width (maxWidth + 1) - $(this).position().left
+
+    'onion-skin': ->
+      maxWidth = 0
+      maxHeight = 0
+
+      dragTrackWidth = $('.drag-track', @file).width() - $('.dragger', @file).width()
+
+      $('.onion-skin.view', @file).each (index, view) =>
+
+        [maxWidth, maxHeight] = prepareFrames(view)
+
+        $('.onion-skin-frame', view).css
+          width: maxWidth + 16
+          height: maxHeight + 28
+
+        $('.swipe-wrap', view).css
+          width: maxWidth + 1
+          height: maxHeight + 2
+        
+        $('.dragger', view).css
+          left: dragTrackWidth
+        .draggable
+          axis: 'x'
+          containment: 'parent'
+          drag: (event) ->
+            $('.frame.added', view).css('opacity', $(this).position().left / dragTrackWidth)
+          stop: (event) ->
+            $('.frame.added', view).css('opacity', $(this).position().left / dragTrackWidth)
+        
+      
+
+  requestImageInfo: (img, callback) ->
+    domImg = img.get(0)
+    if domImg.complete
+      callback.call(this, domImg.naturalWidth, domImg.naturalHeight)
+    else
+      img.on 'load', =>
+        callback.call(this, domImg.naturalWidth, domImg.naturalHeight)
+
+this.ImageFile = ImageFile
\ No newline at end of file
diff --git a/app/assets/javascripts/commits.js b/app/assets/javascripts/commits.js
deleted file mode 100644
index b31fe485896..00000000000
--- a/app/assets/javascripts/commits.js
+++ /dev/null
@@ -1,59 +0,0 @@
-var CommitsList = {
-  ref:null,
-  limit:0,
-  offset:0,
-  disable:false,
-
-  init:
-    function(ref, limit) {
-      $(".day-commits-table li.commit").live('click', function(e){
-        if(e.target.nodeName != "A") {
-          location.href = $(this).attr("url");
-          e.stopPropagation();
-          return false;
-        }
-      });
-
-      this.ref=ref;
-      this.limit=limit;
-      this.offset=limit;
-      this.initLoadMore();
-      $('.loading').show();
-    },
-
-  getOld:
-    function() {
-      $('.loading').show();
-      $.ajax({
-        type: "GET",
-        url: location.href,
-        data: "limit=" + this.limit + "&offset=" + this.offset + "&ref=" + this.ref,
-        complete: function(){ $('.loading').hide()},
-        dataType: "script"});
-    },
-
-  append:
-    function(count, html) {
-      $("#commits_list").append(html);
-      if(count > 0) {
-        this.offset += count;
-      } else { 
-        this.disable = true;
-      }
-    },
-
-  initLoadMore:
-    function() {
-      $(document).endlessScroll({
-        bottomPixels: 400,
-        fireDelay: 1000,
-        fireOnce:true,
-        ceaseFire: function() { 
-          return CommitsList.disable;
-        },
-        callback: function(i) {
-          CommitsList.getOld();
-        }
-      });
-    }
-}
diff --git a/app/assets/javascripts/commits.js.coffee b/app/assets/javascripts/commits.js.coffee
new file mode 100644
index 00000000000..47d6fcf8089
--- /dev/null
+++ b/app/assets/javascripts/commits.js.coffee
@@ -0,0 +1,54 @@
+class CommitsList
+  @data =
+    ref: null
+    limit: 0
+    offset: 0
+  @disable = false
+  
+  @showProgress: ->
+    $('.loading').show()
+    
+  @hideProgress: ->
+    $('.loading').hide()
+  
+  @init: (ref, limit) ->
+    $(".day-commits-table li.commit").live 'click', (event) ->
+      if event.target.nodeName != "A"
+        location.href = $(this).attr("url")
+        e.stopPropagation()
+        return false
+
+    @data.ref = ref
+    @data.limit = limit
+    @data.offset = limit
+    
+    this.initLoadMore()
+    this.showProgress();
+
+  @getOld: ->
+    this.showProgress()
+    $.ajax
+      type: "GET"
+      url: location.href
+      data: @data
+      complete: this.hideProgress
+      dataType: "script"
+
+  @append: (count, html) ->
+    $("#commits-list").append(html)
+    if count > 0
+      @data.offset += count
+    else
+      @disable = true
+  
+  @initLoadMore: -> 
+    $(document).endlessScroll
+      bottomPixels: 400
+      fireDelay: 1000
+      fireOnce: true
+      ceaseFire: =>
+        @disable
+      callback: =>
+        this.getOld()
+
+this.CommitsList = CommitsList
\ No newline at end of file
diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss
index 0d25b104bb5..1884c39bc61 100644
--- a/app/assets/stylesheets/common.scss
+++ b/app/assets/stylesheets/common.scss
@@ -338,7 +338,7 @@ li.note {
     li {
       border-bottom:none !important;
     }
-    .file {
+    .attachment {
       padding-left: 20px;
       background:url("icon-attachment.png") no-repeat left center;
     }
diff --git a/app/assets/stylesheets/gitlab_bootstrap/files.scss b/app/assets/stylesheets/gitlab_bootstrap/files.scss
index 865a10e1fd7..279cfcd2103 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/files.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/files.scss
@@ -135,7 +135,7 @@
         pre {
           border: none;
           border-radius: 0;
-          font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
+          font-family: $monospace_font;
           font-size: 12px !important;
           line-height: 16px !important;
           margin: 0;
diff --git a/app/assets/stylesheets/gitlab_bootstrap/fonts.scss b/app/assets/stylesheets/gitlab_bootstrap/fonts.scss
index b4217fa9cfa..a0c9a6c7b8a 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/fonts.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/fonts.scss
@@ -4,4 +4,4 @@
 }
 
 /** Typo **/
-$monospace: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono', 'lucida console', monospace;
+$monospace_font: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono', 'lucida console', monospace;
diff --git a/app/assets/stylesheets/gitlab_bootstrap/typography.scss b/app/assets/stylesheets/gitlab_bootstrap/typography.scss
index e74a0de125b..781577c2147 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/typography.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/typography.scss
@@ -21,7 +21,7 @@ h6 {
 
 /** CODE **/
 pre {
-  font-family:'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
+  font-family: $monospace_font;
 
   &.dark {
     background: #333;
@@ -79,7 +79,7 @@ a:focus {
 }
 
 .monospace {
-  font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
+  font-family: $monospace_font;
 }
 
 /**
diff --git a/app/assets/stylesheets/gitlab_bootstrap/variables.scss b/app/assets/stylesheets/gitlab_bootstrap/variables.scss
index 869eb168c0d..aeabe7ad2e8 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/variables.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/variables.scss
@@ -1,5 +1,13 @@
-/** Colors **/
+/**
+ * General Colors
+ */
 $primary_color: #2FA0BB;
 $link_color: #3A89A3;
 $style_color: #474D57;
 $hover: #D9EDF7;
+
+/**
+ * Commit Diff Colors
+ */
+$added: #63c363;
+$deleted: #f77;
diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss
index c60aae49eaa..8b93287ed1e 100644
--- a/app/assets/stylesheets/sections/commits.scss
+++ b/app/assets/stylesheets/sections/commits.scss
@@ -1,7 +1,5 @@
 /**
- *
- * COMMIT SHOw
- *
+ * Commit file
  */
 .commit-committer-link,
 .commit-author-link {
@@ -12,11 +10,11 @@
   }
 }
 
-.diff_file {
+.file {
   border: 1px solid #CCC;
   margin-bottom: 1em;
 
-  .diff_file_header {
+  .header {
     @extend .clearfix;
     padding: 5px 5px 5px 10px;
     color: #555;
@@ -28,32 +26,35 @@
     background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
     background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
 
+    a{
+      color: $style_color;
+    }
+    
     > span {
-      font-family: $monospace;
+      font-family: $monospace_font;
       font-size: 14px;
       line-height: 30px;
     }
 
-    a.view-commit{
+    a.view-file{
       font-weight: bold;
     }
 
     .commit-short-id{
-      font-family: $monospace;
+      font-family: $monospace_font;
       font-size: smaller;
     }
 
     .file-mode{
-      font-family: $monospace;
+      font-family: $monospace_font;
     }
   }
-  .diff_file_content {
+  .content {
     overflow: auto;
     overflow-y: hidden;
-    background: #fff;
+    background: #FFF;
     color: #333;
     font-size: 12px;
-    font-family: $monospace;
     .old{
       span.idiff{
         background-color: #FAA;
@@ -66,114 +67,274 @@
     }
 
     table {
+      font-family: $monospace_font;
+      border: none;
+      margin: 0px;
+      padding: 0px;
       td {
         line-height: 18px;
+        font-size: 12px;
+      }
+    }
+    .old_line, .new_line {
+      margin: 0px;
+      padding: 0px;
+      border: none;
+      background: #EEE;
+      color: #666;
+      padding: 0px 5px;
+      border-right: 1px solid #ccc;
+      text-align: right;
+      min-width: 35px;
+      max-width: 35px;
+      width: 35px;
+      @include user-select(none);
+      a {
+        float: left;
+        width: 35px;
+        font-weight: normal;
+        color: #666;
+        &:hover {
+          text-decoration: underline;
+        }
+      }
+    }
+    .line_content {
+      white-space: pre;
+      height: 14px;
+      margin: 0px;
+      padding: 0px;
+      border: none;
+      &.new {
+        background: #CFD;
+      }
+      &.old {
+        background: #FDD;
+      }
+      &.matched {
+        color: #ccc;
+        background: #fafafa;
       }
     }
   }
-  .diff_file_content_image {
-    background: #eee;
+  .image {
+    background: #ddd;
     text-align: center;
-    .image {
+    padding: 30px;
+    .wrap{
       display: inline-block;
-      margin: 50px;
-      max-width: 400px;
-
+    }
+    
+    .frame {
+      display: inline-block;
+      background-color: #fff;
+      line-height: 0;
       img{
+        border: 1px solid #FFF;
         background: url('trans_bg.gif');
       }
+      &.deleted {
+        border: 1px solid $deleted;
+      }
 
-      &.diff_removed {
-        img{
-          border: 1px solid #C00;
-        }
+      &.added {
+        border: 1px solid $added;
       }
+    }
+    .image-info{
+      font-size: 12px;
+      margin: 5px 0 0 0;
+      color: grey;
+    }
 
-      &.diff_added {
-        img{
-          border: 1px solid #0C0;
+    .view.swipe{
+      position: relative;
+      
+      .swipe-frame{
+        display: block;
+        margin: auto;
+        position: relative;
+      }
+      .swipe-wrap{
+        overflow: hidden;
+        border-left: 1px solid #999;
+        position: absolute;
+        display: block;
+        top: 13px;
+        right: 7px;
+      }
+      .frame{
+        top: 0;
+        right: 0;
+        position: absolute;
+        &.deleted{
+          margin: 0;
+          display: block;
+          top: 13px;
+          right: 7px;
         }
       }
-
-      .image-info{
-        margin: 5px 0 0 0;
+      .swipe-bar{
+        display: block;
+        height: 100%;
+        width: 15px;
+        z-index: 100;
+        position: absolute;
+        cursor: pointer;
+        &:hover{
+          .top-handle{
+            background-position: -15px 3px;
+          }
+          .bottom-handle{
+            background-position: -15px -11px;
+          }
+        };
+        .top-handle{
+          display: block;
+          height: 14px;
+          width: 15px;
+          position: absolute;
+          top: 0px;
+          background: url('swipemode_sprites.gif') 0 3px no-repeat;
+        }
+        .bottom-handle{
+          display: block;
+          height: 14px;
+          width: 15px;
+          position: absolute;
+          bottom: 0px;
+          background: url('swipemode_sprites.gif') 0 -11px no-repeat;
+        }
       }
-    }
-
-    &.img_compared {
-      .image {
-        max-width: 300px;
+    } //.view.swipe
+    .view.onion-skin{
+      .onion-skin-frame{
+        display: block;
+        margin: auto;
+        position: relative;
       }
-    }
+      .frame.added, .frame.deleted {
+        position: absolute;
+        display: block;
+        top: 0px;
+        left: 0px;
+      }
+      .controls{
+        display: block;
+        height: 14px;
+        width: 300px;
+        z-index: 100;
+        position: absolute;
+        bottom: 0px;
+        left: 50%;
+        margin-left: -150px;
+        
+        .drag-track{
+          display: block;
+          position: absolute;
+          left: 12px;
+          height: 10px;
+          width: 276px;
+          background: url('onion_skin_sprites.gif') -4px -20px repeat-x;
+        }
+        
+        .dragger {
+          display: block;
+          position: absolute;
+          left: 0px;
+          top: 0px;
+          height: 14px;
+          width: 14px;
+          background: url('onion_skin_sprites.gif') 0px -34px repeat-x;
+          cursor: pointer;
+        }
+        
+        .transparent {
+          display: block;
+          position: absolute;
+          top: 2px;
+          right: 0px;
+          height: 10px;
+          width: 10px;
+          background: url('onion_skin_sprites.gif') -2px 0px no-repeat;
+        }
+        
+        .opaque {
+          display: block;
+          position: absolute;
+          top: 2px;
+          left: 0px;
+          height: 10px;
+          width: 10px;
+          background: url('onion_skin_sprites.gif') -2px -10px no-repeat;
+        }
+      }
+    } //.view.onion-skin
   }
-}
+  .view-modes{
 
-.diff_file_content{
-  table {
-    border: none;
-    margin: 0px;
-    padding: 0px;
-    tr {
-      td {
-        font-size: 12px;
-      }
+    padding: 10px;
+    text-align: center;
+    
+    background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
+    background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
+    background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
+    background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
+    
+    ul, li{
+      list-style: none;
+      margin: 0;
+      padding: 0;
+      display: inline-block;
     }
-  }
-  .new_line,
-  .old_line,
-  .notes_line {
-    margin:0px;
-    padding:0px;
-    border:none;
-    background:#EEE;
-    color:#666;
-    padding: 0px 5px;
-    border-right: 1px solid #ccc;
-    text-align: right;
-    min-width: 35px;
-    max-width: 35px;
-    width: 35px;
-    moz-user-select: none;
-    -khtml-user-select: none;
-    user-select: none;
-
-    a {
-      float: left;
-      width: 35px;
-      font-weight: normal;
-      color: #666;
-      &:hover {
+    
+    li{
+      color: grey;
+      border-left: 1px solid #c1c1c1;
+      padding: 0 12px 0 16px;
+      cursor: pointer;
+      &:first-child{
+        border-left: none;
+      }
+      &:hover{
         text-decoration: underline;
       }
-    }
-  }
-  .line_content {
-    white-space: pre;
-    height: 14px;
-    margin: 0px;
-    padding: 0px;
-    border: none;
-    &.new {
-      background: #CFD;
-    }
-    &.old {
-      background: #FDD;
-    }
-    &.matched {
-      color: #ccc;
-      background: #fafafa;
+      &.active{
+        &:hover{
+          text-decoration: none;
+        }
+        cursor: default;
+        color: #333;
+      }
+      &.disabled{
+        display: none;
+      }
     }
   }
 }
 
 /** COMMIT BLOCK **/
-.commit-title{display: block;}
-.commit-title{margin-bottom: 10px}
-.commit-author, .commit-committer{display: block;color: #999; font-weight: normal; font-style: italic;}
-.commit-author strong, .commit-committer strong{font-weight: bold; font-style: normal;}
+.commit-title{
+  display: block;
+}
+.commit-title{
+  margin-bottom: 10px;
+}
+.commit-author, .commit-committer{
+  display: block;
+  color: #999; 
+  font-weight: normal; 
+  font-style: italic;
+}
+.commit-author strong, .commit-committer strong{
+  font-weight: bold; 
+  font-style: normal;
+}
 
 
-/** COMMIT ROW **/
+/**
+ * COMMIT ROW
+ */
 .commit {
   .browse_code_link_holder {
     @extend .span2;
@@ -199,11 +360,10 @@
     float: left;
     @extend .lined;
     min-width: 65px;
-    font-family: $monospace;
+    font-family: $monospace_font;
   }
 }
 
-.diff_file_header a,
 .file-stats a {
   color: $style_color;
 }
@@ -237,7 +397,7 @@
   font-size: 13px;
   background: #474D57;
   color: #fff;
-  font-family: $monospace;
+  font-family: $monospace_font;
 }
 
 
diff --git a/app/assets/stylesheets/sections/merge_requests.scss b/app/assets/stylesheets/sections/merge_requests.scss
index 5225a242726..ff715c0fd18 100644
--- a/app/assets/stylesheets/sections/merge_requests.scss
+++ b/app/assets/stylesheets/sections/merge_requests.scss
@@ -77,7 +77,7 @@ li.merge_request {
   font-size: 14px;
   background: #474D57;
   color: #fff;
-  font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
+  font-family: $monospace_font;
 }
 
 .mr_source_commit,
diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss
index a7fadd4f641..7a1cc444e5d 100644
--- a/app/assets/stylesheets/sections/notes.scss
+++ b/app/assets/stylesheets/sections/notes.scss
@@ -40,13 +40,13 @@ ul.notes {
     .discussion-body {
       margin-left: 50px;
 
-      .diff_file,
+      .file,
       .discussion-hidden,
       .notes {
         @extend .borders;
         background-color: #F9F9F9;
       }
-      .diff_file .notes {
+      .file .notes {
         /* reset */
         background: inherit;
         border: none;
@@ -109,7 +109,7 @@ ul.notes {
   }
 }
 
-.diff_file .notes_holder {
+.file .notes_holder {
   font-family: $sansFontFamily;
   font-size: 13px;
   line-height: 18px;
@@ -134,8 +134,6 @@ ul.notes {
   }
 }
 
-
-
 /**
  * Actions for Discussions/Notes
  */
@@ -171,7 +169,7 @@ ul.notes {
     }
   }
 }
-.diff_file .note .note-actions {
+.file .note .note-actions {
   right: 0;
   top: 0;
 }
@@ -182,7 +180,7 @@ ul.notes {
  * Line note button on the side of diffs
  */
 
-.diff_file tr.line_holder {
+.file tr.line_holder {
   .add-diff-note {
     background: url("diff_note_add.png") no-repeat left 0;
     height: 22px;
@@ -212,8 +210,6 @@ ul.notes {
   }
 }
 
-
-
 /**
  * Note Form
  */
@@ -222,7 +218,12 @@ ul.notes {
 .reply-btn {
   @extend .save-btn;
 }
-.diff_file,
+.file .content tr.line_holder:hover > td { background: $hover !important; }
+.file .content tr.line_holder:hover > td .line_note_link {
+  opacity: 1.0;
+  filter: alpha(opacity=100);
+}
+.file,
 .discussion {
   .new_note {
     margin: 8px 5px 8px 0;
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index 4b5d8bd96a6..6d2ce2feea3 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -59,9 +59,9 @@ module CommitsHelper
 
   def image_diff_class(diff)
     if diff.deleted_file
-      "diff_removed"
+      "deleted"
     elsif diff.new_file
-      "diff_added"
+      "added"
     else
       nil
     end
diff --git a/app/views/commit/show.html.haml b/app/views/commit/show.html.haml
index f920534e03a..6bee6493ac6 100644
--- a/app/views/commit/show.html.haml
+++ b/app/views/commit/show.html.haml
@@ -11,19 +11,7 @@
 
 :javascript
   $(function(){
-    var w, h;
-    $('.diff_file').each(function(){
-      $('.image.diff_removed img', this).on('load', $.proxy(function(event){
-        var w = event.currentTarget.naturalWidth
-          , h = event.currentTarget.naturalHeight;
-        $('.image.diff_removed .image-info', this).append(' | <b>W:</b> ' + w + 'px | <b>H:</b> ' + h + 'px');
-      }, this));
-      $('.image.diff_added img', this).on('load', $.proxy(function(event){
-        var w = event.currentTarget.naturalWidth
-          , h = event.currentTarget.naturalHeight;
-        $('.image.diff_added .image-info', this).append(' | <b>W:</b> ' + w + 'px | <b>H:</b> ' + h + 'px');
-      }, this));
-
+    $('.files .file').each(function(){
+      new CommitFile(this);
     });
-
   });
diff --git a/app/views/commits/_diffs.html.haml b/app/views/commits/_diffs.html.haml
index 7fe45aa25bc..9a9aed39b08 100644
--- a/app/views/commits/_diffs.html.haml
+++ b/app/views/commits/_diffs.html.haml
@@ -12,50 +12,38 @@
 .file-stats
   = render "commits/diff_head", diffs: diffs
 
-- unless @suppress_diff
-  - diffs.each_with_index do |diff, i|
-    - next if diff.diff.empty?
-    - file = (@commit.tree / diff.new_path)
-    - file = (@commit.prev_commit.tree / diff.old_path) unless file
-    - next unless file
-    .diff_file{id: "diff-#{i}"}
-      .diff_file_header
-        - if diff.deleted_file
-          %span= diff.old_path
+.files
+  - unless @suppress_diff
+    - diffs.each_with_index do |diff, i|
+      - next if diff.diff.empty?
+      - file = (@commit.tree / diff.new_path)
+      - file = (@commit.prev_commit.tree / diff.old_path) unless file
+      - next unless file
+      .file{id: "diff-#{i}"}
+        .header
+          - if diff.deleted_file
+            %span= diff.old_path
 
-          - if @commit.prev_commit
-            = link_to project_tree_path(@project, tree_join(@commit.prev_commit_id, diff.new_path)), {:class => 'btn right view-commit'} do
+            - if @commit.prev_commit
+              = link_to project_tree_path(@project, tree_join(@commit.prev_commit_id, diff.new_path)), {:class => 'btn right view-file'} do
+                View file @
+                %span.commit-short-id= @commit.short_id(6)
+          - else
+            %span= diff.new_path
+            - if diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode
+              %span.file-mode= "#{diff.a_mode} → #{diff.b_mode}"
+
+            = link_to project_tree_path(@project, tree_join(@commit.id, diff.new_path)), {:class => 'btn very_small right view-file'} do
               View file @
               %span.commit-short-id= @commit.short_id(6)
-        - else
-          %span= diff.new_path
-          - if diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode
-            %span.file-mode= "#{diff.a_mode} → #{diff.b_mode}"
-
-          = link_to project_tree_path(@project, tree_join(@commit.id, diff.new_path)), {:class => 'btn very_small right view-commit'} do
-            View file @
-            %span.commit-short-id= @commit.short_id(6)
 
-        %br/
-      .diff_file_content
-        -# Skip all non-supported blobs
-        - next unless file.respond_to?('text?')
-        - if file.text?
-          = render "commits/text_diff", diff: diff, index: i
-        - elsif file.image?
-          - old_file = (@commit.prev_commit.tree / diff.old_path) if !@commit.prev_commit.nil?
-          - if diff.renamed_file || diff.new_file || diff.deleted_file
-            .diff_file_content_image
-              .image{class: image_diff_class(diff)}
-                %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"}
-                %div.image-info= "#{number_to_human_size file.size}"
+        .content
+          -# Skipp all non non-supported blobs
+          - next unless file.respond_to?('text?')
+          - if file.text?
+            = render "commits/text_file", diff: diff, index: i
+          - elsif file.image?
+            - old_file = (@commit.prev_commit.tree / diff.old_path) if !@commit.prev_commit.nil?
+            = render "commits/image", diff: diff, old_file: old_file, file: file, index: i
           - else
-            .diff_file_content_image.img_compared
-              .image.diff_removed
-                %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(old_file.data)}"}
-                %div.image-info= "#{number_to_human_size file.size}"
-              .image.diff_added
-                %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"}
-                %div.image-info= "#{number_to_human_size file.size}"
-        - else
-          %p.nothing_here_message No preview for this file type
+            %p.nothing_here_message No preview for this file type
diff --git a/app/views/commits/_image.html.haml b/app/views/commits/_image.html.haml
new file mode 100644
index 00000000000..db02fa333b9
--- /dev/null
+++ b/app/views/commits/_image.html.haml
@@ -0,0 +1,63 @@
+- if diff.renamed_file || diff.new_file || diff.deleted_file
+  .image
+    %span.wrap
+      .frame{class: image_diff_class(diff)}
+        %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"}
+      %p.image-info= "#{number_to_human_size file.size}"
+- else
+  .image
+    %div.two-up.view
+      %span.wrap
+        .frame.deleted
+          %a{href: project_tree_path(@project, tree_join(@commit.id, diff.old_path))}
+            %img{src: "data:#{old_file.mime_type};base64,#{Base64.encode64(old_file.data)}"}
+        %p.image-info.hide
+          %span.meta-filesize= "#{number_to_human_size old_file.size}"
+          |
+          %b W:
+          %span.meta-width 
+          |
+          %b H:
+          %span.meta-height
+      %span.wrap
+        .frame.added
+          %a{href: project_tree_path(@project, tree_join(@commit.id, diff.new_path))}
+            %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"}
+        %p.image-info.hide
+          %span.meta-filesize= "#{number_to_human_size file.size}"
+          |
+          %b W:
+          %span.meta-width 
+          |
+          %b H:
+          %span.meta-height
+
+    %div.swipe.view.hide
+      .swipe-frame
+        .frame.deleted
+          %img{src: "data:#{old_file.mime_type};base64,#{Base64.encode64(old_file.data)}"}
+        .swipe-wrap
+          .frame.added
+            %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"}
+        %span.swipe-bar
+          %span.top-handle
+          %span.bottom-handle
+
+    %div.onion-skin.view.hide
+      .onion-skin-frame
+        .frame.deleted
+          %img{src: "data:#{old_file.mime_type};base64,#{Base64.encode64(old_file.data)}"}
+        .frame.added
+          %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"}
+        .controls
+          .transparent
+          .drag-track
+            .dragger{:style => "left: 0px;"}
+          .opaque
+
+
+  .view-modes.hide
+    %ul.view-modes-menu
+      %li.two-up{data: {mode: 'two-up'}} 2-up
+      %li.swipe{data: {mode: 'swipe'}} Swipe
+      %li.onion-skin{data: {mode: 'onion-skin'}} Onion skin
\ No newline at end of file
diff --git a/app/views/commits/_text_diff.html.haml b/app/views/commits/_text_file.html.haml
similarity index 95%
rename from app/views/commits/_text_diff.html.haml
rename to app/views/commits/_text_file.html.haml
index 8afad96bde2..760fd07ed8b 100644
--- a/app/views/commits/_text_diff.html.haml
+++ b/app/views/commits/_text_file.html.haml
@@ -2,7 +2,7 @@
 - if too_big
   %a.supp_diff_link Diff suppressed. Click to show
 
-%table{class: "#{'hide' if too_big}"}
+%table.text-file{class: "#{'hide' if too_big}"}
   - each_diff_line(diff, index) do |line, type, line_code, line_new, line_old|
     %tr.line_holder{ id: line_code }
       - if type == "match"
diff --git a/app/views/commits/show.html.haml b/app/views/commits/show.html.haml
index 9451a038df0..d180b8ec426 100644
--- a/app/views/commits/show.html.haml
+++ b/app/views/commits/show.html.haml
@@ -5,7 +5,7 @@
     = breadcrumbs
 
 %div{id: dom_id(@project)}
-  #commits_list= render "commits"
+  #commits-list= render "commits"
 .clear
 .loading{ style: "display:none;"}
 
diff --git a/app/views/notes/_discussion.html.haml b/app/views/notes/_discussion.html.haml
index a9a11fc2d7e..24cb4228174 100644
--- a/app/views/notes/_discussion.html.haml
+++ b/app/views/notes/_discussion.html.haml
@@ -38,7 +38,7 @@
     - if note.for_diff_line?
       - if note.diff
         .content
-          .diff_file= render "notes/discussion_diff", discussion_notes: discussion_notes, note: note
+          .file= render "notes/discussion_diff", discussion_notes: discussion_notes, note: note
       - else
         = link_to 'show outdated discussion', '#', class: 'js-show-outdated-discussion'
         %div.hide.outdated-discussion
diff --git a/app/views/notes/_discussion_diff.html.haml b/app/views/notes/_discussion_diff.html.haml
index 93ab59c72c5..790b77333d5 100644
--- a/app/views/notes/_discussion_diff.html.haml
+++ b/app/views/notes/_discussion_diff.html.haml
@@ -1,5 +1,5 @@
 - diff = note.diff
-.diff_file_header
+.header
   - if diff.deleted_file
     %span= diff.old_path
   - else
@@ -7,7 +7,7 @@
     - if diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode
       %span.file-mode= "#{diff.a_mode} → #{diff.b_mode}"
   %br/
-.diff_file_content
+.content
   %table
     - each_diff_line(diff, note.diff_file_index) do |line, type, line_code, line_new, line_old|
       %tr.line_holder{ id: line_code }
diff --git a/features/steps/shared/diff_note.rb b/features/steps/shared/diff_note.rb
index 2ae0f1241b8..04862338026 100644
--- a/features/steps/shared/diff_note.rb
+++ b/features/steps/shared/diff_note.rb
@@ -2,27 +2,27 @@ module SharedDiffNote
   include Spinach::DSL
 
   Given 'I cancel the diff comment' do
-    within(".diff_file") do
+    within(".file") do
       find(".js-close-discussion-note-form").trigger("click")
     end
   end
 
   Given 'I delete a diff comment' do
     sleep 1
-    within(".diff_file") do
+    within(".file") do
       first(".js-note-delete").trigger("click")
     end
   end
 
   Given 'I haven\'t written any diff comment text' do
-    within(".diff_file") do
+    within(".file") do
       fill_in "note[note]", with: ""
     end
   end
 
   Given 'I leave a diff comment like "Typo, please fix"' do
     find("#586fb7c4e1add2d4d24e27566ed7064680098646_29_14.line_holder .js-add-diff-note-button").trigger("click")
-    within(".diff_file") do
+    within(".file") do
       fill_in "note[note]", with: "Typo, please fix"
       #click_button("Add Comment")
       find(".js-comment-button").trigger("click")
@@ -32,7 +32,7 @@ module SharedDiffNote
 
   Given 'I preview a diff comment text like "Should fix it :smile:"' do
     find("#586fb7c4e1add2d4d24e27566ed7064680098646_29_14.line_holder .js-add-diff-note-button").trigger("click")
-    within(".diff_file") do
+    within(".file") do
       fill_in "note[note]", with: "Should fix it :smile:"
       find(".js-note-preview-button").trigger("click")
     end
@@ -40,7 +40,7 @@ module SharedDiffNote
 
   Given 'I preview another diff comment text like "DRY this up"' do
     find("#586fb7c4e1add2d4d24e27566ed7064680098646_57_41.line_holder .js-add-diff-note-button").trigger("click")
-    within(".diff_file") do
+    within(".file") do
       fill_in "note[note]", with: "DRY this up"
       find(".js-note-preview-button").trigger("click")
     end
@@ -55,13 +55,13 @@ module SharedDiffNote
   end
 
   Given 'I write a diff comment like ":-1: I don\'t like this"' do
-    within(".diff_file") do
+    within(".file") do
       fill_in "note[note]", with: ":-1: I don\'t like this"
     end
   end
 
   Given 'I submit the diff comment' do
-    within(".diff_file") do
+    within(".file") do
       click_button("Add Comment")
     end
   end
@@ -69,49 +69,49 @@ module SharedDiffNote
 
 
   Then 'I should not see the diff comment form' do
-    within(".diff_file") do
+    within(".file") do
       page.should_not have_css("form.new_note")
     end
   end
 
   Then 'I should not see the diff comment preview button' do
-    within(".diff_file") do
+    within(".file") do
       page.should have_css(".js-note-preview-button", visible: false)
     end
   end
 
   Then 'I should not see the diff comment text field' do
-    within(".diff_file") do
+    within(".file") do
       page.should have_css(".js-note-text", visible: false)
     end
   end
 
   Then 'I should only see one diff form' do
-    within(".diff_file") do
+    within(".file") do
       page.should have_css("form.new_note", count: 1)
     end
   end
 
   Then 'I should see a diff comment form with ":-1: I don\'t like this"' do
-    within(".diff_file") do
+    within(".file") do
       page.should have_field("note[note]", with: ":-1: I don\'t like this")
     end
   end
 
   Then 'I should see a diff comment saying "Typo, please fix"' do
-    within(".diff_file .note") do
+    within(".file .note") do
       page.should have_content("Typo, please fix")
     end
   end
 
   Then 'I should see a discussion reply button' do
-    within(".diff_file") do
+    within(".file") do
       page.should have_link("Reply")
     end
   end
 
   Then 'I should see a temporary diff comment form' do
-    within(".diff_file") do
+    within(".file") do
       page.should have_css(".js-temp-notes-holder form.new_note")
     end
   end
@@ -121,37 +121,37 @@ module SharedDiffNote
   end
 
   Then 'I should see an empty diff comment form' do
-    within(".diff_file") do
+    within(".file") do
       page.should have_field("note[note]", with: "")
     end
   end
 
   Then 'I should see the cancel comment button' do
-    within(".diff_file form") do
+    within(".file form") do
       page.should have_css(".js-close-discussion-note-form", text: "Cancel")
     end
   end
 
   Then 'I should see the diff comment preview' do
-    within(".diff_file form") do
+    within(".file form") do
       page.should have_css(".js-note-preview", visible: false)
     end
   end
 
   Then 'I should see the diff comment edit button' do
-    within(".diff_file") do
+    within(".file") do
       page.should have_css(".js-note-edit-button", visible: true)
     end
   end
 
   Then 'I should see the diff comment preview button' do
-    within(".diff_file") do
+    within(".file") do
       page.should have_css(".js-note-preview-button", visible: true)
     end
   end
 
   Then 'I should see two separate previews' do
-    within(".diff_file") do
+    within(".file") do
       page.should have_css(".js-note-preview", visible: true, count: 2)
       page.should have_content("Should fix it")
       page.should have_content("DRY this up")
-- 
GitLab


From bd948549293e1abfa32ec566b687670fed47a3d7 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 28 Jan 2013 08:59:34 +0200
Subject: [PATCH 120/197] fix tests

---
 spec/models/project_hooks_spec.rb | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/spec/models/project_hooks_spec.rb b/spec/models/project_hooks_spec.rb
index 60457e20c51..3559c72f6f0 100644
--- a/spec/models/project_hooks_spec.rb
+++ b/spec/models/project_hooks_spec.rb
@@ -38,11 +38,14 @@ describe Project, "Hooks" do
         @project_hook = create(:project_hook)
         @project_hook_2 = create(:project_hook)
         project.hooks << [@project_hook, @project_hook_2]
+
+        stub_request(:post, @project_hook.url)
+        stub_request(:post, @project_hook_2.url)
       end
 
       it "executes multiple web hook" do
-        @project_hook.should_receive(:execute).once
-        @project_hook_2.should_receive(:execute).once
+        @project_hook.should_receive(:async_execute).once
+        @project_hook_2.should_receive(:async_execute).once
 
         project.trigger_post_receive('oldrev', 'newrev', 'refs/heads/master', @user)
       end
-- 
GitLab


From 3c47e6248ade6cd8561e1e361a01f7a770907bfd Mon Sep 17 00:00:00 2001
From: Felix Gilcher <felix.gilcher@asquera.de>
Date: Mon, 28 Jan 2013 10:59:39 +0100
Subject: [PATCH 121/197] remove incorrect information about the api version
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The API version is currently not equal to the gitlab major version number. Gitlab 4.1 
still uses API version 3. Point to the lib/api.rb file instead which contains the
autoritative information.
---
 doc/api/README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/doc/api/README.md b/doc/api/README.md
index 477429c9fa0..65eec6bec3c 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -10,7 +10,7 @@ If no, or an invalid, `private_token` is provided then an error message will be
 }
 ```
 
-API requests should be prefixed with `api` and the API version. The API version is equal to the GitLab major version number, which is defined in `lib/api.rb`.
+API requests should be prefixed with `api` and the API version. The API version is defined in `lib/api.rb`.
 
 Example of a valid API request:
 
-- 
GitLab


From dc13af90b12a2366f77a9b68a7b74d7b5f54bc1a Mon Sep 17 00:00:00 2001
From: Lennart Rosam <lennart.rosam@medien-systempartner.de>
Date: Mon, 28 Jan 2013 12:54:07 +0100
Subject: [PATCH 122/197] Fix rake task - Update method name

---
 lib/tasks/gitlab/bulk_add_permission.rake | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/lib/tasks/gitlab/bulk_add_permission.rake b/lib/tasks/gitlab/bulk_add_permission.rake
index 36c51d060bc..54a5c7aea76 100644
--- a/lib/tasks/gitlab/bulk_add_permission.rake
+++ b/lib/tasks/gitlab/bulk_add_permission.rake
@@ -7,9 +7,9 @@ namespace :gitlab do
 
       Project.find_each do |project|
         puts "Importing #{user_ids.size} users into #{project.code}"
-        UsersProject.bulk_import(project, user_ids, UsersProject::DEVELOPER)
+        UsersProject.add_users_into_projects(project, user_ids, UsersProject::DEVELOPER)
         puts "Importing #{admin_ids.size} admins into #{project.code}"
-        UsersProject.bulk_import(project, admin_ids, UsersProject::MASTER)
+        UsersProject.add_users_into_projects(project, admin_ids, UsersProject::MASTER)
       end
     end
 
@@ -18,7 +18,7 @@ namespace :gitlab do
       user = User.find_by_email args.email
       project_ids = Project.pluck(:id)
 
-      UsersProject.user_bulk_import(user, project_ids, UsersProject::DEVELOPER)
+      UsersProject.add_users_into_projects(user, project_ids, UsersProject::DEVELOPER)
     end
   end
 end
\ No newline at end of file
-- 
GitLab


From f9a48f72d485af69b5cad6062b48ac5cfb651b74 Mon Sep 17 00:00:00 2001
From: Lennart Rosam <lennart.rosam@medien-systempartner.de>
Date: Mon, 28 Jan 2013 13:52:30 +0100
Subject: [PATCH 123/197] Fix issue #2790

---
 lib/tasks/gitlab/bulk_add_permission.rake | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/lib/tasks/gitlab/bulk_add_permission.rake b/lib/tasks/gitlab/bulk_add_permission.rake
index 54a5c7aea76..eb1a7559dbd 100644
--- a/lib/tasks/gitlab/bulk_add_permission.rake
+++ b/lib/tasks/gitlab/bulk_add_permission.rake
@@ -4,21 +4,21 @@ namespace :gitlab do
     task :all_users_to_all_projects => :environment  do |t, args|
       user_ids = User.where(:admin => false).pluck(:id)
       admin_ids = User.where(:admin => true).pluck(:id)
+      projects_ids = Project.pluck(:id)
 
-      Project.find_each do |project|
-        puts "Importing #{user_ids.size} users into #{project.code}"
-        UsersProject.add_users_into_projects(project, user_ids, UsersProject::DEVELOPER)
-        puts "Importing #{admin_ids.size} admins into #{project.code}"
-        UsersProject.add_users_into_projects(project, admin_ids, UsersProject::MASTER)
-      end
+      puts "Importing #{user_ids.size} users into #{projects_ids.size} projects"
+      UsersProject.add_users_into_projects(projects_ids, user_ids, UsersProject::DEVELOPER)
+
+      puts "Importing #{admin_ids.size} admins into #{projects_ids.size} projects"
+      UsersProject.add_users_into_projects(projects_ids, admin_ids, UsersProject::MASTER)
     end
 
     desc "GITLAB | Add a specific user to all projects (as a developer)"
     task :user_to_projects, [:email] => :environment  do |t, args|
       user = User.find_by_email args.email
       project_ids = Project.pluck(:id)
-
-      UsersProject.add_users_into_projects(user, project_ids, UsersProject::DEVELOPER)
+      puts "Importing #{user.email} users into #{project_ids.size} projects"
+      UsersProject.add_users_into_projects(project_ids, Array.wrap(user.id), UsersProject::DEVELOPER)
     end
   end
 end
\ No newline at end of file
-- 
GitLab


From 1c5876eb7b2deb069d919bd19b51c9f6218e0f41 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 28 Jan 2013 17:22:45 +0200
Subject: [PATCH 124/197] Do gitolite calls async. Remove satellite with
 project remove

---
 Procfile                                |  2 +-
 app/contexts/projects/create_context.rb | 12 ++------
 app/models/project.rb                   | 16 +++++++----
 app/models/users_project.rb             |  2 +-
 app/observers/project_observer.rb       |  1 +
 app/workers/gitolite_worker.rb          | 10 +++++++
 app/workers/post_receive.rb             | 15 +++++-----
 lib/gitlab/backend/gitolite.rb          | 14 +++++++--
 lib/gitlab/backend/gitolite_config.rb   | 38 ++++++++++---------------
 lib/gitlab/popen.rb                     | 18 ++++++++++++
 lib/gitlab/satellite/satellite.rb       | 12 ++++++--
 lib/tasks/sidekiq.rake                  |  2 +-
 12 files changed, 90 insertions(+), 52 deletions(-)
 create mode 100644 app/workers/gitolite_worker.rb
 create mode 100644 lib/gitlab/popen.rb

diff --git a/Procfile b/Procfile
index 28a97ddafd7..1a4145cc7d3 100644
--- a/Procfile
+++ b/Procfile
@@ -1,2 +1,2 @@
 web: bundle exec unicorn_rails -p $PORT
-worker: bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,common,default
+worker: bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,common,default,gitolite
diff --git a/app/contexts/projects/create_context.rb b/app/contexts/projects/create_context.rb
index e644d89a356..915bd8be8b0 100644
--- a/app/contexts/projects/create_context.rb
+++ b/app/contexts/projects/create_context.rb
@@ -32,16 +32,10 @@ module Projects
         @project.namespace_id = current_user.namespace_id
       end
 
-      Project.transaction do
-        @project.creator = current_user
-        @project.save!
+      @project.creator = current_user
 
-        # Add user as project master
-        @project.users_projects.create!(project_access: UsersProject::MASTER, user: current_user)
-
-        # when project saved no team member exist so
-        # project repository should be updated after first user add
-        @project.update_repository
+      if @project.save
+        @project.users_projects.create(project_access: UsersProject::MASTER, user: current_user)
       end
 
       @project
diff --git a/app/models/project.rb b/app/models/project.rb
index cb6986ce43d..dde15927808 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -299,6 +299,9 @@ class Project < ActiveRecord::Base
   def trigger_post_receive(oldrev, newrev, ref, user)
     data = post_receive_data(oldrev, newrev, ref, user)
 
+    # Create satellite
+    self.satellite.create unless self.satellite.exists?
+
     # Create push event
     self.observe_push(data)
 
@@ -313,9 +316,6 @@ class Project < ActiveRecord::Base
       self.execute_services(data.dup)
     end
 
-    # Create satellite
-    self.satellite.create unless self.satellite.exists?
-
     # Discover the default branch, but only if it hasn't already been set to
     # something else
     if repository && default_branch.nil?
@@ -460,11 +460,17 @@ class Project < ActiveRecord::Base
   end
 
   def update_repository
-    gitolite.update_repository(self)
+    GitoliteWorker.perform_async(
+      :update_repository,
+      self.id
+    )
   end
 
   def destroy_repository
-    gitolite.remove_repository(self)
+    GitoliteWorker.perform_async(
+      :remove_repository,
+      self.path_with_namespace
+    )
   end
 
   def repo_exists?
diff --git a/app/models/users_project.rb b/app/models/users_project.rb
index ca5048ca7d4..3206600413c 100644
--- a/app/models/users_project.rb
+++ b/app/models/users_project.rb
@@ -129,7 +129,7 @@ class UsersProject < ActiveRecord::Base
   end
 
   def update_repository
-    gitolite.update_repository(project)
+    project.update_repository
   end
 
   def project_access_human
diff --git a/app/observers/project_observer.rb b/app/observers/project_observer.rb
index b1c694569d7..cc454ae3e35 100644
--- a/app/observers/project_observer.rb
+++ b/app/observers/project_observer.rb
@@ -10,6 +10,7 @@ class ProjectObserver < ActiveRecord::Observer
   def after_destroy(project)
     log_info("Project \"#{project.name}\" was removed")
 
+    project.satellite.destroy
     project.destroy_repository
   end
 
diff --git a/app/workers/gitolite_worker.rb b/app/workers/gitolite_worker.rb
new file mode 100644
index 00000000000..d134ea035f4
--- /dev/null
+++ b/app/workers/gitolite_worker.rb
@@ -0,0 +1,10 @@
+class GitoliteWorker
+  include Sidekiq::Worker
+  include Gitolited
+
+  sidekiq_options queue: :gitolite
+
+  def perform(action, arg)
+    gitolite.send(action, arg)
+  end
+end
diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb
index e74379a65dd..a906f78f7e3 100644
--- a/app/workers/post_receive.rb
+++ b/app/workers/post_receive.rb
@@ -13,13 +13,14 @@ class PostReceive
 
     # Ignore push from non-gitlab users
     user = if identifier.eql? Gitlab.config.gitolite.admin_key
-      email = project.repository.commit(newrev).author.email rescue nil
-      User.find_by_email(email) if email
-    elsif /^[A-Z0-9._%a-z\-]+@(?:[A-Z0-9a-z\-]+\.)+[A-Za-z]{2,4}$/.match(identifier)
-      User.find_by_email(identifier)
-    else
-      Key.find_by_identifier(identifier).try(:user)
-    end
+             email = project.repository.commit(newrev).author.email rescue nil
+             User.find_by_email(email) if email
+           elsif /^[A-Z0-9._%a-z\-]+@(?:[A-Z0-9a-z\-]+\.)+[A-Za-z]{2,4}$/.match(identifier)
+             User.find_by_email(identifier)
+           else
+             Key.find_by_identifier(identifier).try(:user)
+           end
+
     return false unless user
 
     project.trigger_post_receive(oldrev, newrev, ref, user)
diff --git a/lib/gitlab/backend/gitolite.rb b/lib/gitlab/backend/gitolite.rb
index 3b8a2090f73..d026b76f5ef 100644
--- a/lib/gitlab/backend/gitolite.rb
+++ b/lib/gitlab/backend/gitolite.rb
@@ -22,7 +22,8 @@ module Gitlab
       end
     end
 
-    def update_repository project
+    def update_repository project_id
+      project = Project.find(project_id)
       config.update_project!(project)
     end
 
@@ -33,8 +34,15 @@ module Gitlab
       end
     end
 
-    def remove_repository project
-      config.destroy_project!(project)
+    # Remove repository from gitolite
+    #
+    # name - project path with namespace
+    #
+    # Ex.
+    #   remove_repository("gitlab/gitlab-ci")
+    #
+    def remove_repository(name)
+      config.destroy_project!(name)
     end
 
     def url_to_repo path
diff --git a/lib/gitlab/backend/gitolite_config.rb b/lib/gitlab/backend/gitolite_config.rb
index e4ebd595a93..748f9d74390 100644
--- a/lib/gitlab/backend/gitolite_config.rb
+++ b/lib/gitlab/backend/gitolite_config.rb
@@ -4,6 +4,8 @@ require 'fileutils'
 
 module Gitlab
   class GitoliteConfig
+    include Gitlab::Popen
+
     class PullError < StandardError; end
     class PushError < StandardError; end
     class BrokenGitolite < StandardError; end
@@ -87,12 +89,14 @@ module Gitlab
       Gitlab::GitLogger.error(message)
     end
 
-    def destroy_project(project)
-      # do rm-rf only if repository exists
-      if project.repository
-        FileUtils.rm_rf(project.repository.path_to_repo)
-      end
-      conf.rm_repo(project.path_with_namespace)
+    def path_to_repo(name)
+      File.join(Gitlab.config.gitolite.repos_path, "#{name}.git")
+    end
+
+    def destroy_project(name)
+      full_path = path_to_repo(name)
+      FileUtils.rm_rf(full_path) if File.exists?(full_path)
+      conf.rm_repo(name)
     end
 
     def clean_repo repo_name
@@ -210,14 +214,14 @@ module Gitlab
     end
 
     def push
-      output, status = popen('git add -A')
+      output, status = popen('git add -A', tmp_conf_path)
       raise "Git add failed." unless status.zero?
 
       # git commit returns 0 on success, and 1 if there is nothing to commit
-      output, status = popen('git commit -m "GitLab"')
+      output, status = popen('git commit -m "GitLab"', tmp_conf_path)
       raise "Git add failed." unless [0,1].include?(status)
 
-      output, status = popen('git push')
+      output, status = popen('git push', tmp_conf_path)
 
       if output =~ /remote\: FATAL/
         raise BrokenGitolite, output
@@ -230,20 +234,8 @@ module Gitlab
       end
     end
 
-    def popen(cmd, path = nil)
-      path ||= File.join(config_tmp_dir,'gitolite')
-      vars = { "PWD" => path }
-      options = { :chdir => path }
-
-      @cmd_output = ""
-      @cmd_status = 0
-      Open3.popen3(vars, cmd, options) do |stdin, stdout, stderr, wait_thr|
-        @cmd_status = wait_thr.value.exitstatus
-        @cmd_output << stdout.read
-        @cmd_output << stderr.read
-      end
-
-      return @cmd_output, @cmd_status
+    def tmp_conf_path
+      File.join(config_tmp_dir,'gitolite')
     end
   end
 end
diff --git a/lib/gitlab/popen.rb b/lib/gitlab/popen.rb
new file mode 100644
index 00000000000..f2cfd8073e3
--- /dev/null
+++ b/lib/gitlab/popen.rb
@@ -0,0 +1,18 @@
+module Gitlab
+  module Popen
+    def popen(cmd, path)
+      vars = { "PWD" => path }
+      options = { :chdir => path }
+
+      @cmd_output = ""
+      @cmd_status = 0
+      Open3.popen3(vars, cmd, options) do |stdin, stdout, stderr, wait_thr|
+        @cmd_status = wait_thr.value.exitstatus
+        @cmd_output << stdout.read
+        @cmd_output << stderr.read
+      end
+
+      return @cmd_output, @cmd_status
+    end
+  end
+end
diff --git a/lib/gitlab/satellite/satellite.rb b/lib/gitlab/satellite/satellite.rb
index 164af55d895..d8e8f58963b 100644
--- a/lib/gitlab/satellite/satellite.rb
+++ b/lib/gitlab/satellite/satellite.rb
@@ -3,6 +3,8 @@ module Gitlab
 
   module Satellite
     class Satellite
+      include Gitlab::Popen
+
       PARKING_BRANCH = "__parking_branch"
 
       attr_accessor :project
@@ -24,8 +26,10 @@ module Gitlab
       end
 
       def create
-        create_cmd = "git clone #{project.url_to_repo} #{path}"
-        if system(create_cmd)
+        output, status = popen("git clone #{project.url_to_repo} #{path}",
+                               Gitlab.config.satellites.path)
+
+        if status.zero?
           true
         else
           Gitlab::GitLogger.error("Failed to create satellite for #{project.name_with_namespace}")
@@ -66,6 +70,10 @@ module Gitlab
         @repo ||= Grit::Repo.new(path)
       end
 
+      def destroy
+        FileUtils.rm_rf(path)
+      end
+
       private
 
       # Clear the working directory
diff --git a/lib/tasks/sidekiq.rake b/lib/tasks/sidekiq.rake
index 0d2ec6f332c..e4eb0e6776f 100644
--- a/lib/tasks/sidekiq.rake
+++ b/lib/tasks/sidekiq.rake
@@ -6,7 +6,7 @@ namespace :sidekiq do
 
   desc "GITLAB | Start sidekiq"
   task :start do
-    run "nohup bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,common,default -e #{Rails.env} -P #{pidfile} >> #{Rails.root.join("log", "sidekiq.log")} 2>&1 &"
+    run "nohup bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,gitolite,common,default -e #{Rails.env} -P #{pidfile} >> #{Rails.root.join("log", "sidekiq.log")} 2>&1 &"
   end
 
   def pidfile
-- 
GitLab


From 8b54b7233ef58a2a39da9777dbeab59b4024cc75 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 28 Jan 2013 17:39:02 +0200
Subject: [PATCH 125/197] Async perform for add/remove team members

---
 app/models/protected_branch.rb     |  2 +-
 app/models/users_project.rb        | 12 ++++++++++--
 lib/gitlab/backend/gitolite.rb     | 26 +++++++++++++++++++-------
 spec/lib/gitolite_spec.rb          |  2 +-
 spec/support/stubbed_repository.rb |  4 ++++
 5 files changed, 35 insertions(+), 11 deletions(-)

diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb
index 3308caf360a..2e7010ea9c9 100644
--- a/app/models/protected_branch.rb
+++ b/app/models/protected_branch.rb
@@ -22,7 +22,7 @@ class ProtectedBranch < ActiveRecord::Base
   after_destroy :update_repository
 
   def update_repository
-    gitolite.update_repository(project)
+    project.update_repository
   end
 
   def commit
diff --git a/app/models/users_project.rb b/app/models/users_project.rb
index 3206600413c..183878cb30c 100644
--- a/app/models/users_project.rb
+++ b/app/models/users_project.rb
@@ -82,9 +82,13 @@ class UsersProject < ActiveRecord::Base
             users_project.save
           end
         end
-        Gitlab::Gitolite.new.update_repositories(Project.where(id: project_ids))
       end
 
+      GitoliteWorker.perform_async(
+        :update_repositories,
+        project_ids
+      )
+
       true
     rescue
       false
@@ -97,9 +101,13 @@ class UsersProject < ActiveRecord::Base
           users_project.skip_git = true
           users_project.destroy
         end
-        Gitlab::Gitolite.new.update_repositories(Project.where(id: project_ids))
       end
 
+      GitoliteWorker.perform_async(
+        :update_repositories,
+        project_ids
+      )
+
       true
     rescue
       false
diff --git a/lib/gitlab/backend/gitolite.rb b/lib/gitlab/backend/gitolite.rb
index d026b76f5ef..1bcf1264fa9 100644
--- a/lib/gitlab/backend/gitolite.rb
+++ b/lib/gitlab/backend/gitolite.rb
@@ -22,7 +22,12 @@ module Gitlab
       end
     end
 
-    def update_repository project_id
+    # Update project config in gitolite by project id
+    #
+    # Ex.
+    #   update_repository(23)
+    #
+    def update_repository(project_id)
       project = Project.find(project_id)
       config.update_project!(project)
     end
@@ -45,6 +50,19 @@ module Gitlab
       config.destroy_project!(name)
     end
 
+    # Update projects configs in gitolite by project ids
+    #
+    # Ex.
+    #   update_repositories([1, 4, 6])
+    #
+    def update_repositories(project_ids)
+      projects = Project.where(id: project_ids)
+
+      config.apply do |config|
+        config.update_projects(projects)
+      end
+    end
+
     def url_to_repo path
       Gitlab.config.gitolite.ssh_path_prefix + "#{path}.git"
     end
@@ -53,12 +71,6 @@ module Gitlab
       config.admin_all_repo!
     end
 
-    def update_repositories projects
-      config.apply do |config|
-        config.update_projects(projects)
-      end
-    end
-
     alias_method :create_repository, :update_repository
   end
 end
diff --git a/spec/lib/gitolite_spec.rb b/spec/lib/gitolite_spec.rb
index 8075b99ed99..df6dc368820 100644
--- a/spec/lib/gitolite_spec.rb
+++ b/spec/lib/gitolite_spec.rb
@@ -20,6 +20,6 @@ describe Gitlab::Gitolite do
 
   it "should call config update" do
     gitolite_config.should_receive(:update_project!)
-    gitolite.update_repository project
+    gitolite.update_repository(project.id)
   end
 end
diff --git a/spec/support/stubbed_repository.rb b/spec/support/stubbed_repository.rb
index e6e194d70f5..e092f8a4776 100644
--- a/spec/support/stubbed_repository.rb
+++ b/spec/support/stubbed_repository.rb
@@ -21,6 +21,10 @@ class Project
       true
     end
 
+    def destroy
+      true
+    end
+
     def create
       true
     end
-- 
GitLab


From 9ad5fbb416b00bf87c5f5ab3e1ee7ac5d5378b64 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 28 Jan 2013 17:46:24 +0200
Subject: [PATCH 126/197] user factory username over sequence

---
 spec/factories.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/spec/factories.rb b/spec/factories.rb
index 593b8350fda..0e0c04f9875 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -12,7 +12,7 @@ FactoryGirl.define do
   factory :user, aliases: [:author, :assignee, :owner, :creator] do
     email { Faker::Internet.email }
     name
-    username { Faker::Internet.user_name }
+    sequence(:username) { |n| "#{Faker::Internet.user_name}#{n}" }
     password "123456"
     password_confirmation { password }
 
-- 
GitLab


From f7ade3b682a104dca76b0eb4e9a0fbc62cfd9cf7 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 28 Jan 2013 17:53:01 +0200
Subject: [PATCH 127/197] fix tests

---
 spec/lib/gitolite_spec.rb | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/spec/lib/gitolite_spec.rb b/spec/lib/gitolite_spec.rb
index df6dc368820..7ba4a633fb1 100644
--- a/spec/lib/gitolite_spec.rb
+++ b/spec/lib/gitolite_spec.rb
@@ -1,12 +1,13 @@
 require 'spec_helper'
 
 describe Gitlab::Gitolite do
-  let(:project) { double('Project', path: 'diaspora') }
+  let(:project) { double('Project', id: 7, path: 'diaspora') }
   let(:gitolite_config) { double('Gitlab::GitoliteConfig') }
   let(:gitolite) { Gitlab::Gitolite.new }
 
   before do
     gitolite.stub(config: gitolite_config)
+    Project.stub(find: project)
   end
 
   it { should respond_to :set_key }
-- 
GitLab


From 299a9a10400e7fdcc641a90db95290322058c529 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 28 Jan 2013 21:02:10 +0200
Subject: [PATCH 128/197] keys to gitolite via sidekiq now

---
 app/observers/key_observer.rb  | 14 ++++++++++++--
 app/workers/gitolite_worker.rb |  4 ++--
 lib/gitlab/backend/gitolite.rb | 18 ++++++++++++++++--
 3 files changed, 30 insertions(+), 6 deletions(-)

diff --git a/app/observers/key_observer.rb b/app/observers/key_observer.rb
index bf5fa647647..44e78643d83 100644
--- a/app/observers/key_observer.rb
+++ b/app/observers/key_observer.rb
@@ -2,11 +2,21 @@ class KeyObserver < ActiveRecord::Observer
   include Gitolited
 
   def after_save(key)
-    gitolite.set_key(key.identifier, key.key, key.projects)
+    GitoliteWorker.perform_async(
+      :set_key,
+      key.identifier,
+      key.key,
+      key.projects.map(&:id)
+    )
   end
 
   def after_destroy(key)
     return if key.is_deploy_key && !key.last_deploy?
-    gitolite.remove_key(key.identifier, key.projects)
+
+    GitoliteWorker.perform_async(
+      :remove_key,
+      key.identifier,
+      key.projects.map(&:id)
+    )
   end
 end
diff --git a/app/workers/gitolite_worker.rb b/app/workers/gitolite_worker.rb
index d134ea035f4..bff7a8c6a6f 100644
--- a/app/workers/gitolite_worker.rb
+++ b/app/workers/gitolite_worker.rb
@@ -4,7 +4,7 @@ class GitoliteWorker
 
   sidekiq_options queue: :gitolite
 
-  def perform(action, arg)
-    gitolite.send(action, arg)
+  def perform(action, *arg)
+    gitolite.send(action, *arg)
   end
 end
diff --git a/lib/gitlab/backend/gitolite.rb b/lib/gitlab/backend/gitolite.rb
index 1bcf1264fa9..cd9ac1554d6 100644
--- a/lib/gitlab/backend/gitolite.rb
+++ b/lib/gitlab/backend/gitolite.rb
@@ -8,14 +8,28 @@ module Gitlab
       Gitlab::GitoliteConfig.new
     end
 
-    def set_key key_id, key_content, projects
+    # Update gitolite config with new key
+    #
+    # Ex.
+    #   set_key("m_gitlab_com_12343", "sha-rsa ...", [2, 3, 6])
+    #
+    def set_key(key_id, key_content, project_ids)
+      projects = Project.where(id: project_ids)
+
       config.apply do |config|
         config.write_key(key_id, key_content)
         config.update_projects(projects)
       end
     end
 
-    def remove_key key_id, projects
+    # Remove ssh key from gitolite config
+    #
+    # Ex.
+    #   remove_key("m_gitlab_com_12343", [2, 3, 6])
+    #
+    def remove_key(key_id, project_ids)
+      projects = Project.where(id: project_ids)
+
       config.apply do |config|
         config.rm_key(key_id)
         config.update_projects(projects)
-- 
GitLab


From 1c931fb81477397929a31a6b95c5d65b6d582182 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 28 Jan 2013 23:03:38 +0200
Subject: [PATCH 129/197] fix key observer tests

---
 app/observers/project_observer.rb   |  2 +-
 spec/observers/key_observer_spec.rb | 10 ++--------
 2 files changed, 3 insertions(+), 9 deletions(-)

diff --git a/app/observers/project_observer.rb b/app/observers/project_observer.rb
index cc454ae3e35..ccdb146140b 100644
--- a/app/observers/project_observer.rb
+++ b/app/observers/project_observer.rb
@@ -15,7 +15,7 @@ class ProjectObserver < ActiveRecord::Observer
   end
 
   def after_create project
-    log_info("#{project.owner.name} created a new project \"#{project.name}\"")
+    log_info("#{project.owner.name} created a new project \"#{project.name_with_namespace}\"")
   end
 
   protected
diff --git a/spec/observers/key_observer_spec.rb b/spec/observers/key_observer_spec.rb
index ae7b0f73e57..11f975cc57d 100644
--- a/spec/observers/key_observer_spec.rb
+++ b/spec/observers/key_observer_spec.rb
@@ -9,25 +9,19 @@ describe KeyObserver do
       is_deploy_key: false
     )
 
-    @gitolite = double('Gitlab::Gitolite',
-      set_key: true,
-      remove_key: true
-    )
-
     @observer = KeyObserver.instance
-    @observer.stub(gitolite: @gitolite)
   end
 
   context :after_save do
     it do
-      @gitolite.should_receive(:set_key).with(@key.identifier, @key.key, @key.projects)
+      GitoliteWorker.should_receive(:perform_async).with(:set_key, @key.identifier, @key.key, @key.projects.map(&:id))
       @observer.after_save(@key)
     end
   end
 
   context :after_destroy do
     it do
-      @gitolite.should_receive(:remove_key).with(@key.identifier, @key.projects)
+      GitoliteWorker.should_receive(:perform_async).with(:remove_key, @key.identifier, @key.projects.map(&:id))
       @observer.after_destroy(@key)
     end
   end
-- 
GitLab


From f72dc7f7798f521d20a71fb465df57f0d66befb5 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 29 Jan 2013 11:00:56 +0200
Subject: [PATCH 130/197] dont escape images inside links for gfm. Fixes #2701

---
 app/helpers/gitlab_markdown_helper.rb | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb
index 111982e9147..1a3d34eb886 100644
--- a/app/helpers/gitlab_markdown_helper.rb
+++ b/app/helpers/gitlab_markdown_helper.rb
@@ -13,7 +13,13 @@ module GitlabMarkdownHelper
   def link_to_gfm(body, url, html_options = {})
     return "" if body.blank?
 
-    gfm_body = gfm(escape_once(body), html_options)
+    escaped_body = if body =~ /^\<img/
+                     body
+                   else
+                     escape_once(body)
+                   end
+
+    gfm_body = gfm(escaped_body, html_options)
 
     gfm_body.gsub!(%r{<a.*?>.*?</a>}m) do |match|
       "</a>#{match}#{link_to("", url, html_options)[0..-5]}" # "</a>".length +1
-- 
GitLab


From 7121a58eb9e4dcb63d762e17a668f3bb4b0eaa85 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 29 Jan 2013 11:32:05 +0200
Subject: [PATCH 131/197] Advanced logging for post-receive worker

---
 app/workers/post_receive.rb | 14 ++++++++++++--
 config/gitlab.yml.example   |  3 ++-
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb
index a906f78f7e3..6d31c08fefc 100644
--- a/app/workers/post_receive.rb
+++ b/app/workers/post_receive.rb
@@ -4,12 +4,22 @@ class PostReceive
   sidekiq_options queue: :post_receive
 
   def perform(repo_path, oldrev, newrev, ref, identifier)
-    repo_path.gsub!(Gitlab.config.gitolite.repos_path.to_s, "")
+
+    if repo_path.start_with?(Gitlab.config.gitolite.repos_path.to_s)
+      repo_path.gsub!(Gitlab.config.gitolite.repos_path.to_s, "")
+    else
+      Gitlab::GitLogger.error("POST-RECEIVE: Check gitlab.yml config for correct gitolite.repos_path variable. \"#{Gitlab.config.gitolite.repos_path}\" does not match \"#{repo_path}\"")
+    end
+
     repo_path.gsub!(/.git$/, "")
     repo_path.gsub!(/^\//, "")
 
     project = Project.find_with_namespace(repo_path)
-    return false if project.nil?
+
+    if project.nil?
+      Gitlab::GitLogger.error("POST-RECEIVE: Triggered hook for non-existing project with full path \"#{repo_path} \"")
+      return false
+    end
 
     # Ignore push from non-gitlab users
     user = if identifier.eql? Gitlab.config.gitolite.admin_key
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 4df8efa9c06..1a34d22417f 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -106,7 +106,8 @@ backup:
 ## Gitolite settings
 gitolite:
   admin_uri: git@localhost:gitolite-admin
-  # repos_path must not be a symlink
+
+  # REPOS_PATH MUST NOT BE A SYMLINK!!!
   repos_path: /home/git/repositories/
   hooks_path: /home/git/.gitolite/hooks/
   admin_key: gitlab
-- 
GitLab


From c84675ee06dfc72c46c178ef40e30f03053dcc5a Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 29 Jan 2013 12:12:24 +0200
Subject: [PATCH 132/197] satellites logs

---
 lib/gitlab/satellite/logger.rb    | 13 +++++++++++++
 lib/gitlab/satellite/satellite.rb |  9 ++++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)
 create mode 100644 lib/gitlab/satellite/logger.rb

diff --git a/lib/gitlab/satellite/logger.rb b/lib/gitlab/satellite/logger.rb
new file mode 100644
index 00000000000..6f3f8255aca
--- /dev/null
+++ b/lib/gitlab/satellite/logger.rb
@@ -0,0 +1,13 @@
+module Gitlab
+  module Satellite
+    class Logger < Gitlab::Logger
+      def self.file_name
+        'satellites.log'
+      end
+
+      def format_message(severity, timestamp, progname, msg)
+        "#{timestamp.to_s(:long)}: #{msg}\n"
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/satellite/satellite.rb b/lib/gitlab/satellite/satellite.rb
index d8e8f58963b..95273a6d208 100644
--- a/lib/gitlab/satellite/satellite.rb
+++ b/lib/gitlab/satellite/satellite.rb
@@ -13,6 +13,10 @@ module Gitlab
         @project = project
       end
 
+      def log message
+        Gitlab::Satellite::Logger.error(message)
+      end
+
       def raise_no_satellite
         raise SatelliteNotExistError.new("Satellite doesn't exist")
       end
@@ -29,10 +33,13 @@ module Gitlab
         output, status = popen("git clone #{project.url_to_repo} #{path}",
                                Gitlab.config.satellites.path)
 
+        log("PID: #{project.id}: git clone #{project.url_to_repo} #{path}")
+        log("PID: #{project.id}: -> #{output}")
+
         if status.zero?
           true
         else
-          Gitlab::GitLogger.error("Failed to create satellite for #{project.name_with_namespace}")
+          log("Failed to create satellite for #{project.name_with_namespace}")
           false
         end
       end
-- 
GitLab


From 9fdbdc662a01ac0845638c1012aa0625de6158be Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 29 Jan 2013 14:49:10 +0200
Subject: [PATCH 133/197] set link to gitlab-ci

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 1a43be134da..ee029f9bfcb 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
 
 GitLab is a free project and repository management application
 
-![CI](http://ci.gitlab.org/projects/1/status?ref=master)
+[![CI](http://ci.gitlab.org/projects/1/status?ref=master)](http://ci.gitlab.org/projects/1?ref=master)
 
 ## Application details
 
-- 
GitLab


From cdd55431735ab359f12bb9b6e203c0face879272 Mon Sep 17 00:00:00 2001
From: Carlos Xudiera <xudiera@gmail.com>
Date: Tue, 29 Jan 2013 12:58:34 -0500
Subject: [PATCH 134/197] Fixed a grammar mistake in
 alert-message.block-message

---
 app/views/commits/_diffs.html.haml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/views/commits/_diffs.html.haml b/app/views/commits/_diffs.html.haml
index 9a9aed39b08..556e67f6cda 100644
--- a/app/views/commits/_diffs.html.haml
+++ b/app/views/commits/_diffs.html.haml
@@ -1,7 +1,7 @@
 - if @suppress_diff
   .alert-message.block-message
     %p
-      %strong Warning! Large commit with more then #{Commit::DIFF_SAFE_SIZE} files changed.
+      %strong Warning! Large commit with more than #{Commit::DIFF_SAFE_SIZE} files changed.
     %p To prevent performance issue we rejected diff information.
     %p
       But if you still want to see diff
-- 
GitLab


From 033aa1a885801c299a20ab39af6f897bb53dc3d4 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 29 Jan 2013 22:18:19 +0200
Subject: [PATCH 135/197] refactor buttons pt1

---
 .../stylesheets/gitlab_bootstrap/buttons.scss | 31 +++++++++----------
 app/assets/stylesheets/sections/notes.scss    |  6 ++--
 app/views/admin/groups/edit.html.haml         |  4 +--
 app/views/admin/groups/index.html.haml        |  4 +--
 app/views/admin/groups/new.html.haml          |  2 +-
 app/views/admin/groups/show.html.haml         |  8 ++---
 app/views/admin/hooks/index.html.haml         |  2 +-
 app/views/admin/projects/_form.html.haml      |  4 +--
 app/views/admin/projects/index.html.haml      |  4 +--
 .../admin/projects/members/_form.html.haml    |  2 +-
 app/views/admin/projects/show.html.haml       |  4 +--
 app/views/admin/teams/edit.html.haml          |  4 +--
 app/views/admin/teams/index.html.haml         |  4 +--
 app/views/admin/teams/members/_form.html.haml |  2 +-
 app/views/admin/teams/members/new.html.haml   |  2 +-
 app/views/admin/teams/new.html.haml           |  2 +-
 .../admin/teams/projects/_form.html.haml      |  2 +-
 app/views/admin/teams/projects/new.html.haml  |  2 +-
 app/views/admin/teams/show.html.haml          | 10 +++---
 app/views/admin/users/_form.html.haml         |  8 ++---
 app/views/admin/users/index.html.haml         |  6 ++--
 app/views/admin/users/show.html.haml          |  4 +--
 app/views/commits/_commit_box.html.haml       |  2 +-
 app/views/compare/_form.html.haml             |  2 +-
 .../_zero_authorized_projects.html.haml       |  2 +-
 app/views/deploy_keys/_form.html.haml         |  4 +--
 app/views/devise/passwords/edit.html.haml     |  2 +-
 app/views/devise/passwords/new.html.erb       |  2 +-
 app/views/devise/registrations/new.html.haml  |  2 +-
 app/views/devise/sessions/_new_ldap.html.haml |  6 ++--
 app/views/devise/sessions/new.html.haml       |  2 +-
 app/views/groups/_new_group_member.html.haml  |  2 +-
 app/views/groups/_new_member.html.haml        |  2 +-
 app/views/groups/new.html.haml                |  2 +-
 app/views/groups/search.html.haml             |  2 +-
 app/views/hooks/index.html.haml               |  2 +-
 app/views/issues/_form.html.haml              |  6 ++--
 app/views/issues/index.html.haml              |  4 +--
 app/views/keys/_form.html.haml                |  4 +--
 app/views/keys/_show.html.haml                |  2 +-
 app/views/keys/show.html.haml                 |  2 +-
 app/views/merge_requests/_form.html.haml      | 10 +++---
 app/views/merge_requests/index.html.haml      |  2 +-
 app/views/milestones/_form.html.haml          | 10 +++---
 app/views/milestones/show.html.haml           |  2 +-
 app/views/profiles/account.html.haml          |  6 ++--
 app/views/profiles/show.html.haml             |  2 +-
 app/views/projects/_form.html.haml            |  4 +--
 app/views/projects/_new_form.html.haml        |  2 +-
 app/views/projects/empty.html.haml            |  2 +-
 app/views/projects/teams/available.html.haml  |  4 +--
 app/views/protected_branches/index.html.haml  |  2 +-
 app/views/search/show.html.haml               |  2 +-
 app/views/services/_gitlab_ci.html.haml       |  2 +-
 app/views/snippets/_form.html.haml            |  2 +-
 app/views/team_members/_form.html.haml        |  4 +--
 app/views/team_members/_show.html.haml        |  2 +-
 app/views/team_members/_show_team.html.haml   |  2 +-
 app/views/team_members/import.html.haml       |  4 +--
 app/views/team_members/index.html.haml        |  2 +-
 app/views/team_members/show.html.haml         |  2 +-
 app/views/teams/edit.html.haml                |  4 +--
 app/views/teams/members/_form.html.haml       |  2 +-
 app/views/teams/members/_show.html.haml       |  4 +--
 app/views/teams/members/index.html.haml       |  2 +-
 app/views/teams/members/new.html.haml         |  2 +-
 app/views/teams/members/show.html.haml        |  2 +-
 app/views/teams/new.html.haml                 |  2 +-
 app/views/teams/projects/_form.html.haml      |  4 +--
 app/views/teams/projects/edit.html.haml       | 14 ++-------
 app/views/teams/projects/index.html.haml      |  4 +--
 app/views/teams/projects/new.html.haml        |  2 +-
 app/views/tree/edit.html.haml                 |  4 +--
 app/views/wikis/_form.html.haml               |  4 +--
 app/views/wikis/edit.html.haml                |  2 +-
 75 files changed, 139 insertions(+), 150 deletions(-)

diff --git a/app/assets/stylesheets/gitlab_bootstrap/buttons.scss b/app/assets/stylesheets/gitlab_bootstrap/buttons.scss
index 674481e2cd2..ed102253ab6 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/buttons.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/buttons.scss
@@ -7,11 +7,7 @@
     color: #333;
   }
 
-  &.btn-white {
-    background: #FFF;
-  }
-
-  &.primary {
+  &.btn-primary {
     background: #2a79A3;
     @include linear-gradient(#47A7b7, #2585b5);
     border-color: #2A79A3;
@@ -58,21 +54,17 @@
     }
   }
 
-  &.save-btn {
+  &.btn-create {
     @extend .wide;
-    @extend .primary;
-  }
-
-  &.cancel-btn {
-    float: right;
+    @extend .success;
   }
 
-  &.wide {
-    padding-left: 30px;
-    padding-right: 30px;
+  &.btn-save {
+    @extend .wide;
+    @extend .btn-primary;
   }
 
-  &.danger {
+  &.btn-remove {
     @extend .btn-danger;
     border-color: #BD362F;
 
@@ -82,8 +74,13 @@
     }
   }
 
-  &.danger {
-    @extend .btn-danger;
+  &.btn-cancel {
+    float: right;
+  }
+
+  &.wide {
+    padding-left: 20px;
+    padding-right: 20px;
   }
 
   &.small {
diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss
index 7a1cc444e5d..d4934791110 100644
--- a/app/assets/stylesheets/sections/notes.scss
+++ b/app/assets/stylesheets/sections/notes.scss
@@ -214,9 +214,11 @@ ul.notes {
  * Note Form
  */
 
-.comment-btn,
+.comment-btn {
+  @extend .create-btn;
+}
 .reply-btn {
-  @extend .save-btn;
+  @extend .primary;
 }
 .file .content tr.line_holder:hover > td { background: $hover !important; }
 .file .content tr.line_holder:hover > td .line_note_link {
diff --git a/app/views/admin/groups/edit.html.haml b/app/views/admin/groups/edit.html.haml
index 901d07e74f3..6ec520e74b4 100644
--- a/app/views/admin/groups/edit.html.haml
+++ b/app/views/admin/groups/edit.html.haml
@@ -24,5 +24,5 @@
         %li It will change the git path to repositories under this group.
 
   .form-actions
-    = f.submit 'Rename group', class: "btn danger"
-    = link_to  'Cancel', admin_groups_path, class: "btn cancel-btn"
+    = f.submit 'Rename group', class: "btn btn-remove"
+    = link_to  'Cancel', admin_groups_path, class: "btn btn-cancel"
diff --git a/app/views/admin/groups/index.html.haml b/app/views/admin/groups/index.html.haml
index 49acedc8c79..443abece919 100644
--- a/app/views/admin/groups/index.html.haml
+++ b/app/views/admin/groups/index.html.haml
@@ -8,7 +8,7 @@
 %br
 = form_tag admin_groups_path, method: :get, class: 'form-inline' do
   = text_field_tag :name, params[:name], class: "xlarge"
-  = submit_tag "Search", class: "btn submit primary"
+  = submit_tag "Search", class: "btn submit btn-primary"
 
 %table
   %thead
@@ -31,5 +31,5 @@
         = link_to group.owner_name, admin_user_path(group.owner_id)
       %td.bgred
         = link_to 'Rename', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: "btn small"
-        = link_to 'Destroy', [:admin, group], confirm: "REMOVE #{group.name}? Are you sure?", method: :delete, class: "btn small danger"
+        = link_to 'Destroy', [:admin, group], confirm: "REMOVE #{group.name}? Are you sure?", method: :delete, class: "btn small btn-remove"
 = paginate @groups, theme: "admin"
diff --git a/app/views/admin/groups/new.html.haml b/app/views/admin/groups/new.html.haml
index 6ff0e781d17..f8d1dfcf931 100644
--- a/app/views/admin/groups/new.html.haml
+++ b/app/views/admin/groups/new.html.haml
@@ -10,7 +10,7 @@
     .input
       = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
       &nbsp;
-      = f.submit 'Create group', class: "btn primary"
+      = f.submit 'Create group', class: "btn btn-primary"
   %hr
   .padded
     %ul
diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml
index e347f916c4f..b5bdeeaaded 100644
--- a/app/views/admin/groups/show.html.haml
+++ b/app/views/admin/groups/show.html.haml
@@ -42,7 +42,7 @@
       = form_for [:admin, @group] do |f|
         = f.select :owner_id, User.all.map { |user| [user.name, user.id] }, {}, {class: 'chosen'}
         %div
-          = f.submit 'Change Owner', class: "btn danger"
+          = f.submit 'Change Owner', class: "btn btn-remove"
           = link_to "Cancel", "#", class: "btn change-owner-cancel-link"
 
 - if @group.projects.any?
@@ -63,7 +63,7 @@
             %span.monospace= project.path_with_namespace + ".git"
           %td= project.users.count
           %td.bgred
-            = link_to 'Transfer project to global namespace', remove_project_admin_group_path(@group, project_id: project.id), confirm: 'Remove project from group and move to global namespace. Are you sure?', method: :delete, class: "btn danger small"
+            = link_to 'Transfer project to global namespace', remove_project_admin_group_path(@group, project_id: project.id), confirm: 'Remove project from group and move to global namespace. Are you sure?', method: :delete, class: "btn btn-remove small"
 
   = form_tag project_teams_update_admin_group_path(@group), id: "new_team_member", class: "bulk_import", method: :put  do
     %table.zebra-striped
@@ -88,7 +88,7 @@
         %td= select_tag :project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3"}
 
       %tr
-        %td= submit_tag 'Add user to projects in group', class: "btn primary"
+        %td= submit_tag 'Add user to projects in group', class: "btn btn-primary"
         %td
           Read more about project permissions
           %strong= link_to "here", help_permissions_path, class: "vlink"
@@ -110,7 +110,7 @@
       .input
         = select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name_with_namespace), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5'
     .form-actions
-      = submit_tag 'Add', class: "btn primary"
+      = submit_tag 'Add', class: "btn btn-primary"
 
 :javascript
   $(function(){
diff --git a/app/views/admin/hooks/index.html.haml b/app/views/admin/hooks/index.html.haml
index f17355fb2c2..15bff871cd5 100644
--- a/app/views/admin/hooks/index.html.haml
+++ b/app/views/admin/hooks/index.html.haml
@@ -15,7 +15,7 @@
     .input
       = f.text_field :url, class: "text_field xxlarge"
       &nbsp;
-      = f.submit "Add System Hook", class: "btn primary"
+      = f.submit "Add System Hook", class: "btn btn-primary"
 %hr
 
 -if @hooks.any?
diff --git a/app/views/admin/projects/_form.html.haml b/app/views/admin/projects/_form.html.haml
index 0c7cf68ef43..6342802c699 100644
--- a/app/views/admin/projects/_form.html.haml
+++ b/app/views/admin/projects/_form.html.haml
@@ -65,8 +65,8 @@
 
 
   .actions
-    = f.submit 'Save Project', class: "btn save-btn"
-    = link_to 'Cancel', admin_projects_path, class: "btn cancel-btn"
+    = f.submit 'Save Project', class: "btn btn-save"
+    = link_to 'Cancel', admin_projects_path, class: "btn btn-cancel"
 
 
 
diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml
index e47cda76636..8ac2fa12520 100644
--- a/app/views/admin/projects/index.html.haml
+++ b/app/views/admin/projects/index.html.haml
@@ -37,7 +37,7 @@
 
 
         .form-actions
-          = submit_tag "Search", class: "btn submit primary"
+          = submit_tag "Search", class: "btn submit btn-primary"
           = link_to "Reset", admin_projects_path, class: "btn"
   .span8
     .ui-box
@@ -53,7 +53,7 @@
             = link_to project.name_with_namespace, [:admin, project]
             .right
               = link_to 'Edit', edit_admin_project_path(project), id: "edit_#{dom_id(project)}", class: "btn small"
-              = link_to 'Destroy', [:admin, project], confirm: "REMOVE #{project.name}? Are you sure?", method: :delete, class: "btn small danger"
+              = link_to 'Destroy', [:admin, project], confirm: "REMOVE #{project.name}? Are you sure?", method: :delete, class: "btn small btn-remove"
         - if @projects.blank?
           %p.nothing_here_message 0 projects matches
         - else
diff --git a/app/views/admin/projects/members/_form.html.haml b/app/views/admin/projects/members/_form.html.haml
index f1bb6cfa226..bbd419be576 100644
--- a/app/views/admin/projects/members/_form.html.haml
+++ b/app/views/admin/projects/members/_form.html.haml
@@ -12,5 +12,5 @@
 
   %br
   .actions
-    = f.submit 'Save', class: "btn primary"
+    = f.submit 'Save', class: "btn btn-primary"
     = link_to 'Cancel', :back, class: "btn"
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index a213c09d456..fb1a7b488c1 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -130,7 +130,7 @@
         = link_to tm.name, admin_user_path(tm)
       %td= @project.project_access_human(tm)
       %td= link_to 'Edit Access', edit_admin_project_member_path(@project, tm), class: "btn small"
-      %td= link_to 'Remove from team', admin_project_member_path(@project, tm), confirm: 'Are you sure?', method: :delete, class: "btn danger small"
+      %td= link_to 'Remove from team', admin_project_member_path(@project, tm), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove small"
 
 %br
 %h5 Add new team member
@@ -147,7 +147,7 @@
       %td= select_tag :project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3"}
 
     %tr
-      %td= submit_tag 'Add', class: "btn primary"
+      %td= submit_tag 'Add', class: "btn btn-primary"
       %td
         Read more about project permissions
         %strong= link_to "here", help_permissions_path, class: "vlink"
diff --git a/app/views/admin/teams/edit.html.haml b/app/views/admin/teams/edit.html.haml
index b2499ef6b8b..d024d82381a 100644
--- a/app/views/admin/teams/edit.html.haml
+++ b/app/views/admin/teams/edit.html.haml
@@ -19,5 +19,5 @@
         %li It will change web url for access team and team projects.
 
   .form-actions
-    = f.submit 'Rename team', class: "btn danger"
-    = link_to  'Cancel', admin_teams_path, class: "btn cancel-btn"
+    = f.submit 'Rename team', class: "btn btn-remove"
+    = link_to  'Cancel', admin_teams_path, class: "btn btn-cancel"
diff --git a/app/views/admin/teams/index.html.haml b/app/views/admin/teams/index.html.haml
index 3ab57448ab2..e7344f4ea2c 100644
--- a/app/views/admin/teams/index.html.haml
+++ b/app/views/admin/teams/index.html.haml
@@ -8,7 +8,7 @@
 
 = form_tag admin_teams_path, method: :get, class: 'form-inline' do
   = text_field_tag :name, params[:name], class: "xlarge"
-  = submit_tag "Search", class: "btn submit primary"
+  = submit_tag "Search", class: "btn submit btn-primary"
 
 %table
   %thead
@@ -33,6 +33,6 @@
         = link_to team.owner.name, admin_user_path(team.owner_id)
       %td.bgred
         = link_to 'Rename', edit_admin_team_path(team), id: "edit_#{dom_id(team)}", class: "btn small"
-        = link_to 'Destroy', admin_team_path(team), confirm: "REMOVE #{team.name}? Are you sure?", method: :delete, class: "btn small danger"
+        = link_to 'Destroy', admin_team_path(team), confirm: "REMOVE #{team.name}? Are you sure?", method: :delete, class: "btn small btn-remove"
 
 = paginate @teams, theme: "admin"
diff --git a/app/views/admin/teams/members/_form.html.haml b/app/views/admin/teams/members/_form.html.haml
index b75d788a94a..098118a645d 100644
--- a/app/views/admin/teams/members/_form.html.haml
+++ b/app/views/admin/teams/members/_form.html.haml
@@ -16,5 +16,5 @@
 
   %br
   .actions
-    = submit_tag 'Save', class: "btn primary"
+    = submit_tag 'Save', class: "btn btn-primary"
     = link_to 'Cancel', :back, class: "btn"
diff --git a/app/views/admin/teams/members/new.html.haml b/app/views/admin/teams/members/new.html.haml
index 066ab19fd08..a37c941db53 100644
--- a/app/views/admin/teams/members/new.html.haml
+++ b/app/views/admin/teams/members/new.html.haml
@@ -26,4 +26,4 @@
         %td
           %span= check_box_tag :group_admin
           %span Admin?
-        %td= submit_tag 'Add', class: "btn primary", id: :add_members_to_team
+        %td= submit_tag 'Add', class: "btn btn-primary", id: :add_members_to_team
diff --git a/app/views/admin/teams/new.html.haml b/app/views/admin/teams/new.html.haml
index a40a2c4ebf9..7483f1bf32d 100644
--- a/app/views/admin/teams/new.html.haml
+++ b/app/views/admin/teams/new.html.haml
@@ -10,7 +10,7 @@
     .input
       = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
       &nbsp;
-      = f.submit 'Create team', class: "btn primary"
+      = f.submit 'Create team', class: "btn btn-primary"
   %hr
   .padded
     %ul
diff --git a/app/views/admin/teams/projects/_form.html.haml b/app/views/admin/teams/projects/_form.html.haml
index db4fe85b000..9ba406ea125 100644
--- a/app/views/admin/teams/projects/_form.html.haml
+++ b/app/views/admin/teams/projects/_form.html.haml
@@ -12,5 +12,5 @@
 
   %br
   .actions
-    = submit_tag 'Save', class: "btn primary"
+    = submit_tag 'Save', class: "btn btn-primary"
     = link_to 'Cancel', :back, class: "btn"
diff --git a/app/views/admin/teams/projects/new.html.haml b/app/views/admin/teams/projects/new.html.haml
index 8a0a18a48c0..b60dad35214 100644
--- a/app/views/admin/teams/projects/new.html.haml
+++ b/app/views/admin/teams/projects/new.html.haml
@@ -20,4 +20,4 @@
       %tr
         %td= select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name_with_namespace), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5'
         %td= select_tag :greatest_project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3" }
-        %td= submit_tag 'Add', class: "btn primary", id: :assign_projects_to_team
+        %td= submit_tag 'Add', class: "btn btn-primary", id: :assign_projects_to_team
diff --git a/app/views/admin/teams/show.html.haml b/app/views/admin/teams/show.html.haml
index 6a1deaff989..2561e3aeaf5 100644
--- a/app/views/admin/teams/show.html.haml
+++ b/app/views/admin/teams/show.html.haml
@@ -36,13 +36,13 @@
       = form_for @team, url: admin_team_path(@team) do |f|
         = f.select :owner_id, User.all.map { |user| [user.name, user.id] }, {}, {class: 'chosen'}
         %div
-          = f.submit 'Change Owner', class: "btn danger"
+          = f.submit 'Change Owner', class: "btn btn-remove"
           = link_to "Cancel", "#", class: "btn change-owner-cancel-link"
 
 %fieldset
   %legend
     Members (#{@team.members.count})
-    %span= link_to 'Add members', new_admin_team_member_path(@team), class: "btn success small right", id: :add_members_to_team
+    %span= link_to 'Add members', new_admin_team_member_path(@team), class: "btn btn-primary small right", id: :add_members_to_team
   - if @team.members.any?
     %table#members_list
       %thead
@@ -62,12 +62,12 @@
           %td.bgred
             = link_to 'Edit', edit_admin_team_member_path(@team, member), class: "btn small"
             &nbsp;
-            = link_to 'Remove', admin_team_member_path(@team, member), confirm: 'Remove member from team. Are you sure?', method: :delete, class: "btn danger small", id: "remove_member_#{member.id}"
+            = link_to 'Remove', admin_team_member_path(@team, member), confirm: 'Remove member from team. Are you sure?', method: :delete, class: "btn btn-remove small", id: "remove_member_#{member.id}"
 
 %fieldset
   %legend
     Projects (#{@team.projects.count})
-    %span= link_to 'Add projects', new_admin_team_project_path(@team), class: "btn success small right", id: :assign_projects_to_team
+    %span= link_to 'Add projects', new_admin_team_project_path(@team), class: "btn btn-primary small right", id: :assign_projects_to_team
   - if @team.projects.any?
     %table#projects_list
       %thead
@@ -84,7 +84,7 @@
           %td.bgred
             = link_to 'Edit', edit_admin_team_project_path(@team, project), class: "btn small"
             &nbsp;
-            = link_to 'Relegate', admin_team_project_path(@team, project), confirm: 'Remove project from team. Are you sure?', method: :delete, class: "btn danger small", id: "relegate_project_#{project.id}"
+            = link_to 'Relegate', admin_team_project_path(@team, project), confirm: 'Remove project from team. Are you sure?', method: :delete, class: "btn btn-remove small", id: "relegate_project_#{project.id}"
 
 :javascript
   $(function(){
diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml
index 465568ade9e..9f447bcd9e7 100644
--- a/app/views/admin/users/_form.html.haml
+++ b/app/views/admin/users/_form.html.haml
@@ -66,7 +66,7 @@
                 = link_to 'Unblock User', unblock_admin_user_path(@admin_user), method: :put, class: "btn small"
               - else
                 %p Blocked users will be removed from all projects &amp; will not be able to login to GitLab.
-                = link_to 'Block User', block_admin_user_path(@admin_user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn small danger"
+                = link_to 'Block User', block_admin_user_path(@admin_user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn small btn-remove"
     %fieldset
       %legend Profile
       .clearfix
@@ -80,8 +80,8 @@
         .input= f.text_field :twitter
 
     .actions
-      = f.submit 'Save', class: "btn save-btn"
+      = f.submit 'Save', class: "btn btn-save"
       - if @admin_user.new_record?
-        = link_to 'Cancel', admin_users_path, class: "btn cancel-btn"
+        = link_to 'Cancel', admin_users_path, class: "btn btn-cancel"
       - else
-        = link_to 'Cancel', admin_user_path(@admin_user), class: "btn cancel-btn"
+        = link_to 'Cancel', admin_user_path(@admin_user), class: "btn btn-cancel"
diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml
index 87290abe7a6..0aa8a16fbc6 100644
--- a/app/views/admin/users/index.html.haml
+++ b/app/views/admin/users/index.html.haml
@@ -5,7 +5,7 @@
 
 = form_tag admin_users_path, method: :get, class: 'form-inline' do
   = text_field_tag :name, params[:name], class: "xlarge"
-  = submit_tag "Search", class: "btn submit primary"
+  = submit_tag "Search", class: "btn submit btn-primary"
 %ul.nav.nav-tabs
   %li{class: "#{'active' unless params[:filter]}"}
     = link_to admin_users_path do
@@ -52,7 +52,7 @@
           - if user.blocked
             = link_to 'Unblock', unblock_admin_user_path(user), method: :put, class: "btn small success"
           - else
-            = link_to 'Block', block_admin_user_path(user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn small danger"
-          = link_to 'Destroy', [:admin, user], confirm: "USER #{user.name} WILL BE REMOVED! Are you sure?", method: :delete, class: "btn small danger"
+            = link_to 'Block', block_admin_user_path(user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn small btn-remove"
+          = link_to 'Destroy', [:admin, user], confirm: "USER #{user.name} WILL BE REMOVED! Are you sure?", method: :delete, class: "btn small btn-remove"
 
 = paginate @admin_users, theme: "admin"
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index d9d720dad76..fefb5706a93 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -86,7 +86,7 @@
       %td= select_tag :project_access, options_for_select(Project.access_options), class: "project-access-select chosen span3"
 
     %tr
-      %td= submit_tag 'Add', class: "btn primary"
+      %td= submit_tag 'Add', class: "btn btn-primary"
       %td
         Read more about project permissions
         %strong= link_to "here", help_permissions_path, class: "vlink"
@@ -124,4 +124,4 @@
         %td= link_to project.name_with_namespace, admin_project_path(project)
         %td= tm.project_access_human
         %td= link_to 'Edit Access', edit_admin_project_member_path(project, tm.user), class: "btn small"
-        %td= link_to 'Remove from team', admin_project_member_path(project, tm.user), confirm: 'Are you sure?', method: :delete, class: "btn small danger"
+        %td= link_to 'Remove from team', admin_project_member_path(project, tm.user), confirm: 'Are you sure?', method: :delete, class: "btn small btn-remove"
diff --git a/app/views/commits/_commit_box.html.haml b/app/views/commits/_commit_box.html.haml
index 0544a1d10fe..4767c493ab7 100644
--- a/app/views/commits/_commit_box.html.haml
+++ b/app/views/commits/_commit_box.html.haml
@@ -13,7 +13,7 @@
         %ul.dropdown-menu
           %li= link_to "Email Patches", project_commit_path(@project, @commit, format: :patch)
           %li= link_to "Plain Diff",    project_commit_path(@project, @commit, format: :diff)
-      = link_to project_tree_path(@project, @commit), class: "btn primary grouped" do
+      = link_to project_tree_path(@project, @commit), class: "btn btn-primary grouped" do
         %span Browse Code »
     %h3.commit-title.page_title
       = gfm escape_once(@commit.title)
diff --git a/app/views/compare/_form.html.haml b/app/views/compare/_form.html.haml
index 0915782dddc..7c0688a2287 100644
--- a/app/views/compare/_form.html.haml
+++ b/app/views/compare/_form.html.haml
@@ -19,7 +19,7 @@
         = text_field_tag :to, params[:to], placeholder: "aa8b4ef", class: "xlarge"
       .pull-left
         &nbsp;
-        = submit_tag "Compare", class: "btn primary wide commits-compare-btn"
+        = submit_tag "Compare", class: "btn btn-primary wide commits-compare-btn"
     - if @refs_are_same
       .alert
         %span Refs are the same
diff --git a/app/views/dashboard/_zero_authorized_projects.html.haml b/app/views/dashboard/_zero_authorized_projects.html.haml
index d1676ed11fa..4b0d0d6873d 100644
--- a/app/views/dashboard/_zero_authorized_projects.html.haml
+++ b/app/views/dashboard/_zero_authorized_projects.html.haml
@@ -6,7 +6,7 @@
     = current_user.projects_limit
     projects. Click on button below to add a new one
     .link_holder
-      = link_to new_project_path, class: "btn primary" do
+      = link_to new_project_path, class: "btn btn-primary" do
         New Project »
   - else
     If you will be added to project - it will be displayed here
diff --git a/app/views/deploy_keys/_form.html.haml b/app/views/deploy_keys/_form.html.haml
index 6beba562a95..4deeb0e8e07 100644
--- a/app/views/deploy_keys/_form.html.haml
+++ b/app/views/deploy_keys/_form.html.haml
@@ -18,6 +18,6 @@
           = link_to "here", help_ssh_path
 
     .actions
-      = f.submit 'Save', class: "save-btn btn"
-      = link_to "Cancel", project_deploy_keys_path(@project), class: "btn cancel-btn"
+      = f.submit 'Save', class: "btn-save btn"
+      = link_to "Cancel", project_deploy_keys_path(@project), class: "btn btn-cancel"
 
diff --git a/app/views/devise/passwords/edit.html.haml b/app/views/devise/passwords/edit.html.haml
index 31d355673ab..6ca0c5d8c08 100644
--- a/app/views/devise/passwords/edit.html.haml
+++ b/app/views/devise/passwords/edit.html.haml
@@ -8,5 +8,5 @@
   %div
     = f.password_field :password_confirmation, class: "text bottom", placeholder: "Confirm new password"
   %div
-    = f.submit "Change my password", class: "btn primary"
+    = f.submit "Change my password", class: "btn btn-primary"
     .right= render partial: "devise/shared/links"
diff --git a/app/views/devise/passwords/new.html.erb b/app/views/devise/passwords/new.html.erb
index 860d67d19e7..1171b3bfb75 100644
--- a/app/views/devise/passwords/new.html.erb
+++ b/app/views/devise/passwords/new.html.erb
@@ -4,6 +4,6 @@
   <%= f.email_field :email, :placeholder => "Email",  :class => "text" %>
   <br/>
   <br/>
-  <%= f.submit "Reset password", :class => "primary btn"  %>
+  <%= f.submit "Reset password", :class => "btn-primary btn"  %>
   <div class="right"> <%= link_to "Sign in", new_session_path(resource_name), :class => "btn" %><br /></div>
 <% end %>
diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml
index 81eb2622261..2b72d4ade87 100644
--- a/app/views/devise/registrations/new.html.haml
+++ b/app/views/devise/registrations/new.html.haml
@@ -12,7 +12,7 @@
   %div
     = f.password_field :password_confirmation, :class => "text bottom", :placeholder => "Confirm password", :required => true
   %div
-    = f.submit "Sign up", :class => "primary btn wide"
+    = f.submit "Sign up", :class => "btn-primary btn wide"
   %br
   %hr
   = link_to "Sign in", new_session_path(resource_name)
diff --git a/app/views/devise/sessions/_new_ldap.html.haml b/app/views/devise/sessions/_new_ldap.html.haml
index 4233aa61ecb..a4060130552 100644
--- a/app/views/devise/sessions/_new_ldap.html.haml
+++ b/app/views/devise/sessions/_new_ldap.html.haml
@@ -3,11 +3,11 @@
   = text_field_tag :username, nil, {:class => "text top", :placeholder => "LDAP Login"}
   = password_field_tag :password, nil, {:class => "text bottom", :placeholder => "Password"}
   %br/
-  = submit_tag "LDAP Sign in", :class => "primary btn"
+  = submit_tag "LDAP Sign in", :class => "btn-primary btn"
   - if devise_mapping.omniauthable?
     - (resource_class.omniauth_providers - [:ldap]).each do |provider|
       %hr/
-      = link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider), :class => "btn primary"
+      = link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider), :class => "btn btn-primary"
       %br/
   %hr/
   %a#other_form_toggle{:href => "#", :onclick => "javascript:$('#new_user').toggle();"} Other Sign in
@@ -24,6 +24,6 @@
         = f.check_box :remember_me
         %span Remember me
   %br/
-  = f.submit "Sign in", :class => "primary btn"
+  = f.submit "Sign in", :class => "btn-primary btn"
   .right
     = render :partial => "devise/shared/links"
diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml
index 0983f3157c4..0a252e25487 100644
--- a/app/views/devise/sessions/new.html.haml
+++ b/app/views/devise/sessions/new.html.haml
@@ -11,7 +11,7 @@
           = f.check_box :remember_me
           %span Remember me
     %br/
-    = f.submit "Sign in", :class => "primary btn wide"
+    = f.submit "Sign in", :class => "btn-primary btn wide"
     .right
       = link_to "Forgot your password?", new_password_path(resource_name), :class => "btn"
     %br/
diff --git a/app/views/groups/_new_group_member.html.haml b/app/views/groups/_new_group_member.html.haml
index 2d599816e2a..9cdbea60370 100644
--- a/app/views/groups/_new_group_member.html.haml
+++ b/app/views/groups/_new_group_member.html.haml
@@ -14,5 +14,5 @@
 
     .form-actions
       = hidden_field_tag :redirect_to, people_group_path(@group)
-      = f.submit 'Add', class: "btn save-btn"
+      = f.submit 'Add', class: "btn btn-save"
 
diff --git a/app/views/groups/_new_member.html.haml b/app/views/groups/_new_member.html.haml
index 89ac05e774e..b3424b01bcb 100644
--- a/app/views/groups/_new_member.html.haml
+++ b/app/views/groups/_new_member.html.haml
@@ -14,5 +14,5 @@
 
     .form-actions
       = hidden_field_tag :redirect_to, people_group_path(@group, project_id: @project.id)
-      = f.submit 'Add', class: "btn save-btn"
+      = f.submit 'Add', class: "btn btn-save"
 
diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml
index b6d5f46507e..8fdedce95c9 100644
--- a/app/views/groups/new.html.haml
+++ b/app/views/groups/new.html.haml
@@ -10,7 +10,7 @@
     .input
       = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
       &nbsp;
-      = f.submit 'Create group', class: "btn primary"
+      = f.submit 'Create group', class: "btn btn-primary"
   %hr
   .padded
     %ul
diff --git a/app/views/groups/search.html.haml b/app/views/groups/search.html.haml
index 1ba4707aa52..f56bbadeac0 100644
--- a/app/views/groups/search.html.haml
+++ b/app/views/groups/search.html.haml
@@ -4,6 +4,6 @@
       %strong Looking for
     .input
       = search_field_tag :search, params[:search], placeholder: "issue 143", class: "input-xxlarge search-text-input", id: "dashboard_search"
-      = submit_tag 'Search', class: "btn primary wide"
+      = submit_tag 'Search', class: "btn btn-primary wide"
 - if params[:search].present?
   = render 'search/result'
diff --git a/app/views/hooks/index.html.haml b/app/views/hooks/index.html.haml
index 1fcf6e1c57a..98a82f110de 100644
--- a/app/views/hooks/index.html.haml
+++ b/app/views/hooks/index.html.haml
@@ -18,7 +18,7 @@
     .input
       = f.text_field :url, class: "text_field xxlarge"
       &nbsp;
-      = f.submit "Add Web Hook", class: "btn primary"
+      = f.submit "Add Web Hook", class: "btn btn-primary"
 %hr
 
 -if @hooks.any?
diff --git a/app/views/issues/_form.html.haml b/app/views/issues/_form.html.haml
index bef235f2dea..16d1b163ee8 100644
--- a/app/views/issues/_form.html.haml
+++ b/app/views/issues/_form.html.haml
@@ -44,12 +44,12 @@
 
     .actions
       - if @issue.new_record?
-        = f.submit 'Submit new issue', class: "btn success"
+        = f.submit 'Submit new issue', class: "btn btn-create"
       -else
-        = f.submit 'Save changes', class: "save-btn btn"
+        = f.submit 'Save changes', class: "btn-save btn"
 
       - cancel_path = @issue.new_record? ? project_issues_path(@project) : project_issue_path(@project, @issue)
-      = link_to "Cancel", cancel_path, class: 'btn cancel-btn'
+      = link_to "Cancel", cancel_path, class: 'btn btn-cancel'
 
 
 
diff --git a/app/views/issues/index.html.haml b/app/views/issues/index.html.haml
index d5c29c780ce..a3fb0335205 100644
--- a/app/views/issues/index.html.haml
+++ b/app/views/issues/index.html.haml
@@ -6,7 +6,7 @@
     .right
       .span5
         - if can? current_user, :write_issue, @project
-          = link_to new_project_issue_path(@project, issue: { assignee_id: params[:assignee_id], milestone_id: params[:milestone_id]}), class: "right btn primary", title: "New Issue", id: "new_issue_link" do
+          = link_to new_project_issue_path(@project, issue: { assignee_id: params[:assignee_id], milestone_id: params[:milestone_id]}), class: "right btn btn-primary", title: "New Issue", id: "new_issue_link" do
             %i.icon-plus
             New Issue
         = form_tag search_project_issues_path(@project), method: :get, remote: true, id: "issue_search_form", class: :right  do
@@ -33,7 +33,7 @@
                 = select_tag('update[milestone_id]', options_from_collection_for_select(issues_active_milestones, "id", "title", params[:milestone_id]), prompt: "Milestone")
                 = hidden_field_tag 'update[issues_ids]', []
                 = hidden_field_tag :status, params[:status]
-              = button_tag "Save", class: "btn update_selected_issues btn-small save-btn"
+              = button_tag "Save", class: "btn update_selected_issues btn-small btn-save"
           .issues_filters
             = form_tag project_issues_path(@project), method: :get  do
               = select_tag(:label_name, options_for_select(issue_tags, params[:label_name]), prompt: "Labels")
diff --git a/app/views/keys/_form.html.haml b/app/views/keys/_form.html.haml
index 26700803e61..b60ad7df0ae 100644
--- a/app/views/keys/_form.html.haml
+++ b/app/views/keys/_form.html.haml
@@ -19,6 +19,6 @@
 
 
     .actions
-      = f.submit 'Save', class: "btn save-btn"
-      = link_to "Cancel", keys_path, class: "btn cancel-btn"
+      = f.submit 'Save', class: "btn btn-save"
+      = link_to "Cancel", keys_path, class: "btn btn-cancel"
 
diff --git a/app/views/keys/_show.html.haml b/app/views/keys/_show.html.haml
index 9d4485cf9a4..049981766b6 100644
--- a/app/views/keys/_show.html.haml
+++ b/app/views/keys/_show.html.haml
@@ -8,5 +8,5 @@
       = time_ago_in_words(key.created_at)
       ago
   %td
-    = link_to 'Remove', key, confirm: 'Are you sure?', method: :delete, class: "btn small danger delete-key right"
+    = link_to 'Remove', key, confirm: 'Are you sure?', method: :delete, class: "btn small btn-remove delete-key right"
 
diff --git a/app/views/keys/show.html.haml b/app/views/keys/show.html.haml
index a8cba6c8f9e..089d0558b52 100644
--- a/app/views/keys/show.html.haml
+++ b/app/views/keys/show.html.haml
@@ -11,4 +11,4 @@
 
 %pre= @key.key
 .right
-  = link_to 'Remove', @key, confirm: 'Are you sure?', method: :delete, class: "btn danger delete-key"
+  = link_to 'Remove', @key, confirm: 'Are you sure?', method: :delete, class: "btn btn-remove delete-key"
diff --git a/app/views/merge_requests/_form.html.haml b/app/views/merge_requests/_form.html.haml
index 9a4f0617a3a..603f30407b9 100644
--- a/app/views/merge_requests/_form.html.haml
+++ b/app/views/merge_requests/_form.html.haml
@@ -51,19 +51,19 @@
 
   .form-actions
     - if @merge_request.new_record?
-      = f.submit 'Submit merge request', class: "btn success"
+      = f.submit 'Submit merge request', class: "btn btn-create"
     -else
-      = f.submit 'Save changes', class: "save-btn btn"
+      = f.submit 'Save changes', class: "btn btn-save"
     - if @merge_request.new_record?
-      = link_to project_merge_requests_path(@project), class: "btn cancel-btn" do
+      = link_to project_merge_requests_path(@project), class: "btn btn-cancel" do
         Cancel
     - else
-      = link_to project_merge_request_path(@project, @merge_request), class: "btn cancel-btn" do
+      = link_to project_merge_request_path(@project, @merge_request), class: "btn btn-cancel" do
         Cancel
 
 :javascript
   $(function(){
-    disableButtonIfEmptyField("#merge_request_title", ".save-btn");
+    disableButtonIfEmptyField("#merge_request_title", ".btn-save");
 
     var source_branch = $("#merge_request_source_branch")
       , target_branch = $("#merge_request_target_branch");
diff --git a/app/views/merge_requests/index.html.haml b/app/views/merge_requests/index.html.haml
index 61c32b533f6..8c688e26814 100644
--- a/app/views/merge_requests/index.html.haml
+++ b/app/views/merge_requests/index.html.haml
@@ -1,5 +1,5 @@
 - if can? current_user, :write_merge_request, @project
-  = link_to new_project_merge_request_path(@project), class: "right btn primary", title: "New Merge Request" do
+  = link_to new_project_merge_request_path(@project), class: "right btn btn-primary", title: "New Merge Request" do
     %i.icon-plus
     New Merge Request
 %h3.page_title
diff --git a/app/views/milestones/_form.html.haml b/app/views/milestones/_form.html.haml
index 1c496a93e54..2dc90bb89d0 100644
--- a/app/views/milestones/_form.html.haml
+++ b/app/views/milestones/_form.html.haml
@@ -32,16 +32,16 @@
 
   .form-actions
     - if @milestone.new_record?
-      = f.submit 'Create milestone', class: "save-btn btn"
-      = link_to "Cancel", project_milestones_path(@project), class: "btn cancel-btn"
+      = f.submit 'Create milestone', class: "btn-save btn"
+      = link_to "Cancel", project_milestones_path(@project), class: "btn btn-cancel"
     -else
-      = f.submit 'Save changes', class: "save-btn btn"
-      = link_to "Cancel", project_milestone_path(@project, @milestone), class: "btn cancel-btn"
+      = f.submit 'Save changes', class: "btn-save btn"
+      = link_to "Cancel", project_milestone_path(@project, @milestone), class: "btn btn-cancel"
 
 
 :javascript
   $(function() {
-    disableButtonIfEmptyField("#milestone_title", ".save-btn");
+    disableButtonIfEmptyField("#milestone_title", ".btn-save");
     $( ".datepicker" ).datepicker({
       dateFormat: "yy-mm-dd",
       onSelect: function(dateText, inst) { $("#milestone_due_date").val(dateText) }
diff --git a/app/views/milestones/show.html.haml b/app/views/milestones/show.html.haml
index fc7ae51f184..797f35befa5 100644
--- a/app/views/milestones/show.html.haml
+++ b/app/views/milestones/show.html.haml
@@ -25,7 +25,7 @@
   %hr
   %p
     %span All issues for this milestone are closed. You may close milestone now.
-    = link_to 'Close Milestone', project_milestone_path(@project, @milestone, milestone: {closed: true }), method: :put, class: "btn small danger"
+    = link_to 'Close Milestone', project_milestone_path(@project, @milestone, milestone: {closed: true }), method: :put, class: "btn small btn-remove"
 
 .ui-box.ui-box-show
   .ui-box-head
diff --git a/app/views/profiles/account.html.haml b/app/views/profiles/account.html.haml
index 522e45e637a..71eacd571bd 100644
--- a/app/views/profiles/account.html.haml
+++ b/app/views/profiles/account.html.haml
@@ -24,7 +24,7 @@
         %p.cgray
           - if current_user.private_token
             = text_field_tag "token", current_user.private_token, class: "xxlarge large_text"
-            = f.submit 'Reset', confirm: "Are you sure?", class: "btn primary btn-build-token"
+            = f.submit 'Reset', confirm: "Are you sure?", class: "btn btn-primary btn-build-token"
           - else
             %span You don`t have one yet. Click generate to fix it.
             = f.submit 'Generate', class: "btn success btn-build-token"
@@ -49,7 +49,7 @@
           = f.password_field :password_confirmation, required: true
       .clearfix
         .input
-          = f.submit 'Save password', class: "btn save-btn"
+          = f.submit 'Save password', class: "btn btn-save"
 
 
 
@@ -75,6 +75,6 @@
           %li It will change web url for personal projects.
           %li It will change the git path to repositories for personal projects.
       .input
-        = f.submit 'Save username', class: "btn save-btn"
+        = f.submit 'Save username', class: "btn btn-save"
 
 
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index 7a3177f0efc..4c0463aff79 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -93,4 +93,4 @@
           = link_to "Add Public Key", new_key_path, class: "btn small"
 
   .form-actions
-    = f.submit 'Save', class: "btn save-btn"
+    = f.submit 'Save', class: "btn btn-save"
diff --git a/app/views/projects/_form.html.haml b/app/views/projects/_form.html.haml
index b582adc97a2..a3e97fe9b70 100644
--- a/app/views/projects/_form.html.haml
+++ b/app/views/projects/_form.html.haml
@@ -77,9 +77,9 @@
   %br
 
   .actions
-    = f.submit 'Save', class: "btn save-btn"
+    = f.submit 'Save', class: "btn btn-save"
     = link_to 'Cancel', @project, class: "btn"
     - unless @project.new_record?
       - if can?(current_user, :remove_project, @project)
         .right
-          = link_to 'Remove Project', @project, confirm: 'Removed project can not be restored! Are you sure?', method: :delete, class: "btn danger"
+          = link_to 'Remove Project', @project, confirm: 'Removed project can not be restored! Are you sure?', method: :delete, class: "btn btn-remove"
diff --git a/app/views/projects/_new_form.html.haml b/app/views/projects/_new_form.html.haml
index 5f7348d47a1..dc4f4e23356 100644
--- a/app/views/projects/_new_form.html.haml
+++ b/app/views/projects/_new_form.html.haml
@@ -7,7 +7,7 @@
       Project name is
     .input
       = f.text_field :name, placeholder: "Example Project", class: "xxlarge"
-      = f.submit 'Create project', class: "btn success project-submit"
+      = f.submit 'Create project', class: "btn btn-create project-submit"
 
   - if current_user.can_select_namespace?
     .clearfix
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index 52dff687a3a..e7ee8bbb171 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -31,4 +31,4 @@
 
   - if can? current_user, :remove_project, @project
     .prepend-top-20
-      = link_to 'Remove project', @project, confirm: 'Are you sure?', method: :delete, class: "btn danger right"
+      = link_to 'Remove project', @project, confirm: 'Are you sure?', method: :delete, class: "btn btn-remove right"
diff --git a/app/views/projects/teams/available.html.haml b/app/views/projects/teams/available.html.haml
index 814e216d6ad..da7823638b9 100644
--- a/app/views/projects/teams/available.html.haml
+++ b/app/views/projects/teams/available.html.haml
@@ -17,6 +17,6 @@
 
 
   .actions
-    = submit_tag 'Assign', class: "btn save-btn"
-    = link_to "Cancel", project_team_index_path(@project), class: "btn cancel-btn"
+    = submit_tag 'Assign', class: "btn btn-create"
+    = link_to "Cancel", project_team_index_path(@project), class: "btn btn-cancel"
 
diff --git a/app/views/protected_branches/index.html.haml b/app/views/protected_branches/index.html.haml
index c1ecceda435..8ceff635fd9 100644
--- a/app/views/protected_branches/index.html.haml
+++ b/app/views/protected_branches/index.html.haml
@@ -24,7 +24,7 @@
           .span3
             = f.select(:name, @project.open_branches.map { |br| [br.name, br.name] } , {include_blank: "Select branch"}, {class: "chosen span3"})
           &nbsp;
-          = f.submit 'Protect', class: "primary btn"
+          = f.submit 'Protect', class: "btn-primary btn"
 
     - unless @branches.empty?
       %table
diff --git a/app/views/search/show.html.haml b/app/views/search/show.html.haml
index 22e1ae50df1..5914c22df6e 100644
--- a/app/views/search/show.html.haml
+++ b/app/views/search/show.html.haml
@@ -4,7 +4,7 @@
       %span Looking for
     .input
       = search_field_tag :search, params[:search], placeholder: "issue 143", class: "input-xxlarge search-text-input", id: "dashboard_search"
-      = submit_tag 'Search', class: "btn primary wide"
+      = submit_tag 'Search', class: "btn btn-primary wide"
   .clearfix
   .row
     .span3
diff --git a/app/views/services/_gitlab_ci.html.haml b/app/views/services/_gitlab_ci.html.haml
index 649c5cc4c3c..822892c8337 100644
--- a/app/views/services/_gitlab_ci.html.haml
+++ b/app/views/services/_gitlab_ci.html.haml
@@ -40,7 +40,7 @@
 
 
   .form-actions
-    = f.submit 'Save', class: 'btn save-btn'
+    = f.submit 'Save', class: 'btn btn-save'
     &nbsp;
     - if @service.valid? && @service.active
       = link_to 'Test settings', test_project_service_path(@project), class: 'btn btn-small'
diff --git a/app/views/snippets/_form.html.haml b/app/views/snippets/_form.html.haml
index baef737b565..1405bd1110f 100644
--- a/app/views/snippets/_form.html.haml
+++ b/app/views/snippets/_form.html.haml
@@ -27,7 +27,7 @@
               = f.hidden_field :content, class: 'snippet-file-content'
 
     .form-actions
-      = f.submit 'Save', class: "save-btn btn"
+      = f.submit 'Save', class: "btn-save btn"
       = link_to "Cancel", project_snippets_path(@project), class: " btn"
       - unless @snippet.new_record?
         .right= link_to 'Destroy', [@project, @snippet], confirm: 'Are you sure?', method: :delete, class: "btn right danger delete-snippet", id: "destroy_snippet_#{@snippet.id}"
diff --git a/app/views/team_members/_form.html.haml b/app/views/team_members/_form.html.haml
index f9ee49dbdeb..1616ea3c229 100644
--- a/app/views/team_members/_form.html.haml
+++ b/app/views/team_members/_form.html.haml
@@ -19,5 +19,5 @@
     .input= select_tag :project_access, options_for_select(Project.access_options, @user_project_relation.project_access), class: "project-access-select chosen"
 
   .actions
-    = f.submit 'Save', class: "btn save-btn"
-    = link_to "Cancel", project_team_index_path(@project), class: "btn cancel-btn"
+    = f.submit 'Save', class: "btn btn-save"
+    = link_to "Cancel", project_team_index_path(@project), class: "btn btn-cancel"
diff --git a/app/views/team_members/_show.html.haml b/app/views/team_members/_show.html.haml
index 52992033805..c8138af4428 100644
--- a/app/views/team_members/_show.html.haml
+++ b/app/views/team_members/_show.html.haml
@@ -23,6 +23,6 @@
         - elsif user.blocked
           %span.btn.disabled.blocked Blocked
         - elsif allow_admin
-          = link_to project_team_member_path(@project, user), confirm: remove_from_project_team_message(@project, user), method: :delete, class: "very_small btn danger" do
+          = link_to project_team_member_path(@project, user), confirm: remove_from_project_team_message(@project, user), method: :delete, class: "very_small btn btn-remove" do
             %i.icon-minus.icon-white
 
diff --git a/app/views/team_members/_show_team.html.haml b/app/views/team_members/_show_team.html.haml
index da0262efda5..ebe6f633d68 100644
--- a/app/views/team_members/_show_team.html.haml
+++ b/app/views/team_members/_show_team.html.haml
@@ -11,5 +11,5 @@
       .right
         - if allow_admin
           .left
-            = link_to resign_project_team_path(@project, team), method: :delete, confirm: "Are you shure?", class: "btn danger small" do
+            = 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/import.html.haml b/app/views/team_members/import.html.haml
index 135db946041..d6c81befd08 100644
--- a/app/views/team_members/import.html.haml
+++ b/app/views/team_members/import.html.haml
@@ -12,6 +12,6 @@
     .input= select_tag(:source_project_id, options_from_collection_for_select(current_user.authorized_projects, :id, :name_with_namespace), prompt: "Select project", class: "chosen xxlarge", required: true)
 
   .actions
-    = submit_tag 'Import', class: "btn save-btn"
-    = link_to "Cancel", project_team_index_path(@project), class: "btn cancel-btn"
+    = submit_tag 'Import', class: "btn btn-save"
+    = link_to "Cancel", project_team_index_path(@project), class: "btn btn-cancel"
 
diff --git a/app/views/team_members/index.html.haml b/app/views/team_members/index.html.haml
index 6425302b83b..935755f36c4 100644
--- a/app/views/team_members/index.html.haml
+++ b/app/views/team_members/index.html.haml
@@ -12,7 +12,7 @@
         Import team from another project
       = link_to available_project_teams_path(@project), class: "btn small grouped", title: "Assign project to team of users" do
         Assign project to Team of users
-      = link_to new_project_team_member_path(@project), class: "btn success small grouped", title: "New Team Member" do
+      = link_to new_project_team_member_path(@project), class: "btn btn-primary small grouped", title: "New Team Member" do
         New Team Member
 
 %hr
diff --git a/app/views/team_members/show.html.haml b/app/views/team_members/show.html.haml
index a6a7152e92a..99564f8e167 100644
--- a/app/views/team_members/show.html.haml
+++ b/app/views/team_members/show.html.haml
@@ -2,7 +2,7 @@
 
 .team_member_show
   - if can? current_user, :admin_project, @project
-    = link_to 'Remove from team', project_team_member_path(@project, @member), confirm: 'Are you sure?', method: :delete, class: "right btn danger"
+    = link_to 'Remove from team', project_team_member_path(@project, @member), confirm: 'Are you sure?', method: :delete, class: "right btn btn-remove"
   .profile_avatar_holder
     = image_tag gravatar_icon(@member.email, 60), class: "borders"
   %h3.page_title
diff --git a/app/views/teams/edit.html.haml b/app/views/teams/edit.html.haml
index 60535330c4a..2c565230b85 100644
--- a/app/views/teams/edit.html.haml
+++ b/app/views/teams/edit.html.haml
@@ -17,6 +17,6 @@
       = f.text_field :path, placeholder: "opensource", class: "xxlarge left"
   .clearfix
     .input.span3.center
-      = f.submit 'Save team changes', class: "btn primary"
+      = f.submit 'Save team changes', class: "btn btn-primary"
     .input.span3.center
-      = link_to 'Delete team', team_path(@team), method: :delete, confirm: "You are shure?", class: "btn danger"
+      = link_to 'Delete team', team_path(@team), method: :delete, confirm: "You are shure?", class: "btn btn-remove"
diff --git a/app/views/teams/members/_form.html.haml b/app/views/teams/members/_form.html.haml
index b75d788a94a..701eb4f2233 100644
--- a/app/views/teams/members/_form.html.haml
+++ b/app/views/teams/members/_form.html.haml
@@ -16,5 +16,5 @@
 
   %br
   .actions
-    = submit_tag 'Save', class: "btn primary"
+    = submit_tag 'Save', class: "btn btn-save"
     = link_to 'Cancel', :back, class: "btn"
diff --git a/app/views/teams/members/_show.html.haml b/app/views/teams/members/_show.html.haml
index 740d5a498c0..a14177dfe29 100644
--- a/app/views/teams/members/_show.html.haml
+++ b/app/views/teams/members/_show.html.haml
@@ -17,8 +17,8 @@
             = f.select :permission, options_for_select(UsersProject.access_roles, @team.default_projects_access(user)), {}, class: "medium project-access-select span2"
         .left.span2
           %span
-            Admin access
             = check_box_tag :group_admin, true, @team.admin?(user)
+            Admin access
       .right
         - if current_user == user
           %span.btn.disabled This is you!
@@ -27,5 +27,5 @@
         - 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: "very_small btn danger" do
+          = link_to team_member_path(@team, user), confirm: remove_from_user_team_message(@team, user), method: :delete, class: "very_small btn btn-remove" do
             %i.icon-minus.icon-white
diff --git a/app/views/teams/members/index.html.haml b/app/views/teams/members/index.html.haml
index 90fa0aef35c..8ce6e5d83c0 100644
--- a/app/views/teams/members/index.html.haml
+++ b/app/views/teams/members/index.html.haml
@@ -7,7 +7,7 @@
 
   - if can? current_user, :manage_user_team, @team
     %span.right
-      = link_to new_team_member_path(@team), class: "btn success small grouped", title: "New Team Member" do
+      = link_to new_team_member_path(@team), class: "btn btn-primary small grouped", title: "New Team Member" do
         New Team Member
 %hr
 
diff --git a/app/views/teams/members/new.html.haml b/app/views/teams/members/new.html.haml
index 274cdbadf29..083e137e0ae 100644
--- a/app/views/teams/members/new.html.haml
+++ b/app/views/teams/members/new.html.haml
@@ -25,4 +25,4 @@
         %td
           %span= check_box_tag :group_admin
           %span Admin?
-        %td= submit_tag 'Add', class: "btn primary", id: :add_members_to_team
+        %td= submit_tag 'Add User', class: "btn btn-create", id: :add_members_to_team
diff --git a/app/views/teams/members/show.html.haml b/app/views/teams/members/show.html.haml
index 4008e8bd23e..6e655cee08e 100644
--- a/app/views/teams/members/show.html.haml
+++ b/app/views/teams/members/show.html.haml
@@ -3,7 +3,7 @@
 
 .team_member_show
   - if can? current_user, :admin_project, @project
-    = link_to 'Remove from team', project_team_member_path(project_id: @project, id: @team_member.id), confirm: 'Are you sure?', method: :delete, class: "right btn danger"
+    = link_to 'Remove from team', project_team_member_path(project_id: @project, id: @team_member.id), confirm: 'Are you sure?', method: :delete, class: "right btn btn-remove"
   .profile_avatar_holder
     = image_tag gravatar_icon(user.email, 60), class: "borders"
   %h3.page_title
diff --git a/app/views/teams/new.html.haml b/app/views/teams/new.html.haml
index 12695f2b5ae..ca28f313e72 100644
--- a/app/views/teams/new.html.haml
+++ b/app/views/teams/new.html.haml
@@ -10,7 +10,7 @@
     .input
       = f.text_field :name, placeholder: "Ex. Ruby Developers", class: "xxlarge left"
       &nbsp;
-      = f.submit 'Create team', class: "btn primary"
+      = f.submit 'Create team', class: "btn btn-primary"
   %hr
   .padded
     %ul
diff --git a/app/views/teams/projects/_form.html.haml b/app/views/teams/projects/_form.html.haml
index 3749dbc4f99..763d07a1c7e 100644
--- a/app/views/teams/projects/_form.html.haml
+++ b/app/views/teams/projects/_form.html.haml
@@ -12,5 +12,5 @@
 
   %br
   .actions
-    = submit_tag 'Save', class: "btn primary"
-    = link_to 'Cancel', :back, class: "btn"
+    = submit_tag 'Save', class: "btn btn-save"
+    = link_to 'Cancel', :back, class: "btn btn-cancel"
diff --git a/app/views/teams/projects/edit.html.haml b/app/views/teams/projects/edit.html.haml
index b91a4982b81..82c7d734815 100644
--- a/app/views/teams/projects/edit.html.haml
+++ b/app/views/teams/projects/edit.html.haml
@@ -1,16 +1,6 @@
-%h3
-  Edit max access in #{@project.name} for #{@team.name} team
+%h3.page_title
+  Edit max access in #{link_to @project.name_with_namespace, @project} for #{link_to(@team.name, team_path(@team))} team
 
 %hr
-%table.zebra-striped
-  %tr
-    %td Project:
-    %td= @project.name
-  %tr
-    %td Team:
-    %td= @team.name
-  %tr
-    %td Since:
-    %td= assigned_since(@team, @project).stamp("Nov 11, 2010")
 
 = render 'form'
diff --git a/app/views/teams/projects/index.html.haml b/app/views/teams/projects/index.html.haml
index 493fc2c5c9e..5aa6a999c20 100644
--- a/app/views/teams/projects/index.html.haml
+++ b/app/views/teams/projects/index.html.haml
@@ -6,7 +6,7 @@
 
   - if current_user.can?(:manage_user_team, @team) && @avaliable_projects.any?
     %span.right
-      = link_to new_team_project_path(@team), class: "btn success small grouped", title: "New Team Member" do
+      = link_to new_team_project_path(@team), class: "btn btn-primary small grouped", title: "New Team Member" do
         Assign project to Team
 
 %hr
@@ -30,7 +30,7 @@
         - if current_user.can?(:admin_user_team, @team)
           %td.bgred
             = link_to 'Edit max access', edit_team_project_path(@team, project), class: "btn small"
-            = link_to 'Relegate', team_project_path(@team, project), confirm: 'Remove project from team and move to global namespace. Are you sure?', method: :delete, class: "btn danger small"
+            = link_to 'Relegate', team_project_path(@team, project), confirm: 'Remove project from team and move to global namespace. Are you sure?', method: :delete, class: "btn btn-remove small"
 
 - else
   %p.nothing_here_message This team has no projects yet
diff --git a/app/views/teams/projects/new.html.haml b/app/views/teams/projects/new.html.haml
index d57f56b2fee..3f3671aa0a4 100644
--- a/app/views/teams/projects/new.html.haml
+++ b/app/views/teams/projects/new.html.haml
@@ -20,4 +20,4 @@
       %tr
         %td= select_tag :project_ids, options_from_collection_for_select(@avaliable_projects , :id, :name_with_namespace), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5'
         %td= select_tag :greatest_project_access, options_for_select(UserTeam.access_roles), {class: "project-access-select chosen span3" }
-        %td= submit_tag 'Add', class: "btn primary", id: :assign_projects_to_team
+        %td= submit_tag 'Add Project', class: "btn btn-create", id: :assign_projects_to_team
diff --git a/app/views/tree/edit.html.haml b/app/views/tree/edit.html.haml
index adee68a00f8..281f4cc5ba2 100644
--- a/app/views/tree/edit.html.haml
+++ b/app/views/tree/edit.html.haml
@@ -10,7 +10,7 @@
             %strong= @ref
         %span.options
           .btn-group.tree-btn-group
-            = link_to "Cancel", project_tree_path(@project, @id), class: "btn very_small cancel-btn", confirm: "Are you sure?"
+            = link_to "Cancel", project_tree_path(@project, @id), class: "btn very_small btn-cancel", confirm: "Are you sure?"
       .file_content.code
         %pre#editor= @tree.data
 
@@ -27,7 +27,7 @@
         .message
           to branch
           %strong= @ref
-      = link_to "Cancel", project_tree_path(@project, @id), class: "btn cancel-btn", confirm: "Are you sure?"
+      = link_to "Cancel", project_tree_path(@project, @id), class: "btn btn-cancel", confirm: "Are you sure?"
 
 :javascript
   var ace_mode = "#{@tree.language.try(:ace_mode)}";
diff --git a/app/views/wikis/_form.html.haml b/app/views/wikis/_form.html.haml
index 9eb2a571fe5..7758b129b07 100644
--- a/app/views/wikis/_form.html.haml
+++ b/app/views/wikis/_form.html.haml
@@ -23,5 +23,5 @@
       = f.label :content
       .input= f.text_area :content, class: 'span8 js-gfm-input'
   .actions
-    = f.submit 'Save', class: "save-btn btn"
-    = link_to "Cancel", project_wiki_path(@project, :index), class: "btn cancel-btn"
+    = f.submit 'Save', class: "btn-save btn"
+    = link_to "Cancel", project_wiki_path(@project, :index), class: "btn btn-cancel"
diff --git a/app/views/wikis/edit.html.haml b/app/views/wikis/edit.html.haml
index 8f6b457f22a..bf4a9aad444 100644
--- a/app/views/wikis/edit.html.haml
+++ b/app/views/wikis/edit.html.haml
@@ -4,5 +4,5 @@
 
 .right
   - if can? current_user, :admin_wiki, @project
-    = link_to project_wiki_path(@project, @wiki), confirm: "Are you sure you want to delete this page?", method: :delete, class: "btn small danger" do
+    = link_to project_wiki_path(@project, @wiki), confirm: "Are you sure you want to delete this page?", method: :delete, class: "btn small btn-remove" do
       Delete this page
\ No newline at end of file
-- 
GitLab


From fb617c61b95aef4615346a5e554db469384d9b6c Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 29 Jan 2013 22:29:21 +0200
Subject: [PATCH 136/197] refactor buttons pt2

---
 app/assets/stylesheets/gitlab_bootstrap/buttons.scss |  2 +-
 app/assets/stylesheets/sections/notes.scss           |  4 ++--
 app/views/admin/dashboard/index.html.haml            |  6 +++---
 app/views/admin/groups/index.html.haml               |  6 +++---
 app/views/admin/hooks/index.html.haml                |  4 ++--
 app/views/admin/projects/index.html.haml             |  6 +++---
 app/views/admin/projects/show.html.haml              |  2 +-
 app/views/admin/teams/index.html.haml                |  6 +++---
 app/views/admin/teams/show.html.haml                 | 10 +++++-----
 app/views/admin/users/_form.html.haml                |  4 ++--
 app/views/admin/users/index.html.haml                | 10 +++++-----
 app/views/admin/users/show.html.haml                 |  4 ++--
 app/views/commits/_diffs.html.haml                   |  2 +-
 app/views/dashboard/_groups.html.haml                |  2 +-
 app/views/dashboard/_projects.html.haml              |  2 +-
 app/views/dashboard/_teams.html.haml                 |  2 +-
 app/views/dashboard/projects.html.haml               |  2 +-
 app/views/deploy_keys/_show.html.haml                |  2 +-
 app/views/deploy_keys/index.html.haml                |  2 +-
 app/views/deploy_keys/show.html.haml                 |  2 +-
 app/views/groups/_projects.html.haml                 |  2 +-
 app/views/groups/show.html.haml                      |  2 +-
 app/views/hooks/index.html.haml                      |  4 ++--
 app/views/issues/_show.html.haml                     |  8 ++++----
 app/views/keys/_show.html.haml                       |  2 +-
 app/views/merge_requests/_merge_request.html.haml    |  8 ++++----
 app/views/merge_requests/show/_mr_accept.html.haml   |  2 +-
 app/views/milestones/_milestone.html.haml            |  2 +-
 app/views/milestones/index.html.haml                 |  2 +-
 app/views/milestones/show.html.haml                  |  6 +++---
 app/views/notes/_form.html.haml                      |  2 +-
 app/views/profiles/show.html.haml                    |  6 +++---
 app/views/projects/_new_form.html.haml               |  4 ++--
 app/views/protected_branches/index.html.haml         |  2 +-
 app/views/snippets/_blob.html.haml                   |  2 +-
 app/views/snippets/index.html.haml                   |  2 +-
 app/views/snippets/show.html.haml                    |  2 +-
 app/views/team_members/_show.html.haml               |  4 ++--
 app/views/team_members/index.html.haml               |  4 ++--
 app/views/teams/_projects.html.haml                  |  2 +-
 app/views/teams/members/_show.html.haml              |  4 ++--
 app/views/teams/projects/index.html.haml             |  2 +-
 app/views/teams/show.html.haml                       |  2 +-
 app/views/tree/_blob_actions.html.haml               | 10 +++++-----
 app/views/tree/_tree.html.haml                       |  2 +-
 app/views/tree/edit.html.haml                        |  2 +-
 app/views/users/show.html.haml                       |  2 +-
 app/views/wikis/edit.html.haml                       |  2 +-
 app/views/wikis/show.html.haml                       |  6 +++---
 49 files changed, 90 insertions(+), 90 deletions(-)

diff --git a/app/assets/stylesheets/gitlab_bootstrap/buttons.scss b/app/assets/stylesheets/gitlab_bootstrap/buttons.scss
index ed102253ab6..86b4c5b3b64 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/buttons.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/buttons.scss
@@ -92,7 +92,7 @@
     background-color: #ccc;
   }
 
-  &.very_small {
+  &.btn-tiny {
     font-size: 11px;
     padding: 2px 6px;
     line-height: 16px;
diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss
index d4934791110..b29d2991d34 100644
--- a/app/assets/stylesheets/sections/notes.scss
+++ b/app/assets/stylesheets/sections/notes.scss
@@ -215,10 +215,10 @@ ul.notes {
  */
 
 .comment-btn {
-  @extend .create-btn;
+  @extend .btn-create;
 }
 .reply-btn {
-  @extend .primary;
+  @extend .btn-primary;
 }
 .file .content tr.line_holder:hover > td { background: $hover !important; }
 .file .content tr.line_holder:hover > td .line_note_link {
diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml
index 9a5e7edea0f..3698778e9fc 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -6,7 +6,7 @@
         = link_to admin_projects_path do
           %h1= Project.count
         %hr
-        = link_to 'New Project', new_project_path, class: "btn small"
+        = link_to 'New Project', new_project_path, class: "btn btn-small"
   .span4
     .ui-box
       %h5.title Groups
@@ -14,7 +14,7 @@
         = link_to admin_groups_path do
           %h1= Group.count
         %hr
-        = link_to 'New Group', new_admin_group_path, class: "btn small"
+        = link_to 'New Group', new_admin_group_path, class: "btn btn-small"
   .span4
     .ui-box
       %h5.title Users
@@ -22,7 +22,7 @@
         = link_to admin_users_path do
           %h1= User.count
         %hr
-        = link_to 'New User', new_admin_user_path, class: "btn small"
+        = link_to 'New User', new_admin_user_path, class: "btn btn-small"
 
 .row
   .span4
diff --git a/app/views/admin/groups/index.html.haml b/app/views/admin/groups/index.html.haml
index 443abece919..f1e857eca8a 100644
--- a/app/views/admin/groups/index.html.haml
+++ b/app/views/admin/groups/index.html.haml
@@ -4,7 +4,7 @@
     allows you to keep projects organized.
     Use groups for uniting related projects.
 
-  = link_to 'New Group', new_admin_group_path, class: "btn small right"
+  = link_to 'New Group', new_admin_group_path, class: "btn btn-small right"
 %br
 = form_tag admin_groups_path, method: :get, class: 'form-inline' do
   = text_field_tag :name, params[:name], class: "xlarge"
@@ -30,6 +30,6 @@
       %td
         = link_to group.owner_name, admin_user_path(group.owner_id)
       %td.bgred
-        = link_to 'Rename', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: "btn small"
-        = link_to 'Destroy', [:admin, group], confirm: "REMOVE #{group.name}? Are you sure?", method: :delete, class: "btn small btn-remove"
+        = link_to 'Rename', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: "btn btn-small"
+        = link_to 'Destroy', [:admin, group], confirm: "REMOVE #{group.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove"
 = paginate @groups, theme: "admin"
diff --git a/app/views/admin/hooks/index.html.haml b/app/views/admin/hooks/index.html.haml
index 15bff871cd5..412a7ff2038 100644
--- a/app/views/admin/hooks/index.html.haml
+++ b/app/views/admin/hooks/index.html.haml
@@ -33,7 +33,7 @@
         %td
           = link_to admin_hook_path(hook) do
             %strong= hook.url
-          = link_to 'Test Hook', admin_hook_test_path(hook), class: "btn small right"
+          = link_to 'Test Hook', admin_hook_test_path(hook), class: "btn btn-small right"
         %td POST
         %td
-          = link_to 'Remove', admin_hook_path(hook), confirm: 'Are you sure?', method: :delete, class: "danger btn small right"
+          = link_to 'Remove', admin_hook_path(hook), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove btn-small right"
diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml
index 8ac2fa12520..f42e1f3af86 100644
--- a/app/views/admin/projects/index.html.haml
+++ b/app/views/admin/projects/index.html.haml
@@ -1,6 +1,6 @@
 %h3.page_title
   Projects
-  = link_to 'New Project', new_project_path, class: "btn small right"
+  = link_to 'New Project', new_project_path, class: "btn btn-small right"
 
 %hr
 
@@ -52,8 +52,8 @@
               %i.icon-lock.cgreen
             = link_to project.name_with_namespace, [:admin, project]
             .right
-              = link_to 'Edit', edit_admin_project_path(project), id: "edit_#{dom_id(project)}", class: "btn small"
-              = link_to 'Destroy', [:admin, project], confirm: "REMOVE #{project.name}? Are you sure?", method: :delete, class: "btn small btn-remove"
+              = link_to 'Edit', edit_admin_project_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small"
+              = link_to 'Destroy', [:admin, project], confirm: "REMOVE #{project.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove"
         - if @projects.blank?
           %p.nothing_here_message 0 projects matches
         - else
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index fb1a7b488c1..fc3ed1e8b23 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -129,7 +129,7 @@
       %td
         = link_to tm.name, admin_user_path(tm)
       %td= @project.project_access_human(tm)
-      %td= link_to 'Edit Access', edit_admin_project_member_path(@project, tm), class: "btn small"
+      %td= link_to 'Edit Access', edit_admin_project_member_path(@project, tm), class: "btn btn-small"
       %td= link_to 'Remove from team', admin_project_member_path(@project, tm), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove small"
 
 %br
diff --git a/app/views/admin/teams/index.html.haml b/app/views/admin/teams/index.html.haml
index e7344f4ea2c..1d54a27f8f5 100644
--- a/app/views/admin/teams/index.html.haml
+++ b/app/views/admin/teams/index.html.haml
@@ -3,7 +3,7 @@
   %small
     simple Teams description
 
-  = link_to 'New Team', new_admin_team_path, class: "btn small right"
+  = link_to 'New Team', new_admin_team_path, class: "btn btn-small right"
   %br
 
 = form_tag admin_teams_path, method: :get, class: 'form-inline' do
@@ -32,7 +32,7 @@
       %td
         = link_to team.owner.name, admin_user_path(team.owner_id)
       %td.bgred
-        = link_to 'Rename', edit_admin_team_path(team), id: "edit_#{dom_id(team)}", class: "btn small"
-        = link_to 'Destroy', admin_team_path(team), confirm: "REMOVE #{team.name}? Are you sure?", method: :delete, class: "btn small btn-remove"
+        = link_to 'Rename', edit_admin_team_path(team), id: "edit_#{dom_id(team)}", class: "btn btn-small"
+        = link_to 'Destroy', admin_team_path(team), confirm: "REMOVE #{team.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove"
 
 = paginate @teams, theme: "admin"
diff --git a/app/views/admin/teams/show.html.haml b/app/views/admin/teams/show.html.haml
index 2561e3aeaf5..4d27f31be58 100644
--- a/app/views/admin/teams/show.html.haml
+++ b/app/views/admin/teams/show.html.haml
@@ -42,7 +42,7 @@
 %fieldset
   %legend
     Members (#{@team.members.count})
-    %span= link_to 'Add members', new_admin_team_member_path(@team), class: "btn btn-primary small right", id: :add_members_to_team
+    %span= link_to 'Add members', new_admin_team_member_path(@team), class: "btn btn-primary btn-small right", id: :add_members_to_team
   - if @team.members.any?
     %table#members_list
       %thead
@@ -60,14 +60,14 @@
           %td= @team.human_default_projects_access(member)
           %td= @team.admin?(member) ? "Admin" : "Member"
           %td.bgred
-            = link_to 'Edit', edit_admin_team_member_path(@team, member), class: "btn small"
+            = link_to 'Edit', edit_admin_team_member_path(@team, member), class: "btn btn-small"
             &nbsp;
-            = link_to 'Remove', admin_team_member_path(@team, member), confirm: 'Remove member from team. Are you sure?', method: :delete, class: "btn btn-remove small", id: "remove_member_#{member.id}"
+            = link_to 'Remove', admin_team_member_path(@team, member), confirm: 'Remove member from team. Are you sure?', method: :delete, class: "btn btn-remove btn-small", id: "remove_member_#{member.id}"
 
 %fieldset
   %legend
     Projects (#{@team.projects.count})
-    %span= link_to 'Add projects', new_admin_team_project_path(@team), class: "btn btn-primary small right", id: :assign_projects_to_team
+    %span= link_to 'Add projects', new_admin_team_project_path(@team), class: "btn btn-primary btn-small right", id: :assign_projects_to_team
   - if @team.projects.any?
     %table#projects_list
       %thead
@@ -82,7 +82,7 @@
           %td
             %span= @team.human_max_project_access(project)
           %td.bgred
-            = link_to 'Edit', edit_admin_team_project_path(@team, project), class: "btn small"
+            = link_to 'Edit', edit_admin_team_project_path(@team, project), class: "btn btn-small"
             &nbsp;
             = link_to 'Relegate', admin_team_project_path(@team, project), confirm: 'Remove project from team. Are you sure?', method: :delete, class: "btn btn-remove small", id: "relegate_project_#{project.id}"
 
diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml
index 9f447bcd9e7..51b05c05993 100644
--- a/app/views/admin/users/_form.html.haml
+++ b/app/views/admin/users/_form.html.haml
@@ -63,10 +63,10 @@
             .alert.alert-error
               - if @admin_user.blocked
                 %p This user is blocked and is not able to login to GitLab
-                = link_to 'Unblock User', unblock_admin_user_path(@admin_user), method: :put, class: "btn small"
+                = link_to 'Unblock User', unblock_admin_user_path(@admin_user), method: :put, class: "btn btn-small"
               - else
                 %p Blocked users will be removed from all projects &amp; will not be able to login to GitLab.
-                = link_to 'Block User', block_admin_user_path(@admin_user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn small btn-remove"
+                = link_to 'Block User', block_admin_user_path(@admin_user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn btn-small btn-remove"
     %fieldset
       %legend Profile
       .clearfix
diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml
index 0aa8a16fbc6..d8828183083 100644
--- a/app/views/admin/users/index.html.haml
+++ b/app/views/admin/users/index.html.haml
@@ -1,6 +1,6 @@
 %h3.page_title
   Users
-  = link_to 'New User', new_admin_user_path, class: "btn small right"
+  = link_to 'New User', new_admin_user_path, class: "btn btn-small right"
 %br
 
 = form_tag admin_users_path, method: :get, class: 'form-inline' do
@@ -44,15 +44,15 @@
       %td= user.username
       %td= user.email
       %td= user.users_projects.count
-      %td= link_to 'Edit', edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: "btn small"
+      %td= link_to 'Edit', edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: "btn btn-small"
       %td.bgred
         - if user == current_user
           %span.cred It's you!
         - else
           - if user.blocked
-            = link_to 'Unblock', unblock_admin_user_path(user), method: :put, class: "btn small success"
+            = link_to 'Unblock', unblock_admin_user_path(user), method: :put, class: "btn btn-small success"
           - else
-            = link_to 'Block', block_admin_user_path(user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn small btn-remove"
-          = link_to 'Destroy', [:admin, user], confirm: "USER #{user.name} WILL BE REMOVED! Are you sure?", method: :delete, class: "btn small btn-remove"
+            = link_to 'Block', block_admin_user_path(user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn btn-small btn-remove"
+          = link_to 'Destroy', [:admin, user], confirm: "USER #{user.name} WILL BE REMOVED! Are you sure?", method: :delete, class: "btn btn-small btn-remove"
 
 = paginate @admin_users, theme: "admin"
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index fefb5706a93..69062aa375a 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -123,5 +123,5 @@
       %tr
         %td= link_to project.name_with_namespace, admin_project_path(project)
         %td= tm.project_access_human
-        %td= link_to 'Edit Access', edit_admin_project_member_path(project, tm.user), class: "btn small"
-        %td= link_to 'Remove from team', admin_project_member_path(project, tm.user), confirm: 'Are you sure?', method: :delete, class: "btn small btn-remove"
+        %td= link_to 'Edit Access', edit_admin_project_member_path(project, tm.user), class: "btn btn-small"
+        %td= link_to 'Remove from team', admin_project_member_path(project, tm.user), confirm: 'Are you sure?', method: :delete, class: "btn btn-small btn-remove"
diff --git a/app/views/commits/_diffs.html.haml b/app/views/commits/_diffs.html.haml
index 9a9aed39b08..5e7d43c99cb 100644
--- a/app/views/commits/_diffs.html.haml
+++ b/app/views/commits/_diffs.html.haml
@@ -33,7 +33,7 @@
             - if diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode
               %span.file-mode= "#{diff.a_mode} → #{diff.b_mode}"
 
-            = link_to project_tree_path(@project, tree_join(@commit.id, diff.new_path)), {:class => 'btn very_small right view-file'} do
+            = link_to project_tree_path(@project, tree_join(@commit.id, diff.new_path)), {:class => 'btn btn-tiny right view-file'} do
               View file @
               %span.commit-short-id= @commit.short_id(6)
 
diff --git a/app/views/dashboard/_groups.html.haml b/app/views/dashboard/_groups.html.haml
index f9774669d9a..535f0349212 100644
--- a/app/views/dashboard/_groups.html.haml
+++ b/app/views/dashboard/_groups.html.haml
@@ -5,7 +5,7 @@
       (#{groups.count})
     - if current_user.can_create_group?
       %span.right
-        = link_to new_group_path, class: "btn very_small info" do
+        = link_to new_group_path, class: "btn btn-tiny info" do
           %i.icon-plus
           New Group
   %ul.well-list
diff --git a/app/views/dashboard/_projects.html.haml b/app/views/dashboard/_projects.html.haml
index f2acd2b0b0c..a5396a0023d 100644
--- a/app/views/dashboard/_projects.html.haml
+++ b/app/views/dashboard/_projects.html.haml
@@ -5,7 +5,7 @@
       (#{@projects_count})
     - if current_user.can_create_project?
       %span.right
-        = link_to new_project_path, class: "btn very_small info" do
+        = link_to new_project_path, class: "btn btn-tiny info" do
           %i.icon-plus
           New Project
 
diff --git a/app/views/dashboard/_teams.html.haml b/app/views/dashboard/_teams.html.haml
index 5b2ea7a2384..1be6e25c54d 100644
--- a/app/views/dashboard/_teams.html.haml
+++ b/app/views/dashboard/_teams.html.haml
@@ -4,7 +4,7 @@
     %small
       (#{@teams.count})
     %span.right
-      = link_to new_team_path, class: "btn very_small info" do
+      = link_to new_team_path, class: "btn btn-tiny info" do
         %i.icon-plus
         New Team
   %ul.well-list
diff --git a/app/views/dashboard/projects.html.haml b/app/views/dashboard/projects.html.haml
index e6c710e68e9..94b319fe24f 100644
--- a/app/views/dashboard/projects.html.haml
+++ b/app/views/dashboard/projects.html.haml
@@ -4,7 +4,7 @@
     (#{@projects.total_count})
   - if current_user.can_create_project?
     %span.right
-      = link_to new_project_path, class: "btn very_small info" do
+      = link_to new_project_path, class: "btn btn-tiny info" do
         %i.icon-plus
         New Project
 
diff --git a/app/views/deploy_keys/_show.html.haml b/app/views/deploy_keys/_show.html.haml
index a5314ae92ad..68b00568c6d 100644
--- a/app/views/deploy_keys/_show.html.haml
+++ b/app/views/deploy_keys/_show.html.haml
@@ -8,5 +8,5 @@
       = time_ago_in_words(key.created_at)
       ago
   %td
-    = link_to 'Remove', project_deploy_key_path(key.project, key), confirm: 'Are you sure?', method: :delete, class: "danger btn delete-key small right"
+    = link_to 'Remove', project_deploy_key_path(key.project, key), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove delete-key btn-small right"
 
diff --git a/app/views/deploy_keys/index.html.haml b/app/views/deploy_keys/index.html.haml
index b9c654a1abe..db167f4e2f2 100644
--- a/app/views/deploy_keys/index.html.haml
+++ b/app/views/deploy_keys/index.html.haml
@@ -4,7 +4,7 @@
   Deploy keys allow read-only access to repository. It matches perfectly for CI, staging or production servers.
 
   - if can? current_user, :admin_project, @project
-    = link_to new_project_deploy_key_path(@project), class: "btn small", title: "New Deploy Key" do
+    = link_to new_project_deploy_key_path(@project), class: "btn btn-small", title: "New Deploy Key" do
       Add Deploy Key
 - if @keys.any?
   %table
diff --git a/app/views/deploy_keys/show.html.haml b/app/views/deploy_keys/show.html.haml
index c94cf10dde0..4a864fae9d7 100644
--- a/app/views/deploy_keys/show.html.haml
+++ b/app/views/deploy_keys/show.html.haml
@@ -11,4 +11,4 @@
 %hr
 %pre= @key.key
 .right
-  = link_to 'Remove', project_deploy_key_path(@key.project, @key), confirm: 'Are you sure?', method: :delete, class: "danger btn delete-key"
+  = link_to 'Remove', project_deploy_key_path(@key.project, @key), confirm: 'Are you sure?', method: :delete, class: "btn-remove btn delete-key"
diff --git a/app/views/groups/_projects.html.haml b/app/views/groups/_projects.html.haml
index 040d1ae94aa..b7732c50a32 100644
--- a/app/views/groups/_projects.html.haml
+++ b/app/views/groups/_projects.html.haml
@@ -5,7 +5,7 @@
       (#{projects.count})
     - if can? current_user, :manage_group, @group
       %span.right
-        = link_to new_project_path(namespace_id: @group.id), class: "btn very_small info" do
+        = link_to new_project_path(namespace_id: @group.id), class: "btn btn-tiny info" do
           %i.icon-plus
           New Project
   %ul.well-list
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index 84dd17c045d..a140b401b9d 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -1,7 +1,7 @@
 .projects
   .activities.span8
     = render "events/event_last_push", event: @last_push
-    = link_to dashboard_path, class: 'btn very_small' do
+    = link_to dashboard_path, class: 'btn btn-tiny' do
       &larr; To dashboard
     &nbsp;
     %span.cgray You will only see events from projects in this group
diff --git a/app/views/hooks/index.html.haml b/app/views/hooks/index.html.haml
index 98a82f110de..3d814ab4db8 100644
--- a/app/views/hooks/index.html.haml
+++ b/app/views/hooks/index.html.haml
@@ -38,5 +38,5 @@
           %span.monospace= hook.url
         %td
           .right
-            = link_to 'Test Hook', test_project_hook_path(@project, hook), class: "btn small grouped"
-            = link_to 'Remove', project_hook_path(@project, hook), confirm: 'Are you sure?', method: :delete, class: "danger btn small grouped"
+            = link_to 'Test Hook', test_project_hook_path(@project, hook), class: "btn btn-small grouped"
+            = link_to 'Remove', project_hook_path(@project, hook), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove btn-small grouped"
diff --git a/app/views/issues/_show.html.haml b/app/views/issues/_show.html.haml
index dcef901c15f..9f543ef97d8 100644
--- a/app/views/issues/_show.html.haml
+++ b/app/views/issues/_show.html.haml
@@ -4,15 +4,15 @@
       = check_box_tag dom_id(issue,"selected"), nil, false, 'data-id' => issue.id, class: "selected_issue", disabled: !can?(current_user, :modify_issue, issue)
   .right
     - if issue.notes.any?
-      %span.btn.small.disabled.grouped
+      %span.btn.btn-small.disabled.grouped
         %i.icon-comment
         = issue.notes.count
     - if can? current_user, :modify_issue, issue
       - if issue.closed
-        = link_to 'Reopen', project_issue_path(issue.project, issue, issue: {closed: false }, status_only: true), method: :put,  class: "btn small grouped reopen_issue", remote: true
+        = link_to 'Reopen', project_issue_path(issue.project, issue, issue: {closed: false }, status_only: true), method: :put,  class: "btn btn-small grouped reopen_issue", remote: true
       - else
-        = link_to 'Close', project_issue_path(issue.project, issue, issue: {closed: true }, status_only: true), method: :put, class: "btn small grouped close_issue", remote: true
-      = link_to edit_project_issue_path(issue.project, issue), class: "btn small edit-issue-link grouped" do
+        = link_to 'Close', project_issue_path(issue.project, issue, issue: {closed: true }, status_only: true), method: :put, class: "btn btn-small grouped close_issue", remote: true
+      = link_to edit_project_issue_path(issue.project, issue), class: "btn btn-small edit-issue-link grouped" do
         %i.icon-edit
         Edit
 
diff --git a/app/views/keys/_show.html.haml b/app/views/keys/_show.html.haml
index 049981766b6..9e85e6228ce 100644
--- a/app/views/keys/_show.html.haml
+++ b/app/views/keys/_show.html.haml
@@ -8,5 +8,5 @@
       = time_ago_in_words(key.created_at)
       ago
   %td
-    = link_to 'Remove', key, confirm: 'Are you sure?', method: :delete, class: "btn small btn-remove delete-key right"
+    = link_to 'Remove', key, confirm: 'Are you sure?', method: :delete, class: "btn btn-small btn-remove delete-key right"
 
diff --git a/app/views/merge_requests/_merge_request.html.haml b/app/views/merge_requests/_merge_request.html.haml
index 7369f3dd061..cdfc623d0a5 100644
--- a/app/views/merge_requests/_merge_request.html.haml
+++ b/app/views/merge_requests/_merge_request.html.haml
@@ -2,19 +2,19 @@
   .right
     .left
       - if merge_request.merged?
-        %span.btn.small.disabled.grouped
+        %span.btn.btn-small.disabled.grouped
           %strong
             %i.icon-ok
             = "MERGED"
       - if merge_request.notes.any?
-        %span.btn.small.disabled.grouped
+        %span.btn.btn-small.disabled.grouped
           %i.icon-comment
           = merge_request.mr_and_commit_notes.count
       - if merge_request.milestone_id?
-        %span.btn.small.disabled.grouped
+        %span.btn.btn-small.disabled.grouped
           %i.icon-time
           = merge_request.milestone.title
-      %span.btn.small.disabled.grouped
+      %span.btn.btn-small.disabled.grouped
         = merge_request.source_branch
         &rarr;
         = merge_request.target_branch
diff --git a/app/views/merge_requests/show/_mr_accept.html.haml b/app/views/merge_requests/show/_mr_accept.html.haml
index 128ffe76782..27f1c2ab8e1 100644
--- a/app/views/merge_requests/show/_mr_accept.html.haml
+++ b/app/views/merge_requests/show/_mr_accept.html.haml
@@ -31,7 +31,7 @@
   .automerge_widget.cannot_be_merged{style: "display:none"}
     .alert.alert-info
       %span
-        = link_to "Show how to merge", "#", class: "how_to_merge_link btn small padded", title: "How To Merge"
+        = link_to "Show how to merge", "#", class: "how_to_merge_link btn btn-small padded", title: "How To Merge"
         &nbsp;
         %strong This request can't be merged with GitLab. You should do it manually
 
diff --git a/app/views/milestones/_milestone.html.haml b/app/views/milestones/_milestone.html.haml
index 3864792f7e8..9111ff8b954 100644
--- a/app/views/milestones/_milestone.html.haml
+++ b/app/views/milestones/_milestone.html.haml
@@ -1,7 +1,7 @@
 %li{class: "milestone milestone-#{milestone.closed ? 'closed' : 'open'}", id: dom_id(milestone) }
   .right
     - if can?(current_user, :admin_milestone, milestone.project) and milestone.open?
-      = link_to edit_project_milestone_path(milestone.project, milestone), class: "btn small edit-milestone-link grouped" do
+      = link_to edit_project_milestone_path(milestone.project, milestone), class: "btn btn-small edit-milestone-link grouped" do
         %i.icon-edit
         Edit
   %h4
diff --git a/app/views/milestones/index.html.haml b/app/views/milestones/index.html.haml
index 3089595fe0b..c1dc6da983d 100644
--- a/app/views/milestones/index.html.haml
+++ b/app/views/milestones/index.html.haml
@@ -3,7 +3,7 @@
   %h3.page_title
     Milestones
     - if can? current_user, :admin_milestone, @project
-      = link_to "New Milestone", new_project_milestone_path(@project), class: "right btn small", title: "New Milestone"
+      = link_to "New Milestone", new_project_milestone_path(@project), class: "right btn btn-small", title: "New Milestone"
   %br
   %div.ui-box
     .title
diff --git a/app/views/milestones/show.html.haml b/app/views/milestones/show.html.haml
index 797f35befa5..eeefb70e57c 100644
--- a/app/views/milestones/show.html.haml
+++ b/app/views/milestones/show.html.haml
@@ -10,12 +10,12 @@
   .span6
     .right
       - unless  @milestone.closed
-        = link_to new_project_issue_path(@project, issue: { milestone_id: @milestone.id }), class: "btn small grouped", title: "New Issue" do
+        = link_to new_project_issue_path(@project, issue: { milestone_id: @milestone.id }), class: "btn btn-small grouped", title: "New Issue" do
           %i.icon-plus
           New Issue
         = link_to 'Browse Issues', project_issues_path(@milestone.project, milestone_id: @milestone.id), class: "btn edit-milestone-link small grouped"
         - if can?(current_user, :admin_milestone, @project)
-          = link_to edit_project_milestone_path(@project, @milestone), class: "btn small grouped" do
+          = link_to edit_project_milestone_path(@project, @milestone), class: "btn btn-small grouped" do
             %i.icon-edit
             Edit
 
@@ -25,7 +25,7 @@
   %hr
   %p
     %span All issues for this milestone are closed. You may close milestone now.
-    = link_to 'Close Milestone', project_milestone_path(@project, @milestone, milestone: {closed: true }), method: :put, class: "btn small btn-remove"
+    = link_to 'Close Milestone', project_milestone_path(@project, @milestone, milestone: {closed: true }), method: :put, class: "btn btn-small btn-remove"
 
 .ui-box.ui-box-show
   .ui-box-head
diff --git a/app/views/notes/_form.html.haml b/app/views/notes/_form.html.haml
index d094119a9da..a063fb0a6bb 100644
--- a/app/views/notes/_form.html.haml
+++ b/app/views/notes/_form.html.haml
@@ -26,7 +26,7 @@
     .attachment
       %h6 Attachment:
       .file_name.js-attachment-filename File name...
-      %a.choose-btn.btn.small.js-choose-note-attachment-button Choose File ...
+      %a.choose-btn.btn.btn-small.js-choose-note-attachment-button Choose File ...
       .hint Any file up to 10 MB
 
       = f.file_field :attachment, class: "js-note-attachment-input"
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index 4c0463aff79..65b5a5d29fc 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -65,13 +65,13 @@
             %li
               %p
                 Need a group for several dependent projects?
-                = link_to new_group_path, class: "btn very_small" do
+                = link_to new_group_path, class: "btn btn-tiny" do
                   Create a group
           - if current_user.can_create_team?
             %li
               %p
                 Want to share a team between projects?
-                = link_to new_team_path, class: "btn very_small" do
+                = link_to new_team_path, class: "btn btn-tiny" do
                   Create a team
       %fieldset
         %legend
@@ -90,7 +90,7 @@
           %span.right
             = link_to pluralize(current_user.keys.count, 'key'), keys_path
         .padded
-          = link_to "Add Public Key", new_key_path, class: "btn small"
+          = link_to "Add Public Key", new_key_path, class: "btn btn-small"
 
   .form-actions
     = f.submit 'Save', class: "btn btn-save"
diff --git a/app/views/projects/_new_form.html.haml b/app/views/projects/_new_form.html.haml
index dc4f4e23356..b3f2b82eb77 100644
--- a/app/views/projects/_new_form.html.haml
+++ b/app/views/projects/_new_form.html.haml
@@ -24,11 +24,11 @@
     .clearfix
       .input.light
         Need a group for several dependent projects?
-        = link_to new_group_path, class: "btn very_small" do
+        = link_to new_group_path, class: "btn btn-tiny" do
           Create a group
   - if current_user.can_create_team?
     .clearfix
       .input.light
         Want to share a project between team?
-        = link_to new_team_path, class: "btn very_small" do
+        = link_to new_team_path, class: "btn btn-tiny" do
           Create a team
diff --git a/app/views/protected_branches/index.html.haml b/app/views/protected_branches/index.html.haml
index 8ceff635fd9..6e7c638eb0f 100644
--- a/app/views/protected_branches/index.html.haml
+++ b/app/views/protected_branches/index.html.haml
@@ -51,4 +51,4 @@
                   (branch was removed from repository)
               %td
                 - if can? current_user, :admin_project, @project
-                  = link_to 'Unprotect', [@project, branch], confirm: 'Are you sure?', method: :delete, class: "danger btn small"
+                  = link_to 'Unprotect', [@project, branch], confirm: 'Are you sure?', method: :delete, class: "btn btn-remove btn-small"
diff --git a/app/views/snippets/_blob.html.haml b/app/views/snippets/_blob.html.haml
index ed518300ac0..017a33b34f3 100644
--- a/app/views/snippets/_blob.html.haml
+++ b/app/views/snippets/_blob.html.haml
@@ -3,7 +3,7 @@
     %i.icon-file
     %strong= @snippet.file_name
     %span.options
-      = link_to "raw", raw_project_snippet_path(@project, @snippet), class: "btn very_small", target: "_blank"
+      = link_to "raw", raw_project_snippet_path(@project, @snippet), class: "btn btn-tiny", target: "_blank"
   .file_content.code
     - unless @snippet.content.empty?
       %div{class: user_color_scheme_class}
diff --git a/app/views/snippets/index.html.haml b/app/views/snippets/index.html.haml
index 7b8f94de7dd..db2185745ef 100644
--- a/app/views/snippets/index.html.haml
+++ b/app/views/snippets/index.html.haml
@@ -5,7 +5,7 @@
   %small share code pastes with others out of git repository
 
   - if can? current_user, :write_snippet, @project
-    = link_to new_project_snippet_path(@project), class: "btn small add_new right", title: "New Snippet" do
+    = link_to new_project_snippet_path(@project), class: "btn btn-small add_new right", title: "New Snippet" do
       Add new snippet
 %br
 %table
diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml
index 02022185f9a..767b9736545 100644
--- a/app/views/snippets/show.html.haml
+++ b/app/views/snippets/show.html.haml
@@ -4,7 +4,7 @@
   = @snippet.title
   %small= @snippet.file_name
   - if can?(current_user, :admin_snippet, @project) || @snippet.author == current_user
-    = link_to "Edit", edit_project_snippet_path(@project, @snippet), class: "btn small right"
+    = link_to "Edit", edit_project_snippet_path(@project, @snippet), class: "btn btn-small right"
 
 %br
 %div= render 'blob'
diff --git a/app/views/team_members/_show.html.haml b/app/views/team_members/_show.html.haml
index c8138af4428..c85ec9812a8 100644
--- a/app/views/team_members/_show.html.haml
+++ b/app/views/team_members/_show.html.haml
@@ -19,10 +19,10 @@
         - if current_user == user
           %span.btn.disabled This is you!
         - if @project.namespace_owner == user
-          %span.btn.disabled.success Owner
+          %span.btn.disabled.btn-success Owner
         - elsif user.blocked
           %span.btn.disabled.blocked Blocked
         - elsif allow_admin
-          = link_to project_team_member_path(@project, user), confirm: remove_from_project_team_message(@project, user), method: :delete, class: "very_small btn btn-remove" do
+          = link_to project_team_member_path(@project, user), confirm: remove_from_project_team_message(@project, user), method: :delete, class: "btn-tiny btn btn-remove" do
             %i.icon-minus.icon-white
 
diff --git a/app/views/team_members/index.html.haml b/app/views/team_members/index.html.haml
index 935755f36c4..6e5090c7799 100644
--- a/app/views/team_members/index.html.haml
+++ b/app/views/team_members/index.html.haml
@@ -8,9 +8,9 @@
 
   - if can? current_user, :admin_team_member, @project
     %span.right
-      = link_to import_project_team_members_path(@project), class: "btn small grouped", title: "Import team from another project" do
+      = link_to import_project_team_members_path(@project), class: "btn btn-small grouped", title: "Import team from another project" do
         Import team from another project
-      = link_to available_project_teams_path(@project), class: "btn small grouped", title: "Assign project to team of users" do
+      = link_to available_project_teams_path(@project), class: "btn btn-small grouped", title: "Assign project to team of users" do
         Assign project to Team of users
       = link_to new_project_team_member_path(@project), class: "btn btn-primary small grouped", title: "New Team Member" do
         New Team Member
diff --git a/app/views/teams/_projects.html.haml b/app/views/teams/_projects.html.haml
index 4d99d5c259b..e72125919b1 100644
--- a/app/views/teams/_projects.html.haml
+++ b/app/views/teams/_projects.html.haml
@@ -5,7 +5,7 @@
       (#{projects.count})
     - if can? current_user, :manage_user_team, @team
       %span.right
-        = link_to new_team_project_path(@team), class: "btn very_small info" do
+        = link_to new_team_project_path(@team), class: "btn btn-tiny info" do
           %i.icon-plus
           Assign Project
   %ul.well-list
diff --git a/app/views/teams/members/_show.html.haml b/app/views/teams/members/_show.html.haml
index a14177dfe29..e2b702ab0d7 100644
--- a/app/views/teams/members/_show.html.haml
+++ b/app/views/teams/members/_show.html.haml
@@ -23,9 +23,9 @@
         - if current_user == user
           %span.btn.disabled This is you!
         - if @team.owner == user
-          %span.btn.disabled.success Owner
+          %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: "very_small btn btn-remove" do
+          = 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/projects/index.html.haml b/app/views/teams/projects/index.html.haml
index 5aa6a999c20..de2bee093ec 100644
--- a/app/views/teams/projects/index.html.haml
+++ b/app/views/teams/projects/index.html.haml
@@ -29,7 +29,7 @@
 
         - if current_user.can?(:admin_user_team, @team)
           %td.bgred
-            = link_to 'Edit max access', edit_team_project_path(@team, project), class: "btn small"
+            = link_to 'Edit max access', edit_team_project_path(@team, project), class: "btn btn-small"
             = link_to 'Relegate', team_project_path(@team, project), confirm: 'Remove project from team and move to global namespace. Are you sure?', method: :delete, class: "btn btn-remove small"
 
 - else
diff --git a/app/views/teams/show.html.haml b/app/views/teams/show.html.haml
index d9257ab090c..d6e80e2a51e 100644
--- a/app/views/teams/show.html.haml
+++ b/app/views/teams/show.html.haml
@@ -1,6 +1,6 @@
 .projects
   .activities.span8
-    = link_to dashboard_path, class: 'btn very_small' do
+    = link_to dashboard_path, class: 'btn btn-tiny' do
       &larr; To dashboard
     &nbsp;
     %span.cgray Events and projects are filtered in scope of team
diff --git a/app/views/tree/_blob_actions.html.haml b/app/views/tree/_blob_actions.html.haml
index 21334ea1f16..0bde968d0e6 100644
--- a/app/views/tree/_blob_actions.html.haml
+++ b/app/views/tree/_blob_actions.html.haml
@@ -1,12 +1,12 @@
 .btn-group.tree-btn-group
   -# only show edit link for text files
   - if @tree.text?
-    = link_to "edit", edit_project_tree_path(@project, @id), class: "btn very_small", disabled: !allowed_tree_edit?
-  = link_to "raw", project_blob_path(@project, @id), class: "btn very_small", target: "_blank"
+    = link_to "edit", edit_project_tree_path(@project, @id), class: "btn btn-tiny", disabled: !allowed_tree_edit?
+  = link_to "raw", project_blob_path(@project, @id), class: "btn btn-tiny", target: "_blank"
   -# only show normal/blame view links for text files
   - if @tree.text?
     - if current_page? project_blame_path(@project, @id)
-      = link_to "normal view", project_tree_path(@project, @id), class: "btn very_small"
+      = link_to "normal view", project_tree_path(@project, @id), class: "btn btn-tiny"
     - else
-      = link_to "blame", project_blame_path(@project, @id), class: "btn very_small"
-  = link_to "history", project_commits_path(@project, @id), class: "btn very_small"
+      = link_to "blame", project_blame_path(@project, @id), class: "btn btn-tiny"
+  = link_to "history", project_commits_path(@project, @id), class: "btn btn-tiny"
diff --git a/app/views/tree/_tree.html.haml b/app/views/tree/_tree.html.haml
index c2842959510..b0f775673b5 100644
--- a/app/views/tree/_tree.html.haml
+++ b/app/views/tree/_tree.html.haml
@@ -24,7 +24,7 @@
           %th Name
           %th Last Update
           %th Last Commit
-          %th= link_to "history", project_commits_path(@project, @id), class: "btn very_small right"
+          %th= link_to "history", project_commits_path(@project, @id), class: "btn btn-tiny right"
 
       - if tree.up_dir?
         %tr.tree-item
diff --git a/app/views/tree/edit.html.haml b/app/views/tree/edit.html.haml
index 281f4cc5ba2..81918e509b8 100644
--- a/app/views/tree/edit.html.haml
+++ b/app/views/tree/edit.html.haml
@@ -10,7 +10,7 @@
             %strong= @ref
         %span.options
           .btn-group.tree-btn-group
-            = link_to "Cancel", project_tree_path(@project, @id), class: "btn very_small btn-cancel", confirm: "Are you sure?"
+            = link_to "Cancel", project_tree_path(@project, @id), class: "btn btn-tiny btn-cancel", confirm: "Are you sure?"
       .file_content.code
         %pre#editor= @tree.data
 
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index 644826282b8..3977de24280 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -5,7 +5,7 @@
       = @user.name
       - if @user == current_user
         .right
-          = link_to profile_path, class: 'btn small' do
+          = link_to profile_path, class: 'btn btn-small' do
             %i.icon-edit
             Edit Profile
       %br
diff --git a/app/views/wikis/edit.html.haml b/app/views/wikis/edit.html.haml
index bf4a9aad444..71f8d6a9b6c 100644
--- a/app/views/wikis/edit.html.haml
+++ b/app/views/wikis/edit.html.haml
@@ -4,5 +4,5 @@
 
 .right
   - if can? current_user, :admin_wiki, @project
-    = link_to project_wiki_path(@project, @wiki), confirm: "Are you sure you want to delete this page?", method: :delete, class: "btn small btn-remove" do
+    = link_to project_wiki_path(@project, @wiki), confirm: "Are you sure you want to delete this page?", method: :delete, class: "btn btn-small btn-remove" do
       Delete this page
\ No newline at end of file
diff --git a/app/views/wikis/show.html.haml b/app/views/wikis/show.html.haml
index d3bd58bbeec..245d192efa1 100644
--- a/app/views/wikis/show.html.haml
+++ b/app/views/wikis/show.html.haml
@@ -1,12 +1,12 @@
 %h3.page_title
   = @wiki.title
   %span.right
-    = link_to pages_project_wikis_path(@project), class: "btn small grouped" do
+    = link_to pages_project_wikis_path(@project), class: "btn btn-small grouped" do
       Pages
     - if can? current_user, :write_wiki, @project
-      = link_to history_project_wiki_path(@project, @wiki), class: "btn small grouped" do
+      = link_to history_project_wiki_path(@project, @wiki), class: "btn btn-small grouped" do
         History
-      = link_to edit_project_wiki_path(@project, @wiki), class: "btn small grouped" do
+      = link_to edit_project_wiki_path(@project, @wiki), class: "btn btn-small grouped" do
         %i.icon-edit
         Edit
 %br
-- 
GitLab


From 7ba4f2dcfaa85fb89e15d9caa21bf75ad976389f Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 29 Jan 2013 22:57:15 +0200
Subject: [PATCH 137/197] few styling for buttons

---
 app/assets/stylesheets/gitlab_bootstrap/blocks.scss  | 4 ++++
 app/assets/stylesheets/gitlab_bootstrap/buttons.scss | 9 ++++++---
 app/views/groups/new.html.haml                       | 2 +-
 app/views/teams/new.html.haml                        | 2 +-
 4 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/app/assets/stylesheets/gitlab_bootstrap/blocks.scss b/app/assets/stylesheets/gitlab_bootstrap/blocks.scss
index 8cb1c045778..26681c65bf4 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/blocks.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/blocks.scss
@@ -98,6 +98,10 @@
       margin-top: 3px;
     }
 
+    .btn-tiny {
+      @include box-shadow(0 0px 0px 1px #f1f1f1);
+    }
+
     .nav-pills {
       > li {
         > a {
diff --git a/app/assets/stylesheets/gitlab_bootstrap/buttons.scss b/app/assets/stylesheets/gitlab_bootstrap/buttons.scss
index 86b4c5b3b64..a20c9b1b31e 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/buttons.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/buttons.scss
@@ -1,9 +1,12 @@
 .btn {
-  @include linear-gradient(#f7f7f7, #d5d5d5);
+  @include linear-gradient(#f1f1f1, #e1e1e1);
+  text-shadow: 0 1px 1px #FFF;
   border-color: #BBB;
+
   &:hover {
-    @include bg-gray-gradient;
-    border-color: #bbb;
+    background: #f1f1f1;
+    @include linear-gradient(#fAfAfA, #f1f1f1);
+    border-color: #AAA;
     color: #333;
   }
 
diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml
index 8fdedce95c9..224962df013 100644
--- a/app/views/groups/new.html.haml
+++ b/app/views/groups/new.html.haml
@@ -10,7 +10,7 @@
     .input
       = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
       &nbsp;
-      = f.submit 'Create group', class: "btn btn-primary"
+      = f.submit 'Create group', class: "btn btn-create"
   %hr
   .padded
     %ul
diff --git a/app/views/teams/new.html.haml b/app/views/teams/new.html.haml
index ca28f313e72..c0363fe39a8 100644
--- a/app/views/teams/new.html.haml
+++ b/app/views/teams/new.html.haml
@@ -10,7 +10,7 @@
     .input
       = f.text_field :name, placeholder: "Ex. Ruby Developers", class: "xxlarge left"
       &nbsp;
-      = f.submit 'Create team', class: "btn btn-primary"
+      = f.submit 'Create team', class: "btn btn-create"
   %hr
   .padded
     %ul
-- 
GitLab


From 525a8cd3e96b7bae0acda8b6e94df529fa06ff6a Mon Sep 17 00:00:00 2001
From: Sato Hiroyuki <sathiroyuki@gmail.com>
Date: Tue, 29 Jan 2013 17:25:17 +0900
Subject: [PATCH 138/197] Switchable the main branch on network graph

---
 app/controllers/graph_controller.rb            | 18 ++++++++++++++++++
 app/controllers/projects_controller.rb         | 10 ----------
 app/controllers/refs_controller.rb             |  2 ++
 .../graph.html.haml => graph/show.html.haml}   |  8 +++++---
 app/views/layouts/project_resource.html.haml   |  4 ++--
 config/routes.rb                               |  2 +-
 lib/extracts_path.rb                           |  3 ++-
 lib/gitlab/graph/json_builder.rb               |  7 ++++---
 vendor/assets/javascripts/branch-graph.js      | 11 +++++++++--
 9 files changed, 43 insertions(+), 22 deletions(-)
 create mode 100644 app/controllers/graph_controller.rb
 rename app/views/{projects/graph.html.haml => graph/show.html.haml} (63%)

diff --git a/app/controllers/graph_controller.rb b/app/controllers/graph_controller.rb
new file mode 100644
index 00000000000..30ec5e89db2
--- /dev/null
+++ b/app/controllers/graph_controller.rb
@@ -0,0 +1,18 @@
+class GraphController < ProjectResourceController
+  include ExtractsPath
+
+  # Authorize
+  before_filter :authorize_read_project!
+  before_filter :authorize_code_access!
+  before_filter :require_non_empty_project
+
+  def show
+    respond_to do |format|
+      format.html
+      format.json do
+        graph = Gitlab::Graph::JsonBuilder.new(project, @ref)
+        render :json => graph.to_json
+      end
+    end
+  end
+end
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 6e5e1f91381..7978ea6222c 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -90,16 +90,6 @@ class ProjectsController < ProjectResourceController
     end
   end
 
-  def graph
-    respond_to do |format|
-      format.html
-      format.json do
-        graph = Gitlab::Graph::JsonBuilder.new(project)
-        render :json => graph.to_json
-      end
-    end
-  end
-
   def destroy
     return access_denied! unless can?(current_user, :remove_project, project)
 
diff --git a/app/controllers/refs_controller.rb b/app/controllers/refs_controller.rb
index 09d9eb51b82..0e4dba3dc4b 100644
--- a/app/controllers/refs_controller.rb
+++ b/app/controllers/refs_controller.rb
@@ -13,6 +13,8 @@ class RefsController < ProjectResourceController
       format.html do
         new_path = if params[:destination] == "tree"
                      project_tree_path(@project, (@ref + "/" + params[:path]))
+                   elsif params[:destination] == "graph"
+                     project_graph_path(@project, @ref)
                    else
                      project_commits_path(@project, @ref)
                    end
diff --git a/app/views/projects/graph.html.haml b/app/views/graph/show.html.haml
similarity index 63%
rename from app/views/projects/graph.html.haml
rename to app/views/graph/show.html.haml
index 72d9cb5ef15..ca3a8706313 100644
--- a/app/views/projects/graph.html.haml
+++ b/app/views/graph/show.html.haml
@@ -1,6 +1,7 @@
 %h3.page_title Project Network Graph
 %br
-
+= render partial: 'shared/ref_switcher', locals: {destination: 'graph', path: @path}
+%br
 .graph_holder
   %h4
     %small You can move around the graph by using the arrow keys.
@@ -11,7 +12,8 @@
   var branch_graph;
   $(function(){
     branch_graph = new BranchGraph($("#holder"), {
-      url: '#{url_for controller: 'projects', action: 'graph', format: :json}',
-      commit_url: '#{project_commit_path(@project, 'ae45ca32').gsub("ae45ca32", "%s")}'
+      url: '#{project_graph_path(@project, @ref, format: :json)}',
+      commit_url: '#{project_commit_path(@project, 'ae45ca32').gsub("ae45ca32", "%s")}',
+      ref: '#{@ref}'
     });
   });
diff --git a/app/views/layouts/project_resource.html.haml b/app/views/layouts/project_resource.html.haml
index 14671c5ca70..c19d33ceec9 100644
--- a/app/views/layouts/project_resource.html.haml
+++ b/app/views/layouts/project_resource.html.haml
@@ -20,8 +20,8 @@
               = link_to 'Files', project_tree_path(@project, @ref || @repository.root_ref)
             = nav_link(controller: %w(commit commits compare repositories protected_branches)) do
               = link_to "Commits", project_commits_path(@project, @ref || @repository.root_ref)
-            = nav_link(path: 'projects#graph') do
-              = link_to "Network", graph_project_path(@project)
+            = nav_link(controller: %w(graph)) do
+              = link_to "Network", project_graph_path(@project, @ref || @repository.root_ref)
 
         - if @project.issues_enabled
           = nav_link(controller: %w(issues milestones labels)) do
diff --git a/config/routes.rb b/config/routes.rb
index 7ffa081ac32..1abd37fe45f 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -163,7 +163,6 @@ Gitlab::Application.routes.draw do
   resources :projects, constraints: { id: /[a-zA-Z.0-9_\-\/]+/ }, except: [:new, :create, :index], path: "/" do
     member do
       get "wall"
-      get "graph"
       get "files"
     end
 
@@ -173,6 +172,7 @@ Gitlab::Application.routes.draw do
     resources :compare, only: [:index, :create]
     resources :blame,   only: [:show], constraints: {id: /.+/}
     resources :blob,    only: [:show], constraints: {id: /.+/}
+    resources :graph,   only: [:show], constraints: {id: /.+/}
     match "/compare/:from...:to" => "compare#show", as: "compare",
                     :via => [:get, :post], constraints: {from: /.+/, to: /.+/}
 
diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb
index 12700e4f4ac..976ac018204 100644
--- a/lib/extracts_path.rb
+++ b/lib/extracts_path.rb
@@ -54,9 +54,10 @@ module ExtractsPath
     input.gsub!(/^#{Gitlab.config.gitlab.relative_url_root}/, "")
     # Remove project, actions and all other staff from path
     input.gsub!(/^\/#{Regexp.escape(@project.path_with_namespace)}/, "")
-    input.gsub!(/^\/(tree|commits|blame|blob|refs)\//, "") # remove actions
+    input.gsub!(/^\/(tree|commits|blame|blob|refs|graph)\//, "") # remove actions
     input.gsub!(/\?.*$/, "") # remove stamps suffix
     input.gsub!(/.atom$/, "") # remove rss feed
+    input.gsub!(/.json$/, "") # remove json suffix
     input.gsub!(/\/edit$/, "") # remove edit route part
 
     if input.match(/^([[:alnum:]]{40})(.+)/)
diff --git a/lib/gitlab/graph/json_builder.rb b/lib/gitlab/graph/json_builder.rb
index a3157aa4b4d..5a2f27fc1af 100644
--- a/lib/gitlab/graph/json_builder.rb
+++ b/lib/gitlab/graph/json_builder.rb
@@ -9,8 +9,9 @@ module Gitlab
         @max_count ||= 650
       end
 
-      def initialize project
+      def initialize project, ref
         @project = project
+        @ref = ref
         @repo = project.repo
         @ref_cache = {}
 
@@ -66,9 +67,9 @@ module Gitlab
         heads.select!{|h| h.is_a? Grit::Head or h.is_a? Grit::Remote}
         # sort heads so the master is top and current branches are closer
         heads.sort! do |a,b|
-          if a.name == "master"
+          if a.name == @ref
             -1
-          elsif b.name == "master"
+          elsif b.name == @ref
             1
           else
             b.commit.committed_date <=> a.commit.committed_date
diff --git a/vendor/assets/javascripts/branch-graph.js b/vendor/assets/javascripts/branch-graph.js
index 93849c79e80..cdaa8dd8d37 100644
--- a/vendor/assets/javascripts/branch-graph.js
+++ b/vendor/assets/javascripts/branch-graph.js
@@ -73,7 +73,8 @@
       , cumonth = ""
       , offsetX = 20
       , offsetY = 60
-      , barWidth = Math.max(graphWidth, this.dayCount * 20 + 320);
+      , barWidth = Math.max(graphWidth, this.dayCount * 20 + 320)
+      , scrollLeft = cw;
     
     this.raphael = r;
     
@@ -145,12 +146,18 @@
       
       if (this.commits[i].refs) {
         this.appendLabel(x, y, this.commits[i].refs);
+
+        // The main branch is displayed in the center.
+        re = new RegExp('(^| )' + this.options.ref + '( |$)');
+        if (this.commits[i].refs.match(re)) {
+          scrollLeft = x - graphWidth / 2;
+        }
       }
       
       this.appendAnchor(top, this.commits[i], x, y);
     }
     top.toFront();
-    this.element.scrollLeft(cw);
+    this.element.scrollLeft(scrollLeft);
     this.bindEvents();
   };
   
-- 
GitLab


From 1694dc8fe226c0687ce2c54a71739adba22f33c5 Mon Sep 17 00:00:00 2001
From: Micah Huff <micah@micahhuff.com>
Date: Tue, 29 Jan 2013 21:15:13 -0800
Subject: [PATCH 139/197] Expose MergeRequest object as a notable in the API to
 allow for easy retrieval of comments

---
 lib/api/notes.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/api/notes.rb b/lib/api/notes.rb
index 4613db54578..70344d6e381 100644
--- a/lib/api/notes.rb
+++ b/lib/api/notes.rb
@@ -3,7 +3,7 @@ module Gitlab
   class Notes < Grape::API
     before { authenticate! }
 
-    NOTEABLE_TYPES = [Issue, Snippet]
+    NOTEABLE_TYPES = [Issue, MergeRequest, Snippet]
 
     resource :projects do
       # Get a list of project wall notes
-- 
GitLab


From e2fb18a3ec8052997f0c9b795f76a6e4d57a9d97 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 30 Jan 2013 16:40:43 +0200
Subject: [PATCH 140/197] replace right with pull-right

---
 .../stylesheets/gitlab_bootstrap/blocks.scss     |  2 +-
 .../stylesheets/gitlab_bootstrap/common.scss     |  1 -
 app/assets/stylesheets/sections/events.scss      |  2 +-
 app/assets/stylesheets/sections/notes.scss       |  4 ++--
 app/assets/stylesheets/sections/projects.scss    |  2 +-
 app/views/admin/dashboard/index.html.haml        | 16 ++++++++--------
 app/views/admin/groups/index.html.haml           |  2 +-
 app/views/admin/groups/show.html.haml            |  4 ++--
 app/views/admin/hooks/index.html.haml            |  4 ++--
 app/views/admin/logs/show.html.haml              |  8 ++++----
 app/views/admin/projects/index.html.haml         |  4 ++--
 app/views/admin/projects/show.html.haml          |  2 +-
 app/views/admin/teams/index.html.haml            |  2 +-
 app/views/admin/teams/show.html.haml             |  8 ++++----
 app/views/admin/users/index.html.haml            |  2 +-
 app/views/admin/users/show.html.haml             |  2 +-
 app/views/blame/_head.html.haml                  |  2 +-
 app/views/commit/show.html.haml                  |  2 +-
 app/views/commits/_commit_box.html.haml          |  2 +-
 app/views/commits/_diffs.html.haml               |  4 ++--
 app/views/commits/_head.html.haml                |  2 +-
 app/views/dashboard/_filter.html.haml            |  4 ++--
 app/views/dashboard/_groups.html.haml            |  4 ++--
 app/views/dashboard/_projects.html.haml          |  2 +-
 app/views/dashboard/_teams.html.haml             |  4 ++--
 app/views/dashboard/issues.html.haml             |  2 +-
 app/views/dashboard/merge_requests.html.haml     |  2 +-
 app/views/dashboard/projects.html.haml           |  4 ++--
 app/views/deploy_keys/_show.html.haml            |  2 +-
 app/views/deploy_keys/show.html.haml             |  2 +-
 app/views/devise/passwords/edit.html.haml        |  2 +-
 app/views/devise/sessions/_new_ldap.html.haml    |  2 +-
 app/views/devise/sessions/new.html.haml          |  2 +-
 app/views/events/_event.html.haml                |  2 +-
 app/views/groups/_filter.html.haml               |  4 ++--
 app/views/groups/_people_filter.html.haml        |  4 ++--
 app/views/groups/_projects.html.haml             |  2 +-
 app/views/groups/issues.html.haml                |  2 +-
 app/views/groups/merge_requests.html.haml        |  2 +-
 app/views/groups/people.html.haml                |  2 +-
 app/views/help/_layout.html.haml                 |  2 +-
 app/views/help/index.html.haml                   |  2 +-
 app/views/hooks/index.html.haml                  |  2 +-
 app/views/issues/_filter.html.haml               |  2 +-
 app/views/issues/_head.html.haml                 |  2 +-
 app/views/issues/_issues.html.haml               |  2 +-
 app/views/issues/_show.html.haml                 |  2 +-
 app/views/issues/index.html.haml                 |  8 ++++----
 app/views/issues/show.html.haml                  |  6 +++---
 app/views/kaminari/admin/_paginator.html.haml    |  2 +-
 app/views/kaminari/gitlab/_paginator.html.haml   |  2 +-
 app/views/keys/_show.html.haml                   |  2 +-
 app/views/keys/index.html.haml                   |  2 +-
 app/views/keys/show.html.haml                    |  2 +-
 app/views/labels/_label.html.haml                |  2 +-
 app/views/merge_requests/_filter.html.haml       |  2 +-
 .../merge_requests/_merge_request.html.haml      |  2 +-
 app/views/merge_requests/index.html.haml         |  6 +++---
 .../merge_requests/show/_mr_title.html.haml      |  4 ++--
 app/views/milestones/_milestone.html.haml        |  2 +-
 app/views/milestones/index.html.haml             |  2 +-
 app/views/milestones/show.html.haml              |  4 ++--
 app/views/notes/_form.html.haml                  |  2 +-
 app/views/notes/_note.html.haml                  |  2 +-
 app/views/profiles/account.html.haml             |  4 ++--
 app/views/profiles/show.html.haml                |  8 ++++----
 app/views/projects/_clone_panel.html.haml        |  4 ++--
 app/views/projects/_form.html.haml               |  2 +-
 app/views/projects/empty.html.haml               |  2 +-
 app/views/public/projects/index.html.haml        |  2 +-
 app/views/repositories/_feed.html.haml           |  2 +-
 app/views/repositories/stats.html.haml           |  2 +-
 app/views/services/_gitlab_ci.html.haml          |  2 +-
 app/views/services/index.html.haml               |  6 +++---
 app/views/snippets/_form.html.haml               |  2 +-
 app/views/snippets/index.html.haml               |  2 +-
 app/views/snippets/show.html.haml                |  2 +-
 app/views/team_members/_show.html.haml           |  4 ++--
 app/views/team_members/_show_team.html.haml      |  4 ++--
 app/views/team_members/index.html.haml           |  2 +-
 app/views/team_members/show.html.haml            |  2 +-
 app/views/teams/_filter.html.haml                |  4 ++--
 app/views/teams/_projects.html.haml              |  2 +-
 app/views/teams/issues.html.haml                 |  2 +-
 app/views/teams/members/_show.html.haml          |  4 ++--
 app/views/teams/members/index.html.haml          |  2 +-
 app/views/teams/members/show.html.haml           |  2 +-
 app/views/teams/merge_requests.html.haml         |  2 +-
 app/views/teams/projects/index.html.haml         |  2 +-
 app/views/tree/_head.html.haml                   |  2 +-
 app/views/tree/_tree.html.haml                   |  2 +-
 app/views/users/_profile.html.haml               | 10 +++++-----
 app/views/users/_projects.html.haml              |  2 +-
 app/views/users/show.html.haml                   |  2 +-
 app/views/wikis/edit.html.haml                   |  2 +-
 app/views/wikis/show.html.haml                   |  2 +-
 96 files changed, 143 insertions(+), 144 deletions(-)

diff --git a/app/assets/stylesheets/gitlab_bootstrap/blocks.scss b/app/assets/stylesheets/gitlab_bootstrap/blocks.scss
index 26681c65bf4..4d1b6446362 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/blocks.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/blocks.scss
@@ -95,7 +95,7 @@
 
     form {
       margin-bottom: 0;
-      margin-top: 3px;
+      margin-top: 0;
     }
 
     .btn-tiny {
diff --git a/app/assets/stylesheets/gitlab_bootstrap/common.scss b/app/assets/stylesheets/gitlab_bootstrap/common.scss
index f6b4881658c..fb2f34179b7 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/common.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/common.scss
@@ -9,7 +9,6 @@
 
 /** COMMON CLASSES **/
 .left { float:left }
-.right { float:right!important }
 .append-bottom-10 { margin-bottom:10px }
 .append-bottom-20 { margin-bottom:20px }
 .prepend-top-10 { margin-top:10px }
diff --git a/app/assets/stylesheets/sections/events.scss b/app/assets/stylesheets/sections/events.scss
index 7472cb09326..ff810147178 100644
--- a/app/assets/stylesheets/sections/events.scss
+++ b/app/assets/stylesheets/sections/events.scss
@@ -127,7 +127,7 @@
   .btn-new-mr {
     @extend .btn-info;
     @extend .small;
-    @extend .right;
+    @extend .pull-right;
     margin: -3px;
   }
 }
diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss
index b29d2991d34..895e9dfa4e3 100644
--- a/app/assets/stylesheets/sections/notes.scss
+++ b/app/assets/stylesheets/sections/notes.scss
@@ -258,7 +258,7 @@ ul.notes {
     }
 
     .attachment {
-      @extend .right;
+      @extend .pull-right;
       position: relative;
       width: 350px;
       height: 50px;
@@ -274,7 +274,7 @@ ul.notes {
       }
     }
     .notify_options {
-      @extend .right;
+      @extend .pull-right;
     }
   }
   .note_text_and_preview {
diff --git a/app/assets/stylesheets/sections/projects.scss b/app/assets/stylesheets/sections/projects.scss
index b6db65adff1..28df1b5ac28 100644
--- a/app/assets/stylesheets/sections/projects.scss
+++ b/app/assets/stylesheets/sections/projects.scss
@@ -4,7 +4,7 @@
   }
 
   .side {
-    @extend .right;
+    @extend .pull-right;
 
     .projects_box {
       > .title {
diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml
index 3698778e9fc..46a876294ce 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -31,7 +31,7 @@
     - @projects.each do |project|
       %p
         = link_to project.name_with_namespace, [:admin, project]
-        %span.light.right
+        %span.light.pull-right
           = time_ago_in_words project.created_at
           ago
 
@@ -42,7 +42,7 @@
       %p
         = link_to [:admin, user] do
           = user.name
-        %span.light.right
+        %span.light.pull-right
           = time_ago_in_words user.created_at
           ago
 
@@ -51,25 +51,25 @@
     %hr
     %p
       Issues
-      %span.light.right
+      %span.light.pull-right
         = Issue.count
     %p
       Merge Requests
-      %span.light.right
+      %span.light.pull-right
         = MergeRequest.count
     %p
       Notes
-      %span.light.right
+      %span.light.pull-right
         = Note.count
     %p
       Snippets
-      %span.light.right
+      %span.light.pull-right
         = Snippet.count
     %p
       SSH Keys
-      %span.light.right
+      %span.light.pull-right
         = Key.count
     %p
       Milestones
-      %span.light.right
+      %span.light.pull-right
         = Milestone.count
diff --git a/app/views/admin/groups/index.html.haml b/app/views/admin/groups/index.html.haml
index f1e857eca8a..25ce66575bf 100644
--- a/app/views/admin/groups/index.html.haml
+++ b/app/views/admin/groups/index.html.haml
@@ -4,7 +4,7 @@
     allows you to keep projects organized.
     Use groups for uniting related projects.
 
-  = link_to 'New Group', new_admin_group_path, class: "btn btn-small right"
+  = link_to 'New Group', new_admin_group_path, class: "btn btn-small pull-right"
 %br
 = form_tag admin_groups_path, method: :get, class: 'form-inline' do
   = text_field_tag :name, params[:name], class: "xlarge"
diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml
index b5bdeeaaded..6ae8a75d696 100644
--- a/app/views/admin/groups/show.html.haml
+++ b/app/views/admin/groups/show.html.haml
@@ -14,7 +14,7 @@
     %td
       = @group.name
       &nbsp;
-      = link_to edit_admin_group_path(@group), class: "btn btn-small right" do
+      = link_to edit_admin_group_path(@group), class: "btn btn-small pull-right" do
         %i.icon-edit
         Rename
   %tr
@@ -29,7 +29,7 @@
         Owner:
     %td
       = @group.owner_name
-      .right
+      .pull-right
         = link_to "#", class: "btn btn-small change-owner-link" do
           %i.icon-edit
           Change owner
diff --git a/app/views/admin/hooks/index.html.haml b/app/views/admin/hooks/index.html.haml
index 412a7ff2038..838296ccf3a 100644
--- a/app/views/admin/hooks/index.html.haml
+++ b/app/views/admin/hooks/index.html.haml
@@ -33,7 +33,7 @@
         %td
           = link_to admin_hook_path(hook) do
             %strong= hook.url
-          = link_to 'Test Hook', admin_hook_test_path(hook), class: "btn btn-small right"
+          = link_to 'Test Hook', admin_hook_test_path(hook), class: "btn btn-small pull-right"
         %td POST
         %td
-          = link_to 'Remove', admin_hook_path(hook), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove btn-small right"
+          = link_to 'Remove', admin_hook_path(hook), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove btn-small pull-right"
diff --git a/app/views/admin/logs/show.html.haml b/app/views/admin/logs/show.html.haml
index c8be2ffa43c..9ddd781c6ec 100644
--- a/app/views/admin/logs/show.html.haml
+++ b/app/views/admin/logs/show.html.haml
@@ -15,7 +15,7 @@
       .file_title
         %i.icon-file
         githost.log
-        .right
+        .pull-right
           = link_to '#', class: 'log-bottom' do
             %i.icon-arrow-down
             Scroll down
@@ -29,7 +29,7 @@
       .file_title
         %i.icon-file
         application.log
-        .right
+        .pull-right
           = link_to '#', class: 'log-bottom' do
             %i.icon-arrow-down
             Scroll down
@@ -43,7 +43,7 @@
       .file_title
         %i.icon-file
         production.log
-        .right
+        .pull-right
           = link_to '#', class: 'log-bottom' do
             %i.icon-arrow-down
             Scroll down
@@ -57,7 +57,7 @@
       .file_title
         %i.icon-file
         sidekiq.log
-        .right
+        .pull-right
           = link_to '#', class: 'log-bottom' do
             %i.icon-arrow-down
             Scroll down
diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml
index f42e1f3af86..15b2778252a 100644
--- a/app/views/admin/projects/index.html.haml
+++ b/app/views/admin/projects/index.html.haml
@@ -1,6 +1,6 @@
 %h3.page_title
   Projects
-  = link_to 'New Project', new_project_path, class: "btn btn-small right"
+  = link_to 'New Project', new_project_path, class: "btn btn-small pull-right"
 
 %hr
 
@@ -51,7 +51,7 @@
             - else
               %i.icon-lock.cgreen
             = link_to project.name_with_namespace, [:admin, project]
-            .right
+            .pull-right
               = link_to 'Edit', edit_admin_project_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small"
               = link_to 'Destroy', [:admin, project], confirm: "REMOVE #{project.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove"
         - if @projects.blank?
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index fc3ed1e8b23..b9294bbafbe 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -1,6 +1,6 @@
 %h3.page_title
   Project: #{@project.name_with_namespace}
-  = link_to edit_admin_project_path(@project), class: "btn right" do
+  = link_to edit_admin_project_path(@project), class: "btn pull-right" do
     %i.icon-edit
     Edit
 
diff --git a/app/views/admin/teams/index.html.haml b/app/views/admin/teams/index.html.haml
index 1d54a27f8f5..1f2f4763f76 100644
--- a/app/views/admin/teams/index.html.haml
+++ b/app/views/admin/teams/index.html.haml
@@ -3,7 +3,7 @@
   %small
     simple Teams description
 
-  = link_to 'New Team', new_admin_team_path, class: "btn btn-small right"
+  = link_to 'New Team', new_admin_team_path, class: "btn btn-small pull-right"
   %br
 
 = form_tag admin_teams_path, method: :get, class: 'form-inline' do
diff --git a/app/views/admin/teams/show.html.haml b/app/views/admin/teams/show.html.haml
index 4d27f31be58..e5d079981c0 100644
--- a/app/views/admin/teams/show.html.haml
+++ b/app/views/admin/teams/show.html.haml
@@ -14,7 +14,7 @@
     %td
       = @team.name
       &nbsp;
-      = link_to edit_admin_team_path(@team), class: "btn btn-small right" do
+      = link_to edit_admin_team_path(@team), class: "btn btn-small pull-right" do
         %i.icon-edit
         Rename
   %tr
@@ -23,7 +23,7 @@
         Owner:
     %td
       = @team.owner.name
-      .right
+      .pull-right
         = link_to "#", class: "btn btn-small change-owner-link" do
           %i.icon-edit
           Change owner
@@ -42,7 +42,7 @@
 %fieldset
   %legend
     Members (#{@team.members.count})
-    %span= link_to 'Add members', new_admin_team_member_path(@team), class: "btn btn-primary btn-small right", id: :add_members_to_team
+    %span= link_to 'Add members', new_admin_team_member_path(@team), class: "btn btn-primary btn-small pull-right", id: :add_members_to_team
   - if @team.members.any?
     %table#members_list
       %thead
@@ -67,7 +67,7 @@
 %fieldset
   %legend
     Projects (#{@team.projects.count})
-    %span= link_to 'Add projects', new_admin_team_project_path(@team), class: "btn btn-primary btn-small right", id: :assign_projects_to_team
+    %span= link_to 'Add projects', new_admin_team_project_path(@team), class: "btn btn-primary btn-small pull-right", id: :assign_projects_to_team
   - if @team.projects.any?
     %table#projects_list
       %thead
diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml
index d8828183083..87d6309aefd 100644
--- a/app/views/admin/users/index.html.haml
+++ b/app/views/admin/users/index.html.haml
@@ -1,6 +1,6 @@
 %h3.page_title
   Users
-  = link_to 'New User', new_admin_user_path, class: "btn btn-small right"
+  = link_to 'New User', new_admin_user_path, class: "btn btn-small pull-right"
 %br
 
 = form_tag admin_users_path, method: :get, class: 'form-inline' do
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index 69062aa375a..08201abd7d5 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -4,7 +4,7 @@
     %small Blocked
   - if @admin_user.admin
     %small Administrator
-  = link_to edit_admin_user_path(@admin_user), class: "btn right" do
+  = link_to edit_admin_user_path(@admin_user), class: "btn pull-right" do
     %i.icon-edit
     Edit
 
diff --git a/app/views/blame/_head.html.haml b/app/views/blame/_head.html.haml
index 85da18052b4..ef9e6c9c532 100644
--- a/app/views/blame/_head.html.haml
+++ b/app/views/blame/_head.html.haml
@@ -3,5 +3,5 @@
     = render partial: 'shared/ref_switcher', locals: {destination: 'tree', path: params[:path]}
   = nav_link(controller: :refs) do
     = link_to 'Source', project_tree_path(@project, @ref)
-  %li.right
+  %li.pull-right
     = render "shared/clone_panel"
diff --git a/app/views/commit/show.html.haml b/app/views/commit/show.html.haml
index 6bee6493ac6..485f2d1e67c 100644
--- a/app/views/commit/show.html.haml
+++ b/app/views/commit/show.html.haml
@@ -1,6 +1,6 @@
 = render "commits/commit_box"
 
-%p.right.cgray
+%p.pull-right.cgray
   This commit has
   %span.cgreen #{@commit.stats.additions} additions
   and
diff --git a/app/views/commits/_commit_box.html.haml b/app/views/commits/_commit_box.html.haml
index 4767c493ab7..4c80c13ced1 100644
--- a/app/views/commits/_commit_box.html.haml
+++ b/app/views/commits/_commit_box.html.haml
@@ -1,6 +1,6 @@
 .ui-box.ui-box-show
   .ui-box-head
-    .right
+    .pull-right
       - if @notes_count > 0
         %span.btn.disabled.grouped
           %i.icon-comment
diff --git a/app/views/commits/_diffs.html.haml b/app/views/commits/_diffs.html.haml
index 5e7d43c99cb..db9180c4057 100644
--- a/app/views/commits/_diffs.html.haml
+++ b/app/views/commits/_diffs.html.haml
@@ -25,7 +25,7 @@
             %span= diff.old_path
 
             - if @commit.prev_commit
-              = link_to project_tree_path(@project, tree_join(@commit.prev_commit_id, diff.new_path)), {:class => 'btn right view-file'} do
+              = link_to project_tree_path(@project, tree_join(@commit.prev_commit_id, diff.new_path)), {:class => 'btn pull-right view-file'} do
                 View file @
                 %span.commit-short-id= @commit.short_id(6)
           - else
@@ -33,7 +33,7 @@
             - if diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode
               %span.file-mode= "#{diff.a_mode} → #{diff.b_mode}"
 
-            = link_to project_tree_path(@project, tree_join(@commit.id, diff.new_path)), {:class => 'btn btn-tiny right view-file'} do
+            = link_to project_tree_path(@project, tree_join(@commit.id, diff.new_path)), {:class => 'btn btn-tiny pull-right view-file'} do
               View file @
               %span.commit-short-id= @commit.short_id(6)
 
diff --git a/app/views/commits/_head.html.haml b/app/views/commits/_head.html.haml
index a5f3fdf5c5e..02debe426fe 100644
--- a/app/views/commits/_head.html.haml
+++ b/app/views/commits/_head.html.haml
@@ -22,7 +22,7 @@
 
 
   - if current_controller?(:commits) && current_user.private_token
-    %li.right
+    %li.pull-right
       %span.rss-icon
         = link_to project_commits_path(@project, @ref, {format: :atom, private_token: current_user.private_token}), title: "Feed" do
           = image_tag "rss_ui.png", title: "feed"
diff --git a/app/views/dashboard/_filter.html.haml b/app/views/dashboard/_filter.html.haml
index 4624af79948..82e679d5927 100644
--- a/app/views/dashboard/_filter.html.haml
+++ b/app/views/dashboard/_filter.html.haml
@@ -25,9 +25,9 @@
           %li{class: ("active" if params[:project_id] == project.id.to_s)}
             = link_to dashboard_filter_path(entity, project_id: project.id) do
               = project.name_with_namespace
-              %small.right= entities_per_project(project, entity)
+              %small.pull-right= entities_per_project(project, entity)
 
   %fieldset
     %hr
-    = link_to "Reset", dashboard_filter_path(entity), class: 'btn right'
+    = link_to "Reset", dashboard_filter_path(entity), class: 'btn pull-right'
 
diff --git a/app/views/dashboard/_groups.html.haml b/app/views/dashboard/_groups.html.haml
index 535f0349212..ba8d3029eaf 100644
--- a/app/views/dashboard/_groups.html.haml
+++ b/app/views/dashboard/_groups.html.haml
@@ -4,7 +4,7 @@
     %small
       (#{groups.count})
     - if current_user.can_create_group?
-      %span.right
+      %span.pull-right
         = link_to new_group_path, class: "btn btn-tiny info" do
           %i.icon-plus
           New Group
@@ -13,6 +13,6 @@
       %li
         = link_to group_path(id: group.path), class: dom_class(group) do
           %strong.well-title= truncate(group.name, length: 35)
-        %span.right.light
+        %span.pull-right.light
           - if group.owner == current_user
             %i.icon-wrench
diff --git a/app/views/dashboard/_projects.html.haml b/app/views/dashboard/_projects.html.haml
index a5396a0023d..30fb7268014 100644
--- a/app/views/dashboard/_projects.html.haml
+++ b/app/views/dashboard/_projects.html.haml
@@ -4,7 +4,7 @@
     %small
       (#{@projects_count})
     - if current_user.can_create_project?
-      %span.right
+      %span.pull-right
         = link_to new_project_path, class: "btn btn-tiny info" do
           %i.icon-plus
           New Project
diff --git a/app/views/dashboard/_teams.html.haml b/app/views/dashboard/_teams.html.haml
index 1be6e25c54d..f56115856a7 100644
--- a/app/views/dashboard/_teams.html.haml
+++ b/app/views/dashboard/_teams.html.haml
@@ -3,7 +3,7 @@
     Teams
     %small
       (#{@teams.count})
-    %span.right
+    %span.pull-right
       = link_to new_team_path, class: "btn btn-tiny info" do
         %i.icon-plus
         New Team
@@ -12,7 +12,7 @@
       %li
         = link_to team_path(id: team.path), class: dom_class(team) do
           %strong.well-title= truncate(team.name, length: 35)
-        %span.right.light
+        %span.pull-right.light
           - if team.owner == current_user
             %i.icon-wrench
           - tm = current_user.user_team_user_relationships.find_by_user_team_id(team.id)
diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml
index 307d0d85ea3..affe01a7ef9 100644
--- a/app/views/dashboard/issues.html.haml
+++ b/app/views/dashboard/issues.html.haml
@@ -1,7 +1,7 @@
 %h3.page_title
   Issues
   %small (assigned to you)
-  %small.right #{@issues.total_count} issues
+  %small.pull-right #{@issues.total_count} issues
 
 %hr
 
diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml
index 0c4d6e0aadf..a311729dd4d 100644
--- a/app/views/dashboard/merge_requests.html.haml
+++ b/app/views/dashboard/merge_requests.html.haml
@@ -1,7 +1,7 @@
 %h3.page_title
   Merge Requests
   %small (authored by or assigned to you)
-  %small.right #{@merge_requests.total_count} merge requests
+  %small.pull-right #{@merge_requests.total_count} merge requests
 
 %hr
 .row
diff --git a/app/views/dashboard/projects.html.haml b/app/views/dashboard/projects.html.haml
index 94b319fe24f..8e21b0c7e02 100644
--- a/app/views/dashboard/projects.html.haml
+++ b/app/views/dashboard/projects.html.haml
@@ -3,7 +3,7 @@
   %span
     (#{@projects.total_count})
   - if current_user.can_create_project?
-    %span.right
+    %span.pull-right
       = link_to new_project_path, class: "btn btn-tiny info" do
         %i.icon-plus
         New Project
@@ -42,7 +42,7 @@
             %small.light
               %strong Last activity:
               %span= project_last_activity(project)
-          .right.light
+          .pull-right.light
             - if project.owner == current_user
               %i.icon-wrench
             - tm = project.team.get_tm(current_user.id)
diff --git a/app/views/deploy_keys/_show.html.haml b/app/views/deploy_keys/_show.html.haml
index 68b00568c6d..635054350ec 100644
--- a/app/views/deploy_keys/_show.html.haml
+++ b/app/views/deploy_keys/_show.html.haml
@@ -8,5 +8,5 @@
       = time_ago_in_words(key.created_at)
       ago
   %td
-    = link_to 'Remove', project_deploy_key_path(key.project, key), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove delete-key btn-small right"
+    = link_to 'Remove', project_deploy_key_path(key.project, key), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove delete-key btn-small pull-right"
 
diff --git a/app/views/deploy_keys/show.html.haml b/app/views/deploy_keys/show.html.haml
index 4a864fae9d7..227afecb061 100644
--- a/app/views/deploy_keys/show.html.haml
+++ b/app/views/deploy_keys/show.html.haml
@@ -10,5 +10,5 @@
     &larr; To keys list
 %hr
 %pre= @key.key
-.right
+.pull-right
   = link_to 'Remove', project_deploy_key_path(@key.project, @key), confirm: 'Are you sure?', method: :delete, class: "btn-remove btn delete-key"
diff --git a/app/views/devise/passwords/edit.html.haml b/app/views/devise/passwords/edit.html.haml
index 6ca0c5d8c08..e5800025c6d 100644
--- a/app/views/devise/passwords/edit.html.haml
+++ b/app/views/devise/passwords/edit.html.haml
@@ -9,4 +9,4 @@
     = f.password_field :password_confirmation, class: "text bottom", placeholder: "Confirm new password"
   %div
     = f.submit "Change my password", class: "btn btn-primary"
-    .right= render partial: "devise/shared/links"
+    .pull-right= render partial: "devise/shared/links"
diff --git a/app/views/devise/sessions/_new_ldap.html.haml b/app/views/devise/sessions/_new_ldap.html.haml
index a4060130552..7968b0e9c9f 100644
--- a/app/views/devise/sessions/_new_ldap.html.haml
+++ b/app/views/devise/sessions/_new_ldap.html.haml
@@ -25,5 +25,5 @@
         %span Remember me
   %br/
   = f.submit "Sign in", :class => "btn-primary btn"
-  .right
+  .pull-right
     = render :partial => "devise/shared/links"
diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml
index 0a252e25487..7ea41876e44 100644
--- a/app/views/devise/sessions/new.html.haml
+++ b/app/views/devise/sessions/new.html.haml
@@ -12,7 +12,7 @@
           %span Remember me
     %br/
     = f.submit "Sign in", :class => "btn-primary btn wide"
-    .right
+    .pull-right
       = link_to "Forgot your password?", new_password_path(resource_name), :class => "btn"
     %br/
     %br/
diff --git a/app/views/events/_event.html.haml b/app/views/events/_event.html.haml
index 191aed0747e..719f6c3787f 100644
--- a/app/views/events/_event.html.haml
+++ b/app/views/events/_event.html.haml
@@ -1,6 +1,6 @@
 - if event.proper?
   %div.event-item
-    %span.cgray.right
+    %span.cgray.pull-right
       #{time_ago_in_words(event.created_at)} ago.
 
     = image_tag gravatar_icon(event.author_email), class: "avatar s24"
diff --git a/app/views/groups/_filter.html.haml b/app/views/groups/_filter.html.haml
index c8b0ad0f433..c14fc8e5e4b 100644
--- a/app/views/groups/_filter.html.haml
+++ b/app/views/groups/_filter.html.haml
@@ -25,9 +25,9 @@
           %li{class: ("active" if params[:project_id] == project.id.to_s)}
             = link_to group_filter_path(entity, project_id: project.id) do
               = project.name_with_namespace
-              %small.right= entities_per_project(project, entity)
+              %small.pull-right= entities_per_project(project, entity)
 
   %fieldset
     %hr
-    = link_to "Reset", group_filter_path(entity), class: 'btn right'
+    = link_to "Reset", group_filter_path(entity), class: 'btn pull-right'
 
diff --git a/app/views/groups/_people_filter.html.haml b/app/views/groups/_people_filter.html.haml
index 79a1b01a5fa..901a037adf3 100644
--- a/app/views/groups/_people_filter.html.haml
+++ b/app/views/groups/_people_filter.html.haml
@@ -6,9 +6,9 @@
         %li{class: ("active" if params[:project_id] == project.id.to_s)}
           = link_to people_group_path(@group, project_id: project.id) do
             = project.name_with_namespace
-            %small.right= project.users.count
+            %small.pull-right= project.users.count
 
   %fieldset
     %hr
-    = link_to "Reset", people_group_path(@group), class: 'btn right'
+    = link_to "Reset", people_group_path(@group), class: 'btn pull-right'
 
diff --git a/app/views/groups/_projects.html.haml b/app/views/groups/_projects.html.haml
index b7732c50a32..4fa4a177983 100644
--- a/app/views/groups/_projects.html.haml
+++ b/app/views/groups/_projects.html.haml
@@ -4,7 +4,7 @@
     %small
       (#{projects.count})
     - if can? current_user, :manage_group, @group
-      %span.right
+      %span.pull-right
         = link_to new_project_path(namespace_id: @group.id), class: "btn btn-tiny info" do
           %i.icon-plus
           New Project
diff --git a/app/views/groups/issues.html.haml b/app/views/groups/issues.html.haml
index 9e8642f3b2c..94682bdd51e 100644
--- a/app/views/groups/issues.html.haml
+++ b/app/views/groups/issues.html.haml
@@ -1,7 +1,7 @@
 %h3.page_title
   Issues
   %small (assigned to you)
-  %small.right #{@issues.total_count} issues
+  %small.pull-right #{@issues.total_count} issues
 
 %hr
 .row
diff --git a/app/views/groups/merge_requests.html.haml b/app/views/groups/merge_requests.html.haml
index 0c4d6e0aadf..a311729dd4d 100644
--- a/app/views/groups/merge_requests.html.haml
+++ b/app/views/groups/merge_requests.html.haml
@@ -1,7 +1,7 @@
 %h3.page_title
   Merge Requests
   %small (authored by or assigned to you)
-  %small.right #{@merge_requests.total_count} merge requests
+  %small.pull-right #{@merge_requests.total_count} merge requests
 
 %hr
 .row
diff --git a/app/views/groups/people.html.haml b/app/views/groups/people.html.haml
index 0bceeaa3ceb..3e4eb082f56 100644
--- a/app/views/groups/people.html.haml
+++ b/app/views/groups/people.html.haml
@@ -16,5 +16,5 @@
             %strong= user.name
             %span.cgray= user.email
             - if @group.owner == user
-              %span.btn.btn-small.disabled.right Group Owner
+              %span.btn.btn-small.disabled.pull-right Group Owner
 
diff --git a/app/views/help/_layout.html.haml b/app/views/help/_layout.html.haml
index 3839be2773c..fa5e3a30b29 100644
--- a/app/views/help/_layout.html.haml
+++ b/app/views/help/_layout.html.haml
@@ -30,5 +30,5 @@
         %li
           %strong= link_to "Public Access", help_public_access_path
 
-  .span9.right
+  .span9.pull-right
     = yield
diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml
index 28791b321f1..1a4411c8f30 100644
--- a/app/views/help/index.html.haml
+++ b/app/views/help/index.html.haml
@@ -1,6 +1,6 @@
 %h3.page_title
   GITLAB
-  .right
+  .pull-right
     %span= Gitlab::Version
     %small= Gitlab::Revision
 %hr
diff --git a/app/views/hooks/index.html.haml b/app/views/hooks/index.html.haml
index 3d814ab4db8..334b0f19301 100644
--- a/app/views/hooks/index.html.haml
+++ b/app/views/hooks/index.html.haml
@@ -37,6 +37,6 @@
           &rarr;
           %span.monospace= hook.url
         %td
-          .right
+          .pull-right
             = link_to 'Test Hook', test_project_hook_path(@project, hook), class: "btn btn-small grouped"
             = link_to 'Remove', project_hook_path(@project, hook), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove btn-small grouped"
diff --git a/app/views/issues/_filter.html.haml b/app/views/issues/_filter.html.haml
index 779e55bb7af..21efaa5357c 100644
--- a/app/views/issues/_filter.html.haml
+++ b/app/views/issues/_filter.html.haml
@@ -16,5 +16,5 @@
 
   %fieldset
     %hr
-    = link_to "Reset", project_issues_path(@project), class: 'btn right'
+    = link_to "Reset", project_issues_path(@project), class: 'btn pull-right'
 
diff --git a/app/views/issues/_head.html.haml b/app/views/issues/_head.html.haml
index 4294503c211..7e0b2cde074 100644
--- a/app/views/issues/_head.html.haml
+++ b/app/views/issues/_head.html.haml
@@ -5,7 +5,7 @@
     = link_to 'Milestones', project_milestones_path(@project), class: "tab"
   = nav_link(controller: :labels) do
     = link_to 'Labels', project_labels_path(@project), class: "tab"
-  %li.right
+  %li.pull-right
     %span.rss-icon
       = link_to project_issues_path(@project, :atom, { private_token: current_user.private_token }) do
         = image_tag "rss_ui.png", title: "feed"
diff --git a/app/views/issues/_issues.html.haml b/app/views/issues/_issues.html.haml
index 8821dbb8d98..3bbd293dba2 100644
--- a/app/views/issues/_issues.html.haml
+++ b/app/views/issues/_issues.html.haml
@@ -4,7 +4,7 @@
 - if @issues.present?
   %li.bottom
     .left= paginate @issues, remote: true, theme: "gitlab"
-    .right
+    .pull-right
       %span.issue_counter #{@issues.total_count}
       issues for this filter
 - else
diff --git a/app/views/issues/_show.html.haml b/app/views/issues/_show.html.haml
index 9f543ef97d8..fa888618066 100644
--- a/app/views/issues/_show.html.haml
+++ b/app/views/issues/_show.html.haml
@@ -2,7 +2,7 @@
   - if controller.controller_name == 'issues'
     .issue_check
       = check_box_tag dom_id(issue,"selected"), nil, false, 'data-id' => issue.id, class: "selected_issue", disabled: !can?(current_user, :modify_issue, issue)
-  .right
+  .pull-right
     - if issue.notes.any?
       %span.btn.btn-small.disabled.grouped
         %i.icon-comment
diff --git a/app/views/issues/index.html.haml b/app/views/issues/index.html.haml
index a3fb0335205..875f29e2600 100644
--- a/app/views/issues/index.html.haml
+++ b/app/views/issues/index.html.haml
@@ -3,16 +3,16 @@
   %h3.page_title
     Issues
     %span (<span class=issue_counter>#{@issues.total_count}</span>)
-    .right
+    .pull-right
       .span5
         - if can? current_user, :write_issue, @project
-          = link_to new_project_issue_path(@project, issue: { assignee_id: params[:assignee_id], milestone_id: params[:milestone_id]}), class: "right btn btn-primary", title: "New Issue", id: "new_issue_link" do
+          = link_to new_project_issue_path(@project, issue: { assignee_id: params[:assignee_id], milestone_id: params[:milestone_id]}), class: "btn btn-primary pull-right", title: "New Issue", id: "new_issue_link" do
             %i.icon-plus
             New Issue
-        = form_tag search_project_issues_path(@project), method: :get, remote: true, id: "issue_search_form", class: :right  do
+        = form_tag search_project_issues_path(@project), method: :get, remote: true, id: "issue_search_form", class: 'pull-right'  do
           = hidden_field_tag :project_id, @project.id, { id: 'project_id' }
           = hidden_field_tag :status, params[:status]
-          = search_field_tag :issue_search, nil, { placeholder: 'Search', class: 'issue_search span3 right neib search-text-input' }
+          = search_field_tag :issue_search, nil, { placeholder: 'Search', class: 'issue_search span3 pull-right neib search-text-input' }
 
   .clearfix
 
diff --git a/app/views/issues/show.html.haml b/app/views/issues/show.html.haml
index 6bf78929699..474955cc665 100644
--- a/app/views/issues/show.html.haml
+++ b/app/views/issues/show.html.haml
@@ -5,7 +5,7 @@
     created at
     = @issue.created_at.stamp("Aug 21, 2011")
 
-  %span.right
+  %span.pull-right
     - if can?(current_user, :admin_project, @project) || @issue.author == current_user
       - if @issue.closed
         = link_to 'Reopen', project_issue_path(@project, @issue, issue: {closed: false }, status_only: true), method: :put,  class: "btn grouped reopen_issue"
@@ -16,7 +16,7 @@
         %i.icon-edit
         Edit
 
-.right
+.pull-right
   .span3#votes= render 'votes/votes_block', votable: @issue
 
 .back_link
@@ -42,7 +42,7 @@
       %cite.cgray and attached to milestone
       %strong= link_to_gfm truncate(milestone.title, length: 20), project_milestone_path(milestone.project, milestone)
 
-    .right
+    .pull-right
       - @issue.labels.each do |label|
         %span.label
           %i.icon-tag
diff --git a/app/views/kaminari/admin/_paginator.html.haml b/app/views/kaminari/admin/_paginator.html.haml
index 6f9fb332261..40b330feb3b 100644
--- a/app/views/kaminari/admin/_paginator.html.haml
+++ b/app/views/kaminari/admin/_paginator.html.haml
@@ -10,7 +10,7 @@
     %ul
       = prev_page_tag unless current_page.first?
       - each_page do |page|
-        - if page.left_outer? || page.right_outer? || page.inside_window?
+        - if page.left_outer? || page.pull-right_outer? || page.inside_window?
           = page_tag page
         - elsif !page.was_truncated?
           = gap_tag
diff --git a/app/views/kaminari/gitlab/_paginator.html.haml b/app/views/kaminari/gitlab/_paginator.html.haml
index 6dd5a5782a2..2fe4c183d15 100644
--- a/app/views/kaminari/gitlab/_paginator.html.haml
+++ b/app/views/kaminari/gitlab/_paginator.html.haml
@@ -9,7 +9,7 @@
   %nav.gitlab_pagination
     = prev_page_tag
     - each_page do |page|
-      - if page.left_outer? || page.right_outer? || page.inside_window?
+      - if page.left_outer? || page.pull-right_outer? || page.inside_window?
         = page_tag page
       - elsif !page.was_truncated?
         = gap_tag
diff --git a/app/views/keys/_show.html.haml b/app/views/keys/_show.html.haml
index 9e85e6228ce..52bbea6fc7b 100644
--- a/app/views/keys/_show.html.haml
+++ b/app/views/keys/_show.html.haml
@@ -8,5 +8,5 @@
       = time_ago_in_words(key.created_at)
       ago
   %td
-    = link_to 'Remove', key, confirm: 'Are you sure?', method: :delete, class: "btn btn-small btn-remove delete-key right"
+    = link_to 'Remove', key, confirm: 'Are you sure?', method: :delete, class: "btn btn-small btn-remove delete-key pull-right"
 
diff --git a/app/views/keys/index.html.haml b/app/views/keys/index.html.haml
index f5a8283a0ce..7730b344a7d 100644
--- a/app/views/keys/index.html.haml
+++ b/app/views/keys/index.html.haml
@@ -1,6 +1,6 @@
 %h3.page_title
   SSH Keys
-  = link_to "Add new", new_key_path, class: "btn right"
+  = link_to "Add new", new_key_path, class: "btn pull-right"
 
 %hr
 %p.slead
diff --git a/app/views/keys/show.html.haml b/app/views/keys/show.html.haml
index 089d0558b52..059fe5e5806 100644
--- a/app/views/keys/show.html.haml
+++ b/app/views/keys/show.html.haml
@@ -10,5 +10,5 @@
 %hr
 
 %pre= @key.key
-.right
+.pull-right
   = link_to 'Remove', @key, confirm: 'Are you sure?', method: :delete, class: "btn btn-remove delete-key"
diff --git a/app/views/labels/_label.html.haml b/app/views/labels/_label.html.haml
index 6e223e8e61d..027b041d58e 100644
--- a/app/views/labels/_label.html.haml
+++ b/app/views/labels/_label.html.haml
@@ -2,7 +2,7 @@
   %strong
     %i.icon-tag
     = label.name
-  .right
+  .pull-right
     = link_to project_issues_path(label_name: label.name) do
       %strong
         = pluralize(label.count, 'issue')
diff --git a/app/views/merge_requests/_filter.html.haml b/app/views/merge_requests/_filter.html.haml
index 86148fbcfee..4b48306ed05 100644
--- a/app/views/merge_requests/_filter.html.haml
+++ b/app/views/merge_requests/_filter.html.haml
@@ -16,5 +16,5 @@
 
   %fieldset
     %hr
-    = link_to "Reset", project_merge_requests_path(@project), class: 'btn right'
+    = link_to "Reset", project_merge_requests_path(@project), class: 'btn pull-right'
 
diff --git a/app/views/merge_requests/_merge_request.html.haml b/app/views/merge_requests/_merge_request.html.haml
index cdfc623d0a5..09c55d98465 100644
--- a/app/views/merge_requests/_merge_request.html.haml
+++ b/app/views/merge_requests/_merge_request.html.haml
@@ -1,5 +1,5 @@
 %li{ class: mr_css_classes(merge_request) }
-  .right
+  .pull-right
     .left
       - if merge_request.merged?
         %span.btn.btn-small.disabled.grouped
diff --git a/app/views/merge_requests/index.html.haml b/app/views/merge_requests/index.html.haml
index 8c688e26814..3073c8f6bab 100644
--- a/app/views/merge_requests/index.html.haml
+++ b/app/views/merge_requests/index.html.haml
@@ -1,5 +1,5 @@
 - if can? current_user, :write_merge_request, @project
-  = link_to new_project_merge_request_path(@project), class: "right btn btn-primary", title: "New Merge Request" do
+  = link_to new_project_merge_request_path(@project), class: "pull-right btn btn-primary", title: "New Merge Request" do
     %i.icon-plus
     New Merge Request
 %h3.page_title
@@ -28,8 +28,8 @@
         - if @merge_requests.present?
           %li.bottom
             .left= paginate @merge_requests, theme: "gitlab"
-            .right
-              %span.cgray.right #{@merge_requests.total_count} merge requests for this filter
+            .pull-right
+              %span.cgray.pull-right #{@merge_requests.total_count} merge requests for this filter
 
 :javascript
   $(merge_requestsPage);
diff --git a/app/views/merge_requests/show/_mr_title.html.haml b/app/views/merge_requests/show/_mr_title.html.haml
index c2ffe8e3770..1b9b7ca2d26 100644
--- a/app/views/merge_requests/show/_mr_title.html.haml
+++ b/app/views/merge_requests/show/_mr_title.html.haml
@@ -5,7 +5,7 @@
   &rarr;
   %span.label_branch= @merge_request.target_branch
 
-  %span.right
+  %span.pull-right
     - if can?(current_user, :modify_merge_request, @merge_request)
       - if @merge_request.open?
         .left.btn-group
@@ -23,7 +23,7 @@
           %i.icon-edit
           Edit
 
-.right
+.pull-right
   .span3#votes= render 'votes/votes_block', votable: @merge_request
 
 .back_link
diff --git a/app/views/milestones/_milestone.html.haml b/app/views/milestones/_milestone.html.haml
index 9111ff8b954..00e20117f36 100644
--- a/app/views/milestones/_milestone.html.haml
+++ b/app/views/milestones/_milestone.html.haml
@@ -1,5 +1,5 @@
 %li{class: "milestone milestone-#{milestone.closed ? 'closed' : 'open'}", id: dom_id(milestone) }
-  .right
+  .pull-right
     - if can?(current_user, :admin_milestone, milestone.project) and milestone.open?
       = link_to edit_project_milestone_path(milestone.project, milestone), class: "btn btn-small edit-milestone-link grouped" do
         %i.icon-edit
diff --git a/app/views/milestones/index.html.haml b/app/views/milestones/index.html.haml
index c1dc6da983d..b78f17053fd 100644
--- a/app/views/milestones/index.html.haml
+++ b/app/views/milestones/index.html.haml
@@ -3,7 +3,7 @@
   %h3.page_title
     Milestones
     - if can? current_user, :admin_milestone, @project
-      = link_to "New Milestone", new_project_milestone_path(@project), class: "right btn btn-small", title: "New Milestone"
+      = link_to "New Milestone", new_project_milestone_path(@project), class: "pull-right btn btn-small", title: "New Milestone"
   %br
   %div.ui-box
     .title
diff --git a/app/views/milestones/show.html.haml b/app/views/milestones/show.html.haml
index eeefb70e57c..43d82a54dd6 100644
--- a/app/views/milestones/show.html.haml
+++ b/app/views/milestones/show.html.haml
@@ -8,7 +8,7 @@
       = link_to project_milestones_path(@project) do
         &larr; To milestones list
   .span6
-    .right
+    .pull-right
       - unless  @milestone.closed
         = link_to new_project_issue_path(@project, issue: { milestone_id: @milestone.id }), class: "btn btn-small grouped", title: "New Issue" do
           %i.icon-plus
@@ -43,7 +43,7 @@
       #{@milestone.closed_items_count} closed
       &ndash;
       #{@milestone.open_items_count} open
-      %span.right= @milestone.expires_at
+      %span.pull-right= @milestone.expires_at
     .progress.progress-info
       .bar{style: "width: #{@milestone.percent_complete}%;"}
 
diff --git a/app/views/notes/_form.html.haml b/app/views/notes/_form.html.haml
index a063fb0a6bb..f008712c529 100644
--- a/app/views/notes/_form.html.haml
+++ b/app/views/notes/_form.html.haml
@@ -19,7 +19,7 @@
     = f.submit 'Add Comment', class: "btn comment-btn grouped js-comment-button"
     %a.btn.grouped.js-close-discussion-note-form Cancel
   .hint
-    .right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
+    .pull-right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
   .clearfix
 
   .note_options
diff --git a/app/views/notes/_note.html.haml b/app/views/notes/_note.html.haml
index 9efeb563e0a..9c51da2913c 100644
--- a/app/views/notes/_note.html.haml
+++ b/app/views/notes/_note.html.haml
@@ -30,7 +30,7 @@
   - if note.attachment.url
     - if note.attachment.image?
       = image_tag note.attachment.url, class: 'note-image-attach'
-    .attachment.right
+    .attachment.pull-right
       = link_to note.attachment.url, target: "_blank" do
         %i.icon-attachment
         = note.attachment_identifier
diff --git a/app/views/profiles/account.html.haml b/app/views/profiles/account.html.haml
index 71eacd571bd..f907cec5b61 100644
--- a/app/views/profiles/account.html.haml
+++ b/app/views/profiles/account.html.haml
@@ -12,7 +12,7 @@
 %fieldset
   %legend
     Private token
-    %span.cred.right
+    %span.cred.pull-right
       keep it secret!
   .padded
     = form_for @user, url: reset_private_token_profile_path, method: :put do |f|
@@ -56,7 +56,7 @@
 %fieldset.update-username
   %legend
     Username
-    %small.cred.right
+    %small.cred.pull-right
       Changing your username can have unintended side effects!
   = form_for @user, url: update_username_profile_path,  method: :put, remote: true do |f|
     .padded
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index 65b5a5d29fc..8a85716adbc 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -6,7 +6,7 @@
   %small
     = @user.email
 
-  .right
+  .pull-right
     = link_to destroy_user_session_path, class: "logout", method: :delete do
       %small
         %i.icon-signout
@@ -46,7 +46,7 @@
           = f.text_area :bio, rows: 6, class: "input-xlarge", maxlength: 250
           %span.help-block Tell us about yourself in fewer than 250 characters.
 
-    .span5.right
+    .span5.pull-right
       %fieldset.tips
         %legend Tips:
         %ul
@@ -76,7 +76,7 @@
       %fieldset
         %legend
           Personal projects:
-          %small.right
+          %small.pull-right
             %span= current_user.personal_projects.count
             of
             %span= current_user.projects_limit
@@ -87,7 +87,7 @@
       %fieldset
         %legend
           SSH public keys:
-          %span.right
+          %span.pull-right
             = link_to pluralize(current_user.keys.count, 'key'), keys_path
         .padded
           = link_to "Add Public Key", new_key_path, class: "btn btn-small"
diff --git a/app/views/projects/_clone_panel.html.haml b/app/views/projects/_clone_panel.html.haml
index 2962ad980b3..e52df19be96 100644
--- a/app/views/projects/_clone_panel.html.haml
+++ b/app/views/projects/_clone_panel.html.haml
@@ -2,8 +2,8 @@
   .row
     .span7
       .form-horizontal= render "shared/clone_panel"
-    .span4.right
-      .right
+    .span4.pull-right
+      .pull-right
         - unless @project.empty_repo?
           - if can? current_user, :download_code, @project
             = link_to archive_project_repository_path(@project), class: "btn-small btn grouped" do
diff --git a/app/views/projects/_form.html.haml b/app/views/projects/_form.html.haml
index a3e97fe9b70..254008a42ce 100644
--- a/app/views/projects/_form.html.haml
+++ b/app/views/projects/_form.html.haml
@@ -81,5 +81,5 @@
     = link_to 'Cancel', @project, class: "btn"
     - unless @project.new_record?
       - if can?(current_user, :remove_project, @project)
-        .right
+        .pull-right
           = link_to 'Remove Project', @project, confirm: 'Removed project can not be restored! Are you sure?', method: :delete, class: "btn btn-remove"
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index e7ee8bbb171..9426517876e 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -31,4 +31,4 @@
 
   - if can? current_user, :remove_project, @project
     .prepend-top-20
-      = link_to 'Remove project', @project, confirm: 'Are you sure?', method: :delete, class: "btn btn-remove right"
+      = link_to 'Remove project', @project, confirm: 'Are you sure?', method: :delete, class: "btn btn-remove pull-right"
diff --git a/app/views/public/projects/index.html.haml b/app/views/public/projects/index.html.haml
index afdd4c5fd95..21e9d2e6029 100644
--- a/app/views/public/projects/index.html.haml
+++ b/app/views/public/projects/index.html.haml
@@ -9,7 +9,7 @@
       %h5
         %i.icon-share
         = project.name_with_namespace
-        .right
+        .pull-right
           %pre.dark.tiny git clone #{project.http_url_to_repo}
 
 
diff --git a/app/views/repositories/_feed.html.haml b/app/views/repositories/_feed.html.haml
index 44380133718..eaf15ca77d6 100644
--- a/app/views/repositories/_feed.html.haml
+++ b/app/views/repositories/_feed.html.haml
@@ -15,6 +15,6 @@
       = image_tag gravatar_icon(commit.author_email), class: "", width: 16
       = gfm escape_once(truncate(commit.title, length: 40))
   %td
-    %span.right.cgray
+    %span.pull-right.cgray
       = time_ago_in_words(commit.committed_date)
       ago
diff --git a/app/views/repositories/stats.html.haml b/app/views/repositories/stats.html.haml
index bdf047f1e98..dde35ea38aa 100644
--- a/app/views/repositories/stats.html.haml
+++ b/app/views/repositories/stats.html.haml
@@ -23,7 +23,7 @@
           = image_tag gravatar_icon(author.email, 16), class: 'avatar s16'
           = author.name
           %small.light= author.email
-          .right
+          .pull-right
             = author.commits
 
 
diff --git a/app/views/services/_gitlab_ci.html.haml b/app/views/services/_gitlab_ci.html.haml
index 822892c8337..732a3d6c3e9 100644
--- a/app/views/services/_gitlab_ci.html.haml
+++ b/app/views/services/_gitlab_ci.html.haml
@@ -1,7 +1,7 @@
 %h3.page_title
   GitLab CI
   %small Continuous integration server from GitLab
-  .right
+  .pull-right
     - if @service.active
       %small.cgreen Enabled
     - else
diff --git a/app/views/services/index.html.haml b/app/views/services/index.html.haml
index 2c94f965eec..27dbf502569 100644
--- a/app/views/services/index.html.haml
+++ b/app/views/services/index.html.haml
@@ -8,7 +8,7 @@
       = link_to edit_project_service_path(@project, :gitlab_ci) do
         GitLab CI
         %small Continuous integration server from GitLab
-      .right
+      .pull-right
         - if @gitlab_ci_service.try(:active)
           %small.cgreen
             %i.icon-ok
@@ -21,11 +21,11 @@
     %h4
       Jenkins CI
       %small An extendable open source continuous integration server
-      .right
+      .pull-right
         %small Not implemented yet
   %li.disabled
     %h4
       Campfire
       %small Web-based group chat tool
-      .right
+      .pull-right
         %small Not implemented yet
diff --git a/app/views/snippets/_form.html.haml b/app/views/snippets/_form.html.haml
index 1405bd1110f..3b0b8be6f4d 100644
--- a/app/views/snippets/_form.html.haml
+++ b/app/views/snippets/_form.html.haml
@@ -30,7 +30,7 @@
       = f.submit 'Save', class: "btn-save btn"
       = link_to "Cancel", project_snippets_path(@project), class: " btn"
       - unless @snippet.new_record?
-        .right= link_to 'Destroy', [@project, @snippet], confirm: 'Are you sure?', method: :delete, class: "btn right danger delete-snippet", id: "destroy_snippet_#{@snippet.id}"
+        .pull-right= link_to 'Destroy', [@project, @snippet], confirm: 'Are you sure?', method: :delete, class: "btn pull-right danger delete-snippet", id: "destroy_snippet_#{@snippet.id}"
 
 
 :javascript
diff --git a/app/views/snippets/index.html.haml b/app/views/snippets/index.html.haml
index db2185745ef..28a533d238f 100644
--- a/app/views/snippets/index.html.haml
+++ b/app/views/snippets/index.html.haml
@@ -5,7 +5,7 @@
   %small share code pastes with others out of git repository
 
   - if can? current_user, :write_snippet, @project
-    = link_to new_project_snippet_path(@project), class: "btn btn-small add_new right", title: "New Snippet" do
+    = link_to new_project_snippet_path(@project), class: "btn btn-small add_new pull-right", title: "New Snippet" do
       Add new snippet
 %br
 %table
diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml
index 767b9736545..e6bcd88f830 100644
--- a/app/views/snippets/show.html.haml
+++ b/app/views/snippets/show.html.haml
@@ -4,7 +4,7 @@
   = @snippet.title
   %small= @snippet.file_name
   - if can?(current_user, :admin_snippet, @project) || @snippet.author == current_user
-    = link_to "Edit", edit_project_snippet_path(@project, @snippet), class: "btn btn-small right"
+    = link_to "Edit", edit_project_snippet_path(@project, @snippet), class: "btn btn-small pull-right"
 
 %br
 %div= render 'blob'
diff --git a/app/views/team_members/_show.html.haml b/app/views/team_members/_show.html.haml
index c85ec9812a8..b59bb7b1e52 100644
--- a/app/views/team_members/_show.html.haml
+++ b/app/views/team_members/_show.html.haml
@@ -10,12 +10,12 @@
         %br
         %small.cgray= user.email
 
-    .span5.right
+    .span5.pull-right
       - if allow_admin
         .left
           = form_for(member, as: :team_member, url: project_team_member_path(@project, member.user)) do |f|
             = f.select :project_access, options_for_select(UsersProject.access_roles, member.project_access), {}, class: "medium project-access-select span2"
-      .right
+      .pull-right
         - if current_user == user
           %span.btn.disabled This is you!
         - if @project.namespace_owner == user
diff --git a/app/views/team_members/_show_team.html.haml b/app/views/team_members/_show_team.html.haml
index ebe6f633d68..f1555f0b87b 100644
--- a/app/views/team_members/_show_team.html.haml
+++ b/app/views/team_members/_show_team.html.haml
@@ -7,8 +7,8 @@
       %br
       %small.cgray Members: #{team.members.count}
 
-    .span5.right
-      .right
+    .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
diff --git a/app/views/team_members/index.html.haml b/app/views/team_members/index.html.haml
index 6e5090c7799..3264f58cb32 100644
--- a/app/views/team_members/index.html.haml
+++ b/app/views/team_members/index.html.haml
@@ -7,7 +7,7 @@
     %strong= link_to "here", help_permissions_path, class: "vlink"
 
   - if can? current_user, :admin_team_member, @project
-    %span.right
+    %span.pull-right
       = link_to import_project_team_members_path(@project), class: "btn btn-small grouped", title: "Import team from another project" do
         Import team from another project
       = link_to available_project_teams_path(@project), class: "btn btn-small grouped", title: "Assign project to team of users" do
diff --git a/app/views/team_members/show.html.haml b/app/views/team_members/show.html.haml
index 99564f8e167..192948eff7d 100644
--- a/app/views/team_members/show.html.haml
+++ b/app/views/team_members/show.html.haml
@@ -2,7 +2,7 @@
 
 .team_member_show
   - if can? current_user, :admin_project, @project
-    = link_to 'Remove from team', project_team_member_path(@project, @member), confirm: 'Are you sure?', method: :delete, class: "right btn btn-remove"
+    = link_to 'Remove from team', project_team_member_path(@project, @member), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove pull-right"
   .profile_avatar_holder
     = image_tag gravatar_icon(@member.email, 60), class: "borders"
   %h3.page_title
diff --git a/app/views/teams/_filter.html.haml b/app/views/teams/_filter.html.haml
index 8e358319651..f461fcad42e 100644
--- a/app/views/teams/_filter.html.haml
+++ b/app/views/teams/_filter.html.haml
@@ -25,9 +25,9 @@
           %li{class: ("active" if params[:project_id] == project.id.to_s)}
             = link_to team_filter_path(entity, project_id: project.id) do
               = project.name_with_namespace
-              %small.right= entities_per_project(project, entity)
+              %small.pull-right= entities_per_project(project, entity)
 
   %fieldset
     %hr
-    = link_to "Reset", team_filter_path(entity), class: 'btn right'
+    = link_to "Reset", team_filter_path(entity), class: 'btn pull-right'
 
diff --git a/app/views/teams/_projects.html.haml b/app/views/teams/_projects.html.haml
index e72125919b1..5677255b15b 100644
--- a/app/views/teams/_projects.html.haml
+++ b/app/views/teams/_projects.html.haml
@@ -4,7 +4,7 @@
     %small
       (#{projects.count})
     - if can? current_user, :manage_user_team, @team
-      %span.right
+      %span.pull-right
         = link_to new_team_project_path(@team), class: "btn btn-tiny info" do
           %i.icon-plus
           Assign Project
diff --git a/app/views/teams/issues.html.haml b/app/views/teams/issues.html.haml
index 4481e2eaa03..c6a68c37b9c 100644
--- a/app/views/teams/issues.html.haml
+++ b/app/views/teams/issues.html.haml
@@ -1,7 +1,7 @@
 %h3.page_title
   Issues
   %small (in Team projects assigned to Team members)
-  %small.right #{@issues.total_count} issues
+  %small.pull-right #{@issues.total_count} issues
 
 %hr
 .row
diff --git a/app/views/teams/members/_show.html.haml b/app/views/teams/members/_show.html.haml
index e2b702ab0d7..6cddb8e4826 100644
--- a/app/views/teams/members/_show.html.haml
+++ b/app/views/teams/members/_show.html.haml
@@ -10,7 +10,7 @@
         %br
         %small.cgray= user.email
 
-    .span6.right
+    .span6.pull-right
       - if allow_admin
         .left.span2
           = form_for(member, as: :team_member, url: team_member_path(@team, user)) do |f|
@@ -19,7 +19,7 @@
           %span
             = check_box_tag :group_admin, true, @team.admin?(user)
             Admin access
-      .right
+      .pull-right
         - if current_user == user
           %span.btn.disabled This is you!
         - if @team.owner == user
diff --git a/app/views/teams/members/index.html.haml b/app/views/teams/members/index.html.haml
index 8ce6e5d83c0..87438266cfb 100644
--- a/app/views/teams/members/index.html.haml
+++ b/app/views/teams/members/index.html.haml
@@ -6,7 +6,7 @@
     %strong= link_to "here", help_permissions_path, class: "vlink"
 
   - if can? current_user, :manage_user_team, @team
-    %span.right
+    %span.pull-right
       = link_to new_team_member_path(@team), class: "btn btn-primary small grouped", title: "New Team Member" do
         New Team Member
 %hr
diff --git a/app/views/teams/members/show.html.haml b/app/views/teams/members/show.html.haml
index 6e655cee08e..f760c2dae3a 100644
--- a/app/views/teams/members/show.html.haml
+++ b/app/views/teams/members/show.html.haml
@@ -3,7 +3,7 @@
 
 .team_member_show
   - if can? current_user, :admin_project, @project
-    = link_to 'Remove from team', project_team_member_path(project_id: @project, id: @team_member.id), confirm: 'Are you sure?', method: :delete, class: "right btn btn-remove"
+    = link_to 'Remove from team', project_team_member_path(project_id: @project, id: @team_member.id), confirm: 'Are you sure?', method: :delete, class: "pull-right btn btn-remove"
   .profile_avatar_holder
     = image_tag gravatar_icon(user.email, 60), class: "borders"
   %h3.page_title
diff --git a/app/views/teams/merge_requests.html.haml b/app/views/teams/merge_requests.html.haml
index c9af529e113..417d1aa6040 100644
--- a/app/views/teams/merge_requests.html.haml
+++ b/app/views/teams/merge_requests.html.haml
@@ -1,7 +1,7 @@
 %h3.page_title
   Merge Requests
   %small (authored by or assigned to Team members)
-  %small.right #{@merge_requests.total_count} merge requests
+  %small.pull-right #{@merge_requests.total_count} merge requests
 
 %hr
 .row
diff --git a/app/views/teams/projects/index.html.haml b/app/views/teams/projects/index.html.haml
index de2bee093ec..696ee29c778 100644
--- a/app/views/teams/projects/index.html.haml
+++ b/app/views/teams/projects/index.html.haml
@@ -5,7 +5,7 @@
     %strong= link_to "here", help_permissions_path, class: "vlink"
 
   - if current_user.can?(:manage_user_team, @team) && @avaliable_projects.any?
-    %span.right
+    %span.pull-right
       = link_to new_team_project_path(@team), class: "btn btn-primary small grouped", title: "New Team Member" do
         Assign project to Team
 
diff --git a/app/views/tree/_head.html.haml b/app/views/tree/_head.html.haml
index f14526cf23a..32c3882400e 100644
--- a/app/views/tree/_head.html.haml
+++ b/app/views/tree/_head.html.haml
@@ -3,5 +3,5 @@
     = render partial: 'shared/ref_switcher', locals: {destination: 'tree', path: @path}
   = nav_link(controller: :tree) do
     = link_to 'Source', project_tree_path(@project, @ref)
-  %li.right
+  %li.pull-right
     = render "shared/clone_panel"
diff --git a/app/views/tree/_tree.html.haml b/app/views/tree/_tree.html.haml
index b0f775673b5..29a2ed02d31 100644
--- a/app/views/tree/_tree.html.haml
+++ b/app/views/tree/_tree.html.haml
@@ -24,7 +24,7 @@
           %th Name
           %th Last Update
           %th Last Commit
-          %th= link_to "history", project_commits_path(@project, @id), class: "btn btn-tiny right"
+          %th= link_to "history", project_commits_path(@project, @id), class: "btn btn-tiny pull-right"
 
       - if tree.up_dir?
         %tr.tree-item
diff --git a/app/views/users/_profile.html.haml b/app/views/users/_profile.html.haml
index ab6538f083b..4981aaba0ac 100644
--- a/app/views/users/_profile.html.haml
+++ b/app/views/users/_profile.html.haml
@@ -4,20 +4,20 @@
   %ul.well-list
     %li
       %strong Email
-      %span.right= mail_to @user.email
+      %span.pull-right= mail_to @user.email
     - unless @user.skype.blank?
       %li
         %strong Skype
-        %span.right= @user.skype
+        %span.pull-right= @user.skype
     - unless @user.linkedin.blank?
       %li
         %strong LinkedIn
-        %span.right= @user.linkedin
+        %span.pull-right= @user.linkedin
     - unless @user.twitter.blank?
       %li
         %strong Twitter
-        %span.right= @user.twitter
+        %span.pull-right= @user.twitter
     - unless @user.bio.blank?
       %li
         %strong Bio
-        %span.right= @user.bio
+        %span.pull-right= @user.bio
diff --git a/app/views/users/_projects.html.haml b/app/views/users/_projects.html.haml
index f46a0ed1161..73f635f3a08 100644
--- a/app/views/users/_projects.html.haml
+++ b/app/views/users/_projects.html.haml
@@ -9,7 +9,7 @@
             \/
           %strong.well-title
             = truncate(project.name, length: 45)
-          %span.right.light
+          %span.pull-right.light
             - if project.owner == @user
               %i.icon-wrench
             - tm = project.team.get_tm(@user.id)
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index 3977de24280..969fed9ce53 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -4,7 +4,7 @@
       = image_tag gravatar_icon(@user.email, 90), class: "avatar s90"
       = @user.name
       - if @user == current_user
-        .right
+        .pull-right
           = link_to profile_path, class: 'btn btn-small' do
             %i.icon-edit
             Edit Profile
diff --git a/app/views/wikis/edit.html.haml b/app/views/wikis/edit.html.haml
index 71f8d6a9b6c..9e221aba47d 100644
--- a/app/views/wikis/edit.html.haml
+++ b/app/views/wikis/edit.html.haml
@@ -2,7 +2,7 @@
 %hr
 = render 'form'
 
-.right
+.pull-right
   - if can? current_user, :admin_wiki, @project
     = link_to project_wiki_path(@project, @wiki), confirm: "Are you sure you want to delete this page?", method: :delete, class: "btn btn-small btn-remove" do
       Delete this page
\ No newline at end of file
diff --git a/app/views/wikis/show.html.haml b/app/views/wikis/show.html.haml
index 245d192efa1..7ff8b5cc01e 100644
--- a/app/views/wikis/show.html.haml
+++ b/app/views/wikis/show.html.haml
@@ -1,6 +1,6 @@
 %h3.page_title
   = @wiki.title
-  %span.right
+  %span.pull-right
     = link_to pages_project_wikis_path(@project), class: "btn btn-small grouped" do
       Pages
     - if can? current_user, :write_wiki, @project
-- 
GitLab


From 59b6de93cebe4aaa8cca121e6147fd7c83786f17 Mon Sep 17 00:00:00 2001
From: Sato Hiroyuki <sathiroyuki@gmail.com>
Date: Wed, 30 Jan 2013 22:20:00 +0900
Subject: [PATCH 141/197] Improve overlap of lines in network graph

---
 lib/gitlab/graph/commit.rb                |  4 +-
 lib/gitlab/graph/json_builder.rb          | 88 +++++++++++++++++------
 vendor/assets/javascripts/branch-graph.js | 25 +++++--
 3 files changed, 91 insertions(+), 26 deletions(-)

diff --git a/lib/gitlab/graph/commit.rb b/lib/gitlab/graph/commit.rb
index a6bf23a2381..13c8ebc9952 100644
--- a/lib/gitlab/graph/commit.rb
+++ b/lib/gitlab/graph/commit.rb
@@ -5,12 +5,13 @@ module Gitlab
     class Commit
       include ActionView::Helpers::TagHelper
 
-      attr_accessor :time, :space, :refs
+      attr_accessor :time, :space, :refs, :parent_spaces
 
       def initialize(commit)
         @_commit = commit
         @time = -1
         @space = 0
+        @parent_spaces = []
       end
 
       def method_missing(m, *args, &block)
@@ -28,6 +29,7 @@ module Gitlab
         }
         h[:time]    = time
         h[:space]   = space
+        h[:parent_spaces]   = parent_spaces
         h[:refs]    = refs.collect{|r|r.name}.join(" ") unless refs.nil?
         h[:id]      = sha
         h[:date]    = date
diff --git a/lib/gitlab/graph/json_builder.rb b/lib/gitlab/graph/json_builder.rb
index a3157aa4b4d..b25e313df40 100644
--- a/lib/gitlab/graph/json_builder.rb
+++ b/lib/gitlab/graph/json_builder.rb
@@ -16,7 +16,6 @@ module Gitlab
 
         @commits = collect_commits
         @days = index_commits
-        @space = 0
       end
 
       def to_json(*args)
@@ -53,7 +52,7 @@ module Gitlab
       #
       # @return [Array<TimeDate>] list of commit dates corelated with time on commits
       def index_commits
-        days, heads = [], []
+        days, heads, times = [], [], []
         map = {}
 
         commits.reverse.each_with_index do |c,i|
@@ -61,6 +60,7 @@ module Gitlab
           days[i] = c.committed_date
           map[c.id] = c
           heads += c.refs unless c.refs.nil?
+          times[i] = c
         end
 
         heads.select!{|h| h.is_a? Grit::Head or h.is_a? Grit::Remote}
@@ -86,9 +86,62 @@ module Gitlab
           end
         end
 
+        # find parent spaces for not overlap lines
+        times.each do |c|
+          c.parent_spaces.concat(find_free_parent_spaces(c, map, times))
+        end
+
         days
       end
 
+      def find_free_parent_spaces(commit, map, times)
+        spaces = []
+
+        commit.parents.each do |p|
+          if map.include?(p.id) then
+            parent = map[p.id]
+
+            range = if commit.time < parent.time then
+                      commit.time..parent.time
+                    else
+                      parent.time..commit.time
+                    end
+
+            space = if commit.space >= parent.space then
+                      find_free_parent_space(range, map, parent.space, 1, commit.space, times)
+                    else
+                      find_free_parent_space(range, map, parent.space, -1, parent.space, times)
+                    end
+
+            mark_reserved(range, space)
+            spaces << space
+          end
+        end
+
+        spaces
+      end
+
+      def find_free_parent_space(range, map, space_base, space_step, space_default, times)
+        if is_overlap?(range, times, space_default) then
+          find_free_space(range, map, space_base, space_step)
+        else
+          space_default
+        end
+      end
+
+      def is_overlap?(range, times, overlap_space)
+        range.each do |i|
+          if i != range.first &&
+            i != range.last &&
+            times[i].space == overlap_space then
+
+            return true;
+          end
+        end
+
+        false
+      end
+
       # Add space mark on commit and its parents
       #
       # @param [Graph::Commit] the commit object.
@@ -98,8 +151,9 @@ module Gitlab
         if leaves.empty?
           return
         end
-        @space = find_free_space(leaves, map)
-        leaves.each{|l| l.space = @space}
+        time_range = leaves.last.time..leaves.first.time
+        space = find_free_space(time_range, map, 1, 2)
+        leaves.each{|l| l.space = space}
         # and mark it as reserved
         min_time = leaves.last.time
         parents = leaves.last.parents.collect
@@ -116,7 +170,7 @@ module Gitlab
         else
           max_time = parent_time - 1
         end
-        mark_reserved(min_time..max_time, @space)
+        mark_reserved(min_time..max_time, space)
 
         # Visit branching chains
         leaves.each do |l|
@@ -133,28 +187,22 @@ module Gitlab
         end
       end
 
-      def find_free_space(leaves, map)
-        time_range = leaves.last.time..leaves.first.time
+      def find_free_space(time_range, map, space_base, space_step)
         reserved = []
         for day in time_range
           reserved += @_reserved[day]
         end
-        space = base_space(leaves, map)
-        while (reserved.include? space) || (space == @space) do
-          space += 1
-        end
-
-        space
-      end
 
-      def base_space(leaves, map)
-        parents = []
-        leaves.each do |l|
-          parents.concat l.parents.collect.select{|p| map.include? p.id and map[p.id].space.nonzero?}
+        space = space_base
+        while reserved.include?(space) do
+          space += space_step
+          if space <= 0 then
+            space_step *= -1
+            space = space_base + space_step
+          end
         end
 
-        space = parents.map{|p| map[p.id].space}.max || 0
-        space += 1
+        space
       end
 
       # Takes most left subtree branch of commits
diff --git a/vendor/assets/javascripts/branch-graph.js b/vendor/assets/javascripts/branch-graph.js
index 93849c79e80..76494196e43 100644
--- a/vendor/assets/javascripts/branch-graph.js
+++ b/vendor/assets/javascripts/branch-graph.js
@@ -103,8 +103,9 @@
     
     for (i = 0; i < this.commitCount; i++) {
       var x = offsetX + 20 * this.commits[i].time
-        , y = offsetY + 20 * this.commits[i].space
-        , c;
+        , y = offsetY + 10 * this.commits[i].space
+        , c
+        , ps;
       
       // Draw dot
       r.circle(x, y, 3).attr({
@@ -115,9 +116,11 @@
       // Draw lines
       for (var j = 0, jj = this.commits[i].parents.length; j < jj; j++) {
         c = this.preparedCommits[this.commits[i].parents[j][0]];
+        ps = this.commits[i].parent_spaces[j];
         if (c) {
           var cx = offsetX + 20 * c.time
-            , cy = offsetY + 20 * c.space;
+            , cy = offsetY + 10 * c.space
+            , psy = offsetY + 10 * ps;
           if (c.space == this.commits[i].space) {
             r.path([
               "M", x, y,
@@ -128,13 +131,25 @@
             });
 
           } else if (c.space < this.commits[i].space) {
-            r.path(["M", x - 5, y + .0001, "l-5-2,0,4,5,-2C", x - 5, y, x - 17, y + 2, x - 20, y - 5, "L", cx, y - 5, cx, cy])
+            r.path([
+                "M", x - 5, y,
+                "l-5-2,0,4,5,-2",
+                "L", x - 10, y,
+                "L", x - 15, psy,
+                "L", cx + 5, psy,
+                "L", cx, cy])
             .attr({
               stroke: this.colors[this.commits[i].space], 
               "stroke-width": 2
             });
           } else {
-            r.path(["M", x - 3, y + 6, "l-4,3,4,2,0,-5L", x - 10, y + 20, "L", x - 10, cy, cx, cy])
+            r.path([
+                "M", x - 3, y + 6,
+                "l-4,3,4,2,0,-5",
+                "L", x - 5, y + 10,
+                "L", x - 10, psy,
+                "L", cx + 5, psy,
+                "L", cx, cy])
             .attr({
               stroke: this.colors[c.space], 
               "stroke-width": 2
-- 
GitLab


From b742f47e89674c7aaae78b6e4174339480594d1f Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 30 Jan 2013 16:53:18 +0200
Subject: [PATCH 142/197] remove old alert messages

---
 app/assets/stylesheets/gitlab_bootstrap/buttons.scss | 1 +
 app/assets/stylesheets/gitlab_bootstrap/common.scss  | 7 ++++++-
 app/views/admin/groups/edit.html.haml                | 2 +-
 app/views/admin/groups/new.html.haml                 | 2 +-
 app/views/admin/hooks/index.html.haml                | 2 +-
 app/views/admin/projects/_form.html.haml             | 2 +-
 app/views/admin/projects/members/_form.html.haml     | 2 +-
 app/views/admin/teams/edit.html.haml                 | 2 +-
 app/views/admin/teams/members/_form.html.haml        | 2 +-
 app/views/admin/teams/new.html.haml                  | 2 +-
 app/views/admin/teams/projects/_form.html.haml       | 2 +-
 app/views/commit/huge_commit.html.haml               | 2 +-
 app/views/commits/_diffs.html.haml                   | 2 +-
 app/views/deploy_keys/_form.html.haml                | 2 +-
 app/views/groups/new.html.haml                       | 2 +-
 app/views/hooks/index.html.haml                      | 2 +-
 app/views/issues/_form.html.haml                     | 2 +-
 app/views/keys/_form.html.haml                       | 2 +-
 app/views/merge_requests/_form.html.haml             | 2 +-
 app/views/merge_requests/show/_mr_accept.html.haml   | 6 +++---
 app/views/merge_requests/show/_mr_ci.html.haml       | 2 +-
 app/views/merge_requests/show/_mr_title.html.haml    | 2 +-
 app/views/milestones/_form.html.haml                 | 2 +-
 app/views/profiles/account.html.haml                 | 2 +-
 app/views/profiles/show.html.haml                    | 2 +-
 app/views/projects/_form.html.haml                   | 2 +-
 app/views/projects/_new_form.html.haml               | 2 +-
 app/views/protected_branches/index.html.haml         | 2 +-
 app/views/services/_gitlab_ci.html.haml              | 2 +-
 app/views/snippets/_form.html.haml                   | 2 +-
 app/views/team_members/_form.html.haml               | 2 +-
 app/views/teams/edit.html.haml                       | 2 +-
 app/views/teams/members/_form.html.haml              | 2 +-
 app/views/teams/new.html.haml                        | 2 +-
 app/views/teams/projects/_form.html.haml             | 2 +-
 35 files changed, 42 insertions(+), 36 deletions(-)

diff --git a/app/assets/stylesheets/gitlab_bootstrap/buttons.scss b/app/assets/stylesheets/gitlab_bootstrap/buttons.scss
index a20c9b1b31e..03497e32d26 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/buttons.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/buttons.scss
@@ -67,6 +67,7 @@
     @extend .btn-primary;
   }
 
+  &.btn-close,
   &.btn-remove {
     @extend .btn-danger;
     border-color: #BD362F;
diff --git a/app/assets/stylesheets/gitlab_bootstrap/common.scss b/app/assets/stylesheets/gitlab_bootstrap/common.scss
index fb2f34179b7..e30492677d0 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/common.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/common.scss
@@ -86,9 +86,14 @@
 
 /** ALERT MESSAGES **/
 .alert-message { @extend .alert; }
-.alert-messag.success { @extend .alert-success; }
 .alert-message.error { @extend .alert-error; }
 
+.alert.alert-disabled {
+  background: #EEE;
+  color: #777;
+  border-color: #DDD;
+}
+
 /** AVATARS **/
 img.avatar { float: left; margin-right: 12px; width: 40px; border: 1px solid #ddd; padding: 1px; }
 img.avatar.s16 { width: 16px; height: 16px; margin-right: 6px; }
diff --git a/app/views/admin/groups/edit.html.haml b/app/views/admin/groups/edit.html.haml
index 6ec520e74b4..dce044956c3 100644
--- a/app/views/admin/groups/edit.html.haml
+++ b/app/views/admin/groups/edit.html.haml
@@ -2,7 +2,7 @@
 %hr
 = form_for [:admin, @group] do |f|
   - if @group.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %span= @group.errors.full_messages.first
   .clearfix.group_name_holder
     = f.label :name do
diff --git a/app/views/admin/groups/new.html.haml b/app/views/admin/groups/new.html.haml
index f8d1dfcf931..60c6fa5ad09 100644
--- a/app/views/admin/groups/new.html.haml
+++ b/app/views/admin/groups/new.html.haml
@@ -2,7 +2,7 @@
 %hr
 = form_for [:admin, @group] do |f|
   - if @group.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %span= @group.errors.full_messages.first
   .clearfix
     = f.label :name do
diff --git a/app/views/admin/hooks/index.html.haml b/app/views/admin/hooks/index.html.haml
index 838296ccf3a..acbf7a108b8 100644
--- a/app/views/admin/hooks/index.html.haml
+++ b/app/views/admin/hooks/index.html.haml
@@ -7,7 +7,7 @@
 
 = form_for @hook, as: :hook, url: admin_hooks_path, html: { class: 'form-inline' } do |f|
   -if @hook.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       - @hook.errors.full_messages.each do |msg|
         %p= msg
   .clearfix
diff --git a/app/views/admin/projects/_form.html.haml b/app/views/admin/projects/_form.html.haml
index 6342802c699..ebf69924a25 100644
--- a/app/views/admin/projects/_form.html.haml
+++ b/app/views/admin/projects/_form.html.haml
@@ -1,6 +1,6 @@
 = form_for [:admin, project] do |f|
   -if project.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %ul
         - project.errors.full_messages.each do |msg|
           %li= msg
diff --git a/app/views/admin/projects/members/_form.html.haml b/app/views/admin/projects/members/_form.html.haml
index bbd419be576..8041202980d 100644
--- a/app/views/admin/projects/members/_form.html.haml
+++ b/app/views/admin/projects/members/_form.html.haml
@@ -1,6 +1,6 @@
 = form_for @team_member_relation, as: :team_member, url: admin_project_member_path(@project, @member)  do |f|
   -if @team_member_relation.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %ul
         - @team_member_relation.errors.full_messages.each do |msg|
           %li= msg
diff --git a/app/views/admin/teams/edit.html.haml b/app/views/admin/teams/edit.html.haml
index d024d82381a..9282398ce5b 100644
--- a/app/views/admin/teams/edit.html.haml
+++ b/app/views/admin/teams/edit.html.haml
@@ -2,7 +2,7 @@
 %hr
 = form_for @team, url: admin_team_path(@team), method: :put do |f|
   - if @team.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %span= @team.errors.full_messages.first
   .clearfix.team_name_holder
     = f.label :name do
diff --git a/app/views/admin/teams/members/_form.html.haml b/app/views/admin/teams/members/_form.html.haml
index 098118a645d..f1388aab4bb 100644
--- a/app/views/admin/teams/members/_form.html.haml
+++ b/app/views/admin/teams/members/_form.html.haml
@@ -1,6 +1,6 @@
 = form_tag admin_team_member_path(@team, @member), method: :put do
   -if @member.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %ul
         - @member.errors.full_messages.each do |msg|
           %li= msg
diff --git a/app/views/admin/teams/new.html.haml b/app/views/admin/teams/new.html.haml
index 7483f1bf32d..5d55a7975ee 100644
--- a/app/views/admin/teams/new.html.haml
+++ b/app/views/admin/teams/new.html.haml
@@ -2,7 +2,7 @@
 %hr
 = form_for @team, url: admin_teams_path do |f|
   - if @team.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %span= @team.errors.full_messages.first
   .clearfix
     = f.label :name do
diff --git a/app/views/admin/teams/projects/_form.html.haml b/app/views/admin/teams/projects/_form.html.haml
index 9ba406ea125..5b79d518d42 100644
--- a/app/views/admin/teams/projects/_form.html.haml
+++ b/app/views/admin/teams/projects/_form.html.haml
@@ -1,6 +1,6 @@
 = form_tag admin_team_project_path(@team, @project), method: :put do
   -if @project.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %ul
         - @project.errors.full_messages.each do |msg|
           %li= msg
diff --git a/app/views/commit/huge_commit.html.haml b/app/views/commit/huge_commit.html.haml
index ba97a7c572c..7f0bcf38037 100644
--- a/app/views/commit/huge_commit.html.haml
+++ b/app/views/commit/huge_commit.html.haml
@@ -1,3 +1,3 @@
 = render "commits/commit_box"
-.alert-message.block-message.error
+.alert.alert-error
   %h4 Commit diffs are too big to be displayed
diff --git a/app/views/commits/_diffs.html.haml b/app/views/commits/_diffs.html.haml
index db9180c4057..07c37d1e8c5 100644
--- a/app/views/commits/_diffs.html.haml
+++ b/app/views/commits/_diffs.html.haml
@@ -1,5 +1,5 @@
 - if @suppress_diff
-  .alert-message.block-message
+  .alert.alert-block
     %p
       %strong Warning! Large commit with more then #{Commit::DIFF_SAFE_SIZE} files changed.
     %p To prevent performance issue we rejected diff information.
diff --git a/app/views/deploy_keys/_form.html.haml b/app/views/deploy_keys/_form.html.haml
index 4deeb0e8e07..5fb83021dc0 100644
--- a/app/views/deploy_keys/_form.html.haml
+++ b/app/views/deploy_keys/_form.html.haml
@@ -1,7 +1,7 @@
 %div
   = form_for [@project, @key], url: project_deploy_keys_path do |f|
     -if @key.errors.any?
-      .alert-message.block-message.error
+      .alert.alert-error
         %ul
           - @key.errors.full_messages.each do |msg|
             %li= msg
diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml
index 224962df013..73be474e278 100644
--- a/app/views/groups/new.html.haml
+++ b/app/views/groups/new.html.haml
@@ -2,7 +2,7 @@
 %hr
 = form_for @group do |f|
   - if @group.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %span= @group.errors.full_messages.first
   .clearfix
     = f.label :name do
diff --git a/app/views/hooks/index.html.haml b/app/views/hooks/index.html.haml
index 334b0f19301..88a5a7dcffe 100644
--- a/app/views/hooks/index.html.haml
+++ b/app/views/hooks/index.html.haml
@@ -10,7 +10,7 @@
 
 = form_for [@project, @hook], as: :hook, url: project_hooks_path(@project), html: { class: 'form-inline' } do |f|
   -if @hook.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       - @hook.errors.full_messages.each do |msg|
         %p= msg
   .clearfix
diff --git a/app/views/issues/_form.html.haml b/app/views/issues/_form.html.haml
index 16d1b163ee8..6d7613a700d 100644
--- a/app/views/issues/_form.html.haml
+++ b/app/views/issues/_form.html.haml
@@ -2,7 +2,7 @@
   %h3.page_title= @issue.new_record? ? "New Issue" : "Edit Issue ##{@issue.id}"
   = form_for [@project, @issue] do |f|
     -if @issue.errors.any?
-      .alert-message.block-message.error
+      .alert.alert-error
         - @issue.errors.full_messages.each do |msg|
           %span= msg
           %br
diff --git a/app/views/keys/_form.html.haml b/app/views/keys/_form.html.haml
index b60ad7df0ae..fe26216b1d5 100644
--- a/app/views/keys/_form.html.haml
+++ b/app/views/keys/_form.html.haml
@@ -1,7 +1,7 @@
 %div
   = form_for @key do |f|
     -if @key.errors.any?
-      .alert-message.block-message.error
+      .alert.alert-error
         %ul
           - @key.errors.full_messages.each do |msg|
             %li= msg
diff --git a/app/views/merge_requests/_form.html.haml b/app/views/merge_requests/_form.html.haml
index 603f30407b9..816c852d24b 100644
--- a/app/views/merge_requests/_form.html.haml
+++ b/app/views/merge_requests/_form.html.haml
@@ -1,6 +1,6 @@
 = form_for [@project, @merge_request], html: { class: "#{controller.action_name}-merge-request form-horizontal" } do |f|
   -if @merge_request.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %ul
         - @merge_request.errors.full_messages.each do |msg|
           %li= msg
diff --git a/app/views/merge_requests/show/_mr_accept.html.haml b/app/views/merge_requests/show/_mr_accept.html.haml
index 27f1c2ab8e1..c2c04b863e7 100644
--- a/app/views/merge_requests/show/_mr_accept.html.haml
+++ b/app/views/merge_requests/show/_mr_accept.html.haml
@@ -1,5 +1,5 @@
 - unless can?(current_user, :accept_mr, @project)
-  .alert-message
+  .alert
     %strong Only masters can accept MR
 
 
@@ -29,14 +29,14 @@
         %strong This repository does not have satellite. Ask administrator to fix this issue
 
   .automerge_widget.cannot_be_merged{style: "display:none"}
-    .alert.alert-info
+    .alert.alert-disabled
       %span
         = link_to "Show how to merge", "#", class: "how_to_merge_link btn btn-small padded", title: "How To Merge"
         &nbsp;
         %strong This request can't be merged with GitLab. You should do it manually
 
   .automerge_widget.unchecked
-    .alert-message
+    .alert
       %strong
         %i.icon-refresh
         Checking for ability to automatically merge…
diff --git a/app/views/merge_requests/show/_mr_ci.html.haml b/app/views/merge_requests/show/_mr_ci.html.haml
index d46b606ef7f..dd1e78a0205 100644
--- a/app/views/merge_requests/show/_mr_ci.html.haml
+++ b/app/views/merge_requests/show/_mr_ci.html.haml
@@ -23,7 +23,7 @@
         = link_to "Build page", ci_build_details_path(@merge_request)
 
   .ci_widget
-    .alert-message
+    .alert
       %strong
         %i.icon-refresh
         Checking for CI status for #{@merge_request.last_commit_short_sha}
diff --git a/app/views/merge_requests/show/_mr_title.html.haml b/app/views/merge_requests/show/_mr_title.html.haml
index 1b9b7ca2d26..8119728dcb9 100644
--- a/app/views/merge_requests/show/_mr_title.html.haml
+++ b/app/views/merge_requests/show/_mr_title.html.haml
@@ -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 danger", title: "Close merge request"
+        = link_to 'Close', project_merge_request_path(@project, @merge_request, merge_request: {closed: true }, status_only: true), method: :put, class: "btn grouped btn-close", title: "Close merge request"
 
         = link_to edit_project_merge_request_path(@project, @merge_request), class: "btn grouped" do
           %i.icon-edit
diff --git a/app/views/milestones/_form.html.haml b/app/views/milestones/_form.html.haml
index 2dc90bb89d0..fbaf64a305c 100644
--- a/app/views/milestones/_form.html.haml
+++ b/app/views/milestones/_form.html.haml
@@ -7,7 +7,7 @@
 
 = form_for [@project, @milestone], html: {class: "new_milestone form-horizontal"}  do |f|
   -if @milestone.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %ul
         - @milestone.errors.full_messages.each do |msg|
           %li= msg
diff --git a/app/views/profiles/account.html.haml b/app/views/profiles/account.html.haml
index f907cec5b61..2ad000b815b 100644
--- a/app/views/profiles/account.html.haml
+++ b/app/views/profiles/account.html.haml
@@ -35,7 +35,7 @@
     .padded
       %p.slead After successful password update you will be redirected to login page where you should login with new password
       -if @user.errors.any?
-        .alert-message.block-message.error
+        .alert.alert-error
           %ul
             - @user.errors.full_messages.each do |msg|
               %li= msg
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index 8a85716adbc..3cf6330cc3c 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -15,7 +15,7 @@
 
 = form_for @user, url: profile_path, method: :put, html: { class: "edit_user form-horizontal" }  do |f|
   -if @user.errors.any?
-    %div.alert-message.block-message.error
+    %div.alert.alert-error
       %ul
         - @user.errors.full_messages.each do |msg|
           %li= msg
diff --git a/app/views/projects/_form.html.haml b/app/views/projects/_form.html.haml
index 254008a42ce..8d3b1aded5c 100644
--- a/app/views/projects/_form.html.haml
+++ b/app/views/projects/_form.html.haml
@@ -1,6 +1,6 @@
 = form_for(@project, remote: true) do |f|
   - if @project.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %ul
         - @project.errors.full_messages.each do |msg|
           %li= msg
diff --git a/app/views/projects/_new_form.html.haml b/app/views/projects/_new_form.html.haml
index b3f2b82eb77..185164955fc 100644
--- a/app/views/projects/_new_form.html.haml
+++ b/app/views/projects/_new_form.html.haml
@@ -1,6 +1,6 @@
 = form_for(@project, remote: true) do |f|
   - if @project.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %span= @project.errors.full_messages.first
   .clearfix.project_name_holder
     = f.label :name do
diff --git a/app/views/protected_branches/index.html.haml b/app/views/protected_branches/index.html.haml
index 6e7c638eb0f..15644de552f 100644
--- a/app/views/protected_branches/index.html.haml
+++ b/app/views/protected_branches/index.html.haml
@@ -14,7 +14,7 @@
     - if can? current_user, :admin_project, @project
       = form_for [@project, @protected_branch] do |f|
         -if @protected_branch.errors.any?
-          .alert-message.block-message.error
+          .alert.alert-error
             %ul
               - @protected_branch.errors.full_messages.each do |msg|
                 %li= msg
diff --git a/app/views/services/_gitlab_ci.html.haml b/app/views/services/_gitlab_ci.html.haml
index 732a3d6c3e9..dfde643849e 100644
--- a/app/views/services/_gitlab_ci.html.haml
+++ b/app/views/services/_gitlab_ci.html.haml
@@ -16,7 +16,7 @@
 %hr
 = form_for(@service, :as => :service, :url => project_service_path(@project, :gitlab_ci), :method => :put) do |f|
   - if @service.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %ul
         - @service.errors.full_messages.each do |msg|
           %li= msg
diff --git a/app/views/snippets/_form.html.haml b/app/views/snippets/_form.html.haml
index 3b0b8be6f4d..77162cdcde3 100644
--- a/app/views/snippets/_form.html.haml
+++ b/app/views/snippets/_form.html.haml
@@ -4,7 +4,7 @@
 .snippet-form-holder
   = form_for [@project, @snippet] do |f|
     -if @snippet.errors.any?
-      .alert-message.block-message.error
+      .alert.alert-error
         %ul
           - @snippet.errors.full_messages.each do |msg|
             %li= msg
diff --git a/app/views/team_members/_form.html.haml b/app/views/team_members/_form.html.haml
index 1616ea3c229..ee435c84ca2 100644
--- a/app/views/team_members/_form.html.haml
+++ b/app/views/team_members/_form.html.haml
@@ -3,7 +3,7 @@
 %hr
 = form_for @user_project_relation, as: :team_member, url: project_team_members_path(@project) do |f|
   -if @user_project_relation.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %ul
         - @user_project_relation.errors.full_messages.each do |msg|
           %li= msg
diff --git a/app/views/teams/edit.html.haml b/app/views/teams/edit.html.haml
index 2c565230b85..a3b1c734414 100644
--- a/app/views/teams/edit.html.haml
+++ b/app/views/teams/edit.html.haml
@@ -2,7 +2,7 @@
 %hr
 = form_for @team, url: teams_path do |f|
   - if @team.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %span= @team.errors.full_messages.first
   .clearfix
     = f.label :name do
diff --git a/app/views/teams/members/_form.html.haml b/app/views/teams/members/_form.html.haml
index 701eb4f2233..c22ee78305f 100644
--- a/app/views/teams/members/_form.html.haml
+++ b/app/views/teams/members/_form.html.haml
@@ -1,6 +1,6 @@
 = form_tag admin_team_member_path(@team, @member), method: :put do
   -if @member.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %ul
         - @member.errors.full_messages.each do |msg|
           %li= msg
diff --git a/app/views/teams/new.html.haml b/app/views/teams/new.html.haml
index c0363fe39a8..38f61c11c0c 100644
--- a/app/views/teams/new.html.haml
+++ b/app/views/teams/new.html.haml
@@ -2,7 +2,7 @@
 %hr
 = form_for @team, url: teams_path do |f|
   - if @team.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %span= @team.errors.full_messages.first
   .clearfix
     = f.label :name do
diff --git a/app/views/teams/projects/_form.html.haml b/app/views/teams/projects/_form.html.haml
index 763d07a1c7e..d2c89b0c36b 100644
--- a/app/views/teams/projects/_form.html.haml
+++ b/app/views/teams/projects/_form.html.haml
@@ -1,6 +1,6 @@
 = form_tag team_project_path(@team, @project), method: :put do
   -if @project.errors.any?
-    .alert-message.block-message.error
+    .alert.alert-error
       %ul
         - @project.errors.full_messages.each do |msg|
           %li= msg
-- 
GitLab


From b096ee327598919b2d78a99ce82e6b0107369604 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 30 Jan 2013 17:01:58 +0200
Subject: [PATCH 143/197] a bit of split up for gitlab-bootstrap

---
 app/assets/stylesheets/gitlab_bootstrap.scss  |  2 +
 .../stylesheets/gitlab_bootstrap/avatar.scss  |  8 ++
 .../stylesheets/gitlab_bootstrap/common.scss  | 74 -------------------
 .../stylesheets/gitlab_bootstrap/nav.scss     | 65 ++++++++++++++++
 4 files changed, 75 insertions(+), 74 deletions(-)
 create mode 100644 app/assets/stylesheets/gitlab_bootstrap/avatar.scss
 create mode 100644 app/assets/stylesheets/gitlab_bootstrap/nav.scss

diff --git a/app/assets/stylesheets/gitlab_bootstrap.scss b/app/assets/stylesheets/gitlab_bootstrap.scss
index f53e0e50bab..2ad1bf944a9 100644
--- a/app/assets/stylesheets/gitlab_bootstrap.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap.scss
@@ -17,6 +17,8 @@ $baseLineHeight: 18px !default;
 @import "gitlab_bootstrap/variables.scss";
 @import "gitlab_bootstrap/fonts.scss";
 @import "gitlab_bootstrap/mixins.scss";
+@import "gitlab_bootstrap/avatar.scss";
+@import "gitlab_bootstrap/nav.scss";
 @import "gitlab_bootstrap/common.scss";
 @import "gitlab_bootstrap/typography.scss";
 @import "gitlab_bootstrap/buttons.scss";
diff --git a/app/assets/stylesheets/gitlab_bootstrap/avatar.scss b/app/assets/stylesheets/gitlab_bootstrap/avatar.scss
new file mode 100644
index 00000000000..de1fb1551bf
--- /dev/null
+++ b/app/assets/stylesheets/gitlab_bootstrap/avatar.scss
@@ -0,0 +1,8 @@
+/** AVATARS **/
+img.avatar { float: left; margin-right: 12px; width: 40px; border: 1px solid #ddd; padding: 1px; }
+img.avatar.s16 { width: 16px; height: 16px; margin-right: 6px; }
+img.avatar.s24 { width: 24px; height: 24px; margin-right: 8px; }
+img.avatar.s32 { width: 32px; height: 32px; margin-right: 10px; }
+img.avatar.s90 { width: 90px; height: 90px; margin-right: 15px; }
+img.lil_av { padding-left: 4px; padding-right: 3px; }
+img.small { width: 80px; }
diff --git a/app/assets/stylesheets/gitlab_bootstrap/common.scss b/app/assets/stylesheets/gitlab_bootstrap/common.scss
index e30492677d0..cb292bc711f 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/common.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/common.scss
@@ -21,88 +21,14 @@
 .light { color: #888 }
 .tiny { font-weight: normal }
 
-/** PILLS & TABS**/
-.nav-pills {
-  .active a {
-    background: $primary_color;
-  }
-
-  > li > a {
-    @include border-radius(0);
-  }
-  &.nav-stacked {
-    > li > a {
-      border-left: 4px solid #EEE;
-      padding: 12px;
-    }
-    > .active > a {
-      border-color: #29B;
-      border-radius: 0;
-      background: #F1F1F1;
-      color: $style_color;
-      font-weight: bold;
-    }
-  }
-}
-
-.nav-pills > .active > a > i[class^="icon-"] { background: inherit; }
-
-
-
-/**
- * nav-tabs
- *
- */
-.nav-tabs > li > a, .nav-pills > li > a { color: $style_color; }
-.nav.nav-tabs {
-  li {
-    > a {
-      padding: 8px 20px;
-      margin-right: 7px;
-      line-height: 20px;
-      border-color: #EEE;
-      color: #888;
-      border-bottom: 1px solid #ddd;
-      .badge {
-        background-color: #eee;
-        color: #888;
-        text-shadow: 0 1px 1px #fff;
-      }
-      i[class^="icon-"] {
-        line-height: 14px;
-      }
-    }
-    &.active {
-      > a {
-        border-color: #CCC;
-        border-bottom: 1px solid #fff;
-        color: #333;
-      }
-    }
-  }
-
-  &.nav-small-tabs > li > a { padding: 6px 9px; }
-}
 
 /** ALERT MESSAGES **/
-.alert-message { @extend .alert; }
-.alert-message.error { @extend .alert-error; }
-
 .alert.alert-disabled {
   background: #EEE;
   color: #777;
   border-color: #DDD;
 }
 
-/** AVATARS **/
-img.avatar { float: left; margin-right: 12px; width: 40px; border: 1px solid #ddd; padding: 1px; }
-img.avatar.s16 { width: 16px; height: 16px; margin-right: 6px; }
-img.avatar.s24 { width: 24px; height: 24px; margin-right: 8px; }
-img.avatar.s32 { width: 32px; height: 32px; margin-right: 10px; }
-img.avatar.s90 { width: 90px; height: 90px; margin-right: 15px; }
-img.lil_av { padding-left: 4px; padding-right: 3px; }
-img.small { width: 80px; }
-
 /** HELPERS **/
 .nothing_here_message {
   text-align: center;
diff --git a/app/assets/stylesheets/gitlab_bootstrap/nav.scss b/app/assets/stylesheets/gitlab_bootstrap/nav.scss
new file mode 100644
index 00000000000..2eaef61ca33
--- /dev/null
+++ b/app/assets/stylesheets/gitlab_bootstrap/nav.scss
@@ -0,0 +1,65 @@
+/**
+ * nav-pills
+ *
+ */
+.nav-pills {
+  .active a {
+    background: $primary_color;
+  }
+
+  > li > a {
+    @include border-radius(0);
+  }
+  &.nav-stacked {
+    > li > a {
+      border-left: 4px solid #EEE;
+      padding: 12px;
+    }
+    > .active > a {
+      border-color: #29B;
+      border-radius: 0;
+      background: #F1F1F1;
+      color: $style_color;
+      font-weight: bold;
+    }
+  }
+}
+
+.nav-pills > .active > a > i[class^="icon-"] { background: inherit; }
+
+
+
+/**
+ * nav-tabs
+ *
+ */
+.nav-tabs > li > a, .nav-pills > li > a { color: $style_color; }
+.nav.nav-tabs {
+  li {
+    > a {
+      padding: 8px 20px;
+      margin-right: 7px;
+      line-height: 20px;
+      border-color: #EEE;
+      color: #888;
+      border-bottom: 1px solid #ddd;
+      .badge {
+        background-color: #eee;
+        color: #888;
+        text-shadow: 0 1px 1px #fff;
+      }
+      i[class^="icon-"] {
+        line-height: 14px;
+      }
+    }
+    &.active {
+      > a {
+        border-color: #CCC;
+        border-bottom: 1px solid #fff;
+        color: #333;
+      }
+    }
+  }
+
+  &.nav-small-tabs > li > a { padding: 6px 9px; }
+}
-- 
GitLab


From 560985b0f685f810a1ce16ae206fbbf81b8fb704 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 30 Jan 2013 17:07:44 +0200
Subject: [PATCH 144/197] Fixed link_to_member

---
 app/helpers/projects_helper.rb | 2 +-
 app/models/users_project.rb    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 4f0a80710cb..05303e86ae8 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -43,7 +43,7 @@ module ProjectsHelper
     tm = project.team_member_by_id(author)
 
     if tm
-      link_to author_html, project_team_member_path(project, tm), class: "author_link"
+      link_to author_html, project_team_member_path(project, tm.user_username), class: "author_link"
     else
       author_html
     end.html_safe
diff --git a/app/models/users_project.rb b/app/models/users_project.rb
index 183878cb30c..94edfd9eddf 100644
--- a/app/models/users_project.rb
+++ b/app/models/users_project.rb
@@ -33,7 +33,7 @@ class UsersProject < ActiveRecord::Base
   validates :project_access, inclusion: { in: [GUEST, REPORTER, DEVELOPER, MASTER] }, presence: true
   validates :project, presence: true
 
-  delegate :name, :email, to: :user, prefix: true
+  delegate :name, :username, :email, to: :user, prefix: true
 
   scope :guests, where(project_access: GUEST)
   scope :reporters, where(project_access: REPORTER)
-- 
GitLab


From bfd00caff3010100f367ed60d73f065cc8b21f06 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Wed, 30 Jan 2013 17:13:05 +0200
Subject: [PATCH 145/197] Few usability improvments

---
 app/views/projects/_project_head.html.haml        | 8 ++++----
 app/views/team_members/_form.html.haml            | 2 +-
 app/views/team_members/_show.html.haml            | 2 +-
 features/steps/project/project_team_management.rb | 2 +-
 4 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/app/views/projects/_project_head.html.haml b/app/views/projects/_project_head.html.haml
index cc215502859..b8c88853a62 100644
--- a/app/views/projects/_project_head.html.haml
+++ b/app/views/projects/_project_head.html.haml
@@ -13,19 +13,19 @@
     = link_to 'Snippets', project_snippets_path(@project), class: "snippets-tab tab"
 
   - if can? current_user, :admin_project, @project
-    = nav_link(controller: :deploy_keys, html_options: {class: 'right'}) do
+    = nav_link(controller: :deploy_keys, html_options: {class: 'pull-right'}) do
       = link_to project_deploy_keys_path(@project) do
         %span
         Deploy Keys
-    = nav_link(controller: :hooks, html_options: {class: 'right'}) do
+    = nav_link(controller: :hooks, html_options: {class: 'pull-right'}) do
       = link_to project_hooks_path(@project) do
         %span
         Hooks
-    = nav_link(controller: :services, html_options: {class: 'right'}) do
+    = nav_link(controller: :services, html_options: {class: 'pull-right'}) do
       = link_to project_services_path(@project) do
         %span
         Services
-    = nav_link(path: 'projects#edit', html_options: {class: 'right'}) do
+    = nav_link(path: 'projects#edit', html_options: {class: 'pull-right'}) do
       = link_to edit_project_path(@project), class: "stat-tab tab " do
         %i.icon-edit
         Edit
diff --git a/app/views/team_members/_form.html.haml b/app/views/team_members/_form.html.haml
index ee435c84ca2..05bea2db87e 100644
--- a/app/views/team_members/_form.html.haml
+++ b/app/views/team_members/_form.html.haml
@@ -19,5 +19,5 @@
     .input= select_tag :project_access, options_for_select(Project.access_options, @user_project_relation.project_access), class: "project-access-select chosen"
 
   .actions
-    = f.submit 'Save', class: "btn btn-save"
+    = f.submit 'Add users', class: "btn btn-create"
     = link_to "Cancel", project_team_index_path(@project), class: "btn btn-cancel"
diff --git a/app/views/team_members/_show.html.haml b/app/views/team_members/_show.html.haml
index b59bb7b1e52..3df2caed64a 100644
--- a/app/views/team_members/_show.html.haml
+++ b/app/views/team_members/_show.html.haml
@@ -19,7 +19,7 @@
         - if current_user == user
           %span.btn.disabled This is you!
         - if @project.namespace_owner == user
-          %span.btn.disabled.btn-success Owner
+          %span.btn.disabled Owner
         - elsif user.blocked
           %span.btn.disabled.blocked Blocked
         - elsif allow_admin
diff --git a/features/steps/project/project_team_management.rb b/features/steps/project/project_team_management.rb
index 91b3ffeee9a..19352fe0ab8 100644
--- a/features/steps/project/project_team_management.rb
+++ b/features/steps/project/project_team_management.rb
@@ -24,7 +24,7 @@ class ProjectTeamManagement < Spinach::FeatureSteps
       select user.name, :from => "user_ids"
       select "Reporter", :from => "project_access"
     end
-    click_button "Save"
+    click_button "Add users"
   end
 
   Then 'I should see "Mike" in team list as "Reporter"' do
-- 
GitLab


From f8a2db53417a345d78d8e6b78367d5bbb9bb601b Mon Sep 17 00:00:00 2001
From: Sato Hiroyuki <sathiroyuki@gmail.com>
Date: Thu, 31 Jan 2013 10:37:23 +0900
Subject: [PATCH 146/197] Displaying commit on a new window, when clicking
 commit on network graph.

---
 vendor/assets/javascripts/branch-graph.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/vendor/assets/javascripts/branch-graph.js b/vendor/assets/javascripts/branch-graph.js
index 93849c79e80..2fc39423b41 100644
--- a/vendor/assets/javascripts/branch-graph.js
+++ b/vendor/assets/javascripts/branch-graph.js
@@ -260,7 +260,7 @@
       cursor: "pointer"
     })
     .click(function(){
-      window.location = options.commit_url.replace('%s', commit.id);
+      window.open(options.commit_url.replace('%s', commit.id), '_blank');
     })
     .hover(function(){
       this.tooltip = r.commitTooltip(x, y + 5, commit);
-- 
GitLab


From ad33c398008d9a2ec4a900c1d54f678a47de2cdd Mon Sep 17 00:00:00 2001
From: Sato Hiroyuki <sathiroyuki@gmail.com>
Date: Thu, 31 Jan 2013 13:22:08 +0900
Subject: [PATCH 147/197] Fix wrong path of features.

---
 features/steps/project/project_network_graph.rb | 2 +-
 features/steps/shared/paths.rb                  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/features/steps/project/project_network_graph.rb b/features/steps/project/project_network_graph.rb
index 77149bfe2c3..f26deff9367 100644
--- a/features/steps/project/project_network_graph.rb
+++ b/features/steps/project/project_network_graph.rb
@@ -14,6 +14,6 @@ class ProjectNetworkGraph < Spinach::FeatureSteps
     Gitlab::Graph::JsonBuilder.stub(max_count: 10)
 
     project = Project.find_by_name("Shop")
-    visit graph_project_path(project)
+    visit project_graph_path(project, "master")
   end
 end
diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb
index 42ef40d6b95..97adfd13f30 100644
--- a/features/steps/shared/paths.rb
+++ b/features/steps/shared/paths.rb
@@ -141,7 +141,7 @@ module SharedPaths
     # Stub Graph::JsonBuilder max_size to speed up test (10 commits vs. 650)
     Gitlab::Graph::JsonBuilder.stub(max_count: 10)
 
-    visit graph_project_path(@project)
+    visit project_graph_path(@project, root_ref)
   end
 
   Given "I visit my project's issues page" do
-- 
GitLab


From 9da7b2e8d8ed08cb193af2babf150cb8c7715f80 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 31 Jan 2013 08:42:11 +0200
Subject: [PATCH 148/197] add specs for api -> merge request notes

---
 spec/requests/api/notes_spec.rb | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb
index ae4fc111f63..ee99d85df4d 100644
--- a/spec/requests/api/notes_spec.rb
+++ b/spec/requests/api/notes_spec.rb
@@ -6,8 +6,10 @@ describe Gitlab::API do
   let(:user) { create(:user) }
   let!(:project) { create(:project, namespace: user.namespace ) }
   let!(:issue) { create(:issue, project: project, author: user) }
+  let!(:merge_request) { create(:merge_request, project: project, author: user) }
   let!(:snippet) { create(:snippet, project: project, author: user) }
   let!(:issue_note) { create(:note, noteable: issue, project: project, author: user) }
+  let!(:merge_request_note) { create(:note, noteable: merge_request, project: project, author: user) }
   let!(:snippet_note) { create(:note, noteable: snippet, project: project, author: user) }
   let!(:wall_note) { create(:note, project: project, author: user) }
   before { project.team << [user, :reporter] }
@@ -64,6 +66,15 @@ describe Gitlab::API do
         json_response.first['body'].should == snippet_note.note
       end
     end
+
+    context "when noteable is a Merge Request" do
+      it "should return an array of merge_requests notes" do
+        get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/notes", user)
+        response.status.should == 200
+        json_response.should be_an Array
+        json_response.first['body'].should == merge_request_note.note
+      end
+    end
   end
 
   describe "GET /projects/:id/noteable/:noteable_id/notes/:note_id" do
-- 
GitLab


From bcc0eed3e4565a346d15a17a90722ebb0c3cefab Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 31 Jan 2013 08:46:59 +0200
Subject: [PATCH 149/197] missing doc for api

---
 doc/api/notes.md | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/doc/api/notes.md b/doc/api/notes.md
index bb33efb8c25..a4ba2826076 100644
--- a/doc/api/notes.md
+++ b/doc/api/notes.md
@@ -30,6 +30,19 @@ Parameters:
 
 + `id` (required) - The ID of a project
 
+### List merge request notes
+
+Get a list of merge request notes.
+
+```
+GET /projects/:id/merge_requests/:merge_request_id/notes
+```
+
+Parameters:
+
++ `id` (required) - The ID of a project
++ `merge_request_id` (required) - The ID of an merge request
+
 ### List issue notes
 
 Get a list of issue notes.
-- 
GitLab


From 563c55eb7e4db988048bd1b2675ee73e0e601402 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 31 Jan 2013 08:55:31 +0200
Subject: [PATCH 150/197] fix pagination issue

---
 app/views/kaminari/admin/_paginator.html.haml  | 2 +-
 app/views/kaminari/gitlab/_paginator.html.haml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/views/kaminari/admin/_paginator.html.haml b/app/views/kaminari/admin/_paginator.html.haml
index 40b330feb3b..6f9fb332261 100644
--- a/app/views/kaminari/admin/_paginator.html.haml
+++ b/app/views/kaminari/admin/_paginator.html.haml
@@ -10,7 +10,7 @@
     %ul
       = prev_page_tag unless current_page.first?
       - each_page do |page|
-        - if page.left_outer? || page.pull-right_outer? || page.inside_window?
+        - if page.left_outer? || page.right_outer? || page.inside_window?
           = page_tag page
         - elsif !page.was_truncated?
           = gap_tag
diff --git a/app/views/kaminari/gitlab/_paginator.html.haml b/app/views/kaminari/gitlab/_paginator.html.haml
index 2fe4c183d15..6dd5a5782a2 100644
--- a/app/views/kaminari/gitlab/_paginator.html.haml
+++ b/app/views/kaminari/gitlab/_paginator.html.haml
@@ -9,7 +9,7 @@
   %nav.gitlab_pagination
     = prev_page_tag
     - each_page do |page|
-      - if page.left_outer? || page.pull-right_outer? || page.inside_window?
+      - if page.left_outer? || page.right_outer? || page.inside_window?
         = page_tag page
       - elsif !page.was_truncated?
         = gap_tag
-- 
GitLab


From 193a5624b2daf4d638c382b88001d06535f57f2d Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 31 Jan 2013 09:11:35 +0200
Subject: [PATCH 151/197] add path and path_with_namespace to api project
 entity

---
 app/models/project.rb                               |  2 +-
 app/models/user.rb                                  |  2 ++
 app/models/user_team.rb                             | 12 ++++++++++++
 app/models/user_team_project_relationship.rb        | 12 ++++++++++++
 app/models/user_team_user_relationship.rb           | 13 +++++++++++++
 ...130131070232_remove_private_flag_from_project.rb |  9 +++++++++
 db/schema.rb                                        |  3 +--
 doc/api/projects.md                                 |  6 ++++++
 lib/api/entities.rb                                 |  1 +
 spec/factories/user_team_project_relationships.rb   | 12 ++++++++++++
 spec/factories/user_team_user_relationships.rb      | 13 +++++++++++++
 spec/factories/user_teams.rb                        | 12 ++++++++++++
 spec/models/project_spec.rb                         |  3 +--
 spec/models/user_spec.rb                            |  2 ++
 spec/models/user_team_project_relationship_spec.rb  | 12 ++++++++++++
 spec/models/user_team_spec.rb                       | 12 ++++++++++++
 spec/models/user_team_user_relationship_spec.rb     | 13 +++++++++++++
 17 files changed, 134 insertions(+), 5 deletions(-)
 create mode 100644 db/migrate/20130131070232_remove_private_flag_from_project.rb

diff --git a/app/models/project.rb b/app/models/project.rb
index dde15927808..6a3d7ab15d2 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -8,7 +8,6 @@
 #  description            :text
 #  created_at             :datetime         not null
 #  updated_at             :datetime         not null
-#  private_flag           :boolean          default(TRUE), not null
 #  creator_id             :integer
 #  default_branch         :string(255)
 #  issues_enabled         :boolean          default(TRUE), not null
@@ -16,6 +15,7 @@
 #  merge_requests_enabled :boolean          default(TRUE), not null
 #  wiki_enabled           :boolean          default(TRUE), not null
 #  namespace_id           :integer
+#  public                 :boolean          default(FALSE), not null
 #
 
 require "grit"
diff --git a/app/models/user.rb b/app/models/user.rb
index 5a95deec53d..5b0df09a439 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -31,6 +31,8 @@
 #  extern_uid             :string(255)
 #  provider               :string(255)
 #  username               :string(255)
+#  can_create_group       :boolean          default(TRUE), not null
+#  can_create_team        :boolean          default(TRUE), not null
 #
 
 class User < ActiveRecord::Base
diff --git a/app/models/user_team.rb b/app/models/user_team.rb
index b28a6a041ac..dc8cf9eeb22 100644
--- a/app/models/user_team.rb
+++ b/app/models/user_team.rb
@@ -1,3 +1,15 @@
+# == Schema Information
+#
+# Table name: user_teams
+#
+#  id         :integer          not null, primary key
+#  name       :string(255)
+#  path       :string(255)
+#  owner_id   :integer
+#  created_at :datetime         not null
+#  updated_at :datetime         not null
+#
+
 class UserTeam < ActiveRecord::Base
   attr_accessible :name, :owner_id, :path
 
diff --git a/app/models/user_team_project_relationship.rb b/app/models/user_team_project_relationship.rb
index 1b0368c7ecc..a7aa88970c7 100644
--- a/app/models/user_team_project_relationship.rb
+++ b/app/models/user_team_project_relationship.rb
@@ -1,3 +1,15 @@
+# == Schema Information
+#
+# Table name: user_team_project_relationships
+#
+#  id              :integer          not null, primary key
+#  project_id      :integer
+#  user_team_id    :integer
+#  greatest_access :integer
+#  created_at      :datetime         not null
+#  updated_at      :datetime         not null
+#
+
 class UserTeamProjectRelationship < ActiveRecord::Base
   attr_accessible :greatest_access, :project_id, :user_team_id
 
diff --git a/app/models/user_team_user_relationship.rb b/app/models/user_team_user_relationship.rb
index 63bdc49e5b6..1f7e2625f5f 100644
--- a/app/models/user_team_user_relationship.rb
+++ b/app/models/user_team_user_relationship.rb
@@ -1,3 +1,16 @@
+# == Schema Information
+#
+# Table name: user_team_user_relationships
+#
+#  id           :integer          not null, primary key
+#  user_id      :integer
+#  user_team_id :integer
+#  group_admin  :boolean
+#  permission   :integer
+#  created_at   :datetime         not null
+#  updated_at   :datetime         not null
+#
+
 class UserTeamUserRelationship < ActiveRecord::Base
   attr_accessible :group_admin, :permission, :user_id, :user_team_id
 
diff --git a/db/migrate/20130131070232_remove_private_flag_from_project.rb b/db/migrate/20130131070232_remove_private_flag_from_project.rb
new file mode 100644
index 00000000000..5754db11558
--- /dev/null
+++ b/db/migrate/20130131070232_remove_private_flag_from_project.rb
@@ -0,0 +1,9 @@
+class RemovePrivateFlagFromProject < ActiveRecord::Migration
+  def up
+    remove_column :projects, :private_flag
+  end
+
+  def down
+    add_column :projects, :private_flag, :boolean, default: true, null: false
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 144f4a57036..0f07d2bc8c5 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 => 20130125090214) do
+ActiveRecord::Schema.define(:version => 20130131070232) do
 
   create_table "events", :force => true do |t|
     t.string   "target_type"
@@ -147,7 +147,6 @@ ActiveRecord::Schema.define(:version => 20130125090214) do
     t.text     "description"
     t.datetime "created_at",                                :null => false
     t.datetime "updated_at",                                :null => false
-    t.boolean  "private_flag",           :default => true,  :null => false
     t.integer  "creator_id"
     t.string   "default_branch"
     t.boolean  "issues_enabled",         :default => true,  :null => false
diff --git a/doc/api/projects.md b/doc/api/projects.md
index 411286750f8..82bb0c0d561 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -22,6 +22,8 @@ GET /projects
       "created_at": "2012-05-23T08:00:58Z"
     },
     "private": true,
+    "path": "rails",
+    "path_with_namespace": "rails/rails",
     "issues_enabled": false,
     "merge_requests_enabled": false,
     "wall_enabled": true,
@@ -42,6 +44,8 @@ GET /projects
       "created_at": "2012-05-23T08:00:58Z"
     },
     "private": true,
+    "path": "gitlab",
+    "path_with_namespace": "randx/gitlab",
     "issues_enabled": true,
     "merge_requests_enabled": true,
     "wall_enabled": true,
@@ -78,6 +82,8 @@ Parameters:
     "created_at": "2012-05-23T08:00:58Z"
   },
   "private": true,
+  "path": "gitlab",
+  "path_with_namespace": "randx/gitlab",
   "issues_enabled": true,
   "merge_requests_enabled": true,
   "wall_enabled": true,
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 80e2954a344..3637464676b 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -21,6 +21,7 @@ module Gitlab
       expose :id, :name, :description, :default_branch
       expose :owner, using: Entities::UserBasic
       expose :private_flag, as: :private
+      expose :path, :path_with_namespace
       expose :issues_enabled, :merge_requests_enabled, :wall_enabled, :wiki_enabled, :created_at
       expose :namespace
     end
diff --git a/spec/factories/user_team_project_relationships.rb b/spec/factories/user_team_project_relationships.rb
index 93c7b57d0fa..e900d86c2e4 100644
--- a/spec/factories/user_team_project_relationships.rb
+++ b/spec/factories/user_team_project_relationships.rb
@@ -1,3 +1,15 @@
+# == Schema Information
+#
+# Table name: user_team_project_relationships
+#
+#  id              :integer          not null, primary key
+#  project_id      :integer
+#  user_team_id    :integer
+#  greatest_access :integer
+#  created_at      :datetime         not null
+#  updated_at      :datetime         not null
+#
+
 # Read about factories at https://github.com/thoughtbot/factory_girl
 
 FactoryGirl.define do
diff --git a/spec/factories/user_team_user_relationships.rb b/spec/factories/user_team_user_relationships.rb
index 55179f9a45b..8c729dd8751 100644
--- a/spec/factories/user_team_user_relationships.rb
+++ b/spec/factories/user_team_user_relationships.rb
@@ -1,3 +1,16 @@
+# == Schema Information
+#
+# Table name: user_team_user_relationships
+#
+#  id           :integer          not null, primary key
+#  user_id      :integer
+#  user_team_id :integer
+#  group_admin  :boolean
+#  permission   :integer
+#  created_at   :datetime         not null
+#  updated_at   :datetime         not null
+#
+
 # Read about factories at https://github.com/thoughtbot/factory_girl
 
 FactoryGirl.define do
diff --git a/spec/factories/user_teams.rb b/spec/factories/user_teams.rb
index f4fe45cbb8a..1a9ae8e885c 100644
--- a/spec/factories/user_teams.rb
+++ b/spec/factories/user_teams.rb
@@ -1,3 +1,15 @@
+# == Schema Information
+#
+# Table name: user_teams
+#
+#  id         :integer          not null, primary key
+#  name       :string(255)
+#  path       :string(255)
+#  owner_id   :integer
+#  created_at :datetime         not null
+#  updated_at :datetime         not null
+#
+
 # Read about factories at https://github.com/thoughtbot/factory_girl
 
 FactoryGirl.define do
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 17bc988bf05..6e67ca8233d 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -8,7 +8,6 @@
 #  description            :text
 #  created_at             :datetime         not null
 #  updated_at             :datetime         not null
-#  private_flag           :boolean          default(TRUE), not null
 #  creator_id             :integer
 #  default_branch         :string(255)
 #  issues_enabled         :boolean          default(TRUE), not null
@@ -16,6 +15,7 @@
 #  merge_requests_enabled :boolean          default(TRUE), not null
 #  wiki_enabled           :boolean          default(TRUE), not null
 #  namespace_id           :integer
+#  public                 :boolean          default(FALSE), not null
 #
 
 require 'spec_helper'
@@ -42,7 +42,6 @@ describe Project do
   describe "Mass assignment" do
     it { should_not allow_mass_assignment_of(:namespace_id) }
     it { should_not allow_mass_assignment_of(:creator_id) }
-    it { should_not allow_mass_assignment_of(:private_flag) }
   end
 
   describe "Validation" do
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 2ca82edf74e..8ab0a0343bb 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -31,6 +31,8 @@
 #  extern_uid             :string(255)
 #  provider               :string(255)
 #  username               :string(255)
+#  can_create_group       :boolean          default(TRUE), not null
+#  can_create_team        :boolean          default(TRUE), not null
 #
 
 require 'spec_helper'
diff --git a/spec/models/user_team_project_relationship_spec.rb b/spec/models/user_team_project_relationship_spec.rb
index 81051d59971..86150cf305f 100644
--- a/spec/models/user_team_project_relationship_spec.rb
+++ b/spec/models/user_team_project_relationship_spec.rb
@@ -1,3 +1,15 @@
+# == Schema Information
+#
+# Table name: user_team_project_relationships
+#
+#  id              :integer          not null, primary key
+#  project_id      :integer
+#  user_team_id    :integer
+#  greatest_access :integer
+#  created_at      :datetime         not null
+#  updated_at      :datetime         not null
+#
+
 require 'spec_helper'
 
 describe UserTeamProjectRelationship do
diff --git a/spec/models/user_team_spec.rb b/spec/models/user_team_spec.rb
index 2d1b99db6f8..76d47f41498 100644
--- a/spec/models/user_team_spec.rb
+++ b/spec/models/user_team_spec.rb
@@ -1,3 +1,15 @@
+# == Schema Information
+#
+# Table name: user_teams
+#
+#  id         :integer          not null, primary key
+#  name       :string(255)
+#  path       :string(255)
+#  owner_id   :integer
+#  created_at :datetime         not null
+#  updated_at :datetime         not null
+#
+
 require 'spec_helper'
 
 describe UserTeam do
diff --git a/spec/models/user_team_user_relationship_spec.rb b/spec/models/user_team_user_relationship_spec.rb
index 309f1975e51..981ad1e8873 100644
--- a/spec/models/user_team_user_relationship_spec.rb
+++ b/spec/models/user_team_user_relationship_spec.rb
@@ -1,3 +1,16 @@
+# == Schema Information
+#
+# Table name: user_team_user_relationships
+#
+#  id           :integer          not null, primary key
+#  user_id      :integer
+#  user_team_id :integer
+#  group_admin  :boolean
+#  permission   :integer
+#  created_at   :datetime         not null
+#  updated_at   :datetime         not null
+#
+
 require 'spec_helper'
 
 describe UserTeamUserRelationship do
-- 
GitLab


From 315fd7d746aebe3456d5cc87caf0416cb83ea671 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 31 Jan 2013 10:08:20 +0200
Subject: [PATCH 152/197] fix routing specs

---
 spec/routing/project_routing_spec.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb
index 6171141648c..f94bedc79a1 100644
--- a/spec/routing/project_routing_spec.rb
+++ b/spec/routing/project_routing_spec.rb
@@ -76,7 +76,7 @@ describe ProjectsController, "routing" do
   end
 
   it "to #graph" do
-    get("/gitlabhq/graph").should route_to('projects#graph', id: 'gitlabhq')
+    get("/gitlabhq/graph/master").should route_to('graph#show', project_id: 'gitlabhq', id: 'master')
   end
 
   it "to #files" do
-- 
GitLab


From 41332212005d2a6d2d2131bc30c29bd29b81453e Mon Sep 17 00:00:00 2001
From: Sato Hiroyuki <sathiroyuki@gmail.com>
Date: Thu, 31 Jan 2013 17:29:36 +0900
Subject: [PATCH 153/197] Fix bug of network graph(#2847) and trivial code
 clean up.

---
 lib/gitlab/graph/json_builder.rb          | 23 +++++++++++++++--------
 vendor/assets/javascripts/branch-graph.js |  2 +-
 2 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/lib/gitlab/graph/json_builder.rb b/lib/gitlab/graph/json_builder.rb
index 90d384449f5..4b3687e06c3 100644
--- a/lib/gitlab/graph/json_builder.rb
+++ b/lib/gitlab/graph/json_builder.rb
@@ -109,9 +109,9 @@ module Gitlab
                     end
 
             space = if commit.space >= parent.space then
-                      find_free_parent_space(range, map, parent.space, 1, commit.space, times)
+                      find_free_parent_space(range, parent.space, 1, commit.space, times)
                     else
-                      find_free_parent_space(range, map, parent.space, -1, parent.space, times)
+                      find_free_parent_space(range, parent.space, -1, parent.space, times)
                     end
 
             mark_reserved(range, space)
@@ -122,9 +122,9 @@ module Gitlab
         spaces
       end
 
-      def find_free_parent_space(range, map, space_base, space_step, space_default, times)
+      def find_free_parent_space(range, space_base, space_step, space_default, times)
         if is_overlap?(range, times, space_default) then
-          find_free_space(range, map, space_base, space_step)
+          find_free_space(range, space_base, space_step)
         else
           space_default
         end
@@ -152,11 +152,9 @@ module Gitlab
         if leaves.empty?
           return
         end
-        time_range = leaves.last.time..leaves.first.time
-        space = find_free_space(time_range, map, 1, 2)
-        leaves.each{|l| l.space = space}
         # and mark it as reserved
         min_time = leaves.last.time
+        max_space = 1
         parents = leaves.last.parents.collect
         parents.each do |p|
           if map.include? p.id
@@ -164,6 +162,9 @@ module Gitlab
             if parent.time < min_time
               min_time = parent.time
             end
+            if max_space < parent.space then
+              max_space = parent.space
+            end
           end
         end
         if parent_time.nil?
@@ -171,6 +172,11 @@ module Gitlab
         else
           max_time = parent_time - 1
         end
+
+        time_range = leaves.last.time..leaves.first.time
+        space = find_free_space(time_range, max_space, 2)
+        leaves.each{|l| l.space = space}
+
         mark_reserved(min_time..max_time, space)
 
         # Visit branching chains
@@ -188,11 +194,12 @@ module Gitlab
         end
       end
 
-      def find_free_space(time_range, map, space_base, space_step)
+      def find_free_space(time_range, space_base, space_step)
         reserved = []
         for day in time_range
           reserved += @_reserved[day]
         end
+        reserved.uniq!
 
         space = space_base
         while reserved.include?(space) do
diff --git a/vendor/assets/javascripts/branch-graph.js b/vendor/assets/javascripts/branch-graph.js
index 4ca8680416b..7929d3b2a14 100644
--- a/vendor/assets/javascripts/branch-graph.js
+++ b/vendor/assets/javascripts/branch-graph.js
@@ -122,7 +122,7 @@
           var cx = offsetX + 20 * c.time
             , cy = offsetY + 10 * c.space
             , psy = offsetY + 10 * ps;
-          if (c.space == this.commits[i].space) {
+          if (c.space == this.commits[i].space && c.space == ps) {
             r.path([
               "M", x, y,
               "L", cx, cy
-- 
GitLab


From 130f60d55b13682cc4ca4cba390535dc10dbca07 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 31 Jan 2013 11:22:06 +0200
Subject: [PATCH 154/197] a bit of restyling. Replace some images with icons.
 Simplify note form

---
 app/assets/images/home_icon.PNG              | Bin 596 -> 0 bytes
 app/assets/images/icon-attachment.png        | Bin 450 -> 0 bytes
 app/assets/javascripts/notes.js              |   4 +-
 app/assets/stylesheets/common.scss           |   4 --
 app/assets/stylesheets/sections/nav.scss     |  12 ++--
 app/assets/stylesheets/sections/notes.scss   |  58 +++++--------------
 app/views/layouts/admin.html.haml            |   3 +-
 app/views/layouts/application.html.haml      |   3 +-
 app/views/layouts/group.html.haml            |   3 +-
 app/views/layouts/profile.html.haml          |   3 +-
 app/views/layouts/project_resource.html.haml |   3 +-
 app/views/layouts/user_team.html.haml        |   3 +-
 app/views/notes/_form.html.haml              |  32 +++++-----
 app/views/notes/_note.html.haml              |   2 +-
 14 files changed, 50 insertions(+), 80 deletions(-)
 delete mode 100644 app/assets/images/home_icon.PNG
 delete mode 100644 app/assets/images/icon-attachment.png

diff --git a/app/assets/images/home_icon.PNG b/app/assets/images/home_icon.PNG
deleted file mode 100644
index b1d60d5935760d7f7c448a6ea3e7270fe405a664..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 596
zcmV-a0;~OrP)<h;3K|Lk000e1NJLTq000sI000sQ1^@s6R?d!B00001b5ch_0Itp)
z=>Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyV_
z4K@a3G(t}R00GoVL_t(I%bk-wXjMTJgul5yMH`8gAo!CY*xAX$Qna`S6)}aD3N`^d
z6%@6Q7+VVwA&qHN5Y%>WX~aSiVj4ljM(~G}Hez1P8;k6d%{4#bsrInv&d$u43+q%w
zbRuFXpWAnT&RPQi+Z{=hz<%IlO6hZ5*CUdS0Pj;uF9!3~8e}R-kAO44K43N?woB>)
zlfda^!z)pZh#kPR?W4AD0oQ;}z*pdK9`BdmcFHEDL_~}L)4(=KSAiSAX5a#F0yqcQ
zHh(cHm;~?+n6o_rOaMa}=pHZw+y*3RPpL$8UDGrTbzPqV9!q+e8C_{h&nzBDdYb{C
zr<4u>C?Ylimw|EMA@B{jWZRN{0P`7V1F$u3`Wf&VxDL$NK3>@#wmlA<1$F@!0Rysq
z)Aj+NYkL&vWphS>G26#%@0PSvh0a$%cOXF$z<JwKT53jsH`%X2EvA$@?ez~2HjzQF
zJtpa??I*xpU}Gz53lXumz5c~^A|>6ieP2?Q8O;J)O8*CWs@D0{`c2dHQ%b*pg?4sU
zP4)_<<plNLK>u7-OYf>>o3^yFFU|faX|4e50N;!Io}>@iTxY2j&}#$LOJP>|;(TGy
i7vSJvCTGpSPk`SQOT{AUHr@FE0000<MNUMnLSTZy7W7g8

diff --git a/app/assets/images/icon-attachment.png b/app/assets/images/icon-attachment.png
deleted file mode 100644
index 168ad8dce3765ac98968def2101ba9f298e9f637..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 450
zcmV;z0X_bSP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzWJyFpRCwBalg~#4VHn4!F_!*=PSGh!
zr_v!(tX3(~Eh42+iZ0z!qI65ETcngtS)#R(D6ObdI>ZvO_7I&qMMNxp9=^*Mv+v8t
z?9M#%dEe*9G-WawkClQASb=7EhXSla&2y|k*KNIg0#DEl^Uw;@E{U(J1@Ay8$ujiA
z5FENr;75MH#h(2@8b)1`y1;f_gBJbofGTu>6=?$YT!K~jf=A_Tr&)qrL^1=rjRe06
z`jDgz4kS5_NakQOsSEWr2A7hgC8?<fp`PFB-d0>tRqw~)0v;qef<H-mU<7Vd<ZM(B
z>O~u*N#$RcoWi2on$;#nOF1gI))9-E%qiu64<*$hRO}thTIc*&4NBT^7|t|>3s8p6
z*sNSx$AW~`KEt4jmDfoM32~NA#cwcRWsP#L>XM2*Z&!NzzGKWQ(5GN4=72sj`{-Wa
s+$K2i-0M>($*GOs65G933-}jc09s5_9C^sJwg3PC07*qoM6N<$f`59&Qvd(}

diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index 8a7e08dd0e8..919c6b7f4a2 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -20,12 +20,12 @@ var NoteList = {
 
     if(NoteList.reversed) {
       var form = $(".js-main-target-form");
-      form.find(".buttons, .note_options").hide();
+      form.find(".note-form-actions").hide();
       var textarea = form.find(".js-note-text");
       textarea.css("height", "40px");
       textarea.on("focus", function(){
         textarea.css("height", "80px");
-        form.find(".buttons, .note_options").show();
+        form.find(".note-form-actions").show();
       });
     }
 
diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss
index 1884c39bc61..c9a11d0a1ac 100644
--- a/app/assets/stylesheets/common.scss
+++ b/app/assets/stylesheets/common.scss
@@ -338,10 +338,6 @@ li.note {
     li {
       border-bottom:none !important;
     }
-    .attachment {
-      padding-left: 20px;
-      background:url("icon-attachment.png") no-repeat left center;
-    }
   }
 }
 
diff --git a/app/assets/stylesheets/sections/nav.scss b/app/assets/stylesheets/sections/nav.scss
index bc19bc75a67..50091cd7365 100644
--- a/app/assets/stylesheets/sections/nav.scss
+++ b/app/assets/stylesheets/sections/nav.scss
@@ -6,8 +6,7 @@ ul.main_menu {
   margin: auto;
   margin: 30px 0;
   margin-top: 10px;
-  border-bottom: 1px solid #DDD;
-  height: 37px;
+  height: 38px;
   position: relative;
   overflow: hidden;
   .count {
@@ -33,6 +32,7 @@ ul.main_menu {
     margin: 0;
     display: table-cell;
     width: 1%;
+    border-bottom: 2px solid #EEE;
     &.active {
       border-bottom: 2px solid #474D57;
       a {
@@ -42,10 +42,8 @@ ul.main_menu {
 
     &.home {
       a {
-        background: url(home_icon.PNG) no-repeat center center;
-        text-indent:-9999px;
-        min-width: 20px;
-        img {
+        i {
+          font-size: 20px;
           position: relative;
           top: 4px;
         }
@@ -56,7 +54,7 @@ ul.main_menu {
     display: block;
     text-align: center;
     font-weight: normal;
-    height: 35px;
+    height: 36px;
     line-height: 36px;
     color: #777;
     text-shadow: 0 1px 1px white;
diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss
index 895e9dfa4e3..648cb210e9c 100644
--- a/app/assets/stylesheets/sections/notes.scss
+++ b/app/assets/stylesheets/sections/notes.scss
@@ -81,14 +81,6 @@ ul.notes {
     .attachment {
       font-size: 14px;
       margin-top: -20px;
-
-      .icon-attachment {
-        @extend .icon-paper-clip;
-        font-size: 24px;
-        position: relative;
-        text-align: right;
-        top: 6px;
-      }
     }
     .note-body {
       margin-left: 45px;
@@ -229,11 +221,6 @@ ul.notes {
 .discussion {
   .new_note {
     margin: 8px 5px 8px 0;
-
-    .note_options {
-      // because of the smaller width and the extra "cancel" button
-      margin-top: 8px;
-    }
   }
 }
 .new_note {
@@ -246,37 +233,6 @@ ul.notes {
   .clearfix {
     margin-bottom: 0;
   }
-  .note_options {
-    h6 {
-      @extend .left;
-      line-height: 20px;
-      padding-right: 16px;
-      padding-bottom: 16px;
-    }
-    label {
-      padding: 0;
-    }
-
-    .attachment {
-      @extend .pull-right;
-      position: relative;
-      width: 350px;
-      height: 50px;
-      margin:0 0 5px !important;
-
-      // hide the actual file field
-      input {
-        display: none;
-      }
-
-      .choose-btn {
-        float: right;
-      }
-    }
-    .notify_options {
-      @extend .pull-right;
-    }
-  }
   .note_text_and_preview {
     // makes the "absolute" position for links relative to this
     position: relative;
@@ -315,3 +271,17 @@ ul.notes {
   @extend .thumbnail;
   margin-left: 45px;
 }
+
+
+.note-form-actions {
+  background: #F9F9F9;
+  height: 45px;
+  padding: 0 5px;
+
+  .note-form-option {
+    margin-top: 8px;
+    margin-left: 15px;
+    @extend .pull-left;
+    @extend .span4;
+  }
+}
diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml
index 28626b9c682..a01886cdabf 100644
--- a/app/views/layouts/admin.html.haml
+++ b/app/views/layouts/admin.html.haml
@@ -7,7 +7,8 @@
     .container
       %ul.main_menu
         = nav_link(controller: :dashboard, html_options: {class: 'home'}) do
-          = link_to "Stats", admin_root_path
+          = link_to admin_root_path, title: "Stats" do
+            %i.icon-home
         = nav_link(controller: :projects) do
           = link_to "Projects", admin_projects_path
         = nav_link(controller: :teams) do
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index 261a8608ca4..7ee44238d10 100644
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -7,7 +7,8 @@
     .container
       %ul.main_menu
         = nav_link(path: 'dashboard#show', html_options: {class: 'home'}) do
-          = link_to "Home", root_path, title: "Home"
+          = link_to root_path, title: "Home" do
+            %i.icon-home
         = nav_link(path: 'dashboard#projects') do
           = link_to projects_dashboard_path do
             Projects
diff --git a/app/views/layouts/group.html.haml b/app/views/layouts/group.html.haml
index 46bc9ef1457..4395e408649 100644
--- a/app/views/layouts/group.html.haml
+++ b/app/views/layouts/group.html.haml
@@ -7,7 +7,8 @@
     .container
       %ul.main_menu
         = nav_link(path: 'groups#show', html_options: {class: 'home'}) do
-          = link_to "Home", group_path(@group), title: "Home"
+          = link_to group_path(@group), title: "Home" do
+            %i.icon-home
         = nav_link(path: 'groups#issues') do
           = link_to issues_group_path(@group) do
             Issues
diff --git a/app/views/layouts/profile.html.haml b/app/views/layouts/profile.html.haml
index 7852ed6f0e1..57f250c775b 100644
--- a/app/views/layouts/profile.html.haml
+++ b/app/views/layouts/profile.html.haml
@@ -7,7 +7,8 @@
     .container
       %ul.main_menu
         = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
-          = link_to "Profile", profile_path
+          = link_to profile_path, title: "Profile" do
+            %i.icon-home
         = nav_link(path: 'profiles#account') do
           = link_to "Account", account_profile_path
         = nav_link(controller: :keys) do
diff --git a/app/views/layouts/project_resource.html.haml b/app/views/layouts/project_resource.html.haml
index c19d33ceec9..09ccb1d7b6a 100644
--- a/app/views/layouts/project_resource.html.haml
+++ b/app/views/layouts/project_resource.html.haml
@@ -12,7 +12,8 @@
     .container
       %ul.main_menu
         = nav_link(html_options: {class: "home #{project_tab_class}"}) do
-          = link_to @project.path, project_path(@project), title: "Project"
+          = link_to project_path(@project), title: "Project" do
+            %i.icon-home
 
         - if @project.repo_exists?
           - if can? current_user, :download_code, @project
diff --git a/app/views/layouts/user_team.html.haml b/app/views/layouts/user_team.html.haml
index 2d397e80905..19bbc373f46 100644
--- a/app/views/layouts/user_team.html.haml
+++ b/app/views/layouts/user_team.html.haml
@@ -7,7 +7,8 @@
     .container
       %ul.main_menu
         = nav_link(path: 'teams#show', html_options: {class: 'home'}) do
-          = link_to "Home", team_path(@team), title: "Home"
+          = link_to team_path(@team), title: "Home" do
+            %i.icon-home
 
         = nav_link(path: 'teams#issues') do
           = link_to issues_team_path(@team) do
diff --git a/app/views/notes/_form.html.haml b/app/views/notes/_form.html.haml
index f008712c529..a154c31e5ab 100644
--- a/app/views/notes/_form.html.haml
+++ b/app/views/notes/_form.html.haml
@@ -15,30 +15,30 @@
     = f.text_area :note, size: 255, class: 'note_text js-note-text js-gfm-input turn-on'
     .note_preview.js-note-preview.turn-off
 
-  .buttons
-    = f.submit 'Add Comment', class: "btn comment-btn grouped js-comment-button"
-    %a.btn.grouped.js-close-discussion-note-form Cancel
   .hint
     .pull-right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
   .clearfix
 
-  .note_options
-    .attachment
-      %h6 Attachment:
-      .file_name.js-attachment-filename File name...
-      %a.choose-btn.btn.btn-small.js-choose-note-attachment-button Choose File ...
-      .hint Any file up to 10 MB
+  .note-form-actions
+    .buttons
+      = f.submit 'Add Comment', class: "btn comment-btn grouped js-comment-button"
+      %a.btn.grouped.js-close-discussion-note-form Cancel
 
-      = f.file_field :attachment, class: "js-note-attachment-input"
-
-    .notify_options
-      %h6 Notify via email:
+    .note-form-option
       = label_tag :notify do
         = check_box_tag :notify, 1, !@note.for_commit?
-        Project team
+        %span.light Notify team via email
 
       .js-notify-commit-author
         = label_tag :notify_author do
           = check_box_tag :notify_author, 1 , @note.for_commit?
-          Commit author
-  .clearfix
+          %span.light Notify commit author
+    .note-form-option
+      %a.choose-btn.btn.btn-small.js-choose-note-attachment-button
+        %i.icon-paper-clip
+        %span Choose File ...
+      &nbsp;
+      %span.file_name.js-attachment-filename File name...
+      = f.file_field :attachment, class: "js-note-attachment-input hide"
+
+    .clearfix
diff --git a/app/views/notes/_note.html.haml b/app/views/notes/_note.html.haml
index 9c51da2913c..4d3007a0ed1 100644
--- a/app/views/notes/_note.html.haml
+++ b/app/views/notes/_note.html.haml
@@ -32,6 +32,6 @@
       = image_tag note.attachment.url, class: 'note-image-attach'
     .attachment.pull-right
       = link_to note.attachment.url, target: "_blank" do
-        %i.icon-attachment
+        %i.icon-paper-clip
         = note.attachment_identifier
   .clear
-- 
GitLab


From 2c7554e897356fe424f292c66cd03e0192b05167 Mon Sep 17 00:00:00 2001
From: Matt Humphrey <matt@tomatto.co.uk>
Date: Mon, 28 Jan 2013 17:22:44 +0000
Subject: [PATCH 155/197] Added methods to protect and unprotect branches

---
 doc/api/repositories.md            | 89 +++++++++++++++++++++++++++++-
 lib/api/entities.rb                |  5 ++
 lib/api/projects.rb                | 40 +++++++++++++-
 spec/requests/api/projects_spec.rb | 23 ++++++++
 4 files changed, 152 insertions(+), 5 deletions(-)

diff --git a/doc/api/repositories.md b/doc/api/repositories.md
index 685797ad78d..bc6ca70aa50 100644
--- a/doc/api/repositories.md
+++ b/doc/api/repositories.md
@@ -33,7 +33,8 @@ Parameters:
       },
       "authored_date": "2012-06-27T05:51:39-07:00",
       "committed_date": "2012-06-28T03:44:20-07:00"
-    }
+    },
+    "protected": true
   }
 ]
 ```
@@ -73,7 +74,88 @@ Parameters:
     },
     "authored_date": "2012-06-27T05:51:39-07:00",
     "committed_date": "2012-06-28T03:44:20-07:00"
-  }
+  },
+  "protected": true
+}
+```
+
+## Protect a project repository branch
+
+Protect a single project repository branch.
+
+```
+PUT /projects/:id/repository/branches/:branch/protect
+```
+
+Parameters:
+
++ `id` (required) - The ID of a project
++ `branch` (required) - The name of the branch
+
+```json
+{
+  "name": "master",
+  "commit": {
+    "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
+    "parents": [
+      {
+        "id": "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
+      }
+    ],
+    "tree": "46e82de44b1061621357f24c05515327f2795a95",
+    "message": "add projects API",
+    "author": {
+      "name": "John Smith",
+      "email": "john@example.com"
+    },
+    "committer": {
+      "name": "John Smith",
+      "email": "john@example.com"
+    },
+    "authored_date": "2012-06-27T05:51:39-07:00",
+    "committed_date": "2012-06-28T03:44:20-07:00"
+  },
+  "protected": true
+}
+```
+
+## Unprotect a project repository branch
+
+Unprotect a single project repository branch.
+
+```
+PUT /projects/:id/repository/branches/:branch/unprotect
+```
+
+Parameters:
+
++ `id` (required) - The ID of a project
++ `branch` (required) - The name of the branch
+
+```json
+{
+  "name": "master",
+  "commit": {
+    "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
+    "parents": [
+      {
+        "id": "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
+      }
+    ],
+    "tree": "46e82de44b1061621357f24c05515327f2795a95",
+    "message": "add projects API",
+    "author": {
+      "name": "John Smith",
+      "email": "john@example.com"
+    },
+    "committer": {
+      "name": "John Smith",
+      "email": "john@example.com"
+    },
+    "authored_date": "2012-06-27T05:51:39-07:00",
+    "committed_date": "2012-06-28T03:44:20-07:00"
+  },
+  "protected": false
 }
 ```
 
@@ -110,7 +192,8 @@ Parameters:
       },
       "authored_date": "2012-05-28T04:42:42-07:00",
       "committed_date": "2012-05-28T04:42:42-07:00"
-    }
+    },
+    "protected": null
   }
 ]
 ```
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 80e2954a344..3f228300e26 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -33,6 +33,11 @@ module Gitlab
 
     class RepoObject < Grape::Entity
       expose :name, :commit
+      expose :protected do |repo, options|
+        if options[:project]
+          options[:project].protected_branch? repo.name
+        end
+      end
     end
 
     class RepoCommit < Grape::Entity
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index cbef1ed3b50..a16243aa822 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -218,7 +218,7 @@ module Gitlab
       # Example Request:
       #   GET /projects/:id/repository/branches
       get ":id/repository/branches" do
-        present user_project.repo.heads.sort_by(&:name), with: Entities::RepoObject
+        present user_project.repo.heads.sort_by(&:name), with: Entities::RepoObject, project: user_project
       end
 
       # Get a single branch
@@ -230,7 +230,43 @@ module Gitlab
       #   GET /projects/:id/repository/branches/:branch
       get ":id/repository/branches/:branch" do
         @branch = user_project.repo.heads.find { |item| item.name == params[:branch] }
-        present @branch, with: Entities::RepoObject
+        present @branch, with: Entities::RepoObject, project: user_project
+      end
+
+      # Protect a single branch
+      #
+      # Parameters:
+      #   id (required) - The ID of a project
+      #   branch (required) - The name of the branch
+      # Example Request:
+      #   PUT /projects/:id/repository/branches/:branch/protect
+      put ":id/repository/branches/:branch/protect" do
+        @branch = user_project.repo.heads.find { |item| item.name == params[:branch] }
+        protected = user_project.protected_branches.find_by_name(@branch.name)
+
+        unless protected
+          user_project.protected_branches.create(:name => @branch.name)
+        end
+
+        present @branch, with: Entities::RepoObject, project: user_project
+      end
+
+      # Unprotect a single branch
+      #
+      # Parameters:
+      #   id (required) - The ID of a project
+      #   branch (required) - The name of the branch
+      # Example Request:
+      #   PUT /projects/:id/repository/branches/:branch/unprotect
+      put ":id/repository/branches/:branch/unprotect" do
+        @branch = user_project.repo.heads.find { |item| item.name == params[:branch] }
+        protected = user_project.protected_branches.find_by_name(@branch.name)
+
+        if protected
+          protected.destroy
+        end
+
+        present @branch, with: Entities::RepoObject, project: user_project
       end
 
       # Get a project repository tags
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index c2244210bcf..d932fd9e74d 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -107,6 +107,29 @@ describe Gitlab::API do
 
       json_response['name'].should == 'new_design'
       json_response['commit']['id'].should == '621491c677087aa243f165eab467bfdfbee00be1'
+      json_response['protected'].should == false
+    end
+  end
+
+  describe "PUT /projects/:id/repository/branches/:branch/protect" do
+    it "should protect a single branch" do
+      put api("/projects/#{project.id}/repository/branches/new_design/protect", user)
+      response.status.should == 200
+
+      json_response['name'].should == 'new_design'
+      json_response['commit']['id'].should == '621491c677087aa243f165eab467bfdfbee00be1'
+      json_response['protected'].should == true
+    end
+  end
+
+  describe "PUT /projects/:id/repository/branches/:branch/unprotect" do
+    it "should unprotect a single branch" do
+      put api("/projects/#{project.id}/repository/branches/new_design/unprotect", user)
+      response.status.should == 200
+
+      json_response['name'].should == 'new_design'
+      json_response['commit']['id'].should == '621491c677087aa243f165eab467bfdfbee00be1'
+      json_response['protected'].should == false
     end
   end
 
-- 
GitLab


From 2af323bbd1993b121b2ff7bcc695e2bb10af5a1b Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 31 Jan 2013 12:08:56 +0200
Subject: [PATCH 156/197] fix active tabs tests

---
 features/steps/admin/admin_active_tab.rb     | 2 +-
 features/steps/profile/profile_active_tab.rb | 2 +-
 features/steps/project/project_active_tab.rb | 2 +-
 features/steps/shared/active_tab.rb          | 6 +++++-
 4 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/features/steps/admin/admin_active_tab.rb b/features/steps/admin/admin_active_tab.rb
index 48ec7bac0d6..f14c5f396be 100644
--- a/features/steps/admin/admin_active_tab.rb
+++ b/features/steps/admin/admin_active_tab.rb
@@ -4,7 +4,7 @@ class AdminActiveTab < Spinach::FeatureSteps
   include SharedActiveTab
 
   Then 'the active main tab should be Home' do
-    ensure_active_main_tab('Stats')
+    ensure_active_main_tab('Home')
   end
 
   Then 'the active main tab should be Projects' do
diff --git a/features/steps/profile/profile_active_tab.rb b/features/steps/profile/profile_active_tab.rb
index 1924a6fa785..ee9f5f201cf 100644
--- a/features/steps/profile/profile_active_tab.rb
+++ b/features/steps/profile/profile_active_tab.rb
@@ -4,7 +4,7 @@ class ProfileActiveTab < Spinach::FeatureSteps
   include SharedActiveTab
 
   Then 'the active main tab should be Home' do
-    ensure_active_main_tab('Profile')
+    ensure_active_main_tab('Home')
   end
 
   Then 'the active main tab should be Account' do
diff --git a/features/steps/project/project_active_tab.rb b/features/steps/project/project_active_tab.rb
index a5c80353862..bce67c82962 100644
--- a/features/steps/project/project_active_tab.rb
+++ b/features/steps/project/project_active_tab.rb
@@ -7,7 +7,7 @@ class ProjectActiveTab < Spinach::FeatureSteps
   # Main Tabs
 
   Then 'the active main tab should be Home' do
-    ensure_active_main_tab(@project.name)
+    ensure_active_main_tab('Home')
   end
 
   Then 'the active main tab should be Files' do
diff --git a/features/steps/shared/active_tab.rb b/features/steps/shared/active_tab.rb
index 884f2d5fb71..446e3b9a8b3 100644
--- a/features/steps/shared/active_tab.rb
+++ b/features/steps/shared/active_tab.rb
@@ -2,7 +2,11 @@ module SharedActiveTab
   include Spinach::DSL
 
   def ensure_active_main_tab(content)
-    page.find('ul.main_menu li.active').should have_content(content)
+    if content == "Home"
+      page.find('ul.main_menu li.active').should have_css('i.icon-home')
+    else
+      page.find('ul.main_menu li.active').should have_content(content)
+    end
   end
 
   def ensure_active_sub_tab(content)
-- 
GitLab


From dfe2a742c2f2b862109a757cf90495ea1fcde70c Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 31 Jan 2013 13:13:17 +0200
Subject: [PATCH 157/197] fix notes specs

---
 spec/requests/notes_on_merge_requests_spec.rb | 8 ++++----
 spec/requests/notes_on_wall_spec.rb           | 6 +++---
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/spec/requests/notes_on_merge_requests_spec.rb b/spec/requests/notes_on_merge_requests_spec.rb
index 2b670359a49..0111cf42ac7 100644
--- a/spec/requests/notes_on_merge_requests_spec.rb
+++ b/spec/requests/notes_on_merge_requests_spec.rb
@@ -22,9 +22,9 @@ describe "On a merge request", js: true do
     it { within(".js-main-target-form") { should_not have_link("Cancel") } }
 
     # notifiactions
-    it { within(".js-main-target-form") { should have_checked_field("Project team") } }
-    it { within(".js-main-target-form") { should_not have_checked_field("Commit author") } }
-    it { within(".js-main-target-form") { should_not have_unchecked_field("Commit author") } }
+    it { within(".js-main-target-form") { should have_checked_field("Notify team via email") } }
+    it { within(".js-main-target-form") { should_not have_checked_field("Notify commit author") } }
+    it { within(".js-main-target-form") { should_not have_unchecked_field("Notify commit author") } }
 
     describe "without text" do
       it { within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: false) } }
@@ -125,7 +125,7 @@ describe "On a merge request diff", js: true, focus: true do
       it { should have_css(".js-close-discussion-note-form", text: "Cancel") }
 
       # notification options
-      it { should have_checked_field("Project team") }
+      it { should have_checked_field("Notify team via email") }
 
       it "shouldn't add a second form for same row" do
         find("#4735dfc552ad7bf15ca468adc3cad9d05b624490_185_185.line_holder .js-add-diff-note-button").trigger("click")
diff --git a/spec/requests/notes_on_wall_spec.rb b/spec/requests/notes_on_wall_spec.rb
index 01673f997e9..4adcf74e0b6 100644
--- a/spec/requests/notes_on_wall_spec.rb
+++ b/spec/requests/notes_on_wall_spec.rb
@@ -21,9 +21,9 @@ describe "On the project wall", js: true do
     it { within(".js-main-target-form") { should_not have_link("Cancel") } }
 
     # notifiactions
-    it { within(".js-main-target-form") { should have_checked_field("Project team") } }
-    it { within(".js-main-target-form") { should_not have_checked_field("Commit author") } }
-    it { within(".js-main-target-form") { should_not have_unchecked_field("Commit author") } }
+    it { within(".js-main-target-form") { should have_checked_field("Notify team via email") } }
+    it { within(".js-main-target-form") { should_not have_checked_field("Notify commit author") } }
+    it { within(".js-main-target-form") { should_not have_unchecked_field("Notify commit author") } }
 
     describe "without text" do
       it { within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: false) } }
-- 
GitLab


From cc2484c3e61764adbb61d78c97148c41cf346cd1 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Fri, 1 Feb 2013 08:59:30 +0200
Subject: [PATCH 158/197] Fix sending commit note email to id instead email

---
 app/mailers/notify.rb          | 4 ++--
 app/observers/note_observer.rb | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb
index 0ed06475fa8..c672940a05e 100644
--- a/app/mailers/notify.rb
+++ b/app/mailers/notify.rb
@@ -63,12 +63,12 @@ class Notify < ActionMailer::Base
   # Note
   #
 
-  def note_commit_email(commit_autor_email, note_id)
+  def note_commit_email(recipient_id, note_id)
     @note = Note.find(note_id)
     @commit = @note.noteable
     @commit = CommitDecorator.decorate(@commit)
     @project = @note.project
-    mail(to: commit_autor_email, subject: subject("note for commit #{@commit.short_id}", @commit.title))
+    mail(to: recipient(recipient_id), subject: subject("note for commit #{@commit.short_id}", @commit.title))
   end
 
   def note_issue_email(recipient_id, note_id)
diff --git a/app/observers/note_observer.rb b/app/observers/note_observer.rb
index 2ec644ef7c1..3f6d1dfcb70 100644
--- a/app/observers/note_observer.rb
+++ b/app/observers/note_observer.rb
@@ -11,7 +11,7 @@ class NoteObserver < ActiveRecord::Observer
       notify_team(note)
     elsif note.notify_author
       # Notify only author of resource
-      Notify.delay.note_commit_email(note.noteable.author_email, note.id)
+      Notify.delay.note_commit_email(note.commit_author.id, note.id)
     else
       # Otherwise ignore it
       nil
-- 
GitLab


From 61833bcb7457d98800c0581b6d09406929057a54 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Fri, 1 Feb 2013 09:33:12 +0200
Subject: [PATCH 159/197] fix app crash if author is missing

---
 app/observers/note_observer.rb | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/app/observers/note_observer.rb b/app/observers/note_observer.rb
index 3f6d1dfcb70..4ee9fadf4da 100644
--- a/app/observers/note_observer.rb
+++ b/app/observers/note_observer.rb
@@ -11,7 +11,9 @@ class NoteObserver < ActiveRecord::Observer
       notify_team(note)
     elsif note.notify_author
       # Notify only author of resource
-      Notify.delay.note_commit_email(note.commit_author.id, note.id)
+      if note.commit_author
+        Notify.delay.note_commit_email(note.commit_author.id, note.id)
+      end
     else
       # Otherwise ignore it
       nil
-- 
GitLab


From 8edc6b6a8c240322499356df96e1199bb6bbc872 Mon Sep 17 00:00:00 2001
From: Christian Simon <cs@f03.eu>
Date: Tue, 8 Jan 2013 22:05:00 +0100
Subject: [PATCH 160/197] Add api for creating/listing/viewing groups

---
 lib/api.rb          |  3 ++-
 lib/api/entities.rb | 10 +++++++++
 lib/api/groups.rb   | 50 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 62 insertions(+), 1 deletion(-)
 create mode 100644 lib/api/groups.rb

diff --git a/lib/api.rb b/lib/api.rb
index f58b82ff98e..81a5919f1d3 100644
--- a/lib/api.rb
+++ b/lib/api.rb
@@ -11,7 +11,8 @@ module Gitlab
     format :json
     error_format :json
     helpers APIHelpers
-
+    
+    mount Groups
     mount Users
     mount Projects
     mount Issues
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 5cbb1118a89..3bbbd831548 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -32,6 +32,16 @@ module Gitlab
       end
     end
 
+    class Group < Grape::Entity
+      expose :id, :name, :path, :name, :owner_id, :type
+    end
+    
+    class GroupDetail < Grape::Entity
+      expose :id, :name, :path, :name, :owner_id, :type
+      expose :projects, using: Entities::Project
+    end
+
+    
     class RepoObject < Grape::Entity
       expose :name, :commit
       expose :protected do |repo, options|
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
new file mode 100644
index 00000000000..bc856eccdab
--- /dev/null
+++ b/lib/api/groups.rb
@@ -0,0 +1,50 @@
+module Gitlab
+  # groups API
+  class Groups < Grape::API
+    before { authenticate! }
+   
+       resource :groups do
+         # Get a groups list
+         #
+         # Example Request:
+         #  GET /groups
+         get do
+           @groups = paginate Group
+           present @groups, with: Entities::Group
+
+         end
+         
+         # Create group. Available only for admin
+         #
+         # Parameters:
+         #   name (required)                   - Name
+         #   path (required)                   - Path
+         # Example Request:
+         #   POST /groups
+         post do
+           authenticated_as_admin!
+           attrs = attributes_for_keys [:name, :path]
+           @group = Group.new(attrs)
+           @group.owner = current_user
+           
+           if @group.save
+             present @group, with: Entities::Group
+           else
+             not_found!
+           end
+         end
+         
+         # Get a single group, with containing projects
+         #
+         # Parameters:
+         #   id (required) - The ID of a group
+         # Example Request:
+         #   GET /groups/:id
+         get ":id" do
+           @group = Group.find(params[:id])
+           present @group, with: Entities::GroupDetail
+         end
+         
+       end
+  end
+end
-- 
GitLab


From d53befb0d165df1f9b51c4cc1e19b6b4bcdf821d Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Fri, 1 Feb 2013 15:37:21 +0200
Subject: [PATCH 161/197] Fix mailer tests

---
 spec/mailers/notify_spec.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index d947f0e2882..befc10594db 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -266,7 +266,7 @@ describe Notify do
 
         before(:each) { note.stub(:noteable).and_return(commit) }
 
-        subject { Notify.note_commit_email(recipient.email, note.id) }
+        subject { Notify.note_commit_email(recipient.id, note.id) }
 
         it_behaves_like 'a note email'
 
-- 
GitLab


From fc0c69287069af9a47176abb1488f653f91eebdb Mon Sep 17 00:00:00 2001
From: Christian Simon <cs@f03.eu>
Date: Fri, 1 Feb 2013 14:59:22 +0100
Subject: [PATCH 162/197] Add docs/tests for groups api

---
 doc/api/README.md                |  1 +
 doc/api/groups.md                | 45 ++++++++++++++++
 spec/requests/api/groups_spec.rb | 88 ++++++++++++++++++++++++++++++++
 3 files changed, 134 insertions(+)
 create mode 100644 doc/api/groups.md
 create mode 100644 spec/requests/api/groups_spec.rb

diff --git a/doc/api/README.md b/doc/api/README.md
index 65eec6bec3c..0618db7e369 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -32,6 +32,7 @@ When listing resources you can pass the following parameters:
 + [Users](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/users.md)
 + [Session](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/session.md)
 + [Projects](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/projects.md)
++ [Groups](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/groups.md)
 + [Snippets](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/snippets.md)
 + [Repositories](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/repositories.md)
 + [Issues](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/issues.md)
diff --git a/doc/api/groups.md b/doc/api/groups.md
new file mode 100644
index 00000000000..00a7387c76f
--- /dev/null
+++ b/doc/api/groups.md
@@ -0,0 +1,45 @@
+## List project groups
+
+Get a list of groups. (As user: my groups, as admin: all groups)
+
+```
+GET /groups
+```
+
+```json
+[
+    {
+        "id": 1,
+        "name": "Foobar Group",
+        "path": "foo-bar",
+        "owner_id": 18
+    }
+]
+```
+
+## Details of group
+
+Get all details of a group.
+
+```
+GET /groups/:id
+```
+
+Parameters:
+
++ `id` (required) - The ID of a group
+
+## New group
+
+Create a new project group. Available only for admin
+
+```
+POST /groups
+```
+
+Parameters:
++ `name` (required)                  - Email
++ `path`                             - Password
+
+Will return created group with status `201 Created` on success, or `404 Not found` on fail.
+
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
new file mode 100644
index 00000000000..c9980db9ad6
--- /dev/null
+++ b/spec/requests/api/groups_spec.rb
@@ -0,0 +1,88 @@
+require 'spec_helper'
+
+describe Gitlab::API do
+  include ApiHelpers
+
+  let(:user1)  { create(:user) }
+  let(:user2)  { create(:user) }
+  let(:admin) { create(:admin) }
+  let!(:group1)  { create(:group, owner: user1) }
+  let!(:group2)  { create(:group, owner: user2) }
+
+  describe "GET /groups" do
+    context "when unauthenticated" do
+      it "should return authentication error" do
+        get api("/groups")
+        response.status.should == 401
+      end
+    end
+
+    context "when authenticated as user" do
+      it "normal user: should return an array of groups of user1" do
+        get api("/groups", user1)
+        response.status.should == 200
+        json_response.should be_an Array
+        json_response.length.should == 1
+        json_response.first['name'].should == group1.name
+      end
+    end
+    
+    context "when authenticated as  admin" do
+      it "admin: should return an array of all groups" do
+        get api("/groups", admin)
+        response.status.should == 200
+        json_response.should be_an Array
+        json_response.length.should == 2
+      end
+    end
+  end
+  
+  describe "GET /groups/:id" do
+    context "when authenticated as user" do
+      it "should return one of user1's groups" do
+        get api("/groups/#{group1.id}", user1)
+        response.status.should == 200
+        json_response['name'] == group1.name
+      end
+      
+      it "should not return a non existing group" do
+        get api("/groups/1328", user1)
+        response.status.should == 404
+      end
+      
+      it "should not return a group not attached to user1" do
+        get api("/groups/#{group2.id}", user1)
+        response.status.should == 404
+      end
+    end
+    
+    context "when authenticated as admin" do
+      it "should return any existing group" do
+        get api("/groups/#{group2.id}", admin)
+        response.status.should == 200
+        json_response['name'] == group2.name
+      end
+      
+      it "should not return a non existing group" do
+        get api("/groups/1328", admin)
+        response.status.should == 404
+      end
+    end
+  end
+  
+  describe "POST /groups" do
+    context "when authenticated as user" do
+      it "should not create group" do
+        post api("/groups", user1), attributes_for(:group)
+        response.status.should == 403
+      end
+    end
+    
+    context "when authenticated as admin" do
+      it "should create group" do
+        post api("/groups", admin), attributes_for(:group)
+        response.status.should == 201
+      end
+    end
+  end
+end
-- 
GitLab


From 149ccd5d91abf0c4b7ec610c03ad46a8ad17eec2 Mon Sep 17 00:00:00 2001
From: Christian Simon <cs@f03.eu>
Date: Fri, 1 Feb 2013 15:00:12 +0100
Subject: [PATCH 163/197] Fix groups api: differ between users and admin

---
 lib/api/entities.rb |  2 +-
 lib/api/groups.rb   | 92 ++++++++++++++++++++++++---------------------
 2 files changed, 50 insertions(+), 44 deletions(-)

diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 3bbbd831548..b78fc1b86fe 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -33,7 +33,7 @@ module Gitlab
     end
 
     class Group < Grape::Entity
-      expose :id, :name, :path, :name, :owner_id, :type
+      expose :id, :name, :path, :owner_id
     end
     
     class GroupDetail < Grape::Entity
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index bc856eccdab..a67caef0bc5 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -2,49 +2,55 @@ module Gitlab
   # groups API
   class Groups < Grape::API
     before { authenticate! }
-   
-       resource :groups do
-         # Get a groups list
-         #
-         # Example Request:
-         #  GET /groups
-         get do
-           @groups = paginate Group
-           present @groups, with: Entities::Group
 
-         end
-         
-         # Create group. Available only for admin
-         #
-         # Parameters:
-         #   name (required)                   - Name
-         #   path (required)                   - Path
-         # Example Request:
-         #   POST /groups
-         post do
-           authenticated_as_admin!
-           attrs = attributes_for_keys [:name, :path]
-           @group = Group.new(attrs)
-           @group.owner = current_user
-           
-           if @group.save
-             present @group, with: Entities::Group
-           else
-             not_found!
-           end
-         end
-         
-         # Get a single group, with containing projects
-         #
-         # Parameters:
-         #   id (required) - The ID of a group
-         # Example Request:
-         #   GET /groups/:id
-         get ":id" do
-           @group = Group.find(params[:id])
-           present @group, with: Entities::GroupDetail
-         end
-         
-       end
+    resource :groups do
+      # Get a groups list
+      #
+      # Example Request:
+      #  GET /groups
+      get do
+        if current_user.admin
+          @groups = paginate Group
+        else
+          @groups = paginate current_user.groups
+        end
+        present @groups, with: Entities::Group
+      end
+
+      # Create group. Available only for admin
+      #
+      # Parameters:
+      #   name (required)                   - Name
+      #   path (required)                   - Path
+      # Example Request:
+      #   POST /groups
+      post do
+        authenticated_as_admin!
+        attrs = attributes_for_keys [:name, :path]
+        @group = Group.new(attrs)
+        @group.owner = current_user
+
+        if @group.save
+          present @group, with: Entities::Group
+        else
+          not_found!
+        end
+      end
+
+      # Get a single group, with containing projects
+      #
+      # Parameters:
+      #   id (required) - The ID of a group
+      # Example Request:
+      #   GET /groups/:id
+      get ":id" do
+        @group = Group.find(params[:id])
+        if current_user.admin or current_user.groups.include? @group
+          present @group, with: Entities::GroupDetail
+        else
+          not_found!
+        end
+      end
+    end
   end
 end
-- 
GitLab


From 591e094e0636c084f218d52f25c01d51f7d3ecf5 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Fri, 1 Feb 2013 17:04:41 +0200
Subject: [PATCH 164/197] Add a delay for sending emails

---
 app/mailers/notify.rb | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb
index c672940a05e..08f7e01aab1 100644
--- a/app/mailers/notify.rb
+++ b/app/mailers/notify.rb
@@ -10,6 +10,10 @@ class Notify < ActionMailer::Base
 
   default from: Gitlab.config.gitlab.email_from
 
+  # Just send email with 3 seconds delay
+  def self.delay
+    delay_for(2.seconds)
+  end
 
 
   #
-- 
GitLab


From e6002bdaffc819ea3b743955315cf50eb804dbdb Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Fri, 1 Feb 2013 19:04:11 +0200
Subject: [PATCH 165/197] Ability to manage and remove group as owner outside
 of admin area

---
 app/controllers/groups_controller.rb | 36 +++++++++++++++++++-
 app/views/groups/edit.html.haml      | 50 ++++++++++++++++++++++++++++
 app/views/layouts/group.html.haml    |  6 ++++
 app/views/projects/_form.html.haml   |  2 +-
 app/views/teams/edit.html.haml       |  8 ++---
 config/routes.rb                     |  2 +-
 features/group/group.feature         |  6 ++++
 features/steps/group/group.rb        | 11 ++++++
 features/steps/shared/paths.rb       |  4 +++
 9 files changed, 117 insertions(+), 8 deletions(-)
 create mode 100644 app/views/groups/edit.html.haml

diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 72df170f1fd..7b8649a6bdf 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -6,6 +6,7 @@ class GroupsController < ApplicationController
 
   # Authorize
   before_filter :authorize_read_group!, except: [:new, :create]
+  before_filter :authorize_admin_group!, only: [:edit, :update, :destroy]
   before_filter :authorize_create_group!, only: [:new, :create]
 
   # Load group projects
@@ -84,6 +85,31 @@ class GroupsController < ApplicationController
     redirect_to people_group_path(@group), notice: 'Users was successfully added.'
   end
 
+  def edit
+  end
+
+  def update
+    group_params = params[:group].dup
+    owner_id =group_params.delete(:owner_id)
+
+    if owner_id
+      @group.owner = User.find(owner_id)
+    end
+
+    if @group.update_attributes(group_params)
+      redirect_to @group, notice: 'Group was successfully updated.'
+    else
+      render action: "edit"
+    end
+  end
+
+  def destroy
+    @group.truncate_teams
+    @group.destroy
+
+    redirect_to root_path, notice: 'Group was removed.'
+  end
+
   protected
 
   def group
@@ -106,6 +132,14 @@ class GroupsController < ApplicationController
   end
 
   def authorize_create_group!
-    can?(current_user, :create_group, nil)
+    unless can?(current_user, :create_group, nil)
+      return render_404
+    end
+  end
+
+  def authorize_admin_group!
+    unless can?(current_user, :manage_group, group)
+      return render_404
+    end
   end
 end
diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml
new file mode 100644
index 00000000000..7202ef26c70
--- /dev/null
+++ b/app/views/groups/edit.html.haml
@@ -0,0 +1,50 @@
+%h3.page_title Edit Group
+%hr
+= form_for @group do |f|
+  - if @group.errors.any?
+    .alert.alert-error
+      %span= @group.errors.full_messages.first
+  .clearfix
+    = f.label :name do
+      Group name is
+    .input
+      = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
+      &nbsp;
+      = f.submit 'Save group', class: "btn btn-save"
+%hr
+
+
+.row
+  .span7
+    .ui-box
+      %h5.title Projects
+      %ul.well-list
+        - @group.projects.each do |project|
+          %li
+            - if project.public
+              %i.icon-share
+            - else
+              %i.icon-lock.cgreen
+            = link_to project.name_with_namespace, project
+            .pull-right
+              = link_to 'Team', project_team_index_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small"
+              = link_to 'Edit', edit_project_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small"
+              = link_to 'Remove', project, confirm: "REMOVE #{project.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove"
+
+  .span5
+    .ui-box
+      %h5.title Transfer group
+      .padded
+        %p
+          Transferring group will cause loss of admin control over group and all child projects
+        = form_for @group do |f|
+          = f.select :owner_id, User.all.map { |user| [user.name, user.id] }, {}, {class: 'chosen'}
+          = f.submit 'Transfer group', class: "btn btn-small"
+    .ui-box
+      %h5.title Remove group
+      .padded.bgred
+        %p
+          Remove of group will cause removing all child projects and resources
+          %br
+          Removed group can not be restored!
+        = link_to 'Remove Group', @group, confirm: 'Removed group can not be restored! Are you sure?', method: :delete, class: "btn btn-remove btn-small"
diff --git a/app/views/layouts/group.html.haml b/app/views/layouts/group.html.haml
index 4395e408649..9057ad50ce6 100644
--- a/app/views/layouts/group.html.haml
+++ b/app/views/layouts/group.html.haml
@@ -22,4 +22,10 @@
         = nav_link(path: 'groups#people') do
           = link_to "People", people_group_path(@group)
 
+        - if can?(current_user, :manage_group, @group)
+          = nav_link(path: 'groups#edit') do
+            = link_to edit_group_path(@group), class: "tab " do
+              %i.icon-edit
+              Edit Group
+
       .content= yield
diff --git a/app/views/projects/_form.html.haml b/app/views/projects/_form.html.haml
index 8d3b1aded5c..0336654dc69 100644
--- a/app/views/projects/_form.html.haml
+++ b/app/views/projects/_form.html.haml
@@ -42,7 +42,7 @@
         = f.check_box :wiki_enabled
         %span.descr Pages for project documentation
 
-  - if can? current_user, :change_public_mode, @project
+  - if can?(current_user, :change_public_mode, @project)
     %fieldset.features
       %legend
         %i.icon-share
diff --git a/app/views/teams/edit.html.haml b/app/views/teams/edit.html.haml
index a3b1c734414..e0962f2b05b 100644
--- a/app/views/teams/edit.html.haml
+++ b/app/views/teams/edit.html.haml
@@ -15,8 +15,6 @@
       Team path is
     .input
       = f.text_field :path, placeholder: "opensource", class: "xxlarge left"
-  .clearfix
-    .input.span3.center
-      = f.submit 'Save team changes', class: "btn btn-primary"
-    .input.span3.center
-      = link_to 'Delete team', team_path(@team), method: :delete, confirm: "You are shure?", class: "btn btn-remove"
+  .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/config/routes.rb b/config/routes.rb
index 1abd37fe45f..d6432b86007 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -129,7 +129,7 @@ Gitlab::Application.routes.draw do
   #
   # Groups Area
   #
-  resources :groups, constraints: { id: /[^\/]+/ }, only: [:show, :new, :create] do
+  resources :groups, constraints: { id: /[^\/]+/ }  do
     member do
       get :issues
       get :merge_requests
diff --git a/features/group/group.feature b/features/group/group.feature
index a4a55a7fc26..a48affe8e02 100644
--- a/features/group/group.feature
+++ b/features/group/group.feature
@@ -24,3 +24,9 @@ Feature: Groups
     When I visit group people page
     And I select user "John" from list with role "Reporter"
     Then I should see user "John" in team list
+
+  Scenario: I should see edit group page
+    When I visit group settings page
+    And I change group name
+    Then I should see new group name
+
diff --git a/features/steps/group/group.rb b/features/steps/group/group.rb
index c6c6b4b5e5b..5cfa4756ac3 100644
--- a/features/steps/group/group.rb
+++ b/features/steps/group/group.rb
@@ -82,6 +82,17 @@ class Groups < Spinach::FeatureSteps
     current_path.should == group_path(Group.last)
   end
 
+  And 'I change group name' do
+    fill_in 'group_name', :with => 'new-name'
+    click_button "Save group"
+  end
+
+  Then 'I should see new group name' do
+    within ".navbar-gitlab" do
+      page.should have_content "group: new-name"
+    end
+  end
+
   protected
 
   def current_group
diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb
index 97adfd13f30..a8e68012d05 100644
--- a/features/steps/shared/paths.rb
+++ b/features/steps/shared/paths.rb
@@ -25,6 +25,10 @@ module SharedPaths
     visit people_group_path(current_group)
   end
 
+  When 'I visit group settings page' do
+    visit edit_group_path(current_group)
+  end
+
   # ----------------------------------------
   # Dashboard
   # ----------------------------------------
-- 
GitLab


From 0965aeb2ea3a7f89b0a74b746ec9aee063b0713c Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Fri, 1 Feb 2013 19:07:54 +0200
Subject: [PATCH 166/197] Fix crash on team update

---
 app/views/teams/edit.html.haml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/views/teams/edit.html.haml b/app/views/teams/edit.html.haml
index e0962f2b05b..3435583600d 100644
--- a/app/views/teams/edit.html.haml
+++ b/app/views/teams/edit.html.haml
@@ -1,6 +1,6 @@
 %h3.page_title= "Edit Team #{@team.name}"
 %hr
-= form_for @team, url: teams_path do |f|
+= form_for @team, url: team_path(@team) do |f|
   - if @team.errors.any?
     .alert.alert-error
       %span= @team.errors.full_messages.first
-- 
GitLab


From 6dba727cb282ee19b5e4c6b0d0e3ec3bff01ac63 Mon Sep 17 00:00:00 2001
From: Christian Simon <cs@f03.eu>
Date: Fri, 1 Feb 2013 18:58:53 +0100
Subject: [PATCH 167/197] Add test for duplicate group paths

---
 spec/requests/api/groups_spec.rb | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index c9980db9ad6..c39a4228408 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -83,6 +83,11 @@ describe Gitlab::API do
         post api("/groups", admin), attributes_for(:group)
         response.status.should == 201
       end
+
+      it "should not create group, duplicate" do
+        post api("/groups", admin), {:name => "Duplicate Test", :path => group2.path}
+        response.status.should == 404
+      end
     end
   end
 end
-- 
GitLab


From 42dd006dfc39fc637027a6c2c8c659febde24ad6 Mon Sep 17 00:00:00 2001
From: Riyad Preukschas <riyad@informatik.uni-bremen.de>
Date: Fri, 1 Feb 2013 21:06:15 +0100
Subject: [PATCH 168/197] Small fixes to the installation guide and check task

---
 doc/install/installation.md | 2 +-
 lib/tasks/gitlab/check.rake | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/doc/install/installation.md b/doc/install/installation.md
index 1672b77afff..11fbedffe97 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -147,7 +147,7 @@ Fix the directory permissions for the repositories:
     # Make sure the repositories dir is owned by git and it stays that way
     sudo chmod -R ug+rwX,o-rwx /home/git/repositories/
     sudo chown -R git:git /home/git/repositories/
-    find /home/git/repositories -type d -print0 | sudo xargs -0 chmod g+s 
+    find /home/git/repositories -type d -print0 | sudo xargs -0 chmod g+s
 
 
 ## Add domains to list to the list of known hosts
diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake
index 5e25d1b5d4b..27e94fca922 100644
--- a/lib/tasks/gitlab/check.rake
+++ b/lib/tasks/gitlab/check.rake
@@ -730,7 +730,7 @@ namespace :gitlab do
         puts "no".red
         try_fixing_it(
           "sudo chmod -R ug+rwX,o-rwx #{repo_base_path}",
-          "sudo chmod -R u-s #{repo_base_path}",
+          "sudo chmod -R ug-s #{repo_base_path}",
           "find #{repo_base_path} -type d -print0 | sudo xargs -0 chmod g+s"
         )
         for_more_information(
-- 
GitLab


From fac503877dbd3541009a30c8b9353d6eef85b059 Mon Sep 17 00:00:00 2001
From: Riyad Preukschas <riyad@informatik.uni-bremen.de>
Date: Fri, 1 Feb 2013 21:18:09 +0100
Subject: [PATCH 169/197] Port changes from #2803

---
 lib/tasks/gitlab/check.rake | 85 ++++++++++++++++++++-----------------
 1 file changed, 47 insertions(+), 38 deletions(-)

diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake
index 27e94fca922..b54e63acfbc 100644
--- a/lib/tasks/gitlab/check.rake
+++ b/lib/tasks/gitlab/check.rake
@@ -782,21 +782,25 @@ namespace :gitlab do
       Project.find_each(batch_size: 100) do |project|
         print "#{project.name_with_namespace.yellow} ... "
 
-        correct_options = options.map do |name, value|
-          run("git --git-dir=\"#{project.repository.path_to_repo}\" config --get #{name}").try(:chomp) == value
-        end
-
-        if correct_options.all?
-          puts "ok".green
+        if project.empty_repo?
+          puts "repository is empty".magenta
         else
-          puts "wrong or missing".red
-          try_fixing_it(
-            sudo_gitlab("bundle exec rake gitlab:gitolite:update_repos RAILS_ENV=production")
-          )
-          for_more_information(
-            "doc/raketasks/maintenance.md"
-          )
-          fix_and_rerun
+          correct_options = options.map do |name, value|
+            run("git --git-dir=\"#{project.repository.path_to_repo}\" config --get #{name}").try(:chomp) == value
+          end
+
+          if correct_options.all?
+            puts "ok".green
+          else
+            puts "wrong or missing".red
+            try_fixing_it(
+              sudo_gitlab("bundle exec rake gitlab:gitolite:update_repos RAILS_ENV=production")
+            )
+            for_more_information(
+              "doc/raketasks/maintenance.md"
+            )
+            fix_and_rerun
+          end
         end
       end
     end
@@ -822,32 +826,37 @@ namespace :gitlab do
 
       Project.find_each(batch_size: 100) do |project|
         print "#{project.name_with_namespace.yellow} ... "
-        project_hook_file = File.join(project.repository.path_to_repo, "hooks", hook_file)
 
-        unless File.exists?(project_hook_file)
-          puts "missing".red
-          try_fixing_it(
-            "sudo -u #{gitolite_ssh_user} ln -sf #{gitolite_hook_file} #{project_hook_file}"
-          )
-          for_more_information(
-            "lib/support/rewrite-hooks.sh"
-          )
-          fix_and_rerun
-          next
-        end
-
-        if File.lstat(project_hook_file).symlink? &&
-            File.realpath(project_hook_file) == File.realpath(gitolite_hook_file)
-          puts "ok".green
+        if project.empty_repo?
+          puts "repository is empty".magenta
         else
-          puts "not a link to Gitolite's hook".red
-          try_fixing_it(
-            "sudo -u #{gitolite_ssh_user} ln -sf #{gitolite_hook_file} #{project_hook_file}"
-          )
-          for_more_information(
-            "lib/support/rewrite-hooks.sh"
-          )
-          fix_and_rerun
+          project_hook_file = File.join(project.repository.path_to_repo, "hooks", hook_file)
+
+          unless File.exists?(project_hook_file)
+            puts "missing".red
+            try_fixing_it(
+              "sudo -u #{gitolite_ssh_user} ln -sf #{gitolite_hook_file} #{project_hook_file}"
+            )
+            for_more_information(
+              "lib/support/rewrite-hooks.sh"
+            )
+            fix_and_rerun
+            next
+          end
+
+          if File.lstat(project_hook_file).symlink? &&
+              File.realpath(project_hook_file) == File.realpath(gitolite_hook_file)
+            puts "ok".green
+          else
+            puts "not a link to Gitolite's hook".red
+            try_fixing_it(
+              "sudo -u #{gitolite_ssh_user} ln -sf #{gitolite_hook_file} #{project_hook_file}"
+            )
+            for_more_information(
+              "lib/support/rewrite-hooks.sh"
+            )
+            fix_and_rerun
+          end
         end
       end
     end
-- 
GitLab


From 85de55a120a615f8cf51a343a89789b802d776e2 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Sat, 2 Feb 2013 20:32:13 +0200
Subject: [PATCH 170/197] Dont allow gitlab be loaded in iframe

---
 app/controllers/application_controller.rb | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 74125e3308a..ca2a5623f42 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -4,6 +4,7 @@ class ApplicationController < ActionController::Base
   before_filter :set_current_user_for_observers
   before_filter :add_abilities
   before_filter :dev_tools if Rails.env == 'development'
+  before_filter :default_headers
 
   protect_from_forgery
 
@@ -148,4 +149,8 @@ class ApplicationController < ActionController::Base
     Rack::MiniProfiler.authorize_request
   end
 
+  def default_headers
+    headers['X-Frame-Options'] = 'DENY'
+    headers['X-XSS-Protection'] = '1; mode=block'
+  end
 end
-- 
GitLab


From 33c48ecd35f4a2d5b2596882e36e722f700aff2f Mon Sep 17 00:00:00 2001
From: Christian Simon <cs@f03.eu>
Date: Sun, 3 Feb 2013 19:38:33 +0100
Subject: [PATCH 171/197] Code deduplication using inheritance for GroupDetail

---
 lib/api/entities.rb | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index b78fc1b86fe..c1873d87b55 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -36,8 +36,7 @@ module Gitlab
       expose :id, :name, :path, :owner_id
     end
     
-    class GroupDetail < Grape::Entity
-      expose :id, :name, :path, :name, :owner_id, :type
+    class GroupDetail < Group
       expose :projects, using: Entities::Project
     end
 
-- 
GitLab


From d223cddc78dd2b256bdea381ab80b0ed4b37fa74 Mon Sep 17 00:00:00 2001
From: Michael <michael@fallo.ws>
Date: Mon, 4 Feb 2013 11:36:05 +0000
Subject: [PATCH 172/197] Update step 5 "database" (Issue #2894)

Made it a bit clearer what step 5 is for to stop people skipping it. This time with a relative link.
---
 doc/install/installation.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/doc/install/installation.md b/doc/install/installation.md
index 11fbedffe97..e42176370ba 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -174,7 +174,7 @@ and make sure you have followed all of the above steps carefully.
 
 # 5. Database
 
-See `doc/install/databases.md`
+To setup the MySQL/PostgreSQL database and dependencies please see [`doc/install/databases.md`](./databases.md) .
 
 
 # 6. GitLab
-- 
GitLab


From 6b9a60904451fb192e445774768ccb53f7f8d2f8 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 4 Feb 2013 14:28:10 +0200
Subject: [PATCH 173/197] preparing for gitlab-shell

---
 Gemfile                               |   3 -
 Gemfile.lock                          |   9 -
 lib/gitlab/backend/gitolite.rb        |  65 ++-----
 lib/gitlab/backend/gitolite_config.rb | 241 --------------------------
 4 files changed, 16 insertions(+), 302 deletions(-)
 delete mode 100644 lib/gitlab/backend/gitolite_config.rb

diff --git a/Gemfile b/Gemfile
index 96b5bb6a074..23adddced75 100644
--- a/Gemfile
+++ b/Gemfile
@@ -32,9 +32,6 @@ gem 'gitlab_omniauth-ldap', '1.0.2', require: "omniauth-ldap"
 # Dump db to yml file. Mostly used to migrate from sqlite to mysql
 gem 'gitlab_yaml_db', '1.0.0', require: "yaml_db"
 
-# Gitolite client (for work with gitolite-admin repo)
-gem "gitolite", '1.1.0'
-
 # Syntax highlighter
 gem "pygments.rb",  git: "https://github.com/gitlabhq/pygments.rb.git", branch: "master"
 
diff --git a/Gemfile.lock b/Gemfile.lock
index 7bf31c95bab..d91dbf7e826 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -107,7 +107,6 @@ GEM
       coderay (>= 1.0.0)
       erubis (>= 2.7.0)
     binding_of_caller (0.6.8)
-    blankslate (3.1.2)
     bootstrap-sass (2.2.1.1)
       sass (~> 3.2)
     builder (3.0.4)
@@ -195,10 +194,6 @@ GEM
       pyu-ruby-sasl (~> 0.0.3.1)
       rubyntlm (~> 0.1.1)
     gitlab_yaml_db (1.0.0)
-    gitolite (1.1.0)
-      gratr19 (~> 0.4.4.1)
-      grit (~> 2.5.0)
-      hashery (~> 1.5.0)
     grape (0.2.2)
       activesupport
       hashie (~> 1.2)
@@ -208,7 +203,6 @@ GEM
       rack-accept
       rack-mount
       virtus
-    gratr19 (0.4.4.1)
     growl (1.0.3)
     guard (1.5.4)
       listen (>= 0.4.2)
@@ -227,8 +221,6 @@ GEM
       activesupport (>= 3.1, < 4.1)
       haml (~> 3.1)
       railties (>= 3.1, < 4.1)
-    hashery (1.5.0)
-      blankslate
     hashie (1.2.0)
     hike (1.2.1)
     http_parser.rb (0.5.3)
@@ -497,7 +489,6 @@ DEPENDENCIES
   gitlab_meta (= 4.0)
   gitlab_omniauth-ldap (= 1.0.2)
   gitlab_yaml_db (= 1.0.0)
-  gitolite (= 1.1.0)
   grack!
   grape (~> 0.2.1)
   grit!
diff --git a/lib/gitlab/backend/gitolite.rb b/lib/gitlab/backend/gitolite.rb
index cd9ac1554d6..62eb500bcd6 100644
--- a/lib/gitlab/backend/gitolite.rb
+++ b/lib/gitlab/backend/gitolite.rb
@@ -1,5 +1,3 @@
-require_relative 'gitolite_config'
-
 module Gitlab
   class Gitolite
     class AccessDenied < StandardError; end
@@ -8,52 +6,25 @@ module Gitlab
       Gitlab::GitoliteConfig.new
     end
 
-    # Update gitolite config with new key
-    #
-    # Ex.
-    #   set_key("m_gitlab_com_12343", "sha-rsa ...", [2, 3, 6])
-    #
-    def set_key(key_id, key_content, project_ids)
-      projects = Project.where(id: project_ids)
-
-      config.apply do |config|
-        config.write_key(key_id, key_content)
-        config.update_projects(projects)
-      end
-    end
-
-    # Remove ssh key from gitolite config
+    # Add new key to gitlab-shell
     #
     # Ex.
-    #   remove_key("m_gitlab_com_12343", [2, 3, 6])
+    #   add_key("randx", "sha-rsa ...")
     #
-    def remove_key(key_id, project_ids)
-      projects = Project.where(id: project_ids)
-
-      config.apply do |config|
-        config.rm_key(key_id)
-        config.update_projects(projects)
-      end
+    def add_key(username, key_content)
+      # TODO: implement
     end
 
-    # Update project config in gitolite by project id
+    # Remove ssh key from gitlab shell
     #
     # Ex.
-    #   update_repository(23)
+    #   remove_key("sha-rsa")
     #
-    def update_repository(project_id)
-      project = Project.find(project_id)
-      config.update_project!(project)
-    end
-
-    def move_repository(old_repo, project)
-      config.apply do |config|
-        config.clean_repo(old_repo)
-        config.update_project(project)
-      end
+    def remove_key(key_content)
+      # TODO: implement
     end
 
-    # Remove repository from gitolite
+    # Remove repository from file system
     #
     # name - project path with namespace
     #
@@ -61,20 +32,18 @@ module Gitlab
     #   remove_repository("gitlab/gitlab-ci")
     #
     def remove_repository(name)
-      config.destroy_project!(name)
+      # TODO: implement
     end
 
-    # Update projects configs in gitolite by project ids
+    # Init new repository
+    #
+    # name - project path with namespace
     #
     # Ex.
-    #   update_repositories([1, 4, 6])
+    #   add_repository("gitlab/gitlab-ci")
     #
-    def update_repositories(project_ids)
-      projects = Project.where(id: project_ids)
-
-      config.apply do |config|
-        config.update_projects(projects)
-      end
+    def add_repository(name)
+      # TODO: implement
     end
 
     def url_to_repo path
@@ -84,7 +53,5 @@ module Gitlab
     def enable_automerge
       config.admin_all_repo!
     end
-
-    alias_method :create_repository, :update_repository
   end
 end
diff --git a/lib/gitlab/backend/gitolite_config.rb b/lib/gitlab/backend/gitolite_config.rb
deleted file mode 100644
index 748f9d74390..00000000000
--- a/lib/gitlab/backend/gitolite_config.rb
+++ /dev/null
@@ -1,241 +0,0 @@
-require 'gitolite'
-require 'timeout'
-require 'fileutils'
-
-module Gitlab
-  class GitoliteConfig
-    include Gitlab::Popen
-
-    class PullError < StandardError; end
-    class PushError < StandardError; end
-    class BrokenGitolite < StandardError; end
-
-    attr_reader :config_tmp_dir, :tmp_dir, :ga_repo, :conf
-
-    def initialize
-      @tmp_dir = Rails.root.join("tmp").to_s
-      @config_tmp_dir = File.join(@tmp_dir,"gitlabhq-gitolite-#{Time.now.to_i}")
-    end
-
-    def ga_repo
-      @ga_repo ||= ::Gitolite::GitoliteAdmin.new(
-        File.join(config_tmp_dir,'gitolite'),
-        conf: Gitlab.config.gitolite.config_file
-      )
-    end
-
-    def apply
-      Timeout::timeout(30) do
-        File.open(File.join(tmp_dir, "gitlabhq-gitolite.lock"), "w+") do |f|
-          begin
-            # Set exclusive lock
-            # to prevent race condition
-            f.flock(File::LOCK_EX)
-
-            # Pull gitolite-admin repo
-            # in tmp dir before do any changes
-            pull
-
-            # Build ga_repo object and @conf
-            # to access gitolite-admin configuration
-            @conf = ga_repo.config
-
-            # Do any changes
-            # in gitolite-admin
-            # config here
-            yield(self)
-
-            # Save changes in
-            # gitolite-admin repo
-            # before push it
-            ga_repo.save
-
-            # Push gitolite-admin repo
-            # to apply all changes
-            push
-          ensure
-            # Remove tmp dir
-            # removing the gitolite folder first is important to avoid
-            # NFS issues.
-            FileUtils.rm_rf(File.join(config_tmp_dir, 'gitolite'))
-
-            # Remove parent tmp dir
-            FileUtils.rm_rf(config_tmp_dir)
-
-            # Unlock so other task can access
-            # gitolite configuration
-            f.flock(File::LOCK_UN)
-          end
-        end
-      end
-    rescue PullError => ex
-      log("Pull error ->  " + ex.message)
-      raise Gitolite::AccessDenied, ex.message
-
-    rescue PushError => ex
-      log("Push error ->  " + " " + ex.message)
-      raise Gitolite::AccessDenied, ex.message
-
-    rescue BrokenGitolite => ex
-      log("Gitolite error ->  " + " " + ex.message)
-      raise Gitolite::AccessDenied, ex.message
-
-    rescue Exception => ex
-      log(ex.class.name + " " + ex.message)
-      raise Gitolite::AccessDenied.new("gitolite timeout")
-    end
-
-    def log message
-      Gitlab::GitLogger.error(message)
-    end
-
-    def path_to_repo(name)
-      File.join(Gitlab.config.gitolite.repos_path, "#{name}.git")
-    end
-
-    def destroy_project(name)
-      full_path = path_to_repo(name)
-      FileUtils.rm_rf(full_path) if File.exists?(full_path)
-      conf.rm_repo(name)
-    end
-
-    def clean_repo repo_name
-      conf.rm_repo(repo_name)
-    end
-
-    def destroy_project!(project)
-      apply do |config|
-        config.destroy_project(project)
-      end
-    end
-
-    def write_key(id, key)
-      File.open(File.join(config_tmp_dir, 'gitolite/keydir',"#{id}.pub"), 'w') do |f|
-        f.write(key.gsub(/\n/,''))
-      end
-    end
-
-    def rm_key(user)
-      key_path = File.join(config_tmp_dir, 'gitolite/keydir', "#{user}.pub")
-      ga_key = ::Gitolite::SSHKey.from_file(key_path)
-      ga_repo.rm_key(ga_key)
-    end
-
-    # update or create
-    def update_project(project)
-      repo = update_project_config(project, conf)
-      conf.add_repo(repo, true)
-    end
-
-    def update_project!( project)
-      apply do |config|
-        config.update_project(project)
-      end
-    end
-
-    # Updates many projects and uses project.path_with_namespace as the repo path
-    # An order of magnitude faster than update_project
-    def update_projects(projects)
-      projects.each do |project|
-        repo = update_project_config(project, conf)
-        conf.add_repo(repo, true)
-      end
-    end
-
-    def update_project_config(project, conf)
-      repo_name = project.path_with_namespace
-
-      repo = if conf.has_repo?(repo_name)
-               conf.get_repo(repo_name)
-             else
-               ::Gitolite::Config::Repo.new(repo_name)
-             end
-
-      name_readers = project.team.repository_readers
-      name_writers = project.team.repository_writers
-      name_masters = project.team.repository_masters
-
-      pr_br = project.protected_branches.map(&:name).join("$ ")
-
-      repo.clean_permissions
-
-      # Deny access to protected branches for writers
-      unless name_writers.blank? || pr_br.blank?
-        repo.add_permission("-", pr_br.strip + "$ ", name_writers)
-      end
-
-      # Add read permissions
-      repo.add_permission("R", "", name_readers) unless name_readers.blank?
-
-      # Add write permissions
-      repo.add_permission("RW+", "", name_writers) unless name_writers.blank?
-      repo.add_permission("RW+", "", name_masters) unless name_masters.blank?
-
-      # Add sharedRepository config
-      repo.set_git_config("core.sharedRepository", "0660")
-
-      repo
-    end
-
-    # Enable access to all repos for gitolite admin.
-    # We use it for accept merge request feature
-    def admin_all_repo
-      owner_name = Gitlab.config.gitolite.admin_key
-
-      # @ALL repos premission for gitolite owner
-      repo_name = "@all"
-      repo = if conf.has_repo?(repo_name)
-               conf.get_repo(repo_name)
-             else
-               ::Gitolite::Config::Repo.new(repo_name)
-             end
-
-      repo.add_permission("RW+", "", owner_name)
-      conf.add_repo(repo, true)
-    end
-
-    def admin_all_repo!
-      apply { |config| config.admin_all_repo }
-    end
-
-    private
-
-    def pull
-      # Create config tmp dir like "RAILS_ROOT/tmp/gitlabhq-gitolite-132545"
-      Dir.mkdir config_tmp_dir
-
-      # Clone gitolite-admin repo into tmp dir
-      popen("git clone #{Gitlab.config.gitolite.admin_uri} #{config_tmp_dir}/gitolite", tmp_dir)
-
-      # Ensure file with config presents after cloning
-      unless File.exists?(File.join(config_tmp_dir, 'gitolite', 'conf', 'gitolite.conf'))
-        raise PullError, "unable to clone gitolite-admin repo"
-      end
-    end
-
-    def push
-      output, status = popen('git add -A', tmp_conf_path)
-      raise "Git add failed." unless status.zero?
-
-      # git commit returns 0 on success, and 1 if there is nothing to commit
-      output, status = popen('git commit -m "GitLab"', tmp_conf_path)
-      raise "Git add failed." unless [0,1].include?(status)
-
-      output, status = popen('git push', tmp_conf_path)
-
-      if output =~ /remote\: FATAL/
-        raise BrokenGitolite, output
-      end
-
-      if status.zero? || output =~ /Everything up\-to\-date/
-        return true
-      else
-        raise PushError, "unable to push gitolite-admin repo"
-      end
-    end
-
-    def tmp_conf_path
-      File.join(config_tmp_dir,'gitolite')
-    end
-  end
-end
-- 
GitLab


From 27d9ac0fe8a33f0e94178c1f46826bc114e16467 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 4 Feb 2013 15:07:56 +0200
Subject: [PATCH 174/197] Make gitlab works with gitlab-shell

---
 app/controllers/application_controller.rb    |  5 ---
 app/models/key.rb                            |  4 ++
 app/models/project.rb                        | 14 ------
 app/models/users_project.rb                  |  7 ---
 app/observers/key_observer.rb                | 12 ++---
 app/observers/project_observer.rb            | 16 ++++---
 config/initializers/5_backend.rb             |  4 +-
 lib/gitlab/backend/{gitolite.rb => shell.rb} | 47 +++++++++-----------
 lib/gitolited.rb                             |  2 +-
 9 files changed, 42 insertions(+), 69 deletions(-)
 rename lib/gitlab/backend/{gitolite.rb => shell.rb} (69%)

diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index ca2a5623f42..1f211bac9c2 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -10,11 +10,6 @@ class ApplicationController < ActionController::Base
 
   helper_method :abilities, :can?
 
-  rescue_from Gitlab::Gitolite::AccessDenied do |exception|
-    log_exception(exception)
-    render "errors/gitolite", layout: "errors", status: 500
-  end
-
   rescue_from Encoding::CompatibilityError do |exception|
     log_exception(exception)
     render "errors/encoding", layout: "errors", status: 500
diff --git a/app/models/key.rb b/app/models/key.rb
index 2bf50f56565..f1c9e42f04f 100644
--- a/app/models/key.rb
+++ b/app/models/key.rb
@@ -80,4 +80,8 @@ class Key < ActiveRecord::Base
   def last_deploy?
     Key.where(identifier: identifier).count == 0
   end
+
+  def owner_name
+    user.username
+  end
 end
diff --git a/app/models/project.rb b/app/models/project.rb
index 6a3d7ab15d2..e774949ed12 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -459,20 +459,6 @@ class Project < ActiveRecord::Base
     namespace.try(:path) || ''
   end
 
-  def update_repository
-    GitoliteWorker.perform_async(
-      :update_repository,
-      self.id
-    )
-  end
-
-  def destroy_repository
-    GitoliteWorker.perform_async(
-      :remove_repository,
-      self.path_with_namespace
-    )
-  end
-
   def repo_exists?
     @repo_exists ||= (repository && repository.branches.present?)
   rescue
diff --git a/app/models/users_project.rb b/app/models/users_project.rb
index 94edfd9eddf..359db20000b 100644
--- a/app/models/users_project.rb
+++ b/app/models/users_project.rb
@@ -25,9 +25,6 @@ class UsersProject < ActiveRecord::Base
 
   attr_accessor :skip_git
 
-  after_save :update_repository, unless: :skip_git?
-  after_destroy :update_repository, unless: :skip_git?
-
   validates :user, presence: true
   validates :user_id, uniqueness: { scope: [:project_id], message: "already exists in project" }
   validates :project_access, inclusion: { in: [GUEST, REPORTER, DEVELOPER, MASTER] }, presence: true
@@ -136,10 +133,6 @@ class UsersProject < ActiveRecord::Base
     end
   end
 
-  def update_repository
-    project.update_repository
-  end
-
   def project_access_human
     Project.access_options.key(self.project_access)
   end
diff --git a/app/observers/key_observer.rb b/app/observers/key_observer.rb
index 44e78643d83..261e2245b97 100644
--- a/app/observers/key_observer.rb
+++ b/app/observers/key_observer.rb
@@ -3,20 +3,16 @@ class KeyObserver < ActiveRecord::Observer
 
   def after_save(key)
     GitoliteWorker.perform_async(
-      :set_key,
-      key.identifier,
-      key.key,
-      key.projects.map(&:id)
+      :add_key,
+      key.owner_name,
+      key.key
     )
   end
 
   def after_destroy(key)
-    return if key.is_deploy_key && !key.last_deploy?
-
     GitoliteWorker.perform_async(
       :remove_key,
-      key.identifier,
-      key.projects.map(&:id)
+      key.key,
     )
   end
 end
diff --git a/app/observers/project_observer.rb b/app/observers/project_observer.rb
index ccdb146140b..32004503fbf 100644
--- a/app/observers/project_observer.rb
+++ b/app/observers/project_observer.rb
@@ -1,6 +1,11 @@
 class ProjectObserver < ActiveRecord::Observer
   def after_create(project)
-    project.update_repository
+    GitoliteWorker.perform_async(
+      :add_repository,
+      project.path_with_namespace
+    )
+
+    log_info("#{project.owner.name} created a new project \"#{project.name_with_namespace}\"")
   end
 
   def after_update(project)
@@ -8,14 +13,15 @@ class ProjectObserver < ActiveRecord::Observer
   end
 
   def after_destroy(project)
-    log_info("Project \"#{project.name}\" was removed")
+    GitoliteWorker.perform_async(
+      :remove_repository,
+      self.path_with_namespace
+    )
 
     project.satellite.destroy
     project.destroy_repository
-  end
 
-  def after_create project
-    log_info("#{project.owner.name} created a new project \"#{project.name_with_namespace}\"")
+    log_info("Project \"#{project.name}\" was removed")
   end
 
   protected
diff --git a/config/initializers/5_backend.rb b/config/initializers/5_backend.rb
index 85f747ac334..73436608c93 100644
--- a/config/initializers/5_backend.rb
+++ b/config/initializers/5_backend.rb
@@ -1,5 +1,5 @@
 # GIT over HTTP
 require Rails.root.join("lib", "gitlab", "backend", "grack_auth")
 
-# GITOLITE backend
-require Rails.root.join("lib", "gitlab", "backend", "gitolite")
+# GIT over SSH
+require Rails.root.join("lib", "gitlab", "backend", "shell")
diff --git a/lib/gitlab/backend/gitolite.rb b/lib/gitlab/backend/shell.rb
similarity index 69%
rename from lib/gitlab/backend/gitolite.rb
rename to lib/gitlab/backend/shell.rb
index 62eb500bcd6..7423b106a45 100644
--- a/lib/gitlab/backend/gitolite.rb
+++ b/lib/gitlab/backend/shell.rb
@@ -1,27 +1,16 @@
 module Gitlab
-  class Gitolite
+  class Shell
     class AccessDenied < StandardError; end
 
-    def config
-      Gitlab::GitoliteConfig.new
-    end
-
-    # Add new key to gitlab-shell
-    #
-    # Ex.
-    #   add_key("randx", "sha-rsa ...")
+    # Init new repository
     #
-    def add_key(username, key_content)
-      # TODO: implement
-    end
-
-    # Remove ssh key from gitlab shell
+    # name - project path with namespace
     #
     # Ex.
-    #   remove_key("sha-rsa")
+    #   add_repository("gitlab/gitlab-ci")
     #
-    def remove_key(key_content)
-      # TODO: implement
+    def add_repository(name)
+      system("/home/git/gitlab-shell/bin/gitlab-projects add-project #{name}.git")
     end
 
     # Remove repository from file system
@@ -32,26 +21,30 @@ module Gitlab
     #   remove_repository("gitlab/gitlab-ci")
     #
     def remove_repository(name)
-      # TODO: implement
+      system("/home/git/gitlab-shell/bin/gitlab-projects rm-project #{name}.git")
     end
 
-    # Init new repository
+    # Add new key to gitlab-shell
     #
-    # name - project path with namespace
+    # Ex.
+    #   add_key("randx", "sha-rsa ...")
+    #
+    def add_key(username, key_content)
+      system("/home/git/gitlab-shell/bin/gitlab-keys add-key #{username} \"#{key_content}\"")
+    end
+
+    # Remove ssh key from gitlab shell
     #
     # Ex.
-    #   add_repository("gitlab/gitlab-ci")
+    #   remove_key("sha-rsa")
     #
-    def add_repository(name)
-      # TODO: implement
+    def remove_key(key_content)
+      system("/home/git/gitlab-shell/bin/gitlab-keys rm-key \"#{key_content}\"")
     end
 
+
     def url_to_repo path
       Gitlab.config.gitolite.ssh_path_prefix + "#{path}.git"
     end
-
-    def enable_automerge
-      config.admin_all_repo!
-    end
   end
 end
diff --git a/lib/gitolited.rb b/lib/gitolited.rb
index 68b9b625525..4911a473f05 100644
--- a/lib/gitolited.rb
+++ b/lib/gitolited.rb
@@ -6,6 +6,6 @@
 #
 module Gitolited
   def gitolite
-    Gitlab::Gitolite.new
+    Gitlab::Shell.new
   end
 end
-- 
GitLab


From 5c6492662ef730eef7a9122f53438c32724ae91d Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 4 Feb 2013 15:18:20 +0200
Subject: [PATCH 175/197] update installation docs

---
 doc/install/installation.md | 126 +++++++++++-------------------------
 1 file changed, 36 insertions(+), 90 deletions(-)

diff --git a/doc/install/installation.md b/doc/install/installation.md
index 11fbedffe97..7c0c5e6c9bb 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -90,86 +90,32 @@ Install the Bundler Gem:
 
 # 3. System Users
 
-Create a user for Git and Gitolite:
+Create a `git` user for Gitlab:
 
-    sudo adduser \
-      --system \
-      --shell /bin/sh \
-      --gecos 'Git Version Control' \
-      --group \
-      --disabled-password \
-      --home /home/git \
-      git
+    sudo adduser --disabled-login --gecos 'GitLab' git
 
-Create a user for GitLab:
+# 4. GitLab shell
 
-    sudo adduser --disabled-login --gecos 'GitLab' gitlab
-
-    # Add it to the git group
-    sudo usermod -a -G git gitlab
-
-    # Generate the SSH key
-    sudo -u gitlab -H ssh-keygen -q -N '' -t rsa -f /home/gitlab/.ssh/id_rsa
-
-
-# 4. Gitolite
-
-Clone GitLab's fork of the Gitolite source code:
+    # login as git 
+    sudo su git
 
+    # go to home directory 
     cd /home/git
-    sudo -u git -H git clone -b gl-v320 https://github.com/gitlabhq/gitolite.git /home/git/gitolite
-
-Setup Gitolite with GitLab as its admin:
-
-**Important Note:**
-GitLab assumes *full and unshared* control over this Gitolite installation.
-
-    # Add Gitolite scripts to $PATH
-    sudo -u git -H mkdir /home/git/bin
-    sudo -u git -H sh -c 'printf "%b\n%b\n" "PATH=\$PATH:/home/git/bin" "export PATH" >> /home/git/.profile'
-    sudo -u git -H sh -c 'gitolite/install -ln /home/git/bin'
-
-    # Copy the gitlab user's (public) SSH key ...
-    sudo cp /home/gitlab/.ssh/id_rsa.pub /home/git/gitlab.pub
-    sudo chmod 0444 /home/git/gitlab.pub
 
-    # ... and use it as the admin key for the Gitolite setup
-    sudo -u git -H sh -c "PATH=/home/git/bin:$PATH; gitolite setup -pk /home/git/gitlab.pub"
+    # clone gitlab shell
+    git clone https://dzaporozhets@dev.gitlab.org/gitlab/gitlab-shell.git
 
-Fix the directory permissions for the configuration directory:
-
-    # Make sure the Gitolite config dir is owned by git
-    sudo chmod 750 /home/git/.gitolite/
-    sudo chown -R git:git /home/git/.gitolite/
-
-Fix the directory permissions for the repositories:
-
-    # Make sure the repositories dir is owned by git and it stays that way
-    sudo chmod -R ug+rwX,o-rwx /home/git/repositories/
-    sudo chown -R git:git /home/git/repositories/
-    find /home/git/repositories -type d -print0 | sudo xargs -0 chmod g+s
+    # setup
+    cd gitlab-shell
+    cp config.yml.example config.yml
+    ./bin/install 
 
 
 ## Add domains to list to the list of known hosts
 
-    sudo -u gitlab -H ssh git@localhost
-    sudo -u gitlab -H ssh git@YOUR_DOMAIN_NAME
-    sudo -u gitlab -H ssh git@YOUR_GITOLITE_DOMAIN_NAME
-
-
-## Test if everything works so far
-
-    # Clone the admin repo so SSH adds localhost to known_hosts ...
-    # ... and to be sure your users have access to Gitolite
-    sudo -u gitlab -H git clone git@localhost:gitolite-admin.git /tmp/gitolite-admin
-
-    # If it succeeded without errors you can remove the cloned repo
-    sudo rm -rf /tmp/gitolite-admin
-
-**Important Note:**
-If you can't clone the `gitolite-admin` repository: **DO NOT PROCEED WITH INSTALLATION**!
-Check the [Trouble Shooting Guide](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Trouble-Shooting-Guide)
-and make sure you have followed all of the above steps carefully.
+    sudo -u git -H ssh git@localhost
+    sudo -u git -H ssh git@YOUR_DOMAIN_NAME
+    sudo -u git -H ssh git@YOUR_GITOLITE_DOMAIN_NAME
 
 
 # 5. Database
@@ -179,19 +125,19 @@ See `doc/install/databases.md`
 
 # 6. GitLab
 
-    # We'll install GitLab into home directory of the user "gitlab"
-    cd /home/gitlab
+    # We'll install GitLab into home directory of the user "git"
+    cd /home/git
 
 ## Clone the Source
 
     # Clone GitLab repository
-    sudo -u gitlab -H git clone https://github.com/gitlabhq/gitlabhq.git gitlab
+    sudo -u git -H git clone https://github.com/gitlabhq/gitlabhq.git gitlab
 
     # Go to gitlab dir 
-    cd /home/gitlab/gitlab
+    cd /home/git/gitlab
    
     # Checkout to stable release
-    sudo -u gitlab -H git checkout 4-1-stable
+    sudo -u git -H git checkout 4-1-stable
 
 **Note:**
 You can change `4-1-stable` to `master` if you want the *bleeding edge* version, but
@@ -199,14 +145,14 @@ do so with caution!
 
 ## Configure it
 
-    cd /home/gitlab/gitlab
+    cd /home/git/gitlab
 
     # Copy the example GitLab config
-    sudo -u gitlab -H cp config/gitlab.yml.example config/gitlab.yml
+    sudo -u git -H cp config/gitlab.yml.example config/gitlab.yml
 
     # Make sure to change "localhost" to the fully-qualified domain name of your
     # host serving GitLab where necessary
-    sudo -u gitlab -H vim config/gitlab.yml
+    sudo -u git -H vim config/gitlab.yml
 
     # Make sure GitLab can write to the log/ and tmp/ directories
     sudo chown -R gitlab log/
@@ -215,10 +161,10 @@ do so with caution!
     sudo chmod -R u+rwX  tmp/
 
     # Make directory for satellites
-    sudo -u gitlab -H mkdir /home/gitlab/gitlab-satellites
+    sudo -u git -H mkdir /home/git/gitlab-satellites
 
     # Copy the example Unicorn config
-    sudo -u gitlab -H cp config/unicorn.rb.example config/unicorn.rb
+    sudo -u git -H cp config/unicorn.rb.example config/unicorn.rb
 
 **Important Note:**
 Make sure to edit both files to match your setup.
@@ -226,24 +172,24 @@ Make sure to edit both files to match your setup.
 ## Configure GitLab DB settings
 
     # Mysql
-    sudo -u gitlab cp config/database.yml.mysql config/database.yml
+    sudo -u git cp config/database.yml.mysql config/database.yml
 
     # PostgreSQL
-    sudo -u gitlab cp config/database.yml.postgresql config/database.yml
+    sudo -u git cp config/database.yml.postgresql config/database.yml
 
 Make sure to update username/password in config/database.yml.
 
 ## Install Gems
 
-    cd /home/gitlab/gitlab
+    cd /home/git/gitlab
 
     sudo gem install charlock_holmes --version '0.6.9'
 
     # For MySQL (note, the option says "without")
-    sudo -u gitlab -H bundle install --deployment --without development test postgres
+    sudo -u git -H bundle install --deployment --without development test postgres
 
     # Or for PostgreSQL
-    sudo -u gitlab -H bundle install --deployment --without development test mysql
+    sudo -u git -H bundle install --deployment --without development test mysql
 
 ## Configure Git
 
@@ -251,8 +197,8 @@ GitLab needs to be able to commit and push changes to Gitolite. In order to do
 that Git requires a username and email. (We recommend using the same address
 used for the `email.from` setting in `config/gitlab.yml`)
 
-    sudo -u gitlab -H git config --global user.name "GitLab"
-    sudo -u gitlab -H git config --global user.email "gitlab@localhost"
+    sudo -u git -H git config --global user.name "GitLab"
+    sudo -u git -H git config --global user.email "gitlab@localhost"
 
 ## Setup GitLab Hooks
 
@@ -261,7 +207,7 @@ used for the `email.from` setting in `config/gitlab.yml`)
 
 ## Initialise Database and Activate Advanced Features
 
-    sudo -u gitlab -H bundle exec rake gitlab:setup RAILS_ENV=production
+    sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production
 
 
 ## Install Init Script
@@ -280,11 +226,11 @@ Make GitLab start on boot:
 
 Check if GitLab and its environment is configured correctly:
 
-    sudo -u gitlab -H bundle exec rake gitlab:env:info RAILS_ENV=production
+    sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
 
 To make sure you didn't miss anything run a more thorough check with:
 
-    sudo -u gitlab -H bundle exec rake gitlab:check RAILS_ENV=production
+    sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
 
 If all items are green, then congratulations on successfully installing GitLab!
 However there are still a few steps left.
@@ -357,7 +303,7 @@ a different host, you can configure its connection string via the
 
 If you are running SSH on a non-standard port, you must change the gitlab user'S SSH config.
     
-    # Add to /home/gitlab/.ssh/config
+    # Add to /home/git/.ssh/config
     host localhost          # Give your setup a name (here: override localhost)
         user git            # Your remote git user
         port 2222           # Your port number
-- 
GitLab


From 896c3a0a9d4c9ccdfab275d772ae5991dd92865e Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 4 Feb 2013 15:24:16 +0200
Subject: [PATCH 176/197] remove update_repository calls

---
 app/models/namespace.rb        |  6 ------
 app/models/project_team.rb     |  1 -
 app/models/protected_branch.rb |  7 -------
 app/models/users_project.rb    | 10 ----------
 4 files changed, 24 deletions(-)

diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index ad04d0ef99b..f17d8f65183 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -27,7 +27,6 @@ class Namespace < ActiveRecord::Base
 
   after_create :ensure_dir_exist
   after_update :move_dir
-  after_commit :update_gitolite, on: :update, if: :require_update_gitolite
   after_destroy :rm_dir
 
   scope :root, where('type IS NULL')
@@ -89,11 +88,6 @@ class Namespace < ActiveRecord::Base
     end
   end
 
-  def update_gitolite
-    @require_update_gitolite = false
-    projects.each(&:update_repository)
-  end
-
   def rm_dir
     dir_path = File.join(Gitlab.config.gitolite.repos_path, path)
     FileUtils.rm_r( dir_path, force: true )
diff --git a/app/models/project_team.rb b/app/models/project_team.rb
index 2cc76974987..c2cf83c0ca8 100644
--- a/app/models/project_team.rb
+++ b/app/models/project_team.rb
@@ -112,7 +112,6 @@ class ProjectTeam
       source_team.each do |tm|
         tm.save
       end
-      target_project.update_repository
     end
 
     true
diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb
index 2e7010ea9c9..57229d50759 100644
--- a/app/models/protected_branch.rb
+++ b/app/models/protected_branch.rb
@@ -18,13 +18,6 @@ class ProtectedBranch < ActiveRecord::Base
   validates :name, presence: true
   validates :project, presence: true
 
-  after_save :update_repository
-  after_destroy :update_repository
-
-  def update_repository
-    project.update_repository
-  end
-
   def commit
     project.repository.commit(self.name)
   end
diff --git a/app/models/users_project.rb b/app/models/users_project.rb
index 359db20000b..dd8ceb9da70 100644
--- a/app/models/users_project.rb
+++ b/app/models/users_project.rb
@@ -81,11 +81,6 @@ class UsersProject < ActiveRecord::Base
         end
       end
 
-      GitoliteWorker.perform_async(
-        :update_repositories,
-        project_ids
-      )
-
       true
     rescue
       false
@@ -100,11 +95,6 @@ class UsersProject < ActiveRecord::Base
         end
       end
 
-      GitoliteWorker.perform_async(
-        :update_repositories,
-        project_ids
-      )
-
       true
     rescue
       false
-- 
GitLab


From 6f7ccea6686d4cc6c6241bc4289c13ff04cc8557 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 4 Feb 2013 16:19:37 +0200
Subject: [PATCH 177/197] Fix satellites to use filesystem. Correct
 post-receive user finder

---
 app/workers/post_receive.rb       | 7 +++++--
 lib/gitlab/satellite/satellite.rb | 4 ++--
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb
index 6d31c08fefc..17ccfae21ec 100644
--- a/app/workers/post_receive.rb
+++ b/app/workers/post_receive.rb
@@ -28,10 +28,13 @@ class PostReceive
            elsif /^[A-Z0-9._%a-z\-]+@(?:[A-Z0-9a-z\-]+\.)+[A-Za-z]{2,4}$/.match(identifier)
              User.find_by_email(identifier)
            else
-             Key.find_by_identifier(identifier).try(:user)
+             User.find_by_username(identifier.strip)
            end
 
-    return false unless user
+    unless user
+      Gitlab::GitLogger.error("POST-RECEIVE: Triggered hook for non-existing user \"#{identifier} \"")
+      return false
+    end
 
     project.trigger_post_receive(oldrev, newrev, ref, user)
   end
diff --git a/lib/gitlab/satellite/satellite.rb b/lib/gitlab/satellite/satellite.rb
index 95273a6d208..e7f7a7673b5 100644
--- a/lib/gitlab/satellite/satellite.rb
+++ b/lib/gitlab/satellite/satellite.rb
@@ -30,10 +30,10 @@ module Gitlab
       end
 
       def create
-        output, status = popen("git clone #{project.url_to_repo} #{path}",
+        output, status = popen("git clone #{project.repository.path_to_repo} #{path}",
                                Gitlab.config.satellites.path)
 
-        log("PID: #{project.id}: git clone #{project.url_to_repo} #{path}")
+        log("PID: #{project.id}: git clone #{project.repository.path_to_repo} #{path}")
         log("PID: #{project.id}: -> #{output}")
 
         if status.zero?
-- 
GitLab


From 935b6ae6534e77f2b9e84bcb686aeeda88089122 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 4 Feb 2013 17:53:43 +0200
Subject: [PATCH 178/197] Internal API

---
 lib/api.rb          |  1 +
 lib/api/internal.rb | 24 ++++++++++++++++++++++++
 2 files changed, 25 insertions(+)
 create mode 100644 lib/api/internal.rb

diff --git a/lib/api.rb b/lib/api.rb
index f58b82ff98e..3ee56a7f79e 100644
--- a/lib/api.rb
+++ b/lib/api.rb
@@ -19,5 +19,6 @@ module Gitlab
     mount Session
     mount MergeRequests
     mount Notes
+    mount Internal
   end
 end
diff --git a/lib/api/internal.rb b/lib/api/internal.rb
new file mode 100644
index 00000000000..c12605841ab
--- /dev/null
+++ b/lib/api/internal.rb
@@ -0,0 +1,24 @@
+module Gitlab
+  # Access API
+  class Internal < Grape::API
+
+    get "/allowed" do
+      user = User.find_by_username(params[:username])
+      project = Project.find_with_namespace(params[:project])
+      action = case params[:action]
+               when 'git-upload-pack'
+                 then :download_code
+               when 'git-receive-pack'
+                 then
+                 if project.protected_branch?(params[:ref])
+                   :push_code_to_protected_branches
+                 else
+                   :push_code
+                 end
+               end
+
+      user.can?(action, project)
+    end
+  end
+end
+
-- 
GitLab


From c75fc9c7a692f8b7613ca8824f18e075af785c9b Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Mon, 4 Feb 2013 18:18:36 +0200
Subject: [PATCH 179/197] remove gitolite stub

---
 spec/spec_helper.rb                |  3 ---
 spec/support/gitolite_stub.rb      | 21 ---------------------
 spec/support/stubbed_repository.rb | 21 +++++++++++++++++++++
 3 files changed, 21 insertions(+), 24 deletions(-)
 delete mode 100644 spec/support/gitolite_stub.rb

diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index dbac3c54901..bb314e60eb7 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -24,7 +24,6 @@ RSpec.configure do |config|
   config.mock_with :rspec
 
   config.include LoginHelpers, type: :request
-  config.include GitoliteStub
   config.include FactoryGirl::Syntax::Methods
   config.include Devise::TestHelpers, type: :controller
 
@@ -34,8 +33,6 @@ RSpec.configure do |config|
   config.use_transactional_fixtures = false
 
   config.before do
-    stub_gitolite!
-
     # Use tmp dir for FS manipulations
     temp_repos_path = Rails.root.join('tmp', 'test-git-base-path')
     Gitlab.config.gitolite.stub(repos_path: temp_repos_path)
diff --git a/spec/support/gitolite_stub.rb b/spec/support/gitolite_stub.rb
deleted file mode 100644
index 574bb5a12a3..00000000000
--- a/spec/support/gitolite_stub.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-module GitoliteStub
-  def stub_gitolite!
-    stub_gitlab_gitolite
-    stub_gitolite_admin
-  end
-
-  def stub_gitolite_admin
-    gitolite_admin = double('Gitolite::GitoliteAdmin')
-    gitolite_admin.as_null_object
-
-    Gitolite::GitoliteAdmin.stub(new: gitolite_admin)
-  end
-
-  def stub_gitlab_gitolite
-    gitolite_config = double('Gitlab::GitoliteConfig')
-    gitolite_config.stub(apply: ->() { yield(self) })
-    gitolite_config.as_null_object
-
-    Gitlab::GitoliteConfig.stub(new: gitolite_config)
-  end
-end
diff --git a/spec/support/stubbed_repository.rb b/spec/support/stubbed_repository.rb
index e092f8a4776..fd891b1ce14 100644
--- a/spec/support/stubbed_repository.rb
+++ b/spec/support/stubbed_repository.rb
@@ -1,5 +1,6 @@
 require "repository"
 require "project"
+require "shell"
 
 # Stubs out all Git repository access done by models so that specs can run
 # against fake repositories without Grit complaining that they don't exist.
@@ -36,3 +37,23 @@ class GitLabTestRepo < Repository
     @repo ||= Grit::Repo.new(Rails.root.join('tmp', 'repositories', 'gitlabhq'))
   end
 end
+
+module Gitlab
+  class Shell
+    def add_repository name
+      true
+    end
+
+    def remove_repository name
+      true
+    end
+
+    def add_key name, key
+      true
+    end
+
+    def remove_key key
+      true
+    end
+  end
+end
-- 
GitLab


From 0d5a098c1978accd5691acc19b3c2868e8273506 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 5 Feb 2013 09:01:29 +0200
Subject: [PATCH 180/197] updated

---
 ROADMAP.md | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/ROADMAP.md b/ROADMAP.md
index acfd2eded97..d148b518b0e 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -1,13 +1,12 @@
 ## GitLab Roadmap
 
-### v4.3 March 22
+### v5.0 March 22
 
-* Jenkins CI integration service
+* Replace gitolite with gitlab-shell 
 * Usability improvements
 * Notification improvements
 
 ### v4.2 February 22
 
-* Campfire integration service
 * Teams
 
-- 
GitLab


From f385c7212ebe4a69af05335f223117b740ff9560 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 5 Feb 2013 09:14:35 +0200
Subject: [PATCH 181/197] remove unexisting stubs

---
 features/support/env.rb | 9 +--------
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/features/support/env.rb b/features/support/env.rb
index a08aa0de9f8..c19ca3088cb 100644
--- a/features/support/env.rb
+++ b/features/support/env.rb
@@ -9,17 +9,12 @@ require 'spinach/capybara'
 require 'sidekiq/testing/inline'
 
 
-%w(gitolite_stub stubbed_repository valid_commit).each do |f|
+%w(stubbed_repository valid_commit).each do |f|
   require Rails.root.join('spec', 'support', f)
 end
 
 Dir["#{Rails.root}/features/steps/shared/*.rb"].each {|file| require file}
 
-#
-# Stub gitolite
-#
-include GitoliteStub
-
 WebMock.allow_net_connect!
 #
 # JS driver
@@ -49,6 +44,4 @@ Spinach.hooks.before_run do
   RSpec::Mocks::setup self
 
   include FactoryGirl::Syntax::Methods
-
-  stub_gitolite!
 end
-- 
GitLab


From 12198bee2ff321eed6f2580e40675c4081999d4f Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 5 Feb 2013 09:17:45 +0200
Subject: [PATCH 182/197] update structure

---
 doc/install/structure.md | 24 +++++-------------------
 1 file changed, 5 insertions(+), 19 deletions(-)

diff --git a/doc/install/structure.md b/doc/install/structure.md
index a67e12cc217..f580ea159a2 100644
--- a/doc/install/structure.md
+++ b/doc/install/structure.md
@@ -3,37 +3,23 @@
 This is the directory structure you will end up with following the instructions in the Installation Guide.
 
     |-- home
-    |   |-- gitlab
+    |   |-- git
     |       |-- .ssh
     |       |-- gitlab
     |       |-- gitlab-satellites
-    |   |-- git
-    |       |-- .gitolite
-    |       |-- .ssh
-    |       |-- bin
-    |       |-- gitolite
+    |       |-- gitlab-shell
     |       |-- repositories
 
 
-**/home/gitlab/.ssh**
-  Contains the Gitolite admin key GitLab uses to configure Gitolite.
+**/home/git/.ssh**
 
-**/home/gitlab/gitlab**
+**/home/git/gitlab**
   This is where GitLab lives.
 
-**/home/gitlab/gitlab-satellites**
+**/home/git/gitlab-satellites**
   Contains a copy of all repositories with a working tree.
   It's used for merge requests, editing files, etc.
 
-**/home/git/.ssh**
-  Contains the SSH access configuration managed by Gitolite.
-
-**/home/git/bin**
-  Contains Gitolite executables.
-
-**/home/git/gitolite**
-  This is where Gitolite lives.
-
 **/home/git/repositories**
   Holds all your repositories in bare format.
   This is the place Git uses when you pull/push to your projects.
-- 
GitLab


From 081c272b85d9344ff3a0b548f8f5eabc60e9a58d Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 5 Feb 2013 10:15:49 +0200
Subject: [PATCH 183/197] Remove outdated specs and fixed key remove

---
 app/observers/key_observer.rb    |  1 +
 lib/gitlab/backend/shell.rb      |  4 ++--
 spec/lib/gitolite_config_spec.rb | 16 ----------------
 spec/lib/gitolite_spec.rb        | 10 +---------
 4 files changed, 4 insertions(+), 27 deletions(-)
 delete mode 100644 spec/lib/gitolite_config_spec.rb

diff --git a/app/observers/key_observer.rb b/app/observers/key_observer.rb
index 261e2245b97..ad371d304c3 100644
--- a/app/observers/key_observer.rb
+++ b/app/observers/key_observer.rb
@@ -12,6 +12,7 @@ class KeyObserver < ActiveRecord::Observer
   def after_destroy(key)
     GitoliteWorker.perform_async(
       :remove_key,
+      key.owner_name,
       key.key,
     )
   end
diff --git a/lib/gitlab/backend/shell.rb b/lib/gitlab/backend/shell.rb
index 7423b106a45..c596148b13c 100644
--- a/lib/gitlab/backend/shell.rb
+++ b/lib/gitlab/backend/shell.rb
@@ -38,8 +38,8 @@ module Gitlab
     # Ex.
     #   remove_key("sha-rsa")
     #
-    def remove_key(key_content)
-      system("/home/git/gitlab-shell/bin/gitlab-keys rm-key \"#{key_content}\"")
+    def remove_key(username, key_content)
+      system("/home/git/gitlab-shell/bin/gitlab-keys rm-key #{username} \"#{key_content}\"")
     end
 
 
diff --git a/spec/lib/gitolite_config_spec.rb b/spec/lib/gitolite_config_spec.rb
deleted file mode 100644
index c3ce0db569a..00000000000
--- a/spec/lib/gitolite_config_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::GitoliteConfig do
-  let(:gitolite) { Gitlab::GitoliteConfig.new }
-
-  it { should respond_to :write_key }
-  it { should respond_to :rm_key }
-  it { should respond_to :update_project }
-  it { should respond_to :update_project! }
-  it { should respond_to :update_projects }
-  it { should respond_to :destroy_project }
-  it { should respond_to :destroy_project! }
-  it { should respond_to :apply }
-  it { should respond_to :admin_all_repo }
-  it { should respond_to :admin_all_repo! }
-end
diff --git a/spec/lib/gitolite_spec.rb b/spec/lib/gitolite_spec.rb
index 7ba4a633fb1..2705298876f 100644
--- a/spec/lib/gitolite_spec.rb
+++ b/spec/lib/gitolite_spec.rb
@@ -2,25 +2,17 @@ require 'spec_helper'
 
 describe Gitlab::Gitolite do
   let(:project) { double('Project', id: 7, path: 'diaspora') }
-  let(:gitolite_config) { double('Gitlab::GitoliteConfig') }
   let(:gitolite) { Gitlab::Gitolite.new }
 
   before do
-    gitolite.stub(config: gitolite_config)
     Project.stub(find: project)
   end
 
   it { should respond_to :set_key }
   it { should respond_to :remove_key }
 
-  it { should respond_to :update_repository }
-  it { should respond_to :create_repository }
+  it { should respond_to :add_repository }
   it { should respond_to :remove_repository }
 
   it { gitolite.url_to_repo('diaspora').should == Gitlab.config.gitolite.ssh_path_prefix + "diaspora.git" }
-
-  it "should call config update" do
-    gitolite_config.should_receive(:update_project!)
-    gitolite.update_repository(project.id)
-  end
 end
-- 
GitLab


From 39e37677f291c344e25583916a1811a052e38db6 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 5 Feb 2013 11:12:15 +0200
Subject: [PATCH 184/197] add remove keys from gitlab-shell by id

---
 app/models/key.rb             |  4 ++--
 app/observers/key_observer.rb |  4 ++--
 lib/gitlab/backend/shell.rb   | 12 ++++++------
 3 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/app/models/key.rb b/app/models/key.rb
index f1c9e42f04f..0c01edcbe71 100644
--- a/app/models/key.rb
+++ b/app/models/key.rb
@@ -81,7 +81,7 @@ class Key < ActiveRecord::Base
     Key.where(identifier: identifier).count == 0
   end
 
-  def owner_name
-    user.username
+  def shell_id
+    "key-#{self.id}"
   end
 end
diff --git a/app/observers/key_observer.rb b/app/observers/key_observer.rb
index ad371d304c3..4146216d82f 100644
--- a/app/observers/key_observer.rb
+++ b/app/observers/key_observer.rb
@@ -4,7 +4,7 @@ class KeyObserver < ActiveRecord::Observer
   def after_save(key)
     GitoliteWorker.perform_async(
       :add_key,
-      key.owner_name,
+      key.shell_id,
       key.key
     )
   end
@@ -12,7 +12,7 @@ class KeyObserver < ActiveRecord::Observer
   def after_destroy(key)
     GitoliteWorker.perform_async(
       :remove_key,
-      key.owner_name,
+      key.shell_id,
       key.key,
     )
   end
diff --git a/lib/gitlab/backend/shell.rb b/lib/gitlab/backend/shell.rb
index c596148b13c..50ebfc5b07c 100644
--- a/lib/gitlab/backend/shell.rb
+++ b/lib/gitlab/backend/shell.rb
@@ -27,19 +27,19 @@ module Gitlab
     # Add new key to gitlab-shell
     #
     # Ex.
-    #   add_key("randx", "sha-rsa ...")
+    #   add_key("key-42", "sha-rsa ...")
     #
-    def add_key(username, key_content)
-      system("/home/git/gitlab-shell/bin/gitlab-keys add-key #{username} \"#{key_content}\"")
+    def add_key(key_id, key_content)
+      system("/home/git/gitlab-shell/bin/gitlab-keys add-key #{key_id} \"#{key_content}\"")
     end
 
     # Remove ssh key from gitlab shell
     #
     # Ex.
-    #   remove_key("sha-rsa")
+    #   remove_key("key-342", "sha-rsa ...")
     #
-    def remove_key(username, key_content)
-      system("/home/git/gitlab-shell/bin/gitlab-keys rm-key #{username} \"#{key_content}\"")
+    def remove_key(key_id, key_content)
+      system("/home/git/gitlab-shell/bin/gitlab-keys rm-key #{key_id} \"#{key_content}\"")
     end
 
 
-- 
GitLab


From 70e3bffd95eb5736dd108e0836abaa85a2f1c742 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 5 Feb 2013 12:47:50 +0200
Subject: [PATCH 185/197] Fixed: post-receive, project remove, tests

---
 app/observers/project_observer.rb            |  3 +-
 app/workers/post_receive.rb                  |  5 ++-
 lib/api/internal.rb                          | 44 +++++++++++++-------
 spec/lib/{gitolite_spec.rb => shell_spec.rb} |  7 ++--
 spec/models/project_spec.rb                  |  2 -
 spec/models/protected_branch_spec.rb         | 15 -------
 spec/observers/key_observer_spec.rb          |  6 +--
 spec/support/stubbed_repository.rb           |  4 +-
 spec/workers/post_receive_spec.rb            |  4 +-
 9 files changed, 43 insertions(+), 47 deletions(-)
 rename spec/lib/{gitolite_spec.rb => shell_spec.rb} (77%)

diff --git a/app/observers/project_observer.rb b/app/observers/project_observer.rb
index 32004503fbf..cc2a0224b72 100644
--- a/app/observers/project_observer.rb
+++ b/app/observers/project_observer.rb
@@ -15,11 +15,10 @@ class ProjectObserver < ActiveRecord::Observer
   def after_destroy(project)
     GitoliteWorker.perform_async(
       :remove_repository,
-      self.path_with_namespace
+      project.path_with_namespace
     )
 
     project.satellite.destroy
-    project.destroy_repository
 
     log_info("Project \"#{project.name}\" was removed")
   end
diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb
index 17ccfae21ec..6e2d0e7aba2 100644
--- a/app/workers/post_receive.rb
+++ b/app/workers/post_receive.rb
@@ -27,8 +27,9 @@ class PostReceive
              User.find_by_email(email) if email
            elsif /^[A-Z0-9._%a-z\-]+@(?:[A-Z0-9a-z\-]+\.)+[A-Za-z]{2,4}$/.match(identifier)
              User.find_by_email(identifier)
-           else
-             User.find_by_username(identifier.strip)
+           elsif identifier =~ /key/
+             key_id = identifier.gsub("key-", "")
+             Key.find_by_id(key_id).try(:user)
            end
 
     unless user
diff --git a/lib/api/internal.rb b/lib/api/internal.rb
index c12605841ab..576b64d04c3 100644
--- a/lib/api/internal.rb
+++ b/lib/api/internal.rb
@@ -1,23 +1,37 @@
 module Gitlab
-  # Access API
+  # Internal access API
   class Internal < Grape::API
+    namespace 'internal' do
+      #
+      # Check if ssh key has access to project code
+      #
+      get "/allowed" do
+        key = Key.find(params[:key_id])
+        user = key.user
 
-    get "/allowed" do
-      user = User.find_by_username(params[:username])
-      project = Project.find_with_namespace(params[:project])
-      action = case params[:action]
-               when 'git-upload-pack'
-                 then :download_code
-               when 'git-receive-pack'
-                 then
-                 if project.protected_branch?(params[:ref])
-                   :push_code_to_protected_branches
-                 else
-                   :push_code
+        project = Project.find_with_namespace(params[:project])
+        action = case params[:action]
+                 when 'git-upload-pack'
+                   then :download_code
+                 when 'git-receive-pack'
+                   then
+                   if project.protected_branch?(params[:ref])
+                     :push_code_to_protected_branches
+                   else
+                     :push_code
+                   end
                  end
-               end
 
-      user.can?(action, project)
+        user.can?(action, project)
+      end
+
+      #
+      # Discover user by ssh key
+      #
+      get "/discover" do
+        key = Key.find(params[:key_id])
+        present key.user, with: Entities::User
+      end
     end
   end
 end
diff --git a/spec/lib/gitolite_spec.rb b/spec/lib/shell_spec.rb
similarity index 77%
rename from spec/lib/gitolite_spec.rb
rename to spec/lib/shell_spec.rb
index 2705298876f..1c546e59235 100644
--- a/spec/lib/gitolite_spec.rb
+++ b/spec/lib/shell_spec.rb
@@ -1,16 +1,15 @@
 require 'spec_helper'
 
-describe Gitlab::Gitolite do
+describe Gitlab::Shell do
   let(:project) { double('Project', id: 7, path: 'diaspora') }
-  let(:gitolite) { Gitlab::Gitolite.new }
+  let(:gitolite) { Gitlab::Shell.new }
 
   before do
     Project.stub(find: project)
   end
 
-  it { should respond_to :set_key }
+  it { should respond_to :add_key }
   it { should respond_to :remove_key }
-
   it { should respond_to :add_repository }
   it { should respond_to :remove_repository }
 
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 6e67ca8233d..3dccb482375 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -77,8 +77,6 @@ describe Project do
     it { should respond_to(:url_to_repo) }
     it { should respond_to(:repo_exists?) }
     it { should respond_to(:satellite) }
-    it { should respond_to(:update_repository) }
-    it { should respond_to(:destroy_repository) }
     it { should respond_to(:observe_push) }
     it { should respond_to(:update_merge_requests) }
     it { should respond_to(:execute_hooks) }
diff --git a/spec/models/protected_branch_spec.rb b/spec/models/protected_branch_spec.rb
index c4d2e2f49f5..6e830393e32 100644
--- a/spec/models/protected_branch_spec.rb
+++ b/spec/models/protected_branch_spec.rb
@@ -24,19 +24,4 @@ describe ProtectedBranch do
     it { should validate_presence_of(:project) }
     it { should validate_presence_of(:name) }
   end
-
-  describe 'Callbacks' do
-    let(:branch) { build(:protected_branch) }
-
-    it 'call update_repository after save' do
-      branch.should_receive(:update_repository)
-      branch.save
-    end
-
-    it 'call update_repository after destroy' do
-      branch.save
-      branch.should_receive(:update_repository)
-      branch.destroy
-    end
-  end
 end
diff --git a/spec/observers/key_observer_spec.rb b/spec/observers/key_observer_spec.rb
index 11f975cc57d..0a886a57afd 100644
--- a/spec/observers/key_observer_spec.rb
+++ b/spec/observers/key_observer_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
 describe KeyObserver do
   before do
     @key = double('Key',
-      identifier: 'admin_654654',
+      shell_id: 'key-32',
       key: '== a vaild ssh key',
       projects: [],
       is_deploy_key: false
@@ -14,14 +14,14 @@ describe KeyObserver do
 
   context :after_save do
     it do
-      GitoliteWorker.should_receive(:perform_async).with(:set_key, @key.identifier, @key.key, @key.projects.map(&:id))
+      GitoliteWorker.should_receive(:perform_async).with(:add_key, @key.shell_id, @key.key)
       @observer.after_save(@key)
     end
   end
 
   context :after_destroy do
     it do
-      GitoliteWorker.should_receive(:perform_async).with(:remove_key, @key.identifier, @key.projects.map(&:id))
+      GitoliteWorker.should_receive(:perform_async).with(:remove_key, @key.shell_id, @key.key)
       @observer.after_destroy(@key)
     end
   end
diff --git a/spec/support/stubbed_repository.rb b/spec/support/stubbed_repository.rb
index fd891b1ce14..434cab6516e 100644
--- a/spec/support/stubbed_repository.rb
+++ b/spec/support/stubbed_repository.rb
@@ -48,11 +48,11 @@ module Gitlab
       true
     end
 
-    def add_key name, key
+    def add_key id, key
       true
     end
 
-    def remove_key key
+    def remove_key id, key
       true
     end
   end
diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb
index f408c89afdd..f1a69b1b2e4 100644
--- a/spec/workers/post_receive_spec.rb
+++ b/spec/workers/post_receive_spec.rb
@@ -11,7 +11,7 @@ describe PostReceive do
   context "web hook" do
     let(:project) { create(:project) }
     let(:key) { create(:key, user: project.owner) }
-    let(:key_id) { key.identifier }
+    let(:key_id) { key.shell_id }
 
     it "fetches the correct project" do
       Project.should_receive(:find_with_namespace).with(project.path_with_namespace).and_return(project)
@@ -19,7 +19,7 @@ describe PostReceive do
     end
 
     it "does not run if the author is not in the project" do
-      Key.stub(find_by_identifier: nil)
+      Key.stub(find_by_id: nil)
 
       project.should_not_receive(:observe_push)
       project.should_not_receive(:execute_hooks)
-- 
GitLab


From 867945d193743ca6abe5064570ae5854a0bf2826 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 5 Feb 2013 13:02:58 +0200
Subject: [PATCH 186/197] Improving installation docs

---
 config/gitlab.yml.example   |  4 +---
 config/unicorn.rb.example   |  2 +-
 doc/install/installation.md | 27 ++++-----------------------
 3 files changed, 6 insertions(+), 27 deletions(-)

diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 1a34d22417f..02118cbd950 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -96,7 +96,7 @@ omniauth:
 # GitLab Satellites
 satellites:
   # Relative paths are relative to Rails.root (default: tmp/repo_satellites/)
-  path: /home/gitlab/gitlab-satellites/
+  path: /home/git/gitlab-satellites/
 
 ## Backup settings
 backup:
@@ -105,8 +105,6 @@ backup:
 
 ## Gitolite settings
 gitolite:
-  admin_uri: git@localhost:gitolite-admin
-
   # REPOS_PATH MUST NOT BE A SYMLINK!!!
   repos_path: /home/git/repositories/
   hooks_path: /home/git/.gitolite/hooks/
diff --git a/config/unicorn.rb.example b/config/unicorn.rb.example
index 4852cd65daa..29b7146c7df 100644
--- a/config/unicorn.rb.example
+++ b/config/unicorn.rb.example
@@ -2,7 +2,7 @@
 # note that config/gitlab.yml web path should also be changed
 # ENV['RAILS_RELATIVE_URL_ROOT'] = "/gitlab"
 
-app_dir = "/home/gitlab/gitlab/"
+app_dir = "/home/git/gitlab/"
 worker_processes 2
 working_directory app_dir
 
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 7c0c5e6c9bb..9e7d80f8cc9 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -111,12 +111,6 @@ Create a `git` user for Gitlab:
     ./bin/install 
 
 
-## Add domains to list to the list of known hosts
-
-    sudo -u git -H ssh git@localhost
-    sudo -u git -H ssh git@YOUR_DOMAIN_NAME
-    sudo -u git -H ssh git@YOUR_GITOLITE_DOMAIN_NAME
-
 
 # 5. Database
 
@@ -137,10 +131,10 @@ See `doc/install/databases.md`
     cd /home/git/gitlab
    
     # Checkout to stable release
-    sudo -u git -H git checkout 4-1-stable
+    sudo -u git -H git checkout 5-0-stable
 
 **Note:**
-You can change `4-1-stable` to `master` if you want the *bleeding edge* version, but
+You can change `5-0-stable` to `master` if you want the *bleeding edge* version, but
 do so with caution!
 
 ## Configure it
@@ -155,8 +149,8 @@ do so with caution!
     sudo -u git -H vim config/gitlab.yml
 
     # Make sure GitLab can write to the log/ and tmp/ directories
-    sudo chown -R gitlab log/
-    sudo chown -R gitlab tmp/
+    sudo chown -R git log/
+    sudo chown -R git tmp/
     sudo chmod -R u+rwX  log/
     sudo chmod -R u+rwX  tmp/
 
@@ -191,19 +185,6 @@ Make sure to update username/password in config/database.yml.
     # Or for PostgreSQL
     sudo -u git -H bundle install --deployment --without development test mysql
 
-## Configure Git
-
-GitLab needs to be able to commit and push changes to Gitolite. In order to do
-that Git requires a username and email. (We recommend using the same address
-used for the `email.from` setting in `config/gitlab.yml`)
-
-    sudo -u git -H git config --global user.name "GitLab"
-    sudo -u git -H git config --global user.email "gitlab@localhost"
-
-## Setup GitLab Hooks
-
-    sudo cp ./lib/hooks/post-receive /home/git/.gitolite/hooks/common/post-receive
-    sudo chown git:git /home/git/.gitolite/hooks/common/post-receive
 
 ## Initialise Database and Activate Advanced Features
 
-- 
GitLab


From adfd36f26a448d54069713667c488404314c1887 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 5 Feb 2013 13:30:56 +0200
Subject: [PATCH 187/197] no need to run gitolite for enable_automerge

---
 lib/tasks/gitlab/enable_automerge.rake | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/lib/tasks/gitlab/enable_automerge.rake b/lib/tasks/gitlab/enable_automerge.rake
index e92da81021f..a89c6eaa5c4 100644
--- a/lib/tasks/gitlab/enable_automerge.rake
+++ b/lib/tasks/gitlab/enable_automerge.rake
@@ -3,11 +3,6 @@ namespace :gitlab do
   task :enable_automerge => :environment do
     warn_user_is_not_gitlab
 
-    puts "Updating repo permissions ..."
-    Gitlab::Gitolite.new.enable_automerge
-    puts "... #{"done".green}"
-    puts ""
-
     print "Creating satellites for ..."
     unless Project.count > 0
       puts "skipping, because you have no projects".magenta
-- 
GitLab


From 478570dc323e2a92204e1598e0f9232c54661429 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 5 Feb 2013 13:43:25 +0200
Subject: [PATCH 188/197] fix move repository

---
 app/models/project.rb | 2 --
 1 file changed, 2 deletions(-)

diff --git a/app/models/project.rb b/app/models/project.rb
index e774949ed12..e6be2d2ce84 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -262,8 +262,6 @@ class Project < ActiveRecord::Base
 
       Gitlab::ProjectMover.new(self, old_dir, new_dir).execute
 
-      gitolite.move_repository(old_repo, self)
-
       save!
     end
   rescue Gitlab::ProjectMover::ProjectMoveError => ex
-- 
GitLab


From bd3288e3207c12e90d7fed629b345cfe83018bbf Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 5 Feb 2013 15:55:49 +0200
Subject: [PATCH 189/197] api check call

---
 lib/api/internal.rb | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/lib/api/internal.rb b/lib/api/internal.rb
index 576b64d04c3..0a0f55bc512 100644
--- a/lib/api/internal.rb
+++ b/lib/api/internal.rb
@@ -32,6 +32,12 @@ module Gitlab
         key = Key.find(params[:key_id])
         present key.user, with: Entities::User
       end
+
+      get "/check" do
+        {
+          api_version: '3'
+        }
+      end
     end
   end
 end
-- 
GitLab


From 18fc0900523a850179bb15f8ca73a0bdf8631607 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 5 Feb 2013 15:59:40 +0200
Subject: [PATCH 190/197] remove hooks and support scripts from main repo.
 Moved to gitlab-shell

---
 lib/hooks/post-receive               | 12 -----------
 lib/support/rewrite-hooks.sh         | 32 ----------------------------
 lib/support/truncate_repositories.sh | 11 ----------
 3 files changed, 55 deletions(-)
 delete mode 100755 lib/hooks/post-receive
 delete mode 100755 lib/support/rewrite-hooks.sh
 delete mode 100755 lib/support/truncate_repositories.sh

diff --git a/lib/hooks/post-receive b/lib/hooks/post-receive
deleted file mode 100755
index 6944d3e3f72..00000000000
--- a/lib/hooks/post-receive
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/env bash
-
-# Version 4.1
-# This file was placed here by GitLab. It makes sure that your pushed commits
-# will be processed properly.
-
-while read oldrev newrev ref
-do
-  # For every branch or tag that was pushed, create a Resque job in redis.
-  repo_path=`pwd`
-  env -i redis-cli rpush "resque:gitlab:queue:post_receive" "{\"class\":\"PostReceive\",\"args\":[\"$repo_path\",\"$oldrev\",\"$newrev\",\"$ref\",\"$GL_USER\"]}" > /dev/null 2>&1
-done
diff --git a/lib/support/rewrite-hooks.sh b/lib/support/rewrite-hooks.sh
deleted file mode 100755
index b8fd36b9a1e..00000000000
--- a/lib/support/rewrite-hooks.sh
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/bin/bash
-
-src="/home/git/repositories"
-
-for dir in `ls "$src/"`
-do
-  if [ -d "$src/$dir" ]; then
-
-    if [ "$dir" = "gitolite-admin.git" ]
-    then
-      continue 
-    fi
-
-    if [[ "$dir" =~ ^.*.git$ ]]
-    then
-      project_hook="$src/$dir/hooks/post-receive"
-      gitolite_hook="/home/git/.gitolite/hooks/common/post-receive"
-
-      ln -s -f $gitolite_hook $project_hook
-    else
-      for subdir in `ls "$src/$dir/"`
-      do
-        if [ -d "$src/$dir/$subdir" ] && [[ "$subdir" =~ ^.*.git$ ]]; then
-          project_hook="$src/$dir/$subdir/hooks/post-receive"
-          gitolite_hook="/home/git/.gitolite/hooks/common/post-receive"
-
-          ln -s -f $gitolite_hook $project_hook
-        fi
-      done
-    fi
-  fi
-done
diff --git a/lib/support/truncate_repositories.sh b/lib/support/truncate_repositories.sh
deleted file mode 100755
index 3b14e2ee362..00000000000
--- a/lib/support/truncate_repositories.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash
-
-echo "Danger!!! Data Loss"
-while true; do
-  read -p "Do you wish to all directories except gitolite-admin.git from /home/git/repositories/ (y/n) ?:  " yn
-  case $yn in
-    [Yy]* ) sh -c "find /home/git/repositories/. -maxdepth 1  -not -name 'gitolite-admin.git' -not -name '.' | xargs sudo rm -rf"; break;;
-    [Nn]* ) exit;;
-    * ) echo "Please answer yes or no.";;
-  esac
-done
-- 
GitLab


From 48628d31d59f007fbf4b6958eb2a48adedaef8e4 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 7 Feb 2013 09:42:22 +0200
Subject: [PATCH 191/197] dont allow duplicates in ssh keys

---
 app/models/key.rb | 18 +++---------------
 1 file changed, 3 insertions(+), 15 deletions(-)

diff --git a/app/models/key.rb b/app/models/key.rb
index 0c01edcbe71..895e8d6cb9c 100644
--- a/app/models/key.rb
+++ b/app/models/key.rb
@@ -24,8 +24,8 @@ class Key < ActiveRecord::Base
   before_save :set_identifier
 
   validates :title, presence: true, length: { within: 0..255 }
-  validates :key, presence: true, length: { within: 0..5000 }, format: { :with => /ssh-.{3} / }
-  validate :unique_key, :fingerprintable_key
+  validates :key, presence: true, length: { within: 0..5000 }, format: { :with => /ssh-.{3} / }, uniqueness: true
+  validate :fingerprintable_key
 
   delegate :name, :email, to: :user, prefix: true
 
@@ -33,14 +33,6 @@ class Key < ActiveRecord::Base
     self.key = self.key.strip unless self.key.blank?
   end
 
-  def unique_key
-    query = Key.where(key: key)
-    query = query.where('(project_id IS NULL OR project_id = ?)', project_id) if project_id
-    if (query.count > 0)
-      errors.add :key, 'already exist.'
-    end
-  end
-
   def fingerprintable_key
     return true unless key # Don't test if there is no key.
     # `ssh-keygen -lf /dev/stdin <<< "#{key}"` errors with: redirection unexpected
@@ -65,7 +57,7 @@ class Key < ActiveRecord::Base
   end
 
   def is_deploy_key
-    true if project_id
+    !!project_id
   end
 
   # projects that has this key
@@ -77,10 +69,6 @@ class Key < ActiveRecord::Base
     end
   end
 
-  def last_deploy?
-    Key.where(identifier: identifier).count == 0
-  end
-
   def shell_id
     "key-#{self.id}"
   end
-- 
GitLab


From 8ae1d812dc9c8099b691e164e7119ede7eb21c61 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 7 Feb 2013 09:56:13 +0200
Subject: [PATCH 192/197] deploy keys support for gitlab-shell api

---
 lib/api/internal.rb | 31 ++++++++++++++++++-------------
 1 file changed, 18 insertions(+), 13 deletions(-)

diff --git a/lib/api/internal.rb b/lib/api/internal.rb
index 0a0f55bc512..3e5e3a478ba 100644
--- a/lib/api/internal.rb
+++ b/lib/api/internal.rb
@@ -7,22 +7,27 @@ module Gitlab
       #
       get "/allowed" do
         key = Key.find(params[:key_id])
-        user = key.user
-
         project = Project.find_with_namespace(params[:project])
-        action = case params[:action]
-                 when 'git-upload-pack'
-                   then :download_code
-                 when 'git-receive-pack'
-                   then
-                   if project.protected_branch?(params[:ref])
-                     :push_code_to_protected_branches
-                   else
-                     :push_code
+        git_cmd = params[:action]
+
+        if key.is_deploy_key
+          project == key.project && git_cmd == 'git-upload-pack'
+        else
+          user = key.user
+          action = case git_cmd
+                   when 'git-upload-pack'
+                     then :download_code
+                   when 'git-receive-pack'
+                     then
+                     if project.protected_branch?(params[:ref])
+                       :push_code_to_protected_branches
+                     else
+                       :push_code
+                     end
                    end
-                 end
 
-        user.can?(action, project)
+          user.can?(action, project)
+        end
       end
 
       #
-- 
GitLab


From cdcf69d0d9c06bbaf6a6ba25793985fe02dd1092 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 7 Feb 2013 10:06:39 +0200
Subject: [PATCH 193/197] gitlab;shell init script

---
 config/initializers/1_settings.rb |  2 +-
 lib/tasks/gitlab/shell.rake       | 32 +++++++++++++++++++++++++++++++
 2 files changed, 33 insertions(+), 1 deletion(-)
 create mode 100644 lib/tasks/gitlab/shell.rake

diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index a1afa5b22c4..c3179d78cc5 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -51,7 +51,7 @@ Settings.gitlab['protocol']   ||= Settings.gitlab.https ? "https" : "http"
 Settings.gitlab['email_from'] ||= "gitlab@#{Settings.gitlab.host}"
 Settings.gitlab['support_email']  ||= Settings.gitlab.email_from
 Settings.gitlab['url']        ||= Settings.send(:build_gitlab_url)
-Settings.gitlab['user']       ||= 'gitlab'
+Settings.gitlab['user']       ||= 'git'
 Settings.gitlab['signup_enabled'] ||= false
 
 Settings['gravatar'] ||= Settingslogic.new({})
diff --git a/lib/tasks/gitlab/shell.rake b/lib/tasks/gitlab/shell.rake
new file mode 100644
index 00000000000..25713482ed8
--- /dev/null
+++ b/lib/tasks/gitlab/shell.rake
@@ -0,0 +1,32 @@
+namespace :gitlab do
+  namespace :shell do
+    desc "GITLAB | Setup gitlab-shell"
+    task :setup => :environment do
+      setup
+    end
+  end
+
+  def setup
+    warn_user_is_not_gitlab
+
+    puts "This will rebuild an authorized_keys file."
+    puts "You will lose any data stored in /home/git/.ssh/authorized_keys."
+    ask_to_continue
+    puts ""
+
+    system("echo '# Managed by gitlab-shell' > /home/git/.ssh/authorized_keys")
+
+    Key.find_each(:batch_size => 1000) do |key|
+      if Gitlab::Shell.new.add_key(key.shell_id, key.key)
+        print '.'
+      else
+        print 'F'
+      end
+    end
+
+  rescue Gitlab::TaskAbortedByUserError
+    puts "Quitting...".red
+    exit 1
+  end
+end
+
-- 
GitLab


From d09d87e3b022f6b7cba0988c4377e44196e35939 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 7 Feb 2013 10:25:47 +0200
Subject: [PATCH 194/197] fix deploy key spec

---
 spec/models/key_spec.rb | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb
index 6d2310df5c0..94b952cf932 100644
--- a/spec/models/key_spec.rb
+++ b/spec/models/key_spec.rb
@@ -46,9 +46,9 @@ describe Key do
         key.should_not be_valid
       end
 
-      it "does accept the same key for another project" do
+      it "does not accept the same key for another project" do
         key = build(:key, project_id: 0)
-        key.should be_valid
+        key.should_not be_valid
       end
     end
 
-- 
GitLab


From 210e9cd489bc0c413474ad347e6ce065f3ec7c81 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 7 Feb 2013 13:05:30 +0200
Subject: [PATCH 195/197] It should be 5.0.0pre

---
 CHANGELOG | 3 +++
 VERSION   | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG b/CHANGELOG
index 4510b6d5cd9..65344736e9c 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,6 @@
+v 5.0.0
+  - replaced gitolite with gitlab-shell
+
 v 4.2.0
   - User show page. Via /u/username
   - Show help contents on pages for better navigation
diff --git a/VERSION b/VERSION
index b5d76fb80d8..0ceadf72ef7 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-4.2.0pre
+5.0.0pre
-- 
GitLab


From 66121d6caabb7f5169e4fc21e6bb8938a5ec14b5 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 7 Feb 2013 13:20:33 +0200
Subject: [PATCH 196/197] Improve devise views

---
 app/assets/stylesheets/sections/login.scss   |  6 +++---
 app/views/devise/passwords/new.html.erb      | 10 +++++-----
 app/views/devise/registrations/new.html.haml | 19 +++++++++----------
 app/views/devise/sessions/new.html.haml      |  6 +++---
 4 files changed, 20 insertions(+), 21 deletions(-)

diff --git a/app/assets/stylesheets/sections/login.scss b/app/assets/stylesheets/sections/login.scss
index 7536abff44f..89b8f1c0055 100644
--- a/app/assets/stylesheets/sections/login.scss
+++ b/app/assets/stylesheets/sections/login.scss
@@ -1,7 +1,7 @@
 /* Login Page */
-body.login-page{ 
-  padding-top: 10%;
-  background: #f1f1f1;
+body.login-page{
+  padding-top: 7%;
+  background: #666;
 }
 
 .login-box{
diff --git a/app/views/devise/passwords/new.html.erb b/app/views/devise/passwords/new.html.erb
index 1171b3bfb75..0e39f318726 100644
--- a/app/views/devise/passwords/new.html.erb
+++ b/app/views/devise/passwords/new.html.erb
@@ -1,9 +1,9 @@
-<%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :class => "login-box", :method => :post }) do |f| %>
-  <%= image_tag "login-logo.png", :width => "304", :height => "66", :class => "login-logo", :alt => "Login Logo" %>
+<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { class: "login-box", method: :post }) do |f| %>
+  <%= image_tag "login-logo.png", width: "304", height: "66", class: "login-logo", alt: "Login Logo" %>
   <%= devise_error_messages! %>
-  <%= f.email_field :email, :placeholder => "Email",  :class => "text" %>
+  <%= f.email_field :email, placeholder: "Email",  class: "text" %>
   <br/>
   <br/>
-  <%= f.submit "Reset password", :class => "btn-primary btn"  %>
-  <div class="right"> <%= link_to "Sign in", new_session_path(resource_name), :class => "btn" %><br /></div>
+  <%= f.submit "Reset password", class: "btn-primary btn"  %>
+  <div class="pull-right"> <%= link_to "Sign in", new_session_path(resource_name), class: "btn" %><br /></div>
 <% end %>
diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml
index 2b72d4ade87..12b0438229b 100644
--- a/app/views/devise/registrations/new.html.haml
+++ b/app/views/devise/registrations/new.html.haml
@@ -1,19 +1,18 @@
-= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :class => "login-box" }) do |f|
-  = image_tag "login-logo.png", :width => "304", :height => "66", :class => "login-logo", :alt => "Login Logo"
+= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { class: "login-box" }) do |f|
+  = image_tag "login-logo.png", width: "304", height: "66", class: "login-logo", alt: "Login Logo"
   = devise_error_messages!
   %div
-    = f.text_field :name, :class => "text top", :placeholder => "Name", :required => true
+    = f.text_field :name, class: "text top", placeholder: "Name", required: true
   %div
-    = f.text_field :username, :class => "text middle", :placeholder => "Username", :required => true
+    = f.text_field :username, class: "text middle", placeholder: "Username", required: true
   %div
-    = f.email_field :email, :class => "text middle", :placeholder => "Email", :required => true
+    = f.email_field :email, class: "text middle", placeholder: "Email", required: true
   %div
-    = f.password_field :password, :class => "text middle", :placeholder => "Password", :required => true
+    = f.password_field :password, class: "text middle", placeholder: "Password", required: true
   %div
-    = f.password_field :password_confirmation, :class => "text bottom", :placeholder => "Confirm password", :required => true
+    = f.password_field :password_confirmation, class: "text bottom", placeholder: "Confirm password", required: true
   %div
-    = f.submit "Sign up", :class => "btn-primary btn wide"
-  %br
+    = f.submit "Sign up", class: "btn-create btn"
   %hr
   = link_to "Sign in", new_session_path(resource_name)
-  = link_to "Forgot your password?", new_password_path(resource_name), :class => "right"
+  = link_to "Forgot your password?", new_password_path(resource_name), class: "pull-right"
diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml
index 7ea41876e44..d904e701b8a 100644
--- a/app/views/devise/sessions/new.html.haml
+++ b/app/views/devise/sessions/new.html.haml
@@ -11,18 +11,18 @@
           = f.check_box :remember_me
           %span Remember me
     %br/
-    = f.submit "Sign in", :class => "btn-primary btn wide"
+    = f.submit "Sign in", :class => "btn-create btn"
     .pull-right
       = link_to "Forgot your password?", new_password_path(resource_name), :class => "btn"
     %br/
-    %br/
     - if Gitlab.config.gitlab.signup_enabled
       %hr/
       Don't have an account?
       = link_to "Sign up", new_registration_path(resource_name)
-    .clearfix
     - if devise_mapping.omniauthable? && resource_class.omniauth_providers.present?
+      %hr
       %div
+        %span Sign in with: &nbsp;
         - resource_class.omniauth_providers.each do |provider|
           %span
             = link_to authbutton(provider, 32), omniauth_authorize_path(resource_name, provider)
-- 
GitLab


From a59585b4168768c9bfc79db44e1f6d4a6d42c2e8 Mon Sep 17 00:00:00 2001
From: Alex Yaroshevich <zxqfox@gmail.com>
Date: Fri, 8 Feb 2013 04:27:21 +0400
Subject: [PATCH 197/197] Expanding paths with repos and hooks

---
 config/initializers/1_settings.rb | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index c3179d78cc5..ebcbbf91636 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -63,10 +63,10 @@ Settings['gitolite'] ||= Settingslogic.new({})
 Settings.gitolite['admin_key']    ||= 'gitlab'
 Settings.gitolite['admin_uri']    ||= 'git@localhost:gitolite-admin'
 Settings.gitolite['config_file']  ||= 'gitolite.conf'
-Settings.gitolite['hooks_path']   ||= '/home/git/share/gitolite/hooks/'
+Settings.gitolite['hooks_path']     = File.expand_path(Settings.gitolite['hooks_path'] || '/home/git/share/gitolite/hooks/', Rails.root)
 Settings.gitolite['receive_pack']   = true if Settings.gitolite['receive_pack'].nil?
 Settings.gitolite['upload_pack']    = true if Settings.gitolite['upload_pack'].nil?
-Settings.gitolite['repos_path']   ||= '/home/git/repositories/'
+Settings.gitolite['repos_path']     = File.expand_path(Settings.gitolite['repos_path'] || '/home/git/repositories/', Rails.root)
 Settings.gitolite['ssh_host']     ||= (Settings.gitlab.host || 'localhost')
 Settings.gitolite['ssh_port']     ||= 22
 Settings.gitolite['ssh_user']     ||= 'git'
-- 
GitLab